/// <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 the current group items SyncChildrenToRibbonGroupItems(); // Clear down the cache of item sizes _sizeList.Clear(); _viewList.Clear(); _viewToGap.Clear(); int totalWidth = 0; ViewBase previousChild = null; // Find the size of each individual visible child item for (int i = 0; i < this.Count; i++) { ViewBase child = this[i]; // Only interested in visible items if (child.Visible) { // Are we positioning a cluster? if (child is ViewLayoutRibbonGroupCluster) { // Inform cluster if it is immediatley after another cluster (and so potentially needs a separator) ViewLayoutRibbonGroupCluster clusterChild = (ViewLayoutRibbonGroupCluster)child; clusterChild.StartSeparator = (previousChild != null) && !(previousChild is ViewLayoutRibbonGroupCluster); clusterChild.EndSeparator = true; } // Can we calculate the spacing gap between the previous and this item if (previousChild != null) { if (_viewToItem.ContainsKey(child) && _viewToItem.ContainsKey(previousChild)) { // Cast to correct type IRibbonGroupItem childItem = _viewToItem[child] as IRibbonGroupItem; IRibbonGroupItem previousItem = _viewToItem[previousChild] as IRibbonGroupItem; // Find the requested gap between them _viewToGap.Add(child, childItem.ItemGap(previousItem)); } else { // Default the gap _viewToGap.Add(child, DEFAULT_GAP); } } // Get requested size of the child Size childSize = child.GetPreferredSize(context); // Add to list of visible child sizes _sizeList.Add(childSize); _viewList.Add(child); // Cache total visible width for later totalWidth += childSize.Width; // This is now the previous child previousChild = child; } } // Find the item size specific preferred calculation switch (_currentSize) { case GroupItemSize.Large: return(LargeMediumPreferredSize(totalWidth, ref _split1Large)); case GroupItemSize.Medium: return(LargeMediumPreferredSize(totalWidth, ref _split1Medium)); case GroupItemSize.Small: return(SmallPreferredSize(totalWidth)); default: // Should never happen! Debug.Assert(false); return(Size.Empty); } }
private void SmallLayout(ViewLayoutContext context) { int x = ClientLocation.X; int y = ClientLocation.Y; // At design time we reserve space at the left side for the selection flap if (_ribbon.InDesignHelperMode) { x += DesignTimeDraw.FlapWidth; } ViewBase previousChild = null; // Position the visible items in turn for (int i = 0, visibleIndex = 0; i < this.Count; i++) { ViewBase child = this[i]; // We only position visible items if (child.Visible) { // Are we positioning a cluster? if (child is ViewLayoutRibbonGroupCluster) { // Inform cluster if it is immediatley after another item and so needs a start separator ViewLayoutRibbonGroupCluster clusterChild = (ViewLayoutRibbonGroupCluster)child; clusterChild.StartSeparator = (previousChild != null) && !(previousChild is ViewLayoutRibbonGroupCluster); clusterChild.EndSeparator = false; } if ((previousChild != null) && (previousChild is ViewLayoutRibbonGroupCluster)) { // Inform cluster if it is before another item and so needs an end separator ViewLayoutRibbonGroupCluster clusterChild = (ViewLayoutRibbonGroupCluster)previousChild; clusterChild.EndSeparator = true; // Need to layout the item again with the new setting context.DisplayRectangle = new Rectangle(previousChild.ClientLocation.X, previousChild.ClientLocation.Y, previousChild.ClientWidth, previousChild.ClientHeight); previousChild.Layout(context); } // If not the first item on the line, then get the pixel gap between them if ((previousChild != null) && _viewToGap.ContainsKey(child)) { x += _viewToGap[child]; } // Get the size of the child item Size childSize = _sizeList[visibleIndex]; // Define display rectangle for the group context.DisplayRectangle = new Rectangle(x, y, childSize.Width, childSize.Height); // Position the element this[i].Layout(context); // Do we need to split after this item if ((_split1Small == visibleIndex) || (_split2Small == visibleIndex)) { // Move back to start of line and downwards to next line x = ClientLocation.X; // At design time we reserve space at the left side for the selection flap if (_ribbon.InDesignHelperMode) { x += DesignTimeDraw.FlapWidth; } y += _ribbon.CalculatedValues.GroupLineHeight; // As last item on the line, there is no previous item on next line previousChild = null; } else { // Move across to next position x += childSize.Width; // We have become the previous child previousChild = child; } // Not all child items are visible, so track separately visibleIndex++; } } }