190 lines
6.8 KiB
C#
190 lines
6.8 KiB
C#
using System;
|
|
using System.Windows.Forms;
|
|
using System.Collections;
|
|
using System.Collections.Specialized;
|
|
using System.Diagnostics;
|
|
namespace AyaNova
|
|
{
|
|
class TabOrderManager
|
|
{
|
|
/// <summary>
|
|
/// Case 152 tab order on forms
|
|
/// Compare two controls in the selected tab scheme.
|
|
/// </summary>
|
|
private class TabSchemeComparer : IComparer
|
|
{
|
|
private TabScheme comparisonScheme;
|
|
|
|
#region IComparer Members
|
|
|
|
public int Compare(object x, object y)
|
|
{
|
|
Control control1 = x as Control;
|
|
Control control2 = y as Control;
|
|
|
|
if (control1 == control2)
|
|
return 0;
|
|
|
|
if (control1 == null || control2 == null)
|
|
{
|
|
Debug.Assert(false, "Attempting to compare a non-control");
|
|
return 0;
|
|
}
|
|
|
|
if (comparisonScheme == TabScheme.None)
|
|
{
|
|
// Nothing to do.
|
|
return 0;
|
|
}
|
|
|
|
if (comparisonScheme == TabScheme.AcrossFirst)
|
|
{
|
|
// The primary direction to sort is the y direction (using the Top property).
|
|
// If two controls have the same y coordination, then we sort them by their x's.
|
|
if (control1.Top < control2.Top)
|
|
{
|
|
return -1;
|
|
}
|
|
else if (control1.Top > control2.Top)
|
|
{
|
|
return 1;
|
|
}
|
|
else
|
|
{
|
|
return (control1.Left.CompareTo(control2.Left));
|
|
}
|
|
}
|
|
else // comparisonScheme = TabScheme.DownFirst
|
|
{
|
|
// The primary direction to sort is the x direction (using the Left property).
|
|
// If two controls have the same x coordination, then we sort them by their y's.
|
|
if (control1.Left < control2.Left)
|
|
{
|
|
return -1;
|
|
}
|
|
else if (control1.Left > control2.Left)
|
|
{
|
|
return 1;
|
|
}
|
|
else
|
|
{
|
|
return (control1.Top.CompareTo(control2.Top));
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
/// <summary>
|
|
/// Create a tab scheme comparer that compares using the given scheme.
|
|
/// </summary>
|
|
/// <param name="scheme"></param>
|
|
public TabSchemeComparer(TabScheme scheme)
|
|
{
|
|
comparisonScheme = scheme;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// The container whose tab order we manage.
|
|
/// </summary>
|
|
private Control container;
|
|
|
|
/// <summary>
|
|
/// Hash of controls to schemes so that individual containers can have different ordering
|
|
/// strategies than their parents.
|
|
/// </summary>
|
|
private Hashtable schemeOverrides;
|
|
|
|
/// <summary>
|
|
/// The tab index we start numbering from when the tab order is applied.
|
|
/// </summary>
|
|
private int curTabIndex = 0;
|
|
|
|
/// <summary>
|
|
/// The general tab-ordering strategy (i.e. whether we tab across rows first, or down columns).
|
|
/// </summary>
|
|
public enum TabScheme
|
|
{
|
|
None,
|
|
AcrossFirst,
|
|
DownFirst
|
|
}
|
|
|
|
/// <summary>
|
|
/// Constructor
|
|
/// </summary>
|
|
/// <param name="container">The container whose tab order we manage.</param>
|
|
public TabOrderManager(Control container)
|
|
{
|
|
this.container = container;
|
|
this.curTabIndex = 0;
|
|
this.schemeOverrides = new Hashtable();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Construct a tab order manager that starts numbering at the given tab index.
|
|
/// </summary>
|
|
/// <param name="container">The container whose tab order we manage.</param>
|
|
/// <param name="curTabIndex">Where to start numbering.</param>
|
|
/// <param name="schemeOverrides">List of controls with explicitly defined schemes.</param>
|
|
private TabOrderManager(Control container, int curTabIndex, Hashtable schemeOverrides)
|
|
{
|
|
this.container = container;
|
|
this.curTabIndex = curTabIndex;
|
|
this.schemeOverrides = schemeOverrides;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Explicitly set a tab order scheme for a given (presumably container) control.
|
|
/// </summary>
|
|
/// <param name="c">The control to set the scheme for.</param>
|
|
/// <param name="scheme">The requested scheme.</param>
|
|
public void SetSchemeForControl(Control c, TabScheme scheme)
|
|
{
|
|
schemeOverrides[c] = scheme;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Recursively set the tab order on this container and all of its children.
|
|
/// </summary>
|
|
/// <param name="scheme">The tab ordering strategy to apply.</param>
|
|
/// <returns>The next tab index to be used.</returns>
|
|
public int SetTabOrder(TabScheme scheme)
|
|
{
|
|
// Tab order isn't important enough to ever cause a crash, so replace any exceptions
|
|
// with assertions.
|
|
try
|
|
{
|
|
ArrayList controlArraySorted = new ArrayList();
|
|
controlArraySorted.AddRange(container.Controls);
|
|
controlArraySorted.Sort(new TabSchemeComparer(scheme));
|
|
|
|
foreach (Control c in controlArraySorted)
|
|
{
|
|
// Debug.WriteLine("TabOrderManager: Changing tab index for " + c.Name);
|
|
|
|
c.TabIndex = curTabIndex++;
|
|
if (c.Controls.Count > 0)
|
|
{
|
|
// Control has children -- recurse.
|
|
TabScheme childScheme = scheme;
|
|
if (schemeOverrides.Contains(c))
|
|
{
|
|
childScheme = (TabScheme)schemeOverrides[c];
|
|
}
|
|
curTabIndex = (new TabOrderManager(c, curTabIndex, schemeOverrides)).SetTabOrder(childScheme);
|
|
}
|
|
}
|
|
|
|
return curTabIndex;
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Debug.Assert(false, "Exception in TabOrderManager.SetTabOrder: " + e.Message);
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
}
|