7 changed files with 1386 additions and 0 deletions
@ -0,0 +1,389 @@ |
|||
using System; |
|||
using System.Windows; |
|||
using System.Windows.Controls; |
|||
using System.Windows.Input; |
|||
using System.Windows.Media; |
|||
using System.Windows.Controls.Primitives; |
|||
|
|||
namespace Microsoft.Windows.Controls |
|||
{ |
|||
public class ColorPicker : Control |
|||
{ |
|||
#region Private Members
|
|||
|
|||
ToggleButton _colorPickerToggleButton; |
|||
Popup _colorPickerCanvasPopup; |
|||
Button _okButton; |
|||
private TranslateTransform _colorShadeSelectorTransform = new TranslateTransform(); |
|||
private Canvas _colorShadingCanvas; |
|||
private Canvas _colorShadeSelector; |
|||
private ColorSpectrumSlider _spectrumSlider; |
|||
private Point? _currentColorPosition; |
|||
private Color _currentColor = Colors.White; |
|||
|
|||
#endregion //Private Members
|
|||
|
|||
#region Constructors
|
|||
|
|||
static ColorPicker() |
|||
{ |
|||
DefaultStyleKeyProperty.OverrideMetadata(typeof(ColorPicker), new FrameworkPropertyMetadata(typeof(ColorPicker))); |
|||
} |
|||
|
|||
public ColorPicker() |
|||
{ |
|||
|
|||
} |
|||
|
|||
#endregion //Constructors
|
|||
|
|||
#region Properties
|
|||
|
|||
public static readonly DependencyProperty CurrentColorProperty = DependencyProperty.Register("CurrentColor", typeof(Color), typeof(ColorPicker), new PropertyMetadata(Colors.White)); |
|||
public Color CurrentColor |
|||
{ |
|||
get { return (Color)GetValue(CurrentColorProperty); } |
|||
set { SetValue(CurrentColorProperty, value); } |
|||
} |
|||
|
|||
#region SelectedColor
|
|||
|
|||
public static readonly DependencyProperty SelectedColorProperty = DependencyProperty.Register("SelectedColor", typeof(Color), typeof(ColorPicker), new FrameworkPropertyMetadata(Colors.White, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, new PropertyChangedCallback(SelectedColorPropertyChanged))); |
|||
public Color SelectedColor |
|||
{ |
|||
get { return (Color)GetValue(SelectedColorProperty); } |
|||
set { SetValue(SelectedColorProperty, value); } |
|||
} |
|||
|
|||
private static void SelectedColorPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) |
|||
{ |
|||
ColorPicker colorPicker = (ColorPicker)d; |
|||
colorPicker.SetSelectedColor((Color)e.NewValue); |
|||
} |
|||
|
|||
#endregion //SelectedColor
|
|||
|
|||
#region ScRGB
|
|||
|
|||
#region ScA
|
|||
|
|||
public static readonly DependencyProperty ScAProperty = DependencyProperty.Register("ScA", typeof(float), typeof(ColorPicker), new PropertyMetadata((float)1, new PropertyChangedCallback(OnScAPropertyChangedChanged))); |
|||
public double ScA |
|||
{ |
|||
get { return (double)GetValue(ScAProperty); } |
|||
set { SetValue(ScAProperty, value); } |
|||
} |
|||
|
|||
private static void OnScAPropertyChangedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) |
|||
{ |
|||
ColorPicker c = (ColorPicker)d; |
|||
c.SetScA((float)e.NewValue); |
|||
} |
|||
|
|||
protected virtual void SetScA(float newValue) |
|||
{ |
|||
_currentColor.ScA = newValue; |
|||
A = _currentColor.A; |
|||
CurrentColor = _currentColor; |
|||
HexadecimalString = _currentColor.ToString(); |
|||
} |
|||
|
|||
#endregion //ScA
|
|||
|
|||
#region ScR
|
|||
|
|||
public static readonly DependencyProperty ScRProperty = DependencyProperty.Register("ScR", typeof(float), typeof(ColorPicker), new PropertyMetadata((float)1, new PropertyChangedCallback(ScRChanged))); |
|||
public double ScR |
|||
{ |
|||
get { return (double)GetValue(ScRProperty); } |
|||
set { SetValue(RProperty, value); } |
|||
} |
|||
|
|||
private static void ScRChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) |
|||
{ |
|||
|
|||
} |
|||
|
|||
#endregion //ScR
|
|||
|
|||
#region ScG
|
|||
|
|||
public static readonly DependencyProperty ScGProperty = DependencyProperty.Register("ScG", typeof(float), typeof(ColorPicker), new PropertyMetadata((float)1, new PropertyChangedCallback(ScGChanged))); |
|||
public double ScG |
|||
{ |
|||
get { return (double)GetValue(ScGProperty); } |
|||
set { SetValue(GProperty, value); } |
|||
} |
|||
|
|||
private static void ScGChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) |
|||
{ |
|||
|
|||
} |
|||
|
|||
#endregion //ScG
|
|||
|
|||
#region ScB
|
|||
|
|||
public static readonly DependencyProperty ScBProperty = DependencyProperty.Register("ScB", typeof(float), typeof(ColorPicker), new PropertyMetadata((float)1, new PropertyChangedCallback(OnScBPropertyChanged))); |
|||
public double ScB |
|||
{ |
|||
get { return (double)GetValue(BProperty); } |
|||
set { SetValue(BProperty, value); } |
|||
} |
|||
|
|||
private static void OnScBPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) |
|||
{ |
|||
|
|||
} |
|||
|
|||
#endregion //ScB
|
|||
|
|||
#endregion //ScRGB
|
|||
|
|||
#region RGB
|
|||
|
|||
#region A
|
|||
|
|||
public static readonly DependencyProperty AProperty = DependencyProperty.Register("A", typeof(byte), typeof(ColorPicker), new PropertyMetadata((byte)255, new PropertyChangedCallback(OnAPropertyChanged))); |
|||
public byte A |
|||
{ |
|||
get { return (byte)GetValue(AProperty); } |
|||
set { SetValue(AProperty, value); } |
|||
} |
|||
|
|||
private static void OnAPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) |
|||
{ |
|||
ColorPicker c = (ColorPicker)d; |
|||
c.SetA((byte)e.NewValue); |
|||
} |
|||
|
|||
protected virtual void SetA(byte newValue) |
|||
{ |
|||
_currentColor.A = newValue; |
|||
SetValue(CurrentColorProperty, _currentColor); |
|||
} |
|||
|
|||
#endregion //A
|
|||
|
|||
#region R
|
|||
|
|||
public static readonly DependencyProperty RProperty = DependencyProperty.Register("R", typeof(byte), typeof(ColorPicker), new PropertyMetadata((byte)255, new PropertyChangedCallback(OnRPropertyChanged))); |
|||
public byte R |
|||
{ |
|||
get { return (byte)GetValue(RProperty); } |
|||
set { SetValue(RProperty, value); } |
|||
} |
|||
|
|||
private static void OnRPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) |
|||
{ |
|||
|
|||
} |
|||
|
|||
#endregion //R
|
|||
|
|||
#region G
|
|||
|
|||
public static readonly DependencyProperty GProperty = DependencyProperty.Register("G", typeof(byte), typeof(ColorPicker), new PropertyMetadata((byte)255, new PropertyChangedCallback(OnGPropertyChanged))); |
|||
public byte G |
|||
{ |
|||
get { return (byte)GetValue(GProperty); } |
|||
set { SetValue(GProperty, value); } |
|||
} |
|||
|
|||
private static void OnGPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) |
|||
{ |
|||
|
|||
} |
|||
|
|||
#endregion //G
|
|||
|
|||
#region B
|
|||
|
|||
public static readonly DependencyProperty BProperty = DependencyProperty.Register("B", typeof(byte), typeof(ColorPicker), new PropertyMetadata((byte)255, new PropertyChangedCallback(OnBPropertyChanged))); |
|||
public byte B |
|||
{ |
|||
get { return (byte)GetValue(BProperty); } |
|||
set { SetValue(BProperty, value); } |
|||
} |
|||
|
|||
private static void OnBPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) |
|||
{ |
|||
|
|||
} |
|||
|
|||
#endregion //B
|
|||
|
|||
#endregion //RGB
|
|||
|
|||
#region HexadecimalString
|
|||
|
|||
public static readonly DependencyProperty HexadecimalStringProperty = DependencyProperty.Register("HexadecimalString", typeof(string), typeof(ColorPicker), new PropertyMetadata("#FFFFFFFF", new PropertyChangedCallback(OnHexadecimalStringPropertyChanged))); |
|||
public string HexadecimalString |
|||
{ |
|||
get { return (string)GetValue(HexadecimalStringProperty); } |
|||
set { SetValue(HexadecimalStringProperty, value); } |
|||
} |
|||
|
|||
private static void OnHexadecimalStringPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) |
|||
{ |
|||
|
|||
} |
|||
|
|||
#endregion //HexadecimalString
|
|||
|
|||
#endregion //Properties
|
|||
|
|||
#region Base Class Overrides
|
|||
|
|||
public override void OnApplyTemplate() |
|||
{ |
|||
base.OnApplyTemplate(); |
|||
|
|||
_colorPickerToggleButton = (ToggleButton)GetTemplateChild("PART_ColorPickerToggleButton"); |
|||
_colorPickerToggleButton.Click += ColorPickerToggleButton_Clicked; |
|||
|
|||
_colorPickerCanvasPopup = (Popup)GetTemplateChild("PART_ColorPickerCanvasPopup"); |
|||
|
|||
_colorShadingCanvas = (Canvas)GetTemplateChild("PART_ColorShadingCanvas"); |
|||
_colorShadingCanvas.MouseLeftButtonDown += ColorShadingCanvas_MouseLeftButtonDown; |
|||
_colorShadingCanvas.MouseMove += ColorShadingCanvas_MouseMove; |
|||
_colorShadingCanvas.SizeChanged += ColorShadingCanvas_SizeChanged; |
|||
|
|||
_colorShadeSelector = (Canvas)GetTemplateChild("PART_ColorShadeSelector"); |
|||
_colorShadeSelector.RenderTransform = _colorShadeSelectorTransform; |
|||
|
|||
_spectrumSlider = (ColorSpectrumSlider)GetTemplateChild("PART_SpectrumSlider"); |
|||
_spectrumSlider.ValueChanged += SpectrumSlider_ValueChanged; |
|||
|
|||
_okButton = (Button)GetTemplateChild("PART_OkButton"); |
|||
_okButton.Click += OkButton_Click; |
|||
} |
|||
|
|||
#endregion //Base Class Overrides
|
|||
|
|||
#region Event Handlers
|
|||
|
|||
void ColorShadingCanvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) |
|||
{ |
|||
Point p = e.GetPosition(_colorShadingCanvas); |
|||
UpdateColorShadeSelectorPositionAndCalculateColor(p); |
|||
} |
|||
|
|||
void ColorShadingCanvas_MouseMove(object sender, MouseEventArgs e) |
|||
{ |
|||
if (e.LeftButton == MouseButtonState.Pressed) |
|||
{ |
|||
Point p = e.GetPosition(_colorShadingCanvas); |
|||
UpdateColorShadeSelectorPositionAndCalculateColor(p); |
|||
Mouse.Synchronize(); |
|||
} |
|||
} |
|||
|
|||
void ColorShadingCanvas_SizeChanged(object sender, SizeChangedEventArgs e) |
|||
{ |
|||
if (_currentColorPosition != null) |
|||
{ |
|||
Point _newPoint = new Point |
|||
{ |
|||
X = ((Point)_currentColorPosition).X * e.NewSize.Width, |
|||
Y = ((Point)_currentColorPosition).Y * e.NewSize.Height |
|||
}; |
|||
|
|||
UpdateColorShadeSelectorPositionAndCalculateColor(_newPoint, false); |
|||
} |
|||
} |
|||
|
|||
void SpectrumSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e) |
|||
{ |
|||
if (_currentColorPosition != null) |
|||
{ |
|||
CalculateColor((Point)_currentColorPosition); |
|||
} |
|||
} |
|||
|
|||
void OkButton_Click(object sender, RoutedEventArgs e) |
|||
{ |
|||
if (_colorPickerCanvasPopup.IsOpen || _colorPickerToggleButton.IsChecked == true) |
|||
{ |
|||
CloseColorPicker(); |
|||
SelectedColor = CurrentColor; |
|||
} |
|||
} |
|||
|
|||
void ColorPickerToggleButton_Clicked(object sender, RoutedEventArgs e) |
|||
{ |
|||
_colorPickerCanvasPopup.IsOpen = _colorPickerToggleButton.IsChecked ?? false; |
|||
} |
|||
|
|||
#endregion //Event Handlers
|
|||
|
|||
#region Methods
|
|||
|
|||
private void CloseColorPicker() |
|||
{ |
|||
_colorPickerToggleButton.IsChecked = false; |
|||
_colorPickerCanvasPopup.IsOpen = false; |
|||
} |
|||
|
|||
private void SetSelectedColor(Color theColor) |
|||
{ |
|||
_currentColor = theColor; |
|||
SetValue(AProperty, _currentColor.A); |
|||
SetValue(RProperty, _currentColor.R); |
|||
SetValue(GProperty, _currentColor.G); |
|||
SetValue(BProperty, _currentColor.B); |
|||
UpdateColorShadeSelectorPosition(theColor); |
|||
} |
|||
|
|||
private void UpdateColorShadeSelectorPositionAndCalculateColor(Point p, bool calculateColor = true) |
|||
{ |
|||
if (p.Y < 0) |
|||
p.Y = 0; |
|||
|
|||
if (p.X < 0) |
|||
p.X = 0; |
|||
|
|||
if (p.X > _colorShadingCanvas.ActualWidth) |
|||
p.X = _colorShadingCanvas.ActualWidth; |
|||
|
|||
if (p.Y > _colorShadingCanvas.ActualHeight) |
|||
p.Y = _colorShadingCanvas.ActualHeight; |
|||
|
|||
_colorShadeSelectorTransform.X = p.X - (_colorShadeSelector.Width / 2); |
|||
_colorShadeSelectorTransform.Y = p.Y - (_colorShadeSelector.Height / 2); |
|||
|
|||
p.X = p.X / _colorShadingCanvas.ActualWidth; |
|||
p.Y = p.Y / _colorShadingCanvas.ActualHeight; |
|||
|
|||
_currentColorPosition = p; |
|||
|
|||
CalculateColor(p); |
|||
} |
|||
|
|||
private void UpdateColorShadeSelectorPosition(Color color) |
|||
{ |
|||
_currentColorPosition = null; |
|||
|
|||
HsvColor hsv = ColorUtilities.ConvertRgbToHsv(color.R, color.G, color.B); |
|||
_spectrumSlider.Value = hsv.H; |
|||
|
|||
Point p = new Point(hsv.S, 1 - hsv.V); |
|||
|
|||
_currentColorPosition = p; |
|||
|
|||
_colorShadeSelectorTransform.X = p.X * _colorShadingCanvas.Width; |
|||
_colorShadeSelectorTransform.Y = p.Y * _colorShadingCanvas.Height; |
|||
} |
|||
|
|||
private void CalculateColor(Point p) |
|||
{ |
|||
HsvColor hsv = new HsvColor(360 - _spectrumSlider.Value, 1, 1) { S = p.X, V = 1 - p.Y }; |
|||
_currentColor = ColorUtilities.ConvertHsvToRgb(hsv.H, hsv.S, hsv.V); ; |
|||
_currentColor.ScA = (float)GetValue(ScAProperty); |
|||
CurrentColor = _currentColor; |
|||
SetValue(HexadecimalStringProperty, _currentColor.ToString()); |
|||
} |
|||
|
|||
#endregion //Methods
|
|||
} |
|||
} |
|||
@ -0,0 +1,367 @@ |
|||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
|||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
|||
xmlns:local="clr-namespace:Microsoft.Windows.Controls"> |
|||
|
|||
<!-- =============================================================================== --> |
|||
<!-- ColorPicker --> |
|||
<!-- =============================================================================== --> |
|||
|
|||
<LinearGradientBrush x:Key="ColorPickerDarkBorderBrush" EndPoint="0.5,1" StartPoint="0.5,0"> |
|||
<GradientStop Color="#FFA3AEB9" Offset="0"/> |
|||
<GradientStop Color="#FF8399A9" Offset="0.375"/> |
|||
<GradientStop Color="#FF718597" Offset="0.375"/> |
|||
<GradientStop Color="#FF617584" Offset="1"/> |
|||
</LinearGradientBrush> |
|||
|
|||
<DrawingBrush x:Key="CheckerBrush" Viewport="0,0,10,10" ViewportUnits="Absolute" TileMode="Tile"> |
|||
<DrawingBrush.Drawing> |
|||
<DrawingGroup> |
|||
<GeometryDrawing Brush="White"> |
|||
<GeometryDrawing.Geometry> |
|||
<RectangleGeometry Rect="0,0 100,100" /> |
|||
</GeometryDrawing.Geometry> |
|||
</GeometryDrawing> |
|||
<GeometryDrawing Brush="LightGray"> |
|||
<GeometryDrawing.Geometry> |
|||
<GeometryGroup> |
|||
<RectangleGeometry Rect="0,0 50,50" /> |
|||
<RectangleGeometry Rect="50,50 50,50" /> |
|||
</GeometryGroup> |
|||
</GeometryDrawing.Geometry> |
|||
</GeometryDrawing> |
|||
</DrawingGroup> |
|||
</DrawingBrush.Drawing> |
|||
</DrawingBrush> |
|||
|
|||
<Style x:Key="SliderRepeatButtonStyle" |
|||
TargetType="{x:Type RepeatButton}"> |
|||
<Setter Property="OverridesDefaultStyle" Value="true"/> |
|||
<Setter Property="IsTabStop" Value="false"/> |
|||
<Setter Property="Focusable" Value="false"/> |
|||
<Setter Property="Background" Value="Transparent"/> |
|||
<Setter Property="Template"> |
|||
<Setter.Value> |
|||
<ControlTemplate TargetType="{x:Type RepeatButton}"> |
|||
<Border Background="{TemplateBinding Background}"/> |
|||
</ControlTemplate> |
|||
</Setter.Value> |
|||
</Setter> |
|||
</Style> |
|||
|
|||
<Style x:Key="VerticalSlideThumbStyle" TargetType="{x:Type Thumb}"> |
|||
<Setter Property="Template"> |
|||
<Setter.Value> |
|||
<ControlTemplate TargetType="{x:Type Thumb}"> |
|||
<Canvas x:Name="selector" Height="8" Background="Transparent" IsHitTestVisible="True" > |
|||
<Path Width="5" Height="8" Stretch="Fill" StrokeLineJoin="Round" Stroke="#FF000000" Fill="#FF000000" Data="F1 M 276.761,316L 262.619,307.835L 262.619,324.165L 276.761,316 Z " /> |
|||
<Path Width="5" Height="8" Canvas.Top="8" Canvas.Left="20" Stretch="Fill" StrokeLineJoin="Round" Stroke="#FF000000" Fill="#FF000000" Data="F1 M 276.761,316L 262.619,307.835L 262.619,324.165L 276.761,316 Z "> |
|||
<Path.RenderTransform> |
|||
<RotateTransform Angle="180"/> |
|||
</Path.RenderTransform> |
|||
</Path> |
|||
</Canvas> |
|||
<ControlTemplate.Triggers> |
|||
<Trigger Property="IsDragging" Value="True"> |
|||
<Setter Property="Foreground" |
|||
Value="{DynamicResource {x:Static SystemColors.ControlLightLightBrushKey}}"/> |
|||
</Trigger> |
|||
<Trigger Property="IsEnabled" Value="False"> |
|||
<Setter Property="Foreground" |
|||
Value="{DynamicResource {x:Static SystemColors.ControlLightLightBrushKey}}"/> |
|||
</Trigger> |
|||
</ControlTemplate.Triggers> |
|||
</ControlTemplate> |
|||
</Setter.Value> |
|||
</Setter> |
|||
</Style> |
|||
|
|||
<Style x:Key="OpacitySliderStyle" TargetType="{x:Type Slider}"> |
|||
<Setter Property="Orientation" Value="Vertical"/> |
|||
<Setter Property="Minimum" Value="0" /> |
|||
<Setter Property="Maximum" Value="1" /> |
|||
<Setter Property="TickFrequency" Value="0.01" /> |
|||
<Setter Property="SmallChange" Value="0.01" /> |
|||
<Setter Property="LargeChange" Value="0.02" /> |
|||
<Setter Property="IsDirectionReversed" Value="False" /> |
|||
<Setter Property="IsMoveToPointEnabled" Value="True" /> |
|||
<Setter Property="Background"> |
|||
<Setter.Value> |
|||
<LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5"> |
|||
<LinearGradientBrush.RelativeTransform> |
|||
<TransformGroup> |
|||
<ScaleTransform CenterY="0.5" CenterX="0.5"/> |
|||
<SkewTransform CenterY="0.5" CenterX="0.5"/> |
|||
<RotateTransform Angle="90" CenterY="0.5" CenterX="0.5"/> |
|||
<TranslateTransform/> |
|||
</TransformGroup> |
|||
</LinearGradientBrush.RelativeTransform> |
|||
<GradientStop Color="White" /> |
|||
<GradientStop Color="Transparent" Offset="1" /> |
|||
</LinearGradientBrush> |
|||
</Setter.Value> |
|||
</Setter> |
|||
<Setter Property="Template"> |
|||
<Setter.Value> |
|||
<ControlTemplate TargetType="{x:Type Slider}"> |
|||
<Grid> |
|||
<Grid.ColumnDefinitions> |
|||
<ColumnDefinition Width="Auto"/> |
|||
<ColumnDefinition Width="Auto" /> |
|||
<ColumnDefinition Width="Auto"/> |
|||
</Grid.ColumnDefinitions> |
|||
<Grid.RowDefinitions> |
|||
<RowDefinition Height="*"/> |
|||
</Grid.RowDefinitions> |
|||
|
|||
<Border x:Name="PART_TrackBackground" Background="{TemplateBinding Background}" Grid.Column="1" Width="20" /> |
|||
|
|||
<Track Grid.Column="1" Name="PART_Track"> |
|||
<Track.DecreaseRepeatButton> |
|||
<RepeatButton Style="{StaticResource SliderRepeatButtonStyle}" Command="Slider.DecreaseLarge"/> |
|||
</Track.DecreaseRepeatButton> |
|||
<Track.IncreaseRepeatButton> |
|||
<RepeatButton Style="{StaticResource SliderRepeatButtonStyle}" Command="Slider.IncreaseLarge"/> |
|||
</Track.IncreaseRepeatButton> |
|||
|
|||
<Track.Thumb> |
|||
<Thumb Style="{StaticResource VerticalSlideThumbStyle}" /> |
|||
</Track.Thumb> |
|||
</Track> |
|||
|
|||
</Grid> |
|||
</ControlTemplate> |
|||
</Setter.Value> |
|||
</Setter> |
|||
</Style> |
|||
|
|||
<Style x:Key="ColorPickerToggleButton" TargetType="ToggleButton"> |
|||
<Setter Property="Foreground" Value="#FF000000"/> |
|||
<Setter Property="Padding" Value="5"/> |
|||
<Setter Property="BorderThickness" Value="1,0,0,0"/> |
|||
<Setter Property="Template"> |
|||
<Setter.Value> |
|||
<ControlTemplate TargetType="ToggleButton"> |
|||
<Grid> |
|||
<VisualStateManager.VisualStateGroups> |
|||
<VisualStateGroup x:Name="CommonStates"> |
|||
<VisualState x:Name="Normal"/> |
|||
<VisualState x:Name="MouseOver"> |
|||
<Storyboard> |
|||
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="_backgroundHighlight" Storyboard.TargetProperty="Opacity"> |
|||
<SplineDoubleKeyFrame KeyTime="0" Value="1"/> |
|||
</DoubleAnimationUsingKeyFrames> |
|||
<ColorAnimationUsingKeyFrames Storyboard.TargetName="_backgroundGradient" Storyboard.TargetProperty="(Rectangle.Fill).(GradientBrush.GradientStops)[1].(GradientStop.Color)"> |
|||
<SplineColorKeyFrame KeyTime="0" Value="#F2FFFFFF"/> |
|||
</ColorAnimationUsingKeyFrames> |
|||
<ColorAnimationUsingKeyFrames Storyboard.TargetName="_backgroundGradient" Storyboard.TargetProperty="(Rectangle.Fill).(GradientBrush.GradientStops)[2].(GradientStop.Color)"> |
|||
<SplineColorKeyFrame KeyTime="0" Value="#CCFFFFFF"/> |
|||
</ColorAnimationUsingKeyFrames> |
|||
<ColorAnimationUsingKeyFrames Storyboard.TargetName="_backgroundGradient" Storyboard.TargetProperty="(Rectangle.Fill).(GradientBrush.GradientStops)[3].(GradientStop.Color)"> |
|||
<SplineColorKeyFrame KeyTime="0" Value="#7FFFFFFF"/> |
|||
</ColorAnimationUsingKeyFrames> |
|||
</Storyboard> |
|||
</VisualState> |
|||
</VisualStateGroup> |
|||
</VisualStateManager.VisualStateGroups> |
|||
|
|||
<Grid.ColumnDefinitions> |
|||
<ColumnDefinition Width="*"/> |
|||
<ColumnDefinition Width="1"/> |
|||
<ColumnDefinition Width="Auto"/> |
|||
</Grid.ColumnDefinitions> |
|||
|
|||
<Border x:Name="Background" Background="White" BorderThickness="0" Grid.ColumnSpan="3" Cursor="Hand"> |
|||
<Grid Margin="1" Background="#FF1F3B53"> |
|||
<Border x:Name="_backgroundHighlight" Opacity="0" Background="#FF448DCA"/> |
|||
<Rectangle x:Name="_backgroundGradient"> |
|||
<Rectangle.Fill> |
|||
<LinearGradientBrush EndPoint="0,1" StartPoint="0,0"> |
|||
<GradientStop Color="#F3F3F3" Offset="0"/> |
|||
<GradientStop Color="#EBEBEB" Offset="0.5"/> |
|||
<GradientStop Color="#DDDDDD" Offset="0.5"/> |
|||
<GradientStop Color="#CDCDCD" Offset="1"/> |
|||
</LinearGradientBrush> |
|||
</Rectangle.Fill> |
|||
</Rectangle> |
|||
</Grid> |
|||
</Border> |
|||
|
|||
<Border Margin="5" BorderBrush="{StaticResource ColorPickerDarkBorderBrush}" BorderThickness="1" CornerRadius="3"> |
|||
<Rectangle Fill="{TemplateBinding Background}" /> |
|||
</Border> |
|||
|
|||
<Border Grid.Column="1" Background="#FFC9CACA" BorderBrush="White" BorderThickness="1,0,0,0" Margin="0,2"/> |
|||
|
|||
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}" Grid.Column="2"/> |
|||
</Grid> |
|||
</ControlTemplate> |
|||
</Setter.Value> |
|||
</Setter> |
|||
</Style> |
|||
|
|||
<Style TargetType="{x:Type local:ColorPicker}"> |
|||
<Setter Property="Template"> |
|||
<Setter.Value> |
|||
<ControlTemplate TargetType="{x:Type local:ColorPicker}"> |
|||
<Grid> |
|||
<Border BorderBrush="{StaticResource ColorPickerDarkBorderBrush}" BorderThickness="1" CornerRadius="1"> |
|||
<Grid> |
|||
<ToggleButton x:Name="PART_ColorPickerToggleButton" Style="{StaticResource ColorPickerToggleButton}" Height="25"> |
|||
<ToggleButton.Background> |
|||
<SolidColorBrush Color="{Binding SelectedColor, RelativeSource={RelativeSource TemplatedParent}}"/> |
|||
</ToggleButton.Background> |
|||
<ToggleButton.Content> |
|||
<Grid x:Name="arrowGlyph" IsHitTestVisible="False"> |
|||
<Path Height="3" Width="5" Stretch="Fill" Fill="#FFFFFFFF" Margin="0,1,0,0" |
|||
Data="M 0,0 C0,0 0,1 0,1 0,1 1,1 1,1 1,1 1,2 1,2 1,2 2,2 2,2 2,2 2,3 2,3 2,3 3,3 3,3 3,3 3,2 3,2 3,2 4,2 4,2 4,2 4,1 4,1 4,1 5,1 5,1 5,1 5,0 5,0 5,0 0,0 0,0 z" /> |
|||
<Path Height="3" Width="5" Stretch="Fill" Fill="{StaticResource ColorPickerDarkBorderBrush}" |
|||
Data="M 0,0 C0,0 0,1 0,1 0,1 1,1 1,1 1,1 1,2 1,2 1,2 2,2 2,2 2,2 2,3 2,3 2,3 3,3 3,3 3,3 3,2 3,2 3,2 4,2 4,2 4,2 4,1 4,1 4,1 5,1 5,1 5,1 5,0 5,0 5,0 0,0 0,0 z" /> |
|||
</Grid> |
|||
</ToggleButton.Content> |
|||
</ToggleButton> |
|||
</Grid> |
|||
</Border> |
|||
|
|||
<Popup x:Name="PART_ColorPickerCanvasPopup" VerticalAlignment="Bottom" IsOpen="False" > |
|||
<Border BorderThickness="1" Background="White" BorderBrush="{StaticResource ColorPickerDarkBorderBrush}" Padding="3"> |
|||
<Grid> |
|||
<Grid.RowDefinitions> |
|||
<RowDefinition /> |
|||
<RowDefinition Height="Auto" /> |
|||
</Grid.RowDefinitions> |
|||
<Grid Margin="2"> |
|||
<Grid> |
|||
<Grid.ColumnDefinitions > |
|||
<ColumnDefinition Width="200"></ColumnDefinition> |
|||
<ColumnDefinition Width="5"></ColumnDefinition> |
|||
<ColumnDefinition Width="22"></ColumnDefinition> |
|||
<ColumnDefinition Width="5"></ColumnDefinition> |
|||
<ColumnDefinition Width="22"></ColumnDefinition> |
|||
</Grid.ColumnDefinitions> |
|||
<Grid.RowDefinitions> |
|||
<RowDefinition Height="Auto" /> |
|||
<RowDefinition Height="20"/> |
|||
</Grid.RowDefinitions> |
|||
|
|||
<Border BorderThickness="1" BorderBrush="DarkGray" ClipToBounds="True" Background="{StaticResource CheckerBrush}"> |
|||
<Canvas x:Name="PART_ColorShadingCanvas" Width="200" Height="100" HorizontalAlignment="Left" VerticalAlignment="Top"> |
|||
<Rectangle x:Name="ColorShadingRectangle" Height="{Binding ElementName=PART_ColorShadingCanvas,Path=Height}" Width="{Binding ElementName=PART_ColorShadingCanvas,Path=Width}" > |
|||
<Rectangle.Fill> |
|||
<SolidColorBrush Color="{Binding ElementName=PART_SpectrumSlider, Path=SelectedColor}" /> |
|||
</Rectangle.Fill> |
|||
</Rectangle> |
|||
<Rectangle x:Name="WhiteGradient" Width="{Binding ElementName=PART_ColorShadingCanvas,Path=Width}" Height="{Binding ElementName=PART_ColorShadingCanvas,Path=Height}" > |
|||
<Rectangle.Fill> |
|||
<LinearGradientBrush StartPoint="0,0" EndPoint="1,0"> |
|||
<GradientStop Offset="0" Color="#ffffffff"/> |
|||
<GradientStop Offset="1" Color="Transparent"/> |
|||
</LinearGradientBrush> |
|||
</Rectangle.Fill> |
|||
</Rectangle> |
|||
<Rectangle x:Name="BlackGradient" Width="{Binding ElementName=PART_ColorShadingCanvas,Path=Width}" Height="{Binding ElementName=PART_ColorShadingCanvas,Path=Height}" > |
|||
<Rectangle.Fill> |
|||
<LinearGradientBrush StartPoint="0,1" EndPoint="0, 0"> |
|||
<GradientStop Offset="0" Color="#ff000000"/> |
|||
<GradientStop Offset="1" Color="#00000000"/> |
|||
</LinearGradientBrush> |
|||
</Rectangle.Fill> |
|||
</Rectangle> |
|||
<Canvas x:Name="PART_ColorShadeSelector" Width="10" Height="10" IsHitTestVisible="False"> |
|||
<Ellipse Width="10" Height="10" StrokeThickness="3" Stroke="#FFFFFFFF" IsHitTestVisible="False" /> |
|||
<Ellipse Width="10" Height="10" StrokeThickness="1" Stroke="#FF000000" IsHitTestVisible="False" /> |
|||
</Canvas> |
|||
</Canvas> |
|||
</Border> |
|||
|
|||
<Border BorderThickness="0,1,0,0" Grid.Row="1"> |
|||
<Grid> |
|||
<Grid.ColumnDefinitions> |
|||
<ColumnDefinition Width="*"/> |
|||
<ColumnDefinition Width="*"/> |
|||
</Grid.ColumnDefinitions> |
|||
<Grid Background="{StaticResource CheckerBrush}"> |
|||
<Rectangle x:Name="SelectedColor"> |
|||
<Rectangle.Fill> |
|||
<SolidColorBrush Color="{Binding SelectedColor, RelativeSource={RelativeSource TemplatedParent}}"/> |
|||
</Rectangle.Fill> |
|||
</Rectangle> |
|||
</Grid> |
|||
<Grid Grid.Column="1" Background="{StaticResource CheckerBrush}"> |
|||
<Rectangle x:Name="CurrentColor"> |
|||
<Rectangle.Fill> |
|||
<SolidColorBrush Color="{Binding CurrentColor, RelativeSource={RelativeSource TemplatedParent}}"/> |
|||
</Rectangle.Fill> |
|||
</Rectangle> |
|||
</Grid> |
|||
</Grid> |
|||
</Border> |
|||
|
|||
<Border BorderThickness="1" BorderBrush="DarkGray" Grid.Column="2" Grid.RowSpan="2" ClipToBounds="True"> |
|||
<local:ColorSpectrumSlider x:Name="PART_SpectrumSlider" Width="20" /> |
|||
</Border> |
|||
|
|||
|
|||
<Border Grid.Column="4" Grid.RowSpan="2" BorderThickness="1" BorderBrush="DarkGray" Background="{StaticResource CheckerBrush}" ClipToBounds="True"> |
|||
<Slider x:Name="PART_OpacitySlider" |
|||
Style="{StaticResource OpacitySliderStyle}" |
|||
Value="{Binding Path=ScA, RelativeSource={RelativeSource TemplatedParent}}"/> |
|||
</Border> |
|||
</Grid> |
|||
</Grid> |
|||
<Button x:Name="PART_OkButton" Grid.Row="1" HorizontalAlignment="Right" MinWidth="50" Cursor="Hand" Content="OK" /> |
|||
</Grid> |
|||
</Border> |
|||
</Popup> |
|||
</Grid> |
|||
</ControlTemplate> |
|||
</Setter.Value> |
|||
</Setter> |
|||
</Style> |
|||
|
|||
<Style TargetType="{x:Type local:ColorSpectrumSlider}"> |
|||
<Setter Property="Orientation" Value="Vertical"/> |
|||
<Setter Property="Background" Value="Transparent"/> |
|||
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/> |
|||
<Setter Property="Minimum" Value="1"/> |
|||
<Setter Property="Maximum" Value="360"/> |
|||
<Setter Property="TickFrequency" Value="0.001" /> |
|||
<Setter Property="IsSnapToTickEnabled" Value="True" /> |
|||
<Setter Property="IsDirectionReversed" Value="False" /> |
|||
<Setter Property="IsMoveToPointEnabled" Value="True" /> |
|||
<Setter Property="Value" Value="1" /> |
|||
<Setter Property="Template"> |
|||
<Setter.Value> |
|||
<ControlTemplate TargetType="{x:Type local:ColorSpectrumSlider}"> |
|||
<Grid> |
|||
<Grid.ColumnDefinitions> |
|||
<ColumnDefinition Width="Auto"/> |
|||
<ColumnDefinition Width="Auto" /> |
|||
<ColumnDefinition Width="Auto"/> |
|||
</Grid.ColumnDefinitions> |
|||
<Grid.RowDefinitions> |
|||
<RowDefinition Height="*"/> |
|||
</Grid.RowDefinitions> |
|||
|
|||
<Border x:Name="PART_TrackBackground" Grid.Column="1" Width="20"> |
|||
<Rectangle x:Name="PART_SpectrumDisplay" Stretch="Fill" VerticalAlignment="Stretch" /> |
|||
</Border> |
|||
|
|||
<Track Grid.Column="1" Name="PART_Track"> |
|||
<Track.DecreaseRepeatButton> |
|||
<RepeatButton Style="{StaticResource SliderRepeatButtonStyle}" Command="Slider.DecreaseLarge"/> |
|||
</Track.DecreaseRepeatButton> |
|||
<Track.IncreaseRepeatButton> |
|||
<RepeatButton Style="{StaticResource SliderRepeatButtonStyle}" Command="Slider.IncreaseLarge"/> |
|||
</Track.IncreaseRepeatButton> |
|||
|
|||
<Track.Thumb> |
|||
<Thumb Style="{StaticResource VerticalSlideThumbStyle}" /> |
|||
</Track.Thumb> |
|||
</Track> |
|||
</Grid> |
|||
</ControlTemplate> |
|||
</Setter.Value> |
|||
</Setter> |
|||
</Style> |
|||
|
|||
</ResourceDictionary> |
|||
@ -0,0 +1,85 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Windows; |
|||
using System.Windows.Controls; |
|||
using System.Windows.Media; |
|||
using System.Windows.Shapes; |
|||
|
|||
namespace Microsoft.Windows.Controls |
|||
{ |
|||
internal class ColorSpectrumSlider : Slider |
|||
{ |
|||
#region Private Members
|
|||
|
|||
private Rectangle _spectrumDisplay; |
|||
private LinearGradientBrush _pickerBrush; |
|||
|
|||
#endregion //Private Members
|
|||
|
|||
#region Constructors
|
|||
|
|||
static ColorSpectrumSlider() |
|||
{ |
|||
DefaultStyleKeyProperty.OverrideMetadata(typeof(ColorSpectrumSlider), new FrameworkPropertyMetadata(typeof(ColorSpectrumSlider))); |
|||
} |
|||
|
|||
#endregion //Constructors
|
|||
|
|||
#region Dependency Properties
|
|||
|
|||
public static readonly DependencyProperty SelectedColorProperty = DependencyProperty.Register("SelectedColor", typeof(Color), typeof(ColorSpectrumSlider), new PropertyMetadata(System.Windows.Media.Colors.Transparent)); |
|||
public Color SelectedColor |
|||
{ |
|||
get { return (Color)GetValue(SelectedColorProperty); } |
|||
set { SetValue(SelectedColorProperty, value); } |
|||
} |
|||
|
|||
#endregion //Dependency Properties
|
|||
|
|||
#region Base Class Overrides
|
|||
|
|||
public override void OnApplyTemplate() |
|||
{ |
|||
base.OnApplyTemplate(); |
|||
|
|||
_spectrumDisplay = (Rectangle)GetTemplateChild("PART_SpectrumDisplay"); |
|||
CreateSpectrum(); |
|||
OnValueChanged(Double.NaN, Value); |
|||
} |
|||
|
|||
protected override void OnValueChanged(double oldValue, double newValue) |
|||
{ |
|||
base.OnValueChanged(oldValue, newValue); |
|||
|
|||
Color color = ColorUtilities.ConvertHsvToRgb(360 - newValue, 1, 1); |
|||
SelectedColor = color; |
|||
} |
|||
|
|||
#endregion //Base Class Overrides
|
|||
|
|||
#region Methods
|
|||
|
|||
private void CreateSpectrum() |
|||
{ |
|||
_pickerBrush = new LinearGradientBrush(); |
|||
_pickerBrush.StartPoint = new Point(0.5, 0); |
|||
_pickerBrush.EndPoint = new Point(0.5, 1); |
|||
_pickerBrush.ColorInterpolationMode = ColorInterpolationMode.SRgbLinearInterpolation; |
|||
|
|||
List<Color> colorsList = ColorUtilities.GenerateHsvSpectrum(); |
|||
|
|||
double stopIncrement = (double)1 / colorsList.Count; |
|||
|
|||
int i; |
|||
for (i = 0; i < colorsList.Count; i++) |
|||
{ |
|||
_pickerBrush.GradientStops.Add(new GradientStop(colorsList[i], i * stopIncrement)); |
|||
} |
|||
|
|||
_pickerBrush.GradientStops[i - 1].Offset = 1.0; |
|||
_spectrumDisplay.Fill = _pickerBrush; |
|||
} |
|||
|
|||
#endregion //Methods
|
|||
} |
|||
} |
|||
@ -0,0 +1,156 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Windows.Media; |
|||
|
|||
namespace Microsoft.Windows.Controls |
|||
{ |
|||
internal static class ColorUtilities |
|||
{ |
|||
/// <summary>
|
|||
/// Converts an RGB color to an HSV color.
|
|||
/// </summary>
|
|||
/// <param name="r"></param>
|
|||
/// <param name="b"></param>
|
|||
/// <param name="g"></param>
|
|||
/// <returns></returns>
|
|||
public static HsvColor ConvertRgbToHsv(int r, int b, int g) |
|||
{ |
|||
double delta, min; |
|||
double h = 0, s, v; |
|||
|
|||
min = Math.Min(Math.Min(r, g), b); |
|||
v = Math.Max(Math.Max(r, g), b); |
|||
delta = v - min; |
|||
|
|||
if (v == 0.0) |
|||
{ |
|||
s = 0; |
|||
} |
|||
else |
|||
s = delta / v; |
|||
|
|||
if (s == 0) |
|||
h = 0.0; |
|||
|
|||
else |
|||
{ |
|||
if (r == v) |
|||
h = (g - b) / delta; |
|||
else if (g == v) |
|||
h = 2 + (b - r) / delta; |
|||
else if (b == v) |
|||
h = 4 + (r - g) / delta; |
|||
|
|||
h *= 60; |
|||
if (h < 0.0) |
|||
h = h + 360; |
|||
|
|||
} |
|||
|
|||
return new HsvColor { H = h, S = s, V = v / 255 }; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts an HSV color to an RGB color.
|
|||
/// </summary>
|
|||
/// <param name="h"></param>
|
|||
/// <param name="s"></param>
|
|||
/// <param name="v"></param>
|
|||
/// <returns></returns>
|
|||
public static Color ConvertHsvToRgb(double h, double s, double v) |
|||
{ |
|||
double r = 0, g = 0, b = 0; |
|||
|
|||
if (s == 0) |
|||
{ |
|||
r = v; |
|||
g = v; |
|||
b = v; |
|||
} |
|||
else |
|||
{ |
|||
int i; |
|||
double f, p, q, t; |
|||
|
|||
if (h == 360) |
|||
h = 0; |
|||
else |
|||
h = h / 60; |
|||
|
|||
i = (int)Math.Truncate(h); |
|||
f = h - i; |
|||
|
|||
p = v * (1.0 - s); |
|||
q = v * (1.0 - (s * f)); |
|||
t = v * (1.0 - (s * (1.0 - f))); |
|||
|
|||
switch (i) |
|||
{ |
|||
case 0: |
|||
{ |
|||
r = v; |
|||
g = t; |
|||
b = p; |
|||
break; |
|||
} |
|||
case 1: |
|||
{ |
|||
r = q; |
|||
g = v; |
|||
b = p; |
|||
break; |
|||
} |
|||
case 2: |
|||
{ |
|||
r = p; |
|||
g = v; |
|||
b = t; |
|||
break; |
|||
} |
|||
case 3: |
|||
{ |
|||
r = p; |
|||
g = q; |
|||
b = v; |
|||
break; |
|||
} |
|||
case 4: |
|||
{ |
|||
r = t; |
|||
g = p; |
|||
b = v; |
|||
break; |
|||
} |
|||
default: |
|||
{ |
|||
r = v; |
|||
g = p; |
|||
b = q; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
} |
|||
|
|||
return Color.FromArgb(255, (byte)(r * 255), (byte)(g * 255), (byte)(b * 255)); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Generates a list of colors with hues ranging from 0 360 and a saturation and value of 1.
|
|||
/// </summary>
|
|||
/// <returns></returns>
|
|||
public static List<Color> GenerateHsvSpectrum() |
|||
{ |
|||
List<Color> colorsList = new List<Color>(8); |
|||
|
|||
for (int i = 0; i < 29; i++) |
|||
{ |
|||
colorsList.Add(ColorUtilities.ConvertHsvToRgb(i * 12, 1, 1)); |
|||
} |
|||
|
|||
colorsList.Add(ColorUtilities.ConvertHsvToRgb(0, 1, 1)); |
|||
|
|||
return colorsList; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,18 @@ |
|||
using System; |
|||
|
|||
namespace Microsoft.Windows.Controls |
|||
{ |
|||
internal struct HsvColor |
|||
{ |
|||
public double H; |
|||
public double S; |
|||
public double V; |
|||
|
|||
public HsvColor(double h, double s, double v) |
|||
{ |
|||
H = h; |
|||
S = s; |
|||
V = v; |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue