Example #1
0
        /// <summary>
        /// Draws the content of a <see cref="T:System.Windows.Media.DrawingContext" /> object during the render pass of a <see cref="T:System.Windows.Controls.Panel" /> element.
        /// </summary>
        /// <param name="dc">The <see cref="T:System.Windows.Media.DrawingContext" /> object to draw.</param>
        protected override void OnRender(DrawingContext dc)
        {
            base.OnRender(dc);

            if (!ShowGroupHeaders || GroupHeaderRenderer == null)
            {
                return;
            }

            var offsetTop = 0d;

            if (_scrollVertical.Visibility == Visibility.Visible)
            {
                offsetTop = _scrollVertical.Value * -1;
            }

            var currentTop             = offsetTop + Padding.Top;
            var currentGroupIsExpanded = true;

            foreach (var control in _lastControls)
            {
                var lineHeight = 0d;
                if (control.Label != null)
                {
                    lineHeight = control.Label.DesiredSize.Height;
                }
                if (control.Edit != null)
                {
                    lineHeight = Math.Max(lineHeight, control.Edit.DesiredSize.Height);
                }
                lineHeight = SnapToPixel(lineHeight);

                if (control.Label != null && SimpleView.GetGroupBreak(control.Label))
                {
                    var groupTitle = SimpleView.GetGroupTitle(control.Label);
                    if (_renderedGroups.ContainsKey(groupTitle))
                    {
                        currentGroupIsExpanded = _renderedGroups[groupTitle].IsExpanded;

                        var group = _renderedGroups[groupTitle];
                        var width = ActualWidth - Padding.Left - Padding.Right;
                        if (_scrollVertical.Visibility == Visibility.Visible)
                        {
                            width -= SystemParameters.VerticalScrollBarWidth;
                        }
                        dc.PushTransform(new TranslateTransform(Padding.Left, currentTop));
                        GroupHeaderRenderer.RenderHeader(dc, currentTop, width, groupTitle, group.IsExpanded);
                        dc.Pop();
                        group.LastRenderTopPosition = currentTop;

                        currentTop += _renderedGroups[groupTitle].Height;
                    }
                }

                if (currentGroupIsExpanded)
                {
                    currentTop += lineHeight + VerticalElementSpacing;
                }
            }
        }
Example #2
0
        /// <summary>
        /// Invoked when an unhandled MouseDown attached event reaches an element in its route that is derived from this class. Implement this method to add class handling for this event.
        /// </summary>
        /// <param name="e">The <see cref="T:System.Windows.Input.MouseButtonEventArgs" /> that contains the event data. This event data reports details about the mouse button that was pressed and the handled state.</param>
        protected override void OnMouseDown(MouseButtonEventArgs e)
        {
            if (e.LeftButton == MouseButtonState.Pressed && e.ClickCount == 1)
            {
                foreach (var control in _lastControls)
                {
                    if (control.Label != null && SimpleView.GetGroupBreak(control.Label))
                    {
                        var groupTitle = SimpleView.GetGroupTitle(control.Label);
                        if (_renderedGroups.ContainsKey(groupTitle))
                        {
                            var group     = _renderedGroups[groupTitle];
                            var y         = group.LastRenderTopPosition;
                            var positionY = e.GetPosition(this).Y;
                            if (positionY >= y && positionY <= y + group.Height)
                            {
                                e.Handled        = true;
                                group.IsExpanded = !group.IsExpanded;
                                InvalidateMeasure();
                                InvalidateArrange();
                                InvalidateVisual();
                                return;
                            }
                        }
                    }
                }
            }

            base.OnMouseDown(e);
        }
Example #3
0
        /// <summary>
        /// Arranges the content of a <see cref="T:System.Windows.Controls.StackPanel"/> element.
        /// </summary>
        /// <param name="arrangeSize">The <see cref="T:System.Windows.Size"/> that this element should use to arrange its child elements.</param>
        /// <returns>
        /// The <see cref="T:System.Windows.Size"/> that represents the arranged size of this <see cref="T:System.Windows.Controls.StackPanel"/> element and its child elements.
        /// </returns>
        protected override Size ArrangeOverride(Size arrangeSize)
        {
            var top    = 0d;
            var left   = 0d;
            var bottom = 0d;
            var right  = 0d;

            var usableWidth  = _calculatedContentWidth;
            var usableHeight = _calculatedContentHeight;

            if (Orientation == Orientation.Vertical)
            {
                usableWidth = Math.Max(usableWidth, arrangeSize.Width);
            }
            else
            {
                usableHeight = Math.Max(usableHeight, arrangeSize.Height);
            }

            var extraMargin = ChildItemMargin;

            var topElements    = new List <FrameworkElement>();
            var bottomElements = new List <FrameworkElement>();

            if (Orientation == Orientation.Vertical && _scrollVertical.Visibility == Visibility.Visible)
            {
                top          = _scrollVertical.Value * -1;
                usableWidth -= _scrollVertical.ActualWidth + 2;
            }
            else if (Orientation == Orientation.Horizontal && _scrollHorizontal.Visibility == Visibility.Visible)
            {
                left          = _scrollHorizontal.Value * -1;
                usableHeight -= _scrollHorizontal.ActualHeight + 2;
            }

            var contentSize = GeometryHelper.NewSize(usableWidth, usableHeight);

            var topOrigin  = top;
            var leftOrigin = left;

            foreach (var element2 in Children.OfType <FrameworkElement>().Where(e => e.Visibility != Visibility.Collapsed))
            {
                if (Orientation == Orientation.Vertical)
                {
                    if (element2.VerticalAlignment != VerticalAlignment.Bottom)
                    {
                        topElements.Add(element2);
                    }
                    else
                    {
                        bottomElements.Add(element2);
                    }
                }
                else if (element2.HorizontalAlignment != HorizontalAlignment.Right)
                {
                    topElements.Add(element2);
                }
                else
                {
                    bottomElements.Add(element2);
                }
            }

            // Calculating the height of the bottom items
            foreach (var element in bottomElements)
            {
                if (Orientation == Orientation.Vertical)
                {
                    var extraBottom = extraMargin.Bottom;
                    if (element is TextBlock || element is Label)
                    {
                        if (IgnoreChildItemBottomMarginForTextElements)
                        {
                            extraBottom = 0;
                        }
                    }
                    bottom += element.DesiredSize.Height + extraMargin.Top + extraBottom;
                    if (SimpleView.GetGroupBreak(element))
                    {
                        bottom += GroupSpacing;
                    }
                }
                else
                {
                    right += element.DesiredSize.Width;
                    if (SimpleView.GetGroupBreak(element))
                    {
                        right += GroupSpacing;
                    }
                }
            }

            var topCounter = 0;

            foreach (var element2 in topElements)
            {
                topCounter++;
                var extraBottom = extraMargin.Bottom;
                if (element2 is TextBlock || element2 is Label)
                {
                    if (IgnoreChildItemBottomMarginForTextElements)
                    {
                        extraBottom = 0;
                    }
                }
                var desiredSize = GeometryHelper.NewSize(element2.DesiredSize.Width + extraMargin.Left + extraMargin.Right, element2.DesiredSize.Height + extraMargin.Top + extraBottom);
                if (Orientation == Orientation.Vertical)
                {
                    // Top Alignment
                    if (topCounter < topElements.Count || !LastTopItemFillsSpace)
                    {
                        if (SimpleView.GetGroupBreak(element2))
                        {
                            top += GroupSpacing;
                        }
                        element2.Arrange(GeometryHelper.NewRect(extraMargin.Left, top + extraMargin.Top, contentSize.Width - extraMargin.Left - extraMargin.Right, element2.DesiredSize.Height));
                        top += desiredSize.Height;
                    }
                    else
                    {
                        var elementAutoSizeHeight = Math.Max(0, usableHeight + topOrigin - top - bottom - extraMargin.Top - extraMargin.Bottom - LastTopItemFillMargin);
                        element2.Arrange(GeometryHelper.NewRect(extraMargin.Left, top + extraMargin.Top, contentSize.Width - extraMargin.Left - extraMargin.Right - extraMargin.Left, elementAutoSizeHeight));
                        top += elementAutoSizeHeight;
                    }
                }
                else
                {
                    // Left Alignment
                    if (topCounter < topElements.Count || !LastTopItemFillsSpace)
                    {
                        if (SimpleView.GetGroupBreak(element2))
                        {
                            left += GroupSpacing;
                        }
                        element2.Arrange(GeometryHelper.NewRect(left + extraMargin.Left, extraMargin.Top, element2.DesiredSize.Width, contentSize.Height - extraBottom));
                        left += desiredSize.Width;
                    }
                    else
                    {
                        var elementAutoSizeWidth = Math.Max(0, usableWidth + leftOrigin - left - right - extraMargin.Left - extraMargin.Right - LastTopItemFillMargin);
                        element2.Arrange(GeometryHelper.NewRect(left + extraMargin.Left, extraMargin.Top, elementAutoSizeWidth, contentSize.Height - extraBottom - extraMargin.Top));
                        left += elementAutoSizeWidth;
                    }
                }
            }

            // Second pass to arrange the elements on the "other side"
            var availableHeight = contentSize.Height;
            var availableWidth  = contentSize.Width;
            var top2            = topOrigin + availableHeight - bottom - extraMargin.Top;

            if (top2 < top)
            {
                top2 = top;             // Can't overlap the items that are already there
            }
            var left2 = leftOrigin + availableWidth - right;

            if (left2 < left)
            {
                left2 = left;               // Can't overlap the items that are already there
            }
            foreach (var element2 in bottomElements)
            {
                var extraBottom = extraMargin.Bottom;
                if (element2 is TextBlock || element2 is Label)
                {
                    if (IgnoreChildItemBottomMarginForTextElements)
                    {
                        extraBottom = 0;
                    }
                }
                var desiredSize = GeometryHelper.NewSize(element2.DesiredSize.Width + extraMargin.Left + extraMargin.Right, element2.DesiredSize.Height + extraMargin.Top + extraBottom);
                if (Orientation == Orientation.Vertical)
                {
                    if (SimpleView.GetGroupBreak(element2))
                    {
                        top2 += GroupSpacing;
                    }
                    element2.Arrange(GeometryHelper.NewRect(extraMargin.Left, top2 + extraMargin.Top, contentSize.Width - extraMargin.Left - extraMargin.Right, element2.DesiredSize.Height));
                    top2 += desiredSize.Height;
                }
                else
                {
                    if (SimpleView.GetGroupBreak(element2))
                    {
                        left2 += GroupSpacing;
                    }
                    element2.Arrange(GeometryHelper.NewRect(left2 + extraMargin.Left, extraMargin.Top, element2.DesiredSize.Width, contentSize.Height - extraMargin.Top - extraBottom));
                    left2 += desiredSize.Width;
                }
            }

            return(arrangeSize);
        }
Example #4
0
        /// <summary>
        /// Measures the child elements of a <see cref="T:System.Windows.Controls.StackPanel"/> in anticipation of arranging them during the <see cref="M:System.Windows.Controls.StackPanel.ArrangeOverride(System.Windows.Size)"/> pass.
        /// </summary>
        /// <param name="constraint">An upper limit <see cref="T:System.Windows.Size"/> that should not be exceeded.</param>
        /// <returns>
        /// The <see cref="T:System.Windows.Size"/> that represents the desired size of the element.
        /// </returns>
        protected override Size MeasureOverride(Size constraint)
        {
            var topUsed    = 0d;
            var bottomUsed = 0d;
            var leftUsed   = 0d;
            var rightUsed  = 0d;

            var extraMargin = ChildItemMargin;

            var topElements    = new List <FrameworkElement>();
            var bottomElements = new List <FrameworkElement>();

            if (Orientation == Orientation.Vertical && _scrollVertical.Visibility == Visibility.Visible)
            {
                constraint.Width = Math.Max(constraint.Width - _scrollVertical.ActualWidth, 0d);
            }
            else if (Orientation == Orientation.Horizontal && _scrollHorizontal.Visibility == Visibility.Visible)
            {
                constraint.Height = Math.Max(constraint.Height - _scrollHorizontal.ActualHeight, 0d);
            }

            foreach (var element2 in Children.OfType <FrameworkElement>().Where(e => e.Visibility != Visibility.Collapsed))
            {
                if (Orientation == Orientation.Vertical)
                {
                    if (element2.VerticalAlignment != VerticalAlignment.Bottom)
                    {
                        topElements.Add(element2);
                    }
                    else
                    {
                        bottomElements.Add(element2);
                    }
                }
                else if (element2.HorizontalAlignment != HorizontalAlignment.Right)
                {
                    topElements.Add(element2);
                }
                else
                {
                    bottomElements.Add(element2);
                }
            }

            // starting with the bottom elements
            foreach (var element2 in bottomElements)
            {
                if (Orientation == Orientation.Vertical)
                {
                    element2.Measure(new Size(constraint.Width, double.PositiveInfinity));
                }
                else
                {
                    element2.Measure(new Size(double.PositiveInfinity, constraint.Height));
                }
                var extraBottom = extraMargin.Bottom;
                if (element2 is TextBlock || element2 is Label)
                {
                    if (IgnoreChildItemBottomMarginForTextElements)
                    {
                        extraBottom = 0;
                    }
                }
                var desiredSize = GeometryHelper.NewSize(element2.DesiredSize.Width + extraMargin.Left + extraMargin.Right, element2.DesiredSize.Height + extraMargin.Top + extraBottom);
                if (Orientation == Orientation.Vertical)
                {
                    bottomUsed += desiredSize.Height;
                    leftUsed    = Math.Max(leftUsed, desiredSize.Width);
                }
                else
                {
                    rightUsed += desiredSize.Width;
                    topUsed    = Math.Max(topUsed, desiredSize.Height);
                }
            }

            // now for the top elements
            var topCounter = 0;

            foreach (var element2 in topElements)
            {
                topCounter++;
                var constraint2 = constraint;
                var extraBottom = extraMargin.Bottom;
                if (topCounter == topElements.Count && LastTopItemFillsSpace)
                {
                    if (Orientation == Orientation.Vertical && !double.IsInfinity(constraint.Height) && constraint.Height > 0)
                    {
                        constraint2 = GeometryHelper.NewSize(constraint.Width, Math.Max(element2.MinHeight, constraint.Height - topUsed - bottomUsed - LastTopItemFillMargin - extraMargin.Top - extraBottom));
                        extraBottom = LastTopItemFillMargin;
                    }
                    else if (Orientation == Orientation.Horizontal && !double.IsInfinity(constraint.Width) && constraint.Width > 0)
                    {
                        constraint2 = GeometryHelper.NewSize(Math.Max(element2.MinWidth, constraint.Width - leftUsed - rightUsed - LastTopItemFillMargin), constraint.Height);
                        extraBottom = LastTopItemFillMargin;
                    }
                }
                else
                {
                    if (Orientation == Orientation.Vertical)
                    {
                        constraint2 = new Size(constraint2.Width, double.PositiveInfinity);
                    }
                    else
                    {
                        constraint2 = new Size(double.PositiveInfinity, constraint2.Height);
                    }
                }
                element2.Measure(constraint2);
                if (element2 is TextBlock || element2 is Label)
                {
                    if (IgnoreChildItemBottomMarginForTextElements)
                    {
                        extraBottom = 0;
                    }
                }
                var desiredSize = GeometryHelper.NewSize(Math.Max(0, element2.DesiredSize.Width + extraMargin.Left + extraMargin.Right), Math.Max(0, element2.DesiredSize.Height + extraMargin.Top + extraBottom));
                if (Orientation == Orientation.Vertical)
                {
                    topUsed += desiredSize.Height;
                    leftUsed = Math.Max(leftUsed, desiredSize.Width);
                    if (SimpleView.GetGroupBreak(element2))
                    {
                        leftUsed += GroupSpacing;
                    }
                }
                else
                {
                    leftUsed += desiredSize.Width;
                    topUsed   = Math.Max(topUsed, desiredSize.Height);
                    if (SimpleView.GetGroupBreak(element2))
                    {
                        topUsed += GroupSpacing;
                    }
                }
            }

            var widthUsed  = leftUsed + rightUsed;
            var heightUsed = topUsed + bottomUsed;

            if (Orientation == Orientation.Vertical && !double.IsInfinity(constraint.Width) && constraint.Width > 0)
            {
                widthUsed = Math.Min(constraint.Width, widthUsed); // In vertical orientation, we use no more than the width available to us
            }
            if (Orientation == Orientation.Horizontal && !double.IsInfinity(constraint.Width) && constraint.Width > 0 && widthUsed < constraint.Width)
            {
                widthUsed = Math.Min(constraint.Width, widthUsed); // In horizontal orientation, if we haven't used up the entire width yet, we occupy the entire available space
            }
            if (Orientation == Orientation.Horizontal && !double.IsInfinity(constraint.Height) && constraint.Height > 0)
            {
                heightUsed = Math.Min(constraint.Height, heightUsed); // In horizontal orientation, we use no more than the height available to us
            }
            if (Orientation == Orientation.Vertical && !double.IsInfinity(constraint.Height) && constraint.Height > 0 && heightUsed < constraint.Height)
            {
                heightUsed = Math.Min(constraint.Height, heightUsed); // In vertical orientation, if we haven't used up the entire height yet, we occupy the entire available space
            }
            if (Orientation == Orientation.Vertical)
            {
                _calculatedContentHeight = double.IsInfinity(constraint.Height) ? heightUsed : Math.Max(constraint.Height, heightUsed);
                _calculatedContentWidth  = widthUsed;
            }
            else
            {
                _calculatedContentHeight = heightUsed;
                _calculatedContentWidth  = double.IsInfinity(constraint.Width) ? widthUsed : Math.Max(constraint.Width, widthUsed);
            }

            var finalSize = GeometryHelper.NewSize(widthUsed, heightUsed);

            // Checking if this forces us to change scroll bar visibility and thus invalidate everything
            if (Orientation == Orientation.Vertical)
            {
                if (heightUsed > constraint.Height)
                {
                    if (_scrollVertical.Visibility != Visibility.Visible && ScrollBarMode == BidirectionalStackPanelScrollBarModes.Automatic)
                    {
                        _scrollVertical.Visibility = Visibility.Visible;
                        InvalidateAllVisuals(this); // Triggers recalculation of everything with a visible scroll bar
                    }
                    _scrollVertical.Maximum      = _calculatedContentHeight - constraint.Height;
                    _scrollVertical.ViewportSize = constraint.Height;
                    _scrollVertical.LargeChange  = constraint.Height;
                    finalSize.Height             = constraint.Height;
                }
                else if (heightUsed <= constraint.Height && _scrollVertical.Visibility != Visibility.Collapsed)
                {
                    _scrollVertical.Visibility = Visibility.Collapsed;
                    InvalidateAllVisuals(this);
                }
            }
            else
            {
                if (widthUsed > constraint.Width)
                {
                    if (_scrollHorizontal.Visibility != Visibility.Visible && ScrollBarMode == BidirectionalStackPanelScrollBarModes.Automatic)
                    {
                        _scrollHorizontal.Visibility = Visibility.Visible;
                        InvalidateAllVisuals(this); // Triggers recalculation of everything with a visible scroll bar
                    }
                    _scrollHorizontal.Maximum      = _calculatedContentWidth - constraint.Width;
                    _scrollHorizontal.LargeChange  = constraint.Width;
                    _scrollHorizontal.ViewportSize = constraint.Width;
                    finalSize.Width = constraint.Width;
                }
                else if (widthUsed <= constraint.Width && _scrollHorizontal.Visibility != Visibility.Collapsed)
                {
                    _scrollHorizontal.Visibility = Visibility.Collapsed;
                    InvalidateAllVisuals(this);
                }
            }

            if (Orientation == Orientation.Vertical && _scrollVertical.Visibility == Visibility.Visible)
            {
                finalSize.Width += _scrollVertical.ActualWidth;
            }
            else if (Orientation == Orientation.Horizontal && _scrollHorizontal.Visibility == Visibility.Visible)
            {
                finalSize.Height += _scrollHorizontal.ActualHeight;
            }

            return(finalSize);
        }
Example #5
0
        /// <summary>
        /// When overridden in a derived class, positions child elements and determines a size for a <see cref="T:System.Windows.FrameworkElement" /> derived class.
        /// </summary>
        /// <param name="finalSize">The final area within the parent that this element should use to arrange itself and its children.</param>
        /// <returns>The actual size used.</returns>
        protected override Size ArrangeOverride(Size finalSize)
        {
            var finalSizeInternal = finalSize;

            if (Padding.Top > 0 || Padding.Bottom > 0 || Padding.Right > 0 || Padding.Left > 0)
            {
                var availableHeight = finalSize.Height - Padding.Top - Padding.Bottom;
                if (availableHeight < 0d)
                {
                    availableHeight = 0d;
                }
                var availableWidth = finalSize.Width - Padding.Left - Padding.Right;
                if (availableWidth < 0d)
                {
                    availableWidth = 0d;
                }
                finalSizeInternal = GeometryHelper.NewSize(availableWidth, availableHeight);
            }

            if (_lastControls == null)
            {
                return(base.ArrangeOverride(finalSize));
            }

            var finalWidth = finalSizeInternal.Width;

            if (_scrollVertical.Visibility == Visibility.Visible)
            {
                finalWidth = Math.Max(finalWidth - SystemParameters.VerticalScrollBarWidth, 1);
            }

            var offsetTop = 0d;

            if (_scrollVertical.Visibility == Visibility.Visible)
            {
                offsetTop = _scrollVertical.Value * -1;
            }

            var currentTop = offsetTop + Padding.Top;

            if (!ShowGroupHeaders || GroupHeaderRenderer == null)
            {
                foreach (var control in _lastControls)
                {
                    var lineHeight = 0d;
                    if (control.Label != null)
                    {
                        lineHeight = control.Label.DesiredSize.Height;
                    }
                    if (control.Edit != null)
                    {
                        lineHeight = Math.Max(lineHeight, control.Edit.DesiredSize.Height);
                    }
                    lineHeight = SnapToPixel(lineHeight);

                    if (control.Label != null)
                    {
                        if (!control.LabelSpansFullWidth)
                        {
                            control.Label.Arrange(GeometryHelper.NewRect(Padding.Left, currentTop, _labelWidth, lineHeight));
                        }
                        else
                        {
                            control.Label.Arrange(GeometryHelper.NewRect(Padding.Left, currentTop, SnapToPixel(finalWidth), lineHeight));
                        }
                    }
                    if (control.Edit != null && !control.LabelSpansFullWidth)
                    {
                        var editLeft  = SnapToPixel(_labelWidth + HorizontalElementSpacing + Padding.Left);
                        var editWidth = Math.Max(SnapToPixel(finalWidth - editLeft + Padding.Left), 0);

                        for (var flowControlCounter = control.AdditionalEditControls.Count - 1; flowControlCounter >= 0; flowControlCounter--)
                        {
                            var flowControl = control.AdditionalEditControls[flowControlCounter];
                            var flowWidth   = Math.Min(flowControl.DesiredSize.Width, editWidth);
                            flowControl.Arrange(GeometryHelper.NewRect(editLeft + editWidth - flowWidth, currentTop, flowWidth, lineHeight));
                            editWidth -= (flowWidth + AdditionalFlowElementSpacing);
                            if (editWidth < 0.1)
                            {
                                editWidth = 0d;
                            }
                        }

                        control.Edit.Arrange(GeometryHelper.NewRect(editLeft, currentTop, editWidth, lineHeight));
                    }
                    currentTop += lineHeight + VerticalElementSpacing;
                }
            }
            else
            {
                var itemIndent             = GroupHeaderRenderer.GetHeaderPaddingUsedForRendering("X").Left;
                var currentGroupIsExpanded = true;
                foreach (var control in _lastControls)
                {
                    var lineHeight = 0d;
                    if (control.Label != null)
                    {
                        lineHeight = control.Label.DesiredSize.Height;
                    }
                    if (control.Edit != null)
                    {
                        lineHeight = Math.Max(lineHeight, control.Edit.DesiredSize.Height);
                    }
                    lineHeight = SnapToPixel(lineHeight);

                    if (control.Label != null && SimpleView.GetGroupBreak(control.Label))
                    {
                        var groupTitle = SimpleView.GetGroupTitle(control.Label);
                        if (_renderedGroups.ContainsKey(groupTitle))
                        {
                            currentGroupIsExpanded = _renderedGroups[groupTitle].IsExpanded;
                            currentTop            += _renderedGroups[groupTitle].Height;
                        }
                    }

                    if (currentGroupIsExpanded)
                    {
                        if (control.Label != null)
                        {
                            control.Label.Visibility = Visibility.Visible;
                            if (!control.LabelSpansFullWidth)
                            {
                                control.Label.Arrange(GeometryHelper.NewRect(Padding.Left + itemIndent, currentTop, _labelWidth, lineHeight));
                            }
                            else
                            {
                                control.Label.Arrange(GeometryHelper.NewRect(Padding.Left + itemIndent, currentTop, SnapToPixel(finalWidth - itemIndent), lineHeight));
                            }
                        }
                        if (control.Edit != null)
                        {
                            control.Edit.Visibility = Visibility.Visible;
                            var editLeft  = SnapToPixel(_labelWidth + HorizontalElementSpacing + Padding.Left + itemIndent);
                            var editWidth = Math.Max(SnapToPixel(finalWidth - editLeft + Padding.Left), 0);

                            for (var flowControlCounter = control.AdditionalEditControls.Count - 1; flowControlCounter >= 0; flowControlCounter--)
                            {
                                var flowControl = control.AdditionalEditControls[flowControlCounter];
                                var flowWidth   = Math.Min(flowControl.DesiredSize.Width, editWidth);
                                flowControl.Visibility = Visibility.Visible;
                                flowControl.Arrange(GeometryHelper.NewRect(editLeft + editWidth - flowWidth, currentTop, flowWidth, lineHeight));
                                editWidth -= (flowWidth + AdditionalFlowElementSpacing);
                                if (editWidth < 0.1)
                                {
                                    editWidth = 0d;
                                }
                            }

                            control.Edit.Arrange(GeometryHelper.NewRect(editLeft, currentTop, editWidth, lineHeight));
                        }
                        currentTop += lineHeight + VerticalElementSpacing;
                    }
                    else
                    {
                        if (control.Label != null)
                        {
                            control.Label.Visibility = Visibility.Collapsed;
                        }
                        if (control.Edit != null)
                        {
                            control.Edit.Visibility = Visibility.Collapsed;
                        }
                        foreach (var flowControl in control.AdditionalEditControls)
                        {
                            flowControl.Visibility = Visibility.Collapsed;
                        }
                    }
                }
            }

            return(base.ArrangeOverride(finalSize));
        }
Example #6
0
        /// <summary>
        /// When overridden in a derived class, measures the size in layout required for child elements and determines a size for the <see cref="T:System.Windows.FrameworkElement" />-derived class.
        /// </summary>
        /// <param name="availableSize">The available size that this element can give to child elements. Infinity can be specified as a value to indicate that the element will size to whatever content is available.</param>
        /// <returns>The size that this element determines it needs during layout, based on its calculations of child element sizes.</returns>
        protected override Size MeasureOverride(Size availableSize)
        {
            var availableSizeInternal = availableSize;

            if (Padding.Top > 0 || Padding.Bottom > 0 || Padding.Right > 0 || Padding.Left > 0)
            {
                var availableHeight = availableSize.Height - Padding.Top - Padding.Bottom;
                if (availableHeight < 0d)
                {
                    availableHeight = 0d;
                }
                var availableWidth = availableSize.Width - Padding.Left - Padding.Right;
                if (availableWidth < 0d)
                {
                    availableWidth = 0d;
                }
                availableSizeInternal = GeometryHelper.NewSize(availableWidth, availableHeight);
            }

            _lastControls = GetControls();
            InvalidateVisual();

            var widestLabel = 0d;
            var totalHeight = 0d;

            var foundGroupHeader = false;
            var groupPadding     = new Thickness();

            if (ShowGroupHeaders && GroupHeaderRenderer != null)
            {
                foundGroupHeader = _lastControls.Where(c => c.Label != null).Any(control => !string.IsNullOrEmpty(SimpleView.GetGroupTitle(control.Label)));
            }
            if (foundGroupHeader)
            {
                groupPadding          = GroupHeaderRenderer.GetHeaderPaddingUsedForRendering("X");
                availableSizeInternal = GeometryHelper.NewSize(Math.Max(availableSizeInternal.Width - groupPadding.Left, 0), Math.Max(availableSizeInternal.Height, 0));
            }

            foreach (var control in _lastControls.Where(c => c.Label != null))
            {
                control.Label.Measure(availableSizeInternal);
                if (!control.LabelSpansFullWidth) // For widest-label measurements, we do not consider span labels, since they always use the full width
                {
                    widestLabel = Math.Max(control.Label.DesiredSize.Width, widestLabel);
                }
            }
            foreach (var control in _lastControls.Where(c => !c.LabelSpansFullWidth && c.Edit != null))
            {
                var currentMaxWidth = SnapToPixel(availableSizeInternal.Width - widestLabel - HorizontalElementSpacing - groupPadding.Left);
                for (var flowControlCounter = control.AdditionalEditControls.Count - 1; flowControlCounter >= 0; flowControlCounter--)
                {
                    var flowControl       = control.AdditionalEditControls[flowControlCounter];
                    var availableEditSize = GeometryHelper.NewSize(currentMaxWidth, availableSize.Height);
                    flowControl.Measure(availableEditSize);
                    currentMaxWidth = Math.Max(SnapToPixel(currentMaxWidth - flowControl.DesiredSize.Width), 0);
                }
                control.Edit.Measure(GeometryHelper.NewSize(currentMaxWidth, availableSize.Height));
            }

            var currentGroupIsExpanded = true;

            foreach (var control in _lastControls)
            {
                var itemHeight = 0d;
                if (control.Label != null)
                {
                    itemHeight = control.Label.DesiredSize.Height;
                }
                if (control.Edit != null && !control.LabelSpansFullWidth)
                {
                    itemHeight = Math.Max(itemHeight, control.Edit.DesiredSize.Height);
                    foreach (var flowControl in control.AdditionalEditControls)
                    {
                        itemHeight = Math.Max(itemHeight, flowControl.DesiredSize.Height);
                    }
                }

                itemHeight = SnapToPixel(itemHeight);

                if (ShowGroupHeaders && control.Label != null && GroupHeaderRenderer != null && SimpleView.GetGroupBreak(control.Label))
                {
                    var groupHeader = SimpleView.GetGroupTitle(control.Label) ?? string.Empty;
                    if (!_renderedGroups.ContainsKey(groupHeader))
                    {
                        _renderedGroups.Add(groupHeader, new PropertySheetGroupHeaderInfo {
                            IsExpanded = true
                        });
                    }
                    currentGroupIsExpanded = _renderedGroups[groupHeader].IsExpanded;
                    var currentPadding = GroupHeaderRenderer.GetHeaderPaddingUsedForRendering(string.IsNullOrEmpty(groupHeader) ? "X" : groupHeader);
                    _renderedGroups[groupHeader].Height = currentPadding.Top;
                    totalHeight += SnapToPixel(currentPadding.Top);
                }

                if (currentGroupIsExpanded)
                {
                    totalHeight += itemHeight + VerticalElementSpacing;
                }
            }

            _labelWidth      = widestLabel;
            totalHeight     += Padding.Top + Padding.Bottom;
            _lastTotalHeight = totalHeight;

            HandleScrollBarVisibility(totalHeight, availableSize);

            if (_scrollVertical.Visibility == Visibility.Visible)
            {
                foreach (var control in _lastControls.Where(c => !c.LabelSpansFullWidth && c.Edit != null))
                {
                    var currentMaxWidth = SnapToPixel(SnapToPixel(availableSizeInternal.Width - widestLabel - HorizontalElementSpacing - SystemParameters.VerticalScrollBarWidth - 1));
                    for (var flowControlCounter = control.AdditionalEditControls.Count - 1; flowControlCounter >= 0; flowControlCounter--)
                    {
                        var flowControl       = control.AdditionalEditControls[flowControlCounter];
                        var availableEditSize = GeometryHelper.NewSize(currentMaxWidth, availableSize.Height);
                        flowControl.Measure(availableEditSize);
                        currentMaxWidth = Math.Max(SnapToPixel(currentMaxWidth - flowControl.DesiredSize.Width), 0);
                    }
                    control.Edit.Measure(GeometryHelper.NewSize(currentMaxWidth, availableSize.Height));
                }
            }

            return(GeometryHelper.NewSize(availableSize.Width, Math.Min(totalHeight, availableSize.Height)));
        }