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
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
{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
{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}
}
Splitter {
Focusable = "true";
- Margin = "1";
+ Margin = "0";
+ StickyMouseEnabled="true";
+ StickyMouse="10";
Background = "Grey";
}
Focusable="true";
}
DockStack {
- Margin="1";
+ Margin="2";
+ Spacing="2";
AllowDrop = "true";
Focusable="true";
//DragEnter="{Background=Blue}";
<?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}">
</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"
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 ();
}
}
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 ();
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
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>
//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;
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;
_activeWidget = value;
+ NotifyValueChanged ("ActiveWidget", _activeWidget);
#if DEBUG_LOG
- NotifyValueChanged("ActiveWidget", _activeWidget);
DbgLogger.AddEvent (DbgEvtType.ActiveWidget, _activeWidget);
#endif
_hoverWidget = value;
+ NotifyValueChanged ("HoverWidget", _hoverWidget);
#if DEBUG_LOG
- NotifyValueChanged("HoverWidget", _hoverWidget);
DbgLogger.AddEvent (DbgEvtType.HoverWidget, _hoverWidget);
#endif
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)
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);
/// 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);
//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
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;
}
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> ();
+ }
+ }
}
}
//[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);
}
public void ShowText(string str)
{
- NativeMethods.cairo_show_text (handle, str);
+ NativeMethods.cairo_show_text (handle, TerminateUtf8 (str));
}
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);
Rectangle rIn = default(Rectangle);
double dockThresh = 0.2;
+ const int dockWidthDivisor = 8;
Widget focusedChild;
internal Widget stretchedChild;
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;
}
}
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)
protected override void onStartDrag (object sender, DragDropEventArgs e)
{
- base.onStartDrag (sender, e);
+ if (currentDirection == Direction.None)
+ base.onStartDrag (sender, e);
undockingMousePosOrig = IFace.MousePosition;
}
}
gr.Dispose ();
- ctx.SetSourceSurface (bmp, rb.X, rb.Y);
+ ctx.SetSource (bmp, rb.X, rb.Y);
ctx.Paint ();
Clipping.Dispose();
gr.Dispose ();
- ctx.SetSourceSurface (bmp, rb.X, rb.Y);
+ ctx.SetSource (bmp, rb.X, rb.Y);
ctx.Paint ();
Clipping.Dispose();
Clipping = new Region ();
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 ();
}
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 ();
}
}
bool isActive;
bool isHover;
bool mouseRepeat;
+ bool stickyMouseEnabled;
+ int stickyMouse;
MouseCursor mouseCursor = MouseCursor.top_left_arrow;
protected bool isVisible = true;
bool isEnabled = true;
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;
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);
}
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>
/// </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
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 ();
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
}
public virtual void onMouseEnter(object sender, MouseMoveEventArgs e)
{
- IFace.MouseCursor = MouseCursor;
+ IFace.MouseCursor = MouseCursor;
if (IFace.DragAndDropOperation != null) {
Widget g = this;
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);
}
Rectangle savedBounds;
bool _minimized = false;
- Direction currentDirection = Direction.None;
+ protected Direction currentDirection = Direction.None;
#region Events
public event EventHandler Closing;
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 {
/// <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;
{
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
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);
<Project>
<PropertyGroup>
- <TargetFrameworks>net472;netcoreapp3.1</TargetFrameworks>
+ <TargetFrameworks>netcoreapp3.1</TargetFrameworks>
<OutputType>Exe</OutputType>
<SolutionDir>$(MSBuildThisFileDirectory)..\</SolutionDir>
{
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 ();
}
set {
if (source == value)
return;
+
source = value;
reloadFromSource ();
CMDSave.CanExecute = source != origSource;
}
public new bool IsDirty {
- get => origSource != source;
+ get => !string.Equals(origSource, source);
}
void onSave ()
{
Unchecked = "{Background=Black}";
//Initialized="GetDrawModeIcon";
//Initialized="{Background=Blue}";
+}
+smallLabel {
+ Font="consolas, 8";
}
\ No newline at end of file
<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
<?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"/>-->
<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"/>
<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"/>
--- /dev/null
+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);
+ }
+
+ }
+}
--- /dev/null
+<?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
--- /dev/null
+<?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>
--- /dev/null
+<?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>
--- /dev/null
+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);
+ }
+
+
+ }
+}
--- /dev/null
+<?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
--- /dev/null
+<?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>
--- /dev/null
+<?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