aboutsummaryrefslogtreecommitdiffstatsci
path: root/src/GraphicObjects/DockStack.cs
diff options
context:
space:
mode:
authorj-p <jp.bruyere@live.be>2018-04-14 12:15:08 +0200
committerGitHub <noreply@github.com>2018-04-14 12:15:08 +0200
commit907358fed63b4a89e8dee5184cc9901a7107ab9f (patch)
tree18c473a86b553dbe9f08cfe345b6278c71e9594e /src/GraphicObjects/DockStack.cs
parent7c735fa149bf23223eda734f19d5547797ca8ac2 (diff)
parent5a06966fd4be89263988d0838556b78a7988b5a9 (diff)
Merge pull request #40 from jpbruyere/devel
Devel
Diffstat (limited to 'src/GraphicObjects/DockStack.cs')
-rw-r--r--src/GraphicObjects/DockStack.cs363
1 files changed, 363 insertions, 0 deletions
diff --git a/src/GraphicObjects/DockStack.cs b/src/GraphicObjects/DockStack.cs
new file mode 100644
index 00000000..ae8b9c89
--- /dev/null
+++ b/src/GraphicObjects/DockStack.cs
@@ -0,0 +1,363 @@
+//
+// DockStack.cs
+//
+// Author:
+// Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+//
+// Copyright (c) 2013-2017 Jean-Philippe Bruyère
+//
+// 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 Crow.IML;
+
+namespace Crow
+{
+ [DesignIgnore]
+ public class DockStack : GenericStack
+ {
+ #region CTor
+ public DockStack () {}
+ public DockStack (Interface iface) : base (iface) {}
+ #endregion
+
+ public override void AddChild (GraphicObject g)
+ {
+ base.AddChild (g);
+ if (localLogicalParentIsNull)
+ g.LogicalParent = this;
+ else
+ g.LogicalParent = this.LogicalParent;
+ }
+ public override void InsertChild (int idx, GraphicObject g)
+ {
+ base.InsertChild (idx, g);
+ g.LogicalParent = this.LogicalParent;
+ }
+
+ public override bool PointIsIn (ref Point m)
+ {
+ if (!base.PointIsIn(ref m))
+ return false;
+
+ Group p = Parent as Group;
+ if (p != null) {
+ childrenRWLock.EnterReadLock ();
+ for (int i = p.Children.Count - 1; i >= 0; i--) {
+ if (p.Children [i] == this)
+ break;
+ if (p.Children [i].IsDragged)
+ continue;
+ if (p.Children [i].Slot.ContainsOrIsEqual (m)) {
+ childrenRWLock.ExitReadLock ();
+ return false;
+ }
+ }
+ }
+ childrenRWLock.ExitReadLock ();
+ return Slot.ContainsOrIsEqual(m);
+ }
+
+// public override void OnLayoutChanges (LayoutingType layoutType)
+// {
+// base.OnLayoutChanges (layoutType);
+//
+// if ((layoutType & LayoutingType.Sizing) > 0)
+// computeRects();
+// }
+
+ Rectangle rIn = default(Rectangle);
+ double dockThresh = 0.2;
+ GraphicObject focusedChild;
+ internal GraphicObject stretchedChild;
+
+ void getFocusedChild (Point lm) {
+ Rectangle cb = ClientRectangle;
+
+ childrenRWLock.EnterReadLock ();
+ foreach (GraphicObject c in Children) {
+ Rectangle bounds = c.Slot + cb.Position;
+ if (!bounds.ContainsOrIsEqual (lm))
+ continue;
+ rIn = bounds;
+ focusedChild = c;
+ break;
+ }
+ childrenRWLock.ExitReadLock ();
+ }
+
+ public override void onMouseMove (object sender, MouseMoveEventArgs e)
+ {
+ if (IsDropTarget) {
+ DockWindow dw = IFace.DragAndDropOperation.DragSource as DockWindow;
+ if (dw.IsDocked) {
+ base.onMouseMove (sender, e);
+ return;
+ }
+
+ Alignment curDockPos = dw.DockingPosition;
+ dw.DockingPosition = Alignment.Undefined;
+
+ Rectangle cb = ClientRectangle;
+ Point lm = ScreenPointToLocal (e.Position);
+
+ if (Children.Count == 0) {
+ Rectangle r = cb;
+ r.Inflate (r.Width / -5, r.Height / -5);
+ if (r.ContainsOrIsEqual(lm))
+ dw.DockingPosition = Alignment.Center;
+ } else {
+ rIn = cb;
+
+ if (Orientation == Orientation.Horizontal || Children.Count == 1) {
+ if (lm.Y > cb.Top + cb.Height / 3 && lm.Y < cb.Bottom - cb.Height / 3) {
+ if (lm.X < cb.Left + cb.Width / 3)
+ dw.DockingPosition = Alignment.Left;
+ else if (lm.X > cb.Right - cb.Width / 3)
+ dw.DockingPosition = Alignment.Right;
+ } else {
+ getFocusedChild (lm);
+ if (focusedChild != null) {
+ if (lm.Y < rIn.Top + rIn.Height / 3)
+ dw.DockingPosition = Alignment.Top;
+ else if (lm.Y > rIn.Bottom - rIn.Height / 3)
+ dw.DockingPosition = Alignment.Bottom;
+ }
+ }
+ }
+ if (Orientation == Orientation.Vertical || Children.Count == 1) {
+ if (lm.X > cb.Left + cb.Width / 3 && lm.X < cb.Right - cb.Width / 3) {
+ if (lm.Y < cb.Top + cb.Height / 3)
+ dw.DockingPosition = Alignment.Top;
+ else if (lm.Y > cb.Bottom - cb.Height / 3)
+ dw.DockingPosition = Alignment.Bottom;
+ } else {
+ getFocusedChild (lm);
+ if (focusedChild != null) {
+ if (lm.X < rIn.Left + rIn.Width / 3)
+ dw.DockingPosition = Alignment.Left;
+ else if (lm.X > rIn.Right - rIn.Width / 3)
+ dw.DockingPosition = Alignment.Right;
+ }
+ }
+ }
+ }
+
+ if (curDockPos != dw.DockingPosition)
+ RegisterForGraphicUpdate ();
+ }
+ base.onMouseMove (sender, e);
+ }
+
+ protected override void onDragEnter (object sender, DragDropEventArgs e)
+ {
+ base.onDragEnter (sender, e);
+ RegisterForGraphicUpdate ();
+ }
+ protected override void onDragLeave (object sender, DragDropEventArgs e)
+ {
+ DockWindow dw = e.DragSource as DockWindow;
+ if (dw != null)
+ dw.DockingPosition = Alignment.Undefined;
+ base.onDragLeave (sender, e);
+ RegisterForGraphicUpdate ();
+ }
+
+ protected override void onDraw (Cairo.Context gr)
+ {
+ gr.Save ();
+
+ Rectangle rBack = new Rectangle (Slot.Size);
+
+ Background.SetAsSource (gr, rBack);
+ CairoHelpers.CairoRectangle (gr, rBack, CornerRadius);
+ gr.Fill ();
+
+ if (ClipToClientRect) {
+ //clip to client zone
+ CairoHelpers.CairoRectangle (gr, ClientRectangle, CornerRadius);
+ gr.Clip ();
+ }
+
+ childrenRWLock.EnterReadLock ();
+
+ foreach (GraphicObject g in Children)
+ g.Paint (ref gr);
+
+ childrenRWLock.ExitReadLock ();
+
+
+ if (!IsDropTarget) {
+ gr.Restore ();
+ return;
+ }
+
+ DockWindow dw = IFace.DragAndDropOperation.DragSource as DockWindow;
+ if (dw == null)
+ return;
+ if (!dw.IsDocked) {
+ Rectangle cb = ClientRectangle;
+ double minDim = Math.Min (cb.Width, cb.Height);
+
+ Rectangle r = rIn;
+ if (Children.Count <= 1 || dw.DockingPosition.GetOrientation()==Orientation )
+ r = cb;
+
+ switch (dw.DockingPosition) {
+ case Alignment.Top:
+ gr.Rectangle (r.Left, r.Top, r.Width, r.Height * dockThresh);
+ break;
+ case Alignment.Bottom:
+ gr.Rectangle (r.Left, r.Bottom - r.Height * dockThresh, r.Width, r.Height * dockThresh);
+ break;
+ case Alignment.Left:
+ gr.Rectangle (r.Left, r.Top, r.Width * dockThresh, r.Height);
+ break;
+ case Alignment.Right:
+ gr.Rectangle (r.Right - r.Width * dockThresh, r.Top, r.Width * dockThresh, r.Height);
+ break;
+ case Alignment.Center:
+ r.Inflate ((int)Math.Ceiling (Math.Min (r.Width, r.Height) * -0.05));
+ gr.Rectangle (r);
+ break;
+ }
+ gr.LineWidth = 1;
+ gr.SetSourceRGBA (0.4, 0.4, 0.9, 0.4);
+ gr.FillPreserve ();
+ gr.SetSourceRGBA (0.9, 0.9, 1.0, 0.8);
+ gr.Stroke ();
+ }
+ gr.Restore ();
+ }
+
+ public void Dock(DockWindow dw){
+ DockStack activeStack = this;
+
+ if (Children.Count == 1) {
+ Orientation = dw.DockingPosition.GetOrientation ();
+ if (Children [0] is DockWindow) {
+ (Children [0] as DockWindow).DockingPosition = dw.DockingPosition.GetOpposite ();
+ }
+ } else if (Children.Count > 0 && dw.DockingPosition.GetOrientation () != Orientation) {
+ activeStack = new DockStack (IFace);
+ activeStack.Orientation = dw.DockingPosition.GetOrientation ();
+ activeStack.Width = focusedChild.Width;
+ activeStack.Height = focusedChild.Height;
+ int idx = Children.IndexOf (focusedChild);
+ RemoveChild (focusedChild);
+ focusedChild.Height = Measure.Stretched;
+ focusedChild.Width = Measure.Stretched;
+ InsertChild (idx, activeStack);
+ activeStack.AddChild (focusedChild);
+ activeStack.stretchedChild = focusedChild;
+ if (focusedChild is DockWindow)
+ (focusedChild as DockWindow).DockingPosition = dw.DockingPosition.GetOpposite ();
+ focusedChild = null;
+ }
+
+ Rectangle r = ClientRectangle;
+ int vTreshold = (int)(r.Height * dockThresh);
+ int hTreshold = (int)(r.Width * dockThresh);
+
+ Console.WriteLine ("Docking {0} as {2} in {1}", dw.Name, activeStack.Name, dw.DockingPosition);
+ switch (dw.DockingPosition) {
+ case Alignment.Top:
+ dw.Height = vTreshold;
+ dw.Width = Measure.Stretched;
+ activeStack.InsertChild (0, dw);
+ activeStack.InsertChild (1, new Splitter(IFace));
+ break;
+ case Alignment.Bottom:
+ dw.Height = vTreshold;
+ dw.Width = Measure.Stretched;
+ activeStack.AddChild (new Splitter(IFace));
+ activeStack.AddChild (dw);
+ break;
+ case Alignment.Left:
+ dw.Width = hTreshold;
+ dw.Height = Measure.Stretched;
+ activeStack.InsertChild (0, dw);
+ activeStack.InsertChild (1, new Splitter(IFace));
+ break;
+ case Alignment.Right:
+ dw.Width = hTreshold;
+ dw.Height = Measure.Stretched;
+ activeStack.AddChild (new Splitter(IFace));
+ activeStack.AddChild (dw);
+ break;
+ case Alignment.Center:
+ dw.Width = dw.Height = Measure.Stretched;
+ AddChild (dw);
+ stretchedChild = dw;
+ break;
+ }
+ }
+ public void Undock (DockWindow dw){
+ int idx = Children.IndexOf(dw);
+
+ RemoveChild(dw);
+
+ if (Children.Count == 0)
+ return;
+
+ if (dw.DockingPosition == Alignment.Left || dw.DockingPosition == Alignment.Top) {
+ RemoveChild (idx);
+ if (stretchedChild == dw) {
+ stretchedChild = Children [idx];
+ stretchedChild.Width = stretchedChild.Height = Measure.Stretched;
+ }
+ } else {
+ RemoveChild (idx - 1);
+ if (stretchedChild == dw) {
+ stretchedChild = Children [idx-2];
+ stretchedChild.Width = stretchedChild.Height = Measure.Stretched;
+ }
+ }
+
+ if (Children.Count == 1) {
+ DockStack dsp = Parent as DockStack;
+ if (dsp == null) {
+ Children [0].Width = Children [0].Height = Measure.Stretched;
+ return;
+ }
+ //remove level and move remaining obj to level above
+ GraphicObject g = Children [0];
+ RemoveChild (g);
+ idx = dsp.Children.IndexOf (this);
+ dsp.RemoveChild (this);
+ dsp.InsertChild (idx, g);
+ g.Width = this.Width;
+ g.Height = this.Height;
+ if (dsp.stretchedChild == this)
+ dsp.stretchedChild = g;
+ dsp.checkAlignments ();
+ } else
+ checkAlignments ();
+ }
+
+ internal void checkAlignments () {
+ DockWindow dw = Children[0] as DockWindow;
+ if (dw != null)
+ dw.DockingPosition = (Orientation == Orientation.Horizontal ? Alignment.Left : Alignment.Top);
+ dw = Children[Children.Count - 1] as DockWindow;
+ if (dw != null)
+ dw.DockingPosition = (Orientation == Orientation.Horizontal ? Alignment.Right : Alignment.Bottom);
+ }
+ }
+}
+