User avatar
jsantos
Site Admin
Topic Author
Posts: 4123
Joined: 20 Jan 2012, 17:18
Contact:

Color Picker

14 Oct 2013, 14:03

Basic HSV color picker inspired by http://colorpicker.com/
ColorPicker.png
<UserControl
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  x:Class="Sample.ColorPicker"
  UseLayoutRounding="True">
 
  <UserControl.Resources>
    <Style x:Key="SpectrumSliderButtonStyle" TargetType="{x:Type RepeatButton}">
      <Setter Property="OverridesDefaultStyle" Value="True"/>
      <Setter Property="UseLayoutRounding" Value="True"/>
      <Setter Property="IsTabStop" Value="False"/>
      <Setter Property="Focusable" Value="False"/>
      <Setter Property="ClickMode" Value="Press"/>
      <Setter Property="Delay" Value="250"/>
      <Setter Property="Interval" Value="100"/>
      <Setter Property="Template">
        <Setter.Value>
          <ControlTemplate TargetType="{x:Type RepeatButton}">
            <Border Background="Transparent" />
          </ControlTemplate>
        </Setter.Value>
      </Setter>
    </Style>
    <ControlTemplate x:Key="SpectrumSliderThumbTemplate" TargetType="{x:Type Thumb}">
      <Grid Background="Transparent">
        <Grid.ColumnDefinitions>
          <ColumnDefinition Width="*"/>
          <ColumnDefinition Width="20"/>
          <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Path Grid.Column="0" Data="M0,0L8,5 0,10z" Fill="Black" HorizontalAlignment="Right"/>
        <Path Grid.Column="2" Data="M8,0L0,5 8,10z" Fill="Black" HorizontalAlignment="Left"/>
      </Grid>
    </ControlTemplate>
    <ControlTemplate x:Key="SpectrumSliderTemplate" TargetType="{x:Type Slider}">
      <Grid>
        <Rectangle StrokeThickness="1" Stroke="#000000" Width="20">
          <Rectangle.Fill>
            <LinearGradientBrush StartPoint="0.5, 0" EndPoint="0.5, 1">
              <GradientStop Color="#FFFF0000" Offset="0"/>
              <GradientStop Color="#FFFF00FF" Offset="0.1666666"/>
              <GradientStop Color="#FF0000FF" Offset="0.3333333"/>
              <GradientStop Color="#FF00FFFF" Offset="0.5"/>
              <GradientStop Color="#FF00FF00" Offset="0.6666666"/>
              <GradientStop Color="#FFFFFF00" Offset="0.8333333"/>
              <GradientStop Color="#FFFF0000" Offset="1"/>
            </LinearGradientBrush>
          </Rectangle.Fill>
        </Rectangle>
        <Track x:Name="PART_Track">
          <Track.Thumb>
            <Thumb Template="{StaticResource SpectrumSliderThumbTemplate}" Margin="0,-4"/>
          </Track.Thumb>
          <Track.DecreaseRepeatButton>
            <RepeatButton Style="{StaticResource SpectrumSliderButtonStyle}" Command="Slider.DecreaseLarge" />
          </Track.DecreaseRepeatButton>
          <Track.IncreaseRepeatButton>
            <RepeatButton Style="{StaticResource SpectrumSliderButtonStyle}" Command="Slider.IncreaseLarge" />
          </Track.IncreaseRepeatButton>
        </Track>
      </Grid>
    </ControlTemplate>
  </UserControl.Resources>
 
  <Grid Background="Gray">
    <Grid.RowDefinitions>
      <RowDefinition Height="Auto"/>
      <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
 
    <Grid.ColumnDefinitions>
      <ColumnDefinition Width="*"/>
      <ColumnDefinition Width="Auto"/>
    </Grid.ColumnDefinitions>
 
    <!-- Color selected -->
    <Grid Grid.Row="0" Grid.ColumnSpan="2">
      <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="0">
        <TextBlock x:Name="Text" FontSize="15" VerticalAlignment="Center" Width = "70"/>
        <Rectangle Width="50" Height="50" Margin="10" StrokeThickness="1" Stroke="#000000">
          <Rectangle.Fill>
            <SolidColorBrush x:Name="Color" Color="#FF0000"/>
          </Rectangle.Fill>
        </Rectangle>
      </StackPanel>
    </Grid>
 
    <!-- Picker -->
    <Grid x:Name="HS" Grid.Row="1" Grid.Column="0">
      <Rectangle>
        <Rectangle.Fill>
          <LinearGradientBrush StartPoint="0,1" EndPoint="0,0">
            <GradientStop Color="White" Offset="0"/>
            <GradientStop x:Name="Stop" Color="Red" Offset="1"/>
          </LinearGradientBrush>
        </Rectangle.Fill>
      </Rectangle>
      <Rectangle StrokeThickness="1" Stroke="#000000">
        <Rectangle.Fill>
          <LinearGradientBrush StartPoint="1,0" EndPoint="0,0">
            <GradientStop Offset="0" Color="#00000000"/>
            <GradientStop Offset="1" Color="#FF000000"/>
          </LinearGradientBrush>
        </Rectangle.Fill>
      </Rectangle>
 
      <Canvas Height="12" Width="12" RenderTransformOrigin="0.5,0.5"  ClipToBounds="true">
        <Canvas.RenderTransform>
          <TranslateTransform x:Name="PickerTransform" X="0" Y="0"/>
        </Canvas.RenderTransform>
        <Grid>
          <Ellipse Stroke="Black" Width="12" Height="12"/>
          <Ellipse Stroke="White" Width="10" Height="10"/>
        </Grid>
      </Canvas>
 
    </Grid>
 
    <!-- Spectrum -->
    <Grid Grid.Row="1" Grid.Column="1">
      <Slider x:Name="Slider" Orientation="Vertical" IsMoveToPointEnabled="True" Minimum="0" Maximum="360"
        Value="0" Template="{StaticResource SpectrumSliderTemplate}" Margin="5,0"/>
    </Grid>
 
  </Grid>
 
</UserControl>
using Noesis;
using System;
 
namespace Sample
{
 
[Noesis.Extended]
[Noesis.UserControlSource("Assets/Test/ColorPicker.xaml")]
public class ColorPicker : Noesis.UserControl
{
    public static DependencyProperty ColorProperty = DependencyProperty.Register("Color",
        typeof(SolidColorBrush), typeof(ColorPicker), new PropertyMetadata(null));
 
    public SolidColorBrush Color
    {
        get { return GetValue<SolidColorBrush>(ColorProperty); }
        set { SetValue<SolidColorBrush>(ColorProperty, value); }
    }
 
    public void OnPostInit()
    {
        _spectrum = FindName<Slider>("Slider");
        _hs = FindName<FrameworkElement>("HS");
        _pickerTransform = FindName<TranslateTransform>("PickerTransform");
        _text = FindName<TextBlock>("Text");
        _color = FindName<SolidColorBrush>("Color");
        _stop = FindName<GradientStop>("Stop");
 
        _spectrum.ValueChanged += this.OnSpectrumChange;
        _hs.MouseLeftButtonDown += this.OnMouseLeftButtonDown;
        _hs.MouseLeftButtonUp += this.OnMouseLeftButtonUp;
        _hs.MouseMove += this.OnMouseMove;
        _hs.SizeChanged += this.OnSizeChanged;
 
        _hue = 0.0f;
        _saturation = 0.5f;
        _value = 0.5f;
 
        Update();
    }
 
    private void OnSpectrumChange(float oldValue, float newValue)
    {
        _hue = newValue;
        _stop.SetColor(HSVToColor(_hue, 1, 1));
        Update();
    }
 
    private void OnMouseLeftButtonDown(BaseComponent c, MouseButtonEventArgs args)
    {
        Focus();
        _hs.CaptureMouse();
        Noesis.Point p = _hs.PointFromScreen(args.position);
        UpdatePickerPosition(p);
    }
 
    private void OnMouseLeftButtonUp(BaseComponent c, MouseButtonEventArgs args)
    {
        _hs.ReleaseMouseCapture();
    }
 
    private void OnMouseMove(BaseComponent c, MouseEventArgs args)
    {
        if (_hs.GetIsMouseCaptured())
        {
            Noesis.Point p = _hs.PointFromScreen(args.position);
            UpdatePickerPosition(p);
        }
    }
 
    private void OnSizeChanged(BaseComponent c, SizeChangedEventArgs args)
    {
        Noesis.Size size = args.sizeChangedInfo.newSize;
        _pickerTransform.SetX(_value * size.width - 0.5f * size.width);
        _pickerTransform.SetY(size.height - _saturation * size.height - 0.5f * size.height);
    }
 
    private void UpdatePickerPosition(Noesis.Point pos)
    {
        Noesis.Size size = _hs.GetRenderSize();
 
        pos.x = Math.Max(0.0f, Math.Min(size.width, pos.x));
        pos.y = Math.Max(0.0f, Math.Min(size.height, pos.y));
 
        _pickerTransform.SetX(pos.x - 0.5f * size.width);
        _pickerTransform.SetY(pos.y - 0.5f * size.height);
 
        _value = pos.x / size.width;
        _saturation = (size.height - pos.y) / size.height;
 
        Update();
    }
 
    private void Update()
    {
        Noesis.Color color = HSVToColor(_hue, _saturation, _value);
        int red = color.GetRedI();
        int green = color.GetGreenI();
        int blue = color.GetBlueI();
        _text.SetText(String.Format("#{0:X2}{1:X2}{2:X2}", red, green, blue));
        _color.SetColor(color);
        Color = new SolidColorBrush(color);
    }
 
    private Noesis.Color HSVToColor(float hue, float saturation, float value)
    {
        float chroma = value * saturation;
        float hueTag = (hue % 360) / 60;
        float x = chroma * (1 - Math.Abs(hueTag % 2.0f - 1));
        float m = value - chroma;
 
        switch ((int)hueTag)
        {
            case 0:
            {
                return new Noesis.Color(chroma + m, x + m, m);
            }
            case 1:
            {
                return new Noesis.Color(x + m, chroma + m, m);
            }
            case 2:
            {
                return new Noesis.Color(m, chroma + m, x + m);
            }
            case 3:
            {
                return new Noesis.Color(m, x + m, chroma + m);
            }
            case 4:
            {
                return new Noesis.Color(x + m, m, chroma + m);
            }
            default:
            {
                return new Noesis.Color(chroma + m, m, x + m);
            }
        }
    }
 
    private Slider _spectrum;
    private FrameworkElement _hs;
    private TranslateTransform _pickerTransform;
    private TextBlock _text;
    private SolidColorBrush _color;
    private GradientStop _stop;
 
    private float _hue;
    private float _saturation;
    private float _value;
}
 
}

Who is online

Users browsing this forum: rjmg and 1 guest