diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index 34f931ff41..46e8665945 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -18,7 +18,7 @@
- [ ] Added unit tests (if possible)?
- [ ] Added XML documentation to any related classes?
-- [ ] Consider submitting a PR to https://github.com/AvaloniaUI/Avaloniaui.net with user documentation
+- [ ] Consider submitting a PR to https://github.com/AvaloniaUI/Documentation with user documentation
## Breaking changes
diff --git a/native/Avalonia.Native/src/OSX/window.h b/native/Avalonia.Native/src/OSX/window.h
index b1f64bca88..6a4ca2b8d8 100644
--- a/native/Avalonia.Native/src/OSX/window.h
+++ b/native/Avalonia.Native/src/OSX/window.h
@@ -34,6 +34,7 @@ class WindowBaseImpl;
-(double) getScaling;
-(double) getExtendedTitleBarHeight;
-(void) setIsExtended:(bool)value;
+-(void) updateShadow;
@end
struct INSWindowHolder
diff --git a/native/Avalonia.Native/src/OSX/window.mm b/native/Avalonia.Native/src/OSX/window.mm
index d7afbdaa3a..e7c144b2d3 100644
--- a/native/Avalonia.Native/src/OSX/window.mm
+++ b/native/Avalonia.Native/src/OSX/window.mm
@@ -124,7 +124,11 @@ public:
[Window setTitle:_lastTitle];
_shown = true;
-
+
+ dispatch_async(dispatch_get_main_queue(), ^{
+ [Window updateShadow];
+ });
+
return S_OK;
}
}
@@ -1838,6 +1842,19 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
double _lastScaling;
}
+- (void)updateShadow
+{
+ // Common problem in Cocoa where [invalidateShadow] does work,
+ // This hack forces Cocoa to invalidate the shadow.
+
+ NSRect frame = [self frame];
+ NSRect updatedFrame = NSMakeRect(frame.origin.x, frame.origin.y, frame.size.width + 1.0, frame.size.height + 1.0);
+ [self setFrame:updatedFrame display:YES];
+ [self setFrame:frame display:YES];
+
+ [self invalidateShadow];
+}
+
-(void) setIsExtended:(bool)value;
{
_isExtended = value;
diff --git a/samples/ControlCatalog/App.xaml.cs b/samples/ControlCatalog/App.xaml.cs
index 020fb2fff3..f3ec7b48aa 100644
--- a/samples/ControlCatalog/App.xaml.cs
+++ b/samples/ControlCatalog/App.xaml.cs
@@ -39,6 +39,10 @@ namespace ControlCatalog
public static Styles DefaultLight = new Styles
{
+ new StyleInclude(new Uri("resm:Styles?assembly=ControlCatalog"))
+ {
+ Source = new Uri("avares://Avalonia.Themes.Fluent/Accents/AccentColors.xaml")
+ },
new StyleInclude(new Uri("resm:Styles?assembly=ControlCatalog"))
{
Source = new Uri("avares://Avalonia.Themes.Fluent/Accents/Base.xaml")
@@ -60,6 +64,10 @@ namespace ControlCatalog
public static Styles DefaultDark = new Styles
{
+ new StyleInclude(new Uri("resm:Styles?assembly=ControlCatalog"))
+ {
+ Source = new Uri("avares://Avalonia.Themes.Fluent/Accents/AccentColors.xaml")
+ },
new StyleInclude(new Uri("resm:Styles?assembly=ControlCatalog"))
{
Source = new Uri("avares://Avalonia.Themes.Fluent/Accents/Base.xaml")
diff --git a/samples/ControlCatalog/Pages/ViewboxPage.xaml b/samples/ControlCatalog/Pages/ViewboxPage.xaml
index 6e649b39a5..ef802db33e 100644
--- a/samples/ControlCatalog/Pages/ViewboxPage.xaml
+++ b/samples/ControlCatalog/Pages/ViewboxPage.xaml
@@ -12,8 +12,9 @@
-
+
@@ -25,7 +26,7 @@
-
+
diff --git a/samples/ControlCatalog/Pages/ViewboxPage.xaml.cs b/samples/ControlCatalog/Pages/ViewboxPage.xaml.cs
index 7a2bceb8f2..94b3f3ea14 100644
--- a/samples/ControlCatalog/Pages/ViewboxPage.xaml.cs
+++ b/samples/ControlCatalog/Pages/ViewboxPage.xaml.cs
@@ -6,23 +6,18 @@ namespace ControlCatalog.Pages
{
public class ViewboxPage : UserControl
{
- private readonly Viewbox _viewbox;
- private readonly ComboBox _stretchSelector;
-
public ViewboxPage()
{
InitializeComponent();
- _viewbox = this.FindControl("Viewbox");
-
- _stretchSelector = this.FindControl("StretchSelector");
+ var stretchSelector = this.FindControl("StretchSelector");
- _stretchSelector.Items = new[]
+ stretchSelector.Items = new[]
{
Stretch.Uniform, Stretch.UniformToFill, Stretch.Fill, Stretch.None
};
- _stretchSelector.SelectedIndex = 0;
+ stretchSelector.SelectedIndex = 0;
var stretchDirectionSelector = this.FindControl("StretchDirectionSelector");
@@ -38,10 +33,5 @@ namespace ControlCatalog.Pages
{
AvaloniaXamlLoader.Load(this);
}
-
- private void StretchSelector_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
- {
- _viewbox.Stretch = (Stretch) _stretchSelector.SelectedItem!;
- }
}
}
diff --git a/samples/RenderDemo/Pages/AnimationsPage.xaml b/samples/RenderDemo/Pages/AnimationsPage.xaml
index 12fb31ea59..21c7d68b5d 100644
--- a/samples/RenderDemo/Pages/AnimationsPage.xaml
+++ b/samples/RenderDemo/Pages/AnimationsPage.xaml
@@ -1,7 +1,8 @@
+ x:Class="RenderDemo.Pages.AnimationsPage"
+ MaxWidth="600">
@@ -167,8 +168,8 @@
-
- Hover to activate Transform Keyframe Animations.
+
+ Hover to activate Keyframe Animations.
diff --git a/samples/RenderDemo/Pages/TransitionsPage.xaml b/samples/RenderDemo/Pages/TransitionsPage.xaml
index d6da293ff3..f9f69fb341 100644
--- a/samples/RenderDemo/Pages/TransitionsPage.xaml
+++ b/samples/RenderDemo/Pages/TransitionsPage.xaml
@@ -1,7 +1,8 @@
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ x:Class="RenderDemo.Pages.TransitionsPage"
+ MaxWidth="600">
@@ -90,6 +91,56 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -98,8 +149,8 @@
-
- Hover to activate Transform Keyframe Animations.
+
+ Hover to activate Transitions.
@@ -109,6 +160,12 @@
+
+
+
+
+
+
diff --git a/src/Avalonia.Animation/Transitions/DoubleTransition.cs b/src/Avalonia.Animation/Transitions/DoubleTransition.cs
index 8cae1e1f81..d5bb1aac20 100644
--- a/src/Avalonia.Animation/Transitions/DoubleTransition.cs
+++ b/src/Avalonia.Animation/Transitions/DoubleTransition.cs
@@ -1,6 +1,8 @@
using System;
using System.Reactive.Linq;
+using Avalonia.Animation.Animators;
+
namespace Avalonia.Animation
{
///
@@ -8,15 +10,13 @@ namespace Avalonia.Animation
///
public class DoubleTransition : Transition
{
+ private static readonly DoubleAnimator s_animator = new DoubleAnimator();
+
///
public override IObservable DoTransition(IObservable progress, double oldValue, double newValue)
{
return progress
- .Select(p =>
- {
- var f = Easing.Ease(p);
- return ((newValue - oldValue) * f) + oldValue;
- });
+ .Select(progress => s_animator.Interpolate(Easing.Ease(progress), oldValue, newValue));
}
}
}
diff --git a/src/Avalonia.Animation/Transitions/FloatTransition.cs b/src/Avalonia.Animation/Transitions/FloatTransition.cs
index 427563e559..37b644fa96 100644
--- a/src/Avalonia.Animation/Transitions/FloatTransition.cs
+++ b/src/Avalonia.Animation/Transitions/FloatTransition.cs
@@ -1,6 +1,8 @@
using System;
using System.Reactive.Linq;
+using Avalonia.Animation.Animators;
+
namespace Avalonia.Animation
{
///
@@ -8,12 +10,13 @@ namespace Avalonia.Animation
///
public class FloatTransition : Transition
{
+ private static readonly FloatAnimator s_animator = new FloatAnimator();
+
///
public override IObservable DoTransition(IObservable progress, float oldValue, float newValue)
{
- var delta = newValue - oldValue;
return progress
- .Select(p => (float)Easing.Ease(p) * delta + oldValue);
+ .Select(progress => s_animator.Interpolate(Easing.Ease(progress), oldValue, newValue));
}
}
}
diff --git a/src/Avalonia.Animation/Transitions/IntegerTransition.cs b/src/Avalonia.Animation/Transitions/IntegerTransition.cs
index 7a85bd75dc..223b2ba531 100644
--- a/src/Avalonia.Animation/Transitions/IntegerTransition.cs
+++ b/src/Avalonia.Animation/Transitions/IntegerTransition.cs
@@ -1,6 +1,8 @@
using System;
using System.Reactive.Linq;
+using Avalonia.Animation.Animators;
+
namespace Avalonia.Animation
{
///
@@ -8,12 +10,13 @@ namespace Avalonia.Animation
///
public class IntegerTransition : Transition
{
+ private static readonly Int32Animator s_animator = new Int32Animator();
+
///
public override IObservable DoTransition(IObservable progress, int oldValue, int newValue)
{
- var delta = newValue - oldValue;
return progress
- .Select(p => (int)(Easing.Ease(p) * delta + oldValue));
+ .Select(progress => s_animator.Interpolate(Easing.Ease(progress), oldValue, newValue));
}
}
}
diff --git a/src/Avalonia.Controls.DataGrid/DataGrid.cs b/src/Avalonia.Controls.DataGrid/DataGrid.cs
index a070a1b9d7..1b4632d368 100644
--- a/src/Avalonia.Controls.DataGrid/DataGrid.cs
+++ b/src/Avalonia.Controls.DataGrid/DataGrid.cs
@@ -535,7 +535,8 @@ namespace Avalonia.Controls
AvaloniaProperty.RegisterDirect(
nameof(SelectedIndex),
o => o.SelectedIndex,
- (o, v) => o.SelectedIndex = v);
+ (o, v) => o.SelectedIndex = v,
+ defaultBindingMode: BindingMode.TwoWay);
///
/// Gets or sets the index of the current selection.
@@ -553,7 +554,8 @@ namespace Avalonia.Controls
AvaloniaProperty.RegisterDirect(
nameof(SelectedItem),
o => o.SelectedItem,
- (o, v) => o.SelectedItem = v);
+ (o, v) => o.SelectedItem = v,
+ defaultBindingMode: BindingMode.TwoWay);
///
/// Gets or sets the data item corresponding to the selected row.
diff --git a/src/Avalonia.Controls/ApiCompatBaseline.txt b/src/Avalonia.Controls/ApiCompatBaseline.txt
index 7199c15d21..a79b3b4d7b 100644
--- a/src/Avalonia.Controls/ApiCompatBaseline.txt
+++ b/src/Avalonia.Controls/ApiCompatBaseline.txt
@@ -4,10 +4,11 @@ InterfacesShouldHaveSameMembers : Interface member 'public System.Boolean Avalon
InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Controls.IMenuItem.StaysOpenOnClick.set(System.Boolean)' is present in the implementation but not in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Controls.INativeMenuExporterEventsImplBridge.RaiseClosed()' is present in the implementation but not in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Controls.INativeMenuExporterEventsImplBridge.RaiseOpening()' is present in the implementation but not in the contract.
+MembersMustExist : Member 'public Avalonia.AvaloniaProperty Avalonia.AvaloniaProperty Avalonia.Controls.Viewbox.StretchProperty' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'public void Avalonia.Controls.Embedding.Offscreen.OffscreenTopLevelImplBase.SetCursor(Avalonia.Platform.IPlatformHandle)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'public Avalonia.AvaloniaProperty Avalonia.AvaloniaProperty Avalonia.Controls.Notifications.NotificationCard.CloseOnClickProperty' does not exist in the implementation but it does exist in the contract.
EnumValuesMustMatch : Enum value 'Avalonia.Platform.ExtendClientAreaChromeHints Avalonia.Platform.ExtendClientAreaChromeHints.Default' is (System.Int32)2 in the implementation but (System.Int32)1 in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Platform.ITopLevelImpl.SetCursor(Avalonia.Platform.ICursorImpl)' is present in the implementation but not in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Platform.ITopLevelImpl.SetCursor(Avalonia.Platform.IPlatformHandle)' is present in the contract but not in the implementation.
MembersMustExist : Member 'public void Avalonia.Platform.ITopLevelImpl.SetCursor(Avalonia.Platform.IPlatformHandle)' does not exist in the implementation but it does exist in the contract.
-Total Issues: 11
+Total Issues: 12
diff --git a/src/Avalonia.Controls/DateTimePickers/TimePicker.cs b/src/Avalonia.Controls/DateTimePickers/TimePicker.cs
index e4ff5e9e5b..d0cf772c01 100644
--- a/src/Avalonia.Controls/DateTimePickers/TimePicker.cs
+++ b/src/Avalonia.Controls/DateTimePickers/TimePicker.cs
@@ -8,7 +8,7 @@ using System.Globalization;
namespace Avalonia.Controls
{
///
- /// A control to allow the user to select a time
+ /// A control to allow the user to select a time.
///
[PseudoClasses(":hasnotime")]
public class TimePicker : TemplatedControl
diff --git a/src/Avalonia.Controls/Expander.cs b/src/Avalonia.Controls/Expander.cs
index 9ff2e41fa9..052b42a233 100644
--- a/src/Avalonia.Controls/Expander.cs
+++ b/src/Avalonia.Controls/Expander.cs
@@ -4,14 +4,35 @@ using Avalonia.Controls.Primitives;
namespace Avalonia.Controls
{
+ ///
+ /// Direction in which an control opens.
+ ///
public enum ExpandDirection
{
+ ///
+ /// Opens down.
+ ///
Down,
+
+ ///
+ /// Opens up.
+ ///
Up,
+
+ ///
+ /// Opens left.
+ ///
Left,
+
+ ///
+ /// Opens right.
+ ///
Right
}
+ ///
+ /// A control with a header that has a collapsible content section.
+ ///
[PseudoClasses(":expanded", ":up", ":down", ":left", ":right")]
public class Expander : HeaderedContentControl
{
diff --git a/src/Avalonia.Controls/Grid.cs b/src/Avalonia.Controls/Grid.cs
index 105a2744e5..c7d598006d 100644
--- a/src/Avalonia.Controls/Grid.cs
+++ b/src/Avalonia.Controls/Grid.cs
@@ -17,7 +17,7 @@ using Avalonia.VisualTree;
namespace Avalonia.Controls
{
///
- /// Grid
+ /// Defines a flexible grid area that consists of columns and rows.
///
public class Grid : Panel
{
diff --git a/src/Avalonia.Controls/Primitives/ScrollBarVisibility.cs b/src/Avalonia.Controls/Primitives/ScrollBarVisibility.cs
index 90727a3505..e62e087140 100644
--- a/src/Avalonia.Controls/Primitives/ScrollBarVisibility.cs
+++ b/src/Avalonia.Controls/Primitives/ScrollBarVisibility.cs
@@ -1,10 +1,28 @@
namespace Avalonia.Controls.Primitives
{
+ ///
+ /// Specifies the visibility of a for scrollable content.
+ ///
public enum ScrollBarVisibility
{
+ ///
+ /// No scrollbars and no scrolling in this dimension.
+ ///
Disabled,
+
+ ///
+ /// The scrollbar should be visible only if there is more content than fits in the viewport.
+ ///
Auto,
+
+ ///
+ /// The scrollbar should never be visible. No space should ever be reserved for the scrollbar.
+ ///
Hidden,
+
+ ///
+ /// The scrollbar should always be visible. Space should always be reserved for the scrollbar.
+ ///
Visible,
}
}
diff --git a/src/Avalonia.Controls/RadioButton.cs b/src/Avalonia.Controls/RadioButton.cs
index 4bda241497..681278d247 100644
--- a/src/Avalonia.Controls/RadioButton.cs
+++ b/src/Avalonia.Controls/RadioButton.cs
@@ -8,6 +8,9 @@ using Avalonia.VisualTree;
namespace Avalonia.Controls
{
+ ///
+ /// Represents a button that allows a user to select a single option from a group of options.
+ ///
public class RadioButton : ToggleButton
{
private class RadioButtonGroupManager
diff --git a/src/Avalonia.Controls/RelativePanel.cs b/src/Avalonia.Controls/RelativePanel.cs
index 2305d8fb9e..c5de004f09 100644
--- a/src/Avalonia.Controls/RelativePanel.cs
+++ b/src/Avalonia.Controls/RelativePanel.cs
@@ -8,6 +8,9 @@ using Avalonia.Layout;
namespace Avalonia.Controls
{
+ ///
+ /// Defines an area within which you can position and align child objects in relation to each other or the parent panel.
+ ///
public partial class RelativePanel : Panel
{
private readonly Graph _childGraph;
diff --git a/src/Avalonia.Controls/RepeatButton.cs b/src/Avalonia.Controls/RepeatButton.cs
index fcd6607feb..ba770634d9 100644
--- a/src/Avalonia.Controls/RepeatButton.cs
+++ b/src/Avalonia.Controls/RepeatButton.cs
@@ -4,6 +4,9 @@ using Avalonia.Threading;
namespace Avalonia.Controls
{
+ ///
+ /// Represents a control that raises its event repeatedly when it is pressed and held.
+ ///
public class RepeatButton : Button
{
///
diff --git a/src/Avalonia.Controls/TextBox.cs b/src/Avalonia.Controls/TextBox.cs
index 69da667011..3c221cbf27 100644
--- a/src/Avalonia.Controls/TextBox.cs
+++ b/src/Avalonia.Controls/TextBox.cs
@@ -17,6 +17,9 @@ using Avalonia.Controls.Metadata;
namespace Avalonia.Controls
{
+ ///
+ /// Represents a control that can be used to display or edit unformatted text.
+ ///
[PseudoClasses(":empty")]
public class TextBox : TemplatedControl, UndoRedoHelper.IUndoRedoHost
{
@@ -260,7 +263,11 @@ namespace Avalonia.Controls
set
{
value = CoerceCaretIndex(value);
- SetAndRaise(SelectionStartProperty, ref _selectionStart, value);
+ var changed = SetAndRaise(SelectionStartProperty, ref _selectionStart, value);
+ if (changed)
+ {
+ UpdateCommandStates();
+ }
if (SelectionStart == SelectionEnd)
{
CaretIndex = SelectionStart;
@@ -278,7 +285,11 @@ namespace Avalonia.Controls
set
{
value = CoerceCaretIndex(value);
- SetAndRaise(SelectionEndProperty, ref _selectionEnd, value);
+ var changed = SetAndRaise(SelectionEndProperty, ref _selectionEnd, value);
+ if (changed)
+ {
+ UpdateCommandStates();
+ }
if (SelectionStart == SelectionEnd)
{
CaretIndex = SelectionEnd;
diff --git a/src/Avalonia.Controls/Viewbox.cs b/src/Avalonia.Controls/Viewbox.cs
index b65f4b31d8..624c61bb82 100644
--- a/src/Avalonia.Controls/Viewbox.cs
+++ b/src/Avalonia.Controls/Viewbox.cs
@@ -11,7 +11,7 @@ namespace Avalonia.Controls
///
/// Defines the property.
///
- public static readonly AvaloniaProperty StretchProperty =
+ public static readonly StyledProperty StretchProperty =
AvaloniaProperty.Register(nameof(Stretch), Stretch.Uniform);
///
@@ -20,8 +20,6 @@ namespace Avalonia.Controls
public static readonly StyledProperty StretchDirectionProperty =
AvaloniaProperty.Register(nameof(StretchDirection), StretchDirection.Both);
- private Stretch _stretch = Stretch.Uniform;
-
static Viewbox()
{
ClipToBoundsProperty.OverrideDefaultValue(true);
@@ -34,8 +32,8 @@ namespace Avalonia.Controls
///
public Stretch Stretch
{
- get => _stretch;
- set => SetAndRaise(StretchProperty, ref _stretch, value);
+ get => GetValue(StretchProperty);
+ set => SetValue(StretchProperty, value);
}
///
diff --git a/src/Avalonia.Diagnostics/Diagnostics/Controls/ThicknessEditor.axaml b/src/Avalonia.Diagnostics/Diagnostics/Controls/ThicknessEditor.axaml
new file mode 100644
index 0000000000..c202d13778
--- /dev/null
+++ b/src/Avalonia.Diagnostics/Diagnostics/Controls/ThicknessEditor.axaml
@@ -0,0 +1,87 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Avalonia.Diagnostics/Diagnostics/Views/ThicknessEditor.cs b/src/Avalonia.Diagnostics/Diagnostics/Controls/ThicknessEditor.cs
similarity index 90%
rename from src/Avalonia.Diagnostics/Diagnostics/Views/ThicknessEditor.cs
rename to src/Avalonia.Diagnostics/Diagnostics/Controls/ThicknessEditor.cs
index c7611c8c46..e5b3b080e2 100644
--- a/src/Avalonia.Diagnostics/Diagnostics/Views/ThicknessEditor.cs
+++ b/src/Avalonia.Diagnostics/Diagnostics/Controls/ThicknessEditor.cs
@@ -1,21 +1,9 @@
using Avalonia.Controls;
using Avalonia.Data;
-using Avalonia.Data.Converters;
using Avalonia.Media;
-namespace Avalonia.Diagnostics.Views
+namespace Avalonia.Diagnostics.Controls
{
- internal static class Converters
- {
- public static IValueConverter HasConstraintConverter =
- new FuncValueConverter