using System; using System.Collections.Generic; using System.Text; using System.Windows.Forms.Design; using DevComponents.DotNetBar.Layout; using System.Drawing; using System.ComponentModel.Design; using System.Windows.Forms; using System.ComponentModel; using System.Collections; using System.Drawing.Drawing2D; namespace DevComponents.DotNetBar.Layout.Design { public class LayoutControlDesigner : ParentControlDesigner { #region Constructor #endregion #region Implementation public override void Initialize(System.ComponentModel.IComponent component) { base.Initialize(component); IComponentChangeService changeService = (IComponentChangeService)GetService(typeof(IComponentChangeService)); if (changeService != null) { changeService.ComponentAdded += new ComponentEventHandler(ComponentAdded); changeService.ComponentAdding += new ComponentEventHandler(ComponentAdding); changeService.ComponentChanged += new ComponentChangedEventHandler(ComponentChanged); changeService.ComponentRemoved += OnComponentRemoved; changeService.ComponentRemoving += OnComponentRemoving; } //ISelectionService selectionService = (ISelectionService)GetService(typeof(ISelectionService)); //if (selectionService != null) // selectionService.SelectionChanged += SelectionChanged; } protected override void Dispose(bool disposing) { IComponentChangeService ss = (IComponentChangeService)GetService(typeof(IComponentChangeService)); if (ss != null) { ss.ComponentAdded -= ComponentAdded; ss.ComponentAdding -= ComponentAdding; ss.ComponentChanged -= ComponentChanged; ss.ComponentRemoved -= OnComponentRemoved; } //ISelectionService selectionService = (ISelectionService)GetService(typeof(ISelectionService)); //if (selectionService != null) // selectionService.SelectionChanged -= SelectionChanged; base.Dispose(disposing); } private bool _ControlDeleting = false; private void DestroyChildItems(LayoutItemBase parent, IDesignerHost dh) { LayoutGroup group = parent as LayoutGroup; if (group == null) return; foreach (LayoutItemBase item in group.Items) { DestroyChildItems(item, dh); dh.DestroyComponent(item); } } private void OnComponentRemoving(object sender, ComponentEventArgs e) { if (e.Component != this.Component) return; IDesignerHost dh = (IDesignerHost)GetService(typeof(IDesignerHost)); if (dh == null) return; _ControlDeleting = true; LayoutControl lc = (LayoutControl)e.Component; if (lc.RootGroup.Items.Count == 0) return; LayoutItemBase[] items = new LayoutItemBase[lc.RootGroup.Items.Count]; lc.RootGroup.Items.CopyTo(items); foreach (LayoutItemBase item in items) { DestroyChildItems(item, dh); dh.DestroyComponent(item); } _ControlDeleting = false; } private void OnComponentRemoved(object sender, ComponentEventArgs e) { if (_ControlDeleting) return; if (e.Component is LayoutItemBase && ((LayoutItemBase)e.Component).GetLayoutControl() == this.Control && !_DestroyingItem) { CleanupRemovedControls(false); CleanupRemovedItems((LayoutItemBase)e.Component, true, false); } else if (e.Component is Control && IsContained((Control)e.Component)) { LayoutControl lc = (LayoutControl)this.Control; if (lc != null) { LayoutItemBase item = lc.FindControlItem((Control)e.Component); if (item != null) CleanupRemovedItems(item, false, true); } } } private bool IsContained(Control c) { LayoutControl lc = (LayoutControl)this.Control; if (lc == null || c == null || lc == c) return false; Control stopParent = lc.Parent; Control test = c; do { if (test == lc) return true; test = test.Parent; } while (test != null && test != stopParent); return false; } private bool _DestroyingItem = false; private void CleanupRemovedItems(LayoutItemBase item, bool removeControl, bool destroyItem) { if (item == null || item.Parent == null) return; LayoutControl lc = this.Control as LayoutControl; if (lc == null) return; IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); IComponentChangeService cc = (IComponentChangeService)GetService(typeof(IComponentChangeService)); DesignerTransaction dt = host.CreateTransaction("Removing Layout Item"); cc.OnComponentChanging(lc, TypeDescriptor.GetProperties(lc)["RootGroup"]); ISelectionService ss = (ISelectionService)GetService(typeof(ISelectionService)); ICollection selectedComponents = ss.GetSelectedComponents(); if (IsSelected(selectedComponents, item)) { ss.SetSelectedComponents(new IComponent[] { item }, SelectionTypes.Remove); } if (item.Parent is LayoutGroup) { LayoutGroup parentGroup = null; if (item.Parent != lc.RootGroup && item.Parent is LayoutGroup) { parentGroup = (LayoutGroup)item.Parent; cc.OnComponentChanging(parentGroup, TypeDescriptor.GetProperties(parentGroup)["Items"]); } ((LayoutGroup)item.Parent).Items.Remove(item); if (parentGroup != null) cc.OnComponentChanged(parentGroup, TypeDescriptor.GetProperties(parentGroup)["Items"], null, null); if (destroyItem) { _DestroyingItem = true; try { host.DestroyComponent(item); } finally { _DestroyingItem = false; } } } if (removeControl && item is LayoutControlItem) { LayoutControlItem lci = (LayoutControlItem)item; if (lci.Control != null && lci.Control.Parent == lc) { cc.OnComponentChanging(lc, TypeDescriptor.GetProperties(lc)["Controls"]); lc.Controls.Remove(lci.Control); cc.OnComponentChanged(lc, TypeDescriptor.GetProperties(lc)["Controls"], null, null); host.DestroyComponent(lci.Control); } } cc.OnComponentChanged(lc, TypeDescriptor.GetProperties(lc)["RootGroup"], null, null); dt.Commit(); lc.PerformLayout(); ss.SetSelectedComponents(new IComponent[] { lc }, SelectionTypes.Replace); } private void CleanupRemovedControls(bool destroyComponents) { LayoutControl lc = this.Control as LayoutControl; if (lc == null) return; List removed = lc.FindOrphanedControlItems(); if (removed != null && removed.Count > 0) { IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); IComponentChangeService cc = (IComponentChangeService)GetService(typeof(IComponentChangeService)); DesignerTransaction dt = host.CreateTransaction("Removing Layout Control Item"); cc.OnComponentChanging(lc, TypeDescriptor.GetProperties(lc)["RootGroup"]); ISelectionService ss = (ISelectionService)GetService(typeof(ISelectionService)); ICollection selectedComponents = ss.GetSelectedComponents(); foreach (LayoutItemBase item in removed) { LayoutControlItem lci = item as LayoutControlItem; if (IsSelected(selectedComponents, item)) { ss.SetSelectedComponents(new IComponent[] { item }, SelectionTypes.Remove); } if (lci != null && IsSelected(selectedComponents, lci.Control)) { ss.SetSelectedComponents(new IComponent[] { lci.Control }, SelectionTypes.Remove); } lci.Control = null; if (lci.Parent is LayoutGroup) { LayoutGroup parentGroup = null; if (item.Parent != lc.RootGroup && item.Parent is LayoutGroup) { parentGroup = (LayoutGroup)item.Parent; cc.OnComponentChanging(parentGroup, TypeDescriptor.GetProperties(parentGroup)["Items"]); } ((LayoutGroup)lci.Parent).Items.Remove(item); if (parentGroup != null) cc.OnComponentChanged(parentGroup, TypeDescriptor.GetProperties(parentGroup)["Items"], null, null); } if (destroyComponents) host.DestroyComponent(item); } cc.OnComponentChanged(lc, TypeDescriptor.GetProperties(lc)["RootGroup"], null, null); dt.Commit(); lc.PerformLayout(); ss.SetSelectedComponents(new IComponent[] { lc }, SelectionTypes.Replace); } } private bool IsControlSelected { get { ISelectionService ss = (ISelectionService)GetService(typeof(ISelectionService)); if (ss == null) return false; ICollection selected = ss.GetSelectedComponents(); if (IsSelected(selected, this.Control)) return true; return false; } } private bool IsSelected(ICollection selectedComponents, object item) { foreach (object o in selectedComponents) { if (o == item) return true; } return false; } void ComponentChanged(object sender, ComponentChangedEventArgs e) { if (e.Component == this.Control) { if (e.Member != null && e.Member.Name == "Controls") { // Find out what changed... LayoutControl lc = (LayoutControl)this.Control; if (lc == null) return; foreach (Control c in lc.Controls) { if (lc.IsSystemControl(c)) continue; LayoutItemBase item = lc.FindControlItem(c); if (item == null) { IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); IComponentChangeService cc = (IComponentChangeService)GetService(typeof(IComponentChangeService)); DesignerTransaction dt = host.CreateTransaction("Creating Layout Control Item"); LayoutControlItem lci = (LayoutControlItem)host.CreateComponent(typeof(LayoutControlItem)); TypeDescriptor.GetProperties(lci)["Control"].SetValue(lci, c); lc.SetupControlItem(lci); cc.OnComponentChanging(lc, TypeDescriptor.GetProperties(lc)["RootGroup"]); cc.OnComponentChanging(lc.RootGroup, TypeDescriptor.GetProperties(lc)["Items"]); lc.RootGroup.Items.Add(lci); cc.OnComponentChanged(lc.RootGroup, TypeDescriptor.GetProperties(lc)["Items"], null, null); cc.OnComponentChanged(lc, TypeDescriptor.GetProperties(lc)["RootGroup"], null, null); dt.Commit(); lc.PerformLayout(); } } // Check removed CleanupRemovedControls(true); } } } protected override bool AllowSetChildIndexOnDrop { get { return false; } } protected override void OnMouseDragBegin(int x, int y) { //base.OnMouseDragBegin(x, y); } protected override void OnDragEnter(DragEventArgs de) { if (de.Data is LayoutItemDataObject) { de.Effect = DragDropEffects.Move; //LayoutControl lc = (LayoutControl)this.Control; //lc.Text = string.Format("{0} DragEnter", DateTime.Now.TimeOfDay); //lc.Invalidate(); return; } base.OnDragEnter(de); } protected override void OnDragOver(DragEventArgs de) { LayoutControl lc = (LayoutControl)this.Control; if (lc == null) return; //lc.Text = de.Data.GetType().ToString(); //lc.Invalidate(); //lc.Text = "DragOver"; //lc.Invalidate(); ISelectionService selectionService = (ISelectionService)this.GetService(typeof(ISelectionService)); //lc.Text = string.Format("GetSelectedComponents().Count={0}", selectionService.GetSelectedComponents().Count); if (selectionService != null && (selectionService.PrimarySelection is Control || de.Data is LayoutItemDataObject) && selectionService.GetSelectedComponents().Count == 1) { LayoutItemBase item = null; if (de.Data is LayoutItemDataObject) { LayoutItemDataObject d = (LayoutItemDataObject)de.Data; item = d.DragComponent; } else { Control c = (Control)selectionService.PrimarySelection; item = lc.FindControlItem(c); } if (item != null) { HitTestInsertInfo info = lc.GetHitTestInsertInfo(item, lc.PointToClient(new Point(de.X, de.Y))); if (!info.InsertMarkerBounds.IsEmpty) lc.ShowInsertMarker(info.InsertMarkerBounds); else lc.HideInsertMarker(); de.Effect = DragDropEffects.Move; return; } } base.OnDragOver(de); } protected override void OnDragLeave(EventArgs e) { LayoutControl lc = (LayoutControl)this.Control; if (lc == null) return; lc.HideInsertMarker(); base.OnDragLeave(e); } protected override void OnDragDrop(DragEventArgs de) { LayoutControl lc = (LayoutControl)this.Control; if (lc == null) return; lc.HideInsertMarker(); ISelectionService selectionService = (ISelectionService)this.GetService(typeof(ISelectionService)); if (selectionService != null && (selectionService.PrimarySelection is Control || de.Data is LayoutItemDataObject) && selectionService.GetSelectedComponents().Count == 1) { LayoutItemBase item = null; if (de.Data is LayoutItemDataObject) { item = ((LayoutItemDataObject)de.Data).DragComponent; } else { Control c = (Control)selectionService.PrimarySelection; item = lc.FindControlItem(c); } if (item != null) { HitTestInsertInfo info = lc.GetHitTestInsertInfo(item, lc.PointToClient(new Point(de.X, de.Y))); if (info.Parent != null) { IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost)); IComponentChangeService cc = (IComponentChangeService)GetService(typeof(IComponentChangeService)); DesignerTransaction dt = host.CreateTransaction("Moving Layout Control Item"); cc.OnComponentChanging(lc, TypeDescriptor.GetProperties(lc)["RootGroup"]); //lc.Text = string.Format("Moving at: {0}", info.InsertIndex); //lc.Invalidate(); if (info.Parent != item.Parent) { LayoutGroup parentGroup = (LayoutGroup)item.Parent; if (parentGroup != lc.RootGroup) cc.OnComponentChanging(parentGroup, TypeDescriptor.GetProperties(parentGroup)["Items"]); parentGroup.Items.Remove(item); if (parentGroup != lc.RootGroup) cc.OnComponentChanged(parentGroup, TypeDescriptor.GetProperties(parentGroup)["Items"], null, null); if (info.Parent != lc.RootGroup) cc.OnComponentChanging(info.Parent, TypeDescriptor.GetProperties(parentGroup)["Items"]); if (info.InsertIndex >= 0) info.Parent.Items.Insert(info.InsertIndex, item); else info.Parent.Items.Add(item); if (info.Parent != lc.RootGroup) cc.OnComponentChanged(info.Parent, TypeDescriptor.GetProperties(parentGroup)["Items"], null, null); } else { LayoutGroup parentGroup = (LayoutGroup)item.Parent; if (parentGroup != lc.RootGroup) cc.OnComponentChanging(parentGroup, TypeDescriptor.GetProperties(parentGroup)["Items"]); info.Parent.Items.Move(item, info.InsertIndex); if (parentGroup != lc.RootGroup) cc.OnComponentChanged(parentGroup, TypeDescriptor.GetProperties(parentGroup)["Items"], null, null); } cc.OnComponentChanged(lc, TypeDescriptor.GetProperties(lc)["RootGroup"], null, null); dt.Commit(); lc.PerformLayout(); SelectionRefresh(); } return; } } base.OnDragDrop(de); } void ComponentAdding(object sender, ComponentEventArgs e) { //Control c = e.Component as Control; //if (c != null) //{ // if (c != null && c.Parent == this.Control) // { // MessageBox.Show("Component ADDING"); // } // else // MessageBox.Show(string.Format("Component ADDING UNRECOGNIZED Parent: {0} Site:{1}", c.Parent, e.Component.Site)); //} } void ComponentAdded(object sender, ComponentEventArgs e) { //Control c = e.Component as Control; //if (c != null) //{ // if (c != null && c.Parent == this.Control) // { // MessageBox.Show("Component ADDED"); // } // else // MessageBox.Show(string.Format("Component ADDED UNRECOGNIZED Parent: {0}", c.Parent)); //} } protected override bool GetHitTest(System.Drawing.Point point) { if (base.GetHitTest(point)) return true; LayoutControl c = this.Control as LayoutControl; if (c == null) return false; Point pc = c.PointToClient(point); if (c.VScrollBar.Visible && c.VScrollBar.Bounds.Contains(pc)) return true; if (c.HScrollBar.Visible && c.HScrollBar.Bounds.Contains(pc)) return true; return base.GetHitTest(point); } public void SelectionRefresh() { Message m = new Message(); m.Msg = 0x115; base.WndProc(ref m); } private System.Windows.Forms.Control _DesignerHost = null; /// /// Selection support for items on container. /// protected override void WndProc(ref Message m) { if (_DesignerHost == null) _DesignerHost = System.Windows.Forms.Control.FromHandle(m.HWnd); switch (m.Msg) { case WinApi.WM_LBUTTONDOWN: case WinApi.WM_RBUTTONDOWN: { if (OnMouseDown(ref m, m.Msg == WinApi.WM_LBUTTONDOWN ? MouseButtons.Left : MouseButtons.Right)) return; break; } case WinApi.WM_RBUTTONUP: case WinApi.WM_LBUTTONUP: { if (OnMouseUp(ref m, m.Msg == WinApi.WM_LBUTTONDOWN ? MouseButtons.Left : MouseButtons.Right)) return; break; } } base.WndProc(ref m); } protected virtual bool OnMouseUp(ref Message m, MouseButtons param1) { if (_MouseDownSelectionPerformed) { _MouseDownSelectionPerformed = false; return true; } return false; } private bool _MouseDownSelectionPerformed = false; protected virtual bool OnMouseDown(ref Message m, MouseButtons button) { LayoutControl lc = this.Control as LayoutControl; if (lc == null) return false; Point p = new Point(WinApi.LOWORD(m.LParam), WinApi.HIWORD(m.LParam)); LayoutItemBase item = lc.HitTest(p); if (item != null) { SelectComponent(item, (Control.ModifierKeys == Keys.Control || Control.ModifierKeys == Keys.Shift) ? SelectionTypes.Add : SelectionTypes.Primary); _MouseDownSelectionPerformed = true; return true; } else if (!IsControlSelected) { SelectComponent(this.Control, SelectionTypes.Replace); //return true; } return false; } protected virtual void SelectComponent(IComponent comp, SelectionTypes selectionType) { ISelectionService selection = (ISelectionService)this.GetService(typeof(ISelectionService)); if (selection != null && comp != null) { ArrayList arr = new ArrayList(1); arr.Add(comp); selection.SetSelectedComponents(arr, selectionType); } } public override ICollection AssociatedComponents { get { ArrayList list = base.AssociatedComponents as ArrayList; if (list == null) list = new ArrayList(); LayoutControl lc = (LayoutControl)this.Control; if (lc == null) return list; if (list != null) { foreach (LayoutItemBase item in lc.RootGroup.Items) { list.Add(item); } } return list; } } protected override void OnPaintAdornments(PaintEventArgs pe) { LayoutControl lc = (LayoutControl)base.Component; if (lc != null && lc.Visible) { using (Pen borderPen = this.BorderPen) { Rectangle clientRectangle = this.Control.ClientRectangle; clientRectangle.Width--; clientRectangle.Height--; pe.Graphics.DrawRectangle(borderPen, clientRectangle); } } base.OnPaintAdornments(pe); } protected Pen BorderPen { get { Color color = (this.Control.BackColor.GetBrightness() < 0.5) ? ControlPaint.Light(this.Control.BackColor) : ControlPaint.Dark(this.Control.BackColor); Pen pen = new Pen(color); pen.DashStyle = DashStyle.Dash; return pen; } } public override DesignerVerbCollection Verbs { get { DesignerVerb[] verbs; verbs = new DesignerVerb[] { new DesignerVerb("Add Spacer", new EventHandler(AddSpacerItem)), new DesignerVerb("Add Group", new EventHandler(AddGroupItem)) }; return new DesignerVerbCollection(verbs); } } //private void AddLabelItem(object sender, EventArgs e) //{ // AddLabelItem(); //} //private void AddLabelItem() //{ // IDesignerHost dh = (IDesignerHost)GetService(typeof(IDesignerHost)); // LayoutControl lc = this.Control as LayoutControl; // if (lc == null || dh == null) // return; // DesignerTransaction dt = dh.CreateTransaction("Creating Label Item"); // try // { // IComponentChangeService cc = this.GetService(typeof(IComponentChangeService)) as IComponentChangeService; // if (cc != null) // { // cc.OnComponentChanging(this.Component, null); // cc.OnComponentChanging(lc, TypeDescriptor.GetProperties(lc)["RootGroup"]); // cc.OnComponentChanging(lc.RootGroup, TypeDescriptor.GetProperties(lc)["Items"]); // } // LayoutLabelItem item = null; // item = dh.CreateComponent(typeof(LayoutLabelItem)) as LayoutLabelItem; // item.Width = 100; // item.WidthType = eLayoutSizeType.Percent; // item.Height = 22; // item.Text = "Layout Label"; // lc.RootGroup.Items.Add(item); // lc.PerformLayout(); // if (cc != null) // { // cc.OnComponentChanged(lc.RootGroup, TypeDescriptor.GetProperties(lc)["Items"], null, null); // cc.OnComponentChanged(lc, TypeDescriptor.GetProperties(lc)["RootGroup"], null, null); // cc.OnComponentChanged(this.Component, null, null, null); // } // SelectComponent(item, SelectionTypes.Replace); // } // catch // { // dt.Cancel(); // } // finally // { // if (!dt.Canceled) dt.Commit(); // } //} private void AddSpacerItem(object sender, EventArgs e) { AddSpacerItem(); } private void AddSpacerItem() { IDesignerHost dh = (IDesignerHost)GetService(typeof(IDesignerHost)); LayoutControl lc = this.Control as LayoutControl; if (lc == null || dh == null) return; DesignerTransaction dt = dh.CreateTransaction("Creating Spacer Item"); try { IComponentChangeService cc = this.GetService(typeof(IComponentChangeService)) as IComponentChangeService; if (cc != null) { cc.OnComponentChanging(this.Component, null); cc.OnComponentChanging(lc, TypeDescriptor.GetProperties(lc)["RootGroup"]); cc.OnComponentChanging(lc.RootGroup, TypeDescriptor.GetProperties(lc)["Items"]); } LayoutSpacerItem item = null; item = dh.CreateComponent(typeof(LayoutSpacerItem)) as LayoutSpacerItem; item.Width = 32; item.Height = 32; lc.RootGroup.Items.Add(item); lc.PerformLayout(); if (cc != null) { cc.OnComponentChanged(lc.RootGroup, TypeDescriptor.GetProperties(lc)["Items"], null, null); cc.OnComponentChanged(lc, TypeDescriptor.GetProperties(lc)["RootGroup"], null, null); cc.OnComponentChanged(this.Component, null, null, null); } SelectComponent(item, SelectionTypes.Replace); } catch { dt.Cancel(); } finally { if (!dt.Canceled) dt.Commit(); } } private void AddGroupItem(object sender, EventArgs e) { AddGroupItem(); } private void AddGroupItem() { IDesignerHost dh = (IDesignerHost)GetService(typeof(IDesignerHost)); LayoutControl lc = this.Control as LayoutControl; if (lc == null || dh == null) return; DesignerTransaction dt = dh.CreateTransaction("Creating Group Item"); try { IComponentChangeService cc = this.GetService(typeof(IComponentChangeService)) as IComponentChangeService; if (cc != null) { cc.OnComponentChanging(this.Component, null); cc.OnComponentChanging(lc, TypeDescriptor.GetProperties(lc)["RootGroup"]); cc.OnComponentChanging(lc.RootGroup, TypeDescriptor.GetProperties(lc)["Items"]); } LayoutGroup item = null; item = dh.CreateComponent(typeof(LayoutGroup)) as LayoutGroup; item.Width = 200; item.Height = 100; item.TextPosition = eLayoutPosition.Top; item.MinSize = new Size(120, 32); lc.RootGroup.Items.Add(item); lc.PerformLayout(); if (cc != null) { cc.OnComponentChanged(lc.RootGroup, TypeDescriptor.GetProperties(lc)["Items"], null, null); cc.OnComponentChanged(lc, TypeDescriptor.GetProperties(lc)["RootGroup"], null, null); cc.OnComponentChanged(this.Component, null, null, null); } SelectComponent(item, SelectionTypes.Replace); } catch { dt.Cancel(); } finally { if (!dt.Canceled) dt.Commit(); } } #endregion } }