private void OnCheckButtonDragRect(object sender, ButtonDragRectangleEventArgs e)
        {
            // Cast incoming reference to the actual check button view
            ViewDrawNavCheckButtonStack reorderItem = (ViewDrawNavCheckButtonStack)sender;

            e.PreDragOffset = (Navigator.AllowPageReorder && reorderItem.Page.AreFlagsSet(KryptonPageFlags.AllowPageReorder));
            Rectangle dragRect = Rectangle.Union(e.DragRect, _viewScrollViewport.ClientRectangle);

            dragRect.Inflate(new Size(15, 15));
            e.DragRect = dragRect;
        }
        private void RecreateView()
        {
            // Remove all the existing layout content except the old root at postiion 0
            ViewBase firstChild = _viewLayout[0];

            _viewLayout.Clear();
            _viewLayout.Add(firstChild);

            // Start stacking from the top/left if not explicitly set to be far aligned
            RelativePositionAlign alignment   = Navigator.Stack.StackAlignment;
            Orientation           stackOrient = Navigator.Stack.StackOrientation;
            ViewDockStyle         dockNear    = (stackOrient == Orientation.Vertical ? ViewDockStyle.Top : ViewDockStyle.Left);
            ViewDockStyle         dockFar     = (stackOrient == Orientation.Vertical ? ViewDockStyle.Bottom : ViewDockStyle.Right);

            bool dockTopLeft = (alignment != RelativePositionAlign.Far);

            foreach (KryptonPage page in Navigator.Pages)
            {
                // Grab the page associated view elements
                ViewDrawNavCheckButtonStack checkButton = (ViewDrawNavCheckButtonStack)_pageLookup[page];
                ViewDrawBorderEdge          buttonEdge  = (ViewDrawBorderEdge)_buttonEdgeLookup[page];

                // Add to the child collection with the correct docking style
                if (dockTopLeft)
                {
                    _viewLayout.Insert(1, checkButton);
                    _viewLayout.Insert(1, buttonEdge);
                    _viewLayout.SetDock(buttonEdge, dockNear);
                    _viewLayout.SetDock(checkButton, dockNear);
                }
                else
                {
                    _viewLayout.Add(buttonEdge, dockFar);
                    _viewLayout.Add(checkButton, dockFar);
                }

                // All entries after the selected page are docked at the bottom/right unless
                // we have been set to stack near or far, in which case we do not change.
                if (checkButton.Checked && (alignment == RelativePositionAlign.Center))
                {
                    dockTopLeft = false;
                }
            }
        }
        private void OnPageInserted(object sender, TypedCollectionEventArgs <KryptonPage> e)
        {
            if (!Navigator.IsDisposed && _events)
            {
                // Create the draw view element for the check button and provide page it represents
                ViewDrawNavCheckButtonStack checkButton = new ViewDrawNavCheckButtonStack(Navigator, e.Item, ResolveButtonOrientation());

                // Provide the drag rectangle when requested for this button
                checkButton.ButtonDragRectangle += new EventHandler <ButtonDragRectangleEventArgs>(OnCheckButtonDragRect);
                checkButton.ButtonDragOffset    += new EventHandler <ButtonDragOffsetEventArgs>(OnCheckButtonDragOffset);

                // Need to know when check button needs repainting
                checkButton.NeedPaint = NeedPaintDelegate;

                // Set the initial state
                checkButton.Visible = e.Item.LastVisibleSet;
                checkButton.Enabled = e.Item.Enabled;
                checkButton.Checked = (Navigator.SelectedPage == e.Item);

                // Find the border edge palette to use
                PaletteBorderEdge buttonEdgePalette = (Navigator.Enabled ? Navigator.StateNormal.BorderEdge :
                                                       Navigator.StateDisabled.BorderEdge);

                // Create the border edge for use next to the check button
                ViewDrawBorderEdge buttonEdge = new ViewDrawBorderEdge(buttonEdgePalette, Navigator.Stack.StackOrientation);
                buttonEdge.Visible = e.Item.LastVisibleSet;

                // Add to lookup dictionary
                _pageLookup.Add(e.Item, checkButton);
                _buttonEdgeLookup.Add(e.Item, buttonEdge);

                // Set correct ordering and dock setting
                ReorderCheckButtons();

                // Need to repaint to show the change
                Navigator.PerformNeedPaint(true);
            }
        }
        private void CreateNavCheckButtons()
        {
            // Maintain lookup between page and check button/button edge that represent it
            _pageLookup       = new PageToNavCheckButton();
            _buttonEdgeLookup = new PageToButtonEdge();

            VisualOrientation     checkButtonOrient = ResolveButtonOrientation();
            RelativePositionAlign alignment         = Navigator.Stack.StackAlignment;
            Orientation           stackOrient       = Navigator.Stack.StackOrientation;
            Orientation           buttonEdgeOrient  = (stackOrient == Orientation.Vertical ? Orientation.Horizontal : Orientation.Vertical);
            ViewDockStyle         dockNear          = (stackOrient == Orientation.Vertical ? ViewDockStyle.Top : ViewDockStyle.Left);
            ViewDockStyle         dockFar           = (stackOrient == Orientation.Vertical ? ViewDockStyle.Bottom : ViewDockStyle.Right);

            // Cache the border edge palette to use
            PaletteBorderEdge buttonEdgePalette = (Navigator.Enabled ? Navigator.StateNormal.BorderEdge :
                                                   Navigator.StateDisabled.BorderEdge);

            // Start stacking from the top/left if not explicitly set to be far aligned
            bool dockTopLeft = (alignment != RelativePositionAlign.Far);

            // Create a check button to represent each krypton page
            foreach (KryptonPage page in Navigator.Pages)
            {
                // Create the draw view element for the check button and provide page it represents
                ViewDrawNavCheckButtonStack checkButton = new ViewDrawNavCheckButtonStack(Navigator, page, checkButtonOrient);

                // Provide the drag rectangle when requested for this button
                checkButton.ButtonDragRectangle += new EventHandler <ButtonDragRectangleEventArgs>(OnCheckButtonDragRect);
                checkButton.ButtonDragOffset    += new EventHandler <ButtonDragOffsetEventArgs>(OnCheckButtonDragOffset);

                // Need to know when check button needs repainting
                checkButton.NeedPaint = NeedPaintDelegate;

                // Set the initial state
                checkButton.Visible     = page.LastVisibleSet;
                checkButton.Enabled     = page.Enabled;
                checkButton.Checked     = (Navigator.SelectedPage == page);
                checkButton.Orientation = checkButtonOrient;

                // Create the border edge for use next to the check button
                ViewDrawBorderEdge buttonEdge = new ViewDrawBorderEdge(buttonEdgePalette, buttonEdgeOrient);
                buttonEdge.Visible = page.LastVisibleSet;

                // Add to lookup dictionary
                _pageLookup.Add(page, checkButton);
                _buttonEdgeLookup.Add(page, buttonEdge);

                // Add to the child collection with the correct docking style
                if (dockTopLeft)
                {
                    _viewLayout.Insert(1, checkButton);
                    _viewLayout.Insert(1, buttonEdge);
                    _viewLayout.SetDock(buttonEdge, dockNear);
                    _viewLayout.SetDock(checkButton, dockNear);
                }
                else
                {
                    _viewLayout.Add(buttonEdge, dockFar);
                    _viewLayout.Add(checkButton, dockFar);
                }

                // All entries after the selected page are docked at the bottom/right unless
                // we have been set to stack near or far, in which case we do not change.
                if (checkButton.Checked && (alignment == RelativePositionAlign.Center))
                {
                    dockTopLeft = false;
                }
            }

            // Need to monitor changes in the page collection to reflect in layout bar
            Navigator.Pages.Inserted += new TypedHandler <KryptonPage>(OnPageInserted);
            Navigator.Pages.Removed  += new TypedHandler <KryptonPage>(OnPageRemoved);
            Navigator.Pages.Cleared  += new EventHandler(OnPagesCleared);
            _events = true;
        }
        private void OnCheckButtonDragOffset(object sender, ButtonDragOffsetEventArgs e)
        {
            // Cast incoming reference to the actual check button view
            ViewDrawNavCheckButtonStack reorderView = (ViewDrawNavCheckButtonStack)sender;

            // Scan the collection of children
            bool        foundReorderView = false;
            Orientation stackOrient      = Navigator.Stack.StackOrientation;

            foreach (KryptonPage page in Navigator.Pages)
            {
                // If the mouse is over this button
                ViewDrawNavCheckButtonStack childView = (ViewDrawNavCheckButtonStack)_pageLookup[page];
                if (childView.ClientRectangle.Contains(e.PointOffset))
                {
                    // Only interested if mouse over a different check button
                    if (childView != reorderView)
                    {
                        Rectangle childRect = childView.ClientRectangle;

                        if (foundReorderView)
                        {
                            if (stackOrient == Orientation.Vertical)
                            {
                                int shrink = childRect.Height - Math.Min(childRect.Height, reorderView.ClientHeight);
                                childRect.Y      += shrink;
                                childRect.Height -= shrink;
                            }
                            else
                            {
                                int shrink = childRect.Width - Math.Min(childRect.Width, reorderView.ClientWidth);
                                childRect.X     += shrink;
                                childRect.Width -= shrink;
                            }

                            // Ensure that when we are placed in the 'after' position the mouse is still over
                            // ourself as the moved button. Otherwise we just end up toggling back and forth.
                            if (childRect.Contains(e.PointOffset))
                            {
                                KryptonPage          movePage   = PageFromView(reorderView);
                                KryptonPage          targetPage = PageFromView(childView);
                                PageReorderEventArgs reorder    = new PageReorderEventArgs(movePage, targetPage, false);

                                // Give event handlers a chance to cancel this reorder
                                Navigator.OnBeforePageReorder(reorder);
                                if (!reorder.Cancel)
                                {
                                    Navigator.Pages.MoveAfter(movePage, PageFromView(childView));
                                    RecreateView();
                                    Navigator.PerformLayout();
                                    Navigator.Refresh();
                                    Navigator.OnTabMoved(new TabMovedEventArgs(movePage, Navigator.Pages.IndexOf(movePage)));
                                }
                            }
                        }
                        else
                        {
                            if (stackOrient == Orientation.Vertical)
                            {
                                childRect.Height = Math.Min(childRect.Height, reorderView.ClientHeight);
                            }
                            else
                            {
                                childRect.Width = Math.Min(childRect.Width, reorderView.ClientWidth);
                            }

                            // Ensure that when we are placed in the 'before' position the mouse is still over
                            // ourself as the moved button. Otherwise we just end up toggling back and forth.
                            if (childRect.Contains(e.PointOffset))
                            {
                                KryptonPage          movePage   = PageFromView(reorderView);
                                KryptonPage          targetPage = PageFromView(childView);
                                PageReorderEventArgs reorder    = new PageReorderEventArgs(movePage, targetPage, true);

                                // Give event handlers a chance to cancel this reorder
                                Navigator.OnBeforePageReorder(reorder);
                                if (!reorder.Cancel)
                                {
                                    Navigator.Pages.MoveBefore(movePage, PageFromView(childView));
                                    RecreateView();
                                    Navigator.PerformLayout();
                                    Navigator.Refresh();
                                    Navigator.OnTabMoved(new TabMovedEventArgs(movePage, Navigator.Pages.IndexOf(movePage)));
                                }
                            }
                        }

                        break;
                    }
                }

                foundReorderView = (childView == reorderView);
            }
        }