Code:
/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / Orcas / QFE / 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

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- DiagnosticStrings.cs
- GroupStyle.cs
- FixedSchema.cs
- StandardCommandToolStripMenuItem.cs
- ModelProperty.cs
- DataPointer.cs
- ping.cs
- GeometryGroup.cs
- MissingMethodException.cs
- ContentTextAutomationPeer.cs
- TableSectionStyle.cs
- _ListenerResponseStream.cs
- CannotUnloadAppDomainException.cs
- TraceSection.cs
- ConnectionConsumerAttribute.cs
- _HelperAsyncResults.cs
- DesignTimeHTMLTextWriter.cs
- ShapingWorkspace.cs
- VarRemapper.cs
- MailAddressCollection.cs
- PhoneCallDesigner.cs
- _DigestClient.cs
- InteropExecutor.cs
- MemberHolder.cs
- CombinedGeometry.cs
- PeerContact.cs
- ReadOnlyMetadataCollection.cs
- localization.cs
- ObjectListComponentEditor.cs
- SoundPlayer.cs
- PropertyFilter.cs
- Highlights.cs
- MetadataArtifactLoaderComposite.cs
- HtmlElement.cs
- WebPartDescription.cs
- XmlSchemaRedefine.cs
- DefaultMemberAttribute.cs
- X509SecurityTokenProvider.cs
- XmlPreloadedResolver.cs
- WebPartMenu.cs
- DataGridComponentEditor.cs
- TextDecorations.cs
- QueryIntervalOp.cs
- Popup.cs
- Compress.cs
- CodeTypeDelegate.cs
- Sql8ExpressionRewriter.cs
- DataObject.cs
- InlineUIContainer.cs
- RSAPKCS1KeyExchangeFormatter.cs
- TypeUtil.cs
- basemetadatamappingvisitor.cs
- MonitoringDescriptionAttribute.cs
- BitStack.cs
- DragEvent.cs
- XmlEnumAttribute.cs
- ArgumentNullException.cs
- SafeRightsManagementSessionHandle.cs
- JoinGraph.cs
- CodeExpressionCollection.cs
- ContentPlaceHolder.cs
- Model3DGroup.cs
- ResourceDisplayNameAttribute.cs
- FacetDescription.cs
- DataGridViewColumnHeaderCell.cs
- NGCPageContentSerializerAsync.cs
- ExpressionsCollectionConverter.cs
- XsdBuilder.cs
- GradientStop.cs
- ExpressionParser.cs
- DataGridViewColumnHeaderCell.cs
- ExecutionEngineException.cs
- CompoundFileReference.cs
- XmlNotation.cs
- QueueProcessor.cs
- BamlRecords.cs
- TreeSet.cs
- Stack.cs
- PromptStyle.cs
- XmlSortKey.cs
- EncodingDataItem.cs
- InteropBitmapSource.cs
- TabRenderer.cs
- DataObjectPastingEventArgs.cs
- MetricEntry.cs
- StrongNameIdentityPermission.cs
- XmlWriterTraceListener.cs
- MinimizableAttributeTypeConverter.cs
- MouseBinding.cs
- FirstMatchCodeGroup.cs
- MsmqHostedTransportManager.cs
- InboundActivityHelper.cs
- WizardStepBase.cs
- FileDialogCustomPlacesCollection.cs
- DirectoryNotFoundException.cs
- PersonalizationDictionary.cs
- UpdateInfo.cs
- ItemMap.cs
- MultilineStringConverter.cs
- RC2CryptoServiceProvider.cs