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:
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/parameters.cake b/parameters.cake
index e224cce151..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);
+ ZipSourceControlCatalogDesktopDirs = (DirectoryPath)context.Directory("./samples/ControlCatalog.Desktop/bin/" + DirSuffix + "/net461");
ZipTargetControlCatalogDesktopDirs = ZipRoot.CombineWithFilePath("ControlCatalog.Desktop-" + FileZipSuffix);
}
}
diff --git a/samples/ControlCatalog/Pages/TextBoxPage.xaml b/samples/ControlCatalog/Pages/TextBoxPage.xaml
index 7bfcad6d51..db1c9cb69d 100644
--- a/samples/ControlCatalog/Pages/TextBoxPage.xaml
+++ b/samples/ControlCatalog/Pages/TextBoxPage.xaml
@@ -10,10 +10,16 @@
-
+
+
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/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.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/Presenters/TextPresenter.cs b/src/Avalonia.Controls/Presenters/TextPresenter.cs
index d2d4151e3d..c241466aea 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
@@ -202,9 +211,25 @@ namespace Avalonia.Controls.Presenters
}
}
- protected override FormattedText CreateFormattedText(Size constraint)
+ ///
+ /// 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)
{
- var result = base.CreateFormattedText(constraint);
+ FormattedText result = null;
+
+ if (PasswordChar != default(char))
+ {
+ result = base.CreateFormattedText(constraint, new string(PasswordChar, Text.Length));
+ }
+ else
+ {
+ result = base.CreateFormattedText(constraint, Text);
+ }
+
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..32a0efc440 100644
--- a/src/Avalonia.Controls/Primitives/AccessText.cs
+++ b/src/Avalonia.Controls/Primitives/AccessText.cs
@@ -78,21 +78,10 @@ namespace Avalonia.Controls.Primitives
}
}
- ///
- /// Creates the used to render the text.
- ///
- /// 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..1fee309360 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 format.
/// 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,
};
diff --git a/src/Avalonia.Controls/TextBox.cs b/src/Avalonia.Controls/TextBox.cs
index 890926db54..874d2a3229 100644
--- a/src/Avalonia.Controls/TextBox.cs
+++ b/src/Avalonia.Controls/TextBox.cs
@@ -30,10 +30,13 @@ namespace Avalonia.Controls
nameof(CaretIndex),
o => o.CaretIndex,
(o, v) => o.CaretIndex = v);
-
+
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),
@@ -87,7 +90,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()
{
@@ -116,7 +119,7 @@ namespace Avalonia.Controls
ScrollViewer.HorizontalScrollBarVisibilityProperty,
horizontalScrollBarVisibility,
BindingPriority.Style);
- _undoRedoHelper = new UndoRedoHelper(this);
+ _undoRedoHelper = new UndoRedoHelper(this);
}
public bool AcceptsReturn
@@ -147,13 +150,19 @@ namespace Avalonia.Controls
_undoRedoHelper.UpdateLastState();
}
}
-
+
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
@@ -237,7 +246,7 @@ namespace Avalonia.Controls
_presenter = e.NameScope.Get("PART_TextPresenter");
_presenter.Cursor = new Cursor(StandardCursorType.Ibeam);
- if(IsFocused)
+ if (IsFocused)
{
_presenter.ShowCaret();
}
@@ -349,7 +358,10 @@ namespace Avalonia.Controls
case Key.C:
if (modifiers == InputModifiers.Control)
{
- Copy();
+ if (!IsPasswordBox)
+ {
+ Copy();
+ }
handled = true;
}
break;
@@ -357,8 +369,11 @@ namespace Avalonia.Controls
case Key.X:
if (modifiers == InputModifiers.Control)
{
- Copy();
- DeleteSelection();
+ if (!IsPasswordBox)
+ {
+ Copy();
+ DeleteSelection();
+ }
handled = true;
}
break;
@@ -578,7 +593,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)
@@ -856,6 +871,8 @@ namespace Avalonia.Controls
SelectionEnd = CaretIndex;
}
+ private bool IsPasswordBox => PasswordChar != default(char);
+
UndoRedoState UndoRedoHelper.IUndoRedoHost.UndoRedoState
{
get { return new UndoRedoState(Text, CaretIndex); }
diff --git a/src/Avalonia.Controls/Window.cs b/src/Avalonia.Controls/Window.cs
index 91d6c874d3..c4a09ac043 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/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/Avalonia.Themes.Default/TextBox.xaml b/src/Avalonia.Themes.Default/TextBox.xaml
index e228aebf58..c57e5b792d 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}"
+ PasswordChar="{TemplateBinding PasswordChar}"/>
diff --git a/src/Avalonia.Visuals/Matrix.cs b/src/Avalonia.Visuals/Matrix.cs
index b09ea2b68c..9ed5923109 100644
--- a/src/Avalonia.Visuals/Matrix.cs
+++ b/src/Avalonia.Visuals/Matrix.cs
@@ -11,7 +11,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 82cc19347a..aacce3fdce 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 62be3bf276..34070ac71f 100644
--- a/src/Avalonia.Visuals/Point.cs
+++ b/src/Avalonia.Visuals/Point.cs
@@ -11,7 +11,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 73021ca29a..d28fff0216 100644
--- a/src/Avalonia.Visuals/Rect.cs
+++ b/src/Avalonia.Visuals/Rect.cs
@@ -11,7 +11,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 e4d7ea05cb..5d3cb23a90 100644
--- a/src/Avalonia.Visuals/RelativePoint.cs
+++ b/src/Avalonia.Visuals/RelativePoint.cs
@@ -28,7 +28,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.
@@ -45,7 +45,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 ad42e30057..0afe74f0be 100644
--- a/src/Avalonia.Visuals/RelativeRect.cs
+++ b/src/Avalonia.Visuals/RelativeRect.cs
@@ -11,7 +11,7 @@ namespace Avalonia
///
/// Defines a rectangle that may be defined relative to a containing element.
///
- public struct RelativeRect : IEquatable
+ public readonly struct RelativeRect : IEquatable
{
private static readonly char[] PercentChar = { '%' };
diff --git a/src/Avalonia.Visuals/Rendering/SceneGraph/DeferredDrawingContextImpl.cs b/src/Avalonia.Visuals/Rendering/SceneGraph/DeferredDrawingContextImpl.cs
index dfd45fba9c..f3dbfbd8fb 100644
--- a/src/Avalonia.Visuals/Rendering/SceneGraph/DeferredDrawingContextImpl.cs
+++ b/src/Avalonia.Visuals/Rendering/SceneGraph/DeferredDrawingContextImpl.cs
@@ -320,7 +320,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 b6889af6f0..50a3973a5c 100644
--- a/src/Avalonia.Visuals/Size.cs
+++ b/src/Avalonia.Visuals/Size.cs
@@ -11,7 +11,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 43a5fed9e7..759abd5943 100644
--- a/src/Avalonia.Visuals/Thickness.cs
+++ b/src/Avalonia.Visuals/Thickness.cs
@@ -11,7 +11,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 435ca85a05..f8356bbcd6 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/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/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/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/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 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/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;
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))]
diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs
index be28b64c5a..7b9f8ee066 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
@@ -626,14 +629,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:
@@ -663,6 +677,7 @@ namespace Avalonia.Win32
(Screen as ScreenImpl)?.InvalidateScreensCache();
return IntPtr.Zero;
}
+
#if USE_MANAGED_DRAG
if (_managedDrag.PreprocessInputEvent(ref e))
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);
+ }
}
}
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);