add HorizontalContentAlignment

This commit is contained in:
heartacker
2024-03-20 15:48:21 +08:00
parent af13b9a539
commit 795abc9929
2 changed files with 47 additions and 36 deletions

View File

@@ -3,7 +3,7 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:u="https://irihi.tech/ursa"> xmlns:u="https://irihi.tech/ursa">
<!-- Add Resources Here --> <!-- Add Resources Here -->
<ControlTheme x:Key="InputClearButton" TargetType="Button"> <ControlTheme x:Key="InputClearButton" TargetType="Button">
<Setter Property="Button.Foreground" Value="{DynamicResource TextBoxButtonDefaultForeground}" /> <Setter Property="Button.Foreground" Value="{DynamicResource TextBoxButtonDefaultForeground}" />
<Setter Property="Button.Cursor" Value="Hand" /> <Setter Property="Button.Cursor" Value="Hand" />
@@ -23,7 +23,7 @@
<Setter Property="Foreground" Value="{DynamicResource TextBoxButtonPointeroverForeground}" /> <Setter Property="Foreground" Value="{DynamicResource TextBoxButtonPointeroverForeground}" />
</Style> </Style>
</ControlTheme> </ControlTheme>
<ControlTheme x:Key="{x:Type u:NumericUpDown}" TargetType="{x:Type u:NumericUpDown}"> <ControlTheme x:Key="{x:Type u:NumericUpDown}" TargetType="{x:Type u:NumericUpDown}">
<Setter Property="NumericUpDown.VerticalContentAlignment" Value="Center" /> <Setter Property="NumericUpDown.VerticalContentAlignment" Value="Center" />
<Setter Property="NumericUpDown.CornerRadius" Value="{DynamicResource NumericUpDownCornerRadius}" /> <Setter Property="NumericUpDown.CornerRadius" Value="{DynamicResource NumericUpDownCornerRadius}" />
@@ -50,6 +50,7 @@
DataValidationErrors.Errors="{ReflectionBinding $parent[NumericUpDown].(DataValidationErrors.Errors)}" DataValidationErrors.Errors="{ReflectionBinding $parent[NumericUpDown].(DataValidationErrors.Errors)}"
FontSize="{TemplateBinding FontSize}" FontSize="{TemplateBinding FontSize}"
Foreground="{TemplateBinding Foreground}" Foreground="{TemplateBinding Foreground}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
IsReadOnly="{TemplateBinding IsReadOnly}" IsReadOnly="{TemplateBinding IsReadOnly}"
TextWrapping="NoWrap" TextWrapping="NoWrap"
InnerLeftContent="{TemplateBinding InnerLeftContent}" InnerLeftContent="{TemplateBinding InnerLeftContent}"
@@ -75,7 +76,7 @@
</DataValidationErrors> </DataValidationErrors>
</ControlTemplate> </ControlTemplate>
</Setter> </Setter>
<Style Selector="^.clearButton, ^.ClearButton"> <Style Selector="^.clearButton, ^.ClearButton">
<Style Selector="^[IsReadOnly=False]:focus /template/ Button#PART_ClearButton"> <Style Selector="^[IsReadOnly=False]:focus /template/ Button#PART_ClearButton">
<Setter Property="IsVisible" Value="True" /> <Setter Property="IsVisible" Value="True" />

View File

@@ -9,6 +9,7 @@ using Avalonia.Data;
using Avalonia.Data.Converters; using Avalonia.Data.Converters;
using Avalonia.Input; using Avalonia.Input;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Avalonia.Layout;
using Irihi.Avalonia.Shared.Contracts; using Irihi.Avalonia.Shared.Contracts;
namespace Ursa.Controls; namespace Ursa.Controls;
@@ -21,14 +22,14 @@ public abstract class NumericUpDown : TemplatedControl, IClearControl
public const string PART_Spinner = "PART_Spinner"; public const string PART_Spinner = "PART_Spinner";
public const string PART_TextBox = "PART_TextBox"; public const string PART_TextBox = "PART_TextBox";
public const string PART_DragPanel = "PART_DragPanel"; public const string PART_DragPanel = "PART_DragPanel";
protected internal ButtonSpinner? _spinner; protected internal ButtonSpinner? _spinner;
protected internal TextBox? _textBox; protected internal TextBox? _textBox;
protected internal Panel? _dragPanel; protected internal Panel? _dragPanel;
private Point? _point; private Point? _point;
protected internal bool _updateFromTextInput; protected internal bool _updateFromTextInput;
public static readonly StyledProperty<bool> AllowDragProperty = AvaloniaProperty.Register<NumericUpDown, bool>( public static readonly StyledProperty<bool> AllowDragProperty = AvaloniaProperty.Register<NumericUpDown, bool>(
nameof(AllowDrag), defaultValue: false); nameof(AllowDrag), defaultValue: false);
@@ -47,6 +48,15 @@ public abstract class NumericUpDown : TemplatedControl, IClearControl
set => SetValue(IsReadOnlyProperty, value); set => SetValue(IsReadOnlyProperty, value);
} }
public static readonly StyledProperty<HorizontalAlignment> HorizontalContentAlignmentProperty = AvaloniaProperty.Register<NumericUpDown, HorizontalAlignment>(
nameof(HorizontalContentAlignment), HorizontalAlignment.Left);
public HorizontalAlignment HorizontalContentAlignment
{
get => GetValue(HorizontalContentAlignmentProperty);
set => SetValue(HorizontalContentAlignmentProperty, value);
}
public static readonly StyledProperty<object?> InnerLeftContentProperty = AvaloniaProperty.Register<NumericUpDown, object?>( public static readonly StyledProperty<object?> InnerLeftContentProperty = AvaloniaProperty.Register<NumericUpDown, object?>(
nameof(InnerLeftContent)); nameof(InnerLeftContent));
@@ -120,12 +130,12 @@ public abstract class NumericUpDown : TemplatedControl, IClearControl
} }
public event EventHandler<SpinEventArgs>? Spinned; public event EventHandler<SpinEventArgs>? Spinned;
static NumericUpDown() static NumericUpDown()
{ {
NumberFormatProperty.Changed.AddClassHandler<NumericUpDown>((o, e) => o.OnFormatChange(e)); NumberFormatProperty.Changed.AddClassHandler<NumericUpDown>((o, e) => o.OnFormatChange(e));
FormatStringProperty.Changed.AddClassHandler<NumericUpDown>((o, e) => o.OnFormatChange(e)); FormatStringProperty.Changed.AddClassHandler<NumericUpDown>((o, e) => o.OnFormatChange(e));
IsReadOnlyProperty.Changed.AddClassHandler<NumericUpDown>((o,e)=>o.ChangeToSetSpinDirection(e)); IsReadOnlyProperty.Changed.AddClassHandler<NumericUpDown>((o, e) => o.ChangeToSetSpinDirection(e));
TextConverterProperty.Changed.AddClassHandler<NumericUpDown>((o, e) => o.OnFormatChange(e)); TextConverterProperty.Changed.AddClassHandler<NumericUpDown>((o, e) => o.OnFormatChange(e));
} }
@@ -155,7 +165,7 @@ public abstract class NumericUpDown : TemplatedControl, IClearControl
protected override void OnApplyTemplate(TemplateAppliedEventArgs e) protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
{ {
base.OnApplyTemplate(e); base.OnApplyTemplate(e);
if(_spinner is not null) if (_spinner is not null)
{ {
_spinner.Spin -= OnSpin; _spinner.Spin -= OnSpin;
} }
@@ -174,18 +184,18 @@ public abstract class NumericUpDown : TemplatedControl, IClearControl
} }
if (_dragPanel is not null) if (_dragPanel is not null)
{ {
_dragPanel.PointerPressed+= OnDragPanelPointerPressed; _dragPanel.PointerPressed += OnDragPanelPointerPressed;
_dragPanel.PointerMoved += OnDragPanelPointerMoved; _dragPanel.PointerMoved += OnDragPanelPointerMoved;
_dragPanel.PointerReleased += OnDragPanelPointerReleased; _dragPanel.PointerReleased += OnDragPanelPointerReleased;
} }
} }
protected override void OnLostFocus(RoutedEventArgs e) protected override void OnLostFocus(RoutedEventArgs e)
{ {
CommitInput(true); CommitInput(true);
base.OnLostFocus(e); base.OnLostFocus(e);
if(AllowDrag && _dragPanel is not null) if (AllowDrag && _dragPanel is not null)
{ {
_dragPanel.IsVisible = true; _dragPanel.IsVisible = true;
} }
@@ -233,11 +243,11 @@ public abstract class NumericUpDown : TemplatedControl, IClearControl
{ {
_point = null; _point = null;
} }
private void OnDragPanelPointerMoved(object sender, PointerEventArgs e) private void OnDragPanelPointerMoved(object sender, PointerEventArgs e)
{ {
if (!AllowDrag || IsReadOnly) return; if (!AllowDrag || IsReadOnly) return;
if(!e.GetCurrentPoint(this).Properties.IsLeftButtonPressed) return; if (!e.GetCurrentPoint(this).Properties.IsLeftButtonPressed) return;
var point = e.GetPosition(this); var point = e.GetPosition(this);
var delta = point - _point; var delta = point - _point;
if (delta is null) if (delta is null)
@@ -245,7 +255,7 @@ public abstract class NumericUpDown : TemplatedControl, IClearControl
return; return;
} }
int d = GetDelta(delta.Value); int d = GetDelta(delta.Value);
if(d > 0) if (d > 0)
{ {
Increase(); Increase();
} }
@@ -267,7 +277,7 @@ public abstract class NumericUpDown : TemplatedControl, IClearControl
_ => 0 _ => 0
}; };
} }
private void OnSpin(object sender, SpinEventArgs e) private void OnSpin(object sender, SpinEventArgs e)
{ {
if (AllowSpin && !IsReadOnly) if (AllowSpin && !IsReadOnly)
@@ -307,7 +317,7 @@ public abstract class NumericUpDown : TemplatedControl, IClearControl
public abstract void Clear(); public abstract void Clear();
} }
public abstract class NumericUpDownBase<T>: NumericUpDown where T: struct, IComparable<T> public abstract class NumericUpDownBase<T> : NumericUpDown where T : struct, IComparable<T>
{ {
public static readonly StyledProperty<T?> ValueProperty = AvaloniaProperty.Register<NumericUpDownBase<T>, T?>( public static readonly StyledProperty<T?> ValueProperty = AvaloniaProperty.Register<NumericUpDownBase<T>, T?>(
nameof(Value), defaultBindingMode: BindingMode.TwoWay); nameof(Value), defaultBindingMode: BindingMode.TwoWay);
@@ -319,8 +329,8 @@ public abstract class NumericUpDownBase<T>: NumericUpDown where T: struct, IComp
} }
public static readonly StyledProperty<T> MaximumProperty = AvaloniaProperty.Register<NumericUpDownBase<T>, T>( public static readonly StyledProperty<T> MaximumProperty = AvaloniaProperty.Register<NumericUpDownBase<T>, T>(
nameof(Maximum), defaultBindingMode:BindingMode.TwoWay, coerce: CoerceMaximum); nameof(Maximum), defaultBindingMode: BindingMode.TwoWay, coerce: CoerceMaximum);
public T Maximum public T Maximum
{ {
get => GetValue(MaximumProperty); get => GetValue(MaximumProperty);
@@ -328,14 +338,14 @@ public abstract class NumericUpDownBase<T>: NumericUpDown where T: struct, IComp
} }
public static readonly StyledProperty<T> MinimumProperty = AvaloniaProperty.Register<NumericUpDownBase<T>, T>( public static readonly StyledProperty<T> MinimumProperty = AvaloniaProperty.Register<NumericUpDownBase<T>, T>(
nameof(Minimum), defaultBindingMode:BindingMode.TwoWay, coerce: CoerceMinimum); nameof(Minimum), defaultBindingMode: BindingMode.TwoWay, coerce: CoerceMinimum);
public T Minimum public T Minimum
{ {
get => GetValue(MinimumProperty); get => GetValue(MinimumProperty);
set => SetValue(MinimumProperty, value); set => SetValue(MinimumProperty, value);
} }
#region Max and Min Coerce #region Max and Min Coerce
private static T CoerceMaximum(AvaloniaObject instance, T value) private static T CoerceMaximum(AvaloniaObject instance, T value)
{ {
@@ -345,9 +355,9 @@ public abstract class NumericUpDownBase<T>: NumericUpDown where T: struct, IComp
} }
return value; return value;
} }
private T CoerceMaximum(T value) private T CoerceMaximum(T value)
{ {
if (value.CompareTo(Minimum) < 0) if (value.CompareTo(Minimum) < 0)
{ {
@@ -355,7 +365,7 @@ public abstract class NumericUpDownBase<T>: NumericUpDown where T: struct, IComp
} }
return value; return value;
} }
private static T CoerceMinimum(AvaloniaObject instance, T value) private static T CoerceMinimum(AvaloniaObject instance, T value)
{ {
if (instance is NumericUpDownBase<T> n) if (instance is NumericUpDownBase<T> n)
@@ -365,8 +375,8 @@ public abstract class NumericUpDownBase<T>: NumericUpDown where T: struct, IComp
return value; return value;
} }
private T CoerceMinimum(T value) private T CoerceMinimum(T value)
{ {
if (value.CompareTo(Maximum) > 0) if (value.CompareTo(Maximum) > 0)
{ {
@@ -374,7 +384,7 @@ public abstract class NumericUpDownBase<T>: NumericUpDown where T: struct, IComp
} }
return value; return value;
} }
#endregion #endregion
public static readonly StyledProperty<T> StepProperty = AvaloniaProperty.Register<NumericUpDownBase<T>, T>( public static readonly StyledProperty<T> StepProperty = AvaloniaProperty.Register<NumericUpDownBase<T>, T>(
@@ -395,7 +405,7 @@ public abstract class NumericUpDownBase<T>: NumericUpDown where T: struct, IComp
get => GetValue(EmptyInputValueProperty); get => GetValue(EmptyInputValueProperty);
set => SetValue(EmptyInputValueProperty, value); set => SetValue(EmptyInputValueProperty, value);
} }
/// <summary> /// <summary>
/// Defines the <see cref="ValueChanged"/> event. /// Defines the <see cref="ValueChanged"/> event.
/// </summary> /// </summary>
@@ -416,9 +426,9 @@ public abstract class NumericUpDownBase<T>: NumericUpDown where T: struct, IComp
StepProperty.Changed.AddClassHandler<NumericUpDownBase<T>>((o, e) => o.ChangeToSetSpinDirection(e)); StepProperty.Changed.AddClassHandler<NumericUpDownBase<T>>((o, e) => o.ChangeToSetSpinDirection(e));
MaximumProperty.Changed.AddClassHandler<NumericUpDownBase<T>>((o, e) => o.OnConstraintChanged(e)); MaximumProperty.Changed.AddClassHandler<NumericUpDownBase<T>>((o, e) => o.OnConstraintChanged(e));
MinimumProperty.Changed.AddClassHandler<NumericUpDownBase<T>>((o, e) => o.OnConstraintChanged(e)); MinimumProperty.Changed.AddClassHandler<NumericUpDownBase<T>>((o, e) => o.OnConstraintChanged(e));
ValueProperty.Changed.AddClassHandler<NumericUpDownBase<T>>((o, e) => o.OnValueChanged(e) ); ValueProperty.Changed.AddClassHandler<NumericUpDownBase<T>>((o, e) => o.OnValueChanged(e));
} }
private void OnConstraintChanged(AvaloniaPropertyChangedEventArgs avaloniaPropertyChangedEventArgs) private void OnConstraintChanged(AvaloniaPropertyChangedEventArgs avaloniaPropertyChangedEventArgs)
{ {
if (IsInitialized) if (IsInitialized)
@@ -430,7 +440,7 @@ public abstract class NumericUpDownBase<T>: NumericUpDown where T: struct, IComp
SetCurrentValue(ValueProperty, Clamp(Value, Maximum, Minimum)); SetCurrentValue(ValueProperty, Clamp(Value, Maximum, Minimum));
} }
} }
private void OnValueChanged(AvaloniaPropertyChangedEventArgs args) private void OnValueChanged(AvaloniaPropertyChangedEventArgs args)
{ {
if (IsInitialized) if (IsInitialized)
@@ -470,7 +480,7 @@ public abstract class NumericUpDownBase<T>: NumericUpDown where T: struct, IComp
} }
return value; return value;
} }
protected override void SetValidSpinDirection() protected override void SetValidSpinDirection()
{ {
var validDirection = ValidSpinDirections.None; var validDirection = ValidSpinDirections.None;
@@ -497,7 +507,7 @@ public abstract class NumericUpDownBase<T>: NumericUpDown where T: struct, IComp
} }
private bool _isSyncingTextAndValue; private bool _isSyncingTextAndValue;
protected override bool SyncTextAndValue(bool fromTextToValue = false, string? text = null, bool forceTextUpdate = false) protected override bool SyncTextAndValue(bool fromTextToValue = false, string? text = null, bool forceTextUpdate = false)
{ {
if (_isSyncingTextAndValue) return true; if (_isSyncingTextAndValue) return true;
@@ -530,7 +540,7 @@ public abstract class NumericUpDownBase<T>: NumericUpDown where T: struct, IComp
if (forceTextUpdate) if (forceTextUpdate)
{ {
var newText = ConvertValueToText(Value); var newText = ConvertValueToText(Value);
if (_textBox!= null && !Equals(_textBox.Text, newText)) if (_textBox != null && !Equals(_textBox.Text, newText))
{ {
_textBox.Text = newText; _textBox.Text = newText;
_textBox.CaretIndex = newText?.Length ?? 0; _textBox.CaretIndex = newText?.Length ?? 0;
@@ -592,7 +602,7 @@ public abstract class NumericUpDownBase<T>: NumericUpDown where T: struct, IComp
return ValueToString(Value); return ValueToString(Value);
} }
protected override void Increase() protected override void Increase()
{ {
T? value; T? value;
@@ -621,7 +631,7 @@ public abstract class NumericUpDownBase<T>: NumericUpDown where T: struct, IComp
SetCurrentValue(ValueProperty, Clamp(value, Maximum, Minimum)); SetCurrentValue(ValueProperty, Clamp(value, Maximum, Minimum));
} }
protected abstract bool ParseText(string? text, out T number); protected abstract bool ParseText(string? text, out T number);
protected abstract string? ValueToString(T? value); protected abstract string? ValueToString(T? value);
protected abstract T Zero { get; } protected abstract T Zero { get; }