ControlCaptionHoverColor = "White";
ControlCornerRadius = "0";
ControlInsideMargin = "1";
+ControlHighlight = "RoyalBlue";
IconSize = "11";
IconMargin = "1";
ToggleIconSize = "16";
+WindowBackgroundColor = "";
+WindowBorderColor = "Grey";
+WindowBorderWidth = "1";
+WindowTitleBarBackground = "vgradient|0:Onyx|1:SteelBlue";
+WindowTitleBarForeground = "White";
+
Button, CheckBox, RadioButton, ComboBox, Expandable,
MessageBox, Popper, Slider, Spinner, TextBox {
Focusable = "true";
Height = "Fit";
Width = "Stretched";
VerticalAlignment = "Top";
- SelectionBackground = "Transparent";
+ SelectionBackground = "${ControlHighlight}";
}
MenuItem {
Caption = "MenuItem";
Width = "Stretched";
Height = "Fit";
- //Background = "vgradient|0:DimGrey|1:Black";
- //Background = "Transparent";
+ Background = "DimGrey";
Foreground = "LightGrey";
- MouseEnter = "{Background=SteelBlue;}";
- MouseLeave = "{Background=Transparent;}";
- //MouseEnter = "{Background = vgradient|0:SteelBlue|1:Jet;Foreground=White;}";
- //MouseLeave = "{Foreground=LightGrey;Background=Transparent;}";
- SelectionBackground = "Transparent";
+ MouseEnter = "{Background=${ControlHighlight}}";
+ MouseLeave = "{Background=Transparent}";
+ SelectionBackground = "${ControlHighlight}";
}
MessageBox {
- Background = "0.1,0.1,0.2,0.7";
+ Background = "0.1,0.1,0.2,0.85";
Width = "Fit";
Caption="MessageBox";
Font = "serif, 12";
- MinimumSize = "200,120";
+ //MinimumSize = "200,120";
AlwaysOnTop = "true";
+ Resizable = "false";
}
Slider {
Foreground = "Grey";
Width = "150";
Height = "150";
}
+winBorder {
+ BorderWidth = "${WindowBorderWidth}";
+ Foreground = "${WindowBorderColor}";
+ Background = "${WindowBackgroundColor}";
+ Margin = "0";
+}
WindowIconBorder {
BorderWidth="1";
Foreground="Transparent";
ScrollBar {
Orientation = "Vertical";
- Maximum = "0";
- Value = "0";
- Foreground="Transparent";
- Background="Onyx";
- Width = "14";
- CornerRadius = "0";
+ Maximum = "0";
+ Value = "0";
+ Foreground="Transparent";
+ Background="Onyx";
+ Width = "14";
+ CornerRadius = "0";
}
HScrollBar {
Template = "#Crow.HScrollBar.template";
<?xml version="1.0"?>
-<HorizontalStack Style="Control" Background="{./Background}">
+<HorizontalStack Style="Control" Background="{./Background}" CornerRadius="{$ControlCornerRadius}">
<Image Style="Icon" Width="${ToggleIconSize}" Height="${ToggleIconSize}" Path="#Crow.Icons.checkbox.svg" SvgSub="{./IsChecked}"/>
<Label Style="ControlCaption" Font="{./Font}" Text="{./Caption}" Foreground="{./Foreground}"/>
</HorizontalStack>
\ No newline at end of file
<?xml version="1.0"?>
-<Border CornerRadius="0"
- MouseEnter="./onBorderMouseEnter"
- MouseLeave="./onBorderMouseLeave">
- <VerticalStack Background="{./Background}">
- <Border BorderWidth="0" Foreground="White" Height="Fit" Width="Stretched" MinimumSize="200,0"
- Background="{./TitleBarBackground}">
- <HorizontalStack Name="hs" Margin="2" Spacing="1" Height="Fit" >
- <Widget Width="5" Height="5"/>
- <Image Margin="1" Width="12" Height="12" Path="{./Icon}"/>
- <Label Width="Stretched" Foreground="{./TitleBarForeground}" Margin="1" TextAlignment="Center" Text="{./Caption}" />
- <Border CornerRadius="3" BorderWidth="1" Foreground="Transparent" Height="12" Width="12"
- MouseEnter="{Foreground=White}" MouseLeave="{Foreground=Transparent}">
- <Image Focusable="true" Name="Image" Path="#Crow.Icons.exit2.svg"
- MouseClick="./butQuitPress"/>
- </Border>
- <Widget Width="5" Height="5"/>
- </HorizontalStack>
- </Border>
+<Border Name="SizeHandle" Style="winBorder" CornerRadius="{./CornerRadius}" Background="{./Background}">
+ <VerticalStack Spacing="0">
+ <HorizontalStack Background="${WindowTitleBarBackground}"
+ Name="hs" Margin="2" Spacing="1" Height="Fit" Width="Stretched" >
+ <Widget Width="5" />
+ <Image Margin="1" Width="12" Height="12" Path="{./Icon}"/>
+ <Label Name="MoveHandle" Width="Stretched" Foreground="${WindowTitleBarForeground" Margin="2" TextAlignment="Center" Text="{./Caption}" />
+ <Border CornerRadius="3" BorderWidth="1" Foreground="Transparent" Height="12" Width="12"
+ MouseEnter="{Foreground=White}" MouseLeave="{Foreground=Transparent}">
+ <Image Focusable="true" Name="Image" Path="#Crow.Icons.exit2.svg"
+ MouseClick="./butQuitPress"/>
+ </Border>
+ <Widget Width="5" />
+ </HorizontalStack>
<HorizontalStack Margin="5" >
<Image Name="Image" Width="50" Height="30" Path="{./MsgIcon}" />
<Label Margin="5" Font="{./Font}" Text="{./Message}"
<?xml version="1.0"?>
-<HorizontalStack Style="Control" Background="{./Background}">
+<HorizontalStack Style="Control" Background="{./Background}" CornerRadius="${ControlCornerRadius}">
<Image Style="Icon" Width="${ToggleIconSize}" Height="${ToggleIconSize}" Path="#Crow.Icons.radiobutton.svg" SvgSub="{./IsChecked}"/>
<Label Style="ControlCaption" Font="{./Font}" Text="{./Caption}" Foreground="{./Foreground}"/>
</HorizontalStack>
\ No newline at end of file
<?xml version="1.0"?>
<Border BorderWidth="1" Foreground="White" CornerRadius="{./CornerRadius}"
- Background="{./Background}"
- MouseEnter="./onBorderMouseEnter"
- MouseLeave="./onBorderMouseLeave">
+ Background="{./Background}">
<VerticalStack Spacing="0">
-<!-- <Border Name="TitleBar" BorderWidth="1" Foreground="White" Width="{./WidthPolicy}" Height="Fit"
- Background="vgradient|0:0.4,0.6,0.0,0.5|1:0.0,0.8,0.8,0.9">-->
<HorizontalStack Background="{./TitleBarBackground}" Width="Stretched"
Name="hs" Margin="2" Spacing="0" Height="Fit">
<Widget Width="5"/>
</Border>
<Widget Width="5"/>
</HorizontalStack>
-<!-- </Border>-->
<Container Name="Content" MinimumSize="50,50" Background="0.5,0.5,0.5,0.5"/>
</VerticalStack>
</Border>
<?xml version="1.0"?>
-<Border BorderWidth="1" Foreground="Grey" CornerRadius="{./CornerRadius}"
- Background="{./Background}">
+<Border Name="SizeHandle" Style="winBorder" CornerRadius="{./CornerRadius}" Background="{./Background}" >
<VerticalStack Spacing="0">
- <HorizontalStack Background="{./TitleBarBackground}"
- Name="hs" Margin="0" Spacing="0" Height="Fit">
+ <HorizontalStack Background="${WindowTitleBarBackground}" Margin="0" Spacing="0" Height="Fit">
<Widget Width="5"/>
<Image Margin="1" Width="12" Height="12" Path="{./Icon}"/>
- <Label Width="Stretched" Foreground="{./TitleBarForeground}" Margin="2" TextAlignment="Center" Text="{./Caption}" />
+ <Label Name="MoveHandle" Width="Stretched" Foreground="${WindowTitleBarForeground" Margin="2" TextAlignment="Center" Text="{./Caption}" />
<Border Visible="{./ShowMinimize}" Style="WindowIconBorder">
<Image Focusable="true" Path="#Crow.Icons.minimize.svg"
MouseClick="./onMinimized"/>
using System.ComponentModel;
namespace Crow {
+ public class CommandGroup : ObservableList<Command>, IValueChange
+ {
+ string caption;
+ string icon;
+
+ /// <summary>
+ /// label to display in the bound control
+ /// </summary>
+ [DefaultValue ("Unamed Command Group")]
+ public virtual string Caption {
+ get { return caption; }
+ set {
+ if (caption == value)
+ return;
+ caption = value;
+ NotifyValueChanged ("Caption", caption);
+
+ }
+ }
+ /// <summary>
+ /// Icon to display in the bound control
+ /// </summary>
+ public string Icon {
+ get { return icon; }
+ set {
+ if (icon == value)
+ return;
+ icon = value;
+ NotifyValueChanged ("Icon", icon);
+ }
+ }
+ }
+
+
/// <summary>
/// helper class to bind in one step icon, caption, action, and validity tests to a controls
/// </summary>
}
/// <summary>
/// Icon to display in the bound control
- /// </summary>
-
+ /// </summary>
public string Icon {
get { return icon; }
set {
-//
-// Node.cs
+// Copyright (c) 2013-2020 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
//
-// Author:
-// Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
-//
-// Copyright (c) 2013-2017 Jean-Philippe Bruyère
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
using System;
using System.Reflection;
-//
-// NodeStack.cs
+// Copyright (c) 2013-2020 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
//
-// Author:
-// Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
-//
-// Copyright (c) 2013-2017 Jean-Philippe Bruyère
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
using System;
using System.Collections.Generic;
{
public class NodeStack : Stack<Node>
{
- public NodeStack () : base()
- {
- }
public void IncrementCurrentNodeIndex(){
Node n = this.Pop();
this.Push (new Node (n.CrowType, n.Index + 1));
/// <summary>Crow configuration root path</summary>
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 = true;
+ public static bool FOCUS_ON_HOVER = false;
/// <summary> Threshold to catch borders for sizing </summary>
- public static int BorderThreshold = 10;
+ public static int BorderThreshold = 3;
/// <summary> delay before tooltip appears </summary>
public static int TOOLTIP_DELAY = 500;
/// <summary>Double click threshold in milisecond</summary>
public Widget ActiveWidget
{
get { return _activeWidget; }
- set
+ internal set
{
if (_activeWidget == value)
return;
#if DEBUG_FOCUS
NotifyValueChanged("HoverWidget", _hoverWidget);
-#endif
+ #endif
if (DragAndDropOperation == null && FOCUS_ON_HOVER) {
Widget w = _hoverWidget;
}
/// <summary>Widget has the keyboard or mouse focus</summary>
public Widget FocusedWidget {
- get { return _focusedWidget; }
+ get => _focusedWidget;
set {
if (_focusedWidget == value)
return;
//MouseCursorChanged.Raise (this,new MouseCursorChangedEventArgs(cursor));
}
}
+
+ uint stickyMouse = 0;
+ Point stickyMousePos = default;
+ internal void SetStickyMouse (uint threshold = 5)
+ {
+ stickyMouse = threshold;
+ stickyMousePos = MousePosition;
+ }
+
/// <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)
{
+
+ if (stickyMouse>0) {
+ if (Math.Abs(x - stickyMousePos.X) < stickyMouse && Math.Abs(y - stickyMousePos.Y) < stickyMouse)
+ 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);
mouseRepeatTimer.Reset ();
lastMouseDownEvent = null;
- MouseButtonEventArgs e = new MouseButtonEventArgs (MousePosition.X, MousePosition.Y, button, InputAction.Repeat);
if (_activeWidget == null)
return false;
- _activeWidget.onMouseUp (_activeWidget, e);
+ _activeWidget.onMouseUp (_activeWidget, new MouseButtonEventArgs (MousePosition.X, MousePosition.Y, button, InputAction.Release));
if (doubleClickTriggered)
- _activeWidget.onMouseDoubleClick (_activeWidget, e);
+ _activeWidget.onMouseDoubleClick (_activeWidget, new MouseButtonEventArgs (MousePosition.X, MousePosition.Y, button, InputAction.Press));
else
- _activeWidget.onMouseClick (_activeWidget, e);
+ _activeWidget.onMouseClick (_activeWidget, new MouseButtonEventArgs (MousePosition.X, MousePosition.Y, button, InputAction.Press));
ActiveWidget = null;
// if (!lastActive.MouseIsIn (Mouse.Position)) {
public override void onMouseClick (object sender, MouseButtonEventArgs e)
{
IsChecked = !IsChecked;
+ e.Handled = true;
base.onMouseClick (sender, e);
}
}
}
public override void onMouseDown (object sender, MouseButtonEventArgs e)
{
- if (this.HasFocus && _selectable){
- updatemouseLocalPos (e.Position);
- SelBegin = -1;
- SelRelease = -1;
- SelectionInProgress = true;
- RegisterForRedraw();//TODO:should put it in properties
+ if (HasFocus) {
+ if (_selectable) {
+ updatemouseLocalPos (e.Position);
+ SelBegin = -1;
+ SelRelease = -1;
+ SelectionInProgress = true;
+ RegisterForRedraw ();//TODO:should put it in properties
+ }
}
//done at the end to set 'hasFocus' value after testing it
public override void onMouseUp (object sender, MouseButtonEventArgs e)
{
base.onMouseUp (sender, e);
- if (!(this.HasFocus || _selectable))
+ if (!(HasFocus || _selectable))
return;
if (!SelectionInProgress)
return;
-//
-// MessageBox.cs
+// Copyright (c) 2013-2020 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
//
-// Author:
-// Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
-//
-// Copyright (c) 2013-2017 Jean-Philippe Bruyère
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
using System;
-using System.Xml.Serialization;
using System.ComponentModel;
namespace Crow
public class MessageBox : Window
{
#region CTOR
- protected MessageBox () : base(){}
- public MessageBox (Interface iface) : base(iface){}
+ protected MessageBox () {}
+ public MessageBox (Interface iface, string style = null) : base(iface, style){}
#endregion
public enum Type {
#region mouse handling
public override void onMouseDown (object sender, MouseButtonEventArgs e)
{
- base.onMouseDown (sender, e);
+ e.Handled = true;
mouseDownInit = ScreenPointToLocal (e.Position);
mouseDownInitValue = Value;
Rectangle cursInScreenCoord = cursor == null ? default : cursor.ScreenCoordinates (cursor.Slot);
else
Value += LargeIncrement;
+ base.onMouseDown (sender, e);
}
public override void onMouseUp (object sender,MouseButtonEventArgs e)
{
- base.onMouseUp (sender, e);
-
holdCursor = false;
+ e.Handled = true;
+ base.onMouseUp (sender, e);
}
public override void onMouseMove (object sender, MouseMoveEventArgs e)
{
IFace.MouseCursor = MouseCursor.sb_v_double_arrow;
}
public override void onMouseDown (object sender, MouseButtonEventArgs e)
- {
- base.onMouseDown (sender, e);
+ {
go1 = go2 = null;
init1 = init2 = -1;
delta = 0;
if (init2 >= 0)
go2.Height = init2;
}
+ e.Handled = true;
+ base.onMouseDown (sender, e);
}
public override void onMouseMove (object sender, MouseMoveEventArgs e)
{
+ e.Handled = true;
base.onMouseMove (sender, e);
- if (!IsActive || go1 == null || go2 == null)
- return;
-
- GenericStack gs = Parent as GenericStack;
- int newDelta = delta, size1 = init1 , size2 = init2;
- if (gs.Orientation == Orientation.Horizontal) {
- newDelta -= e.XDelta;
- if (size1 < 0)
- size1 = go1.Slot.Width + delta;
- if (size2 < 0)
- size2 = go2.Slot.Width - delta;
- } else {
- newDelta -= e.YDelta;
- if (size1 < 0)
- size1 = go1.Slot.Height + delta;
- if (size2 < 0)
- size2 = go2.Slot.Height - delta;
- }
+ if (IsActive && go1 != null && go2 != null) {
+ GenericStack gs = Parent as GenericStack;
+ int newDelta = delta, size1 = init1, size2 = init2;
+ if (gs.Orientation == Orientation.Horizontal) {
+ newDelta -= e.XDelta;
+ if (size1 < 0)
+ size1 = go1.Slot.Width + delta;
+ if (size2 < 0)
+ size2 = go2.Slot.Width - delta;
+ } else {
+ newDelta -= e.YDelta;
+ if (size1 < 0)
+ size1 = go1.Slot.Height + delta;
+ if (size2 < 0)
+ size2 = go2.Slot.Height - delta;
+ }
- if (size1 - newDelta < min1 || (max1 > 0 && size1 - newDelta > max1) ||
- size2 + newDelta < min2 || (max2 > 0 && size2 + newDelta > max2))
- return;
+ if (size1 - newDelta < min1 || (max1 > 0 && size1 - newDelta > max1) ||
+ size2 + newDelta < min2 || (max2 > 0 && size2 + newDelta > max2))
+ return;
- delta = newDelta;
+ delta = newDelta;
+
+ if (gs.Orientation == Orientation.Horizontal) {
+ if (init1 >= 0)
+ go1.Width = init1 - delta;
+ if (init2 >= 0)
+ go2.Width = init2 + delta;
+ } else {
+ if (init1 >= 0)
+ go1.Height = init1 - delta;
+ if (init2 >= 0)
+ go2.Height = init2 + delta;
+ }
- if (gs.Orientation == Orientation.Horizontal) {
- if (init1 >= 0)
- go1.Width = init1 - delta;
- if (init2 >= 0)
- go2.Width = init2 + delta;
- } else {
- if (init1 >= 0)
- go1.Height = init1 - delta;
- if (init2 >= 0)
- go2.Height = init2 + delta;
}
}
public override void onMouseUp (object sender, MouseButtonEventArgs e)
[XmlIgnore]public override bool HasFocus //trigger update when lost focus to errase text beam
{
get => base.HasFocus;
- set {
+ internal set {
+ if (base.HasFocus == value)
+ return;
base.HasFocus = value;
RegisterForRedraw();
}
case Key.Backspace:
if (CurrentPosition == 0)
return;
- this.DeleteChar();
+ DeleteChar();
break;
case Key.Delete:
if (selectionIsEmpty) {
if (!MoveRight ())
return;
}else if (IFace.Shift)
- IFace.Clipboard = this.SelectedText;
- this.DeleteChar ();
+ IFace.Clipboard = SelectedText;
+ DeleteChar ();
break;
case Key.KeypadEnter:
case Key.Enter:
if (!selectionIsEmpty)
- this.DeleteChar ();
+ DeleteChar ();
if (Multiline)
- this.InsertLineBreak ();
+ InsertLineBreak ();
else
OnTextChanged(this,new TextChangeEventArgs(Text));
break;
/// <summary>
/// Mouse routing need to go back to logical parent for popups
/// </summary>
- public Widget FocusParent => (parent is Interface ? LogicalParent : parent) as Widget;
+ internal Widget FocusParent => (parent is Interface ? LogicalParent : parent) as Widget;
[XmlIgnore]public ILayoutable LogicalParent {
get { return logicalParent == null ? Parent : logicalParent; }
/// </summary>
[XmlIgnore]public virtual bool HasFocus {
get { return hasFocus; }
- set {
+ internal set {
if (value == hasFocus)
return;
/// </summary>
[XmlIgnore]public virtual bool IsActive {
get { return isActive; }
- set {
+ internal set {
if (value == isActive)
return;
/// </summary>
[XmlIgnore]public virtual bool IsHover {
get { return isHover; }
- set {
+ internal set {
if (value == isHover)
return;
if (r.Bottom > cb.Bottom)
r.Height -= r.Bottom - cb.Bottom;
if (r.Width < 0 || r.Height < 0) {
- Debug.WriteLine ($"Invalid clip: {clip}:{r} hnd:{this}");//\n{Environment.StackTrace}");
+ //Debug.WriteLine ($"Invalid clip: {clip}:{r} hnd:{this}");//\n{Environment.StackTrace}");
return;
}
if (cacheEnabled && !IsDirty)
{
#if DEBUG
if (disposed) {
- System.Diagnostics.Debug.WriteLine ($"RegisterForGraphicUpdate for disposed Widget: {this}\n{System.Environment.StackTrace}");
+// System.Diagnostics.Debug.WriteLine ($"RegisterForGraphicUpdate for disposed Widget: {this}\n{System.Environment.StackTrace}");
return;
}
#endif
public virtual void checkHoverWidget(MouseMoveEventArgs e)
{
if (IFace.HoverWidget != this) {
- IFace.HoverWidget = this;
onMouseEnter (this, e);
+ IFace.HoverWidget = this;
}
//this.onMouseMove (this, e);//without this, window border doesn't work, should be removed
#if DEBUG_FOCUS
Debug.WriteLine("MOUSE DOWN => " + this.ToString());
#endif
+ if (Focusable)
+ IFace.FocusedWidget = this;
if (e.Button == MouseButton.Right && contextCommands != null) {
IFace.ShowContextMenu (this);
{
#if DEBUG_FOCUS
Debug.WriteLine("MouseEnter => " + this.ToString());
-#endif
+ #endif
IFace.MouseCursor = MouseCursor;
bool modal;
protected bool hoverBorder = false;
bool alwaysOnTop = false;
- Fill titleBarBackground = Colors.SteelBlue;
- Fill titleBarForeground = Colors.White;
Rectangle savedBounds;
bool _minimized = false;
public Window (Interface iface, string style = null) : base (iface, style) { }
#endregion
+ Widget moveHandle, sizingHandle;
+
+
#region TemplatedContainer overrides
protected override void loadTemplate(Widget template = null)
{
NotifyValueChanged ("ShowNormal", false);
NotifyValueChanged ("ShowMinimize", true);
NotifyValueChanged ("ShowMaximize", true);
+
+ moveHandle = child?.FindByName ("MoveHandle");
+ sizingHandle = child?.FindByName ("SizeHandle");
+
+ if (sizingHandle == null)
+ return;
+ sizingHandle.MouseEnter += (arg1, arg2) => IFace.SetStickyMouse(5);
}
#endregion
NotifyValueChangedAuto (_icon);
}
}
- /// <summary>
- /// Background of the title bar if any.
- /// </summary>
- [DefaultValue("vgradient|0:Onyx|1:SteelBlue")]
- public virtual Fill TitleBarBackground {
- get { return titleBarBackground; }
- set {
- if (titleBarBackground == value)
- return;
- titleBarBackground = value;
- NotifyValueChangedAuto (titleBarBackground);
- RegisterForRedraw ();
- }
- }
- /// <summary>
- /// Foreground of the title bar, usualy used for the window caption color.
- /// </summary>
- [DefaultValue("White")]
- public virtual Fill TitleBarForeground {
- get { return titleBarForeground; }
- set {
- if (titleBarForeground == value)
- return;
- titleBarForeground = value;
- NotifyValueChangedAuto (titleBarForeground);
- RegisterForRedraw ();
- }
- }
[DefaultValue(true)]
public bool Resizable {
get {
NotifyValueChangedAuto (AlwaysOnTop);
}
}
-// [DefaultValue(WindowState.Normal)]
-// public virtual WindowState State {
-// get { return _state; }
-// set {
-// if (_state == value)
-// return;
-// _state = value;
-// NotifyValueChanged ("State", _state);
-// NotifyValueChanged ("IsNormal", IsNormal);
-// NotifyValueChanged ("IsMaximized", IsMaximized);
-// NotifyValueChanged ("IsMinimized", IsMinimized);
-// NotifyValueChanged ("IsNotMinimized", IsNotMinimized);
-// }
-// }
#endregion
/// <summary>
}
}
+ bool maySize => sizingHandle == null ? false : resizable & sizingHandle.IsHover;
+ bool mayMove => moveHandle == null ? false : movable & moveHandle.IsHover;
+
#region GraphicObject Overrides
public override void onMouseMove (object sender, MouseMoveEventArgs e)
{
Interface otkgw = IFace;
- if (HasFocus) {
- if (movable) {
- if (IFace.IsDown (MouseButton.Left)) {
- MoveAndResize (e.XDelta, e.YDelta, currentDirection);
- return;
- }
+ if (maySize || mayMove) {
+ if (grabMouse) {
+ MoveAndResize (e.XDelta, e.YDelta, currentDirection);
+ return;
}
- } else {
- currentDirection = Direction.None;
+ }else
return;
- }
-
Point m = Parent is Widget ? (Parent as Widget).ScreenPointToLocal (e.Position) : e.Position;
- if (Resizable) {
- Direction lastDir = currentDirection;
-
+ if (maySize) {
if (Math.Abs (m.Y - this.Slot.Y) < Interface.BorderThreshold) {
if (Math.Abs (m.X - this.Slot.X) < Interface.BorderThreshold)
currentDirection = Direction.NW;
currentDirection = Direction.W;
else if (Math.Abs (m.X - this.Slot.Right) < Interface.BorderThreshold)
currentDirection = Direction.E;
- else
- currentDirection = Direction.None;
-
- //if (currentDirection != lastDir) {
- switch (currentDirection) {
- case Direction.None:
- otkgw.MouseCursor = MouseCursor.move;
- break;
- case Direction.N:
- otkgw.MouseCursor = MouseCursor.top_side;
- break;
- case Direction.S:
- otkgw.MouseCursor = MouseCursor.bottom_side;
- break;
- case Direction.E:
- otkgw.MouseCursor = MouseCursor.right_side;
- break;
- case Direction.W:
- otkgw.MouseCursor = MouseCursor.left_side;
- break;
- case Direction.NW:
- otkgw.MouseCursor = MouseCursor.top_left_corner;
- break;
- case Direction.NE:
- otkgw.MouseCursor = MouseCursor.top_right_corner;
- break;
- case Direction.SW:
- otkgw.MouseCursor = MouseCursor.bottom_left_corner;
- break;
- case Direction.SE:
- otkgw.MouseCursor = MouseCursor.bottom_right_corner;
- break;
- }
- //}
- }
+ } else if (mayMove)
+ currentDirection = Direction.None;
+ else
+ return;
+
+ switch (currentDirection) {
+ case Direction.None:
+ otkgw.MouseCursor = MouseCursor.move;
+ break;
+ case Direction.N:
+ otkgw.MouseCursor = MouseCursor.top_side;
+ break;
+ case Direction.S:
+ otkgw.MouseCursor = MouseCursor.bottom_side;
+ break;
+ case Direction.E:
+ otkgw.MouseCursor = MouseCursor.right_side;
+ break;
+ case Direction.W:
+ otkgw.MouseCursor = MouseCursor.left_side;
+ break;
+ case Direction.NW:
+ otkgw.MouseCursor = MouseCursor.top_left_corner;
+ break;
+ case Direction.NE:
+ otkgw.MouseCursor = MouseCursor.top_right_corner;
+ break;
+ case Direction.SW:
+ otkgw.MouseCursor = MouseCursor.bottom_left_corner;
+ break;
+ case Direction.SE:
+ otkgw.MouseCursor = MouseCursor.bottom_right_corner;
+ break;
+ }
+
}
public override void onMouseLeave (object sender, MouseMoveEventArgs e)
{
currentDirection = Direction.None;
IFace.MouseCursor = MouseCursor.top_left_arrow;
}
+ bool grabMouse;
public override void onMouseDown (object sender, MouseButtonEventArgs e)
{
+ grabMouse = true;
+ e.Handled = true;
base.onMouseDown (sender, e);
}
+ public override void onMouseUp (object sender, MouseButtonEventArgs e)
+ {
+ grabMouse = false;
+ e.Handled = true;
+ base.onMouseUp (sender, e);
+ }
public override bool MouseIsIn (Point m)
{
return modal ? true : base.MouseIsIn (m);
lock (IFace.LayoutMutex) {
if (!IsMinimized)
savedBounds = this.LastPaintedSlot;
- this.Left = this.Top = 0;
- this.RegisterForLayouting (LayoutingType.Positioning);
- this.Width = this.Height = Measure.Stretched;
+ Left = Top = 0;
+ RegisterForLayouting (LayoutingType.Positioning);
+ Width = Height = Measure.Stretched;
IsMinimized = false;
Resizable = false;
NotifyValueChanged ("ShowNormal", true);
}
protected void onUnmaximized (object sender, EventArgs e){
lock (IFace.LayoutMutex) {
- this.Left = savedBounds.Left;
- this.Top = savedBounds.Top;
- this.Width = savedBounds.Width;
- this.Height = savedBounds.Height;
+ Left = savedBounds.Left;
+ Top = savedBounds.Top;
+ Width = savedBounds.Width;
+ Height = savedBounds.Height;
IsMinimized = false;
Resizable = true;
NotifyValueChanged ("ShowNormal", false);
(Parent as Interface).DeleteWidget (this);
else {
Widget p = Parent as Widget;
- if (p is Group) {
+ if (p is Group g) {
lock (IFace.UpdateMutex) {
RegisterClip (p.ScreenCoordinates (p.LastPaintedSlot));
- (p as Group).DeleteChild (this);
+ g.DeleteChild (this);
}
//(Parent as Group).RegisterForRedraw ();
- } else if (Parent is PrivateContainer)
- (Parent as Container).Child = null;
+ } else if (Parent is Container c)
+ c.Child = null;
}
}
return w;
}
}
+
}
}
-<Container Background="Onyx">
- <VerticalStack Background="Jet" Fit="true" Margin="1" Spacing="1">
- <Gauge Width="200" Height="10" Background="RoyalBlue" Value="50" CornerRadius="5"/>
- <NumericControl Width="200" Height="10" Value="40">
- <Template>
- <Gauge Maximum="{./Maximum}" Foreground="Black" BorderWidth="1" Background="RoyalBlue" Value="{./Value}" CornerRadius="5"/>
- </Template>
- </NumericControl>
- <Gauge Width="10" Height="100" Background="RoyalBlue" Value="50" CornerRadius="5" Orientation="Vertical"/>
- <HorizontalStack Width="400" Height="300">
- <Scroller Name="scroller1" Background="White"
- Margin="2" ScrollY="{../scrollbar1.Value}"
- ValueChanged="./_scroller_ValueChanged">
- <Widget VerticalAlignment="Top" Background="vgradient|0:1,0,0,1|1:0,1,0,1" Width="1000" Height="1000"/>
- </Scroller>
- <Slider Template="#Crow.VScrollBar.template" Name="scrollbar1" Value="{../scroller1.ScrollY}"
- LargeIncrement="{../scroller1.PageHeight}" SmallIncrement="30" Height="Stretched"
- CursorSize="{../scroller1.ChildHeightRatio}"
- Maximum="{../scroller1.MaxScrollY}" Orientation="Vertical" Width="14" >
- <Template>
- <Border BorderWidth="1" Foreground="{./Foreground}" Background="{./Background}">
- <GenericStack Orientation="{./Orientation}" Spacing="0">
- <Shape Style="ArrowBut" MouseDown="./OnDecrease"
- Height="10" Size="10,10" Path="M 4.5,0.5 L 9.5,9.5 L 0.5,9.5 Z F"/>
- <Gauge Name="Slider"
- Orientation="{./Orientation}"
- Value="{²./Value}"
- Maximum="{./Maximum}"
- Height="{./HeightPolicy}" Width="{./WidthPolicy}"
- Background="RoyalBlue" Foreground="{./Foreground}"/>
- <Shape Style="ArrowBut" MouseDown="./OnIncrease"
- Height="10" Size="10,10" Path="M 0.5,0.5 L 9.5,0.5 L 4.5,9.5 Z F"/>
- </GenericStack>
- </Border>
- </Template>
- </Slider>
- </HorizontalStack>
- </VerticalStack>
-</Container>
\ No newline at end of file
+<?xml version="1.0"?>
+<Label Text="Hello World"/>
\ No newline at end of file
--- /dev/null
+<Window Width="80%" Movable="false">
+ <VerticalStack>
+ <HorizontalStack Height="Fit">
+ <Label Text="Hover:" Width="50" Foreground="Grey"/>
+ <Label Text="{HoverWidget}" Font="mono, 8"/>
+ </HorizontalStack>
+ <HorizontalStack Height="Fit">
+ <Label Text="Focus:" Width="50" Foreground="Grey"/>
+ <Label Text="{FocusedWidget}" Font="mono, 8"/>
+ </HorizontalStack>
+ <HorizontalStack Height="Fit">
+ <Label Text="Active:" Width="50" Foreground="Grey"/>
+ <Label Text="{ActiveWidget}" Font="mono, 8"/>
+ </HorizontalStack>
+ </VerticalStack>
+</Window>
+
+++ /dev/null
-<?xml version="1.0"?>
-<Window Caption="Hello World" Icon="#Crow.Icons.crow.svg" Width="40%" Height="40%" CornerRadius="5">
- <VerticalStack>
- <Label Text="Hello World" Font="mono, 20"/>
- <Image Path="#Crow.Icons.crow.svg"/>
- </VerticalStack>
-</Window>
-
ValueChanged="./_scroller_ValueChanged">
<TextBox VerticalAlignment="Top"
Text="{²Source}" Multiline="true" TextAlignment="TopLeft"
- Font="Courriernew 10"/>
+ Font="mono 10"/>
</Scroller>
<ScrollBar Name="scrollbar1" Value="{../scroller1.ScrollY}"
LargeIncrement="{../scroller1.PageHeight}" SmallIncrement="30"
<?xml version="1.0"?>
<HorizontalStack Margin="50">
<VerticalStack Spacing="10" Width="50%">
- <Slider Height="20" Width="Stretched"/>
+ <Slider Background="DarkGrey" Height="20" Width="Stretched"/>
<Slider Background="RoyalBlue" Height="50" Width="Stretched" CursorSize="50">
<Template>
<Group Background="DarkGrey" >