/// <summary>
        /// This method draws additional elements into the main display area
        /// </summary>
        /// <param name="dc">Drawing context</param>
        protected override void CustomRender(DrawingContext dc)
        {
            var primaryTitle   = string.Empty;
            var secondaryTitle = string.Empty;

            foreach (UIElement element in Children)
            {
                var elementType = SimpleView.GetUIElementType(element);
                if (elementType == UIElementTypes.Primary)
                {
                    primaryTitle = SimpleView.GetUIElementTitle(element);
                    break;
                }
            }
            foreach (UIElement element in Children)
            {
                var elementType = SimpleView.GetUIElementType(element);
                if (elementType == UIElementTypes.Secondary)
                {
                    secondaryTitle = SimpleView.GetUIElementTitle(element);
                    break;
                }
            }

            var primaryTitleFont               = PrimaryTitleFont;
            var primaryTitleFontSize           = PrimaryTitleFontSize;
            var primaryTitleBrush1             = PrimaryTitleHeaderBrush;
            var primaryTitleBrush2             = PrimaryTitleFooterBrush;
            var primaryHeaderBackgroundBrush   = PrimaryAreaHeaderBackgroundBrush;
            var secondaryTitleFont             = SecondaryTitleFont;
            var secondaryTitleFontSize         = PrimaryTitleFontSize;
            var secondaryTitleBrush1           = SecondaryTitleHeaderBrush;
            var secondaryTitleBrush2           = SecondaryTitleFooterBrush;
            var secondaryHeaderBackgroundBrush = SecondaryAreaHeaderBackgroundBrush;

            // Calculating the general areas
            var primaryRect = new Rect();

            switch (CalculatedLayout)
            {
            case PrimarySecondaryLayout.PrimaryTopSecondaryBottom:
                primaryRect.Y      = 0d;
                primaryRect.X      = 0d;
                primaryRect.Height = RowDefinitions[0].ActualHeight + RowDefinitions[1].ActualHeight;
                primaryRect.Width  = ActualWidth;
                break;

            case PrimarySecondaryLayout.SecondaryTopPrimaryBottom:
                primaryRect.Y      = RowDefinitions[0].ActualHeight;
                primaryRect.X      = 0d;
                primaryRect.Height = RowDefinitions[1].ActualHeight + RowDefinitions[2].ActualHeight;
                primaryRect.Width  = ActualWidth;
                break;

            case PrimarySecondaryLayout.PrimaryLeftSecondaryRight:
                primaryRect.Y      = 0d;
                primaryRect.X      = 0d;
                primaryRect.Height = ActualHeight;
                primaryRect.Width  = ColumnDefinitions[0].ActualWidth + ColumnDefinitions[1].ActualWidth;
                break;

            case PrimarySecondaryLayout.SecondaryLeftPrimaryRight:
                primaryRect.Y      = 0d;
                primaryRect.X      = ColumnDefinitions[0].ActualWidth;
                primaryRect.Height = ActualHeight;
                primaryRect.Width  = ColumnDefinitions[1].ActualWidth + ColumnDefinitions[2].ActualWidth;
                break;
            }

            var secondaryRect = new Rect();

            switch (CalculatedLayout)
            {
            case PrimarySecondaryLayout.PrimaryTopSecondaryBottom:
                secondaryRect.Y      = RowDefinitions[0].ActualHeight + RowDefinitions[1].ActualHeight;
                secondaryRect.X      = 0d;
                secondaryRect.Height = RowDefinitions[2].ActualHeight;
                secondaryRect.Width  = ActualWidth;
                break;

            case PrimarySecondaryLayout.SecondaryTopPrimaryBottom:
                secondaryRect.Y      = 0d;
                secondaryRect.X      = 0d;
                secondaryRect.Height = RowDefinitions[0].ActualHeight;
                secondaryRect.Width  = ActualWidth;
                break;

            case PrimarySecondaryLayout.PrimaryLeftSecondaryRight:
                secondaryRect.Y      = 0d;
                secondaryRect.X      = ColumnDefinitions[0].ActualWidth + ColumnDefinitions[1].ActualWidth;
                secondaryRect.Height = ActualHeight;
                secondaryRect.Width  = ColumnDefinitions[2].ActualWidth;
                break;

            case PrimarySecondaryLayout.SecondaryLeftPrimaryRight:
                secondaryRect.Y      = 0d;
                secondaryRect.X      = 0d;
                secondaryRect.Height = ActualHeight;
                secondaryRect.Width  = ColumnDefinitions[0].ActualWidth;
                break;
            }

            if (!string.IsNullOrEmpty(primaryTitle))
            {
                var primaryFormattedText1 = new FormattedText(primaryTitle, CultureInfo.CurrentUICulture, FlowDirection.LeftToRight, new Typeface(primaryTitleFont, FontStyles.Normal, FontWeights.Normal, FontStretches.Normal), primaryTitleFontSize, primaryTitleBrush1)
                {
                    MaxTextWidth = secondaryRect.Width - 4, Trimming = TextTrimming.CharacterEllipsis
                };
                var primaryFormattedText2 = new FormattedText(primaryTitle, CultureInfo.CurrentUICulture, FlowDirection.LeftToRight, new Typeface(primaryTitleFont, FontStyles.Normal, FontWeights.Normal, FontStretches.Normal), primaryTitleFontSize, primaryTitleBrush2)
                {
                    MaxTextWidth = secondaryRect.Width - 4, Trimming = TextTrimming.CharacterEllipsis
                };

                var headerRect = new Rect(primaryRect.X + 2, primaryRect.Y + 2, primaryRect.Width - 4, primaryFormattedText1.Height + 4);
                dc.DrawRectangle(primaryHeaderBackgroundBrush, null, headerRect);
                dc.DrawText(primaryFormattedText1, new Point(primaryRect.X + 4, primaryRect.Y + 3));

                var mainAreaRect = new Rect(primaryRect.X + 2, primaryRect.Y + headerRect.Height + 4, primaryRect.Width - 4, primaryRect.Height - 2 - headerRect.Height - primaryFormattedText2.Height - 4);
                dc.DrawRectangle(PrimaryAreaBackgroundBrush, null, mainAreaRect);

                var tabRect = new Rect(primaryRect.X + 2, primaryRect.Y + primaryRect.Height - primaryFormattedText2.Height - 4, Math.Min(primaryRect.Width, primaryFormattedText2.Width + 10), primaryFormattedText2.Height + 4);
                dc.DrawRectangle(PrimaryAreaBackgroundBrush, null, tabRect);
                dc.DrawText(primaryFormattedText2, new Point(tabRect.X + 4, tabRect.Y + 2));
            }
            else if (PrimaryAreaBackgroundBrush != null)
            {
                dc.DrawRectangle(PrimaryAreaBackgroundBrush, null, primaryRect);
            }

            if (!string.IsNullOrEmpty(secondaryTitle))
            {
                var secondaryFormattedText1 = new FormattedText(secondaryTitle, CultureInfo.CurrentUICulture, FlowDirection.LeftToRight, new Typeface(secondaryTitleFont, FontStyles.Normal, FontWeights.Normal, FontStretches.Normal), secondaryTitleFontSize, secondaryTitleBrush1)
                {
                    MaxTextWidth = secondaryRect.Width - 4, Trimming = TextTrimming.CharacterEllipsis
                };
                var secondaryFormattedText2 = new FormattedText(secondaryTitle, CultureInfo.CurrentUICulture, FlowDirection.LeftToRight, new Typeface(secondaryTitleFont, FontStyles.Normal, FontWeights.Normal, FontStretches.Normal), secondaryTitleFontSize, secondaryTitleBrush2)
                {
                    MaxTextWidth = secondaryRect.Width - 4, Trimming = TextTrimming.CharacterEllipsis
                };

                var headerRect = new Rect(secondaryRect.X + 2, secondaryRect.Y + 2, secondaryRect.Width - 4, secondaryFormattedText1.Height + 4);
                dc.DrawRectangle(secondaryHeaderBackgroundBrush, null, headerRect);
                dc.DrawText(secondaryFormattedText1, new Point(secondaryRect.X + 4, secondaryRect.Y + 3));

                var mainAreaRect = new Rect(secondaryRect.X + 2, secondaryRect.Y + headerRect.Height + 4, secondaryRect.Width - 4, secondaryRect.Height - 2 - headerRect.Height - secondaryFormattedText2.Height - 4);
                dc.DrawRectangle(SecondaryAreaBackgroundBrush, null, mainAreaRect);

                var tabRect = new Rect(secondaryRect.X + 2, secondaryRect.Y + secondaryRect.Height - secondaryFormattedText2.Height - 4, Math.Min(secondaryRect.Width, secondaryFormattedText2.Width + 10), secondaryFormattedText2.Height + 4);
                dc.DrawRectangle(SecondaryAreaBackgroundBrush, null, tabRect);
                dc.DrawText(secondaryFormattedText2, new Point(tabRect.X + 4, tabRect.Y + 2));
            }
            else if (SecondaryAreaBackgroundBrush != null)
            {
                dc.DrawRectangle(SecondaryAreaBackgroundBrush, null, secondaryRect);
            }
        }
 /// <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)
 {
     foreach (UIElement element in Children)
     {
         if (SimpleView.GetUIElementType(element) == UIElementTypes.Primary)
         {
             if (CanCollapseSecondary && IsSecondaryElementCollapsed)
             {
                 var minimumCollapsedWidth = 0d;
                 var mainAreaLeft          = 0d;
                 if (HeaderRenderer != null)
                 {
                     minimumCollapsedWidth = HeaderRenderer.GetMinimumCollapsedAreaWidth(this);
                     if (SecondaryAreaLocation == SecondaryAreaLocation.Left)
                     {
                         mainAreaLeft = minimumCollapsedWidth + (minimumCollapsedWidth > 0d ? ElementSpacing : 0d);
                     }
                 }
                 var primaryArea = new Rect(mainAreaLeft, 0d, finalSize.Width - minimumCollapsedWidth - (minimumCollapsedWidth > 0d ? ElementSpacing : 0d), finalSize.Height);
                 if (HeaderRenderer != null)
                 {
                     primaryArea = HeaderRenderer.GetPrimaryClientArea(primaryArea, this);
                 }
                 _currentPrimaryArea = primaryArea;
                 element.Arrange(primaryArea);
             }
             else
             {
                 var currentX = 0d;
                 if (SecondaryAreaLocation == SecondaryAreaLocation.Left)
                 {
                     currentX = SecondaryElementWidth + ElementSpacing;
                 }
                 var primaryArea = new Rect(currentX, 0d, Math.Max(finalSize.Width - SecondaryElementWidth - ElementSpacing, 0), finalSize.Height);
                 if (HeaderRenderer != null)
                 {
                     primaryArea = HeaderRenderer.GetPrimaryClientArea(primaryArea, this);
                 }
                 _currentPrimaryArea = primaryArea;
                 element.Arrange(primaryArea);
             }
         }
         else
         {
             if (CanCollapseSecondary && IsSecondaryElementCollapsed)
             {
                 _currentSecondaryArea = new Rect(-100000d, -100000d, 0d, finalSize.Height);
                 element.Arrange(_currentSecondaryArea);
             }
             else
             {
                 var secondaryArea = SecondaryAreaLocation == SecondaryAreaLocation.Left ? new Rect(0d, 0d, SecondaryElementWidth, finalSize.Height) : new Rect(finalSize.Width - SecondaryElementWidth, 0d, SecondaryElementWidth, finalSize.Height);
                 if (HeaderRenderer != null)
                 {
                     secondaryArea = HeaderRenderer.GetSecondaryClientArea(secondaryArea, this);
                 }
                 _currentSecondaryArea = secondaryArea;
                 element.Arrange(secondaryArea);
             }
         }
     }
     return(base.ArrangeOverride(finalSize));
 }
        /// <summary>
        /// Measures the children of a <see cref="T:System.Windows.Controls.Grid" /> in anticipation of arranging them during the <see cref="M:System.Windows.Controls.Grid.ArrangeOverride(System.Windows.Size)" /> pass.
        /// </summary>
        /// <param name="constraint">Indicates an upper limit size that should not be exceeded.</param>
        /// <returns><see cref="T:System.Windows.Size" /> that represents the required size to arrange child content.</returns>
        protected override Size MeasureOverride(Size constraint)
        {
            var noMargin = new Thickness();

            foreach (var child in Children.OfType <UIElement>().Where(e => e.Visibility != Visibility.Collapsed))
            {
                var element = child as FrameworkElement;
                if (element == null)
                {
                    continue;
                }
                var mode = SimpleView.GetUIElementType(element);
                if (mode == UIElementTypes.Primary)
                {
                    var localMargin = PrimaryUIElementMargin;
                    if (localMargin != noMargin && element.Margin != localMargin)
                    {
                        element.Margin = localMargin;
                    }
                }
                else if (mode == UIElementTypes.Secondary)
                {
                    var localMargin = SecondaryUIElementMargin;
                    if (localMargin != noMargin && element.Margin != localMargin)
                    {
                        element.Margin = localMargin;
                    }
                }
            }

            var size = base.MeasureOverride(constraint);

            bool mustInvalidate; // Used to potentially trigger a secondary measure pass
            var  secondaryElementVisible = true;

            // We find the tallest secondary element. If it is taller than the threshold, we switch to horizontal layout
            var maxHeight = 0d;

            foreach (var element in Children.OfType <UIElement>().Where(e => e.Visibility != Visibility.Collapsed))
            {
                var type = SimpleView.GetUIElementType(element);
                if (type == UIElementTypes.Secondary)
                {
                    if (element.Visibility != Visibility.Visible)
                    {
                        secondaryElementVisible = false;
                        maxHeight = 0;
                    }
                    else
                    {
                        maxHeight = Math.Max(element.DesiredSize.Height, maxHeight);
                    }
                }
            }

            if (maxHeight > SecondaryUIElementAlignmentChangeSize)
            {
                // Going to left/right
                CalculatedLayout = UIElementOrder == PrimarySecondaryOrientation.SecondaryPrimary ? PrimarySecondaryLayout.SecondaryLeftPrimaryRight : PrimarySecondaryLayout.PrimaryLeftSecondaryRight;
                mustInvalidate   = SizeGrid(CalculatedLayout, secondaryElementVisible ? SecondaryUIElementSize : new GridLength(0d));

                UIElement primary   = null;
                var       secondary = new List <UIElement>();

                // We need to assign children to columns
                foreach (var child in Children)
                {
                    var element = child as UIElement;
                    if (element == null)
                    {
                        continue;
                    }
                    var type = SimpleView.GetUIElementType(element);
                    if (type == UIElementTypes.Secondary)
                    {
                        secondary.Add(element);
                    }
                    else
                    {
                        primary = element;
                    }
                }
                mustInvalidate = AssignElements(CalculatedLayout, primary, secondary, mustInvalidate);
            }
            else
            {
                // This is a top/bottom layout
                CalculatedLayout = UIElementOrder == PrimarySecondaryOrientation.SecondaryPrimary ? PrimarySecondaryLayout.SecondaryTopPrimaryBottom : PrimarySecondaryLayout.PrimaryTopSecondaryBottom;
                mustInvalidate   = SizeGrid(CalculatedLayout, secondaryElementVisible ? SecondaryUIElementSize : new GridLength(0d));

                UIElement primary   = null;
                var       secondary = new List <UIElement>();

                // We need to assign children to rows
                foreach (var element in Children.OfType <UIElement>().Where(e => e.Visibility != Visibility.Collapsed))
                {
                    var type = SimpleView.GetUIElementType(element);
                    if (type == UIElementTypes.Secondary)
                    {
                        secondary.Add(element);
                    }
                    else
                    {
                        primary = element;
                    }
                }
                mustInvalidate = AssignElements(CalculatedLayout, primary, secondary, mustInvalidate);
            }

            if (maxHeight > 0 && mustInvalidate)
            {
                // Need to run all this one more time to make sure everything got picked up right
                MeasureOverride(constraint);
                InvalidateVisual();
            }

            return(size);
        }
        /// <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)
        {
            if (HeaderRenderer == null)
            {
                HeaderRenderer = new StandardPrimarySecondaryHorizontalPanelHeaderRenderer();
            }

            foreach (UIElement element in Children)
            {
                if (SimpleView.GetUIElementType(element) == UIElementTypes.Primary)
                {
                    if (CanCollapseSecondary && IsSecondaryElementCollapsed)
                    {
                        var minimumCollapsedWidth = 0d;
                        var mainAreaLeft          = 0d;
                        if (HeaderRenderer != null)
                        {
                            minimumCollapsedWidth = HeaderRenderer.GetMinimumCollapsedAreaWidth(this);
                            if (SecondaryAreaLocation == SecondaryAreaLocation.Left)
                            {
                                mainAreaLeft = minimumCollapsedWidth + (minimumCollapsedWidth > 0d ? ElementSpacing : 0d);
                            }
                        }
                        var primaryArea = new Rect(mainAreaLeft, 0d, availableSize.Width - minimumCollapsedWidth - (minimumCollapsedWidth > 0d ? ElementSpacing : 0d), availableSize.Height);
                        if (HeaderRenderer != null)
                        {
                            primaryArea = HeaderRenderer.GetPrimaryClientArea(primaryArea, this);
                        }
                        element.Measure(primaryArea.Size);
                    }
                    else
                    {
                        var currentX = 0d;
                        if (SecondaryAreaLocation == SecondaryAreaLocation.Left)
                        {
                            currentX = SecondaryElementWidth + ElementSpacing;
                        }
                        var primaryArea = new Rect(currentX, 0d, Math.Max(availableSize.Width - SecondaryElementWidth - ElementSpacing, 0), availableSize.Height);
                        if (HeaderRenderer != null)
                        {
                            primaryArea = HeaderRenderer.GetPrimaryClientArea(primaryArea, this);
                        }
                        element.Measure(primaryArea.Size);
                    }
                }
                else
                {
                    if (CanCollapseSecondary && IsSecondaryElementCollapsed)
                    {
                        element.Measure(new Size(0, availableSize.Height));
                    }
                    else
                    {
                        var secondaryArea = SecondaryAreaLocation == SecondaryAreaLocation.Left ? new Rect(0d, 0d, SecondaryElementWidth, availableSize.Height) : new Rect(availableSize.Width - SecondaryElementWidth, 0d, SecondaryElementWidth, availableSize.Height);
                        if (HeaderRenderer != null)
                        {
                            secondaryArea = HeaderRenderer.GetSecondaryClientArea(secondaryArea, this);
                        }
                        element.Measure(secondaryArea.Size);
                    }
                }
            }
            return(base.MeasureOverride(availableSize));
        }
Пример #5
0
        private void CreateScrollbars()
        {
            if (Parent != null && !(Parent is AdornerDecorator) && (Parent is Grid || Parent is SimpleView || Parent is ContentControl))
            {
                // We need to make sure this control is directly within an adorner decorator
                // so elements in the adorner layer (scroll bars) behave correctly in the Z-Order
                var decorator = new AdornerDecorator
                {
                    VerticalAlignment   = VerticalAlignment,
                    HorizontalAlignment = HorizontalAlignment,
                    Margin = new Thickness(Margin.Left, Margin.Top, Margin.Right, Margin.Bottom),
                    Width  = Width,
                    Height = Height
                };

                Grid.SetColumn(decorator, Grid.GetColumn(this));
                Grid.SetRow(decorator, Grid.GetRow(this));
                Grid.SetColumnSpan(decorator, Grid.GetColumnSpan(this));
                Grid.SetRowSpan(decorator, Grid.GetRowSpan(this));

                SimpleView.SetUIElementTitle(decorator, SimpleView.GetUIElementTitle(this));
                SimpleView.SetUIElementType(decorator, SimpleView.GetUIElementType(this));

                Margin              = new Thickness(0d);
                VerticalAlignment   = VerticalAlignment.Stretch;
                HorizontalAlignment = HorizontalAlignment.Stretch;

                var parentPanel = Parent as Panel;
                if (parentPanel != null)
                {
                    var childItemIndex = -1;
                    var found          = false;
                    foreach (var child in parentPanel.Children)
                    {
                        childItemIndex++;
                        if (child == this)
                        {
                            found = true;
                            break;
                        }
                    }
                    if (found)
                    {
                        parentPanel.Children.Remove(this);
                        parentPanel.Children.Insert(childItemIndex, decorator);
                        decorator.Child = this;
                    }
                }
                else
                {
                    var parentContent = Parent as ContentControl;
                    if (parentContent != null)
                    {
                        parentContent.Content = null;
                        parentContent.Content = decorator;
                        decorator.Child       = this;
                    }
                }
            }

            if (_scrollbarsCreated)
            {
                return;
            }
            _adorner = AdornerLayer.GetAdornerLayer(this);
            if (_adorner == null)
            {
                return;
            }
            _adorner.Add(new BidirectionalStackPanelScrollAdorner(this, _scrollHorizontal, _scrollVertical)
            {
                Visibility = Visibility.Visible
            });
            _scrollHorizontal.ValueChanged += (s, e) => Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, new Action(DispatchInvalidateScroll));
            _scrollVertical.ValueChanged   += (s, e) => Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, new Action(DispatchInvalidateScroll));
            _scrollbarsCreated              = true;
        }