4 using System.Windows.Controls;
6 using System.Windows.Data;
7 using System.Windows.Media;
8 using SiliconStudio.Core.Mathematics;
10 using System.Windows.Media.Imaging;
11 using System.Windows.Input;
12 using SiliconStudio.Presentation.Extensions;
18 namespace SiliconStudio.Presentation.Controls
23 [TemplatePart(Name =
"PART_ColorPickerSelector", Type = typeof(Canvas))]
24 [TemplatePart(Name =
"PART_ColorPickerRenderSurface", Type = typeof(
Rectangle))]
25 [TemplatePart(Name =
"PART_ColorPreviewRenderSurface", Type = typeof(
Rectangle))]
26 [TemplatePart(Name =
"PART_HuePickerSelector", Type = typeof(FrameworkElement))]
27 [TemplatePart(Name =
"PART_HuePickerRenderSurface", Type = typeof(
Rectangle))]
32 DefaultStyleKeyProperty.OverrideMetadata(typeof(
ColorPicker),
new FrameworkPropertyMetadata(typeof(
ColorPicker)));
35 private Canvas colorPickerSelector;
36 private Rectangle colorPickerRenderSurface;
37 private Rectangle colorPreviewRenderSurface;
38 private FrameworkElement huePickerRenderSurface;
40 private bool interlock;
42 private bool suspendBindingUpdates;
43 private bool templateApplied;
44 private DependencyProperty initializingProperty;
49 public static readonly DependencyProperty ColorProperty = DependencyProperty.Register(
"Color", typeof(
Color4), typeof(
ColorPicker),
new FrameworkPropertyMetadata(
default(
Color4), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnColorPropertyChanged, CoreceColorValue,
false, UpdateSourceTrigger.Explicit));
54 public static readonly DependencyProperty HueProperty = DependencyProperty.Register(
"Hue", typeof(
float), typeof(
ColorPicker),
new FrameworkPropertyMetadata(0.0f, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnHSVPropertyChanged, CoerceHueValue));
59 public static readonly DependencyProperty SaturationProperty = DependencyProperty.Register(
"Saturation", typeof(
float), typeof(
ColorPicker),
new FrameworkPropertyMetadata(0.0f, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnHSVPropertyChanged, CoercePercentageValue));
64 public static readonly DependencyProperty BrightnessProperty = DependencyProperty.Register(
"Brightness", typeof(
float), typeof(
ColorPicker),
new FrameworkPropertyMetadata(0.0f, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnHSVPropertyChanged, CoercePercentageValue));
69 public static readonly DependencyProperty RedProperty = DependencyProperty.Register(
"Red", typeof(byte), typeof(
ColorPicker),
new FrameworkPropertyMetadata((byte)0, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnRGBAPropertyChanged));
74 public static readonly DependencyProperty GreenProperty = DependencyProperty.Register(
"Green", typeof(byte), typeof(
ColorPicker),
new FrameworkPropertyMetadata((byte)0, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnRGBAPropertyChanged));
79 public static readonly DependencyProperty BlueProperty = DependencyProperty.Register(
"Blue", typeof(byte), typeof(
ColorPicker),
new FrameworkPropertyMetadata((byte)0, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnRGBAPropertyChanged));
84 public static readonly DependencyProperty AlphaProperty = DependencyProperty.Register(
"Alpha", typeof(byte), typeof(
ColorPicker),
new FrameworkPropertyMetadata((byte)0, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnRGBAPropertyChanged));
90 public Color4 Color {
get {
return (
Color4)GetValue(ColorProperty); } set { SetValue(ColorProperty, value); } }
95 public float Hue {
get {
return (
float)GetValue(HueProperty); } set { SetValue(HueProperty, value); } }
100 public float Saturation {
get {
return (
float)GetValue(SaturationProperty); } set { SetValue(SaturationProperty, value); } }
105 public float Brightness {
get {
return (
float)GetValue(BrightnessProperty); } set { SetValue(BrightnessProperty, value); } }
110 public byte Red {
get {
return (byte)GetValue(RedProperty); } set { SetValue(RedProperty, value); } }
115 public byte Green {
get {
return (byte)GetValue(GreenProperty); } set { SetValue(GreenProperty, value); } }
120 public byte Blue {
get {
return (byte)GetValue(BlueProperty); } set { SetValue(BlueProperty, value); } }
125 public byte Alpha {
get {
return (byte)GetValue(AlphaProperty); } set { SetValue(AlphaProperty, value); } }
130 private ColorHSV InternalColor {
get {
return internalColor; } set { internalColor = value; var prev = interlock; interlock =
true;
Color = value.ToColor(); interlock = prev; } }
135 templateApplied =
false;
136 base.OnApplyTemplate();
138 if (colorPickerRenderSurface != null)
140 colorPickerRenderSurface.MouseDown -= OnColorPickerRenderSurfaceMouseDown;
141 colorPickerRenderSurface.MouseUp -= OnColorPickerRenderSurfaceMouseUp;
142 colorPickerRenderSurface.MouseMove -= OnColorPickerRenderSurfaceMouseMove;
145 if (huePickerRenderSurface != null)
147 huePickerRenderSurface.MouseDown -= OnHuePickerRenderSurfaceMouseDown;
148 huePickerRenderSurface.MouseUp -= OnHuePickerRenderSurfaceMouseUp;
149 huePickerRenderSurface.MouseMove -= OnHuePickerRenderSurfaceMouseMove;
153 colorPickerRenderSurface = FrameworkElementExtensions.CheckTemplatePart<
Rectangle>(GetTemplateChild(
"PART_ColorPickerRenderSurface"));
154 colorPreviewRenderSurface = FrameworkElementExtensions.CheckTemplatePart<
Rectangle>(GetTemplateChild(
"PART_ColorPreviewRenderSurface"));
155 colorPickerSelector = FrameworkElementExtensions.CheckTemplatePart<Canvas>(GetTemplateChild(
"PART_ColorPickerSelector"));
156 huePickerSelector = FrameworkElementExtensions.CheckTemplatePart<
Rectangle>(GetTemplateChild(
"PART_HuePickerSelector"));
157 huePickerRenderSurface = FrameworkElementExtensions.CheckTemplatePart<FrameworkElement>(GetTemplateChild(
"PART_HuePickerRenderSurface"));
159 if (colorPickerRenderSurface != null)
161 colorPickerRenderSurface.MouseDown += OnColorPickerRenderSurfaceMouseDown;
162 colorPickerRenderSurface.MouseUp += OnColorPickerRenderSurfaceMouseUp;
163 colorPickerRenderSurface.MouseMove += OnColorPickerRenderSurfaceMouseMove;
166 if (huePickerRenderSurface != null)
168 huePickerRenderSurface.MouseDown += OnHuePickerRenderSurfaceMouseDown;
169 huePickerRenderSurface.MouseUp += OnHuePickerRenderSurfaceMouseUp;
170 huePickerRenderSurface.MouseMove += OnHuePickerRenderSurfaceMouseMove;
173 RenderColorPickerSurface();
175 if (colorPickerSelector != null && colorPickerRenderSurface != null)
177 Canvas.SetLeft(colorPickerSelector, Saturation * colorPickerRenderSurface.Width / 100.0);
178 Canvas.SetTop(colorPickerSelector, Brightness * colorPickerRenderSurface.Height / 100.0);
180 if (huePickerSelector != null && huePickerRenderSurface != null)
182 Canvas.SetLeft(huePickerSelector, Hue * huePickerRenderSurface.Width / 360.0);
184 templateApplied =
true;
192 private void OnColorPickerRenderSurfaceMouseDown(
object sender, MouseButtonEventArgs e)
194 if (e.LeftButton == MouseButtonState.Pressed)
196 colorPickerRenderSurface.CaptureMouse();
197 suspendBindingUpdates =
true;
198 UpdateColorPickerFromMouse(e.GetPosition(colorPickerRenderSurface));
207 private void OnColorPickerRenderSurfaceMouseUp(
object sender, MouseButtonEventArgs e)
209 if (e.LeftButton == MouseButtonState.Released)
211 colorPickerRenderSurface.ReleaseMouseCapture();
212 suspendBindingUpdates =
false;
222 private void OnColorPickerRenderSurfaceMouseMove(
object sender, MouseEventArgs e)
224 if (e.LeftButton == MouseButtonState.Pressed && colorPickerRenderSurface.IsMouseCaptured)
226 UpdateColorPickerFromMouse(e.GetPosition(colorPickerRenderSurface));
234 private void UpdateColorPickerFromMouse(
Point position)
236 Canvas.SetLeft(colorPickerSelector, MathUtil.Clamp(position.X, 0.0f, colorPickerRenderSurface.Width));
237 Canvas.SetTop(colorPickerSelector, MathUtil.Clamp(position.Y, 0.0f, colorPickerRenderSurface.Height));
238 var x = (float)(position.X / colorPickerRenderSurface.Width);
239 var
y = (float)(position.Y / colorPickerRenderSurface.Height);
240 x = MathUtil.Clamp(x, 0.0f, 1.0f);
241 y = MathUtil.Clamp(
y, 0.0f, 1.0f);
242 var colorHSV =
new ColorHSV(Hue, x, y, Alpha / 255.0f);
244 SetCurrentValue(SaturationProperty, colorHSV.S * 100.0f);
245 SetCurrentValue(BrightnessProperty, colorHSV.V * 100.0f);
254 private void OnHuePickerRenderSurfaceMouseDown(
object sender, MouseButtonEventArgs e)
256 if (e.LeftButton == MouseButtonState.Pressed)
258 huePickerRenderSurface.CaptureMouse();
259 suspendBindingUpdates =
true;
260 UpdateHuePickerFromMouse(e.GetPosition(huePickerRenderSurface));
269 private void OnHuePickerRenderSurfaceMouseUp(
object sender, MouseButtonEventArgs e)
271 if (e.LeftButton == MouseButtonState.Released)
273 huePickerRenderSurface.ReleaseMouseCapture();
274 suspendBindingUpdates =
false;
284 private void OnHuePickerRenderSurfaceMouseMove(
object sender, MouseEventArgs e)
286 if (e.LeftButton == MouseButtonState.Pressed && huePickerRenderSurface.IsMouseCaptured)
288 UpdateHuePickerFromMouse(e.GetPosition(huePickerRenderSurface));
296 private void UpdateHuePickerFromMouse(
Point position)
298 Canvas.SetLeft(huePickerSelector, MathUtil.Clamp(position.X, 0.0f, huePickerRenderSurface.Width));
299 var x = (float)(position.X / huePickerRenderSurface.Width);
303 SetCurrentValue(HueProperty, x);
309 private void RenderColorPickerSurface()
311 if (colorPreviewRenderSurface != null)
313 colorPreviewRenderSurface.Fill =
new SolidColorBrush(
Color.ToSystemColor());
315 if (colorPickerRenderSurface != null)
318 if (!
double.IsNaN(colorPickerRenderSurface.Width) && !double.IsNaN(colorPickerRenderSurface.Height))
320 var width = (int)colorPickerRenderSurface.Width;
321 var height = (
int)colorPickerRenderSurface.Height;
324 int rawStride = (width * pf.BitsPerPixel + 7) / 8;
325 var rawImage =
new byte[rawStride * height];
327 for (
int j = 0; j < height; ++j)
329 float y = j / (float)(height - 1);
331 for (
int i = 0; i < width; ++i)
333 float x = i / (float)(width - 1);
335 System.Windows.Media.Color color =
new ColorHSV(Hue, x, y, 1.0f).ToSystemColor();
336 rawImage[(i + j * width) * 4 + 0] = color.B;
337 rawImage[(i + j * width) * 4 + 1] = color.G;
338 rawImage[(i + j * width) * 4 + 2] = color.R;
342 colorPickerRenderSurface.Fill =
new DrawingBrush(
new ImageDrawing(BitmapSource.Create(width, height, 96, 96, pf, null, rawImage, rawStride),
new Rect(0.0f, 0.0f, width, height)));
350 private void OnColorChanged()
352 bool isInitializing = !templateApplied && initializingProperty == null;
354 initializingProperty = ColorProperty;
358 InternalColor = ColorHSV.FromColor(
Color);
359 var colorRGBA = InternalColor.ToColor();
362 SetCurrentValue(RedProperty, (byte)(Math.Round(colorRGBA.R * 255.0f)));
363 SetCurrentValue(GreenProperty, (byte)(Math.Round(colorRGBA.G * 255.0f)));
364 SetCurrentValue(BlueProperty, (byte)(Math.Round(colorRGBA.B * 255.0f)));
365 SetCurrentValue(AlphaProperty, (byte)(Math.Round(colorRGBA.A * 255.0f)));
367 SetCurrentValue(HueProperty, InternalColor.H);
368 SetCurrentValue(SaturationProperty, InternalColor.S * 100.0f);
369 SetCurrentValue(BrightnessProperty, InternalColor.V * 100.0f);
373 if (!suspendBindingUpdates)
375 RenderColorPickerSurface();
377 else if (colorPreviewRenderSurface != null)
379 colorPreviewRenderSurface.Fill =
new SolidColorBrush(
Color.ToSystemColor());
381 UpdateBinding(ColorProperty);
384 initializingProperty = null;
391 private void OnRGBAValueChanged(DependencyPropertyChangedEventArgs e)
393 bool isInitializing = !templateApplied && initializingProperty == null;
395 initializingProperty = e.Property;
400 if (e.Property == RedProperty)
401 colorRGBA =
new Color4((byte)e.NewValue / 255.0f, Green / 255.0f, Blue / 255.0f, Alpha / 255.0f);
402 else if (e.Property == GreenProperty)
403 colorRGBA =
new Color4(Red / 255.0f, (byte)e.NewValue / 255.0f, Blue / 255.0f, Alpha / 255.0f);
404 else if (e.Property == BlueProperty)
405 colorRGBA =
new Color4(Red / 255.0f, Green / 255.0f, (byte)e.NewValue / 255.0f, Alpha / 255.0f);
406 else if (e.Property == AlphaProperty)
407 colorRGBA =
new Color4(Red / 255.0f, Green / 255.0f, Blue / 255.0f, (byte)e.NewValue / 255.0f);
409 throw new ArgumentException(
"Property unsupported by method OnRGBAValueChanged.");
412 InternalColor = ColorHSV.FromColor(colorRGBA);
413 SetCurrentValue(HueProperty, InternalColor.H);
414 SetCurrentValue(SaturationProperty, InternalColor.S * 100.0f);
415 SetCurrentValue(BrightnessProperty, InternalColor.V * 100.0f);
419 UpdateBinding(e.Property);
421 initializingProperty = null;
428 private void OnHSVValueChanged(DependencyPropertyChangedEventArgs e)
430 bool isInitializing = !templateApplied && initializingProperty == null;
432 initializingProperty = e.Property;
436 if (e.Property == HueProperty)
438 InternalColor =
new ColorHSV((
float)e.NewValue, Saturation / 100.0f, Brightness / 100.0f, Alpha / 255.0f);
439 RenderColorPickerSurface();
441 else if (e.Property == SaturationProperty)
442 InternalColor =
new ColorHSV(Hue, (
float)e.NewValue / 100.0f, Brightness / 100.0f, Alpha / 255.0f);
443 else if (e.Property == BrightnessProperty)
444 InternalColor =
new ColorHSV(Hue, Saturation / 100.0f, (
float)e.NewValue / 100.0f, Alpha / 255.0f);
446 throw new ArgumentException(
"Property unsupported by method OnHSVValueChanged.");
448 var colorRGBA = InternalColor.ToColor();
450 SetCurrentValue(RedProperty, (byte)(Math.Round(colorRGBA.R * 255.0f)));
451 SetCurrentValue(GreenProperty, (byte)(Math.Round(colorRGBA.G * 255.0f)));
452 SetCurrentValue(BlueProperty, (byte)(Math.Round(colorRGBA.B * 255.0f)));
453 SetCurrentValue(AlphaProperty, (byte)(Math.Round(colorRGBA.A * 255.0f)));
457 UpdateBinding(e.Property);
459 if (colorPickerSelector != null && colorPickerRenderSurface != null && !suspendBindingUpdates)
461 Canvas.SetLeft(colorPickerSelector,
Saturation * colorPickerRenderSurface.Width / 100.0);
462 Canvas.SetTop(colorPickerSelector, Brightness * colorPickerRenderSurface.Height / 100.0);
464 if (huePickerSelector != null && huePickerRenderSurface != null && !suspendBindingUpdates)
466 Canvas.SetLeft(huePickerSelector,
Hue * huePickerRenderSurface.Width / 360.0);
470 initializingProperty = null;
477 private void UpdateBinding(DependencyProperty dependencyProperty)
479 if (!suspendBindingUpdates && dependencyProperty != initializingProperty)
481 BindingExpression expression = GetBindingExpression(dependencyProperty);
482 if (expression != null)
483 expression.UpdateSource();
490 private void UpdateAllBindings()
492 UpdateBinding(ColorProperty);
493 UpdateBinding(RedProperty);
494 UpdateBinding(GreenProperty);
495 UpdateBinding(BlueProperty);
496 UpdateBinding(AlphaProperty);
497 UpdateBinding(HueProperty);
498 UpdateBinding(SaturationProperty);
499 UpdateBinding(BrightnessProperty);
507 private static void OnColorPropertyChanged(
DependencyObject sender, DependencyPropertyChangedEventArgs e)
509 var colorPicker = (ColorPicker)sender;
510 colorPicker.OnColorChanged();
519 private static void OnHSVPropertyChanged(
DependencyObject sender, DependencyPropertyChangedEventArgs e)
521 var colorPicker = (ColorPicker)sender;
522 colorPicker.OnHSVValueChanged(e);
531 private static void OnRGBAPropertyChanged(
DependencyObject sender, DependencyPropertyChangedEventArgs e)
533 var colorPicker = (ColorPicker)sender;
534 colorPicker.OnRGBAValueChanged(e);
540 private static object CoreceColorValue(
DependencyObject sender,
object baseValue)
542 return new Color(((
Color4)baseValue).ToArray()).ToColor4();
548 private static object CoerceHueValue(
DependencyObject sender,
object baseValue)
550 return ((
float)baseValue + 360.0f) % 360.0f;
556 private static object CoercePercentageValue(
DependencyObject sender,
object baseValue)
558 return MathUtil.Clamp((float)baseValue, 0.0f, 100.0f);
Hue effect from the two textures.
override void OnApplyTemplate()
_In_ size_t _In_ DXGI_FORMAT _In_ size_t _In_ float size_t y
Represents a color picker control.
Represents a color in the form of rgba.
Saturation effect from the two textures.
static float Clamp(float value, float min, float max)
Clamps the specified value.
Structure using the same layout than System.Drawing.Point.
SiliconStudio.Core.Mathematics.Color Color
Represents a 32-bit color (4 bytes) in the form of RGBA (in byte order: R, G, B, A).
System.Windows.Shapes.Rectangle Rectangle
Structure using the same layout than System.Drawing.Rectangle
PixelFormat
Defines various types of pixel formats.
System.Windows.Point Point
Represents a color in the form of Hue, Saturation, Value, Alpha.