|
//------------------------------------------------------------------------------
// <copyright file="ToolStripPanelCell.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
namespace System.Windows.Forms {
using System.Drawing;
using System.Windows.Forms.Layout;
using System.Collections.Specialized;
using System.Collections;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
/// this class is a container for toolstrips on a rafting row.
/// you can set layout styles on this container all day long and not
/// affect the underlying toolstrip's properties.... so if its
/// removed from a rafting container its still got its defaults
/// set up for it.
internal class ToolStripPanelCell : ArrangedElement {
private ToolStrip _wrappedToolStrip = null;
private ToolStripPanelRow parent = null;
private Size maxSize = LayoutUtils.MaxSize;
private bool currentlySizing = false;
private bool currentlyDragging = false;
private bool restoreOnVisibleChanged = false;
private Rectangle cachedBounds = Rectangle.Empty;
#if DEBUG
private string cellID;
[ThreadStatic]
private static int cellCount;
#endif
public ToolStripPanelCell(Control control):this(null, control) {
}
public ToolStripPanelCell(ToolStripPanelRow parent, Control control) {
#if DEBUG
// Ensure 1:1 Cell/ToolStripPanel mapping
cellID = string.Format(CultureInfo.CurrentCulture, "{0}.{1}", control.Name, ++cellCount);
Debug.Assert(cellCount <= ToolStripManager.ToolStrips.Count, "who is allocating an extra toolstrippanel cell?");
#endif
this.ToolStripPanelRow = parent;
this._wrappedToolStrip = control as ToolStrip;
if (control == null) {
throw new ArgumentNullException("control");
}
else if (_wrappedToolStrip == null) {
throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, SR.GetString(SR.TypedControlCollectionShouldBeOfType, typeof(ToolStrip).Name)), control.GetType().Name);
}
CommonProperties.SetAutoSize(this, true);
_wrappedToolStrip.LocationChanging += new ToolStripLocationCancelEventHandler(this.OnToolStripLocationChanging);
_wrappedToolStrip.VisibleChanged += new EventHandler(this.OnToolStripVisibleChanged);
}
public Rectangle CachedBounds {
get { return cachedBounds; }
set { cachedBounds = value;
Debug.Assert(cachedBounds.X >= 0 && cachedBounds.Y >= 0, "cached bounds are outside of the client area, investigate");
}
}
public Control Control {
get { return _wrappedToolStrip; }
}
// ToolStripPanelCell is considered to be Visible if the wrapped control is InDesignMode.
// This property is accessed from the ToolStripPanelRow in cases where we are moving the toolStrip around
// during a drag operation.
public bool ControlInDesignMode {
get { return (_wrappedToolStrip != null && _wrappedToolStrip.IsInDesignMode); }
}
public IArrangedElement InnerElement {
get { return _wrappedToolStrip as IArrangedElement; }
}
public ISupportToolStripPanel DraggedControl {
get { return _wrappedToolStrip as ISupportToolStripPanel; }
}
public ToolStripPanelRow ToolStripPanelRow {
get { return parent; }
set {
if (parent != value) {
if (parent != null) {
((IList)parent.Cells).Remove(this);
}
parent = value;
this.Margin = Padding.Empty;
}
}
}
public override bool Visible {
get {
if (Control != null && Control.ParentInternal == ToolStripPanelRow.ToolStripPanel) {
return InnerElement.ParticipatesInLayout;
}
return false;
}
set {
Control.Visible = value;
}
}
public Size MaximumSize {
get { return maxSize; }
}
public override LayoutEngine LayoutEngine {
get { return DefaultLayout.Instance; }
}
protected override IArrangedElement GetContainer() {
return parent;
}
public int Grow(int growBy) {
if (ToolStripPanelRow.Orientation == Orientation.Vertical) {
return GrowVertical(growBy);
}
else {
return GrowHorizontal(growBy);
}
}
private int GrowVertical(int growBy) {
// Grow ---]
// Pref [ ]
// Max [ ]
if (MaximumSize.Height >= Control.PreferredSize.Height) {
// nothing to grow.
return 0;
}
// Grow ---]
// Pref [ ]
// Max [ ]
if (MaximumSize.Height + growBy >= Control.PreferredSize.Height) {
int freed = Control.PreferredSize.Height - MaximumSize.Height;
maxSize=LayoutUtils.MaxSize;
return freed;
}
// Grow ---]
// Pref [ ]
// Max [ ]
if (MaximumSize.Height + growBy < Control.PreferredSize.Height) {
maxSize.Height += growBy;
return growBy;
}
return 0;
}
private int GrowHorizontal(int growBy) {
// Grow ---]
// Pref [ ]
// Max [ ]
if (MaximumSize.Width >= Control.PreferredSize.Width) {
// nothing to grow.
return 0;
}
// Grow ---]
// Pref [ ]
// Max [ ]
if (MaximumSize.Width + growBy >= Control.PreferredSize.Width) {
int freed = Control.PreferredSize.Width - MaximumSize.Width;
maxSize=LayoutUtils.MaxSize;
return freed;
}
// Grow ---]
// Pref [ ]
// Max [ ]
if (MaximumSize.Width + growBy < Control.PreferredSize.Width) {
maxSize.Width += growBy;
return growBy;
}
return 0;
}
protected override void Dispose(bool disposing) {
try {
if (disposing) {
if (_wrappedToolStrip != null) {
#if DEBUG
cellCount--;
#endif
_wrappedToolStrip.LocationChanging -= new ToolStripLocationCancelEventHandler(this.OnToolStripLocationChanging);
_wrappedToolStrip.VisibleChanged -= new EventHandler(this.OnToolStripVisibleChanged);
}
_wrappedToolStrip = null;
if (parent != null) {
((IList)parent.Cells).Remove(this);
}
parent = null;
}
#if DEBUG
else {
cellCount--;
}
#endif
}
finally {
base.Dispose(disposing);
}
}
protected override ArrangedElementCollection GetChildren() {
return ArrangedElementCollection.Empty;
}
public override Size GetPreferredSize(Size constrainingSize) {
ISupportToolStripPanel draggedControl = DraggedControl;
Size preferredSize = Size.Empty;
if (draggedControl.Stretch) {
if (ToolStripPanelRow.Orientation == Orientation.Horizontal) {
constrainingSize.Width = ToolStripPanelRow.Bounds.Width;
preferredSize = _wrappedToolStrip.GetPreferredSize(constrainingSize);
preferredSize.Width = constrainingSize.Width;
}
else {
constrainingSize.Height = ToolStripPanelRow.Bounds.Height;
preferredSize = _wrappedToolStrip.GetPreferredSize(constrainingSize);
preferredSize.Height = constrainingSize.Height;
}
}
else {
preferredSize = (!_wrappedToolStrip.AutoSize) ? _wrappedToolStrip.Size : _wrappedToolStrip.GetPreferredSize(constrainingSize);
}
// return LayoutUtils.IntersectSizes(constrainingSize, preferredSize);
return preferredSize;
}
protected override void SetBoundsCore(Rectangle bounds, BoundsSpecified specified) {
currentlySizing = true;
this.CachedBounds = bounds;
try
{
if (DraggedControl.IsCurrentlyDragging) {
if (ToolStripPanelRow.Cells[ToolStripPanelRow.Cells.Count -1] == this) {
Rectangle displayRectangle = ToolStripPanelRow.DisplayRectangle;
if (ToolStripPanelRow.Orientation == Orientation.Horizontal) {
int spaceToFree = bounds.Right - displayRectangle.Right;
if (spaceToFree > 0 && bounds.Width > spaceToFree) {
bounds.Width -= spaceToFree;
}
}
else {
int spaceToFree = bounds.Bottom - displayRectangle.Bottom;
if (spaceToFree > 0 && bounds.Height > spaceToFree) {
bounds.Height -= spaceToFree;
}
}
}
Debug.WriteLineIf(ToolStripPanelRow.ToolStripPanelMouseDebug.TraceVerbose, "[CELL] DRAGGING calling SetBounds " + bounds.ToString());
base.SetBoundsCore(bounds,specified);
InnerElement.SetBounds(bounds, specified);
}
else {
if (!ToolStripPanelRow.CachedBoundsMode) {
Debug.WriteLineIf(ToolStripPanelRow.ToolStripPanelMouseDebug.TraceVerbose, "[CELL] NOT DRAGGING calling SetBounds " + bounds.ToString());
base.SetBoundsCore(bounds,specified);
InnerElement.SetBounds(bounds, specified);
}
}
}
finally
{
currentlySizing = false;
}
}
public int Shrink(int shrinkBy) {
if (ToolStripPanelRow.Orientation == Orientation.Vertical) {
return ShrinkVertical(shrinkBy);
}
else {
return ShrinkHorizontal(shrinkBy);
}
}
private int ShrinkHorizontal(int shrinkBy) {
return 0;
}
private int ShrinkVertical(int shrinkBy) {
return 0;
}
/// <devdoc>
/// New EventHandler for The LocationChanging so that ToolStripPanelCell Listens to the Location Property on the ToolStrips's being changed.
/// The ToolStrip needs to Raft (Join) to the approriate Location Depending on the new Location w.r.t to the oldLocation ...
/// Hence the need for this event listener.
/// </devdoc>
private void OnToolStripLocationChanging(object sender, ToolStripLocationCancelEventArgs e)
{
if (ToolStripPanelRow == null) {
return;
}
if (!currentlySizing && !currentlyDragging) {
try {
currentlyDragging = true;
Point newloc = e.NewLocation;
// detect if we havent yet performed a layout - force one so we can
// properly join to the row.
if (ToolStripPanelRow != null && ToolStripPanelRow.Bounds == Rectangle.Empty) {
ToolStripPanelRow.ToolStripPanel.PerformUpdate(true);
}
if (_wrappedToolStrip != null) {
ToolStripPanelRow.ToolStripPanel.Join(_wrappedToolStrip, newloc);
}
}
finally {
currentlyDragging = false;
e.Cancel = true;
}
}
}
private void OnToolStripVisibleChanged(object sender, EventArgs e) {
if (_wrappedToolStrip != null
&& !_wrappedToolStrip.IsInDesignMode
&& !_wrappedToolStrip.IsCurrentlyDragging
&& !_wrappedToolStrip.IsDisposed // ensure we have a live-runtime only toolstrip.
&& !_wrappedToolStrip.Disposing) {
// VSWhidbey 395502 - rejoin the row when visibility is toggled.
// we dont want to do this logic at DT, as the DropSourceBehavior
// will set the toolstrip visible = false.
if (!Control.Visible) {
// if we are becoming visible = false, remember if we were in a toolstrippanelrow at the time.
restoreOnVisibleChanged = (ToolStripPanelRow != null && ((IList)ToolStripPanelRow.Cells).Contains(this));
}
else if (restoreOnVisibleChanged) {
try {
// if we are becoming visible = true, and we ARE in a toolstrippanelrow, rejoin.
if (ToolStripPanelRow != null && ((IList)ToolStripPanelRow.Cells).Contains(this)) {
ToolStripPanelRow.ToolStripPanel.Join(_wrappedToolStrip, _wrappedToolStrip.Location);
}
}
finally {
restoreOnVisibleChanged = false;
}
}
}
}
}
}
|