diff options
| author | j-p <jp.bruyere@live.be> | 2018-04-14 12:15:08 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-04-14 12:15:08 +0200 |
| commit | 907358fed63b4a89e8dee5184cc9901a7107ab9f (patch) | |
| tree | 18c473a86b553dbe9f08cfe345b6278c71e9594e /src/GraphicObjects | |
| parent | 7c735fa149bf23223eda734f19d5547797ca8ac2 (diff) | |
| parent | 5a06966fd4be89263988d0838556b78a7988b5a9 (diff) | |
Merge pull request #40 from jpbruyere/devel
Devel
Diffstat (limited to 'src/GraphicObjects')
37 files changed, 1819 insertions, 1922 deletions
diff --git a/src/GraphicObjects/Border.cs b/src/GraphicObjects/Border.cs index f2be5993..adeb32e7 100644 --- a/src/GraphicObjects/Border.cs +++ b/src/GraphicObjects/Border.cs @@ -55,7 +55,7 @@ namespace Crow int _borderWidth; BorderStyle _borderStyle; Fill raisedColor = Color.Gray; - Fill sunkenColor = Color.Jet; + Fill sunkenColor = Color.DimGray; #endregion #region public properties diff --git a/src/GraphicObjects/ColorPicker.cs b/src/GraphicObjects/ColorPicker.cs index 3a5ec23f..cc955191 100644 --- a/src/GraphicObjects/ColorPicker.cs +++ b/src/GraphicObjects/ColorPicker.cs @@ -165,7 +165,12 @@ namespace Crow NotifyValueChanged ("SelectedColorName", n); else NotifyValueChanged ("SelectedColorName", "-"); - NotifyValueChanged ("HexColor", ((int)R).ToString ("X2") + ((int)G).ToString ("X2") + ((int)B).ToString ("X2") + ((int)A).ToString ("X2")); + string tmp = ((int)Math.Round (R)).ToString ("X2") + + ((int)Math.Round (G)).ToString ("X2") + + ((int)Math.Round (B)).ToString ("X2"); + if (curColor.A < 1.0) + tmp += ((int)Math.Round (A)).ToString ("X2"); + NotifyValueChanged ("HexColor", tmp); } void notifyRGBAHasChanged(){ NotifyValueChanged ("R", R); diff --git a/src/GraphicObjects/ColorSelector.cs b/src/GraphicObjects/ColorSelector.cs index 5b32fc95..ee57a262 100644 --- a/src/GraphicObjects/ColorSelector.cs +++ b/src/GraphicObjects/ColorSelector.cs @@ -33,6 +33,7 @@ namespace Crow /// <summary> /// simple squarred rgb color selector /// </summary> + [DesignIgnore] public class ColorSelector : GraphicObject { #region CTOR @@ -47,7 +48,7 @@ namespace Crow public override void onMouseMove (object sender, MouseMoveEventArgs e) { base.onMouseMove (sender, e); - if (CurrentInterface.Mouse.LeftButton == ButtonState.Released) + if (IFace.Mouse.LeftButton == ButtonState.Released) return; updateMouseLocalPos (e.Position); } diff --git a/src/GraphicObjects/Container.cs b/src/GraphicObjects/Container.cs index fedee0af..364bad83 100644 --- a/src/GraphicObjects/Container.cs +++ b/src/GraphicObjects/Container.cs @@ -38,6 +38,18 @@ namespace Crow /// </summary> public class Container : PrivateContainer { + #if DESIGN_MODE + public override void getIML (System.Xml.XmlDocument doc, System.Xml.XmlNode parentElem) + { + if (this.design_isTGItem) + return; + base.getIML (doc, parentElem); + if (child == null) + return; + child.getIML (doc, parentElem.LastChild); + } + #endif + #region CTOR protected Container() : base(){} public Container (Interface iface) : base(iface){} 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); + } + } +} + diff --git a/src/GraphicObjects/DockWindow.cs b/src/GraphicObjects/DockWindow.cs index b68a3085..ca4b93f4 100644 --- a/src/GraphicObjects/DockWindow.cs +++ b/src/GraphicObjects/DockWindow.cs @@ -24,6 +24,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. using System; +using System.Xml.Serialization; namespace Crow { @@ -35,10 +36,10 @@ namespace Crow } #endregion + int undockThreshold = 4; bool isDocked = false; - Alignment docking = Alignment.Center; + Alignment docking = Alignment.Undefined; - Point lastMousePos; //last known mouse pos in this control Point undockingMousePosOrig; //mouse pos when docking was donne, use for undocking on mouse move Rectangle savedSlot; //last undocked slot recalled when view is undocked bool wasResizable; @@ -50,8 +51,11 @@ namespace Crow return; isDocked = value; NotifyValueChanged ("IsDocked", isDocked); + NotifyValueChanged ("IsFloating", !isDocked); } } + [XmlIgnore] public bool IsFloating { get { return !isDocked; }} + public Alignment DockingPosition { get { return docking; } set { @@ -61,12 +65,7 @@ namespace Crow NotifyValueChanged ("DockingPosition", DockingPosition); } } - protected override void onDrop (object sender, DragDropEventArgs e) - { - base.onDrop (sender, e); - Docker dv = Parent as Docker; - dv.Dock (this); - } + public override bool PointIsIn (ref Point m) { if (!base.PointIsIn(ref m)) @@ -78,6 +77,8 @@ namespace Crow 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)) { return false; } @@ -87,156 +88,91 @@ namespace Crow return Slot.ContainsOrIsEqual(m); } -// public override void OnLayoutChanges (LayoutingType layoutType) -// { -// base.OnLayoutChanges (layoutType); -// -// if (isDocked) -// return; - -// Docker dv = Parent as Docker; -// if (dv == null) -// return; -// -// Rectangle dvCliRect = dv.ClientRectangle; -// -// if (layoutType == LayoutingType.X) { -// if (Slot.X < dv.DockingThreshold) -// dock (Alignment.Left); -// else if (Slot.Right > dvCliRect.Width - dv.DockingThreshold) -// dock (Alignment.Right); -// }else if (layoutType == LayoutingType.Y) { -// if (Slot.Y < dv.DockingThreshold) -// dock (Alignment.Top); -// else if (Slot.Bottom > dvCliRect.Height - dv.DockingThreshold) -// dock (Alignment.Bottom); -// } -// } -// -// public override void onMouseMove (object sender, MouseMoveEventArgs e) -// { -// lastMousePos = e.Position; -// + public override void onMouseMove (object sender, MouseMoveEventArgs e) + { // if (this.HasFocus && e.Mouse.IsButtonDown (MouseButton.Left) && IsDocked) { -// Docker dv = Parent as Docker; -// if (docking == Alignment.Left) { -// if (lastMousePos.X - undockingMousePosOrig.X > dv.DockingThreshold) -// undock (); -// } else if (docking == Alignment.Right) { -// if (undockingMousePosOrig.X - lastMousePos.X > dv.DockingThreshold) -// undock (); -// } else if (docking == Alignment.Top) { -// if (lastMousePos.Y - undockingMousePosOrig.Y > dv.DockingThreshold) -// undock (); -// } else if (docking == Alignment.Bottom) { -// if (undockingMousePosOrig.Y - lastMousePos.Y > dv.DockingThreshold) -// undock (); -// } -// return; +// if (Math.Abs (e.Position.X - undockingMousePosOrig.X) > 10 || +// Math.Abs (e.Position.X - undockingMousePosOrig.X) > 10) +// Undock (); // } -// -// base.onMouseMove (sender, e); -// } -// public override void onMouseDown (object sender, MouseButtonEventArgs e) -// { -// base.onMouseDown (sender, e); -// -// if (this.HasFocus && IsDocked && e.Button == MouseButton.Left) -// undockingMousePosOrig = lastMousePos; -// } -// protected override void onBorderMouseEnter (object sender, MouseMoveEventArgs e) -// { -// base.onBorderMouseEnter (sender, e); -// -// if (isDocked) { -// switch (docking) { -// case Alignment.Top: -// if (this.currentDirection != Window.Direction.S) -// onBorderMouseLeave (this, null); -// break; -// case Alignment.Left: -// if (this.currentDirection != Window.Direction.E) -// onBorderMouseLeave (this, null); -// break; -// case Alignment.TopLeft: -// break; -// case Alignment.Right: -// if (this.currentDirection != Window.Direction.W) -// onBorderMouseLeave (this, null); -// break; -// case Alignment.TopRight: -// break; -// case Alignment.Bottom: -// if (this.currentDirection != Window.Direction.N) -// onBorderMouseLeave (this, null); -// break; -// case Alignment.BottomLeft: -// break; -// case Alignment.BottomRight: -// break; -// case Alignment.Center: -// break; -// default: -// break; -// } -// } -// } + if (this.HasFocus && e.Mouse.IsButtonDown (MouseButton.Left) && IsDocked) + CheckUndock (e.Position); - void undock () { - this.Left = savedSlot.Left; - this.Top = savedSlot.Top; - this.Width = savedSlot.Width; - this.Height = savedSlot.Height; + base.onMouseMove (sender, e); + } + public override void onMouseDown (object sender, MouseButtonEventArgs e) + { + base.onMouseDown (sender, e); - IsDocked = false; - Resizable = wasResizable; + if (this.HasFocus && IsDocked && e.Button == MouseButton.Left) + undockingMousePosOrig = e.Position; } - void dock (Alignment align){ - IsDocked = true; - docking = align; - undockingMousePosOrig = lastMousePos; - savedSlot = this.LastPaintedSlot; - wasResizable = Resizable; - Resizable = false; + public bool CheckUndock (Point mousePos) { + if (DockingPosition == Alignment.Center) + return false; + if (Math.Abs (mousePos.X - undockingMousePosOrig.X) < undockThreshold || + Math.Abs (mousePos.X - undockingMousePosOrig.X) < undockThreshold) + return false; + Undock (); + return true; + } + + protected override void onStartDrag (object sender, DragDropEventArgs e) + { + base.onStartDrag (sender, e); + + undockingMousePosOrig = IFace.Mouse.Position; + } + protected override void onDrop (object sender, DragDropEventArgs e) + { + if (!isDocked && DockingPosition != Alignment.Undefined) + Dock (e.DropTarget as DockStack); + base.onDrop (sender, e); + } + public void Undock () { + lock (IFace.UpdateMutex) { + DockStack ds = Parent as DockStack; + ds.Undock (this); + + IFace.AddWidget (this); - this.Left = this.Top = 0; + this.Left = savedSlot.Left; + this.Top = savedSlot.Top; + this.Width = savedSlot.Width; + this.Height = savedSlot.Height; - switch (align) { - case Alignment.Top: - this.HorizontalAlignment = HorizontalAlignment.Left; - this.VerticalAlignment = VerticalAlignment.Top; - this.Width = Measure.Stretched; - break; - case Alignment.Left: - this.HorizontalAlignment = HorizontalAlignment.Left; - this.VerticalAlignment = VerticalAlignment.Top; - this.Height = Measure.Stretched; - break; - case Alignment.TopLeft: - break; - case Alignment.Right: - this.HorizontalAlignment = HorizontalAlignment.Right; - this.VerticalAlignment = VerticalAlignment.Top; - this.Height = Measure.Stretched; - break; - case Alignment.TopRight: - break; - case Alignment.Bottom: - this.HorizontalAlignment = HorizontalAlignment.Left; - this.VerticalAlignment = VerticalAlignment.Bottom; - this.Width = Measure.Stretched; - break; - case Alignment.BottomLeft: - break; - case Alignment.BottomRight: - break; - case Alignment.Center: - break; - default: - break; + IsDocked = false; + DockingPosition = Alignment.Undefined; + Resizable = wasResizable; } - + } + + public void Dock (DockStack target){ + lock (IFace.UpdateMutex) { + IsDocked = true; + //undockingMousePosOrig = lastMousePos; + savedSlot = this.LastPaintedSlot; + wasResizable = Resizable; + Resizable = false; + LastSlots = LastPaintedSlot = Slot = default(Rectangle); + Left = Top = 0; + + IFace.RemoveWidget (this); + + target.Dock (this); + } + } + + protected override void close () + { + if (isDocked) + Undock (); + base.close (); + } + + public string ExportWinConfigs () { + return string.Format ("{0};{1};{2}", this.Name, DockingPosition, savedSlot); } } } diff --git a/src/GraphicObjects/Docker.cs b/src/GraphicObjects/Docker.cs deleted file mode 100644 index c52c094f..00000000 --- a/src/GraphicObjects/Docker.cs +++ /dev/null @@ -1,256 +0,0 @@ -// -// DocksView.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 System.Xml.Serialization; -using System.ComponentModel; -using Crow.IML; - -namespace Crow -{ - public class Docker : Group - { - static Instantiator instStack, instSplit, instSpacer; - #region CTOR - static Docker () { - instStack = Instantiator.CreateFromImlFragment(@"<GenericStack Background='Blue' AllowDrop='true' DragEnter='onStackDragEnter'/>"); - instSplit = Instantiator.CreateFromImlFragment(@"<Splitter/>"); - instSpacer = Instantiator.CreateFromImlFragment(@"<GraphicObject Background='Red' IsEnabled='false'/>"); - } - public Docker () : base () - { - } - #endregion - - GenericStack rootStack = null; - - public override void AddChild (GraphicObject g) - { - DockWindow dw = g as DockWindow; - if (dw == null) - throw new Exception ("Docker accept only DockWindow as child"); - - base.AddChild (g); - - dw.LogicalParent = this; - } - public override void RemoveChild (GraphicObject child) - { - child.LogicalParent = null; - - - base.RemoveChild (child); - } - - GenericStack mainStack = null; - int dockingThreshold; - - [XmlAttributeAttribute][DefaultValue(10)] - public virtual int DockingThreshold { - get { return dockingThreshold; } - set { - if (dockingThreshold == value) - return; - dockingThreshold = value; - NotifyValueChanged ("DockingThreshold", dockingThreshold); - - } - } - - bool showDockingTarget = false; - Alignment dockingDirection = Alignment.Center; - int dockingDiv = 5; - - public override void onMouseMove (object sender, MouseMoveEventArgs e) - { - if (CurrentInterface.DragAndDropOperation?.DragSource as DockWindow != null) { - DockWindow dw = CurrentInterface.DragAndDropOperation?.DragSource as DockWindow; - if (CurrentInterface.DragAndDropOperation.DragSource.Parent == this && !dw.IsDocked) - dw.MoveAndResize (e.XDelta, e.YDelta); - - Rectangle r = ClientRectangle; - int vTreshold = r.Height / dockingDiv; - int hTreshold = r.Width / dockingDiv; - - - bool showDock = true; - - if (dw.Slot.Left < hTreshold) - dockingDirection = Alignment.Left; - else if (dw.Slot.Right > r.Right - hTreshold) - dockingDirection = Alignment.Right; - else if (dw.Slot.Top < vTreshold) - dockingDirection = Alignment.Top; - else if (dw.Slot.Bottom > r.Bottom - vTreshold) - dockingDirection = Alignment.Bottom; - else { - dockingDirection = Alignment.Center; - showDock = false; - } - - showDockingTarget = showDock; - - RegisterForGraphicUpdate (); - - //System.Diagnostics.Debug.WriteLine ("Dock: {0}", dockingDirection); - } else - showDockingTarget = false; - - base.onMouseMove (sender, e); - } - protected override void onDragEnter (object sender, DragDropEventArgs e) - { - base.onDragEnter (sender, e); - } - void onStackDragEnter (object sender, DragDropEventArgs e) - { - base.onDragEnter (sender, e); - - mainStack = sender as GenericStack; - } - 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) { - if (CurrentInterface.DragAndDropOperation?.DragSource == g) - continue; - g.Paint (ref gr); - } - - childrenRWLock.ExitReadLock (); - - if (showDockingTarget) { - Rectangle r; - if (mainStack == null) - r = ClientRectangle; - else - r = mainStack.ClientRectangle; - - switch (dockingDirection) { - case Alignment.Top: - gr.Rectangle (r.Left, r.Top, r.Width, r.Height / dockingDiv); - break; - case Alignment.Bottom: - gr.Rectangle (r.Left, r.Bottom - r.Height / dockingDiv, r.Width, r.Height / dockingDiv); - break; - case Alignment.Left: - gr.Rectangle (r.Left, r.Top, r.Width / dockingDiv, r.Height); - break; - case Alignment.Right: - gr.Rectangle (r.Right - r.Width / dockingDiv, r.Top, r.Width / dockingDiv, r.Height); - 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 (); - } - - if (CurrentInterface.DragAndDropOperation != null) - CurrentInterface.DragAndDropOperation.DragSource.Paint (ref gr); - - - gr.Restore (); - } - - public void Dock(DockWindow dw){ - if (dockingDirection == Alignment.Center) - return; - lock (CurrentInterface.UpdateMutex) { - - Splitter splitter = instSplit.CreateInstance<Splitter> (CurrentInterface); - - dw.Resizable = false; - dw.Left = dw.Top = 0; - this.RemoveChild (dw); - - Rectangle r; - if (mainStack == null) { - mainStack = instStack.CreateInstance<GenericStack> (CurrentInterface); - this.AddChild (mainStack); - this.putWidgetOnBottom (mainStack); - r = ClientRectangle; - } else - r = mainStack.ClientRectangle; - - int vTreshold = r.Height / dockingDiv; - int hTreshold = r.Width / dockingDiv; - - switch (dockingDirection) { - case Alignment.Top: - dw.Width = Measure.Stretched; - mainStack.Orientation = Orientation.Vertical; - mainStack.AddChild (dw); - mainStack.AddChild (splitter); - //mainStack.AddChild (instSpacer.CreateInstance (CurrentInterface)); - break; - case Alignment.Bottom: - dw.Width = Measure.Stretched; - mainStack.Orientation = Orientation.Vertical; - //mainStack.AddChild (instSpacer.CreateInstance (CurrentInterface)); - mainStack.AddChild (splitter); - mainStack.AddChild (dw); - break; - case Alignment.Left: - dw.Height = Measure.Stretched; - mainStack.Orientation = Orientation.Horizontal; - mainStack.AddChild (dw); - mainStack.AddChild (splitter); - //mainStack.AddChild (instSpacer.CreateInstance (CurrentInterface)); - break; - case Alignment.Right: - dw.Height = Measure.Stretched; - mainStack.Orientation = Orientation.Horizontal; - //mainStack.AddChild (instSpacer.CreateInstance (CurrentInterface)); - mainStack.AddChild (splitter); - mainStack.AddChild (dw); - break; - } - - } - } - protected override void onDrop (object sender, DragDropEventArgs e) - { - base.onDrop (sender, e); - } - } -} - diff --git a/src/GraphicObjects/Expandable.cs b/src/GraphicObjects/Expandable.cs index aff804f8..1920a8fe 100644 --- a/src/GraphicObjects/Expandable.cs +++ b/src/GraphicObjects/Expandable.cs @@ -77,7 +77,7 @@ namespace Crow NotifyValueChanged ("Image", image); } } - [XmlAttributeAttribute][DefaultValue(false)] + [DefaultValue(false)] public bool IsExpanded { get { return _isExpanded; } @@ -90,7 +90,7 @@ namespace Crow bool isExp = IsExpandable; NotifyValueChanged ("IsExpandable", isExp); - if (!(HasContent & isExp)) + if (!isExp) _isExpanded = false; NotifyValueChanged ("IsExpanded", _isExpanded); diff --git a/src/GraphicObjects/FileDialog.cs b/src/GraphicObjects/FileDialog.cs index 285ca253..8069b8a7 100644 --- a/src/GraphicObjects/FileDialog.cs +++ b/src/GraphicObjects/FileDialog.cs @@ -143,12 +143,13 @@ namespace Crow CurrentDirectory = SelectedDirectory; else { OkClicked.Raise (this, null); - CurrentInterface.DeleteWidget (this); + IFace.DeleteWidget (this); } } void onCancel(object sender, MouseButtonEventArgs e){ - CurrentInterface.DeleteWidget (this); + IFace.DeleteWidget (this); } + } } diff --git a/src/GraphicObjects/GenericStack.cs b/src/GraphicObjects/GenericStack.cs index 7976f837..64841d4b 100644 --- a/src/GraphicObjects/GenericStack.cs +++ b/src/GraphicObjects/GenericStack.cs @@ -28,6 +28,7 @@ using System.ComponentModel; using System.Diagnostics; using System.Xml.Serialization; using System; +using System.Linq; namespace Crow { @@ -79,13 +80,7 @@ namespace Crow } protected override int measureRawSize (LayoutingType lt) { - int totSpace = 0; - for (int i = 0; i < Children.Count; i++) { - if (Children [i].Visible) - totSpace += Spacing; - } - if (totSpace > 0) - totSpace -= Spacing; + int totSpace = Math.Max(0, Spacing * (Children.Count (c => c.Visible) - 1)); if (lt == LayoutingType.Width) { if (Orientation == Orientation.Horizontal) return contentSize.Width + totSpace + 2 * Margin; @@ -128,7 +123,7 @@ namespace Crow //if no layouting remains in queue for item, registre for redraw if (RegisteredLayoutings == LayoutingType.None && IsDirty) - CurrentInterface.EnqueueForRepaint (this); + IFace.EnqueueForRepaint (this); return true; } @@ -136,6 +131,46 @@ namespace Crow return base.UpdateLayout(layoutType); } + void adjustStretchedGo (LayoutingType lt){ + if (stretchedGO == null) + return; + if (lt == LayoutingType.Width) { + int newW = Math.Max ( + this.ClientRectangle.Width - contentSize.Width - Spacing * (Children.Count - 1), + stretchedGO.MinimumSize.Width); + if (stretchedGO.MaximumSize.Width > 0) + newW = Math.Min (newW, stretchedGO.MaximumSize.Width); + if (newW != stretchedGO.Slot.Width) { + stretchedGO.Slot.Width = newW; + stretchedGO.IsDirty = true; + #if DEBUG_LAYOUTING + Debug.WriteLine ("\tAdjusting Width of " + stretchedGO.ToString()); + #endif + stretchedGO.LayoutChanged -= OnChildLayoutChanges; + stretchedGO.OnLayoutChanges (LayoutingType.Width); + stretchedGO.LayoutChanged += OnChildLayoutChanges; + stretchedGO.LastSlots.Width = stretchedGO.Slot.Width; + } + } else { + int newH = Math.Max ( + this.ClientRectangle.Height - contentSize.Height - Spacing * (Children.Count - 1), + stretchedGO.MinimumSize.Height); + if (stretchedGO.MaximumSize.Height > 0) + newH = Math.Min (newH, stretchedGO.MaximumSize.Height); + if (newH != stretchedGO.Slot.Height) { + stretchedGO.Slot.Height = newH; + stretchedGO.IsDirty = true; + #if DEBUG_LAYOUTING + Debug.WriteLine ("\tAdjusting Height of " + stretchedGO.ToString()); + #endif + stretchedGO.LayoutChanged -= OnChildLayoutChanges; + stretchedGO.OnLayoutChanges (LayoutingType.Height); + stretchedGO.LayoutChanged += OnChildLayoutChanges; + stretchedGO.LastSlots.Height = stretchedGO.Slot.Height; + } + } + } + public override void OnChildLayoutChanges (object sender, LayoutingEventArgs arg) { GraphicObject go = sender as GraphicObject; @@ -154,24 +189,7 @@ namespace Crow } else contentSize.Width += go.Slot.Width - go.LastSlots.Width; - if (stretchedGO != null) { - int newW = Math.Max ( - this.ClientRectangle.Width - contentSize.Width - Spacing * (Children.Count - 1), - stretchedGO.MinimumSize.Width); - if (stretchedGO.MaximumSize.Width > 0) - newW = Math.Min (newW, stretchedGO.MaximumSize.Width); - if (newW != stretchedGO.Slot.Width) { - stretchedGO.Slot.Width = newW; - stretchedGO.IsDirty = true; -#if DEBUG_LAYOUTING - Debug.WriteLine ("\tAdjusting Width of " + stretchedGO.ToString()); -#endif - stretchedGO.LayoutChanged -= OnChildLayoutChanges; - stretchedGO.OnLayoutChanges (LayoutingType.Width); - stretchedGO.LayoutChanged += OnChildLayoutChanges; - stretchedGO.LastSlots.Width = stretchedGO.Slot.Width; - } - } + adjustStretchedGo (LayoutingType.Width); if (Width == Measure.Fit) this.RegisterForLayouting (LayoutingType.Width); @@ -193,24 +211,7 @@ namespace Crow } else contentSize.Height += go.Slot.Height - go.LastSlots.Height; - if (stretchedGO != null) { - int newH = Math.Max ( - this.ClientRectangle.Height - contentSize.Height - Spacing * (Children.Count - 1), - stretchedGO.MinimumSize.Height); - if (stretchedGO.MaximumSize.Height > 0) - newH = Math.Min (newH, stretchedGO.MaximumSize.Height); - if (newH != stretchedGO.Slot.Height) { - stretchedGO.Slot.Height = newH; - stretchedGO.IsDirty = true; -#if DEBUG_LAYOUTING - Debug.WriteLine ("\tAdjusting Height of " + stretchedGO.ToString()); -#endif - stretchedGO.LayoutChanged -= OnChildLayoutChanges; - stretchedGO.OnLayoutChanges (LayoutingType.Height); - stretchedGO.LayoutChanged += OnChildLayoutChanges; - stretchedGO.LastSlots.Height = stretchedGO.Slot.Height; - } - } + adjustStretchedGo (LayoutingType.Height); if (Height == Measure.Fit) this.RegisterForLayouting (LayoutingType.Height); @@ -224,6 +225,22 @@ namespace Crow } #endregion - + public override void RemoveChild (GraphicObject child) + { + if (child != stretchedGO) { + if (Orientation == Orientation.Horizontal) + contentSize.Width -= child.LastSlots.Width; + else + contentSize.Height -= child.LastSlots.Height; + } + base.RemoveChild (child); + if (child == stretchedGO) { + stretchedGO = null; + RegisterForLayouting (LayoutingType.Sizing); + }else if (Orientation == Orientation.Horizontal) + adjustStretchedGo (LayoutingType.Width); + else + adjustStretchedGo (LayoutingType.Height); + } } } diff --git a/src/GraphicObjects/GraduatedSlider.cs b/src/GraphicObjects/GraduatedSlider.cs index 52ba2960..e1d4dd46 100644 --- a/src/GraphicObjects/GraduatedSlider.cs +++ b/src/GraphicObjects/GraduatedSlider.cs @@ -33,6 +33,7 @@ using System.Xml.Serialization; namespace Crow { + [DesignIgnore] public class GraduatedSlider : Slider { #region CTOR diff --git a/src/GraphicObjects/GraphicObject.cs b/src/GraphicObjects/GraphicObject.cs index f671239d..bc955368 100644 --- a/src/GraphicObjects/GraphicObject.cs +++ b/src/GraphicObjects/GraphicObject.cs @@ -36,6 +36,12 @@ using System.Diagnostics; using Crow.IML; using System.Threading; + +#if DESIGN_MODE +using System.Xml; +using System.IO; +#endif + namespace Crow { /// <summary> @@ -45,6 +51,101 @@ namespace Crow { internal ReaderWriterLockSlim parentRWLock = new ReaderWriterLockSlim(); + #if DESIGN_MODE + static MethodInfo miDesignAddDefLoc = typeof(GraphicObject).GetMethod("design_add_style_location", + BindingFlags.Instance | BindingFlags.NonPublic); + static MethodInfo miDesignAddValLoc = typeof(GraphicObject).GetMethod("design_add_iml_location", + BindingFlags.Instance | BindingFlags.NonPublic); + + public volatile bool design_HasChanged = false; + public string design_id; + public int design_line; + public int design_column; + public string design_imlPath; + public bool design_isTGItem = false;//true if this is a templated item's root + public Dictionary<string,string> design_iml_values = new Dictionary<string, string>(); + public Dictionary<string,string> design_style_values = new Dictionary<string, string>(); + //public Dictionary<string,FileLocation> design_iml_locations = new Dictionary<string, FileLocation>(); + public Dictionary<string,FileLocation> design_style_locations = new Dictionary<string, FileLocation>(); + + internal void design_add_style_location (string memberName, string path, int line, int col) { + if (design_style_locations.ContainsKey(memberName)){ + Console.WriteLine ("default value localtion already set for {0}{1}.{2}", this.GetType().Name, this.design_id, memberName); + return; + } + design_style_locations.Add(memberName, new FileLocation(path,line,col)); + } +// internal void design_add_iml_location (string memberName, string path, int line, int col) { +// if (design_iml_locations.ContainsKey(memberName)){ +// Console.WriteLine ("IML value localtion already set for {0}{1}.{2}", this.GetType().Name, this.design_id, memberName); +// return; +// } +// design_iml_locations.Add(memberName, new FileLocation(path,line,col)); +// } + + public virtual bool FindByDesignID(string designID, out GraphicObject go){ + go = null; + if (this.design_id == designID){ + go = this; + return true; + } + return false; + } + + public string GetIML(){ + XmlDocument doc = new XmlDocument( ); + + using (StringWriter sw = new StringWriter ()) { + XmlWriterSettings settings = new XmlWriterSettings { + Indent = true, + IndentChars = "\t", + }; + using (XmlWriter xtw = XmlWriter.Create (sw, settings)) { + //(1) the xml declaration is recommended, but not mandatory + XmlDeclaration xmlDeclaration = doc.CreateXmlDeclaration ("1.0", "UTF-8", null); + doc.InsertBefore (xmlDeclaration, null); + getIML (doc, (XmlNode)doc); + doc.WriteTo (xtw); + } + this.design_HasChanged = false; + return sw.ToString (); + } + } + + public virtual void getIML(XmlDocument doc, XmlNode parentElem) { + if (this.design_isTGItem) + return; + + XmlElement xe = doc.CreateElement(this.GetType().Name); + + foreach (KeyValuePair<string,string> kv in design_iml_values) { + XmlAttribute xa = doc.CreateAttribute (kv.Key); + xa.Value = kv.Value; + xe.Attributes.Append (xa); + } + + parentElem.AppendChild (xe); + } + public Surface CreateIcon (int dragIconSize = 32) { + ImageSurface di = new ImageSurface (Format.Argb32, dragIconSize, dragIconSize); + using (Context ctx = new Context (di)) { + double div = Math.Max (LastPaintedSlot.Width, LastPaintedSlot.Height); + double s = (double)dragIconSize / div; + ctx.Scale (s, s); + if (bmp == null) + this.onDraw (ctx); + else { + if (LastPaintedSlot.Width>LastPaintedSlot.Height) + ctx.SetSourceSurface (bmp, 0, (LastPaintedSlot.Width-LastPaintedSlot.Height)/2); + else + ctx.SetSourceSurface (bmp, (LastPaintedSlot.Height-LastPaintedSlot.Width)/2, 0); + ctx.Paint (); + } + } + return di; + } + #endif + #region IDisposable implementation protected bool disposed = false; @@ -53,6 +154,7 @@ namespace Crow GC.SuppressFinalize(this); } ~GraphicObject(){ + Debug.WriteLine(this.ToString() + " not disposed by user"); Dispose(false); } protected virtual void Dispose(bool disposing){ @@ -70,18 +172,8 @@ namespace Crow throw new Exception("Trying to dispose an object queued for Redraw: " + this.ToString()); #endif - if (CurrentInterface.HoverWidget != null) { - if (CurrentInterface.HoverWidget.IsOrIsInside(this)) - CurrentInterface.HoverWidget = null; - } - if (CurrentInterface.ActiveWidget != null) { - if (CurrentInterface.ActiveWidget.IsOrIsInside (this)) - CurrentInterface.ActiveWidget = null; - } - if (CurrentInterface.FocusedWidget != null) { - if (CurrentInterface.FocusedWidget.IsOrIsInside (this)) - CurrentInterface.FocusedWidget = null; - } + unshownPostActions (); + if (!localDataSourceIsNull) DataSource = null; @@ -100,14 +192,14 @@ namespace Crow internal ulong uid = 0; internal bool isPopup = false; - internal GraphicObject focusParent { + public GraphicObject focusParent { get { return (isPopup ? LogicalParent : parent) as GraphicObject; } } /// <summary> /// interface this widget is bound to, this should not be changed once the instance is created /// </summary> - public Interface CurrentInterface = null; + public Interface IFace = null; /// <summary> /// contains the dirty rectangles in the coordinate system of the cache. those dirty zones @@ -159,17 +251,17 @@ namespace Crow /// <param name="iface">Iface.</param> public GraphicObject (Interface iface) : this() { - CurrentInterface = iface; + IFace = iface; Initialize (); } #endregion - internal bool initialized = false; + //internal bool initialized = false; /// <summary> /// Initialize this Graphic object instance by setting style and default values and loading template if required /// </summary> public virtual void Initialize(){ loadDefaultValues (); - initialized = true; + //initialized = true; } #region private fields LayoutingType registeredLayoutings = LayoutingType.All; @@ -186,6 +278,7 @@ namespace Crow bool focusable = false; bool hasFocus = false; bool isActive = false; + bool isHover = false; bool mouseRepeat; protected bool isVisible = true; bool isEnabled = true; @@ -196,6 +289,7 @@ namespace Crow bool cacheEnabled = false; bool clipToClientRect = true; protected object dataSource; + bool rootDataLevel; string style; object tag; bool isDragged; @@ -252,6 +346,7 @@ namespace Crow parentRWLock.EnterWriteLock(); parent = value; + Slot = LastSlots = default(Rectangle); parentRWLock.ExitWriteLock(); onParentChanged (this, e); @@ -288,11 +383,24 @@ namespace Crow Parent.ContextCoordinates (r); } public virtual Rectangle ScreenCoordinates (Rectangle r){ - return - Parent.ScreenCoordinates(r) + Parent.getSlot().Position + Parent.ClientRectangle.Position; + try { + return + Parent.ScreenCoordinates(r) + Parent.getSlot().Position + Parent.ClientRectangle.Position; + } catch (Exception ex) { + Debug.WriteLine (ex); + return default(Rectangle); + } } public virtual Rectangle getSlot () { return Slot;} #endregion + public Point ScreenPointToLocal(Point p){ + Point pt = p - ScreenCoordinates(Slot).TopLeft - ClientRectangle.TopLeft; + if (pt.X < 0) + pt.X = 0; + if (pt.Y < 0) + pt.Y = 0; + return pt; + } #region EVENT HANDLERS /// <summary>Occurs when mouse wheel is rolled in this object. It bubbles to the root</summary> @@ -321,15 +429,29 @@ namespace Crow public event EventHandler Focused; /// <summary>Occurs when this object loose focus</summary> public event EventHandler Unfocused; - /// <summary>Occurs when the enabled state this object is set to true</summary> + /// <summary>Occurs when mouse is over</summary> + public event EventHandler Hover; + /// <summary>Occurs when this control is no longer the Hover one</summary> + public event EventHandler UnHover; + /// <summary>Occurs when this object loose focus</summary> public event EventHandler Enabled; /// <summary>Occurs when the enabled state this object is set to false</summary> public event EventHandler Disabled; - public event EventHandler StartDrag; - public event EventHandler DragEnter; - public event EventHandler DragLeave; - public event EventHandler EndDrag; - public event EventHandler Drop; + + #region DragAndDrop Events + public event EventHandler<DragDropEventArgs> StartDrag; + public event EventHandler<DragDropEventArgs> DragEnter; + public event EventHandler<DragDropEventArgs> DragLeave; + public event EventHandler<DragDropEventArgs> EndDrag; + public event EventHandler<DragDropEventArgs> Drop; + #endregion + + /// <summary> + /// Occurs when default value and styling are loaded, and for templated control, + /// template is also loaded. Bindings should be functionnal as well. + /// </summary> + public event EventHandler Initialized; + /// <summary>Occurs when one part of the rendering slot changed</summary> public event EventHandler<LayoutingEventArgs> LayoutChanged; /// <summary>Occurs when DataSource changed</summary> @@ -342,7 +464,7 @@ namespace Crow #region public properties /// <summary>Random value placeholder</summary> - [XmlAttributeAttribute] + [DesignCategory ("Divers")] public object Tag { get { return tag; } set { @@ -356,7 +478,7 @@ namespace Crow /// If enabled, resulting bitmap of graphic object is cached /// speeding up rendering of complex object. Default is enabled. /// </summary> - [XmlAttributeAttribute][DefaultValue(true)] + [DesignCategory ("Behavior")][DefaultValue(true)] public virtual bool CacheEnabled { get { return cacheEnabled; } set { @@ -369,7 +491,7 @@ namespace Crow /// <summary> /// If true, rendering of GraphicObject is clipped inside client rectangle /// </summary> - [XmlAttributeAttribute][DefaultValue(true)] + [DesignCategory ("Appearance")][DefaultValue(true)] public virtual bool ClipToClientRect { get { return clipToClientRect; } set { @@ -390,7 +512,7 @@ namespace Crow /// and by template controls to find special element in their template implementation such /// as a container or a group to put children in. /// </summary> - [XmlAttributeAttribute][DefaultValue(null)] + [DesignCategory ("Divers")][DefaultValue(null)] public virtual string Name { get { #if DEBUG @@ -410,7 +532,7 @@ namespace Crow /// Vertical alignment inside parent, disabled if height is stretched /// or top coordinate is not null /// </summary> - [XmlAttributeAttribute ()][DefaultValue(VerticalAlignment.Center)] + [DesignCategory ("Layout")][DefaultValue(VerticalAlignment.Center)] public virtual VerticalAlignment VerticalAlignment { get { return verticalAlignment; } set { @@ -426,7 +548,7 @@ namespace Crow /// Horizontal alignment inside parent, disabled if width is stretched /// or left coordinate is not null /// </summary> - [XmlAttributeAttribute()][DefaultValue(HorizontalAlignment.Center)] + [DesignCategory ("Layout")][DefaultValue(HorizontalAlignment.Center)] public virtual HorizontalAlignment HorizontalAlignment { get { return horizontalAlignment; } set { @@ -440,7 +562,7 @@ namespace Crow /// <summary> /// x position inside parent /// </summary> - [XmlAttributeAttribute()][DefaultValue(0)] + [DesignCategory ("Layout")][DefaultValue(0)] public virtual int Left { get { return left; } set { @@ -454,7 +576,7 @@ namespace Crow /// <summary> /// y position inside parent /// </summary> - [XmlAttributeAttribute()][DefaultValue(0)] + [DesignCategory ("Layout")][DefaultValue(0)] public virtual int Top { get { return top; } set { @@ -468,7 +590,7 @@ namespace Crow /// <summary> /// Helper property used to set width and height to fit in one call /// </summary> - [XmlAttributeAttribute()][DefaultValue(false)] + [DesignCategory ("Layout")][DefaultValue(false)] public virtual bool Fit { get { return Width == Measure.Fit && Height == Measure.Fit ? true : false; } set { @@ -482,7 +604,7 @@ namespace Crow /// Width of this control, by default inherited from parent. May have special values /// such as Stretched or Fit. It may be proportionnal or absolute. /// </summary> - [XmlAttributeAttribute()][DefaultValue("Inherit")] + [DesignCategory ("Layout")][DefaultValue("Inherit")] public virtual Measure Width { get { return width.Units == Unit.Inherit ? @@ -496,23 +618,24 @@ namespace Crow if (value < MinimumSize.Width || (value > MaximumSize.Width && MaximumSize.Width > 0)) return; } - Measure lastWP = WidthPolicy; + Measure old = width; width = value; NotifyValueChanged ("Width", width); - if (WidthPolicy != lastWP) { - NotifyValueChanged ("WidthPolicy", WidthPolicy); + if (width == Measure.Stretched || old == Measure.Stretched) { + //NotifyValueChanged ("WidthPolicy", width.Policy); //contentSize in Stacks are only update on childLayoutChange, and the single stretched //child of the stack is not counted in contentSize, so when changing size policy of a child //we should adapt contentSize //TODO:check case when child become stretched, and another stretched item already exists. - if (parent is GenericStack) {//TODO:check if I should test Group instead - if ((parent as GenericStack).Orientation == Orientation.Horizontal) { - if (lastWP == Measure.Fit) - (parent as GenericStack).contentSize.Width -= this.LastSlots.Width; + GenericStack gs = Parent as GenericStack; + if (gs != null){ //TODO:check if I should test Group instead + if (gs.Orientation == Orientation.Horizontal) { + if (width == Measure.Stretched) + gs.contentSize.Width -= this.LastSlots.Width; else - (parent as GenericStack).contentSize.Width += this.LastSlots.Width; + gs.contentSize.Width += this.LastSlots.Width; } - } + } } this.RegisterForLayouting (LayoutingType.Width); @@ -522,7 +645,7 @@ namespace Crow /// Height of this control, by default inherited from parent. May have special values /// such as Stretched or Fit. It may be proportionnal or absolute. /// </summary> - [XmlAttributeAttribute()][DefaultValue("Inherit")] + [DesignCategory ("Layout")][DefaultValue("Inherit")] public virtual Measure Height { get { return height.Units == Unit.Inherit ? @@ -536,17 +659,18 @@ namespace Crow if (value < MinimumSize.Height || (value > MaximumSize.Height && MaximumSize.Height > 0)) return; } - Measure lastHP = HeightPolicy; + Measure old = height; height = value; NotifyValueChanged ("Height", height); - if (HeightPolicy != lastHP) { - NotifyValueChanged ("HeightPolicy", HeightPolicy); - if (parent is GenericStack) { - if ((parent as GenericStack).Orientation == Orientation.Vertical) { - if (lastHP == Measure.Fit) - (parent as GenericStack).contentSize.Height -= this.LastSlots.Height; + if (height == Measure.Stretched || old == Measure.Stretched) { + //NotifyValueChanged ("HeightPolicy", HeightPolicy); + GenericStack gs = Parent as GenericStack; + if (gs != null){ //TODO:check if I should test Group instead + if (gs.Orientation == Orientation.Vertical) { + if (height == Measure.Stretched) + gs.contentSize.Height -= this.LastSlots.Height; else - (parent as GenericStack).contentSize.Height += this.LastSlots.Height; + gs.contentSize.Height += this.LastSlots.Height; } } } @@ -555,13 +679,13 @@ namespace Crow } } /// <summary> - /// Used for binding on dimensions, this property will never hold fixed size, but instead only + /// Was Used for binding on dimensions, this property will never hold fixed size, but instead only /// Fit or Stretched, **with inherited state implementation, it is not longer used in binding** /// </summary> [XmlIgnore]public virtual Measure WidthPolicy { get { return Width.IsFit ? Measure.Fit : Measure.Stretched; } } /// <summary> - /// Used for binding on dimensions, this property will never hold fixed size, but instead only + /// Was Used for binding on dimensions, this property will never hold fixed size, but instead only /// Fit or Stretched, **with inherited state implementation, it is not longer used in binding** /// </summary> [XmlIgnore]public virtual Measure HeightPolicy { get { @@ -570,7 +694,7 @@ namespace Crow /// Indicate that this object may received focus or not, if not focusable all the descendants are /// affected. /// </summary> - [XmlAttributeAttribute()][DefaultValue(false)] + [DesignCategory ("Behaviour")][DefaultValue(false)] public virtual bool Focusable { get { return focusable; } set { @@ -612,9 +736,28 @@ namespace Crow } } /// <summary> + /// true if this control has the pointer hover + /// </summary> + [XmlIgnore]public virtual bool IsHover { + get { return isHover; } + set { + if (value == isHover) + return; + + isHover = value; + + if (isHover) + onHover (this, null); + else + onUnHover (this, null); + + NotifyValueChanged ("IsHover", isHover); + } + } + /// <summary> /// true if holding mouse button down should trigger multiple click events /// </summary> - [XmlAttributeAttribute()][DefaultValue(false)] + [DesignCategory ("Behaviour")][DefaultValue(false)] public virtual bool MouseRepeat { get { return mouseRepeat; } set { @@ -628,7 +771,7 @@ namespace Crow /// <summary> /// background fill of the control, maybe solid color, gradient, image, or svg /// </summary> - [XmlAttributeAttribute()][DefaultValue("Transparent")] + [DesignCategory ("Appearance")][DefaultValue("Transparent")] public virtual Fill Background { get { return background; } set { @@ -649,7 +792,7 @@ namespace Crow /// <summary> /// Foreground fill of the control, usage may be different among derived controls /// </summary> - [XmlAttributeAttribute()][DefaultValue("White")] + [DesignCategory ("Appearance")][DefaultValue("White")] public virtual Fill Foreground { get { return foreground; } set { @@ -663,7 +806,7 @@ namespace Crow /// <summary> /// Font being used in many controls, it is defined in the base GraphicObject class. /// </summary> - [XmlAttributeAttribute()][DefaultValue("sans,10")] + [DesignCategory ("Appearance")][DefaultValue("sans,10")] public virtual Font Font { get { return font; } set { @@ -677,7 +820,7 @@ namespace Crow /// <summary> /// to get rounded corners /// </summary> - [XmlAttributeAttribute()][DefaultValue(0.0)] + [DesignCategory ("Appearance")][DefaultValue(0.0)] public virtual double CornerRadius { get { return cornerRadius; } set { @@ -692,7 +835,7 @@ namespace Crow /// This is a single integer for the 4 direction, a gap between the control and it's container, /// by default it is filled with the background. /// </summary> - [XmlAttributeAttribute()][DefaultValue(0)] + [DesignCategory ("Layout")][DefaultValue(0)] public virtual int Margin { get { return margin; } set { @@ -706,7 +849,7 @@ namespace Crow /// <summary> /// set the visible state of the control, invisible controls does reserve space in the layouting system. /// </summary> - [XmlAttributeAttribute][DefaultValue(true)] + [DesignCategory ("Appearance")][DefaultValue(true)] public virtual bool Visible { get { return isVisible; } set { @@ -717,8 +860,8 @@ namespace Crow RegisterForLayouting (LayoutingType.Sizing); - //trigger a mouse to handle possible hover changes - //CurrentInterface.ProcessMouseMove (CurrentInterface.Mouse.X, CurrentInterface.Mouse.Y); + if (!isVisible) + unshownPostActions (); NotifyValueChanged ("Visible", isVisible); } @@ -727,7 +870,7 @@ namespace Crow /// get or set the enabled state, disabling a control will affect focuability and /// also it's rendering which will be grayed /// </summary> - [XmlAttributeAttribute][DefaultValue(true)] + [DesignCategory ("Behaviour")][DefaultValue(true)] public virtual bool IsEnabled { get { return isEnabled; } set { @@ -748,7 +891,7 @@ namespace Crow /// <summary> /// Minimal width and height for this control /// </summary> - [XmlAttributeAttribute()][DefaultValue("1,1")] + [DesignCategory ("Layout")][DefaultValue("1,1")] public virtual Size MinimumSize { get { return minimumSize; } set { @@ -764,7 +907,7 @@ namespace Crow /// <summary> /// Maximum width and height for this control, unlimited if null. /// </summary> - [XmlAttributeAttribute()][DefaultValue("0,0")] + [DesignCategory ("Layout")][DefaultValue("0,0")] public virtual Size MaximumSize { get { return maximumSize; } set { @@ -781,7 +924,7 @@ namespace Crow /// Seek first logical tree upward if logicalParent is set, or seek graphic tree for /// a not null dataSource that will be active for all descendants having dataSource=null /// </summary> - [XmlAttributeAttribute] + [DesignCategory ("Data")] public virtual object DataSource { set { if (DataSource == value) @@ -793,19 +936,36 @@ namespace Crow if (dse.NewDataSource == dse.OldDataSource) return; - - OnDataSourceChanged (this, dse); - - NotifyValueChanged ("DataSource", DataSource); + if (value != null) + rootDataLevel = true; + + lock (IFace.LayoutMutex) { + OnDataSourceChanged (this, dse); + NotifyValueChanged ("DataSource", DataSource); + } } get { - return dataSource == null ? + return rootDataLevel ? dataSource : dataSource == null ? LogicalParent == null ? null : LogicalParent is GraphicObject ? (LogicalParent as GraphicObject).DataSource : null : dataSource; } } + /// <summary> + /// If true, rendering of GraphicObject is clipped inside client rectangle + /// </summary> + [DesignCategory ("Data")][DefaultValue(false)] + public virtual bool RootDataLevel { + get { return rootDataLevel; } + set { + if (rootDataLevel == value) + return; + rootDataLevel = value; + NotifyValueChanged ("RootDataLevel", rootDataLevel); + this.RegisterForRedraw (); + } + } protected virtual void onLogicalParentDataSourceChanged(object sender, DataSourceChangeEventArgs e){ if (localDataSourceIsNull) OnDataSourceChanged (this, e); @@ -822,7 +982,7 @@ namespace Crow /// <summary> /// Style key to use for this control /// </summary> - [XmlAttributeAttribute] + [DesignCategory ("Appearance")] public virtual string Style { get { return style; } set { @@ -834,7 +994,7 @@ namespace Crow NotifyValueChanged ("Style", style); } } - [XmlAttributeAttribute] + [DesignCategory ("Divers")] public virtual string Tooltip { get { return tooltip; } set { @@ -844,7 +1004,7 @@ namespace Crow NotifyValueChanged("Tooltip", tooltip); } } - [XmlAttributeAttribute] + [DesignCategory ("Divers")] public IList<Command> ContextCommands { get { return contextCommands; } set { @@ -867,20 +1027,19 @@ namespace Crow Type thisType = this.GetType (); if (!string.IsNullOrEmpty (Style)) { - if (CurrentInterface.DefaultValuesLoader.ContainsKey (Style)) { - CurrentInterface.DefaultValuesLoader [Style] (this); + if (IFace.DefaultValuesLoader.ContainsKey (Style)) { + IFace.DefaultValuesLoader [Style] (this); + onInitialized (this, null); return; } - } else { - if (CurrentInterface.DefaultValuesLoader.ContainsKey (thisType.FullName)) { - CurrentInterface.DefaultValuesLoader [thisType.FullName] (this); - return; - } else if (!CurrentInterface.Styling.ContainsKey (thisType.FullName)) { - if (CurrentInterface.DefaultValuesLoader.ContainsKey (thisType.Name)) { - CurrentInterface.DefaultValuesLoader [thisType.Name] (this); - return; - } - } + } else if (IFace.DefaultValuesLoader.ContainsKey (thisType.FullName)) { + IFace.DefaultValuesLoader [thisType.FullName] (this); + onInitialized (this, null); + return; + } else if (IFace.DefaultValuesLoader.ContainsKey (thisType.Name)) { + IFace.DefaultValuesLoader [thisType.Name] (this); + onInitialized (this, null); + return; } List<Style> styling = new List<Style>(); @@ -892,17 +1051,17 @@ namespace Crow // those files being placed in a Styles folder string styleKey = Style; if (!string.IsNullOrEmpty (Style)) { - if (CurrentInterface.Styling.ContainsKey (Style)) { - styling.Add (CurrentInterface.Styling [Style]); + if (IFace.Styling.ContainsKey (Style)) { + styling.Add (IFace.Styling [Style]); } } - if (CurrentInterface.Styling.ContainsKey (thisType.FullName)) { - styling.Add (CurrentInterface.Styling [thisType.FullName]); + if (IFace.Styling.ContainsKey (thisType.FullName)) { + styling.Add (IFace.Styling [thisType.FullName]); if (string.IsNullOrEmpty (styleKey)) styleKey = thisType.FullName; } - if (CurrentInterface.Styling.ContainsKey (thisType.Name)) { - styling.Add (CurrentInterface.Styling [thisType.Name]); + if (IFace.Styling.ContainsKey (thisType.Name)) { + styling.Add (IFace.Styling [thisType.Name]); if (string.IsNullOrEmpty (styleKey)) styleKey = thisType.Name; } @@ -910,7 +1069,6 @@ namespace Crow if (string.IsNullOrEmpty (styleKey)) styleKey = thisType.FullName; - //Reflexion being very slow compared to dyn method or delegates, //I compile the initial values coded in the CustomAttribs of the class, //all other instance of this type would not longer use reflexion to init properly @@ -962,21 +1120,76 @@ namespace Crow foreach (PropertyInfo pi in thisType.GetProperties(BindingFlags.Public | BindingFlags.Instance)) { if (pi.GetSetMethod () == null) continue; - object defaultValue; - if (!getDefaultValue (pi, styling, out defaultValue)) + XmlIgnoreAttribute xia = (XmlIgnoreAttribute)pi.GetCustomAttribute (typeof(XmlIgnoreAttribute)); + if (xia != null) continue; + object defaultValue; + string name = ""; + XmlAttributeAttribute xaa = (XmlAttributeAttribute)pi.GetCustomAttribute (typeof(XmlAttributeAttribute)); + if (xaa != null) { + if (string.IsNullOrEmpty (xaa.AttributeName)) + name = pi.Name; + else + name = xaa.AttributeName; + }else + name = pi.Name; + + int styleIndex = -1; + if (styling.Count > 0){ + for (int i = 0; i < styling.Count; i++) { + if (styling[i].ContainsKey (name)){ + styleIndex = i; + break; + } + } + } + if (styleIndex >= 0){ + if (pi.PropertyType.IsEnum)//maybe should be in parser.. + defaultValue = Enum.Parse(pi.PropertyType, (string)styling[styleIndex] [name], true); + else + defaultValue = styling[styleIndex] [name]; + + #if DESIGN_MODE + if (defaultValue != null){ + FileLocation fl = styling[styleIndex].Locations[name]; + il.Emit (OpCodes.Ldloc_0); + il.Emit (OpCodes.Ldstr, name); + il.Emit (OpCodes.Ldstr, fl.FilePath); + il.Emit (OpCodes.Ldc_I4, fl.Line); + il.Emit (OpCodes.Ldc_I4, fl.Column); + il.Emit (OpCodes.Call, miDesignAddDefLoc); + + il.Emit (OpCodes.Ldloc_0); + il.Emit (OpCodes.Ldfld, typeof(GraphicObject).GetField("design_style_values")); + il.Emit (OpCodes.Ldstr, name); + il.Emit (OpCodes.Ldstr, defaultValue.ToString()); + il.Emit (OpCodes.Call, CompilerServices.miDicStrStrAdd); + } + #endif + + }else { + DefaultValueAttribute dv = (DefaultValueAttribute)pi.GetCustomAttribute (typeof (DefaultValueAttribute)); + if (dv == null) + continue; + defaultValue = dv.Value; + } + CompilerServices.EmitSetValue (il, pi, defaultValue); } il.Emit(OpCodes.Ret); #endregion try { - CurrentInterface.DefaultValuesLoader[styleKey] = (Interface.LoaderInvoker)dm.CreateDelegate(typeof(Interface.LoaderInvoker)); - CurrentInterface.DefaultValuesLoader[styleKey] (this); + IFace.DefaultValuesLoader[styleKey] = (Interface.LoaderInvoker)dm.CreateDelegate(typeof(Interface.LoaderInvoker)); + IFace.DefaultValuesLoader[styleKey] (this); } catch (Exception ex) { throw new Exception ("Error applying style <" + styleKey + ">:", ex); } + onInitialized (this, null); + } + protected virtual void onInitialized (object sender, EventArgs e){ + Initialized.Raise(sender, e); } bool getDefaultEvent(EventInfo ei, List<Style> styling, out string expression){ @@ -991,51 +1204,6 @@ namespace Crow } return false; } - /// <summary> - /// Gets the default value of the widget's property from either the style, or from xml default - /// </summary> - /// <returns><c>true</c>, if default value is defined, <c>false</c> otherwise.</returns> - /// <param name="pi">PropertyInfo</param> - /// <param name="styling">Styling informations</param> - /// <param name="defaultValue">output of Default value, null if not found</param> - bool getDefaultValue(PropertyInfo pi, List<Style> styling, - out object defaultValue){ - defaultValue = null; - string name = ""; - - XmlIgnoreAttribute xia = (XmlIgnoreAttribute)pi.GetCustomAttribute (typeof(XmlIgnoreAttribute)); - if (xia != null) - return false; - XmlAttributeAttribute xaa = (XmlAttributeAttribute)pi.GetCustomAttribute (typeof(XmlAttributeAttribute)); - if (xaa != null) { - if (string.IsNullOrEmpty (xaa.AttributeName)) - name = pi.Name; - else - name = xaa.AttributeName; - } - - int styleIndex = -1; - if (styling.Count > 0){ - for (int i = 0; i < styling.Count; i++) { - if (styling[i].ContainsKey (name)){ - styleIndex = i; - break; - } - } - } - if (styleIndex >= 0){ - if (pi.PropertyType.IsEnum)//maybe should be in parser.. - defaultValue = Enum.Parse(pi.PropertyType, (string)styling[styleIndex] [name], true); - else - defaultValue = styling[styleIndex] [name]; - }else { - DefaultValueAttribute dv = (DefaultValueAttribute)pi.GetCustomAttribute (typeof (DefaultValueAttribute)); - if (dv == null) - return false; - defaultValue = dv.Value; - } - return true; - } #endregion public virtual GraphicObject FindByName(string nameToFind){ @@ -1060,7 +1228,7 @@ namespace Crow } #region Drag&Drop - [XmlAttributeAttribute][DefaultValue(false)] + [DesignCategory ("DragAndDrop")][DefaultValue(false)] public virtual bool AllowDrag { get { return allowDrag; } set { @@ -1070,7 +1238,7 @@ namespace Crow NotifyValueChanged ("AllowDrag", allowDrag); } } - [XmlAttributeAttribute][DefaultValue(false)] + [DesignCategory ("DragAndDrop")][DefaultValue(false)] public virtual bool AllowDrop { get { return allowDrop; } set { @@ -1105,10 +1273,12 @@ namespace Crow /// fired when drag and drop operation start /// </summary> protected virtual void onStartDrag (object sender, DragDropEventArgs e){ - CurrentInterface.HoverWidget = null; + IFace.HoverWidget = null; IsDragged = true; StartDrag.Raise (this, e); + #if DEBUG_DRAGNDROP Debug.WriteLine(this.ToString() + " : START DRAG => " + e.ToString()); + #endif } /// <summary> /// Occured when dragging ends without dropping @@ -1116,22 +1286,34 @@ namespace Crow protected virtual void onEndDrag (object sender, DragDropEventArgs e){ IsDragged = false; EndDrag.Raise (this, e); + #if DEBUG_DRAGNDROP Debug.WriteLine(this.ToString() + " : END DRAG => " + e.ToString()); + #endif } protected virtual void onDragEnter (object sender, DragDropEventArgs e){ e.DropTarget = this; DragEnter.Raise (this, e); + #if DEBUG_DRAGNDROP Debug.WriteLine(this.ToString() + " : DRAG Enter => " + e.ToString()); + #endif } protected virtual void onDragLeave (object sender, DragDropEventArgs e){ e.DropTarget = null; DragLeave.Raise (this, e); + #if DEBUG_DRAGNDROP Debug.WriteLine(this.ToString() + " : DRAG Leave => " + e.ToString()); + #endif } protected virtual void onDrop (object sender, DragDropEventArgs e){ IsDragged = false; Drop.Raise (this, e); + //e.DropTarget.onDragLeave (this, e);//raise drag leave in target + #if DEBUG_DRAGNDROP Debug.WriteLine(this.ToString() + " : DROP => " + e.ToString()); + #endif + } + public bool IsDropTarget { + get { return IFace.DragAndDropOperation?.DropTarget == this; } } #endregion @@ -1180,7 +1362,7 @@ namespace Crow if (Width.IsFit || Height.IsFit) RegisterForLayouting (LayoutingType.Sizing); else if (RegisteredLayoutings == LayoutingType.None) - CurrentInterface.EnqueueForRepaint (this); + IFace.EnqueueForRepaint (this); } /// <summary> query an update of the content, a redraw </summary> [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -1191,7 +1373,7 @@ namespace Crow #endif IsDirty = true; if (RegisteredLayoutings == LayoutingType.None) - CurrentInterface.EnqueueForRepaint (this); + IFace.EnqueueForRepaint (this); } #endregion @@ -1209,7 +1391,7 @@ namespace Crow public virtual void RegisterForLayouting(LayoutingType layoutType){ if (Parent == null) return; - lock (CurrentInterface.LayoutMutex) { + lock (IFace.LayoutMutex) { //prevent queueing same LayoutingType for this layoutType &= (~RegisteredLayoutings); @@ -1236,27 +1418,21 @@ namespace Crow //enqueue LQI LayoutingTypes separately if (layoutType.HasFlag (LayoutingType.Width)) - CurrentInterface.LayoutingQueue.Enqueue (new LayoutingQueueItem (LayoutingType.Width, this)); + IFace.LayoutingQueue.Enqueue (new LayoutingQueueItem (LayoutingType.Width, this)); if (layoutType.HasFlag (LayoutingType.Height)) - CurrentInterface.LayoutingQueue.Enqueue (new LayoutingQueueItem (LayoutingType.Height, this)); + IFace.LayoutingQueue.Enqueue (new LayoutingQueueItem (LayoutingType.Height, this)); if (layoutType.HasFlag (LayoutingType.X)) - CurrentInterface.LayoutingQueue.Enqueue (new LayoutingQueueItem (LayoutingType.X, this)); + IFace.LayoutingQueue.Enqueue (new LayoutingQueueItem (LayoutingType.X, this)); if (layoutType.HasFlag (LayoutingType.Y)) - CurrentInterface.LayoutingQueue.Enqueue (new LayoutingQueueItem (LayoutingType.Y, this)); + IFace.LayoutingQueue.Enqueue (new LayoutingQueueItem (LayoutingType.Y, this)); if (layoutType.HasFlag (LayoutingType.ArrangeChildren)) - CurrentInterface.LayoutingQueue.Enqueue (new LayoutingQueueItem (LayoutingType.ArrangeChildren, this)); + IFace.LayoutingQueue.Enqueue (new LayoutingQueueItem (LayoutingType.ArrangeChildren, this)); } } /// <summary> trigger dependant sizing component update </summary> public virtual void OnLayoutChanges(LayoutingType layoutType) { - #if DEBUG_LAYOUTING - CurrentInterface.currentLQI.Slot = LastSlots; - CurrentInterface.currentLQI.NewSlot = Slot; - Debug.WriteLine ("\t\t{0} => {1}",LastSlots,Slot); - #endif - switch (layoutType) { case LayoutingType.Width: RegisterForLayouting (LayoutingType.X); @@ -1420,7 +1596,7 @@ namespace Crow //if no layouting remains in queue for item, registre for redraw if (this.registeredLayoutings == LayoutingType.None && IsDirty) - CurrentInterface.EnqueueForRepaint (this); + IFace.EnqueueForRepaint (this); return true; } @@ -1557,8 +1733,8 @@ namespace Crow } public virtual void checkHoverWidget(MouseMoveEventArgs e) { - if (CurrentInterface.HoverWidget != this) { - CurrentInterface.HoverWidget = this; + if (IFace.HoverWidget != this) { + IFace.HoverWidget = this; onMouseEnter (this, e); } @@ -1567,12 +1743,17 @@ namespace Crow public virtual void onMouseMove(object sender, MouseMoveEventArgs e) { if (AllowDrag & HasFocus & e.Mouse.LeftButton == ButtonState.Pressed) { - if (CurrentInterface.DragAndDropOperation == null) { - CurrentInterface.DragAndDropOperation = new DragDropEventArgs (this); - onStartDrag (this, CurrentInterface.DragAndDropOperation); + if (IFace.DragAndDropOperation == null) { + IFace.DragAndDropOperation = new DragDropEventArgs (this); + onStartDrag (this, IFace.DragAndDropOperation); } } + //dont bubble event if dragged, mouse move is routed directely from iface + //to let other control behind have mouse entering + if (isDragged) + return; + //bubble event to the top GraphicObject p = focusParent; if (p != null) @@ -1585,15 +1766,15 @@ namespace Crow Debug.WriteLine("MOUSE DOWN => " + this.ToString()); #endif - if (CurrentInterface.ActiveWidget == null) - CurrentInterface.ActiveWidget = this; + if (IFace.ActiveWidget == null) + IFace.ActiveWidget = this; if (this.Focusable && !Interface.FocusOnHover) { BubblingMouseButtonEventArg be = e as BubblingMouseButtonEventArg; if (be.Focused == null) { be.Focused = this; - CurrentInterface.FocusedWidget = this; + IFace.FocusedWidget = this; if (e.Button == MouseButton.Right && this.ContextCommands != null) - CurrentInterface.ShowContextMenu (this); + IFace.ShowContextMenu (this); } } //bubble event to the top @@ -1608,13 +1789,13 @@ namespace Crow Debug.WriteLine("MOUSE UP => " + this.ToString()); #endif - if (CurrentInterface.DragAndDropOperation != null){ - if (CurrentInterface.DragAndDropOperation.DragSource == this) { - if (CurrentInterface.DragAndDropOperation.DropTarget != null) - onDrop (this, CurrentInterface.DragAndDropOperation); + if (IFace.DragAndDropOperation != null){ + if (IFace.DragAndDropOperation.DragSource == this) { + if (IFace.DragAndDropOperation.DropTarget != null) + onDrop (this, IFace.DragAndDropOperation); else - onEndDrag (this, CurrentInterface.DragAndDropOperation); - CurrentInterface.DragAndDropOperation = null; + onEndDrag (this, IFace.DragAndDropOperation); + IFace.DragAndDropOperation = null; } } @@ -1655,14 +1836,6 @@ namespace Crow #if DEBUG_FOCUS Debug.WriteLine("MouseEnter => " + this.ToString()); #endif - - if (CurrentInterface.DragAndDropOperation != null) { - if (this.AllowDrop) { - if (CurrentInterface.DragAndDropOperation.DragSource != this && CurrentInterface.DragAndDropOperation.DropTarget != this) - onDragEnter (this, CurrentInterface.DragAndDropOperation); - } - } - MouseEnter.Raise (this, e); } public virtual void onMouseLeave(object sender, MouseMoveEventArgs e) @@ -1670,12 +1843,36 @@ namespace Crow #if DEBUG_FOCUS Debug.WriteLine("MouseLeave => " + this.ToString()); #endif - if (CurrentInterface.DragAndDropOperation != null) { - if (CurrentInterface.DragAndDropOperation.DropTarget == this) - onDragLeave (this, CurrentInterface.DragAndDropOperation); - } MouseLeave.Raise (this, e); } + public virtual void onHover(object sender, EventArgs e) + { + #if DEBUG_FOCUS + Debug.WriteLine("MouseHover => " + this.ToString()); + #endif + if (IFace.DragAndDropOperation != null) { + GraphicObject g = this; + while (g != null) { + if (g.AllowDrop) { + if (IFace.DragAndDropOperation.DragSource != this && IFace.DragAndDropOperation.DropTarget != this) { + if (IFace.DragAndDropOperation.DropTarget != null) + IFace.DragAndDropOperation.DropTarget.onDragLeave (this, IFace.DragAndDropOperation); + g.onDragEnter (this, IFace.DragAndDropOperation); + } + break; + } + g = g.focusParent; + } + } + Hover.Raise (this, e); + } + public virtual void onUnHover(object sender, EventArgs e) + { + #if DEBUG_FOCUS + Debug.WriteLine("MouseUnHover => " + this.ToString()); + #endif + UnHover.Raise (this, e); + } #endregion protected virtual void onFocused(object sender, EventArgs e){ @@ -1697,6 +1894,13 @@ namespace Crow Disabled.Raise (this, e); } protected virtual void onParentChanged(object sender, DataSourceChangeEventArgs e) { +// if (e.NewDataSource != null) { +// if (width == Measure.Inherit) +// RegisterForLayouting (LayoutingType.Width); +// if (height == Measure.Inherit) +// RegisterForLayouting (LayoutingType.Height); +// } + ParentChanged.Raise (this, e); if (logicalParent == null) LogicalParentChanged.Raise (this, e); @@ -1732,5 +1936,24 @@ namespace Crow return Name == "unamed" ? tmp + "." + this.GetType ().Name : tmp + "." + Name; #endif } + /// <summary> + /// Checks to handle when widget is removed from the visible graphic tree + /// </summary> + void unshownPostActions () { + if (IFace.ActiveWidget != null) { + if (IFace.ActiveWidget.IsOrIsInside (this)) + IFace.ActiveWidget = null; + } + if (IFace.FocusedWidget != null) { + if (IFace.FocusedWidget.IsOrIsInside (this)) + IFace.FocusedWidget = null; + } + if (IFace.HoverWidget != null) { + if (IFace.HoverWidget.IsOrIsInside (this)) { + IFace.HoverWidget = null; + IFace.ProcessMouseMove (IFace.Mouse.X, IFace.Mouse.Y); + } + } + } } } diff --git a/src/GraphicObjects/Grid.cs b/src/GraphicObjects/Grid.cs index f8a50264..4ae906a7 100644 --- a/src/GraphicObjects/Grid.cs +++ b/src/GraphicObjects/Grid.cs @@ -157,7 +157,7 @@ namespace Crow //if no layouting remains in queue for item, registre for redraw if (RegisteredLayoutings == LayoutingType.None && IsDirty) - CurrentInterface.EnqueueForRepaint (this); + IFace.EnqueueForRepaint (this); return true; } diff --git a/src/GraphicObjects/Group.cs b/src/GraphicObjects/Group.cs index e7604842..a90947a5 100644 --- a/src/GraphicObjects/Group.cs +++ b/src/GraphicObjects/Group.cs @@ -38,7 +38,33 @@ namespace Crow { public class Group : GraphicObject { - protected ReaderWriterLockSlim childrenRWLock = new ReaderWriterLockSlim(); + #if DESIGN_MODE + public override bool FindByDesignID(string designID, out GraphicObject go){ + go = null; + if (base.FindByDesignID (designID, out go)) + return true; + childrenRWLock.EnterReadLock (); + foreach (GraphicObject w in Children) { + if (!w.FindByDesignID (designID, out go)) + continue; + childrenRWLock.ExitReadLock (); + return true; + } + childrenRWLock.ExitReadLock (); + return false; + } + public override void getIML (System.Xml.XmlDocument doc, System.Xml.XmlNode parentElem) + { + if (this.design_isTGItem) + return; + base.getIML (doc, parentElem); + foreach (GraphicObject g in Children) { + g.getIML (doc, parentElem.LastChild); + } + } + #endif + + protected ReaderWriterLockSlim childrenRWLock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion); #region CTOR public Group () : base() {} @@ -80,14 +106,15 @@ namespace Crow { child.LayoutChanged -= OnChildLayoutChanges; //check if HoverWidget is removed from Tree - if (CurrentInterface.HoverWidget != null) { - if (this.Contains (CurrentInterface.HoverWidget)) - CurrentInterface.HoverWidget = null; + if (IFace.HoverWidget != null) { + if (this.Contains (IFace.HoverWidget)) + IFace.HoverWidget = null; } childrenRWLock.EnterWriteLock (); Children.Remove(child); + child.Parent = null; childrenRWLock.ExitWriteLock (); @@ -116,6 +143,9 @@ namespace Crow g.LayoutChanged += OnChildLayoutChanges; g.RegisterForLayouting (LayoutingType.Sizing | LayoutingType.ArrangeChildren); } + public virtual void RemoveChild (int idx) { + RemoveChild (children[idx]); + } public virtual void DeleteChild (int idx) { DeleteChild (children[idx]); } @@ -137,6 +167,17 @@ namespace Crow this.RegisterForLayouting (LayoutingType.Sizing); ChildrenCleared.Raise (this, new EventArgs ()); } + public override void OnDataSourceChanged (object sender, DataSourceChangeEventArgs e) + { + base.OnDataSourceChanged (this, e); + + childrenRWLock.EnterReadLock (); + foreach (GraphicObject g in Children) { + if (g.localDataSourceIsNull & g.localLogicalParentIsNull) + g.OnDataSourceChanged (g, e); + } + childrenRWLock.ExitReadLock (); + } public void putWidgetOnTop(GraphicObject w) { @@ -164,18 +205,7 @@ namespace Crow } #region GraphicObject overrides - public override void OnDataSourceChanged (object sender, DataSourceChangeEventArgs e) - { - base.OnDataSourceChanged (this, e); - - childrenRWLock.EnterReadLock (); - foreach (GraphicObject g in children) - if (g.localDataSourceIsNull & g.localLogicalParentIsNull) - g.OnDataSourceChanged (g, e); - - childrenRWLock.ExitReadLock (); - } public override GraphicObject FindByName (string nameToFind) { if (Name == nameToFind) @@ -237,7 +267,7 @@ namespace Crow switch (layoutType) { case LayoutingType.Width: foreach (GraphicObject c in Children) { - if (c.Width.Units == Unit.Percent) + if (c.Width.IsRelativeToParent) c.RegisterForLayouting (LayoutingType.Width); else c.RegisterForLayouting (LayoutingType.X); @@ -245,7 +275,7 @@ namespace Crow break; case LayoutingType.Height: foreach (GraphicObject c in Children) { - if (c.Height.Units == Unit.Percent) + if (c.Height.IsRelativeToParent) c.RegisterForLayouting (LayoutingType.Height); else c.RegisterForLayouting (LayoutingType.Y); @@ -268,9 +298,9 @@ namespace Crow childrenRWLock.EnterReadLock (); - foreach (GraphicObject g in Children) { - g.Paint (ref gr); - } + foreach (GraphicObject g in Children) { + g.Paint (ref gr); + } childrenRWLock.ExitReadLock (); gr.Restore (); @@ -397,8 +427,8 @@ namespace Crow #region Mouse handling public override void checkHoverWidget (MouseMoveEventArgs e) { - if (CurrentInterface.HoverWidget != this) { - CurrentInterface.HoverWidget = this; + if (IFace.HoverWidget != this) { + IFace.HoverWidget = this; onMouseEnter (this, e); } for (int i = Children.Count - 1; i >= 0; i--) { diff --git a/src/GraphicObjects/HueSelector.cs b/src/GraphicObjects/HueSelector.cs index 518ee6c4..67f4ec6e 100644 --- a/src/GraphicObjects/HueSelector.cs +++ b/src/GraphicObjects/HueSelector.cs @@ -31,6 +31,7 @@ using Cairo; namespace Crow { + [DesignIgnore] public class HueSelector : ColorSelector { #region CTOR diff --git a/src/GraphicObjects/IMLContainer.cs b/src/GraphicObjects/IMLContainer.cs index a221a78b..84692284 100644 --- a/src/GraphicObjects/IMLContainer.cs +++ b/src/GraphicObjects/IMLContainer.cs @@ -41,7 +41,7 @@ namespace Crow if (path == value) return; path = value; - this.SetChild (CurrentInterface.Load (path)); + this.SetChild (IFace.Load (path)); NotifyValueChanged ("Path", path); } } diff --git a/src/GraphicObjects/Image.cs b/src/GraphicObjects/Image.cs index 75c59f4a..e83183c0 100644 --- a/src/GraphicObjects/Image.cs +++ b/src/GraphicObjects/Image.cs @@ -93,9 +93,9 @@ namespace Crow if (string.IsNullOrEmpty(value)) Picture = null; else { - lock(CurrentInterface.LayoutMutex){ + //lock(IFace.LayoutMutex){ LoadImage (value); - } + //} } } catch (Exception ex) { Debug.WriteLine (ex.Message); @@ -169,11 +169,11 @@ namespace Crow { Picture pic; if (path.EndsWith (".svg", true, System.Globalization.CultureInfo.InvariantCulture)) - pic = new SvgPicture (); + pic = new SvgPicture (path); else - pic = new BmpPicture (); + pic = new BmpPicture (path); - pic.Load (path); + pic.Load (IFace, path); pic.Scaled = scaled; pic.KeepProportions = keepProps; diff --git a/src/GraphicObjects/Label.cs b/src/GraphicObjects/Label.cs index ea68fde0..0e0d9fe1 100644 --- a/src/GraphicObjects/Label.cs +++ b/src/GraphicObjects/Label.cs @@ -55,6 +55,7 @@ namespace Crow public virtual void OnTextChanged(Object sender, TextChangeEventArgs e) { + textMeasureIsUpToDate = false; NotifyValueChanged ("Text", Text); TextChanged.Raise (this, e); } @@ -86,7 +87,7 @@ namespace Crow protected TextExtents te; #endregion - [XmlAttributeAttribute][DefaultValue("BlueGray")] + [XmlAttributeAttribute][DefaultValue("SteelBlue")] public virtual Color SelectionBackground { get { return selBackground; } set { @@ -437,48 +438,49 @@ namespace Crow CurrentColumn = 0; OnTextChanged (this, new TextChangeEventArgs (Text)); } + bool textMeasureIsUpToDate = false; + Size cachedTextSize = default(Size); #region GraphicObject overrides protected override int measureRawSize(LayoutingType lt) - { + { if (lines == null) lines = getLines; + if (!textMeasureIsUpToDate) { + using (ImageSurface img = new ImageSurface (Format.Argb32, 10, 10)) { + using (Context gr = new Context (img)) { + //Cairo.FontFace cf = gr.GetContextFontFace (); - using (ImageSurface img = new ImageSurface (Format.Argb32, 10, 10)) { - using (Context gr = new Context (img)) { - //Cairo.FontFace cf = gr.GetContextFontFace (); - - gr.SelectFontFace (Font.Name, Font.Slant, Font.Wheight); - gr.SetFontSize (Font.Size); + gr.SelectFontFace (Font.Name, Font.Slant, Font.Wheight); + gr.SetFontSize (Font.Size); + gr.FontOptions = Interface.FontRenderingOptions; + gr.Antialias = Interface.Antialias; + fe = gr.FontExtents; + te = new TextExtents (); - fe = gr.FontExtents; - te = new TextExtents(); + cachedTextSize.Height = (int)Math.Ceiling ((fe.Ascent+fe.Descent) * Math.Max (1, lines.Count)) + Margin * 2; - if (lt == LayoutingType.Height){ - int lc = lines.Count; - //ensure minimal height = text line height - if (lc == 0) - lc = 1; - - return (int)Math.Ceiling(fe.Height * lc) + Margin * 2; - } - try { - foreach (string s in lines) { - string l = s.Replace("\t", new String (' ', Interface.TabSize)); + try { + foreach (string s in lines) { + string l = s.Replace ("\t", new String (' ', Interface.TabSize)); - TextExtents tmp = gr.TextExtents (l); + TextExtents tmp = gr.TextExtents (l); - if (tmp.XAdvance > te.XAdvance) - te = tmp; - } - } catch (Exception ex) { - return -1; + if (tmp.XAdvance > te.XAdvance) + te = tmp; + } + cachedTextSize.Width = (int)Math.Ceiling (te.XAdvance) + Margin * 2; + textMeasureIsUpToDate = true; + } catch { + return -1; + } } - return (int)Math.Ceiling (te.XAdvance) + Margin * 2; } + } - } + return lt == LayoutingType.Height ? cachedTextSize.Height : cachedTextSize.Width; + } protected override void onDraw (Context gr) { base.onDraw (gr); @@ -552,11 +554,12 @@ namespace Crow break; case Alignment.Center://ok rText.X = cb.X + cb.Width / 2 - rText.Width / 2; - rText.Y = cb.Y + cb.Height / 2 - rText.Height / 2; + //rText.Y = cb.Y + cb.Height / 2 - rText.Height / 2; + rText.Y = cb.Y + (int)Math.Floor((double)cb.Height / 2.0 - (double)rText.Height / 2.0); break; } - gr.FontMatrix = new Matrix(widthRatio * (float)Font.Size, 0, 0, heightRatio * (float)Font.Size, 0, 0); + //gr.FontMatrix = new Matrix(widthRatio * (float)Font.Size, 0, 0, heightRatio * (float)Font.Size, 0, 0); fe = gr.FontExtents; #region draw text cursor @@ -586,8 +589,8 @@ namespace Crow Foreground.SetAsSource (gr); gr.LineWidth = 1.0; - gr.MoveTo (0.5 + textCursorPos + rText.X, rText.Y + CurrentLine * fe.Height); - gr.LineTo (0.5 + textCursorPos + rText.X, rText.Y + (CurrentLine + 1) * fe.Height); + gr.MoveTo (0.5 + textCursorPos + rText.X, rText.Y + CurrentLine * (fe.Ascent+fe.Descent)); + gr.LineTo (0.5 + textCursorPos + rText.X, rText.Y + (CurrentLine + 1) * (fe.Ascent+fe.Descent)); gr.Stroke(); } #endregion @@ -597,9 +600,9 @@ namespace Crow // new SolidColor(Color.DarkGreen).SetAsSource(gr); // Rectangle R = new Rectangle ( // rText.X + (int)SelEndCursorPos - 3, -// rText.Y + (int)(SelRelease.Y * fe.Height), +// rText.Y + (int)(SelRelease.Y * (fe.Ascent+fe.Descent)), // 6, -// (int)fe.Height); +// (int)(fe.Ascent+fe.Descent)); // gr.Rectangle (R); // gr.Fill (); // } @@ -607,9 +610,9 @@ namespace Crow // new SolidColor(Color.DarkRed).SetAsSource(gr); // Rectangle R = new Rectangle ( // rText.X + (int)SelStartCursorPos - 3, -// rText.Y + (int)(SelBegin.Y * fe.Height), +// rText.Y + (int)(SelBegin.Y * (fe.Ascent+fe.Descent)), // 6, -// (int)fe.Height); +// (int)(fe.Ascent+fe.Descent)); // gr.Rectangle (R); // gr.Fill (); // } @@ -620,9 +623,9 @@ namespace Crow int lineLength = (int)gr.TextExtents (l).XAdvance; Rectangle lineRect = new Rectangle ( rText.X, - rText.Y + (int)Math.Ceiling(i * fe.Height), + rText.Y + i * (int)(fe.Ascent+fe.Descent), lineLength, - (int)Math.Ceiling(fe.Height)); + (int)(fe.Ascent+fe.Descent)); // if (TextAlignment == Alignment.Center || // TextAlignment == Alignment.Top || @@ -636,7 +639,7 @@ namespace Crow continue; Foreground.SetAsSource (gr); - gr.MoveTo (lineRect.X, rText.Y + fe.Ascent + fe.Height * i); + gr.MoveTo (lineRect.X,(double)rText.Y + fe.Ascent + (fe.Ascent+fe.Descent) * i) ; gr.ShowText (l); gr.Fill (); @@ -666,7 +669,7 @@ namespace Crow gr.Save (); gr.Clip (); gr.SetSourceColor (SelectionForeground); - gr.MoveTo (lineRect.X, rText.Y + fe.Ascent + fe.Height * i); + gr.MoveTo (lineRect.X, rText.Y + fe.Ascent + (fe.Ascent+fe.Descent) * i); gr.ShowText (l); gr.Fill (); gr.Restore (); @@ -688,12 +691,12 @@ namespace Crow { base.onMouseEnter (sender, e); if (Selectable) - CurrentInterface.MouseCursor = XCursor.Text; + IFace.MouseCursor = XCursor.Text; } public override void onMouseLeave (object sender, MouseMoveEventArgs e) { base.onMouseLeave (sender, e); - CurrentInterface.MouseCursor = XCursor.Default; + IFace.MouseCursor = XCursor.Default; } protected override void onFocused (object sender, EventArgs e) { @@ -774,7 +777,7 @@ namespace Crow double cPos = 0f; - CurrentLine = (int)(mouseLocalPos.Y / fe.Height); + CurrentLine = (int)(mouseLocalPos.Y / (fe.Ascent+fe.Descent)); //fix cu if (CurrentLine >= lines.Count) diff --git a/src/GraphicObjects/MDIContainer.cs b/src/GraphicObjects/MDIContainer.cs deleted file mode 100644 index d8ce4647..00000000 --- a/src/GraphicObjects/MDIContainer.cs +++ /dev/null @@ -1,40 +0,0 @@ -// -// MDIContainer.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; - -namespace Crow -{ - public class MDIContainer : Group - { - #region CTOR - public MDIContainer () : base() - { - } - #endregion - - } -} - diff --git a/src/GraphicObjects/MessageBox.cs b/src/GraphicObjects/MessageBox.cs index c0754eaa..45ef1e00 100644 --- a/src/GraphicObjects/MessageBox.cs +++ b/src/GraphicObjects/MessageBox.cs @@ -38,10 +38,13 @@ namespace Crow #endregion public enum Type { + None, Information, - YesNo, Alert, - Error + Error, + YesNo, + YesNoCancel, + } protected override void loadTemplate (GraphicObject template) @@ -49,13 +52,14 @@ namespace Crow base.loadTemplate (template); NotifyValueChanged ("MsgIcon", "#Crow.Images.Icons.Informations.svg"); } - string message, okMessage, cancelMessage; - Type msgType = Type.Information; + string message, okMessage, cancelMessage, noMessage; + Type msgType = Type.None; - public event EventHandler Ok; + public event EventHandler Yes; + public event EventHandler No; public event EventHandler Cancel; - [XmlAttributeAttribute][DefaultValue("Informations")] + [DefaultValue("Informations")] public virtual string Message { get { return message; } @@ -66,7 +70,7 @@ namespace Crow NotifyValueChanged ("Message", message); } } - [XmlAttributeAttribute][DefaultValue("Ok")] + [DefaultValue("Ok")] public virtual string OkMessage { get { return okMessage; } @@ -77,7 +81,7 @@ namespace Crow NotifyValueChanged ("OkMessage", okMessage); } } - [XmlAttributeAttribute][DefaultValue("Cancel")] + [DefaultValue("Cancel")] public virtual string CancelMessage { get { return cancelMessage; } @@ -88,7 +92,18 @@ namespace Crow NotifyValueChanged ("CancelMessage", cancelMessage); } } - [XmlAttributeAttribute][DefaultValue("Information")] + [DefaultValue("No")] + public virtual string NoMessage + { + get { return cancelMessage; } + set { + if (cancelMessage == value) + return; + cancelMessage = value; + NotifyValueChanged ("NoMessage", cancelMessage); + } + } + [DefaultValue("Information")] public virtual Type MsgType { get { return msgType; } @@ -99,34 +114,58 @@ namespace Crow NotifyValueChanged ("MsgType", msgType); switch (msgType) { case Type.Information: - NotifyValueChanged ("MsgIcon", "#Crow.Images.Icons.Informations.svg"); + MsgIcon = "#Crow.Images.Icons.Informations.svg"; Caption = "Informations"; OkMessage = "Ok"; - CancelMessage = "Cancel"; + NotifyValueChanged ("CancelButIsVisible", false); + NotifyValueChanged ("NoButIsVisible", false); break; case Type.YesNo: - NotifyValueChanged ("MsgIcon", "#Crow.Icons.question.svg"); + case Type.YesNoCancel: + MsgIcon = "#Crow.Icons.question.svg"; Caption = "Choice"; OkMessage = "Yes"; - CancelMessage = "No"; + NoMessage = "No"; + NotifyValueChanged ("CancelButIsVisible", msgType == Type.YesNoCancel); + NotifyValueChanged ("NoButIsVisible", true); break; case Type.Alert: - NotifyValueChanged ("MsgIcon", "#Crow.Images.Icons.IconAlerte.svg"); + MsgIcon = "#Crow.Images.Icons.IconAlerte.svg"; Caption = "Alert"; OkMessage = "Ok"; CancelMessage = "Cancel"; + NotifyValueChanged ("CancelButIsVisible", true); + NotifyValueChanged ("NoButIsVisible", false); break; case Type.Error: - NotifyValueChanged ("MsgIcon", "#Crow.Images.Icons.exit.svg"); + MsgIcon = "#Crow.Images.Icons.exit.svg"; Caption = "Error"; OkMessage = "Ok"; + NotifyValueChanged ("CancelButIsVisible", false); + NotifyValueChanged ("NoButIsVisible", false); break; } } } + + string msgIcon = null; + public string MsgIcon { + get { return msgIcon; } + set { + if (value == MsgIcon) + return; + msgIcon = value; + NotifyValueChanged ("MsgIcon", MsgIcon); + } + } void onOkButtonClick (object sender, EventArgs e) { - Ok.Raise (this, null); + Yes.Raise (this, null); + close (); + } + void onNoButtonClick (object sender, EventArgs e) + { + No.Raise (this, null); close (); } void onCancelButtonClick (object sender, EventArgs e) @@ -137,7 +176,7 @@ namespace Crow public static MessageBox Show (Interface iface, Type msgBoxType, string message, string okMsg = "", string cancelMsg = ""){ lock (iface.UpdateMutex) { MessageBox mb = new MessageBox (iface); - mb.CurrentInterface.AddWidget (mb); + mb.IFace.AddWidget (mb); mb.MsgType = msgBoxType; mb.Message = message; if (!string.IsNullOrEmpty(okMsg)) @@ -147,6 +186,18 @@ namespace Crow return mb; } } + public static MessageBox ShowModal (Interface iface, Type msgBoxType, string message){ + lock (iface.UpdateMutex) { + MessageBox mb = new MessageBox (iface) { + Modal = true, + MsgType = msgBoxType, + Message = message + }; + + iface.AddWidget (mb); + return mb; + } + } } } diff --git a/src/GraphicObjects/Popper.cs b/src/GraphicObjects/Popper.cs index 70804bda..1186e8e7 100644 --- a/src/GraphicObjects/Popper.cs +++ b/src/GraphicObjects/Popper.cs @@ -201,8 +201,8 @@ namespace Crow } public override void checkHoverWidget (MouseMoveEventArgs e) { - if (CurrentInterface.HoverWidget != this) { - CurrentInterface.HoverWidget = this; + if (IFace.HoverWidget != this) { + IFace.HoverWidget = this; onMouseEnter (this, e); } if (Content != null){ @@ -222,10 +222,10 @@ namespace Crow if (Content != null) { Content.Visible = true; if (Content.Parent == null) - CurrentInterface.AddWidget (Content); + IFace.AddWidget (Content); if (Content.LogicalParent != this) Content.LogicalParent = this; - CurrentInterface.PutOnTop (Content, true); + IFace.PutOnTop (Content, true); _content_LayoutChanged (this, new LayoutingEventArgs (LayoutingType.Sizing)); } Popped.Raise (this, e); diff --git a/src/GraphicObjects/PrivateContainer.cs b/src/GraphicObjects/PrivateContainer.cs index 8383a274..d6637247 100644 --- a/src/GraphicObjects/PrivateContainer.cs +++ b/src/GraphicObjects/PrivateContainer.cs @@ -38,6 +38,7 @@ namespace Crow /// TemplatedControl may have 3 children (template,templateItem,content) but /// behave exactely as a container for layouting and drawing /// </summary> + [DesignIgnore] public class PrivateContainer : GraphicObject { #region CTOR @@ -45,6 +46,14 @@ namespace Crow public PrivateContainer (Interface iface) : base(iface){} #endregion + #if DESIGN_MODE + public override bool FindByDesignID(string designID, out GraphicObject go){ + go = null; + if (base.FindByDesignID (designID, out go)) + return true; + return (bool)child?.FindByDesignID (designID, out go); + } + #endif protected GraphicObject child; protected virtual void SetChild(GraphicObject _child) @@ -52,13 +61,12 @@ namespace Crow if (child != null) { //check if HoverWidget is removed from Tree - if (CurrentInterface.HoverWidget != null) { - if (this.Contains (CurrentInterface.HoverWidget)) - CurrentInterface.HoverWidget = null; + if (IFace.HoverWidget != null) { + if (this.Contains (IFace.HoverWidget)) + IFace.HoverWidget = null; } - contentSize = new Size (0, 0); + contentSize = default(Size); child.LayoutChanged -= OnChildLayoutChanges; - child.Dispose (); this.RegisterForGraphicUpdate (); } @@ -72,6 +80,13 @@ namespace Crow child.RegisterForLayouting (LayoutingType.Sizing); } } + //dispose child if not null + protected virtual void deleteChild () { + GraphicObject g = child; + SetChild (null); + if (g != null) + g.Dispose (); + } #region GraphicObject Overrides @@ -100,11 +115,11 @@ namespace Crow //force sizing to fit if sizing on children and child has stretched size switch (layoutType) { case LayoutingType.Width: - if (Width == Measure.Fit && child.Width.Units == Unit.Percent) + if (Width == Measure.Fit && child.Width.IsRelativeToParent) child.Width = Measure.Fit; break; case LayoutingType.Height: - if (Height == Measure.Fit && child.Height.Units == Unit.Percent) + if (Height == Measure.Fit && child.Height.IsRelativeToParent) child.Height = Measure.Fit; break; } @@ -121,14 +136,14 @@ namespace Crow LayoutingType ltChild = LayoutingType.None; if (layoutType == LayoutingType.Width) { - if (child.Width.Units == Unit.Percent) { + if (child.Width.IsRelativeToParent) { ltChild |= LayoutingType.Width; if (child.Width.Value < 100 && child.Left == 0) ltChild |= LayoutingType.X; } else if (child.Left == 0) ltChild |= LayoutingType.X; } else if (layoutType == LayoutingType.Height) { - if (child.Height.Units == Unit.Percent) { + if (child.Height.IsRelativeToParent) { ltChild |= LayoutingType.Height; if (child.Height.Value < 100 && child.Top == 0) ltChild |= LayoutingType.Y; diff --git a/src/GraphicObjects/SaturationValueSelector.cs b/src/GraphicObjects/SaturationValueSelector.cs index d9ee0a00..485a33d2 100644 --- a/src/GraphicObjects/SaturationValueSelector.cs +++ b/src/GraphicObjects/SaturationValueSelector.cs @@ -30,6 +30,7 @@ using System.Xml.Serialization; namespace Crow { + [DesignIgnore] public class SaturationValueSelector : ColorSelector { public SaturationValueSelector () : base(){} @@ -101,7 +102,7 @@ namespace Crow ctx.Translate (rb.X, rb.Y); - ctx.SetSourceColor (Color.Jet); + ctx.SetSourceColor (Color.DimGrey); ctx.Arc (mousePos.X, mousePos.Y, 3.5, 0, Math.PI * 2.0); ctx.LineWidth = 0.5; ctx.Stroke (); diff --git a/src/GraphicObjects/Scroller.cs b/src/GraphicObjects/Scroller.cs index 397d7de0..30dd1480 100644 --- a/src/GraphicObjects/Scroller.cs +++ b/src/GraphicObjects/Scroller.cs @@ -42,160 +42,159 @@ namespace Crow public Scroller (Interface iface) : base(iface){} #endregion - bool _verticalScrolling; - bool _horizontalScrolling; - bool _scrollbarVisible; - int _scrollX = 0; - int _scrollY = 0; - int scrollSpeed; - public event EventHandler<ScrollingEventArgs> Scrolled; + int scrollX, scrollY, maxScrollX, maxScrollY, scrollSpeed; + + /// <summary> + /// if true, key stroke are handled in derrived class + /// </summary> + protected bool KeyEventsOverrides = false; + #region public properties - [XmlAttributeAttribute][DefaultValue(true)] - public bool VerticalScrolling { - get { return _verticalScrolling; } - set { _verticalScrolling = value; } - } + /// <summary> Horizontal Scrolling Position </summary> + [XmlAttributeAttribute][DefaultValue(0)] + public virtual int ScrollX { + get { return scrollX; } + set { + if (scrollX == value) + return; - [XmlAttributeAttribute][DefaultValue(false)] - public bool HorizontalScrolling { - get { return _horizontalScrolling; } - set { _horizontalScrolling = value; } - } - [XmlAttributeAttribute][DefaultValue(true)] - public bool ScrollbarVisible { - get { return _scrollbarVisible; } - set { _scrollbarVisible = value; } + int newS = value; + if (newS < 0) + newS = 0; + else if (newS > maxScrollX) + newS = maxScrollX; + + if (newS == scrollX) + return; + + scrollX = value; + + NotifyValueChanged ("ScrollX", scrollX); + RegisterForGraphicUpdate (); + } } + /// <summary> Vertical Scrolling Position </summary> [XmlAttributeAttribute][DefaultValue(0)] - public int ScrollX { - get { - return _scrollX; - } + public virtual int ScrollY { + get { return scrollY; } set { - if (_scrollX == value) + if (scrollY == value) return; - if (value < 0) - _scrollX = 0; - else if (value > Child.Slot.Width - ClientRectangle.Width) - _scrollX = Math.Max(0, Child.Slot.Width - ClientRectangle.Width); - else - _scrollX = value; - NotifyValueChanged("ScrollX", _scrollX); - RegisterForRedraw (); - Scrolled.Raise (this, new ScrollingEventArgs (Orientation.Horizontal)); + + int newS = value; + if (newS < 0) + newS = 0; + else if (newS > maxScrollY) + newS = maxScrollY; + + if (newS == scrollY) + return; + + scrollY = value; + + NotifyValueChanged ("ScrollY", scrollY); + RegisterForGraphicUpdate (); } } + /// <summary> Horizontal Scrolling maximum value </summary> [XmlAttributeAttribute][DefaultValue(0)] - public int ScrollY { - get { - return _scrollY; - } + public virtual int MaxScrollX { + get { return maxScrollX; } set { - if (_scrollY == value) + if (maxScrollX == value) return; - if (value < 0) - _scrollY = 0; - else if (value > Child.Slot.Height - ClientRectangle.Height) - _scrollY = Math.Max(0,Child.Slot.Height - ClientRectangle.Height); - else - _scrollY = value; - NotifyValueChanged("ScrollY", _scrollY); - RegisterForRedraw (); - Scrolled.Raise (this, new ScrollingEventArgs (Orientation.Vertical)); + + maxScrollX = value; + + if (scrollX > maxScrollX) + ScrollX = maxScrollX; + + NotifyValueChanged ("MaxScrollX", maxScrollX); + RegisterForGraphicUpdate (); } } + /// <summary> Vertical Scrolling maximum value </summary> + [XmlAttributeAttribute][DefaultValue(0)] + public virtual int MaxScrollY { + get { return maxScrollY; } + set { + if (maxScrollY == value) + return; + + maxScrollY = value; + + if (scrollY > maxScrollY) + ScrollY = maxScrollY; - [XmlIgnore] - public int MaximumScroll { - get { - try { - return VerticalScrolling ? - Math.Max(Child.Slot.Height - ClientRectangle.Height,0) : - Math.Max(Child.Slot.Width - ClientRectangle.Width,0); - } catch { - return 0; - } + NotifyValueChanged ("MaxScrollY", maxScrollY); + RegisterForGraphicUpdate (); } } - - [XmlAttributeAttribute][DefaultValue(30)] - public int ScrollSpeed { + /// <summary> Mouse Wheel Scrolling multiplier </summary> + [XmlAttributeAttribute][DefaultValue(50)] + public virtual int ScrollSpeed { get { return scrollSpeed; } set { + if (scrollSpeed == value) + return; + scrollSpeed = value; - NotifyValueChanged("ScrollSpeed", scrollSpeed); + + NotifyValueChanged ("ScrollSpeed", scrollSpeed); } } #endregion - #region GraphicObject Overrides - public override void OnLayoutChanges (LayoutingType layoutType) + public override void SetChild (GraphicObject _child) { - base.OnLayoutChanges (layoutType); + Group g = child as Group; + if (g != null) + g.ChildrenCleared -= onChildListCleared; + + base.SetChild (_child); - NotifyValueChanged("MaximumScroll", MaximumScroll); - if (layoutType == LayoutingType.Height) { - NotifyValueChanged ("PageHeight", Slot.Height); - if (child?.Slot.Height > 0) - NotifyValueChanged ("ChildHeightRatio", Slot.Height * Slot.Height / child.Slot.Height); - } else { - NotifyValueChanged ("PageWidth", Slot.Width); - if (child?.Slot.Width > 0) - NotifyValueChanged ("ChildWidthRatio", Slot.Width * Slot.Width / child.Slot.Width); - } + g = _child as Group; + if (g != null) + g.ChildrenCleared += onChildListCleared; } - void OnChildLayoutChanges (object sender, LayoutingEventArgs arg) + public override void OnChildLayoutChanges (object sender, LayoutingEventArgs arg) { - //Debug.WriteLine ("scroller childLayoutChanges"); - int maxScroll = MaximumScroll; - //Debug.WriteLine ("maxscroll={0}", maxScroll); - if (_verticalScrolling) { - if (arg.LayoutType == LayoutingType.Height) { - if (maxScroll < ScrollY) { - //Debug.WriteLine ("scrolly={0} maxscroll={1}", ScrollY, maxScroll); - ScrollY = maxScroll; - } - NotifyValueChanged("MaximumScroll", maxScroll); - if (child?.Slot.Height > 0) - NotifyValueChanged ("ChildHeightRatio", Slot.Height * Slot.Height / child.Slot.Height); - } - } else if (arg.LayoutType == LayoutingType.Width) { - if (maxScroll < ScrollX) { - //Debug.WriteLine ("scrolly={0} maxscroll={1}", ScrollY, maxScroll); - ScrollX = maxScroll; - } - NotifyValueChanged("MaximumScroll", maxScroll); - if (child?.Slot.Width > 0) - NotifyValueChanged ("ChildWidthRatio", Slot.Width * Slot.Width / child.Slot.Width); - } + base.OnChildLayoutChanges (sender, arg); + updateMaxScroll (arg.LayoutType); } - void onChildListCleared(object sender, EventArgs e){ - ScrollY = 0; - ScrollX = 0; + + + #region GraphicObject Overrides + public override Rectangle ScreenCoordinates (Rectangle r) + { + return base.ScreenCoordinates (r) - new Point((int)ScrollX,(int)ScrollY); } - public override void SetChild (GraphicObject _child) + public override bool PointIsIn (ref Point m) { - GraphicObject c = child as GraphicObject; - Group g = child as Group; - if (c != null) { - c.LayoutChanged -= OnChildLayoutChanges; - if (g != null) - g.ChildrenCleared -= onChildListCleared; - } - c = _child as GraphicObject; - g = _child as Group; - if (c != null) { - c.LayoutChanged += OnChildLayoutChanges; - if (g != null) - g.ChildrenCleared += onChildListCleared; - } - base.SetChild (_child); + if (!base.PointIsIn(ref m)) + return false; + if (!Slot.ContainsOrIsEqual (m) || child==null) + return false; + m += new Point (ScrollX, ScrollY); + return true; } - public override Rectangle ScreenCoordinates (Rectangle r) + public override void RegisterClip (Rectangle clip) { - return base.ScreenCoordinates (r) - new Point((int)ScrollX,(int)ScrollY); + base.RegisterClip (clip - new Point(ScrollX,ScrollY)); + } + public override void OnLayoutChanges (LayoutingType layoutType) + { + base.OnLayoutChanges (layoutType); + + if (layoutType == LayoutingType.Height) + NotifyValueChanged ("PageHeight", Slot.Height); + else if (layoutType == LayoutingType.Width) + NotifyValueChanged ("PageWidth", Slot.Width); + else + return; + updateMaxScroll(layoutType); } protected override void onDraw (Context gr) { @@ -218,50 +217,75 @@ namespace Crow gr.Restore (); } - #region Mouse handling - //internal Point savedMousePos; - - public override bool PointIsIn (ref Point m) - { - if (!base.PointIsIn(ref m)) - return false; - if (!Slot.ContainsOrIsEqual (m) || child==null) - return false; - m += new Point (ScrollX, ScrollY); - return true; - } -// public override bool MouseIsIn (Point m) -// { -// return Visible ? base.ScreenCoordinates(Slot).ContainsOrIsEqual (m) : false; -// } -// public override void checkHoverWidget (MouseMoveEventArgs e) -// { -// savedMousePos = e.Position; -// Point m = e.Position - new Point (ScrollX, ScrollY); -// base.checkHoverWidget (new MouseMoveEventArgs(m.X,m.Y,e.XDelta,e.YDelta)); -// } + #region Mouse & Keyboard + /// <summary> Process scrolling vertically, or if shift is down, vertically </summary> public override void onMouseWheel (object sender, MouseWheelEventArgs e) { - if (Child == null) - return; - - if (VerticalScrolling ) + base.onMouseWheel (sender, e); + if (IFace.Keyboard.IsKeyDown (Key.ShiftLeft)) + ScrollX += e.Delta * ScrollSpeed; + else ScrollY -= e.Delta * ScrollSpeed; - if (HorizontalScrolling ) - ScrollX -= e.Delta * ScrollSpeed; } -// public override void onMouseMove (object sender, MouseMoveEventArgs e) -// { -// savedMousePos.X += e.XDelta; -// savedMousePos.Y += e.YDelta; -// base.onMouseMove (sender, new MouseMoveEventArgs(savedMousePos.X,savedMousePos.Y,e.XDelta,e.YDelta)); -// } - public override void RegisterClip (Rectangle clip) + /// <summary> Process scrolling with arrow keys, home and end keys. </summary> + public override void onKeyDown (object sender, KeyboardKeyEventArgs e) { - base.RegisterClip (clip - new Point(ScrollX,ScrollY)); + base.onKeyDown (sender, e); + + if (KeyEventsOverrides) + return; + + switch (e.Key) { + case Key.Up: + ScrollY--; + break; + case Key.Down: + ScrollY++; + break; + case Key.Left: + ScrollX--; + break; + case Key.Right: + ScrollX++; + break; + case Key.Home: + ScrollX = 0; + ScrollY = 0; + break; + case Key.End: + ScrollX = MaxScrollX; + ScrollY = MaxScrollY; + break; + } } #endregion #endregion + + void updateMaxScroll (LayoutingType lt){ + if (Child == null) { + MaxScrollX = 0; + MaxScrollY = 0; + return; + } + + Rectangle cb = ClientRectangle; + + if (lt == LayoutingType.Height) { + MaxScrollY = child.Slot.Height - cb.Height; + if (child.Slot.Height > 0) + NotifyValueChanged ("ChildHeightRatio", Slot.Height * Slot.Height / child.Slot.Height); + } else if (lt == LayoutingType.Width) { + MaxScrollX = child.Slot.Width - cb.Width; + if (child.Slot.Width > 0) + NotifyValueChanged ("ChildWidthRatio", Slot.Width * Slot.Width / child.Slot.Width); + } + } + void onChildListCleared(object sender, EventArgs e){ + ScrollY = 0; + ScrollX = 0; + } + + } } diff --git a/src/GraphicObjects/ScrollingObject.cs b/src/GraphicObjects/ScrollingObject.cs index 9059d8ed..de4b2113 100644 --- a/src/GraphicObjects/ScrollingObject.cs +++ b/src/GraphicObjects/ScrollingObject.cs @@ -36,6 +36,7 @@ namespace Crow /// <summary> /// generic class to build scrolling control in both directions /// </summary> + [DesignIgnore] public class ScrollingObject : GraphicObject { #region CTOR @@ -148,7 +149,7 @@ namespace Crow public override void onMouseWheel (object sender, MouseWheelEventArgs e) { base.onMouseWheel (sender, e); - if (CurrentInterface.Keyboard.IsKeyDown (Key.ShiftLeft)) + if (IFace.Keyboard.IsKeyDown (Key.ShiftLeft)) ScrollX += e.Delta * MouseWheelSpeed; else ScrollY -= e.Delta * MouseWheelSpeed; diff --git a/src/GraphicObjects/ScrollingTextBox.cs b/src/GraphicObjects/ScrollingTextBox.cs deleted file mode 100644 index c84594df..00000000 --- a/src/GraphicObjects/ScrollingTextBox.cs +++ /dev/null @@ -1,794 +0,0 @@ -// -// ScrollingTextBox.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 System.Xml.Serialization; -using System.ComponentModel; -using System.Collections; -using Cairo; -using System.Text; -using System.Collections.Generic; -using System.Text.RegularExpressions; -using System.Linq; - -namespace Crow -{ - /// <summary> - /// Scrolling text box optimized for monospace fonts, for coding - /// </summary> - public class ScrollingTextBox : ScrollingObject - { - #region CTOR - protected ScrollingTextBox ():base() - { - KeyEventsOverrides = true; - } - public ScrollingTextBox (Interface iface):base(iface){ - KeyEventsOverrides = true; - } - #endregion - - public event EventHandler TextChanged; - - public virtual void OnTextChanged(Object sender, EventArgs e) - { - TextChanged.Raise (this, e); - } - - #region private and protected fields - string lineBreak = Interface.LineBreak; - int visibleLines = 1; - List<string> lines; - string _text = "label"; - Color selBackground; - Color selForeground; - Point mouseLocalPos = 0;//mouse coord in widget space - int _currentCol; //0 based cursor position in string - int _currentLine; - Point _selBegin = -1; //selection start (row,column) - Point _selRelease = -1; //selection end (row,column) - - protected Rectangle rText; - protected FontExtents fe; - protected TextExtents te; - #endregion - - [XmlAttributeAttribute][DefaultValue("label")] - public string Text - { - get { - return lines == null ? - _text : lines.Aggregate((i, j) => i + Interface.LineBreak + j); - } - set - { - if (string.Equals (value, _text, StringComparison.Ordinal)) - return; - - _text = value; - - if (string.IsNullOrEmpty(_text)) - _text = ""; - - lines = getLines; - MaxScrollY = Math.Max (0, lines.Count - visibleLines); - - OnTextChanged (this, null); - RegisterForGraphicUpdate (); - } - } - - - [XmlAttributeAttribute][DefaultValue("BlueGray")] - public virtual Color SelectionBackground { - get { return selBackground; } - set { - if (value == selBackground) - return; - selBackground = value; - NotifyValueChanged ("SelectionBackground", selBackground); - RegisterForRedraw (); - } - } - [XmlAttributeAttribute][DefaultValue("White")] - public virtual Color SelectionForeground { - get { return selForeground; } - set { - if (value == selForeground) - return; - selForeground = value; - NotifyValueChanged ("SelectionForeground", selForeground); - RegisterForRedraw (); - } - } - [XmlAttributeAttribute][DefaultValue(0)] - public int CurrentColumn{ - get { return _currentCol; } - set { - if (value == _currentCol) - return; - if (value < 0) - _currentCol = 0; - else if (value > lines [_currentLine].Length) - _currentCol = lines [_currentLine].Length; - else - _currentCol = value; - NotifyValueChanged ("CurrentColumn", _currentCol); - } - } - [XmlAttributeAttribute][DefaultValue(0)] - public int CurrentLine{ - get { return _currentLine; } - set { - if (value == _currentLine) - return; - if (value >= lines.Count) - _currentLine = lines.Count-1; - else if (value < 0) - _currentLine = 0; - else - _currentLine = value; - //force recheck of currentCol for bounding - int cc = _currentCol; - _currentCol = 0; - CurrentColumn = cc; - NotifyValueChanged ("CurrentLine", _currentLine); - - if (CurrentLine < ScrollY) - ScrollY = CurrentLine; - else if (CurrentLine >= ScrollY + visibleLines) - ScrollY = Math.Max (0, CurrentLine - visibleLines + 1); - } - } - [XmlIgnore]public Point CurrentPosition { - get { return new Point(CurrentColumn, CurrentLine); } - } - //TODO:using HasFocus for drawing selection cause SelBegin and Release binding not to work - /// <summary> - /// Selection begin position in char units (line, column) - /// </summary> - [XmlAttributeAttribute][DefaultValue("-1")] - public Point SelBegin { - get { return _selBegin; } - set { - if (value == _selBegin) - return; - _selBegin = value; - System.Diagnostics.Debug.WriteLine ("SelBegin=" + _selBegin); - NotifyValueChanged ("SelBegin", _selBegin); - NotifyValueChanged ("SelectedText", SelectedText); - } - } - /// <summary> - /// Selection release position in char units (line, column) - /// </summary> - [XmlAttributeAttribute][DefaultValue("-1")] - public Point SelRelease { - get { - return _selRelease; - } - set { - if (value == _selRelease) - return; - _selRelease = value; - NotifyValueChanged ("SelRelease", _selRelease); - NotifyValueChanged ("SelectedText", SelectedText); - } - } - /// <summary> - /// return char at CurrentLine, CurrentColumn - /// </summary> - [XmlIgnore]protected Char CurrentChar - { - get { - return lines [CurrentLine] [CurrentColumn]; - } - } - /// <summary> - /// ordered selection start and end positions in char units - /// </summary> - [XmlIgnore]protected Point selectionStart - { - get { - return SelRelease < 0 || SelBegin.Y < SelRelease.Y ? SelBegin : - SelBegin.Y > SelRelease.Y ? SelRelease : - SelBegin.X < SelRelease.X ? SelBegin : SelRelease; - } - } - [XmlIgnore]public Point selectionEnd - { - get { - return SelRelease < 0 || SelBegin.Y > SelRelease.Y ? SelBegin : - SelBegin.Y < SelRelease.Y ? SelRelease : - SelBegin.X > SelRelease.X ? SelBegin : SelRelease; - } - } - [XmlIgnore]public string SelectedText - { - get { - - if (SelRelease < 0 || SelBegin < 0) - return ""; - if (selectionStart.Y == selectionEnd.Y) - return lines [selectionStart.Y].Substring (selectionStart.X, selectionEnd.X - selectionStart.X); - string tmp = ""; - tmp = lines [selectionStart.Y].Substring (selectionStart.X); - for (int l = selectionStart.Y + 1; l < selectionEnd.Y; l++) { - tmp += Interface.LineBreak + lines [l]; - } - tmp += Interface.LineBreak + lines [selectionEnd.Y].Substring (0, selectionEnd.X); - return tmp; - } - } - [XmlIgnore]public bool selectionIsEmpty - { get { return SelRelease == SelBegin; } } - - List<string> getLines { - get { - return Regex.Split (_text, "\r\n|\r|\n|\\\\n").ToList(); - } - } - /// <summary> - /// Moves cursor one char to the left. - /// </summary> - /// <returns><c>true</c> if move succeed</returns> - public bool MoveLeft(){ - int tmp = _currentCol - 1; - if (tmp < 0) { - if (_currentLine == 0) - return false; - CurrentLine--; - CurrentColumn = int.MaxValue; - } else - CurrentColumn = tmp; - return true; - } - /// <summary> - /// Moves cursor one char to the right. - /// </summary> - /// <returns><c>true</c> if move succeed</returns> - public bool MoveRight(){ - int tmp = _currentCol + 1; - if (tmp > lines [_currentLine].Length){ - if (CurrentLine == lines.Count - 1) - return false; - CurrentLine++; - CurrentColumn = 0; - } else - CurrentColumn = tmp; - return true; - } - public void GotoWordStart(){ - if (lines[CurrentLine].Length == 0) - return; - CurrentColumn--; - //skip white spaces - while (!char.IsLetterOrDigit (this.CurrentChar) && CurrentColumn > 0) - CurrentColumn--; - while (char.IsLetterOrDigit (lines [CurrentLine] [CurrentColumn]) && CurrentColumn > 0) - CurrentColumn--; - if (!char.IsLetterOrDigit (this.CurrentChar)) - CurrentColumn++; - } - public void GotoWordEnd(){ - //skip white spaces - if (CurrentColumn >= lines [CurrentLine].Length - 1) - return; - while (!char.IsLetterOrDigit (this.CurrentChar) && CurrentColumn < lines [CurrentLine].Length-1) - CurrentColumn++; - while (char.IsLetterOrDigit (this.CurrentChar) && CurrentColumn < lines [CurrentLine].Length-1) - CurrentColumn++; - if (char.IsLetterOrDigit (this.CurrentChar)) - CurrentColumn++; - } - public void DeleteChar() - { - if (selectionIsEmpty) { - if (CurrentColumn == 0) { - if (CurrentLine == 0 && lines.Count == 1) - return; - CurrentLine--; - CurrentColumn = lines [CurrentLine].Length; - lines [CurrentLine] += lines [CurrentLine + 1]; - lines.RemoveAt (CurrentLine + 1); - OnTextChanged (this, null); - return; - } - CurrentColumn--; - lines [CurrentLine] = lines [CurrentLine].Remove (CurrentColumn, 1); - } else { - int linesToRemove = selectionEnd.Y - selectionStart.Y + 1; - int l = selectionStart.Y; - - if (linesToRemove > 0) { - lines [l] = lines [l].Remove (selectionStart.X, lines [l].Length - selectionStart.X) + - lines [selectionEnd.Y].Substring (selectionEnd.X, lines [selectionEnd.Y].Length - selectionEnd.X); - l++; - for (int c = 0; c < linesToRemove-1; c++) - lines.RemoveAt (l); - CurrentLine = selectionStart.Y; - CurrentColumn = selectionStart.X; - } else - lines [l] = lines [l].Remove (selectionStart.X, selectionEnd.X - selectionStart.X); - CurrentColumn = selectionStart.X; - SelBegin = -1; - SelRelease = -1; - } - OnTextChanged (this, null); - } - - #region GraphicObject overrides - public override Font Font { - get { return base.Font; } - set { - base.Font = value; - - using (ImageSurface img = new ImageSurface (Format.Argb32, 1, 1)) { - using (Context gr = new Context (img)) { - gr.SelectFontFace (Font.Name, Font.Slant, Font.Wheight); - gr.SetFontSize (Font.Size); - - fe = gr.FontExtents; - } - } - MaxScrollY = 0; - RegisterForGraphicUpdate (); - } - } - protected override int measureRawSize(LayoutingType lt) - { - if (lt == LayoutingType.Height) - return (int)Math.Ceiling(fe.Height * lines.Count) + Margin * 2; - - string txt = _text.Replace("\t", new String (' ', Interface.TabSize)); - - - int maxChar = 0; - foreach (string s in Regex.Split (txt, "\r\n|\r|\n|\\\\n")) { - if (maxChar < s.Length) - maxChar = s.Length; - } - return (int)(fe.MaxXAdvance * maxChar) + Margin * 2; - } - public override void OnLayoutChanges (LayoutingType layoutType) - { - base.OnLayoutChanges (layoutType); - - if (layoutType == LayoutingType.Height) - updateVisibleLines (); - } - protected override void onDraw (Context gr) - { - base.onDraw (gr); - - gr.SelectFontFace (Font.Name, Font.Slant, Font.Wheight); - gr.SetFontSize (Font.Size); - gr.FontOptions = Interface.FontRenderingOptions; - gr.Antialias = Interface.Antialias; - - Rectangle cb = ClientRectangle; - - Foreground.SetAsSource (gr); - - bool selectionInProgress = false; - - #region draw text cursor - if (SelBegin != SelRelease) - selectionInProgress = true; - else if (HasFocus){ - gr.SetSourceColor(Color.Red); - gr.LineWidth = 2.0; - double cursorX = cb.X + (CurrentColumn - ScrollX) * fe.MaxXAdvance; - gr.MoveTo (0.5 + cursorX, cb.Y + (CurrentLine - ScrollY) * fe.Height); - gr.LineTo (0.5 + cursorX, cb.Y + (CurrentLine + 1 - ScrollY) * fe.Height); - gr.Stroke(); - } - #endregion - - Foreground.SetAsSource (gr); - - for (int i = 0; i < visibleLines; i++) { - int curL = i + ScrollY; - if (curL >= lines.Count) - break; - string lstr = lines[curL]; - - gr.MoveTo (cb.X, cb.Y + fe.Ascent + fe.Height * i); - gr.ShowText (lstr); - gr.Fill (); - - if (selectionInProgress && curL >= selectionStart.Y && curL <= selectionEnd.Y) { - - double rLineX = cb.X, - rLineY = cb.Y + i * fe.Height, - rLineW = lstr.Length * fe.MaxXAdvance; - - System.Diagnostics.Debug.WriteLine ("sel start: " + selectionStart + " sel end: " + selectionEnd); - if (curL == selectionStart.Y) { - rLineX += (selectionStart.X - ScrollX) * fe.MaxXAdvance; - rLineW -= selectionStart.X * fe.MaxXAdvance; - } - if (curL == selectionEnd.Y) - rLineW -= (lstr.Length - selectionEnd.X) * fe.MaxXAdvance; - - gr.Save (); - gr.Operator = Operator.Source; - gr.Rectangle (rLineX, rLineY, rLineW, fe.Height); - gr.SetSourceColor (SelectionBackground); - gr.FillPreserve (); - gr.Clip (); - gr.Operator = Operator.Over; - gr.SetSourceColor (SelectionForeground); - gr.MoveTo (cb.X, cb.Y + fe.Ascent + fe.Height * i); - gr.ShowText (lstr); - gr.Fill (); - gr.Restore (); - } - } - } - #endregion - - #region Mouse handling - void updatemouseLocalPos(Point mpos){ - Point mouseLocalPos = mpos - ScreenCoordinates(Slot).TopLeft - ClientRectangle.TopLeft; - if (mouseLocalPos.X < 0) - CurrentColumn--; - else - CurrentColumn = ScrollX + (int)Math.Round (mouseLocalPos.X / fe.MaxXAdvance); - - if (mouseLocalPos.Y < 0) - CurrentLine--; - else - CurrentLine = ScrollY + (int)Math.Floor (mouseLocalPos.Y / fe.Height); - } - public override void onMouseEnter (object sender, MouseMoveEventArgs e) - { - base.onMouseEnter (sender, e); - CurrentInterface.MouseCursor = XCursor.Text; - } - public override void onMouseLeave (object sender, MouseMoveEventArgs e) - { - base.onMouseLeave (sender, e); - CurrentInterface.MouseCursor = XCursor.Default; - } - protected override void onFocused (object sender, EventArgs e) - { - base.onFocused (sender, e); - - // SelBegin = new Point(0,0); - // SelRelease = new Point (lines.LastOrDefault ().Length, lines.Count-1); - RegisterForRedraw (); - } - protected override void onUnfocused (object sender, EventArgs e) - { - base.onUnfocused (sender, e); - - // SelBegin = -1; - // SelRelease = -1; - RegisterForRedraw (); - } - public override void onMouseMove (object sender, MouseMoveEventArgs e) - { - base.onMouseMove (sender, e); - - if (!e.Mouse.IsButtonDown (MouseButton.Left)) - return; - if (!HasFocus || SelBegin < 0) - return; - - updatemouseLocalPos (e.Position); - SelRelease = CurrentPosition; - - RegisterForRedraw(); - } - public override void onMouseDown (object sender, MouseButtonEventArgs e) - { - if (this.HasFocus){ - updatemouseLocalPos (e.Position); - SelBegin = SelRelease = CurrentPosition; - RegisterForRedraw();//TODO:should put it in properties - } - - //done at the end to set 'hasFocus' value after testing it - base.onMouseDown (sender, e); - } - public override void onMouseUp (object sender, MouseButtonEventArgs e) - { - base.onMouseUp (sender, e); - - if (SelBegin == SelRelease) - SelBegin = SelRelease = -1; - - updatemouseLocalPos (e.Position); - RegisterForRedraw (); - } - public override void onMouseDoubleClick (object sender, MouseButtonEventArgs e) - { - base.onMouseDoubleClick (sender, e); - - GotoWordStart (); - SelBegin = CurrentPosition; - GotoWordEnd (); - SelRelease = CurrentPosition; - RegisterForRedraw (); - } - #endregion - - #region Keyboard handling - public override void onKeyDown (object sender, KeyboardKeyEventArgs e) - { - base.onKeyDown (sender, e); - - Key key = e.Key; - - switch (key) - { - case Key.Back: - if (CurrentPosition == 0) - return; - this.DeleteChar(); - break; - case Key.Clear: - break; - case Key.Delete: - if (selectionIsEmpty) { - if (!MoveRight ()) - return; - }else if (e.Shift) - CurrentInterface.Clipboard = this.SelectedText; - this.DeleteChar (); - break; - case Key.Enter: - case Key.KeypadEnter: - if (!selectionIsEmpty) - this.DeleteChar (); - this.InsertLineBreak (); - break; - case Key.Escape: - Text = ""; - CurrentColumn = 0; - SelRelease = -1; - break; - case Key.Home: - if (e.Shift) { - if (selectionIsEmpty) - SelBegin = new Point (CurrentColumn, CurrentLine); - if (e.Control) - CurrentLine = 0; - CurrentColumn = 0; - SelRelease = new Point (CurrentColumn, CurrentLine); - break; - } - SelRelease = -1; - if (e.Control) - CurrentLine = 0; - CurrentColumn = 0; - break; - case Key.End: - if (e.Shift) { - if (selectionIsEmpty) - SelBegin = CurrentPosition; - if (e.Control) - CurrentLine = int.MaxValue; - CurrentColumn = int.MaxValue; - SelRelease = CurrentPosition; - break; - } - SelRelease = -1; - if (e.Control) - CurrentLine = int.MaxValue; - CurrentColumn = int.MaxValue; - break; - case Key.Insert: - if (e.Shift) - this.Insert (CurrentInterface.Clipboard); - else if (e.Control && !selectionIsEmpty) - CurrentInterface.Clipboard = this.SelectedText; - break; - case Key.Left: - if (e.Shift) { - if (selectionIsEmpty) - SelBegin = new Point(CurrentColumn, CurrentLine); - if (e.Control) - GotoWordStart (); - else if (!MoveLeft ()) - return; - SelRelease = CurrentPosition; - break; - } - SelRelease = -1; - if (e.Control) - GotoWordStart (); - else - MoveLeft(); - break; - case Key.Right: - if (e.Shift) { - if (selectionIsEmpty) - SelBegin = CurrentPosition; - if (e.Control) - GotoWordEnd (); - else if (!MoveRight ()) - return; - SelRelease = CurrentPosition; - break; - } - SelRelease = -1; - if (e.Control) - GotoWordEnd (); - else - MoveRight (); - break; - case Key.Up: - if (e.Shift) { - if (selectionIsEmpty) - SelBegin = CurrentPosition; - CurrentLine--; - SelRelease = CurrentPosition; - break; - } - SelRelease = -1; - CurrentLine--; - break; - case Key.Down: - if (e.Shift) { - if (selectionIsEmpty) - SelBegin = CurrentPosition; - CurrentLine++; - SelRelease = CurrentPosition; - break; - } - SelRelease = -1; - CurrentLine++; - break; - case Key.Menu: - break; - case Key.NumLock: - break; - case Key.PageDown: - if (e.Shift) { - if (selectionIsEmpty) - SelBegin = CurrentPosition; - CurrentLine += visibleLines; - SelRelease = CurrentPosition; - break; - } - SelRelease = -1; - CurrentLine += visibleLines; - break; - case Key.PageUp: - if (e.Shift) { - if (selectionIsEmpty) - SelBegin = CurrentPosition; - CurrentLine -= visibleLines; - SelRelease = CurrentPosition; - break; - } - CurrentLine -= visibleLines; - break; - case Key.RWin: - break; - case Key.Tab: - this.Insert ("\t"); - break; - default: - break; - } - RegisterForGraphicUpdate(); - } - public override void onKeyPress (object sender, KeyPressEventArgs e) - { - base.onKeyPress (sender, e); - - this.Insert (e.KeyChar.ToString()); - - SelRelease = -1; - SelBegin = -1; //new Point(CurrentColumn, SelBegin.Y); - - RegisterForGraphicUpdate(); - } - #endregion - - - /// <summary> Compute x offset in cairo unit from text position </summary> - double GetXFromTextPointer(Context gr, Point pos) - { - try { - string l = lines [pos.Y].Substring (0, pos.X). - Replace ("\t", new String (' ', Interface.TabSize)); - return gr.TextExtents (l).XAdvance; - } catch{ - return -1; - } - } - - /// <summary> line break could be '\r' or '\n' or '\r\n' </summary> - string detectLineBreakKind(){ - string strLB = ""; - - if (string.IsNullOrEmpty(_text)) - return Interface.LineBreak; - int i = 0; - while ( i < _text.Length) { - if (_text [i] == '\r') { - strLB += '\r'; - i++; - } - if (i < _text.Length) { - if (_text [i] == '\r') - return "\r"; - if (_text [i] == '\n') - strLB += '\n'; - } - if (!string.IsNullOrEmpty (strLB)) - return strLB; - i++; - } - return Interface.LineBreak; - } - - void updateVisibleLines(){ - visibleLines = (int)Math.Floor ((double)ClientRectangle.Height / fe.Height); - MaxScrollY = Math.Max (0, lines.Count - visibleLines); - - System.Diagnostics.Debug.WriteLine ("update visible lines: " + visibleLines); - System.Diagnostics.Debug.WriteLine ("update MaxScrollY: " + MaxScrollY); - } - - - /// <summary> - /// Insert new string at caret position, should be sure no line break is inside. - /// </summary> - /// <param name="str">String.</param> - protected void Insert(string str) - { - if (!selectionIsEmpty) - this.DeleteChar (); - string[] strLines = Regex.Split (str, "\r\n|\r|\n|" + @"\\n").ToArray(); - lines [CurrentLine] = lines [CurrentLine].Insert (CurrentColumn, strLines[0]); - CurrentColumn += strLines[0].Length; - for (int i = 1; i < strLines.Length; i++) { - InsertLineBreak (); - lines [CurrentLine] = lines [CurrentLine].Insert (CurrentColumn, strLines[i]); - CurrentColumn += strLines[i].Length; - } - OnTextChanged (this, null); - RegisterForGraphicUpdate(); - } - - /// <summary> - /// Insert a line break. - /// </summary> - protected void InsertLineBreak() - { - lines.Insert(CurrentLine + 1, lines[CurrentLine].Substring(CurrentColumn)); - lines [CurrentLine] = lines [CurrentLine].Substring (0, CurrentColumn); - CurrentLine++; - CurrentColumn = 0; - OnTextChanged (this, null); - } - } -}
\ No newline at end of file diff --git a/src/GraphicObjects/Slider.cs b/src/GraphicObjects/Slider.cs index 2e4a5fef..2bdd5b8a 100644 --- a/src/GraphicObjects/Slider.cs +++ b/src/GraphicObjects/Slider.cs @@ -68,7 +68,7 @@ namespace Crow protected double unity; #region Public properties - [XmlAttributeAttribute()][DefaultValue("vgradient|0:White|0,1:LightGray|0,9:LightGray|1:DimGray")] + [DefaultValue("vgradient|0:White|0,1:LightGray|0,9:LightGray|1:DimGray")] public virtual Fill CursorColor { get { return _cursorColor; } set { @@ -79,7 +79,7 @@ namespace Crow NotifyValueChanged ("CursorColor", _cursorColor); } } - [XmlAttributeAttribute()][DefaultValue(20)] + [DefaultValue(20)] public virtual int CursorSize { get { return _cursorSize; } set { @@ -90,7 +90,7 @@ namespace Crow NotifyValueChanged ("CursorSize", _cursorSize); } } - [XmlAttributeAttribute()][DefaultValue(Orientation.Horizontal)] + [DefaultValue(Orientation.Horizontal)] public virtual Orientation Orientation { get { return _orientation; } @@ -105,7 +105,7 @@ namespace Crow } #endregion - [XmlAttributeAttribute()][DefaultValue(10.0)] + [DefaultValue(10.0)] public override double Maximum { get { return base.Maximum; } set { @@ -186,16 +186,24 @@ namespace Crow } cursor.Inflate (-1); } - + Point mouseDownInit; + double mouseDownInitValue; + #region mouse handling public override void onMouseDown (object sender, MouseButtonEventArgs e) { base.onMouseDown (sender, e); - + mouseDownInit = ScreenPointToLocal (e.Position); + mouseDownInitValue = Value; Rectangle cursInScreenCoord = ScreenCoordinates (cursor + Slot.Position); - if (cursInScreenCoord.ContainsOrIsEqual (e.Position)) + if (cursInScreenCoord.ContainsOrIsEqual (e.Position)){ +// Rectangle r = ClientRectangle; +// if (r.Width - _cursorSize > 0) { +// double unit = (Maximum - Minimum) / (double)(r.Width - _cursorSize); +// mouseDownInit += new Point ((int)(Value / unit), (int)(Value / unit)); +// } holdCursor = true; - else if (_orientation == Orientation.Horizontal) { + }else if (_orientation == Orientation.Horizontal) { if (e.Position.X < cursInScreenCoord.Left) Value -= LargeIncrement; else @@ -215,11 +223,25 @@ namespace Crow } public override void onMouseMove (object sender, MouseMoveEventArgs e) { - if (holdCursor) { - if (_orientation == Orientation.Horizontal) - Value += (double)e.XDelta / unity; - else - Value += (double)e.YDelta / unity; + if (holdCursor) { + Point m = ScreenPointToLocal (e.Position) - mouseDownInit; + Rectangle r = ClientRectangle; + + if (_orientation == Orientation.Horizontal) { + if (r.Width - _cursorSize == 0) + return; + double unit = (Maximum - Minimum) / (double)(r.Width - _cursorSize); + double tmp = mouseDownInitValue + (double)m.X * unit; + tmp -= tmp % SmallIncrement; + Value = tmp; + } else { + if (r.Height - _cursorSize == 0) + return; + double unit = (Maximum - Minimum) / (double)(r.Height - _cursorSize); + double tmp = mouseDownInitValue + (double)m.Y * unit; + tmp -= tmp % SmallIncrement; + Value = tmp; + } } base.onMouseMove (sender, e); diff --git a/src/GraphicObjects/Splitter.cs b/src/GraphicObjects/Splitter.cs index c688f773..84e1ade0 100644 --- a/src/GraphicObjects/Splitter.cs +++ b/src/GraphicObjects/Splitter.cs @@ -91,14 +91,14 @@ namespace Crow { base.onMouseEnter (sender, e); if ((Parent as GenericStack).Orientation == Orientation.Horizontal) - CurrentInterface.MouseCursor = XCursor.H; + IFace.MouseCursor = XCursor.H; else - CurrentInterface.MouseCursor = XCursor.V; + IFace.MouseCursor = XCursor.V; } public override void onMouseLeave (object sender, MouseMoveEventArgs e) { base.onMouseLeave (sender, e); - CurrentInterface.MouseCursor = XCursor.Default; + IFace.MouseCursor = XCursor.Default; } public override void onMouseDown (object sender, MouseButtonEventArgs e) { @@ -217,6 +217,20 @@ namespace Crow } return base.UpdateLayout (layoutType); } + public override bool PointIsIn (ref Point m) + { + if (!(Visible & IsEnabled)||IsDragged) + return false; + if (!Parent.PointIsIn(ref m)) + return false; + m -= (Parent.getSlot().Position + Parent.ClientRectangle.Position) ; + Rectangle r = Slot; + if (Width == Measure.Stretched) + r.Inflate (0, 5); + else + r.Inflate (5, 0); + return r.ContainsOrIsEqual (m); + } #endregion } } diff --git a/src/GraphicObjects/TabItem.cs b/src/GraphicObjects/TabItem.cs index eab0cb0d..473fc313 100644 --- a/src/GraphicObjects/TabItem.cs +++ b/src/GraphicObjects/TabItem.cs @@ -42,6 +42,8 @@ namespace Crow public event EventHandler QueryClose; + internal TabView tview = null; + #region Private fields GraphicObject titleWidget; int tabOffset; @@ -87,20 +89,9 @@ namespace Crow NotifyValueChanged ("ViewIndex", viewIndex); } } - - [XmlAttributeAttribute][DefaultValue("18")] - public virtual Measure TabThickness { - get { return tabThickness; } - set { - if (tabThickness == value) - return; - tabThickness = value; - NotifyValueChanged ("TabThickness", tabThickness); - RegisterForGraphicUpdate (); - } - } - [XmlAttributeAttribute][DefaultValue(0)] - public virtual int TabOffset { + + [DefaultValue(0)] + public int TabOffset { get { return tabOffset; } set { if (tabOffset == value) @@ -112,8 +103,13 @@ namespace Crow RegisterForGraphicUpdate (); } } - - [XmlAttributeAttribute][DefaultValue(false)] + public Measure TabHeight { + get { return tview == null ? Measure.Fit : tview.TabHeight; } + } + public Measure TabWidth { + get { return tview == null ? Measure.Fit : tview.TabWidth; } + } + [DefaultValue(false)] public virtual bool IsSelected { get { return isSelected; } set { @@ -127,20 +123,23 @@ namespace Crow { gr.Save (); - int spacing = (Parent as TabView).Spacing; + TabView tv = Parent as TabView; + + Rectangle r = TabTitle.Slot; + r.Width = TabWidth; - gr.MoveTo (0.5, TabTitle.Slot.Bottom-0.5); - gr.LineTo (TabTitle.Slot.Left - spacing, TabTitle.Slot.Bottom-0.5); + gr.MoveTo (0.5, r.Bottom-0.5); + gr.LineTo (r.Left - tv.LeftSlope, r.Bottom-0.5); gr.CurveTo ( - TabTitle.Slot.Left - spacing / 2, TabTitle.Slot.Bottom-0.5, - TabTitle.Slot.Left - spacing / 2, 0.5, - TabTitle.Slot.Left, 0.5); - gr.LineTo (TabTitle.Slot.Right, 0.5); + r.Left - tv.LeftSlope / 2, r.Bottom-0.5, + r.Left - tv.LeftSlope / 2, 0.5, + r.Left, 0.5); + gr.LineTo (r.Right, 0.5); gr.CurveTo ( - TabTitle.Slot.Right + spacing / 2, 0.5, - TabTitle.Slot.Right + spacing / 2, TabTitle.Slot.Bottom-0.5, - TabTitle.Slot.Right + spacing, TabTitle.Slot.Bottom-0.5); - gr.LineTo (Slot.Width-0.5, TabTitle.Slot.Bottom-0.5); + r.Right + tv.RightSlope / 2, 0.5, + r.Right + tv.RightSlope / 2, r.Bottom-0.5, + r.Right + tv.RightSlope, r.Bottom-0.5); + gr.LineTo (Slot.Width-0.5, r.Bottom-0.5); gr.LineTo (Slot.Width-0.5, Slot.Height-0.5); @@ -149,61 +148,138 @@ namespace Crow gr.LineWidth = 1; Foreground.SetAsSource (gr); gr.StrokePreserve (); - gr.Clip (); base.onDraw (gr); gr.Restore (); } + Point dragStartPoint; + int dragThreshold = 16; + int dis = 128; + internal TabView savedParent = null; + + void makeFloating (TabView tv) { + lock (IFace.UpdateMutex) { + ImageSurface di = new ImageSurface (Format.Argb32, dis, dis); + IFace.DragImageHeight = dis; + IFace.DragImageWidth = dis; + using (Context ctx = new Context (di)) { + double div = Math.Max (LastPaintedSlot.Width, LastPaintedSlot.Height); + double s = (double)dis / div; + ctx.Scale (s, s); + if (bmp == null) + this.onDraw (ctx); + else { + if (LastPaintedSlot.Width>LastPaintedSlot.Height) + ctx.SetSourceSurface (bmp, 0, (LastPaintedSlot.Width-LastPaintedSlot.Height)/2); + else + ctx.SetSourceSurface (bmp, (LastPaintedSlot.Height-LastPaintedSlot.Width)/2, 0); + + ctx.Paint (); + } + } + IFace.DragImage = di; + } + tv.RemoveChild (this); + savedParent = tv; + } + + public override ILayoutable Parent { + get { + return base.Parent; + } + set { + base.Parent = value; + if (value != null) { + dragStartPoint = IFace.Mouse.Position; + savedParent = value as TabView; + } + } + } + protected override void onStartDrag (object sender, DragDropEventArgs e) + { + base.onStartDrag (sender, e); + + dragStartPoint = IFace.Mouse.Position; + } + protected override void onEndDrag (object sender, DragDropEventArgs e) + { + base.onEndDrag (sender, e); + + if (Parent != null) + return; + + savedParent.AddChild (this); + + IFace.ClearDragImage (); + } + protected override void onDrop (object sender, DragDropEventArgs e) + { + base.onDrop (sender, e); + if (Parent != null) + return; + TabView tv = e.DropTarget as TabView; + if (tv == null) + return; + + IFace.ClearDragImage (); + + tv.AddChild (this); + } #region Mouse Handling - public bool HoldCursor = false; public override bool PointIsIn (ref Point m) { if (!base.PointIsIn (ref m)) return false; - if (m.Y < tabThickness) + if (m.Y < tview.TabHeight) return TabTitle.Slot.ContainsOrIsEqual (m); else return this.isSelected; } - public override void onMouseDown (object sender, MouseButtonEventArgs e) - { - base.onMouseDown (sender, e); - HoldCursor = true; - } public override void onMouseUp (object sender, MouseButtonEventArgs e) { base.onMouseUp (sender, e); - HoldCursor = false; - (Parent as TabView).UpdateLayout (LayoutingType.ArrangeChildren); + tview.UpdateLayout (LayoutingType.ArrangeChildren); } public override void onMouseMove (object sender, MouseMoveEventArgs e) { base.onMouseMove (sender, e); - if (!(HasFocus && HoldCursor)) + if (Parent == null) return; + + if (!IsDragged) + return; + TabView tv = Parent as TabView; - TabItem previous = null, next = null; + if (Math.Abs (e.Position.Y - dragStartPoint.Y) > dragThreshold || + Math.Abs (e.Position.X - dragStartPoint.X) > dragThreshold) { + makeFloating (tv); + return; + } + + Rectangle cb = ClientRectangle; + int tmp = TabOffset + e.XDelta; - if (tmp < tv.Spacing) - TabOffset = tv.Spacing; - else if (tmp > Parent.getSlot ().Width - TabTitle.Slot.Width - tv.Spacing) - TabOffset = Parent.getSlot ().Width - TabTitle.Slot.Width - tv.Spacing; - else{ + if (tmp < tview.LeftSlope) { + TabOffset = tview.LeftSlope; + } else if (tmp > cb.Width - tv.RightSlope - tv.TabWidth) { + TabOffset = cb.Width - tv.RightSlope - tv.TabWidth; + }else{ + dragStartPoint.X = e.Position.X; TabItem[] tabItms = tv.Children.Cast<TabItem>().OrderBy (t=>t.ViewIndex).ToArray(); if (ViewIndex > 0 && e.XDelta < 0) { - previous = tabItms [ViewIndex - 1]; - if (tmp < previous.TabOffset + previous.TabTitle.Slot.Width / 2) { + TabItem previous = tabItms [ViewIndex - 1]; + if (tmp < previous.TabOffset + tview.TabWidth / 2) { previous.ViewIndex = ViewIndex; ViewIndex--; tv.UpdateLayout (LayoutingType.ArrangeChildren); } }else if (ViewIndex < tabItms.Length - 1 && e.XDelta > 0) { - next = tabItms [ViewIndex + 1]; - if (tmp > next.TabOffset - next.TabTitle.Slot.Width / 2){ + TabItem next = tabItms [ViewIndex + 1]; + if (tmp > next.TabOffset - tview.TabWidth / 2){ next.ViewIndex = ViewIndex; ViewIndex++; tv.UpdateLayout (LayoutingType.ArrangeChildren); @@ -217,7 +293,7 @@ namespace Crow //if tab is used as a templated item root in a templatedGroup, local datasource //is not null, in this case, removing the data entries will delete automatically the item if (localDataSourceIsNull) - (Parent as TabView).DeleteChild (this); + (Parent as TabView)?.DeleteChild (this); } #endregion diff --git a/src/GraphicObjects/TabView.cs b/src/GraphicObjects/TabView.cs index abaa6ac0..304e820d 100644 --- a/src/GraphicObjects/TabView.cs +++ b/src/GraphicObjects/TabView.cs @@ -41,14 +41,16 @@ namespace Crow #endregion #region Private fields - int _spacing; - Measure tabThickness; + int adjustedTab = -1; + int leftSlope; + int rightSlope; + Measure tabHeight, tabWidth; Orientation _orientation; - int selectedTab = 0; + int selectedTab; #endregion #region public properties - [XmlAttributeAttribute()][DefaultValue(Orientation.Horizontal)] + [DefaultValue(Orientation.Horizontal)] public virtual Orientation Orientation { get { return _orientation; } @@ -60,30 +62,83 @@ namespace Crow if (_orientation == Orientation.Horizontal) NotifyValueChanged ("TabOrientation", Orientation.Vertical); else - NotifyValueChanged ("TabOrientation", Orientation.Horizontal); + NotifyValueChanged ("TabOrientation", Orientation.Horizontal); + this.RegisterForLayouting (LayoutingType.ArrangeChildren); + } + } + [DefaultValue(16)] + public int LeftSlope + { + get { return leftSlope; } + set { + if (leftSlope == value) + return; + leftSlope = value; + NotifyValueChanged ("leftSlope", leftSlope); + tabSizeHasChanged = true; + //RegisterForLayouting (LayoutingType.ArrangeChildren); } } - [XmlAttributeAttribute()][DefaultValue(16)] - public int Spacing + bool tabSizeHasChanged = false; + [DefaultValue(16)] + public int RightSlope { - get { return _spacing; } + get { return rightSlope; } + set { + if (rightSlope == value) + return; + rightSlope = value; + NotifyValueChanged ("RightSlope", rightSlope); + tabSizeHasChanged = true; + //RegisterForLayouting (LayoutingType.ArrangeChildren); + } + } + [DefaultValue("18")] + public Measure TabHeight { + get { return tabHeight; } set { - if (_spacing == value) + if (tabHeight == value) return; - _spacing = value; - NotifyValueChanged ("Spacing", Spacing); + tabHeight = value; + NotifyValueChanged ("TabHeight", tabHeight); +// childrenRWLock.EnterReadLock (); +// foreach (GraphicObject ti in Children) { +// ti.NotifyValueChanged ("TabHeight", tabHeight); +// } +// childrenRWLock.ExitReadLock (); + RegisterForLayouting (LayoutingType.ArrangeChildren); } } - [XmlAttributeAttribute()][DefaultValue(0)] + [DefaultValue("120")] + public Measure TabWidth { + get { return adjustedTab > 0 ? (Measure)adjustedTab : tabWidth; } + set { + if (tabWidth == value) + return; + tabWidth = value; + NotifyValueChanged ("TabWidth", TabWidth); +// +// childrenRWLock.EnterReadLock (); +// foreach (GraphicObject ti in Children) { +// ti.NotifyValueChanged ("TabWidth", tabWidth); +// } +// childrenRWLock.ExitReadLock (); + RegisterForLayouting (LayoutingType.ArrangeChildren); + } + } + public virtual int SelectedTab { get { return selectedTab; } set { - if (selectedTab < Children.Count && SelectedTab >= 0) + if (value == selectedTab) + return; + + if (selectedTab < Children.Count && selectedTab >= 0) (Children [selectedTab] as TabItem).IsSelected = false; selectedTab = value; - if (selectedTab < Children.Count && SelectedTab >= 0) + if (selectedTab < Children.Count && selectedTab >= 0) (Children [selectedTab] as TabItem).IsSelected = true; NotifyValueChanged ("SelectedTab", selectedTab); @@ -92,12 +147,6 @@ namespace Crow } #endregion - void Ti_TabTitle_LayoutChanged (object sender, LayoutingEventArgs e) - { - if (e.LayoutType == LayoutingType.Width) - this.RegisterForLayouting (LayoutingType.ArrangeChildren); - } - public override void AddChild (GraphicObject child) { TabItem ti = child as TabItem; @@ -106,13 +155,14 @@ namespace Crow ti.MouseDown += Ti_MouseDown; ti.TabTitle.LayoutChanged += Ti_TabTitle_LayoutChanged; + ti.tview = this; base.AddChild (child); SelectedTab = ti.ViewIndex = Children.Count - 1; + this.RegisterForLayouting (LayoutingType.ArrangeChildren); } - - public override void DeleteChild (GraphicObject child) + public override void RemoveChild (GraphicObject child) { TabItem ti = child as TabItem; if (ti == null) @@ -120,11 +170,30 @@ namespace Crow ti.MouseDown -= Ti_MouseDown; ti.TabTitle.LayoutChanged -= Ti_TabTitle_LayoutChanged; + ti.tview = null; - if (selectedTab > Children.Count - 2) - SelectedTab--; - - base.DeleteChild (child); + childrenRWLock.EnterReadLock (); + + TabItem[] tabItms = Children.Cast<TabItem>().OrderBy (t=>t.ViewIndex).ToArray(); + int selTabViewIdx = -1; + + if (SelectedTab < tabItms.Length && SelectedTab >= 0) + selTabViewIdx = (Children [SelectedTab] as TabItem).ViewIndex; + + for (int i = selTabViewIdx+1; i < tabItms.Length; i++) + tabItms [i].ViewIndex--; + + if (selTabViewIdx > tabItms.Length - 2) + selTabViewIdx = tabItms.Length - 2; + + if (selTabViewIdx < 0) + SelectedTab = -1; + else + SelectedTab = Children.IndexOf (tabItms [selTabViewIdx]); + + childrenRWLock.ExitReadLock (); + + base.RemoveChild (child); } public override bool ArrangeChildren { get { return true; } } @@ -132,34 +201,62 @@ namespace Crow { RegisteredLayoutings &= (~layoutType); - if (layoutType == LayoutingType.ArrangeChildren) { - int curOffset = Spacing; + if (layoutType == LayoutingType.ArrangeChildren && Children.Count > 0) { + Rectangle cb = ClientRectangle; + + int tabSpace = tabWidth + leftSlope; + int tc = Children.Count (c => c.Visible == true); + + if (tc > 0) + tabSpace = Math.Min(tabSpace, (cb.Width-rightSlope) / tc); + + if (tabSpace < tabWidth + leftSlope) + adjustedTab = tabSpace - leftSlope; + else + adjustedTab = -1; + + //Console.WriteLine ("tabspace: {0} tw:{1}", tabSpace, tabWidth); + + childrenRWLock.EnterReadLock(); TabItem[] tabItms = Children.Cast<TabItem>().OrderBy (t=>t.ViewIndex).ToArray(); + childrenRWLock.ExitReadLock(); + int curOffset = leftSlope; + for (int i = 0; i < tabItms.Length; i++) { if (!tabItms [i].Visible) continue; - if (!tabItms [i].HoldCursor) + tabItms [i].NotifyValueChanged ("TabHeight", tabHeight); + tabItms [i].NotifyValueChanged ("TabWidth", TabWidth); + if (!tabItms [i].IsDragged) { tabItms [i].TabOffset = curOffset; - if (Orientation == Orientation.Horizontal) { - if (tabItms [i].TabTitle.RegisteredLayoutings.HasFlag (LayoutingType.Width)) - return false; - curOffset += tabItms [i].TabTitle.Slot.Width + Spacing; - } else { - if (tabItms [i].TabTitle.RegisteredLayoutings.HasFlag (LayoutingType.Height)) - return false; - curOffset += tabItms [i].TabTitle.Slot.Height + Spacing; + //Console.WriteLine ("offset: {0}=>{1}", tabItms [i].Name, tabItms [i].TabOffset); } + if (Orientation == Orientation.Horizontal) { + curOffset += tabSpace; + } else + curOffset += tabSpace; } //if no layouting remains in queue for item, registre for redraw if (RegisteredLayoutings == LayoutingType.None && IsDirty) - CurrentInterface.EnqueueForRepaint (this); + IFace.EnqueueForRepaint (this); return true; } return base.UpdateLayout(layoutType); } + public override void OnLayoutChanges (LayoutingType layoutType) + { + if (_orientation == Orientation.Horizontal) { + if (layoutType == LayoutingType.Width) + RegisterForLayouting (LayoutingType.ArrangeChildren); + } else if (layoutType == LayoutingType.Height) + RegisterForLayouting (LayoutingType.ArrangeChildren); + + base.OnLayoutChanges (layoutType); + } + protected override void onDraw (Context gr) { Rectangle rBack = new Rectangle (Slot.Size); @@ -178,48 +275,59 @@ namespace Crow childrenRWLock.EnterReadLock (); - TabItem[] tabItms = Children.Cast<TabItem> ().OrderBy (t => t.ViewIndex).ToArray (); - for (int i = 0; i < tabItms.Length; i++) { - if (tabItms [i] == Children [SelectedTab]) - continue; - tabItms [i].Paint (ref gr); - } + TabItem[] tabItms = Children.Where(tt=>tt.Visible).Cast<TabItem> (). + OrderBy (t => t.ViewIndex).ToArray (); + int selTabViewIdx = -1; if (SelectedTab < tabItms.Length && SelectedTab >= 0) - Children [SelectedTab].Paint (ref gr); + selTabViewIdx = (Children [SelectedTab] as TabItem).ViewIndex; childrenRWLock.ExitReadLock (); + + int i = 0; + while (i < selTabViewIdx) { + tabItms [i].Paint (ref gr); + i++; + } + i = tabItms.Length - 1; + while (i > selTabViewIdx) { + tabItms [i].Paint (ref gr); + i--; + } + + if (selTabViewIdx >= 0) + tabItms [selTabViewIdx].Paint (ref gr); gr.Restore (); } - #region Mouse handling - public override void checkHoverWidget (MouseMoveEventArgs e) + protected override void onDragEnter (object sender, DragDropEventArgs e) { - if (CurrentInterface.HoverWidget != this) { - CurrentInterface.HoverWidget = this; - onMouseEnter (this, e); - } + base.onDragEnter (sender, e); - if (SelectedTab > Children.Count - 1) + TabItem ti = e.DragSource as TabItem; + if (ti == null) return; - - if (((Children[SelectedTab] as TabItem).Content.Parent as GraphicObject).MouseIsIn(e.Position)) - { - Children[SelectedTab].checkHoverWidget (e); + if (ti.Parent != null || ti.savedParent == this) return; - } - TabItem[] tabItms = Children.Cast<TabItem>().OrderBy (t=>t.ViewIndex).ToArray(); - for (int i = tabItms.Length - 1; i >= 0; i--) { - if (tabItms [i].TabTitle.MouseIsIn(e.Position)) - { - tabItms [i].checkHoverWidget (e); - return; - } - } + + this.AddChild (ti); + + Point p = ScreenPointToLocal (IFace.Mouse.Position) - Margin; + + p.X = Math.Max (leftSlope, p.X); + p.X = Math.Min (ClientRectangle.Width - rightSlope - TabWidth, p.X); + ti.TabOffset = p.X; + + IFace.ClearDragImage (); + } - #endregion + void Ti_TabTitle_LayoutChanged (object sender, LayoutingEventArgs e) + { + if (e.LayoutType == LayoutingType.X) + RegisterForLayouting (LayoutingType.ArrangeChildren); + } void Ti_MouseDown (object sender, MouseButtonEventArgs e) { SelectedTab = Children.IndexOf (sender as GraphicObject); diff --git a/src/GraphicObjects/TemplatedContainer.cs b/src/GraphicObjects/TemplatedContainer.cs index 3e0dd801..a779595d 100644 --- a/src/GraphicObjects/TemplatedContainer.cs +++ b/src/GraphicObjects/TemplatedContainer.cs @@ -38,6 +38,18 @@ namespace Crow /// </summary> public class TemplatedContainer : TemplatedControl { + #if DESIGN_MODE + public override void getIML (System.Xml.XmlDocument doc, System.Xml.XmlNode parentElem) + { + if (this.design_isTGItem) + return; + base.getIML (doc, parentElem); + if (!HasContent) + return; + Content.getIML (doc, parentElem.LastChild); + } + #endif + #region CTOR protected TemplatedContainer() : base(){} public TemplatedContainer (Interface iface) : base(iface){} diff --git a/src/GraphicObjects/TemplatedControl.cs b/src/GraphicObjects/TemplatedControl.cs index 34e4ce07..54991a41 100644 --- a/src/GraphicObjects/TemplatedControl.cs +++ b/src/GraphicObjects/TemplatedControl.cs @@ -43,6 +43,20 @@ namespace Crow /// </summary> public abstract class TemplatedControl : PrivateContainer { + #if DESIGN_MODE + public bool design_inlineTemplate = false; + public override void getIML (System.Xml.XmlDocument doc, System.Xml.XmlNode parentElem) + { + if (this.design_isTGItem) + return; + base.getIML (doc, parentElem); + if (child == null || !design_inlineTemplate) + return; + XmlElement xe = doc.CreateElement("Template"); + child.getIML (doc, xe); + parentElem.LastChild.AppendChild (xe); + } + #endif #region CTOR protected TemplatedControl() : base(){} public TemplatedControl (Interface iface) : base(iface){} @@ -66,7 +80,7 @@ namespace Crow if (string.IsNullOrEmpty(_template)) loadTemplate (); else - loadTemplate (CurrentInterface.Load (_template)); + loadTemplate (IFace.Load (_template)); } } /// <summary> @@ -133,9 +147,9 @@ namespace Crow this.ClearTemplateBinding(); if (template == null) { - if (!Interface.DefaultTemplates.ContainsKey (this.GetType ().FullName)) + if (!IFace.DefaultTemplates.ContainsKey (this.GetType ().FullName)) throw new Exception (string.Format ("No default template found for '{0}'", this.GetType ().FullName)); - this.SetChild (CurrentInterface.Load (Interface.DefaultTemplates[this.GetType ().FullName])); + this.SetChild (IFace.Load (IFace.DefaultTemplates[this.GetType ().FullName])); }else this.SetChild (template); } diff --git a/src/GraphicObjects/TemplatedGroup.cs b/src/GraphicObjects/TemplatedGroup.cs index 8025435d..f7c93763 100644 --- a/src/GraphicObjects/TemplatedGroup.cs +++ b/src/GraphicObjects/TemplatedGroup.cs @@ -40,6 +40,24 @@ namespace Crow { public abstract class TemplatedGroup : TemplatedControl { + #if DESIGN_MODE + public override void getIML (System.Xml.XmlDocument doc, System.Xml.XmlNode parentElem) + { + if (this.design_isTGItem) + return; + base.getIML (doc, parentElem); + + if (string.IsNullOrEmpty(_itemTemplate)) { + foreach (ItemTemplate it in ItemTemplates.Values) + it.getIML (doc, parentElem.LastChild); + } + + foreach (GraphicObject g in Items) { + g.getIML (doc, parentElem.LastChild); + } + } + #endif + #region CTOR protected TemplatedGroup() : base(){} public TemplatedGroup (Interface iface) : base(iface){} @@ -130,7 +148,7 @@ namespace Crow : items.Children; } } - [XmlAttributeAttribute][DefaultValue(-1)]public int SelectedIndex{ + [XmlAttributeAttribute][DefaultValue(-1)]public virtual int SelectedIndex{ get { return _selectedIndex; } set { if (value == _selectedIndex) @@ -427,17 +445,21 @@ namespace Crow iTemp = ItemTemplates ["default"]; } - //lock (CurrentInterface.LayoutMutex) { - g = iTemp.CreateInstance(CurrentInterface); + lock (IFace.LayoutMutex) { + g = iTemp.CreateInstance(); + #if DESIGN_MODE + g.design_isTGItem = true; + #endif page.AddChild (g); // if (isPaged) g.LogicalParent = this; g.MouseDown += itemClick; - //} + } if (iTemp.Expand != null && g is Expandable) { - (g as Expandable).Expand += iTemp.Expand; - (g as Expandable).GetIsExpandable = iTemp.HasSubItems; + Expandable e = g as Expandable; + e.Expand += iTemp.Expand; + e.GetIsExpandable = iTemp.HasSubItems; } g.DataSource = o; diff --git a/src/GraphicObjects/TextBox.cs b/src/GraphicObjects/TextBox.cs index a14aea6a..e29ff9bf 100644 --- a/src/GraphicObjects/TextBox.cs +++ b/src/GraphicObjects/TextBox.cs @@ -86,7 +86,7 @@ namespace Crow if (!MoveRight ()) return; }else if (e.Shift) - CurrentInterface.Clipboard = this.SelectedText; + IFace.Clipboard = this.SelectedText; this.DeleteChar (); break; case Key.Enter: @@ -135,9 +135,9 @@ namespace Crow break; case Key.Insert: if (e.Shift) - this.Insert (CurrentInterface.Clipboard); + this.Insert (IFace.Clipboard); else if (e.Control && !selectionIsEmpty) - CurrentInterface.Clipboard = this.SelectedText; + IFace.Clipboard = this.SelectedText; break; case Key.Left: if (e.Shift) { diff --git a/src/GraphicObjects/TextRun.cs b/src/GraphicObjects/TextRun.cs index 69495647..17e3b770 100644 --- a/src/GraphicObjects/TextRun.cs +++ b/src/GraphicObjects/TextRun.cs @@ -36,6 +36,7 @@ using System.ComponentModel; namespace Crow { + [DesignIgnore] public class TextRun : GraphicObject { #region CTOR diff --git a/src/GraphicObjects/Window.cs b/src/GraphicObjects/Window.cs index bbfb196d..56632ff3 100644 --- a/src/GraphicObjects/Window.cs +++ b/src/GraphicObjects/Window.cs @@ -47,11 +47,12 @@ namespace Crow } string _icon; - bool _resizable; - bool _movable; + bool resizable; + bool movable; + bool modal; protected bool hoverBorder = false; bool alwaysOnTop = false; - Fill titleBarBackground = Color.UnitedNationsBlue; + Fill titleBarBackground = Color.SteelBlue; Fill titleBarForeground = Color.White; Rectangle savedBounds; @@ -96,7 +97,7 @@ namespace Crow /// <summary> /// Background of the title bar if any. /// </summary> - [XmlAttributeAttribute][DefaultValue("vgradient|0:Onyx|1:UnitedNationsBlue")] + [XmlAttributeAttribute][DefaultValue("vgradient|0:Onyx|1:SteelBlue")] public virtual Fill TitleBarBackground { get { return titleBarBackground; } set { @@ -124,25 +125,37 @@ namespace Crow [XmlAttributeAttribute][DefaultValue(true)] public bool Resizable { get { - return _resizable; + return resizable; } set { - if (_resizable == value) + if (resizable == value) return; - _resizable = value; - NotifyValueChanged ("Resizable", _resizable); + resizable = value; + NotifyValueChanged ("Resizable", resizable); } } [XmlAttributeAttribute][DefaultValue(true)] public bool Movable { get { - return _movable; + return movable; } set { - if (_movable == value) + if (movable == value) return; - _movable = value; - NotifyValueChanged ("Movable", _movable); + movable = value; + NotifyValueChanged ("Movable", movable); + } + } + [XmlAttributeAttribute][DefaultValue(false)] + public bool Modal { + get { + return modal; + } + set { + if (modal == value) + return; + modal = value; + NotifyValueChanged ("Modal", modal); } } [XmlAttributeAttribute][DefaultValue(false)] @@ -167,17 +180,18 @@ namespace Crow [XmlAttributeAttribute][DefaultValue(false)] public bool AlwaysOnTop { get { - return alwaysOnTop; + return modal ? true : alwaysOnTop; } set { if (alwaysOnTop == value) return; + alwaysOnTop = value; - if (alwaysOnTop && Parent != null) - CurrentInterface.PutOnTop (this); + if (AlwaysOnTop && Parent != null) + IFace.PutOnTop (this); - NotifyValueChanged ("AlwaysOnTop", alwaysOnTop); + NotifyValueChanged ("AlwaysOnTop", AlwaysOnTop); } } // [XmlAttributeAttribute()][DefaultValue(WindowState.Normal)] @@ -278,15 +292,15 @@ namespace Crow { base.onMouseMove (sender, e); - Interface otkgw = CurrentInterface; + Interface otkgw = IFace; if (!hoverBorder) { currentDirection = Direction.None; - CurrentInterface.MouseCursor = XCursor.Default; + IFace.MouseCursor = XCursor.Default; return; } - if (this.HasFocus && _movable) { + if (this.HasFocus && movable) { if (e.Mouse.IsButtonDown (MouseButton.Left)) { MoveAndResize (e.XDelta, e.YDelta, currentDirection); return; @@ -353,10 +367,14 @@ namespace Crow { base.onMouseDown (sender, e); } + public override bool MouseIsIn (Point m) + { + return modal ? true : base.MouseIsIn (m); + } #endregion protected void onMaximized (object sender, EventArgs e){ - lock (CurrentInterface.LayoutMutex) { + lock (IFace.LayoutMutex) { if (!IsMinimized) savedBounds = this.LastPaintedSlot; this.Left = this.Top = 0; @@ -372,7 +390,7 @@ namespace Crow Maximized.Raise (sender, e); } protected void onUnmaximized (object sender, EventArgs e){ - lock (CurrentInterface.LayoutMutex) { + lock (IFace.LayoutMutex) { this.Left = savedBounds.Left; this.Top = savedBounds.Top; this.Width = savedBounds.Width; @@ -387,7 +405,7 @@ namespace Crow Unmaximized.Raise (sender, e); } protected void onMinimized (object sender, EventArgs e){ - lock (CurrentInterface.LayoutMutex) { + lock (IFace.LayoutMutex) { if (IsNormal) savedBounds = this.LastPaintedSlot; Width = 200; @@ -405,7 +423,7 @@ namespace Crow { hoverBorder = false; currentDirection = Direction.None; - CurrentInterface.MouseCursor = XCursor.Default; + IFace.MouseCursor = XCursor.Default; } protected virtual void onBorderMouseEnter (object sender, MouseMoveEventArgs e) { @@ -415,18 +433,33 @@ namespace Crow protected void butQuitPress (object sender, MouseButtonEventArgs e) { - CurrentInterface.MouseCursor = XCursor.Default; + IFace.MouseCursor = XCursor.Default; close (); } - protected void close(){ + protected virtual void close(){ Closing.Raise (this, null); if (Parent is Interface) (Parent as Interface).DeleteWidget (this); - else if (Parent is Group) - (Parent as Group).DeleteChild (this); - else if (Parent is PrivateContainer) - (Parent as Container).Child = null; + else { + GraphicObject p = Parent as GraphicObject; + if (p is Group) { + lock (IFace.UpdateMutex) { + RegisterClip (p.ScreenCoordinates (p.LastPaintedSlot)); + (p as Group).DeleteChild (this); + } + //(Parent as Group).RegisterForRedraw (); + } else if (Parent is PrivateContainer) + (Parent as Container).Child = null; + } + } + + public static Window Show (Interface iface, string imlPath, bool modal = false){ + lock (iface.UpdateMutex) { + Window w = iface.AddWidget (imlPath) as Window; + w.Modal = modal; + return w; + } } } } diff --git a/src/GraphicObjects/Wrapper.cs b/src/GraphicObjects/Wrapper.cs index 4fff17ff..a7f5f73b 100644 --- a/src/GraphicObjects/Wrapper.cs +++ b/src/GraphicObjects/Wrapper.cs @@ -104,7 +104,7 @@ namespace Crow this.RegisterForLayouting (LayoutingType.Width); break; case LayoutingType.Height: - if (Orientation == Orientation.Vertical && go.Height.Units == Unit.Percent) { + if (Orientation == Orientation.Vertical && go.Height.IsRelativeToParent) { go.Height = Measure.Fit; return; } @@ -137,7 +137,7 @@ namespace Crow foreach (GraphicObject c in Children) { if (!c.Visible) continue; - if (c.Height.Units == Unit.Percent && + if (c.Height.IsRelativeToParent && c.RegisteredLayoutings.HasFlag (LayoutingType.Height)) { childrenRWLock.ExitReadLock(); return -1; @@ -172,7 +172,7 @@ namespace Crow foreach (GraphicObject c in Children) { if (!c.Visible) continue; - if (c.Width.Units == Unit.Percent && + if (c.Width.IsRelativeToParent && c.RegisteredLayoutings.HasFlag (LayoutingType.Width)) { childrenRWLock.ExitReadLock(); return -1; @@ -207,7 +207,7 @@ namespace Crow //if no layouting remains in queue for item, registre for redraw if (RegisteredLayoutings == LayoutingType.None && IsDirty) - CurrentInterface.EnqueueForRepaint (this); + IFace.EnqueueForRepaint (this); return true; } @@ -217,13 +217,13 @@ namespace Crow public override void OnLayoutChanges (LayoutingType layoutType) { #if DEBUG_LAYOUTING - CurrentInterface.currentLQI.Slot = LastSlots; - CurrentInterface.currentLQI.Slot = Slot; + IFace.currentLQI.Slot = LastSlots; + IFace.currentLQI.Slot = Slot; #endif switch (layoutType) { case LayoutingType.Width: foreach (GraphicObject c in Children) { - if (c.Width.Units == Unit.Percent) + if (c.Width.IsRelativeToParent) c.RegisterForLayouting (LayoutingType.Width); } if (Height == Measure.Fit) @@ -232,7 +232,7 @@ namespace Crow break; case LayoutingType.Height: foreach (GraphicObject c in Children) { - if (c.Height.Units == Unit.Percent) + if (c.Height.IsRelativeToParent) c.RegisterForLayouting (LayoutingType.Height); } if (Width == Measure.Fit) |