From e0dc9ee6615bab20767d96634be328d3ef3369bd Mon Sep 17 00:00:00 2001
From: Janko Buve <26929742+jnkb@users.noreply.github.com>
Date: Fri, 15 Apr 2022 16:31:28 +0200
Subject: [PATCH 1/2] Added separate actions for button down and up
---
TabletFriend/TabletFriend/Data/ButtonData.cs | 6 +-
.../TabletFriend/Models/ButtonModel.cs | 28 +-
TabletFriend/TabletFriend/UiFactory.cs | 552 ++++++++++--------
.../files/layouts/sample_layout.yaml | 12 +
4 files changed, 335 insertions(+), 263 deletions(-)
diff --git a/TabletFriend/TabletFriend/Data/ButtonData.cs b/TabletFriend/TabletFriend/Data/ButtonData.cs
index d7b2819..fdc3955 100644
--- a/TabletFriend/TabletFriend/Data/ButtonData.cs
+++ b/TabletFriend/TabletFriend/Data/ButtonData.cs
@@ -5,7 +5,11 @@ public class ButtonData
{
public string Action;
public string[] Actions;
- public string Text;
+
+ public string ActionRelease;
+ public string[] ActionsRelease;
+
+ public string Text;
public string Icon;
public StretchData IconStretch;
public string Size;
diff --git a/TabletFriend/TabletFriend/Models/ButtonModel.cs b/TabletFriend/TabletFriend/Models/ButtonModel.cs
index 468aa4d..f434196 100644
--- a/TabletFriend/TabletFriend/Models/ButtonModel.cs
+++ b/TabletFriend/TabletFriend/Models/ButtonModel.cs
@@ -10,11 +10,24 @@
namespace TabletFriend.Models
{
- public class ButtonModel : IDisposable
+ public enum ButtonProcessedEvent
+ {
+ None,
+ Down,
+ Up
+
+ }
+ public class ButtonModel : IDisposable
{
public ButtonAction Action;
+ public ButtonAction ActionRelease;
- public string Text = "";
+ ///
+ /// Logging of last processed event to avoid multiple invocations due to double triggered mouse and touch events when action(s)_release is used
+ ///
+ public ButtonProcessedEvent LastProcessedEvent { get; set; } = ButtonProcessedEvent.None;
+
+ public string Text = "";
public object Icon;
public Vector2 Position = Vector2.Zero;
@@ -81,7 +94,16 @@ public ButtonModel(ButtonData data)
Action = new BatchAction(ButtonActionResolver.Resolve(data.Actions));
}
- Style = data.Style;
+ if (data.ActionsRelease == null || data.ActionsRelease.Length == 0)
+ {
+ ActionRelease = ButtonActionResolver.Resolve(data.ActionRelease);
+ }
+ else
+ {
+ ActionRelease = new BatchAction(ButtonActionResolver.Resolve(data.ActionsRelease));
+ }
+
+ Style = data.Style;
Font = data.Font;
FontSize = data.FontSize;
diff --git a/TabletFriend/TabletFriend/UiFactory.cs b/TabletFriend/TabletFriend/UiFactory.cs
index 3f357f8..f2ae7ec 100644
--- a/TabletFriend/TabletFriend/UiFactory.cs
+++ b/TabletFriend/TabletFriend/UiFactory.cs
@@ -13,263 +13,297 @@
namespace TabletFriend
{
- public static class UiFactory
- {
- public static void CreateUi(LayoutModel layout, MainWindow window)
- {
- ToggleManager.ClearButtons();
- var theme = layout.Theme;
-
- window.MainCanvas.Children.Clear();
-
- var isDocked = AppState.Settings.DockingMode != DockingMode.None;
-
- if (!isDocked)
- {
- window.MainBorder.CornerRadius = new CornerRadius(theme.Rounding);
- }
- else
- {
- window.MainBorder.CornerRadius = new CornerRadius(0);
- }
- var sizes = layout.Buttons.GetSizes(isDocked);
- var positions = Packer.Pack(sizes, layout.LayoutWidth);
-
- var size = Packer.GetSize(positions, sizes);
-
-
- var rotateLayout = false;
- var layoutVertical = size.Y > size.X;
- if (AppState.Settings.DockingMode != DockingMode.None)
- {
- var dockingVertical = AppState.Settings.DockingMode == DockingMode.Left
- || AppState.Settings.DockingMode == DockingMode.Right;
-
- if (layoutVertical != dockingVertical)
- {
- rotateLayout = true;
- }
- }
-
- var titlebarHeight = TitlebarManager.GetTitlebarHeight(theme);
-
- if (rotateLayout)
- {
- window.Height = size.X * theme.CellSize + theme.Margin + titlebarHeight;
- window.Width = size.Y * theme.CellSize + theme.Margin;
- }
- else
- {
- window.Width = size.X * theme.CellSize + theme.Margin;
- window.Height = size.Y * theme.CellSize + theme.Margin + titlebarHeight;
- }
-
- var offset = Vector2.Zero;
- if (AppState.Settings.DockingMode != DockingMode.None)
- {
- if (AppState.Settings.DockingMode == DockingMode.Top || AppState.Settings.DockingMode == DockingMode.Bottom)
- {
- offset.X = (float)(SystemParameters.PrimaryScreenWidth - window.Width) / 2;
- }
- else
- {
- offset.Y = (float)(SystemParameters.PrimaryScreenHeight - window.Height) / 2;
- }
- }
- else
- {
- offset.Y = (float)titlebarHeight;
- }
-
- if (AppState.Settings.DockingMode != DockingMode.None)
- {
- window.MinOpacity = theme.MaxOpacity;
- }
- else
- {
- window.MinOpacity = theme.MinOpacity;
- }
- window.MaxOpacity = theme.MaxOpacity;
- window.BeginAnimation(UIElement.OpacityProperty, null);
- window.Opacity = theme.MaxOpacity;
- if (window.IsMouseOver)
- {
- window.BeginAnimation(UIElement.OpacityProperty, window.FadeIn);
- }
- else
- {
- window.BeginAnimation(UIElement.OpacityProperty, window.FadeOut);
- }
-
- Application.Current.Resources["PrimaryHueMidBrush"] = new SolidColorBrush(theme.PrimaryColor);
- Application.Current.Resources["PrimaryHueMidForegroundBrush"] = new SolidColorBrush(theme.SecondaryColor);
- Application.Current.Resources["MaterialDesignToolForeground"] = new SolidColorBrush(theme.SecondaryColor);
-
- Application.Current.Resources["MaterialDesignPaper"] = new SolidColorBrush(theme.BackgroundColor);
- Application.Current.Resources["MaterialDesignFont"] = new SolidColorBrush(theme.SecondaryColor);
- Application.Current.Resources["MaterialDesignBody"] = new SolidColorBrush(theme.SecondaryColor);
-
- window.MainBorder.Background = new SolidColorBrush(theme.BackgroundColor);
-
- var visibleButtons = new List();
-
- foreach (var button in layout.Buttons)
- {
- if (button.IsVisible(isDocked))
- {
- visibleButtons.Add(button);
- }
- }
-
- for (var i = 0; i < positions.Length; i += 1)
- {
- var button = visibleButtons[i];
-
-
- if (button.Spacer)
- {
- continue;
- }
- var buttonPosition = positions[i];
- var buttonSize = sizes[i];
-
- if (rotateLayout)
- {
- var buffer = buttonPosition.X;
- buttonPosition.X = buttonPosition.Y;
- buttonPosition.Y = buffer;
-
- buffer = buttonSize.X;
- buttonSize.X = buttonSize.Y;
- buttonSize.Y = buffer;
- }
-
- CreateButton(layout, window, button, buttonPosition, buttonSize, offset);
- }
-
-
- TitlebarManager.CreateTitlebar(window, theme);
- }
-
- private static void CreateButton(
- LayoutModel layout,
- MainWindow window,
- ButtonModel button,
- Vector2 position,
- Vector2 size,
- Vector2 offset
- )
- {
- var theme = layout.Theme;
-
- ButtonBase uiButton;
- var isToggle = button.Action is ToggleAction;
- var isRepeat = button.Action is RepeatAction;
-
- if (isToggle)
- {
- uiButton = new ToggleButton();
- }
- else
- {
- if (isRepeat)
- {
- uiButton = new RepeatButton();
- Stylus.SetIsPressAndHoldEnabled(uiButton, false);
- }
- else
- {
- uiButton = new Button();
- }
- }
- uiButton.Width = theme.CellSize * size.X - theme.Margin;
- uiButton.Height = theme.CellSize * size.Y - theme.Margin;
-
- var font = button.Font;
- if (font == null)
- {
- font = layout.Theme.DefaultFont;
- }
- var fontSize = button.FontSize;
- if (fontSize == 0)
- {
- fontSize = layout.Theme.DefaultFontSize;
- }
- var fontWeight = button.FontWeight;
- if (fontWeight == 0)
- {
- fontWeight = layout.Theme.DefaultFontWeight;
- }
-
- var text = new TextBlock();
- text.Text = button.Text;
- if (fontSize > 0)
- {
- text.FontSize = fontSize;
- }
- if (font != null)
- {
- text.FontFamily = new FontFamily(font);
- }
- if (fontWeight > 0)
- {
- text.FontWeight = FontWeight.FromOpenTypeWeight(Math.Min(999, fontWeight));
- }
-
- uiButton.Content = text;
-
- if (button.Icon != null)
- {
- uiButton.Content = button.Icon;
- if (!string.IsNullOrEmpty(button.Text))
- {
- uiButton.ToolTip = new ToolTip()
- {
- Style = Application.Current.Resources["tool_tip"] as Style,
- Content = button.Text,
- HasDropShadow = true,
- };
- }
- }
-
- var style = button.Style;
- if (style == null)
- {
- style = theme.DefaultStyle;
- }
-
- if (isToggle)
- {
- uiButton.Style = Application.Current.Resources["toggle"] as Style;
-
- var key = ((ToggleAction)button.Action).Key;
- var toggle = (ToggleButton)uiButton;
- if (ToggleManager.IsHeld(key))
- {
- toggle.IsChecked = true;
- }
- ToggleManager.AddButton(key, toggle);
- }
- else
- {
- if (style == null)
- {
- uiButton.Style = null;
- }
- else
- {
- uiButton.Style = Application.Current.Resources[style] as Style;
- }
- }
-
- if (button.Action != null)
- {
- uiButton.Click += (e, o) => _ = button.Action.Invoke();
- }
-
- Canvas.SetTop(uiButton, theme.CellSize * position.Y + theme.Margin + offset.Y);
- Canvas.SetLeft(uiButton, theme.CellSize * position.X + theme.Margin + offset.X);
- window.MainCanvas.Children.Add(uiButton);
- }
- }
+ public static class UiFactory
+ {
+ public static void CreateUi(LayoutModel layout, MainWindow window)
+ {
+ ToggleManager.ClearButtons();
+ var theme = layout.Theme;
+
+ window.MainCanvas.Children.Clear();
+
+ var isDocked = AppState.Settings.DockingMode != DockingMode.None;
+
+ if (!isDocked)
+ {
+ window.MainBorder.CornerRadius = new CornerRadius(theme.Rounding);
+ }
+ else
+ {
+ window.MainBorder.CornerRadius = new CornerRadius(0);
+ }
+ var sizes = layout.Buttons.GetSizes(isDocked);
+ var positions = Packer.Pack(sizes, layout.LayoutWidth);
+
+ var size = Packer.GetSize(positions, sizes);
+
+
+ var rotateLayout = false;
+ var layoutVertical = size.Y > size.X;
+ if (AppState.Settings.DockingMode != DockingMode.None)
+ {
+ var dockingVertical = AppState.Settings.DockingMode == DockingMode.Left
+ || AppState.Settings.DockingMode == DockingMode.Right;
+
+ if (layoutVertical != dockingVertical)
+ {
+ rotateLayout = true;
+ }
+ }
+
+ var titlebarHeight = TitlebarManager.GetTitlebarHeight(theme);
+
+ if (rotateLayout)
+ {
+ window.Height = size.X * theme.CellSize + theme.Margin + titlebarHeight;
+ window.Width = size.Y * theme.CellSize + theme.Margin;
+ }
+ else
+ {
+ window.Width = size.X * theme.CellSize + theme.Margin;
+ window.Height = size.Y * theme.CellSize + theme.Margin + titlebarHeight;
+ }
+
+ var offset = Vector2.Zero;
+ if (AppState.Settings.DockingMode != DockingMode.None)
+ {
+ if (AppState.Settings.DockingMode == DockingMode.Top || AppState.Settings.DockingMode == DockingMode.Bottom)
+ {
+ offset.X = (float)(SystemParameters.PrimaryScreenWidth - window.Width) / 2;
+ }
+ else
+ {
+ offset.Y = (float)(SystemParameters.PrimaryScreenHeight - window.Height) / 2;
+ }
+ }
+ else
+ {
+ offset.Y = (float)titlebarHeight;
+ }
+
+ if (AppState.Settings.DockingMode != DockingMode.None)
+ {
+ window.MinOpacity = theme.MaxOpacity;
+ }
+ else
+ {
+ window.MinOpacity = theme.MinOpacity;
+ }
+ window.MaxOpacity = theme.MaxOpacity;
+ window.BeginAnimation(UIElement.OpacityProperty, null);
+ window.Opacity = theme.MaxOpacity;
+ if (window.IsMouseOver)
+ {
+ window.BeginAnimation(UIElement.OpacityProperty, window.FadeIn);
+ }
+ else
+ {
+ window.BeginAnimation(UIElement.OpacityProperty, window.FadeOut);
+ }
+
+ Application.Current.Resources["PrimaryHueMidBrush"] = new SolidColorBrush(theme.PrimaryColor);
+ Application.Current.Resources["PrimaryHueMidForegroundBrush"] = new SolidColorBrush(theme.SecondaryColor);
+ Application.Current.Resources["MaterialDesignToolForeground"] = new SolidColorBrush(theme.SecondaryColor);
+
+ Application.Current.Resources["MaterialDesignPaper"] = new SolidColorBrush(theme.BackgroundColor);
+ Application.Current.Resources["MaterialDesignFont"] = new SolidColorBrush(theme.SecondaryColor);
+ Application.Current.Resources["MaterialDesignBody"] = new SolidColorBrush(theme.SecondaryColor);
+
+ window.MainBorder.Background = new SolidColorBrush(theme.BackgroundColor);
+
+ var visibleButtons = new List();
+
+ foreach (var button in layout.Buttons)
+ {
+ if (button.IsVisible(isDocked))
+ {
+ visibleButtons.Add(button);
+ }
+ }
+
+ for (var i = 0; i < positions.Length; i += 1)
+ {
+ var button = visibleButtons[i];
+
+
+ if (button.Spacer)
+ {
+ continue;
+ }
+ var buttonPosition = positions[i];
+ var buttonSize = sizes[i];
+
+ if (rotateLayout)
+ {
+ var buffer = buttonPosition.X;
+ buttonPosition.X = buttonPosition.Y;
+ buttonPosition.Y = buffer;
+
+ buffer = buttonSize.X;
+ buttonSize.X = buttonSize.Y;
+ buttonSize.Y = buffer;
+ }
+
+ CreateButton(layout, window, button, buttonPosition, buttonSize, offset);
+ }
+
+
+ TitlebarManager.CreateTitlebar(window, theme);
+ }
+
+ private static void CreateButton(
+ LayoutModel layout,
+ MainWindow window,
+ ButtonModel button,
+ Vector2 position,
+ Vector2 size,
+ Vector2 offset
+ )
+ {
+ var theme = layout.Theme;
+
+ ButtonBase uiButton;
+ var isToggle = button.Action is ToggleAction;
+ var isRepeat = button.Action is RepeatAction;
+
+ if (isToggle)
+ {
+ uiButton = new ToggleButton();
+ }
+ else
+ {
+ if (isRepeat)
+ {
+ uiButton = new RepeatButton();
+ Stylus.SetIsPressAndHoldEnabled(uiButton, false);
+ }
+ else
+ {
+ uiButton = new Button();
+ }
+ }
+ uiButton.Width = theme.CellSize * size.X - theme.Margin;
+ uiButton.Height = theme.CellSize * size.Y - theme.Margin;
+
+ var font = button.Font;
+ if (font == null)
+ {
+ font = layout.Theme.DefaultFont;
+ }
+ var fontSize = button.FontSize;
+ if (fontSize == 0)
+ {
+ fontSize = layout.Theme.DefaultFontSize;
+ }
+ var fontWeight = button.FontWeight;
+ if (fontWeight == 0)
+ {
+ fontWeight = layout.Theme.DefaultFontWeight;
+ }
+
+ var text = new TextBlock();
+ text.Text = button.Text;
+ if (fontSize > 0)
+ {
+ text.FontSize = fontSize;
+ }
+ if (font != null)
+ {
+ text.FontFamily = new FontFamily(font);
+ }
+ if (fontWeight > 0)
+ {
+ text.FontWeight = FontWeight.FromOpenTypeWeight(Math.Min(999, fontWeight));
+ }
+
+ uiButton.Content = text;
+
+ if (button.Icon != null)
+ {
+ uiButton.Content = button.Icon;
+ if (!string.IsNullOrEmpty(button.Text))
+ {
+ uiButton.ToolTip = new ToolTip()
+ {
+ Style = Application.Current.Resources["tool_tip"] as Style,
+ Content = button.Text,
+ HasDropShadow = true,
+ };
+ }
+ }
+
+ var style = button.Style;
+ if (style == null)
+ {
+ style = theme.DefaultStyle;
+ }
+
+ if (isToggle)
+ {
+ uiButton.Style = Application.Current.Resources["toggle"] as Style;
+
+ var key = ((ToggleAction)button.Action).Key;
+ var toggle = (ToggleButton)uiButton;
+ if (ToggleManager.IsHeld(key))
+ {
+ toggle.IsChecked = true;
+ }
+ ToggleManager.AddButton(key, toggle);
+ }
+ else
+ {
+ if (style == null)
+ {
+ uiButton.Style = null;
+ }
+ else
+ {
+ uiButton.Style = Application.Current.Resources[style] as Style;
+ }
+ }
+
+ if (button.ActionRelease == null)
+ {
+ // Default Click Action
+ if (button.Action != null)
+ {
+ uiButton.Click += (e, o) => _ = button.Action.Invoke();
+ }
+ }
+ else
+ { // Separate actions for Pointer-Down and Pointer-Up
+
+ // disable long press context menu on button
+ uiButton.SetValue(Stylus.IsPressAndHoldEnabledProperty, false);
+
+ if (button.Action != null)
+ {
+ void downAction(object o, EventArgs e)
+ {
+ if (button.LastProcessedEvent == ButtonProcessedEvent.Down) return; // invoke only once
+ button.LastProcessedEvent = ButtonProcessedEvent.Down;
+ button.Action.Invoke();
+ }
+ uiButton.TouchDown += downAction;
+ uiButton.PreviewMouseLeftButtonDown += downAction;
+
+ }
+ if (button.ActionRelease != null)
+ {
+ void releaseAction(object o, EventArgs e)
+ {
+ if (button.LastProcessedEvent == ButtonProcessedEvent.Up) return;
+ button.LastProcessedEvent = ButtonProcessedEvent.Up;
+ button.ActionRelease.Invoke();
+ };
+ uiButton.PreviewMouseLeftButtonUp += releaseAction;
+ uiButton.TouchUp += releaseAction;
+ }
+ }
+
+ Canvas.SetTop(uiButton, theme.CellSize * position.Y + theme.Margin + offset.Y);
+ Canvas.SetLeft(uiButton, theme.CellSize * position.X + theme.Margin + offset.X);
+ window.MainCanvas.Children.Add(uiButton);
+ }
+ }
}
diff --git a/TabletFriend/TabletFriend/files/layouts/sample_layout.yaml b/TabletFriend/TabletFriend/files/layouts/sample_layout.yaml
index 7a43936..3958840 100644
--- a/TabletFriend/TabletFriend/files/layouts/sample_layout.yaml
+++ b/TabletFriend/TabletFriend/files/layouts/sample_layout.yaml
@@ -91,6 +91,18 @@ buttons:
icon: apple_keyboard_shift
text: shift
size: 2,1
+
+ shift2:
+ action: hold shift # shift is pressed while the button is pressed
+ action_release: release shift # for multiple actions use actions_release
+ style: outlined
+ icon: apple_keyboard_shift
+ text: shift (while button is pressed)
+ size: 2,1
+
+ spacer2:
+ spacer: true
+ size: 2,1
type:
actions: # Typing "actions" instead of "action" will make the button chain multiple actions. Any action can be used.
From 048d002b4e91cf79fa3b10a468281e7b1da96f67 Mon Sep 17 00:00:00 2001
From: Janko Buve <26929742+jnkb@users.noreply.github.com>
Date: Fri, 15 Apr 2022 20:19:36 +0200
Subject: [PATCH 2/2] Indentation fix for PR, added .editorconfig
---
TabletFriend/TabletFriend/.editorconfig | 200 ++++++
TabletFriend/TabletFriend/Data/ButtonData.cs | 6 +-
.../TabletFriend/Models/ButtonModel.cs | 38 +-
TabletFriend/TabletFriend/UiFactory.cs | 586 +++++++++---------
4 files changed, 515 insertions(+), 315 deletions(-)
create mode 100644 TabletFriend/TabletFriend/.editorconfig
diff --git a/TabletFriend/TabletFriend/.editorconfig b/TabletFriend/TabletFriend/.editorconfig
new file mode 100644
index 0000000..0d27111
--- /dev/null
+++ b/TabletFriend/TabletFriend/.editorconfig
@@ -0,0 +1,200 @@
+# Rules in this file were initially inferred by Visual Studio IntelliCode from the \TabletFriend\TabletFriend\ codebase based on best match to current usage at 15.04.2022
+# You can modify the rules from these initially generated values to suit your own policies
+# You can learn more about editorconfig here: https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-code-style-settings-reference
+[*.cs]
+
+
+#Core editorconfig formatting - indentation
+
+#use hard tabs for indentation
+indent_style = tab
+
+#Formatting - new line options
+
+#place catch statements on a new line
+csharp_new_line_before_catch = true
+#place else statements on a new line
+csharp_new_line_before_else = true
+#require members of object initializers to be on the same line
+csharp_new_line_before_members_in_object_initializers = false
+#require braces to be on a new line for control_blocks, lambdas, object_collection_array_initializers, methods, types, and properties (also known as "Allman" style)
+csharp_new_line_before_open_brace = control_blocks, lambdas, object_collection_array_initializers, methods, types, properties
+
+#Formatting - organize using options
+
+#sort System.* using directives alphabetically, and place them before other usings
+dotnet_sort_system_directives_first = true
+
+#Formatting - spacing options
+
+#require NO space between a cast and the value
+csharp_space_after_cast = false
+#require a space before the colon for bases or interfaces in a type declaration
+csharp_space_after_colon_in_inheritance_clause = true
+#require a space after a keyword in a control flow statement such as a for loop
+csharp_space_after_keywords_in_control_flow_statements = true
+#require a space before the colon for bases or interfaces in a type declaration
+csharp_space_before_colon_in_inheritance_clause = true
+#remove space within empty argument list parentheses
+csharp_space_between_method_call_empty_parameter_list_parentheses = false
+#remove space between method call name and opening parenthesis
+csharp_space_between_method_call_name_and_opening_parenthesis = false
+#do not place space characters after the opening parenthesis and before the closing parenthesis of a method call
+csharp_space_between_method_call_parameter_list_parentheses = false
+#remove space within empty parameter list parentheses for a method declaration
+csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
+#place a space character after the opening parenthesis and before the closing parenthesis of a method declaration parameter list.
+csharp_space_between_method_declaration_parameter_list_parentheses = false
+
+#Formatting - wrapping options
+
+#leave code block on single line
+csharp_preserve_single_line_blocks = true
+#leave statements and member declarations on the same line
+csharp_preserve_single_line_statements = true
+
+#Style - Code block preferences
+
+#prefer curly braces even for one line of code
+csharp_prefer_braces = true:suggestion
+
+#Style - expression bodied member options
+
+#prefer expression-bodied members for accessors
+csharp_style_expression_bodied_accessors = true:suggestion
+#prefer block bodies for constructors
+csharp_style_expression_bodied_constructors = false:suggestion
+#prefer expression-bodied members for methods when they will be a single line
+csharp_style_expression_bodied_methods = when_on_single_line:suggestion
+#prefer expression-bodied members for properties
+csharp_style_expression_bodied_properties = true:suggestion
+
+#Style - expression level options
+
+#prefer out variables to be declared inline in the argument list of a method call when possible
+csharp_style_inlined_variable_declaration = true:suggestion
+#prefer the language keyword for member access expressions, instead of the type name, for types that have a keyword to represent them
+dotnet_style_predefined_type_for_member_access = true:suggestion
+
+#Style - Expression-level preferences
+
+#prefer default(T) over default
+csharp_prefer_simple_default_expression = false:suggestion
+#prefer objects to be initialized using object initializers when possible
+dotnet_style_object_initializer = true:suggestion
+
+#Style - implicit and explicit types
+
+#prefer var over explicit type in all cases, unless overridden by another code style rule
+csharp_style_var_elsewhere = true:suggestion
+#prefer var is used to declare variables with built-in system types such as int
+csharp_style_var_for_built_in_types = true:suggestion
+#prefer var when the type is already mentioned on the right-hand side of a declaration expression
+csharp_style_var_when_type_is_apparent = true:suggestion
+
+#Style - language keyword and framework type options
+
+#prefer the language keyword for local variables, method parameters, and class members, instead of the type name, for types that have a keyword to represent them
+dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
+
+#Style - Miscellaneous preferences
+
+#prefer local functions over anonymous functions
+csharp_style_pattern_local_over_anonymous_function = true:suggestion
+
+#Style - modifier options
+
+#prefer accessibility modifiers to be declared except for public interface members. This will currently not differ from always and will act as future proofing for if C# adds default interface methods.
+dotnet_style_require_accessibility_modifiers = for_non_interface_members:suggestion
+
+#Style - Modifier preferences
+
+#when this rule is set to a list of modifiers, prefer the specified ordering.
+csharp_preferred_modifier_order = public,private,internal,protected,static,readonly,async,extern,override:suggestion
+
+#Style - qualification options
+
+#prefer events not to be prefaced with this. or Me. in Visual Basic
+dotnet_style_qualification_for_event = false:suggestion
+#prefer fields not to be prefaced with this. or Me. in Visual Basic
+dotnet_style_qualification_for_field = false:suggestion
+#prefer methods not to be prefaced with this. or Me. in Visual Basic
+dotnet_style_qualification_for_method = false:suggestion
+#prefer properties not to be prefaced with this. or Me. in Visual Basic
+dotnet_style_qualification_for_property = false:suggestion
+csharp_indent_labels = one_less_than_current
+csharp_using_directive_placement = outside_namespace:silent
+csharp_prefer_simple_using_statement = true:suggestion
+csharp_style_namespace_declarations = block_scoped:silent
+csharp_style_expression_bodied_operators = false:silent
+csharp_style_expression_bodied_indexers = true:silent
+csharp_style_expression_bodied_lambdas = true:silent
+csharp_style_expression_bodied_local_functions = false:silent
+
+[*.{cs,vb}]
+dotnet_style_operator_placement_when_wrapping = beginning_of_line
+tab_width = 4
+indent_size = 4
+end_of_line = crlf
+dotnet_style_coalesce_expression = true:suggestion
+dotnet_style_null_propagation = true:suggestion
+dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion
+dotnet_style_prefer_auto_properties = true:silent
+dotnet_style_object_initializer = true:suggestion
+dotnet_style_collection_initializer = true:suggestion
+dotnet_style_prefer_simplified_boolean_expressions = true:suggestion
+dotnet_style_prefer_conditional_expression_over_assignment = true:silent
+dotnet_style_prefer_conditional_expression_over_return = true:silent
+dotnet_style_explicit_tuple_names = true:suggestion
+dotnet_style_prefer_inferred_tuple_names = true:suggestion
+dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
+dotnet_style_prefer_compound_assignment = true:suggestion
+dotnet_style_prefer_simplified_interpolation = true:suggestion
+dotnet_style_namespace_match_folder = true:suggestion
+[*.{cs,vb}]
+#### Naming styles ####
+
+# Naming rules
+
+dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion
+dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface
+dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i
+
+dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion
+dotnet_naming_rule.types_should_be_pascal_case.symbols = types
+dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case
+
+dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion
+dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members
+dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case
+
+# Symbol specifications
+
+dotnet_naming_symbols.interface.applicable_kinds = interface
+dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
+dotnet_naming_symbols.interface.required_modifiers =
+
+dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum
+dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
+dotnet_naming_symbols.types.required_modifiers =
+
+dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
+dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
+dotnet_naming_symbols.non_field_members.required_modifiers =
+
+# Naming styles
+
+dotnet_naming_style.begins_with_i.required_prefix = I
+dotnet_naming_style.begins_with_i.required_suffix =
+dotnet_naming_style.begins_with_i.word_separator =
+dotnet_naming_style.begins_with_i.capitalization = pascal_case
+
+dotnet_naming_style.pascal_case.required_prefix =
+dotnet_naming_style.pascal_case.required_suffix =
+dotnet_naming_style.pascal_case.word_separator =
+dotnet_naming_style.pascal_case.capitalization = pascal_case
+
+dotnet_naming_style.pascal_case.required_prefix =
+dotnet_naming_style.pascal_case.required_suffix =
+dotnet_naming_style.pascal_case.word_separator =
+dotnet_naming_style.pascal_case.capitalization = pascal_case
diff --git a/TabletFriend/TabletFriend/Data/ButtonData.cs b/TabletFriend/TabletFriend/Data/ButtonData.cs
index fdc3955..e93889b 100644
--- a/TabletFriend/TabletFriend/Data/ButtonData.cs
+++ b/TabletFriend/TabletFriend/Data/ButtonData.cs
@@ -6,10 +6,10 @@ public class ButtonData
public string Action;
public string[] Actions;
- public string ActionRelease;
- public string[] ActionsRelease;
+ public string ActionRelease;
+ public string[] ActionsRelease;
- public string Text;
+ public string Text;
public string Icon;
public StretchData IconStretch;
public string Size;
diff --git a/TabletFriend/TabletFriend/Models/ButtonModel.cs b/TabletFriend/TabletFriend/Models/ButtonModel.cs
index f434196..9ef6a45 100644
--- a/TabletFriend/TabletFriend/Models/ButtonModel.cs
+++ b/TabletFriend/TabletFriend/Models/ButtonModel.cs
@@ -10,14 +10,14 @@
namespace TabletFriend.Models
{
- public enum ButtonProcessedEvent
- {
- None,
- Down,
- Up
-
- }
- public class ButtonModel : IDisposable
+ public enum ButtonProcessedEvent
+ {
+ None,
+ Down,
+ Up
+
+ }
+ public class ButtonModel : IDisposable
{
public ButtonAction Action;
public ButtonAction ActionRelease;
@@ -25,9 +25,9 @@ public class ButtonModel : IDisposable
///
/// Logging of last processed event to avoid multiple invocations due to double triggered mouse and touch events when action(s)_release is used
///
- public ButtonProcessedEvent LastProcessedEvent { get; set; } = ButtonProcessedEvent.None;
+ public ButtonProcessedEvent LastProcessedEvent { get; set; } = ButtonProcessedEvent.None;
- public string Text = "";
+ public string Text = "";
public object Icon;
public Vector2 Position = Vector2.Zero;
@@ -94,16 +94,16 @@ public ButtonModel(ButtonData data)
Action = new BatchAction(ButtonActionResolver.Resolve(data.Actions));
}
- if (data.ActionsRelease == null || data.ActionsRelease.Length == 0)
- {
- ActionRelease = ButtonActionResolver.Resolve(data.ActionRelease);
- }
- else
- {
- ActionRelease = new BatchAction(ButtonActionResolver.Resolve(data.ActionsRelease));
- }
+ if (data.ActionsRelease == null || data.ActionsRelease.Length == 0)
+ {
+ ActionRelease = ButtonActionResolver.Resolve(data.ActionRelease);
+ }
+ else
+ {
+ ActionRelease = new BatchAction(ButtonActionResolver.Resolve(data.ActionsRelease));
+ }
- Style = data.Style;
+ Style = data.Style;
Font = data.Font;
FontSize = data.FontSize;
diff --git a/TabletFriend/TabletFriend/UiFactory.cs b/TabletFriend/TabletFriend/UiFactory.cs
index f2ae7ec..81d9346 100644
--- a/TabletFriend/TabletFriend/UiFactory.cs
+++ b/TabletFriend/TabletFriend/UiFactory.cs
@@ -13,297 +13,297 @@
namespace TabletFriend
{
- public static class UiFactory
- {
- public static void CreateUi(LayoutModel layout, MainWindow window)
- {
- ToggleManager.ClearButtons();
- var theme = layout.Theme;
-
- window.MainCanvas.Children.Clear();
-
- var isDocked = AppState.Settings.DockingMode != DockingMode.None;
-
- if (!isDocked)
- {
- window.MainBorder.CornerRadius = new CornerRadius(theme.Rounding);
- }
- else
- {
- window.MainBorder.CornerRadius = new CornerRadius(0);
- }
- var sizes = layout.Buttons.GetSizes(isDocked);
- var positions = Packer.Pack(sizes, layout.LayoutWidth);
-
- var size = Packer.GetSize(positions, sizes);
-
-
- var rotateLayout = false;
- var layoutVertical = size.Y > size.X;
- if (AppState.Settings.DockingMode != DockingMode.None)
- {
- var dockingVertical = AppState.Settings.DockingMode == DockingMode.Left
- || AppState.Settings.DockingMode == DockingMode.Right;
-
- if (layoutVertical != dockingVertical)
- {
- rotateLayout = true;
- }
- }
-
- var titlebarHeight = TitlebarManager.GetTitlebarHeight(theme);
-
- if (rotateLayout)
- {
- window.Height = size.X * theme.CellSize + theme.Margin + titlebarHeight;
- window.Width = size.Y * theme.CellSize + theme.Margin;
- }
- else
- {
- window.Width = size.X * theme.CellSize + theme.Margin;
- window.Height = size.Y * theme.CellSize + theme.Margin + titlebarHeight;
- }
-
- var offset = Vector2.Zero;
- if (AppState.Settings.DockingMode != DockingMode.None)
- {
- if (AppState.Settings.DockingMode == DockingMode.Top || AppState.Settings.DockingMode == DockingMode.Bottom)
- {
- offset.X = (float)(SystemParameters.PrimaryScreenWidth - window.Width) / 2;
- }
- else
- {
- offset.Y = (float)(SystemParameters.PrimaryScreenHeight - window.Height) / 2;
- }
- }
- else
- {
- offset.Y = (float)titlebarHeight;
- }
-
- if (AppState.Settings.DockingMode != DockingMode.None)
- {
- window.MinOpacity = theme.MaxOpacity;
- }
- else
- {
- window.MinOpacity = theme.MinOpacity;
- }
- window.MaxOpacity = theme.MaxOpacity;
- window.BeginAnimation(UIElement.OpacityProperty, null);
- window.Opacity = theme.MaxOpacity;
- if (window.IsMouseOver)
- {
- window.BeginAnimation(UIElement.OpacityProperty, window.FadeIn);
- }
- else
- {
- window.BeginAnimation(UIElement.OpacityProperty, window.FadeOut);
- }
-
- Application.Current.Resources["PrimaryHueMidBrush"] = new SolidColorBrush(theme.PrimaryColor);
- Application.Current.Resources["PrimaryHueMidForegroundBrush"] = new SolidColorBrush(theme.SecondaryColor);
- Application.Current.Resources["MaterialDesignToolForeground"] = new SolidColorBrush(theme.SecondaryColor);
-
- Application.Current.Resources["MaterialDesignPaper"] = new SolidColorBrush(theme.BackgroundColor);
- Application.Current.Resources["MaterialDesignFont"] = new SolidColorBrush(theme.SecondaryColor);
- Application.Current.Resources["MaterialDesignBody"] = new SolidColorBrush(theme.SecondaryColor);
-
- window.MainBorder.Background = new SolidColorBrush(theme.BackgroundColor);
-
- var visibleButtons = new List();
-
- foreach (var button in layout.Buttons)
- {
- if (button.IsVisible(isDocked))
- {
- visibleButtons.Add(button);
- }
- }
-
- for (var i = 0; i < positions.Length; i += 1)
- {
- var button = visibleButtons[i];
-
-
- if (button.Spacer)
- {
- continue;
- }
- var buttonPosition = positions[i];
- var buttonSize = sizes[i];
-
- if (rotateLayout)
- {
- var buffer = buttonPosition.X;
- buttonPosition.X = buttonPosition.Y;
- buttonPosition.Y = buffer;
-
- buffer = buttonSize.X;
- buttonSize.X = buttonSize.Y;
- buttonSize.Y = buffer;
- }
-
- CreateButton(layout, window, button, buttonPosition, buttonSize, offset);
- }
-
-
- TitlebarManager.CreateTitlebar(window, theme);
- }
-
- private static void CreateButton(
- LayoutModel layout,
- MainWindow window,
- ButtonModel button,
- Vector2 position,
- Vector2 size,
- Vector2 offset
- )
- {
- var theme = layout.Theme;
-
- ButtonBase uiButton;
- var isToggle = button.Action is ToggleAction;
- var isRepeat = button.Action is RepeatAction;
-
- if (isToggle)
- {
- uiButton = new ToggleButton();
- }
- else
- {
- if (isRepeat)
- {
- uiButton = new RepeatButton();
- Stylus.SetIsPressAndHoldEnabled(uiButton, false);
- }
- else
- {
- uiButton = new Button();
- }
- }
- uiButton.Width = theme.CellSize * size.X - theme.Margin;
- uiButton.Height = theme.CellSize * size.Y - theme.Margin;
-
- var font = button.Font;
- if (font == null)
- {
- font = layout.Theme.DefaultFont;
- }
- var fontSize = button.FontSize;
- if (fontSize == 0)
- {
- fontSize = layout.Theme.DefaultFontSize;
- }
- var fontWeight = button.FontWeight;
- if (fontWeight == 0)
- {
- fontWeight = layout.Theme.DefaultFontWeight;
- }
-
- var text = new TextBlock();
- text.Text = button.Text;
- if (fontSize > 0)
- {
- text.FontSize = fontSize;
- }
- if (font != null)
- {
- text.FontFamily = new FontFamily(font);
- }
- if (fontWeight > 0)
- {
- text.FontWeight = FontWeight.FromOpenTypeWeight(Math.Min(999, fontWeight));
- }
-
- uiButton.Content = text;
-
- if (button.Icon != null)
- {
- uiButton.Content = button.Icon;
- if (!string.IsNullOrEmpty(button.Text))
- {
- uiButton.ToolTip = new ToolTip()
- {
- Style = Application.Current.Resources["tool_tip"] as Style,
- Content = button.Text,
- HasDropShadow = true,
- };
- }
- }
-
- var style = button.Style;
- if (style == null)
- {
- style = theme.DefaultStyle;
- }
-
- if (isToggle)
- {
- uiButton.Style = Application.Current.Resources["toggle"] as Style;
-
- var key = ((ToggleAction)button.Action).Key;
- var toggle = (ToggleButton)uiButton;
- if (ToggleManager.IsHeld(key))
- {
- toggle.IsChecked = true;
- }
- ToggleManager.AddButton(key, toggle);
- }
- else
- {
- if (style == null)
- {
- uiButton.Style = null;
- }
- else
- {
- uiButton.Style = Application.Current.Resources[style] as Style;
- }
- }
-
- if (button.ActionRelease == null)
- {
- // Default Click Action
- if (button.Action != null)
- {
- uiButton.Click += (e, o) => _ = button.Action.Invoke();
- }
- }
- else
- { // Separate actions for Pointer-Down and Pointer-Up
-
- // disable long press context menu on button
- uiButton.SetValue(Stylus.IsPressAndHoldEnabledProperty, false);
-
- if (button.Action != null)
- {
- void downAction(object o, EventArgs e)
- {
- if (button.LastProcessedEvent == ButtonProcessedEvent.Down) return; // invoke only once
- button.LastProcessedEvent = ButtonProcessedEvent.Down;
- button.Action.Invoke();
- }
- uiButton.TouchDown += downAction;
- uiButton.PreviewMouseLeftButtonDown += downAction;
-
- }
- if (button.ActionRelease != null)
- {
- void releaseAction(object o, EventArgs e)
- {
- if (button.LastProcessedEvent == ButtonProcessedEvent.Up) return;
- button.LastProcessedEvent = ButtonProcessedEvent.Up;
- button.ActionRelease.Invoke();
- };
- uiButton.PreviewMouseLeftButtonUp += releaseAction;
- uiButton.TouchUp += releaseAction;
- }
- }
-
- Canvas.SetTop(uiButton, theme.CellSize * position.Y + theme.Margin + offset.Y);
- Canvas.SetLeft(uiButton, theme.CellSize * position.X + theme.Margin + offset.X);
- window.MainCanvas.Children.Add(uiButton);
- }
- }
+ public static class UiFactory
+ {
+ public static void CreateUi(LayoutModel layout, MainWindow window)
+ {
+ ToggleManager.ClearButtons();
+ var theme = layout.Theme;
+
+ window.MainCanvas.Children.Clear();
+
+ var isDocked = AppState.Settings.DockingMode != DockingMode.None;
+
+ if (!isDocked)
+ {
+ window.MainBorder.CornerRadius = new CornerRadius(theme.Rounding);
+ }
+ else
+ {
+ window.MainBorder.CornerRadius = new CornerRadius(0);
+ }
+ var sizes = layout.Buttons.GetSizes(isDocked);
+ var positions = Packer.Pack(sizes, layout.LayoutWidth);
+
+ var size = Packer.GetSize(positions, sizes);
+
+
+ var rotateLayout = false;
+ var layoutVertical = size.Y > size.X;
+ if (AppState.Settings.DockingMode != DockingMode.None)
+ {
+ var dockingVertical = AppState.Settings.DockingMode == DockingMode.Left
+ || AppState.Settings.DockingMode == DockingMode.Right;
+
+ if (layoutVertical != dockingVertical)
+ {
+ rotateLayout = true;
+ }
+ }
+
+ var titlebarHeight = TitlebarManager.GetTitlebarHeight(theme);
+
+ if (rotateLayout)
+ {
+ window.Height = size.X * theme.CellSize + theme.Margin + titlebarHeight;
+ window.Width = size.Y * theme.CellSize + theme.Margin;
+ }
+ else
+ {
+ window.Width = size.X * theme.CellSize + theme.Margin;
+ window.Height = size.Y * theme.CellSize + theme.Margin + titlebarHeight;
+ }
+
+ var offset = Vector2.Zero;
+ if (AppState.Settings.DockingMode != DockingMode.None)
+ {
+ if (AppState.Settings.DockingMode == DockingMode.Top || AppState.Settings.DockingMode == DockingMode.Bottom)
+ {
+ offset.X = (float)(SystemParameters.PrimaryScreenWidth - window.Width) / 2;
+ }
+ else
+ {
+ offset.Y = (float)(SystemParameters.PrimaryScreenHeight - window.Height) / 2;
+ }
+ }
+ else
+ {
+ offset.Y = (float)titlebarHeight;
+ }
+
+ if (AppState.Settings.DockingMode != DockingMode.None)
+ {
+ window.MinOpacity = theme.MaxOpacity;
+ }
+ else
+ {
+ window.MinOpacity = theme.MinOpacity;
+ }
+ window.MaxOpacity = theme.MaxOpacity;
+ window.BeginAnimation(UIElement.OpacityProperty, null);
+ window.Opacity = theme.MaxOpacity;
+ if (window.IsMouseOver)
+ {
+ window.BeginAnimation(UIElement.OpacityProperty, window.FadeIn);
+ }
+ else
+ {
+ window.BeginAnimation(UIElement.OpacityProperty, window.FadeOut);
+ }
+
+ Application.Current.Resources["PrimaryHueMidBrush"] = new SolidColorBrush(theme.PrimaryColor);
+ Application.Current.Resources["PrimaryHueMidForegroundBrush"] = new SolidColorBrush(theme.SecondaryColor);
+ Application.Current.Resources["MaterialDesignToolForeground"] = new SolidColorBrush(theme.SecondaryColor);
+
+ Application.Current.Resources["MaterialDesignPaper"] = new SolidColorBrush(theme.BackgroundColor);
+ Application.Current.Resources["MaterialDesignFont"] = new SolidColorBrush(theme.SecondaryColor);
+ Application.Current.Resources["MaterialDesignBody"] = new SolidColorBrush(theme.SecondaryColor);
+
+ window.MainBorder.Background = new SolidColorBrush(theme.BackgroundColor);
+
+ var visibleButtons = new List();
+
+ foreach (var button in layout.Buttons)
+ {
+ if (button.IsVisible(isDocked))
+ {
+ visibleButtons.Add(button);
+ }
+ }
+
+ for (var i = 0; i < positions.Length; i += 1)
+ {
+ var button = visibleButtons[i];
+
+
+ if (button.Spacer)
+ {
+ continue;
+ }
+ var buttonPosition = positions[i];
+ var buttonSize = sizes[i];
+
+ if (rotateLayout)
+ {
+ var buffer = buttonPosition.X;
+ buttonPosition.X = buttonPosition.Y;
+ buttonPosition.Y = buffer;
+
+ buffer = buttonSize.X;
+ buttonSize.X = buttonSize.Y;
+ buttonSize.Y = buffer;
+ }
+
+ CreateButton(layout, window, button, buttonPosition, buttonSize, offset);
+ }
+
+
+ TitlebarManager.CreateTitlebar(window, theme);
+ }
+
+ private static void CreateButton(
+ LayoutModel layout,
+ MainWindow window,
+ ButtonModel button,
+ Vector2 position,
+ Vector2 size,
+ Vector2 offset
+ )
+ {
+ var theme = layout.Theme;
+
+ ButtonBase uiButton;
+ var isToggle = button.Action is ToggleAction;
+ var isRepeat = button.Action is RepeatAction;
+
+ if (isToggle)
+ {
+ uiButton = new ToggleButton();
+ }
+ else
+ {
+ if (isRepeat)
+ {
+ uiButton = new RepeatButton();
+ Stylus.SetIsPressAndHoldEnabled(uiButton, false);
+ }
+ else
+ {
+ uiButton = new Button();
+ }
+ }
+ uiButton.Width = theme.CellSize * size.X - theme.Margin;
+ uiButton.Height = theme.CellSize * size.Y - theme.Margin;
+
+ var font = button.Font;
+ if (font == null)
+ {
+ font = layout.Theme.DefaultFont;
+ }
+ var fontSize = button.FontSize;
+ if (fontSize == 0)
+ {
+ fontSize = layout.Theme.DefaultFontSize;
+ }
+ var fontWeight = button.FontWeight;
+ if (fontWeight == 0)
+ {
+ fontWeight = layout.Theme.DefaultFontWeight;
+ }
+
+ var text = new TextBlock();
+ text.Text = button.Text;
+ if (fontSize > 0)
+ {
+ text.FontSize = fontSize;
+ }
+ if (font != null)
+ {
+ text.FontFamily = new FontFamily(font);
+ }
+ if (fontWeight > 0)
+ {
+ text.FontWeight = FontWeight.FromOpenTypeWeight(Math.Min(999, fontWeight));
+ }
+
+ uiButton.Content = text;
+
+ if (button.Icon != null)
+ {
+ uiButton.Content = button.Icon;
+ if (!string.IsNullOrEmpty(button.Text))
+ {
+ uiButton.ToolTip = new ToolTip()
+ {
+ Style = Application.Current.Resources["tool_tip"] as Style,
+ Content = button.Text,
+ HasDropShadow = true,
+ };
+ }
+ }
+
+ var style = button.Style;
+ if (style == null)
+ {
+ style = theme.DefaultStyle;
+ }
+
+ if (isToggle)
+ {
+ uiButton.Style = Application.Current.Resources["toggle"] as Style;
+
+ var key = ((ToggleAction)button.Action).Key;
+ var toggle = (ToggleButton)uiButton;
+ if (ToggleManager.IsHeld(key))
+ {
+ toggle.IsChecked = true;
+ }
+ ToggleManager.AddButton(key, toggle);
+ }
+ else
+ {
+ if (style == null)
+ {
+ uiButton.Style = null;
+ }
+ else
+ {
+ uiButton.Style = Application.Current.Resources[style] as Style;
+ }
+ }
+
+ if (button.ActionRelease == null)
+ {
+ // Default Click Action
+ if (button.Action != null)
+ {
+ uiButton.Click += (e, o) => _ = button.Action.Invoke();
+ }
+ }
+ else
+ { // Separate actions for Pointer-Down and Pointer-Up
+
+ // disable long press context menu on button
+ uiButton.SetValue(Stylus.IsPressAndHoldEnabledProperty, false);
+
+ if (button.Action != null)
+ {
+ void downAction(object o, EventArgs e)
+ {
+ if (button.LastProcessedEvent == ButtonProcessedEvent.Down) return; // invoke only once
+ button.LastProcessedEvent = ButtonProcessedEvent.Down;
+ button.Action.Invoke();
+ }
+ uiButton.TouchDown += downAction;
+ uiButton.PreviewMouseLeftButtonDown += downAction;
+
+ }
+ if (button.ActionRelease != null)
+ {
+ void releaseAction(object o, EventArgs e)
+ {
+ if (button.LastProcessedEvent == ButtonProcessedEvent.Up) return;
+ button.LastProcessedEvent = ButtonProcessedEvent.Up;
+ button.ActionRelease.Invoke();
+ };
+ uiButton.PreviewMouseLeftButtonUp += releaseAction;
+ uiButton.TouchUp += releaseAction;
+ }
+ }
+
+ Canvas.SetTop(uiButton, theme.CellSize * position.Y + theme.Margin + offset.Y);
+ Canvas.SetLeft(uiButton, theme.CellSize * position.X + theme.Margin + offset.X);
+ window.MainCanvas.Children.Add(uiButton);
+ }
+ }
}