/// <summary> /// Generate a key tip info for each visible tab. /// </summary> /// <returns>Array of KeyTipInfo instances.</returns> public KeyTipInfo[] GetTabKeyTips() { KeyTipInfoList keyTipList = new KeyTipInfoList(); foreach (ViewBase child in this) { // Only interested in tab views if (child is ViewDrawRibbonTab) { // Cast to correct type ViewDrawRibbonTab viewTab = (ViewDrawRibbonTab)child; // Get the screen location of the view tab Rectangle tabRect = viewTab.OwningControl.RectangleToScreen(viewTab.ClientRectangle); // The keytip should be centered on the bottom center of the view Point screenPt = new Point(tabRect.Left + (tabRect.Width / 2), tabRect.Bottom + 2); // Create new key tip that invokes the tab controller when selected keyTipList.Add(new KeyTipInfo(true, viewTab.RibbonTab.KeyTip, screenPt, viewTab.ClientRectangle, viewTab.KeyTipTarget)); } } return(keyTipList.ToArray()); }
/// <summary> /// Gets the view element for drawing the previous tab from the provided one. /// </summary> /// <param name="ribbonTab">Current ribbon tab to use when searching.</param> /// <returns>View element for a tab; otherwise null.</returns> public ViewDrawRibbonTab GetViewForPreviousRibbonTab(KryptonRibbonTab ribbonTab) { bool found = false; foreach (ViewBase child in this.Reverse()) { // Only interested in tab views if (child is ViewDrawRibbonTab) { // Cast to correct type ViewDrawRibbonTab viewTab = (ViewDrawRibbonTab)child; // Wait until we see the provided tab, then first visible tab after it if (!found) { found = (viewTab.RibbonTab == ribbonTab); } else if (child.Visible) { return(viewTab); } } } return(null); }
/// <summary> /// Initialize a new instance of the ContextTabSet class. /// </summary> /// <param name="tab">Reference to first tab of the set.</param> /// <param name="context">Reference to owning context details.</param> public ContextTabSet(ViewDrawRibbonTab tab, KryptonRibbonContext context) { Debug.Assert(tab != null); Debug.Assert(context != null); FirstTab = tab; _lastTab = tab; Context = context; }
private void AddTabsWithContextName(string contextName) { ContextTabSet cts = null; // Remove the ribbon tab reference from the draw tab // (Must do this for all tabs before setting them to the corret value) for (int i = 0; i < _ribbon.RibbonTabs.Count; i++) { KryptonRibbonTab ribbonTab = _ribbon.RibbonTabs[i]; if (IsRibbonVisible(ribbonTab, contextName)) { _tabCache[i].RibbonTab = null; } } // Add child elements appropriate for each ribbon tab for (int i = 0; i < _ribbon.RibbonTabs.Count; i++) { KryptonRibbonTab ribbonTab = _ribbon.RibbonTabs[i]; if (IsRibbonVisible(ribbonTab, contextName)) { // Get the matching indexed items ViewDrawRibbonTab drawTab = _tabCache[i]; // Every tab needs a draw tab element followed by a separator Add(drawTab); Add(_tabSepCache[i]); // Associate the draw element with matching ribbon tab drawTab.RibbonTab = ribbonTab; // If we are dealing with a real context and not the empty one if (!string.IsNullOrEmpty(contextName)) { // Create tab set when first needed, otherwise this tab must be the last one if (cts == null) { cts = new ContextTabSet(drawTab, _ribbon.RibbonContexts[ribbonTab.ContextName]); } else { cts.UpdateLastTab(drawTab); } } } } // If we created a new tab set, then add to the collection if (cts != null) { ContextTabSets.Add(cts); } }
/// <summary> /// Process the mouse wheel change of selection. /// </summary> /// <param name="next">True if movement to next tab required; otherwise previous.</param> public void ProcessMouseWheel(bool next) { KryptonRibbonTab selectTab = _ribbon.SelectedTab; // Scan to find the prev and next tabs bool prevSelected = false; KryptonRibbonTab prev = null; foreach (ViewBase child in this) { // Only interested in visible ribbon tabs if (child.Visible && (child is ViewDrawRibbonTab)) { // Cast to correct type of view element ViewDrawRibbonTab viewTab = (ViewDrawRibbonTab)child; // Is this element for the currently selected tab? if (viewTab.RibbonTab == _ribbon.SelectedTab) { // If we want the previous tab to the currently selected one! if (!next) { // And if we have a previous tab, then use it if (prev != null) { selectTab = prev; } break; } prevSelected = true; } else { // If we want the next tab and the previous was the selected one if (next && prevSelected) { // Then this is the next one! selectTab = viewTab.RibbonTab; break; } } prev = viewTab.RibbonTab; } } // Is there a change in selection? if (selectTab != null) { _ribbon.SelectedTab = selectTab; } }
/// <summary> /// Initialize a new instance of the RibbonTabController class. /// </summary> /// <param name="ribbon">Reference to owning control.</param> /// <param name="target">Target for state changes.</param> /// <param name="needPaint">Delegate for notifying paint requests.</param> public RibbonTabController(KryptonRibbon ribbon, ViewDrawRibbonTab target, NeedPaintHandler needPaint) { Debug.Assert(ribbon != null); Debug.Assert(target != null); // Remember incoming references _target = target; _ribbon = ribbon; // Store the provided paint notification delegate NeedPaint = needPaint; }
/// <summary> /// Update the last tab in the set with new refernece. /// </summary> /// <param name="tab">Reference to new last tab.</param> public void UpdateLastTab(ViewDrawRibbonTab tab) { Debug.Assert(tab != null); _lastTab = tab; }
/// <summary> /// Gets a value indicating if the tab is the first or last in set. /// </summary> /// <param name="tab">Tab to test.</param> /// <returns>True if first or last; otherwise false.</returns> public bool IsFirstOrLastTab(ViewDrawRibbonTab tab) { return((tab == FirstTab) || (tab == _lastTab)); }
/// <summary> /// Gets a value indicating if the tab is the last in set. /// </summary> /// <param name="tab">Tab to test.</param> /// <returns>True if last; otherwise false.</returns> public bool IsLastTab(ViewDrawRibbonTab tab) { return(tab == _lastTab); }
/// <summary> /// Gets a value indicating if the tab is the first in set. /// </summary> /// <param name="tab">Tab to test.</param> /// <returns>True if first; otherwise false.</returns> public bool IsFirstTab(ViewDrawRibbonTab tab) { return(tab == FirstTab); }
private Rectangle CalculatePopupRect(ViewLayoutRibbonTabsArea tabsArea, ViewDrawPanel drawMinimizedPanel) { Size popupSize; // Get the preferred size of the groups area, we only really want the height using (ViewLayoutContext context = new ViewLayoutContext(_ribbon, Renderer)) popupSize = drawMinimizedPanel.GetPreferredSize(context); // The width should default to being the same width as the ribbon control popupSize.Width = _ribbon.Width; // Get the screen rectangles for the ribbon and the tabs area of the ribbon Rectangle parentRibbonRect = _ribbon.RectangleToScreen(_ribbon.ClientRectangle); Rectangle parentTabsRect = _ribbon.RectangleToScreen(tabsArea.ClientRectangle); // Default popup is placed below the ribbon Rectangle popupRect = new Rectangle(parentRibbonRect.X, parentTabsRect.Bottom - 1, popupSize.Width, popupSize.Height); // Get the view element for the currently selected tab ViewDrawRibbonTab viewTab = tabsArea.LayoutTabs.GetViewForRibbonTab(_ribbon.SelectedTab); //!!!!betauser. can crash if (viewTab == null) { return(new Rectangle(0, 0, 0, 0)); } // Convert the view tab client area to screen coordinates Rectangle viewTabRect = _ribbon.RectangleToScreen(viewTab.ClientRectangle); // Get the screen that the tab is mostly within Screen screen = Screen.FromRectangle(viewTabRect); Rectangle workingArea = screen.WorkingArea; workingArea.Width -= BOTTOMRIGHT_GAP; workingArea.Height -= BOTTOMRIGHT_GAP; // Is the right side of the popup extending over the right edge of the screen... if (popupRect.Right > workingArea.Right) { // Reduce width to bring it back onto the screen popupRect.Width -= (popupRect.Right - workingArea.Right); // Enforce a minimum useful width for the popup if (popupRect.Width < MINIMUM_WIDTH) { popupRect.X -= (MINIMUM_WIDTH - popupRect.Width); popupRect.Width = MINIMUM_WIDTH; } } else { // Is the left side of the popup extending over left edge of screen... if (popupRect.Left < workingArea.Left) { // Reduce left side of popup to start at screen left edge int reduce = (workingArea.Left - popupRect.Left); popupRect.Width -= reduce; popupRect.X += reduce; // Enforce a minimum useful width for the popup if (popupRect.Width < MINIMUM_WIDTH) { popupRect.Width = MINIMUM_WIDTH; } } } // If there is not enough room to place the popup below the tabs area if (popupRect.Bottom > workingArea.Bottom) { // Is there enough room above the parent for the entire popup height? if ((parentTabsRect.Top - popupRect.Height) >= workingArea.Top) { // Place the popup above the parent popupRect.Y = parentTabsRect.Top - popupSize.Height; } else { // Cannot show entire popup above or below, find which has most space int spareAbove = parentTabsRect.Top - workingArea.Top; int spareBelow = workingArea.Bottom - parentTabsRect.Bottom; // Place it in the area with the most space if (spareAbove > spareBelow) { popupRect.Y = workingArea.Top; } else { popupRect.Y = parentTabsRect.Bottom; } } } return(popupRect); }
/// <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 child elements to represent the current ribbon tabs collection setup SyncChildrenToRibbonTabs(); // We take on all the available display area ClientRectangle = context.DisplayRectangle; int x = ClientLocation.X; // Are there any children to layout? if (this.Count > 0) { // Modify the cached sizes so they are ideally sized for actual space Size[] layoutSizes = AdjustSizesToFit(); int y = ClientRectangle.Y; int bottom = ClientRectangle.Bottom; int height = ClientHeight; // Position each item from left to right taking up entire height for (int i = 0; i < this.Count; i++) { // Only interested in visible items if (layoutSizes[i].Width > 0) { // Separators are made the full height, others are aligned on the bottom edge if (this[i] is ViewDrawRibbonTabSep) { // Update separator with latest calculated need to draw ViewDrawRibbonTabSep tabSep = this[i] as ViewDrawRibbonTabSep; tabSep.Draw = _showSeparators; context.DisplayRectangle = new Rectangle(x, y, layoutSizes[i].Width, height); } else if (this[i] is ViewDrawRibbonTab) { // Update checked state of the tab ViewDrawRibbonTab tab = this[i] as ViewDrawRibbonTab; tab.Checked = (_ribbon.SelectedTab == tab.RibbonTab); context.DisplayRectangle = new Rectangle(x, bottom - layoutSizes[i].Height, layoutSizes[i].Width, layoutSizes[i].Height); } else if (this[i] is ViewDrawRibbonDesignTab) { context.DisplayRectangle = new Rectangle(x, bottom - layoutSizes[i].Height, layoutSizes[i].Width, layoutSizes[i].Height); } // Position the element this[i].Layout(context); // Move across to next position x += layoutSizes[i].Width; } } } // Fill remainder space with the tabs spare element Rectangle customCaptionRect = Rectangle.Empty; if (_tabsSpare != null) { _tabsSpare.Visible = false; if (x < ClientRectangle.Right) { if (_ribbon.GetRedirector().GetMetricBool(PaletteState.Normal, PaletteMetricBool.RibbonTabsSpareCaption) == InheritBool.True) { customCaptionRect = new Rectangle(x, ClientRectangle.Y, ClientRectangle.Right - x, ClientHeight); context.DisplayRectangle = customCaptionRect; _tabsSpare.Visible = true; _tabsSpare.Layout(context); x = ClientRectangle.Right; } } } // We have an owning form we need to update the custom area it treats as a caption if (_ribbon.CaptionArea.KryptonForm != null) { if (!customCaptionRect.IsEmpty) { // Convert the rectangle to the owning form coordinates customCaptionRect = _parentControl.RectangleToScreen(customCaptionRect); customCaptionRect = _ribbon.CaptionArea.KryptonForm.RectangleToClient(customCaptionRect); } _ribbon.CaptionArea.KryptonForm.CustomCaptionArea = customCaptionRect; } // 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> /// Discover the preferred size of the element. /// </summary> /// <param name="context">Layout context.</param> public override Size GetPreferredSize(ViewLayoutContext context) { // Sync child elements to represent the current ribbon tabs collection setup SyncChildrenToRibbonTabs(); Size preferredSize = Size.Empty; // Reset cached variables _cachedSizes = new Size[this.Count]; _cachedMinimumWidth = 0; _cachedAllTabCount = 0; _cachedNonContextTabCount = 0; // Find total width and maximum height across all child elements for (int i = 0; i < this.Count; i++) { ViewBase child = this[i]; // Only interested in visible items if (child.Visible) { // Cache preferred size of the child _cachedSizes[i] = child.GetPreferredSize(context); // Only need extra processing for children that have some width if (_cachedSizes[i].Width > 0) { // Always add on to the width preferredSize.Width += _cachedSizes[i].Width; int childHeight = _cachedSizes[i].Height; if (child is ViewDrawRibbonTab) { // Tabs need an extra pixel height as a separator gap childHeight++; // Cache number of tabs encountered _cachedAllTabCount++; // Cache number of non-context tabs encountered ViewDrawRibbonTab tab = child as ViewDrawRibbonTab; if (string.IsNullOrEmpty(tab.RibbonTab.ContextName)) { _cachedNonContextTabCount++; } } else if (child is ViewDrawRibbonDesignTab) { // Tabs need an extra pixel height as a separator gap childHeight++; // Cache number of tabs encountered _cachedAllTabCount++; } // Find maximum height encountered preferredSize.Height = Math.Max(preferredSize.Height, childHeight); // Find the minimum allowed width for all children _cachedMinimumWidth += Math.Min(_cachedSizes[i].Width, TAB_MINWIDTH); } } } // Remember total size requested to fit everything into view normally _cachedPreferredWidth = preferredSize.Width; // Minimum height is the height of a tab preferredSize.Height = Math.Max(preferredSize.Height, _ribbon.CalculatedValues.TabHeight); // Preferred with is the minimum allowed, so the parent scroller knows if scroll bars are needed preferredSize.Width = _cachedMinimumWidth; // If we have the tabs spare area... if (_tabsSpare != null) { // Always take up the entire provided width as the spare will take up any remainder not used by actual tabs if (preferredSize.Width < context.DisplayRectangle.Width) { preferredSize.Width = context.DisplayRectangle.Width; } } return(preferredSize); }