Beispiel #1
0
        void SetupSplitters()
        {
            if (!splitterListIsDirty)
                return;

            if (setupSplitters)
                return;

            setupSplitters = true;

            while (_splitterList.Count > 0)
            {
                ResizingPanelSplitter splitter = _splitterList[0];
                splitter.DragStarted -= new DragStartedEventHandler(splitter_DragStarted);
                splitter.DragDelta -= new DragDeltaEventHandler(splitter_DragDelta);
                splitter.DragCompleted -= new DragCompletedEventHandler(splitter_DragCompleted);
                _splitterList.Remove(splitter);
                Children.Remove(splitter);
            }

            int i = 0;//child index
            int j = 0;//splitter index

            while (i < Children.Count - 1)
            {
                if (j == _splitterList.Count)
                {
                    ResizingPanelSplitter splitter = new ResizingPanelSplitter();
                    _splitterList.Add(splitter);
                    splitter.DragStarted += new DragStartedEventHandler(splitter_DragStarted);
                    splitter.DragDelta += new DragDeltaEventHandler(splitter_DragDelta);
                    splitter.DragCompleted += new DragCompletedEventHandler(splitter_DragCompleted);
                    Children.Insert(i + 1, splitter);
                }

                i += 2;
                j++;
            }

            for (j = 0; j < _splitterList.Count; j++)
            {
                _splitterList[j].Width = (Orientation == Orientation.Horizontal) ? 4 : double.NaN;
                _splitterList[j].Height = (Orientation == Orientation.Vertical) ? 4 : double.NaN;
            }

#if DEBUG
            Debug.Assert(_splitterList.Count == Children.Count / 2);
            i = 0;
            while (Children.Count > 0)
            {
                Debug.Assert(Children[i] != null);
                Debug.Assert(!(Children[i] is ResizingPanelSplitter));
                i++;
                if (i >= Children.Count)
                    break;

                Debug.Assert((Children[i] is ResizingPanelSplitter));
                i++;

            }
#endif
            splitterListIsDirty = false;
            setupSplitters = false;
        }
        void SetupSplitters()
        {
            if (!splitterListIsDirty)
            {
                return;
            }

            if (setupSplitters)
            {
                return;
            }

            setupSplitters = true;

            while (_splitterList.Count > 0)
            {
                ResizingPanelSplitter splitter = _splitterList[0];
                splitter.DragStarted   -= new DragStartedEventHandler(splitter_DragStarted);
                splitter.DragDelta     -= new DragDeltaEventHandler(splitter_DragDelta);
                splitter.DragCompleted -= new DragCompletedEventHandler(splitter_DragCompleted);
                _splitterList.Remove(splitter);
                Children.Remove(splitter);
            }

            int i = 0; //child index
            int j = 0; //splitter index

            while (i < Children.Count - 1)
            {
                if (j == _splitterList.Count)
                {
                    ResizingPanelSplitter splitter = new ResizingPanelSplitter();
                    _splitterList.Add(splitter);
                    splitter.DragStarted   += new DragStartedEventHandler(splitter_DragStarted);
                    splitter.DragDelta     += new DragDeltaEventHandler(splitter_DragDelta);
                    splitter.DragCompleted += new DragCompletedEventHandler(splitter_DragCompleted);
                    Children.Insert(i + 1, splitter);
                }

                i += 2;
                j++;
            }

            for (j = 0; j < _splitterList.Count; j++)
            {
                _splitterList[j].Width  = (Orientation == Orientation.Horizontal) ? 4 : double.NaN;
                _splitterList[j].Height = (Orientation == Orientation.Vertical) ? 4 : double.NaN;
            }

#if DEBUG
            Debug.Assert(_splitterList.Count == Children.Count / 2);
            i = 0;
            while (true)
            {
                Debug.Assert(Children[i] != null);
                Debug.Assert(!(Children[i] is ResizingPanelSplitter));
                i++;
                if (i >= Children.Count)
                {
                    break;
                }

                Debug.Assert((Children[i] is ResizingPanelSplitter));
                i++;
            }
#endif
            splitterListIsDirty = false;
            setupSplitters      = false;
        }
        void splitter_DragDelta(object sender, DragDeltaEventArgs e)
        {
            ResizingPanelSplitter splitter = e.Source as ResizingPanelSplitter;
            int iSplitter = Children.IndexOf(splitter);

            UIElement childPrev = null;
            UIElement childNext = null;

            //int posInc = ResizingDirection == ResizingDirection.Direct ? 2 : -2;
            int posInc = 2;// FlowDirection == FlowDirection.LeftToRight ? 2 : -2;
            int negInc = -posInc;
            int i      = iSplitter;

            while (i >= 0 ||
                   i < Children.Count - 1)
            {
                if (NextChildIsVisible(i))
                {
                    //childNext = Children[ResizingDirection == ResizingDirection.Direct ? i + 1 : i - 1];
                    childNext = Children[i + 1];//FlowDirection == FlowDirection.LeftToRight ? i + 1 : i - 1];
                    break;
                }

                i += posInc;
            }

            i = iSplitter;

            while (i >= 0 ||
                   i < Children.Count - 1)
            {
                if (PrevChildIsVisible(i))
                {
                    //childPrev = Children[ResizingDirection == ResizingDirection.Direct ? i - 1 : i + 1];
                    childPrev = Children[i - 1];//FlowDirection == FlowDirection.LeftToRight ? i - 1 : i + 1];
                    break;
                }

                i -= posInc;
            }

            Size resExtPrev = new Size((double)childPrev.GetValue(ResizeWidthProperty), (double)childPrev.GetValue(ResizeHeightProperty));
            Size resExtNext = new Size((double)childNext.GetValue(ResizeWidthProperty), (double)childNext.GetValue(ResizeHeightProperty));


            #region Orientation == Horizontal
            if (Orientation == Orientation.Horizontal)
            {
                double delta = e.HorizontalChange;

                if (!double.IsPositiveInfinity(resExtPrev.Width) &&
                    (resExtPrev.Width + delta < 0))
                {
                    delta = -resExtPrev.Width;
                }

                if (!double.IsPositiveInfinity(resExtNext.Width) &&
                    resExtNext.Width - delta < 0)
                {
                    delta = resExtNext.Width;
                }


                if (!double.IsPositiveInfinity(resExtPrev.Width))
                {
                    childPrev.SetValue(ResizeWidthProperty, resExtPrev.Width + delta);
                }
                if (!double.IsPositiveInfinity(resExtNext.Width))
                {
                    childNext.SetValue(ResizeWidthProperty, resExtNext.Width - delta);
                }
            }
            #endregion
            #region Orientation == Vertical
            else //if (Orientation == Orientation.Vertical)
            {
                double delta = e.VerticalChange;

                if (!double.IsPositiveInfinity(resExtPrev.Height) &&
                    (resExtPrev.Height + delta < 0))
                {
                    delta = -resExtPrev.Height;
                }

                if (!double.IsPositiveInfinity(resExtNext.Height) &&
                    resExtNext.Height - delta < 0)
                {
                    delta = resExtNext.Height;
                }


                if (!double.IsPositiveInfinity(resExtPrev.Height))
                {
                    childPrev.SetValue(ResizeHeightProperty, resExtPrev.Height + delta);
                }

                if (!double.IsPositiveInfinity(resExtNext.Height))
                {
                    childNext.SetValue(ResizeHeightProperty, resExtNext.Height - delta);
                }
            }
            #endregion
        }
        protected override Size MeasureOverride(Size availableSize)
        {
            SetupSplitters();
            ChildDefinitiveLenght.Clear();

            if (Children.Count == 0)
            {
                return(base.MeasureOverride(availableSize));
            }

            //if (!IsDocked)
            //    return new Size();

            System.Diagnostics.Debug.Assert(_splitterList.Count == Children.Count / 2, "One and only one splitter must be present between two consecutive childs!");
            bool foundChildWithInfResizeProperty = false;

            foreach (UIElement child in Children)
            {
                if (child is ResizingPanelSplitter)
                {
                    continue;
                }

                if (Orientation == Orientation.Horizontal &&
                    double.IsInfinity(GetResizeWidth(child)))
                {
                    if (child is DocumentPane ||
                        (child is ResizingPanel && DockingManager.IsPanelContainingDocumentPane(child as ResizingPanel)))
                    {
                        if (foundChildWithInfResizeProperty)
                        {
                            Debug.WriteLine("A child with resize width set to infinty has been corrected to 200");
                            SetResizeWidth(child, 200);
                        }

                        foundChildWithInfResizeProperty = true;
                    }
                    else
                    {
                        SetResizeWidth(child, 200);
                    }
                }
                else if (Orientation == Orientation.Vertical &&
                         double.IsInfinity(GetResizeHeight(child)))
                {
                    if (child is DocumentPane ||
                        (child is ResizingPanel && DockingManager.IsPanelContainingDocumentPane(child as ResizingPanel)))
                    {
                        if (foundChildWithInfResizeProperty)
                        {
                            Debug.WriteLine("A child with resize height set to infinty has been corrected to 200");
                            SetResizeHeight(child, 200);
                        }

                        foundChildWithInfResizeProperty = true;
                    }
                    else
                    {
                        SetResizeHeight(child, 200);
                    }
                }
            }

            if (!foundChildWithInfResizeProperty)
            {
                foreach (UIElement child in Children)
                {
                    if (child is ResizingPanelSplitter)
                    {
                        continue;
                    }

                    if (Orientation == Orientation.Horizontal)
                    {
                        if (child is DocumentPane ||
                            (child is ResizingPanel && DockingManager.IsPanelContainingDocumentPane(child as ResizingPanel)))
                        {
                            SetResizeWidth(child, double.PositiveInfinity);
                            foundChildWithInfResizeProperty = true;
                            break;
                        }
                    }
                    else if (Orientation == Orientation.Vertical &&
                             double.IsInfinity(GetResizeHeight(child)))
                    {
                        if (child is DocumentPane ||
                            (child is ResizingPanel && DockingManager.IsPanelContainingDocumentPane(child as ResizingPanel)))
                        {
                            SetResizeHeight(child, double.PositiveInfinity);
                            foundChildWithInfResizeProperty = true;
                            break;
                        }
                    }
                }
            }

            if (!foundChildWithInfResizeProperty)
            {
                if (Children.Count == 1)
                {
                    if (Orientation == Orientation.Horizontal)
                    {
                        SetResizeWidth(Children[0], double.PositiveInfinity);
                    }
                    else
                    {
                        SetResizeHeight(Children[0], double.PositiveInfinity);
                    }
                }
                else if (Children.Count > 2)
                {
                    if (Orientation == Orientation.Horizontal)
                    {
                        SetResizeWidth(Children[2], double.PositiveInfinity);
                    }
                    else
                    {
                        SetResizeHeight(Children[2], double.PositiveInfinity);
                    }
                }
            }



            #region Horizontal orientation
            if (Orientation == Orientation.Horizontal)
            {
                double totSplittersWidth    = 0;
                double totWidth             = 0;
                int    childWithPosInfWidth = 0;

                List <UIElement>      childsOrderedByWidth = new List <UIElement>();
                ResizingPanelSplitter currentSplitter      = null;
                bool prevChildIsVisible = false;

                for (int i = 0; i < Children.Count; i++)
                {
                    UIElement        child         = Children[i];
                    IDockableControl dockableChild = child as IDockableControl;
                    if (dockableChild != null && !dockableChild.IsDocked)
                    {
                        prevChildIsVisible = false;
                        child.Measure(new Size());
                    }
                    else if (child is ResizingPanelSplitter)
                    {
                        if (currentSplitter != null)
                        {
                            child.Measure(new Size());
                        }
                        else if (prevChildIsVisible)
                        {
                            currentSplitter = child as ResizingPanelSplitter;
                        }

                        //if (//(i < Children.Count - 2 && PrevChildIsVisible(i)) ||
                        //    NextChildIsVisible(i) && PrevChildIsVisible(i)
                        //    )
                        //{
                        //    child.Measure(new Size(double.PositiveInfinity, availableSize.Height));
                        //    totSplittersWidth += child.DesiredSize.Width;
                        //}
                        //else
                        //{
                        //    child.Measure(new Size());
                        //}
                    }
                    else
                    {
                        if (currentSplitter != null)
                        {
                            currentSplitter.Measure(new Size(double.PositiveInfinity, availableSize.Height));
                            totSplittersWidth += currentSplitter.DesiredSize.Width;
                            currentSplitter    = null;
                        }

                        prevChildIsVisible = true;
                        double resWidth = (double)child.GetValue(ResizeWidthProperty);

                        if (double.IsPositiveInfinity(resWidth))
                        {
                            childWithPosInfWidth++;
                        }
                        else
                        {
                            totWidth += resWidth;
                            childsOrderedByWidth.Add(child);
                        }
                    }
                }

                if (currentSplitter != null)
                {
                    currentSplitter.Measure(new Size());
                    currentSplitter = null;
                }


                double widthForPosInfChilds = 0;
                double availWidth           = availableSize.Width - totSplittersWidth;
                double shWidth = double.PositiveInfinity;

                if (totWidth > availWidth)
                {
                    childsOrderedByWidth.Sort(delegate(UIElement e1, UIElement e2)
                    {
                        double resWidth1 = (double)e1.GetValue(ResizeWidthProperty);
                        double resWidth2 = (double)e2.GetValue(ResizeWidthProperty);

                        return(resWidth1.CompareTo(resWidth2));
                    });


                    int    count    = childsOrderedByWidth.Count;
                    int    i        = 0;
                    double resWidth = 0;

                    while ((double)childsOrderedByWidth[i].GetValue(ResizeWidthProperty) * (count - i) + resWidth < availWidth)
                    {
                        i++;

                        if (i >= count)
                        {
                            break;
                        }

                        resWidth += (double)childsOrderedByWidth[i - 1].GetValue(ResizeWidthProperty);
                    }

                    shWidth = (availWidth - resWidth) / (count - i);
                    if (shWidth < 0)
                    {
                        shWidth = 0;
                    }
                }
                else
                {
                    if (childWithPosInfWidth > 0)
                    {
                        widthForPosInfChilds = (availWidth - totWidth) / childWithPosInfWidth;
                    }
                    else
                    {
                        widthForPosInfChilds = (availWidth - totWidth) / childsOrderedByWidth.Count;

                        foreach (UIElement child in childsOrderedByWidth)
                        {
                            double resWidth = (double)child.GetValue(ResizeWidthProperty);
                            //double resHeight = (double)child.GetValue(ResizeHeightProperty);

                            child.SetValue(ResizeWidthProperty, resWidth + widthForPosInfChilds);
                        }
                    }
                }



                for (int i = 0; i < Children.Count; i++)
                {
                    UIElement        child         = Children[i];
                    IDockableControl dockableChild = child as IDockableControl;
                    if (dockableChild != null && !dockableChild.IsDocked)
                    {
                        child.Measure(new Size());
                    }
                    else if (!(child is ResizingPanelSplitter))
                    {
                        double resWidth = (double)child.GetValue(ResizeWidthProperty);

                        if (double.IsPositiveInfinity(resWidth))
                        {
                            ChildDefinitiveLenght[child] = widthForPosInfChilds;
                        }
                        else if (shWidth < resWidth)
                        {
                            ChildDefinitiveLenght[child] = shWidth;
                        }
                        else
                        {
                            ChildDefinitiveLenght[child] = resWidth;
                        }

                        child.Measure(new Size(ChildDefinitiveLenght[child], availableSize.Height));
                    }
                }
            }
            #endregion
            #region Vertical orientation
            else //if (Orientation == Orientation.Horizontal)
            {
                double totSplittersHeight    = 0;
                double totHeight             = 0;
                int    childWithPosInfHeight = 0;

                List <UIElement>      childsOrderedByHeight = new List <UIElement>();
                ResizingPanelSplitter currentSplitter       = null;
                bool prevChildIsVisible = false;

                for (int i = 0; i < Children.Count; i++)
                {
                    UIElement        child         = Children[i];
                    IDockableControl dockableChild = child as IDockableControl;

                    if (dockableChild != null && !dockableChild.IsDocked)
                    {
                        prevChildIsVisible = true;
                        child.Measure(new Size());
                    }
                    else if (child is ResizingPanelSplitter)
                    {
                        if (currentSplitter != null)
                        {
                            child.Measure(new Size());
                        }
                        else if (prevChildIsVisible)
                        {
                            currentSplitter = child as ResizingPanelSplitter;
                        }

                        //if ((i < Children.Count - 2 &&
                        //    PrevChildIsVisible(i)) ||
                        //    NextChildIsVisible(i) && PrevChildIsVisible(i)
                        //    )
                        //{
                        //    child.Measure(new Size(availableSize.Width, double.PositiveInfinity));
                        //    totSplittersHeight += child.DesiredSize.Height;
                        //}
                        //else
                        //{
                        //    child.Measure(new Size());
                        //}
                    }
                    else
                    {
                        if (currentSplitter != null)
                        {
                            currentSplitter.Measure(new Size(double.PositiveInfinity, availableSize.Height));
                            totSplittersHeight += currentSplitter.DesiredSize.Height;
                            currentSplitter     = null;
                        }

                        prevChildIsVisible = true;

                        double resHeight = (double)child.GetValue(ResizeHeightProperty);

                        if (double.IsPositiveInfinity(resHeight))
                        {
                            childWithPosInfHeight++;
                        }
                        else
                        {
                            totHeight += resHeight;
                            childsOrderedByHeight.Add(child);
                        }
                    }
                }

                if (currentSplitter != null)
                {
                    currentSplitter.Measure(new Size());
                    currentSplitter = null;
                }

                Debug.Assert(childWithPosInfHeight <= 1);

                double heightForPosInfChilds = 0;
                double availHeight           = availableSize.Height - totSplittersHeight;
                double shHeight = double.PositiveInfinity;

                if (totHeight > availHeight)
                {
                    childsOrderedByHeight.Sort(delegate(UIElement e1, UIElement e2)
                    {
                        double resHeight1 = (double)e1.GetValue(ResizeHeightProperty);
                        double resHeight2 = (double)e2.GetValue(ResizeHeightProperty);

                        return(resHeight1.CompareTo(resHeight2));
                    });

                    int    count     = childsOrderedByHeight.Count;
                    int    i         = 0;
                    double resHeight = 0;

                    while ((double)childsOrderedByHeight[i].GetValue(ResizeHeightProperty) * (count - i) + resHeight < availHeight)
                    {
                        i++;

                        if (i >= count)
                        {
                            break;
                        }

                        resHeight += (double)childsOrderedByHeight[i - 1].GetValue(ResizeHeightProperty);
                    }

                    shHeight = (availHeight - resHeight) / (count - i);
                    if (shHeight < 0)
                    {
                        shHeight = 0;
                    }
                }
                else
                {
                    if (childWithPosInfHeight > 0)
                    {
                        heightForPosInfChilds = (availHeight - totHeight) / childWithPosInfHeight;
                    }
                    else
                    {
                        heightForPosInfChilds = (availHeight - totHeight) / childsOrderedByHeight.Count;

                        foreach (UIElement child in childsOrderedByHeight)
                        {
                            //double resWidth = (double)child.GetValue(ResizeWidthProperty);
                            double resHeight = (double)child.GetValue(ResizeHeightProperty);


                            child.SetValue(ResizeHeightProperty, resHeight + heightForPosInfChilds);
                        }
                    }
                }

                for (int i = 0; i < Children.Count; i++)
                {
                    UIElement        child         = Children[i];
                    IDockableControl dockableChild = child as IDockableControl;
                    if (dockableChild != null && !dockableChild.IsDocked)
                    {
                        child.Measure(new Size());
                    }
                    else if (!(child is ResizingPanelSplitter))
                    {
                        double resHeight = (double)child.GetValue(ResizeHeightProperty);

                        if (double.IsPositiveInfinity(resHeight))
                        {
                            ChildDefinitiveLenght[child] = heightForPosInfChilds;
                        }
                        else if (shHeight < resHeight)
                        {
                            ChildDefinitiveLenght[child] = shHeight;
                        }
                        else
                        {
                            ChildDefinitiveLenght[child] = resHeight;
                        }

                        child.Measure(new Size(availableSize.Width, ChildDefinitiveLenght[child]));
                    }
                }
            }
            #endregion

            //Debug.Assert(ChildDefinitiveLenght.Count > 0);

            return(base.MeasureOverride(availableSize));
        }