mirror of
https://github.com/Artemis-RGB/Artemis
synced 2026-11-12 11:56:30 +00:00
Draggable numberbox - Added and use in editor
This commit is contained in:
1 parent
ecbc3e4f35
commit
c0e2d8e579
17 files changed
+395
-98
No files matched your search
@@ -0,0 +1,40 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||
xmlns:sharedControls="clr-namespace:Artemis.UI.Shared.Controls"
|
||||
xmlns:attachedProperties="clr-namespace:Artemis.UI.Shared.AttachedProperties"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Artemis.UI.Shared.Controls.DraggableNumberBox">
|
||||
<UserControl.Styles>
|
||||
<Styles>
|
||||
<Style Selector="sharedControls|DraggableNumberBox:not(:focus-within)">
|
||||
<Setter Property="Cursor" Value="{DynamicResource DragHorizontalCursor}" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="sharedControls|DraggableNumberBox:focus-within Rectangle#DragCollider">
|
||||
<Setter Property="IsHitTestVisible" Value="False" />
|
||||
</Style>
|
||||
<Style Selector="sharedControls|DraggableNumberBox:not(:focus-within) controls|NumberBox#NumberBox">
|
||||
<Setter Property="IsHitTestVisible" Value="False" />
|
||||
</Style>
|
||||
</Styles>
|
||||
</UserControl.Styles>
|
||||
|
||||
<Panel>
|
||||
<controls:NumberBox Name="NumberBox"
|
||||
AcceptsExpression="True"
|
||||
Value="{Binding $parent[sharedControls:DraggableNumberBox].Value}"
|
||||
Minimum="{Binding $parent[sharedControls:DraggableNumberBox].Minimum}"
|
||||
Maximum="{Binding $parent[sharedControls:DraggableNumberBox].Maximum}"
|
||||
LargeChange="{Binding $parent[sharedControls:DraggableNumberBox].LargeChange}"
|
||||
SmallChange="{Binding $parent[sharedControls:DraggableNumberBox].SmallChange}"
|
||||
SimpleNumberFormat="{Binding $parent[sharedControls:DraggableNumberBox].SimpleNumberFormat}"
|
||||
attachedProperties:NumberBoxAssist.PrefixText="{Binding $parent[sharedControls:DraggableNumberBox].Prefix}"
|
||||
attachedProperties:NumberBoxAssist.SuffixText="{Binding $parent[sharedControls:DraggableNumberBox].Suffix}"
|
||||
HorizontalAlignment="{Binding $parent[sharedControls:DraggableNumberBox].HorizontalAlignment}" />
|
||||
<Rectangle Name="DragCollider" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Fill="Transparent"></Rectangle>
|
||||
</Panel>
|
||||
|
||||
</UserControl>
|
||||
@@ -0,0 +1,179 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Data;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.VisualTree;
|
||||
using FluentAvalonia.Core;
|
||||
using FluentAvalonia.UI.Controls;
|
||||
|
||||
namespace Artemis.UI.Shared.Controls;
|
||||
|
||||
public partial class DraggableNumberBox : UserControl
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the value of the number box.
|
||||
/// </summary>
|
||||
public static readonly StyledProperty<double> ValueProperty = AvaloniaProperty.Register<DraggableNumberBox, double>(nameof(Value), defaultBindingMode: BindingMode.TwoWay);
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the value of the number box.
|
||||
/// </summary>
|
||||
public double Value
|
||||
{
|
||||
get => GetValue(ValueProperty);
|
||||
set => SetValue(ValueProperty, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the minimum of the number box.
|
||||
/// </summary>
|
||||
public static readonly StyledProperty<double> MinimumProperty = AvaloniaProperty.Register<DraggableNumberBox, double>(nameof(Minimum), double.MinValue);
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the minimum of the number box.
|
||||
/// </summary>
|
||||
public double Minimum
|
||||
{
|
||||
get => GetValue(MinimumProperty);
|
||||
set => SetValue(MinimumProperty, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the maximum of the number box.
|
||||
/// </summary>
|
||||
public static readonly StyledProperty<double> MaximumProperty = AvaloniaProperty.Register<DraggableNumberBox, double>(nameof(Maximum), double.MaxValue);
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the maximum of the number box.
|
||||
/// </summary>
|
||||
public double Maximum
|
||||
{
|
||||
get => GetValue(MaximumProperty);
|
||||
set => SetValue(MaximumProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<double> LargeChangeProperty = AvaloniaProperty.Register<DraggableNumberBox, double>(nameof(LargeChange));
|
||||
|
||||
public double LargeChange
|
||||
{
|
||||
get => GetValue(LargeChangeProperty);
|
||||
set => SetValue(LargeChangeProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<double> SmallChangeProperty = AvaloniaProperty.Register<DraggableNumberBox, double>(nameof(SmallChange));
|
||||
|
||||
public double SmallChange
|
||||
{
|
||||
get => GetValue(SmallChangeProperty);
|
||||
set => SetValue(SmallChangeProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<string> SimpleNumberFormatProperty = AvaloniaProperty.Register<DraggableNumberBox, string>(nameof(SimpleNumberFormat));
|
||||
|
||||
public string SimpleNumberFormat
|
||||
{
|
||||
get => GetValue(SimpleNumberFormatProperty);
|
||||
set => SetValue(SimpleNumberFormatProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<string> PrefixProperty = AvaloniaProperty.Register<DraggableNumberBox, string>(nameof(Prefix));
|
||||
|
||||
public string Prefix
|
||||
{
|
||||
get => GetValue(PrefixProperty);
|
||||
set => SetValue(PrefixProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<string> SuffixProperty = AvaloniaProperty.Register<DraggableNumberBox, string>(nameof(Suffix));
|
||||
|
||||
public string Suffix
|
||||
{
|
||||
get => GetValue(SuffixProperty);
|
||||
set => SetValue(SuffixProperty, value);
|
||||
}
|
||||
|
||||
public event TypedEventHandler<DraggableNumberBox, EventArgs>? DragStarted;
|
||||
public event TypedEventHandler<DraggableNumberBox, EventArgs>? DragFinished;
|
||||
|
||||
private readonly NumberBox _numberBox;
|
||||
private TextBox? _inputTextBox;
|
||||
private bool _moved;
|
||||
private double _lastX;
|
||||
private double _startX;
|
||||
|
||||
public DraggableNumberBox()
|
||||
{
|
||||
InitializeComponent();
|
||||
_numberBox = this.Get<NumberBox>("NumberBox");
|
||||
|
||||
PointerPressed += OnPointerPressed;
|
||||
PointerMoved += OnPointerMoved;
|
||||
PointerReleased += OnPointerReleased;
|
||||
|
||||
AddHandler(KeyUpEvent, HandleKeyUp, RoutingStrategies.Direct | RoutingStrategies.Tunnel | RoutingStrategies.Bubble, true);
|
||||
}
|
||||
|
||||
private void HandleKeyUp(object? sender, KeyEventArgs e)
|
||||
{
|
||||
if (e.Key == Key.Enter || e.Key == Key.Escape)
|
||||
Parent?.Focus();
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
|
||||
private void OnPointerPressed(object? sender, PointerPressedEventArgs e)
|
||||
{
|
||||
PointerPoint point = e.GetCurrentPoint(this);
|
||||
_inputTextBox = _numberBox.FindDescendantOfType<TextBox>();
|
||||
_moved = false;
|
||||
_startX = point.Position.X;
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void OnPointerMoved(object? sender, PointerEventArgs e)
|
||||
{
|
||||
PointerPoint point = e.GetCurrentPoint(this);
|
||||
if (!_moved && Math.Abs(point.Position.X - _startX) < 2 || !point.Properties.IsLeftButtonPressed || _inputTextBox == null || _inputTextBox.IsFocused)
|
||||
{
|
||||
_lastX = point.Position.X;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_moved)
|
||||
{
|
||||
// Let our parent take focus, it would make more sense to take focus ourselves but that hides the collider
|
||||
Parent?.Focus();
|
||||
_moved = true;
|
||||
e.Pointer.Capture(this);
|
||||
DragStarted?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
double smallChange = SmallChange != 0 ? SmallChange : 0.1;
|
||||
double largeChange = LargeChange != 0 ? LargeChange : smallChange * 10;
|
||||
double changeMultiplier = e.KeyModifiers.HasFlag(KeyModifiers.Shift) ? smallChange : largeChange;
|
||||
|
||||
Value += (point.Position.X - _lastX) * changeMultiplier;
|
||||
_lastX = point.Position.X;
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void OnPointerReleased(object? sender, PointerReleasedEventArgs e)
|
||||
{
|
||||
if (!_moved)
|
||||
_inputTextBox?.Focus();
|
||||
else
|
||||
{
|
||||
_moved = false;
|
||||
DragFinished?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,8 @@
|
||||
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||
xmlns:gradientPicker="clr-namespace:Artemis.UI.Shared.GradientPicker"
|
||||
xmlns:dataModelPicker="clr-namespace:Artemis.UI.Shared.DataModelPicker"
|
||||
xmlns:controls1="clr-namespace:Artemis.UI.Shared">
|
||||
xmlns:controls1="clr-namespace:Artemis.UI.Shared"
|
||||
xmlns:controls2="clr-namespace:Artemis.UI.Shared.Controls">
|
||||
<Design.PreviewWith>
|
||||
<Border Padding="50">
|
||||
<StackPanel Spacing="5">
|
||||
@@ -15,7 +16,9 @@
|
||||
<TextBox Classes="condensed" Watermark="Watermark" />
|
||||
|
||||
<controls:NumberBox Value="1337"></controls:NumberBox>
|
||||
<controls:NumberBox Classes="condensed" Value="1337"></controls:NumberBox>
|
||||
<controls2:DraggableNumberBox Value="1337" HorizontalAlignment="Left"></controls2:DraggableNumberBox>
|
||||
<controls:NumberBox Classes="condensed" Value="1337" ></controls:NumberBox>
|
||||
<controls2:DraggableNumberBox Classes="condensed" Value="1337" HorizontalAlignment="Left"></controls2:DraggableNumberBox>
|
||||
|
||||
<ComboBox SelectedIndex="1">
|
||||
<ComboBoxItem>Bluasdadseheh</ComboBoxItem>
|
||||
@@ -42,25 +45,31 @@
|
||||
|
||||
<!-- Add Styles Here -->
|
||||
<Style Selector="TextBox.condensed">
|
||||
<Setter Property="Padding" Value="4 2" />
|
||||
<Setter Property="Padding" Value="2" />
|
||||
<Setter Property="FontSize" Value="13" />
|
||||
<Setter Property="MinHeight" Value="24" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="controls|NumberBox.condensed /template/ TextBox#InputBox">
|
||||
<Setter Property="Padding" Value="4 2" />
|
||||
<Setter Property="Padding" Value="6 2" />
|
||||
<Setter Property="FontSize" Value="13" />
|
||||
<Setter Property="MinHeight" Value="24" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="controls2|DraggableNumberBox.condensed controls|NumberBox /template/ TextBox#InputBox">
|
||||
<Setter Property="Padding" Value="6 2" />
|
||||
<Setter Property="FontSize" Value="13" />
|
||||
<Setter Property="MinHeight" Value="24" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="ComboBox.condensed">
|
||||
<Setter Property="Padding" Value="4 2" />
|
||||
<Setter Property="Padding" Value="6 2" />
|
||||
<Setter Property="FontSize" Value="13" />
|
||||
<Setter Property="Height" Value="24" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="controls1|EnumComboBox.condensed > ComboBox">
|
||||
<Setter Property="Padding" Value="4 2" />
|
||||
<Setter Property="Padding" Value="6 2" />
|
||||
<Setter Property="FontSize" Value="13" />
|
||||
<Setter Property="Height" Value="24" />
|
||||
</Style>
|
||||
|
||||
Reference in new issue
Block a user