public VCanvas(double H, double S, double V, Bitmap colourBitmap) { this.Width = 128; this.Height = 96; Shaft = new AnimatableCylinderShaft(V); Shaft.Path.Fill = HSB.CylinderBrush; this.Children.Add(Shaft.Path); ColourCanvas = new Canvas() { Width = 256, Height = 256, ClipToBounds = false }; ColourImage = new Image() { Source = colourBitmap }; ColourCanvas.Children.Add(ColourImage); PositionEllipse = new Ellipse() { Width = 32, Height = 32, Fill = (S <0.5 && V> 0.5 ? Brushes.Black : Brushes.White) }; PositionEllipse.RenderTransform = ColorPicker.GetTranslateTransform(128 - 16 + S * Math.Cos(H * 2 * Math.PI) * 128, 128 - 16 + S * Math.Sin(H * 2 * Math.PI) * 128); ColourCanvas.Children.Add(PositionEllipse); Point v23 = new Point(128, 56 - V * 56); Point v14 = new Point(0, 56 - V * 56); Point v67 = new Point(128, 96 - V * 56); double m11 = (v23.X - v14.X) / 256; double m12 = (v67.X - v23.X) / 256; double m21 = (v23.Y - v14.Y) / 256; double m22 = (v67.Y - v23.Y) / 256; ColourCanvasTransform = new AnimatableTransform(new Matrix(m11, m21, m12, m22, v14.X, v14.Y)); ColourCanvas.RenderTransform = ColourCanvasTransform.MatrixTransform; ColourCanvas.RenderTransformOrigin = new RelativePoint(0, 0, RelativeUnit.Absolute); this.Children.Add(ColourCanvas); }
private static void AddColorHexagon(int i, Palette palette, Canvas container, PaletteSelector owner, List <PaletteColorInfo> infos, Func <Color, Color> colourBlindnessFunction) { AnimatableTransform transform = new AnimatableTransform(new Matrix(1, 0, 0, 1, 0, 0)); PaletteColorInfo info = new PaletteColorInfo() { Index = i, OriginalIndex = i, Transform = transform }; infos.Insert(i, info); double centerX = (1.5 + 2.5 * i) * HexagonRadius + 6.93; double centerY = HexagonRadius * Math.Cos(Math.PI / 6) * (i % 2 == 0 ? 1 : 2); PathGeometry leftHexagon = GetHexagonPath(new Point(centerX - 0.5 * HexagonRadius, centerY), HexagonRadius); PathGeometry centerHexagon = GetHexagonPath(new Point(centerX, centerY), HexagonRadius); PathGeometry rightHexagon = GetHexagonPath(new Point(centerX + 0.5 * HexagonRadius, centerY), HexagonRadius); Color color = palette.Colors[i % palette.Colors.Count]; Color lighterColor = ColorPicker.GetLighterColor(color); Color darkerColor = ColorPicker.GetDarkerColor(color); Avalonia.Controls.Shapes.Path leftPath = new Avalonia.Controls.Shapes.Path() { Data = leftHexagon, Fill = new ColorVisualBrush(colourBlindnessFunction(lighterColor)), Cursor = new Avalonia.Input.Cursor(Avalonia.Input.StandardCursorType.Hand) }; Avalonia.Controls.Shapes.Path rightPath = new Avalonia.Controls.Shapes.Path() { Data = rightHexagon, Fill = new ColorVisualBrush(colourBlindnessFunction(darkerColor)), Cursor = new Avalonia.Input.Cursor(Avalonia.Input.StandardCursorType.Hand) }; Avalonia.Controls.Shapes.Path centerPath = new Avalonia.Controls.Shapes.Path() { Data = centerHexagon, Fill = new ColorVisualBrush(colourBlindnessFunction(color)), Cursor = new Avalonia.Input.Cursor(Avalonia.Input.StandardCursorType.Hand) }; if (!ColorPicker.TransitionsDisabled) { leftPath.Transitions = new Transitions { new ThicknessTransition() { Property = Avalonia.Controls.Shapes.Path.MarginProperty, Duration = new TimeSpan(0, 0, 0, 0, 100) } }; rightPath.Transitions = new Transitions { new ThicknessTransition() { Property = Avalonia.Controls.Shapes.Path.MarginProperty, Duration = new TimeSpan(0, 0, 0, 0, 100) } }; } leftPath.Classes.Add("HexagonLeftPalette"); rightPath.Classes.Add("HexagonRightPalette"); centerPath.Classes.Add("HexagonCenter"); rightPath.PointerEnter += (s, e) => { rightPath.ZIndex = 10; centerPath.ZIndex = 10; }; rightPath.PointerLeave += async(s, e) => { await Task.Delay(100); rightPath.ZIndex = 0; centerPath.ZIndex = 0; }; leftPath.PointerPressed += (s, e) => { owner.ColorSelected?.Invoke(owner, new ColorSelectedEventArgs(lighterColor)); }; rightPath.PointerPressed += (s, e) => { owner.ColorSelected?.Invoke(owner, new ColorSelectedEventArgs(darkerColor)); }; centerPath.PointerPressed += (s, e) => { owner.ColorSelected?.Invoke(owner, new ColorSelectedEventArgs(color)); }; Point p1, p2, p3, p4; if (i % 2 == 0) { p1 = new Point(centerX + HexagonRadius * Math.Cos(Math.PI * 2 / 3) - HexagonRadius * 0.5, centerY + HexagonRadius * Math.Sin(Math.PI * 2 / 3)); p2 = new Point(centerX + HexagonRadius * Math.Cos(Math.PI * 1 / 3) + HexagonRadius * 0.5, centerY + HexagonRadius * Math.Sin(Math.PI * 1 / 3)); p3 = p2 + new Point(-Math.Cos(Math.PI / 3), Math.Sin(Math.PI / 3)) * HexagonRadius * 0.6; p4 = p1 + new Point(Math.Cos(Math.PI / 3), Math.Sin(Math.PI / 3)) * HexagonRadius * 0.6; } else { p1 = new Point(centerX + HexagonRadius * Math.Cos(Math.PI * 4 / 3) - HexagonRadius * 0.5, centerY + HexagonRadius * Math.Sin(Math.PI * 4 / 3)); p2 = new Point(centerX + HexagonRadius * Math.Cos(Math.PI * 5 / 3) + HexagonRadius * 0.5, centerY + HexagonRadius * Math.Sin(Math.PI * 5 / 3)); p3 = p2 + new Point(-Math.Cos(Math.PI / 3), -Math.Sin(Math.PI / 3)) * HexagonRadius * 0.6; p4 = p1 + new Point(Math.Cos(Math.PI / 3), -Math.Sin(Math.PI / 3)) * HexagonRadius * 0.6; } AnimatablePath4Points deleteBG = new AnimatablePath4Points(p1, p2, p2, p1); AnimatableColorBrush bgFill = new AnimatableColorBrush(Color.FromRgb(180, 180, 180), col => deleteBG.Path.Fill = new SolidColorBrush(col)); deleteBG.Path.Cursor = new Avalonia.Input.Cursor(Avalonia.Input.StandardCursorType.Hand); PathGeometry deleteGeometry = new PathGeometry(); PathFigure seg1 = new PathFigure() { StartPoint = new Point(centerX - HexagonRadius * 0.15, centerY - HexagonRadius * 0.15), IsClosed = false }; seg1.Segments.Add(new LineSegment() { Point = seg1.StartPoint + new Point(HexagonRadius * 0.3, HexagonRadius * 0.3) }); PathFigure seg2 = new PathFigure() { StartPoint = new Point(centerX + HexagonRadius * 0.15, centerY - HexagonRadius * 0.15), IsClosed = false }; seg2.Segments.Add(new LineSegment() { Point = seg2.StartPoint + new Point(-HexagonRadius * 0.3, HexagonRadius * 0.3) }); deleteGeometry.Figures.Add(seg1); deleteGeometry.Figures.Add(seg2); RelativePoint renderTransformOrigin = new RelativePoint(centerX, centerY, RelativeUnit.Absolute); leftPath.RenderTransform = transform.MatrixTransform; leftPath.RenderTransformOrigin = renderTransformOrigin; rightPath.RenderTransform = transform.MatrixTransform; rightPath.RenderTransformOrigin = renderTransformOrigin; centerPath.RenderTransform = transform.MatrixTransform; centerPath.RenderTransformOrigin = renderTransformOrigin; deleteBG.Path.RenderTransform = transform.MatrixTransform; deleteBG.Path.RenderTransformOrigin = renderTransformOrigin; AnimatableTransform fgTransform = new AnimatableTransform(new Matrix(1, 0, 0, 1, 0, (info.Index % 2 == 0 ? 1 : -1) * HexagonRadius * Math.Sin(Math.PI / 3) * 0.7)); TransformGroup fgTransforms = new TransformGroup(); fgTransforms.Children.Add(transform.MatrixTransform); fgTransforms.Children.Add(fgTransform.MatrixTransform); Avalonia.Controls.Shapes.Path deleteFG = new Avalonia.Controls.Shapes.Path() { Data = deleteGeometry, StrokeThickness = HexagonRadius * 0.1, IsHitTestVisible = false, RenderTransform = fgTransforms, RenderTransformOrigin = renderTransformOrigin }; info.DeleteBGPath = deleteBG; info.DeleteFBTransform = fgTransform; AnimatableColorBrush fgStroke = new AnimatableColorBrush(Color.FromRgb(255, 255, 255), col => deleteFG.Stroke = new SolidColorBrush(col)); deleteBG.Path.PointerEnter += (s, e) => { bgFill.Update(Color.FromRgb(240, 240, 240), false); fgStroke.Update(Color.FromRgb(128, 128, 128), false); }; deleteBG.Path.PointerLeave += (s, e) => { bgFill.Update(Color.FromRgb(180, 180, 180), false); fgStroke.Update(Colors.White, false); }; container.Children.Add(deleteBG.Path); container.Children.Add(deleteFG); bool deleteVisible = false; centerPath.PointerEnter += async(s, e) => { if (!deleteVisible) { double _centerX = (1.5 + 2.5 * info.OriginalIndex) * HexagonRadius + 6.93; double _centerY = HexagonRadius * Math.Cos(Math.PI / 6) * (info.OriginalIndex % 2 == 0 ? 1 : 2); Point _p1, _p2, _p3, _p4; if (info.Index % 2 == 0) { _p1 = new Point(_centerX + HexagonRadius * Math.Cos(Math.PI * 2 / 3) - HexagonRadius * 0.5, _centerY + HexagonRadius * Math.Sin(Math.PI * 2 / 3)); _p2 = new Point(_centerX + HexagonRadius * Math.Cos(Math.PI * 1 / 3) + HexagonRadius * 0.5, _centerY + HexagonRadius * Math.Sin(Math.PI * 1 / 3)); _p3 = _p2 + new Point(-Math.Cos(Math.PI / 3), Math.Sin(Math.PI / 3)) * HexagonRadius * 0.6; _p4 = _p1 + new Point(Math.Cos(Math.PI / 3), Math.Sin(Math.PI / 3)) * HexagonRadius * 0.6; } else { _p1 = new Point(_centerX + HexagonRadius * Math.Cos(Math.PI * 4 / 3) - HexagonRadius * 0.5, _centerY + HexagonRadius * Math.Sin(Math.PI * 4 / 3)); _p2 = new Point(_centerX + HexagonRadius * Math.Cos(Math.PI * 5 / 3) + HexagonRadius * 0.5, _centerY + HexagonRadius * Math.Sin(Math.PI * 5 / 3)); _p3 = _p2 + new Point(-Math.Cos(Math.PI / 3), -Math.Sin(Math.PI / 3)) * HexagonRadius * 0.6; _p4 = _p1 + new Point(Math.Cos(Math.PI / 3), -Math.Sin(Math.PI / 3)) * HexagonRadius * 0.6; } deleteVisible = true; deleteBG.Points = new PointCollection4(_p1, _p2, _p3, _p4); fgTransform.Matrix = new Matrix(1, 0, 0, 1, 0, (info.Index % 2 == 0 ? 1 : -1) * HexagonRadius * Math.Sin(Math.PI / 3) * 1.3); await Task.Delay(100); deleteBG.Path.ZIndex = 11; deleteFG.ZIndex = 11; await Task.Delay(1000); deleteBG.Path.ZIndex = 0; deleteFG.ZIndex = 0; fgTransform.Matrix = new Matrix(1, 0, 0, 1, 0, (info.Index % 2 == 0 ? 1 : -1) * HexagonRadius * Math.Sin(Math.PI / 3) * 0.7); deleteBG.Points = new PointCollection4(_p1, _p2, _p2, _p1); deleteVisible = false; } }; container.Children.Add(leftPath); container.Children.Add(rightPath); container.Children.Add(centerPath); deleteBG.Path.PointerPressed += async(s, e) => { transform.Matrix = new Matrix(0, 0, 0, 0, transform.Matrix.M31, transform.Matrix.M32); for (int j = info.Index + 1; j < infos.Count; j++) { infos[j].Transform.Matrix = new Matrix(1, 0, 0, 1, infos[j].Transform.Matrix.M31 - HexagonRadius * 2.5, infos[j].Transform.Matrix.M32 + HexagonRadius * Math.Sin(Math.PI / 3) * (j % 2 == 0 ? 1 : -1)); infos[j].Index--; if (infos[j].DeleteBGPath != null) { double _centerX = (1.5 + 2.5 * infos[j].OriginalIndex) * HexagonRadius + 6.93; double _centerY = HexagonRadius * Math.Cos(Math.PI / 6) * (infos[j].OriginalIndex % 2 == 0 ? 1 : 2); Point _p1, _p2; if (infos[j].Index % 2 == 0) { _p1 = new Point(_centerX + HexagonRadius * Math.Cos(Math.PI * 2 / 3) - HexagonRadius * 0.5, _centerY + HexagonRadius * Math.Sin(Math.PI * 2 / 3)); _p2 = new Point(_centerX + HexagonRadius * Math.Cos(Math.PI * 1 / 3) + HexagonRadius * 0.5, _centerY + HexagonRadius * Math.Sin(Math.PI * 1 / 3)); } else { _p1 = new Point(_centerX + HexagonRadius * Math.Cos(Math.PI * 4 / 3) - HexagonRadius * 0.5, _centerY + HexagonRadius * Math.Sin(Math.PI * 4 / 3)); _p2 = new Point(_centerX + HexagonRadius * Math.Cos(Math.PI * 5 / 3) + HexagonRadius * 0.5, _centerY + HexagonRadius * Math.Sin(Math.PI * 5 / 3)); } infos[j].DeleteBGPath.Points = new PointCollection4(_p1, _p2, _p2, _p1); infos[j].DeleteFBTransform.Matrix = new Matrix(1, 0, 0, 1, 0, -infos[j].DeleteFBTransform.Matrix.M32); } } await Task.Delay(100); container.Width -= HexagonRadius * 2.5; infos.RemoveAt(info.Index); palette.Colors.RemoveAt(info.Index); container.Children.Remove(leftPath); container.Children.Remove(rightPath); container.Children.Remove(centerPath); container.Children.Remove(deleteBG.Path); container.Children.Remove(deleteFG); }; }
private Canvas BuildPaletteCanvas(Palette palette) { int n = palette.Colors.Count + 1; Canvas tbr = new Canvas() { Height = HexagonRadius * Math.Cos(Math.PI / 6) * 3, Width = HexagonRadius * (3 + 2.5 * (n - 1)) + 13.86, Margin = new Thickness(0, 0, 0, 5) }; if (!ColorPicker.TransitionsDisabled) { tbr.Transitions = new Transitions { new DoubleTransition() { Property = Canvas.WidthProperty, Duration = new TimeSpan(0, 0, 0, 0, 100) } }; } List <PaletteColorInfo> infos = new List <PaletteColorInfo>(); for (int i = 0; i < n - 1; i++) { AddColorHexagon(i, palette, tbr, this, infos, this.ColourBlindnessFunction); } { int i = n - 1; double centerX = (1.5 + 2.5 * i) * HexagonRadius + 6.93; double centerY = HexagonRadius * Math.Cos(Math.PI / 6) * (i % 2 == 0 ? 1 : 2); PathGeometry leftHexagon = GetHexagonPath(new Point(centerX - 0.5 * HexagonRadius, centerY), HexagonRadius); PathGeometry centerHexagon = GetHexagonPath(new Point(centerX, centerY), HexagonRadius); PathGeometry rightHexagon = GetHexagonPath(new Point(centerX + 0.5 * HexagonRadius, centerY), HexagonRadius); Avalonia.Controls.Shapes.Path leftPath = new Avalonia.Controls.Shapes.Path() { Data = leftHexagon, ZIndex = 2 }; Avalonia.Controls.Shapes.Path rightPath = new Avalonia.Controls.Shapes.Path() { Data = rightHexagon, ZIndex = 2 }; Avalonia.Controls.Shapes.Path centerPath = new Avalonia.Controls.Shapes.Path() { Data = centerHexagon, Cursor = new Avalonia.Input.Cursor(Avalonia.Input.StandardCursorType.Hand), ZIndex = 2 }; AnimatableColorBrush leftFill = new AnimatableColorBrush(Color.FromRgb(240, 240, 240), col => leftPath.Fill = new SolidColorBrush(col)); AnimatableColorBrush rightFill = new AnimatableColorBrush(Color.FromRgb(240, 240, 240), col => rightPath.Fill = new SolidColorBrush(col)); AnimatableColorBrush centerFill = new AnimatableColorBrush(Color.FromRgb(200, 200, 200), col => centerPath.Fill = new SolidColorBrush(col)); tbr.Children.Add(leftPath); tbr.Children.Add(rightPath); tbr.Children.Add(centerPath); PathGeometry plusGeometry = new PathGeometry(); PathFigure verticalPlusFigure = new PathFigure() { StartPoint = new Point(centerX, centerY - HexagonRadius * 0.5), IsClosed = false }; verticalPlusFigure.Segments.Add(new LineSegment() { Point = new Point(centerX, centerY + HexagonRadius * 0.5) }); PathFigure horizontalPlusFigure = new PathFigure() { StartPoint = new Point(centerX - HexagonRadius * 0.5, centerY), IsClosed = false }; horizontalPlusFigure.Segments.Add(new LineSegment() { Point = new Point(centerX + HexagonRadius * 0.5, centerY) }); plusGeometry.Figures.Add(verticalPlusFigure); plusGeometry.Figures.Add(horizontalPlusFigure); Avalonia.Controls.Shapes.Path plusPath = new Avalonia.Controls.Shapes.Path() { Data = plusGeometry, StrokeThickness = HexagonRadius * 0.2, IsHitTestVisible = false, ZIndex = 2 }; AnimatableColorBrush plusStroke = new AnimatableColorBrush(Colors.White, col => plusPath.Stroke = new SolidColorBrush(col)); tbr.Children.Add(plusPath); AnimatableTransform transform = new AnimatableTransform(new Matrix(1, 0, 0, 1, 0, 0)); leftPath.RenderTransform = transform.MatrixTransform; rightPath.RenderTransform = transform.MatrixTransform; centerPath.RenderTransform = transform.MatrixTransform; plusPath.RenderTransform = transform.MatrixTransform; bool disabled = false; centerPath.PointerEnter += (s, e) => { if (!disabled) { leftFill.Update(Color.FromRgb(180, 180, 180), false); rightFill.Update(Color.FromRgb(180, 180, 180), false); centerFill.Update(Color.FromRgb(240, 240, 240), false); plusStroke.Update(Color.FromRgb(180, 180, 180), false); } }; centerPath.PointerLeave += (s, e) => { if (!disabled) { leftFill.Update(Color.FromRgb(240, 240, 240), false); rightFill.Update(Color.FromRgb(240, 240, 240), false); centerFill.Update(Color.FromRgb(200, 200, 200), false); plusStroke.Update(Colors.White, false); } }; centerPath.PointerPressed += async(s, e) => { disabled = true; Color col = this.Owner.Color; leftFill.Update(ColorPicker.GetLighterColor(col), false); rightFill.Update(ColorPicker.GetDarkerColor(col), false); centerFill.Update(col, false); plusStroke.Update(Color.FromArgb(0, 255, 255, 255), false); await Task.Delay(100); leftPath.ZIndex = -1; centerPath.ZIndex = -1; rightPath.ZIndex = -1; plusPath.ZIndex = -1; palette.Colors.Add(col); AddColorHexagon(palette.Colors.Count - 1, palette, tbr, this, infos, this.ColourBlindnessFunction); leftFill.Update(Color.FromRgb(240, 240, 240), false); rightFill.Update(Color.FromRgb(240, 240, 240), false); centerFill.Update(Color.FromRgb(200, 200, 200), false); plusStroke.Update(Colors.White, false); tbr.Width += HexagonRadius * 2.5; double deltaX = HexagonRadius * 2.5; double deltaY = HexagonRadius * Math.Sin(Math.PI / 3) * (palette.Colors.Count % 2 == 0 ? -1 : 1); transform.Matrix = new Matrix(1, 0, 0, 1, transform.Matrix.M31 + deltaX, transform.Matrix.M32 + deltaY); await Task.Delay(100); leftPath.ZIndex = 2; centerPath.ZIndex = 2; rightPath.ZIndex = 2; plusPath.ZIndex = 2; disabled = false; }; infos.Add(new PaletteColorInfo() { Index = -1, Transform = transform }); } return(tbr); }
public BCanvas(byte R, byte G, byte B, Bitmap colourBitmap) : base() { (double _, double S, double V) = HSB.RGBToHSB(R / 255.0, G / 255.0, B / 255.0); this.Width = 128; this.Height = 96; Point v1 = new Point(51.673, 0); Point v2 = new Point(104, 15.955); Point v3 = new Point(76.327, 46.125); Point v4 = new Point(24, 30.170); Point v5 = new Point(51.673, 49.875); Point v6 = new Point(104, 65.830); Point v7 = new Point(76.327, 96); Point v8 = new Point(24, 80.045); Point v15 = v1 * (B / 255.0) + v5 * (1 - B / 255.0); Point v26 = v2 * (B / 255.0) + v6 * (1 - B / 255.0); Point v37 = v3 * (B / 255.0) + v7 * (1 - B / 255.0); Point v48 = v4 * (B / 255.0) + v8 * (1 - B / 255.0); Fill1 = new AnimatablePath4Points(v48, v8, v7, v37) { Fill = RGB.MiddleCubeBrush }; this.Children.Add(Fill1.Path); Fill2 = new AnimatablePath4Points(v37, v7, v6, v26) { Fill = RGB.DarkCubeBrush }; this.Children.Add(Fill2.Path); ColourCanvas = new Canvas() { Width = 256, Height = 256, ClipToBounds = false }; ColourImage = new Image() { Source = colourBitmap }; ColourCanvas.Children.Add(ColourImage); PathGeometry border2Geometry = new PathGeometry(); PathFigure border2Figure = new PathFigure() { StartPoint = new Point(0, 256), IsClosed = false }; border2Figure.Segments.Add(new LineSegment() { Point = new Point(256, 256) }); border2Geometry.Figures.Add(border2Figure); ColourCanvas.Children.Add(new Path() { Data = border2Geometry, StrokeThickness = 4, Stroke = RGB.MiddleCubeBrush }); PathGeometry border3Geometry = new PathGeometry(); PathFigure border3Figure = new PathFigure() { StartPoint = new Point(256, 256), IsClosed = false }; border3Figure.Segments.Add(new LineSegment() { Point = new Point(256, 0) }); border3Geometry.Figures.Add(border3Figure); ColourCanvas.Children.Add(new Path() { Data = border3Geometry, StrokeThickness = 4, Stroke = RGB.DarkCubeBrush }); PositionEllipse = new Ellipse() { Width = 48, Height = 48, Fill = (S <0.5 && V> 0.5 ? Brushes.Black : Brushes.White) }; PositionEllipse.RenderTransform = ColorPicker.GetTranslateTransform(G - 24, R - 24); ColourCanvas.Children.Add(PositionEllipse); double m11 = (v26.X - v15.X) / 256; double m12 = (v37.X - v26.X) / 256; double m21 = (v26.Y - v15.Y) / 256; double m22 = (v37.Y - v26.Y) / 256; ColourCanvasTransform = new AnimatableTransform(new Matrix(m11, m21, m12, m22, v15.X, v15.Y)); ColourCanvas.RenderTransform = ColourCanvasTransform.MatrixTransform; ColourCanvas.RenderTransformOrigin = new RelativePoint(0, 0, RelativeUnit.Absolute); this.Children.Add(ColourCanvas); }