// // DockGroupItem.cs // // Author: // Lluis Sanchez Gual // // // Copyright (C) 2007 Novell, Inc (http://www.novell.com) // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Xml; using Gtk; namespace MonoDevelop.Components.Docking { internal class DockGroupItem: DockObject { DockItem item; bool visibleFlag; DockItemStatus status; Gdk.Rectangle floatRect; Gtk.PositionType barDocPosition; int autoHideSize = -1; public DockItem Item { get { return item; } set { item = value; } } public string Id { get { return item.Id; } } public DockGroupItem (DockFrame frame, DockItem item): base (frame) { this.item = item; visibleFlag = item.Visible; } internal override void GetDefaultSize (out int width, out int height) { width = item.DefaultWidth; height = item.DefaultHeight; } internal override void GetMinSize (out int width, out int height) { Requisition req = SizeRequest (); width = req.Width; height = req.Height; } internal override Requisition SizeRequest () { return item.Widget.SizeRequest (); } public override void SizeAllocate (Gdk.Rectangle newAlloc) { item.Widget.SizeAllocate (newAlloc); base.SizeAllocate (newAlloc); } public override bool Expand { get { return item.Expand; } } internal override void QueueResize () { item.Widget.QueueResize (); } internal override bool GetDockTarget (DockItem item, int px, int py, out DockDelegate dockDelegate, out Gdk.Rectangle rect) { return GetDockTarget (item, px, py, Allocation, out dockDelegate, out rect); } public bool GetDockTarget (DockItem item, int px, int py, Gdk.Rectangle rect, out DockDelegate dockDelegate, out Gdk.Rectangle outrect) { dockDelegate = null; if (item != this.item && this.item.Visible && rect.Contains (px, py)) { int xdockMargin = (int) ((double)rect.Width * (1.0 - DockFrame.ItemDockCenterArea)) / 2; int ydockMargin = (int) ((double)rect.Height * (1.0 - DockFrame.ItemDockCenterArea)) / 2; DockPosition pos; /* if (ParentGroup.Type == DockGroupType.Tabbed) { rect = new Gdk.Rectangle (rect.X + xdockMargin, rect.Y + ydockMargin, rect.Width - xdockMargin*2, rect.Height - ydockMargin*2); pos = DockPosition.CenterAfter; } */ if (px <= rect.X + xdockMargin && ParentGroup.Type != DockGroupType.Horizontal) { outrect = new Gdk.Rectangle (rect.X, rect.Y, xdockMargin, rect.Height); pos = DockPosition.Left; } else if (px >= rect.Right - xdockMargin && ParentGroup.Type != DockGroupType.Horizontal) { outrect = new Gdk.Rectangle (rect.Right - xdockMargin, rect.Y, xdockMargin, rect.Height); pos = DockPosition.Right; } else if (py <= rect.Y + ydockMargin && ParentGroup.Type != DockGroupType.Vertical) { outrect = new Gdk.Rectangle (rect.X, rect.Y, rect.Width, ydockMargin); pos = DockPosition.Top; } else if (py >= rect.Bottom - ydockMargin && ParentGroup.Type != DockGroupType.Vertical) { outrect = new Gdk.Rectangle (rect.X, rect.Bottom - ydockMargin, rect.Width, ydockMargin); pos = DockPosition.Bottom; } else { outrect = new Gdk.Rectangle (rect.X + xdockMargin, rect.Y + ydockMargin, rect.Width - xdockMargin*2, rect.Height - ydockMargin*2); pos = DockPosition.Center; } dockDelegate = delegate (DockItem dit) { DockGroupItem it = ParentGroup.AddObject (dit, pos, Id); it.SetVisible (true); ParentGroup.FocusItem (it); }; return true; } outrect = Gdk.Rectangle.Zero; return false; } internal override void Dump (int ind) { Console.WriteLine (new string (' ', ind) + item.Id + " size:" + Size + " alloc:" + Allocation); } internal override void Write (XmlWriter writer) { base.Write (writer); writer.WriteAttributeString ("id", item.Id); writer.WriteAttributeString ("visible", visibleFlag.ToString ()); writer.WriteAttributeString ("status", status.ToString ()); if (status == DockItemStatus.AutoHide) writer.WriteAttributeString ("autoHidePosition", barDocPosition.ToString ()); if (autoHideSize != -1) writer.WriteAttributeString ("autoHideSize", autoHideSize.ToString ()); if (!floatRect.Equals (Gdk.Rectangle.Zero)) { writer.WriteAttributeString ("floatX", floatRect.X.ToString ()); writer.WriteAttributeString ("floatY", floatRect.Y.ToString ()); writer.WriteAttributeString ("floatWidth", floatRect.Width.ToString ()); writer.WriteAttributeString ("floatHeight", floatRect.Height.ToString ()); } } internal override void Read (XmlReader reader) { base.Read (reader); visibleFlag = bool.Parse (reader.GetAttribute ("visible")) && !item.IsPositionMarker; status = (DockItemStatus) Enum.Parse (typeof (DockItemStatus), reader.GetAttribute ("status")); int fx=0, fy=0, fw=0, fh=0; string s = reader.GetAttribute ("floatX"); if (s != null) fx = int.Parse (s); s = reader.GetAttribute ("floatY"); if (s != null) fy = int.Parse (s); s = reader.GetAttribute ("floatWidth"); if (s != null) fw = int.Parse (s); s = reader.GetAttribute ("floatHeight"); if (s != null) fh = int.Parse (s); s = reader.GetAttribute ("autoHidePosition"); if (s != null) barDocPosition = (PositionType) Enum.Parse (typeof (PositionType), s); s = reader.GetAttribute ("autoHideSize"); if (s != null) autoHideSize = int.Parse (s); floatRect = new Gdk.Rectangle (fx, fy, fw, fh); } public override void CopyFrom (DockObject ob) { base.CopyFrom (ob); DockGroupItem it = (DockGroupItem)ob; item = it.item; visibleFlag = it.visibleFlag; floatRect = it.floatRect; } internal override bool Visible { get { return visibleFlag && status == DockItemStatus.Dockable; } } internal bool VisibleFlag { get { return visibleFlag; } } public DockItemStatus Status { get { return status; } set { if (status == value) return; DockItemStatus oldValue = status; status = value; if (status == DockItemStatus.Floating) { if (floatRect.Equals (Gdk.Rectangle.Zero)) { int x, y; item.Widget.TranslateCoordinates (item.Widget.Toplevel, 0, 0, out x, out y); Gtk.Window win = Frame.Toplevel as Window; if (win != null) { int wx, wy; win.GetPosition (out wx, out wy); floatRect = new Gdk.Rectangle (wx + x, wy + y, Allocation.Width, Allocation.Height); } } item.SetFloatMode (floatRect); } else if (status == DockItemStatus.AutoHide) { SetBarDocPosition (); item.SetAutoHideMode (barDocPosition, GetAutoHideSize (barDocPosition)); } else item.ResetMode (); if (oldValue == DockItemStatus.Dockable || status == DockItemStatus.Dockable) { // Update visibility if changing from/to dockable mode if (ParentGroup != null) ParentGroup.UpdateVisible (this); } } } void SetBarDocPosition () { // Determine the best position for docking the item if (Allocation.IsEmpty) { int uniqueTrue = -1; int uniqueFalse = -1; for (int n=0; n<4; n++) { bool inMargin = IsNextToMargin ((PositionType) n, false); if (inMargin) { if (uniqueTrue == -1) uniqueTrue = n; else uniqueTrue = -2; } else { if (uniqueFalse == -1) uniqueFalse = n; else uniqueFalse = -2; } } if (uniqueTrue >= 0) { barDocPosition = (PositionType) uniqueTrue; autoHideSize = 200; return; } else if (uniqueFalse >= 0) { barDocPosition = (PositionType) uniqueFalse; switch (barDocPosition) { case PositionType.Left: barDocPosition = PositionType.Right; break; case PositionType.Right: barDocPosition = PositionType.Left; break; case PositionType.Top: barDocPosition = PositionType.Bottom; break; case PositionType.Bottom: barDocPosition = PositionType.Top; break; } autoHideSize = 200; return; } // If the item is in a group, use the dock location of other items DockObject current = this; do { if (EstimateBarDocPosition (current.ParentGroup, current, out barDocPosition, out autoHideSize)) return; current = current.ParentGroup; } while (current.ParentGroup != null); // Can't find a good location. Just guess. barDocPosition = PositionType.Bottom; autoHideSize = 200; return; } barDocPosition = CalcBarDocPosition (); } bool EstimateBarDocPosition (DockGroup grp, DockObject ignoreChild, out PositionType pos, out int size) { foreach (DockObject ob in grp.Objects) { if (ob == ignoreChild) continue; if (ob is DockGroup) { if (EstimateBarDocPosition ((DockGroup)ob, null, out pos, out size)) return true; } else if (ob is DockGroupItem) { DockGroupItem it = (DockGroupItem) ob; if (it.status == DockItemStatus.AutoHide) { pos = it.barDocPosition; size = it.autoHideSize; return true; } if (!it.Allocation.IsEmpty) { pos = it.CalcBarDocPosition (); size = it.GetAutoHideSize (pos); return true; } } } pos = PositionType.Bottom; size = 0; return false; } PositionType CalcBarDocPosition () { if (Allocation.Width < Allocation.Height) { int mid = Allocation.Left + Allocation.Width / 2; if (mid > Frame.Allocation.Left + Frame.Allocation.Width / 2) return PositionType.Right; else return PositionType.Left; } else { int mid = Allocation.Top + Allocation.Height / 2; if (mid > Frame.Allocation.Top + Frame.Allocation.Height / 2) return PositionType.Bottom; else return PositionType.Top; } } internal void SetVisible (bool value) { if (visibleFlag != value) { visibleFlag = value; if (visibleFlag) item.ShowWidget (); else item.HideWidget (); if (ParentGroup != null) ParentGroup.UpdateVisible (this); } } internal override void StoreAllocation () { base.StoreAllocation (); if (Status == DockItemStatus.Floating) floatRect = item.FloatingPosition; else if (Status == DockItemStatus.AutoHide) autoHideSize = item.AutoHideSize; } internal override void RestoreAllocation () { base.RestoreAllocation (); item.UpdateVisibleStatus (); if (Status == DockItemStatus.Floating) item.SetFloatMode (floatRect); else if (Status == DockItemStatus.AutoHide) item.SetAutoHideMode (barDocPosition, GetAutoHideSize (barDocPosition)); else item.ResetMode (); if (!visibleFlag) item.HideWidget (); } int GetAutoHideSize (Gtk.PositionType pos) { if (autoHideSize != -1) return autoHideSize; if (pos == PositionType.Left || pos == PositionType.Right) return Allocation.Width; else return Allocation.Height; } public Gdk.Rectangle FloatRect { get { return floatRect; } set { floatRect = value; } } public override string ToString () { return "[DockItem " + Item.Id + "]"; } } }