diff options
| author | Roy <roy.mail.net@gmail.com> | 2018-03-03 23:05:27 +0200 |
|---|---|---|
| committer | Roy <roy.mail.net@gmail.com> | 2018-03-03 23:05:27 +0200 |
| commit | 9dedf143c3ac44ca593e735861f4e1e2e6f947c9 (patch) | |
| tree | 24e74858582300add1f165d4515d9ee8e4a609c5 /Software/Visual_Studio/Tango.BrushPicker/Implementation | |
| parent | 96efb4716d16ab7dab67ead42f27b871b81d4111 (diff) | |
| download | Tango-9dedf143c3ac44ca593e735861f4e1e2e6f947c9.tar.gz Tango-9dedf143c3ac44ca593e735861f4e1e2e6f947c9.zip | |
Implemented Brush Picker.
Diffstat (limited to 'Software/Visual_Studio/Tango.BrushPicker/Implementation')
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 + } +} + |
