]> O.S.I.I.S - jp/crow.git/commitdiff
improve dragNdrop, debug docking
authorJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Wed, 17 Mar 2021 01:20:56 +0000 (02:20 +0100)
committerJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Wed, 17 Mar 2021 01:20:56 +0000 (02:20 +0100)
12 files changed:
Crow/src/EventArgs/DragDropEventArgs.cs
Crow/src/Interface.cs
Crow/src/Widgets/DockStack.cs
Crow/src/Widgets/DockWindow.cs
Crow/src/Widgets/Group.cs
Crow/src/Widgets/MenuItem.cs
Crow/src/Widgets/Popper.cs
Crow/src/Widgets/TabItem.cs
Crow/src/Widgets/Widget.cs
Samples/dockableWindows/dockableWindows.cs
Samples/dockableWindows/ui/test.crow
Samples/dragNdrop/dragNdrop.cs

index 3a505527098157391acb9908ccec06dfe953bf6a..3bca5c239fee730070178c085a27759045cd07d6 100644 (file)
@@ -29,7 +29,7 @@ namespace Crow
 
                public override string ToString ()
                {
-                       return string.Format ("{0} => {1}", DragSource,DropTarget);
+                       return string.Format ("{0} => {1}", DragSource, DropTarget);
                }
        }
 }
index 66b9b594546b4daba6a8d9b445f56fb722209902..63a86a14a68cfa676a6f4212a75f391f34b20a59 100644 (file)
@@ -460,7 +460,10 @@ namespace Crow
 
                public List<CrowThread> CrowThreads = new List<CrowThread>();//used to monitor thread finished
 
+               public bool DragAndDropInProgress => DragAndDropOperation != null;
                public DragDropEventArgs DragAndDropOperation = null;
+               internal Widget dragndropHover;
+
                public Surface DragImage = null;
                public int DragImageWidth, DragImageHeight, DragImageX, DragImageY;
                public void ClearDragImage () {
@@ -763,14 +766,16 @@ namespace Crow
                /// , it can not lose focus while Active</summary>
                public Widget ActiveWidget
                {
-                       get { return _activeWidget; }
+                       get => _activeWidget;
                        internal set
                        {
                                if (_activeWidget == value)
                                        return;
 
-                               if (_activeWidget != null)
+                               if (_activeWidget != null) {
+                                       debugRegisterClip (_activeWidget);
                                        _activeWidget.IsActive = false;
+                               }
 
                                _activeWidget = value;
 
@@ -784,20 +789,22 @@ namespace Crow
                /// <summary>Pointer is over the widget</summary>
                public virtual Widget HoverWidget
                {
-                       get { return _hoverWidget; }
+                       get => _hoverWidget;
                        set {
                                if (_hoverWidget == value)
                                        return;
 
-                               if (_hoverWidget != null)
+                               if (_hoverWidget != null) {
+                                       debugRegisterClip (_hoverWidget);
                                        _hoverWidget.IsHover = false;
+                               }
 
                                _hoverWidget = value;
 
                                NotifyValueChanged ("HoverWidget", _hoverWidget);
                                DbgLogger.AddEvent (DbgEvtType.HoverWidget, _hoverWidget);
 
-                               if (DragAndDropOperation == null && FOCUS_ON_HOVER) {
+                               if (FOCUS_ON_HOVER) {
                                        Widget w = _hoverWidget;
                                        while (w != null) {
                                                if (w.Focusable) {
@@ -818,8 +825,10 @@ namespace Crow
                        set {
                                if (_focusedWidget == value)
                                        return;
-                               if (_focusedWidget != null)
+                               if (_focusedWidget != null) {
+                                       debugRegisterClip (_focusedWidget);
                                        _focusedWidget.HasFocus = false;
+                               }
                                _focusedWidget = value;
 
                                NotifyValueChanged ("FocusedWidget", _focusedWidget);                           
@@ -1017,11 +1026,37 @@ namespace Crow
                        }
 
                        drawTextCursor (ctx);
+
+                       debugHighlightFocus (ctx);
                        
                        DbgLogger.EndEvent (DbgEvtType.Drawing, true);
                }
                #endregion
 
+               [Conditional ("DEBUG_HIGHLIGHT_FOCUS")]
+               internal void debugRegisterClip (Widget w) {
+                       RegisterClip (w.ScreenCoordinates (w.Slot));
+               }
+               [Conditional ("DEBUG_HIGHLIGHT_FOCUS")]
+               void debugHighlightFocus (Context ctx) {
+                       if (HoverWidget!= null) {
+                               ctx.SetSource (Colors.Purple);
+                               ctx.Rectangle (HoverWidget.ScreenCoordinates (HoverWidget.Slot), 1);
+                       }
+                       if (FocusedWidget != null) {
+                               ctx.SetSource (Colors.Blue);
+                               ctx.Rectangle (FocusedWidget.ScreenCoordinates (FocusedWidget.Slot), 1);
+                       }
+                       if (ActiveWidget != null) {
+                               ctx.SetSource (Colors.Yellow);
+                               ctx.Rectangle (ActiveWidget.ScreenCoordinates (ActiveWidget.Slot), 1);
+                       }
+                       /*if (DragAndDropInProgress) {
+
+            }*/
+                       surf.Flush ();
+               }
+
                #region Blinking text cursor
                /// <summary>
                /// Text cursor blinking frequency.
@@ -1317,6 +1352,17 @@ namespace Crow
                Point stickyMouseDelta = default;
                internal Widget stickedWidget = null;
 
+               Widget HoverOrDropTarget {
+                       get => DragAndDropInProgress ? dragndropHover : HoverWidget;
+                       set {
+                               if (DragAndDropInProgress) {
+                                       dragndropHover = value;
+                               } else
+                                       HoverWidget = value;
+            }
+        }
+               
+
                /// <summary>Processes mouse move events from the root container, this function
                /// should be called by the host on mouse move event to forward events to crow interfaces</summary>
                /// <returns>true if mouse is in the interface</returns>
@@ -1325,78 +1371,89 @@ namespace Crow
                        int deltaX = x - MousePosition.X;
                        int deltaY = y - MousePosition.Y;
 
-                       if (stickedWidget != null && _activeWidget == null) {
-                               stickyMouseDelta.X += deltaX;
-                               stickyMouseDelta.Y += deltaY;                           
+                       if (!DragAndDropInProgress) {
+                               if (stickedWidget != null && ActiveWidget == null) {
+                                       stickyMouseDelta.X += deltaX;
+                                       stickyMouseDelta.Y += deltaY;
 
-                               if (Math.Abs (stickyMouseDelta.X) > stickedWidget.StickyMouse || Math.Abs (stickyMouseDelta.Y) > stickedWidget.StickyMouse) {
-                                       stickedWidget = null;
-                                       stickyMouseDelta = default;
-                               } else {
-                                       Glfw3.SetCursorPosition (hWin, MousePosition.X, MousePosition.Y);
-                                       return true;
+                                       if (Math.Abs (stickyMouseDelta.X) > stickedWidget.StickyMouse || Math.Abs (stickyMouseDelta.Y) > stickedWidget.StickyMouse) {
+                                               stickedWidget = null;
+                                               stickyMouseDelta = default;
+                                       } else {
+                                               Glfw3.SetCursorPosition (hWin, MousePosition.X, MousePosition.Y);
+                                               return true;
+                                       }
                                }
                        }
 
                        MousePosition = new Point (x, y);
                        MouseMoveEventArgs e = new MouseMoveEventArgs (x, y, deltaX, deltaY);
 
-                       if (DragAndDropOperation != null)//drag source cant have hover event, so move has to be handle here
-                               DragAndDropOperation.DragSource.onMouseMove (this, e);
-                       else if (ActiveWidget != null) {
+                       if (!(DragAndDropInProgress || ActiveWidget == null)) {
                                //TODO, ensure object is still in the graphic tree
                                //send move evt even if mouse move outside bounds
-                               _activeWidget.onMouseMove (this, e);
+                               ActiveWidget.onMouseMove (this, e);
                                return true;
                        }
 
-                       if (_hoverWidget != null) {
+                       if (HoverOrDropTarget != null) {
                                resetTooltip ();
-                               //check topmost graphicobject first
-                               Widget tmp = _hoverWidget;
-                               Widget topc = null;
-                               while (tmp is Widget) {
-                                       topc = tmp;
-                                       tmp = tmp.LogicalParent as Widget;
-                               }
-                               int idxhw = GraphicTree.IndexOf (topc);
-                               if (idxhw != 0) {
-                                       int i = 0;
-                                       while (i < idxhw) {
-                                               //if logical parent of top container is a widget, that's a popup
+
+                               //check topmost graphicobject first                             
+                               Widget topContainer = HoverOrDropTarget;
+                               while (topContainer.LogicalParent is Widget w)
+                                       topContainer = w;                                       
+                               
+                               int indexOfTopContainer = GraphicTree.IndexOf (topContainer);
+                               if (indexOfTopContainer != 0) {
+                    for (int i = 0; i < indexOfTopContainer; i++) {
+                                               //if logical parent of top container is a Interface, that's not a popup.
                                                if (GraphicTree [i].LogicalParent is Interface) {
                                                        if (GraphicTree [i].MouseIsIn (e.Position)) {
-                                                               while (_hoverWidget != null) {
-                                                                       _hoverWidget.onMouseLeave (_hoverWidget, e);
-                                                                       HoverWidget = _hoverWidget.FocusParent;
-                                                               }
-
-                                                               GraphicTree [i].checkHoverWidget (e);
-                                                               _hoverWidget.onMouseMove (this, e);
+                                                               //mouse is in another top container than the actual one,
+                                                               //so we must leave first the current top container starting from HoverWidget
+                                                               if (DragAndDropInProgress) {
+                                                                       DragAndDropOperation.DropTarget?.onDragLeave (this, DragAndDropOperation);
+                                                                       GraphicTree[i].checkHoverWidget (e);
+                                                                       DragAndDropOperation.DragSource.onDrag (this, e);
+                                                               } else {
+                                                                       while (HoverWidget != null) {
+                                                                               HoverWidget.onMouseLeave (this, e);
+                                                                               HoverWidget = HoverWidget.FocusParent;
+                                                                       }
+                                                                       GraphicTree[i].checkHoverWidget (e);
+                                                                       HoverWidget.onMouseMove (this, e);
+                                                               }                                                                       
                                                                return true;
                                                        }
                                                }
-                                               i++;
                                        }
                                }
 
-                               if (_hoverWidget.MouseIsIn (e.Position)) {
-                                       _hoverWidget.checkHoverWidget (e);
-                                       _hoverWidget.onMouseMove (this, e);
+                               if (HoverOrDropTarget.MouseIsIn (e.Position)) {
+                                       HoverOrDropTarget.checkHoverWidget (e);
+                                       if (DragAndDropInProgress)
+                                               DragAndDropOperation.DragSource.onDrag (this, e);
+                                       else
+                                               HoverWidget.onMouseMove (this, e);
                                        return true;
-                               }
-                               _hoverWidget.onMouseLeave (_hoverWidget, e);
-                               //seek upward from last focused graph obj's
-                               tmp = _hoverWidget.FocusParent;
-                               while (tmp != null) {
-                                       HoverWidget = tmp;
-                                       if (_hoverWidget.MouseIsIn (e.Position)) {
-                                               _hoverWidget.checkHoverWidget (e);
-                                               _hoverWidget.onMouseMove (_hoverWidget, e);
-                                               return true;
+                               } else {
+                                       if (DragAndDropInProgress && dragndropHover == DragAndDropOperation.DropTarget)
+                                               DragAndDropOperation.DropTarget.onDragLeave (this, DragAndDropOperation);
+                                       //seek upward from last focused graph obj's     
+                                       while (HoverOrDropTarget.FocusParent != null) {
+                                               if (!DragAndDropInProgress)
+                                                       HoverWidget.onMouseLeave (this, e);
+                                               HoverOrDropTarget = HoverOrDropTarget.FocusParent;
+                                               if (HoverOrDropTarget.MouseIsIn (e.Position)) {
+                                                       HoverOrDropTarget.checkHoverWidget (e);
+                                                       if (DragAndDropInProgress)
+                                                               DragAndDropOperation.DragSource?.onDrag (this, e);
+                                                       else
+                                                               HoverWidget.onMouseMove (this, e);
+                                                       return true;
+                                               }                                               
                                        }
-                                       _hoverWidget.onMouseLeave (_hoverWidget, e);
-                                       tmp = _hoverWidget.FocusParent;
                                }
                        }
 
@@ -1404,19 +1461,23 @@ namespace Crow
                        lock (GraphicTree) {
                                for (int i = 0; i < GraphicTree.Count; i++) {
                                        Widget g = GraphicTree [i];
+                                       if (DragAndDropInProgress && DragAndDropOperation.DragSource == g)
+                                               continue;
                                        if (g.MouseIsIn (e.Position)) {
                                                g.checkHoverWidget (e);
-                                               if (g is Window && FOCUS_ON_HOVER && g.Focusable) {
-                                                       FocusedWidget = g;
-                                                       if (RAISE_WIN_ON_FOCUS)
-                                                               PutOnTop (g);
+                                               if (!DragAndDropInProgress) {
+                                                       if (g is Window && FOCUS_ON_HOVER && g.Focusable) {
+                                                               FocusedWidget = g;
+                                                               if (RAISE_WIN_ON_FOCUS)
+                                                                       PutOnTop (g);
+                                                       }
+                                                       HoverWidget.onMouseMove (this, e);
                                                }
-                                               _hoverWidget.onMouseMove (_hoverWidget, e);
                                                return true;
                                        }
                                }
                        }
-                       HoverWidget = null;
+                       HoverOrDropTarget = null;
                        return false;
                }
                /// <summary>
@@ -1431,12 +1492,12 @@ namespace Crow
 
                        lastMouseDownEvent = new MouseButtonEventArgs (MousePosition.X, MousePosition.Y, button, InputAction.Press);
 
-                       if (_hoverWidget == null)
+                       if (HoverWidget == null)
                                return false;
 
-                       _hoverWidget.onMouseDown (_hoverWidget, lastMouseDownEvent);
+                       HoverWidget.onMouseDown (this, lastMouseDownEvent);
 
-                       ActiveWidget = _hoverWidget;
+                       ActiveWidget = HoverWidget;
                        return true;
                }
                /// <summary>
@@ -1449,6 +1510,19 @@ namespace Crow
                        mouseRepeatTimer.Reset ();
                        lastMouseDownEvent = null;
 
+                       if (DragAndDropInProgress) {                            
+                               if (DragAndDropOperation.DropTarget != null)
+                                       DragAndDropOperation.DragSource.onDrop (this, DragAndDropOperation);
+                               else
+                                       DragAndDropOperation.DragSource.onEndDrag (this, DragAndDropOperation);
+                               DragAndDropOperation = null;
+                               if (ActiveWidget != null) {
+                                       ActiveWidget.onMouseUp (_activeWidget, new MouseButtonEventArgs (MousePosition.X, MousePosition.Y, button, InputAction.Release));
+                                       ActiveWidget = null;
+                               }
+                               return true;
+            }
+
                        if (_activeWidget == null)
                                return false;
 
@@ -1611,6 +1685,7 @@ namespace Crow
                {
                        ctxMenuContainer = CreateInstance ("#Crow.ContextMenu.template") as MenuItem;
                        ctxMenuContainer.LayoutChanged += CtxMenuContainer_LayoutChanged;
+                       ctxMenuContainer.Focusable = true;
                }
                protected void disposeContextMenus () {
                        if (ctxMenuContainer == null)
@@ -1641,17 +1716,19 @@ namespace Crow
                                else
                                        ctxMenuContainer.IsOpened = true;
 
-                               //ctxMenuContainer.isPopup = true;
+                               ctxMenuContainer.BubbleMouseEvent = false;
                                ctxMenuContainer.LogicalParent = go;
                                ctxMenuContainer.DataSource = go;
+                               
 
                                PutOnTop (ctxMenuContainer, true);
                        }
                        ctxMenuContainer.Left = MousePosition.X - 5;
                        ctxMenuContainer.Top = MousePosition.Y - 5;
 
-                       _hoverWidget = ctxMenuContainer;
-                       ctxMenuContainer.onMouseEnter (ctxMenuContainer, new MouseMoveEventArgs (MousePosition.X, MousePosition.Y, 0, 0));
+                       //OnMouseMove (MousePosition.X, MousePosition.Y);
+                       HoverWidget = ctxMenuContainer;
+                       ctxMenuContainer.onMouseEnter (ctxMenuContainer, new MouseMoveEventArgs (MousePosition.X, MousePosition.Y, 0, 0));                                              
                }
                #endregion
 
index 3b8594eaf7b2157683ab0f8088bbd5457b998856..50f241b5bb72c897e71e0009e48d0084e1bd424a 100644 (file)
@@ -90,7 +90,7 @@ namespace Crow
                        childrenRWLock.ExitReadLock ();                 
                }
 
-               public override void onMouseMove (object sender, MouseMoveEventArgs e)
+               public void onDragMouseMove (object sender, MouseMoveEventArgs e)
                {
                        if (IsDropTarget) {                             
                                DockWindow dw = IFace.DragAndDropOperation.DragSource as DockWindow;
@@ -150,7 +150,7 @@ namespace Crow
                                if (curDockPos != dw.DockingPosition)
                                        RegisterForGraphicUpdate ();
                        }
-                       base.onMouseMove (sender, e);
+                       //base.onMouseMove (sender, e);
                }
 
                protected override void onDragEnter (object sender, DragDropEventArgs e)
@@ -158,7 +158,7 @@ namespace Crow
                        base.onDragEnter (sender, e);
                        RegisterForGraphicUpdate ();
                }
-               protected override void onDragLeave (object sender, DragDropEventArgs e)
+               public override void onDragLeave (object sender, DragDropEventArgs e)
                {
                        DockWindow dw = e.DragSource as DockWindow;
                        //if (dw != null)
@@ -295,6 +295,7 @@ namespace Crow
                                stretchedChild = dw;
                                break;
                        }
+                       dw.IsDocked = true;
                }
                public void Undock (DockWindow dw){                     
                        int idx = Children.IndexOf(dw);
index bf59b155bc88198f967d9de78dbf08bdf009be50..a020397ed6a0a5e6e07544f2995dc2dee4a70608 100644 (file)
@@ -66,21 +66,15 @@ namespace Crow
                        return Slot.ContainsOrIsEqual(m);
                }
 
-               public override void onMouseMove (object sender, MouseMoveEventArgs e)
-               {
-                       //                      if (this.HasFocus && e.Mouse.IsButtonDown (MouseButton.Left) && IsDocked) {
-                       //                              if (Math.Abs (e.Position.X - undockingMousePosOrig.X) > 10 ||
-                       //                                  Math.Abs (e.Position.X - undockingMousePosOrig.X) > 10)
-                       //                                      Undock ();
-                       //                      }
-                       if (IFace.IsDown (MouseButton.Left) && IFace.DragAndDropOperation?.DragSource == this) {
-                               if (isDocked)
-                                       CheckUndock (e.Position);
-                               else
-                                       moveAndResize (e.XDelta, e.YDelta, currentDirection);
-
-                       }
-                       base.onMouseMove (sender, e);
+               public override void onDrag (object sender, MouseMoveEventArgs e)
+               {                       
+                       if (isDocked)
+                               CheckUndock (e.Position);
+                       else
+                               moveAndResize (e.XDelta, e.YDelta, currentDirection);
+                       
+                       base.onDrag (sender, e);
+                       (IFace.DragAndDropOperation.DropTarget as DockStack)?.onDragMouseMove (this, e);
                }
                public override void onMouseDown (object sender, MouseButtonEventArgs e)
                {
@@ -108,7 +102,7 @@ namespace Crow
 
                        undockingMousePosOrig = IFace.MousePosition;
                }
-               protected override void onDrop (object sender, DragDropEventArgs e)
+               public override void onDrop (object sender, DragDropEventArgs e)
                {
                        if (!isDocked && DockingPosition != Alignment.Undefined && e.DropTarget is DockStack)
                                Dock (e.DropTarget as DockStack);
@@ -134,7 +128,8 @@ namespace Crow
 
                public void Dock (DockStack target){
                        lock (IFace.UpdateMutex) {
-                               IsDocked = true;
+                               //IsDocked = true;
+                               undockingMousePosOrig = IFace.MousePosition;
                                //undockingMousePosOrig = lastMousePos;
                                savedSlot = this.LastPaintedSlot;
                                wasResizable = Resizable;
index 57e452031b07cc0edd8235ea620432fc362d7c94..69fc614e2677a07073dbb992175b123ba2bcd1b8 100644 (file)
@@ -444,20 +444,17 @@ namespace Crow
 
 
                #region Mouse handling
-               public override void checkHoverWidget (MouseMoveEventArgs e)
-               {
-                       if (IFace.HoverWidget != this) {
-                               IFace.HoverWidget = this;
-                               onMouseEnter (this, e);
-                       }
+               public override void checkHoverWidget (MouseMoveEventArgs e) {
+                       base.checkHoverWidget (e);//TODO:check if not possible to put it at beginning of meth to avoid doubled check to DropTarget.
+                       childrenRWLock.EnterReadLock ();
                        for (int i = Children.Count - 1; i >= 0; i--) {
-                               if (Children[i].MouseIsIn(e.Position))
-                               {
+                               if (Children[i].MouseIsIn (e.Position)) {
                                        Children[i].checkHoverWidget (e);
+                                       childrenRWLock.ExitReadLock ();
                                        return;
                                }
                        }
-                       base.checkHoverWidget (e);
+                       childrenRWLock.ExitReadLock ();                 
                }
 //             public override bool PointIsIn (ref Point m)
 //             {
index eb49147e4a2ed3c06e302a4193564b4060081cae..08db92915283e3dd7562dc5e89ecb60114d6fe21 100644 (file)
@@ -126,9 +126,8 @@ namespace Crow
                        Close.Raise (this, null);
                }
                public override bool MouseIsIn (Point m)
-               {
-                       return IsEnabled && !IsDragged ? base.MouseIsIn (m) || child.MouseIsIn (m) : false;
-               }
+                       => IsEnabled && !IsDragged ? base.MouseIsIn (m) || child.MouseIsIn (m) : false;
+               
                public override void onMouseEnter (object sender, MouseMoveEventArgs e)
                {
                        base.onMouseEnter (sender, e);
index 2fc5629da42b753d6578064f99ed8989fe4abee9..99b3ef7d2c792274966872b7065c084c64a3fd70 100644 (file)
@@ -178,10 +178,7 @@ namespace Crow
                }
                public override void checkHoverWidget (MouseMoveEventArgs e)
                {
-                       if (IFace.HoverWidget != this) {
-                               IFace.HoverWidget = this;
-                               onMouseEnter (this, e);
-                       }
+                       base.checkHoverWidget (e);
                        if (Content != null){
                                if (Content.Parent != null) {
                                        if (Content.MouseIsIn (e.Position)) {
@@ -190,7 +187,6 @@ namespace Crow
                                        }
                                }
                        }
-                       base.checkHoverWidget (e);
                }
                #endregion
 
index 61a34c2e0c52f39bf0937c97d2323a950af170b5..bc147a878b9a76ebda0108334b4f171f5da35e48 100644 (file)
@@ -226,7 +226,7 @@ namespace Crow
 
                        dragStartPoint = IFace.MousePosition;
                }
-               protected override void onEndDrag (object sender, DragDropEventArgs e)
+               public override void onEndDrag (object sender, DragDropEventArgs e)
                {
                        base.onEndDrag (sender, e);
 
@@ -237,7 +237,7 @@ namespace Crow
 
                        IFace.ClearDragImage ();
                }
-               protected override void onDrop (object sender, DragDropEventArgs e)
+               public override void onDrop (object sender, DragDropEventArgs e)
                {
                        base.onDrop (sender, e);
                        if (Parent != null)
index eb963926beb370637d763c80ca1362e065125399..d1f085aa0e66f0ee398095e4f166d8089051a2a7 100644 (file)
@@ -266,6 +266,7 @@ namespace Crow
                bool hasFocus;
                bool isActive;
                bool isHover;
+               bool bubbleMouseEvent;
                bool mouseRepeat;
                bool stickyMouseEnabled;
                int stickyMouse;
@@ -455,6 +456,7 @@ namespace Crow
                public event EventHandler<DragDropEventArgs> DragLeave;
                public event EventHandler<DragDropEventArgs> EndDrag;
                public event EventHandler<DragDropEventArgs> Drop;
+               public event EventHandler<MouseMoveEventArgs> Drag;
                #endregion
 
                /// <summary>
@@ -704,7 +706,7 @@ namespace Crow
                                        onUnfocused (this, null);
                                NotifyValueChangedAuto (hasFocus);
                        }
-               }
+               }               
                /// <summary>
                /// true if this control is active, this means that mouse has been pressed in it and not yet released. It could 
                /// be used for other two states periferic action.
@@ -743,6 +745,20 @@ namespace Crow
                        }
                }
                /// <summary>
+               /// if false, prevent mouse events to bubble to the parent in any case.
+               /// </summary>
+               [DesignCategory ("Behaviour")]
+               [DefaultValue (true)]
+               public virtual bool BubbleMouseEvent {
+                       get => bubbleMouseEvent;
+                       set {
+                               if (bubbleMouseEvent == value)
+                                       return;
+                               bubbleMouseEvent = value;
+                               NotifyValueChangedAuto (bubbleMouseEvent);
+                       }
+               }
+               /// <summary>
                /// true if holding mouse button down should trigger multiple click events
                /// </summary>
                [DesignCategory ("Behaviour")][DefaultValue(false)]
@@ -1300,7 +1316,7 @@ namespace Crow
                #region Drag&Drop
                [DesignCategory ("DragAndDrop")][DefaultValue(false)]
                public virtual bool AllowDrag {
-                       get { return allowDrag; }
+                       get => allowDrag;
                        set {
                                if (allowDrag == value)
                                        return;
@@ -1310,7 +1326,7 @@ namespace Crow
                }
                [DesignCategory ("DragAndDrop")][DefaultValue(false)]
                public virtual bool AllowDrop {
-                       get { return allowDrop; }
+                       get => allowDrop;
                        set {
                                if (allowDrop == value)
                                        return;
@@ -1330,7 +1346,7 @@ namespace Crow
 //                     get { return AllowedDroppedTypes?.Count>0; }
 //             }
                [XmlIgnore]public virtual bool IsDragged {
-                       get { return isDragged; }
+                       get => isDragged;
                        set {
                                if (isDragged == value)
                                        return;
@@ -1339,54 +1355,62 @@ namespace Crow
                                NotifyValueChanged ("IsDragged", IsDragged);
                        }
                }
+               /// <summary>
+               /// equivalent to mouse move for a dragged widget, no bubbling.
+               /// </summary>
+               public virtual void onDrag (object sender, MouseMoveEventArgs e) {
+                       if (Drag != null)
+                               Drag.Invoke (this, e);
+#if DEBUG_DRAGNDROP
+                       Debug.WriteLine (this.ToString () + " : DRAG => " + e.ToString ());
+#endif
+               }
+
                /// <summary>
                /// fired when drag and drop operation start
                /// </summary>
                protected virtual void onStartDrag (object sender, DragDropEventArgs e){
-                       IFace.HoverWidget = null;
-                       IFace.DragAndDropOperation = new DragDropEventArgs (this);
+                       IFace.DragAndDropOperation = e;
+                       IFace.dragndropHover = e.DropTarget;
                        IsDragged = true;
                        StartDrag.Raise (this, IFace.DragAndDropOperation);
                        #if DEBUG_DRAGNDROP
-                       Debug.WriteLine(this.ToString() + " : START DRAG => " + e.ToString());
+                       Debug.WriteLine(this.ToString() + " : START DRAG => " + e.ToString());                  
                        #endif
                }
-               /// <summary>
-               ///  Occured when dragging ends without dropping
-               /// </summary>
-               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;
+               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;
+               public virtual void onDragLeave (object sender, DragDropEventArgs e){                   
                        DragLeave.Raise (this, e);
-                       #if DEBUG_DRAGNDROP
-                       Debug.WriteLine(this.ToString() + " : DRAG Leave => " + e.ToString());
-                       #endif
+#if DEBUG_DRAGNDROP
+                       Debug.WriteLine (this.ToString () + " : DRAG Leave => " + e.ToString ());
+#endif
+                       e.DropTarget = null;
+               }
+               /// <summary>
+               ///  Occured when dragging ends without dropping
+               /// </summary>
+               public 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 onDrop (object sender, DragDropEventArgs e){                     
+               public 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
+#if DEBUG_DRAGNDROP
                        Debug.WriteLine(this.ToString() + " : DROP => " + e.ToString());
-                       #endif
-               }
-               public bool IsDropTarget {
-                       get { return IFace.DragAndDropOperation?.DropTarget == this; }
+#endif
                }
-
+               public bool IsDropTarget => IFace.DragAndDropOperation?.DropTarget == this;             
                #endregion
 
                #region Queuing
@@ -1882,7 +1906,7 @@ namespace Crow
                {
                        if (parent == null)
                                return false;
-                       if (!(isVisible & IsEnabled)||IsDragged)
+                       if (!(isVisible & IsEnabled))
                                return false;
                        if (!parent.PointIsIn(ref m))
                                return false;
@@ -1890,36 +1914,31 @@ namespace Crow
                        return Slot.ContainsOrIsEqual (m);                                      
                }
                public virtual bool MouseIsIn(Point m)
-               {                       
-                       return (!(isVisible & IsEnabled)||IsDragged) ? false : PointIsIn (ref m);
-               }
+                       => (!(isVisible & IsEnabled) || IsDragged) ? false : PointIsIn (ref m);
                public virtual void checkHoverWidget(MouseMoveEventArgs e)
                {
-                       if (IFace.HoverWidget != this) {
+                       if (IFace.DragAndDropInProgress) {
+                               if (IFace.dragndropHover != this) {
+                                       IFace.dragndropHover = this;
+                                       if (AllowDrop)
+                                               onDragEnter (this, IFace.DragAndDropOperation);
+                               }
+                       } else if (IFace.HoverWidget != this) {
                                onMouseEnter (this, e);
                                IFace.HoverWidget = this;
-                       }
-
-                       //this.onMouseMove (this, e);//without this, window border doesn't work, should be removed
+                       }                       
                }
                public virtual void onMouseMove (object sender, MouseMoveEventArgs e)
                {
-                       if (allowDrag & hasFocus & IFace.IsDown(MouseButton.Left)) {
-                               if (IFace.DragAndDropOperation == null)         
-                                       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)
+                       if (AllowDrag & IFace.IsDown (MouseButton.Left)) {                              
+                               onStartDrag (this, new DragDropEventArgs (this, FocusParent));
                                return;
+                       }
 
                        if (MouseMove != null)
                                MouseMove.Invoke (this, e);                     
-                       else if (!e.Handled)
+                       else if (!e.Handled && BubbleMouseEvent)
                                FocusParent?.onMouseMove (sender, e);
-
-
                }
                /// <summary>
                /// Default mouse button press method. The `MouseDown` event is raised from withing it.
@@ -1942,7 +1961,7 @@ namespace Crow
 
                        if (MouseDown != null)
                                MouseDown?.Invoke (this, e);
-                       else if (!e.Handled)
+                       else if (!e.Handled && BubbleMouseEvent)
                                FocusParent?.onMouseDown (sender, e);
                }
                /// <summary>
@@ -1955,18 +1974,9 @@ namespace Crow
                /// <param name="e">mouse button release event arguments</param>
                public virtual void onMouseUp(object sender, MouseButtonEventArgs e){
 
-                       if (IFace.DragAndDropOperation != null){
-                               if (IFace.DragAndDropOperation.DragSource == this) {
-                                       if (IFace.DragAndDropOperation.DropTarget != null)
-                                               onDrop (this, IFace.DragAndDropOperation);
-                                       else
-                                               onEndDrag (this, IFace.DragAndDropOperation);
-                                       IFace.DragAndDropOperation = null;
-                               }
-                       }
                        if (MouseUp != null)
                                MouseUp.Invoke (this, e);
-                       else if (!e.Handled)
+                       else if (!e.Handled && BubbleMouseEvent)
                                FocusParent?.onMouseUp (sender, e);
                }
                /// <summary>
@@ -1977,7 +1987,7 @@ namespace Crow
                public virtual void onMouseClick(object sender, MouseButtonEventArgs e){
                        if (MouseClick != null)
                                MouseClick.Invoke (this, e);
-                       else if (!e.Handled)
+                       else if (!e.Handled && BubbleMouseEvent)
                                FocusParent?.onMouseClick (sender, e);
                }
                /// <summary>
@@ -1989,19 +1999,19 @@ namespace Crow
                public virtual void onMouseDoubleClick(object sender, MouseButtonEventArgs e){
                        if (MouseDoubleClick != null)                   
                                MouseDoubleClick.Invoke (this, e);
-                       else if (!e.Handled)
+                       else if (!e.Handled && BubbleMouseEvent)
                                FocusParent?.onMouseDoubleClick (sender, e);
                }
                public virtual void onMouseWheel(object sender, MouseWheelEventArgs e){
                        if (MouseWheelChanged != null)
                                MouseWheelChanged.Invoke (this, e);
-                       else if (!e.Handled)
+                       else if (!e.Handled && BubbleMouseEvent)
                                FocusParent?.onMouseWheel (sender, e);
                }
                public virtual void onMouseEnter(object sender, MouseMoveEventArgs e)
                {
                        IFace.MouseCursor = MouseCursor;
-                       if (IFace.DragAndDropOperation != null) {
+                       /*if (IFace.DragAndDropOperation != null) {
                                Widget g = this;
                                while (g != null) {
                                        if (g.AllowDrop) {
@@ -2014,15 +2024,12 @@ namespace Crow
                                        }
                                        g = g.FocusParent;
                                }
-                       }
+                       }*/
 
                        MouseEnter.Raise (this, e);
                }
                public virtual void onMouseLeave(object sender, MouseMoveEventArgs e)
                {                       
-                       if (IFace.DragAndDropOperation?.DropTarget == this)
-                               IFace.DragAndDropOperation.DropTarget.onDragLeave (this, IFace.DragAndDropOperation);
-                       
                        MouseLeave.Raise (this, e);
                }
 
index 4b5a0e11b0596318dab8215d8f32819f749b1ece..27a9612a0518ac76f848775237f42aa2c9940fc4 100644 (file)
@@ -1,4 +1,5 @@
 using Crow;
+using Glfw;
 
 namespace tests
 {
@@ -11,6 +12,17 @@ namespace tests
                        }
                }
 
+               Color[] colors =
+               {
+                       Colors.Blue,
+                       Colors.Red,
+                       Colors.Green,
+                       Colors.Yellow,
+                       Colors.Grey,
+                       Colors.Onyx,
+                       Colors.Cyan,
+                       Colors.Chartreuse,                      
+               };
                protected override void OnInitialized () {
                        Load ("#ui.test.crow").DataSource = this;
                        AddWidget (new DockWindow (this) { Background = Colors.Blue, Left = 10, Top = 110, Resizable = true });
@@ -23,6 +35,17 @@ namespace tests
                        NotifyValueChanged ("GraphicTree", (object)null);
                        NotifyValueChanged ("GraphicTree", GraphicTree);
                }
-
-       }
+               int colorIdx = 0;
+        public override bool OnKeyDown (Key key) {
+                       if (colorIdx >= colors.Length)
+                               colorIdx = 0;
+            switch (key) {
+                       case Key.F6:
+                               AddWidget (new DockWindow (this) { Background = colors[colorIdx++], Left = 90, Top = 190, Resizable = true });
+                               return true;
+                       default:
+                               return base.OnKeyDown (key);
+                       }                       
+        }
+    }
 }
index 3c16376b3aada4e93f451631bb7fdd99c524b427..f576fbbd4fce5922e2a565aa86c36c15e9897fa6 100644 (file)
@@ -14,8 +14,9 @@
                        <Label Style="smallLabel" Text="{ActiveWidget}"/>
                </HorizontalStack>
        </VerticalStack>
-       <DockStack Height="70%"/>
-       <Splitter/>
+       <Label Text="Press 'F6' to add new windows"/>
+       <DockStack Name="mainDock" Height="Stretched"/>
+       <!--<Splitter/>
        <Button Caption="Refresh tree" MouseClick="refreshGraphicTree"/>
        <TreeView IsRoot="true" Name="treeView" Data="{GraphicTree}">
                <ItemTemplate>
@@ -40,5 +41,5 @@
                        Path="#ui.GTreeExp.itemp"/>
                <ItemTemplate DataType="Crow.TemplatedGroup" Data="GetChildren"
                        Path="#ui.GTreeExp.itemp"/>
-       </TreeView>     
+       </TreeView>     -->
 </VerticalStack>
index 62244bf7dc0d9dff9df25a336bd3b7d1debe22d1..281cfe19de98495b60817f38f97ae705b0f14d66 100644 (file)
@@ -35,8 +35,8 @@ namespace tests
                 gr.Paint ();
             }
             DragImage = dragImg;
-            lock (UpdateMutex)
-                startGroup.RemoveChild (e.DragSource);
+            /*lock (UpdateMutex)
+                startGroup.RemoveChild (e.DragSource);*/
         }
         private void W_EndDrag (object sender, DragDropEventArgs e) {
             lock (UpdateMutex)