Draws a quick access toolbar button based on a IQuickAccessToolbarButton source.
Inheritance: ComponentFactory.Krypton.Toolkit.ViewComposite, IContentValues
        /// <summary>
        /// Gets the view element for the button before the one provided.
        /// </summary>
        /// <param name="qatButton">Search for entry after this view.</param>
        /// <returns>ViewBase if found; otherwise false.</returns>
        public ViewBase GetPreviousQATView(ViewBase qatButton)
        {
            // If the provided view is the extra button, then implicitly already found previous entry
            bool found = ((qatButton != null) && (qatButton == _extraButton));

            // Extract the set of views into an array
            ViewDrawRibbonQATButton[] qatViews = new ViewDrawRibbonQATButton[_qatButtonToView.Count];
            _qatButtonToView.Values.CopyTo(qatViews, 0);

            // Search the list in reverse order
            for (int i = qatViews.Length - 1; i >= 0; i--)
            {
                // Extract the correct view to test
                ViewDrawRibbonQATButton qatView = qatViews[i];

                if (!found)
                {
                    found = (qatView == qatButton);
                }
                else if (qatView.Visible && qatView.Enabled)
                {
                    return(qatView);
                }
            }

            return(null);
        }
        /// <summary>
        /// Gets the view element for the first visible and enabled quick access toolbar button.
        /// </summary>
        /// <returns></returns>
        public ViewBase GetLastQATView()
        {
            // If showing the extra button, then use that
            if (_extraButton != null)
            {
                return(_extraButton);
            }

            // Extract the set of views into an array
            ViewDrawRibbonQATButton[] qatViews = new ViewDrawRibbonQATButton[_qatButtonToView.Count];
            _qatButtonToView.Values.CopyTo(qatViews, 0);

            // Search the list in reverse order
            for (int i = qatViews.Length - 1; i >= 0; i--)
            {
                // Extract the correct view to test
                ViewDrawRibbonQATButton qatView = qatViews[i];

                // QAT button must be visible and enabled
                if (qatView.Visible && qatView.Enabled)
                {
                    return(qatView);
                }
            }

            return(null);
        }
        /// <summary>
        /// Discover the preferred size of the element.
        /// </summary>
        /// <param name="context">Layout context.</param>
        public override Size GetPreferredSize(ViewLayoutContext context)
        {
            // Sync to represent the current ribbon QAT buttons
            SyncChildren(false);

            Size preferredSize = Size.Empty;

            // Find total width and maximum height across all child elements
            for (int i = 0; i < Count; i++)
            {
                ViewBase child = this[i];

                // Only interested in visible items that are not the extra button
                if (child != _extraButton)
                {
                    // Cast child to correct type
                    ViewDrawRibbonQATButton view = (ViewDrawRibbonQATButton)child;

                    // If the quick access toolbar button wants to be visible
                    if (view.QATButton.GetVisible() || Ribbon.InDesignHelperMode)
                    {
                        // Cache preferred size of the child
                        Size childSize = child.GetPreferredSize(context);

                        // Only need extra processing for children that have some width
                        if (childSize.Width > 0)
                        {
                            // Always add on to the width
                            preferredSize.Width += childSize.Width;

                            // Find maximum height encountered
                            preferredSize.Height = Math.Max(preferredSize.Height, childSize.Height);
                        }
                    }
                }
            }

            if (_extraButton != null)
            {
                // Cache preferred size of the child
                Size childSize = _extraButton.GetPreferredSize(context);

                // Only need extra processing for children that have some width
                if (childSize.Width > 0)
                {
                    // Always add on to the width
                    preferredSize.Width += childSize.Width;

                    // Find maximum height encountered
                    preferredSize.Height = Math.Max(preferredSize.Height, childSize.Height);
                }
            }

            return(preferredSize);
        }
        private void OnShowToolTip(object sender, ToolTipEventArgs e)
        {
            if (!_ribbon.IsDisposed)
            {
                // Do not show tooltips when the form we are in does not have focus
                Form topForm = _ribbon.FindForm();
                if ((topForm != null) && !topForm.ContainsFocus)
                {
                    return;
                }

                // Never show tooltips are design time
                if (!_ribbon.InDesignMode)
                {
                    IContentValues sourceContent = null;
                    LabelStyle     toolTipStyle  = LabelStyle.SuperTip;
                    Rectangle      screenRect    = new Rectangle(e.ScreenPt, new Size(1, 1));

                    // If the target is the application button
                    if ((e.Target is ViewLayoutRibbonAppButton) || (e.Target is ViewLayoutRibbonAppTab))
                    {
                        // Create a content that recovers values from a the ribbon for the app button/tab
                        AppButtonToolTipToContent appButtonContent = new AppButtonToolTipToContent(_ribbon);

                        // Is there actually anything to show for the tooltip
                        if (appButtonContent.HasContent)
                        {
                            sourceContent = appButtonContent;

                            // Grab the style from the app button settings
                            toolTipStyle = _ribbon.RibbonAppButton.AppButtonToolTipStyle;

                            // Display below the mouse cursor
                            screenRect.Height += SystemInformation.CursorSize.Height / 3 * 2;
                        }
                    }
                    else
                    {
                        // If the target is a QAT button
                        if (e.Target is ViewDrawRibbonQATButton)
                        {
                            // Cast to correct type
                            ViewDrawRibbonQATButton viewElement = (ViewDrawRibbonQATButton)e.Target;

                            // Create a content that recovers values from a IQuickAccessToolbarButton
                            QATButtonToolTipToContent qatButtonContent = new QATButtonToolTipToContent(viewElement.QATButton);

                            // Is there actually anything to show for the tooltip
                            if (qatButtonContent.HasContent)
                            {
                                sourceContent = qatButtonContent;

                                // Grab the style from the QAT button settings
                                toolTipStyle = viewElement.QATButton.GetToolTipStyle();

                                // Display below the mouse cursor
                                screenRect.Height += SystemInformation.CursorSize.Height / 3 * 2;
                            }
                        }
                        else
                        {
                            // If the target is a label
                            if ((e.Target.Parent != null) && (e.Target.Parent is ViewDrawRibbonGroupLabel))
                            {
                                // Cast to correct type
                                ViewDrawRibbonGroupLabel viewElement = (ViewDrawRibbonGroupLabel)e.Target.Parent;

                                // Create a content that recovers values from a KryptonRibbonGroupItem
                                GroupItemToolTipToContent groupItemContent = new GroupItemToolTipToContent(viewElement.GroupLabel);

                                // Is there actually anything to show for the tooltip
                                if (groupItemContent.HasContent)
                                {
                                    sourceContent = groupItemContent;

                                    // Grab the style from the group label settings
                                    toolTipStyle = viewElement.GroupLabel.ToolTipStyle;

                                    // Display below the bottom of the ribbon control
                                    Rectangle ribbonScreenRect = _ribbon.ToolTipScreenRectangle;
                                    screenRect.Y      = ribbonScreenRect.Y;
                                    screenRect.Height = ribbonScreenRect.Height;
                                    screenRect.X      = ribbonScreenRect.X + viewElement.ClientLocation.X;
                                    screenRect.Width  = viewElement.ClientWidth;
                                }
                            }
                            else
                            {
                                // Is the target is a button or cluster button
                                if (e.Target is ViewDrawRibbonGroupButtonBackBorder)
                                {
                                    // Cast to correct type
                                    ViewDrawRibbonGroupButtonBackBorder viewElement = (ViewDrawRibbonGroupButtonBackBorder)e.Target;

                                    // Create a content that recovers values from a KryptonRibbonGroupItem
                                    GroupItemToolTipToContent groupItemContent = new GroupItemToolTipToContent(viewElement.GroupItem);

                                    // Is there actually anything to show for the tooltip
                                    if (groupItemContent.HasContent)
                                    {
                                        sourceContent = groupItemContent;

                                        // Grab the style from the group button/group cluster button settings
                                        toolTipStyle = viewElement.GroupItem.InternalToolTipStyle;

                                        // Display below the bottom of the ribbon control
                                        Rectangle ribbonScreenRect = _ribbon.ToolTipScreenRectangle;
                                        screenRect.Y      = ribbonScreenRect.Y;
                                        screenRect.Height = ribbonScreenRect.Height;
                                        screenRect.X      = ribbonScreenRect.X + viewElement.ClientLocation.X;
                                        screenRect.Width  = viewElement.ClientWidth;
                                    }
                                }
                                else
                                {
                                    if (e.Target is ViewLayoutRibbonCheckBox)
                                    {
                                        // Cast to correct type
                                        ViewDrawRibbonGroupCheckBox viewElement = (ViewDrawRibbonGroupCheckBox)e.Target.Parent;

                                        // Create a content that recovers values from a KryptonRibbonGroupItem
                                        GroupItemToolTipToContent groupItemContent = new GroupItemToolTipToContent(viewElement.GroupCheckBox);

                                        // Is there actually anything to show for the tooltip
                                        if (groupItemContent.HasContent)
                                        {
                                            sourceContent = groupItemContent;

                                            // Grab the style from the group check box cluster button settings
                                            toolTipStyle = viewElement.GroupCheckBox.InternalToolTipStyle;

                                            // Display below the bottom of the ribbon control
                                            Rectangle ribbonScreenRect = _ribbon.ToolTipScreenRectangle;
                                            screenRect.Y      = ribbonScreenRect.Y;
                                            screenRect.Height = ribbonScreenRect.Height;
                                            screenRect.X      = ribbonScreenRect.X + viewElement.ClientLocation.X;
                                            screenRect.Width  = viewElement.ClientWidth;
                                        }
                                    }
                                    else
                                    {
                                        if (e.Target is ViewLayoutRibbonRadioButton)
                                        {
                                            // Cast to correct type
                                            ViewDrawRibbonGroupRadioButton viewElement = (ViewDrawRibbonGroupRadioButton)e.Target.Parent;

                                            // Create a content that recovers values from a KryptonRibbonGroupItem
                                            GroupItemToolTipToContent groupItemContent = new GroupItemToolTipToContent(viewElement.GroupRadioButton);

                                            // Is there actually anything to show for the tooltip
                                            if (groupItemContent.HasContent)
                                            {
                                                sourceContent = groupItemContent;

                                                // Grab the style from the group radio button button settings
                                                toolTipStyle = viewElement.GroupRadioButton.InternalToolTipStyle;

                                                // Display below the bottom of the ribbon control
                                                Rectangle ribbonScreenRect = _ribbon.ToolTipScreenRectangle;
                                                screenRect.Y      = ribbonScreenRect.Y;
                                                screenRect.Height = ribbonScreenRect.Height;
                                                screenRect.X      = ribbonScreenRect.X + viewElement.ClientLocation.X;
                                                screenRect.Width  = viewElement.ClientWidth;
                                            }
                                        }
                                        else
                                        {
                                            // Find the button spec associated with the tooltip request
                                            ButtonSpec buttonSpec = _buttonManager.ButtonSpecFromView(e.Target);

                                            // If the tooltip is for a button spec
                                            if (buttonSpec != null)
                                            {
                                                // Are we allowed to show page related tooltips
                                                if (_ribbon.AllowButtonSpecToolTips)
                                                {
                                                    // Create a helper object to provide tooltip values
                                                    ButtonSpecToContent buttonSpecMapping = new ButtonSpecToContent(_ribbon.GetRedirector(), buttonSpec);

                                                    // Is there actually anything to show for the tooltip
                                                    if (buttonSpecMapping.HasContent)
                                                    {
                                                        sourceContent = buttonSpecMapping;

                                                        // Grab the style from the button spec settings
                                                        toolTipStyle = buttonSpec.ToolTipStyle;

                                                        // Display below the mouse cursor
                                                        screenRect.Height += SystemInformation.CursorSize.Height / 3 * 2;
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }

                    if (sourceContent != null)
                    {
                        // Remove any currently showing tooltip
                        _visualPopupToolTip?.Dispose();

                        // Create the actual tooltip popup object
                        _visualPopupToolTip = new VisualPopupToolTip(_ribbon.GetRedirector(),
                                                                     sourceContent,
                                                                     _ribbon.Renderer,
                                                                     PaletteBackStyle.ControlToolTip,
                                                                     PaletteBorderStyle.ControlToolTip,
                                                                     CommonHelper.ContentStyleFromLabelStyle(toolTipStyle));

                        _visualPopupToolTip.Disposed += new EventHandler(OnVisualPopupToolTipDisposed);

                        // The popup tooltip control always adds on a border above/below so we negate that here.
                        screenRect.Height -= 20;

                        // Show relative to the provided screen rectangle
                        _visualPopupToolTip.ShowCalculatingSize(screenRect);
                    }
                }
            }
        }
        private void SyncChildren(bool layout)
        {
            // Remove all child elements
            Clear();

            // Create a new lookup that reflects any changes in QAT buttons
            QATButtonToView regenerate = new QATButtonToView();

            // Get an array with all the buttons to be considered for display
            IQuickAccessToolbarButton[] qatButtons = QATButtons;

            // Make sure we have a view element to match each QAT button definition
            foreach (IQuickAccessToolbarButton qatButton in qatButtons)
            {
                ViewDrawRibbonQATButton view = null;

                // Get the currently cached view for the button
                if (_qatButtonToView.ContainsKey(qatButton))
                {
                    view = _qatButtonToView[qatButton];
                }

                // If a new button, create a view for it now
                if (view == null)
                {
                    view = new ViewDrawRibbonQATButton(Ribbon, qatButton, _needPaint);
                }

                // Add to the lookup for future reference
                regenerate.Add(qatButton, view);
            }

            // Add child elements appropriate for each qat button
            for (int i = 0; i < qatButtons.Length; i++)
            {
                IQuickAccessToolbarButton qatButton = qatButtons[i];

                // Does the layout processing require the view to be updated
                if (layout)
                {
                    // Update the enabled/visible state of the button
                    regenerate[qatButton].Enabled = Ribbon.InDesignHelperMode || qatButton.GetEnabled();
                    regenerate[qatButton].Visible = Ribbon.InDesignHelperMode || qatButton.GetVisible();
                }

                // Always add the group view
                Add(regenerate[qatButton]);

                // Remove entries we are still using
                if (_qatButtonToView.ContainsKey(qatButton))
                {
                    _qatButtonToView.Remove(qatButton);
                }
            }

            // Dispose of views no longer required
            foreach (ViewDrawRibbonQATButton view in _qatButtonToView.Values)
            {
                view.Dispose();
            }

            // No longer need the old lookup
            _qatButtonToView = regenerate;

            // Always add the customization/overflow button last
            if (_extraButton != null)
            {
                Add(_extraButton);
            }
        }
        /// <summary>
        /// Perform a layout of the elements.
        /// </summary>
        /// <param name="context">Layout context.</param>
        public override void Layout(ViewLayoutContext context)
        {
            Debug.Assert(context != null);

            // Sync to represent the current ribbon QAT buttons
            SyncChildren(true);

            // We take on all the available display area
            ClientRectangle = context.DisplayRectangle;

            int x     = ClientLocation.X;
            int right = ClientRectangle.Right;

            // If we need to show the extra button
            if (_extraButton != null)
            {
                // Find size of the extra button
                Size childSize = _extraButton.GetPreferredSize(context);

                // Make sure there is always enough room for it at the right hand side
                right -= childSize.Width;
            }

            int y      = ClientLocation.Y;
            int height = ClientHeight;

            Overflow = false;

            // Are there any children to layout?
            if (Count > 0)
            {
                // Position each item from left to right taking up entire height
                for (int i = 0; i < Count; i++)
                {
                    ViewBase child = this[i];

                    // We only position visible items and we always ignore the extra button
                    if (child != _extraButton)
                    {
                        if (child.Visible)
                        {
                            // Cache preferred size of the child
                            Size childSize = this[i].GetPreferredSize(context);

                            // Is there enough width for this item to be displayed
                            if ((childSize.Width + x) <= right)
                            {
                                // Define display rectangle for the group
                                context.DisplayRectangle = new Rectangle(x, y, childSize.Width, height);

                                // Position the element
                                this[i].Layout(context);

                                // Move across to next position
                                x += childSize.Width;
                            }
                            else
                            {
                                // Hide the child, not enough for it
                                child.Visible = false;

                                // Need to use the extra button as an overflow button
                                Overflow = true;
                            }
                        }
                        else
                        {
                            // Cast child to correct type
                            ViewDrawRibbonQATButton view = (ViewDrawRibbonQATButton)child;

                            // If the quick access toolbar button wants to be visible
                            if (view.QATButton.GetVisible() || Ribbon.InDesignHelperMode)
                            {
                                Overflow = true;
                            }
                        }
                    }
                }
            }

            // Do we need to position the extra button?
            if (_extraButton != null)
            {
                // Cache preferred size of the child
                Size childSize = _extraButton.GetPreferredSize(context);

                // Is there enough width for this item to be displayed
                if ((childSize.Width + x) <= ClientRectangle.Right)
                {
                    // Define display rectangle for the group
                    context.DisplayRectangle = new Rectangle(x, y, childSize.Width, height);

                    // Position the element
                    _extraButton.Layout(context);

                    // Move across to next position
                    x += childSize.Width;
                }

                // Should button show as overflow or customization
                _extraButton.Overflow = Overflow;
            }

            // Update our own size to reflect how wide we actually need to be for all the children
            ClientRectangle = new Rectangle(ClientLocation, new Size(x - ClientLocation.X, ClientHeight));

            // Update the display rectangle we allocated for use by parent
            context.DisplayRectangle = new Rectangle(ClientLocation, new Size(x - ClientLocation.X, ClientHeight));
        }
        /// <summary>
        /// Generate a key tip info for each visible tab.
        /// </summary>
        /// <param name="ownerForm">KryptonForm instance that owns this view.</param>
        /// <returns>Array of KeyTipInfo instances.</returns>
        public KeyTipInfo[] GetQATKeyTips(KryptonForm ownerForm)
        {
            // Create all the list of all possible QAT key tip strings
            Stack <string> keyTipsPool = new Stack <string>();

            // Then use the alphanumeric 0A - 0Z
            for (int i = 25; i >= 0; i--)
            {
                keyTipsPool.Push("0" + (char)(65 + i));
            }

            // Then use the number 09 - 01
            for (int i = 1; i <= 9; i++)
            {
                keyTipsPool.Push("0" + i.ToString());
            }

            // Start with the number 1 - 9
            for (int i = 9; i >= 1; i--)
            {
                keyTipsPool.Push(i.ToString());
            }

            // If integrated into the caption area then get the caption area height
            Padding borders = Padding.Empty;

            if ((ownerForm != null) && !ownerForm.ApplyComposition)
            {
                borders = ownerForm.RealWindowBorders;
            }

            KeyTipInfoList keyTipList = new KeyTipInfoList();

            foreach (ViewBase child in this)
            {
                // If visible and we have another key tip available on stack
                if (child.Visible && (keyTipsPool.Count > 0) &&
                    (child is ViewDrawRibbonQATButton))
                {
                    // Cast to correct type
                    ViewDrawRibbonQATButton viewQAT = (ViewDrawRibbonQATButton)child;

                    // Get the screen location of the view tab
                    Rectangle viewRect = ParentControl.RectangleToScreen(viewQAT.ClientRectangle);

                    // The keytip should be centered on the bottom center of the view
                    Point screenPt = new Point((viewRect.Left + (viewRect.Width / 2)) - borders.Left,
                                               viewRect.Bottom - 2 - borders.Top);

                    // Create new key tip that invokes the qat controller
                    keyTipList.Add(new KeyTipInfo(viewQAT.Enabled, keyTipsPool.Pop(), screenPt,
                                                  viewQAT.ClientRectangle, viewQAT.KeyTipTarget));
                }
            }

            // If we have the extra button and it is in overflow appearance
            if ((_extraButton != null) && _extraButton.Overflow)
            {
                // Get the screen location of the extra button
                Rectangle viewRect = ParentControl.RectangleToScreen(_extraButton.ClientRectangle);

                // The keytip should be centered on the bottom center of the view
                Point screenPt = new Point((viewRect.Left + (viewRect.Width / 2)) - borders.Left,
                                           viewRect.Bottom - 2 - borders.Top);

                // Create fixed key tip of '00' that invokes the extra button contoller
                keyTipList.Add(new KeyTipInfo(true, "00", screenPt, _extraButton.ClientRectangle, _extraButton.KeyTipTarget));
            }

            return(keyTipList.ToArray());
        }