You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
297 lines
7.7 KiB
297 lines
7.7 KiB
using System; |
|
using System.Collections.Generic; |
|
using System.Linq; |
|
using System.Text; |
|
using System.Windows; |
|
using System.Windows.Controls; |
|
using System.Windows.Data; |
|
using System.Windows.Documents; |
|
using System.Windows.Input; |
|
using System.Windows.Media; |
|
using System.Windows.Media.Imaging; |
|
using System.Windows.Navigation; |
|
using System.Windows.Shapes; |
|
using System.Globalization; |
|
using SharpDevelop.XamlDesigner.Converters; |
|
using System.Reflection; |
|
using System.Windows.Threading; |
|
|
|
namespace SharpDevelop.XamlDesigner.Controls |
|
{ |
|
public class EditSlider : Control |
|
{ |
|
static EditSlider() |
|
{ |
|
DefaultStyleKeyProperty.OverrideMetadata(typeof(EditSlider), |
|
new FrameworkPropertyMetadata(typeof(EditSlider))); |
|
} |
|
|
|
public EditSlider() |
|
{ |
|
SizeChanged += new SizeChangedEventHandler(EditSlider_SizeChanged); |
|
} |
|
|
|
AdvancedThumb thumb; |
|
FrameworkElement bar; |
|
TextBox textBox; |
|
Vector startDelta; |
|
double startValue; |
|
|
|
BindingExpression currentValueExpression; |
|
|
|
static PropertyInfo sourceValueProperty = |
|
typeof(BindingExpression).GetProperty("SourceValue", BindingFlags.NonPublic | BindingFlags.Instance); |
|
|
|
public AdvancedThumb Thumb |
|
{ |
|
get { return thumb; } |
|
} |
|
|
|
public static readonly DependencyProperty ValueProperty = |
|
DependencyProperty.Register("Value", typeof(double), typeof(EditSlider), |
|
new FrameworkPropertyMetadata(0.0, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault)); |
|
|
|
public double Value |
|
{ |
|
get { return (double)GetValue(ValueProperty); } |
|
set { SetValue(ValueProperty, value); } |
|
} |
|
|
|
public static readonly DependencyProperty MinimumProperty = |
|
DependencyProperty.Register("Minimum", typeof(double), typeof(EditSlider), |
|
new FrameworkPropertyMetadata(double.NegativeInfinity)); |
|
|
|
public double Minimum |
|
{ |
|
get { return (double)GetValue(MinimumProperty); } |
|
set { SetValue(MinimumProperty, value); } |
|
} |
|
|
|
public static readonly DependencyProperty MaximumProperty = |
|
DependencyProperty.Register("Maximum", typeof(double), typeof(EditSlider), |
|
new FrameworkPropertyMetadata(double.PositiveInfinity)); |
|
|
|
public double Maximum |
|
{ |
|
get { return (double)GetValue(MaximumProperty); } |
|
set { SetValue(MaximumProperty, value); } |
|
} |
|
|
|
public static readonly DependencyProperty StepProperty = |
|
DependencyProperty.Register("Step", typeof(double), typeof(EditSlider), |
|
new FrameworkPropertyMetadata(0.25)); |
|
|
|
public double Step |
|
{ |
|
get { return (double)GetValue(StepProperty); } |
|
set { SetValue(StepProperty, value); } |
|
} |
|
|
|
public static readonly DependencyProperty DecimalsProperty = |
|
DependencyProperty.Register("Decimals", typeof(int), typeof(EditSlider), |
|
new FrameworkPropertyMetadata(0)); |
|
|
|
public int Decimals |
|
{ |
|
get { return (int)GetValue(DecimalsProperty); } |
|
set { SetValue(DecimalsProperty, value); } |
|
} |
|
|
|
public static readonly DependencyProperty InPercentsProperty = |
|
DependencyProperty.Register("InPercents", typeof(bool), typeof(EditSlider)); |
|
|
|
public bool InPercents |
|
{ |
|
get { return (bool)GetValue(InPercentsProperty); } |
|
set { SetValue(InPercentsProperty, value); } |
|
} |
|
|
|
public static readonly DependencyProperty InvisibleValueProperty = |
|
DependencyProperty.Register("InvisibleValue", typeof(bool), typeof(EditSlider)); |
|
|
|
public bool InvisibleValue |
|
{ |
|
get { return (bool)GetValue(InvisibleValueProperty); } |
|
set { SetValue(InvisibleValueProperty, value); } |
|
} |
|
|
|
protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e) |
|
{ |
|
base.OnPropertyChanged(e); |
|
|
|
if (e.Property == MinimumProperty || |
|
e.Property == MaximumProperty) { |
|
SetNewValue(Value); |
|
UpdateBar(); |
|
} |
|
else if (e.Property == InPercentsProperty) { |
|
PrintCurrentValue(); |
|
} |
|
else if (e.Property == ValueProperty) { |
|
UpdateCurrentValueExpression(); |
|
UpdateBar(); |
|
} |
|
} |
|
|
|
public override void OnApplyTemplate() |
|
{ |
|
base.OnApplyTemplate(); |
|
|
|
bar = Template.FindName("PART_Bar", this) as FrameworkElement; |
|
|
|
textBox = Template.FindName("PART_TextBox", this) as TextBox; |
|
textBox.KeyDown += new KeyEventHandler(textBox_KeyDown); |
|
textBox.GotKeyboardFocus += new KeyboardFocusChangedEventHandler(textBox_GotKeyboardFocus); |
|
textBox.SetBinding(TextBox.TextProperty, new Binding("Value") { |
|
Source = this, |
|
Converter = new TextConverter() { EditSlider = this } |
|
}); |
|
|
|
thumb = Template.FindName("PART_Thumb", this) as AdvancedThumb; |
|
thumb.Click += new AdvancedDragEventHandler(thumb_Click); |
|
thumb.DragStarted += new AdvancedDragEventHandler(thumb_DragStarted); |
|
thumb.DragDelta += new AdvancedDragEventHandler(thumb_DragDelta); |
|
thumb.DragCompleted += new AdvancedDragEventHandler(thumb_DragCompleted); |
|
|
|
UpdateBar(); |
|
} |
|
|
|
void textBox_KeyDown(object sender, KeyEventArgs e) |
|
{ |
|
if (e.Key == Key.Enter) { |
|
Focusable = true; |
|
Focus(); |
|
ClearValue(FocusableProperty); |
|
} |
|
} |
|
|
|
void textBox_GotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e) |
|
{ |
|
textBox.SelectAll(); |
|
} |
|
|
|
void thumb_Click(object sender, AdvancedDragEventArgs e) |
|
{ |
|
textBox.Focus(); |
|
} |
|
|
|
void thumb_DragStarted(object sender, AdvancedDragEventArgs e) |
|
{ |
|
startDelta = e.Delta; |
|
startValue = Value; |
|
} |
|
|
|
void thumb_DragDelta(object sender, AdvancedDragEventArgs e) |
|
{ |
|
var finalDelta = e.Delta - startDelta; |
|
var newValue = startValue + (finalDelta.X - finalDelta.Y) * Step; |
|
SetNewValue(Math.Round(newValue, Decimals + (InPercents ? 2 : 0))); |
|
} |
|
|
|
void thumb_DragCompleted(object sender, AdvancedDragEventArgs e) |
|
{ |
|
if (e.IsCancel) { |
|
SetNewValue(startValue); |
|
} |
|
} |
|
|
|
void EditSlider_SizeChanged(object sender, SizeChangedEventArgs e) |
|
{ |
|
UpdateBar(); |
|
} |
|
|
|
void PrintCurrentValue() |
|
{ |
|
if (textBox != null) { |
|
var expr = BindingOperations.GetBindingExpression(textBox, TextBox.TextProperty); |
|
expr.UpdateTarget(); |
|
} |
|
} |
|
|
|
void UpdateBar() |
|
{ |
|
if (bar != null) { |
|
var range = Maximum - Minimum; |
|
if (range > 0 && range < double.MaxValue) { |
|
var parentWidth = (bar.Parent as FrameworkElement).ActualWidth; |
|
bar.Width = parentWidth * (Value - Minimum) / range; |
|
} |
|
} |
|
} |
|
|
|
void UpdateCurrentValueExpression() |
|
{ |
|
var newExpression = GetBindingExpression(ValueProperty); |
|
|
|
if (currentValueExpression != newExpression) { |
|
currentValueExpression = newExpression; |
|
if (currentValueExpression != null) { |
|
// HACK |
|
var sourceValue = sourceValueProperty.GetValue(currentValueExpression, null); |
|
var sourceType = sourceValue != null ? sourceValue.GetType() : null; |
|
|
|
AutoRange(sourceType); |
|
} |
|
} |
|
|
|
// if there was exception... |
|
if (currentValueExpression != null) { |
|
currentValueExpression.UpdateTarget(); |
|
} |
|
} |
|
|
|
void AutoRange(Type type) |
|
{ |
|
if (type == typeof(Byte)) { |
|
Minimum = Byte.MinValue; |
|
Maximum = Byte.MaxValue; |
|
} |
|
else if (type == typeof(SByte)) { |
|
Minimum = SByte.MinValue; |
|
Maximum = SByte.MaxValue; |
|
} |
|
} |
|
|
|
void SetNewValue(double newValue) |
|
{ |
|
newValue = Math.Max(Minimum, Math.Min(Maximum, newValue)); |
|
// NaN also |
|
if (!object.Equals(Value, newValue)) { |
|
Value = newValue; |
|
} |
|
} |
|
|
|
class TextConverter : IValueConverter |
|
{ |
|
public EditSlider EditSlider; |
|
|
|
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) |
|
{ |
|
if (EditSlider.InvisibleValue) return null; |
|
|
|
var d = (double)value; |
|
if (EditSlider.InPercents) { |
|
d = d * 100; |
|
return Utils.DoubleToInvariantString(d) + "%"; |
|
} |
|
return Utils.DoubleToInvariantString(d); |
|
} |
|
|
|
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) |
|
{ |
|
EditSlider.PrintCurrentValue(); |
|
|
|
var s = (string)value; |
|
if (EditSlider.InPercents) { |
|
s = s.Replace("%", ""); |
|
} |
|
double result; |
|
if (Utils.TryParseDouble(s, out result)) { |
|
return EditSlider.InPercents ? result / 100 : result; |
|
} |
|
|
|
return null; |
|
} |
|
} |
|
} |
|
} |