mirror of
https://github.com/hawkeye-stan/msfs-popout-panel-manager.git
synced 2024-11-28 16:50:11 +00:00
217 lines
8.1 KiB
C#
217 lines
8.1 KiB
C#
|
using System;
|
|||
|
using System.Linq;
|
|||
|
using System.Windows;
|
|||
|
using System.Windows.Controls;
|
|||
|
using System.Windows.Controls.Primitives;
|
|||
|
using System.Windows.Input;
|
|||
|
|
|||
|
namespace MSFSPopoutPanelManager.MainApp.CustomControl
|
|||
|
{
|
|||
|
[TemplatePart(Name = "PART_TextBox", Type = typeof(TextBox))]
|
|||
|
[TemplatePart(Name = "PART_ButtonUp", Type = typeof(ButtonBase))]
|
|||
|
[TemplatePart(Name = "PART_ButtonDown", Type = typeof(ButtonBase))]
|
|||
|
public class NumericUpDown : Control
|
|||
|
{
|
|||
|
private TextBox PART_TextBox = new TextBox();
|
|||
|
|
|||
|
public override void OnApplyTemplate()
|
|||
|
{
|
|||
|
base.OnApplyTemplate();
|
|||
|
|
|||
|
TextBox? textBox = GetTemplateChild("PART_TextBox") as TextBox;
|
|||
|
if (textBox != null)
|
|||
|
{
|
|||
|
PART_TextBox = textBox;
|
|||
|
PART_TextBox.PreviewKeyDown += textBox_PreviewKeyDown;
|
|||
|
PART_TextBox.TextChanged += textBox_TextChanged;
|
|||
|
PART_TextBox.Text = Value.ToString();
|
|||
|
}
|
|||
|
|
|||
|
ButtonBase? PART_ButtonUp = GetTemplateChild("PART_ButtonUp") as ButtonBase;
|
|||
|
if (PART_ButtonUp != null)
|
|||
|
{
|
|||
|
PART_ButtonUp.Click += buttonUp_Click;
|
|||
|
}
|
|||
|
|
|||
|
ButtonBase? PART_ButtonDown = GetTemplateChild("PART_ButtonDown") as ButtonBase;
|
|||
|
if (PART_ButtonDown != null)
|
|||
|
{
|
|||
|
PART_ButtonDown.Click += buttonDown_Click;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
static NumericUpDown()
|
|||
|
{
|
|||
|
DefaultStyleKeyProperty.OverrideMetadata(typeof(NumericUpDown), new FrameworkPropertyMetadata(typeof(NumericUpDown)));
|
|||
|
}
|
|||
|
|
|||
|
public static readonly RoutedEvent ValueChangedEvent = EventManager.RegisterRoutedEvent(
|
|||
|
"ValueChanged", RoutingStrategy.Direct,
|
|||
|
typeof(ValueChangedEventHandler), typeof(NumericUpDown));
|
|||
|
public event ValueChangedEventHandler ValueChanged
|
|||
|
{
|
|||
|
add
|
|||
|
{
|
|||
|
base.AddHandler(NumericUpDown.ValueChangedEvent, value);
|
|||
|
}
|
|||
|
remove
|
|||
|
{
|
|||
|
base.RemoveHandler(NumericUpDown.ValueChangedEvent, value);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public int Places
|
|||
|
{
|
|||
|
get { return (int)GetValue(PlacesProperty); }
|
|||
|
set { SetValue(PlacesProperty, value); }
|
|||
|
}
|
|||
|
|
|||
|
public static readonly DependencyProperty PlacesProperty = DependencyProperty.Register("Places", typeof(int), typeof(NumericUpDown));
|
|||
|
|
|||
|
public double MaxValue
|
|||
|
{
|
|||
|
get { return (double)GetValue(MaxValueProperty); }
|
|||
|
set { SetValue(MaxValueProperty, value); }
|
|||
|
}
|
|||
|
public static readonly DependencyProperty MaxValueProperty =
|
|||
|
DependencyProperty.Register("MaxValue", typeof(double), typeof(NumericUpDown), new FrameworkPropertyMetadata(100D, maxValueChangedCallback, coerceMaxValueCallback));
|
|||
|
private static object coerceMaxValueCallback(DependencyObject d, object value)
|
|||
|
{
|
|||
|
double minValue = ((NumericUpDown)d).MinValue;
|
|||
|
if ((double)value < minValue)
|
|||
|
return minValue;
|
|||
|
|
|||
|
return value;
|
|||
|
}
|
|||
|
private static void maxValueChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
|||
|
{
|
|||
|
NumericUpDown numericUpDown = ((NumericUpDown)d);
|
|||
|
numericUpDown.CoerceValue(MinValueProperty);
|
|||
|
numericUpDown.CoerceValue(ValueProperty);
|
|||
|
}
|
|||
|
|
|||
|
public double MinValue
|
|||
|
{
|
|||
|
get { return (double)GetValue(MinValueProperty); }
|
|||
|
set { SetValue(MinValueProperty, value); }
|
|||
|
}
|
|||
|
|
|||
|
public static readonly DependencyProperty MinValueProperty =
|
|||
|
DependencyProperty.Register("MinValue", typeof(double), typeof(NumericUpDown), new FrameworkPropertyMetadata(0D, minValueChangedCallback, coerceMinValueCallback));
|
|||
|
|
|||
|
private static object coerceMinValueCallback(DependencyObject d, object value)
|
|||
|
{
|
|||
|
double maxValue = ((NumericUpDown)d).MaxValue;
|
|||
|
if ((double)value > maxValue)
|
|||
|
return maxValue;
|
|||
|
|
|||
|
return value;
|
|||
|
}
|
|||
|
|
|||
|
private static void minValueChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
|||
|
{
|
|||
|
NumericUpDown numericUpDown = ((NumericUpDown)d);
|
|||
|
numericUpDown.CoerceValue(NumericUpDown.MaxValueProperty);
|
|||
|
numericUpDown.CoerceValue(NumericUpDown.ValueProperty);
|
|||
|
}
|
|||
|
|
|||
|
public double Increment
|
|||
|
{
|
|||
|
get { return (double)GetValue(IncrementProperty); }
|
|||
|
set { SetValue(IncrementProperty, value); }
|
|||
|
}
|
|||
|
public static readonly DependencyProperty IncrementProperty =
|
|||
|
DependencyProperty.Register("Increment", typeof(double), typeof(NumericUpDown), new FrameworkPropertyMetadata(1D, null, coerceIncrementCallback));
|
|||
|
private static object coerceIncrementCallback(DependencyObject d, object value)
|
|||
|
{
|
|||
|
NumericUpDown numericUpDown = ((NumericUpDown)d);
|
|||
|
double i = numericUpDown.MaxValue - numericUpDown.MinValue;
|
|||
|
if ((double)value > i)
|
|||
|
return i;
|
|||
|
|
|||
|
return value;
|
|||
|
}
|
|||
|
|
|||
|
public double Value
|
|||
|
{
|
|||
|
get { return (double)GetValue(ValueProperty); }
|
|||
|
set { SetValue(ValueProperty, value); }
|
|||
|
}
|
|||
|
public static readonly DependencyProperty ValueProperty =
|
|||
|
DependencyProperty.Register("Value", typeof(double), typeof(NumericUpDown), new FrameworkPropertyMetadata(0D, valueChangedCallback, coerceValueCallback), validateValueCallback);
|
|||
|
private static void valueChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
|||
|
{
|
|||
|
NumericUpDown numericUpDown = (NumericUpDown)d;
|
|||
|
ValueChangedEventArgs ea =
|
|||
|
new ValueChangedEventArgs(NumericUpDown.ValueChangedEvent, d, (double)e.OldValue, (double)e.NewValue);
|
|||
|
numericUpDown.RaiseEvent(ea);
|
|||
|
numericUpDown.PART_TextBox.Text = e.NewValue.ToString();
|
|||
|
}
|
|||
|
private static bool validateValueCallback(object value)
|
|||
|
{
|
|||
|
double val = (double)value;
|
|||
|
if (val > double.MinValue && val < double.MaxValue)
|
|||
|
return true;
|
|||
|
else
|
|||
|
return false;
|
|||
|
}
|
|||
|
private static object coerceValueCallback(DependencyObject d, object value)
|
|||
|
{
|
|||
|
double val = (double)value;
|
|||
|
double minValue = ((NumericUpDown)d).MinValue;
|
|||
|
double maxValue = ((NumericUpDown)d).MaxValue;
|
|||
|
double result;
|
|||
|
if (val < minValue)
|
|||
|
result = minValue;
|
|||
|
else if (val > maxValue)
|
|||
|
result = maxValue;
|
|||
|
else
|
|||
|
result = (double)value;
|
|||
|
|
|||
|
return result;
|
|||
|
}
|
|||
|
|
|||
|
private void buttonUp_Click(object sender, RoutedEventArgs e)
|
|||
|
{
|
|||
|
if (Value < MaxValue)
|
|||
|
Value += Increment;
|
|||
|
|
|||
|
Value = Math.Round(Value, Places);
|
|||
|
}
|
|||
|
private void buttonDown_Click(object sender, RoutedEventArgs e)
|
|||
|
{
|
|||
|
if (Value > MinValue)
|
|||
|
Value -= Increment;
|
|||
|
|
|||
|
Value = Math.Round(Value, Places);
|
|||
|
}
|
|||
|
|
|||
|
private void textBox_PreviewKeyDown(object sender, KeyEventArgs e)
|
|||
|
{
|
|||
|
if (e.Key == Key.Space)
|
|||
|
e.Handled = true;
|
|||
|
}
|
|||
|
private void textBox_TextChanged(object sender, TextChangedEventArgs e)
|
|||
|
{
|
|||
|
int index = PART_TextBox.CaretIndex;
|
|||
|
double result;
|
|||
|
if (!double.TryParse(PART_TextBox.Text, out result))
|
|||
|
{
|
|||
|
var changes = e.Changes.FirstOrDefault();
|
|||
|
if (changes != null)
|
|||
|
{
|
|||
|
PART_TextBox.Text = PART_TextBox.Text.Remove(changes.Offset, changes.AddedLength);
|
|||
|
PART_TextBox.CaretIndex = index > 0 ? index - changes.AddedLength : 0;
|
|||
|
}
|
|||
|
}
|
|||
|
else if (result < MaxValue && result > MinValue)
|
|||
|
Value = result;
|
|||
|
else
|
|||
|
{
|
|||
|
PART_TextBox.Text = Value.ToString();
|
|||
|
PART_TextBox.CaretIndex = index > 0 ? index - 1 : 0;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|