From 7f2f713ff0d549488ad8304547ec2680362af348 Mon Sep 17 00:00:00 2001 From: boombuler Date: Wed, 7 Mar 2018 22:21:19 +0100 Subject: [PATCH 1/9] fixed not updating cursor on osx --- src/OSX/Avalonia.MonoMac/TopLevelImpl.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/OSX/Avalonia.MonoMac/TopLevelImpl.cs b/src/OSX/Avalonia.MonoMac/TopLevelImpl.cs index 667ee12fa0..9dc6c45745 100644 --- a/src/OSX/Avalonia.MonoMac/TopLevelImpl.cs +++ b/src/OSX/Avalonia.MonoMac/TopLevelImpl.cs @@ -133,7 +133,10 @@ namespace Avalonia.MonoMac { ResetCursorRects(); if (_cursor != null) + { AddCursorRect(Frame, _cursor); + _cursor.Set(); + } } static readonly NSCursor ArrowCursor = NSCursor.ArrowCursor; From a3dd74fafab6ef7b95acbe56fad8f32a7e198748 Mon Sep 17 00:00:00 2001 From: boombuler Date: Thu, 8 Mar 2018 07:27:35 +0100 Subject: [PATCH 2/9] only set the cursor if the mouse is over the toplevel --- src/OSX/Avalonia.MonoMac/TopLevelImpl.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/OSX/Avalonia.MonoMac/TopLevelImpl.cs b/src/OSX/Avalonia.MonoMac/TopLevelImpl.cs index 9dc6c45745..a655bc1ec5 100644 --- a/src/OSX/Avalonia.MonoMac/TopLevelImpl.cs +++ b/src/OSX/Avalonia.MonoMac/TopLevelImpl.cs @@ -39,6 +39,7 @@ namespace Avalonia.MonoMac private NSTrackingArea _area; private NSCursor _cursor; private bool _nonUiRedrawQueued; + private bool _isMouseOver; public CGSize PixelSize { get; set; } @@ -135,7 +136,8 @@ namespace Avalonia.MonoMac if (_cursor != null) { AddCursorRect(Frame, _cursor); - _cursor.Set(); + if (_isMouseOver) + _cursor.Set(); } } @@ -302,10 +304,17 @@ namespace Avalonia.MonoMac public override void MouseExited(NSEvent theEvent) { + _isMouseOver = false; MouseEvent(theEvent, RawMouseEventType.LeaveWindow); base.MouseExited(theEvent); } + public override void MouseEntered(NSEvent theEvent) + { + _isMouseOver = true; + base.MouseEntered(theEvent); + } + void KeyboardEvent(RawKeyEventType type, NSEvent ev) { var code = KeyTransform.TransformKeyCode(ev.KeyCode); From e967a8eb7276542166080c2652fe4c6f5b3fa300 Mon Sep 17 00:00:00 2001 From: ahopper Date: Thu, 8 Mar 2018 12:34:47 +0000 Subject: [PATCH 3/9] rename WritableBitmap --- src/Avalonia.Controls/Remote/RemoteWidget.cs | 4 ++-- .../Imaging/{WritableBitmap.cs => WriteableBitmap.cs} | 10 +++++----- .../Platform/IPlatformRenderInterface.cs | 6 +++--- ...{IWritableBitmapImpl.cs => IWriteableBitmapImpl.cs} | 4 ++-- src/Skia/Avalonia.Skia/BitmapImpl.cs | 2 +- src/Skia/Avalonia.Skia/PlatformRenderInterface.cs | 2 +- src/Windows/Avalonia.Direct2D1/Direct2D1Platform.cs | 4 ++-- ...tableWicBitmapImpl.cs => WriteableWicBitmapImpl.cs} | 4 ++-- tests/Avalonia.RenderTests/Media/BitmapTests.cs | 10 +++++----- .../Avalonia.UnitTests/MockPlatformRenderInterface.cs | 2 +- .../VisualTree/MockRenderInterface.cs | 2 +- 11 files changed, 25 insertions(+), 25 deletions(-) rename src/Avalonia.Visuals/Media/Imaging/{WritableBitmap.cs => WriteableBitmap.cs} (51%) rename src/Avalonia.Visuals/Platform/{IWritableBitmapImpl.cs => IWriteableBitmapImpl.cs} (75%) rename src/Windows/Avalonia.Direct2D1/Media/Imaging/{WritableWicBitmapImpl.cs => WriteableWicBitmapImpl.cs} (86%) diff --git a/src/Avalonia.Controls/Remote/RemoteWidget.cs b/src/Avalonia.Controls/Remote/RemoteWidget.cs index 83360a0010..ea8c3ebe52 100644 --- a/src/Avalonia.Controls/Remote/RemoteWidget.cs +++ b/src/Avalonia.Controls/Remote/RemoteWidget.cs @@ -14,7 +14,7 @@ namespace Avalonia.Controls.Remote { private readonly IAvaloniaRemoteTransportConnection _connection; private FrameMessage _lastFrame; - private WritableBitmap _bitmap; + private WriteableBitmap _bitmap; public RemoteWidget(IAvaloniaRemoteTransportConnection connection) { _connection = connection; @@ -62,7 +62,7 @@ namespace Avalonia.Controls.Remote var fmt = (PixelFormat) _lastFrame.Format; if (_bitmap == null || _bitmap.PixelWidth != _lastFrame.Width || _bitmap.PixelHeight != _lastFrame.Height) - _bitmap = new WritableBitmap(_lastFrame.Width, _lastFrame.Height, fmt); + _bitmap = new WriteableBitmap(_lastFrame.Width, _lastFrame.Height, fmt); using (var l = _bitmap.Lock()) { var lineLen = (fmt == PixelFormat.Rgb565 ? 2 : 4) * _lastFrame.Width; diff --git a/src/Avalonia.Visuals/Media/Imaging/WritableBitmap.cs b/src/Avalonia.Visuals/Media/Imaging/WriteableBitmap.cs similarity index 51% rename from src/Avalonia.Visuals/Media/Imaging/WritableBitmap.cs rename to src/Avalonia.Visuals/Media/Imaging/WriteableBitmap.cs index df3e71dc85..af6fde6876 100644 --- a/src/Avalonia.Visuals/Media/Imaging/WritableBitmap.cs +++ b/src/Avalonia.Visuals/Media/Imaging/WriteableBitmap.cs @@ -9,15 +9,15 @@ using Avalonia.Utilities; namespace Avalonia.Media.Imaging { /// - /// Holds a writable bitmap image. + /// Holds a writeable bitmap image. /// - public class WritableBitmap : Bitmap + public class WriteableBitmap : Bitmap { - public WritableBitmap(int width, int height, PixelFormat? format = null) - : base(AvaloniaLocator.Current.GetService().CreateWritableBitmap(width, height, format)) + public WriteableBitmap(int width, int height, PixelFormat? format = null) + : base(AvaloniaLocator.Current.GetService().CreateWriteableBitmap(width, height, format)) { } - public ILockedFramebuffer Lock() => ((IWritableBitmapImpl) PlatformImpl.Item).Lock(); + public ILockedFramebuffer Lock() => ((IWriteableBitmapImpl) PlatformImpl.Item).Lock(); } } diff --git a/src/Avalonia.Visuals/Platform/IPlatformRenderInterface.cs b/src/Avalonia.Visuals/Platform/IPlatformRenderInterface.cs index aab8521f6d..cc17efd2bb 100644 --- a/src/Avalonia.Visuals/Platform/IPlatformRenderInterface.cs +++ b/src/Avalonia.Visuals/Platform/IPlatformRenderInterface.cs @@ -61,13 +61,13 @@ namespace Avalonia.Platform double dpiY); /// - /// Creates a writable bitmap implementation. + /// Creates a writeable bitmap implementation. /// /// The width of the bitmap. /// The height of the bitmap. /// Pixel format (optional). - /// An . - IWritableBitmapImpl CreateWritableBitmap(int width, int height, PixelFormat? format = null); + /// An . + IWriteableBitmapImpl CreateWriteableBitmap(int width, int height, PixelFormat? format = null); /// /// Loads a bitmap implementation from a file.. diff --git a/src/Avalonia.Visuals/Platform/IWritableBitmapImpl.cs b/src/Avalonia.Visuals/Platform/IWriteableBitmapImpl.cs similarity index 75% rename from src/Avalonia.Visuals/Platform/IWritableBitmapImpl.cs rename to src/Avalonia.Visuals/Platform/IWriteableBitmapImpl.cs index b736c11dab..7ab5a7c100 100644 --- a/src/Avalonia.Visuals/Platform/IWritableBitmapImpl.cs +++ b/src/Avalonia.Visuals/Platform/IWriteableBitmapImpl.cs @@ -7,9 +7,9 @@ using System.Threading.Tasks; namespace Avalonia.Platform { /// - /// Defines the platform-specific interface for a . + /// Defines the platform-specific interface for a . /// - public interface IWritableBitmapImpl : IBitmapImpl + public interface IWriteableBitmapImpl : IBitmapImpl { ILockedFramebuffer Lock(); } diff --git a/src/Skia/Avalonia.Skia/BitmapImpl.cs b/src/Skia/Avalonia.Skia/BitmapImpl.cs index 00ab770e01..ccc5a37105 100644 --- a/src/Skia/Avalonia.Skia/BitmapImpl.cs +++ b/src/Skia/Avalonia.Skia/BitmapImpl.cs @@ -6,7 +6,7 @@ using SkiaSharp; namespace Avalonia.Skia { - class BitmapImpl : IRenderTargetBitmapImpl, IWritableBitmapImpl + class BitmapImpl : IRenderTargetBitmapImpl, IWriteableBitmapImpl { private Vector _dpi; diff --git a/src/Skia/Avalonia.Skia/PlatformRenderInterface.cs b/src/Skia/Avalonia.Skia/PlatformRenderInterface.cs index bd3769e4a5..50e65f45dc 100644 --- a/src/Skia/Avalonia.Skia/PlatformRenderInterface.cs +++ b/src/Skia/Avalonia.Skia/PlatformRenderInterface.cs @@ -88,7 +88,7 @@ namespace Avalonia.Skia return new FramebufferRenderTarget(fb); } - public IWritableBitmapImpl CreateWritableBitmap(int width, int height, PixelFormat? format = null) + public IWriteableBitmapImpl CreateWriteableBitmap(int width, int height, PixelFormat? format = null) { return new BitmapImpl(width, height, new Vector(96, 96), format); } diff --git a/src/Windows/Avalonia.Direct2D1/Direct2D1Platform.cs b/src/Windows/Avalonia.Direct2D1/Direct2D1Platform.cs index a47c871f5a..296edcb2d9 100644 --- a/src/Windows/Avalonia.Direct2D1/Direct2D1Platform.cs +++ b/src/Windows/Avalonia.Direct2D1/Direct2D1Platform.cs @@ -168,9 +168,9 @@ namespace Avalonia.Direct2D1 dpiY); } - public IWritableBitmapImpl CreateWritableBitmap(int width, int height, PixelFormat? format = null) + public IWriteableBitmapImpl CreateWriteableBitmap(int width, int height, PixelFormat? format = null) { - return new WritableWicBitmapImpl(s_imagingFactory, width, height, format); + return new WriteableWicBitmapImpl(s_imagingFactory, width, height, format); } public IStreamGeometryImpl CreateStreamGeometry() diff --git a/src/Windows/Avalonia.Direct2D1/Media/Imaging/WritableWicBitmapImpl.cs b/src/Windows/Avalonia.Direct2D1/Media/Imaging/WriteableWicBitmapImpl.cs similarity index 86% rename from src/Windows/Avalonia.Direct2D1/Media/Imaging/WritableWicBitmapImpl.cs rename to src/Windows/Avalonia.Direct2D1/Media/Imaging/WriteableWicBitmapImpl.cs index 5dc07e06c4..fc931c32db 100644 --- a/src/Windows/Avalonia.Direct2D1/Media/Imaging/WritableWicBitmapImpl.cs +++ b/src/Windows/Avalonia.Direct2D1/Media/Imaging/WriteableWicBitmapImpl.cs @@ -9,9 +9,9 @@ using PixelFormat = Avalonia.Platform.PixelFormat; namespace Avalonia.Direct2D1.Media.Imaging { - class WritableWicBitmapImpl : WicBitmapImpl, IWritableBitmapImpl + class WriteableWicBitmapImpl : WicBitmapImpl, IWriteableBitmapImpl { - public WritableWicBitmapImpl(ImagingFactory factory, int width, int height, PixelFormat? pixelFormat) + public WriteableWicBitmapImpl(ImagingFactory factory, int width, int height, PixelFormat? pixelFormat) : base(factory, width, height, pixelFormat) { } diff --git a/tests/Avalonia.RenderTests/Media/BitmapTests.cs b/tests/Avalonia.RenderTests/Media/BitmapTests.cs index a7cd06a894..089579a0a0 100644 --- a/tests/Avalonia.RenderTests/Media/BitmapTests.cs +++ b/tests/Avalonia.RenderTests/Media/BitmapTests.cs @@ -106,9 +106,9 @@ namespace Avalonia.Direct2D1.RenderTests.Media [Theory] [InlineData(PixelFormat.Bgra8888), InlineData(PixelFormat.Rgba8888)] - public void WritableBitmapShouldBeUsable(PixelFormat fmt) + public void WriteableBitmapShouldBeUsable(PixelFormat fmt) { - var writableBitmap = new WritableBitmap(256, 256, fmt); + var writeableBitmap = new WriteableBitmap(256, 256, fmt); var data = new int[256 * 256]; for (int y = 0; y < 256; y++) @@ -116,7 +116,7 @@ namespace Avalonia.Direct2D1.RenderTests.Media data[y * 256 + x] =(int)((uint)(x + (y << 8)) | 0xFF000000u); - using (var l = writableBitmap.Lock()) + using (var l = writeableBitmap.Lock()) { for(var r = 0; r<256; r++) { @@ -125,9 +125,9 @@ namespace Avalonia.Direct2D1.RenderTests.Media } - var name = nameof(WritableBitmapShouldBeUsable) + "_" + fmt; + var name = nameof(WriteableBitmapShouldBeUsable) + "_" + fmt; - writableBitmap.Save(System.IO.Path.Combine(OutputPath, name + ".out.png")); + writeableBitmap.Save(System.IO.Path.Combine(OutputPath, name + ".out.png")); CompareImagesNoRenderer(name); } diff --git a/tests/Avalonia.UnitTests/MockPlatformRenderInterface.cs b/tests/Avalonia.UnitTests/MockPlatformRenderInterface.cs index 8c6c949e07..de2b517956 100644 --- a/tests/Avalonia.UnitTests/MockPlatformRenderInterface.cs +++ b/tests/Avalonia.UnitTests/MockPlatformRenderInterface.cs @@ -39,7 +39,7 @@ namespace Avalonia.UnitTests return new MockStreamGeometryImpl(); } - public IWritableBitmapImpl CreateWritableBitmap(int width, int height, PixelFormat? format = default(PixelFormat?)) + public IWriteableBitmapImpl CreateWriteableBitmap(int width, int height, PixelFormat? format = default(PixelFormat?)) { throw new NotImplementedException(); } diff --git a/tests/Avalonia.Visuals.UnitTests/VisualTree/MockRenderInterface.cs b/tests/Avalonia.Visuals.UnitTests/VisualTree/MockRenderInterface.cs index 54bb5d72d0..93b5a8a764 100644 --- a/tests/Avalonia.Visuals.UnitTests/VisualTree/MockRenderInterface.cs +++ b/tests/Avalonia.Visuals.UnitTests/VisualTree/MockRenderInterface.cs @@ -49,7 +49,7 @@ namespace Avalonia.Visuals.UnitTests.VisualTree throw new NotImplementedException(); } - public IWritableBitmapImpl CreateWritableBitmap(int width, int height, PixelFormat? fmt) + public IWriteableBitmapImpl CreateWriteableBitmap(int width, int height, PixelFormat? fmt) { throw new NotImplementedException(); } From c6a7611150f07a21aa52e3e8364502c93ca39393 Mon Sep 17 00:00:00 2001 From: ahopper Date: Thu, 8 Mar 2018 14:39:29 +0000 Subject: [PATCH 4/9] render test fixed --- ...eableBitmapShouldBeUsable_Bgra8888.expected.png} | Bin ...eableBitmapShouldBeUsable_Rgba8888.expected.png} | Bin 2 files changed, 0 insertions(+), 0 deletions(-) rename tests/TestFiles/Skia/Media/Bitmap/{WritableBitmapShouldBeUsable_Bgra8888.expected.png => WriteableBitmapShouldBeUsable_Bgra8888.expected.png} (100%) rename tests/TestFiles/Skia/Media/Bitmap/{WritableBitmapShouldBeUsable_Rgba8888.expected.png => WriteableBitmapShouldBeUsable_Rgba8888.expected.png} (100%) diff --git a/tests/TestFiles/Skia/Media/Bitmap/WritableBitmapShouldBeUsable_Bgra8888.expected.png b/tests/TestFiles/Skia/Media/Bitmap/WriteableBitmapShouldBeUsable_Bgra8888.expected.png similarity index 100% rename from tests/TestFiles/Skia/Media/Bitmap/WritableBitmapShouldBeUsable_Bgra8888.expected.png rename to tests/TestFiles/Skia/Media/Bitmap/WriteableBitmapShouldBeUsable_Bgra8888.expected.png diff --git a/tests/TestFiles/Skia/Media/Bitmap/WritableBitmapShouldBeUsable_Rgba8888.expected.png b/tests/TestFiles/Skia/Media/Bitmap/WriteableBitmapShouldBeUsable_Rgba8888.expected.png similarity index 100% rename from tests/TestFiles/Skia/Media/Bitmap/WritableBitmapShouldBeUsable_Rgba8888.expected.png rename to tests/TestFiles/Skia/Media/Bitmap/WriteableBitmapShouldBeUsable_Rgba8888.expected.png From c06ac12de709f7e337e78b29b0bced3478e4c4af Mon Sep 17 00:00:00 2001 From: ahopper Date: Thu, 8 Mar 2018 14:56:47 +0000 Subject: [PATCH 5/9] fix d2d render tests --- ...eableBitmapShouldBeUsable_Bgra8888.expected.png} | Bin ...eableBitmapShouldBeUsable_Rgba8888.expected.png} | Bin 2 files changed, 0 insertions(+), 0 deletions(-) rename tests/TestFiles/Direct2D1/Media/Bitmap/{WritableBitmapShouldBeUsable_Bgra8888.expected.png => WriteableBitmapShouldBeUsable_Bgra8888.expected.png} (100%) rename tests/TestFiles/Direct2D1/Media/Bitmap/{WritableBitmapShouldBeUsable_Rgba8888.expected.png => WriteableBitmapShouldBeUsable_Rgba8888.expected.png} (100%) diff --git a/tests/TestFiles/Direct2D1/Media/Bitmap/WritableBitmapShouldBeUsable_Bgra8888.expected.png b/tests/TestFiles/Direct2D1/Media/Bitmap/WriteableBitmapShouldBeUsable_Bgra8888.expected.png similarity index 100% rename from tests/TestFiles/Direct2D1/Media/Bitmap/WritableBitmapShouldBeUsable_Bgra8888.expected.png rename to tests/TestFiles/Direct2D1/Media/Bitmap/WriteableBitmapShouldBeUsable_Bgra8888.expected.png diff --git a/tests/TestFiles/Direct2D1/Media/Bitmap/WritableBitmapShouldBeUsable_Rgba8888.expected.png b/tests/TestFiles/Direct2D1/Media/Bitmap/WriteableBitmapShouldBeUsable_Rgba8888.expected.png similarity index 100% rename from tests/TestFiles/Direct2D1/Media/Bitmap/WritableBitmapShouldBeUsable_Rgba8888.expected.png rename to tests/TestFiles/Direct2D1/Media/Bitmap/WriteableBitmapShouldBeUsable_Rgba8888.expected.png From c2cecbb85a8436abd7a78f7a846178bb60ae258b Mon Sep 17 00:00:00 2001 From: dzhelnin Date: Fri, 9 Mar 2018 19:28:46 +0300 Subject: [PATCH 6/9] ButtonSpinner control is ported from ExtendedWFPToolkit --- samples/ControlCatalog/ControlCatalog.csproj | 6 + samples/ControlCatalog/MainView.xaml | 1 + .../Pages/ButtonSpinnerPage.xaml | 19 ++ .../Pages/ButtonSpinnerPage.xaml.cs | 54 ++++ src/Avalonia.Controls/ButtonSpinner.cs | 235 ++++++++++++++++++ src/Avalonia.Controls/Spinner.cs | 174 +++++++++++++ .../ButtonSpinner.xaml | 54 ++++ src/Avalonia.Themes.Default/DefaultTheme.xaml | 1 + 8 files changed, 544 insertions(+) create mode 100644 samples/ControlCatalog/Pages/ButtonSpinnerPage.xaml create mode 100644 samples/ControlCatalog/Pages/ButtonSpinnerPage.xaml.cs create mode 100644 src/Avalonia.Controls/ButtonSpinner.cs create mode 100644 src/Avalonia.Controls/Spinner.cs create mode 100644 src/Avalonia.Themes.Default/ButtonSpinner.xaml diff --git a/samples/ControlCatalog/ControlCatalog.csproj b/samples/ControlCatalog/ControlCatalog.csproj index 37f9da0c43..a3d7a0cdce 100644 --- a/samples/ControlCatalog/ControlCatalog.csproj +++ b/samples/ControlCatalog/ControlCatalog.csproj @@ -35,6 +35,9 @@ Designer + + Designer + Designer @@ -164,6 +167,9 @@ ToolTipPage.xaml + + ButtonSpinnerPage.xaml + diff --git a/samples/ControlCatalog/MainView.xaml b/samples/ControlCatalog/MainView.xaml index 060369e404..142d0d42b1 100644 --- a/samples/ControlCatalog/MainView.xaml +++ b/samples/ControlCatalog/MainView.xaml @@ -7,6 +7,7 @@ + diff --git a/samples/ControlCatalog/Pages/ButtonSpinnerPage.xaml b/samples/ControlCatalog/Pages/ButtonSpinnerPage.xaml new file mode 100644 index 0000000000..760760e3f4 --- /dev/null +++ b/samples/ControlCatalog/Pages/ButtonSpinnerPage.xaml @@ -0,0 +1,19 @@ + + + + ButtonSpinner + The ButtonSpinner control allows you to add button spinners to any element and then respond to the Spin event to manipulate that element. + + + AllowSpin + ShowButtonSpinner + + + + + + + \ No newline at end of file diff --git a/samples/ControlCatalog/Pages/ButtonSpinnerPage.xaml.cs b/samples/ControlCatalog/Pages/ButtonSpinnerPage.xaml.cs new file mode 100644 index 0000000000..1f753ab3ea --- /dev/null +++ b/samples/ControlCatalog/Pages/ButtonSpinnerPage.xaml.cs @@ -0,0 +1,54 @@ +using System; +using Avalonia; +using Avalonia.Controls; +using Avalonia.Interactivity; +using Avalonia.Markup.Xaml; + +namespace ControlCatalog.Pages +{ + public class ButtonSpinnerPage : UserControl + { + public ButtonSpinnerPage() + { + this.InitializeComponent(); + } + + private void InitializeComponent() + { + AvaloniaXamlLoader.Load(this); + } + + private void OnSpin(object sender, SpinEventArgs e) + { + var spinner = (ButtonSpinner)sender; + var txtBox = (TextBlock)spinner.Content; + + int value = Array.IndexOf(_mountains, txtBox.Text); + if (e.Direction == SpinDirection.Increase) + value++; + else + value--; + + if (value < 0) + value = _mountains.Length - 1; + else if (value >= _mountains.Length) + value = 0; + + txtBox.Text = _mountains[value]; + } + + private readonly string[] _mountains = new[] + { + "Everest", + "K2 (Mount Godwin Austen)", + "Kangchenjunga", + "Lhotse", + "Makalu", + "Cho Oyu", + "Dhaulagiri", + "Manaslu", + "Nanga Parbat", + "Annapurna" + }; + } +} diff --git a/src/Avalonia.Controls/ButtonSpinner.cs b/src/Avalonia.Controls/ButtonSpinner.cs new file mode 100644 index 0000000000..c7b31a8c6c --- /dev/null +++ b/src/Avalonia.Controls/ButtonSpinner.cs @@ -0,0 +1,235 @@ +using System; +using Avalonia.Controls.Primitives; +using Avalonia.Input; +using Avalonia.Interactivity; + +namespace Avalonia.Controls +{ + /// + /// Represents a spinner control that includes two Buttons. + /// + public class ButtonSpinner : Spinner + { + /// + /// Defines the property. + /// + public static readonly StyledProperty AllowSpinProperty = + AvaloniaProperty.Register(nameof(AllowSpin), true); + + /// + /// Defines the property. + /// + public static readonly StyledProperty ShowButtonSpinnerProperty = + AvaloniaProperty.Register(nameof(ShowButtonSpinner), true); + + private Button _decreaseButton; + /// + /// Gets or sets the DecreaseButton template part. + /// + private Button DecreaseButton + { + get { return _decreaseButton; } + set + { + if (_decreaseButton != null) + { + _decreaseButton.Click -= OnButtonClick; + } + _decreaseButton = value; + if (_decreaseButton != null) + { + _decreaseButton.Click += OnButtonClick; + } + } + } + + private Button _increaseButton; + /// + /// Gets or sets the IncreaseButton template part. + /// + private Button IncreaseButton + { + get + { + return _increaseButton; + } + set + { + if (_increaseButton != null) + { + _increaseButton.Click -= OnButtonClick; + } + _increaseButton = value; + if (_increaseButton != null) + { + _increaseButton.Click += OnButtonClick; + } + } + } + + /// + /// Initializes static members of the class. + /// + static ButtonSpinner() + { + AllowSpinProperty.Changed.Subscribe(AllowSpinChanged); + } + + /// + /// Gets or sets a value indicating whether the should allow to spin. + /// + public bool AllowSpin + { + get { return GetValue(AllowSpinProperty); } + set { SetValue(AllowSpinProperty, value); } + } + + /// + /// Gets or sets a value indicating whether the spin buttons should be shown. + /// + public bool ShowButtonSpinner + { + get { return GetValue(ShowButtonSpinnerProperty); } + set { SetValue(ShowButtonSpinnerProperty, value); } + } + + /// + protected override void OnTemplateApplied(TemplateAppliedEventArgs e) + { + IncreaseButton = e.NameScope.Find