From d55edaa18a2791ff024491f25820022c1d1a8531 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Tue, 5 Dec 2017 10:16:35 +0100 Subject: [PATCH 01/19] Use readonly structs where possible. C# 7.2 introduced [readonly structs](https://docs.microsoft.com/en-us/dotnet/csharp/reference-semantics-with-value-types). Using this construct we can make sure that future modifications to these structs don't make them immutable and C# can generate more efficient code. --- src/Avalonia.Visuals/Avalonia.Visuals.csproj | 1 + src/Avalonia.Visuals/Matrix.cs | 2 +- src/Avalonia.Visuals/Media/Color.cs | 2 +- src/Avalonia.Visuals/Media/DrawingContext.cs | 4 ++-- .../Media/Immutable/ImmutableSolidColorBrush.cs | 2 +- src/Avalonia.Visuals/Point.cs | 2 +- src/Avalonia.Visuals/Rect.cs | 2 +- src/Avalonia.Visuals/RelativePoint.cs | 4 ++-- src/Avalonia.Visuals/RelativeRect.cs | 2 +- .../Rendering/SceneGraph/DeferredDrawingContextImpl.cs | 2 +- src/Avalonia.Visuals/Size.cs | 2 +- src/Avalonia.Visuals/Thickness.cs | 2 +- src/Avalonia.Visuals/Vector.cs | 2 +- src/Avalonia.Visuals/VisualTree/TransformedBounds.cs | 2 +- src/Shared/RenderHelpers/ArcToHelper.cs | 2 +- src/Skia/Avalonia.Skia/Avalonia.Skia.csproj | 3 ++- src/Windows/Avalonia.Direct2D1/Avalonia.Direct2D1.csproj | 1 + src/Windows/Avalonia.Direct2D1/OptionalDispose.cs | 2 +- 18 files changed, 21 insertions(+), 18 deletions(-) diff --git a/src/Avalonia.Visuals/Avalonia.Visuals.csproj b/src/Avalonia.Visuals/Avalonia.Visuals.csproj index fe18b0e446..180466d7a8 100644 --- a/src/Avalonia.Visuals/Avalonia.Visuals.csproj +++ b/src/Avalonia.Visuals/Avalonia.Visuals.csproj @@ -3,6 +3,7 @@ netstandard2.0 false Avalonia + latest true diff --git a/src/Avalonia.Visuals/Matrix.cs b/src/Avalonia.Visuals/Matrix.cs index 10549b967d..3ed0287cd1 100644 --- a/src/Avalonia.Visuals/Matrix.cs +++ b/src/Avalonia.Visuals/Matrix.cs @@ -10,7 +10,7 @@ namespace Avalonia /// /// A 2x3 matrix. /// - public struct Matrix + public readonly struct Matrix { private readonly double _m11; private readonly double _m12; diff --git a/src/Avalonia.Visuals/Media/Color.cs b/src/Avalonia.Visuals/Media/Color.cs index cbf5a86fd6..d0a8fb17f8 100644 --- a/src/Avalonia.Visuals/Media/Color.cs +++ b/src/Avalonia.Visuals/Media/Color.cs @@ -11,7 +11,7 @@ namespace Avalonia.Media /// /// An ARGB color. /// - public struct Color + public readonly struct Color { /// /// Gets or sets the Alpha component of the color. diff --git a/src/Avalonia.Visuals/Media/DrawingContext.cs b/src/Avalonia.Visuals/Media/DrawingContext.cs index 1aa3fd21de..1d25224b8d 100644 --- a/src/Avalonia.Visuals/Media/DrawingContext.cs +++ b/src/Avalonia.Visuals/Media/DrawingContext.cs @@ -19,7 +19,7 @@ namespace Avalonia.Media ? new Stack() : TransformStackPool.Pop(); - struct TransformContainer + readonly struct TransformContainer { public readonly Matrix LocalTransform; public readonly Matrix ContainerTransform; @@ -147,7 +147,7 @@ namespace Avalonia.Media } } - public struct PushedState : IDisposable + public readonly struct PushedState : IDisposable { private readonly int _level; private readonly DrawingContext _context; diff --git a/src/Avalonia.Visuals/Media/Immutable/ImmutableSolidColorBrush.cs b/src/Avalonia.Visuals/Media/Immutable/ImmutableSolidColorBrush.cs index 015486c6a4..b55ca251a6 100644 --- a/src/Avalonia.Visuals/Media/Immutable/ImmutableSolidColorBrush.cs +++ b/src/Avalonia.Visuals/Media/Immutable/ImmutableSolidColorBrush.cs @@ -6,7 +6,7 @@ namespace Avalonia.Media.Immutable /// /// Fills an area with a solid color. /// - public struct ImmutableSolidColorBrush : ISolidColorBrush + public readonly struct ImmutableSolidColorBrush : ISolidColorBrush { /// /// Initializes a new instance of the class. diff --git a/src/Avalonia.Visuals/Point.cs b/src/Avalonia.Visuals/Point.cs index 5fbd082967..c1edd9eb42 100644 --- a/src/Avalonia.Visuals/Point.cs +++ b/src/Avalonia.Visuals/Point.cs @@ -10,7 +10,7 @@ namespace Avalonia /// /// Defines a point. /// - public struct Point + public readonly struct Point { /// /// The X position. diff --git a/src/Avalonia.Visuals/Rect.cs b/src/Avalonia.Visuals/Rect.cs index d562429fc7..cdf1ee98f7 100644 --- a/src/Avalonia.Visuals/Rect.cs +++ b/src/Avalonia.Visuals/Rect.cs @@ -10,7 +10,7 @@ namespace Avalonia /// /// Defines a rectangle. /// - public struct Rect + public readonly struct Rect { /// /// An empty rectangle. diff --git a/src/Avalonia.Visuals/RelativePoint.cs b/src/Avalonia.Visuals/RelativePoint.cs index cc34feb5f3..1b84f93166 100644 --- a/src/Avalonia.Visuals/RelativePoint.cs +++ b/src/Avalonia.Visuals/RelativePoint.cs @@ -27,7 +27,7 @@ namespace Avalonia /// /// Defines a point that may be defined relative to a containing element. /// - public struct RelativePoint : IEquatable + public readonly struct RelativePoint : IEquatable { /// /// A point at the top left of the containing element. @@ -44,7 +44,7 @@ namespace Avalonia /// public static readonly RelativePoint BottomRight = new RelativePoint(1, 1, RelativeUnit.Relative); - private Point _point; + private readonly Point _point; private readonly RelativeUnit _unit; diff --git a/src/Avalonia.Visuals/RelativeRect.cs b/src/Avalonia.Visuals/RelativeRect.cs index a11f080e94..33a9fb8b15 100644 --- a/src/Avalonia.Visuals/RelativeRect.cs +++ b/src/Avalonia.Visuals/RelativeRect.cs @@ -10,7 +10,7 @@ namespace Avalonia /// /// Defines a rectangle that may be defined relative to a containing element. /// - public struct RelativeRect : IEquatable + public readonly struct RelativeRect : IEquatable { /// /// A rectangle that represents 100% of an area. diff --git a/src/Avalonia.Visuals/Rendering/SceneGraph/DeferredDrawingContextImpl.cs b/src/Avalonia.Visuals/Rendering/SceneGraph/DeferredDrawingContextImpl.cs index 29c482c336..7af1420bbe 100644 --- a/src/Avalonia.Visuals/Rendering/SceneGraph/DeferredDrawingContextImpl.cs +++ b/src/Avalonia.Visuals/Rendering/SceneGraph/DeferredDrawingContextImpl.cs @@ -319,7 +319,7 @@ namespace Avalonia.Rendering.SceneGraph } } - public struct UpdateState : IDisposable + public readonly struct UpdateState : IDisposable { public UpdateState( DeferredDrawingContextImpl owner, diff --git a/src/Avalonia.Visuals/Size.cs b/src/Avalonia.Visuals/Size.cs index 6ad87c6120..5045f9a837 100644 --- a/src/Avalonia.Visuals/Size.cs +++ b/src/Avalonia.Visuals/Size.cs @@ -10,7 +10,7 @@ namespace Avalonia /// /// Defines a size. /// - public struct Size + public readonly struct Size { /// /// A size representing infinity. diff --git a/src/Avalonia.Visuals/Thickness.cs b/src/Avalonia.Visuals/Thickness.cs index dc9be7341d..10d5f76915 100644 --- a/src/Avalonia.Visuals/Thickness.cs +++ b/src/Avalonia.Visuals/Thickness.cs @@ -10,7 +10,7 @@ namespace Avalonia /// /// Describes the thickness of a frame around a rectangle. /// - public struct Thickness + public readonly struct Thickness { /// /// The thickness on the left. diff --git a/src/Avalonia.Visuals/Vector.cs b/src/Avalonia.Visuals/Vector.cs index c4545b8e5c..acde49a84a 100644 --- a/src/Avalonia.Visuals/Vector.cs +++ b/src/Avalonia.Visuals/Vector.cs @@ -10,7 +10,7 @@ namespace Avalonia /// /// Defines a vector. /// - public struct Vector + public readonly struct Vector { /// /// The X vector. diff --git a/src/Avalonia.Visuals/VisualTree/TransformedBounds.cs b/src/Avalonia.Visuals/VisualTree/TransformedBounds.cs index 4c548669bd..5723331500 100644 --- a/src/Avalonia.Visuals/VisualTree/TransformedBounds.cs +++ b/src/Avalonia.Visuals/VisualTree/TransformedBounds.cs @@ -8,7 +8,7 @@ namespace Avalonia.VisualTree /// /// Holds information about the bounds of a control, together with a transform and a clip. /// - public struct TransformedBounds + public readonly struct TransformedBounds { /// /// Initializes a new instance of the struct. diff --git a/src/Shared/RenderHelpers/ArcToHelper.cs b/src/Shared/RenderHelpers/ArcToHelper.cs index 9da47909cb..2457606f9d 100644 --- a/src/Shared/RenderHelpers/ArcToHelper.cs +++ b/src/Shared/RenderHelpers/ArcToHelper.cs @@ -982,7 +982,7 @@ namespace Avalonia.RenderHelpers /// At some point I did not trust the WPF Matrix struct, and wrote my own simple one -_- /// This is supposed to be replaced with proper WPF Matrices everywhere /// - private struct SimpleMatrix + private readonly struct SimpleMatrix { private readonly double _a, _b, _c, _d; diff --git a/src/Skia/Avalonia.Skia/Avalonia.Skia.csproj b/src/Skia/Avalonia.Skia/Avalonia.Skia.csproj index f5ed89d154..cd27bda607 100644 --- a/src/Skia/Avalonia.Skia/Avalonia.Skia.csproj +++ b/src/Skia/Avalonia.Skia/Avalonia.Skia.csproj @@ -5,7 +5,8 @@ Avalonia.Skia Avalonia.Skia true - true + latest + true diff --git a/src/Windows/Avalonia.Direct2D1/Avalonia.Direct2D1.csproj b/src/Windows/Avalonia.Direct2D1/Avalonia.Direct2D1.csproj index a84c373886..9fac027fd0 100644 --- a/src/Windows/Avalonia.Direct2D1/Avalonia.Direct2D1.csproj +++ b/src/Windows/Avalonia.Direct2D1/Avalonia.Direct2D1.csproj @@ -2,6 +2,7 @@ netstandard2.0 false + latest diff --git a/src/Windows/Avalonia.Direct2D1/OptionalDispose.cs b/src/Windows/Avalonia.Direct2D1/OptionalDispose.cs index cd3eee8d25..e302e71102 100644 --- a/src/Windows/Avalonia.Direct2D1/OptionalDispose.cs +++ b/src/Windows/Avalonia.Direct2D1/OptionalDispose.cs @@ -2,7 +2,7 @@ namespace Avalonia.Direct2D1 { - public struct OptionalDispose : IDisposable where T : IDisposable + public readonly struct OptionalDispose : IDisposable where T : IDisposable { private readonly bool _dispose; From 86f2d45d2b13b574cf2cad64cf8e5d39bfdab314 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Tue, 5 Dec 2017 12:35:28 +0100 Subject: [PATCH 02/19] Use current VS2017 image. --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index ba3680d0b9..76d1ae3e1c 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -os: Previous Visual Studio 2017 +os: Visual Studio 2017 platform: - Any CPU skip_branch_with_pr: true From 2bd00bff491a5c3e508a0288be9f089fab4ec76e Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 3 May 2018 22:07:41 +0100 Subject: [PATCH 03/19] Add a PasswordBox control. --- samples/ControlCatalog/Pages/TextBoxPage.xaml | 7 +- src/Avalonia.Controls/PasswordBox.cs | 47 ++++++++++++++ src/Avalonia.Themes.Default/PasswordBox.xaml | 64 +++++++++++++++++++ 3 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 src/Avalonia.Controls/PasswordBox.cs create mode 100644 src/Avalonia.Themes.Default/PasswordBox.xaml diff --git a/samples/ControlCatalog/Pages/TextBoxPage.xaml b/samples/ControlCatalog/Pages/TextBoxPage.xaml index 7bfcad6d51..87fb1f0b4e 100644 --- a/samples/ControlCatalog/Pages/TextBoxPage.xaml +++ b/samples/ControlCatalog/Pages/TextBoxPage.xaml @@ -14,9 +14,14 @@ Watermark="Floating Watermark" UseFloatingWatermark="True" Text="Lorem ipsum dolor sit amet, consectetur adipiscing elit."/> + + - + diff --git a/src/Avalonia.Controls/PasswordBox.cs b/src/Avalonia.Controls/PasswordBox.cs new file mode 100644 index 0000000000..a7dd03445a --- /dev/null +++ b/src/Avalonia.Controls/PasswordBox.cs @@ -0,0 +1,47 @@ +using Avalonia.Controls.Primitives; +using Avalonia.Styling; +using System; + +namespace Avalonia.Controls +{ + public class PasswordBox : TextBox, IStyleable + { + Type IStyleable.StyleKey => typeof(PasswordBox); + + public PasswordBox() + { + this.GetObservable(TextProperty).Subscribe(text => + { + if (text != null) + { + DisplayText = new string(PasswordChar, text.Length); + } + else + { + DisplayText = null; + } + }); + } + + public static readonly StyledProperty PasswordCharProperty = AvaloniaProperty.Register(nameof(PasswordChar), '*'); + + public char PasswordChar + { + get => GetValue(PasswordCharProperty); + set => SetValue(PasswordCharProperty, value); + } + + public static readonly StyledProperty DisplayTextProperty = AvaloniaProperty.Register(nameof(DisplayText)); + + public string DisplayText + { + get => GetValue(DisplayTextProperty); + set => SetValue(DisplayTextProperty, value); + } + + protected override void OnTemplateApplied(TemplateAppliedEventArgs e) + { + base.OnTemplateApplied(e); + } + } +} diff --git a/src/Avalonia.Themes.Default/PasswordBox.xaml b/src/Avalonia.Themes.Default/PasswordBox.xaml new file mode 100644 index 0000000000..4297a69bab --- /dev/null +++ b/src/Avalonia.Themes.Default/PasswordBox.xaml @@ -0,0 +1,64 @@ + + + + + + \ No newline at end of file From aca0fb3eba886449f0f381dcf94b0e0f99411c2e Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 3 May 2018 22:37:53 +0100 Subject: [PATCH 04/19] Implement password char on TextBox rather than separate control. --- samples/ControlCatalog/Pages/TextBoxPage.xaml | 3 +- src/Avalonia.Controls/PasswordBox.cs | 47 -------------- src/Avalonia.Controls/TextBox.cs | 40 ++++++++++-- src/Avalonia.Themes.Default/PasswordBox.xaml | 64 ------------------- src/Avalonia.Themes.Default/TextBox.xaml | 4 +- 5 files changed, 39 insertions(+), 119 deletions(-) delete mode 100644 src/Avalonia.Controls/PasswordBox.cs delete mode 100644 src/Avalonia.Themes.Default/PasswordBox.xaml diff --git a/samples/ControlCatalog/Pages/TextBoxPage.xaml b/samples/ControlCatalog/Pages/TextBoxPage.xaml index 87fb1f0b4e..96b534fc58 100644 --- a/samples/ControlCatalog/Pages/TextBoxPage.xaml +++ b/samples/ControlCatalog/Pages/TextBoxPage.xaml @@ -15,9 +15,10 @@ UseFloatingWatermark="True" Text="Lorem ipsum dolor sit amet, consectetur adipiscing elit."/> - diff --git a/src/Avalonia.Controls/PasswordBox.cs b/src/Avalonia.Controls/PasswordBox.cs deleted file mode 100644 index a7dd03445a..0000000000 --- a/src/Avalonia.Controls/PasswordBox.cs +++ /dev/null @@ -1,47 +0,0 @@ -using Avalonia.Controls.Primitives; -using Avalonia.Styling; -using System; - -namespace Avalonia.Controls -{ - public class PasswordBox : TextBox, IStyleable - { - Type IStyleable.StyleKey => typeof(PasswordBox); - - public PasswordBox() - { - this.GetObservable(TextProperty).Subscribe(text => - { - if (text != null) - { - DisplayText = new string(PasswordChar, text.Length); - } - else - { - DisplayText = null; - } - }); - } - - public static readonly StyledProperty PasswordCharProperty = AvaloniaProperty.Register(nameof(PasswordChar), '*'); - - public char PasswordChar - { - get => GetValue(PasswordCharProperty); - set => SetValue(PasswordCharProperty, value); - } - - public static readonly StyledProperty DisplayTextProperty = AvaloniaProperty.Register(nameof(DisplayText)); - - public string DisplayText - { - get => GetValue(DisplayTextProperty); - set => SetValue(DisplayTextProperty, value); - } - - protected override void OnTemplateApplied(TemplateAppliedEventArgs e) - { - base.OnTemplateApplied(e); - } - } -} diff --git a/src/Avalonia.Controls/TextBox.cs b/src/Avalonia.Controls/TextBox.cs index 890926db54..a0096ef7ae 100644 --- a/src/Avalonia.Controls/TextBox.cs +++ b/src/Avalonia.Controls/TextBox.cs @@ -30,7 +30,10 @@ namespace Avalonia.Controls nameof(CaretIndex), o => o.CaretIndex, (o, v) => o.CaretIndex = v); - + + public static readonly StyledProperty PasswordCharProperty = + AvaloniaProperty.Register(nameof(PasswordChar)); + public static readonly StyledProperty IsReadOnlyProperty = AvaloniaProperty.Register(nameof(IsReadOnly)); @@ -53,6 +56,9 @@ namespace Avalonia.Controls defaultBindingMode: BindingMode.TwoWay, enableDataValidation: true); + public static readonly StyledProperty DisplayTextProperty = + AvaloniaProperty.Register(nameof(DisplayText)); + public static readonly StyledProperty TextAlignmentProperty = TextBlock.TextAlignmentProperty.AddOwner(); @@ -78,7 +84,7 @@ namespace Avalonia.Controls public bool Equals(UndoRedoState other) => ReferenceEquals(Text, other.Text) || Equals(Text, other.Text); } - + private string _text; private int _caretIndex; private int _selectionStart; @@ -117,6 +123,18 @@ namespace Avalonia.Controls horizontalScrollBarVisibility, BindingPriority.Style); _undoRedoHelper = new UndoRedoHelper(this); + + this.GetObservable(TextProperty).Subscribe(text => + { + if (PasswordChar != default(char)) + { + DisplayText = new string(PasswordChar, text.Length); + } + else + { + DisplayText = Text; + } + }); } public bool AcceptsReturn @@ -147,7 +165,13 @@ namespace Avalonia.Controls _undoRedoHelper.UpdateLastState(); } } - + + public char PasswordChar + { + get => GetValue(PasswordCharProperty); + set => SetValue(PasswordCharProperty, value); + } + public bool IsReadOnly { get { return GetValue(IsReadOnlyProperty); } @@ -208,6 +232,12 @@ namespace Avalonia.Controls } } + public string DisplayText + { + get => GetValue(DisplayTextProperty); + set => SetValue(DisplayTextProperty, value); + } + public TextAlignment TextAlignment { get { return GetValue(TextAlignmentProperty); } @@ -832,9 +862,9 @@ namespace Avalonia.Controls private void SetTextInternal(string value) { try - { + { _ignoreTextChanges = true; - SetAndRaise(TextProperty, ref _text, value); + SetAndRaise(TextProperty, ref _text, value); } finally { diff --git a/src/Avalonia.Themes.Default/PasswordBox.xaml b/src/Avalonia.Themes.Default/PasswordBox.xaml deleted file mode 100644 index 4297a69bab..0000000000 --- a/src/Avalonia.Themes.Default/PasswordBox.xaml +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/src/Avalonia.Themes.Default/TextBox.xaml b/src/Avalonia.Themes.Default/TextBox.xaml index e228aebf58..52e98b0c57 100644 --- a/src/Avalonia.Themes.Default/TextBox.xaml +++ b/src/Avalonia.Themes.Default/TextBox.xaml @@ -38,12 +38,12 @@ Text="{TemplateBinding Watermark}" IsVisible="{TemplateBinding Path=Text, Converter={x:Static StringConverters.NullOrEmpty}}"/> + TextWrapping="{TemplateBinding TextWrapping}"/> From a9747e0bd67ce574996feece816c3645faac5292 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 3 May 2018 22:40:22 +0100 Subject: [PATCH 05/19] whitespace. --- samples/ControlCatalog/Pages/TextBoxPage.xaml | 6 +++--- src/Avalonia.Controls/TextBox.cs | 14 +++++++------- src/Avalonia.Themes.Default/TextBox.xaml | 6 +++--- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/samples/ControlCatalog/Pages/TextBoxPage.xaml b/samples/ControlCatalog/Pages/TextBoxPage.xaml index 96b534fc58..db1c9cb69d 100644 --- a/samples/ControlCatalog/Pages/TextBoxPage.xaml +++ b/samples/ControlCatalog/Pages/TextBoxPage.xaml @@ -10,8 +10,8 @@ - @@ -22,7 +22,7 @@ Text="Password" /> - + diff --git a/src/Avalonia.Controls/TextBox.cs b/src/Avalonia.Controls/TextBox.cs index a0096ef7ae..78ef532a26 100644 --- a/src/Avalonia.Controls/TextBox.cs +++ b/src/Avalonia.Controls/TextBox.cs @@ -32,7 +32,7 @@ namespace Avalonia.Controls (o, v) => o.CaretIndex = v); public static readonly StyledProperty PasswordCharProperty = - AvaloniaProperty.Register(nameof(PasswordChar)); + AvaloniaProperty.Register(nameof(PasswordChar)); public static readonly StyledProperty IsReadOnlyProperty = AvaloniaProperty.Register(nameof(IsReadOnly)); @@ -84,7 +84,7 @@ namespace Avalonia.Controls public bool Equals(UndoRedoState other) => ReferenceEquals(Text, other.Text) || Equals(Text, other.Text); } - + private string _text; private int _caretIndex; private int _selectionStart; @@ -93,7 +93,7 @@ namespace Avalonia.Controls private UndoRedoHelper _undoRedoHelper; private bool _isUndoingRedoing; private bool _ignoreTextChanges; - private static readonly string[] invalidCharacters = new String[1]{"\u007f"}; + private static readonly string[] invalidCharacters = new String[1] { "\u007f" }; static TextBox() { @@ -267,7 +267,7 @@ namespace Avalonia.Controls _presenter = e.NameScope.Get("PART_TextPresenter"); _presenter.Cursor = new Cursor(StandardCursorType.Ibeam); - if(IsFocused) + if (IsFocused) { _presenter.ShowCaret(); } @@ -608,7 +608,7 @@ namespace Avalonia.Controls DataValidationErrors.SetError(this, status.Error); } } - + private int CoerceCaretIndex(int value) => CoerceCaretIndex(value, Text?.Length ?? 0); private int CoerceCaretIndex(int value, int length) @@ -862,9 +862,9 @@ namespace Avalonia.Controls private void SetTextInternal(string value) { try - { + { _ignoreTextChanges = true; - SetAndRaise(TextProperty, ref _text, value); + SetAndRaise(TextProperty, ref _text, value); } finally { diff --git a/src/Avalonia.Themes.Default/TextBox.xaml b/src/Avalonia.Themes.Default/TextBox.xaml index 52e98b0c57..89c445eac5 100644 --- a/src/Avalonia.Themes.Default/TextBox.xaml +++ b/src/Avalonia.Themes.Default/TextBox.xaml @@ -11,7 +11,7 @@ BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"> - + - + + TextWrapping="{TemplateBinding TextWrapping}"/> From d1200e1e4727baa1232e05749d64252d14952bcf Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 3 May 2018 22:43:18 +0100 Subject: [PATCH 06/19] protect against copy and cut. --- src/Avalonia.Controls/TextBox.cs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/Avalonia.Controls/TextBox.cs b/src/Avalonia.Controls/TextBox.cs index 78ef532a26..df68a01722 100644 --- a/src/Avalonia.Controls/TextBox.cs +++ b/src/Avalonia.Controls/TextBox.cs @@ -126,7 +126,7 @@ namespace Avalonia.Controls this.GetObservable(TextProperty).Subscribe(text => { - if (PasswordChar != default(char)) + if (IsPasswordBox) { DisplayText = new string(PasswordChar, text.Length); } @@ -345,7 +345,7 @@ namespace Avalonia.Controls private async void Copy() { await ((IClipboard)AvaloniaLocator.Current.GetService(typeof(IClipboard))) - .SetTextAsync(GetSelection()); + .SetTextAsync(GetSelection()); } private async void Paste() @@ -379,7 +379,10 @@ namespace Avalonia.Controls case Key.C: if (modifiers == InputModifiers.Control) { - Copy(); + if (!IsPasswordBox) + { + Copy(); + } handled = true; } break; @@ -387,8 +390,11 @@ namespace Avalonia.Controls case Key.X: if (modifiers == InputModifiers.Control) { - Copy(); - DeleteSelection(); + if (!IsPasswordBox) + { + Copy(); + DeleteSelection(); + } handled = true; } break; @@ -886,6 +892,8 @@ namespace Avalonia.Controls SelectionEnd = CaretIndex; } + private bool IsPasswordBox => PasswordChar != default(char); + UndoRedoState UndoRedoHelper.IUndoRedoHost.UndoRedoState { get { return new UndoRedoState(Text, CaretIndex); } From a4221ad809296d41c79d9d1f1832c9e2a12a763a Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 3 May 2018 22:45:22 +0100 Subject: [PATCH 07/19] whitespace. --- src/Avalonia.Controls/TextBox.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Avalonia.Controls/TextBox.cs b/src/Avalonia.Controls/TextBox.cs index df68a01722..b09c380faa 100644 --- a/src/Avalonia.Controls/TextBox.cs +++ b/src/Avalonia.Controls/TextBox.cs @@ -345,7 +345,7 @@ namespace Avalonia.Controls private async void Copy() { await ((IClipboard)AvaloniaLocator.Current.GetService(typeof(IClipboard))) - .SetTextAsync(GetSelection()); + .SetTextAsync(GetSelection()); } private async void Paste() From 2af15cbee471984b75df9e64912cf14abb321963 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Pedro?= Date: Wed, 4 Oct 2017 23:15:54 +0100 Subject: [PATCH 08/19] Make WindowState bindable. Requested changes. --- src/Avalonia.Controls/Platform/IWindowImpl.cs | 5 ++++ src/Avalonia.Controls/Window.cs | 26 ++++++++++++------- .../Remote/PreviewerWindowImpl.cs | 1 + src/Avalonia.DesignerSupport/Remote/Stubs.cs | 1 + src/Gtk/Avalonia.Gtk3/WindowBaseImpl.cs | 2 +- src/Gtk/Avalonia.Gtk3/WindowImpl.cs | 24 ++++++++++++++--- src/OSX/Avalonia.MonoMac/WindowImpl.cs | 16 ++++++++++++ src/Windows/Avalonia.Win32/WindowImpl.cs | 19 ++++++++++++-- 8 files changed, 79 insertions(+), 15 deletions(-) diff --git a/src/Avalonia.Controls/Platform/IWindowImpl.cs b/src/Avalonia.Controls/Platform/IWindowImpl.cs index 3f2c977718..f1f3925133 100644 --- a/src/Avalonia.Controls/Platform/IWindowImpl.cs +++ b/src/Avalonia.Controls/Platform/IWindowImpl.cs @@ -16,6 +16,11 @@ namespace Avalonia.Platform /// WindowState WindowState { get; set; } + /// + /// Gets or sets a method called when the minimized/maximized state of the window changes. + /// + Action WindowStateChanged { get; set; } + /// /// Sets the title of the window. /// diff --git a/src/Avalonia.Controls/Window.cs b/src/Avalonia.Controls/Window.cs index 16ee3a46b3..689b664289 100644 --- a/src/Avalonia.Controls/Window.cs +++ b/src/Avalonia.Controls/Window.cs @@ -67,13 +67,19 @@ namespace Avalonia.Controls /// public static readonly StyledProperty HasSystemDecorationsProperty = AvaloniaProperty.Register(nameof(HasSystemDecorations), true); - + /// /// Enables or disables the taskbar icon /// public static readonly StyledProperty ShowInTaskbarProperty = AvaloniaProperty.Register(nameof(ShowInTaskbar), true); - + + /// + /// Enables or disables the taskbar icon + /// + public static readonly StyledProperty WindowStateProperty = + AvaloniaProperty.Register(nameof(WindowState)); + /// /// Defines the property. /// @@ -118,6 +124,9 @@ namespace Avalonia.Controls IconProperty.Changed.AddClassHandler((s, e) => s.PlatformImpl?.SetIcon(((WindowIcon)e.NewValue).PlatformImpl)); CanResizeProperty.Changed.AddClassHandler((w, e) => w.PlatformImpl?.CanResize((bool)e.NewValue)); + + WindowStateProperty.Changed.AddClassHandler( + (w, e) => { if (w.PlatformImpl != null) w.PlatformImpl.WindowState = (WindowState)e.NewValue; }); } /// @@ -138,8 +147,11 @@ namespace Avalonia.Controls impl.Closing = HandleClosing; _maxPlatformClientSize = PlatformImpl?.MaxClientSize ?? default(Size); Screens = new Screens(PlatformImpl?.Screen); - } + if (PlatformImpl != null) + PlatformImpl.WindowStateChanged = s => WindowState = s; + } + /// event EventHandler INameScope.Registered { @@ -205,12 +217,8 @@ namespace Avalonia.Controls /// public WindowState WindowState { - get { return PlatformImpl?.WindowState ?? WindowState.Normal; } - set - { - if (PlatformImpl != null) - PlatformImpl.WindowState = value; - } + get { return GetValue(WindowStateProperty); } + set { SetValue(WindowStateProperty, value); } } /// diff --git a/src/Avalonia.DesignerSupport/Remote/PreviewerWindowImpl.cs b/src/Avalonia.DesignerSupport/Remote/PreviewerWindowImpl.cs index 9750b46aa2..ef16d06b60 100644 --- a/src/Avalonia.DesignerSupport/Remote/PreviewerWindowImpl.cs +++ b/src/Avalonia.DesignerSupport/Remote/PreviewerWindowImpl.cs @@ -42,6 +42,7 @@ namespace Avalonia.DesignerSupport.Remote public Func Closing { get; set; } public IPlatformHandle Handle { get; } public WindowState WindowState { get; set; } + public Action WindowStateChanged { get; set; } public Size MaxClientSize { get; } = new Size(4096, 4096); public event Action LostFocus; diff --git a/src/Avalonia.DesignerSupport/Remote/Stubs.cs b/src/Avalonia.DesignerSupport/Remote/Stubs.cs index ee8569d748..e749d10468 100644 --- a/src/Avalonia.DesignerSupport/Remote/Stubs.cs +++ b/src/Avalonia.DesignerSupport/Remote/Stubs.cs @@ -32,6 +32,7 @@ namespace Avalonia.DesignerSupport.Remote public Point Position { get; set; } public Action PositionChanged { get; set; } public WindowState WindowState { get; set; } + public Action WindowStateChanged { get; set; } public IRenderer CreateRenderer(IRenderRoot root) => new ImmediateRenderer(root); public void Dispose() { diff --git a/src/Gtk/Avalonia.Gtk3/WindowBaseImpl.cs b/src/Gtk/Avalonia.Gtk3/WindowBaseImpl.cs index 0ebfea998a..94537d3475 100644 --- a/src/Gtk/Avalonia.Gtk3/WindowBaseImpl.cs +++ b/src/Gtk/Avalonia.Gtk3/WindowBaseImpl.cs @@ -241,7 +241,7 @@ namespace Avalonia.Gtk3 return true; } - void ConnectEvent(string name, Native.D.signal_onevent handler) + protected void ConnectEvent(string name, Native.D.signal_onevent handler) => Disposables.Add(Signal.Connect(GtkWidget, name, handler)); void Connect(string name, T handler) => Disposables.Add(Signal.Connect(GtkWidget, name, handler)); diff --git a/src/Gtk/Avalonia.Gtk3/WindowImpl.cs b/src/Gtk/Avalonia.Gtk3/WindowImpl.cs index 2d309e19d4..bae34db6f3 100644 --- a/src/Gtk/Avalonia.Gtk3/WindowImpl.cs +++ b/src/Gtk/Avalonia.Gtk3/WindowImpl.cs @@ -1,18 +1,34 @@ using System; -using System.Linq.Expressions; using Avalonia.Controls; using Avalonia.Gtk3.Interop; using Avalonia.Platform; -using System.Runtime.InteropServices; namespace Avalonia.Gtk3 { class WindowImpl : WindowBaseImpl, IWindowImpl { + private WindowState _lastWindowState; + public WindowImpl() : base(Native.GtkWindowNew(GtkWindowType.TopLevel)) { } + protected unsafe override bool OnStateChanged(IntPtr w, IntPtr pev, IntPtr userData) + { + var windowStateEvent = (GdkEventWindowState*)pev; + var newWindowState = windowStateEvent->new_window_state; + var windowState = newWindowState.HasFlag(GdkWindowState.Iconified) ? WindowState.Minimized + : (newWindowState.HasFlag(GdkWindowState.Maximized) ? WindowState.Maximized : WindowState.Normal); + + if (windowState != _lastWindowState) + { + _lastWindowState = windowState; + WindowStateChanged?.Invoke(windowState); + } + + return base.OnStateChanged(w, pev, userData); + } + public void SetTitle(string title) { using (var t = new Utf8Buffer(title)) @@ -43,7 +59,9 @@ namespace Avalonia.Gtk3 } } } - + + public Action WindowStateChanged { get; set; } + public IDisposable ShowDialog() { Native.GtkWindowSetModal(GtkWidget, true); diff --git a/src/OSX/Avalonia.MonoMac/WindowImpl.cs b/src/OSX/Avalonia.MonoMac/WindowImpl.cs index d01cbd6ae3..a2f8df6791 100644 --- a/src/OSX/Avalonia.MonoMac/WindowImpl.cs +++ b/src/OSX/Avalonia.MonoMac/WindowImpl.cs @@ -12,10 +12,24 @@ namespace Avalonia.MonoMac public bool IsResizable = true; public CGRect? UndecoratedLastUnmaximizedFrame; + private WindowState _lastWindowState; + public WindowImpl() { UpdateStyle(); Window.SetCanBecomeKeyAndMain(); + + Window.DidResize += delegate + { + var windowState = Window.IsMiniaturized ? WindowState.Minimized + : (IsZoomed ? WindowState.Maximized : WindowState.Normal); + + if (windowState != _lastWindowState) + { + _lastWindowState = windowState; + WindowStateChanged?.Invoke(windowState); + } + }; } public WindowState WindowState @@ -49,6 +63,8 @@ namespace Avalonia.MonoMac } } + public Action WindowStateChanged { get; set; } + bool IsZoomed => IsDecorated ? Window.IsZoomed : UndecoratedIsMaximized; public bool UndecoratedIsMaximized => Window.Frame == Window.Screen.VisibleFrame; diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index cf6cb40e58..5aa1b30512 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -34,6 +34,7 @@ namespace Avalonia.Win32 private bool _resizable = true; private double _scaling = 1; private WindowState _showWindowState; + private WindowState _lastWindowState; private FramebufferManager _framebuffer; private OleDropTarget _dropTarget; private Size _minSize; @@ -77,6 +78,8 @@ namespace Avalonia.Win32 public Action PositionChanged { get; set; } + public Action WindowStateChanged { get; set; } + public Thickness BorderThickness { get @@ -617,14 +620,25 @@ namespace Avalonia.Win32 return IntPtr.Zero; case UnmanagedMethods.WindowsMessage.WM_SIZE: + var size = (UnmanagedMethods.SizeCommand)wParam; + if (Resized != null && - (wParam == (IntPtr)UnmanagedMethods.SizeCommand.Restored || - wParam == (IntPtr)UnmanagedMethods.SizeCommand.Maximized)) + (size == UnmanagedMethods.SizeCommand.Restored || + size == UnmanagedMethods.SizeCommand.Maximized)) { var clientSize = new Size(ToInt32(lParam) & 0xffff, ToInt32(lParam) >> 16); Resized(clientSize / Scaling); } + var windowState = size == SizeCommand.Maximized ? WindowState.Maximized + : (size == SizeCommand.Minimized ? WindowState.Minimized : WindowState.Normal); + + if (windowState != _lastWindowState) + { + _lastWindowState = windowState; + WindowStateChanged?.Invoke(windowState); + } + return IntPtr.Zero; case UnmanagedMethods.WindowsMessage.WM_MOVE: @@ -654,6 +668,7 @@ namespace Avalonia.Win32 (Screen as ScreenImpl)?.InvalidateScreensCache(); return IntPtr.Zero; } + #if USE_MANAGED_DRAG if (_managedDrag.PreprocessInputEvent(ref e)) From 8493ce8f0427eb1627ab18e148aa8487f9ea7823 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Wed, 9 May 2018 19:25:59 +0100 Subject: [PATCH 09/19] correctly order the properties. --- src/Avalonia.Controls/TextBox.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Avalonia.Controls/TextBox.cs b/src/Avalonia.Controls/TextBox.cs index b09c380faa..fb3eef742a 100644 --- a/src/Avalonia.Controls/TextBox.cs +++ b/src/Avalonia.Controls/TextBox.cs @@ -31,12 +31,12 @@ namespace Avalonia.Controls o => o.CaretIndex, (o, v) => o.CaretIndex = v); - public static readonly StyledProperty PasswordCharProperty = - AvaloniaProperty.Register(nameof(PasswordChar)); - public static readonly StyledProperty IsReadOnlyProperty = AvaloniaProperty.Register(nameof(IsReadOnly)); + public static readonly StyledProperty PasswordCharProperty = + AvaloniaProperty.Register(nameof(PasswordChar)); + public static readonly DirectProperty SelectionStartProperty = AvaloniaProperty.RegisterDirect( nameof(SelectionStart), @@ -166,18 +166,18 @@ namespace Avalonia.Controls } } - public char PasswordChar - { - get => GetValue(PasswordCharProperty); - set => SetValue(PasswordCharProperty, value); - } - public bool IsReadOnly { get { return GetValue(IsReadOnlyProperty); } set { SetValue(IsReadOnlyProperty, value); } } + public char PasswordChar + { + get => GetValue(PasswordCharProperty); + set => SetValue(PasswordCharProperty, value); + } + public int SelectionStart { get From 8befbacba018f8d36bb271d1d6a4c5ea8203c5c1 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Wed, 9 May 2018 19:41:53 +0100 Subject: [PATCH 10/19] Use textpresenter to replace with password char. --- .../Presenters/TextPresenter.cs | 14 +++++++++++ src/Avalonia.Controls/TextBox.cs | 23 +------------------ src/Avalonia.Themes.Default/TextBox.xaml | 5 ++-- 3 files changed, 18 insertions(+), 24 deletions(-) diff --git a/src/Avalonia.Controls/Presenters/TextPresenter.cs b/src/Avalonia.Controls/Presenters/TextPresenter.cs index d2d4151e3d..902f951146 100644 --- a/src/Avalonia.Controls/Presenters/TextPresenter.cs +++ b/src/Avalonia.Controls/Presenters/TextPresenter.cs @@ -17,6 +17,9 @@ namespace Avalonia.Controls.Presenters o => o.CaretIndex, (o, v) => o.CaretIndex = v); + public static readonly StyledProperty PasswordCharProperty = + AvaloniaProperty.Register(nameof(PasswordChar)); + public static readonly DirectProperty SelectionStartProperty = TextBox.SelectionStartProperty.AddOwner( o => o.SelectionStart, @@ -63,6 +66,12 @@ namespace Avalonia.Controls.Presenters } } + public char PasswordChar + { + get => GetValue(PasswordCharProperty); + set => SetValue(PasswordCharProperty, value); + } + public int SelectionStart { get @@ -204,6 +213,11 @@ namespace Avalonia.Controls.Presenters protected override FormattedText CreateFormattedText(Size constraint) { + if (PasswordChar != default(char)) + { + Text = new string(PasswordChar, Text.Length); + } + var result = base.CreateFormattedText(constraint); var selectionStart = SelectionStart; var selectionEnd = SelectionEnd; diff --git a/src/Avalonia.Controls/TextBox.cs b/src/Avalonia.Controls/TextBox.cs index fb3eef742a..874d2a3229 100644 --- a/src/Avalonia.Controls/TextBox.cs +++ b/src/Avalonia.Controls/TextBox.cs @@ -56,9 +56,6 @@ namespace Avalonia.Controls defaultBindingMode: BindingMode.TwoWay, enableDataValidation: true); - public static readonly StyledProperty DisplayTextProperty = - AvaloniaProperty.Register(nameof(DisplayText)); - public static readonly StyledProperty TextAlignmentProperty = TextBlock.TextAlignmentProperty.AddOwner(); @@ -122,19 +119,7 @@ namespace Avalonia.Controls ScrollViewer.HorizontalScrollBarVisibilityProperty, horizontalScrollBarVisibility, BindingPriority.Style); - _undoRedoHelper = new UndoRedoHelper(this); - - this.GetObservable(TextProperty).Subscribe(text => - { - if (IsPasswordBox) - { - DisplayText = new string(PasswordChar, text.Length); - } - else - { - DisplayText = Text; - } - }); + _undoRedoHelper = new UndoRedoHelper(this); } public bool AcceptsReturn @@ -232,12 +217,6 @@ namespace Avalonia.Controls } } - public string DisplayText - { - get => GetValue(DisplayTextProperty); - set => SetValue(DisplayTextProperty, value); - } - public TextAlignment TextAlignment { get { return GetValue(TextAlignmentProperty); } diff --git a/src/Avalonia.Themes.Default/TextBox.xaml b/src/Avalonia.Themes.Default/TextBox.xaml index 89c445eac5..c57e5b792d 100644 --- a/src/Avalonia.Themes.Default/TextBox.xaml +++ b/src/Avalonia.Themes.Default/TextBox.xaml @@ -38,12 +38,13 @@ Text="{TemplateBinding Watermark}" IsVisible="{TemplateBinding Path=Text, Converter={x:Static StringConverters.NullOrEmpty}}"/> + TextWrapping="{TemplateBinding TextWrapping}" + PasswordChar="{TemplateBinding PasswordChar}"/> From 58daa9390b185bb3bc15443c9437f9d69ae2dc92 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Mon, 14 May 2018 15:28:37 +0100 Subject: [PATCH 11/19] Allow CreateFormattedText to have the string it renders overridden. --- src/Avalonia.Controls/Presenters/TextPresenter.cs | 11 ++++++++--- src/Avalonia.Controls/Primitives/AccessText.cs | 11 ++--------- src/Avalonia.Controls/TextBlock.cs | 7 ++++--- 3 files changed, 14 insertions(+), 15 deletions(-) diff --git a/src/Avalonia.Controls/Presenters/TextPresenter.cs b/src/Avalonia.Controls/Presenters/TextPresenter.cs index 902f951146..4d63148b5f 100644 --- a/src/Avalonia.Controls/Presenters/TextPresenter.cs +++ b/src/Avalonia.Controls/Presenters/TextPresenter.cs @@ -211,14 +211,19 @@ namespace Avalonia.Controls.Presenters } } - protected override FormattedText CreateFormattedText(Size constraint) + protected override FormattedText CreateFormattedText(Size constraint, string text) { + FormattedText result = null; + if (PasswordChar != default(char)) { - Text = new string(PasswordChar, Text.Length); + result = base.CreateFormattedText(constraint, new string(PasswordChar, Text.Length)); + } + else + { + result = base.CreateFormattedText(constraint, Text); } - var result = base.CreateFormattedText(constraint); var selectionStart = SelectionStart; var selectionEnd = SelectionEnd; var start = Math.Min(selectionStart, selectionEnd); diff --git a/src/Avalonia.Controls/Primitives/AccessText.cs b/src/Avalonia.Controls/Primitives/AccessText.cs index 4bb80e6d3f..5b0f79c9c8 100644 --- a/src/Avalonia.Controls/Primitives/AccessText.cs +++ b/src/Avalonia.Controls/Primitives/AccessText.cs @@ -83,16 +83,9 @@ namespace Avalonia.Controls.Primitives /// /// The constraint of the text. /// A object. - protected override FormattedText CreateFormattedText(Size constraint) + protected override FormattedText CreateFormattedText(Size constraint, string text) { - return new FormattedText - { - Constraint = constraint, - Typeface = new Typeface(FontFamily, FontSize, FontStyle, FontWeight), - Text = StripAccessKey(Text), - TextAlignment = TextAlignment, - Wrapping = TextWrapping, - }; + return base.CreateFormattedText(constraint, StripAccessKey(text)); } /// diff --git a/src/Avalonia.Controls/TextBlock.cs b/src/Avalonia.Controls/TextBlock.cs index 88a9fe077d..35600a213c 100644 --- a/src/Avalonia.Controls/TextBlock.cs +++ b/src/Avalonia.Controls/TextBlock.cs @@ -197,7 +197,7 @@ namespace Avalonia.Controls { if (_formattedText == null) { - _formattedText = CreateFormattedText(_constraint); + _formattedText = CreateFormattedText(_constraint, Text); } return _formattedText; @@ -348,14 +348,15 @@ namespace Avalonia.Controls /// Creates the used to render the text. /// /// The constraint of the text. + /// The text to generated the for. /// A object. - protected virtual FormattedText CreateFormattedText(Size constraint) + protected virtual FormattedText CreateFormattedText(Size constraint, string text) { return new FormattedText { Constraint = constraint, Typeface = new Typeface(FontFamily, FontSize, FontStyle, FontWeight), - Text = Text ?? string.Empty, + Text = text ?? string.Empty, TextAlignment = TextAlignment, Wrapping = TextWrapping, }; From 515e180cdbcd9b6827e9a6c7847d4e8841575f91 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Mon, 14 May 2018 15:30:58 +0100 Subject: [PATCH 12/19] update documentation for CreateFormattedText method. --- src/Avalonia.Controls/Presenters/TextPresenter.cs | 6 ++++++ src/Avalonia.Controls/Primitives/AccessText.cs | 1 + 2 files changed, 7 insertions(+) diff --git a/src/Avalonia.Controls/Presenters/TextPresenter.cs b/src/Avalonia.Controls/Presenters/TextPresenter.cs index 4d63148b5f..c241466aea 100644 --- a/src/Avalonia.Controls/Presenters/TextPresenter.cs +++ b/src/Avalonia.Controls/Presenters/TextPresenter.cs @@ -211,6 +211,12 @@ namespace Avalonia.Controls.Presenters } } + /// + /// Creates the used to render the text. + /// + /// The constraint of the text. + /// The text to generated the for. + /// A object. protected override FormattedText CreateFormattedText(Size constraint, string text) { FormattedText result = null; diff --git a/src/Avalonia.Controls/Primitives/AccessText.cs b/src/Avalonia.Controls/Primitives/AccessText.cs index 5b0f79c9c8..55f047b009 100644 --- a/src/Avalonia.Controls/Primitives/AccessText.cs +++ b/src/Avalonia.Controls/Primitives/AccessText.cs @@ -82,6 +82,7 @@ namespace Avalonia.Controls.Primitives /// Creates the used to render the text. /// /// The constraint of the text. + /// The text to generated the for. /// A object. protected override FormattedText CreateFormattedText(Size constraint, string text) { From 1e611022be693a390f65647656bee5b32d517906 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Tue, 15 May 2018 09:10:26 +0200 Subject: [PATCH 13/19] Updated .net core SDK version. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index fdffaba477..51b2aaf2bc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,7 +9,7 @@ env: - DOTNET_CLI_TELEMETRY_OPTOUT=1 mono: - 5.2.0 -dotnet: 2.0.0 +dotnet: 2.1.200 script: - ./build.sh --target "Travis" --platform "NetCoreOnly" --configuration "Release" notifications: From cb39aa0426f6b076bdceb457dad2b1c7bb45a70a Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Tue, 15 May 2018 09:13:41 +0200 Subject: [PATCH 14/19] Fixed doc comments. --- src/Avalonia.Controls/Primitives/AccessText.cs | 7 +------ src/Avalonia.Controls/TextBlock.cs | 2 +- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/Avalonia.Controls/Primitives/AccessText.cs b/src/Avalonia.Controls/Primitives/AccessText.cs index 55f047b009..32a0efc440 100644 --- a/src/Avalonia.Controls/Primitives/AccessText.cs +++ b/src/Avalonia.Controls/Primitives/AccessText.cs @@ -78,12 +78,7 @@ namespace Avalonia.Controls.Primitives } } - /// - /// Creates the used to render the text. - /// - /// The constraint of the text. - /// The text to generated the for. - /// A object. + /// protected override FormattedText CreateFormattedText(Size constraint, string text) { return base.CreateFormattedText(constraint, StripAccessKey(text)); diff --git a/src/Avalonia.Controls/TextBlock.cs b/src/Avalonia.Controls/TextBlock.cs index 35600a213c..1fee309360 100644 --- a/src/Avalonia.Controls/TextBlock.cs +++ b/src/Avalonia.Controls/TextBlock.cs @@ -348,7 +348,7 @@ namespace Avalonia.Controls /// Creates the used to render the text. /// /// The constraint of the text. - /// The text to generated the for. + /// The text to format. /// A object. protected virtual FormattedText CreateFormattedText(Size constraint, string text) { From 262e583f5cd5368a6e1aed0b28ac3f1281225e22 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Tue, 15 May 2018 09:54:03 +0200 Subject: [PATCH 15/19] Moved to SharedVersion.props. --- build/SharedVersion.props | 1 + src/Avalonia.Visuals/Avalonia.Visuals.csproj | 1 - src/Skia/Avalonia.Skia/Avalonia.Skia.csproj | 1 - src/Windows/Avalonia.Direct2D1/Avalonia.Direct2D1.csproj | 1 - 4 files changed, 1 insertion(+), 3 deletions(-) diff --git a/build/SharedVersion.props b/build/SharedVersion.props index 8b7b02de5d..351583a106 100644 --- a/build/SharedVersion.props +++ b/build/SharedVersion.props @@ -9,5 +9,6 @@ https://github.com/AvaloniaUI/Avalonia/ true CS1591 + latest \ No newline at end of file diff --git a/src/Avalonia.Visuals/Avalonia.Visuals.csproj b/src/Avalonia.Visuals/Avalonia.Visuals.csproj index 69415dab4d..f320644cd0 100644 --- a/src/Avalonia.Visuals/Avalonia.Visuals.csproj +++ b/src/Avalonia.Visuals/Avalonia.Visuals.csproj @@ -2,7 +2,6 @@ netstandard2.0 Avalonia - latest diff --git a/src/Skia/Avalonia.Skia/Avalonia.Skia.csproj b/src/Skia/Avalonia.Skia/Avalonia.Skia.csproj index 21086525cc..ade7f8778a 100644 --- a/src/Skia/Avalonia.Skia/Avalonia.Skia.csproj +++ b/src/Skia/Avalonia.Skia/Avalonia.Skia.csproj @@ -5,7 +5,6 @@ Avalonia.Skia Avalonia.Skia true - latest true diff --git a/src/Windows/Avalonia.Direct2D1/Avalonia.Direct2D1.csproj b/src/Windows/Avalonia.Direct2D1/Avalonia.Direct2D1.csproj index 9fac027fd0..a84c373886 100644 --- a/src/Windows/Avalonia.Direct2D1/Avalonia.Direct2D1.csproj +++ b/src/Windows/Avalonia.Direct2D1/Avalonia.Direct2D1.csproj @@ -2,7 +2,6 @@ netstandard2.0 false - latest From 0b055771f54618b02d6ccaca9939cad958bda452 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Wed, 16 May 2018 00:40:38 +0200 Subject: [PATCH 16/19] Generate version numbers for assemblies. Don't set `false` because this means that assemblies won't get versions. --- src/Avalonia.Controls/Avalonia.Controls.csproj | 2 -- .../Avalonia.DotNetCoreRuntime.csproj | 1 - .../Avalonia.DotNetFrameworkRuntime.csproj | 1 - src/Avalonia.HtmlRenderer/Avalonia.HtmlRenderer.csproj | 1 - src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj | 1 - src/Markup/Avalonia.Markup.Xaml/Properties/AssemblyInfo.cs | 1 - src/Markup/Avalonia.Markup/Avalonia.Markup.csproj | 1 - src/OSX/Avalonia.MonoMac/Avalonia.MonoMac.csproj | 1 - src/Skia/Avalonia.Skia/Avalonia.Skia.csproj | 1 - src/Windows/Avalonia.Direct2D1/Avalonia.Direct2D1.csproj | 4 ---- src/Windows/Avalonia.Direct2D1/Properties/AssemblyInfo.cs | 1 - 11 files changed, 15 deletions(-) diff --git a/src/Avalonia.Controls/Avalonia.Controls.csproj b/src/Avalonia.Controls/Avalonia.Controls.csproj index ae777115f4..044ed47920 100644 --- a/src/Avalonia.Controls/Avalonia.Controls.csproj +++ b/src/Avalonia.Controls/Avalonia.Controls.csproj @@ -1,8 +1,6 @@  netstandard2.0 - latest - false diff --git a/src/Avalonia.DotNetCoreRuntime/Avalonia.DotNetCoreRuntime.csproj b/src/Avalonia.DotNetCoreRuntime/Avalonia.DotNetCoreRuntime.csproj index 5f40d347b7..f80462e958 100644 --- a/src/Avalonia.DotNetCoreRuntime/Avalonia.DotNetCoreRuntime.csproj +++ b/src/Avalonia.DotNetCoreRuntime/Avalonia.DotNetCoreRuntime.csproj @@ -1,7 +1,6 @@  netcoreapp2.0 - false $(DefineConstants);DOTNETCORE diff --git a/src/Avalonia.DotNetFrameworkRuntime/Avalonia.DotNetFrameworkRuntime.csproj b/src/Avalonia.DotNetFrameworkRuntime/Avalonia.DotNetFrameworkRuntime.csproj index eca5b89419..34022a87f6 100644 --- a/src/Avalonia.DotNetFrameworkRuntime/Avalonia.DotNetFrameworkRuntime.csproj +++ b/src/Avalonia.DotNetFrameworkRuntime/Avalonia.DotNetFrameworkRuntime.csproj @@ -1,7 +1,6 @@  net461 - false bin\$(Configuration)\Avalonia.DotNetFrameworkRuntime.xml $(DefineConstants);FULLDOTNET true diff --git a/src/Avalonia.HtmlRenderer/Avalonia.HtmlRenderer.csproj b/src/Avalonia.HtmlRenderer/Avalonia.HtmlRenderer.csproj index 520687c3ef..6e65264db0 100644 --- a/src/Avalonia.HtmlRenderer/Avalonia.HtmlRenderer.csproj +++ b/src/Avalonia.HtmlRenderer/Avalonia.HtmlRenderer.csproj @@ -3,7 +3,6 @@ netstandard2.0 False False - false CS0436 diff --git a/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj b/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj index 49f6ca9eeb..2d3a43a909 100644 --- a/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj +++ b/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj @@ -3,7 +3,6 @@ netstandard2.0 False false - false true diff --git a/src/Markup/Avalonia.Markup.Xaml/Properties/AssemblyInfo.cs b/src/Markup/Avalonia.Markup.Xaml/Properties/AssemblyInfo.cs index 0b42bedfa8..1b0e056baf 100644 --- a/src/Markup/Avalonia.Markup.Xaml/Properties/AssemblyInfo.cs +++ b/src/Markup/Avalonia.Markup.Xaml/Properties/AssemblyInfo.cs @@ -5,7 +5,6 @@ using System.Reflection; using Avalonia.Metadata; using System.Runtime.CompilerServices; -[assembly: AssemblyTitle("Avalonia.Markup.Xaml")] [assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Markup.Xaml.Data")] [assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Markup.Xaml.MarkupExtensions")] [assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Markup.Xaml.Styling")] diff --git a/src/Markup/Avalonia.Markup/Avalonia.Markup.csproj b/src/Markup/Avalonia.Markup/Avalonia.Markup.csproj index 9707662701..a3b7d07784 100644 --- a/src/Markup/Avalonia.Markup/Avalonia.Markup.csproj +++ b/src/Markup/Avalonia.Markup/Avalonia.Markup.csproj @@ -1,7 +1,6 @@  netstandard2.0 - false diff --git a/src/OSX/Avalonia.MonoMac/Avalonia.MonoMac.csproj b/src/OSX/Avalonia.MonoMac/Avalonia.MonoMac.csproj index cbf91e818a..e675b43389 100644 --- a/src/OSX/Avalonia.MonoMac/Avalonia.MonoMac.csproj +++ b/src/OSX/Avalonia.MonoMac/Avalonia.MonoMac.csproj @@ -2,7 +2,6 @@ netstandard2.0 True - false diff --git a/src/Skia/Avalonia.Skia/Avalonia.Skia.csproj b/src/Skia/Avalonia.Skia/Avalonia.Skia.csproj index ade7f8778a..03618e00f5 100644 --- a/src/Skia/Avalonia.Skia/Avalonia.Skia.csproj +++ b/src/Skia/Avalonia.Skia/Avalonia.Skia.csproj @@ -1,7 +1,6 @@  netstandard2.0 - false Avalonia.Skia Avalonia.Skia true diff --git a/src/Windows/Avalonia.Direct2D1/Avalonia.Direct2D1.csproj b/src/Windows/Avalonia.Direct2D1/Avalonia.Direct2D1.csproj index a84c373886..426a9a85a3 100644 --- a/src/Windows/Avalonia.Direct2D1/Avalonia.Direct2D1.csproj +++ b/src/Windows/Avalonia.Direct2D1/Avalonia.Direct2D1.csproj @@ -1,12 +1,8 @@  netstandard2.0 - false - - Properties\SharedAssemblyInfo.cs - UnmanagedMethods.cs diff --git a/src/Windows/Avalonia.Direct2D1/Properties/AssemblyInfo.cs b/src/Windows/Avalonia.Direct2D1/Properties/AssemblyInfo.cs index c1c5b24048..a09d5c2d1c 100644 --- a/src/Windows/Avalonia.Direct2D1/Properties/AssemblyInfo.cs +++ b/src/Windows/Avalonia.Direct2D1/Properties/AssemblyInfo.cs @@ -5,7 +5,6 @@ using System.Reflection; using Avalonia.Platform; using Avalonia.Direct2D1; -[assembly: AssemblyTitle("Avalonia.Direct2D1")] [assembly: ExportRenderingSubsystem(OperatingSystemType.WinNT, 1, "Direct2D1", typeof(Direct2D1Platform), nameof(Direct2D1Platform.Initialize), typeof(Direct2DChecker))] From ffeefabf1c210cbbae6e23b56ca7bb5074afd44e Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Wed, 16 May 2018 00:46:48 +0200 Subject: [PATCH 17/19] Update ControlCatalog.Desktop output dir. The output path has changed from `bin\Release` to `bin\Release\net461`. --- parameters.cake | 2 +- tests/Avalonia.DesignerSupport.Tests/DesignerSupportTests.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/parameters.cake b/parameters.cake index e224cce151..06cb9ba2b2 100644 --- a/parameters.cake +++ b/parameters.cake @@ -115,7 +115,7 @@ public class Parameters FileZipSuffix = Version + ".zip"; ZipCoreArtifacts = ZipRoot.CombineWithFilePath("Avalonia-" + FileZipSuffix); - ZipSourceControlCatalogDesktopDirs = (DirectoryPath)context.Directory("./samples/ControlCatalog.Desktop/bin/" + DirSuffix); + ZipSourceControlCatalogDesktopDirs = (DirectoryPath)context.Directory("./samples/ControlCatalog.Desktop/bin/" + DirSuffix + "/net461); ZipTargetControlCatalogDesktopDirs = ZipRoot.CombineWithFilePath("ControlCatalog.Desktop-" + FileZipSuffix); } } diff --git a/tests/Avalonia.DesignerSupport.Tests/DesignerSupportTests.cs b/tests/Avalonia.DesignerSupport.Tests/DesignerSupportTests.cs index 32da700acc..f320fa6fe8 100644 --- a/tests/Avalonia.DesignerSupport.Tests/DesignerSupportTests.cs +++ b/tests/Avalonia.DesignerSupport.Tests/DesignerSupportTests.cs @@ -11,9 +11,9 @@ namespace Avalonia.DesignerSupport.Tests { public class DesignerSupportTests { - [Theory(Skip = "Skipping for now as failing on AppVeyor"), + [Theory, InlineData(@"Avalonia.DesignerSupport.TestApp.exe", @"..\..\tests\Avalonia.DesignerSupport.TestApp\MainWindow.xaml"), - InlineData(@"..\..\samples\ControlCatalog.Desktop\bin\$BUILD\ControlCatalog.dll", @"..\..\samples\ControlCatalog\MainWindow.xaml")] + InlineData(@"..\..\samples\ControlCatalog.Desktop\bin\$BUILD\net461\ControlCatalog.dll", @"..\..\samples\ControlCatalog\MainWindow.xaml")] public void DesignerApiShoudBeOperational(string outputDir, string xamlFile) { var xaml = File.ReadAllText(xamlFile); From 6c3305d1b8df3af75dc3eb9e3f97a63a91ed8dc4 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Wed, 16 May 2018 01:16:55 +0200 Subject: [PATCH 18/19] Missing quote. --- parameters.cake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parameters.cake b/parameters.cake index 06cb9ba2b2..9e6eaa9d27 100644 --- a/parameters.cake +++ b/parameters.cake @@ -115,7 +115,7 @@ public class Parameters FileZipSuffix = Version + ".zip"; ZipCoreArtifacts = ZipRoot.CombineWithFilePath("Avalonia-" + FileZipSuffix); - ZipSourceControlCatalogDesktopDirs = (DirectoryPath)context.Directory("./samples/ControlCatalog.Desktop/bin/" + DirSuffix + "/net461); + ZipSourceControlCatalogDesktopDirs = (DirectoryPath)context.Directory("./samples/ControlCatalog.Desktop/bin/" + DirSuffix + "/net461"); ZipTargetControlCatalogDesktopDirs = ZipRoot.CombineWithFilePath("ControlCatalog.Desktop-" + FileZipSuffix); } } From 25ed770790b53be03b64b6923e6c5a77a1db2745 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Wed, 16 May 2018 17:51:14 +0200 Subject: [PATCH 19/19] Fix raising property changed for attached property. Raise a property changed event for attached properties when `InheritanceParent` is set. This was broken by #1499. Fixes #1576 --- src/Avalonia.Base/AvaloniaObject.cs | 5 +- .../AvaloniaObjectTests_Inheritance.cs | 46 +++++++++++++++++++ 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.Base/AvaloniaObject.cs b/src/Avalonia.Base/AvaloniaObject.cs index 68b9871fd1..1a2db9fc3d 100644 --- a/src/Avalonia.Base/AvaloniaObject.cs +++ b/src/Avalonia.Base/AvaloniaObject.cs @@ -139,8 +139,9 @@ namespace Avalonia { _inheritanceParent.PropertyChanged -= ParentPropertyChanged; } - - var inherited = (from property in AvaloniaPropertyRegistry.Instance.GetRegistered(this) + var properties = AvaloniaPropertyRegistry.Instance.GetRegistered(this) + .Concat(AvaloniaPropertyRegistry.Instance.GetRegisteredAttached(this.GetType())); + var inherited = (from property in properties where property.Inherits select new { diff --git a/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Inheritance.cs b/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Inheritance.cs index 5bd888eeb4..ef6e03a60b 100644 --- a/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Inheritance.cs +++ b/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Inheritance.cs @@ -38,6 +38,26 @@ namespace Avalonia.Base.UnitTests Assert.True(raised); } + [Fact] + public void Setting_InheritanceParent_Raises_PropertyChanged_For_Attached_Property_When_Value_Changed_In_Parent() + { + bool raised = false; + + Class1 parent = new Class1(); + parent.SetValue(AttachedOwner.AttachedProperty, "changed"); + + Class2 child = new Class2(); + child.PropertyChanged += (s, e) => + raised = s == child && + e.Property == AttachedOwner.AttachedProperty && + (string)e.OldValue == null && + (string)e.NewValue == "changed"; + + child.Parent = parent; + + Assert.True(raised); + } + [Fact] public void Setting_InheritanceParent_Doesnt_Raise_PropertyChanged_When_Local_Value_Set() { @@ -75,6 +95,26 @@ namespace Avalonia.Base.UnitTests Assert.True(raised); } + [Fact] + public void Setting_Value_Of_Attached_Property_In_InheritanceParent_Raises_PropertyChanged() + { + bool raised = false; + + Class1 parent = new Class1(); + + Class2 child = new Class2(); + child.PropertyChanged += (s, e) => + raised = s == child && + e.Property == AttachedOwner.AttachedProperty && + (string)e.OldValue == null && + (string)e.NewValue == "changed"; + child.Parent = parent; + + parent.SetValue(AttachedOwner.AttachedProperty, "changed"); + + Assert.True(raised); + } + private class Class1 : AvaloniaObject { public static readonly StyledProperty FooProperty = @@ -97,5 +137,11 @@ namespace Avalonia.Base.UnitTests set { InheritanceParent = value; } } } + + private class AttachedOwner : AvaloniaObject + { + public static readonly AttachedProperty AttachedProperty = + AvaloniaProperty.RegisterAttached("Attached", inherits: true); + } } }