mirror of
https://github.com/AtomUI/AtomUI.git
synced 2026-10-29 15:19:12 +08:00
完成禁用样式和选择checkbox和radio的数据关联
This commit is contained in:
@@ -22,6 +22,7 @@
|
||||
<atom:MenuSeparator />
|
||||
<atom:MenuItem Header="Cut" InputGesture="Ctrl+X" />
|
||||
</atom:MenuItem>
|
||||
<atom:MenuItem Header="Disabled Item" IsEnabled="False" />
|
||||
</atom:Menu>
|
||||
</showcase:ShowCaseItem>
|
||||
|
||||
@@ -72,6 +73,7 @@
|
||||
Icon="{atom:IconProvider Kind=CheckOutlined}" />
|
||||
<atom:MenuSeparator />
|
||||
<atom:MenuItem Header="Exit" />
|
||||
<atom:MenuItem Header="Disabled" IsEnabled="False"/>
|
||||
</atom:MenuItem>
|
||||
</atom:Menu>
|
||||
</showcase:ShowCaseItem>
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
using System.Reactive.Disposables;
|
||||
using AtomUI.Data;
|
||||
using AtomUI.Styling;
|
||||
using AtomUI.Styling;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
@@ -8,7 +6,6 @@ using Avalonia.Controls.Diagnostics;
|
||||
using Avalonia.Controls.Primitives.PopupPositioning;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Input.Raw;
|
||||
using Avalonia.LogicalTree;
|
||||
using Avalonia.Metadata;
|
||||
using Avalonia.Threading;
|
||||
|
||||
@@ -146,7 +143,6 @@ public class FlyoutHost : Control
|
||||
}
|
||||
|
||||
private bool _initialized = false;
|
||||
private CompositeDisposable? _compositeDisposable;
|
||||
private DispatcherTimer? _mouseEnterDelayTimer;
|
||||
private DispatcherTimer? _mouseLeaveDelayTimer;
|
||||
|
||||
@@ -171,7 +167,6 @@ public class FlyoutHost : Control
|
||||
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
|
||||
{
|
||||
base.OnAttachedToVisualTree(e);
|
||||
_compositeDisposable = new CompositeDisposable();
|
||||
SetupTriggerHandler();
|
||||
SetupFlyoutProperties();
|
||||
}
|
||||
@@ -179,7 +174,6 @@ public class FlyoutHost : Control
|
||||
protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
|
||||
{
|
||||
base.OnDetachedFromVisualTree(e);
|
||||
_compositeDisposable?.Dispose();
|
||||
StopMouseLeaveTimer();
|
||||
StopMouseEnterTimer();
|
||||
}
|
||||
@@ -187,12 +181,12 @@ public class FlyoutHost : Control
|
||||
private void SetupFlyoutProperties()
|
||||
{
|
||||
if (Flyout is not null) {
|
||||
_compositeDisposable?.Add(BindUtils.RelayBind(this, PlacementProperty, Flyout));
|
||||
_compositeDisposable?.Add(BindUtils.RelayBind(this, PlacementAnchorProperty, Flyout));
|
||||
_compositeDisposable?.Add(BindUtils.RelayBind(this, PlacementGravityProperty, Flyout));
|
||||
_compositeDisposable?.Add(BindUtils.RelayBind(this, IsShowArrowProperty, Flyout));
|
||||
_compositeDisposable?.Add(BindUtils.RelayBind(this, IsPointAtCenterProperty, Flyout));
|
||||
_compositeDisposable?.Add(BindUtils.RelayBind(this, MarginToAnchorProperty, Flyout));
|
||||
BindUtils.RelayBind(this, PlacementProperty, Flyout);
|
||||
BindUtils.RelayBind(this, PlacementAnchorProperty, Flyout);
|
||||
BindUtils.RelayBind(this, PlacementGravityProperty, Flyout);
|
||||
BindUtils.RelayBind(this, IsShowArrowProperty, Flyout);
|
||||
BindUtils.RelayBind(this, IsPointAtCenterProperty, Flyout);
|
||||
BindUtils.RelayBind(this, MarginToAnchorProperty, Flyout);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -202,22 +196,22 @@ public class FlyoutHost : Control
|
||||
return;
|
||||
}
|
||||
if (Trigger == FlyoutTriggerType.Hover) {
|
||||
_compositeDisposable?.Add(IsPointerOverProperty.Changed.Subscribe(args =>
|
||||
IsPointerOverProperty.Changed.Subscribe(args =>
|
||||
{
|
||||
if (args.Sender == AnchorTarget) {
|
||||
HandleAnchorTargetHover(args);
|
||||
}
|
||||
}));
|
||||
});
|
||||
} else if (Trigger == FlyoutTriggerType.Focus) {
|
||||
_compositeDisposable?.Add(IsFocusedProperty.Changed.Subscribe(args =>
|
||||
IsFocusedProperty.Changed.Subscribe(args =>
|
||||
{
|
||||
if (args.Sender == AnchorTarget) {
|
||||
HandleAnchorTargetFocus(args);
|
||||
}
|
||||
}));
|
||||
});
|
||||
} else if (Trigger == FlyoutTriggerType.Click) {
|
||||
var inputManager = AvaloniaLocator.Current.GetService<IInputManager>()!;
|
||||
_compositeDisposable?.Add(inputManager.Process.Subscribe(HandleAnchorTargetClick));
|
||||
inputManager.Process.Subscribe(HandleAnchorTargetClick);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using AtomUI.Styling;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Presenters;
|
||||
using Avalonia.Controls.Templates;
|
||||
|
||||
@@ -108,10 +108,15 @@ public class MenuItem : AvaloniaMenuItem, IControlCustomStyle
|
||||
_togglePresenter.Presenter.IsVisible = false;
|
||||
}
|
||||
} else if (ToggleType == MenuItemToggleType.CheckBox) {
|
||||
_togglePresenter.Content = new CheckBox();
|
||||
var checkbox = new CheckBox();
|
||||
BindUtils.RelayBind(this, IsCheckedProperty, checkbox, CheckBox.IsCheckedProperty);
|
||||
_togglePresenter.Content = checkbox;
|
||||
_togglePresenter.IsVisible = true;
|
||||
} else if (ToggleType == MenuItemToggleType.Radio) {
|
||||
_togglePresenter.Content = new RadioButton();
|
||||
var radioButton = new RadioButton();
|
||||
BindUtils.RelayBind(this, IsCheckedProperty, radioButton, RadioButton.IsCheckedProperty);
|
||||
BindUtils.RelayBind(this, GroupNameProperty, radioButton, RadioButton.GroupNameProperty);
|
||||
_togglePresenter.Content = radioButton;
|
||||
_togglePresenter.IsVisible = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,6 +79,7 @@ internal class MenuItemTheme : ControlTheme
|
||||
VerticalAlignment = VerticalAlignment.Center,
|
||||
IsVisible = false
|
||||
};
|
||||
CreateTemplateParentBinding(togglePresenter, ContentControl.IsEnabledProperty, MenuItem.IsEnabledProperty);
|
||||
Grid.SetColumn(togglePresenter, 0);
|
||||
togglePresenter.RegisterInNameScope(scope);
|
||||
|
||||
@@ -202,6 +203,7 @@ internal class MenuItemTheme : ControlTheme
|
||||
BuildMenuIndicatorStyle();
|
||||
BuildMenuIconStyle();
|
||||
Add(commonStyle);
|
||||
BuildDisabledStyle();
|
||||
}
|
||||
|
||||
private void BuildCommonStyle(Style commonStyle)
|
||||
@@ -264,4 +266,11 @@ internal class MenuItemTheme : ControlTheme
|
||||
}
|
||||
Add(hasIconStyle);
|
||||
}
|
||||
|
||||
private void BuildDisabledStyle()
|
||||
{
|
||||
var disabledStyle = new Style(selector => selector.Nesting().Class(StdPseudoClass.Disabled));
|
||||
disabledStyle.Add(MenuItem.ForegroundProperty, MenuResourceKey.ItemDisabledColor);
|
||||
Add(disabledStyle);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
using AtomUI.Controls.Utils;
|
||||
using AtomUI.Data;
|
||||
using AtomUI.Media;
|
||||
using AtomUI.Styling;
|
||||
using AtomUI.Utils;
|
||||
@@ -7,10 +6,8 @@ using Avalonia;
|
||||
using Avalonia.Animation;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Data;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Layout;
|
||||
using Avalonia.LogicalTree;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Rendering;
|
||||
|
||||
@@ -18,98 +15,98 @@ namespace AtomUI.Controls;
|
||||
|
||||
using AvaloniaRadioButton = Avalonia.Controls.RadioButton;
|
||||
|
||||
public partial class RadioButton : AvaloniaRadioButton,
|
||||
ICustomHitTest,
|
||||
IWaveAdornerInfoProvider,
|
||||
IControlCustomStyle
|
||||
public class RadioButton : AvaloniaRadioButton,
|
||||
ICustomHitTest,
|
||||
IWaveAdornerInfoProvider,
|
||||
IControlCustomStyle
|
||||
{
|
||||
internal static readonly StyledProperty<double> RadioSizeProperty =
|
||||
AvaloniaProperty.Register<Button, double>(nameof(RadioSize), 0);
|
||||
|
||||
|
||||
internal static readonly StyledProperty<double> PaddingInlineProperty =
|
||||
AvaloniaProperty.Register<Button, double>(nameof(PaddingInline), 0);
|
||||
|
||||
|
||||
internal static readonly StyledProperty<IBrush?> RadioBorderBrushProperty =
|
||||
AvaloniaProperty.Register<Button, IBrush?>(nameof(RadioBorderBrush));
|
||||
|
||||
|
||||
internal static readonly StyledProperty<IBrush?> RadioInnerBackgroundProperty =
|
||||
AvaloniaProperty.Register<Button, IBrush?>(nameof(RadioInnerBackground));
|
||||
|
||||
|
||||
internal static readonly StyledProperty<IBrush?> RadioBackgroundProperty =
|
||||
AvaloniaProperty.Register<Button, IBrush?>(nameof(RadioBackground));
|
||||
|
||||
|
||||
internal static readonly StyledProperty<Thickness> RadioBorderThicknessProperty =
|
||||
AvaloniaProperty.Register<Button, Thickness>(nameof(RadioBorderThickness));
|
||||
|
||||
|
||||
internal static readonly StyledProperty<double> RadioDotEffectSizeProperty =
|
||||
AvaloniaProperty.Register<Button, double>(nameof(RadioDotEffectSize));
|
||||
|
||||
|
||||
internal static readonly StyledProperty<double> DotSizeValueProperty =
|
||||
AvaloniaProperty.Register<RadioButton, double>(
|
||||
nameof(DotSizeValue));
|
||||
|
||||
|
||||
internal static readonly StyledProperty<double> DotPaddingProperty =
|
||||
AvaloniaProperty.Register<RadioButton, double>(
|
||||
nameof(DotPadding));
|
||||
|
||||
|
||||
internal double RadioSize
|
||||
{
|
||||
get => GetValue(RadioSizeProperty);
|
||||
set => SetValue(RadioSizeProperty, value);
|
||||
}
|
||||
|
||||
|
||||
internal double PaddingInline
|
||||
{
|
||||
get => GetValue(PaddingInlineProperty);
|
||||
set => SetValue(PaddingInlineProperty, value);
|
||||
}
|
||||
|
||||
|
||||
internal IBrush? RadioBorderBrush
|
||||
{
|
||||
get => GetValue(RadioBorderBrushProperty);
|
||||
set => SetValue(RadioBorderBrushProperty, value);
|
||||
}
|
||||
|
||||
|
||||
internal IBrush? RadioInnerBackground
|
||||
{
|
||||
get => GetValue(RadioInnerBackgroundProperty);
|
||||
set => SetValue(RadioInnerBackgroundProperty, value);
|
||||
}
|
||||
|
||||
|
||||
internal IBrush? RadioBackground
|
||||
{
|
||||
get => GetValue(RadioBackgroundProperty);
|
||||
set => SetValue(RadioBackgroundProperty, value);
|
||||
}
|
||||
|
||||
|
||||
internal Thickness RadioBorderThickness
|
||||
{
|
||||
get => GetValue(RadioBorderThicknessProperty);
|
||||
set => SetValue(RadioBorderThicknessProperty, value);
|
||||
}
|
||||
|
||||
|
||||
internal double RadioDotEffectSize
|
||||
{
|
||||
get => GetValue(RadioDotEffectSizeProperty);
|
||||
set => SetValue(RadioDotEffectSizeProperty, value);
|
||||
}
|
||||
|
||||
|
||||
internal double DotSizeValue
|
||||
{
|
||||
get => GetValue(DotSizeValueProperty);
|
||||
set => SetValue(DotSizeValueProperty, value);
|
||||
}
|
||||
|
||||
|
||||
internal double DotPadding
|
||||
{
|
||||
get => GetValue(DotPaddingProperty);
|
||||
set => SetValue(DotPaddingProperty, value);
|
||||
}
|
||||
|
||||
|
||||
private IPen? _cachedPen;
|
||||
private ControlStyleState _styleState;
|
||||
private IControlCustomStyle _customStyle;
|
||||
|
||||
|
||||
static RadioButton()
|
||||
{
|
||||
AffectsRender<RadioButton>(
|
||||
@@ -130,7 +127,7 @@ public partial class RadioButton : AvaloniaRadioButton,
|
||||
base.OnPropertyChanged(e);
|
||||
_customStyle.HandlePropertyChangedForStyle(e);
|
||||
}
|
||||
|
||||
|
||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||
{
|
||||
base.OnApplyTemplate(e);
|
||||
@@ -180,14 +177,13 @@ public partial class RadioButton : AvaloniaRadioButton,
|
||||
var dotDiameter = RadioDotEffectSize / 2;
|
||||
context.DrawEllipse(RadioInnerBackground, null, radioRect.Center, dotDiameter, dotDiameter);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public bool HitTest(Point point)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#region IControlCustomStyle 实现
|
||||
|
||||
void IControlCustomStyle.CollectStyleState()
|
||||
@@ -218,6 +214,7 @@ public partial class RadioButton : AvaloniaRadioButton,
|
||||
} else {
|
||||
targetValue = DotSizeValue * 0.6;
|
||||
}
|
||||
|
||||
return targetValue;
|
||||
}
|
||||
|
||||
@@ -227,7 +224,8 @@ public partial class RadioButton : AvaloniaRadioButton,
|
||||
{
|
||||
AnimationUtils.CreateTransition<SolidColorBrushTransition>(RadioBorderBrushProperty),
|
||||
AnimationUtils.CreateTransition<DoubleTransition>(RadioDotEffectSizeProperty),
|
||||
AnimationUtils.CreateTransition<SolidColorBrushTransition>(RadioBackgroundProperty, GlobalResourceKey.MotionDurationFast)
|
||||
AnimationUtils.CreateTransition<SolidColorBrushTransition>(RadioBackgroundProperty,
|
||||
GlobalResourceKey.MotionDurationFast)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -243,7 +241,7 @@ public partial class RadioButton : AvaloniaRadioButton,
|
||||
var offsetX = RadioSize + PaddingInline;
|
||||
return new Rect(offsetX, 0d, DesiredSize.Width - offsetX, DesiredSize.Height);
|
||||
}
|
||||
|
||||
|
||||
void IControlCustomStyle.HandlePropertyChangedForStyle(AvaloniaPropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.Property == IsPointerOverProperty ||
|
||||
@@ -253,7 +251,8 @@ public partial class RadioButton : AvaloniaRadioButton,
|
||||
if (VisualRoot is not null) {
|
||||
RadioDotEffectSize = CalculateDotSize(IsEnabled, IsChecked.HasValue && IsChecked.Value);
|
||||
}
|
||||
if (e.Property == IsCheckedProperty &&
|
||||
|
||||
if (e.Property == IsCheckedProperty &&
|
||||
_styleState.HasFlag(ControlStyleState.Enabled) &&
|
||||
_styleState.HasFlag(ControlStyleState.On)) {
|
||||
WaveSpiritAdorner.ShowWaveAdorner(this, WaveType.CircleWave);
|
||||
@@ -265,10 +264,11 @@ public partial class RadioButton : AvaloniaRadioButton,
|
||||
{
|
||||
return RadioRect();
|
||||
}
|
||||
|
||||
|
||||
public CornerRadius WaveBorderRadius()
|
||||
{
|
||||
return new CornerRadius(RadioSize / 2);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
Reference in New Issue
Block a user