FireEnter() private method

private FireEnter ( ) : void
return void
Example #1
0
        internal void SetActiveControl(Control value)
        {
            using (_ = new Focusing())
            {
                if (active_control == value && (value == null || value.Focused))
                {
                    return;
                }

                if (value != null && !Contains(value))
                {
                    throw new ArgumentException("Cannot activate invisible or disabled control.");
                }

                if (value == null)
                {
                    Control previous_active_control = active_control;
                    active_control = null;
                    using (_ = new Focusing(false))
                        previous_active_control?.FireLeave();
                    return;
                }

                // Fire the enter and leave events if possible
                Form      form             = FindForm();
                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;
                    }
                    using (_ = new Focusing(false))
                        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;
                        walk = walk.Parent;
                    }
                }

                Control failed_validation_control = PerformValidation(form == null ? this : form, postpone_validation,
                                                                      validation_chain, topmost_under_root);
                if (failed_validation_control != null)
                {
                    active_control = value = failed_validation_control;
                    fire_enter     = true;
                }

                if (fire_enter)
                {
                    walk = value;
                    while (walk != root && walk != null)
                    {
                        chain.Add(walk);
                        walk = walk.Parent;
                    }

                    if (root != null && walk == root && !(root is ContainerControl))
                    {
                        chain.Add(walk);
                    }

                    for (int i = chain.Count - 1; i >= 0; i--)
                    {
                        walk = (Control)chain [i];
                        using (_ = new Focusing(false))
                            walk.FireEnter();
                    }
                }

                walk = this;
                Control ctl = this;
                while (walk != null)
                {
                    if (walk.Parent is ContainerControl)
                    {
                        ((ContainerControl)walk.Parent).active_control = ctl;
                        ctl = walk.Parent;
                    }
                    walk = walk.Parent;
                }

                if (this is Form)
                {
                    CheckAcceptButton();
                }

                // Scroll control into view
                ScrollControlIntoView(active_control);


                walk = this;
                ctl  = this;
                while (walk != null)
                {
                    if (walk.Parent is ContainerControl)
                    {
                        ctl = walk.Parent;
                    }
                    walk = walk.Parent;
                }

                // Let the control know it's selected
                if (ctl.ContainsFocus && active_control != null &&
                    (!(active_control is UserControl) || (active_control is UserControl && !((UserControl)active_control).HasFocusableChild())))
                {
                    SendControlFocus(active_control);
                }
            }
        }