aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/Tango.BrushPicker/Implementation
diff options
context:
space:
mode:
authorRoy <roy.mail.net@gmail.com>2018-03-03 23:05:27 +0200
committerRoy <roy.mail.net@gmail.com>2018-03-03 23:05:27 +0200
commit9dedf143c3ac44ca593e735861f4e1e2e6f947c9 (patch)
tree24e74858582300add1f165d4515d9ee8e4a609c5 /Software/Visual_Studio/Tango.BrushPicker/Implementation
parent96efb4716d16ab7dab67ead42f27b871b81d4111 (diff)
downloadTango-9dedf143c3ac44ca593e735861f4e1e2e6f947c9.tar.gz
Tango-9dedf143c3ac44ca593e735861f4e1e2e6f947c9.zip
Implemented Brush Picker.
Diffstat (limited to 'Software/Visual_Studio/Tango.BrushPicker/Implementation')
-rw-r--r--Software/Visual_Studio/Tango.BrushPicker/Implementation/AlphaSelector.cs127
-rw-r--r--Software/Visual_Studio/Tango.BrushPicker/Implementation/BaseSelector.cs38
-rw-r--r--Software/Visual_Studio/Tango.BrushPicker/Implementation/BrushPicker.cs803
-rw-r--r--Software/Visual_Studio/Tango.BrushPicker/Implementation/BrushTypes.cs23
-rw-r--r--Software/Visual_Studio/Tango.BrushPicker/Implementation/ColorChangedEventArgs.cs33
-rw-r--r--Software/Visual_Studio/Tango.BrushPicker/Implementation/DoubleUpDown.cs201
-rw-r--r--Software/Visual_Studio/Tango.BrushPicker/Implementation/Enums.cs45
-rw-r--r--Software/Visual_Studio/Tango.BrushPicker/Implementation/GradientStopAdder.cs81
-rw-r--r--Software/Visual_Studio/Tango.BrushPicker/Implementation/GradientStopSlider.cs86
-rw-r--r--Software/Visual_Studio/Tango.BrushPicker/Implementation/HueSelector.cs143
-rw-r--r--Software/Visual_Studio/Tango.BrushPicker/Implementation/SaturationBrightnessSelector.cs174
-rw-r--r--Software/Visual_Studio/Tango.BrushPicker/Implementation/SpinEventArgs .cs37
-rw-r--r--Software/Visual_Studio/Tango.BrushPicker/Implementation/Spinner.cs51
-rw-r--r--Software/Visual_Studio/Tango.BrushPicker/Implementation/UpDownBase.cs747
14 files changed, 2589 insertions, 0 deletions
diff --git a/Software/Visual_Studio/Tango.BrushPicker/Implementation/AlphaSelector.cs b/Software/Visual_Studio/Tango.BrushPicker/Implementation/AlphaSelector.cs
new file mode 100644
index 000000000..8a7f09796
--- /dev/null
+++ b/Software/Visual_Studio/Tango.BrushPicker/Implementation/AlphaSelector.cs
@@ -0,0 +1,127 @@
+using System;
+using System.Windows.Media;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Input;
+
+namespace Tango.BrushPicker
+{
+ class AlphaSelector : BaseSelector
+ {
+ public double Alpha
+ {
+ get { return (double)GetValue(AlphaProperty); }
+ set { SetValue(AlphaProperty, value); }
+ }
+ public static readonly DependencyProperty AlphaProperty =
+ DependencyProperty.Register("Alpha", typeof(double), typeof(AlphaSelector),
+ new FrameworkPropertyMetadata(1.0, new PropertyChangedCallback(AlphaChanged), new CoerceValueCallback(AlphaCoerce)));
+ public static void AlphaChanged(object o, DependencyPropertyChangedEventArgs e)
+ {
+ AlphaSelector h = (AlphaSelector)o;
+ h.SetAlphaOffset();
+ h.SetColor();
+ }
+ public static object AlphaCoerce(DependencyObject d, object Brightness)
+ {
+ double v = (double)Brightness;
+ if (v < 0) return 0.0;
+ if (v > 1) return 1.0;
+ return v;
+ }
+
+
+ public double AlphaOffset
+ {
+ get { return (double)GetValue(AlphaOffsetProperty); }
+ private set { SetValue(AlphaOffsetProperty, value); }
+ }
+ public static readonly DependencyProperty AlphaOffsetProperty =
+ DependencyProperty.Register("AlphaOffset", typeof(double), typeof(AlphaSelector), new UIPropertyMetadata(0.0));
+
+
+ protected override void OnMouseMove(MouseEventArgs e)
+ {
+ if (e.LeftButton == MouseButtonState.Pressed)
+ {
+ Point p = e.GetPosition(this);
+
+ if (Orientation == Orientation.Vertical)
+ {
+ Alpha = 1 - (p.Y / this.ActualHeight);
+ }
+ else
+ {
+ Alpha = 1 - (p.X / this.ActualWidth);
+ }
+ }
+ base.OnMouseMove(e);
+ }
+
+ protected override void OnMouseDown(MouseButtonEventArgs e)
+ {
+ if (e.LeftButton == MouseButtonState.Pressed)
+ {
+ Point p = e.GetPosition(this);
+
+ if (Orientation == Orientation.Vertical)
+ {
+ Alpha = 1 - (p.Y / this.ActualHeight);
+ }
+ else
+ {
+ Alpha = 1 - (p.X / this.ActualWidth);
+ }
+ }
+ Mouse.Capture(this);
+ base.OnMouseMove(e);
+ }
+
+ protected override void OnMouseUp(MouseButtonEventArgs e)
+ {
+ this.ReleaseMouseCapture();
+ base.OnMouseUp(e);
+ }
+
+ protected override void OnRender(DrawingContext dc)
+ {
+ LinearGradientBrush lb = new LinearGradientBrush();
+
+ lb.StartPoint = new Point(0, 0);
+
+ if (Orientation == Orientation.Vertical)
+ lb.EndPoint = new Point(0, 1);
+ else
+ lb.EndPoint = new Point(1, 0);
+
+ lb.GradientStops.Add(new GradientStop(Color.FromArgb(0xFF, 0x00, 0x00, 0x00), 0.00));
+ lb.GradientStops.Add(new GradientStop(Color.FromArgb(0x00, 0x00, 0x00, 0x00), 1.00));
+
+ dc.DrawRectangle(lb, null, new Rect(0, 0, ActualWidth, ActualHeight));
+
+ SetAlphaOffset();
+
+ }
+
+ protected override Size ArrangeOverride(Size finalSize)
+ {
+ SetAlphaOffset();
+ return base.ArrangeOverride(finalSize);
+ }
+
+
+ private void SetAlphaOffset()
+ {
+ double length = ActualHeight;
+ if (Orientation == Orientation.Horizontal)
+ length = ActualWidth;
+ AlphaOffset = length - (length * Alpha);
+ }
+
+ private void SetColor()
+ {
+ Color = Color.FromArgb((byte)Math.Round(Alpha * 255), 0, 0, 0);
+ //Brush = new SolidColorBrush(Color);
+ }
+ }
+}
diff --git a/Software/Visual_Studio/Tango.BrushPicker/Implementation/BaseSelector.cs b/Software/Visual_Studio/Tango.BrushPicker/Implementation/BaseSelector.cs
new file mode 100644
index 000000000..e9ecc37ec
--- /dev/null
+++ b/Software/Visual_Studio/Tango.BrushPicker/Implementation/BaseSelector.cs
@@ -0,0 +1,38 @@
+/***************** NCore Softwares Pvt. Ltd., India **************************
+
+ ColorBox
+
+ Copyright (C) 2013 NCore Softwares Pvt. Ltd.
+
+ This program is provided to you under the terms of the Microsoft Public
+ License (Ms-PL) as published at http://ColorBox.codeplex.com/license
+
+***********************************************************************************/
+
+using System;
+using System.Windows.Media;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Input;
+
+namespace Tango.BrushPicker
+{
+ abstract class BaseSelector : FrameworkElement
+ {
+ public Orientation Orientation
+ {
+ get { return (Orientation)GetValue(OrientationProperty); }
+ set { SetValue(OrientationProperty, value); }
+ }
+ public static readonly DependencyProperty OrientationProperty =
+ DependencyProperty.Register("Orientation", typeof(Orientation), typeof(BaseSelector), new UIPropertyMetadata(Orientation.Vertical));
+
+ public Color Color
+ {
+ get { return (Color)GetValue(ColorProperty); }
+ protected set { SetValue(ColorProperty, value); }
+ }
+ public static readonly DependencyProperty ColorProperty =
+ DependencyProperty.Register("Color", typeof(Color), typeof(BaseSelector), new UIPropertyMetadata(Colors.Red));
+ }
+}
diff --git a/Software/Visual_Studio/Tango.BrushPicker/Implementation/BrushPicker.cs b/Software/Visual_Studio/Tango.BrushPicker/Implementation/BrushPicker.cs
new file mode 100644
index 000000000..b94db6298
--- /dev/null
+++ b/Software/Visual_Studio/Tango.BrushPicker/Implementation/BrushPicker.cs
@@ -0,0 +1,803 @@
+/***************** NCore Softwares Pvt. Ltd., India **************************
+
+ ColorBox
+
+ Copyright (C) 2013 NCore Softwares Pvt. Ltd.
+
+ This program is provided to you under the terms of the Microsoft Public
+ License (Ms-PL) as published at http://colorbox.codeplex.com/license
+
+***********************************************************************************/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Windows.Media;
+using System.Windows.Controls;
+using System.Windows;
+using System.Collections.ObjectModel;
+using System.Windows.Input;
+using System.ComponentModel;
+using System.Windows.Data;
+
+//Tango.BrushPicker
+namespace Tango.BrushPicker
+{
+ [TemplatePart(Name = PART_CurrentColor, Type = typeof(TextBox))]
+ public class BrushPicker : Control
+ {
+ internal const string PART_CurrentColor = "PART_CurrentColor";
+
+ //internal bool _GradientStopSetInternally = false;
+ internal bool _HSBSetInternally = false;
+ internal bool _RGBSetInternally = false;
+ internal bool _BrushSetInternally = false;
+ internal bool _BrushTypeSetInternally = false;
+ internal bool _UpdateBrush = true;
+
+ internal TextBox CurrentColorTextBox
+ {
+ get;
+ private set;
+ }
+
+ static BrushPicker()
+ {
+ DefaultStyleKeyProperty.OverrideMetadata(typeof(BrushPicker), new FrameworkPropertyMetadata(typeof(BrushPicker)));
+ }
+
+ public static RoutedCommand RemoveGradientStop = new RoutedCommand();
+ public static RoutedCommand ReverseGradientStop = new RoutedCommand();
+
+ public override void OnApplyTemplate()
+ {
+ base.OnApplyTemplate();
+
+ CurrentColorTextBox = GetTemplateChild(PART_CurrentColor) as TextBox;
+ if (CurrentColorTextBox != null)
+ {
+ CurrentColorTextBox.PreviewKeyDown += CurrentColorTextBox_PreviewKeyDown;
+ }
+
+ this.CommandBindings.Add(new CommandBinding(BrushPicker.RemoveGradientStop, RemoveGradientStop_Executed));
+ this.CommandBindings.Add(new CommandBinding(BrushPicker.ReverseGradientStop, ReverseGradientStop_Executed));
+
+ BrushType = BrushTypes.Linear;
+ }
+
+ void CurrentColorTextBox_PreviewKeyDown(object sender, KeyEventArgs e)
+ {
+ if (e.Key == Key.Enter)
+ {
+ BindingExpression be = CurrentColorTextBox.GetBindingExpression(TextBox.TextProperty);
+ if (be != null)
+ {
+ be.UpdateSource();
+ }
+ }
+ }
+
+ private void RemoveGradientStop_Executed(object sender, ExecutedRoutedEventArgs e)
+ {
+ if (this.Gradients != null && this.Gradients.Count > 2)
+ {
+ this.Gradients.Remove(this.SelectedGradient);
+ this.SetBrush();
+ }
+ }
+
+ private void ReverseGradientStop_Executed(object sender, ExecutedRoutedEventArgs e)
+ {
+ this._UpdateBrush = false;
+ this._BrushSetInternally = true;
+ foreach (GradientStop gs in Gradients)
+ {
+ gs.Offset = 1.0 - gs.Offset;
+ }
+ this._UpdateBrush = true;
+ this._BrushSetInternally = false;
+ this.SetBrush();
+ }
+
+ void InitTransform()
+ {
+ if (this.Brush.Transform == null || this.Brush.Transform.Value.IsIdentity)
+ {
+ this._BrushSetInternally = true;
+
+ TransformGroup _tg = new TransformGroup();
+ _tg.Children.Add(new RotateTransform());
+ _tg.Children.Add(new ScaleTransform());
+ _tg.Children.Add(new SkewTransform());
+ _tg.Children.Add(new TranslateTransform());
+ this.Brush.Transform = _tg;
+
+ this._BrushSetInternally = false;
+ }
+ }
+
+ #region Private Properties
+
+ double StartX
+ {
+ get { return (double)GetValue(StartXProperty); }
+ set { SetValue(StartXProperty, value); }
+ }
+ static readonly DependencyProperty StartXProperty =
+ DependencyProperty.Register("StartX", typeof(double), typeof(BrushPicker), new PropertyMetadata(0.5, new PropertyChangedCallback(StartXChanged)));
+ static void StartXChanged(DependencyObject property, DependencyPropertyChangedEventArgs args)
+ {
+ BrushPicker cp = property as BrushPicker;
+ if (cp.Brush is LinearGradientBrush)
+ {
+ cp._BrushSetInternally = true;
+ (cp.Brush as LinearGradientBrush).StartPoint = new Point((double)args.NewValue, (cp.Brush as LinearGradientBrush).StartPoint.Y);
+ cp._BrushSetInternally = false;
+ }
+ }
+
+ double StartY
+ {
+ get { return (double)GetValue(StartYProperty); }
+ set { SetValue(StartYProperty, value); }
+ }
+ static readonly DependencyProperty StartYProperty =
+ DependencyProperty.Register("StartY", typeof(double), typeof(BrushPicker), new PropertyMetadata(0.0, new PropertyChangedCallback(StartYChanged)));
+ static void StartYChanged(DependencyObject property, DependencyPropertyChangedEventArgs args)
+ {
+ BrushPicker cp = property as BrushPicker;
+ if (cp.Brush is LinearGradientBrush)
+ {
+ cp._BrushSetInternally = true;
+ (cp.Brush as LinearGradientBrush).StartPoint = new Point((cp.Brush as LinearGradientBrush).StartPoint.X, (double)args.NewValue);
+ cp._BrushSetInternally = false;
+ }
+ }
+
+ double EndX
+ {
+ get { return (double)GetValue(EndXProperty); }
+ set { SetValue(EndXProperty, value); }
+ }
+ static readonly DependencyProperty EndXProperty =
+ DependencyProperty.Register("EndX", typeof(double), typeof(BrushPicker), new PropertyMetadata(0.5, new PropertyChangedCallback(EndXChanged)));
+ static void EndXChanged(DependencyObject property, DependencyPropertyChangedEventArgs args)
+ {
+ BrushPicker cp = property as BrushPicker;
+ if (cp.Brush is LinearGradientBrush)
+ {
+ cp._BrushSetInternally = true;
+ (cp.Brush as LinearGradientBrush).EndPoint = new Point((double)args.NewValue, (cp.Brush as LinearGradientBrush).EndPoint.Y);
+ cp._BrushSetInternally = false;
+ }
+ }
+
+ double EndY
+ {
+ get { return (double)GetValue(EndYProperty); }
+ set { SetValue(EndYProperty, value); }
+ }
+ static readonly DependencyProperty EndYProperty =
+ DependencyProperty.Register("EndY", typeof(double), typeof(BrushPicker), new PropertyMetadata(1.0, new PropertyChangedCallback(EndYChanged)));
+ static void EndYChanged(DependencyObject property, DependencyPropertyChangedEventArgs args)
+ {
+ BrushPicker cp = property as BrushPicker;
+ if (cp.Brush is LinearGradientBrush)
+ {
+ cp._BrushSetInternally = true;
+ (cp.Brush as LinearGradientBrush).EndPoint = new Point((cp.Brush as LinearGradientBrush).EndPoint.X, (double)args.NewValue);
+ cp._BrushSetInternally = false;
+ }
+ }
+
+
+
+ double GradientOriginX
+ {
+ get { return (double)GetValue(GradientOriginXProperty); }
+ set { SetValue(GradientOriginXProperty, value); }
+ }
+ static readonly DependencyProperty GradientOriginXProperty =
+ DependencyProperty.Register("GradientOriginX", typeof(double), typeof(BrushPicker), new PropertyMetadata(0.5, new PropertyChangedCallback(GradientOriginXChanged)));
+ static void GradientOriginXChanged(DependencyObject property, DependencyPropertyChangedEventArgs args)
+ {
+ BrushPicker cp = property as BrushPicker;
+ if (cp.Brush is RadialGradientBrush)
+ {
+ cp._BrushSetInternally = true;
+ (cp.Brush as RadialGradientBrush).GradientOrigin = new Point((double)args.NewValue, (cp.Brush as RadialGradientBrush).GradientOrigin.Y);
+ cp._BrushSetInternally = false;
+ }
+ }
+
+ double GradientOriginY
+ {
+ get { return (double)GetValue(GradientOriginYProperty); }
+ set { SetValue(GradientOriginYProperty, value); }
+ }
+ static readonly DependencyProperty GradientOriginYProperty =
+ DependencyProperty.Register("GradientOriginY", typeof(double), typeof(BrushPicker), new PropertyMetadata(0.5, new PropertyChangedCallback(GradientOriginYChanged)));
+ static void GradientOriginYChanged(DependencyObject property, DependencyPropertyChangedEventArgs args)
+ {
+ BrushPicker cp = property as BrushPicker;
+ if (cp.Brush is RadialGradientBrush)
+ {
+ cp._BrushSetInternally = true;
+ (cp.Brush as RadialGradientBrush).GradientOrigin = new Point((cp.Brush as RadialGradientBrush).GradientOrigin.X, (double)args.NewValue);
+ cp._BrushSetInternally = false;
+ }
+ }
+
+ double CenterX
+ {
+ get { return (double)GetValue(CenterXProperty); }
+ set { SetValue(CenterXProperty, value); }
+ }
+ static readonly DependencyProperty CenterXProperty =
+ DependencyProperty.Register("CenterX", typeof(double), typeof(BrushPicker), new PropertyMetadata(0.5, new PropertyChangedCallback(CenterXChanged)));
+ static void CenterXChanged(DependencyObject property, DependencyPropertyChangedEventArgs args)
+ {
+ BrushPicker cp = property as BrushPicker;
+ if (cp.Brush is RadialGradientBrush)
+ {
+ cp._BrushSetInternally = true;
+ (cp.Brush as RadialGradientBrush).Center = new Point((double)args.NewValue, (cp.Brush as RadialGradientBrush).Center.Y);
+ cp._BrushSetInternally = false;
+ }
+ }
+
+ double CenterY
+ {
+ get { return (double)GetValue(CenterYProperty); }
+ set { SetValue(CenterYProperty, value); }
+ }
+ static readonly DependencyProperty CenterYProperty =
+ DependencyProperty.Register("CenterY", typeof(double), typeof(BrushPicker), new PropertyMetadata(0.5, new PropertyChangedCallback(CenterYChanged)));
+ static void CenterYChanged(DependencyObject property, DependencyPropertyChangedEventArgs args)
+ {
+ BrushPicker cp = property as BrushPicker;
+ if (cp.Brush is RadialGradientBrush)
+ {
+ cp._BrushSetInternally = true;
+ (cp.Brush as RadialGradientBrush).Center = new Point((cp.Brush as RadialGradientBrush).Center.X, (double)args.NewValue);
+ cp._BrushSetInternally = false;
+ }
+ }
+
+ double RadiusX
+ {
+ get { return (double)GetValue(RadiusXProperty); }
+ set { SetValue(RadiusXProperty, value); }
+ }
+ static readonly DependencyProperty RadiusXProperty =
+ DependencyProperty.Register("RadiusX", typeof(double), typeof(BrushPicker), new PropertyMetadata(0.5, new PropertyChangedCallback(RadiusXChanged)));
+ static void RadiusXChanged(DependencyObject property, DependencyPropertyChangedEventArgs args)
+ {
+ BrushPicker cp = property as BrushPicker;
+ if (cp.Brush is RadialGradientBrush)
+ {
+ cp._BrushSetInternally = true;
+ (cp.Brush as RadialGradientBrush).RadiusX = (double)args.NewValue;
+ cp._BrushSetInternally = false;
+ }
+ }
+
+ double RadiusY
+ {
+ get { return (double)GetValue(RadiusYProperty); }
+ set { SetValue(RadiusYProperty, value); }
+ }
+ static readonly DependencyProperty RadiusYProperty =
+ DependencyProperty.Register("RadiusY", typeof(double), typeof(BrushPicker), new PropertyMetadata(0.5, new PropertyChangedCallback(RadiusYChanged)));
+ static void RadiusYChanged(DependencyObject property, DependencyPropertyChangedEventArgs args)
+ {
+ BrushPicker cp = property as BrushPicker;
+ if (cp.Brush is RadialGradientBrush)
+ {
+ cp._BrushSetInternally = true;
+ (cp.Brush as RadialGradientBrush).RadiusY = (double)args.NewValue;
+ cp._BrushSetInternally = false;
+ }
+ }
+
+ double BrushOpacity
+ {
+ get { return (double)GetValue(BrushOpacityProperty); }
+ set { SetValue(BrushOpacityProperty, value); }
+ }
+ static readonly DependencyProperty BrushOpacityProperty =
+ DependencyProperty.Register("BrushOpacity", typeof(double), typeof(BrushPicker), new PropertyMetadata(1.0));
+ //static void BrushOpacityChanged(DependencyObject property, DependencyPropertyChangedEventArgs args)
+ //{
+ // ColorBox cp = property as ColorBox;
+ // cp._BrushSetInternally = true;
+ // cp.Brush.Opacity = (double)args.NewValue;
+ // cp._BrushSetInternally = false;
+ //}
+
+ GradientSpreadMethod SpreadMethod
+ {
+ get { return (GradientSpreadMethod)GetValue(SpreadMethodProperty); }
+ set { SetValue(SpreadMethodProperty, value); }
+ }
+ static readonly DependencyProperty SpreadMethodProperty =
+ DependencyProperty.Register("SpreadMethod", typeof(GradientSpreadMethod), typeof(BrushPicker), new PropertyMetadata(GradientSpreadMethod.Pad, new PropertyChangedCallback(SpreadMethodChanged)));
+ static void SpreadMethodChanged(DependencyObject property, DependencyPropertyChangedEventArgs args)
+ {
+ BrushPicker cp = property as BrushPicker;
+ if (cp.Brush is GradientBrush)
+ {
+ cp._BrushSetInternally = true;
+ (cp.Brush as GradientBrush).SpreadMethod = (GradientSpreadMethod)args.NewValue;
+ cp._BrushSetInternally = false;
+ }
+ }
+
+ BrushMappingMode MappingMode
+ {
+ get { return (BrushMappingMode)GetValue(MappingModeProperty); }
+ set { SetValue(MappingModeProperty, value); }
+ }
+ static readonly DependencyProperty MappingModeProperty =
+ DependencyProperty.Register("MappingMode", typeof(BrushMappingMode), typeof(BrushPicker), new PropertyMetadata(BrushMappingMode.RelativeToBoundingBox, new PropertyChangedCallback(MappingModeChanged)));
+ static void MappingModeChanged(DependencyObject property, DependencyPropertyChangedEventArgs args)
+ {
+ BrushPicker cp = property as BrushPicker;
+ if (cp.Brush is GradientBrush)
+ {
+ cp._BrushSetInternally = true;
+ (cp.Brush as GradientBrush).MappingMode = (BrushMappingMode)args.NewValue;
+ cp._BrushSetInternally = false;
+ }
+ }
+
+ #endregion
+
+ #region Internal Properties
+
+ internal ObservableCollection<GradientStop> Gradients
+ {
+ get { return (ObservableCollection<GradientStop>)GetValue(GradientsProperty); }
+ set { SetValue(GradientsProperty, value); }
+ }
+ internal static readonly DependencyProperty GradientsProperty =
+ DependencyProperty.Register("Gradients", typeof(ObservableCollection<GradientStop>), typeof(BrushPicker));
+
+ internal GradientStop SelectedGradient
+ {
+ get { return (GradientStop)GetValue(SelectedGradientProperty); }
+ set { SetValue(SelectedGradientProperty, value); }
+ }
+ internal static readonly DependencyProperty SelectedGradientProperty =
+ DependencyProperty.Register("SelectedGradient", typeof(GradientStop), typeof(BrushPicker));
+
+ internal BrushTypes BrushType
+ {
+ get { return (BrushTypes)GetValue(BrushTypeProperty); }
+ set { SetValue(BrushTypeProperty, value); }
+ }
+ internal static readonly DependencyProperty BrushTypeProperty =
+ DependencyProperty.Register("BrushType", typeof(BrushTypes), typeof(BrushPicker),
+ new FrameworkPropertyMetadata(BrushTypes.None, new PropertyChangedCallback(BrushTypeChanged)));
+ static void BrushTypeChanged(DependencyObject property, DependencyPropertyChangedEventArgs args)
+ {
+ BrushPicker c = property as BrushPicker;
+ if (!c._BrushTypeSetInternally)
+ {
+ if (c.Gradients == null)
+ {
+ c.Gradients = new ObservableCollection<GradientStop>();
+ c.Gradients.Add(new GradientStop(Colors.Black, 0));
+ c.Gradients.Add(new GradientStop(Colors.White, 1));
+ }
+
+ c.SetBrush();
+ }
+ }
+
+ #endregion
+
+ #region Public Properties
+
+ public IEnumerable<Enum> SpreadMethodTypes
+ {
+ get
+ {
+ GradientSpreadMethod temp = GradientSpreadMethod.Pad | GradientSpreadMethod.Reflect | GradientSpreadMethod.Repeat;
+ foreach (Enum value in Enum.GetValues(temp.GetType()))
+ if (temp.HasFlag(value))
+ yield return value;
+ }
+ }
+
+ public IEnumerable<Enum> MappingModeTypes
+ {
+ get
+ {
+ BrushMappingMode temp = BrushMappingMode.Absolute | BrushMappingMode.RelativeToBoundingBox;
+ foreach (Enum value in Enum.GetValues(temp.GetType()))
+ if (temp.HasFlag(value))
+ yield return value;
+ }
+ }
+
+ public IEnumerable<Enum> AvailableBrushTypes
+ {
+ get
+ {
+ List<Enum> brushTypes = new List<Enum>();
+ brushTypes.Add(BrushTypes.Solid);
+ brushTypes.Add(BrushTypes.Linear);
+ return brushTypes;
+ }
+ }
+
+ public Brush Brush
+ {
+ get { return (Brush)GetValue(BrushProperty); }
+ set { SetValue(BrushProperty, value); }
+ }
+ public static readonly DependencyProperty BrushProperty =
+ DependencyProperty.Register("Brush", typeof(Brush), typeof(BrushPicker)
+ , new FrameworkPropertyMetadata(null, new PropertyChangedCallback(BrushChanged)));
+ static void BrushChanged(DependencyObject property, DependencyPropertyChangedEventArgs args)
+ {
+ BrushPicker c = property as BrushPicker;
+ Brush brush = args.NewValue as Brush;
+
+ if (!c._BrushSetInternally)
+ {
+ c._BrushTypeSetInternally = true;
+
+ if (brush == null)
+ {
+ c.BrushType = BrushTypes.None;
+ }
+ else if (brush is SolidColorBrush)
+ {
+ c.BrushType = BrushTypes.Solid;
+ c.Color = (brush as SolidColorBrush).Color;
+ }
+ else if (brush is LinearGradientBrush)
+ {
+ LinearGradientBrush lgb = brush as LinearGradientBrush;
+ //c.Opacity = lgb.Opacity;
+ c.StartX = lgb.StartPoint.X;
+ c.StartY = lgb.StartPoint.Y;
+ c.EndX = lgb.EndPoint.X;
+ c.EndY = lgb.EndPoint.Y;
+ c.MappingMode = lgb.MappingMode;
+ c.SpreadMethod = lgb.SpreadMethod;
+ c.Gradients = new ObservableCollection<GradientStop>(lgb.GradientStops);
+ c.BrushType = BrushTypes.Linear;
+ //c.Color = lgb.GradientStops.OrderBy(x => x.Offset).Last().Color;
+ //c.SelectedGradient = lgb.GradientStops.OrderBy(x => x.Offset).Last();
+ }
+ else
+ {
+ RadialGradientBrush rgb = brush as RadialGradientBrush;
+ c.GradientOriginX = rgb.GradientOrigin.X;
+ c.GradientOriginY = rgb.GradientOrigin.Y;
+ c.RadiusX = rgb.RadiusX;
+ c.RadiusY = rgb.RadiusY;
+ c.CenterX = rgb.Center.X;
+ c.CenterY = rgb.Center.Y;
+ c.MappingMode = rgb.MappingMode;
+ c.SpreadMethod = rgb.SpreadMethod;
+ c.Gradients = new ObservableCollection<GradientStop>(rgb.GradientStops);
+ c.BrushType = BrushTypes.Radial;
+ //c.Color = rgb.GradientStops.OrderBy(x => x.Offset).Last().Color;
+ //c.SelectedGradient = rgb.GradientStops.OrderBy(x => x.Offset).Last();
+ }
+
+ c._BrushTypeSetInternally = false;
+ }
+ }
+
+ public Color Color
+ {
+ get { return (Color)GetValue(ColorProperty); }
+ set { SetValue(ColorProperty, value); }
+ }
+ public static readonly DependencyProperty ColorProperty =
+ DependencyProperty.Register("Color", typeof(Color), typeof(BrushPicker), new UIPropertyMetadata(Colors.Black, OnColorChanged));
+ public static void OnColorChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
+ {
+ BrushPicker c = (BrushPicker)o;
+
+ if (e.NewValue is Color)
+ {
+ Color color = (Color)e.NewValue;
+
+ if (!c._HSBSetInternally)
+ {
+ // update HSB value based on new value of color
+
+ double H = 0;
+ double S = 0;
+ double B = 0;
+ ColorHelper.HSBFromColor(color, ref H, ref S, ref B);
+
+ c._HSBSetInternally = true;
+
+ c.Alpha = (double)(color.A / 255d);
+ c.Hue = H;
+ c.Saturation = S;
+ c.Brightness = B;
+
+ c._HSBSetInternally = false;
+ }
+
+ if (!c._RGBSetInternally)
+ {
+ // update RGB value based on new value of color
+
+ c._RGBSetInternally = true;
+
+ c.A = color.A;
+ c.R = color.R;
+ c.G = color.G;
+ c.B = color.B;
+
+ c._RGBSetInternally = false;
+ }
+
+ c.RaiseColorChangedEvent((Color)e.NewValue);
+ }
+ }
+
+ #endregion
+
+
+ #region Color Specific Properties
+
+ private double Hue
+ {
+ get { return (double)GetValue(HueProperty); }
+ set { SetValue(HueProperty, value); }
+ }
+ private static readonly DependencyProperty HueProperty =
+ DependencyProperty.Register("Hue", typeof(double), typeof(BrushPicker),
+ new FrameworkPropertyMetadata(1.0, new PropertyChangedCallback(UpdateColorHSB), new CoerceValueCallback(HueCoerce)));
+ private static object HueCoerce(DependencyObject d, object Hue)
+ {
+ double v = (double)Hue;
+ if (v < 0) return 0.0;
+ if (v > 1) return 1.0;
+ return v;
+ }
+
+
+ private double Brightness
+ {
+ get { return (double)GetValue(BrightnessProperty); }
+ set { SetValue(BrightnessProperty, value); }
+ }
+ private static readonly DependencyProperty BrightnessProperty =
+ DependencyProperty.Register("Brightness", typeof(double), typeof(BrushPicker),
+ new FrameworkPropertyMetadata(0.0, new PropertyChangedCallback(UpdateColorHSB), new CoerceValueCallback(BrightnessCoerce)));
+ private static object BrightnessCoerce(DependencyObject d, object Brightness)
+ {
+ double v = (double)Brightness;
+ if (v < 0) return 0.0;
+ if (v > 1) return 1.0;
+ return v;
+ }
+
+
+ private double Saturation
+ {
+ get { return (double)GetValue(SaturationProperty); }
+ set { SetValue(SaturationProperty, value); }
+ }
+ private static readonly DependencyProperty SaturationProperty =
+ DependencyProperty.Register("Saturation", typeof(double), typeof(BrushPicker),
+ new FrameworkPropertyMetadata(0.0, new PropertyChangedCallback(UpdateColorHSB), new CoerceValueCallback(SaturationCoerce)));
+ private static object SaturationCoerce(DependencyObject d, object Saturation)
+ {
+ double v = (double)Saturation;
+ if (v < 0) return 0.0;
+ if (v > 1) return 1.0;
+ return v;
+ }
+
+
+ private double Alpha
+ {
+ get { return (double)GetValue(AlphaProperty); }
+ set { SetValue(AlphaProperty, value); }
+ }
+ private static readonly DependencyProperty AlphaProperty =
+ DependencyProperty.Register("Alpha", typeof(double), typeof(BrushPicker),
+ new FrameworkPropertyMetadata(1.0, new PropertyChangedCallback(UpdateColorHSB), new CoerceValueCallback(AlphaCoerce)));
+ private static object AlphaCoerce(DependencyObject d, object Alpha)
+ {
+ double v = (double)Alpha;
+ if (v < 0) return 0.0;
+ if (v > 1) return 1.0;
+ return v;
+ }
+
+
+ private int A
+ {
+ get { return (int)GetValue(AProperty); }
+ set { SetValue(AProperty, value); }
+ }
+ private static readonly DependencyProperty AProperty =
+ DependencyProperty.Register("A", typeof(int), typeof(BrushPicker),
+ new FrameworkPropertyMetadata(255, new PropertyChangedCallback(UpdateColorRGB), new CoerceValueCallback(RGBCoerce)));
+
+
+ private int R
+ {
+ get { return (int)GetValue(RProperty); }
+ set { SetValue(RProperty, value); }
+ }
+ private static readonly DependencyProperty RProperty =
+ DependencyProperty.Register("R", typeof(int), typeof(BrushPicker),
+ new FrameworkPropertyMetadata(default(int), new PropertyChangedCallback(UpdateColorRGB), new CoerceValueCallback(RGBCoerce)));
+
+
+ private int G
+ {
+ get { return (int)GetValue(GProperty); }
+ set { SetValue(GProperty, value); }
+ }
+ private static readonly DependencyProperty GProperty =
+ DependencyProperty.Register("G", typeof(int), typeof(BrushPicker),
+ new FrameworkPropertyMetadata(default(int), new PropertyChangedCallback(UpdateColorRGB), new CoerceValueCallback(RGBCoerce)));
+
+
+ private int B
+ {
+ get { return (int)GetValue(BProperty); }
+ set { SetValue(BProperty, value); }
+ }
+ private static readonly DependencyProperty BProperty =
+ DependencyProperty.Register("B", typeof(int), typeof(BrushPicker),
+ new FrameworkPropertyMetadata(default(int), new PropertyChangedCallback(UpdateColorRGB), new CoerceValueCallback(RGBCoerce)));
+
+
+ private static object RGBCoerce(DependencyObject d, object value)
+ {
+ int v = (int)value;
+ if (v < 0) return 0;
+ if (v > 255) return 255;
+ return v;
+ }
+
+ #endregion
+
+ /// <summary>
+ /// Shared property changed callback to update the Color property
+ /// </summary>
+ public static void UpdateColorHSB(object o, DependencyPropertyChangedEventArgs e)
+ {
+ BrushPicker c = (BrushPicker)o;
+ Color n = ColorHelper.ColorFromAHSB(c.Alpha, c.Hue, c.Saturation, c.Brightness);
+
+ c._HSBSetInternally = true;
+
+ c.Color = n;
+
+ if (c.SelectedGradient != null)
+ c.SelectedGradient.Color = n;
+
+ c.SetBrush();
+
+ c._HSBSetInternally = false;
+ }
+
+ /// <summary>
+ /// Shared property changed callback to update the Color property
+ /// </summary>
+ public static void UpdateColorRGB(object o, DependencyPropertyChangedEventArgs e)
+ {
+ BrushPicker c = (BrushPicker)o;
+ Color n = Color.FromArgb((byte)c.A, (byte)c.R, (byte)c.G, (byte)c.B);
+
+ c._RGBSetInternally = true;
+
+ c.Color = n;
+
+ if (c.SelectedGradient != null)
+ c.SelectedGradient.Color = n;
+
+ c.SetBrush();
+
+ c._RGBSetInternally = false;
+ }
+
+ #region ColorChanged Event
+
+ public delegate void ColorChangedEventHandler(object sender, ColorChangedEventArgs e);
+
+ public static readonly RoutedEvent ColorChangedEvent =
+ EventManager.RegisterRoutedEvent("ColorChanged", RoutingStrategy.Bubble, typeof(ColorChangedEventHandler), typeof(BrushPicker));
+
+ public event ColorChangedEventHandler ColorChanged
+ {
+ add { AddHandler(ColorChangedEvent, value); }
+ remove { RemoveHandler(ColorChangedEvent, value); }
+ }
+
+ void RaiseColorChangedEvent(Color color)
+ {
+ ColorChangedEventArgs newEventArgs = new ColorChangedEventArgs(BrushPicker.ColorChangedEvent, color);
+ RaiseEvent(newEventArgs);
+ }
+
+ #endregion
+
+ internal void SetBrush()
+ {
+ if (!_UpdateBrush)
+ return;
+
+ this._BrushSetInternally = true;
+
+ // retain old opacity
+ double opacity = 1;
+ TransformGroup tempTG = null;
+ if (this.Brush != null)
+ {
+ opacity = this.Brush.Opacity;
+ tempTG = Brush.Transform as TransformGroup;
+ }
+
+ switch (BrushType)
+ {
+ case BrushTypes.None: Brush = null; break;
+
+ case BrushTypes.Solid:
+
+ Brush = new SolidColorBrush(this.Color);
+
+ break;
+
+ case BrushTypes.Linear:
+
+ var brush = new LinearGradientBrush();
+ foreach (GradientStop g in Gradients)
+ {
+ brush.GradientStops.Add(new GradientStop(g.Color, g.Offset));
+ }
+ brush.StartPoint = new Point(this.StartX, this.StartY);
+ brush.EndPoint = new Point(this.EndX, this.EndY);
+ brush.MappingMode = this.MappingMode;
+ brush.SpreadMethod = this.SpreadMethod;
+ Brush = brush;
+
+ break;
+
+ case BrushTypes.Radial:
+
+ var brush1 = new RadialGradientBrush();
+ foreach (GradientStop g in Gradients)
+ {
+ brush1.GradientStops.Add(new GradientStop(g.Color, g.Offset));
+ }
+ brush1.GradientOrigin = new Point(this.GradientOriginX, this.GradientOriginY);
+ brush1.Center = new Point(this.CenterX, this.CenterY);
+ brush1.RadiusX = this.RadiusX;
+ brush1.RadiusY = this.RadiusY;
+ brush1.MappingMode = this.MappingMode;
+ brush1.SpreadMethod = this.SpreadMethod;
+ Brush = brush1;
+
+ break;
+ }
+
+ if (this.BrushType != BrushTypes.None)
+ {
+ this.Brush.Opacity = opacity; // retain old opacity
+ if (tempTG != null)
+ this.Brush.Transform = tempTG;
+ }
+
+ this._BrushSetInternally = false;
+ }
+ }
+}
diff --git a/Software/Visual_Studio/Tango.BrushPicker/Implementation/BrushTypes.cs b/Software/Visual_Studio/Tango.BrushPicker/Implementation/BrushTypes.cs
new file mode 100644
index 000000000..4656a8611
--- /dev/null
+++ b/Software/Visual_Studio/Tango.BrushPicker/Implementation/BrushTypes.cs
@@ -0,0 +1,23 @@
+/***************** NCore Softwares Pvt. Ltd., India **************************
+
+ ColorBox
+
+ Copyright (C) 2013 NCore Softwares Pvt. Ltd.
+
+ This program is provided to you under the terms of the Microsoft Public
+ License (Ms-PL) as published at http://colorbox.codeplex.com/license
+
+***********************************************************************************/
+
+using System;
+
+namespace Tango.BrushPicker
+{
+ internal enum BrushTypes
+ {
+ None,
+ Solid,
+ Linear,
+ Radial
+ }
+}
diff --git a/Software/Visual_Studio/Tango.BrushPicker/Implementation/ColorChangedEventArgs.cs b/Software/Visual_Studio/Tango.BrushPicker/Implementation/ColorChangedEventArgs.cs
new file mode 100644
index 000000000..b33a5806d
--- /dev/null
+++ b/Software/Visual_Studio/Tango.BrushPicker/Implementation/ColorChangedEventArgs.cs
@@ -0,0 +1,33 @@
+/***************** NCore Softwares Pvt. Ltd., India **************************
+
+ ColorBox
+
+ Copyright (C) 2013 NCore Softwares Pvt. Ltd.
+
+ This program is provided to you under the terms of the Microsoft Public
+ License (Ms-PL) as published at http://ColorBox.codeplex.com/license
+
+***********************************************************************************/
+
+using System;
+using System.Windows.Media;
+using System.Windows;
+
+namespace Tango.BrushPicker
+{
+ public class ColorChangedEventArgs : RoutedEventArgs
+ {
+ public ColorChangedEventArgs(RoutedEvent routedEvent, Color color)
+ {
+ this.RoutedEvent = routedEvent;
+ this.Color = color;
+ }
+
+ private Color _Color;
+ public Color Color
+ {
+ get { return _Color; }
+ set { _Color = value; }
+ }
+ }
+}
diff --git a/Software/Visual_Studio/Tango.BrushPicker/Implementation/DoubleUpDown.cs b/Software/Visual_Studio/Tango.BrushPicker/Implementation/DoubleUpDown.cs
new file mode 100644
index 000000000..755ca7299
--- /dev/null
+++ b/Software/Visual_Studio/Tango.BrushPicker/Implementation/DoubleUpDown.cs
@@ -0,0 +1,201 @@
+/*************************************************************************************
+
+ Extended WPF Toolkit
+
+ Copyright (C) 2007-2013 Xceed Software Inc.
+
+ This program is provided to you under the terms of the Microsoft Public
+ License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
+
+ For more features, controls, and fast professional support,
+ pick up the Plus Edition at http://xceed.com/wpf_toolkit
+
+ Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
+
+ ***********************************************************************************/
+
+using System;
+using System.Windows;
+using System.Globalization;
+using System.IO;
+
+namespace Tango.BrushPicker
+{
+ class DoubleUpDown : UpDownBase
+ {
+ protected delegate double FromText(string s, NumberStyles style, IFormatProvider provider);
+ protected delegate double FromDecimal(decimal d);
+
+ private FromText _fromText;
+ private FromDecimal _fromDecimal;
+ private Func<double, double, bool> _fromLowerThan;
+ private Func<double, double, bool> _fromGreaterThan;
+
+ protected DoubleUpDown(FromText fromText, FromDecimal fromDecimal, Func<double, double, bool> fromLowerThan, Func<double, double, bool> fromGreaterThan)
+ {
+ if (fromText == null)
+ throw new ArgumentNullException("parseMethod");
+
+ if (fromDecimal == null)
+ throw new ArgumentNullException("fromDecimal");
+
+ if (fromLowerThan == null)
+ throw new ArgumentNullException("fromLowerThan");
+
+ if (fromGreaterThan == null)
+ throw new ArgumentNullException("fromGreaterThan");
+
+ _fromText = fromText;
+ _fromDecimal = fromDecimal;
+ _fromLowerThan = fromLowerThan;
+ _fromGreaterThan = fromGreaterThan;
+ }
+
+ protected static void UpdateMetadata(Type type, double? increment, double? minValue, double? maxValue)
+ {
+ DefaultStyleKeyProperty.OverrideMetadata(type, new FrameworkPropertyMetadata(type));
+ IncrementProperty.OverrideMetadata(type, new FrameworkPropertyMetadata(increment));
+ MaximumProperty.OverrideMetadata(type, new FrameworkPropertyMetadata(maxValue));
+ MinimumProperty.OverrideMetadata(type, new FrameworkPropertyMetadata(minValue));
+ }
+
+ private bool IsLowerThan(double? value1, double? value2)
+ {
+ if (value1 == null || value2 == null)
+ return false;
+
+ return _fromLowerThan(value1.Value, value2.Value);
+ }
+
+ private bool IsGreaterThan(double? value1, double? value2)
+ {
+ if (value1 == null || value2 == null)
+ return false;
+
+ return _fromGreaterThan(value1.Value, value2.Value);
+ }
+
+ private bool HandleNullSpin()
+ {
+ if (!Value.HasValue)
+ {
+ double forcedValue = (DefaultValue.HasValue)
+ ? DefaultValue.Value
+ : default(double);
+
+ Value = CoerceValueMinMax(forcedValue);
+
+ return true;
+ }
+ else if (!Increment.HasValue)
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ private double CoerceValueMinMax(double value)
+ {
+ if (IsLowerThan(value, Minimum))
+ return Minimum;
+ else if (IsGreaterThan(value, Maximum))
+ return Maximum;
+ else
+ return value;
+ }
+
+ private void ValidateDefaultMinMax(double? value)
+ {
+ if (object.Equals(value, DefaultValue))
+ return;
+
+ if (IsLowerThan(value, Minimum))
+ throw new ArgumentOutOfRangeException("Minimum", String.Format("Value must be greater than MinValue of {0}", Minimum));
+ else if (IsGreaterThan(value, Maximum))
+ throw new ArgumentOutOfRangeException("Maximum", String.Format("Value must be less than MaxValue of {0}", Maximum));
+ }
+
+ #region Base Class Overrides
+
+ protected override void OnIncrement()
+ {
+ if (!HandleNullSpin())
+ {
+ double? result = Value.Value + Increment.Value;
+ Value = CoerceValueMinMax(result.Value);
+ }
+ }
+
+ protected override void OnDecrement()
+ {
+ if (!HandleNullSpin())
+ {
+ double? result = Value.Value - Increment.Value;
+ Value = CoerceValueMinMax(result.Value);
+ }
+ }
+
+ protected override string ConvertValueToText()
+ {
+ if (Value == null)
+ return string.Empty;
+
+ return Value.Value.ToString(FormatString, CultureInfo);
+ }
+
+ protected override double? ConvertTextToValue(string text)
+ {
+ double? result = 0;
+
+ if (String.IsNullOrEmpty(text))
+ return result;
+
+ string currentValueText = ConvertValueToText();
+ if (object.Equals(currentValueText, text))
+ return this.Value;
+
+ result = FormatString.Contains("P")
+ ? _fromDecimal(ParsePercent(text, CultureInfo))
+ : _fromText(text, this.ParsingNumberStyle, CultureInfo);
+
+ ValidateDefaultMinMax(result);
+
+ return result;
+ }
+
+ protected override void SetValidSpinDirection()
+ {
+ ValidSpinDirections validDirections = ValidSpinDirections.None;
+
+ if ((this.Increment != null) && !IsReadOnly)
+ {
+ if (IsLowerThan(Value, Maximum) || !Value.HasValue)
+ validDirections = validDirections | ValidSpinDirections.Increase;
+
+ if (IsGreaterThan(Value, Minimum) || !Value.HasValue)
+ validDirections = validDirections | ValidSpinDirections.Decrease;
+ }
+
+ if (Spinner != null)
+ Spinner.ValidSpinDirection = validDirections;
+ }
+
+ #endregion
+
+ #region Constructors
+
+ static DoubleUpDown()
+ {
+ UpdateMetadata(typeof(DoubleUpDown), 1d, double.NegativeInfinity, double.PositiveInfinity);
+ }
+
+ public DoubleUpDown()
+ : this(Double.Parse, Decimal.ToDouble, (v1, v2) => v1 < v2, (v1, v2) => v1 > v2)
+ {
+
+ }
+
+ #endregion
+ }
+}
diff --git a/Software/Visual_Studio/Tango.BrushPicker/Implementation/Enums.cs b/Software/Visual_Studio/Tango.BrushPicker/Implementation/Enums.cs
new file mode 100644
index 000000000..7c242e844
--- /dev/null
+++ b/Software/Visual_Studio/Tango.BrushPicker/Implementation/Enums.cs
@@ -0,0 +1,45 @@
+/*************************************************************************************
+
+ Extended WPF Toolkit
+
+ Copyright (C) 2007-2013 Xceed Software Inc.
+
+ This program is provided to you under the terms of the Microsoft Public
+ License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
+
+ For more features, controls, and fast professional support,
+ pick up the Plus Edition at http://xceed.com/wpf_toolkit
+
+ Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
+
+ ***********************************************************************************/
+
+using System;
+
+namespace Tango.BrushPicker
+{
+ internal enum SpinDirection
+ {
+ Increase,
+ Decrease
+ }
+
+
+ internal enum ValidSpinDirections
+ {
+ None,
+ Increase,
+ Decrease
+ }
+
+
+ internal enum AllowedSpecialValues
+ {
+ None = 0,
+ NaN = 1,
+ PositiveInfinity = 2,
+ NegativeInfinity = 4,
+ AnyInfinity = PositiveInfinity | NegativeInfinity,
+ Any = NaN | AnyInfinity
+ }
+}
diff --git a/Software/Visual_Studio/Tango.BrushPicker/Implementation/GradientStopAdder.cs b/Software/Visual_Studio/Tango.BrushPicker/Implementation/GradientStopAdder.cs
new file mode 100644
index 000000000..24f1e9a5a
--- /dev/null
+++ b/Software/Visual_Studio/Tango.BrushPicker/Implementation/GradientStopAdder.cs
@@ -0,0 +1,81 @@
+/***************** NCore Softwares Pvt. Ltd., India **************************
+
+ ColorBox
+
+ Copyright (C) 2013 NCore Softwares Pvt. Ltd.
+
+ This program is provided to you under the terms of the Microsoft Public
+ License (Ms-PL) as published at http://colorbox.codeplex.com/license
+
+***********************************************************************************/
+
+using System;
+using System.Windows.Media;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Input;
+using System.Collections.ObjectModel;
+using System.Windows.Media.Imaging;
+
+namespace Tango.BrushPicker
+{
+ class GradientStopAdder : Button
+ {
+ protected override void OnPreviewMouseLeftButtonDown(MouseButtonEventArgs e)
+ {
+ base.OnPreviewMouseLeftButtonDown(e);
+
+ if (e.Source is GradientStopAdder && this.ColorBox != null)
+ {
+ Button btn = e.Source as Button;
+
+ GradientStop _gs = new GradientStop();
+ _gs.Offset = Mouse.GetPosition(btn).X / btn.ActualWidth;
+ //_gs.Color = this.ColorBox.Color;
+ _gs.Color = GetColorFromImage(e.GetPosition(this));
+ this.ColorBox.Gradients.Insert(this.ColorBox.Gradients.Count - 1, _gs);
+ this.ColorBox.SelectedGradient = _gs;
+ this.ColorBox.Color = _gs.Color;
+ this.ColorBox.SetBrush();
+ }
+ }
+
+ Color GetColorFromImage(Point p)
+ {
+ try
+ {
+ Rect bounds = VisualTreeHelper.GetDescendantBounds(this);
+ RenderTargetBitmap rtb = new RenderTargetBitmap((Int32)bounds.Width, (Int32)bounds.Height, 96, 96, PixelFormats.Default);
+ rtb.Render(this);
+
+ byte[] arr;
+ PngBitmapEncoder png = new PngBitmapEncoder();
+ png.Frames.Add(BitmapFrame.Create(rtb));
+ using (var stream = new System.IO.MemoryStream())
+ {
+ png.Save(stream);
+ arr = stream.ToArray();
+ }
+
+ BitmapSource bitmap = BitmapFrame.Create(new System.IO.MemoryStream(arr));
+
+ byte[] pixels = new byte[4];
+ CroppedBitmap cb = new CroppedBitmap(bitmap, new Int32Rect((int)p.X, (int)p.Y, 1, 1));
+ cb.CopyPixels(pixels, 4, 0);
+ return Color.FromArgb(pixels[3], pixels[2], pixels[1], pixels[0]);
+ }
+ catch (Exception)
+ {
+ return this.ColorBox.Color;
+ }
+ }
+
+ public BrushPicker ColorBox
+ {
+ get { return (BrushPicker)GetValue(ColorBoxProperty); }
+ set { SetValue(ColorBoxProperty, value); }
+ }
+ public static readonly DependencyProperty ColorBoxProperty =
+ DependencyProperty.Register("ColorBox", typeof(BrushPicker), typeof(GradientStopAdder));
+ }
+}
diff --git a/Software/Visual_Studio/Tango.BrushPicker/Implementation/GradientStopSlider.cs b/Software/Visual_Studio/Tango.BrushPicker/Implementation/GradientStopSlider.cs
new file mode 100644
index 000000000..710594415
--- /dev/null
+++ b/Software/Visual_Studio/Tango.BrushPicker/Implementation/GradientStopSlider.cs
@@ -0,0 +1,86 @@
+/***************** NCore Softwares Pvt. Ltd., India **************************
+
+ ColorBox
+
+ Copyright (C) 2013 NCore Softwares Pvt. Ltd.
+
+ This program is provided to you under the terms of the Microsoft Public
+ License (Ms-PL) as published at http://colorbox.codeplex.com/license
+
+***********************************************************************************/
+
+using System;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Linq;
+using System.Collections;
+
+namespace Tango.BrushPicker
+{
+ class GradientStopSlider : Slider
+ {
+ protected override void OnPreviewMouseLeftButtonDown(MouseButtonEventArgs e)
+ {
+ base.OnPreviewMouseLeftButtonDown(e);
+
+ if (this.ColorBox != null)
+ {
+ this.ColorBox._BrushSetInternally = true;
+ this.ColorBox._UpdateBrush = false;
+
+ this.ColorBox.SelectedGradient = this.SelectedGradient;
+ this.ColorBox.Color = this.SelectedGradient.Color;
+
+ this.ColorBox._UpdateBrush = true;
+ }
+ }
+
+ protected override void OnValueChanged(double oldValue, double newValue)
+ {
+ if (ColorBox != null && ColorBox.Gradients != null)
+ {
+ if (ColorBox.Gradients.FirstOrDefault() == SelectedGradient)
+ {
+ Value = 0;
+ return;
+ }
+ else if (ColorBox.Gradients.LastOrDefault() == SelectedGradient)
+ {
+ Value = 1;
+ return;
+ }
+ }
+
+ base.OnValueChanged(oldValue, newValue);
+
+ if (this.ColorBox != null)
+ {
+ //this.ColorBox._HSBSetInternally = true;
+ //this.ColorBox._RGBSetInternally = true;
+ this.ColorBox._BrushSetInternally = true;
+ this.ColorBox.SetBrush();
+ this.ColorBox._HSBSetInternally = false;
+ //this.ColorBox._RGBSetInternally = false;
+ //this.ColorBox._BrushSetInternally = false;
+ }
+ }
+
+ public BrushPicker ColorBox
+ {
+ get { return (BrushPicker)GetValue(ColorBoxProperty); }
+ set { SetValue(ColorBoxProperty, value); }
+ }
+ public static readonly DependencyProperty ColorBoxProperty =
+ DependencyProperty.Register("ColorBox", typeof(BrushPicker), typeof(GradientStopSlider));
+
+ public GradientStop SelectedGradient
+ {
+ get { return (GradientStop)GetValue(SelectedGradientProperty); }
+ set { SetValue(SelectedGradientProperty, value); }
+ }
+ public static readonly DependencyProperty SelectedGradientProperty =
+ DependencyProperty.Register("SelectedGradient", typeof(GradientStop), typeof(GradientStopSlider));
+ }
+}
diff --git a/Software/Visual_Studio/Tango.BrushPicker/Implementation/HueSelector.cs b/Software/Visual_Studio/Tango.BrushPicker/Implementation/HueSelector.cs
new file mode 100644
index 000000000..102c9d74c
--- /dev/null
+++ b/Software/Visual_Studio/Tango.BrushPicker/Implementation/HueSelector.cs
@@ -0,0 +1,143 @@
+/***************** NCore Softwares Pvt. Ltd., India **************************
+
+ ColorBox
+
+ Copyright (C) 2013 NCore Softwares Pvt. Ltd.
+
+ This program is provided to you under the terms of the Microsoft Public
+ License (Ms-PL) as published at http://ColorBox.codeplex.com/license
+
+***********************************************************************************/
+
+using System;
+using System.Windows.Media;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Input;
+
+namespace Tango.BrushPicker
+{
+ class HueSelector : BaseSelector
+ {
+ public double Hue
+ {
+ get { return (double)GetValue(HueProperty); }
+ set { SetValue(HueProperty, value); }
+ }
+ public static readonly DependencyProperty HueProperty =
+ DependencyProperty.Register("Hue", typeof(double), typeof(HueSelector),
+ new FrameworkPropertyMetadata(0.0, new PropertyChangedCallback(HueChanged), new CoerceValueCallback(HueCoerce)));
+ public static void HueChanged(object o, DependencyPropertyChangedEventArgs e)
+ {
+ HueSelector h = (HueSelector)o;
+ h.SetHueOffset();
+ h.SetColor();
+ }
+ public static object HueCoerce(DependencyObject d, object Brightness)
+ {
+ double v = (double)Brightness;
+ if (v < 0) return 0.0;
+ if (v > 1) return 1.0;
+ return v;
+ }
+
+
+ public double HueOffset
+ {
+ get { return (double)GetValue(HueOffsetProperty); }
+ private set { SetValue(HueOffsetProperty, value); }
+ }
+ public static readonly DependencyProperty HueOffsetProperty =
+ DependencyProperty.Register("HueOffset", typeof(double), typeof(HueSelector), new UIPropertyMetadata(0.0));
+
+
+ protected override void OnMouseMove(MouseEventArgs e)
+ {
+ if (e.LeftButton == MouseButtonState.Pressed)
+ {
+ Point p = e.GetPosition(this);
+
+ if (Orientation == Orientation.Vertical)
+ {
+ Hue = 1 - (p.Y / this.ActualHeight);
+ }
+ else
+ {
+ Hue = 1 - (p.X / this.ActualWidth);
+ }
+ }
+ base.OnMouseMove(e);
+ }
+
+ protected override void OnMouseDown(MouseButtonEventArgs e)
+ {
+ if (e.LeftButton == MouseButtonState.Pressed)
+ {
+ Point p = e.GetPosition(this);
+
+ if (Orientation == Orientation.Vertical)
+ {
+ Hue = 1 - (p.Y / this.ActualHeight);
+ }
+ else
+ {
+ Hue = 1 - (p.X / this.ActualWidth);
+ }
+ }
+ Mouse.Capture(this);
+ base.OnMouseMove(e);
+ }
+
+ protected override void OnMouseUp(MouseButtonEventArgs e)
+ {
+ this.ReleaseMouseCapture();
+ base.OnMouseUp(e);
+ }
+
+ protected override void OnRender(DrawingContext dc)
+ {
+ LinearGradientBrush lb = new LinearGradientBrush();
+
+ lb.StartPoint = new Point(0, 0);
+
+ if (Orientation == Orientation.Vertical)
+ lb.EndPoint = new Point(0, 1);
+ else
+ lb.EndPoint = new Point(1, 0);
+
+ lb.GradientStops.Add(new GradientStop(Color.FromRgb(0xFF, 0x00, 0x00), 1.00));
+ lb.GradientStops.Add(new GradientStop(Color.FromRgb(0xFF, 0xFF, 0x00), 0.85));
+ lb.GradientStops.Add(new GradientStop(Color.FromRgb(0x00, 0xFF, 0x00), 0.76));
+ lb.GradientStops.Add(new GradientStop(Color.FromRgb(0x00, 0xFF, 0xFF), 0.50));
+ lb.GradientStops.Add(new GradientStop(Color.FromRgb(0x00, 0x00, 0xFF), 0.33));
+ lb.GradientStops.Add(new GradientStop(Color.FromRgb(0xFF, 0x00, 0xFF), 0.16));
+ lb.GradientStops.Add(new GradientStop(Color.FromRgb(0xFF, 0x00, 0x00), 0.00));
+
+ dc.DrawRectangle(lb, null, new Rect(0, 0, ActualWidth, ActualHeight));
+
+ SetHueOffset();
+ }
+
+ protected override Size ArrangeOverride(Size finalSize)
+ {
+ SetHueOffset();
+ return base.ArrangeOverride(finalSize);
+ }
+
+
+ private void SetHueOffset()
+ {
+ double length = ActualHeight;
+ if (Orientation == Orientation.Horizontal)
+ length = ActualWidth;
+
+ HueOffset = length - (length * Hue);
+ }
+
+ private void SetColor()
+ {
+ base.Color = ColorHelper.ColorFromHSB(Hue, 1, 1);
+ //base.Brush = new SolidColorBrush(Color);
+ }
+ }
+}
diff --git a/Software/Visual_Studio/Tango.BrushPicker/Implementation/SaturationBrightnessSelector.cs b/Software/Visual_Studio/Tango.BrushPicker/Implementation/SaturationBrightnessSelector.cs
new file mode 100644
index 000000000..17a0db112
--- /dev/null
+++ b/Software/Visual_Studio/Tango.BrushPicker/Implementation/SaturationBrightnessSelector.cs
@@ -0,0 +1,174 @@
+/***************** NCore Softwares Pvt. Ltd., India **************************
+
+ ColorBox
+
+ Copyright (C) 2013 NCore Softwares Pvt. Ltd.
+
+ This program is provided to you under the terms of the Microsoft Public
+ License (Ms-PL) as published at http://ColorBox.codeplex.com/license
+
+***********************************************************************************/
+
+using System;
+using System.Windows;
+using System.Windows.Input;
+using System.Windows.Media;
+
+namespace Tango.BrushPicker
+{
+ class SaturationBrightnessSelector : BaseSelector
+ {
+ public Thickness OffsetPadding
+ {
+ get { return (Thickness)GetValue(OffsetPaddingProperty); }
+ set { SetValue(OffsetPaddingProperty, value); }
+ }
+ public static readonly DependencyProperty OffsetPaddingProperty =
+ DependencyProperty.Register("OffsetPadding", typeof(Thickness), typeof(SaturationBrightnessSelector), new UIPropertyMetadata(new Thickness(0.0)));
+
+
+ public double Hue
+ {
+ private get { return (double)GetValue(HueProperty); }
+ set { SetValue(HueProperty, value); }
+ }
+ public static readonly DependencyProperty HueProperty =
+ DependencyProperty.Register("Hue", typeof(double), typeof(SaturationBrightnessSelector), new
+ FrameworkPropertyMetadata(0.0, FrameworkPropertyMetadataOptions.AffectsRender, new PropertyChangedCallback(HueChanged)));
+ public static void HueChanged(object o, DependencyPropertyChangedEventArgs e)
+ {
+ SaturationBrightnessSelector h = (SaturationBrightnessSelector)o;
+ h.SetColor();
+ }
+
+
+ public double SaturationOffset
+ {
+ get { return (double)GetValue(SaturationOffsetProperty); }
+ set { SetValue(SaturationOffsetProperty, value); }
+ }
+ public static readonly DependencyProperty SaturationOffsetProperty =
+ DependencyProperty.Register("SaturationOffset", typeof(double), typeof(SaturationBrightnessSelector), new UIPropertyMetadata(0.0));
+
+
+ public double Saturation
+ {
+ get { return (double)GetValue(SaturationProperty); }
+ set { SetValue(SaturationProperty, value); }
+ }
+ public static readonly DependencyProperty SaturationProperty =
+ DependencyProperty.Register("Saturation", typeof(double), typeof(SaturationBrightnessSelector),
+ new FrameworkPropertyMetadata(0.0, new PropertyChangedCallback(SaturationChanged), new CoerceValueCallback(SaturationCoerce)));
+ public static void SaturationChanged(object o, DependencyPropertyChangedEventArgs e)
+ {
+ SaturationBrightnessSelector h = (SaturationBrightnessSelector)o;
+ h.SetSaturationOffset();
+ }
+ public static object SaturationCoerce(DependencyObject d, object Brightness)
+ {
+ double v = (double)Brightness;
+ if (v < 0) return 0.0;
+ if (v > 1) return 1.0;
+ return v;
+ }
+
+
+ public double BrightnessOffset
+ {
+ get { return (double)GetValue(BrightnessOffsetProperty); }
+ set { SetValue(BrightnessOffsetProperty, value); }
+ }
+ public static readonly DependencyProperty BrightnessOffsetProperty =
+ DependencyProperty.Register("BrightnessOffset", typeof(double), typeof(SaturationBrightnessSelector), new UIPropertyMetadata(0.0));
+
+
+ public double Brightness
+ {
+ get { return (double)GetValue(BrightnessProperty); }
+ set { SetValue(BrightnessProperty, value); }
+ }
+ public static readonly DependencyProperty BrightnessProperty =
+ DependencyProperty.Register("Brightness", typeof(double), typeof(SaturationBrightnessSelector),
+ new FrameworkPropertyMetadata(0.0, new PropertyChangedCallback(BrightnessChanged), new CoerceValueCallback(BrightnessCoerce)));
+ public static void BrightnessChanged(object o, DependencyPropertyChangedEventArgs e)
+ {
+ SaturationBrightnessSelector h = (SaturationBrightnessSelector)o;
+ h.SetBrightnessOffset();
+ }
+ public static object BrightnessCoerce(DependencyObject d, object Brightness)
+ {
+ double v = (double)Brightness;
+ if (v < 0) return 0.0;
+ if (v > 1) return 1.0;
+ return v;
+ }
+
+
+
+ protected override void OnMouseMove(System.Windows.Input.MouseEventArgs e)
+ {
+ if (e.LeftButton == MouseButtonState.Pressed)
+ {
+ Point p = e.GetPosition(this);
+ Saturation = (p.X / (this.ActualWidth - OffsetPadding.Right));
+ Brightness = (((this.ActualHeight - OffsetPadding.Bottom) - p.Y) / (this.ActualHeight - OffsetPadding.Bottom));
+ SetColor();
+ }
+ base.OnMouseMove(e);
+ }
+
+ protected override void OnMouseDown(MouseButtonEventArgs e)
+ {
+ Point p = e.GetPosition(this);
+ Saturation = (p.X / (this.ActualWidth - OffsetPadding.Right));
+ Brightness = (((this.ActualHeight - OffsetPadding.Bottom) - p.Y) / (this.ActualHeight - OffsetPadding.Bottom));
+ SetColor();
+
+ Mouse.Capture(this);
+ base.OnMouseDown(e);
+ }
+
+ protected override void OnMouseUp(MouseButtonEventArgs e)
+ {
+ this.ReleaseMouseCapture();
+ base.OnMouseUp(e);
+ }
+
+ protected override void OnRender(DrawingContext dc)
+ {
+ LinearGradientBrush h = new LinearGradientBrush();
+ h.StartPoint = new Point(0, 0);
+ h.EndPoint = new Point(1, 0);
+ h.GradientStops.Add(new GradientStop(Colors.White, 0.00));
+ h.GradientStops.Add(new GradientStop(ColorHelper.ColorFromHSB(Hue, 1, 1), 1.0));
+ dc.DrawRectangle(h, null, new Rect(0, 0, ActualWidth, ActualHeight));
+
+ LinearGradientBrush v = new LinearGradientBrush();
+ v.StartPoint = new Point(0, 0);
+ v.EndPoint = new Point(0, 1);
+ v.GradientStops.Add(new GradientStop(Color.FromArgb(0xFF, 0, 0, 0), 1.00));
+ v.GradientStops.Add(new GradientStop(Color.FromArgb(0x80, 0, 0, 0), 0.50));
+ v.GradientStops.Add(new GradientStop(Color.FromArgb(0x00, 0, 0, 0), 0.00));
+ dc.DrawRectangle(v, null, new Rect(0, 0, ActualWidth, ActualHeight));
+
+ SetSaturationOffset();
+ SetBrightnessOffset();
+ }
+
+ private void SetSaturationOffset()
+ {
+ SaturationOffset = OffsetPadding.Left + ((ActualWidth - (OffsetPadding.Right + OffsetPadding.Left)) * Saturation);
+ }
+
+ private void SetBrightnessOffset()
+ {
+ BrightnessOffset = OffsetPadding.Top + ((ActualHeight - (OffsetPadding.Bottom + OffsetPadding.Top)) - ((ActualHeight - (OffsetPadding.Bottom + OffsetPadding.Top)) * Brightness));
+ }
+
+ public void SetColor()
+ {
+ Color = ColorHelper.ColorFromHSB(Hue, Saturation, Brightness);
+ //Brush = new SolidColorBrush(Color);
+ }
+ }
+}
diff --git a/Software/Visual_Studio/Tango.BrushPicker/Implementation/SpinEventArgs .cs b/Software/Visual_Studio/Tango.BrushPicker/Implementation/SpinEventArgs .cs
new file mode 100644
index 000000000..88dcc2f5b
--- /dev/null
+++ b/Software/Visual_Studio/Tango.BrushPicker/Implementation/SpinEventArgs .cs
@@ -0,0 +1,37 @@
+/*************************************************************************************
+
+ Extended WPF Toolkit
+
+ Copyright (C) 2007-2013 Xceed Software Inc.
+
+ This program is provided to you under the terms of the Microsoft Public
+ License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
+
+ For more features, controls, and fast professional support,
+ pick up the Plus Edition at http://xceed.com/wpf_toolkit
+
+ Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
+
+ ***********************************************************************************/
+
+using System.Windows;
+
+namespace Tango.BrushPicker
+{
+ class SpinEventArgs : RoutedEventArgs
+ {
+ public SpinDirection Direction
+ {
+ get;
+ private set;
+ }
+
+ public SpinEventArgs(SpinDirection direction)
+ : base()
+ {
+ Direction = direction;
+ }
+ }
+}
+
+
diff --git a/Software/Visual_Studio/Tango.BrushPicker/Implementation/Spinner.cs b/Software/Visual_Studio/Tango.BrushPicker/Implementation/Spinner.cs
new file mode 100644
index 000000000..29a423f44
--- /dev/null
+++ b/Software/Visual_Studio/Tango.BrushPicker/Implementation/Spinner.cs
@@ -0,0 +1,51 @@
+/*************************************************************************************
+
+ Extended WPF Toolkit
+
+ Copyright (C) 2007-2013 Xceed Software Inc.
+
+ This program is provided to you under the terms of the Microsoft Public
+ License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
+
+ For more features, controls, and fast professional support,
+ pick up the Plus Edition at http://xceed.com/wpf_toolkit
+
+ Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
+
+ ***********************************************************************************/
+
+using System;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Markup;
+
+namespace Tango.BrushPicker
+{
+ internal class Spinner : ContentControl
+ {
+ static Spinner()
+ {
+ DefaultStyleKeyProperty.OverrideMetadata(typeof(Spinner), new FrameworkPropertyMetadata(typeof(Spinner)));
+ }
+
+ public static readonly DependencyProperty ValidSpinDirectionProperty = DependencyProperty.Register("ValidSpinDirection", typeof(ValidSpinDirections), typeof(Spinner), new PropertyMetadata(ValidSpinDirections.Increase | ValidSpinDirections.Decrease, OnValidSpinDirectionPropertyChanged));
+ public ValidSpinDirections ValidSpinDirection
+ {
+ get { return (ValidSpinDirections)GetValue(ValidSpinDirectionProperty); }
+ set { SetValue(ValidSpinDirectionProperty, value); }
+ }
+ public static void OnValidSpinDirectionPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ ValidSpinDirections oldvalue = (ValidSpinDirections)e.OldValue;
+ ValidSpinDirections newvalue = (ValidSpinDirections)e.NewValue;
+ }
+
+ public event EventHandler<SpinEventArgs> Spin;
+ protected virtual void OnSpin(SpinEventArgs e)
+ {
+ EventHandler<SpinEventArgs> handler = Spin;
+ if (handler != null)
+ handler(this, e);
+ }
+ }
+}
diff --git a/Software/Visual_Studio/Tango.BrushPicker/Implementation/UpDownBase.cs b/Software/Visual_Studio/Tango.BrushPicker/Implementation/UpDownBase.cs
new file mode 100644
index 000000000..5b6bb3e73
--- /dev/null
+++ b/Software/Visual_Studio/Tango.BrushPicker/Implementation/UpDownBase.cs
@@ -0,0 +1,747 @@
+/*************************************************************************************
+
+ Extended WPF Toolkit
+
+ Copyright (C) 2007-2013 Xceed Software Inc.
+
+ This program is provided to you under the terms of the Microsoft Public
+ License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
+
+ For more features, controls, and fast professional support,
+ pick up the Plus Edition at http://xceed.com/wpf_toolkit
+
+ Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
+
+ ***********************************************************************************/
+
+using System;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Input;
+using System.Globalization;
+using System.Windows.Media;
+
+namespace Tango.BrushPicker
+{
+ [TemplatePart(Name = PART_TextBox, Type = typeof(TextBox))]
+ [TemplatePart(Name = PART_Spinner, Type = typeof(Spinner))]
+ abstract class UpDownBase : Control, IValidateInput
+ {
+ #region Members
+
+ internal const string PART_TextBox = "PART_TextBox";
+ internal const string PART_Spinner = "PART_Spinner";
+ private bool _isSyncingTextAndValueProperties;
+ private bool _isTextChangedFromUI;
+
+ #endregion
+
+
+ #region Properties
+
+ internal Spinner Spinner
+ {
+ get;
+ private set;
+ }
+ internal TextBox TextBox
+ {
+ get;
+ private set;
+ }
+
+ #region CultureInfo
+
+ public static readonly DependencyProperty CultureInfoProperty = DependencyProperty.Register("CultureInfo", typeof(CultureInfo), typeof(UpDownBase), new UIPropertyMetadata(CultureInfo.CurrentCulture, OnCultureInfoChanged));
+ public CultureInfo CultureInfo
+ {
+ get
+ {
+ return (CultureInfo)GetValue(CultureInfoProperty);
+ }
+ set
+ {
+ SetValue(CultureInfoProperty, value);
+ }
+ }
+
+ private static void OnCultureInfoChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
+ {
+ UpDownBase inputBase = o as UpDownBase;
+ if (inputBase != null)
+ inputBase.OnCultureInfoChanged((CultureInfo)e.OldValue, (CultureInfo)e.NewValue);
+ }
+
+ #endregion //CultureInfo
+
+ #region IsReadOnly
+
+ public static readonly DependencyProperty IsReadOnlyProperty = DependencyProperty.Register("IsReadOnly", typeof(bool), typeof(UpDownBase), new UIPropertyMetadata(false, OnReadOnlyChanged));
+ public bool IsReadOnly
+ {
+ get
+ {
+ return (bool)GetValue(IsReadOnlyProperty);
+ }
+ set
+ {
+ SetValue(IsReadOnlyProperty, value);
+ }
+ }
+
+ private static void OnReadOnlyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
+ {
+ UpDownBase inputBase = o as UpDownBase;
+ if (inputBase != null)
+ inputBase.OnReadOnlyChanged((bool)e.OldValue, (bool)e.NewValue);
+ }
+
+ #endregion //IsReadOnly
+
+ #region Text
+
+ public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(UpDownBase), new FrameworkPropertyMetadata(default(String), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnTextChanged, null, false, UpdateSourceTrigger.LostFocus));
+ public string Text
+ {
+ get
+ {
+ return (string)GetValue(TextProperty);
+ }
+ set
+ {
+ SetValue(TextProperty, value);
+ }
+ }
+
+ private static void OnTextChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
+ {
+ UpDownBase inputBase = o as UpDownBase;
+ if (inputBase != null)
+ inputBase.OnTextChanged((string)e.OldValue, (string)e.NewValue);
+ }
+
+ #endregion //Text
+
+ #region FormatString
+
+ public static readonly DependencyProperty FormatStringProperty = DependencyProperty.Register("FormatString", typeof(string), typeof(UpDownBase), new UIPropertyMetadata(String.Empty, OnFormatStringChanged));
+ public string FormatString
+ {
+ get
+ {
+ return (string)GetValue(FormatStringProperty);
+ }
+ set
+ {
+ SetValue(FormatStringProperty, value);
+ }
+ }
+
+ private static void OnFormatStringChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
+ {
+ UpDownBase numericUpDown = o as UpDownBase;
+ if (numericUpDown != null)
+ numericUpDown.OnFormatStringChanged((string)e.OldValue, (string)e.NewValue);
+ }
+
+ protected virtual void OnFormatStringChanged(string oldValue, string newValue)
+ {
+ if (IsInitialized)
+ {
+ this.SyncTextAndValue(false, null);
+ }
+ }
+
+ #endregion //FormatString
+
+ #region Increment
+
+ public static readonly DependencyProperty IncrementProperty = DependencyProperty.Register("Increment", typeof(double?), typeof(UpDownBase), new PropertyMetadata(default(double), OnIncrementChanged, OnCoerceIncrement));
+ public double? Increment
+ {
+ get
+ {
+ return (double?)GetValue(IncrementProperty);
+ }
+ set
+ {
+ SetValue(IncrementProperty, value);
+ }
+ }
+
+ private static void OnIncrementChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
+ {
+ UpDownBase numericUpDown = o as UpDownBase;
+ if (numericUpDown != null)
+ numericUpDown.OnIncrementChanged((double)e.OldValue, (double)e.NewValue);
+ }
+
+ protected virtual void OnIncrementChanged(double oldValue, double newValue)
+ {
+ if (this.IsInitialized)
+ {
+ SetValidSpinDirection();
+ }
+ }
+
+ private static object OnCoerceIncrement(DependencyObject d, object baseValue)
+ {
+ UpDownBase numericUpDown = d as UpDownBase;
+ if (numericUpDown != null)
+ return numericUpDown.OnCoerceIncrement((double)baseValue);
+
+ return baseValue;
+ }
+
+ protected virtual double? OnCoerceIncrement(double? baseValue)
+ {
+ return baseValue;
+ }
+
+ #endregion
+
+ #region Maximum
+
+ public static readonly DependencyProperty MaximumProperty = DependencyProperty.Register("Maximum", typeof(double), typeof(UpDownBase), new UIPropertyMetadata(default(double), OnMaximumChanged, OnCoerceMaximum));
+ public double Maximum
+ {
+ get
+ {
+ return (double)GetValue(MaximumProperty);
+ }
+ set
+ {
+ SetValue(MaximumProperty, value);
+ }
+ }
+
+ private static void OnMaximumChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
+ {
+ UpDownBase numericUpDown = o as UpDownBase;
+ if (numericUpDown != null)
+ numericUpDown.OnMaximumChanged((double)e.OldValue, (double)e.NewValue);
+ }
+
+ protected virtual void OnMaximumChanged(double oldValue, double newValue)
+ {
+ if (this.IsInitialized)
+ {
+ SetValidSpinDirection();
+ }
+ }
+
+ private static object OnCoerceMaximum(DependencyObject d, object baseValue)
+ {
+ UpDownBase numericUpDown = d as UpDownBase;
+ if (numericUpDown != null)
+ return numericUpDown.OnCoerceMaximum((double)baseValue);
+
+ return baseValue;
+ }
+
+ protected virtual double OnCoerceMaximum(double baseValue)
+ {
+ return baseValue;
+ }
+
+ #endregion //Maximum
+
+ #region Minimum
+
+ public static readonly DependencyProperty MinimumProperty = DependencyProperty.Register("Minimum", typeof(double), typeof(UpDownBase), new UIPropertyMetadata(default(double), OnMinimumChanged, OnCoerceMinimum));
+ public double Minimum
+ {
+ get
+ {
+ return (double)GetValue(MinimumProperty);
+ }
+ set
+ {
+ SetValue(MinimumProperty, value);
+ }
+ }
+
+ private static void OnMinimumChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
+ {
+ UpDownBase numericUpDown = o as UpDownBase;
+ if (numericUpDown != null)
+ numericUpDown.OnMinimumChanged((double)e.OldValue, (double)e.NewValue);
+ }
+
+ protected virtual void OnMinimumChanged(double oldValue, double newValue)
+ {
+ if (this.IsInitialized)
+ {
+ SetValidSpinDirection();
+ }
+ }
+
+ private static object OnCoerceMinimum(DependencyObject d, object baseValue)
+ {
+ UpDownBase numericUpDown = d as UpDownBase;
+ if (numericUpDown != null)
+ return numericUpDown.OnCoerceMinimum((double)baseValue);
+
+ return baseValue;
+ }
+
+ protected virtual double? OnCoerceMinimum(double baseValue)
+ {
+ return baseValue;
+ }
+
+ #endregion //Minimum
+
+ #region AllowSpin
+
+ public static readonly DependencyProperty AllowSpinProperty = DependencyProperty.Register("AllowSpin", typeof(bool), typeof(UpDownBase), new UIPropertyMetadata(true));
+ public bool AllowSpin
+ {
+ get
+ {
+ return (bool)GetValue(AllowSpinProperty);
+ }
+ set
+ {
+ SetValue(AllowSpinProperty, value);
+ }
+ }
+
+ #endregion //AllowSpin
+
+ #region DefaultValue
+
+ public static readonly DependencyProperty DefaultValueProperty = DependencyProperty.Register("DefaultValue", typeof(double?), typeof(UpDownBase), new UIPropertyMetadata(default(double), OnDefaultValueChanged));
+ public double? DefaultValue
+ {
+ get
+ {
+ return (double?)GetValue(DefaultValueProperty);
+ }
+ set
+ {
+ SetValue(DefaultValueProperty, value);
+ }
+ }
+
+ private static void OnDefaultValueChanged(DependencyObject source, DependencyPropertyChangedEventArgs args)
+ {
+ ((UpDownBase)source).OnDefaultValueChanged((double)args.OldValue, (double)args.NewValue);
+ }
+
+ private void OnDefaultValueChanged(double oldValue, double newValue)
+ {
+ if (this.IsInitialized && string.IsNullOrEmpty(Text))
+ {
+ this.SyncTextAndValue(true, Text);
+ }
+ }
+
+ #endregion //DefaultValue
+
+ #region AllowInputSpecialValues
+
+ static readonly DependencyProperty AllowInputSpecialValuesProperty =
+ DependencyProperty.Register("AllowInputSpecialValues", typeof(AllowedSpecialValues), typeof(UpDownBase), new UIPropertyMetadata(AllowedSpecialValues.None));
+
+ AllowedSpecialValues AllowInputSpecialValues
+ {
+ get { return (AllowedSpecialValues)GetValue(AllowInputSpecialValuesProperty); }
+ set { SetValue(AllowInputSpecialValuesProperty, value); }
+ }
+
+ #endregion //AllowInputSpecialValues
+
+ #region ParsingNumberStyle
+
+ public static readonly DependencyProperty ParsingNumberStyleProperty =
+ DependencyProperty.Register("ParsingNumberStyle", typeof(NumberStyles), typeof(UpDownBase), new UIPropertyMetadata(NumberStyles.Any));
+
+ public NumberStyles ParsingNumberStyle
+ {
+ get { return (NumberStyles)GetValue(ParsingNumberStyleProperty); }
+ set { SetValue(ParsingNumberStyleProperty, value); }
+ }
+
+ #endregion
+
+ #region Value
+
+ public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(double?), typeof(UpDownBase), new FrameworkPropertyMetadata(default(double), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnValueChanged, OnCoerceValue, false, UpdateSourceTrigger.PropertyChanged));
+ public double? Value
+ {
+ get
+ {
+ return (double?)GetValue(ValueProperty);
+ }
+ set
+ {
+ SetValue(ValueProperty, value);
+ }
+ }
+
+ private static object OnCoerceValue(DependencyObject o, object basevalue)
+ {
+ return ((UpDownBase)o).OnCoerceValue(basevalue);
+ }
+
+ protected virtual object OnCoerceValue(object newValue)
+ {
+ return newValue;
+ }
+
+ private static void OnValueChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
+ {
+ UpDownBase upDownBase = o as UpDownBase;
+ if (upDownBase != null)
+ upDownBase.OnValueChanged((double)e.OldValue, (double)e.NewValue);
+ }
+
+ protected virtual void OnValueChanged(double oldValue, double newValue)
+ {
+ if (this.IsInitialized)
+ {
+ SyncTextAndValue(false, null);
+ }
+
+ SetValidSpinDirection();
+
+ RoutedPropertyChangedEventArgs<object> args = new RoutedPropertyChangedEventArgs<object>(oldValue, newValue);
+ args.RoutedEvent = ValueChangedEvent;
+ RaiseEvent(args);
+ }
+
+ #endregion //Value
+
+ #endregion //Properties
+
+
+ #region Base Class Overrides
+
+ protected override void OnAccessKey(AccessKeyEventArgs e)
+ {
+ if (TextBox != null)
+ TextBox.Focus();
+
+ base.OnAccessKey(e);
+ }
+
+ public override void OnApplyTemplate()
+ {
+ base.OnApplyTemplate();
+
+ TextBox = GetTemplateChild(PART_TextBox) as TextBox;
+ if (TextBox != null)
+ {
+ if (string.IsNullOrEmpty(Text))
+ TextBox.Text = "0.0";
+ else
+ TextBox.Text = Text;
+
+ TextBox.LostFocus += new RoutedEventHandler(TextBox_LostFocus);
+ TextBox.TextChanged += new TextChangedEventHandler(TextBox_TextChanged);
+ }
+
+ if (Spinner != null)
+ Spinner.Spin -= OnSpinnerSpin;
+
+ Spinner = GetTemplateChild(PART_Spinner) as Spinner;
+
+ if (Spinner != null)
+ Spinner.Spin += OnSpinnerSpin;
+
+ SetValidSpinDirection();
+ }
+
+ protected override void OnGotFocus(RoutedEventArgs e)
+ {
+ if (TextBox != null)
+ {
+ TextBox.Focus();
+ }
+ }
+
+ protected override void OnPreviewKeyDown(KeyEventArgs e)
+ {
+ switch (e.Key)
+ {
+ case Key.Up:
+ {
+ if (AllowSpin && !IsReadOnly)
+ DoIncrement();
+ e.Handled = true;
+ break;
+ }
+ case Key.Down:
+ {
+ if (AllowSpin && !IsReadOnly)
+ DoDecrement();
+ e.Handled = true;
+ break;
+ }
+ }
+ }
+
+ protected override void OnKeyDown(KeyEventArgs e)
+ {
+ switch (e.Key)
+ {
+ case Key.Enter:
+ {
+ bool commitSuccess = CommitInput();
+ e.Handled = !commitSuccess;
+ break;
+ }
+ }
+ }
+
+ protected override void OnMouseWheel(MouseWheelEventArgs e)
+ {
+ base.OnMouseWheel(e);
+
+ if (!e.Handled && AllowSpin && !IsReadOnly && (TextBox.IsFocused))
+ {
+ if (e.Delta < 0)
+ {
+ DoDecrement();
+ }
+ else if (0 < e.Delta)
+ {
+ DoIncrement();
+ }
+
+ e.Handled = true;
+ }
+ }
+
+ protected void OnTextChanged(string oldValue, string newValue)
+ {
+ if (this.IsInitialized)
+ {
+ SyncTextAndValue(true, Text);
+ }
+ }
+
+ protected void OnCultureInfoChanged(CultureInfo oldValue, CultureInfo newValue)
+ {
+ if (IsInitialized)
+ {
+ SyncTextAndValue(false, null);
+ }
+ }
+
+ protected void OnReadOnlyChanged(bool oldValue, bool newValue)
+ {
+ SetValidSpinDirection();
+ }
+
+ protected void OnSpin(SpinEventArgs e)
+ {
+ if (e == null)
+ throw new ArgumentNullException("e");
+
+ if (e.Direction == SpinDirection.Increase)
+ DoIncrement();
+ else
+ DoDecrement();
+ }
+
+ #endregion
+
+
+ #region Event Handlers
+
+ private void OnSpinnerSpin(object sender, SpinEventArgs e)
+ {
+ if (AllowSpin && !IsReadOnly)
+ OnSpin(e);
+ }
+
+ #endregion
+
+
+ #region Events
+
+ public event InputValidationErrorEventHandler InputValidationError;
+
+ #region ValueChanged Event
+
+ public static readonly RoutedEvent ValueChangedEvent = EventManager.RegisterRoutedEvent("ValueChanged", RoutingStrategy.Bubble, typeof(RoutedPropertyChangedEventHandler<object>), typeof(UpDownBase));
+ public event RoutedPropertyChangedEventHandler<object> ValueChanged
+ {
+ add
+ {
+ AddHandler(ValueChangedEvent, value);
+ }
+ remove
+ {
+ RemoveHandler(ValueChangedEvent, value);
+ }
+ }
+
+ #endregion
+
+ #endregion //Events
+
+
+ #region Methods
+
+ private void DoDecrement()
+ {
+ if (Spinner == null)
+ {
+ OnDecrement();
+ }
+ }
+
+ private void DoIncrement()
+ {
+ if (Spinner == null)
+ {
+ OnIncrement();
+ }
+ }
+
+ private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
+ {
+ try
+ {
+ _isTextChangedFromUI = true;
+ Text = ((TextBox)sender).Text;
+ }
+ finally
+ {
+ _isTextChangedFromUI = false;
+ }
+ }
+
+ private void TextBox_LostFocus(object sender, RoutedEventArgs e)
+ {
+ CommitInput();
+ }
+
+ private void RaiseInputValidationError(Exception e)
+ {
+ if (InputValidationError != null)
+ {
+ InputValidationErrorEventArgs args = new InputValidationErrorEventArgs(e);
+ InputValidationError(this, args);
+ if (args.ThrowException)
+ {
+ throw args.Exception;
+ }
+ }
+ }
+
+ public bool CommitInput()
+ {
+ return this.SyncTextAndValue(true, Text);
+ }
+
+ protected bool SyncTextAndValue(bool updateValueFromText, string text)
+ {
+ if (_isSyncingTextAndValueProperties)
+ return true;
+
+ _isSyncingTextAndValueProperties = true;
+ bool parsedTextIsValid = true;
+ try
+ {
+ if (updateValueFromText)
+ {
+ if (string.IsNullOrEmpty(text))
+ {
+ // An empty input sets the value to the default value.
+ Value = this.DefaultValue;
+ }
+ else
+ {
+ try
+ {
+ Value = this.ConvertTextToValue(text);
+ }
+ catch (Exception e)
+ {
+ parsedTextIsValid = false;
+
+ // From the UI, just allow any input.
+ if (!_isTextChangedFromUI)
+ {
+ // This call may throw an exception.
+ // See RaiseInputValidationError() implementation.
+ this.RaiseInputValidationError(e);
+ }
+ }
+ }
+ }
+
+ // Do not touch the ongoing text input from user.
+ if (!_isTextChangedFromUI)
+ {
+ // Don't replace the empty Text with the non-empty representation of DefaultValue.
+ bool shouldKeepEmpty = string.IsNullOrEmpty(Text) && object.Equals(Value, DefaultValue);
+ if (!shouldKeepEmpty)
+ {
+ Text = ConvertValueToText();
+ }
+
+ // Sync Text and textBox
+ if (TextBox != null)
+ {
+ if (string.IsNullOrEmpty(Text))
+ TextBox.Text = "0.0";
+ else
+ TextBox.Text = Text;
+ }
+ }
+
+ if (_isTextChangedFromUI && !parsedTextIsValid)
+ {
+ //// Text input was made from the user and the text
+ //// repesents an invalid value. Disable the spinner
+ //// in this case.
+ if (Spinner != null)
+ {
+ Spinner.ValidSpinDirection = ValidSpinDirections.None;
+ }
+ }
+ else
+ {
+ this.SetValidSpinDirection();
+ }
+ }
+ finally
+ {
+ _isSyncingTextAndValueProperties = false;
+ }
+ return parsedTextIsValid;
+ }
+
+ protected static decimal ParsePercent(string text, IFormatProvider cultureInfo)
+ {
+ NumberFormatInfo info = NumberFormatInfo.GetInstance(cultureInfo);
+
+ text = text.Replace(info.PercentSymbol, null);
+
+ decimal result = Decimal.Parse(text, NumberStyles.Any, info);
+ result = result / 100;
+
+ return result;
+ }
+
+ #endregion
+
+
+ #region Abstract
+
+ protected abstract double? ConvertTextToValue(string text);
+ protected abstract string ConvertValueToText();
+ protected abstract void OnIncrement();
+ protected abstract void OnDecrement();
+ protected abstract void SetValidSpinDirection();
+
+ #endregion
+ }
+}
+