ToolBarTray.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / System / Windows / Controls / ToolBarTray.cs / 1305600 / ToolBarTray.cs

                            //---------------------------------------------------------------------------- 
//
// Copyright (C) Microsoft Corporation.  All rights reserved.
//
//--------------------------------------------------------------------------- 

using MS.Internal; 
using MS.Internal.Controls; 
using MS.Internal.Documents;
using MS.Internal.KnownBoxes; 
using MS.Utility;

using System;
using System.Collections; 
using System.Collections.Generic;
using System.Collections.ObjectModel; 
using System.Windows.Controls.Primitives; 
using System.ComponentModel;
using System.Diagnostics; 
using System.Windows.Threading;
using System.Windows.Documents;
using System.Windows.Media;
using System.Windows.Input; 
using System.Windows.Markup; // IAddChild, ContentPropertyAttribute
 
namespace System.Windows.Controls 
{
    ///  
    ///     ToolBarTray is the layout container which handles layout of ToolBars relative to one another.
    /// It is responsible for handling placement, sizing and drag-and-drop to rearrange and
    /// resize behaviors associated with toolbars.
    /// It is also responsible for managing the rows (or "bands") in which toolbars appear. 
    /// A ToolBar tray can be horizontal or vertical and can be used anywhere within an Avalon application,
    /// but it is expected that (like a Menu) it will often be docked to the top or side of the application window. 
    ///  
    [ContentProperty("ToolBars")]
    public class ToolBarTray : FrameworkElement, IAddChild 
    {
        //-------------------------------------------------------------------
        //
        //  Constructors 
        //
        //------------------------------------------------------------------- 
 
        #region Constructors
 
        static ToolBarTray()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(ToolBarTray), new FrameworkPropertyMetadata(typeof(ToolBarTray)));
            _dType = DependencyObjectType.FromSystemTypeInternal(typeof(ToolBarTray)); 

 
            EventManager.RegisterClassHandler(typeof(ToolBarTray), Thumb.DragDeltaEvent, new DragDeltaEventHandler(OnThumbDragDelta)); 
            KeyboardNavigation.ControlTabNavigationProperty.OverrideMetadata(typeof(ToolBarTray), new FrameworkPropertyMetadata(KeyboardNavigationMode.Cycle));
        } 

        /// 
        ///     Default ToolBarTray constructor
        ///  
        public ToolBarTray() : base()
        { 
        } 

        #endregion 

        //--------------------------------------------------------------------
        //
        //  Properties 
        //
        //------------------------------------------------------------------- 
 
        #region Properties
 
        /// 
        /// DependencyProperty for  property.
        /// 
        public static readonly DependencyProperty BackgroundProperty = 
                Panel.BackgroundProperty.AddOwner(typeof(ToolBarTray),
                        new FrameworkPropertyMetadata( 
                                (Brush)null, 
                                FrameworkPropertyMetadataOptions.AffectsRender));
 
        /// 
        /// The Background property defines the brush used to fill the area within the ToolBarTray.
        /// 
        public Brush Background 
        {
            get { return (Brush)GetValue(BackgroundProperty); } 
            set { SetValue(BackgroundProperty, value); } 
        }
 
        /// 
        ///     Orientation property specify the flow direction. The default is horizontal.
        /// 
        public static readonly DependencyProperty OrientationProperty = 
                    DependencyProperty.Register(
                                "Orientation", 
                                typeof(Orientation), 
                                typeof(ToolBarTray),
                                new FrameworkPropertyMetadata( 
                                            Orientation.Horizontal,
                                            FrameworkPropertyMetadataOptions.AffectsParentMeasure,
                                            new PropertyChangedCallback(OnOrientationPropertyChanged)),
                                new ValidateValueCallback(ScrollBar.IsValidOrientation)); 

        // Then ToolBarTray Orientation is changing we need to invalidate its ToolBars Orientation 
        private static void OnOrientationPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
        {
            Collection toolbarCollection = ((ToolBarTray)d).ToolBars; 
            for (int i = 0; i < toolbarCollection.Count; i++)
            {
                toolbarCollection[i].CoerceValue(ToolBar.OrientationProperty);
            } 
        }
 
 
        /// 
        /// Specifies the orientation (horizontal or vertical) 
        /// 
        public Orientation Orientation
        {
            get { return (Orientation) GetValue(OrientationProperty); } 
            set { SetValue(OrientationProperty, value); }
        } 
 
        /// 
        ///     The DependencyProperty for the IsLocked property. 
        /// 
        public static readonly DependencyProperty IsLockedProperty =
                    DependencyProperty.RegisterAttached(
                               "IsLocked", 
                                typeof(bool),
                                typeof(ToolBarTray), 
                                new FrameworkPropertyMetadata( 
                                            BooleanBoxes.FalseBox,
                                            FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.Inherits)); 

        /// 
        /// IsLocked property determine the ability to move the toolbars within the ToolBarTray
        /// If true then thumb from ToolBar style becomes hidden. 
        /// This property inherits so ToolBar can use it in its Style triggers
        /// Default is false. 
        ///  
        public bool IsLocked
        { 
            get { return (bool) GetValue(IsLockedProperty); }
            set { SetValue(IsLockedProperty, value); }
        }
 
        /// 
        /// Writes the attached property IsLocked to the given element. 
        ///  
        /// The element to which to write the attached property.
        /// The property value to set 
        public static void SetIsLocked(DependencyObject element, bool value)
        {
            if (element == null)
            { 
                throw new ArgumentNullException("element");
            } 
            element.SetValue(IsLockedProperty, value); 
        }
 
        /// 
        /// Reads the attached property IsLocked from the given element.
        /// 
        /// The element from which to read the attached property. 
        /// The property's value.
        public static bool GetIsLocked(DependencyObject element) 
        { 
            if (element == null)
            { 
                throw new ArgumentNullException("element");
            }
            return (bool)element.GetValue(IsLockedProperty);
        } 

        ///  
        /// Returns a collection of ToolBar children for user to add/remove children manually 
        /// 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] 
        public Collection ToolBars
        {
            get
            { 
                if (_toolBarsCollection == null)
                    _toolBarsCollection = new ToolBarCollection(this); 
 
                return _toolBarsCollection;
            } 
        }

        private class ToolBarCollection : Collection
        { 
            public ToolBarCollection(ToolBarTray parent)
            { 
                _parent = parent; 
            }
 
            protected override void InsertItem(int index, ToolBar toolBar)
            {
                base.InsertItem(index, toolBar);
 
                _parent.AddLogicalChild(toolBar);
                _parent.AddVisualChild(toolBar); 
                _parent.InvalidateMeasure(); 
            }
 
            protected override void SetItem(int index, ToolBar toolBar)
            {
                ToolBar currentToolBar = Items[index];
                if (toolBar != currentToolBar) 
                {
                    base.SetItem(index, toolBar); 
 
                    // remove old item visual and logical links
                    _parent.RemoveVisualChild(currentToolBar); 
                    _parent.RemoveLogicalChild(currentToolBar);

                    // add new item visual and logical links
                    _parent.AddLogicalChild(toolBar); 
                    _parent.AddVisualChild(toolBar);
                    _parent.InvalidateMeasure(); 
                } 
            }
 
            protected override void RemoveItem(int index)
            {
                ToolBar currentToolBar = this[index];
                base.RemoveItem(index); 

                // remove old item visual and logical links 
                _parent.RemoveVisualChild(currentToolBar); 
                _parent.RemoveLogicalChild(currentToolBar);
                _parent.InvalidateMeasure(); 
            }

            protected override void ClearItems()
            { 
                int count = Count;
                if (count > 0) 
                { 
                    for (int i = 0; i < count; i++)
                    { 
                        ToolBar currentToolBar = this[i];
                        _parent.RemoveVisualChild(currentToolBar);
                        _parent.RemoveLogicalChild(currentToolBar);
                    } 
                    _parent.InvalidateMeasure();
                } 
 
                base.ClearItems();
            } 


            // Ref to a visual/logical ToolBarTray parent
            private readonly ToolBarTray _parent; 
        }
 
        #endregion Properties 

 
        //--------------------------------------------------------------------
        //
        //  Public Methods
        // 
        //--------------------------------------------------------------------
 
        #region Public Methods 
        ///
        /// This method is called to Add the object as a child of the ToolBarTray.  This method is used primarily 
        /// by the parser.
        ///
        ///
        /// The object to add as a child; it must be a UIElement. 
        ///
        ///  
        void IAddChild.AddChild(Object value) 
        {
            if (value == null) 
            {
                throw new ArgumentNullException("value");
            }
 
            ToolBar toolBar = value as ToolBar;
            if (toolBar == null) 
            { 
                throw new ArgumentException(SR.Get(SRID.UnexpectedParameterType, value.GetType(), typeof(ToolBar)), "value");
            } 

            ToolBars.Add(toolBar);
        }
 
        ///
        /// This method is called by the parser when text appears under the tag in markup. 
        /// As default Panels do not support text, calling this method has no effect. 
        ///
        /// 
        /// Text to add as a child.
        ///
        void IAddChild.AddText(string text)
        { 
            XamlSerializerUtil.ThrowIfNonWhiteSpaceInAddText(text, this);
        } 
 

        ///  
        /// Returns enumerator to logical children.
        /// 
        protected internal override IEnumerator LogicalChildren
        { 
            get
            { 
                if (this.VisualChildrenCount == 0) 
                {
                    return EmptyEnumerator.Instance; 
                }

                return this.ToolBars.GetEnumerator();
            } 
        }
 
        #endregion Public Methods 

 
        //-------------------------------------------------------------------
        //
        //  Protected Methods
        // 
        //--------------------------------------------------------------------
 
        #region Protected Methods 

        ///  
        /// Override from UIElement
        /// 
        protected override void OnRender(DrawingContext dc)
        { 
            // Draw background in rectangle inside border.
            Brush background = this.Background; 
            if (background != null) 
            {
                dc.DrawRectangle(background, 
                                 null,
                                 new Rect(0, 0, RenderSize.Width, RenderSize.Height));
            }
        } 

        ///  
        /// Updates DesiredSize of the ToolBarTray. Called by parent UIElement. 
        /// This is the first pass of layout.
        /// MeasureOverride distributes all ToolBars in bands depend on Band and BandIndex properties. 
        /// All ToolBars with the same Band are places in one band. After that they are sorted by BandIndex.
        /// 
        /// Constraint size is an "upper limit" that ToolBarTray should not exceed.
        /// ToolBarTray' desired size. 
        protected override Size MeasureOverride(Size constraint)
        { 
            GenerateBands(); 

            Size toolBarTrayDesiredSize = new Size(); 
            int bandIndex;
            int toolBarIndex;
            bool fHorizontal = (Orientation == Orientation.Horizontal);
            Size childConstraint = new Size(Double.PositiveInfinity, Double.PositiveInfinity); 

            for (bandIndex = 0; bandIndex < _bands.Count; bandIndex++) 
            { 
                // Calculate the available size before we measure the children.
                // remainingLength is the constraint minus sum of all minimum sizes 
                double remainingLength = fHorizontal ? constraint.Width : constraint.Height;
                List band = _bands[bandIndex].Band;
                double bandThickness = 0d;
                double bandLength = 0d; 
                for (toolBarIndex = 0; toolBarIndex < band.Count; toolBarIndex++)
                { 
                    ToolBar toolBar = band[toolBarIndex]; 
                    remainingLength -= toolBar.MinLength;
                    if (DoubleUtil.LessThan(remainingLength, 0)) 
                    {
                        remainingLength = 0;
                        break;
                    } 
                }
 
                // Measure all children passing the remainingLength as a constraint 
                for (toolBarIndex = 0; toolBarIndex < band.Count; toolBarIndex++)
                { 
                    ToolBar toolBar = band[toolBarIndex];
                    remainingLength += toolBar.MinLength;
                    if (fHorizontal)
                        childConstraint.Width = remainingLength; 
                    else
                        childConstraint.Height = remainingLength; 
                    toolBar.Measure(childConstraint); 
                    bandThickness = Math.Max(bandThickness, fHorizontal ? toolBar.DesiredSize.Height : toolBar.DesiredSize.Width);
                    bandLength += fHorizontal ? toolBar.DesiredSize.Width : toolBar.DesiredSize.Height; 
                    remainingLength -= fHorizontal ? toolBar.DesiredSize.Width : toolBar.DesiredSize.Height;
                    if (DoubleUtil.LessThan(remainingLength, 0))
                    {
                        remainingLength = 0; 
                    }
                } 
 
                // Store band thickness in the BandInfo property
                _bands[bandIndex].Thickness = bandThickness; 

                if (fHorizontal)
                {
                    toolBarTrayDesiredSize.Height += bandThickness; 
                    toolBarTrayDesiredSize.Width = Math.Max(toolBarTrayDesiredSize.Width, bandLength);
                } 
                else 
                {
                    toolBarTrayDesiredSize.Width += bandThickness; 
                    toolBarTrayDesiredSize.Height = Math.Max(toolBarTrayDesiredSize.Height, bandLength);
                }

            } 

            return toolBarTrayDesiredSize; 
        } 

        ///  
        /// ToolBarTray arranges its ToolBar children.
        /// 
        /// Size that ToolBarTray will assume to position children.
        protected override Size ArrangeOverride(Size arrangeSize) 
        {
            int bandIndex; 
            int toolBarIndex; 
            bool fHorizontal = (Orientation == Orientation.Horizontal);
            Rect rcChild = new Rect(); 

            for (bandIndex = 0; bandIndex < _bands.Count; bandIndex++)
            {
                List band = _bands[bandIndex].Band; 

                double bandThickness = _bands[bandIndex].Thickness; 
 
                if (fHorizontal)
                    rcChild.X = 0; 
                else
                    rcChild.Y = 0;

                for (toolBarIndex = 0; toolBarIndex < band.Count; toolBarIndex++) 
                {
                    ToolBar toolBar = band[toolBarIndex]; 
                    Size toolBarArrangeSize = new Size(fHorizontal ? toolBar.DesiredSize.Width : bandThickness, fHorizontal ? bandThickness : toolBar.DesiredSize.Height ); 
                    rcChild.Size = toolBarArrangeSize;
                    toolBar.Arrange(rcChild); 
                    if (fHorizontal)
                        rcChild.X += toolBarArrangeSize.Width;
                    else
                        rcChild.Y += toolBarArrangeSize.Height; 
                }
 
                if (fHorizontal) 
                    rcChild.Y += bandThickness;
                else 
                    rcChild.X += bandThickness;
            }

            return arrangeSize; 
        }
 
        ///  
        /// Gets the Visual children count.
        ///  
        protected override int VisualChildrenCount
        {
            get
            { 
                if (_toolBarsCollection == null)
                { 
                    return 0; 
                }
                else 
                {
                    return _toolBarsCollection.Count;
                }
            } 
        }
 
        ///  
        /// Gets the Visual child at the specified index.
        ///  
        protected override Visual GetVisualChild(int index)
        {
            if (_toolBarsCollection == null)
            { 
                throw new ArgumentOutOfRangeException("index", index, SR.Get(SRID.Visual_ArgumentOutOfRange));
            } 
            return _toolBarsCollection[index]; 
        }
 
        #endregion Protected Methods

        //-------------------------------------------------------------------
        // 
        //  Private Methods
        // 
        //------------------------------------------------------------------- 

        #region Private Methods 

        // Event handler to listen to thumb events.
        private static void OnThumbDragDelta(object sender, DragDeltaEventArgs e)
        { 
            ToolBarTray toolBarTray = (ToolBarTray)sender;
 
            // Don't move toolbars if IsLocked == true 
            if (toolBarTray.IsLocked)
                return; 

            toolBarTray.ProcessThumbDragDelta(e);
        }
 
        private void ProcessThumbDragDelta(DragDeltaEventArgs e)
        { 
            // Process thumb event only if Thumb styled parent is a ToolBar under the TollBarTray 
            Thumb thumb = e.OriginalSource as Thumb;
            if (thumb != null) 
            {
                ToolBar toolBar = thumb.TemplatedParent as ToolBar;
                if (toolBar != null && toolBar.Parent == this)
                { 
                    // _bandsDirty would be true at this time only when a Measure gets
                    // skipped between two mouse moves. Ideally that should not happen 
                    // but VS has proved that it can. Hence making the code more robust. 
                    // Uncomment the line below if the measure skip issue ever gets fixed.
                    // Debug.Assert(!_bandsDirty, "Bands should not be dirty at this point"); 
                    if (_bandsDirty)
                    {
                        GenerateBands();
                    } 

                    bool fHorizontal = (Orientation == Orientation.Horizontal); 
                    int currentBand = toolBar.Band; 
                    Point pointRelativeToToolBarTray = Mouse.PrimaryDevice.GetPosition((IInputElement)this);
                    Point pointRelativeToToolBar = TransformPointToToolBar(toolBar, pointRelativeToToolBarTray); 
                    int hittestBand = GetBandFromOffset(fHorizontal ? pointRelativeToToolBarTray.Y : pointRelativeToToolBarTray.X);
                    double newPosition;
                    double thumbChange = fHorizontal ? e.HorizontalChange : e.VerticalChange;
                    double toolBarPosition; 
                    if (fHorizontal)
                    { 
                        toolBarPosition = pointRelativeToToolBarTray.X - pointRelativeToToolBar.X; 
                    }
                    else 
                    {
                        toolBarPosition = pointRelativeToToolBarTray.Y - pointRelativeToToolBar.Y;
                    }
                    newPosition = toolBarPosition + thumbChange; // New toolBar position 

                    // Move within the band 
                    if (hittestBand == currentBand) 
                    {
                        List band = _bands[currentBand].Band; 
                        int toolBarIndex = toolBar.BandIndex;

                        // Move ToolBar within the band
                        if (DoubleUtil.LessThan(thumbChange, 0)) // Move left/up 
                        {
                            double toolBarsTotalMinimum = ToolBarsTotalMinimum(band, 0, toolBarIndex - 1); 
                            // Check if minimized toolbars will fit in the range 
                            if (DoubleUtil.LessThanOrClose(toolBarsTotalMinimum, newPosition))
                            { 
                                ShrinkToolBars(band, 0, toolBarIndex - 1, -thumbChange);
                            }
                            else if (toolBarIndex > 0) // Swap toolbars
                            { 
                                ToolBar prevToolBar = band[toolBarIndex - 1];
                                Point pointRelativeToPreviousToolBar = TransformPointToToolBar(prevToolBar, pointRelativeToToolBarTray); 
                                // if pointer in on the left side of previous toolbar 
                                if (DoubleUtil.LessThan((fHorizontal ? pointRelativeToPreviousToolBar.X : pointRelativeToPreviousToolBar.Y), 0))
                                { 
                                    prevToolBar.BandIndex = toolBarIndex;
                                    band[toolBarIndex] = prevToolBar;

                                    toolBar.BandIndex = toolBarIndex - 1; 
                                    band[toolBarIndex-1] = toolBar;
 
                                    if (toolBarIndex + 1 == band.Count) // If toolBar was the last item in the band 
                                    {
                                        prevToolBar.ClearValue(fHorizontal ? WidthProperty : HeightProperty); 
                                    }

                                }
                                else 
                                { // Move to the left/up and shring the other toolbars
                                    if (fHorizontal) 
                                    { 
                                        if (DoubleUtil.LessThan(toolBarsTotalMinimum, pointRelativeToToolBarTray.X - pointRelativeToToolBar.X))
                                        { 
                                            ShrinkToolBars(band, 0, toolBarIndex - 1, pointRelativeToToolBarTray.X - pointRelativeToToolBar.X - toolBarsTotalMinimum);
                                        }
                                    }
                                    else 
                                    {
                                        if (DoubleUtil.LessThan(toolBarsTotalMinimum, pointRelativeToToolBarTray.Y - pointRelativeToToolBar.Y)) 
                                        { 
                                            ShrinkToolBars(band, 0, toolBarIndex - 1, pointRelativeToToolBarTray.Y - pointRelativeToToolBar.Y - toolBarsTotalMinimum);
                                        } 
                                    }
                                }
                            }
                        } 
                        else // Move right/down
                        { 
                            double toolBarsTotalMaximum = ToolBarsTotalMaximum(band, 0, toolBarIndex - 1); 

                            if (DoubleUtil.GreaterThan(toolBarsTotalMaximum, newPosition)) 
                            {
                                ExpandToolBars(band, 0, toolBarIndex - 1, thumbChange);
                            }
                            else 
                            {
                                if (toolBarIndex < band.Count - 1) // Swap toolbars 
                                { 
                                    ToolBar nextToolBar = band[toolBarIndex + 1];
                                    Point pointRelativeToNextToolBar = TransformPointToToolBar(nextToolBar, pointRelativeToToolBarTray); 
                                    // if pointer in on the right side of next toolbar
                                    if (DoubleUtil.GreaterThanOrClose((fHorizontal ? pointRelativeToNextToolBar.X : pointRelativeToNextToolBar.Y), 0))
                                    {
                                        nextToolBar.BandIndex = toolBarIndex; 
                                        band[toolBarIndex] = nextToolBar;
 
                                        toolBar.BandIndex = toolBarIndex + 1; 
                                        band[toolBarIndex + 1] = toolBar;
                                        if (toolBarIndex + 2 == band.Count) // If toolBar becomes the last item in the band 
                                        {
                                            toolBar.ClearValue(fHorizontal ? WidthProperty : HeightProperty);
                                        }
                                    } 
                                    else
                                    { 
                                        ExpandToolBars(band, 0, toolBarIndex - 1, thumbChange); 
                                    }
                                } 
                                else
                                {
                                    ExpandToolBars(band, 0, toolBarIndex - 1, thumbChange);
                                } 
                            }
                        } 
                    } 
                    else // Move ToolBar to another band
                    { 
                        _bandsDirty = true;
                        toolBar.Band = hittestBand;
                        toolBar.ClearValue(fHorizontal ? WidthProperty : HeightProperty);
 
                        // move to another existing band
                        if (hittestBand >= 0 && hittestBand < _bands.Count) 
                        { 
                            MoveToolBar(toolBar, hittestBand, newPosition);
                        } 

                        List oldBand = _bands[currentBand].Band;
                        // currentBand should restore sizes to Auto
                        for (int i = 0; i < oldBand.Count; i++) 
                        {
                            ToolBar currentToolBar = oldBand[i]; 
                            currentToolBar.ClearValue(fHorizontal ? WidthProperty : HeightProperty); 
                        }
 
                    }

                    e.Handled = true;
                } 
            }
        } 
 
        private Point TransformPointToToolBar(ToolBar toolBar, Point point)
        { 
            Point p = point;
            GeneralTransform transform = this.TransformToDescendant(toolBar);
            if (transform != null)
            { 
                transform.TryTransform(point, out p);
            } 
            return p; 
        }
 
        private void ShrinkToolBars(List band, int startIndex, int endIndex, double shrinkAmount)
        {
            if (Orientation == Orientation.Horizontal)
            { 
                for (int i = endIndex; i >= startIndex; i--)
                { 
                    ToolBar toolBar = band[i]; 
                    if (DoubleUtil.GreaterThanOrClose(toolBar.RenderSize.Width - shrinkAmount, toolBar.MinLength))
                    { 
                        toolBar.Width = toolBar.RenderSize.Width - shrinkAmount;
                        break;
                    }
                    else 
                    {
                        toolBar.Width = toolBar.MinLength; 
                        shrinkAmount -= toolBar.RenderSize.Width - toolBar.MinLength; 
                    }
                } 
            }
            else
            {
                for (int i = endIndex; i >= startIndex; i--) 
                {
                    ToolBar toolBar = band[i]; 
                    if (DoubleUtil.GreaterThanOrClose(toolBar.RenderSize.Height - shrinkAmount, toolBar.MinLength)) 
                    {
                        toolBar.Height = toolBar.RenderSize.Height - shrinkAmount; 
                        break;
                    }
                    else
                    { 
                        toolBar.Height = toolBar.MinLength;
                        shrinkAmount -= toolBar.RenderSize.Height - toolBar.MinLength; 
                    } 
                }
            } 
        }

        private double ToolBarsTotalMinimum(List band, int startIndex, int endIndex)
        { 
            double totalMinLenght = 0d;
            for (int i = startIndex; i <= endIndex; i++) 
            { 
                totalMinLenght += band[i].MinLength;
            } 
            return totalMinLenght;
        }

        private void ExpandToolBars(List band, int startIndex, int endIndex, double expandAmount) 
        {
            if (Orientation == Orientation.Horizontal) 
            { 
                for (int i = endIndex; i >= startIndex; i--)
                { 
                    ToolBar toolBar = band[i];
                    if (DoubleUtil.LessThanOrClose(toolBar.RenderSize.Width + expandAmount, toolBar.MaxLength))
                    {
                        toolBar.Width = toolBar.RenderSize.Width + expandAmount; 
                        break;
                    } 
                    else 
                    {
                        toolBar.Width = toolBar.MaxLength; 
                        expandAmount -= toolBar.MaxLength - toolBar.RenderSize.Width;
                    }
                }
            } 
            else
            { 
                for (int i = endIndex; i >= startIndex; i--) 
                {
                    ToolBar toolBar = band[i]; 
                    if (DoubleUtil.LessThanOrClose(toolBar.RenderSize.Height + expandAmount, toolBar.MaxLength))
                    {
                        toolBar.Height = toolBar.RenderSize.Height + expandAmount;
                        break; 
                    }
                    else 
                    { 
                        toolBar.Height = toolBar.MaxLength;
                        expandAmount -= toolBar.MaxLength - toolBar.RenderSize.Height; 
                    }
                }
            }
        } 

        private double ToolBarsTotalMaximum(List band, int startIndex, int endIndex) 
        { 
            double totalMaxLength = 0d;
            for (int i = startIndex; i <= endIndex; i++) 
            {
                totalMaxLength += band[i].MaxLength;
            }
            return totalMaxLength; 
        }
 
        private void MoveToolBar(ToolBar toolBar, int newBandNumber, double position) 
        {
            int i; 
            bool fHorizontal = Orientation == Orientation.Horizontal;

            List newBand = _bands[newBandNumber].Band;
            // calculate the new BandIndex where toolBar should insert 
            // calculate Width (layout) of the items before the toolBar
            if (DoubleUtil.LessThanOrClose(position, 0)) 
            { 
                toolBar.BandIndex = -1; // This will position toolBar at the first place
            } 
            else
            {
                double toolBarOffset = 0d;
                int newToolBarIndex = -1; 
                for (i = 0; i < newBand.Count; i++)
                { 
                    ToolBar currentToolBar = newBand[i]; 
                    if (newToolBarIndex == -1)
                    { 
                        toolBarOffset += fHorizontal ? currentToolBar.RenderSize.Width : currentToolBar.RenderSize.Height; // points at the end of currentToolBar
                        if (DoubleUtil.GreaterThan(toolBarOffset, position))
                        {
                            newToolBarIndex = i + 1; 
                            toolBar.BandIndex = newToolBarIndex;
                            // Update the currentToolBar width 
                            if (fHorizontal) 
                                currentToolBar.Width = Math.Max(currentToolBar.MinLength, currentToolBar.RenderSize.Width - toolBarOffset + position);
                            else 
                                currentToolBar.Height = Math.Max(currentToolBar.MinLength, currentToolBar.RenderSize.Height - toolBarOffset + position);
                        }
                    }
                    else // After we insert the toolBar we need to increase the indexes 
                    {
                        currentToolBar.BandIndex = i + 1; 
                    } 
                }
                if (newToolBarIndex == -1) 
                {
                    toolBar.BandIndex = i;
                }
            } 

 
        } 

        private int GetBandFromOffset(double toolBarOffset) 
        {
            if (DoubleUtil.LessThan(toolBarOffset, 0))
                return -1;
 
            double bandOffset = 0d;
            for (int i = 0; i < _bands.Count; i++) 
            { 
                bandOffset += _bands[i].Thickness;
                if (DoubleUtil.GreaterThan(bandOffset, toolBarOffset)) 
                    return i;
            }

            return _bands.Count; 
        }
 
        #region Generate and Normalize bands 

        // Generate all bands and normalize Band and BandIndex properties 
        /// All ToolBars with the same Band are places in one band. After that they are sorted by BandIndex.
        private void GenerateBands()
        {
            if (!IsBandsDirty()) 
                return;
 
            Collection toolbarCollection = ToolBars; 

            _bands.Clear(); 
            for (int i = 0; i < toolbarCollection.Count; i++)
            {
                InsertBand(toolbarCollection[i], i);
            } 

            // Normalize bands (make Band and BandIndex property 0,1,2,...) 
            for (int bandIndex = 0; bandIndex < _bands.Count; bandIndex++) 
            {
                List band = _bands[bandIndex].Band; 
                for (int toolBarIndex = 0; toolBarIndex < band.Count; toolBarIndex++)
                {
                    ToolBar toolBar = band[toolBarIndex];
                    // This will cause measure/arrange if some property changes 
                    toolBar.Band = bandIndex;
                    toolBar.BandIndex = toolBarIndex; 
                } 
            }
            _bandsDirty = false; 
        }

        // Verify is all toolbars are normalized (sorted in _bands by Band and BandIndex properties)
        private bool IsBandsDirty() 
        {
            if (_bandsDirty) 
                return true; 

            int totalNumber = 0; 
            Collection toolbarCollection = ToolBars;
            for (int bandIndex = 0; bandIndex < _bands.Count; bandIndex++)
            {
                List band = _bands[bandIndex].Band; 
                for (int toolBarIndex = 0; toolBarIndex < band.Count; toolBarIndex++)
                { 
                    ToolBar toolBar = band[toolBarIndex]; 
                    if (toolBar.Band != bandIndex || toolBar.BandIndex != toolBarIndex || !toolbarCollection.Contains(toolBar))
                        return true; 
                }
                totalNumber += band.Count;
            }
 
            return totalNumber != toolbarCollection.Count;
        } 
 
        // if toolBar.Band does not exist in bands collection when we create a new band
        private void InsertBand(ToolBar toolBar, int toolBarIndex) 
        {
            int bandNumber = toolBar.Band;
            for (int i = 0; i < _bands.Count; i++)
            { 
                int currentBandNumber = ((_bands[i].Band)[0]).Band;
                if (bandNumber == currentBandNumber) 
                    return; 
                if (bandNumber < currentBandNumber)
                { 
                    // Band number does not exist - Insert
                    _bands.Insert(i, CreateBand(toolBarIndex));
                    return;
                } 
            }
 
            // Band number does not exist - Add band at trhe end 
            _bands.Add(CreateBand(toolBarIndex));
 
        }

        // Create new band and add all toolbars with the same Band and toolbar with index startIndex
        private BandInfo CreateBand(int startIndex) 
        {
            Collection toolbarCollection = ToolBars; 
            BandInfo bandInfo = new BandInfo(); 
            ToolBar toolBar = toolbarCollection[startIndex];
            bandInfo.Band.Add(toolBar); 
            int bandNumber = toolBar.Band;
            for (int i = startIndex + 1; i < toolbarCollection.Count; i++)
            {
                toolBar = toolbarCollection[i]; 
                if (bandNumber == toolBar.Band)
                    InsertToolBar(toolBar, bandInfo.Band); 
            } 
            return bandInfo;
        } 

        // Insert toolbar into band list so band remains sorted
        private void InsertToolBar(ToolBar toolBar, List band)
        { 
            for (int i = 0; i < band.Count; i++)
            { 
                if (toolBar.BandIndex < band[i].BandIndex) 
                {
                    band.Insert(i, toolBar); 
                    return;
                }
            }
            band.Add(toolBar); 
        }
 
        #endregion Generate and Normalize bands 

        #endregion 

        //-------------------------------------------------------------------
        //
        //  Private classes 
        //
        //-------------------------------------------------------------------- 
 
        #region Private classes
 
        private class BandInfo
        {
            public BandInfo() { }
 
            public List Band
            { 
                get { return _band; } 
            }
 
            public double Thickness
            {
                get { return _thickness; }
                set { _thickness = value; } 
            }
 
            private List _band = new List(); 
            private double _thickness;
        } 

        #endregion

        #region Private members 

        // ToolBarTray generates list of bands depend on ToolBar.Band property. 
        // Each band is a list of toolbars sorted by ToolBar.BandIndex property. 
        private List _bands = new List(0);
        private bool _bandsDirty = true; 
        private ToolBarCollection _toolBarsCollection = null;

        #endregion
 
        #region DTypeThemeStyleKey
 
        // Returns the DependencyObjectType for the registered ThemeStyleKey's default 
        // value. Controls will override this method to return approriate types.
        internal override DependencyObjectType DTypeThemeStyleKey 
        {
            get { return _dType; }
        }
 
        private static DependencyObjectType _dType;
 
        #endregion DTypeThemeStyleKey 

    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
//---------------------------------------------------------------------------- 
//
// Copyright (C) Microsoft Corporation.  All rights reserved.
//
//--------------------------------------------------------------------------- 

using MS.Internal; 
using MS.Internal.Controls; 
using MS.Internal.Documents;
using MS.Internal.KnownBoxes; 
using MS.Utility;

using System;
using System.Collections; 
using System.Collections.Generic;
using System.Collections.ObjectModel; 
using System.Windows.Controls.Primitives; 
using System.ComponentModel;
using System.Diagnostics; 
using System.Windows.Threading;
using System.Windows.Documents;
using System.Windows.Media;
using System.Windows.Input; 
using System.Windows.Markup; // IAddChild, ContentPropertyAttribute
 
namespace System.Windows.Controls 
{
    ///  
    ///     ToolBarTray is the layout container which handles layout of ToolBars relative to one another.
    /// It is responsible for handling placement, sizing and drag-and-drop to rearrange and
    /// resize behaviors associated with toolbars.
    /// It is also responsible for managing the rows (or "bands") in which toolbars appear. 
    /// A ToolBar tray can be horizontal or vertical and can be used anywhere within an Avalon application,
    /// but it is expected that (like a Menu) it will often be docked to the top or side of the application window. 
    ///  
    [ContentProperty("ToolBars")]
    public class ToolBarTray : FrameworkElement, IAddChild 
    {
        //-------------------------------------------------------------------
        //
        //  Constructors 
        //
        //------------------------------------------------------------------- 
 
        #region Constructors
 
        static ToolBarTray()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(ToolBarTray), new FrameworkPropertyMetadata(typeof(ToolBarTray)));
            _dType = DependencyObjectType.FromSystemTypeInternal(typeof(ToolBarTray)); 

 
            EventManager.RegisterClassHandler(typeof(ToolBarTray), Thumb.DragDeltaEvent, new DragDeltaEventHandler(OnThumbDragDelta)); 
            KeyboardNavigation.ControlTabNavigationProperty.OverrideMetadata(typeof(ToolBarTray), new FrameworkPropertyMetadata(KeyboardNavigationMode.Cycle));
        } 

        /// 
        ///     Default ToolBarTray constructor
        ///  
        public ToolBarTray() : base()
        { 
        } 

        #endregion 

        //--------------------------------------------------------------------
        //
        //  Properties 
        //
        //------------------------------------------------------------------- 
 
        #region Properties
 
        /// 
        /// DependencyProperty for  property.
        /// 
        public static readonly DependencyProperty BackgroundProperty = 
                Panel.BackgroundProperty.AddOwner(typeof(ToolBarTray),
                        new FrameworkPropertyMetadata( 
                                (Brush)null, 
                                FrameworkPropertyMetadataOptions.AffectsRender));
 
        /// 
        /// The Background property defines the brush used to fill the area within the ToolBarTray.
        /// 
        public Brush Background 
        {
            get { return (Brush)GetValue(BackgroundProperty); } 
            set { SetValue(BackgroundProperty, value); } 
        }
 
        /// 
        ///     Orientation property specify the flow direction. The default is horizontal.
        /// 
        public static readonly DependencyProperty OrientationProperty = 
                    DependencyProperty.Register(
                                "Orientation", 
                                typeof(Orientation), 
                                typeof(ToolBarTray),
                                new FrameworkPropertyMetadata( 
                                            Orientation.Horizontal,
                                            FrameworkPropertyMetadataOptions.AffectsParentMeasure,
                                            new PropertyChangedCallback(OnOrientationPropertyChanged)),
                                new ValidateValueCallback(ScrollBar.IsValidOrientation)); 

        // Then ToolBarTray Orientation is changing we need to invalidate its ToolBars Orientation 
        private static void OnOrientationPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
        {
            Collection toolbarCollection = ((ToolBarTray)d).ToolBars; 
            for (int i = 0; i < toolbarCollection.Count; i++)
            {
                toolbarCollection[i].CoerceValue(ToolBar.OrientationProperty);
            } 
        }
 
 
        /// 
        /// Specifies the orientation (horizontal or vertical) 
        /// 
        public Orientation Orientation
        {
            get { return (Orientation) GetValue(OrientationProperty); } 
            set { SetValue(OrientationProperty, value); }
        } 
 
        /// 
        ///     The DependencyProperty for the IsLocked property. 
        /// 
        public static readonly DependencyProperty IsLockedProperty =
                    DependencyProperty.RegisterAttached(
                               "IsLocked", 
                                typeof(bool),
                                typeof(ToolBarTray), 
                                new FrameworkPropertyMetadata( 
                                            BooleanBoxes.FalseBox,
                                            FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.Inherits)); 

        /// 
        /// IsLocked property determine the ability to move the toolbars within the ToolBarTray
        /// If true then thumb from ToolBar style becomes hidden. 
        /// This property inherits so ToolBar can use it in its Style triggers
        /// Default is false. 
        ///  
        public bool IsLocked
        { 
            get { return (bool) GetValue(IsLockedProperty); }
            set { SetValue(IsLockedProperty, value); }
        }
 
        /// 
        /// Writes the attached property IsLocked to the given element. 
        ///  
        /// The element to which to write the attached property.
        /// The property value to set 
        public static void SetIsLocked(DependencyObject element, bool value)
        {
            if (element == null)
            { 
                throw new ArgumentNullException("element");
            } 
            element.SetValue(IsLockedProperty, value); 
        }
 
        /// 
        /// Reads the attached property IsLocked from the given element.
        /// 
        /// The element from which to read the attached property. 
        /// The property's value.
        public static bool GetIsLocked(DependencyObject element) 
        { 
            if (element == null)
            { 
                throw new ArgumentNullException("element");
            }
            return (bool)element.GetValue(IsLockedProperty);
        } 

        ///  
        /// Returns a collection of ToolBar children for user to add/remove children manually 
        /// 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] 
        public Collection ToolBars
        {
            get
            { 
                if (_toolBarsCollection == null)
                    _toolBarsCollection = new ToolBarCollection(this); 
 
                return _toolBarsCollection;
            } 
        }

        private class ToolBarCollection : Collection
        { 
            public ToolBarCollection(ToolBarTray parent)
            { 
                _parent = parent; 
            }
 
            protected override void InsertItem(int index, ToolBar toolBar)
            {
                base.InsertItem(index, toolBar);
 
                _parent.AddLogicalChild(toolBar);
                _parent.AddVisualChild(toolBar); 
                _parent.InvalidateMeasure(); 
            }
 
            protected override void SetItem(int index, ToolBar toolBar)
            {
                ToolBar currentToolBar = Items[index];
                if (toolBar != currentToolBar) 
                {
                    base.SetItem(index, toolBar); 
 
                    // remove old item visual and logical links
                    _parent.RemoveVisualChild(currentToolBar); 
                    _parent.RemoveLogicalChild(currentToolBar);

                    // add new item visual and logical links
                    _parent.AddLogicalChild(toolBar); 
                    _parent.AddVisualChild(toolBar);
                    _parent.InvalidateMeasure(); 
                } 
            }
 
            protected override void RemoveItem(int index)
            {
                ToolBar currentToolBar = this[index];
                base.RemoveItem(index); 

                // remove old item visual and logical links 
                _parent.RemoveVisualChild(currentToolBar); 
                _parent.RemoveLogicalChild(currentToolBar);
                _parent.InvalidateMeasure(); 
            }

            protected override void ClearItems()
            { 
                int count = Count;
                if (count > 0) 
                { 
                    for (int i = 0; i < count; i++)
                    { 
                        ToolBar currentToolBar = this[i];
                        _parent.RemoveVisualChild(currentToolBar);
                        _parent.RemoveLogicalChild(currentToolBar);
                    } 
                    _parent.InvalidateMeasure();
                } 
 
                base.ClearItems();
            } 


            // Ref to a visual/logical ToolBarTray parent
            private readonly ToolBarTray _parent; 
        }
 
        #endregion Properties 

 
        //--------------------------------------------------------------------
        //
        //  Public Methods
        // 
        //--------------------------------------------------------------------
 
        #region Public Methods 
        ///
        /// This method is called to Add the object as a child of the ToolBarTray.  This method is used primarily 
        /// by the parser.
        ///
        ///
        /// The object to add as a child; it must be a UIElement. 
        ///
        ///  
        void IAddChild.AddChild(Object value) 
        {
            if (value == null) 
            {
                throw new ArgumentNullException("value");
            }
 
            ToolBar toolBar = value as ToolBar;
            if (toolBar == null) 
            { 
                throw new ArgumentException(SR.Get(SRID.UnexpectedParameterType, value.GetType(), typeof(ToolBar)), "value");
            } 

            ToolBars.Add(toolBar);
        }
 
        ///
        /// This method is called by the parser when text appears under the tag in markup. 
        /// As default Panels do not support text, calling this method has no effect. 
        ///
        /// 
        /// Text to add as a child.
        ///
        void IAddChild.AddText(string text)
        { 
            XamlSerializerUtil.ThrowIfNonWhiteSpaceInAddText(text, this);
        } 
 

        ///  
        /// Returns enumerator to logical children.
        /// 
        protected internal override IEnumerator LogicalChildren
        { 
            get
            { 
                if (this.VisualChildrenCount == 0) 
                {
                    return EmptyEnumerator.Instance; 
                }

                return this.ToolBars.GetEnumerator();
            } 
        }
 
        #endregion Public Methods 

 
        //-------------------------------------------------------------------
        //
        //  Protected Methods
        // 
        //--------------------------------------------------------------------
 
        #region Protected Methods 

        ///  
        /// Override from UIElement
        /// 
        protected override void OnRender(DrawingContext dc)
        { 
            // Draw background in rectangle inside border.
            Brush background = this.Background; 
            if (background != null) 
            {
                dc.DrawRectangle(background, 
                                 null,
                                 new Rect(0, 0, RenderSize.Width, RenderSize.Height));
            }
        } 

        ///  
        /// Updates DesiredSize of the ToolBarTray. Called by parent UIElement. 
        /// This is the first pass of layout.
        /// MeasureOverride distributes all ToolBars in bands depend on Band and BandIndex properties. 
        /// All ToolBars with the same Band are places in one band. After that they are sorted by BandIndex.
        /// 
        /// Constraint size is an "upper limit" that ToolBarTray should not exceed.
        /// ToolBarTray' desired size. 
        protected override Size MeasureOverride(Size constraint)
        { 
            GenerateBands(); 

            Size toolBarTrayDesiredSize = new Size(); 
            int bandIndex;
            int toolBarIndex;
            bool fHorizontal = (Orientation == Orientation.Horizontal);
            Size childConstraint = new Size(Double.PositiveInfinity, Double.PositiveInfinity); 

            for (bandIndex = 0; bandIndex < _bands.Count; bandIndex++) 
            { 
                // Calculate the available size before we measure the children.
                // remainingLength is the constraint minus sum of all minimum sizes 
                double remainingLength = fHorizontal ? constraint.Width : constraint.Height;
                List band = _bands[bandIndex].Band;
                double bandThickness = 0d;
                double bandLength = 0d; 
                for (toolBarIndex = 0; toolBarIndex < band.Count; toolBarIndex++)
                { 
                    ToolBar toolBar = band[toolBarIndex]; 
                    remainingLength -= toolBar.MinLength;
                    if (DoubleUtil.LessThan(remainingLength, 0)) 
                    {
                        remainingLength = 0;
                        break;
                    } 
                }
 
                // Measure all children passing the remainingLength as a constraint 
                for (toolBarIndex = 0; toolBarIndex < band.Count; toolBarIndex++)
                { 
                    ToolBar toolBar = band[toolBarIndex];
                    remainingLength += toolBar.MinLength;
                    if (fHorizontal)
                        childConstraint.Width = remainingLength; 
                    else
                        childConstraint.Height = remainingLength; 
                    toolBar.Measure(childConstraint); 
                    bandThickness = Math.Max(bandThickness, fHorizontal ? toolBar.DesiredSize.Height : toolBar.DesiredSize.Width);
                    bandLength += fHorizontal ? toolBar.DesiredSize.Width : toolBar.DesiredSize.Height; 
                    remainingLength -= fHorizontal ? toolBar.DesiredSize.Width : toolBar.DesiredSize.Height;
                    if (DoubleUtil.LessThan(remainingLength, 0))
                    {
                        remainingLength = 0; 
                    }
                } 
 
                // Store band thickness in the BandInfo property
                _bands[bandIndex].Thickness = bandThickness; 

                if (fHorizontal)
                {
                    toolBarTrayDesiredSize.Height += bandThickness; 
                    toolBarTrayDesiredSize.Width = Math.Max(toolBarTrayDesiredSize.Width, bandLength);
                } 
                else 
                {
                    toolBarTrayDesiredSize.Width += bandThickness; 
                    toolBarTrayDesiredSize.Height = Math.Max(toolBarTrayDesiredSize.Height, bandLength);
                }

            } 

            return toolBarTrayDesiredSize; 
        } 

        ///  
        /// ToolBarTray arranges its ToolBar children.
        /// 
        /// Size that ToolBarTray will assume to position children.
        protected override Size ArrangeOverride(Size arrangeSize) 
        {
            int bandIndex; 
            int toolBarIndex; 
            bool fHorizontal = (Orientation == Orientation.Horizontal);
            Rect rcChild = new Rect(); 

            for (bandIndex = 0; bandIndex < _bands.Count; bandIndex++)
            {
                List band = _bands[bandIndex].Band; 

                double bandThickness = _bands[bandIndex].Thickness; 
 
                if (fHorizontal)
                    rcChild.X = 0; 
                else
                    rcChild.Y = 0;

                for (toolBarIndex = 0; toolBarIndex < band.Count; toolBarIndex++) 
                {
                    ToolBar toolBar = band[toolBarIndex]; 
                    Size toolBarArrangeSize = new Size(fHorizontal ? toolBar.DesiredSize.Width : bandThickness, fHorizontal ? bandThickness : toolBar.DesiredSize.Height ); 
                    rcChild.Size = toolBarArrangeSize;
                    toolBar.Arrange(rcChild); 
                    if (fHorizontal)
                        rcChild.X += toolBarArrangeSize.Width;
                    else
                        rcChild.Y += toolBarArrangeSize.Height; 
                }
 
                if (fHorizontal) 
                    rcChild.Y += bandThickness;
                else 
                    rcChild.X += bandThickness;
            }

            return arrangeSize; 
        }
 
        ///  
        /// Gets the Visual children count.
        ///  
        protected override int VisualChildrenCount
        {
            get
            { 
                if (_toolBarsCollection == null)
                { 
                    return 0; 
                }
                else 
                {
                    return _toolBarsCollection.Count;
                }
            } 
        }
 
        ///  
        /// Gets the Visual child at the specified index.
        ///  
        protected override Visual GetVisualChild(int index)
        {
            if (_toolBarsCollection == null)
            { 
                throw new ArgumentOutOfRangeException("index", index, SR.Get(SRID.Visual_ArgumentOutOfRange));
            } 
            return _toolBarsCollection[index]; 
        }
 
        #endregion Protected Methods

        //-------------------------------------------------------------------
        // 
        //  Private Methods
        // 
        //------------------------------------------------------------------- 

        #region Private Methods 

        // Event handler to listen to thumb events.
        private static void OnThumbDragDelta(object sender, DragDeltaEventArgs e)
        { 
            ToolBarTray toolBarTray = (ToolBarTray)sender;
 
            // Don't move toolbars if IsLocked == true 
            if (toolBarTray.IsLocked)
                return; 

            toolBarTray.ProcessThumbDragDelta(e);
        }
 
        private void ProcessThumbDragDelta(DragDeltaEventArgs e)
        { 
            // Process thumb event only if Thumb styled parent is a ToolBar under the TollBarTray 
            Thumb thumb = e.OriginalSource as Thumb;
            if (thumb != null) 
            {
                ToolBar toolBar = thumb.TemplatedParent as ToolBar;
                if (toolBar != null && toolBar.Parent == this)
                { 
                    // _bandsDirty would be true at this time only when a Measure gets
                    // skipped between two mouse moves. Ideally that should not happen 
                    // but VS has proved that it can. Hence making the code more robust. 
                    // Uncomment the line below if the measure skip issue ever gets fixed.
                    // Debug.Assert(!_bandsDirty, "Bands should not be dirty at this point"); 
                    if (_bandsDirty)
                    {
                        GenerateBands();
                    } 

                    bool fHorizontal = (Orientation == Orientation.Horizontal); 
                    int currentBand = toolBar.Band; 
                    Point pointRelativeToToolBarTray = Mouse.PrimaryDevice.GetPosition((IInputElement)this);
                    Point pointRelativeToToolBar = TransformPointToToolBar(toolBar, pointRelativeToToolBarTray); 
                    int hittestBand = GetBandFromOffset(fHorizontal ? pointRelativeToToolBarTray.Y : pointRelativeToToolBarTray.X);
                    double newPosition;
                    double thumbChange = fHorizontal ? e.HorizontalChange : e.VerticalChange;
                    double toolBarPosition; 
                    if (fHorizontal)
                    { 
                        toolBarPosition = pointRelativeToToolBarTray.X - pointRelativeToToolBar.X; 
                    }
                    else 
                    {
                        toolBarPosition = pointRelativeToToolBarTray.Y - pointRelativeToToolBar.Y;
                    }
                    newPosition = toolBarPosition + thumbChange; // New toolBar position 

                    // Move within the band 
                    if (hittestBand == currentBand) 
                    {
                        List band = _bands[currentBand].Band; 
                        int toolBarIndex = toolBar.BandIndex;

                        // Move ToolBar within the band
                        if (DoubleUtil.LessThan(thumbChange, 0)) // Move left/up 
                        {
                            double toolBarsTotalMinimum = ToolBarsTotalMinimum(band, 0, toolBarIndex - 1); 
                            // Check if minimized toolbars will fit in the range 
                            if (DoubleUtil.LessThanOrClose(toolBarsTotalMinimum, newPosition))
                            { 
                                ShrinkToolBars(band, 0, toolBarIndex - 1, -thumbChange);
                            }
                            else if (toolBarIndex > 0) // Swap toolbars
                            { 
                                ToolBar prevToolBar = band[toolBarIndex - 1];
                                Point pointRelativeToPreviousToolBar = TransformPointToToolBar(prevToolBar, pointRelativeToToolBarTray); 
                                // if pointer in on the left side of previous toolbar 
                                if (DoubleUtil.LessThan((fHorizontal ? pointRelativeToPreviousToolBar.X : pointRelativeToPreviousToolBar.Y), 0))
                                { 
                                    prevToolBar.BandIndex = toolBarIndex;
                                    band[toolBarIndex] = prevToolBar;

                                    toolBar.BandIndex = toolBarIndex - 1; 
                                    band[toolBarIndex-1] = toolBar;
 
                                    if (toolBarIndex + 1 == band.Count) // If toolBar was the last item in the band 
                                    {
                                        prevToolBar.ClearValue(fHorizontal ? WidthProperty : HeightProperty); 
                                    }

                                }
                                else 
                                { // Move to the left/up and shring the other toolbars
                                    if (fHorizontal) 
                                    { 
                                        if (DoubleUtil.LessThan(toolBarsTotalMinimum, pointRelativeToToolBarTray.X - pointRelativeToToolBar.X))
                                        { 
                                            ShrinkToolBars(band, 0, toolBarIndex - 1, pointRelativeToToolBarTray.X - pointRelativeToToolBar.X - toolBarsTotalMinimum);
                                        }
                                    }
                                    else 
                                    {
                                        if (DoubleUtil.LessThan(toolBarsTotalMinimum, pointRelativeToToolBarTray.Y - pointRelativeToToolBar.Y)) 
                                        { 
                                            ShrinkToolBars(band, 0, toolBarIndex - 1, pointRelativeToToolBarTray.Y - pointRelativeToToolBar.Y - toolBarsTotalMinimum);
                                        } 
                                    }
                                }
                            }
                        } 
                        else // Move right/down
                        { 
                            double toolBarsTotalMaximum = ToolBarsTotalMaximum(band, 0, toolBarIndex - 1); 

                            if (DoubleUtil.GreaterThan(toolBarsTotalMaximum, newPosition)) 
                            {
                                ExpandToolBars(band, 0, toolBarIndex - 1, thumbChange);
                            }
                            else 
                            {
                                if (toolBarIndex < band.Count - 1) // Swap toolbars 
                                { 
                                    ToolBar nextToolBar = band[toolBarIndex + 1];
                                    Point pointRelativeToNextToolBar = TransformPointToToolBar(nextToolBar, pointRelativeToToolBarTray); 
                                    // if pointer in on the right side of next toolbar
                                    if (DoubleUtil.GreaterThanOrClose((fHorizontal ? pointRelativeToNextToolBar.X : pointRelativeToNextToolBar.Y), 0))
                                    {
                                        nextToolBar.BandIndex = toolBarIndex; 
                                        band[toolBarIndex] = nextToolBar;
 
                                        toolBar.BandIndex = toolBarIndex + 1; 
                                        band[toolBarIndex + 1] = toolBar;
                                        if (toolBarIndex + 2 == band.Count) // If toolBar becomes the last item in the band 
                                        {
                                            toolBar.ClearValue(fHorizontal ? WidthProperty : HeightProperty);
                                        }
                                    } 
                                    else
                                    { 
                                        ExpandToolBars(band, 0, toolBarIndex - 1, thumbChange); 
                                    }
                                } 
                                else
                                {
                                    ExpandToolBars(band, 0, toolBarIndex - 1, thumbChange);
                                } 
                            }
                        } 
                    } 
                    else // Move ToolBar to another band
                    { 
                        _bandsDirty = true;
                        toolBar.Band = hittestBand;
                        toolBar.ClearValue(fHorizontal ? WidthProperty : HeightProperty);
 
                        // move to another existing band
                        if (hittestBand >= 0 && hittestBand < _bands.Count) 
                        { 
                            MoveToolBar(toolBar, hittestBand, newPosition);
                        } 

                        List oldBand = _bands[currentBand].Band;
                        // currentBand should restore sizes to Auto
                        for (int i = 0; i < oldBand.Count; i++) 
                        {
                            ToolBar currentToolBar = oldBand[i]; 
                            currentToolBar.ClearValue(fHorizontal ? WidthProperty : HeightProperty); 
                        }
 
                    }

                    e.Handled = true;
                } 
            }
        } 
 
        private Point TransformPointToToolBar(ToolBar toolBar, Point point)
        { 
            Point p = point;
            GeneralTransform transform = this.TransformToDescendant(toolBar);
            if (transform != null)
            { 
                transform.TryTransform(point, out p);
            } 
            return p; 
        }
 
        private void ShrinkToolBars(List band, int startIndex, int endIndex, double shrinkAmount)
        {
            if (Orientation == Orientation.Horizontal)
            { 
                for (int i = endIndex; i >= startIndex; i--)
                { 
                    ToolBar toolBar = band[i]; 
                    if (DoubleUtil.GreaterThanOrClose(toolBar.RenderSize.Width - shrinkAmount, toolBar.MinLength))
                    { 
                        toolBar.Width = toolBar.RenderSize.Width - shrinkAmount;
                        break;
                    }
                    else 
                    {
                        toolBar.Width = toolBar.MinLength; 
                        shrinkAmount -= toolBar.RenderSize.Width - toolBar.MinLength; 
                    }
                } 
            }
            else
            {
                for (int i = endIndex; i >= startIndex; i--) 
                {
                    ToolBar toolBar = band[i]; 
                    if (DoubleUtil.GreaterThanOrClose(toolBar.RenderSize.Height - shrinkAmount, toolBar.MinLength)) 
                    {
                        toolBar.Height = toolBar.RenderSize.Height - shrinkAmount; 
                        break;
                    }
                    else
                    { 
                        toolBar.Height = toolBar.MinLength;
                        shrinkAmount -= toolBar.RenderSize.Height - toolBar.MinLength; 
                    } 
                }
            } 
        }

        private double ToolBarsTotalMinimum(List band, int startIndex, int endIndex)
        { 
            double totalMinLenght = 0d;
            for (int i = startIndex; i <= endIndex; i++) 
            { 
                totalMinLenght += band[i].MinLength;
            } 
            return totalMinLenght;
        }

        private void ExpandToolBars(List band, int startIndex, int endIndex, double expandAmount) 
        {
            if (Orientation == Orientation.Horizontal) 
            { 
                for (int i = endIndex; i >= startIndex; i--)
                { 
                    ToolBar toolBar = band[i];
                    if (DoubleUtil.LessThanOrClose(toolBar.RenderSize.Width + expandAmount, toolBar.MaxLength))
                    {
                        toolBar.Width = toolBar.RenderSize.Width + expandAmount; 
                        break;
                    } 
                    else 
                    {
                        toolBar.Width = toolBar.MaxLength; 
                        expandAmount -= toolBar.MaxLength - toolBar.RenderSize.Width;
                    }
                }
            } 
            else
            { 
                for (int i = endIndex; i >= startIndex; i--) 
                {
                    ToolBar toolBar = band[i]; 
                    if (DoubleUtil.LessThanOrClose(toolBar.RenderSize.Height + expandAmount, toolBar.MaxLength))
                    {
                        toolBar.Height = toolBar.RenderSize.Height + expandAmount;
                        break; 
                    }
                    else 
                    { 
                        toolBar.Height = toolBar.MaxLength;
                        expandAmount -= toolBar.MaxLength - toolBar.RenderSize.Height; 
                    }
                }
            }
        } 

        private double ToolBarsTotalMaximum(List band, int startIndex, int endIndex) 
        { 
            double totalMaxLength = 0d;
            for (int i = startIndex; i <= endIndex; i++) 
            {
                totalMaxLength += band[i].MaxLength;
            }
            return totalMaxLength; 
        }
 
        private void MoveToolBar(ToolBar toolBar, int newBandNumber, double position) 
        {
            int i; 
            bool fHorizontal = Orientation == Orientation.Horizontal;

            List newBand = _bands[newBandNumber].Band;
            // calculate the new BandIndex where toolBar should insert 
            // calculate Width (layout) of the items before the toolBar
            if (DoubleUtil.LessThanOrClose(position, 0)) 
            { 
                toolBar.BandIndex = -1; // This will position toolBar at the first place
            } 
            else
            {
                double toolBarOffset = 0d;
                int newToolBarIndex = -1; 
                for (i = 0; i < newBand.Count; i++)
                { 
                    ToolBar currentToolBar = newBand[i]; 
                    if (newToolBarIndex == -1)
                    { 
                        toolBarOffset += fHorizontal ? currentToolBar.RenderSize.Width : currentToolBar.RenderSize.Height; // points at the end of currentToolBar
                        if (DoubleUtil.GreaterThan(toolBarOffset, position))
                        {
                            newToolBarIndex = i + 1; 
                            toolBar.BandIndex = newToolBarIndex;
                            // Update the currentToolBar width 
                            if (fHorizontal) 
                                currentToolBar.Width = Math.Max(currentToolBar.MinLength, currentToolBar.RenderSize.Width - toolBarOffset + position);
                            else 
                                currentToolBar.Height = Math.Max(currentToolBar.MinLength, currentToolBar.RenderSize.Height - toolBarOffset + position);
                        }
                    }
                    else // After we insert the toolBar we need to increase the indexes 
                    {
                        currentToolBar.BandIndex = i + 1; 
                    } 
                }
                if (newToolBarIndex == -1) 
                {
                    toolBar.BandIndex = i;
                }
            } 

 
        } 

        private int GetBandFromOffset(double toolBarOffset) 
        {
            if (DoubleUtil.LessThan(toolBarOffset, 0))
                return -1;
 
            double bandOffset = 0d;
            for (int i = 0; i < _bands.Count; i++) 
            { 
                bandOffset += _bands[i].Thickness;
                if (DoubleUtil.GreaterThan(bandOffset, toolBarOffset)) 
                    return i;
            }

            return _bands.Count; 
        }
 
        #region Generate and Normalize bands 

        // Generate all bands and normalize Band and BandIndex properties 
        /// All ToolBars with the same Band are places in one band. After that they are sorted by BandIndex.
        private void GenerateBands()
        {
            if (!IsBandsDirty()) 
                return;
 
            Collection toolbarCollection = ToolBars; 

            _bands.Clear(); 
            for (int i = 0; i < toolbarCollection.Count; i++)
            {
                InsertBand(toolbarCollection[i], i);
            } 

            // Normalize bands (make Band and BandIndex property 0,1,2,...) 
            for (int bandIndex = 0; bandIndex < _bands.Count; bandIndex++) 
            {
                List band = _bands[bandIndex].Band; 
                for (int toolBarIndex = 0; toolBarIndex < band.Count; toolBarIndex++)
                {
                    ToolBar toolBar = band[toolBarIndex];
                    // This will cause measure/arrange if some property changes 
                    toolBar.Band = bandIndex;
                    toolBar.BandIndex = toolBarIndex; 
                } 
            }
            _bandsDirty = false; 
        }

        // Verify is all toolbars are normalized (sorted in _bands by Band and BandIndex properties)
        private bool IsBandsDirty() 
        {
            if (_bandsDirty) 
                return true; 

            int totalNumber = 0; 
            Collection toolbarCollection = ToolBars;
            for (int bandIndex = 0; bandIndex < _bands.Count; bandIndex++)
            {
                List band = _bands[bandIndex].Band; 
                for (int toolBarIndex = 0; toolBarIndex < band.Count; toolBarIndex++)
                { 
                    ToolBar toolBar = band[toolBarIndex]; 
                    if (toolBar.Band != bandIndex || toolBar.BandIndex != toolBarIndex || !toolbarCollection.Contains(toolBar))
                        return true; 
                }
                totalNumber += band.Count;
            }
 
            return totalNumber != toolbarCollection.Count;
        } 
 
        // if toolBar.Band does not exist in bands collection when we create a new band
        private void InsertBand(ToolBar toolBar, int toolBarIndex) 
        {
            int bandNumber = toolBar.Band;
            for (int i = 0; i < _bands.Count; i++)
            { 
                int currentBandNumber = ((_bands[i].Band)[0]).Band;
                if (bandNumber == currentBandNumber) 
                    return; 
                if (bandNumber < currentBandNumber)
                { 
                    // Band number does not exist - Insert
                    _bands.Insert(i, CreateBand(toolBarIndex));
                    return;
                } 
            }
 
            // Band number does not exist - Add band at trhe end 
            _bands.Add(CreateBand(toolBarIndex));
 
        }

        // Create new band and add all toolbars with the same Band and toolbar with index startIndex
        private BandInfo CreateBand(int startIndex) 
        {
            Collection toolbarCollection = ToolBars; 
            BandInfo bandInfo = new BandInfo(); 
            ToolBar toolBar = toolbarCollection[startIndex];
            bandInfo.Band.Add(toolBar); 
            int bandNumber = toolBar.Band;
            for (int i = startIndex + 1; i < toolbarCollection.Count; i++)
            {
                toolBar = toolbarCollection[i]; 
                if (bandNumber == toolBar.Band)
                    InsertToolBar(toolBar, bandInfo.Band); 
            } 
            return bandInfo;
        } 

        // Insert toolbar into band list so band remains sorted
        private void InsertToolBar(ToolBar toolBar, List band)
        { 
            for (int i = 0; i < band.Count; i++)
            { 
                if (toolBar.BandIndex < band[i].BandIndex) 
                {
                    band.Insert(i, toolBar); 
                    return;
                }
            }
            band.Add(toolBar); 
        }
 
        #endregion Generate and Normalize bands 

        #endregion 

        //-------------------------------------------------------------------
        //
        //  Private classes 
        //
        //-------------------------------------------------------------------- 
 
        #region Private classes
 
        private class BandInfo
        {
            public BandInfo() { }
 
            public List Band
            { 
                get { return _band; } 
            }
 
            public double Thickness
            {
                get { return _thickness; }
                set { _thickness = value; } 
            }
 
            private List _band = new List(); 
            private double _thickness;
        } 

        #endregion

        #region Private members 

        // ToolBarTray generates list of bands depend on ToolBar.Band property. 
        // Each band is a list of toolbars sorted by ToolBar.BandIndex property. 
        private List _bands = new List(0);
        private bool _bandsDirty = true; 
        private ToolBarCollection _toolBarsCollection = null;

        #endregion
 
        #region DTypeThemeStyleKey
 
        // Returns the DependencyObjectType for the registered ThemeStyleKey's default 
        // value. Controls will override this method to return approriate types.
        internal override DependencyObjectType DTypeThemeStyleKey 
        {
            get { return _dType; }
        }
 
        private static DependencyObjectType _dType;
 
        #endregion DTypeThemeStyleKey 

    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK