From 81a8011338e3ab112397e2327f4a8e734db6198e Mon Sep 17 00:00:00 2001 From: SpoinkyNL Date: Fri, 7 Oct 2016 00:01:31 +0200 Subject: [PATCH] Added ColorBox source Added direction buttons functionality --- Artemis/Artemis.sln | 32 + Artemis/Artemis/Artemis.csproj | 11 +- Artemis/Artemis/Styles/ColorBox.xaml | 8 +- Artemis/ColorBox/AlphaSelector.cs | 134 +++ Artemis/ColorBox/BaseSelector.cs | 39 + Artemis/ColorBox/BrushTypes.cs | 21 + Artemis/ColorBox/ColorBox.cs | 916 ++++++++++++++++++ Artemis/ColorBox/ColorBox.csproj | 93 ++ Artemis/ColorBox/ColorBox.snk | Bin 0 -> 596 bytes Artemis/ColorBox/ColorChangedEventArgs.cs | 27 + Artemis/ColorBox/DoubleUpDown.cs | 201 ++++ Artemis/ColorBox/Enums.cs | 43 + Artemis/ColorBox/GradientStopAdder.cs | 82 ++ Artemis/ColorBox/GradientStopSlider.cs | 74 ++ Artemis/ColorBox/HueSelector.cs | 138 +++ Artemis/ColorBox/Properties/AssemblyInfo.cs | 38 + .../ColorBox/SaturationBrightnessSelector.cs | 189 ++++ Artemis/ColorBox/SpinEventArgs .cs | 30 + Artemis/ColorBox/Spinner.cs | 56 ++ Artemis/ColorBox/Themes/Generic.xaml | 759 +++++++++++++++ Artemis/ColorBox/UpDownBase.cs | 653 +++++++++++++ Artemis/ColorBox/Utils/ColorHelper.cs | 209 ++++ .../Utils/InputValidationErrorEventArgs .cs | 41 + Artemis/ColorBox/Utils/TextBoxBehavior.cs | 61 ++ 24 files changed, 3846 insertions(+), 9 deletions(-) create mode 100644 Artemis/ColorBox/AlphaSelector.cs create mode 100644 Artemis/ColorBox/BaseSelector.cs create mode 100644 Artemis/ColorBox/BrushTypes.cs create mode 100644 Artemis/ColorBox/ColorBox.cs create mode 100644 Artemis/ColorBox/ColorBox.csproj create mode 100644 Artemis/ColorBox/ColorBox.snk create mode 100644 Artemis/ColorBox/ColorChangedEventArgs.cs create mode 100644 Artemis/ColorBox/DoubleUpDown.cs create mode 100644 Artemis/ColorBox/Enums.cs create mode 100644 Artemis/ColorBox/GradientStopAdder.cs create mode 100644 Artemis/ColorBox/GradientStopSlider.cs create mode 100644 Artemis/ColorBox/HueSelector.cs create mode 100644 Artemis/ColorBox/Properties/AssemblyInfo.cs create mode 100644 Artemis/ColorBox/SaturationBrightnessSelector.cs create mode 100644 Artemis/ColorBox/SpinEventArgs .cs create mode 100644 Artemis/ColorBox/Spinner.cs create mode 100644 Artemis/ColorBox/Themes/Generic.xaml create mode 100644 Artemis/ColorBox/UpDownBase.cs create mode 100644 Artemis/ColorBox/Utils/ColorHelper.cs create mode 100644 Artemis/ColorBox/Utils/InputValidationErrorEventArgs .cs create mode 100644 Artemis/ColorBox/Utils/TextBoxBehavior.cs diff --git a/Artemis/Artemis.sln b/Artemis/Artemis.sln index 0e9c57ea1..9e2a09e30 100644 --- a/Artemis/Artemis.sln +++ b/Artemis/Artemis.sln @@ -9,6 +9,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Razer2Artemis", "Razer2Arte EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UnrealTournament2Artemis", "UnrealTournament2Artemis\UnrealTournament2Artemis.vcxproj", "{3541864F-1662-4BD6-8328-2C87AE61D152}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ColorBox", "ColorBox\ColorBox.csproj", "{40085232-ACED-4CBE-945B-90BA8153C151}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution CD_ROM|Any CPU = CD_ROM|Any CPU @@ -114,6 +116,36 @@ Global {3541864F-1662-4BD6-8328-2C87AE61D152}.SingleImage|x64.Build.0 = Release|x64 {3541864F-1662-4BD6-8328-2C87AE61D152}.SingleImage|x86.ActiveCfg = Release|Win32 {3541864F-1662-4BD6-8328-2C87AE61D152}.SingleImage|x86.Build.0 = Release|Win32 + {40085232-ACED-4CBE-945B-90BA8153C151}.CD_ROM|Any CPU.ActiveCfg = Release|Any CPU + {40085232-ACED-4CBE-945B-90BA8153C151}.CD_ROM|Any CPU.Build.0 = Release|Any CPU + {40085232-ACED-4CBE-945B-90BA8153C151}.CD_ROM|x64.ActiveCfg = Release|Any CPU + {40085232-ACED-4CBE-945B-90BA8153C151}.CD_ROM|x64.Build.0 = Release|Any CPU + {40085232-ACED-4CBE-945B-90BA8153C151}.CD_ROM|x86.ActiveCfg = Release|Any CPU + {40085232-ACED-4CBE-945B-90BA8153C151}.CD_ROM|x86.Build.0 = Release|Any CPU + {40085232-ACED-4CBE-945B-90BA8153C151}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {40085232-ACED-4CBE-945B-90BA8153C151}.Debug|Any CPU.Build.0 = Debug|Any CPU + {40085232-ACED-4CBE-945B-90BA8153C151}.Debug|x64.ActiveCfg = Debug|Any CPU + {40085232-ACED-4CBE-945B-90BA8153C151}.Debug|x64.Build.0 = Debug|Any CPU + {40085232-ACED-4CBE-945B-90BA8153C151}.Debug|x86.ActiveCfg = Debug|Any CPU + {40085232-ACED-4CBE-945B-90BA8153C151}.Debug|x86.Build.0 = Debug|Any CPU + {40085232-ACED-4CBE-945B-90BA8153C151}.DVD-5|Any CPU.ActiveCfg = Debug|Any CPU + {40085232-ACED-4CBE-945B-90BA8153C151}.DVD-5|Any CPU.Build.0 = Debug|Any CPU + {40085232-ACED-4CBE-945B-90BA8153C151}.DVD-5|x64.ActiveCfg = Debug|Any CPU + {40085232-ACED-4CBE-945B-90BA8153C151}.DVD-5|x64.Build.0 = Debug|Any CPU + {40085232-ACED-4CBE-945B-90BA8153C151}.DVD-5|x86.ActiveCfg = Debug|Any CPU + {40085232-ACED-4CBE-945B-90BA8153C151}.DVD-5|x86.Build.0 = Debug|Any CPU + {40085232-ACED-4CBE-945B-90BA8153C151}.Release|Any CPU.ActiveCfg = Release|Any CPU + {40085232-ACED-4CBE-945B-90BA8153C151}.Release|Any CPU.Build.0 = Release|Any CPU + {40085232-ACED-4CBE-945B-90BA8153C151}.Release|x64.ActiveCfg = Release|Any CPU + {40085232-ACED-4CBE-945B-90BA8153C151}.Release|x64.Build.0 = Release|Any CPU + {40085232-ACED-4CBE-945B-90BA8153C151}.Release|x86.ActiveCfg = Release|Any CPU + {40085232-ACED-4CBE-945B-90BA8153C151}.Release|x86.Build.0 = Release|Any CPU + {40085232-ACED-4CBE-945B-90BA8153C151}.SingleImage|Any CPU.ActiveCfg = Release|Any CPU + {40085232-ACED-4CBE-945B-90BA8153C151}.SingleImage|Any CPU.Build.0 = Release|Any CPU + {40085232-ACED-4CBE-945B-90BA8153C151}.SingleImage|x64.ActiveCfg = Release|Any CPU + {40085232-ACED-4CBE-945B-90BA8153C151}.SingleImage|x64.Build.0 = Release|Any CPU + {40085232-ACED-4CBE-945B-90BA8153C151}.SingleImage|x86.ActiveCfg = Release|Any CPU + {40085232-ACED-4CBE-945B-90BA8153C151}.SingleImage|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Artemis/Artemis/Artemis.csproj b/Artemis/Artemis/Artemis.csproj index 84f2eed16..cce7cf8c3 100644 --- a/Artemis/Artemis/Artemis.csproj +++ b/Artemis/Artemis/Artemis.csproj @@ -143,10 +143,6 @@ ..\packages\Castle.Core.3.3.3\lib\net45\Castle.Core.dll True - - False - lib\ColorBox.dll - ..\packages\Colore.5.0.0\lib\net35\Corale.Colore.dll True @@ -886,7 +882,12 @@ false - + + + {40085232-aced-4cbe-945b-90ba8153c151} + ColorBox + + diff --git a/Artemis/Artemis/Styles/ColorBox.xaml b/Artemis/Artemis/Styles/ColorBox.xaml index 95467db6b..0331f9aec 100644 --- a/Artemis/Artemis/Styles/ColorBox.xaml +++ b/Artemis/Artemis/Styles/ColorBox.xaml @@ -646,7 +646,7 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Artemis/ColorBox/UpDownBase.cs b/Artemis/ColorBox/UpDownBase.cs new file mode 100644 index 000000000..72228437d --- /dev/null +++ b/Artemis/ColorBox/UpDownBase.cs @@ -0,0 +1,653 @@ +/************************************************************************************* + + 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.Globalization; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Input; + +namespace ColorBox +{ + [TemplatePart(Name = PartTextBox, Type = typeof(TextBox))] + [TemplatePart(Name = PartSpinner, Type = typeof(Spinner))] + public abstract class UpDownBase : Control, IValidateInput + { + #region Event Handlers + + private void OnSpinnerSpin(object sender, SpinEventArgs e) + { + if (AllowSpin && !IsReadOnly) + OnSpin(e); + } + + #endregion + + #region Members + + internal const string PartTextBox = "PART_TextBox"; + internal const string PartSpinner = "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) + { + var 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) + { + var 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) + { + var 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) + { + var 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) + 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) + { + var numericUpDown = o as UpDownBase; + if (numericUpDown != null) + numericUpDown.OnIncrementChanged((double) e.OldValue, (double) e.NewValue); + } + + protected virtual void OnIncrementChanged(double oldValue, double newValue) + { + if (IsInitialized) + SetValidSpinDirection(); + } + + private static object OnCoerceIncrement(DependencyObject d, object baseValue) + { + var 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) + { + var numericUpDown = o as UpDownBase; + if (numericUpDown != null) + numericUpDown.OnMaximumChanged((double) e.OldValue, (double) e.NewValue); + } + + protected virtual void OnMaximumChanged(double oldValue, double newValue) + { + if (IsInitialized) + SetValidSpinDirection(); + } + + private static object OnCoerceMaximum(DependencyObject d, object baseValue) + { + var 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) + { + var numericUpDown = o as UpDownBase; + if (numericUpDown != null) + numericUpDown.OnMinimumChanged((double) e.OldValue, (double) e.NewValue); + } + + protected virtual void OnMinimumChanged(double oldValue, double newValue) + { + if (IsInitialized) + SetValidSpinDirection(); + } + + private static object OnCoerceMinimum(DependencyObject d, object baseValue) + { + var 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 (IsInitialized && string.IsNullOrEmpty(Text)) + SyncTextAndValue(true, Text); + } + + #endregion //DefaultValue + + #region AllowInputSpecialValues + + private static readonly DependencyProperty AllowInputSpecialValuesProperty = + DependencyProperty.Register("AllowInputSpecialValues", typeof(AllowedSpecialValues), typeof(UpDownBase), + new UIPropertyMetadata(AllowedSpecialValues.None)); + + private 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) + { + var upDownBase = o as UpDownBase; + if (upDownBase != null) + upDownBase.OnValueChanged((double) e.OldValue, (double) e.NewValue); + } + + protected virtual void OnValueChanged(double oldValue, double newValue) + { + if (IsInitialized) + SyncTextAndValue(false, null); + + SetValidSpinDirection(); + + var args = new RoutedPropertyChangedEventArgs(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(PartTextBox) as TextBox; + if (TextBox != null) + { + if (string.IsNullOrEmpty(Text)) + TextBox.Text = "0.0"; + else + TextBox.Text = Text; + + TextBox.LostFocus += TextBox_LostFocus; + TextBox.TextChanged += TextBox_TextChanged; + } + + if (Spinner != null) + Spinner.Spin -= OnSpinnerSpin; + + Spinner = GetTemplateChild(PartSpinner) 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: + { + var 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 (IsInitialized) + SyncTextAndValue(true, Text); + } + + protected void OnCultureInfoChanged(CultureInfo oldValue, CultureInfo newValue) + { + if (IsInitialized) + SyncTextAndValue(false, null); + } + + protected void OnReadOnlyChanged(bool oldValue, bool newValue) + { + SetValidSpinDirection(); + } + + public void OnSpin(SpinEventArgs e) + { + if (e == null) + throw new ArgumentNullException("e"); + + if (e.Direction == SpinDirection.Increase) + DoIncrement(); + else + DoDecrement(); + } + + #endregion + + #region Events + + public event InputValidationErrorEventHandler InputValidationError; + + #region ValueChanged Event + + public static readonly RoutedEvent ValueChangedEvent = EventManager.RegisterRoutedEvent("ValueChanged", + RoutingStrategy.Bubble, typeof(RoutedPropertyChangedEventHandler), typeof(UpDownBase)); + + public event RoutedPropertyChangedEventHandler 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) + { + var args = new InputValidationErrorEventArgs(e); + InputValidationError(this, args); + if (args.ThrowException) + throw args.Exception; + } + } + + public bool CommitInput() + { + return SyncTextAndValue(true, Text); + } + + protected bool SyncTextAndValue(bool updateValueFromText, string text) + { + if (_isSyncingTextAndValueProperties) + return true; + + _isSyncingTextAndValueProperties = true; + var parsedTextIsValid = true; + try + { + if (updateValueFromText) + if (string.IsNullOrEmpty(text)) + Value = DefaultValue; + else + try + { + Value = ConvertTextToValue(text); + } + catch (Exception e) + { + parsedTextIsValid = false; + + // From the UI, just allow any input. + if (!_isTextChangedFromUi) + 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. + var shouldKeepEmpty = string.IsNullOrEmpty(Text) && 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 + { + SetValidSpinDirection(); + } + } + finally + { + _isSyncingTextAndValueProperties = false; + } + return parsedTextIsValid; + } + + protected static decimal ParsePercent(string text, IFormatProvider cultureInfo) + { + var info = NumberFormatInfo.GetInstance(cultureInfo); + + text = text.Replace(info.PercentSymbol, null); + + var 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 + } +} \ No newline at end of file diff --git a/Artemis/ColorBox/Utils/ColorHelper.cs b/Artemis/ColorBox/Utils/ColorHelper.cs new file mode 100644 index 000000000..7e6e708a1 --- /dev/null +++ b/Artemis/ColorBox/Utils/ColorHelper.cs @@ -0,0 +1,209 @@ +/***************** 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.Globalization; +using System.Windows.Media; + +namespace ColorBox +{ + internal static class ColorHelper + { + private static readonly char[] HexArray = + { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', + 'E', 'F' + }; + + public static string MakeValidColorString(string S) + { + var s = S; + + for (var i = 0; i < s.Length; i++) + { + var c = s[i]; + + if (!((c >= 'a') && (c <= 'f')) && !((c >= 'A') && (c <= 'F')) && !((c >= '0') && (c <= '9'))) + { + s = s.Remove(i, 1); + i--; + } + } + + if (s.Length > 8) s = s.Substring(0, 8); + + while ((s.Length <= 8) && (s.Length != 3) && (s.Length != 4) && (s.Length != 6) && (s.Length != 8)) + s = s + "0"; + + return s; + } + + public static Color ColorFromString(string S) + { + var s = MakeValidColorString(S); + + byte a = 255; + byte r = 0; + byte g = 0; + byte b = 0; + + if (s.Length == 3) + { + r = byte.Parse(s.Substring(0, 1) + s.Substring(0, 1), NumberStyles.HexNumber); + g = byte.Parse(s.Substring(1, 1) + s.Substring(1, 1), NumberStyles.HexNumber); + b = byte.Parse(s.Substring(2, 1) + s.Substring(2, 1), NumberStyles.HexNumber); + } + + if (s.Length == 4) + { + a = byte.Parse(s.Substring(0, 1) + s.Substring(0, 1), NumberStyles.HexNumber); + r = byte.Parse(s.Substring(1, 1) + s.Substring(1, 1), NumberStyles.HexNumber); + g = byte.Parse(s.Substring(2, 1) + s.Substring(2, 1), NumberStyles.HexNumber); + b = byte.Parse(s.Substring(3, 1) + s.Substring(3, 1), NumberStyles.HexNumber); + } + + if (s.Length == 6) + { + r = byte.Parse(s.Substring(0, 2), NumberStyles.HexNumber); + g = byte.Parse(s.Substring(1, 2), NumberStyles.HexNumber); + b = byte.Parse(s.Substring(2, 2), NumberStyles.HexNumber); + } + + if (s.Length == 8) + { + a = byte.Parse(s.Substring(0, 2), NumberStyles.HexNumber); + r = byte.Parse(s.Substring(1, 2), NumberStyles.HexNumber); + g = byte.Parse(s.Substring(2, 2), NumberStyles.HexNumber); + b = byte.Parse(s.Substring(3, 2), NumberStyles.HexNumber); + } + + return Color.FromArgb(a, r, g, b); + } + + public static string StringFromColor(Color c) + { + var bytes = new byte[4] {c.A, c.R, c.G, c.B}; + + var chars = new char[bytes.Length*2]; + + for (var i = 0; i < bytes.Length; i++) + { + int b = bytes[i]; + chars[i*2] = HexArray[b >> 4]; + chars[i*2 + 1] = HexArray[b & 0xF]; + } + + return new string(chars); + } + + public static Color ColorFromHsb(double H, double S, double b) + { + double red = 0.0, green = 0.0, blue = 0.0; + + if (S == 0.0) + { + red = green = blue = b; + } + else + { + var h = H*360; + while (h >= 360.0) + h -= 360.0; + + h = h/60.0; + var i = (int) h; + + var f = h - i; + var r = b*(1.0 - S); + var s = b*(1.0 - S*f); + var t = b*(1.0 - S*(1.0 - f)); + + switch (i) + { + case 0: + red = b; + green = t; + blue = r; + break; + case 1: + red = s; + green = b; + blue = r; + break; + case 2: + red = r; + green = b; + blue = t; + break; + case 3: + red = r; + green = s; + blue = b; + break; + case 4: + red = t; + green = r; + blue = b; + break; + case 5: + red = b; + green = r; + blue = s; + break; + } + } + + byte iRed = (byte) (red*255.0), iGreen = (byte) (green*255.0), iBlue = (byte) (blue*255.0); + return Color.FromRgb(iRed, iGreen, iBlue); + } + + public static void HsbFromColor(Color c, ref double h, ref double s, ref double b) + { + var red = c.R; + var green = c.G; + var blue = c.B; + + int imax = red, imin = red; + + if (green > imax) imax = green; + else if (green < imin) imin = green; + if (blue > imax) imax = blue; + else if (blue < imin) imin = blue; + double max = imax/255.0, min = imin/255.0; + + var value = max; + var saturation = max > 0 ? (max - min)/max : 0.0; + double hue = 0; + + if (imax > imin) + { + var f = 1.0/((max - min)*255.0); + hue = imax == red + ? 0.0 + f*(green - blue) + : imax == green ? 2.0 + f*(blue - red) : 4.0 + f*(red - green); + hue = hue*60.0; + if (hue < 0.0) + hue += 360.0; + } + + h = hue/360; + s = saturation; + b = value; + } + + public static Color ColorFromAhsb(double a, double h, double s, double b) + { + var r = ColorFromHsb(h, s, b); + r.A = (byte) Math.Round(a*255); + return r; + } + } +} \ No newline at end of file diff --git a/Artemis/ColorBox/Utils/InputValidationErrorEventArgs .cs b/Artemis/ColorBox/Utils/InputValidationErrorEventArgs .cs new file mode 100644 index 000000000..c657d7122 --- /dev/null +++ b/Artemis/ColorBox/Utils/InputValidationErrorEventArgs .cs @@ -0,0 +1,41 @@ +/************************************************************************************* + + 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 ColorBox +{ + public delegate void InputValidationErrorEventHandler(object sender, InputValidationErrorEventArgs e); + + public class InputValidationErrorEventArgs : EventArgs + { + public InputValidationErrorEventArgs(Exception e) + { + Exception = e; + } + + + public Exception Exception { get; private set; } + + public bool ThrowException { get; set; } + } + + internal interface IValidateInput + { + event InputValidationErrorEventHandler InputValidationError; + bool CommitInput(); + } +} \ No newline at end of file diff --git a/Artemis/ColorBox/Utils/TextBoxBehavior.cs b/Artemis/ColorBox/Utils/TextBoxBehavior.cs new file mode 100644 index 000000000..63e58332e --- /dev/null +++ b/Artemis/ColorBox/Utils/TextBoxBehavior.cs @@ -0,0 +1,61 @@ +using System.Windows; +using System.Windows.Controls; +using System.Windows.Input; + +namespace ColorBox +{ + public class TextBoxBehavior + { + public static readonly DependencyProperty SelectAllTextOnFocusProperty = + DependencyProperty.RegisterAttached( + "SelectAllTextOnFocus", + typeof(bool), + typeof(TextBoxBehavior), + new UIPropertyMetadata(false, OnSelectAllTextOnFocusChanged)); + + public static bool GetSelectAllTextOnFocus(TextBox textBox) + { + return (bool) textBox.GetValue(SelectAllTextOnFocusProperty); + } + + public static void SetSelectAllTextOnFocus(TextBox textBox, bool value) + { + textBox.SetValue(SelectAllTextOnFocusProperty, value); + } + + private static void OnSelectAllTextOnFocusChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var textBox = d as TextBox; + if (textBox == null) return; + + if (e.NewValue is bool == false) return; + + if ((bool) e.NewValue) + { + textBox.GotFocus += SelectAll; + textBox.PreviewMouseDown += IgnoreMouseButton; + } + else + { + textBox.GotFocus -= SelectAll; + textBox.PreviewMouseDown -= IgnoreMouseButton; + } + } + + private static void SelectAll(object sender, RoutedEventArgs e) + { + var textBox = e.OriginalSource as TextBox; + if (textBox == null) return; + textBox.SelectAll(); + } + + private static void IgnoreMouseButton(object sender, MouseButtonEventArgs e) + { + var textBox = sender as TextBox; + if ((textBox == null) || textBox.IsKeyboardFocusWithin) return; + + e.Handled = true; + textBox.Focus(); + } + } +} \ No newline at end of file