ToolBarTray.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / wpf / src / Framework / System / Windows / Controls / ToolBarTray.cs / 1 / 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(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 (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 (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)
                { 
                    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 (thumbChange < 0) // Move left/up
                        { 
                            double toolBarsTotalMinimum = ToolBarsTotalMinimum(band, 0, toolBarIndex - 1);
                            // Check if minimized toolbars will fit in the range 
                            if (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 ((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 (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 ((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 
                                        if (DoubleUtil.LessThan(toolBarPosition, toolBarsTotalMaximum))
                                        { 
                                            ExpandToolBars(band, 0, toolBarIndex - 1, toolBarsTotalMaximum - toolBarPosition); 
                                        }
                                } 
                                else
                                    if (DoubleUtil.LessThan(toolBarPosition, toolBarsTotalMaximum))
                                    {
                                        ExpandToolBars(band, 0, toolBarIndex - 1, toolBarsTotalMaximum - toolBarPosition); 
                                    }
                            } 
                        } 
                    }
                    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 (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 (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 (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 (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 (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 (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 (toolBarOffset < 0)
                return -1; 

            double bandOffset = 0d; 
            for (int i = 0; i < _bands.Count; i++) 
            {
                bandOffset += _bands[i].Thickness; 
                if (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(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 (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 (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)
                { 
                    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 (thumbChange < 0) // Move left/up
                        { 
                            double toolBarsTotalMinimum = ToolBarsTotalMinimum(band, 0, toolBarIndex - 1);
                            // Check if minimized toolbars will fit in the range 
                            if (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 ((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 (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 ((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 
                                        if (DoubleUtil.LessThan(toolBarPosition, toolBarsTotalMaximum))
                                        { 
                                            ExpandToolBars(band, 0, toolBarIndex - 1, toolBarsTotalMaximum - toolBarPosition); 
                                        }
                                } 
                                else
                                    if (DoubleUtil.LessThan(toolBarPosition, toolBarsTotalMaximum))
                                    {
                                        ExpandToolBars(band, 0, toolBarIndex - 1, toolBarsTotalMaximum - toolBarPosition); 
                                    }
                            } 
                        } 
                    }
                    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 (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 (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 (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 (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 (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 (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 (toolBarOffset < 0)
                return -1; 

            double bandOffset = 0d; 
            for (int i = 0; i < _bands.Count; i++) 
            {
                bandOffset += _bands[i].Thickness; 
                if (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