diff --git a/native/Avalonia.Native/src/OSX/common.h b/native/Avalonia.Native/src/OSX/common.h
index ea48a19874..05b2d762ae 100644
--- a/native/Avalonia.Native/src/OSX/common.h
+++ b/native/Avalonia.Native/src/OSX/common.h
@@ -28,6 +28,8 @@ extern IAvnNativeControlHost* CreateNativeControlHost(NSView* parent);
extern void SetAppMenu (NSString* appName, IAvnMenu* appMenu);
extern IAvnMenu* GetAppMenu ();
extern NSMenuItem* GetAppMenuItem ();
+extern void SetAutoGenerateDefaultAppMenuItems (bool enabled);
+extern bool GetAutoGenerateDefaultAppMenuItems ();
extern void InitializeAvnApp();
extern NSApplicationActivationPolicy AvnDesiredActivationPolicy;
diff --git a/native/Avalonia.Native/src/OSX/main.mm b/native/Avalonia.Native/src/OSX/main.mm
index 72f5aa0a7d..17746e1d1d 100644
--- a/native/Avalonia.Native/src/OSX/main.mm
+++ b/native/Avalonia.Native/src/OSX/main.mm
@@ -2,6 +2,7 @@
#define COM_GUIDS_MATERIALIZE
#include "common.h"
+static bool s_generateDefaultAppMenuItems = true;
static NSString* s_appTitle = @"Avalonia";
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
@@ -122,6 +123,12 @@ public:
? NSApplicationActivationPolicyRegular : NSApplicationActivationPolicyAccessory;
return S_OK;
}
+
+ virtual HRESULT SetDisableDefaultApplicationMenuItems (bool enabled) override
+ {
+ SetAutoGenerateDefaultAppMenuItems(!enabled);
+ return S_OK;
+ }
};
/// See "Using POSIX Threads in a Cocoa Application" section here:
@@ -310,3 +317,13 @@ CGFloat PrimaryDisplayHeight()
{
return NSMaxY([[[NSScreen screens] firstObject] frame]);
}
+
+void SetAutoGenerateDefaultAppMenuItems (bool enabled)
+{
+ s_generateDefaultAppMenuItems = enabled;
+}
+
+bool GetAutoGenerateDefaultAppMenuItems ()
+{
+ return s_generateDefaultAppMenuItems;
+}
diff --git a/native/Avalonia.Native/src/OSX/menu.mm b/native/Avalonia.Native/src/OSX/menu.mm
index 198b01714f..ea5cca9ce8 100644
--- a/native/Avalonia.Native/src/OSX/menu.mm
+++ b/native/Avalonia.Native/src/OSX/menu.mm
@@ -445,47 +445,50 @@ extern void SetAppMenu (NSString* appName, IAvnMenu* menu)
auto appMenu = [s_appMenuItem submenu];
- [appMenu addItem:[NSMenuItem separatorItem]];
-
- // Services item and menu
- auto servicesItem = [[NSMenuItem alloc] init];
- servicesItem.title = @"Services";
- NSMenu *servicesMenu = [[NSMenu alloc] initWithTitle:@"Services"];
- servicesItem.submenu = servicesMenu;
- [NSApplication sharedApplication].servicesMenu = servicesMenu;
- [appMenu addItem:servicesItem];
-
- [appMenu addItem:[NSMenuItem separatorItem]];
-
- // Hide Application
- auto hideItem = [[NSMenuItem alloc] initWithTitle:[@"Hide " stringByAppendingString:appName] action:@selector(hide:) keyEquivalent:@"h"];
-
- [appMenu addItem:hideItem];
-
- // Hide Others
- auto hideAllOthersItem = [[NSMenuItem alloc] initWithTitle:@"Hide Others"
- action:@selector(hideOtherApplications:)
- keyEquivalent:@"h"];
-
- hideAllOthersItem.keyEquivalentModifierMask = NSEventModifierFlagCommand | NSEventModifierFlagOption;
- [appMenu addItem:hideAllOthersItem];
-
- // Show All
- auto showAllItem = [[NSMenuItem alloc] initWithTitle:@"Show All"
- action:@selector(unhideAllApplications:)
- keyEquivalent:@""];
-
- [appMenu addItem:showAllItem];
-
- [appMenu addItem:[NSMenuItem separatorItem]];
-
- // Quit Application
- auto quitItem = [[NSMenuItem alloc] init];
- quitItem.title = [@"Quit " stringByAppendingString:appName];
- quitItem.keyEquivalent = @"q";
- quitItem.target = [AvnWindow class];
- quitItem.action = @selector(closeAll);
- [appMenu addItem:quitItem];
+ if(GetAutoGenerateDefaultAppMenuItems())
+ {
+ [appMenu addItem:[NSMenuItem separatorItem]];
+
+ // Services item and menu
+ auto servicesItem = [[NSMenuItem alloc] init];
+ servicesItem.title = @"Services";
+ NSMenu *servicesMenu = [[NSMenu alloc] initWithTitle:@"Services"];
+ servicesItem.submenu = servicesMenu;
+ [NSApplication sharedApplication].servicesMenu = servicesMenu;
+ [appMenu addItem:servicesItem];
+
+ [appMenu addItem:[NSMenuItem separatorItem]];
+
+ // Hide Application
+ auto hideItem = [[NSMenuItem alloc] initWithTitle:[@"Hide " stringByAppendingString:appName] action:@selector(hide:) keyEquivalent:@"h"];
+
+ [appMenu addItem:hideItem];
+
+ // Hide Others
+ auto hideAllOthersItem = [[NSMenuItem alloc] initWithTitle:@"Hide Others"
+ action:@selector(hideOtherApplications:)
+ keyEquivalent:@"h"];
+
+ hideAllOthersItem.keyEquivalentModifierMask = NSEventModifierFlagCommand | NSEventModifierFlagOption;
+ [appMenu addItem:hideAllOthersItem];
+
+ // Show All
+ auto showAllItem = [[NSMenuItem alloc] initWithTitle:@"Show All"
+ action:@selector(unhideAllApplications:)
+ keyEquivalent:@""];
+
+ [appMenu addItem:showAllItem];
+
+ [appMenu addItem:[NSMenuItem separatorItem]];
+
+ // Quit Application
+ auto quitItem = [[NSMenuItem alloc] init];
+ quitItem.title = [@"Quit " stringByAppendingString:appName];
+ quitItem.keyEquivalent = @"q";
+ quitItem.target = [AvnWindow class];
+ quitItem.action = @selector(closeAll);
+ [appMenu addItem:quitItem];
+ }
}
else
{
diff --git a/samples/ControlCatalog/Pages/AcrylicPage.xaml b/samples/ControlCatalog/Pages/AcrylicPage.xaml
index 96cfcc5288..7635e1ccc3 100644
--- a/samples/ControlCatalog/Pages/AcrylicPage.xaml
+++ b/samples/ControlCatalog/Pages/AcrylicPage.xaml
@@ -16,13 +16,13 @@
-
-
+
+
-
-
+
+
diff --git a/samples/ControlCatalog/Pages/SliderPage.xaml b/samples/ControlCatalog/Pages/SliderPage.xaml
index eeb198976b..b4901ec780 100644
--- a/samples/ControlCatalog/Pages/SliderPage.xaml
+++ b/samples/ControlCatalog/Pages/SliderPage.xaml
@@ -45,6 +45,12 @@
+
+
diff --git a/src/Avalonia.Animation/Animation.cs b/src/Avalonia.Animation/Animation.cs
index ca1d97290e..05142532e9 100644
--- a/src/Avalonia.Animation/Animation.cs
+++ b/src/Avalonia.Animation/Animation.cs
@@ -22,7 +22,7 @@ namespace Avalonia.Animation
///
public static readonly DirectProperty DurationProperty =
AvaloniaProperty.RegisterDirect(
- nameof(_duration),
+ nameof(Duration),
o => o._duration,
(o, v) => o._duration = v);
@@ -31,7 +31,7 @@ namespace Avalonia.Animation
///
public static readonly DirectProperty IterationCountProperty =
AvaloniaProperty.RegisterDirect(
- nameof(_iterationCount),
+ nameof(IterationCount),
o => o._iterationCount,
(o, v) => o._iterationCount = v);
@@ -40,7 +40,7 @@ namespace Avalonia.Animation
///
public static readonly DirectProperty PlaybackDirectionProperty =
AvaloniaProperty.RegisterDirect(
- nameof(_playbackDirection),
+ nameof(PlaybackDirection),
o => o._playbackDirection,
(o, v) => o._playbackDirection = v);
@@ -49,7 +49,7 @@ namespace Avalonia.Animation
///
public static readonly DirectProperty FillModeProperty =
AvaloniaProperty.RegisterDirect(
- nameof(_fillMode),
+ nameof(FillMode),
o => o._fillMode,
(o, v) => o._fillMode = v);
@@ -58,7 +58,7 @@ namespace Avalonia.Animation
///
public static readonly DirectProperty EasingProperty =
AvaloniaProperty.RegisterDirect(
- nameof(_easing),
+ nameof(Easing),
o => o._easing,
(o, v) => o._easing = v);
@@ -67,7 +67,7 @@ namespace Avalonia.Animation
///
public static readonly DirectProperty DelayProperty =
AvaloniaProperty.RegisterDirect(
- nameof(_delay),
+ nameof(Delay),
o => o._delay,
(o, v) => o._delay = v);
@@ -76,7 +76,7 @@ namespace Avalonia.Animation
///
public static readonly DirectProperty DelayBetweenIterationsProperty =
AvaloniaProperty.RegisterDirect(
- nameof(_delayBetweenIterations),
+ nameof(DelayBetweenIterations),
o => o._delayBetweenIterations,
(o, v) => o._delayBetweenIterations = v);
@@ -85,7 +85,7 @@ namespace Avalonia.Animation
///
public static readonly DirectProperty SpeedRatioProperty =
AvaloniaProperty.RegisterDirect(
- nameof(_speedRatio),
+ nameof(SpeedRatio),
o => o._speedRatio,
(o, v) => o._speedRatio = v,
defaultBindingMode: BindingMode.TwoWay);
diff --git a/src/Avalonia.Controls.DataGrid/DataGridTemplateColumn.cs b/src/Avalonia.Controls.DataGrid/DataGridTemplateColumn.cs
index e513a7b678..7e95dd100c 100644
--- a/src/Avalonia.Controls.DataGrid/DataGridTemplateColumn.cs
+++ b/src/Avalonia.Controls.DataGrid/DataGridTemplateColumn.cs
@@ -8,6 +8,7 @@ using Avalonia.Controls.Utils;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Media;
+using Avalonia.Metadata;
using Avalonia.Utilities;
namespace Avalonia.Controls
@@ -22,6 +23,7 @@ namespace Avalonia.Controls
o => o.CellTemplate,
(o, v) => o.CellTemplate = v);
+ [Content]
public IDataTemplate CellTemplate
{
get { return _cellTemplate; }
diff --git a/src/Avalonia.Controls/Generators/TabItemContainerGenerator.cs b/src/Avalonia.Controls/Generators/TabItemContainerGenerator.cs
index d2e05ee136..840a1f66f1 100644
--- a/src/Avalonia.Controls/Generators/TabItemContainerGenerator.cs
+++ b/src/Avalonia.Controls/Generators/TabItemContainerGenerator.cs
@@ -1,4 +1,10 @@
+using System;
+using System.Collections.Generic;
using Avalonia.Controls.Primitives;
+using Avalonia.Controls.Templates;
+using Avalonia.LogicalTree;
+using Avalonia.Reactive;
+using Avalonia.VisualTree;
namespace Avalonia.Controls.Generators
{
@@ -16,11 +22,15 @@ namespace Avalonia.Controls.Generators
{
var tabItem = (TabItem)base.CreateContainer(item);
- tabItem[~TabControl.TabStripPlacementProperty] = Owner[~TabControl.TabStripPlacementProperty];
+ tabItem.Bind(TabItem.TabStripPlacementProperty, new OwnerBinding(
+ tabItem,
+ TabControl.TabStripPlacementProperty));
if (tabItem.HeaderTemplate == null)
{
- tabItem[~HeaderedContentControl.HeaderTemplateProperty] = Owner[~ItemsControl.ItemTemplateProperty];
+ tabItem.Bind(TabItem.HeaderTemplateProperty, new OwnerBinding(
+ tabItem,
+ TabControl.ItemTemplateProperty));
}
if (tabItem.Header == null)
@@ -40,10 +50,49 @@ namespace Avalonia.Controls.Generators
if (!(tabItem.Content is IControl))
{
- tabItem[~ContentControl.ContentTemplateProperty] = Owner[~TabControl.ContentTemplateProperty];
+ tabItem.Bind(TabItem.ContentTemplateProperty, new OwnerBinding(
+ tabItem,
+ TabControl.ContentTemplateProperty));
}
return tabItem;
}
+
+ private class OwnerBinding : SingleSubscriberObservableBase
+ {
+ private readonly TabItem _item;
+ private readonly StyledProperty _ownerProperty;
+ private IDisposable _ownerSubscription;
+ private IDisposable _propertySubscription;
+
+ public OwnerBinding(TabItem item, StyledProperty ownerProperty)
+ {
+ _item = item;
+ _ownerProperty = ownerProperty;
+ }
+
+ protected override void Subscribed()
+ {
+ _ownerSubscription = ControlLocator.Track(_item, 0, typeof(TabControl)).Subscribe(OwnerChanged);
+ }
+
+ protected override void Unsubscribed()
+ {
+ _ownerSubscription?.Dispose();
+ _ownerSubscription = null;
+ }
+
+ private void OwnerChanged(ILogical c)
+ {
+ _propertySubscription?.Dispose();
+ _propertySubscription = null;
+
+ if (c is TabControl tabControl)
+ {
+ _propertySubscription = tabControl.GetObservable(_ownerProperty)
+ .Subscribe(x => PublishNext(x));
+ }
+ }
+ }
}
}
diff --git a/src/Avalonia.Controls/NativeControlHost.cs b/src/Avalonia.Controls/NativeControlHost.cs
index 20eac11c2c..64414b1f47 100644
--- a/src/Avalonia.Controls/NativeControlHost.cs
+++ b/src/Avalonia.Controls/NativeControlHost.cs
@@ -157,10 +157,14 @@ namespace Avalonia.Controls
var needsShow = IsEffectivelyVisible && bounds.HasValue;
if (needsShow)
+ {
+ if (bounds.Value.IsEmpty)
+ return false;
_attachment?.ShowInBounds(bounds.Value);
+ }
else
_attachment?.HideWithSize(Bounds.Size);
- return false;
+ return true;
}
private void CheckDestruction()
diff --git a/src/Avalonia.Controls/Slider.cs b/src/Avalonia.Controls/Slider.cs
index 74de33529a..e02efc2bd2 100644
--- a/src/Avalonia.Controls/Slider.cs
+++ b/src/Avalonia.Controls/Slider.cs
@@ -49,6 +49,12 @@ namespace Avalonia.Controls
public static readonly StyledProperty OrientationProperty =
ScrollBar.OrientationProperty.AddOwner();
+ ///
+ /// Defines the property.
+ ///
+ public static readonly StyledProperty IsDirectionReversedProperty =
+ Track.IsDirectionReversedProperty.AddOwner();
+
///
/// Defines the property.
///
@@ -83,7 +89,6 @@ namespace Avalonia.Controls
private IDisposable _increaseButtonSubscription;
private IDisposable _increaseButtonReleaseDispose;
private IDisposable _pointerMovedDispose;
- private IDisposable _trackOnKeyDownDispose;
private const double Tolerance = 0.0001;
@@ -93,6 +98,7 @@ namespace Avalonia.Controls
static Slider()
{
PressedMixin.Attach();
+ FocusableProperty.OverrideDefaultValue(true);
OrientationProperty.OverrideDefaultValue(typeof(Slider), Orientation.Horizontal);
Thumb.DragStartedEvent.AddClassHandler((x, e) => x.OnThumbDragStarted(e), RoutingStrategies.Bubble);
Thumb.DragCompletedEvent.AddClassHandler((x, e) => x.OnThumbDragCompleted(e),
@@ -127,6 +133,19 @@ namespace Avalonia.Controls
set { SetValue(OrientationProperty, value); }
}
+ ///
+ /// Gets or sets the direction of increasing value.
+ ///
+ ///
+ /// true if the direction of increasing value is to the left for a horizontal slider or
+ /// down for a vertical slider; otherwise, false. The default is false.
+ ///
+ public bool IsDirectionReversed
+ {
+ get { return GetValue(IsDirectionReversedProperty); }
+ set { SetValue(IsDirectionReversedProperty, value); }
+ }
+
///
/// Gets or sets a value that indicates whether the automatically moves the to the closest tick mark.
///
@@ -165,7 +184,6 @@ namespace Avalonia.Controls
_increaseButtonSubscription?.Dispose();
_increaseButtonReleaseDispose?.Dispose();
_pointerMovedDispose?.Dispose();
- _trackOnKeyDownDispose?.Dispose();
_decreaseButton = e.NameScope.Find