///     Disposes the entire selection manager.
        internal void Dispose()
        {
            // We've got to be careful here.  We're one of the last things to go away when
            // a form is being torn down, and we've got to be wary if things have pulled out
            // already.
            host.RemoveService(typeof(ISelectionService));
            host.TransactionOpened -= new EventHandler(this.DesignerHost_TransactionOpened);
            host.TransactionClosed -= new DesignerTransactionCloseEventHandler(this.DesignerHost_TransactionClosed);
            if (host.InTransaction)
            {
                DesignerHost_TransactionClosed(host, new DesignerTransactionCloseEventArgs(true));
            }
            host.LoadComplete -= new EventHandler(this.DesignerHost_LoadComplete);

            IComponentChangeService cs = (IComponentChangeService)host.GetService(typeof(IComponentChangeService));

            if (cs != null)
            {
                cs.ComponentAdded   -= new ComponentEventHandler(this.DesignerHost_ComponentAdd);
                cs.ComponentRemoved -= new ComponentEventHandler(this.DesignerHost_ComponentRemove);
                cs.ComponentChanged -= new ComponentChangedEventHandler(this.DesignerHost_ComponentChanged);
            }

            EtoSelectionItem[] sels = new EtoSelectionItem[selectionsByComponent.Values.Count];
            selectionsByComponent.Values.CopyTo(sels, 0);

            for (int i = 0; i < sels.Length; i++)
            {
                sels[i].Dispose();
            }

            selectionsByComponent.Clear();
            primarySelection = null;
        }
        ///     Sets the given selection object to be the primary selection.
        internal void SetPrimarySelection(EtoSelectionItem sel)
        {
            if (sel != primarySelection)
            {
                if (null != primarySelection)
                {
                    primarySelection.Primary = false;
                }

                primarySelection = sel;
            }

            if (null != primarySelection)
            {
                primarySelection.Primary = true;
            }
        }
 ///     Removes the given selection from our selection list
 private void RemoveSelection(EtoSelectionItem s)
 {
     selectionsByComponent.Remove(s.Component);
     s.Dispose();
 }
        ///     Called by the formcore when someone has removed a component.  This will
        ///     remove any selection on the component without disturbing the rest of
        ///     the selection.
        private void DesignerHost_ComponentRemove(object sender, ComponentEventArgs ce)
        {
            EtoSelectionItem sel = (EtoSelectionItem)selectionsByComponent[ce.Component];

            if (sel != null)
            {
                RemoveSelection(sel);

                // If we removed the last selection and we have a designer host, then select the base
                // component of the host.  Otherwise, it is OK to have an empty selection.
                if (selectionsByComponent.Count == 0 && host != null)
                {
                    // Now we have to run through all the components and pick
                    // the control with the highest z-order.
                    IComponent[] comps = new IComponent[host.Container.Components.Count];
                    host.Container.Components.CopyTo(comps, 0);

                    if (comps == null)
                    {
                        return;
                    }

                    int    maxZOrder    = -1;
                    int    defaultIndex = -1;
                    object maxIndexComp = null;
                    object baseComp     = host.RootComponent;

                    if (baseComp == null)
                    {
                        return;
                    }

                    for (int i = comps.Length - 1; i >= 0; i--)
                    {
                        if (comps[i] == baseComp)
                        {
                            continue;
                        }
                        else if (defaultIndex == -1)
                        {
                            defaultIndex = i;
                        }

                        if (comps[i] is Control)
                        {
                            int zorder = ((Control)comps[i]).TabIndex;
                            if (zorder > maxZOrder)
                            {
                                maxZOrder    = zorder;
                                maxIndexComp = (object)comps[i];
                            }
                        }
                    }

                    if (maxIndexComp == null)
                    {
                        if (defaultIndex != -1)
                        {
                            maxIndexComp = comps[defaultIndex];
                        }
                        else
                        {
                            maxIndexComp = baseComp;
                        }
                    }

                    ((ISelectionService)this).SetSelectedComponents(new object[] { maxIndexComp }, SelectionTypes.Replace);
                }
                else
                {
                    OnSelectionChanged();
                }
            }
            else
            {
                // Component isn't selected, but our list of selectable components is
                // different.
                OnSelectionContentsChanged();
            }
        }
 ///     Adds the given selection to our selection list.
 private void AddSelection(EtoSelectionItem sel)
 {
     selectionsByComponent[sel.Component] = sel;
 }
        /// Select the given components with the given SelectionType.
        void ISelectionService.SetSelectedComponents(ICollection components, SelectionTypes selectionType)
        {
            bool fToggle  = false;
            bool fControl = false;
            bool fClick   = false;
            bool fChanged = false;  // did we actually change something?

            // Catch a null input list
            if (components == null)
            {
                components = new Component[0];
            }

            if ((selectionType & SelectionTypes.Normal) == SelectionTypes.Normal ||
                (selectionType & SelectionTypes.Click) == SelectionTypes.Click)
            {
                fControl = ((Control.ModifierKeys & Keys.Control) == Keys.Control);

                // Only toggle when we are affecting a single control, and
                // when we are handling the "mouse" state events (i.e. up/down
                // used to show/hide the selection).
                //
                fToggle = ((Control.ModifierKeys & Keys.Control) != 0 || (Control.ModifierKeys & Keys.Shift) != 0) &&
                          components.Count == 1 &&
                          (selectionType & SelectionTypes.MouseUp) != SelectionTypes.MouseUp;
            }

            if ((selectionType & SelectionTypes.Click) == SelectionTypes.Click)
            {
                fClick = true;
            }

            // If we are replacing the selection, only remove the ones that are not in our new list.
            // We also handle the special case here of having a singular component selected that's
            // already selected.  In this case we just move it to the primary selection.
            //
            if (!fToggle && !fControl)
            {
                object firstSelection = null;
                foreach (object o in components)
                {
                    firstSelection = o;
                    break;
                }

                if (fClick && 1 == components.Count && ((ISelectionService)this).GetComponentSelected(firstSelection))
                {
                    EtoSelectionItem oldPrimary = primarySelection;
                    SetPrimarySelection((EtoSelectionItem)selectionsByComponent[firstSelection]);
                    if (oldPrimary != primarySelection)
                    {
                        fChanged = true;
                    }
                }
                else
                {
                    EtoSelectionItem[] selections = new EtoSelectionItem[selectionsByComponent.Values.Count];
                    selectionsByComponent.Values.CopyTo(selections, 0);

                    // Even with several hundred components this should be fairly fast
                    foreach (EtoSelectionItem item in selections)
                    {
                        bool remove = true;

                        foreach (object comp in components)
                        {
                            if (comp == item.Component)
                            {
                                remove = false;
                                break;
                            }
                        }

                        if (remove)
                        {
                            RemoveSelection(item);
                            fChanged = true;
                        }
                    }
                }
            }

            EtoSelectionItem primarySel = null;
            int selectedCount           = selectionsByComponent.Count;

            // Now do the selection.
            foreach (Component comp in components)
            {
                if (comp != null)
                {
                    EtoSelectionItem s = (EtoSelectionItem)selectionsByComponent[comp];

                    if (null == s)
                    {
                        s = new EtoSelectionItem(this, comp);
                        AddSelection(s);

                        if (fControl || fToggle)
                        {
                            primarySel = s;
                        }

                        fChanged = true;
                    }
                    else
                    {
                        if (fToggle)
                        {
                            // Remove the selection from our list.
                            RemoveSelection(s);
                            fChanged = true;
                        }
                    }
                }
            }

            if (primarySel != null)
            {
                SetPrimarySelection(primarySel);
            }

            // Now notify that our selection has changed
            if (fChanged)
            {
                OnSelectionChanged();
            }
        }