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 } }