using System;
using System.Windows.Forms;
using System.Collections;
using System.Collections.Specialized;
using System.Diagnostics;
namespace AyaNova
{
class TabOrderManager
{
///
/// Case 152 tab order on forms
/// Compare two controls in the selected tab scheme.
///
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
///
/// Create a tab scheme comparer that compares using the given scheme.
///
///
public TabSchemeComparer(TabScheme scheme)
{
comparisonScheme = scheme;
}
}
///
/// The container whose tab order we manage.
///
private Control container;
///
/// Hash of controls to schemes so that individual containers can have different ordering
/// strategies than their parents.
///
private Hashtable schemeOverrides;
///
/// The tab index we start numbering from when the tab order is applied.
///
private int curTabIndex = 0;
///
/// The general tab-ordering strategy (i.e. whether we tab across rows first, or down columns).
///
public enum TabScheme
{
None,
AcrossFirst,
DownFirst
}
///
/// Constructor
///
/// The container whose tab order we manage.
public TabOrderManager(Control container)
{
this.container = container;
this.curTabIndex = 0;
this.schemeOverrides = new Hashtable();
}
///
/// Construct a tab order manager that starts numbering at the given tab index.
///
/// The container whose tab order we manage.
/// Where to start numbering.
/// List of controls with explicitly defined schemes.
private TabOrderManager(Control container, int curTabIndex, Hashtable schemeOverrides)
{
this.container = container;
this.curTabIndex = curTabIndex;
this.schemeOverrides = schemeOverrides;
}
///
/// Explicitly set a tab order scheme for a given (presumably container) control.
///
/// The control to set the scheme for.
/// The requested scheme.
public void SetSchemeForControl(Control c, TabScheme scheme)
{
schemeOverrides[c] = scheme;
}
///
/// Recursively set the tab order on this container and all of its children.
///
/// The tab ordering strategy to apply.
/// The next tab index to be used.
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;
}
}
}
}