+ Control active = GetMostDeeplyNestedActiveControl (form == null ? this : form);
+ Control common_ancestor = GetCommonContainer (active, value);
+ ArrayList chain = new ArrayList ();
+ ArrayList validation_chain = new ArrayList ();
+ Control walk = active;
+
+ // we split this up into three steps:
+ // 1. walk up the tree (if we need to) to our root, firing leave events.
+ // 2. validate.
+ // 3. walk down the tree (if we need to), firing enter events.
+
+ // "our root" is either the common ancestor of the current active
+ // control and the new active control, or the current active control,
+ // or the new active control. That is, it's either one of these three
+ // configurations:
+
+ // (1) root (2) new (3) current
+ // / \ / \ / \
+ // ... ... ... ... ... ...
+ // / \ / \
+ // current new current new
+
+
+ // note (3) doesn't require any upward walking, and no leave events are generated.
+ // (2) doesn't require any downward walking, and no enter events are generated.
+
+ // as we walk up the tree, we generate a list of all controls which cause
+ // validation. After firing the leave events, we invoke (in order starting from
+ // the most deeply nested) their Validating event. If one sets CancelEventArgs.Cancel
+ // to true, we ignore the control the user wanted to set ActiveControl to, and use
+ // the Validating control instead.
+
+ bool fire_enter = true;
+ Control root = common_ancestor;
+
+ active_control = value;
+
+ // Generate the leave messages
+ while (walk != common_ancestor && walk != null) {
+ if (walk == value) {
+ root = value;
+ fire_enter = false;
+ break;
+ }
+ walk.FireLeave ();
+ /* clear our idea of the active control as we go back up */
+ if (walk is ContainerControl)
+ ((ContainerControl)walk).active_control = null;
+
+ if (walk.CausesValidation)
+ validation_chain.Add (walk);
+
+ walk = walk.Parent;
+ }
+
+ // Validation can be postponed due to all the controls
+ // in the enter chain not causing validation. If we don't have any
+ // enter chain, it means that the selected control is a child and then
+ // we need to validate the controls anyway
+ bool postpone_validation;
+ Control topmost_under_root = null; // topmost under root, in the *enter* chain
+ if (value == root)
+ postpone_validation = false;
+ else {
+ postpone_validation = true;
+ walk = value;
+ while (walk != root && walk != null) {
+ if (walk.CausesValidation)
+ postpone_validation = false;
+
+ topmost_under_root = walk;