diff --git a/Version.json b/Version.json
index 88819f8..adf8c7f 100644
--- a/Version.json
+++ b/Version.json
@@ -1,6 +1,6 @@
{
"$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json",
- "version": "2.1.2",
+ "version": "2.1.3",
"publicReleaseRefSpec": [
"^refs/heads/master$",
"^refs/heads/main$"
diff --git a/src/CrissCross.WPF.UI.Test/CrissCross.WPF.UI.Test.csproj b/src/CrissCross.WPF.UI.Test/CrissCross.WPF.UI.Test.csproj
index 3668994..501018f 100644
--- a/src/CrissCross.WPF.UI.Test/CrissCross.WPF.UI.Test.csproj
+++ b/src/CrissCross.WPF.UI.Test/CrissCross.WPF.UI.Test.csproj
@@ -23,6 +23,7 @@
+
diff --git a/src/CrissCross.WPF.UI.Test/Views/Pages/DashboardPage.xaml b/src/CrissCross.WPF.UI.Test/Views/Pages/DashboardPage.xaml
index f95da16..0d71ad1 100644
--- a/src/CrissCross.WPF.UI.Test/Views/Pages/DashboardPage.xaml
+++ b/src/CrissCross.WPF.UI.Test/Views/Pages/DashboardPage.xaml
@@ -99,6 +99,46 @@
-
+
+
+
+
diff --git a/src/CrissCross.WPF.UI.Test/Views/Pages/SettingsPage.xaml b/src/CrissCross.WPF.UI.Test/Views/Pages/SettingsPage.xaml
index 0f5fea7..6e0fba6 100644
--- a/src/CrissCross.WPF.UI.Test/Views/Pages/SettingsPage.xaml
+++ b/src/CrissCross.WPF.UI.Test/Views/Pages/SettingsPage.xaml
@@ -47,5 +47,12 @@
FontWeight="Medium"
Text="About CrissCross.WPF.UI" />
+
diff --git a/src/CrissCross.WPF.UI/Controls/Button/BezelButton.xaml b/src/CrissCross.WPF.UI/Controls/Button/BezelButton.xaml
new file mode 100644
index 0000000..4dd85c9
--- /dev/null
+++ b/src/CrissCross.WPF.UI/Controls/Button/BezelButton.xaml
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/CrissCross.WPF.UI/Controls/Button/BezelRepeatButton.xaml b/src/CrissCross.WPF.UI/Controls/Button/BezelRepeatButton.xaml
new file mode 100644
index 0000000..6ac8d43
--- /dev/null
+++ b/src/CrissCross.WPF.UI/Controls/Button/BezelRepeatButton.xaml
@@ -0,0 +1,107 @@
+
+
+
diff --git a/src/CrissCross.WPF.UI/Controls/Button/BezelToggleButton.xaml b/src/CrissCross.WPF.UI/Controls/Button/BezelToggleButton.xaml
new file mode 100644
index 0000000..5f86bef
--- /dev/null
+++ b/src/CrissCross.WPF.UI/Controls/Button/BezelToggleButton.xaml
@@ -0,0 +1,146 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/CrissCross.WPF.UI/Controls/Button/Button.xaml b/src/CrissCross.WPF.UI/Controls/Button/Button.xaml
index c026093..81c44f8 100644
--- a/src/CrissCross.WPF.UI/Controls/Button/Button.xaml
+++ b/src/CrissCross.WPF.UI/Controls/Button/Button.xaml
@@ -20,7 +20,6 @@
-
diff --git a/src/CrissCross.WPF.UI/Controls/Button/Custom/BezelButton.cs b/src/CrissCross.WPF.UI/Controls/Button/Custom/BezelButton.cs
new file mode 100644
index 0000000..5e8f177
--- /dev/null
+++ b/src/CrissCross.WPF.UI/Controls/Button/Custom/BezelButton.cs
@@ -0,0 +1,54 @@
+// Copyright (c) 2019-2024 ReactiveUI Association Incorporated. All rights reserved.
+// ReactiveUI Association Incorporated licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for full license information.
+
+namespace CrissCross.WPF.UI.Controls;
+
+///
+/// GenericButton.
+///
+public class BezelButton : CommonButtonBase
+{
+ ///
+ /// The glare opacity mask property.
+ ///
+ public static readonly DependencyProperty GlareOpacityMaskProperty = DependencyProperty.Register("GlareOpacityMask", typeof(Brush), typeof(BezelButton), new PropertyMetadata(null));
+
+ ///
+ /// The pressed brush property.
+ ///
+ public static readonly DependencyProperty PressedBrushProperty = DependencyProperty.Register("PressedBrush", typeof(Brush), typeof(BezelButton), new PropertyMetadata(null));
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public BezelButton()
+ : base("CrissCross.WPF.UI.Controls.BezelButton")
+ {
+ }
+
+ // Properties
+ ///
+ /// Gets or sets the glare opacity mask.
+ ///
+ ///
+ /// The glare opacity mask.
+ ///
+ public Brush GlareOpacityMask
+ {
+ get => (Brush)GetValue(GlareOpacityMaskProperty);
+ set => SetValue(GlareOpacityMaskProperty, value);
+ }
+
+ ///
+ /// Gets or sets the pressed brush.
+ ///
+ ///
+ /// The pressed brush.
+ ///
+ public Brush PressedBrush
+ {
+ get => (Brush)GetValue(PressedBrushProperty);
+ set => SetValue(PressedBrushProperty, value);
+ }
+}
diff --git a/src/CrissCross.WPF.UI/Controls/Button/Custom/BezelRepeatButton.cs b/src/CrissCross.WPF.UI/Controls/Button/Custom/BezelRepeatButton.cs
new file mode 100644
index 0000000..cd5fe83
--- /dev/null
+++ b/src/CrissCross.WPF.UI/Controls/Button/Custom/BezelRepeatButton.cs
@@ -0,0 +1,53 @@
+// Copyright (c) 2019-2024 ReactiveUI Association Incorporated. All rights reserved.
+// ReactiveUI Association Incorporated licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for full license information.
+
+namespace CrissCross.WPF.UI.Controls;
+
+///
+/// GenericRepeatButton.
+///
+public class BezelRepeatButton : CommonRepeatButtonBase
+{
+ ///
+ /// The glare opacity mask property.
+ ///
+ public static readonly DependencyProperty GlareOpacityMaskProperty = DependencyProperty.Register("GlareOpacityMask", typeof(Brush), typeof(BezelRepeatButton), new PropertyMetadata(null));
+
+ ///
+ /// The pressed brush property.
+ ///
+ public static readonly DependencyProperty PressedBrushProperty = DependencyProperty.Register("PressedBrush", typeof(Brush), typeof(BezelRepeatButton), new PropertyMetadata(Brushes.Green));
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public BezelRepeatButton()
+ : base("CrissCross.WPF.UI.Controls.BezelRepeatButton")
+ {
+ }
+
+ ///
+ /// Gets or sets the glare opacity mask.
+ ///
+ ///
+ /// The glare opacity mask.
+ ///
+ public Brush GlareOpacityMask
+ {
+ get => (Brush)GetValue(GlareOpacityMaskProperty);
+ set => SetValue(GlareOpacityMaskProperty, value);
+ }
+
+ ///
+ /// Gets or sets the pressed brush.
+ ///
+ ///
+ /// The pressed brush.
+ ///
+ public Brush PressedBrush
+ {
+ get => (Brush)GetValue(PressedBrushProperty);
+ set => SetValue(PressedBrushProperty, value);
+ }
+}
diff --git a/src/CrissCross.WPF.UI/Controls/Button/Custom/BezelToggleButton.cs b/src/CrissCross.WPF.UI/Controls/Button/Custom/BezelToggleButton.cs
new file mode 100644
index 0000000..01272fc
--- /dev/null
+++ b/src/CrissCross.WPF.UI/Controls/Button/Custom/BezelToggleButton.cs
@@ -0,0 +1,71 @@
+// Copyright (c) 2019-2024 ReactiveUI Association Incorporated. All rights reserved.
+// ReactiveUI Association Incorporated licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for full license information.
+
+namespace CrissCross.WPF.UI.Controls;
+
+///
+/// GenericToggleButton.
+///
+///
+public class BezelToggleButton : CommonToggleButtonBase
+{
+ ///
+ /// The glare opacity mask property.
+ ///
+ public static readonly DependencyProperty GlareOpacityMaskProperty = DependencyProperty.Register("GlareOpacityMask", typeof(Brush), typeof(BezelToggleButton), new PropertyMetadata(null));
+
+ ///
+ /// The minor background1 property.
+ ///
+ public static readonly DependencyProperty MinorBackground1Property = DependencyProperty.Register("MinorBackground1", typeof(Brush), typeof(BezelToggleButton), new PropertyMetadata(null));
+
+ ///
+ /// The pressed brush property.
+ ///
+ public static readonly DependencyProperty PressedBrushProperty = DependencyProperty.Register("PressedBrush", typeof(Brush), typeof(BezelToggleButton), new PropertyMetadata(Brushes.Green));
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public BezelToggleButton()
+ : base("CrissCross.WPF.UI.Controls.BezelToggleButton")
+ {
+ }
+
+ ///
+ /// Gets or sets the glare opacity mask.
+ ///
+ ///
+ /// The glare opacity mask.
+ ///
+ public Brush GlareOpacityMask
+ {
+ get => (Brush)GetValue(GlareOpacityMaskProperty);
+ set => SetValue(GlareOpacityMaskProperty, value);
+ }
+
+ ///
+ /// Gets or sets the minor background1.
+ ///
+ ///
+ /// The minor background1.
+ ///
+ public Brush MinorBackground1
+ {
+ get => (Brush)GetValue(MinorBackground1Property);
+ set => SetValue(MinorBackground1Property, value);
+ }
+
+ ///
+ /// Gets or sets the pressed brush.
+ ///
+ ///
+ /// The pressed brush.
+ ///
+ public Brush PressedBrush
+ {
+ get => (Brush)GetValue(PressedBrushProperty);
+ set => SetValue(PressedBrushProperty, value);
+ }
+}
diff --git a/src/CrissCross.WPF.UI/Controls/Button/Custom/CommonButtonBase.cs b/src/CrissCross.WPF.UI/Controls/Button/Custom/CommonButtonBase.cs
new file mode 100644
index 0000000..ef148ea
--- /dev/null
+++ b/src/CrissCross.WPF.UI/Controls/Button/Custom/CommonButtonBase.cs
@@ -0,0 +1,302 @@
+// Copyright (c) 2019-2024 ReactiveUI Association Incorporated. All rights reserved.
+// ReactiveUI Association Incorporated licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for full license information.
+
+using System.IO;
+using System.Windows.Input;
+using System.Windows.Markup;
+
+namespace CrissCross.WPF.UI.Controls;
+
+///
+/// CommonButtonBase.
+///
+public abstract class CommonButtonBase : System.Windows.Controls.Button
+{
+ ///
+ /// The corner radius1 property.
+ ///
+ public static readonly DependencyProperty CornerRadius1Property = DependencyProperty.Register("CornerRadius1", typeof(CornerRadius), typeof(CommonButtonBase), new PropertyMetadata(new CornerRadius(3.0)));
+
+ ///
+ /// The corner radius2 property.
+ ///
+ public static readonly DependencyProperty CornerRadius2Property = DependencyProperty.Register("CornerRadius2", typeof(CornerRadius), typeof(CommonButtonBase), new PropertyMetadata(new CornerRadius(2.0)));
+
+ ///
+ /// The focus border thickness property.
+ ///
+ public static readonly DependencyProperty FocusBorderThicknessProperty = DependencyProperty.Register("FocusBorderThickness", typeof(Thickness), typeof(CommonButtonBase), new PropertyMetadata(new Thickness(2.0)));
+
+ ///
+ /// The focus brush property.
+ ///
+ public static readonly DependencyProperty FocusBrushProperty = DependencyProperty.Register("FocusBrush", typeof(Brush), typeof(CommonButtonBase), new PropertyMetadata(Brushes.Orange));
+
+ ///
+ /// The glare brush property.
+ ///
+ public static readonly DependencyProperty GlareBrushProperty = DependencyProperty.Register("GlareBrush", typeof(Brush), typeof(CommonButtonBase), new PropertyMetadata(null));
+
+ ///
+ /// The minor border brush1 property.
+ ///
+ public static readonly DependencyProperty MinorBorderBrush1Property = DependencyProperty.Register("MinorBorderBrush1", typeof(Brush), typeof(CommonButtonBase), new PropertyMetadata(new LinearGradientBrush(SystemColors.ControlDarkDarkColor, SystemColors.ControlDarkDarkColor, 45)));
+
+ ///
+ /// The minor border thickness1 property.
+ ///
+ public static readonly DependencyProperty MinorBorderThickness1Property = DependencyProperty.Register("MinorBorderThickness1", typeof(Thickness), typeof(CommonButtonBase), new PropertyMetadata(new Thickness(0.0)));
+
+ // Methods
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Name of the style.
+ protected CommonButtonBase(string styleName)
+ {
+ try
+ {
+ var style = CommonButtonBase.ControlStyle(styleName);
+ if (style == null)
+ {
+ return;
+ }
+
+ Style = style;
+ }
+ catch (Exception exception)
+ {
+ System.Windows.MessageBox.Show(exception.Message, exception.TargetSite?.ToString(), System.Windows.MessageBoxButton.OK, MessageBoxImage.Hand);
+ }
+
+ IsEnabledChanged += CommonButtonBase_IsEnabledChanged;
+ Loaded += CommonButtonBase_Loaded;
+ }
+
+ ///
+ /// Gets or sets the corner radius1.
+ ///
+ ///
+ /// The corner radius1.
+ ///
+ public CornerRadius CornerRadius1
+ {
+ get => (CornerRadius)GetValue(CornerRadius1Property);
+ set => SetValue(CornerRadius1Property, value);
+ }
+
+ ///
+ /// Gets or sets the corner radius2.
+ ///
+ ///
+ /// The corner radius2.
+ ///
+ public CornerRadius CornerRadius2
+ {
+ get => (CornerRadius)GetValue(CornerRadius2Property);
+ set => SetValue(CornerRadius2Property, value);
+ }
+
+ ///
+ /// Gets or sets the focus border thickness.
+ ///
+ ///
+ /// The focus border thickness.
+ ///
+ public Thickness FocusBorderThickness
+ {
+ get => (Thickness)GetValue(FocusBorderThicknessProperty);
+ set => SetValue(FocusBorderThicknessProperty, value);
+ }
+
+ ///
+ /// Gets or sets the focus brush.
+ ///
+ ///
+ /// The focus brush.
+ ///
+ public Brush FocusBrush
+ {
+ get => (Brush)GetValue(FocusBrushProperty);
+ set => SetValue(FocusBrushProperty, value);
+ }
+
+ ///
+ /// Gets or sets the glare brush.
+ ///
+ ///
+ /// The glare brush.
+ ///
+ public Brush GlareBrush
+ {
+ get => (Brush)GetValue(GlareBrushProperty);
+ set => SetValue(GlareBrushProperty, value);
+ }
+
+ ///
+ /// Gets or sets the minor border brush1.
+ ///
+ ///
+ /// The minor border brush1.
+ ///
+ public Brush MinorBorderBrush1
+ {
+ get => (Brush)GetValue(MinorBorderBrush1Property);
+ set => SetValue(MinorBorderBrush1Property, value);
+ }
+
+ ///
+ /// Gets or sets the minor border thickness1.
+ ///
+ ///
+ /// The minor border thickness1.
+ ///
+ public Thickness MinorBorderThickness1
+ {
+ get => (Thickness)GetValue(MinorBorderThickness1Property);
+ set => SetValue(MinorBorderThickness1Property, value);
+ }
+
+ ///
+ /// Controls the style.
+ ///
+ /// Name of the style.
+ /// A Style.
+ protected static Style? ControlStyle(string styleName)
+ {
+ try
+ {
+ var manifestResourceStream = typeof(CommonButtonBase).Module.Assembly.GetManifestResourceStream(styleName + ".xaml");
+ if (manifestResourceStream == null)
+ {
+ return null;
+ }
+
+ var style = (Style?)XamlReader.Load(manifestResourceStream);
+ manifestResourceStream.Close();
+ return style;
+ }
+ catch (Exception exception)
+ {
+ System.Windows.MessageBox.Show(exception.ToString(), exception.TargetSite?.ToString());
+ return null;
+ }
+ }
+
+ ///
+ /// Raises the routed event by using the event data that is provided.
+ ///
+ /// A that contains event data. This event data must contain the identifier for the event.
+ protected override void OnLostFocus(RoutedEventArgs e)
+ {
+ base.OnLostFocus(e);
+ SetIndicatorBorderSize(0);
+ }
+
+ ///
+ /// Provides class handling for the routed event that occurs when the mouse enters this control.
+ ///
+ /// The event data for the event.
+ protected override void OnMouseEnter(MouseEventArgs e)
+ {
+ base.OnMouseEnter(e);
+ SetIndicatorBorderSize(2);
+ }
+
+ ///
+ /// Provides class handling for the routed event that occurs when the mouse leaves an element.
+ ///
+ /// The event data for the event.
+ protected override void OnMouseLeave(MouseEventArgs e)
+ {
+ base.OnMouseLeave(e);
+ if (IsFocused)
+ {
+ SetIndicatorBorderSize(1);
+ }
+ else
+ {
+ SetIndicatorBorderSize(0);
+ }
+ }
+
+ ///
+ /// Returns a value that indicates whether serialization processes should serialize the value for the provided dependency property.
+ ///
+ /// The identifier for the dependency property that should be serialized.
+ ///
+ /// true if the dependency property that is supplied should be value-serialized; otherwise, false.
+ ///
+ protected override bool ShouldSerializeProperty(DependencyProperty dp)
+ {
+ if (dp == StyleProperty)
+ {
+ return false;
+ }
+
+ return base.ShouldSerializeProperty(dp);
+ }
+
+ private void CommonButtonBase_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e)
+ {
+ var border = UserHintBorder();
+
+ if (border != null)
+ {
+ if (IsEnabled)
+ {
+ border.Background = null;
+ }
+ else
+ {
+ border.Background = new SolidColorBrush(Color.FromArgb(0x55, 0, 0, 0));
+ }
+ }
+ }
+
+ private void CommonButtonBase_Loaded(object sender, RoutedEventArgs e) => SetIndicatorBorderSize(0);
+
+ private void SetIndicatorBorderSize(double size)
+ {
+ var border = UserHintBorder();
+
+ if (border != null)
+ {
+ if (size == 1)
+ {
+ border.BorderThickness = new Thickness(
+ FocusBorderThickness.Left <= 2 ? 1 : (FocusBorderThickness.Left - 2),
+ FocusBorderThickness.Top <= 2 ? 1 : (FocusBorderThickness.Top - 2),
+ FocusBorderThickness.Right <= 2 ? 1 : (FocusBorderThickness.Right - 2),
+ FocusBorderThickness.Bottom <= 2 ? 1 : (FocusBorderThickness.Bottom - 2));
+ if (GetType() == typeof(BezelButton))
+ {
+ border.Margin = new Thickness(0);
+ if (border.BorderThickness.Left == 1)
+ {
+ border.Margin = new Thickness(1);
+ }
+ }
+ }
+ else if (size == 0)
+ {
+ border.BorderThickness = new Thickness(0);
+ }
+ else
+ {
+ border.BorderThickness = FocusBorderThickness;
+ }
+ }
+ }
+
+ private System.Windows.Controls.Border? UserHintBorder()
+ {
+ if (Template == null)
+ {
+ return null;
+ }
+
+ return Template.FindName("PART_UserHintBorder", this) as System.Windows.Controls.Border;
+ }
+}
diff --git a/src/CrissCross.WPF.UI/Controls/Button/Custom/CommonRepeatButtonBase.cs b/src/CrissCross.WPF.UI/Controls/Button/Custom/CommonRepeatButtonBase.cs
new file mode 100644
index 0000000..fbbcf56
--- /dev/null
+++ b/src/CrissCross.WPF.UI/Controls/Button/Custom/CommonRepeatButtonBase.cs
@@ -0,0 +1,304 @@
+// Copyright (c) 2019-2024 ReactiveUI Association Incorporated. All rights reserved.
+// ReactiveUI Association Incorporated licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for full license information.
+
+using System.IO;
+using System.Windows.Controls.Primitives;
+using System.Windows.Input;
+using System.Windows.Markup;
+
+namespace CrissCross.WPF.UI.Controls;
+
+///
+/// CommonRepeatButtonBase.
+///
+public abstract class CommonRepeatButtonBase : RepeatButton
+{
+ ///
+ /// The corner radius1 property.
+ ///
+ public static readonly DependencyProperty CornerRadius1Property = DependencyProperty.Register("CornerRadius1", typeof(CornerRadius), typeof(CommonRepeatButtonBase), new PropertyMetadata(new CornerRadius(3.0)));
+
+ ///
+ /// The corner radius2 property.
+ ///
+ public static readonly DependencyProperty CornerRadius2Property = DependencyProperty.Register("CornerRadius2", typeof(CornerRadius), typeof(CommonRepeatButtonBase), new PropertyMetadata(new CornerRadius(2.0)));
+
+ ///
+ /// The focus border thickness property.
+ ///
+ public static readonly DependencyProperty FocusBorderThicknessProperty = DependencyProperty.Register("FocusBorderThickness", typeof(Thickness), typeof(CommonRepeatButtonBase), new PropertyMetadata(new Thickness(2.0)));
+
+ ///
+ /// The focus brush property.
+ ///
+ public static readonly DependencyProperty FocusBrushProperty = DependencyProperty.Register("FocusBrush", typeof(Brush), typeof(CommonRepeatButtonBase), new PropertyMetadata(Brushes.Orange));
+
+ ///
+ /// The glare brush property.
+ ///
+ public static readonly DependencyProperty GlareBrushProperty = DependencyProperty.Register("GlareBrush", typeof(Brush), typeof(CommonRepeatButtonBase), new PropertyMetadata(null));
+
+ ///
+ /// The minor border brush1 property.
+ ///
+ public static readonly DependencyProperty MinorBorderBrush1Property = DependencyProperty.Register("MinorBorderBrush1", typeof(Brush), typeof(CommonRepeatButtonBase), new PropertyMetadata(new LinearGradientBrush(SystemColors.ControlDarkDarkColor, SystemColors.ControlDarkDarkColor, 45)));
+
+ ///
+ /// The minor border thickness1 property.
+ ///
+ public static readonly DependencyProperty MinorBorderThickness1Property = DependencyProperty.Register("MinorBorderThickness1", typeof(Thickness), typeof(CommonRepeatButtonBase), new PropertyMetadata(new Thickness(0.0)));
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Name of the style.
+ public CommonRepeatButtonBase(string styleName)
+ {
+ try
+ {
+ var style = CommonRepeatButtonBase.ControlStyle(styleName);
+ if (style == null)
+ {
+ return;
+ }
+
+ Style = style;
+ }
+ catch (Exception exception)
+ {
+ System.Windows.MessageBox.Show(exception.Message, exception.TargetSite?.ToString(), System.Windows.MessageBoxButton.OK, MessageBoxImage.Hand);
+ }
+
+ IsEnabledChanged += CommonButtonBase_IsEnabledChanged;
+ Loaded += CommonRepeatButtonBase_Loaded;
+ }
+
+ ///
+ /// Gets or sets the corner radius1.
+ ///
+ ///
+ /// The corner radius1.
+ ///
+ public CornerRadius CornerRadius1
+ {
+ get => (CornerRadius)GetValue(CornerRadius1Property);
+ set => SetValue(CornerRadius1Property, value);
+ }
+
+ ///
+ /// Gets or sets the corner radius2.
+ ///
+ ///
+ /// The corner radius2.
+ ///
+ public CornerRadius CornerRadius2
+ {
+ get => (CornerRadius)GetValue(CornerRadius2Property);
+ set => SetValue(CornerRadius2Property, value);
+ }
+
+ ///
+ /// Gets or sets the focus border thickness.
+ ///
+ ///
+ /// The focus border thickness.
+ ///
+ public Thickness FocusBorderThickness
+ {
+ get => (Thickness)GetValue(FocusBorderThicknessProperty);
+ set => SetValue(FocusBorderThicknessProperty, value);
+ }
+
+ ///
+ /// Gets or sets the focus brush.
+ ///
+ ///
+ /// The focus brush.
+ ///
+ public Brush FocusBrush
+ {
+ get => (Brush)GetValue(FocusBrushProperty);
+ set => SetValue(FocusBrushProperty, value);
+ }
+
+ ///
+ /// Gets or sets the glare brush.
+ ///
+ ///
+ /// The glare brush.
+ ///
+ public Brush GlareBrush
+ {
+ get => (Brush)GetValue(GlareBrushProperty);
+ set => SetValue(GlareBrushProperty, value);
+ }
+
+ ///
+ /// Gets or sets the minor border brush1.
+ ///
+ ///
+ /// The minor border brush1.
+ ///
+ public Brush MinorBorderBrush1
+ {
+ get => (Brush)GetValue(MinorBorderBrush1Property);
+ set => SetValue(MinorBorderBrush1Property, value);
+ }
+
+ ///
+ /// Gets or sets the minor border thickness1.
+ ///
+ ///
+ /// The minor border thickness1.
+ ///
+ public Thickness MinorBorderThickness1
+ {
+ get => (Thickness)GetValue(MinorBorderThickness1Property);
+ set => SetValue(MinorBorderThickness1Property, value);
+ }
+
+ ///
+ /// Controls the style.
+ ///
+ /// Name of the style.
+ /// A Style.
+ protected static Style? ControlStyle(string styleName)
+ {
+ Style? style = null;
+ Stream? manifestResourceStream = null;
+ try
+ {
+ manifestResourceStream = typeof(CommonRepeatButtonBase).Module.Assembly.GetManifestResourceStream(styleName + ".xaml");
+ if (manifestResourceStream == null)
+ {
+ return null;
+ }
+
+ style = (Style)XamlReader.Load(manifestResourceStream);
+ manifestResourceStream.Close();
+ return style;
+ }
+ catch (Exception exception)
+ {
+ System.Windows.MessageBox.Show(exception.ToString(), exception.TargetSite?.ToString());
+ return null;
+ }
+ }
+
+ ///
+ /// Raises the routed event by using the event data that is provided.
+ ///
+ /// A that contains event data. This event data must contain the identifier for the event.
+ protected override void OnLostFocus(RoutedEventArgs e)
+ {
+ base.OnLostFocus(e);
+ SetIndicatorBorderSize(0);
+ }
+
+ ///
+ /// Reports when the mouse enters an element.
+ ///
+ /// The event data for a event.
+ protected override void OnMouseEnter(MouseEventArgs e)
+ {
+ base.OnMouseEnter(e);
+ SetIndicatorBorderSize(2);
+ }
+
+ ///
+ /// Reports when the mouse leaves an element.
+ ///
+ /// The event data for a event.
+ protected override void OnMouseLeave(MouseEventArgs e)
+ {
+ base.OnMouseLeave(e);
+ if (IsFocused)
+ {
+ SetIndicatorBorderSize(1);
+ }
+ else
+ {
+ SetIndicatorBorderSize(0);
+ }
+ }
+
+ ///
+ /// Returns a value that indicates whether serialization processes should serialize the value for the provided dependency property.
+ ///
+ /// The identifier for the dependency property that should be serialized.
+ ///
+ /// true if the dependency property that is supplied should be value-serialized; otherwise, false.
+ ///
+ protected override bool ShouldSerializeProperty(DependencyProperty dp)
+ {
+ if (dp == StyleProperty)
+ {
+ return false;
+ }
+
+ return base.ShouldSerializeProperty(dp);
+ }
+
+ private void CommonButtonBase_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e)
+ {
+ var border = UserHintBorder();
+
+ if (border != null)
+ {
+ if (IsEnabled)
+ {
+ border.Background = null;
+ }
+ else
+ {
+ border.Background = new SolidColorBrush(Color.FromArgb(0x55, 0, 0, 0));
+ }
+ }
+ }
+
+ private void CommonRepeatButtonBase_Loaded(object sender, RoutedEventArgs e) => SetIndicatorBorderSize(0);
+
+ private void SetIndicatorBorderSize(double size)
+ {
+ var border = UserHintBorder();
+
+ if (border != null)
+ {
+ if (size == 1)
+ {
+ border.BorderThickness = new Thickness(
+ FocusBorderThickness.Left <= 2 ? 1 : (FocusBorderThickness.Left - 2),
+ FocusBorderThickness.Top <= 2 ? 1 : (FocusBorderThickness.Top - 2),
+ FocusBorderThickness.Right <= 2 ? 1 : (FocusBorderThickness.Right - 2),
+ FocusBorderThickness.Bottom <= 2 ? 1 : (FocusBorderThickness.Bottom - 2));
+ if (GetType() == typeof(BezelRepeatButton))
+ {
+ border.Margin = new Thickness(0);
+ if (border.BorderThickness.Left == 1)
+ {
+ border.Margin = new Thickness(1);
+ }
+ }
+ }
+ else if (size == 0)
+ {
+ border.BorderThickness = new Thickness(0);
+ }
+ else
+ {
+ border.BorderThickness = FocusBorderThickness;
+ }
+ }
+ }
+
+ private System.Windows.Controls.Border? UserHintBorder()
+ {
+ if (Template == null)
+ {
+ return null;
+ }
+
+ return Template.FindName("PART_UserHintBorder", this) as System.Windows.Controls.Border;
+ }
+}
diff --git a/src/CrissCross.WPF.UI/Controls/Button/Custom/CommonToggleButtonBase.cs b/src/CrissCross.WPF.UI/Controls/Button/Custom/CommonToggleButtonBase.cs
new file mode 100644
index 0000000..9deb08e
--- /dev/null
+++ b/src/CrissCross.WPF.UI/Controls/Button/Custom/CommonToggleButtonBase.cs
@@ -0,0 +1,315 @@
+// Copyright (c) 2019-2024 ReactiveUI Association Incorporated. All rights reserved.
+// ReactiveUI Association Incorporated licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for full license information.
+
+using System.Windows.Input;
+using System.Windows.Markup;
+
+namespace CrissCross.WPF.UI.Controls;
+
+///
+/// CommonToggleButtonBase.
+///
+///
+public abstract class CommonToggleButtonBase : System.Windows.Controls.Primitives.ToggleButton
+{
+ ///
+ /// The corner radius1 property.
+ ///
+ public static readonly DependencyProperty CornerRadius1Property = DependencyProperty.Register("CornerRadius1", typeof(CornerRadius), typeof(CommonToggleButtonBase), new PropertyMetadata(new CornerRadius(3.0)));
+
+ ///
+ /// The corner radius2 property.
+ ///
+ public static readonly DependencyProperty CornerRadius2Property = DependencyProperty.Register("CornerRadius2", typeof(CornerRadius), typeof(CommonToggleButtonBase), new PropertyMetadata(new CornerRadius(2.0)));
+
+ ///
+ /// The focus border thickness property.
+ ///
+ public static readonly DependencyProperty FocusBorderThicknessProperty = DependencyProperty.Register("FocusBorderThickness", typeof(Thickness), typeof(CommonToggleButtonBase), new PropertyMetadata(new Thickness(2.0)));
+
+ ///
+ /// The focus brush property.
+ ///
+ public static readonly DependencyProperty FocusBrushProperty = DependencyProperty.Register("FocusBrush", typeof(Brush), typeof(CommonToggleButtonBase), new PropertyMetadata(Brushes.Orange));
+
+ ///
+ /// The glare brush property.
+ ///
+ public static readonly DependencyProperty GlareBrushProperty = DependencyProperty.Register("GlareBrush", typeof(Brush), typeof(CommonToggleButtonBase), new PropertyMetadata(null));
+
+ ///
+ /// The minor border brush1 property.
+ ///
+ public static readonly DependencyProperty MinorBorderBrush1Property = DependencyProperty.Register("MinorBorderBrush1", typeof(Brush), typeof(CommonToggleButtonBase), new PropertyMetadata(new LinearGradientBrush(SystemColors.ControlDarkDarkColor, SystemColors.ControlDarkDarkColor, 45)));
+
+ ///
+ /// The minor border thickness1 property.
+ ///
+ public static readonly DependencyProperty MinorBorderThickness1Property = DependencyProperty.Register("MinorBorderThickness1", typeof(Thickness), typeof(CommonToggleButtonBase), new PropertyMetadata(new Thickness(0.0)));
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Name of the style.
+ protected CommonToggleButtonBase(string styleName)
+ {
+ try
+ {
+ var style = CommonToggleButtonBase.ControlStyle(styleName);
+ if (style == null)
+ {
+ return;
+ }
+
+ Style = style;
+ }
+ catch (Exception exception)
+ {
+ System.Windows.MessageBox.Show(exception.Message, exception.TargetSite?.ToString(), System.Windows.MessageBoxButton.OK, MessageBoxImage.Hand);
+ }
+
+ IsEnabledChanged += CommonButtonBase_IsEnabledChanged;
+ Loaded += CommonToggleButtonBase_Loaded;
+ Checked += (sender, e) =>
+ {
+ if (sender is CommonToggleButtonBase button && button.IsChecked is bool isChecked)
+ {
+ if (isChecked)
+ {
+ button.Content = "Checked";
+ }
+ else
+ {
+ button.Content = "Unchecked";
+ }
+ }
+ };
+ }
+
+ ///
+ /// Gets or sets the corner radius1.
+ ///
+ ///
+ /// The corner radius1.
+ ///
+ public CornerRadius CornerRadius1
+ {
+ get => (CornerRadius)GetValue(CornerRadius1Property);
+ set => SetValue(CornerRadius1Property, value);
+ }
+
+ ///
+ /// Gets or sets the corner radius2.
+ ///
+ ///
+ /// The corner radius2.
+ ///
+ public CornerRadius CornerRadius2
+ {
+ get => (CornerRadius)GetValue(CornerRadius2Property);
+ set => SetValue(CornerRadius2Property, value);
+ }
+
+ ///
+ /// Gets or sets the focus border thickness.
+ ///
+ ///
+ /// The focus border thickness.
+ ///
+ public Thickness FocusBorderThickness
+ {
+ get => (Thickness)GetValue(FocusBorderThicknessProperty);
+ set => SetValue(FocusBorderThicknessProperty, value);
+ }
+
+ ///
+ /// Gets or sets the focus brush.
+ ///
+ ///
+ /// The focus brush.
+ ///
+ public Brush FocusBrush
+ {
+ get => (Brush)GetValue(FocusBrushProperty);
+ set => SetValue(FocusBrushProperty, value);
+ }
+
+ ///
+ /// Gets or sets the glare brush.
+ ///
+ ///
+ /// The glare brush.
+ ///
+ public Brush GlareBrush
+ {
+ get => (Brush)GetValue(GlareBrushProperty);
+ set => SetValue(GlareBrushProperty, value);
+ }
+
+ ///
+ /// Gets or sets the minor border brush1.
+ ///
+ ///
+ /// The minor border brush1.
+ ///
+ public Brush MinorBorderBrush1
+ {
+ get => (Brush)GetValue(MinorBorderBrush1Property);
+ set => SetValue(MinorBorderBrush1Property, value);
+ }
+
+ ///
+ /// Gets or sets the minor border thickness1.
+ ///
+ ///
+ /// The minor border thickness1.
+ ///
+ public Thickness MinorBorderThickness1
+ {
+ get => (Thickness)GetValue(MinorBorderThickness1Property);
+ set => SetValue(MinorBorderThickness1Property, value);
+ }
+
+ ///
+ /// Controls the style.
+ ///
+ /// Name of the style.
+ /// A Style.
+ protected static Style? ControlStyle(string styleName)
+ {
+ try
+ {
+ var manifestResourceStream = typeof(CommonToggleButtonBase).Module.Assembly.GetManifestResourceStream(styleName + ".xaml");
+ if (manifestResourceStream == null)
+ {
+ return null;
+ }
+
+ var style = (Style)XamlReader.Load(manifestResourceStream);
+ manifestResourceStream.Close();
+ return style;
+ }
+ catch (Exception exception)
+ {
+ System.Windows.MessageBox.Show(exception.ToString(), exception.TargetSite?.ToString());
+ return null;
+ }
+ }
+
+ ///
+ /// Raises the routed event by using the event data that is provided.
+ ///
+ /// A that contains event data. This event data must contain the identifier for the event.
+ protected override void OnLostFocus(RoutedEventArgs e)
+ {
+ base.OnLostFocus(e);
+ SetIndicatorBorderSize(0.0);
+ }
+
+ ///
+ /// Provides class handling for the routed event that occurs when the mouse enters this control.
+ ///
+ /// The event data for the event.
+ protected override void OnMouseEnter(MouseEventArgs e)
+ {
+ base.OnMouseEnter(e);
+ SetIndicatorBorderSize(2.0);
+ }
+
+ ///
+ /// Provides class handling for the routed event that occurs when the mouse leaves an element.
+ ///
+ /// The event data for the event.
+ protected override void OnMouseLeave(MouseEventArgs e)
+ {
+ base.OnMouseLeave(e);
+ if (IsFocused)
+ {
+ SetIndicatorBorderSize(1.0);
+ }
+ else
+ {
+ SetIndicatorBorderSize(0.0);
+ }
+ }
+
+ ///
+ /// Returns a value that indicates whether serialization processes should serialize the value for the provided dependency property.
+ ///
+ /// The identifier for the dependency property that should be serialized.
+ ///
+ /// true if the dependency property that is supplied should be value-serialized; otherwise, false.
+ ///
+ protected override bool ShouldSerializeProperty(DependencyProperty dp)
+ {
+ if (dp == StyleProperty)
+ {
+ return false;
+ }
+
+ return base.ShouldSerializeProperty(dp);
+ }
+
+ private void CommonButtonBase_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e)
+ {
+ var border = UserHintBorder();
+
+ if (border != null)
+ {
+ if (IsEnabled)
+ {
+ border.Background = null;
+ }
+ else
+ {
+ border.Background = new SolidColorBrush(Color.FromArgb(0x55, 0, 0, 0));
+ }
+ }
+ }
+
+ private void CommonToggleButtonBase_Loaded(object sender, RoutedEventArgs e) => SetIndicatorBorderSize(0.0);
+
+ private void SetIndicatorBorderSize(double size)
+ {
+ var border = UserHintBorder();
+
+ if (border != null)
+ {
+ if (size == 1)
+ {
+ border.BorderThickness = new Thickness(
+ FocusBorderThickness.Left <= 2 ? 1 : (FocusBorderThickness.Left - 2),
+ FocusBorderThickness.Top <= 2 ? 1 : (FocusBorderThickness.Top - 2),
+ FocusBorderThickness.Right <= 2 ? 1 : (FocusBorderThickness.Right - 2),
+ FocusBorderThickness.Bottom <= 2 ? 1 : (FocusBorderThickness.Bottom - 2));
+ if (GetType() == typeof(BezelToggleButton))
+ {
+ border.Margin = new Thickness(0);
+ if (border.BorderThickness.Left == 1.0)
+ {
+ border.Margin = new Thickness(1.0);
+ }
+ }
+ }
+ else if (size == 0)
+ {
+ border.BorderThickness = new Thickness(0.0);
+ }
+ else
+ {
+ border.BorderThickness = FocusBorderThickness;
+ }
+ }
+ }
+
+ private Border? UserHintBorder()
+ {
+ if (Template == null)
+ {
+ return null;
+ }
+
+ return Template.FindName("PART_UserHintBorder", this) as Border;
+ }
+}
diff --git a/src/CrissCross.WPF.UI/Controls/Button/Custom/GelButton.cs b/src/CrissCross.WPF.UI/Controls/Button/Custom/GelButton.cs
new file mode 100644
index 0000000..4a2ed13
--- /dev/null
+++ b/src/CrissCross.WPF.UI/Controls/Button/Custom/GelButton.cs
@@ -0,0 +1,20 @@
+// Copyright (c) 2019-2024 ReactiveUI Association Incorporated. All rights reserved.
+// ReactiveUI Association Incorporated licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for full license information.
+
+namespace CrissCross.WPF.UI.Controls;
+
+///
+/// GelButton.
+///
+///
+public class GelButton : CommonButtonBase
+{
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public GelButton()
+ : base("CrissCross.WPF.UI.Controls.GelButton")
+ {
+ }
+}
diff --git a/src/CrissCross.WPF.UI/Controls/Button/Custom/GelRepeatButton.cs b/src/CrissCross.WPF.UI/Controls/Button/Custom/GelRepeatButton.cs
new file mode 100644
index 0000000..12062b4
--- /dev/null
+++ b/src/CrissCross.WPF.UI/Controls/Button/Custom/GelRepeatButton.cs
@@ -0,0 +1,20 @@
+// Copyright (c) 2019-2024 ReactiveUI Association Incorporated. All rights reserved.
+// ReactiveUI Association Incorporated licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for full license information.
+
+namespace CrissCross.WPF.UI.Controls;
+
+///
+/// GelRepeatButton.
+///
+///
+public class GelRepeatButton : CommonToggleButtonBase
+{
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public GelRepeatButton()
+ : base("CrissCross.WPF.UI.Controls.GelRepeatButton")
+ {
+ }
+}
diff --git a/src/CrissCross.WPF.UI/Controls/Button/Custom/GelToggleButton.cs b/src/CrissCross.WPF.UI/Controls/Button/Custom/GelToggleButton.cs
new file mode 100644
index 0000000..bd59025
--- /dev/null
+++ b/src/CrissCross.WPF.UI/Controls/Button/Custom/GelToggleButton.cs
@@ -0,0 +1,20 @@
+// Copyright (c) 2019-2024 ReactiveUI Association Incorporated. All rights reserved.
+// ReactiveUI Association Incorporated licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for full license information.
+
+namespace CrissCross.WPF.UI.Controls;
+
+///
+/// GelToggleButton.
+///
+///
+public class GelToggleButton : CommonToggleButtonBase
+{
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public GelToggleButton()
+ : base("CrissCross.WPF.UI.Controls.GelToggleButton")
+ {
+ }
+}
diff --git a/src/CrissCross.WPF.UI/Controls/Button/Custom/RaisedBorder.cs b/src/CrissCross.WPF.UI/Controls/Button/Custom/RaisedBorder.cs
new file mode 100644
index 0000000..f036ff1
--- /dev/null
+++ b/src/CrissCross.WPF.UI/Controls/Button/Custom/RaisedBorder.cs
@@ -0,0 +1,411 @@
+// Copyright (c) 2019-2024 ReactiveUI Association Incorporated. All rights reserved.
+// ReactiveUI Association Incorporated licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for full license information.
+
+using System.Windows.Controls;
+
+namespace CrissCross.WPF.UI.Controls;
+
+///
+/// AICSBorder.
+///
+///
+public class RaisedBorder : ContentControl
+{
+ ///
+ /// The corner radius1 property.
+ ///
+ public static readonly DependencyProperty CornerRadius1Property = DependencyProperty.Register("CornerRadius1", typeof(CornerRadius), typeof(RaisedBorder), new PropertyMetadata(new CornerRadius(10.0)));
+
+ ///
+ /// The corner radius2 property.
+ ///
+ public static readonly DependencyProperty CornerRadius2Property = DependencyProperty.Register("CornerRadius2", typeof(CornerRadius), typeof(RaisedBorder), new PropertyMetadata(new CornerRadius(20.0)));
+
+ ///
+ /// The glare brush property.
+ ///
+ public static readonly DependencyProperty GlareBrushProperty = DependencyProperty.Register("GlareBrush", typeof(Brush), typeof(RaisedBorder), new PropertyMetadata(null));
+
+ ///
+ /// The glare opacity mask property.
+ ///
+ public static readonly DependencyProperty GlareOpacityMaskProperty = DependencyProperty.Register("GlareOpacityMask", typeof(Brush), typeof(RaisedBorder), new PropertyMetadata(null));
+
+ ///
+ /// The minor border brush1 property.
+ ///
+ public static readonly DependencyProperty MinorBorderBrush1Property = DependencyProperty.Register("MinorBorderBrush1", typeof(Brush), typeof(RaisedBorder), new PropertyMetadata(null));
+
+ ///
+ /// The minor border thickness1 property.
+ ///
+ public static readonly DependencyProperty MinorBorderThickness1Property = DependencyProperty.Register("MinorBorderThickness1", typeof(Thickness), typeof(RaisedBorder), new PropertyMetadata(new Thickness(0.0)));
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public RaisedBorder()
+ {
+ CreateControlTemplate();
+ ClipToBounds = true;
+ }
+
+ ///
+ /// Gets or sets the corner radius1.
+ ///
+ ///
+ /// The corner radius1.
+ ///
+ public CornerRadius CornerRadius1
+ {
+ get => (CornerRadius)GetValue(CornerRadius1Property);
+ set => SetValue(CornerRadius1Property, value);
+ }
+
+ ///
+ /// Gets or sets the corner radius2.
+ ///
+ ///
+ /// The corner radius2.
+ ///
+ public CornerRadius CornerRadius2
+ {
+ get => (CornerRadius)GetValue(CornerRadius2Property);
+ set => SetValue(CornerRadius2Property, value);
+ }
+
+ ///
+ /// Gets or sets the glare brush.
+ ///
+ ///
+ /// The glare brush.
+ ///
+ public Brush GlareBrush
+ {
+ get => (Brush)GetValue(GlareBrushProperty);
+ set => SetValue(GlareBrushProperty, value);
+ }
+
+ ///
+ /// Gets or sets the glare opacity mask.
+ ///
+ ///
+ /// The glare opacity mask.
+ ///
+ public Brush GlareOpacityMask
+ {
+ get => (Brush)GetValue(GlareOpacityMaskProperty);
+ set => SetValue(GlareOpacityMaskProperty, value);
+ }
+
+ ///
+ /// Gets or sets the minor border brush1.
+ ///
+ ///
+ /// The minor border brush1.
+ ///
+ public Brush MinorBorderBrush1
+ {
+ get => (Brush)GetValue(MinorBorderBrush1Property);
+ set => SetValue(MinorBorderBrush1Property, value);
+ }
+
+ ///
+ /// Gets or sets the minor border thickness1.
+ ///
+ ///
+ /// The minor border thickness1.
+ ///
+ public Thickness MinorBorderThickness1
+ {
+ get => (Thickness)GetValue(MinorBorderThickness1Property);
+ set => SetValue(MinorBorderThickness1Property, value);
+ }
+
+ ///
+ /// Invoked whenever the effective value of any dependency property on this has been updated. The specific dependency property that changed is reported in the arguments parameter. Overrides .
+ ///
+ /// The event data that describes the property that changed, as well as old and new values.
+ protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
+ {
+ base.OnPropertyChanged(e);
+ InvalidateVisual();
+ }
+
+ ///
+ /// When overridden in a derived class, participates in rendering operations that are directed by the layout system. The rendering instructions for this element are not used directly when this method is invoked, and are instead preserved for later asynchronous use by layout and drawing.
+ ///
+ /// The drawing instructions for a specific element. This context is provided to the layout system.
+ protected override void OnRender(DrawingContext drawingContext)
+ {
+ if (drawingContext == null)
+ {
+ throw new ArgumentNullException(nameof(drawingContext));
+ }
+
+ var borderThickness = new Thickness(
+ Math.Max(0, BorderThickness.Left + MinorBorderThickness1.Left),
+ Math.Max(0, BorderThickness.Top + MinorBorderThickness1.Top),
+ Math.Max(0, BorderThickness.Right + MinorBorderThickness1.Right),
+ Math.Max(0, BorderThickness.Bottom + MinorBorderThickness1.Bottom));
+
+ var geometry = RaisedBorder.CreateGeometryForPath(ActualWidth, ActualHeight, CornerRadius1);
+ var geometry2 = RaisedBorder.CreateGeometryForPath(ActualWidth, ActualHeight, CornerRadius2, BorderThickness);
+ var geometry3 = RaisedBorder.CreateGeometryForPath(ActualWidth, ActualHeight, CornerRadius2, borderThickness);
+
+ var pen = new Pen(BorderBrush, 0.5);
+ var group = new GeometryGroup();
+ group.Children.Add(geometry);
+ group.Children.Add(geometry2);
+ drawingContext.DrawGeometry(BorderBrush, pen, group);
+
+ var pen2 = new Pen(MinorBorderBrush1, 0.5);
+ group = new GeometryGroup();
+ group.Children.Add(geometry2);
+ group.Children.Add(geometry3);
+ drawingContext.DrawGeometry(MinorBorderBrush1, pen2, group);
+
+ var border = Template.FindName("PART_MainBorder", this) as Border;
+ if (border != null)
+ {
+ border.Padding = new Thickness(
+ borderThickness.Left + Padding.Left,
+ borderThickness.Top + Padding.Top,
+ borderThickness.Right + Padding.Right,
+ borderThickness.Bottom + Padding.Bottom);
+ border.Clip = geometry3;
+ }
+
+ base.OnRender(drawingContext);
+ }
+
+ ///
+ /// Returns a value that indicates whether serialization processes should serialize the value for the provided dependency property.
+ ///
+ /// The identifier for the dependency property that should be serialized.
+ ///
+ /// true if the dependency property that is supplied should be value-serialized; otherwise, false.
+ ///
+ protected override bool ShouldSerializeProperty(DependencyProperty dp)
+ {
+ if (dp == StyleProperty)
+ {
+ return false;
+ }
+
+ return base.ShouldSerializeProperty(dp);
+ }
+
+ private static PathGeometry CreateGeometryForPath(double width, double height, CornerRadius cornerRadius) => CreateGeometryForPath(width, height, cornerRadius, new Thickness(0));
+
+ private static PathGeometry CreateGeometryForPath(double actualWidth, double actualHeight, CornerRadius cornerRadius, Thickness borderThickness)
+ {
+ var geometry = new PathGeometry();
+ var figure = new PathFigure();
+ double x = 0;
+ var num2 = actualWidth - borderThickness.Right - borderThickness.Left;
+ double y = 0;
+ var num4 = actualHeight - borderThickness.Bottom - borderThickness.Top;
+ var num5 = num2 - x;
+ var num6 = num4 - y;
+ Point point;
+ var num7 = cornerRadius.TopLeft + cornerRadius.TopRight;
+ var point2 = new Point((cornerRadius.TopLeft / num7) * num5, y);
+ if (double.IsNaN(point2.X))
+ {
+ point2.X = 0;
+ }
+
+ if (point2.X > cornerRadius.TopLeft)
+ {
+ point2 = new Point(cornerRadius.TopLeft, y);
+ }
+
+ var point3 = new Point(point2.X, y);
+ point = new Point(point3.X + borderThickness.Left, point3.Y + borderThickness.Top);
+ figure.StartPoint = point;
+ point3 = new Point((cornerRadius.TopRight / num7) * num5, y);
+ if (double.IsNaN(point3.X))
+ {
+ point3.X = 0;
+ }
+
+ point3.X = num5 - point3.X;
+ if (point3.X <= x + num5 - cornerRadius.TopRight)
+ {
+ point3 = new Point(num5 - cornerRadius.TopRight, y);
+ point = new Point(point3.X + borderThickness.Left, point3.Y + borderThickness.Top);
+ var segment = new LineSegment(point, false);
+ figure.Segments.Add(segment);
+ }
+
+ var size = default(Size);
+ var num8 = cornerRadius.BottomRight + cornerRadius.TopRight;
+ if (cornerRadius.TopRight != 0)
+ {
+ size.Width = Math.Min(cornerRadius.TopRight, Math.Max(0, num5 - point3.X));
+ point3 = new Point(num2, (cornerRadius.TopRight / num8) * num6);
+ if (double.IsNaN(point3.Y))
+ {
+ point3.Y = 0;
+ }
+
+ if (point3.Y > cornerRadius.TopRight)
+ {
+ point3 = new Point(num2, cornerRadius.TopRight);
+ size.Height = cornerRadius.TopRight;
+ }
+ else
+ {
+ point3.Y = point3.Y;
+ size.Height = Math.Max(0, point3.Y);
+ }
+
+ point = new Point(point3.X + borderThickness.Left, point3.Y + borderThickness.Top);
+ var segment2 = new ArcSegment(point, size, 0, false, SweepDirection.Clockwise, false);
+ figure.Segments.Add(segment2);
+ }
+
+ if (point3.Y < num6 - cornerRadius.BottomRight)
+ {
+ point3 = new Point(num2, num6 - cornerRadius.BottomRight);
+ point = new Point(point3.X + borderThickness.Left, point3.Y + borderThickness.Top);
+ var segment3 = new LineSegment(point, false);
+ figure.Segments.Add(segment3);
+ }
+
+ var num9 = cornerRadius.BottomRight + cornerRadius.BottomLeft;
+ if (cornerRadius.BottomRight != 0)
+ {
+ size.Height = Math.Min(cornerRadius.BottomRight, Math.Max(0, num6 - point3.Y));
+ point3 = new Point((cornerRadius.BottomRight / num9) * num5, num4);
+ if (double.IsNaN(point3.X))
+ {
+ point3.X = 0;
+ }
+
+ if (point3.X > cornerRadius.BottomRight)
+ {
+ point3 = new Point(num5 - cornerRadius.BottomRight, num4);
+ size.Width = cornerRadius.BottomRight;
+ }
+ else
+ {
+ point3 = new Point(num5 - point3.X, num4);
+ size.Width = Math.Max(0, num5 - point3.X);
+ }
+
+ point = new Point(point3.X + borderThickness.Left, point3.Y + borderThickness.Top);
+ var segment4 = new ArcSegment(point, size, 0, false, SweepDirection.Clockwise, false);
+ figure.Segments.Add(segment4);
+ }
+
+ if (point3.X > cornerRadius.BottomLeft)
+ {
+ point3 = new Point(x + cornerRadius.BottomLeft, num4);
+ point = new Point(point3.X + borderThickness.Left, point3.Y + borderThickness.Top);
+ var segment5 = new LineSegment(point, false);
+ figure.Segments.Add(segment5);
+ }
+
+ var num10 = cornerRadius.BottomLeft + cornerRadius.TopLeft;
+ if (cornerRadius.BottomLeft != 0)
+ {
+ size.Width = Math.Min(cornerRadius.BottomLeft, Math.Max(0, point3.X));
+ point3 = new Point(x, (cornerRadius.BottomLeft / num10) * num6);
+ if (double.IsNaN(point3.Y))
+ {
+ point3.Y = 0;
+ }
+
+ if (point3.Y > cornerRadius.BottomLeft)
+ {
+ point3 = new Point(x, num6 - cornerRadius.BottomLeft);
+ size.Height = cornerRadius.BottomLeft;
+ }
+ else
+ {
+ point3 = new Point(x, num6 - point3.Y);
+ size.Height = Math.Max(0, num6 - point3.Y);
+ }
+
+ point = new Point(point3.X + borderThickness.Left, point3.Y + borderThickness.Top);
+ var segment6 = new ArcSegment(point, size, 0, false, SweepDirection.Clockwise, false);
+ figure.Segments.Add(segment6);
+ }
+
+ if (point3.Y > cornerRadius.TopLeft)
+ {
+ point3 = new Point(x, y + cornerRadius.TopLeft);
+ point = new Point(point3.X + borderThickness.Left, point3.Y + borderThickness.Top);
+ var segment7 = new LineSegment(point, false);
+ figure.Segments.Add(segment7);
+ }
+
+ if (cornerRadius.TopLeft != 0)
+ {
+ size.Height = Math.Min(cornerRadius.TopLeft, Math.Max(0, point3.Y));
+ point3 = new Point((cornerRadius.TopLeft / num7) * num5, y);
+ if (double.IsNaN(point3.X))
+ {
+ point3.X = 0;
+ }
+
+ if (point3.X > cornerRadius.TopLeft)
+ {
+ point3 = new Point(cornerRadius.TopLeft, y);
+ size.Width = cornerRadius.TopLeft;
+ }
+ else
+ {
+ point3 = new Point(point3.X, y);
+ size.Width = Math.Max(0, point3.X);
+ }
+
+ point = new Point(point3.X + borderThickness.Left, point3.Y + borderThickness.Top);
+ var segment8 = new ArcSegment(point, size, 0, false, SweepDirection.Clockwise, false);
+ figure.Segments.Add(segment8);
+ }
+
+ figure.IsClosed = true;
+ geometry.Figures.Add(figure);
+ return geometry;
+ }
+
+ private void CreateControlTemplate()
+ {
+ var template = new ControlTemplate(GetType());
+ var factory = new FrameworkElementFactory(typeof(Border), "PART_MainBorder");
+ var extension = new TemplateBindingExtension(BackgroundProperty);
+ factory.SetValue(Border.BackgroundProperty, extension);
+ factory.SetValue(HorizontalAlignmentProperty, HorizontalAlignment.Stretch);
+ factory.SetValue(VerticalAlignmentProperty, VerticalAlignment.Stretch);
+ factory.SetValue(IsHitTestVisibleProperty, true);
+
+ var child = new FrameworkElementFactory(typeof(Grid));
+ child.SetValue(MarginProperty, new Thickness(-1));
+ child.SetValue(IsHitTestVisibleProperty, true);
+ factory.AppendChild(child);
+
+ var factory3 = new FrameworkElementFactory(typeof(ContentPresenter));
+ extension = new TemplateBindingExtension(HorizontalContentAlignmentProperty);
+ factory3.SetValue(HorizontalAlignmentProperty, extension);
+ extension = new TemplateBindingExtension(VerticalContentAlignmentProperty);
+ factory3.SetValue(VerticalAlignmentProperty, extension);
+ extension = new TemplateBindingExtension(ContentProperty);
+ factory3.SetValue(ContentPresenter.ContentProperty, extension);
+ child.AppendChild(factory3);
+
+ var factory4 = new FrameworkElementFactory(typeof(Border), "PART_GlareBorder");
+ extension = new TemplateBindingExtension(GlareBrushProperty);
+ factory4.SetValue(Border.BackgroundProperty, extension);
+ extension = new TemplateBindingExtension(GlareOpacityMaskProperty);
+ factory4.SetValue(OpacityMaskProperty, extension);
+ factory4.SetValue(IsHitTestVisibleProperty, false);
+ child.AppendChild(factory4);
+
+ template.VisualTree = factory;
+ Template = template;
+ }
+}
diff --git a/src/CrissCross.WPF.UI/Controls/Button/GelButton.xaml b/src/CrissCross.WPF.UI/Controls/Button/GelButton.xaml
new file mode 100644
index 0000000..983f4ee
--- /dev/null
+++ b/src/CrissCross.WPF.UI/Controls/Button/GelButton.xaml
@@ -0,0 +1,180 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/CrissCross.WPF.UI/Controls/Button/GelRepeatButton.xaml b/src/CrissCross.WPF.UI/Controls/Button/GelRepeatButton.xaml
new file mode 100644
index 0000000..47712f0
--- /dev/null
+++ b/src/CrissCross.WPF.UI/Controls/Button/GelRepeatButton.xaml
@@ -0,0 +1,184 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/CrissCross.WPF.UI/Controls/Button/GelToggleButton.xaml b/src/CrissCross.WPF.UI/Controls/Button/GelToggleButton.xaml
new file mode 100644
index 0000000..0e8abd8
--- /dev/null
+++ b/src/CrissCross.WPF.UI/Controls/Button/GelToggleButton.xaml
@@ -0,0 +1,191 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/CrissCross.WPF.UI/Controls/NavigationView/NavigationView.Navigation.cs b/src/CrissCross.WPF.UI/Controls/NavigationView/NavigationView.Navigation.cs
index b9934cb..acac797 100644
--- a/src/CrissCross.WPF.UI/Controls/NavigationView/NavigationView.Navigation.cs
+++ b/src/CrissCross.WPF.UI/Controls/NavigationView/NavigationView.Navigation.cs
@@ -185,14 +185,14 @@ private bool NavigateInternal(
if (OnNavigating(pageInstance))
{
#if DEBUG
- Debug.WriteLineIf(EnableDebugMessages, "Navigation canceled");
+ System.Diagnostics.Debug.WriteLineIf(EnableDebugMessages, "Navigation canceled");
#endif
return false;
}
#if DEBUG
- Debug.WriteLineIf(
+ System.Diagnostics.Debug.WriteLineIf(
EnableDebugMessages,
$"DEBUG | {viewItem.Id} - {(string.IsNullOrEmpty(viewItem.TargetPageTag) ? "NO_TAG" : viewItem.TargetPageTag)} - {viewItem.TargetPageType} | NAVIGATED");
#endif
@@ -230,11 +230,11 @@ private void AddToJournal(INavigationViewItem viewItem, bool isBackwardsNavigate
IsBackEnabled = CanGoBack;
#if DEBUG
- Debug.WriteLineIf(EnableDebugMessages, $"JOURNAL INDEX {_currentIndexInJournal}");
+ System.Diagnostics.Debug.WriteLineIf(EnableDebugMessages, $"JOURNAL INDEX {_currentIndexInJournal}");
if (Journal.Count > 0)
{
- Debug.WriteLineIf(EnableDebugMessages, $"JOURNAL LAST ELEMENT {Journal[^1]}");
+ System.Diagnostics.Debug.WriteLineIf(EnableDebugMessages, $"JOURNAL LAST ELEMENT {Journal[^1]}");
}
#endif
}
@@ -278,7 +278,7 @@ private object GetNavigationItemInstance(INavigationViewItem viewItem)
if (_serviceProvider is not null)
{
#if DEBUG
- Debug.WriteLine(
+ System.Diagnostics.Debug.WriteLine(
$"Getting {targetPageType} from cache using IServiceProvider.");
#endif
@@ -289,7 +289,7 @@ private object GetNavigationItemInstance(INavigationViewItem viewItem)
if (_pageService is not null)
{
#if DEBUG
- Debug.WriteLine($"Getting {targetPageType} from cache using IPageService.");
+ System.Diagnostics.Debug.WriteLine($"Getting {targetPageType} from cache using IPageService.");
#endif
return _pageService.GetPage(targetPageType)
@@ -297,7 +297,7 @@ private object GetNavigationItemInstance(INavigationViewItem viewItem)
}
#if DEBUG
- Debug.WriteLine($"Getting {targetPageType} from cache using reflection.");
+ System.Diagnostics.Debug.WriteLine($"Getting {targetPageType} from cache using reflection.");
#endif
return NavigationViewActivator.CreateInstance(targetPageType)
diff --git a/src/CrissCross.WPF.UI/Controls/NumberPad/NumberPad.xaml b/src/CrissCross.WPF.UI/Controls/NumberPad/NumberPad.xaml
index 53cc945..b29ae01 100644
--- a/src/CrissCross.WPF.UI/Controls/NumberPad/NumberPad.xaml
+++ b/src/CrissCross.WPF.UI/Controls/NumberPad/NumberPad.xaml
@@ -20,7 +20,7 @@
0 ? _owner.Minimum : _owner.Maximum < 0 ? _owner.Maximum : 0;
diff --git a/src/CrissCross.WPF.UI/Controls/NumericPushButton/NumericPushButton.cs b/src/CrissCross.WPF.UI/Controls/NumericPushButton/NumericPushButton.cs
index 77ce861..4d11db4 100644
--- a/src/CrissCross.WPF.UI/Controls/NumericPushButton/NumericPushButton.cs
+++ b/src/CrissCross.WPF.UI/Controls/NumericPushButton/NumericPushButton.cs
@@ -14,16 +14,6 @@ namespace CrissCross.WPF.UI.Controls;
///
public class NumericPushButton : System.Windows.Controls.Button, INumberPadButton, IDisposable
{
- ///
- /// Set Background.
- ///
- public static readonly DependencyProperty BackGroundColorProperty =
- DependencyProperty.Register(
- nameof(BackGroundColor),
- typeof(Brush),
- typeof(NumericPushButton),
- new PropertyMetadata(Brushes.White, ChangeBackgroundColor));
-
///
/// Defaults decimal points.
///
@@ -128,6 +118,7 @@ public class NumericPushButton : System.Windows.Controls.Button, INumberPadButto
private readonly DispatcherTimer _isEnabledFalseTimer;
private readonly ReplaySubject<(bool UserChanged, double Value)> _valueD = new(1);
private readonly ReplaySubject<(bool UserChanged, float Value)> _valueF = new(1);
+ private readonly IDisposable _keypadDisposable;
private NumberPad? _keypad;
private bool _disposedValue;
@@ -138,7 +129,7 @@ public NumericPushButton()
{
DefaultStyleKey = typeof(NumericPushButton);
ShowKeypad = ReactiveCommand.Create(() => { });
- ShowKeypad.Subscribe(_ => _keypad = new NumberPad(this));
+ _keypadDisposable = ShowKeypad.Subscribe(_ => _keypad = new NumberPad(this) { MaskColor = MaskColor });
_isEnabledFalseTimer = new DispatcherTimer(
TimeSpan.FromMilliseconds(100),
DispatcherPriority.Normal,
@@ -204,18 +195,6 @@ public NumericPushButton()
///
public event EventHandler<(bool, double)>? ValueChanged;
- ///
- /// Gets or sets set the BackgroundColor.
- ///
- [Description("Sets Background of the Keypad")]
- [Category("Brush")]
- public Brush BackGroundColor
- {
- get => (Brush)GetValue(BackGroundColorProperty);
-
- set => SetValue(BackGroundColorProperty, value);
- }
-
///
/// Gets or sets how many decimal places to visualize.
///
@@ -404,29 +383,13 @@ protected virtual void Dispose(bool disposing)
_valueD.Dispose();
_valueF.Dispose();
_keypad?.Dispose();
+ _keypadDisposable.Dispose();
}
_disposedValue = true;
}
}
- private static void ChangeBackgroundColor(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- var npb = d as NumericPushButton;
- var mycolor = (Brush)e.NewValue;
- if (mycolor.IsFrozen)
- {
- mycolor = mycolor.Clone();
- }
-
- mycolor.Opacity = npb!.InDesignMode ? 0 : 0.5;
-
- if (npb?._keypad != null)
- {
- npb._keypad.Background = mycolor;
- }
- }
-
///
/// Maximum Changed Dependency.
///
@@ -510,7 +473,8 @@ private static void UpdateMask(DependencyObject d, DependencyPropertyChangedEven
{
if (d is NumericPushButton c && c._keypad != null)
{
- c._keypad.MaskColor = (Brush)e.NewValue;
+ c.MaskColor = (Brush)e.NewValue;
+ c._keypad.MaskColor = c.MaskColor;
}
}
diff --git a/src/CrissCross.WPF.UI/Controls/NumericPushButton/NumericPushButton.xaml b/src/CrissCross.WPF.UI/Controls/NumericPushButton/NumericPushButton.xaml
index 02c106c..4a6e244 100644
--- a/src/CrissCross.WPF.UI/Controls/NumericPushButton/NumericPushButton.xaml
+++ b/src/CrissCross.WPF.UI/Controls/NumericPushButton/NumericPushButton.xaml
@@ -15,15 +15,20 @@
@@ -32,7 +37,6 @@
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Background="Red"
- FontFamily="MS Reference Sans Serif"
FontSize="13"
Foreground="White"
Text="{TemplateBinding ErrorText}"
@@ -46,7 +50,7 @@
-
+
diff --git a/src/CrissCross.WPF.UI/Markup/ThemesDictionary.cs b/src/CrissCross.WPF.UI/Markup/ThemesDictionary.cs
index f7f2d43..87268ce 100644
--- a/src/CrissCross.WPF.UI/Markup/ThemesDictionary.cs
+++ b/src/CrissCross.WPF.UI/Markup/ThemesDictionary.cs
@@ -31,7 +31,7 @@ public class ThemesDictionary : ResourceDictionary
///
/// Initializes a new instance of the class.
///
- public ThemesDictionary() => SetSourceBasedOnSelectedTheme(ApplicationTheme.Light);
+ public ThemesDictionary() => SetSourceBasedOnSelectedTheme(ApplicationTheme.Dark);
///
/// Sets the default application theme.
diff --git a/src/CrissCross.WPF.UI/Resources/CrissCross.Ui.xaml b/src/CrissCross.WPF.UI/Resources/CrissCross.Ui.xaml
index fa4aece..10a222b 100644
--- a/src/CrissCross.WPF.UI/Resources/CrissCross.Ui.xaml
+++ b/src/CrissCross.WPF.UI/Resources/CrissCross.Ui.xaml
@@ -84,6 +84,14 @@
+
+
+
+
+
+
+
+
diff --git a/src/CrissCross.WPF.UI/Resources/Variables.xaml b/src/CrissCross.WPF.UI/Resources/Variables.xaml
index d690591..eb4bb2d 100644
--- a/src/CrissCross.WPF.UI/Resources/Variables.xaml
+++ b/src/CrissCross.WPF.UI/Resources/Variables.xaml
@@ -4,6 +4,7 @@
xmlns:system="clr-namespace:System;assembly=System.Runtime">
16
+ 4
4,4,4,4