/// <summary> /// Initialize a new instance of the MetaWrapPanel class. /// </summary> public MetaWrapPanel() { WrapLayout layout = new WrapLayout(); layout.SetBinding(WrapLayout.ItemWidthProperty, ThisBinding("ItemWidth")); layout.SetBinding(WrapLayout.ItemHeightProperty, ThisBinding("ItemHeight")); layout.SetBinding(WrapLayout.OrientationProperty, ThisBinding("Orientation")); layout.SetBinding(WrapLayout.BreakAfterProperty, ThisBinding("BreakAfter")); Layouts.Add(layout); }
/// <summary> /// Calculate target state for each element based on layout algorithm. /// </summary> /// <param name="layoutId">Identifier of the layout to be used.</param> /// <param name="metaPanel">Reference to owning panel instance.</param> /// <param name="stateDict">Dictionary of per-element state.</param> /// <param name="elements">Collection of elements to be arranged.</param> /// <param name="finalSize">Size that layout should use to arrange child elements.</param> public override void TargetChildren(string layoutId, MetaPanelBase metaPanel, MetaElementStateDict stateDict, ICollection elements, Size finalSize) { // Only apply if we match the incoming layout identifier if (string.IsNullOrEmpty(Id) || Id.Equals(layoutId)) { // Cache the dependancy properties for faster perf double itemWidth = ItemWidth; double itemHeight = ItemHeight; Orientation orientation = Orientation; // Cache if the defined sizes are valid bool itemWidthDefined = !double.IsNaN(ItemWidth); bool itemHeightDefined = !double.IsNaN(itemHeight); // Find size we provide to each child for measuring against, we use item sizes if defined Size elementSize = new Size(itemWidthDefined ? itemWidth : double.PositiveInfinity, itemHeightDefined ? itemHeight : double.PositiveInfinity); // Measure each element in turn int current = 0; double lineOffset = 0; double lineMax = 0; double positionOffset = 0; bool breakAfter = false; List <UIElement> targets = new List <UIElement>(); foreach (UIElement element in elements) { // We ignore items being removed if (stateDict[element].Status != MetaElementStatus.Removing) { // Decide on the actual size we will allocate to the element Size childSize = new Size(itemWidthDefined ? itemWidth : element.DesiredSize.Width, itemHeightDefined ? itemHeight : element.DesiredSize.Height); // Calculation depends on orientation if (orientation == Orientation.Horizontal) { // Does this element overflow the line? if (breakAfter || (((lineOffset + childSize.Width) > finalSize.Width) && (current > 0))) { // Create position targets for items on this line TargetLine(stateDict, targets, positionOffset, lineMax, itemWidthDefined, itemHeightDefined, itemWidth, itemHeight, finalSize, orientation); // Move positioning down by height of the line positionOffset += lineMax; // Start at the left edge of the next line lineOffset = 0; lineMax = 0; targets.Clear(); } // Position the child on the current line lineOffset += childSize.Width; lineMax = Math.Max(lineMax, childSize.Height); } else { // Does this element overflow the line? if (breakAfter || (((lineOffset + childSize.Height) > finalSize.Height) && (current > 0))) { // Create position targets for items on this line TargetLine(stateDict, targets, positionOffset, lineMax, itemWidthDefined, itemHeightDefined, itemWidth, itemHeight, finalSize, orientation); // Move positioning down by height of the line positionOffset += lineMax; // Start at the left edge of the next line lineOffset = 0; lineMax = 0; targets.Clear(); } // Position the child on the current line lineOffset += childSize.Height; lineMax = Math.Max(lineMax, childSize.Width); } targets.Add(element); current++; // Do we perform a line break after this element breakAfter = WrapLayout.GetBreakAfter(element); } } // Remember to take into account the last line TargetLine(stateDict, targets, positionOffset, lineMax, itemWidthDefined, itemHeightDefined, itemWidth, itemHeight, finalSize, orientation); } }
/// <summary> /// Measure the layout size required to arrange all elements. /// </summary> /// <param name="layoutId">Identifier of the layout to be used.</param> /// <param name="metaPanel">Reference to owning panel instance.</param> /// <param name="stateDict">Dictionary of per-element state.</param> /// <param name="elements">Collection of elements to be measured.</param> /// <param name="availableSize">Available size that can be given to elements.</param> /// <returns>Size the layout determines it needs based on child element sizes.</returns> public override Size MeasureChildren(string layoutId, MetaPanelBase metaPanel, MetaElementStateDict stateDict, ICollection elements, Size availableSize) { // Only apply if we match the incoming layout identifier if (string.IsNullOrEmpty(Id) || Id.Equals(layoutId)) { // Cache the dependancy properties for faster perf double itemWidth = ItemWidth; double itemHeight = ItemHeight; Orientation orientation = Orientation; // Cache if the defined sizes are valid bool itemWidthDefined = !double.IsNaN(ItemWidth); bool itemHeightDefined = !double.IsNaN(itemHeight); // Find size we provide to each child for measuring against, we use item sizes if defined Size elementSize = new Size(itemWidthDefined ? itemWidth : double.PositiveInfinity, itemHeightDefined ? itemHeight : double.PositiveInfinity); // Measure each element in turn bool breakAfter = false; double lineMax = 0; double lineOffset = 0; Size measureSize = new Size(); foreach (UIElement element in elements) { element.Measure(elementSize); // We ignore items being removed if (stateDict[element].Status != MetaElementStatus.Removing) { // Decide on the actual size we will allocate to the element Size childSize = new Size(itemWidthDefined ? itemWidth : element.DesiredSize.Width, itemHeightDefined ? itemHeight : element.DesiredSize.Height); // Calculation depends on orientation if (orientation == Orientation.Horizontal) { // Does this element overflow the line? if (breakAfter || (((lineOffset + childSize.Width) > availableSize.Width) && !measureSize.IsEmpty)) { // Total measured size is equal to the widest line and tallest item per line measureSize.Width = Math.Max(measureSize.Width, lineOffset); measureSize.Height += lineMax; // Start at the left edge of the next line lineOffset = 0; lineMax = 0; } // Position the child on the current line lineOffset += childSize.Width; lineMax = Math.Max(lineMax, childSize.Height); } else { // Does this element overflow the line? if (breakAfter || (((lineOffset + childSize.Height) > availableSize.Height) && !measureSize.IsEmpty)) { // Total measured size is equal to the tallest line and widest item per line measureSize.Height = Math.Max(measureSize.Height, lineOffset); measureSize.Width += lineMax; // Start at the top edge of the next line lineOffset = 0; lineMax = 0; } // Position the child on the current line lineOffset += childSize.Height; lineMax = Math.Max(lineMax, childSize.Width); } // Do we perform a line break after this element breakAfter = WrapLayout.GetBreakAfter(element); } } // Remember to take into account the last line if (orientation == Orientation.Horizontal) { // Total measured size is equal to the widest line and tallest item per line measureSize.Width = Math.Max(measureSize.Width, lineOffset); measureSize.Height += lineMax; } else { // Total measured size is equal to the tallest line and widest item per line measureSize.Height = Math.Max(measureSize.Height, lineOffset); measureSize.Width += lineMax; } // Return minimum size needed to contain all the elements according to their desired sizes return(measureSize); } else { return(Size.Empty); } }
private void Wrap_Click(object sender, RoutedEventArgs e) { ComponentFactory.Quicksilver.Layout.WrapLayout layout = new ComponentFactory.Quicksilver.Layout.WrapLayout(); TargetPanel.LayoutDefinitions.Clear(); TargetPanel.LayoutDefinitions.Add(layout); }