]> O.S.I.I.S - jp/crow.git/commitdiff
stickyMouse, dragNdrop + mdiWins debug and tests temp 53/head
authorJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Mon, 7 Dec 2020 11:37:23 +0000 (12:37 +0100)
committerJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Mon, 7 Dec 2020 11:37:23 +0000 (12:37 +0100)
30 files changed:
Crow.sln
Crow/Default.style
Crow/Templates/DockWindow.template
Crow/src/Fill/BmpPicture.cs
Crow/src/IML/Instantiator.cs
Crow/src/Interface.cs
Crow/src/ItemTemplate.cs
Crow/src/Mono.Cairo/Context.cs
Crow/src/Mono.Cairo/NativeMethods.cs
Crow/src/Widgets/DockStack.cs
Crow/src/Widgets/DockWindow.cs
Crow/src/Widgets/Group.cs
Crow/src/Widgets/PrivateContainer.cs
Crow/src/Widgets/TabItem.cs
Crow/src/Widgets/Widget.cs
Crow/src/Widgets/Window.cs
Samples/Directory.Build.props
Samples/ShowCase/ShowCase.cs
Samples/common/samples.style
Samples/common/ui/Interfaces/Divers/2.crow
Samples/common/ui/Interfaces/Experimental/testDock.crow
Samples/common/ui/Interfaces/Experimental/testStack.crow
Samples/dockableWindows/dockableWindows.cs [new file with mode: 0644]
Samples/dockableWindows/dockableWindows.csproj [new file with mode: 0644]
Samples/dockableWindows/ui/GTreeExp.itemp [new file with mode: 0644]
Samples/dockableWindows/ui/test.crow [new file with mode: 0644]
Samples/dragNdrop/dragNdrop.cs [new file with mode: 0644]
Samples/dragNdrop/dragNdrop.csproj [new file with mode: 0644]
Samples/dragNdrop/ui/GTreeExp.itemp [new file with mode: 0644]
Samples/dragNdrop/ui/test.crow [new file with mode: 0644]

index ee47449616f2f86f82aa9ecdd57524878d848354..8f6e3f3d6bb980c94b9a40a780941f4766896b91 100644 (file)
--- a/Crow.sln
+++ b/Crow.sln
@@ -8,7 +8,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "global", "global", "{728545
                README.md = README.md
        EndProjectSection
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Crow", "Crow\Crow.csproj", "{C2980F9B-4798-4C05-99E2-E174810F7C7B}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Crow", "Crow\Crow.csproj", "{C2980F9B-4798-4C05-99E2-E174810F7C7B}"
 EndProject
 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{B2C7855A-2878-47FD-AD32-9A83DB4AB8C6}"
        ProjectSection(SolutionItems) = preProject
@@ -27,7 +27,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BasicTests", "Samples\Basic
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PerfTests", "Samples\PerfTests\PerfTests.csproj", "{18EBB41F-815E-4BF5-B80F-C9E2FAB2993A}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DebugLogAnalyzer", "Samples\DebugLogAnalyzer\DebugLogAnalyzer.csproj", "{7915538F-B2B1-414C-95A3-1FC58E3286B9}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DebugLogAnalyzer", "Samples\DebugLogAnalyzer\DebugLogAnalyzer.csproj", "{7915538F-B2B1-414C-95A3-1FC58E3286B9}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dragNdrop", "Samples\dragNdrop\dragNdrop.csproj", "{6E361E34-D266-4BEB-97F4-E209E01C6246}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dockableWindows", "Samples\dockableWindows\dockableWindows.csproj", "{E19FD3DB-902A-4C99-8BF0-5ACAFFE35608}"
 EndProject
 Global
        GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -65,6 +69,14 @@ Global
                {7915538F-B2B1-414C-95A3-1FC58E3286B9}.Debug|Any CPU.Build.0 = Debug|Any CPU
                {7915538F-B2B1-414C-95A3-1FC58E3286B9}.Release|Any CPU.ActiveCfg = Release|Any CPU
                {7915538F-B2B1-414C-95A3-1FC58E3286B9}.Release|Any CPU.Build.0 = Release|Any CPU
+               {6E361E34-D266-4BEB-97F4-E209E01C6246}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+               {6E361E34-D266-4BEB-97F4-E209E01C6246}.Debug|Any CPU.Build.0 = Debug|Any CPU
+               {6E361E34-D266-4BEB-97F4-E209E01C6246}.Release|Any CPU.ActiveCfg = Release|Any CPU
+               {6E361E34-D266-4BEB-97F4-E209E01C6246}.Release|Any CPU.Build.0 = Release|Any CPU
+               {E19FD3DB-902A-4C99-8BF0-5ACAFFE35608}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+               {E19FD3DB-902A-4C99-8BF0-5ACAFFE35608}.Debug|Any CPU.Build.0 = Debug|Any CPU
+               {E19FD3DB-902A-4C99-8BF0-5ACAFFE35608}.Release|Any CPU.ActiveCfg = Release|Any CPU
+               {E19FD3DB-902A-4C99-8BF0-5ACAFFE35608}.Release|Any CPU.Build.0 = Release|Any CPU
        EndGlobalSection
        GlobalSection(SolutionProperties) = preSolution
                HideSolutionNode = FALSE
@@ -76,6 +88,8 @@ Global
                {7AEB6DD5-916E-4415-84E1-78EC6E5881CE} = {B2C7855A-2878-47FD-AD32-9A83DB4AB8C6}
                {18EBB41F-815E-4BF5-B80F-C9E2FAB2993A} = {B2C7855A-2878-47FD-AD32-9A83DB4AB8C6}
                {7915538F-B2B1-414C-95A3-1FC58E3286B9} = {B2C7855A-2878-47FD-AD32-9A83DB4AB8C6}
+               {6E361E34-D266-4BEB-97F4-E209E01C6246} = {B2C7855A-2878-47FD-AD32-9A83DB4AB8C6}
+               {E19FD3DB-902A-4C99-8BF0-5ACAFFE35608} = {B2C7855A-2878-47FD-AD32-9A83DB4AB8C6}
        EndGlobalSection
        GlobalSection(ExtensibilityGlobals) = postSolution
                SolutionGuid = {00D4E149-7131-49F4-BAAD-559AA961A78E}
index cbc9dcbaf87130f119fbe004fe14ace137d9f04d..04cb01dcc9b6f3d83b1a2af512c3f39a932d9c00 100644 (file)
@@ -124,7 +124,9 @@ Slider {
 }
 Splitter {
        Focusable = "true";
-       Margin = "1";
+       Margin = "0";
+       StickyMouseEnabled="true";
+       StickyMouse="10";
        Background = "Grey";
 }
 
@@ -175,7 +177,8 @@ Docker {
        Focusable="true";
 }
 DockStack {
-       Margin="1";
+       Margin="2";
+       Spacing="2";
        AllowDrop = "true";
        Focusable="true";
        //DragEnter="{Background=Blue}";
index e62672bcb9a6a85e8a80dfcd308fa5525d472a07..9a2bd3b40cde05cb66ff115a60d07d371f7908b8 100644 (file)
@@ -1,12 +1,9 @@
 <?xml version="1.0"?>
-<!--<Widget Background="{./Background}"/>-->
-<Border BorderWidth="1" Foreground="Black" CornerRadius="{./CornerRadius}"
-                               Background="{./Background}"
-                               MouseEnter="./onBorderMouseEnter"
-                               MouseLeave="./onBorderMouseLeave">
+<Border Name="SizeHandle" BorderWidth="1" Foreground="Black" CornerRadius="{./CornerRadius}" StickyMouse="8" StickyMouseEnabled="{./IsFloating}"
+                               Background="{./Background}">
        <VerticalStack Spacing="0">
                <HorizontalStack Visible="{./IsDocked}" Height="Fit" Margin="1" Background="vgradient|0:0.3,0.5,0.8,0.9|1:0.1,0.1,0.1,0.9">
-                       <Label  Text="{./Caption}" TextAlignment="Left" Width="Stretched"
+                       <Label  Text="{./CurDir}" TextAlignment="Left" Width="Stretched"
                                         Foreground="White" />
                        <Border CornerRadius="6" BorderWidth="1" Foreground="Transparent"  Height="10" Width="10"
                                MouseEnter="{Foreground=White}" MouseLeave="{Foreground=Transparent}">
@@ -16,9 +13,9 @@
                </HorizontalStack>
                <HorizontalStack Background="vgradient|0:0.5,0.6,0.5,0.5|1:0.2,0.3,0.3,0.7"
                                Name="hs" Margin="0" Spacing="0" Height="Fit" Visible="{./IsFloating}">
-                       <Widget Width="5"/>
+                       <Widget Width="5"/>                     
                        <Image Margin="1" Width="10" Height="10" Path="{./Icon}"/>
-                       <Label Width="Stretched" Foreground="White" Margin="1" TextAlignment="Left" Text="{./Caption}" />
+                       <Label Width="Stretched" Foreground="White" Margin="1" TextAlignment="Left" Text="{./CurDir}" />
                        <Border CornerRadius="6" BorderWidth="1" Foreground="Transparent"  Height="10" Width="10"
                                MouseEnter="{Foreground=White}" MouseLeave="{Foreground=Transparent}">
                                <Image Focusable="true" Name="Image" Margin="0" Path="#Crow.Icons.exit2.svg"
index c000628d5c5c2f137114d51a20808671611015e9..1aade9355796df84c818a38e8d2bd0677bc75ced 100644 (file)
@@ -125,7 +125,7 @@ namespace Crow
 
                                        using (ImageSurface imgSurf = new ImageSurface (image, Format.Argb32, 
                                                Dimensions.Width, Dimensions.Height, 4 * Dimensions.Width)) {
-                                               gr.SetSourceSurface (imgSurf, 0,0);
+                                               gr.SetSource (imgSurf, 0,0);
                                                gr.Paint ();
                                        }
                                }
@@ -166,7 +166,7 @@ namespace Crow
                        
                        using (ImageSurface imgSurf = new ImageSurface (image, Format.Argb32, 
                                Dimensions.Width, Dimensions.Height, 4 * Dimensions.Width)) {
-                               gr.SetSourceSurface (imgSurf, 0,0);
+                               gr.SetSource (imgSurf, 0,0);
                                gr.Paint ();
                        }
                        gr.Restore ();
index 7a4ca5a66c5f6b0b768590b4ed4263050128838c..ac203f08a7d42a09a73d20b27e285a76f709c8f1 100644 (file)
@@ -155,7 +155,7 @@ namespace Crow.IML {
                Delegate templateBinding;
 
 #if DESIGN_MODE
-               public List<DynamicMethod> DsValueChangedDynMeths =>dsValueChangedDynMeths;
+               public List<DynamicMethod> DsValueChangedDynMeths => dsValueChangedDynMeths;
                public List<Delegate> CachedDelegates => cachedDelegates;
                /// <summary>
                /// store indices of template delegate to be handled by root parentChanged event
index d11070f879b3444f6a7c4fc567bdb86570a5e66c..a9a9fa1b455ccad9d1a65a35d3a3927db215e5bf 100644 (file)
@@ -314,6 +314,8 @@ namespace Crow
                public static string CROW_CONFIG_ROOT;
                /// <summary>If true, mouse focus is given when mouse is over control</summary>
                public static bool FOCUS_ON_HOVER = false;
+               /// <summary>If true, newly focused window will be put on top</summary>
+               public static bool RAISE_WIN_ON_FOCUS = true;
                /// <summary> Threshold to catch borders for sizing </summary>
                public static int BorderThreshold = 3;
                /// <summary> delay before tooltip appears </summary>
@@ -354,6 +356,9 @@ namespace Crow
                //public event EventHandler<MouseCursorChangedEventArgs> MouseCursorChanged;
                ////public event EventHandler Quit;
                public event EventHandler Initialized;
+
+               public event EventHandler StartDragOperation;
+               public event EventHandler EndDragOperation;
                //public event EventHandler<MouseWheelEventArgs> MouseWheelChanged;
                //public event EventHandler<MouseButtonEventArgs> MouseButtonUp;
                //public event EventHandler<MouseButtonEventArgs> MouseButtonDown;
@@ -507,7 +512,10 @@ namespace Crow
                        return stream != null;
                }
 
-               public static Stream GetStreamFromPath (string path)
+               public delegate Stream GetStreamFromPathDelegate (string path);
+               public static GetStreamFromPathDelegate GetStreamFromPath = _getStreamFromPath;
+
+               static Stream _getStreamFromPath (string path)
                {
                        if (path.StartsWith ("#", StringComparison.Ordinal)) {
                                Stream stream = null;
@@ -618,8 +626,8 @@ namespace Crow
 
                                _activeWidget = value;
 
+                               NotifyValueChanged ("ActiveWidget", _activeWidget);
 #if DEBUG_LOG
-                               NotifyValueChanged("ActiveWidget", _activeWidget);
                                DbgLogger.AddEvent (DbgEvtType.ActiveWidget, _activeWidget);
 #endif
 
@@ -640,8 +648,8 @@ namespace Crow
 
                                _hoverWidget = value;
 
+                               NotifyValueChanged ("HoverWidget", _hoverWidget);
 #if DEBUG_LOG
-                               NotifyValueChanged("HoverWidget", _hoverWidget);
                                DbgLogger.AddEvent (DbgEvtType.HoverWidget, _hoverWidget);
 #endif
 
@@ -669,8 +677,9 @@ namespace Crow
                                if (_focusedWidget != null)
                                        _focusedWidget.HasFocus = false;
                                _focusedWidget = value;
-#if DEBUG_LOG
-                               NotifyValueChanged("FocusedWidget", _focusedWidget);
+
+                               NotifyValueChanged ("FocusedWidget", _focusedWidget);
+#if DEBUG_LOG                          
                                DbgLogger.AddEvent (DbgEvtType.FocusedWidget, _focusedWidget);
 #endif
                                if (_focusedWidget != null)
@@ -823,7 +832,7 @@ namespace Crow
                                                        DragImageY = MousePosition.Y - DragImageHeight / 2;
                                                        ctx.Save ();
                                                        ctx.ResetClip ();
-                                                       ctx.SetSourceSurface (DragImage, DragImageX, DragImageY);
+                                                       ctx.SetSource (DragImage, DragImageX, DragImageY);
                                                        ctx.PaintWithAlpha (0.8);
                                                        ctx.Restore ();
                                                        DirtyRect += new Rectangle (DragImageX, DragImageY, DragImageWidth, DragImageHeight);
@@ -972,11 +981,31 @@ namespace Crow
                /// when window resize event occurs. 
                /// </summary>
                /// <param name="bounds">bounding box of the interface</param>
-               public virtual void ProcessResize(Rectangle bounds){
+               public virtual void ProcessResize(Rectangle bounds){                    
                        lock (UpdateMutex) {
                                clientRectangle = bounds;
 
-                               surf.SetSize (clientRectangle.Width, clientRectangle.Height);
+                               switch (Environment.OSVersion.Platform) {
+                               case PlatformID.MacOSX:
+                                       break;
+                               case PlatformID.Unix:
+                                       surf.SetSize (clientRectangle.Width, clientRectangle.Height);
+                                       break;
+                               case PlatformID.Win32NT:
+                               case PlatformID.Win32S:
+                               case PlatformID.Win32Windows:
+                                       if (ownWindow) {
+                                               surf.Dispose ();
+                                               IntPtr hWin32 = Glfw3.GetWin32Window (hWin);
+                                               IntPtr hdc = Glfw3.GetWin32DC (hWin32);
+                                               surf = new Win32Surface (hdc);
+                                       }else
+                                               surf.SetSize (clientRectangle.Width, clientRectangle.Height);
+                                       break;
+                               case PlatformID.Xbox:
+                               case PlatformID.WinCE:
+                                       throw new PlatformNotSupportedException ("Unable to create cairo surface.");
+                               }
 
                                foreach (Widget g in GraphicTree)
                                        g.RegisterForLayouting (LayoutingType.All);
@@ -1085,42 +1114,43 @@ namespace Crow
                                //MouseCursorChanged.Raise (this,new MouseCursorChangedEventArgs(cursor));
                        }
                }
-
-               uint stickyMouse = 0;
-               Point stickyMousePos = default;
-               internal void SetStickyMouse (uint threshold = 5)
-               {
-                       stickyMouse = threshold;
-                       stickyMousePos = MousePosition;
-               }
+               
+               Point stickyMouseDelta = default;
+               internal Widget stickedWidget = null;
 
                /// <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>
                public virtual bool OnMouseMove (int x, int y)
-               {
+               {                       
+                       int deltaX = x - MousePosition.X;
+                       int deltaY = y - MousePosition.Y;
+
+                       if (stickedWidget != null && _activeWidget == null) {
+                               stickyMouseDelta.X += deltaX;
+                               stickyMouseDelta.Y += deltaY;                           
 
-                       if (stickyMouse>0) {
-                               if (Math.Abs(x - stickyMousePos.X) < stickyMouse && Math.Abs(y - stickyMousePos.Y) < stickyMouse)
+                               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;
-                               stickyMouse = 0;
+                               }
                        }
-                       int deltaX = x - MousePosition.X;
-                       int deltaY = y - MousePosition.Y;
 
                        MousePosition = new Point (x, y);
                        MouseMoveEventArgs e = new MouseMoveEventArgs (x, y, deltaX, deltaY);
 
-                       if (ActiveWidget != null && DragAndDropOperation == null) {
+                       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) {
                                //TODO, ensure object is still in the graphic tree
                                //send move evt even if mouse move outside bounds
                                _activeWidget.onMouseMove (this, e);
                                return true;
                        }
 
-                       if (DragAndDropOperation != null)//drag source cant have hover event, so move has to be handle here
-                               DragAndDropOperation.DragSource.onMouseMove (this, e);
-
                        if (_hoverWidget != null) {
                                resetTooltip ();
                                //check topmost graphicobject first
@@ -1177,8 +1207,11 @@ namespace Crow
                                        Widget g = GraphicTree [i];
                                        if (g.MouseIsIn (e.Position)) {
                                                g.checkHoverWidget (e);
-                                               if (g is Window)
-                                                       PutOnTop (g);
+                                               if (g is Window && FOCUS_ON_HOVER && g.Focusable) {
+                                                       FocusedWidget = g;
+                                                       if (RAISE_WIN_ON_FOCUS)
+                                                               PutOnTop (g);
+                                               }
                                                _hoverWidget.onMouseMove (_hoverWidget, e);
                                                return true;
                                        }
index 01e76b59f505086edbe023320d9cd4241c79d305..11fea67197d9f1cfd71146b57c5491009b288c26 100644 (file)
@@ -251,5 +251,25 @@ namespace Crow
                 il.Emit (OpCodes.Callvirt, miGetDatas);
         }
        }
+
+       public static partial class Extensions
+       {
+               public static string GetIcon (this Widget go) {
+                       return "#Icons." + go.GetType ().FullName + ".svg";
+               }
+               public static List<Widget> GetChildren (this Widget go) {
+                       Type goType = go.GetType ();
+                       if (typeof (Group).IsAssignableFrom (goType))
+                               return (go as Group).Children;
+                       if (typeof (Container).IsAssignableFrom (goType))
+                               return new List<Widget> (new Widget[] { (go as Container).Child });
+                       if (typeof (TemplatedContainer).IsAssignableFrom (goType))
+                               return new List<Widget> (new Widget[] { (go as TemplatedContainer).Content });
+                       if (typeof (TemplatedGroup).IsAssignableFrom (goType))
+                               return (go as TemplatedGroup).Items;
+
+                       return new List<Widget> ();
+               }
+       }
 }
 
index 7ed5e62ca688c706ef80380455707ad4269b34a4..1ce4cd0f3391d45f76a9bea2c40c2819839861a5 100644 (file)
@@ -340,7 +340,7 @@ namespace Crow.Cairo {
                }
 
                //[Obsolete ("Use SetSource method (with double parameters)")]
-               public void SetSourceSurface (Surface source, int x, int y)
+               public void SetSource (Surface source, int x = 0, int y = 0)
                {
                        NativeMethods.cairo_set_source_surface (handle, source.Handle, x, y);
                }
@@ -861,7 +861,7 @@ namespace Crow.Cairo {
 
                public void ShowText(string str)
                {
-                       NativeMethods.cairo_show_text (handle, str);
+                       NativeMethods.cairo_show_text (handle, TerminateUtf8 (str));
                }
 
 
index 1b423209bba5dc8e0fa847ad2d83448c20145c40..66b528a1cef97c08e737b0721ba2439678ea8a19 100644 (file)
@@ -752,7 +752,7 @@ namespace Crow.Cairo
                internal static extern void cairo_show_page (IntPtr cr);
 
                [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
-               internal static extern void cairo_show_text (IntPtr cr, string text);
+               internal static extern void cairo_show_text (IntPtr cr, byte[] text);
 
                [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
                internal static extern Status cairo_status (IntPtr cr);
index 81aa5e74fb65939166ab426b7fd1f160223433be..da9110e4e7395a7a0c66d96b249d03b3f2d3dd16 100644 (file)
@@ -71,6 +71,7 @@ namespace Crow
 
                Rectangle rIn = default(Rectangle);
                double dockThresh = 0.2;
+               const int dockWidthDivisor = 8;
                Widget focusedChild;
                internal Widget stretchedChild;
 
@@ -113,33 +114,33 @@ namespace Crow
                                        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)
+                                               if (lm.Y > cb.Top + cb.Height / dockWidthDivisor && lm.Y < cb.Bottom - cb.Height / dockWidthDivisor) {
+                                                       if (lm.X < cb.Left + cb.Width / dockWidthDivisor)
                                                                dw.DockingPosition = Alignment.Left;
-                                                       else if (lm.X > cb.Right - cb.Width / 3)
+                                                       else if (lm.X > cb.Right - cb.Width / dockWidthDivisor)
                                                                dw.DockingPosition = Alignment.Right;                                                   
                                                } else {
                                                        getFocusedChild (lm);
                                                        if (focusedChild != null) {
-                                                               if (lm.Y < rIn.Top + rIn.Height / 3)
+                                                               if (lm.Y < rIn.Top + rIn.Height / dockWidthDivisor)
                                                                        dw.DockingPosition = Alignment.Top;
-                                                               else if (lm.Y > rIn.Bottom - rIn.Height / 3)
+                                                               else if (lm.Y > rIn.Bottom - rIn.Height / dockWidthDivisor)
                                                                        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)
+                                               if (lm.X > cb.Left + cb.Width / dockWidthDivisor && lm.X < cb.Right - cb.Width / dockWidthDivisor) {
+                                                       if (lm.Y < cb.Top + cb.Height / dockWidthDivisor)
                                                                dw.DockingPosition = Alignment.Top;
-                                                       else if (lm.Y > cb.Bottom - cb.Height / 3)
+                                                       else if (lm.Y > cb.Bottom - cb.Height / dockWidthDivisor)
                                                                dw.DockingPosition = Alignment.Bottom;                                                  
                                                } else {
                                                        getFocusedChild (lm);
                                                        if (focusedChild != null) {
-                                                               if (lm.X < rIn.Left + rIn.Width / 3)
+                                                               if (lm.X < rIn.Left + rIn.Width / dockWidthDivisor)
                                                                        dw.DockingPosition = Alignment.Left;
-                                                               else if (lm.X > rIn.Right - rIn.Width / 3)
+                                                               else if (lm.X > rIn.Right - rIn.Width / dockWidthDivisor)
                                                                        dw.DockingPosition = Alignment.Right;                                                                           
                                                        }
                                                }
index e9c371795cc0ac0198a75c2d6a5fe323a588bd6e..bf59b155bc88198f967d9de78dbf08bdf009be50 100644 (file)
@@ -68,15 +68,18 @@ namespace Crow
 
                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 (this.HasFocus && IFace.IsDown(MouseButton.Left) && IsDocked)
-                               CheckUndock (e.Position);
+                       //                      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 onMouseDown (object sender, MouseButtonEventArgs e)
@@ -100,7 +103,8 @@ namespace Crow
 
                protected override void onStartDrag (object sender, DragDropEventArgs e)
                {
-                       base.onStartDrag (sender, e);
+                       if (currentDirection == Direction.None)
+                               base.onStartDrag (sender, e);
 
                        undockingMousePosOrig = IFace.MousePosition;
                }
index df452bee84cdebb6ee347a7ab11556fc0b3983e2..5f0a7b21f9ab546463493cf659cfceff2d2cf195 100644 (file)
@@ -350,7 +350,7 @@ namespace Crow
                        }
                        gr.Dispose ();
 
-                       ctx.SetSourceSurface (bmp, rb.X, rb.Y);
+                       ctx.SetSource (bmp, rb.X, rb.Y);
                        ctx.Paint ();
 
                        Clipping.Dispose();
index 415d45d21cae64daa1840635f87b35b3abd0ebb1..ebca78e89adb81b1d076185c2f270c85604d23fe 100644 (file)
@@ -216,7 +216,7 @@ namespace Crow
                                
                        gr.Dispose ();
 
-                       ctx.SetSourceSurface (bmp, rb.X, rb.Y);
+                       ctx.SetSource (bmp, rb.X, rb.Y);
                        ctx.Paint ();
                        Clipping.Dispose();
                        Clipping = new Region ();
index 25c89ae32cd466d5c5098072a997d8cee728de03..19fcb94e5ce00dd9c33f1d0f15d6d831e1099acf 100644 (file)
@@ -189,9 +189,9 @@ namespace Crow
                                                this.onDraw (ctx);
                                        else {
                                                if (LastPaintedSlot.Width>LastPaintedSlot.Height)
-                                                       ctx.SetSourceSurface (bmp, 0, (LastPaintedSlot.Width-LastPaintedSlot.Height)/2);
+                                                       ctx.SetSource (bmp, 0, (LastPaintedSlot.Width-LastPaintedSlot.Height)/2);
                                                else
-                                                       ctx.SetSourceSurface (bmp, (LastPaintedSlot.Height-LastPaintedSlot.Width)/2, 0);
+                                                       ctx.SetSource (bmp, (LastPaintedSlot.Height-LastPaintedSlot.Width)/2, 0);
 
                                                ctx.Paint ();
                                        }
index c060f954f3e9dfe91629dbf6be8e5e579a457778..d75c63c4416a8cb7fa9c11f18f905b293af6624e 100644 (file)
@@ -121,9 +121,9 @@ namespace Crow
                                        this.onDraw (ctx);
                                else {
                                        if (LastPaintedSlot.Width>LastPaintedSlot.Height)
-                                               ctx.SetSourceSurface (bmp, 0, (LastPaintedSlot.Width-LastPaintedSlot.Height)/2);
+                                               ctx.SetSource (bmp, 0, (LastPaintedSlot.Width-LastPaintedSlot.Height)/2);
                                        else
-                                               ctx.SetSourceSurface (bmp, (LastPaintedSlot.Height-LastPaintedSlot.Width)/2, 0);
+                                               ctx.SetSource (bmp, (LastPaintedSlot.Height-LastPaintedSlot.Width)/2, 0);
                                        ctx.Paint ();
                                }
                        }
@@ -278,6 +278,8 @@ namespace Crow
                bool isActive;
                bool isHover;
                bool mouseRepeat;
+               bool stickyMouseEnabled;
+               int stickyMouse;
                MouseCursor mouseCursor = MouseCursor.top_left_arrow;
                protected bool isVisible = true;
                bool isEnabled = true;
@@ -449,11 +451,11 @@ namespace Crow
                public event EventHandler Focused;
                /// <summary>Occurs when this object loose focus</summary>
                public event EventHandler Unfocused;
-               /// <summary>Occurs when mouse is over</summary>
+               /// <summary>Occurs when this widget is hovered by the mouse</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>
+               /// <summary>Occurs when this widget is no longuer the hover one</summary>
+               public event EventHandler Unhover;
+               /// <summary>Occurs when this widget is enabled</summary>
                public event EventHandler Enabled;
                /// <summary>Occurs when the enabled state this object is set to false</summary>
                public event EventHandler Disabled;
@@ -737,10 +739,16 @@ namespace Crow
                                if (value == isHover)
                                        return;
 
+                               if (isHover & !value)
+                                       Unhover.Raise (this, null);
+
                                isHover = value;
 
-                               if (isHover)
+                               if (isHover) {
+                                       if (stickyMouseEnabled && stickyMouse > 0) 
+                                               IFace.stickedWidget = this;                                                                                     
                                        Hover.Raise (this, null);
+                               }
 
                                NotifyValueChangedAuto (isHover);
                        }
@@ -758,6 +766,32 @@ namespace Crow
                                NotifyValueChangedAuto (mouseRepeat);
                        }
                }
+               /// <summary>
+               /// When StickyMouse value is greater than zero and StickyMouseEnabled is true, mouse will be sticked over the widget
+               /// until x or y delta is greater than the StickyMouse value. This is usefulle for very thin (1 pixel) border that need to
+               /// be grabbed with the mouse.
+               /// </summary>
+               public virtual int StickyMouse {
+                       get => stickyMouse;
+                       set {
+                               if (stickyMouse == value)
+                                       return;
+                               stickyMouse = value;
+                               NotifyValueChangedAuto (stickyMouse);
+            }
+        }
+               /// <summary>
+               /// Boolean for enabling or not the sticky mouse mechanic
+               /// </summary>
+               public virtual bool StickyMouseEnabled {
+                       get => stickyMouseEnabled;
+                       set {
+                               if (stickyMouseEnabled == value)
+                                       return;
+                               stickyMouseEnabled = value;
+                               NotifyValueChangedAuto (stickyMouseEnabled);
+            }
+        }
                /// <summary>
                /// Determine Cursor when mouse is Hover.
                /// </summary>
@@ -1347,8 +1381,9 @@ namespace Crow
                /// </summary>
                protected virtual void onStartDrag (object sender, DragDropEventArgs e){
                        IFace.HoverWidget = null;
+                       IFace.DragAndDropOperation = new DragDropEventArgs (this);
                        IsDragged = true;
-                       StartDrag.Raise (this, e);
+                       StartDrag.Raise (this, IFace.DragAndDropOperation);
                        #if DEBUG_DRAGNDROP
                        Debug.WriteLine(this.ToString() + " : START DRAG => " + e.ToString());
                        #endif
@@ -1807,7 +1842,7 @@ namespace Crow
                                ctx.Operator = Operator.Over;
                        }
 
-                       ctx.SetSourceSurface (bmp, rb.X, rb.Y);
+                       ctx.SetSource (bmp, rb.X, rb.Y);
                        ctx.Paint ();
                        Clipping.Dispose ();
                        Clipping = new Region ();
@@ -1935,10 +1970,8 @@ namespace Crow
                public virtual void onMouseMove (object sender, MouseMoveEventArgs e)
                {
                        if (allowDrag & hasFocus & IFace.IsDown(MouseButton.Left)) {
-                               if (IFace.DragAndDropOperation == null) {
-                                       IFace.DragAndDropOperation = new DragDropEventArgs (this);
-                                       onStartDrag (this, IFace.DragAndDropOperation);
-                               }
+                               if (IFace.DragAndDropOperation == null)         
+                                       onStartDrag (this, IFace.DragAndDropOperation);                         
                        }
 
                        //dont bubble event if dragged, mouse move is routed directely from iface
@@ -2005,7 +2038,7 @@ namespace Crow
                }
                public virtual void onMouseEnter(object sender, MouseMoveEventArgs e)
                {
-                       IFace.MouseCursor = MouseCursor;
+                       IFace.MouseCursor = MouseCursor;                        
 
                        if (IFace.DragAndDropOperation != null) {
                                Widget g = this;
@@ -2025,7 +2058,10 @@ namespace Crow
                        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 accf198c88782d94c2d6dcd7b0b01c071b433b86..374b67d265646d553075a5bce110834e2952bff6 100644 (file)
@@ -33,7 +33,7 @@ namespace Crow
                Rectangle savedBounds;
                bool _minimized = false;
 
-               Direction currentDirection = Direction.None;
+               protected Direction currentDirection = Direction.None;
 
                #region Events
                public event EventHandler Closing;
@@ -63,13 +63,19 @@ namespace Crow
                        sizingHandle = child?.FindByName ("SizeHandle");
 
                        if (sizingHandle == null)
-                               return;
-                       sizingHandle.MouseEnter += (arg1, arg2) => IFace.SetStickyMouse(5);
+                               return;                 
+            //sizingHandle.Unhover += (arg1, arg2) => currentDirection = Direction.None;
+            sizingHandle.Unhover += SizingHandle_Unhover;
                }
-               #endregion
 
-               #region public properties
-               [DefaultValue("#Crow.Icons.crow.svg")]
+        private void SizingHandle_Unhover (object sender, EventArgs e) {
+                       currentDirection = Direction.None;
+                       NotifyValueChanged ("CurDir", currentDirection);
+               }
+        #endregion
+
+        #region public properties
+        [DefaultValue("#Crow.Icons.crow.svg")]
                public string Icon {
                        get { return _icon; } 
                        set {
@@ -159,7 +165,7 @@ namespace Crow
                /// <param name="XDelta">mouse delta on the X axis</param>
                /// <param name="YDelta">mouse delta on the Y axis</param>
                /// <param name="currentDirection">Current Direction of the operation, none for moving, other value for resizing in the given direction</param>
-               public void MoveAndResize (int XDelta, int YDelta, Direction currentDirection = (Direction)0) {
+               protected void moveAndResize (int XDelta, int YDelta, Direction currentDirection = (Direction)0) {
                        int currentLeft = this.Left;
                        int currentTop = this.Top;
                        int currentWidth, currentHeight;
@@ -238,11 +244,9 @@ namespace Crow
                {
                        base.onMouseMove (sender, e);
 
-                       Interface otkgw = IFace;
-
                        if (maySize || mayMove) {
                                if (grabMouse) {
-                                       MoveAndResize (e.XDelta, e.YDelta, currentDirection);
+                                       moveAndResize (e.XDelta, e.YDelta, currentDirection);
                                        return;
                                }
                        }else
@@ -276,50 +280,54 @@ namespace Crow
 
                        switch (currentDirection) {
                        case Direction.None:
-                               otkgw.MouseCursor = MouseCursor.move;
+                               IFace.MouseCursor = MouseCursor.move;
                                break;
                        case Direction.N:
-                               otkgw.MouseCursor = MouseCursor.top_side;
+                               IFace.MouseCursor = MouseCursor.top_side;
                                break;
                        case Direction.S:
-                               otkgw.MouseCursor = MouseCursor.bottom_side;
+                               IFace.MouseCursor = MouseCursor.bottom_side;
                                break;
                        case Direction.E:
-                               otkgw.MouseCursor = MouseCursor.right_side;
+                               IFace.MouseCursor = MouseCursor.right_side;
                                break;
                        case Direction.W:
-                               otkgw.MouseCursor = MouseCursor.left_side;
+                               IFace.MouseCursor = MouseCursor.left_side;
                                break;
                        case Direction.NW:
-                               otkgw.MouseCursor = MouseCursor.top_left_corner;
+                               IFace.MouseCursor = MouseCursor.top_left_corner;
                                break;
                        case Direction.NE:
-                               otkgw.MouseCursor = MouseCursor.top_right_corner;
+                               IFace.MouseCursor = MouseCursor.top_right_corner;
                                break;
                        case Direction.SW:
-                               otkgw.MouseCursor = MouseCursor.bottom_left_corner;
+                               IFace.MouseCursor = MouseCursor.bottom_left_corner;
                                break;
                        case Direction.SE:
-                               otkgw.MouseCursor = MouseCursor.bottom_right_corner;
+                               IFace.MouseCursor = MouseCursor.bottom_right_corner;
                                break;
                        }
-                                                       
+                       NotifyValueChanged ("CurDir", currentDirection);
                }
                public override void onMouseLeave (object sender, MouseMoveEventArgs e)
                {
                        base.onMouseLeave (sender, e);
                        currentDirection = Direction.None;
                        IFace.MouseCursor = MouseCursor.top_left_arrow;
+                       NotifyValueChanged ("CurDir", currentDirection);
                }
                bool grabMouse;
                public override void onMouseDown (object sender, MouseButtonEventArgs e)
                {
+                       NotifyValueChanged ("GrabMouse", true);
                        grabMouse = true;
                        e.Handled = true;
                        base.onMouseDown (sender, e);
                }
                public override void onMouseUp (object sender, MouseButtonEventArgs e)
                {
+                       NotifyValueChanged ("GrabMouse", false);
+                       NotifyValueChanged ("CurDir", currentDirection);
                        grabMouse = false;
                        e.Handled = true;
                        base.onMouseUp (sender, e);
index 120aa913a08c29eb9d2fcc166fde000db6b2a2df..190db9dc8376826d074c71fe2ae83654fe52f3ec 100644 (file)
@@ -1,6 +1,6 @@
 <Project>
        <PropertyGroup>
-               <TargetFrameworks>net472;netcoreapp3.1</TargetFrameworks>
+               <TargetFrameworks>netcoreapp3.1</TargetFrameworks>
                <OutputType>Exe</OutputType>
                
                <SolutionDir>$(MSBuildThisFileDirectory)..\</SolutionDir>
index d825431798aa8daaf70860bf9869073b7bc7d804..8af2c0023e45efd5e4612a31593355f1baec788b 100644 (file)
@@ -16,6 +16,7 @@ namespace ShowCase
        {
                static void Main ()
                {
+                       Environment.SetEnvironmentVariable ("FONTCONFIG_PATH", @"C:\Users\Jean-Philippe\source\vcpkg\installed\x64-windows\tools\fontconfig\fonts");
                        using (Showcase app = new Showcase ()) 
                                app.Run ();
                }
@@ -47,6 +48,7 @@ namespace ShowCase
                        set {
                                if (source == value)
                                        return;
+
                                source = value;
                                reloadFromSource ();
                                CMDSave.CanExecute = source != origSource;
@@ -82,7 +84,7 @@ namespace ShowCase
                }
 
                public new bool IsDirty {
-                       get => origSource != source;
+                       get => !string.Equals(origSource, source);
                }
                void onSave ()
                {
index 124cfcf45331cd9a770691f12c2aa6c422325092..50f91f4a4222cc630a65a84308436c843043021c 100644 (file)
@@ -66,4 +66,7 @@ valignStyle2 {
        Unchecked = "{Background=Black}";
        //Initialized="GetDrawModeIcon";
        //Initialized="{Background=Blue}";
+}
+smallLabel {
+       Font="consolas, 8";
 }
\ No newline at end of file
index b4a06b687a7a32a2e048f113a5d89bd55de53820..d2c8c37067864a4d75f6f97154332872b1802e61 100644 (file)
@@ -2,12 +2,13 @@
 <VerticalStack Fit="true">
        <TextBox Font="droid, 20" Text="test text box" Width="Stretched"/>
        <HorizontalStack Margin="5" Fit="true" MouseEnter="{Background=White}" MouseLeave="{Background=Transparent}">
+               <Label Text="left" Width="80" Height="30" Background="DarkBlue" TextAlignment="Left"/>
                <Label Text="centered" Width="80" Height="30" Background="DarkBlue" TextAlignment="Center"/>
                <Label Text="top left" Width="80" Height="30" Background="DarkBlue" TextAlignment="TopLeft"/>
                <Label Text="top right" Width="80" Height="30" Background="DarkBlue" TextAlignment="TopRight"/>
-               <Label Text="right center" Width="80" Height="30" Background="DarkBlue" TextAlignment="Right"/>
+               <Label Text="right" Width="80" Height="30" Background="DarkBlue" TextAlignment="Right"/>
                <Label Text="bottom left" Width="80" Height="30" Background="DarkBlue" TextAlignment="BottomLeft"/>
-               <Label Text="bottom center" Width="80" Height="30" Background="DarkBlue" TextAlignment="Bottom"/>
+               <Label Text="bottom" Width="80" Height="30" Background="DarkBlue" TextAlignment="Bottom"/>
                <Label Text="bottom right" Width="80" Height="30" Background="DarkBlue" TextAlignment="BottomRight"/>
        </HorizontalStack>
 </VerticalStack>
\ No newline at end of file
index b69f8e787051292971c67a52cf43ec2a6306fdcf..14659f88649125a259332738fe4b073c6fedad6b 100644 (file)
@@ -1,8 +1,8 @@
 <?xml version="1.0"?>
-<Window Width="Stretched" Height="Stretched" Background="Jet">
-       <DockStack Name="mainDock" Background="DarkRed" Margin="20">
-       </DockStack>
-</Window>
+<DockStack Name="mainDock" Background="Jet" Margin="0">
+       <DockWindow Resizable = "true" Top="100" Left="100" Caption="View 1" Width="300" Height="300"/>
+</DockStack>
+
 <!---          
                <DockWindow Left="450" Top="450" Width="150" Height="150" Background="Yellow"/>-->
        
@@ -14,7 +14,7 @@
        <Window Top="400" Left="400" Focusable="true" Caption="View 4" Resizable = "true" Width="300" Height="300"><Widget Focusable="true" Background="Black" MouseEnter="{Background=Grey}" MouseLeave="{Background=Black}"/></Window>
 </Group>-->
 <!--<Docker >
-       <DockWindow Resizable = "true" Top="100" Left="100" Caption="View 1" Width="300" Height="300">
+       
                <VerticalStack Background="DarkGreen" Focusable="true">
                        <Label Text="{../../Left}" Background="Black" Width="Stretched"/>
                        <Label Text="{../../Top}" Background="Black"/>
index 0348f0b55e9d3465874fff16ab84631314661e73..97bbe62bec11acc6b5fc04618708c929a8b52ab7 100644 (file)
@@ -6,7 +6,7 @@
        <HorizontalStack>
                <Widget Height="Stretched" Width="100" Background="Red"/>
                <Splitter/>
-               <Widget Height="Stretched" Width="100" Background="DarkRed"/>
+               <Widget Height="Stretched" Width="Stretched" Background="DarkRed"/>
        </HorizontalStack>
        <Splitter/>
        <Widget Height="100" Width="500" Background="Green"/>
diff --git a/Samples/dockableWindows/dockableWindows.cs b/Samples/dockableWindows/dockableWindows.cs
new file mode 100644 (file)
index 0000000..65223ac
--- /dev/null
@@ -0,0 +1,33 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using Crow;
+using Glfw;
+
+namespace tests
+{
+       public class BasicTests : SampleBase
+       {
+               static void Main ()
+               {
+                       using (BasicTests app = new BasicTests ()) {
+                               app.Run ();
+                       }
+               }
+
+               protected override void OnInitialized () {
+                       Load ("#ui.test.crow").DataSource = this;
+                       AddWidget (new DockWindow (this) { Background = Colors.Blue, Left = 10, Top = 110, Resizable = true });
+                       AddWidget (new DockWindow (this) { Background = Colors.Red, Left = 30, Top = 130, Resizable = true });
+                       AddWidget (new DockWindow (this) { Background = Colors.Green, Left = 50, Top = 150, Resizable = true });
+                       AddWidget (new DockWindow (this) { Background = Colors.Yellow, Left = 70, Top = 170, Resizable = true });
+                       AddWidget (new DockWindow (this) { Background = Colors.Grey, Left = 90, Top = 190, Resizable = true });
+               }
+               private void refreshGraphicTree (object sender, MouseButtonEventArgs e) {
+                       NotifyValueChanged ("GraphicTree", (object)null);
+                       NotifyValueChanged ("GraphicTree", GraphicTree);
+               }
+
+       }
+}
diff --git a/Samples/dockableWindows/dockableWindows.csproj b/Samples/dockableWindows/dockableWindows.csproj
new file mode 100644 (file)
index 0000000..3c9729f
--- /dev/null
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project Sdk="Microsoft.NET.Sdk">
+       <ItemGroup>             
+               <EmbeddedResource Include="ui\*.*">
+                       <LogicalName>ui.%(Filename)%(Extension)</LogicalName>
+               </EmbeddedResource>
+       </ItemGroup>
+       <ItemGroup>
+         <EmbeddedResource Update="ui\GTreeExp.itemp">
+           <LogicalName>ui.%(Filename)%(Extension)</LogicalName>
+         </EmbeddedResource>
+       </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/Samples/dockableWindows/ui/GTreeExp.itemp b/Samples/dockableWindows/ui/GTreeExp.itemp
new file mode 100644 (file)
index 0000000..f2a7c2b
--- /dev/null
@@ -0,0 +1,32 @@
+<?xml version="1.0"?>
+<Expandable IsExpanded="{²IsExpanded}" MouseDoubleClick="/onClickForExpand">
+       <Template>
+               <VerticalStack>
+                       <Border CornerRadius="2" Margin="0" Height="Fit"                                                
+                                       Foreground="Transparent"
+                                       MouseEnter="{Foreground=DimGrey}"
+                                       MouseLeave="{Foreground=Transparent}">
+                               <HorizontalStack Spacing="1">
+                                       <Image Margin="1" Width="9" Height="9" Focusable="true" MouseDown="./onClickForExpand"
+                                               Path="{./Image}"
+                                               Visible="{./IsExpandable}"
+                                               SvgSub="{./IsExpanded}"
+                                               MouseEnter="{Background=LightGrey}"
+                                               MouseLeave="{Background=Transparent}"/>
+                                       <Border Width="16" Height="16" Foreground="Black" Background="DimGrey">
+                                               <Image Margin="2" Path="{GetIcon}" />
+                                       </Border>
+                                       <Widget Width="5" Height="5" Background="Blue" Visible="{IsHover}"/>
+                                       <Widget Width="5" Height="5" Background="Green" Visible="{Visible}"/>
+                                       <Label Text="{Name}" Width="Fit"/>
+                                       <Label Text="{LogicalParent}" Width="Stretched" Foreground="Yellow"/>
+                               </HorizontalStack>
+                       </Border>
+                       <Container Name="Content" Visible="false"/>
+               </VerticalStack>
+       </Template>
+       <HorizontalStack Height="Fit">
+               <Widget Width="8" Height="10"/>
+               <VerticalStack Height="Fit" Name="ItemsContainer"/>
+       </HorizontalStack>
+</Expandable>
diff --git a/Samples/dockableWindows/ui/test.crow b/Samples/dockableWindows/ui/test.crow
new file mode 100644 (file)
index 0000000..3c16376
--- /dev/null
@@ -0,0 +1,44 @@
+<?xml version="1.0"?>
+<VerticalStack>
+       <VerticalStack Name="Watches" Background="Black" Height="Fit" Width="Stretched">
+               <HorizontalStack Height="Fit">
+                       <Label Style="smallLabel" Text="hover:" Width="50"/>
+                       <Label Style="smallLabel" Text="{HoverWidget}"/>
+               </HorizontalStack>
+               <HorizontalStack Height="Fit">
+                       <Label Style="smallLabel" Text="focus:" Width="50"/>
+                       <Label Style="smallLabel" Text="{FocusedWidget}"/>
+               </HorizontalStack>
+               <HorizontalStack Height="Fit">
+                       <Label Style="smallLabel" Text="active:" Width="50"/>
+                       <Label Style="smallLabel" Text="{ActiveWidget}"/>
+               </HorizontalStack>
+       </VerticalStack>
+       <DockStack Height="70%"/>
+       <Splitter/>
+       <Button Caption="Refresh tree" MouseClick="refreshGraphicTree"/>
+       <TreeView IsRoot="true" Name="treeView" Data="{GraphicTree}">
+               <ItemTemplate>
+                       <Border Width="Stretched" Focusable="true" Foreground="Transparent">
+                               <HorizontalStack Spacing="5">
+                                       <Widget Width="5" Height="5"/>
+                                       <Border Width="16" Height="16" Foreground="Black" Background="DimGrey">
+                                               <Image Margin="2" Path="{GetIcon}" />
+                                       </Border>
+                                       <Widget Width="2" Height="5" Background="Blue" Visible="{IsHover}"/>
+                                       <Widget Width="5" Height="5" Background="Green" Visible="{Visible}"/>
+                                       <Label Text="{Name}" Width="Fit"/>
+                                       <Label Text="{LogicalParent}" Width="Stretched" Foreground="Yellow"/>
+                               </HorizontalStack>
+                       </Border>
+               </ItemTemplate>
+               <ItemTemplate DataType="Crow.Group" Data="GetChildren"
+                       Path="#ui.GTreeExp.itemp"/>
+               <ItemTemplate DataType="Crow.Container" Data="GetChildren"
+                       Path="#ui.GTreeExp.itemp"/>
+               <ItemTemplate DataType="Crow.TemplatedContainer" Data="GetChildren"
+                       Path="#ui.GTreeExp.itemp"/>
+               <ItemTemplate DataType="Crow.TemplatedGroup" Data="GetChildren"
+                       Path="#ui.GTreeExp.itemp"/>
+       </TreeView>     
+</VerticalStack>
diff --git a/Samples/dragNdrop/dragNdrop.cs b/Samples/dragNdrop/dragNdrop.cs
new file mode 100644 (file)
index 0000000..0c98574
--- /dev/null
@@ -0,0 +1,65 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using Crow;
+using Glfw;
+
+namespace tests
+{
+       public class BasicTests : SampleBase
+       {
+               static void Main ()
+               {
+                       using (BasicTests app = new BasicTests ()) {
+                               app.Run ();
+                       }
+               }
+
+               protected override void OnInitialized ()
+               {
+                       Load ("#ui.test.crow").DataSource = this;
+               }
+
+        private void refreshGraphicTree (object sender, MouseButtonEventArgs e) {
+            NotifyValueChanged ("GraphicTree", (object)null);
+            NotifyValueChanged ("GraphicTree", GraphicTree);
+        }
+
+        Group startGroup = null;
+        
+
+        private void W_StartDrag (object sender, DragDropEventArgs e) {
+            startGroup = e.DragSource.Parent as Group;
+            DragImageHeight = e.DragSource.LastPaintedSlot.Height;
+            DragImageWidth = e.DragSource.LastPaintedSlot.Width;
+
+            Crow.Cairo.Surface dragImg = surf.CreateSimilar (Crow.Cairo.Content.ColorAlpha, DragImageWidth, DragImageHeight);
+            using (Crow.Cairo.Context gr = new Crow.Cairo.Context(dragImg)) {
+                gr.SetSource (e.DragSource.bmp, 0, 0);
+                gr.Paint ();
+            }
+            DragImage = dragImg;
+            lock (UpdateMutex)
+                startGroup.RemoveChild (e.DragSource);
+        }
+        private void W_EndDrag (object sender, DragDropEventArgs e) {
+            lock (UpdateMutex)
+                startGroup.AddChild (e.DragSource);            
+        }
+
+        private void W_DragEnter (object sender, DragDropEventArgs e) {
+            lock (UpdateMutex)
+                (e.DropTarget as Group).AddChild (e.DragSource);
+        }
+        private void W_DragLeave (object sender, DragDropEventArgs e) {
+            lock (UpdateMutex)
+                (e.DragSource.Parent as Group).RemoveChild (e.DragSource);
+        }
+        private void W_Drop (object sender, DragDropEventArgs e) {
+            //(e.DropTarget as Group).AddChild (e.DragSource);            
+        }
+
+
+    }
+}
diff --git a/Samples/dragNdrop/dragNdrop.csproj b/Samples/dragNdrop/dragNdrop.csproj
new file mode 100644 (file)
index 0000000..9961c6b
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project Sdk="Microsoft.NET.Sdk">
+       <ItemGroup>
+               <EmbeddedResource Include="ui\*.*">
+                       <LogicalName>ui.%(Filename)%(Extension)</LogicalName>
+               </EmbeddedResource>
+       </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/Samples/dragNdrop/ui/GTreeExp.itemp b/Samples/dragNdrop/ui/GTreeExp.itemp
new file mode 100644 (file)
index 0000000..f2a7c2b
--- /dev/null
@@ -0,0 +1,32 @@
+<?xml version="1.0"?>
+<Expandable IsExpanded="{²IsExpanded}" MouseDoubleClick="/onClickForExpand">
+       <Template>
+               <VerticalStack>
+                       <Border CornerRadius="2" Margin="0" Height="Fit"                                                
+                                       Foreground="Transparent"
+                                       MouseEnter="{Foreground=DimGrey}"
+                                       MouseLeave="{Foreground=Transparent}">
+                               <HorizontalStack Spacing="1">
+                                       <Image Margin="1" Width="9" Height="9" Focusable="true" MouseDown="./onClickForExpand"
+                                               Path="{./Image}"
+                                               Visible="{./IsExpandable}"
+                                               SvgSub="{./IsExpanded}"
+                                               MouseEnter="{Background=LightGrey}"
+                                               MouseLeave="{Background=Transparent}"/>
+                                       <Border Width="16" Height="16" Foreground="Black" Background="DimGrey">
+                                               <Image Margin="2" Path="{GetIcon}" />
+                                       </Border>
+                                       <Widget Width="5" Height="5" Background="Blue" Visible="{IsHover}"/>
+                                       <Widget Width="5" Height="5" Background="Green" Visible="{Visible}"/>
+                                       <Label Text="{Name}" Width="Fit"/>
+                                       <Label Text="{LogicalParent}" Width="Stretched" Foreground="Yellow"/>
+                               </HorizontalStack>
+                       </Border>
+                       <Container Name="Content" Visible="false"/>
+               </VerticalStack>
+       </Template>
+       <HorizontalStack Height="Fit">
+               <Widget Width="8" Height="10"/>
+               <VerticalStack Height="Fit" Name="ItemsContainer"/>
+       </HorizontalStack>
+</Expandable>
diff --git a/Samples/dragNdrop/ui/test.crow b/Samples/dragNdrop/ui/test.crow
new file mode 100644 (file)
index 0000000..ce49ea7
--- /dev/null
@@ -0,0 +1,55 @@
+<?xml version="1.0"?>
+<VerticalStack Background="Jet" Focusable="true">
+       <VerticalStack Name="Watches" Background="Black" Height="Fit" Width="Stretched">
+               <HorizontalStack Height="Fit">
+                       <Label Style="smallLabel" Text="hover:" Width="50"/>
+                       <Label Style="smallLabel" Text="{HoverWidget}"/>
+               </HorizontalStack>
+               <HorizontalStack Height="Fit">
+                       <Label Style="smallLabel" Text="focus:" Width="50"/>
+                       <Label Style="smallLabel" Text="{FocusedWidget}"/>
+               </HorizontalStack>
+               <HorizontalStack Height="Fit">
+                       <Label Style="smallLabel" Text="active:" Width="50"/>
+                       <Label Style="smallLabel" Text="{ActiveWidget}"/>
+               </HorizontalStack>
+       </VerticalStack>
+       <HorizontalStack Margin="20" Name="zone1" Height="100" Width="Stretched" Background="Grey" AllowDrop="true" DragEnter="W_DragEnter" DragLeave="W_DragLeave">
+               <Widget Name="w1" Background="Blue" Focusable="true" Width="50" Height="Stretched" AllowDrag="true" StartDrag="W_StartDrag" EndDrag="W_EndDrag" Drop="W_Drop"/>
+               <Widget Name="w2" Background="Red" Focusable="true" Width="50" Height="Stretched" AllowDrag="true" StartDrag="W_StartDrag" EndDrag="W_EndDrag" Drop="W_Drop"/>/>
+               <Widget Name="w3" Background="Green" Focusable="true" Width="50" Height="Stretched" AllowDrag="true" StartDrag="W_StartDrag" EndDrag="W_EndDrag" Drop="W_Drop"/>/>
+               <Widget Name="w4" Background="Yellow" Focusable="true" Width="50" Height="Stretched" AllowDrag="true" StartDrag="W_StartDrag" EndDrag="W_EndDrag" Drop="W_Drop"/>/>
+               <Widget Name="w5" Background="DimGrey" Focusable="true" Width="50" Height="Stretched" AllowDrag="true" StartDrag="W_StartDrag" EndDrag="W_EndDrag" Drop="W_Drop"/>/>
+       </HorizontalStack>
+       <Widget Height="20" Focusable="true"/>
+       <HorizontalStack Margin="20" Name="zone2" Height="150" Width="Stretched" Background="Grey" AllowDrop="true" DragEnter="W_DragEnter" DragLeave="W_DragLeave">
+       </HorizontalStack>
+       <Widget Height="20"/>
+       <HorizontalStack Margin="20" Name="zone3" Height="80" Width="Stretched" Background="Grey" AllowDrop="true" DragEnter="W_DragEnter" DragLeave="W_DragLeave">
+       </HorizontalStack>
+       <Button Caption="Refresh tree" MouseClick="refreshGraphicTree"/>
+       <TreeView IsRoot="true" Name="treeView" Data="{GraphicTree}">
+               <ItemTemplate>
+                       <Border Width="Stretched" Focusable="true" Foreground="Transparent">
+                               <HorizontalStack Spacing="5">
+                                       <Widget Width="5" Height="5"/>
+                                       <Border Width="16" Height="16" Foreground="Black" Background="DimGrey">
+                                               <Image Margin="2" Path="{GetIcon}" />
+                                       </Border>
+                                       <Widget Width="2" Height="5" Background="Blue" Visible="{IsHover}"/>
+                                       <Widget Width="5" Height="5" Background="Green" Visible="{Visible}"/>
+                                       <Label Text="{Name}" Width="Fit"/>
+                                       <Label Text="{LogicalParent}" Width="Stretched" Foreground="Yellow"/>
+                               </HorizontalStack>
+                       </Border>
+               </ItemTemplate>
+               <ItemTemplate DataType="Crow.Group" Data="GetChildren"
+                       Path="#ui.GTreeExp.itemp"/>
+               <ItemTemplate DataType="Crow.Container" Data="GetChildren"
+                       Path="#ui.GTreeExp.itemp"/>
+               <ItemTemplate DataType="Crow.TemplatedContainer" Data="GetChildren"
+                       Path="#ui.GTreeExp.itemp"/>
+               <ItemTemplate DataType="Crow.TemplatedGroup" Data="GetChildren"
+                       Path="#ui.GTreeExp.itemp"/>
+       </TreeView>
+</VerticalStack>
\ No newline at end of file