#develop (short for SharpDevelop) is a free IDE for .NET programming languages.
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

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;
}
}
}
}