using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.ComponentModel;
using System.Drawing.Drawing2D;
namespace DevComponents.DotNetBar
{
///
/// Defines an container where you can arrange child elements added to SubItems collection either horizontally or vertically, relative to each other using SetDock and GetDock methods.
///
[ToolboxItem(false), DesignTimeVisible(false), ProvideProperty("Dock", typeof(BaseItem))]
[Designer("DevComponents.DotNetBar.Design.ItemContainerDesigner, DevComponents.DotNetBar.Design, Version=14.1.0.37, Culture=neutral, PublicKeyToken=90f470f34c89ccaf")]
public class ItemDockContainer : ImageItem, System.ComponentModel.IExtenderProvider, IDesignTimeProvider
{
#region Private Variables
private ElementStyle _BackgroundStyle = new ElementStyle();
private Rectangle _DesignerSelectionRectangle = Rectangle.Empty;
private Size _EmptyDesignTimeSize = new Size(24, 24);
#endregion
#region Constructor
///
/// Initializes a new instance of the ItemDockContainer class.
///
public ItemDockContainer()
{
m_IsContainer = true;
_BackgroundStyle.StyleChanged += new EventHandler(BackgroundStyleChanged);
}
#endregion
#region Internal Implementation
///
/// Returns copy of the item.
///
public override BaseItem Copy()
{
ItemDockContainer objCopy = new ItemDockContainer();
this.CopyToItem(objCopy);
return objCopy;
}
///
/// Copies the ButtonItem specific properties to new instance of the item.
///
/// New ButtonItem instance.
internal void InternalCopyToItem(ButtonItem copy)
{
CopyToItem((BaseItem)copy);
}
///
/// Copies the ButtonItem specific properties to new instance of the item.
///
/// New ButtonItem instance.
protected override void CopyToItem(BaseItem copy)
{
base.CopyToItem(copy);
ItemDockContainer idc = (ItemDockContainer)copy;
idc.LastChildFill = _LastChildFill;
}
///
/// Recalculates the size of the container. Assumes that DisplayRectangle.Location is set to the upper left location of this container.
///
public override void RecalcSize()
{
if (this.SuspendLayout)
return;
if (this.SubItems.Count == 0 || this.VisibleSubItems == 0)
{
if (this.DesignMode && !this.SystemContainer)
{
m_Rect.Size = GetEmptyDesignTimeSize();
}
else
{
m_Rect = Rectangle.Empty;
}
base.RecalcSize();
return;
}
m_Rect = LayoutItems(m_Rect);
base.RecalcSize();
}
private BaseItem LastVisibleItem
{
get
{
int count = this.SubItems.Count - 1;
for (int i = count; i >= 0; i--)
{
BaseItem item = SubItems[i];
if (item.Visible)
{
return item;
}
}
return null;
}
}
private System.Drawing.Rectangle LayoutItems(Rectangle bounds)
{
Rectangle itemsBounds = new Rectangle();
BaseItem lastVisibleItem = LastVisibleItem;
foreach (BaseItem item in m_SubItems)
{
if (!item.Visible)
{
item.Displayed = false;
continue;
}
item.Displayed = true;
item.RecalcSize();
eItemDock dock = GetDock(item);
if (_LastChildFill && item == lastVisibleItem)
{
itemsBounds.Width += item.WidthInternal;
if (item.HeightInternal > itemsBounds.Height)
itemsBounds.Height = item.HeightInternal;
}
else if (dock == eItemDock.Left || dock == eItemDock.Right)
{
itemsBounds.Width += item.WidthInternal;
if (item.HeightInternal > itemsBounds.Height)
itemsBounds.Height = item.HeightInternal;
}
else if (dock == eItemDock.Top || dock == eItemDock.Bottom)
{
itemsBounds.Height += item.HeightInternal;
if (item.WidthInternal > itemsBounds.Width)
itemsBounds.Width = item.WidthInternal;
}
}
if (bounds.Width < itemsBounds.Width)
bounds.Width = itemsBounds.Width;
if (bounds.Height < itemsBounds.Height)
bounds.Height = itemsBounds.Height;
if (!this.Stretch)
{
if (itemsBounds.Height < bounds.Height)
bounds.Height = itemsBounds.Height;
}
ArrangeItems(bounds);
return bounds;
}
private void ArrangeItems(Rectangle bounds)
{
BaseItem lastVisibleItem = LastVisibleItem;
Rectangle arrangeBounds = bounds;
foreach (BaseItem item in m_SubItems)
{
if (!item.Visible)
continue;
eItemDock dock = GetDock(item);
if (_LastChildFill && item == lastVisibleItem)
{
item.LeftInternal = arrangeBounds.Left;
item.TopInternal = arrangeBounds.Top;
item.WidthInternal = arrangeBounds.Width;
item.HeightInternal = arrangeBounds.Height;
}
else if (dock == eItemDock.Left)
{
item.LeftInternal = arrangeBounds.Left;
item.TopInternal = arrangeBounds.Top;
item.HeightInternal = arrangeBounds.Height;
if (item.WidthInternal <= arrangeBounds.Width)
{
arrangeBounds.Width -= item.WidthInternal;
arrangeBounds.X += item.WidthInternal;
}
else if (arrangeBounds.Width > 0)
{
arrangeBounds.X += arrangeBounds.Width;
arrangeBounds.Width = 0;
}
}
else if (dock == eItemDock.Right)
{
item.HeightInternal = arrangeBounds.Height;
if (item.WidthInternal <= arrangeBounds.Width)
{
item.LeftInternal = arrangeBounds.Right - item.WidthInternal;
item.TopInternal = arrangeBounds.Top;
arrangeBounds.Width -= item.WidthInternal;
}
else
{
item.LeftInternal = arrangeBounds.Left;
item.TopInternal = arrangeBounds.Top;
if (arrangeBounds.Width > 0)
{
arrangeBounds.X += arrangeBounds.Width;
arrangeBounds.Width = 0;
}
}
}
else if (dock == eItemDock.Top)
{
item.LeftInternal = arrangeBounds.Left;
item.TopInternal = arrangeBounds.Top;
item.WidthInternal = arrangeBounds.Width;
if (item.HeightInternal <= arrangeBounds.Height)
{
arrangeBounds.Height -= item.HeightInternal;
arrangeBounds.Y += item.HeightInternal;
}
else if (arrangeBounds.Height > 0)
{
arrangeBounds.Y += arrangeBounds.Height;
arrangeBounds.Height = 0;
}
}
else if (dock == eItemDock.Bottom)
{
item.WidthInternal = arrangeBounds.Width;
if (item.HeightInternal <= arrangeBounds.Height)
{
item.LeftInternal = arrangeBounds.Left;
item.TopInternal = arrangeBounds.Bottom - item.HeightInternal;
arrangeBounds.Height -= item.HeightInternal;
}
else
{
item.LeftInternal = arrangeBounds.Left;
item.TopInternal = arrangeBounds.Top;
if (arrangeBounds.Height > 0)
{
arrangeBounds.Y += arrangeBounds.Height;
arrangeBounds.Height = 0;
}
}
}
}
}
protected override void OnExternalSizeChange()
{
if (!this.SuspendLayout)
ArrangeItems(m_Rect);
base.OnExternalSizeChange();
}
///
/// Called after TopInternal property has changed
///
protected override void OnTopLocationChanged(int oldValue)
{
base.OnTopLocationChanged(oldValue);
Point offset = new Point(0, this.TopInternal - oldValue);
OffsetSubItems(offset);
}
///
/// Called after LeftInternal property has changed
///
protected override void OnLeftLocationChanged(int oldValue)
{
base.OnLeftLocationChanged(oldValue);
Point offset = new Point(this.LeftInternal - oldValue, 0);
OffsetSubItems(offset);
}
private bool _Offsetting = false;
internal void OffsetSubItems(Point offset)
{
if (_Offsetting || offset.IsEmpty)
return;
try
{
_Offsetting = true;
BaseItem[] items = new BaseItem[this.SubItems.Count];
this.SubItems.CopyTo(items, 0);
foreach (BaseItem b in items)
{
Rectangle r = b.Bounds;
r.Offset(offset);
b.Bounds = r;
}
}
finally
{
_Offsetting = false;
}
}
///
/// Must be overridden by class that is inheriting to provide the painting for the item.
///
public override void Paint(ItemPaintArgs p)
{
Graphics g = p.Graphics;
Region oldClip = null;
bool clipSet = false;
PaintBackground(p);
Rectangle clip = GetClipRectangle();
oldClip = g.Clip;
g.SetClip(clip, CombineMode.Intersect);
clipSet = true;
ItemDisplay display = GetItemDisplay();
display.Paint(this, p);
if (clipSet)
{
if (oldClip != null)
g.Clip = oldClip;
else
g.ResetClip();
}
if (this.DesignMode && !this.SystemContainer && p.DesignerSelection)
{
Rectangle r = this.DisplayRectangle;
Pen pen = null;
if (this.Focused)
pen = new Pen(Color.FromArgb(190, Color.Navy), 1);
else
pen = new Pen(Color.FromArgb(80, Color.Black), 1);
pen.DashStyle = DashStyle.Dot;
DisplayHelp.DrawRoundedRectangle(g, pen, r, 3);
pen.Dispose();
pen = null;
Image image = BarFunctions.LoadBitmap("SystemImages.AddMoreItemsContainer.png");
if (this.Parent is ItemContainer && !((ItemContainer)this.Parent).SystemContainer)
{
ItemContainer pc = this.Parent as ItemContainer;
while (pc != null && !pc.SystemContainer)
{
if (new Rectangle(pc.DisplayRectangle.Location, image.Size).Contains(this.DisplayRectangle.Location))
{
if (r.X + image.Width + 1 > this.DisplayRectangle.Right)
{
r.X = this.DisplayRectangle.X;
if (r.Y + image.Height < this.DisplayRectangle.Bottom)
r.Y += image.Height + 1;
else
break;
}
r.X += (image.Width + 1);
}
pc = pc.Parent as ItemContainer;
}
}
_DesignerSelectionRectangle = new Rectangle(r.X + 1, r.Y + 1, image.Width, image.Height);
g.DrawImageUnscaled(image, _DesignerSelectionRectangle.Location);
}
this.DrawInsertMarker(p.Graphics);
}
private ItemDisplay _ItemDisplay = null;
internal ItemDisplay GetItemDisplay()
{
if (_ItemDisplay == null)
_ItemDisplay = new ItemDisplay();
return _ItemDisplay;
}
protected virtual void PaintBackground(ItemPaintArgs p)
{
_BackgroundStyle.SetColorScheme(p.Colors);
Graphics g = p.Graphics;
ElementStyleDisplay.Paint(new ElementStyleDisplayInfo(_BackgroundStyle, g, this.DisplayRectangle));
}
private void BackgroundStyleChanged(object sender, EventArgs e)
{
this.OnAppearanceChanged();
}
protected virtual Rectangle GetClipRectangle()
{
Rectangle clip = this.DisplayRectangle;
bool disposeStyle = false;
ElementStyle style = ElementStyleDisplay.GetElementStyle(_BackgroundStyle, out disposeStyle);
clip.X += ElementStyleLayout.LeftWhiteSpace(style);
clip.Width -= ElementStyleLayout.HorizontalStyleWhiteSpace(style);
clip.Y += ElementStyleLayout.TopWhiteSpace(style);
clip.Height -= ElementStyleLayout.VerticalStyleWhiteSpace(style);
if (disposeStyle)
style.Dispose();
return clip;
}
private Dictionary _ItemDock = new Dictionary();
///
/// Retrieves the docking for specified item.
///
[DefaultValue(eItemDock.Left)]
public eItemDock GetDock(BaseItem item)
{
if (item == null) throw new ArgumentNullException("item cannot be null");
eItemDock dock = eItemDock.Left;
if (_ItemDock.TryGetValue(item, out dock))
return dock;
return eItemDock.Left;
}
///
/// Sets the docking within container for specified item.
///
/// Item to set docking for.
/// Docking value.
[Localizable(true)]
public void SetDock(BaseItem item, eItemDock dock)
{
if (item == null) throw new ArgumentNullException("item cannot be null");
if (dock == eItemDock.Left)
{
if (_ItemDock.ContainsKey(item))
_ItemDock.Remove(item);
}
else
{
if (_ItemDock.ContainsKey(item))
_ItemDock[item] = dock;
else
_ItemDock.Add(item, dock);
}
if (this.DesignMode)
{
this.NeedRecalcSize = true;
this.Refresh();
}
}
///
/// Returns empty container default design-time size.
///
/// Size of an empty container.
protected virtual Size GetEmptyDesignTimeSize()
{
Size s = _EmptyDesignTimeSize;
return s;
}
private bool _LastChildFill = true;
///
/// Gets or sets a value that indicates whether the last child element within a ItemDockContainer stretches to fill the remaining available space.
///
[DefaultValue(true), Category("Appearance"), Description("Indicates whether the last child element within a ItemDockContainer stretches to fill the remaining available space.")]
public bool LastChildFill
{
get { return _LastChildFill; }
set
{
_LastChildFill = value;
NeedRecalcSize = true;
OnAppearanceChanged();
}
}
private bool _SystemContainer = false;
[Browsable(false)]
public bool SystemContainer
{
get { return _SystemContainer; }
internal set
{
_SystemContainer = value;
}
}
///
/// IBlock member implementation
///
[Browsable(false), DevCoBrowsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), EditorBrowsable(EditorBrowsableState.Never)]
public override System.Drawing.Rectangle Bounds
{
get
{
return base.Bounds;
}
set
{
Point offset = new Point(value.X - m_Rect.X, value.Y - m_Rect.Y);
base.Bounds = value;
if (!offset.IsEmpty)
{
OffsetSubItems(offset);
}
}
}
///
/// Occurs when the mouse pointer is over the item and a mouse button is pressed. This is used by internal implementation only.
///
[System.ComponentModel.Browsable(false), System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
public override void InternalMouseDown(System.Windows.Forms.MouseEventArgs objArg)
{
if (this.DesignMode && !this.SystemContainer)
{
BaseItem item = ItemAtLocation(objArg.X, objArg.Y);
if (item == this && !(item.DesignMode && !item.DesignTimeVisible))
{
IOwner owner = this.GetOwner() as IOwner;
if (owner != null)
{
owner.SetFocusItem(this);
return;
}
}
}
else if (!this.DisplayRectangle.Contains(objArg.X, objArg.Y))
{
if (this.DesignMode)
{
IOwner owner = this.GetOwner() as IOwner;
if (owner != null)
owner.SetFocusItem(null);
LeaveHotSubItem(null);
}
return;
}
base.InternalMouseDown(objArg);
}
///
/// Return Sub Item at specified location
///
public override BaseItem ItemAtLocation(int x, int y)
{
if (this.DesignMode && !this.SystemContainer && !_DesignerSelectionRectangle.IsEmpty)
{
if (_DesignerSelectionRectangle.Contains(x, y))
return this;
}
if (!this.Visible || !this.DisplayRectangle.Contains(x, y))
return null;
if (m_SubItems != null)
{
foreach (BaseItem objSub in m_SubItems)
{
if (objSub.IsContainer)
{
BaseItem item = objSub.ItemAtLocation(x, y);
if (item != null)
return item;
}
else
{
if ((objSub.Visible || this.IsOnCustomizeMenu) && objSub.Displayed && objSub.DisplayRectangle.Contains(x, y))
{
if (this.DesignMode && !this.DisplayRectangle.IntersectsWith(objSub.DisplayRectangle))
continue;
return objSub;
}
}
}
}
if (this.DisplayRectangle.Contains(x, y) && /*this.DesignMode &&*/ !this.SystemContainer)
return this;
return null;
}
#endregion
#region IExtenderProvider Members
bool IExtenderProvider.CanExtend(object extendee)
{
BaseItem item = extendee as BaseItem;
if(item!=null && this.SubItems.Contains(item))
return true;
return false;
}
#endregion
#region IDesignTimeProvider Implementation
protected virtual InsertPosition GetContainerInsertPosition(Point pScreen, BaseItem dragItem)
{
return DesignTimeProviderContainer.GetInsertPosition(this, pScreen, dragItem);
}
InsertPosition IDesignTimeProvider.GetInsertPosition(Point pScreen, BaseItem dragItem)
{
return GetContainerInsertPosition(pScreen, dragItem);
}
void IDesignTimeProvider.DrawReversibleMarker(int iPos, bool Before)
{
DesignTimeProviderContainer.DrawReversibleMarker(this, iPos, Before);
}
void IDesignTimeProvider.InsertItemAt(BaseItem objItem, int iPos, bool Before)
{
DesignTimeProviderContainer.InsertItemAt(this, objItem, iPos, Before);
}
#endregion
}
public enum eItemDock
{
Left,
Right,
Top,
Bottom
}
}