Files
ayanova7/source/WinFormApp/TabOrderManager.cs
2018-06-29 19:47:36 +00:00

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;
}
}
}
}