mariocepoi
Topic Author
Posts: 2
Joined: 18 Jan 2022, 23:10

How to bind class ColorPicker on ui

30 Jan 2022, 20:07

Hello all ,

I am currently moving from Unity's Gui to Noesis and love it so far . However i have a hard time understanding how class extensions bind to the ui .

For instance i am trying to get a color picker and have found this usefull post viewtopic.php?t=1905 .

I did create a class for the logic and pasted the following code . Image

ColorPickerControl.cs
using Noesis;
using System;
using NoesisEventArgs = Noesis.EventArgs;

namespace Example
{
    public class ColorPickerControl : UserControl
    {
        public static readonly DependencyProperty ColorBrushProperty = DependencyProperty.Register("ColorBrush",
            typeof(SolidColorBrush), typeof(ColorPickerControl), new PropertyMetadata(null));

        public event EventHandler<ColorEventArgs> ColorChanged;

        private FrameworkElement _Root;
        private Slider _Spectrum;
        private Grid _HsGrid;
        private TranslateTransform _PickerTransform;
        private TextBlock _Text;
        private SolidColorBrush _Color;
        private GradientStop _Stop;

        private float _Hue;
        private float _Saturation;
        private float _Value;

        public ColorPickerControl()
        {
            Name = "ColorPickerControl";
            InitializeComponent();
        }

        protected void InitializeComponent()
        {
            GUI.LoadComponent(this, "Assets/User Interface/Controls/Color Picker Control/ColorPickerControl.xaml");
            _Root = this.Content as FrameworkElement;

            _Spectrum = _Root.FindName("Slider") as Slider;
            _HsGrid = _Root.FindName("HS") as Grid;
            _PickerTransform = _Root.FindName("PickerTransform") as TranslateTransform;
            _Text = _Root.FindName("Text") as TextBlock;
            _Color = _Root.FindName("Color") as SolidColorBrush;
            _Stop = _Root.FindName("Stop") as GradientStop;

            _Spectrum.ValueChanged += this.OnSpectrumChange;
            _HsGrid.MouseLeftButtonDown += this.OnMouseLeftButtonDown;
            _HsGrid.MouseLeftButtonUp += this.OnMouseLeftButtonUp;
            _HsGrid.MouseMove += this.OnMouseMove;
            _HsGrid.SizeChanged += this.OnSizeChanged;

            _Hue = 0.0f;
            _Saturation = 0.5f;
            _Value = 0.5f;

            Update();
        }

        public SolidColorBrush ColorBrush
        {
            get { return (SolidColorBrush)GetValue(ColorBrushProperty); }
            set { SetValue(ColorBrushProperty, value); }
        }

        private void OnSpectrumChange(object sender, RoutedPropertyChangedEventArgs<float> e)
        {
            _Hue = e.NewValue;
            _Stop.Color = HSVToColor(_Hue, 1, 1);
            Update();
        }

        private void OnMouseLeftButtonDown(Object sender, MouseButtonEventArgs args)
        {
            Focus();
            _HsGrid.CaptureMouse();
            Point point = _HsGrid.PointFromScreen(args.GetPosition(null));
            UpdatePickerPosition(point);
        }

        private void OnMouseLeftButtonUp(Object sender, MouseButtonEventArgs args)
        {
            _HsGrid.ReleaseMouseCapture();
        }

        private void OnMouseMove(object sender, MouseEventArgs args)
        {
            if (_HsGrid.IsMouseCaptured)
            {
                Point point = _HsGrid.PointFromScreen(args.GetPosition(null));
                UpdatePickerPosition(point);
            }
        }

        private void OnSizeChanged(object sender, SizeChangedEventArgs args)
        {
            Size size = args.NewSize;
            _PickerTransform.X = _Value * size.Width - 0.5f * size.Width;
            _PickerTransform.Y = size.Height - _Saturation * size.Height - 0.5f * size.Height;
        }

        private void UpdatePickerPosition(Point pos)
        {
            Size size = _HsGrid.RenderSize;

            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.X = pos.X - 0.5f * size.Width;
            _PickerTransform.Y = pos.Y - 0.5f * size.Height;

            _Value = pos.X / size.Width;
            _Saturation = (size.Height - pos.Y) / size.Height;

            Update();
        }

        private void Update()
        {
           Color color = HSVToColor(_Hue, _Saturation, _Value);
            int red = color.R;
            int green = color.G;
            int blue = color.B;
            _Text.Text = string.Format("#{0:X2}{1:X2}{2:X2}", red, green, blue);
            _Color.Color = color;
            ColorBrush = new SolidColorBrush(color);

            ColorChanged?.Invoke(this, new ColorEventArgs(color));
        }

        private 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 Color.FromScRgb(1, chroma + m, x + m, m);
                case 1:
                    return Color.FromScRgb(1, x + m, chroma + m, m);
                case 2:
                    return Color.FromScRgb(1, m, chroma + m, x + m);
                case 3:
                    return Color.FromScRgb(1, m, x + m, chroma + m);
                case 4:
                    return Color.FromScRgb(1, x + m, m, chroma + m);
                default:
                    return Color.FromScRgb(1, chroma + m, m, x + m);
            }
        }
    }

    public class ColorEventArgs : NoesisEventArgs
    {
        public new Color Empty { get; protected set; }
        public Color Color { get; protected set; }

        public ColorEventArgs(Color color)
        {
            Color = color;
        }
    }
}
Then I created a new window inside blend and pasted the below code and of course corrected the class name >> coppied the grid and pasted on my main panel .

Image
upload image file

Now when i test it the picker does not work at all and i suppose it makes sense since probably i am not suing the logic at all.

How do i use this class and especiallyhow do i do that vissually as unfortunately I don't know xml only c# , preaty sure this is quite basic but havnent't found any info on this .

Thanks in advance .
 <UserControl
  x:Class="Example.ColorPickerControl"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  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="32"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
                <Path Grid.Column="0" Data="M0,0 L16,10 0,20 z" Fill="White" HorizontalAlignment="Right" Margin="0, 0, 0, -5"/>
                <Path Grid.Column="2" Data="M16,0 L0,10 16,20 z" Fill="White" HorizontalAlignment="Left" Margin="0, 0, 0, -5"/>
            </Grid>
        </ControlTemplate>
        <ControlTemplate x:Key="SpectrumSliderTemplate" TargetType="{x:Type Slider}">
            <Grid>
                <Rectangle StrokeThickness="1" Stroke="#000000" Width="32">
                    <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>
        <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="Left" Margin="0">
                <Rectangle Width="50" Height="50" Margin="10" StrokeThickness="1" Stroke="#000000">
                    <Rectangle.Fill>
                        <SolidColorBrush x:Name="Color" Color="#FF0000"/>
                    </Rectangle.Fill>
                </Rectangle>
                <TextBlock x:Name="Text" FontSize="30" Margin="15, 0, 0, 0" VerticalAlignment="Center" Text="Text" Foreground="White"/>
            </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" Height="512" Width="512">
                <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="24" Width="24" RenderTransformOrigin="0.5,0.5" ClipToBounds="true">
                <Canvas.RenderTransform>
                    <TranslateTransform x:Name="PickerTransform" X="0" Y="0"/>
                </Canvas.RenderTransform>
                <Grid>
                    <Ellipse Stroke="Black" Width="24" Height="24"/>
                    <Ellipse Stroke="White" Width="20" Height="20"/>
                </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="10, 0, 0, 0"/>
        </Grid>

    </Grid>
</UserControl>
 
User avatar
sfernandez
Site Admin
Posts: 3363
Joined: 22 Dec 2011, 19:20

Re: How to bind class ColorPicker on ui

31 Jan 2022, 11:09

As explained in our UserControl tutorial, once you have your control defined you can use it in another xaml by referencing it with the corresponding prefix:
<Grid
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:local="clr-namespace:Example">
  ...
  <local:ColorPickerControl x:Name="colorPicker" HorizontalAlignment="Left" VerticalAlignment="Top"/>
  <Rectangle Width="200" Height="100" Fill="{Binding ColorBrush, ElementName=colorPicker}"/>
  ...
</Grid>
Can you try that?

Who is online

Users browsing this forum: No registered users and 4 guests