From 949a6715c7f2d3b375f2ea4e79116beace7d20af Mon Sep 17 00:00:00 2001 From: Jason Steele Date: Tue, 7 Sep 2021 19:15:22 +0100 Subject: [PATCH 01/23] Fixed PercentageProfile --- Winleafs.Wpf/Views/Layout/PercentageProfileWindow.xaml | 5 +++-- Winleafs.Wpf/Views/Layout/PercentageProfileWindow.xaml.cs | 5 +++-- Winleafs.Wpf/Views/MainWindows/MainWindow.xaml | 8 +++++++- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/Winleafs.Wpf/Views/Layout/PercentageProfileWindow.xaml b/Winleafs.Wpf/Views/Layout/PercentageProfileWindow.xaml index ee9ab1a0..b4b1a1c2 100644 --- a/Winleafs.Wpf/Views/Layout/PercentageProfileWindow.xaml +++ b/Winleafs.Wpf/Views/Layout/PercentageProfileWindow.xaml @@ -4,14 +4,15 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:Winleafs.Wpf.Views.Layout" + xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" mc:Ignorable="d" Title="{x:Static local:Resources.PercentageProfileWindow}" Height="828" Width="1020" ResizeMode="CanMinimize"> + diff --git a/Winleafs.Wpf/Views/Layout/FrameUserControl.xaml.cs b/Winleafs.Wpf/Views/Layout/FrameUserControl.xaml.cs new file mode 100644 index 00000000..3af009b3 --- /dev/null +++ b/Winleafs.Wpf/Views/Layout/FrameUserControl.xaml.cs @@ -0,0 +1,42 @@ +using System.Windows.Controls; +using Winleafs.Models.Models.Layouts; + +namespace Winleafs.Wpf.Views.Layout +{ + /// + /// Interaction logic for StepItemUserControl.xaml + /// + public partial class FrameUserControl : UserControl + { + public string Description { get; set; } + + private CreateEffectWindow _parent; + private PercentageStep _percentageStep; + + public FrameUserControl(CreateEffectWindow parent, int stepNumber, PercentageStep percentageStep) + { + _parent = parent; + _percentageStep = percentageStep; + + Description = $"{Layout.Resources.Frame} {stepNumber}"; + + InitializeComponent(); + DataContext = this; + } + + private void Delete_Click(object sender, System.Windows.RoutedEventArgs e) + { + _parent.DeleteStep(_percentageStep); + } + + private void Grid_MouseEnter(object sender, System.Windows.Input.MouseEventArgs e) + { + _parent.HighlightPanels(_percentageStep.PanelIds); + } + + private void Grid_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e) + { + _parent.UnhighlightPanels(_percentageStep.PanelIds); + } + } +} diff --git a/Winleafs.Wpf/Views/Layout/StepItemUserControl.xaml b/Winleafs.Wpf/Views/Layout/StepItemUserControl.xaml index 01398d4f..b533a5ec 100644 --- a/Winleafs.Wpf/Views/Layout/StepItemUserControl.xaml +++ b/Winleafs.Wpf/Views/Layout/StepItemUserControl.xaml @@ -3,12 +3,13 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" mc:Ignorable="d" d:DesignHeight="40" d:DesignWidth="200"> diff --git a/Winleafs.Wpf/Winleafs.Wpf.csproj b/Winleafs.Wpf/Winleafs.Wpf.csproj index 64cd645a..494a1035 100644 --- a/Winleafs.Wpf/Winleafs.Wpf.csproj +++ b/Winleafs.Wpf/Winleafs.Wpf.csproj @@ -171,5 +171,8 @@ $(DefaultXamlRuntime) + + $(DefaultXamlRuntime) + \ No newline at end of file From f06f6196ad7d69acf3b4e633fc3906a3658e07fa Mon Sep 17 00:00:00 2001 From: Jason Steele Date: Fri, 10 Sep 2021 16:44:35 +0100 Subject: [PATCH 04/23] Add and use the CustomEffect and Frames models --- Winleafs.Models/Models/Device.cs | 2 + .../Models/Layouts/CustomEffect.cs | 25 +++++++++++ Winleafs.Models/Models/Layouts/Frame.cs | 15 +++++++ .../Views/Layout/CreateEffectWindow.xaml.cs | 44 +++++++++---------- .../Views/Layout/FrameUserControl.xaml.cs | 30 ++++++------- .../Layout/LayoutDisplayUserControl.xaml.cs | 23 +++++++--- 6 files changed, 95 insertions(+), 44 deletions(-) create mode 100644 Winleafs.Models/Models/Layouts/CustomEffect.cs create mode 100644 Winleafs.Models/Models/Layouts/Frame.cs diff --git a/Winleafs.Models/Models/Device.cs b/Winleafs.Models/Models/Device.cs index c5c99377..1bdecd46 100644 --- a/Winleafs.Models/Models/Device.cs +++ b/Winleafs.Models/Models/Device.cs @@ -39,6 +39,8 @@ public class Device public PercentageProfile PercentageProfile { get;set;} + public CustomEffect CustomEffect { get; set; } + public ScreenMirrorAlgorithm ScreenMirrorAlgorithm { get; set; } public ScreenMirrorFlip ScreenMirrorFlip { get; set; } diff --git a/Winleafs.Models/Models/Layouts/CustomEffect.cs b/Winleafs.Models/Models/Layouts/CustomEffect.cs new file mode 100644 index 00000000..d3873451 --- /dev/null +++ b/Winleafs.Models/Models/Layouts/CustomEffect.cs @@ -0,0 +1,25 @@ +using System.Collections.Generic; + +namespace Winleafs.Models.Models.Layouts +{ + /// + /// A user created Custom Effect which specifies a static pattern or animation + /// + public class CustomEffect + { + /// + /// True if this is just one Frame to set each panel's color + /// + public bool IsStatic { get; set; } + + /// + /// A series of frames each specifying the color for each panel + /// + public IList Frames { get; set; } + + public CustomEffect() + { + Frames = new List(); + } + } +} diff --git a/Winleafs.Models/Models/Layouts/Frame.cs b/Winleafs.Models/Models/Layouts/Frame.cs new file mode 100644 index 00000000..fcdc1ff0 --- /dev/null +++ b/Winleafs.Models/Models/Layouts/Frame.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; +using System.Drawing; + +namespace Winleafs.Models.Models.Layouts +{ + public class Frame + { + public IDictionary PanelColors { get; set; } + + public Frame() + { + PanelColors = new Dictionary(); + } + } +} diff --git a/Winleafs.Wpf/Views/Layout/CreateEffectWindow.xaml.cs b/Winleafs.Wpf/Views/Layout/CreateEffectWindow.xaml.cs index 491ae708..13ee9a31 100644 --- a/Winleafs.Wpf/Views/Layout/CreateEffectWindow.xaml.cs +++ b/Winleafs.Wpf/Views/Layout/CreateEffectWindow.xaml.cs @@ -1,5 +1,6 @@ using Newtonsoft.Json; using System.Collections.Generic; +using System.Drawing; using System.Windows; using Winleafs.Models.Models; using Winleafs.Models.Models.Layouts; @@ -12,7 +13,7 @@ namespace Winleafs.Wpf.Views.Layout /// public partial class CreateEffectWindow : Window { - private PercentageProfile _profile; + private CustomEffect _customEffect; public CreateEffectWindow() { @@ -23,21 +24,16 @@ public CreateEffectWindow() LayoutDisplay.DrawLayout(); LayoutDisplay.DisableColorTimer(); - if (UserSettings.Settings.ActiveDevice.PercentageProfile != null) + if (UserSettings.Settings.ActiveDevice.CustomEffect != null) { - var serialized = JsonConvert.SerializeObject(UserSettings.Settings.ActiveDevice.PercentageProfile); //Deep copy the profile when editing - _profile = JsonConvert.DeserializeObject(serialized); + var serialized = JsonConvert.SerializeObject(UserSettings.Settings.ActiveDevice.CustomEffect); //Deep copy the custom effect when editing + _customEffect = JsonConvert.DeserializeObject(serialized); - //BuildStepList(); - - foreach (var step in _profile.Steps) - { - LayoutDisplay.LockPanels(step.PanelIds); - } + BuildFrameList(); } else { - _profile = new PercentageProfile(); + _customEffect = new CustomEffect(); } } @@ -48,18 +44,18 @@ private void Plus_Click(object sender, RoutedEventArgs e) return; } - var newStep = new PercentageStep(); + var frame = new Frame(); - foreach (var panelId in LayoutDisplay.SelectedPanelIds) + foreach (var panelId in LayoutDisplay.PanelIds) { - newStep.PanelIds.Add(panelId); + frame.PanelColors.Add(panelId, Color.Black); } - _profile.Steps.Add(newStep); + _customEffect.Frames.Add(frame); BuildFrameList(); - LayoutDisplay.LockPanels(LayoutDisplay.SelectedPanelIds); + //LayoutDisplay.LockPanels(LayoutDisplay.SelectedPanelIds); LayoutDisplay.ClearSelectedPanels(); @@ -69,9 +65,9 @@ private void BuildFrameList() { FrameList.Children.Clear(); - for (var i = 0; i < _profile.Steps.Count; i++) + for (var i = 0; i < _customEffect.Frames.Count; i++) { - FrameList.Children.Add(new FrameUserControl(this, i + 1, _profile.Steps[i])); + FrameList.Children.Add(new FrameUserControl(this, i + 1, _customEffect.Frames[i])); } } @@ -85,12 +81,12 @@ public void UnhighlightPanels(HashSet panelIds) LayoutDisplay.UnhighlightPanels(panelIds); } - public void DeleteStep(PercentageStep step) + public void DeleteFrame(Frame frame) { - LayoutDisplay.UnlockPanels(step.PanelIds); + //LayoutDisplay.UnlockPanels(step.PanelIds); - _profile.Steps.Remove(step); - //BuildStepList(); + _customEffect.Frames.Remove(frame); + BuildFrameList(); } private void Cancel_Click(object sender, RoutedEventArgs e) @@ -100,9 +96,9 @@ private void Cancel_Click(object sender, RoutedEventArgs e) private void Add_Click(object sender, RoutedEventArgs e) { - if (_profile.Steps.Count > 0) + if (_customEffect.Frames.Count > 0) { - UserSettings.Settings.ActiveDevice.PercentageProfile = _profile; + UserSettings.Settings.ActiveDevice.CustomEffect = _customEffect; UserSettings.Settings.SaveSettings(); Close(); diff --git a/Winleafs.Wpf/Views/Layout/FrameUserControl.xaml.cs b/Winleafs.Wpf/Views/Layout/FrameUserControl.xaml.cs index 3af009b3..c62a9724 100644 --- a/Winleafs.Wpf/Views/Layout/FrameUserControl.xaml.cs +++ b/Winleafs.Wpf/Views/Layout/FrameUserControl.xaml.cs @@ -1,5 +1,5 @@ using System.Windows.Controls; -using Winleafs.Models.Models.Layouts; +using models = Winleafs.Models.Models.Layouts; namespace Winleafs.Wpf.Views.Layout { @@ -11,14 +11,14 @@ public partial class FrameUserControl : UserControl public string Description { get; set; } private CreateEffectWindow _parent; - private PercentageStep _percentageStep; + private models.Frame _frame; - public FrameUserControl(CreateEffectWindow parent, int stepNumber, PercentageStep percentageStep) + public FrameUserControl(CreateEffectWindow parent, int frameNumber, models.Frame frame) { _parent = parent; - _percentageStep = percentageStep; + _frame = frame; - Description = $"{Layout.Resources.Frame} {stepNumber}"; + Description = $"{Layout.Resources.Frame} {frameNumber}"; InitializeComponent(); DataContext = this; @@ -26,17 +26,17 @@ public FrameUserControl(CreateEffectWindow parent, int stepNumber, PercentageSte private void Delete_Click(object sender, System.Windows.RoutedEventArgs e) { - _parent.DeleteStep(_percentageStep); + _parent.DeleteFrame(_frame); } - private void Grid_MouseEnter(object sender, System.Windows.Input.MouseEventArgs e) - { - _parent.HighlightPanels(_percentageStep.PanelIds); - } + private void Grid_MouseEnter(object sender, System.Windows.Input.MouseEventArgs e) + { + //_parent.HighlightPanels(_frame.PanelIds); + } - private void Grid_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e) - { - _parent.UnhighlightPanels(_percentageStep.PanelIds); - } - } + private void Grid_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e) + { + //_parent.UnhighlightPanels(_frame.PanelIds); + } + } } diff --git a/Winleafs.Wpf/Views/Layout/LayoutDisplayUserControl.xaml.cs b/Winleafs.Wpf/Views/Layout/LayoutDisplayUserControl.xaml.cs index c0bdfba0..a9d51282 100644 --- a/Winleafs.Wpf/Views/Layout/LayoutDisplayUserControl.xaml.cs +++ b/Winleafs.Wpf/Views/Layout/LayoutDisplayUserControl.xaml.cs @@ -26,7 +26,8 @@ public partial class LayoutDisplayUserControl : UserControl private static readonly SolidColorBrush _selectedBorderColor = Brushes.LightSteelBlue; private static readonly SolidColorBrush _borderColor = (SolidColorBrush)Application.Current.FindResource("NanoleafBlack"); - public HashSet SelectedPanelIds { get; set; } + public HashSet PanelIds { get; set; } + public HashSet SelectedPanelIds { get; set; } private static readonly Random _random = new Random(); @@ -48,7 +49,8 @@ public LayoutDisplayUserControl() InitializeComponent(); CanvasArea.MouseDown += CanvasClicked; - SelectedPanelIds = new HashSet(); + PanelIds = new HashSet(); + SelectedPanelIds = new HashSet(); _lockedPanelIds = new HashSet(); _highlightOriginalColors = new Dictionary(); @@ -123,6 +125,7 @@ public void DrawLayout(bool resetLayout = false) foreach (var polygon in _polygons) { CanvasArea.Children.Add(polygon.Polygon); + PanelIds.Add(polygon.PanelId); } UpdateColors(); @@ -240,10 +243,20 @@ private void PolygonClicked(object sender, MouseButtonEventArgs e) return; } - polygon.Stroke = _selectedBorderColor; - polygon.StrokeThickness = 2; + if (SelectedPanelIds.Contains(selectedPanelId)) + { + polygon.Stroke = _borderColor; + polygon.StrokeThickness = 2; - SelectedPanelIds.Add(selectedPanelId); + SelectedPanelIds.Remove(selectedPanelId); + } + else + { + polygon.Stroke = _selectedBorderColor; + polygon.StrokeThickness = 2; + + SelectedPanelIds.Add(selectedPanelId); + } } private void CanvasClicked(object sender, MouseButtonEventArgs e) From 7cb2323bc1d6e79c3ff3f4633bbbbe342e0866ab Mon Sep 17 00:00:00 2001 From: Jason Steele Date: Sun, 12 Sep 2021 21:01:51 +0100 Subject: [PATCH 05/23] Added color picker --- .../Views/Layout/CreateEffectWindow.xaml | 34 +++++-- .../Views/Layout/CreateEffectWindow.xaml.cs | 89 ++++++++++++------- .../Views/Layout/FrameUserControl.xaml | 5 +- .../Views/Layout/FrameUserControl.xaml.cs | 13 ++- .../Layout/LayoutDisplayUserControl.xaml.cs | 43 ++++----- .../Views/Layout/Resources.Designer.cs | 9 ++ Winleafs.Wpf/Views/Layout/Resources.resx | 3 + .../Views/Layout/StepItemUserControl.xaml | 4 +- 8 files changed, 130 insertions(+), 70 deletions(-) diff --git a/Winleafs.Wpf/Views/Layout/CreateEffectWindow.xaml b/Winleafs.Wpf/Views/Layout/CreateEffectWindow.xaml index cd0e37b4..2bf3355f 100644 --- a/Winleafs.Wpf/Views/Layout/CreateEffectWindow.xaml +++ b/Winleafs.Wpf/Views/Layout/CreateEffectWindow.xaml @@ -3,19 +3,35 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit" xmlns:local="clr-namespace:Winleafs.Wpf.Views.Layout" xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" mc:Ignorable="d" Title="{x:Static local:Resources.CreateEffectWindow}" Height="828" Width="1020" ResizeMode="CanMinimize"> - diff --git a/Winleafs.Wpf/Views/Layout/FrameUserControl.xaml.cs b/Winleafs.Wpf/Views/Layout/FrameUserControl.xaml.cs index c62a9724..46bb80bb 100644 --- a/Winleafs.Wpf/Views/Layout/FrameUserControl.xaml.cs +++ b/Winleafs.Wpf/Views/Layout/FrameUserControl.xaml.cs @@ -24,10 +24,10 @@ public FrameUserControl(CreateEffectWindow parent, int frameNumber, models.Frame DataContext = this; } - private void Delete_Click(object sender, System.Windows.RoutedEventArgs e) - { - _parent.DeleteFrame(_frame); - } + //private void Delete_Click(object sender, System.Windows.RoutedEventArgs e) + //{ + // _parent.DeleteFrame(_frame); + //} private void Grid_MouseEnter(object sender, System.Windows.Input.MouseEventArgs e) { @@ -38,5 +38,10 @@ private void Grid_MouseLeave(object sender, System.Windows.Input.MouseEventArgs { //_parent.UnhighlightPanels(_frame.PanelIds); } + + private void Grid_MouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e) + { + _parent.FrameSelected(_frame); + } } } diff --git a/Winleafs.Wpf/Views/Layout/LayoutDisplayUserControl.xaml.cs b/Winleafs.Wpf/Views/Layout/LayoutDisplayUserControl.xaml.cs index a9d51282..dadfdab0 100644 --- a/Winleafs.Wpf/Views/Layout/LayoutDisplayUserControl.xaml.cs +++ b/Winleafs.Wpf/Views/Layout/LayoutDisplayUserControl.xaml.cs @@ -28,10 +28,11 @@ public partial class LayoutDisplayUserControl : UserControl public HashSet PanelIds { get; set; } public HashSet SelectedPanelIds { get; set; } + public event EventHandler PanelClicked; - private static readonly Random _random = new Random(); + private static readonly Random _random = new Random(); - private List _polygons; + private List _drawablePanels; private bool _panelsClickable; private HashSet _lockedPanelIds; private Dictionary _highlightOriginalColors; //This dictionary saves the original colors of the triangles when highlighting @@ -106,26 +107,26 @@ public void DrawLayout(bool resetLayout = false) _panelLayout = orchestrator.PanelLayout; } - _polygons = _panelLayout.GetScaledPolygons((int)ActualWidth, (int)ActualHeight, ScaleType.Fit, FlipType.None); + _drawablePanels = _panelLayout.GetScaledPolygons((int)ActualWidth, (int)ActualHeight, ScaleType.Fit, FlipType.None); - if (_polygons == null || !_polygons.Any()) + if (_drawablePanels == null || !_drawablePanels.Any()) { return; } if (_panelsClickable) { - foreach (var polygon in _polygons) + foreach (var drawablePanel in _drawablePanels) { - polygon.Polygon.MouseDown += PolygonClicked; + drawablePanel.Polygon.MouseDown += PolygonClicked; } } //Draw the triangles - foreach (var polygon in _polygons) + foreach (var drawablePanel in _drawablePanels) { - CanvasArea.Children.Add(polygon.Polygon); - PanelIds.Add(polygon.PanelId); + CanvasArea.Children.Add(drawablePanel.Polygon); + PanelIds.Add(drawablePanel.PanelId); } UpdateColors(); @@ -138,7 +139,7 @@ private void Redraw_Click(object sender, RoutedEventArgs e) public void UpdateColors() { - if (UserSettings.Settings.ActiveDevice == null || _polygons == null) + if (UserSettings.Settings.ActiveDevice == null || _drawablePanels == null) { return; } @@ -196,16 +197,16 @@ public void UpdateColors() if (colors == null) { - foreach (var polygon in _polygons) + foreach (var drawablePanel in _drawablePanels) { - polygon.Polygon.Fill = Brushes.LightSlateGray; + drawablePanel.Polygon.Fill = Brushes.LightSlateGray; } } else { - foreach (var polygon in _polygons) + foreach (var drawablePanel in _drawablePanels) { - polygon.Polygon.Fill = colors[_random.Next(colors.Count)]; + drawablePanel.Polygon.Fill = colors[_random.Next(colors.Count)]; } } })); @@ -218,7 +219,7 @@ private void OnTimedEvent(object source, ElapsedEventArgs e) private void PolygonClicked(object sender, MouseButtonEventArgs e) { - if (_polygons == null) + if (_drawablePanels == null) { return; } @@ -229,7 +230,7 @@ private void PolygonClicked(object sender, MouseButtonEventArgs e) } var polygon = (Polygon)sender; - var selectedPanel = _polygons.FirstOrDefault(t => t.Polygon == polygon); + var selectedPanel = _drawablePanels.FirstOrDefault(t => t.Polygon == polygon); if (selectedPanel == null) { @@ -275,7 +276,7 @@ public void ClearSelectedPanels() { SelectedPanelIds.Clear(); - foreach (var polygon in _polygons) + foreach (var polygon in _drawablePanels) { if (!_lockedPanelIds.Contains(polygon.PanelId)) { @@ -289,7 +290,7 @@ public void LockPanels(HashSet panelIds) { foreach (var panelId in panelIds) { - var polygon = _polygons.FirstOrDefault(t => t.PanelId == panelId).Polygon; + var polygon = _drawablePanels.FirstOrDefault(t => t.PanelId == panelId).Polygon; polygon.Stroke = _lockedBorderColor; polygon.StrokeThickness = 2; @@ -302,7 +303,7 @@ public void UnlockPanels(HashSet panelIds) { foreach (var panelId in panelIds) { - var polygon = _polygons.FirstOrDefault(t => t.PanelId == panelId).Polygon; + var polygon = _drawablePanels.FirstOrDefault(t => t.PanelId == panelId).Polygon; polygon.Stroke = _borderColor; polygon.StrokeThickness = 2; @@ -315,7 +316,7 @@ public void HighlightPanels(HashSet panelIds) { foreach (var panelId in panelIds) { - var polygon = _polygons.FirstOrDefault(t => t.PanelId == panelId).Polygon; + var polygon = _drawablePanels.FirstOrDefault(t => t.PanelId == panelId).Polygon; _highlightOriginalColors.Add(panelId, polygon.Fill); @@ -327,7 +328,7 @@ public void UnhighlightPanels(HashSet panelIds) { foreach (var panelId in panelIds) { - var polygon = _polygons.FirstOrDefault(t => t.PanelId == panelId).Polygon; + var polygon = _drawablePanels.FirstOrDefault(t => t.PanelId == panelId).Polygon; polygon.Fill = _highlightOriginalColors[panelId]; diff --git a/Winleafs.Wpf/Views/Layout/Resources.Designer.cs b/Winleafs.Wpf/Views/Layout/Resources.Designer.cs index a73c6c3e..fba0637d 100644 --- a/Winleafs.Wpf/Views/Layout/Resources.Designer.cs +++ b/Winleafs.Wpf/Views/Layout/Resources.Designer.cs @@ -78,6 +78,15 @@ public static string Cancel { } } + /// + /// Looks up a localized string similar to Colors Used. + /// + public static string ColorsUsed { + get { + return ResourceManager.GetString("ColorsUsed", resourceCulture); + } + } + /// /// Looks up a localized string similar to Create effect. /// diff --git a/Winleafs.Wpf/Views/Layout/Resources.resx b/Winleafs.Wpf/Views/Layout/Resources.resx index 239b553b..0715777e 100644 --- a/Winleafs.Wpf/Views/Layout/Resources.resx +++ b/Winleafs.Wpf/Views/Layout/Resources.resx @@ -123,6 +123,9 @@ Cancel + + Colors Used + Create effect diff --git a/Winleafs.Wpf/Views/Layout/StepItemUserControl.xaml b/Winleafs.Wpf/Views/Layout/StepItemUserControl.xaml index b533a5ec..0804d00e 100644 --- a/Winleafs.Wpf/Views/Layout/StepItemUserControl.xaml +++ b/Winleafs.Wpf/Views/Layout/StepItemUserControl.xaml @@ -8,8 +8,8 @@ d:DesignHeight="40" d:DesignWidth="200"> From 32cd0864149f4f280d654f38bb16e633920e41fc Mon Sep 17 00:00:00 2001 From: Jason Steele Date: Mon, 13 Sep 2021 06:43:41 +0100 Subject: [PATCH 06/23] Build the pallete of used colors --- .../Views/Layout/CreateEffectWindow.xaml.cs | 25 ++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/Winleafs.Wpf/Views/Layout/CreateEffectWindow.xaml.cs b/Winleafs.Wpf/Views/Layout/CreateEffectWindow.xaml.cs index 0b9d5083..b3303e7f 100644 --- a/Winleafs.Wpf/Views/Layout/CreateEffectWindow.xaml.cs +++ b/Winleafs.Wpf/Views/Layout/CreateEffectWindow.xaml.cs @@ -19,6 +19,7 @@ public partial class CreateEffectWindow : Window private Frame _currentFrame; private Color _currentColor = Colors.White; private SolidColorBrush _currentBrush; + private Dictionary _pallete; public CreateEffectWindow() { @@ -36,14 +37,16 @@ public CreateEffectWindow() var serialized = JsonConvert.SerializeObject(UserSettings.Settings.ActiveDevice.CustomEffect); //Deep copy the custom effect when editing _customEffect = JsonConvert.DeserializeObject(serialized); - BuildFrameList(); - BuildPallete(); } else { _customEffect = new CustomEffect(); + _customEffect.Frames.Add(new Frame()); } - } + + BuildFrameList(); + BuildPallete(); + } private void LayoutDisplay_PanelClicked(object sender, System.EventArgs e) { @@ -101,13 +104,29 @@ private void BuildFrameList() { FrameList.Children.Add(new FrameUserControl(this, i + 1, _customEffect.Frames[i])); } + + _currentFrame = _customEffect.Frames.Last(); } private void BuildPallete() { var colorsUsed = _customEffect.Frames.SelectMany(f => f.PanelColors.Values).OrderBy(c => c.GetHue()).Distinct(); + ColorPicker.StandardColors.Clear(); + _pallete = new Dictionary(); + + foreach (var color in colorsUsed) + { + var mediaColor = Color.FromArgb(color.A, color.R, color.G, color.B); + ColorPicker.StandardColors.Add(new Xceed.Wpf.Toolkit.ColorItem(mediaColor, string.Empty)); + _pallete.Add(color.ToArgb(), new SolidColorBrush(mediaColor)); + } + } + private void AddColorToPallete(Color color) + { + ColorPicker.StandardColors.Add(new Xceed.Wpf.Toolkit.ColorItem(color, string.Empty)); + //_pallete.Add(color., new SolidColorBrush(mediaColor)); } //public void DeleteFrame(Frame frame) From 4ad44743a3e07f5856541dc80ba54ea45aece133 Mon Sep 17 00:00:00 2001 From: Jason Steele Date: Mon, 13 Sep 2021 16:43:07 +0100 Subject: [PATCH 07/23] Created panel to Brush mapping and passed it to the panel layout Also started to use a unit for rgb rather than System.Drawing.Color as more efficent and better serialisation --- Winleafs.Models/Models/Layouts/Frame.cs | 5 +- Winleafs.Wpf/Helpers/MediaColorConverter.cs | 31 ++++++ .../Views/Layout/CreateEffectWindow.xaml.cs | 97 +++++++++++++------ .../Layout/LayoutDisplayUserControl.xaml.cs | 72 +++++++++----- 4 files changed, 152 insertions(+), 53 deletions(-) create mode 100644 Winleafs.Wpf/Helpers/MediaColorConverter.cs diff --git a/Winleafs.Models/Models/Layouts/Frame.cs b/Winleafs.Models/Models/Layouts/Frame.cs index fcdc1ff0..e574cc1f 100644 --- a/Winleafs.Models/Models/Layouts/Frame.cs +++ b/Winleafs.Models/Models/Layouts/Frame.cs @@ -1,15 +1,14 @@ using System.Collections.Generic; -using System.Drawing; namespace Winleafs.Models.Models.Layouts { public class Frame { - public IDictionary PanelColors { get; set; } + public IDictionary PanelColors { get; set; } public Frame() { - PanelColors = new Dictionary(); + PanelColors = new Dictionary(); } } } diff --git a/Winleafs.Wpf/Helpers/MediaColorConverter.cs b/Winleafs.Wpf/Helpers/MediaColorConverter.cs new file mode 100644 index 00000000..cec8ed17 --- /dev/null +++ b/Winleafs.Wpf/Helpers/MediaColorConverter.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Media; + +namespace Winleafs.Wpf.Helpers +{ + public static class MediaColorConverter + { + public static uint ToRgb(Color color) + { + var rgb = (uint)(color.R << 16); + rgb += (uint)(color.G << 8); + rgb += (uint)color.B; + + return rgb; + } + + public static Color FromRgb(uint argb) + { + var b = (byte)(argb & 255); + var g = (byte)((argb >> 8) & 255); + var r = (byte)((argb >> 16) & 255); + + return Color.FromArgb(255, r, g, b); + } + + } +} diff --git a/Winleafs.Wpf/Views/Layout/CreateEffectWindow.xaml.cs b/Winleafs.Wpf/Views/Layout/CreateEffectWindow.xaml.cs index b3303e7f..f01636e0 100644 --- a/Winleafs.Wpf/Views/Layout/CreateEffectWindow.xaml.cs +++ b/Winleafs.Wpf/Views/Layout/CreateEffectWindow.xaml.cs @@ -6,6 +6,7 @@ using Winleafs.Models.Models; using Winleafs.Models.Models.Layouts; using Winleafs.Wpf.Api.Layouts; +using Winleafs.Wpf.Helpers; using Winleafs.Wpf.Views.Popup; namespace Winleafs.Wpf.Views.Layout @@ -17,9 +18,9 @@ public partial class CreateEffectWindow : Window { private CustomEffect _customEffect; private Frame _currentFrame; - private Color _currentColor = Colors.White; - private SolidColorBrush _currentBrush; - private Dictionary _pallete; + //private Color _currentColor = Colors.White; + //private SolidColorBrush _currentBrush; + private Dictionary _pallete; public CreateEffectWindow() { @@ -29,8 +30,9 @@ public CreateEffectWindow() LayoutDisplay.InitializeResizeTimer(); LayoutDisplay.DrawLayout(); LayoutDisplay.DisableColorTimer(); + LayoutDisplay.MultiSelectEnabled = false; LayoutDisplay.PanelClicked += LayoutDisplay_PanelClicked; - ColorPicker.SelectedColor = _currentColor; + ColorPicker.SelectedColor = Colors.White; if (UserSettings.Settings.ActiveDevice.CustomEffect != null) { @@ -42,10 +44,45 @@ public CreateEffectWindow() { _customEffect = new CustomEffect(); _customEffect.Frames.Add(new Frame()); - } + } BuildFrameList(); BuildPallete(); + + FrameSelected(_customEffect.Frames[0]); + } + + //private void ColorPicker_SelectedColorChanged(object sender, RoutedPropertyChangedEventArgs e) + //{ + // if (e.NewValue != null) + // { + // _currentColor = e.NewValue.Value; + + // //Try to find a brush for the selecyted color + // var argb = MediaColorConverter.ToInt(_currentColor); + + // if (!_pallete.TryGetValue(argb, out var brush)) + // { + // brush = new SolidColorBrush(_currentColor); + // } + // _currentBrush = brush; + // } + //} + + public void FrameSelected(Frame frame) + { + //TODO Consider whether the pallette to be added will have a collection of Brushes that will + //enable building a separate dictiobnary of panelId->Brush + _currentFrame = frame; + + var panelToBrushMap = new Dictionary(); + + foreach (var panel in _currentFrame.PanelColors) + { + panelToBrushMap.Add(panel.Key, _pallete[panel.Value]); + } + LayoutDisplay.PanelToBrushMap = panelToBrushMap; + LayoutDisplay.UpdateColors(); } private void LayoutDisplay_PanelClicked(object sender, System.EventArgs e) @@ -54,31 +91,37 @@ private void LayoutDisplay_PanelClicked(object sender, System.EventArgs e) if (drawablePanel != null) { - drawablePanel.Polygon.Fill = _currentBrush; + var color = ColorPicker.SelectedColor ?? Colors.Black; + + //Try to find a brush for the selected color + var argb = MediaColorConverter.ToRgb(color); - //Convert from System.Windows.Media to System.Drawing.Color and update the Frame - _currentFrame.PanelColors[drawablePanel.PanelId] = - System.Drawing.Color.FromArgb(_currentColor.A, _currentColor.R, _currentColor.G, _currentColor.B); + if (!_pallete.TryGetValue(argb, out var brush)) + { + brush = new SolidColorBrush(color); + AddColorToPallete(color, brush); + } + + // Color the panel and update the color for the panel on the Frame + drawablePanel.Polygon.Fill = brush; + _currentFrame.PanelColors[drawablePanel.PanelId] = MediaColorConverter.ToRgb(color); } } - public void FrameSelected(Frame frame) + private void Plus_Click(object sender, RoutedEventArgs e) { - //TODO Consider whether the pallette to be added will have a collection of Brushes that will - //enable building a separate dictiobnary of panelId->Brush - _currentFrame = frame; - //LayoutDisplay.UpdateColors(_currentFrame.PanelColors); + AddNewFrame(); } - private void Plus_Click(object sender, RoutedEventArgs e) - { - //Copy the previous frame's panel colors where we can + private void AddNewFrame() + { + // Copy the previous frame's panel colors where we can var prevFrame = _customEffect.Frames.LastOrDefault(); var newFrame = new Frame(); foreach (var panelId in LayoutDisplay.PanelIds) { - var color = System.Drawing.Color.Black; + uint color = 0; if (prevFrame != null && prevFrame.PanelColors.TryGetValue(panelId, out var prevColor)) { color = prevColor; @@ -90,10 +133,8 @@ private void Plus_Click(object sender, RoutedEventArgs e) //Add the frame to the effect and the displayed list _customEffect.Frames.Add(newFrame); FrameList.Children.Add(new FrameUserControl(this, _customEffect.Frames.Count, newFrame)); - //BuildFrameList(); - //LayoutDisplay.ClearSelectedPanels(); - + FrameSelected(newFrame); } private void BuildFrameList() @@ -110,23 +151,23 @@ private void BuildFrameList() private void BuildPallete() { - var colorsUsed = _customEffect.Frames.SelectMany(f => f.PanelColors.Values).OrderBy(c => c.GetHue()).Distinct(); + var colorsUsed = _customEffect.Frames.SelectMany(f => f.PanelColors.Values).Distinct(); ColorPicker.StandardColors.Clear(); - _pallete = new Dictionary(); + _pallete = new Dictionary(); - foreach (var color in colorsUsed) + foreach (var argb in colorsUsed) { - var mediaColor = Color.FromArgb(color.A, color.R, color.G, color.B); + var mediaColor = MediaColorConverter.FromRgb(argb); ColorPicker.StandardColors.Add(new Xceed.Wpf.Toolkit.ColorItem(mediaColor, string.Empty)); - _pallete.Add(color.ToArgb(), new SolidColorBrush(mediaColor)); + _pallete.Add(argb, new SolidColorBrush(mediaColor)); } } - private void AddColorToPallete(Color color) + private void AddColorToPallete(Color color, SolidColorBrush brush) { ColorPicker.StandardColors.Add(new Xceed.Wpf.Toolkit.ColorItem(color, string.Empty)); - //_pallete.Add(color., new SolidColorBrush(mediaColor)); + _pallete.Add(MediaColorConverter.ToRgb(color), brush); } //public void DeleteFrame(Frame frame) diff --git a/Winleafs.Wpf/Views/Layout/LayoutDisplayUserControl.xaml.cs b/Winleafs.Wpf/Views/Layout/LayoutDisplayUserControl.xaml.cs index dadfdab0..8ad05c68 100644 --- a/Winleafs.Wpf/Views/Layout/LayoutDisplayUserControl.xaml.cs +++ b/Winleafs.Wpf/Views/Layout/LayoutDisplayUserControl.xaml.cs @@ -16,19 +16,21 @@ namespace Winleafs.Wpf.Views.Layout { - /// - /// Interaction logic for LayoutDisplay.xaml - /// - public partial class LayoutDisplayUserControl : UserControl - { - private static readonly SolidColorBrush _lockedBorderColor = Brushes.Red; - private static readonly SolidColorBrush _highLightColor = Brushes.OrangeRed; - private static readonly SolidColorBrush _selectedBorderColor = Brushes.LightSteelBlue; - private static readonly SolidColorBrush _borderColor = (SolidColorBrush)Application.Current.FindResource("NanoleafBlack"); + /// + /// Interaction logic for LayoutDisplay.xaml + /// + public partial class LayoutDisplayUserControl : UserControl + { + private static readonly SolidColorBrush _lockedBorderColor = Brushes.Red; + private static readonly SolidColorBrush _highLightColor = Brushes.OrangeRed; + private static readonly SolidColorBrush _selectedBorderColor = Brushes.LightSteelBlue; + private static readonly SolidColorBrush _borderColor = (SolidColorBrush)Application.Current.FindResource("NanoleafBlack"); public HashSet PanelIds { get; set; } public HashSet SelectedPanelIds { get; set; } public event EventHandler PanelClicked; + public bool MultiSelectEnabled { get; set; } = true; + public Dictionary PanelToBrushMap { get; set; } private static readonly Random _random = new Random(); @@ -136,7 +138,7 @@ private void Redraw_Click(object sender, RoutedEventArgs e) { DrawLayout(); } - + public void UpdateColors() { if (UserSettings.Settings.ActiveDevice == null || _drawablePanels == null) @@ -147,7 +149,24 @@ public void UpdateColors() //Run code on main thread since we update the UI Dispatcher.Invoke(new Action(() => { - var orchestrator = OrchestratorCollection.GetOrchestratorForDevice(UserSettings.Settings.ActiveDevice); + if (PanelToBrushMap != null) + { + foreach (var drawablePanel in _drawablePanels) + { + if (PanelToBrushMap.TryGetValue(drawablePanel.PanelId, out var brush)) + { + drawablePanel.Polygon.Fill = brush; + } + else + { + drawablePanel.Polygon.Fill = Brushes.LightSlateGray; + } + } + + return; + } + + var orchestrator = OrchestratorCollection.GetOrchestratorForDevice(UserSettings.Settings.ActiveDevice); //Get colors of current effect, we can display colors for nanoleaf effects or custom color effects var effectName = orchestrator.GetActiveEffectName(); @@ -168,7 +187,8 @@ public void UpdateColors() colors = new List() { new SolidColorBrush(Color.FromArgb(customColorEffect.Color.A, customColorEffect.Color.R, customColorEffect.Color.G, customColorEffect.Color.B)) }; } } - else + + else { var effect = UserSettings.Settings.ActiveDevice.Effects.FirstOrDefault(effect => effect.Name == effectName); @@ -244,19 +264,27 @@ private void PolygonClicked(object sender, MouseButtonEventArgs e) return; } - if (SelectedPanelIds.Contains(selectedPanelId)) + if (PanelClicked != null) { - polygon.Stroke = _borderColor; - polygon.StrokeThickness = 2; - - SelectedPanelIds.Remove(selectedPanelId); + PanelClicked.Invoke(selectedPanel, new EventArgs()); } - else - { - polygon.Stroke = _selectedBorderColor; - polygon.StrokeThickness = 2; - SelectedPanelIds.Add(selectedPanelId); + if (MultiSelectEnabled) + { + if (SelectedPanelIds.Contains(selectedPanelId)) + { + polygon.Stroke = _borderColor; + polygon.StrokeThickness = 2; + + SelectedPanelIds.Remove(selectedPanelId); + } + else + { + polygon.Stroke = _selectedBorderColor; + polygon.StrokeThickness = 2; + + SelectedPanelIds.Add(selectedPanelId); + } } } From c026e39038d9ac1ec1dbe42fb56cc89430db2a71 Mon Sep 17 00:00:00 2001 From: Jason Steele Date: Mon, 13 Sep 2021 19:49:46 +0100 Subject: [PATCH 08/23] Fix missing black brush --- .../Views/Layout/CreateEffectWindow.xaml.cs | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/Winleafs.Wpf/Views/Layout/CreateEffectWindow.xaml.cs b/Winleafs.Wpf/Views/Layout/CreateEffectWindow.xaml.cs index f01636e0..fa94bbf8 100644 --- a/Winleafs.Wpf/Views/Layout/CreateEffectWindow.xaml.cs +++ b/Winleafs.Wpf/Views/Layout/CreateEffectWindow.xaml.cs @@ -38,15 +38,14 @@ public CreateEffectWindow() { var serialized = JsonConvert.SerializeObject(UserSettings.Settings.ActiveDevice.CustomEffect); //Deep copy the custom effect when editing _customEffect = JsonConvert.DeserializeObject(serialized); - - } + BuildFrameList(); + } else { _customEffect = new CustomEffect(); - _customEffect.Frames.Add(new Frame()); + AddNewFrame(); } - - BuildFrameList(); + BuildPallete(); FrameSelected(_customEffect.Frames[0]); @@ -110,10 +109,12 @@ private void LayoutDisplay_PanelClicked(object sender, System.EventArgs e) private void Plus_Click(object sender, RoutedEventArgs e) { - AddNewFrame(); + var frame = AddNewFrame(); + + FrameSelected(frame); } - private void AddNewFrame() + private Frame AddNewFrame() { // Copy the previous frame's panel colors where we can var prevFrame = _customEffect.Frames.LastOrDefault(); @@ -134,13 +135,14 @@ private void AddNewFrame() _customEffect.Frames.Add(newFrame); FrameList.Children.Add(new FrameUserControl(this, _customEffect.Frames.Count, newFrame)); - FrameSelected(newFrame); + return newFrame; } private void BuildFrameList() { FrameList.Children.Clear(); + for (var i = 0; i < _customEffect.Frames.Count; i++) { FrameList.Children.Add(new FrameUserControl(this, i + 1, _customEffect.Frames[i])); @@ -156,11 +158,11 @@ private void BuildPallete() ColorPicker.StandardColors.Clear(); _pallete = new Dictionary(); - foreach (var argb in colorsUsed) + foreach (var rgb in colorsUsed) { - var mediaColor = MediaColorConverter.FromRgb(argb); + var mediaColor = MediaColorConverter.FromRgb(rgb); ColorPicker.StandardColors.Add(new Xceed.Wpf.Toolkit.ColorItem(mediaColor, string.Empty)); - _pallete.Add(argb, new SolidColorBrush(mediaColor)); + _pallete.Add(rgb, new SolidColorBrush(mediaColor)); } } From 484e55707bd1c34a2d691c9bd4b751c284cd7e26 Mon Sep 17 00:00:00 2001 From: Jason Steele Date: Tue, 14 Sep 2021 16:45:37 +0100 Subject: [PATCH 09/23] Add Transition time and Play button --- .../Views/Layout/CreateEffectWindow.xaml | 26 ++++++++-- .../Views/Layout/CreateEffectWindow.xaml.cs | 50 +++++++++++++++---- 2 files changed, 60 insertions(+), 16 deletions(-) diff --git a/Winleafs.Wpf/Views/Layout/CreateEffectWindow.xaml b/Winleafs.Wpf/Views/Layout/CreateEffectWindow.xaml index 2bf3355f..2c725e05 100644 --- a/Winleafs.Wpf/Views/Layout/CreateEffectWindow.xaml +++ b/Winleafs.Wpf/Views/Layout/CreateEffectWindow.xaml @@ -23,15 +23,31 @@ -