From ee936efb8a8a77314f68d414fa6ee5d227619ae6 Mon Sep 17 00:00:00 2001 From: John Lewin Date: Sat, 13 Oct 2018 17:58:54 -0700 Subject: [PATCH] Revise theme support --- .../ApplicationSettings/ThemeColorPanel.cs | 241 +++++++++++++++++ .../GCodeRenderer/GCodeRenderer.cs | 21 +- .../RenderFeatures/RenderFeatureExtrusion.cs | 6 +- .../InspectForm.Designer.cs | 82 +++++- MatterControl.Winforms/InspectForm.cs | 43 +++- MatterControlLib/AboutPage/AboutPage.cs | 13 +- .../AboutPage/CheckForUpdatesPage.cs | 33 ++- .../ActionBar/TemperatureWidgetBed.cs | 1 - .../ActionBar/TemperatureWidgetExtruder.cs | 3 +- .../ApplicationView/ApplicationController.cs | 161 ++++++++---- .../ApplicationView/PrinterModels.cs | 6 +- .../ApplicationView/ThemeConfig.cs | 72 ++---- .../ApplicationView/Themes/ActiveTheme.cs | 58 +++++ .../Themes/ClassicColorsTheme.cs | 143 +++++++++++ .../ApplicationView/Themes/IColorTheme.cs | 44 ++++ .../ApplicationView/Themes/IThemeColors.cs | 46 ++++ .../ApplicationView/Themes/SolarizedTheme.cs | 243 ++++++++++++++++++ .../ApplicationView/Themes/ThemeColors.cs | 67 +++++ .../ApplicationView/WidescreenPanel.cs | 6 +- .../ApplicationSettingsView.cs | 68 ----- .../ApplicationSettings/ThemeColorPanel.cs | 241 +++++++++++++++++ .../ApplicationSettings/ThemePreviewButton.cs | 85 +++--- .../CustomWidgets/DockingTabControl.cs | 3 +- .../CustomWidgets/ThemeColorSelectorWidget.cs | 144 ----------- .../EeProm/EePromRepetierWindow.cs | 2 +- MatterControlLib/Library/ExtensionMethods.cs | 2 +- .../Library/Widgets/LibraryWidget.cs | 2 +- .../Library/Widgets/PrintLibraryWidget.cs | 5 +- .../PartPreviewWindow/GCode2DWidget.cs | 2 - .../PartPreviewWindow/ItemMaterialButton.cs | 2 +- .../PartPreviewWindow/LibraryBrowserPage.cs | 4 +- .../PartPreviewWindow/MaterialControls.cs | 2 +- .../PartPreviewWindow/PartPreviewContent.cs | 6 +- .../PartPreviewWindow/PartTabPage.cs | 2 - .../PartPreviewWindow/PopupMenu.cs | 2 - .../PartPreviewWindow/PopupMenuButton.cs | 6 +- .../PartPreviewWindow/RunningTaskRow.cs | 1 - .../PartPreviewWindow/SelectedObjectPanel.cs | 2 +- .../View3D/ColorSwatchSelector.cs | 10 +- .../View3D/PrinterBar/PrintPopupMenu.cs | 3 +- .../PartPreviewWindow/View3D/View3DWidget.cs | 2 +- .../ControlWidgets/MovementControls.cs | 4 +- .../TerminalWindow/TerminalWidget.cs | 2 +- .../ApplicationSettingsPage.cs | 63 ++++- .../SettingsManagement/UserSettings.cs | 2 + MatterControlLib/SetupWizard/DialogPage.cs | 2 +- MatterControlLib/SetupWizard/DialogWindow.cs | 31 ++- .../Settings/ProfileManager.cs | 8 +- .../Settings/SettingsHelpers.cs | 1 - .../SliceSettingsWidget.cs | 4 +- .../UIFields/ComPortField.cs | 2 - .../UIFields/IpAddessField.cs | 3 +- MatterControlLib/Utilities/JsonPath.cs | 1 + Submodules/agg-sharp | 2 +- .../MatterControl/BoundDropListTests.cs | 2 +- .../MatterControl/PopupAnchorTests.cs | 5 +- .../MatterControl/SliceSettingsFieldTests.cs | 3 +- 57 files changed, 1562 insertions(+), 458 deletions(-) create mode 100644 ConfigurationPage/ApplicationSettings/ThemeColorPanel.cs create mode 100644 MatterControlLib/ApplicationView/Themes/ActiveTheme.cs create mode 100644 MatterControlLib/ApplicationView/Themes/ClassicColorsTheme.cs create mode 100644 MatterControlLib/ApplicationView/Themes/IColorTheme.cs create mode 100644 MatterControlLib/ApplicationView/Themes/IThemeColors.cs create mode 100644 MatterControlLib/ApplicationView/Themes/SolarizedTheme.cs create mode 100644 MatterControlLib/ApplicationView/Themes/ThemeColors.cs create mode 100644 MatterControlLib/ConfigurationPage/ApplicationSettings/ThemeColorPanel.cs delete mode 100644 MatterControlLib/CustomWidgets/ThemeColorSelectorWidget.cs diff --git a/ConfigurationPage/ApplicationSettings/ThemeColorPanel.cs b/ConfigurationPage/ApplicationSettings/ThemeColorPanel.cs new file mode 100644 index 000000000..88be0aac9 --- /dev/null +++ b/ConfigurationPage/ApplicationSettings/ThemeColorPanel.cs @@ -0,0 +1,241 @@ +/* +Copyright (c) 2018, Kevin Pope, John Lewin +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + +using System; +using System.Collections.Generic; +using System.Linq; +using MatterHackers.Agg; +using MatterHackers.Agg.Image; +using MatterHackers.Agg.Platform; +using MatterHackers.Agg.UI; +using MatterHackers.MatterControl.PartPreviewWindow; + +namespace MatterHackers.MatterControl.ConfigurationPage +{ + public class ThemeColorPanel : FlowLayoutWidget + { + private Color lastColor; + private AccentColorsWidget colorSelector; + + private IColorTheme _themeProvider; + private GuiWidget previewButtonPanel; + + public ThemeColorPanel(ThemeConfig activeTheme) + : base (FlowDirection.TopToBottom) + { + string currentProviderName = UserSettings.Instance.get(UserSettingsKey.ThemeName) ?? ""; + + if (AppContext.ThemeProviders.TryGetValue(currentProviderName, out IColorTheme currentProvider)) + { + _themeProvider = currentProvider; + } + else + { + _themeProvider = AppContext.ThemeProviders.Values.First(); + } + + this.SelectionColor = activeTheme.GetBorderColor(80); + + // Add color selector + this.AddChild(colorSelector = new AccentColorsWidget(this) + { + Margin = new BorderDouble(activeTheme.DefaultContainerPadding, 0) + }); + + this.AddChild(previewButtonPanel = new FlowLayoutWidget() + { + HAnchor = HAnchor.Stretch, + VAnchor = VAnchor.Fit, + BackgroundColor = this.SelectionColor, + Padding = new BorderDouble(left: colorSelector.ColorButtons.First().Border.Left) + }); + + this.CreateThemeModeButtons(); + } + + public ImageBuffer CheckMark { get; } = AggContext.StaticData.LoadIcon("426.png", 16, 16, invertImage: true); + + public Color SelectionColor { get; private set; } + + public IColorTheme ThemeProvider + { + get => _themeProvider; + set + { + _themeProvider = value; + + var previewColor = _themeProvider.Colors.First(); + + colorSelector.RebuildColorButtons(); + + this.CreateThemeModeButtons(); + + this.PreviewTheme(previewColor); + } + } + private void CreateThemeModeButtons() + { + previewButtonPanel.CloseAllChildren(); + + var theme = AppContext.Theme; + + var accentColor = theme.Colors.PrimaryAccentColor; + + if (!_themeProvider.Colors.Contains(accentColor)) + { + accentColor = _themeProvider.DefaultColor; + } + + var activeMode = UserSettings.Instance.get(UserSettingsKey.ThemeMode); + + foreach (var mode in _themeProvider.Modes) + { + var themeset = _themeProvider.GetTheme(mode, accentColor); + + previewButtonPanel.AddChild(new ThemePreviewButton(themeset.Theme, this) + { + HAnchor = HAnchor.Absolute, + VAnchor = VAnchor.Absolute, + Width = 80, + Height = 65, + Mode = mode, + Margin = new BorderDouble(theme.DefaultContainerPadding, theme.DefaultContainerPadding, 0, theme.DefaultContainerPadding), + Border = 1, + IsActive = mode == activeMode, + BorderColor = theme.GetBorderColor(20), + }); + } + } + + public void PreviewTheme(Color sourceAccentColor) + { + foreach (var previewButton in previewButtonPanel.Children()) + { + previewButton.PreviewThemeColor(sourceAccentColor); + } + } + + public void SetThemeColor(Color accentColor, string mode = null) + { + lastColor = accentColor; + + foreach (var colorButton in colorSelector.ColorButtons) + { + colorButton.BorderColor = (colorButton.SourceColor == accentColor) ? Color.White : Color.Transparent; + } + + if (mode == null) + { + mode = this.ThemeProvider.DefaultMode; + + var lastMode = UserSettings.Instance.get(UserSettingsKey.ThemeMode); + if (this.ThemeProvider.Modes.Contains(lastMode)) + { + mode = lastMode; + } + } + + Console.WriteLine("Getting/setting theme for " + accentColor.Html); + + AppContext.SetTheme(this.ThemeProvider.GetTheme(mode, accentColor)); + previewButtonPanel.BackgroundColor = this.SelectionColor; + } + + public class AccentColorsWidget : FlowLayoutWidget + { + private int containerHeight = (int)(20 * GuiWidget.DeviceScale); + private ThemeColorPanel themeColorPanel; + + public AccentColorsWidget(ThemeColorPanel themeColorPanel) + { + this.Padding = new BorderDouble(2, 0); + this.themeColorPanel = themeColorPanel; + + this.RebuildColorButtons(); + } + + private List colorButtons = new List(); + + public IEnumerable ColorButtons => colorButtons; + + public void RebuildColorButtons() + { + this.CloseAllChildren(); + + colorButtons.Clear(); + + bool firstItem = true; + + foreach (var color in themeColorPanel.ThemeProvider.Colors) + { + var colorButton = CreateThemeButton(color); + colorButton.Width = containerHeight; + colorButton.BorderColor = (color == AppContext.Theme.Colors.SourceColor) ? themeColorPanel.SelectionColor : Color.Transparent; + + colorButtons.Add(colorButton); + + if (firstItem) + { + firstItem = false; + colorButton.Margin = colorButton.Margin.Clone(left: 0); + } + + this.AddChild(colorButton); + } + } + + public ColorButton CreateThemeButton(Color color) + { + var colorButton = new ColorButton(color) + { + Cursor = Cursors.Hand, + Width = containerHeight, + Height = containerHeight, + Border = 5, + }; + colorButton.Click += (s, e) => + { + themeColorPanel.SetThemeColor(colorButton.BackgroundColor); + }; + + colorButton.MouseEnterBounds += (s, e) => + { + foreach(var button in this.ColorButtons) + { + button.BorderColor = (button == colorButton) ? themeColorPanel.SelectionColor : Color.Transparent; + } + + themeColorPanel.PreviewTheme(colorButton.BackgroundColor); + }; + + return colorButton; + } + } + } +} \ No newline at end of file diff --git a/MatterControl.OpenGL/GCodeRenderer/GCodeRenderer.cs b/MatterControl.OpenGL/GCodeRenderer/GCodeRenderer.cs index d99fc5b38..0ae8a44ef 100644 --- a/MatterControl.OpenGL/GCodeRenderer/GCodeRenderer.cs +++ b/MatterControl.OpenGL/GCodeRenderer/GCodeRenderer.cs @@ -66,6 +66,8 @@ namespace MatterHackers.GCodeVisualizer public ExtrusionColors ExtrusionColors { get; } = null; + public Color Gray { get; set; } + public GCodeRenderer(GCodeFile gCodeFileToDraw) { if (gCodeFileToDraw != null) @@ -133,11 +135,26 @@ namespace MatterHackers.GCodeVisualizer double layerThickness = gCodeFileToDraw.GetLayerHeight(layerToCreate); Color extrusionColor = ExtrusionColors.GetColorForSpeed((float)currentInstruction.FeedRate); - renderFeaturesForLayer.Add(new RenderFeatureExtrusion(previousInstruction.Position, currentInstruction.Position, currentInstruction.ExtruderIndex, currentInstruction.FeedRate, currentInstruction.EPosition - previousInstruction.EPosition, gCodeFileToDraw.GetFilamentDiameter(), layerThickness, extrusionColor)); + renderFeaturesForLayer.Add( + new RenderFeatureExtrusion( + previousInstruction.Position, + currentInstruction.Position, + currentInstruction.ExtruderIndex, + currentInstruction.FeedRate, + currentInstruction.EPosition - previousInstruction.EPosition, + gCodeFileToDraw.GetFilamentDiameter(), + layerThickness, + extrusionColor, + this.Gray)); } else { - renderFeaturesForLayer.Add(new RenderFeatureTravel(previousInstruction.Position, currentInstruction.Position, currentInstruction.ExtruderIndex, currentInstruction.FeedRate)); + renderFeaturesForLayer.Add( + new RenderFeatureTravel( + previousInstruction.Position, + currentInstruction.Position, + currentInstruction.ExtruderIndex, + currentInstruction.FeedRate)); } } } diff --git a/MatterControl.OpenGL/GCodeRenderer/RenderFeatures/RenderFeatureExtrusion.cs b/MatterControl.OpenGL/GCodeRenderer/RenderFeatures/RenderFeatureExtrusion.cs index 6eb811ee4..5ad70566c 100644 --- a/MatterControl.OpenGL/GCodeRenderer/RenderFeatures/RenderFeatureExtrusion.cs +++ b/MatterControl.OpenGL/GCodeRenderer/RenderFeatures/RenderFeatureExtrusion.cs @@ -41,11 +41,13 @@ namespace MatterHackers.GCodeVisualizer private float extrusionVolumeMm3; private float layerHeight; private Color color; + private Color gray; - public RenderFeatureExtrusion(Vector3 start, Vector3 end, int extruderIndex, double travelSpeed, double totalExtrusionMm, double filamentDiameterMm, double layerHeight, Color color) + public RenderFeatureExtrusion(Vector3 start, Vector3 end, int extruderIndex, double travelSpeed, double totalExtrusionMm, double filamentDiameterMm, double layerHeight, Color color, Color gray) : base(start, end, extruderIndex, travelSpeed) { this.color = color; + this.gray = gray; double filamentRadius = filamentDiameterMm / 2; double areaSquareMm = (filamentRadius * filamentRadius) * Math.PI; @@ -98,7 +100,7 @@ namespace MatterHackers.GCodeVisualizer } else if (renderInfo.CurrentRenderType.HasFlag(RenderType.GrayColors)) { - lineColor = ActiveTheme.Instance.IsDarkTheme ? Color.DarkGray : Color.Gray; + lineColor = this.gray; } else { diff --git a/MatterControl.Winforms/InspectForm.Designer.cs b/MatterControl.Winforms/InspectForm.Designer.cs index 055a4943c..53fbc8eb8 100644 --- a/MatterControl.Winforms/InspectForm.Designer.cs +++ b/MatterControl.Winforms/InspectForm.Designer.cs @@ -29,13 +29,17 @@ private void InitializeComponent() { this.splitContainer1 = new System.Windows.Forms.SplitContainer(); + this.debugTextWidget = new System.Windows.Forms.CheckBox(); this.tabControl1 = new System.Windows.Forms.TabControl(); this.tabPage1 = new System.Windows.Forms.TabPage(); this.aggTreeView = new System.Windows.Forms.TreeView(); this.tabPage2 = new System.Windows.Forms.TabPage(); this.sceneTreeView = new System.Windows.Forms.TreeView(); + this.tabPage3 = new System.Windows.Forms.TabPage(); + this.themeTreeView = new System.Windows.Forms.TreeView(); + this.btnSaveTheme = new System.Windows.Forms.Button(); this.propertyGrid1 = new System.Windows.Forms.PropertyGrid(); - this.debugTextWidget = new System.Windows.Forms.CheckBox(); + this.btnApply = new System.Windows.Forms.Button(); ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit(); this.splitContainer1.Panel1.SuspendLayout(); this.splitContainer1.Panel2.SuspendLayout(); @@ -43,6 +47,7 @@ this.tabControl1.SuspendLayout(); this.tabPage1.SuspendLayout(); this.tabPage2.SuspendLayout(); + this.tabPage3.SuspendLayout(); this.SuspendLayout(); // // splitContainer1 @@ -65,10 +70,23 @@ this.splitContainer1.SplitterWidth = 3; this.splitContainer1.TabIndex = 0; // + // debugTextWidget + // + this.debugTextWidget.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.debugTextWidget.AutoSize = true; + this.debugTextWidget.Location = new System.Drawing.Point(489, 3); + this.debugTextWidget.Name = "debugTextWidget"; + this.debugTextWidget.Size = new System.Drawing.Size(116, 17); + this.debugTextWidget.TabIndex = 2; + this.debugTextWidget.Text = "Debug TextWidget"; + this.debugTextWidget.UseVisualStyleBackColor = true; + this.debugTextWidget.CheckedChanged += new System.EventHandler(this.debugTextWidget_CheckedChanged); + // // tabControl1 // this.tabControl1.Controls.Add(this.tabPage1); this.tabControl1.Controls.Add(this.tabPage2); + this.tabControl1.Controls.Add(this.tabPage3); this.tabControl1.Dock = System.Windows.Forms.DockStyle.Fill; this.tabControl1.Location = new System.Drawing.Point(0, 0); this.tabControl1.Name = "tabControl1"; @@ -108,7 +126,7 @@ this.tabPage2.Location = new System.Drawing.Point(4, 22); this.tabPage2.Name = "tabPage2"; this.tabPage2.Padding = new System.Windows.Forms.Padding(3); - this.tabPage2.Size = new System.Drawing.Size(546, 606); + this.tabPage2.Size = new System.Drawing.Size(600, 606); this.tabPage2.TabIndex = 1; this.tabPage2.Text = "Scene"; this.tabPage2.UseVisualStyleBackColor = true; @@ -122,11 +140,45 @@ this.sceneTreeView.Location = new System.Drawing.Point(3, 3); this.sceneTreeView.Margin = new System.Windows.Forms.Padding(2); this.sceneTreeView.Name = "sceneTreeView"; - this.sceneTreeView.Size = new System.Drawing.Size(540, 600); + this.sceneTreeView.Size = new System.Drawing.Size(594, 600); this.sceneTreeView.TabIndex = 2; this.sceneTreeView.DrawNode += new System.Windows.Forms.DrawTreeNodeEventHandler(this.SceneTreeView_DrawNode); this.sceneTreeView.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.SceneTreeView_AfterSelect); // + // tabPage3 + // + this.tabPage3.Controls.Add(this.btnApply); + this.tabPage3.Controls.Add(this.themeTreeView); + this.tabPage3.Controls.Add(this.btnSaveTheme); + this.tabPage3.Location = new System.Drawing.Point(4, 22); + this.tabPage3.Name = "tabPage3"; + this.tabPage3.Padding = new System.Windows.Forms.Padding(3); + this.tabPage3.Size = new System.Drawing.Size(600, 606); + this.tabPage3.TabIndex = 2; + this.tabPage3.Text = "Theme"; + this.tabPage3.UseVisualStyleBackColor = true; + // + // themeTreeView + // + this.themeTreeView.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.themeTreeView.FullRowSelect = true; + this.themeTreeView.HideSelection = false; + this.themeTreeView.Location = new System.Drawing.Point(3, 3); + this.themeTreeView.Margin = new System.Windows.Forms.Padding(2); + this.themeTreeView.Name = "themeTreeView"; + this.themeTreeView.Size = new System.Drawing.Size(592, 253); + this.themeTreeView.TabIndex = 2; + // + // btnSaveTheme + // + this.btnSaveTheme.Location = new System.Drawing.Point(519, 322); + this.btnSaveTheme.Name = "btnSaveTheme"; + this.btnSaveTheme.Size = new System.Drawing.Size(75, 23); + this.btnSaveTheme.TabIndex = 0; + this.btnSaveTheme.Text = "Save Theme"; + this.btnSaveTheme.UseVisualStyleBackColor = true; + // // propertyGrid1 // this.propertyGrid1.Dock = System.Windows.Forms.DockStyle.Fill; @@ -138,17 +190,15 @@ this.propertyGrid1.TabIndex = 0; this.propertyGrid1.PropertyValueChanged += new System.Windows.Forms.PropertyValueChangedEventHandler(this.propertyGrid1_PropertyValueChanged); // - // debugTextWidget + // btnApply // - this.debugTextWidget.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.debugTextWidget.AutoSize = true; - this.debugTextWidget.Location = new System.Drawing.Point(489, 3); - this.debugTextWidget.Name = "debugTextWidget"; - this.debugTextWidget.Size = new System.Drawing.Size(116, 17); - this.debugTextWidget.TabIndex = 2; - this.debugTextWidget.Text = "Debug TextWidget"; - this.debugTextWidget.UseVisualStyleBackColor = true; - this.debugTextWidget.CheckedChanged += new System.EventHandler(this.debugTextWidget_CheckedChanged); + this.btnApply.Location = new System.Drawing.Point(438, 322); + this.btnApply.Name = "btnApply"; + this.btnApply.Size = new System.Drawing.Size(75, 23); + this.btnApply.TabIndex = 3; + this.btnApply.Text = "Apply"; + this.btnApply.UseVisualStyleBackColor = true; + this.btnApply.Click += new System.EventHandler(this.btnApply_Click); // // InspectForm // @@ -159,6 +209,7 @@ this.Margin = new System.Windows.Forms.Padding(2); this.Name = "InspectForm"; this.Text = "InspectForm"; + this.Load += new System.EventHandler(this.InspectForm_Load); this.splitContainer1.Panel1.ResumeLayout(false); this.splitContainer1.Panel1.PerformLayout(); this.splitContainer1.Panel2.ResumeLayout(false); @@ -167,6 +218,7 @@ this.tabControl1.ResumeLayout(false); this.tabPage1.ResumeLayout(false); this.tabPage2.ResumeLayout(false); + this.tabPage3.ResumeLayout(false); this.ResumeLayout(false); } @@ -181,5 +233,9 @@ private System.Windows.Forms.TabPage tabPage2; private System.Windows.Forms.TreeView sceneTreeView; private System.Windows.Forms.CheckBox debugTextWidget; + private System.Windows.Forms.TabPage tabPage3; + private System.Windows.Forms.Button btnSaveTheme; + private System.Windows.Forms.TreeView themeTreeView; + private System.Windows.Forms.Button btnApply; } } diff --git a/MatterControl.Winforms/InspectForm.cs b/MatterControl.Winforms/InspectForm.cs index 3ccf091d9..3bae0c948 100644 --- a/MatterControl.Winforms/InspectForm.cs +++ b/MatterControl.Winforms/InspectForm.cs @@ -340,7 +340,7 @@ namespace MatterHackers.MatterControl private void systemWindow_AfterDraw(object sender, EventArgs e) { - if (this.Inspecting + if (this.Inspecting && !inspectedSystemWindow.HasBeenClosed && tabControl1.SelectedIndex == 0) { @@ -415,7 +415,7 @@ namespace MatterHackers.MatterControl { //var item = node.Tag as IObject3D; e.Graphics.FillRectangle( - (sceneTreeView.SelectedNode == node) ? SystemBrushes.Highlight : Brushes.Transparent, + (sceneTreeView.SelectedNode == node) ? SystemBrushes.Highlight : Brushes.Transparent, node.Bounds); TextRenderer.DrawText( @@ -443,6 +443,7 @@ namespace MatterHackers.MatterControl { scene.DebugItem = null; } + } private void debugTextWidget_CheckedChanged(object sender, EventArgs e) @@ -464,5 +465,43 @@ namespace MatterHackers.MatterControl base.OnKeyUp(e); } + + private void InspectForm_Load(object sender, EventArgs e1) + { + var rootNode = new TreeNode("Theme"); + + var themeNode = new TreeNode("Theme"); + + var menuThemeNode = new TreeNode("MenuTheme"); + + rootNode.Nodes.Add(themeNode); + rootNode.Nodes.Add(menuThemeNode); + + themeTreeView.Nodes.Add(rootNode); + + rootNode.Expand(); + + themeTreeView.AfterSelect += (s, e) => + { + if (e.Node == rootNode) + { + propertyGrid1.SelectedObject = MatterControl.AppContext.ThemeSet; + } + else if (e.Node == themeNode) + { + propertyGrid1.SelectedObject = MatterControl.AppContext.Theme; + + } + else if (e.Node == menuThemeNode) + { + propertyGrid1.SelectedObject = MatterControl.AppContext.MenuTheme; + } + }; + } + + private void btnApply_Click(object sender, EventArgs e) + { + ApplicationController.Instance.ReloadAll(); + } } } diff --git a/MatterControlLib/AboutPage/AboutPage.cs b/MatterControlLib/AboutPage/AboutPage.cs index 6cd544845..eb8ff4db1 100644 --- a/MatterControlLib/AboutPage/AboutPage.cs +++ b/MatterControlLib/AboutPage/AboutPage.cs @@ -135,6 +135,8 @@ namespace MatterHackers.MatterControl var linkIcon = AggContext.StaticData.LoadIcon("fa-link_16.png", 16, 16, theme.InvertIcons); + SectionWidget section = null; + foreach (var item in data.OrderBy(i => i.Name)) { var linkButton = new IconButton(linkIcon, theme); @@ -143,21 +145,26 @@ namespace MatterHackers.MatterControl ApplicationController.Instance.LaunchBrowser(item.Url); }); - var section = new SectionWidget(item.Title ?? item.Name, new LazyLicenseText(item.Name, theme), theme, linkButton, expanded: false) + section = new SectionWidget(item.Title ?? item.Name, new LazyLicenseText(item.Name, theme), theme, linkButton, expanded: false) { HAnchor = HAnchor.Stretch }; licensePanel.AddChild(section); } + // Apply a bottom border to the last time for balance + if (section != null) + { + section.Border = section.Border.Clone(bottom: 1); + } + var scrollable = new ScrollableWidget(autoScroll: true) { HAnchor = HAnchor.Stretch, VAnchor = VAnchor.Stretch, Margin = new BorderDouble(bottom: 10), - Border = new BorderDouble(top: 1), - BorderColor = new Color(theme.Colors.SecondaryTextColor, 50) }; + scrollable.ScrollArea.HAnchor = HAnchor.Stretch; scrollable.AddChild(licensePanel); contentRow.AddChild( scrollable); diff --git a/MatterControlLib/AboutPage/CheckForUpdatesPage.cs b/MatterControlLib/AboutPage/CheckForUpdatesPage.cs index 93a68cbdf..ac62a380e 100644 --- a/MatterControlLib/AboutPage/CheckForUpdatesPage.cs +++ b/MatterControlLib/AboutPage/CheckForUpdatesPage.cs @@ -1,4 +1,33 @@ -using System; +/* +Copyright (c) 2018, Lars Brubaker, John Lewin, Greg Diaz +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + +using System; using System.Collections.Generic; using MatterHackers.Agg; using MatterHackers.Agg.UI; @@ -111,7 +140,7 @@ namespace MatterHackers.MatterControl additionalInfoContainer = new FlowLayoutWidget(FlowDirection.TopToBottom) { - BackgroundColor = theme.Colors.SecondaryBackgroundColor, + BackgroundColor = theme.MinimalShade, HAnchor = HAnchor.Stretch, Padding = new BorderDouble(left: 6, top: 6), Visible = false diff --git a/MatterControlLib/ActionBar/TemperatureWidgetBed.cs b/MatterControlLib/ActionBar/TemperatureWidgetBed.cs index f32c5c13f..f4c9e1f29 100644 --- a/MatterControlLib/ActionBar/TemperatureWidgetBed.cs +++ b/MatterControlLib/ActionBar/TemperatureWidgetBed.cs @@ -71,7 +71,6 @@ namespace MatterHackers.MatterControl.ActionBar Width = 300, HAnchor = HAnchor.Absolute, VAnchor = VAnchor.Fit, - BackgroundColor = theme.Colors.PrimaryBackgroundColor, Padding = new BorderDouble(12, 0) }; diff --git a/MatterControlLib/ActionBar/TemperatureWidgetExtruder.cs b/MatterControlLib/ActionBar/TemperatureWidgetExtruder.cs index 32dc13a22..9363ad0ff 100644 --- a/MatterControlLib/ActionBar/TemperatureWidgetExtruder.cs +++ b/MatterControlLib/ActionBar/TemperatureWidgetExtruder.cs @@ -230,8 +230,7 @@ namespace MatterHackers.MatterControl.ActionBar Width = 350, HAnchor = HAnchor.Absolute, VAnchor = VAnchor.Fit, - BackgroundColor = theme.Colors.PrimaryBackgroundColor, - Padding = new BorderDouble(12, 0) + Padding = new BorderDouble(12, 0), }; var container = new FlowLayoutWidget(FlowDirection.TopToBottom) diff --git a/MatterControlLib/ApplicationView/ApplicationController.cs b/MatterControlLib/ApplicationView/ApplicationController.cs index 57da4bcfe..b2152b977 100644 --- a/MatterControlLib/ApplicationView/ApplicationController.cs +++ b/MatterControlLib/ApplicationView/ApplicationController.cs @@ -81,6 +81,7 @@ namespace MatterHackers.MatterControl using MatterHackers.VectorMath; using MatterHackers.VectorMath.TrackBall; using Newtonsoft.Json.Converters; + using Newtonsoft.Json.Serialization; using SettingsManagement; [JsonConverter(typeof(StringEnumConverter))] @@ -119,6 +120,102 @@ namespace MatterHackers.MatterControl /// The root SystemWindow /// public static SystemWindow RootSystemWindow { get; internal set; } + + public static ThemeConfig Theme => themeset.Theme; + + public static ThemeConfig MenuTheme => themeset.MenuTheme; + + private static ThemeSet themeset; + + public static ThemeSet ThemeSet => themeset; + + public static Dictionary ThemeProviders = new Dictionary() + { + { "Classic" , new ClassicColorsTheme() }, + { "Solarized", new SolarizedTheme() }, + }; + + public static IColorTheme GetColorProvider(string key) + { + if (ThemeProviders.TryGetValue(key, out IColorTheme themeProvider)) + { + return themeProvider; + } + + return ThemeProviders.Values.First(); + } + + static AppContext() + { + // Load theme + try + { + if (File.Exists(ProfileManager.Instance.ProfileThemeSetPath)) + { + themeset = JsonConvert.DeserializeObject(File.ReadAllText(ProfileManager.Instance.ProfileThemeSetPath)); + } + } + catch { } + + if (themeset == null) + { + var themeProvider = ThemeProviders.Values.First(); + var defaultColor = themeProvider.Colors.First(); + + themeset = themeProvider.GetTheme("Dark", defaultColor); + } + + DefaultThumbView.ThumbColor = new Color(themeset.Theme.Colors.PrimaryTextColor, 30); + ActiveTheme.Instance = themeset.Theme.Colors; + + (ActiveTheme.Instance as ThemeColors).DisabledColor = themeset.Theme.GetBorderColor(20); + } + + public static void SetTheme(ThemeSet themeSet) + { + themeset = themeSet; + + //var theme = ApplicationController.ThemeProvider.GetTheme(color); + File.WriteAllText( + ProfileManager.Instance.ProfileThemeSetPath, + JsonConvert.SerializeObject( + themeset, + Formatting.Indented, + new JsonSerializerSettings + { + ContractResolver = new WritablePropertiesOnlyResolver() + })); + + UiThread.RunOnIdle(() => + { + UserSettings.Instance.set(UserSettingsKey.ActiveThemeName, themeset.ThemeName); + + //Set new user selected Default + ActiveTheme.Instance = themeset.Theme.Colors; + (ActiveTheme.Instance as ThemeColors).DisabledColor = themeset.Theme.GetBorderColor(20); + + // Explicitly fire ReloadAll in response to user interaction + ApplicationController.Instance.ReloadAll(); + }); + } + + private class WritablePropertiesOnlyResolver : DefaultContractResolver + { + protected override IList CreateProperties(Type type, MemberSerialization memberSerialization) + { + IList props = base.CreateProperties(type, memberSerialization); + return props.Where(p => p.Writable).ToList(); + } + } + } + + public class ThemeSet + { + public string ThemeName { get; set; } + + public ThemeConfig Theme { get; set; } + + public ThemeConfig MenuTheme { get; set; } } public class ApplicationController @@ -127,9 +224,9 @@ namespace MatterHackers.MatterControl private Dictionary> objectEditorsByType; - public ThemeConfig Theme { get; set; } + public ThemeConfig Theme => AppContext.Theme; - public ThemeConfig MenuTheme { get; set; } + public ThemeConfig MenuTheme => AppContext.MenuTheme; public RunningTasksConfig Tasks { get; set; } = new RunningTasksConfig(); @@ -841,10 +938,9 @@ namespace MatterHackers.MatterControl public ApplicationController() { - // Initialize the AppContext theme object which will sync its content with Agg ActiveTheme changes - this.Theme = new ThemeConfig(); this.Thumbnails = new ThumbnailsConfig(this.Theme); - this.MenuTheme = new ThemeConfig(); + + this.RebuildSceneOperations(this.Theme); HelpArticle helpArticle = null; @@ -860,13 +956,6 @@ namespace MatterHackers.MatterControl this.HelpArticles = helpArticle ?? new HelpArticle(); - ActiveTheme.ThemeChanged.RegisterEvent((s, e) => - { - ChangeToTheme(ActiveTheme.Instance); - }, ref unregisterEvents); - - this.ChangeToTheme(ActiveTheme.Instance); - Object3D.AssetsPath = Path.Combine(ApplicationDataStorage.Instance.ApplicationLibraryDataPath, "Assets"); using (var meshSteam = AggContext.StaticData.OpenStream(Path.Combine("Stls", "missing.stl"))) @@ -1349,28 +1438,6 @@ namespace MatterHackers.MatterControl } } - private void ChangeToTheme(IThemeColors themeColors) - { - this.Theme.RebuildTheme(themeColors); - - var json = JsonConvert.SerializeObject(ActiveTheme.Instance); - - var clonedColors = JsonConvert.DeserializeObject(json); - clonedColors.IsDarkTheme = false; - clonedColors.Name = "MenuColors"; - clonedColors.PrimaryTextColor = new Color("#222"); - clonedColors.SecondaryTextColor = new Color("#666"); - clonedColors.PrimaryBackgroundColor = new Color("#fff"); - clonedColors.SecondaryBackgroundColor = new Color("#ddd"); - clonedColors.TertiaryBackgroundColor = new Color("#ccc"); - - this.MenuTheme.RebuildTheme(clonedColors); - - this.RebuildSceneOperations(this.Theme); - - AggContext.StaticData.PurgeCache(); - } - public bool RunAnyRequiredPrinterSetup(PrinterConfig printer, ThemeConfig theme) { if (PrintLevelingData.NeedsToBeRun(printer)) @@ -1637,23 +1704,6 @@ namespace MatterHackers.MatterControl ApplicationSettings.Instance.ReleaseClientToken(); } - internal static void LoadTheme() - { - string activeThemeName = UserSettings.Instance.get(UserSettingsKey.ActiveThemeName); - if (!string.IsNullOrEmpty(activeThemeName)) - { - ActiveTheme.Instance = ActiveTheme.GetThemeColors(activeThemeName); - } - else if (!string.IsNullOrEmpty(OemSettings.Instance.ThemeColor)) - { - ActiveTheme.Instance = ActiveTheme.GetThemeColors(OemSettings.Instance.ThemeColor); - } - else - { - ActiveTheme.Instance = ActiveTheme.GetThemeColors("Blue - Light"); - } - } - public static ApplicationController Instance { get @@ -2645,18 +2695,15 @@ namespace MatterHackers.MatterControl var systemWindow = new RootSystemWindow(width, height); - // Load theme - ApplicationController.LoadTheme(); - var overlay = new GuiWidget() { - BackgroundColor = ActiveTheme.Instance.PrimaryBackgroundColor + BackgroundColor = AppContext.Theme.ActiveTabColor, }; overlay.AnchorAll(); systemWindow.AddChild(overlay); - var mutedAccentColor = new Color(ActiveTheme.Instance.PrimaryAccentColor, 185).OverlayOn(Color.White).ToColor(); + var mutedAccentColor = AppContext.Theme.SplashAccentColor; var spinner = new LogoSpinner(overlay, rotateX: -0.05) { @@ -2673,7 +2720,7 @@ namespace MatterHackers.MatterControl }; overlay.AddChild(progressPanel); - progressPanel.AddChild(statusText = new TextWidget("", textColor: ActiveTheme.Instance.PrimaryTextColor) + progressPanel.AddChild(statusText = new TextWidget("", textColor: AppContext.Theme.Colors.PrimaryTextColor) { MinimumSize = new Vector2(200, 30), HAnchor = HAnchor.Center, diff --git a/MatterControlLib/ApplicationView/PrinterModels.cs b/MatterControlLib/ApplicationView/PrinterModels.cs index f40186bc1..ef91558b5 100644 --- a/MatterControlLib/ApplicationView/PrinterModels.cs +++ b/MatterControlLib/ApplicationView/PrinterModels.cs @@ -487,7 +487,11 @@ namespace MatterHackers.MatterControl new Vector4(jerkVelocity, jerkVelocity, jerkVelocity, jerkVelocity), new Vector4(multiplier, multiplier, multiplier, multiplier), cancellationToken, progressReporter); - this.GCodeRenderer = new GCodeRenderer(loadedGCode); + + this.GCodeRenderer = new GCodeRenderer(loadedGCode) + { + Gray = AppContext.Theme.Colors.IsDarkTheme ? Color.DarkGray : Color.Gray + }; this.RenderInfo = new GCodeRenderInfo( 0, diff --git a/MatterControlLib/ApplicationView/ThemeConfig.cs b/MatterControlLib/ApplicationView/ThemeConfig.cs index 70c1f0a4c..9066af8cc 100644 --- a/MatterControlLib/ApplicationView/ThemeConfig.cs +++ b/MatterControlLib/ApplicationView/ThemeConfig.cs @@ -41,7 +41,6 @@ namespace MatterHackers.MatterControl using MatterHackers.MatterControl.PartPreviewWindow; using MatterHackers.MatterControl.PrinterCommunication; using MatterHackers.VectorMath; - using Newtonsoft.Json; public class ThemeConfig { @@ -72,7 +71,7 @@ namespace MatterHackers.MatterControl /// /// Indicates if icons should be inverted due to black source images on a dark theme /// - public bool InvertIcons => this.Colors.IsDarkTheme; + public bool InvertIcons => this?.Colors.IsDarkTheme ?? false; internal void ApplyPrimaryActionStyle(GuiWidget guiWidget) { @@ -138,20 +137,18 @@ namespace MatterHackers.MatterControl } } - public IThemeColors Colors { get; set; } = new ThemeColors(); + public ThemeColors Colors { get; set; } = new ThemeColors(); public PresetColors PresetColors { get; set; } = new PresetColors(); - public Color SlightShade { get; } = new Color(0, 0, 0, 40); - public Color MinimalShade { get; } = new Color(0, 0, 0, 15); - public Color Shade { get; } = new Color(0, 0, 0, 120); - public Color DarkShade { get; } = new Color(0, 0, 0, 190); - - public Color MinimalHighlight { get; } = new Color(255, 255, 255, 15); + public Color SlightShade { get; set; } + public Color MinimalShade { get; set; } + public Color Shade { get; set; } + public Color DarkShade { get; set; } public Color ActiveTabColor { get; set; } public Color TabBarBackground { get; set; } public Color InactiveTabColor { get; set; } - public Color InteractionLayerOverlayColor { get; private set; } + public Color InteractionLayerOverlayColor { get; set; } public TextWidget CreateHeading(string text) { @@ -161,8 +158,8 @@ namespace MatterHackers.MatterControl }; } - public Color SplitterBackground { get; private set; } = new Color(0, 0, 0, 60); - public Color TabBodyBackground { get; private set; } + public Color SplitterBackground { get; set; } = new Color(0, 0, 0, 60); + public Color TabBodyBackground { get; set; } public Color ToolbarButtonBackground { get; set; } = Color.Transparent; public Color ToolbarButtonHover => this.SlightShade; public Color ToolbarButtonDown => this.MinimalShade; @@ -173,6 +170,11 @@ namespace MatterHackers.MatterControl public ImageBuffer GeneratingThumbnailIcon { get; private set; } + public Color LightTextColor { get; set; } + public Color BorderColor { get; set; } + public Color DisabledColor { get; set; } + public Color SplashAccentColor { get; set; } + public GuiWidget CreateSearchButton() { return new IconButton(AggContext.StaticData.LoadIcon("icon_search_24x24.png", 16, 16, this.InvertIcons), this) @@ -184,49 +186,27 @@ namespace MatterHackers.MatterControl public ThemeConfig() { this.SeparatorMargin = (this.ButtonSpacing * 2).Clone(left: this.ButtonSpacing.Right); + this.RebuildTheme(); } - public void RebuildTheme(IThemeColors colors) + public void SetDefaults() + { + this.DisabledColor = new Color(this.LightTextColor, 50); + this.SplashAccentColor = new Color(this.Colors.PrimaryAccentColor, 185).OverlayOn(Color.White).ToColor(); + } + + public void RebuildTheme() { int size = (int)(16 * GuiWidget.DeviceScale); - if (AggContext.OperatingSystem == OSType.Android) - { - restoreNormal = ColorCircle(size, new Color(200, 0, 0)); - } - else - { - restoreNormal = ColorCircle(size, Color.Transparent); - } - + // On Android, use red icon as no hover events, otherwise transparent and red on hover + restoreNormal = ColorCircle(size, (AggContext.OperatingSystem == OSType.Android) ? new Color(200, 0, 0) : Color.Transparent); restoreHover = ColorCircle(size, new Color("#DB4437")); restorePressed = ColorCircle(size, new Color(255, 0, 0)); - this.Colors = colors; - this.GeneratingThumbnailIcon = AggContext.StaticData.LoadIcon("building_thumbnail_40x40.png", 40, 40, this.InvertIcons); - DefaultThumbView.ThumbColor = new Color(colors.PrimaryTextColor, 30); - - this.TabBodyBackground = this.ResolveColor( - colors.TertiaryBackgroundColor, - new Color( - Color.White, - (colors.IsDarkTheme) ? 3 : 25)); - - this.ActiveTabColor = this.TabBodyBackground; - this.TabBarBackground = this.ActiveTabColor.AdjustLightness(0.85).ToColor(); - this.ThumbnailBackground = Color.Transparent; - this.AccentMimimalOverlay = new Color(this.Colors.PrimaryAccentColor, 50); - - // Active tab color with slight transparency - this.InteractionLayerOverlayColor = new Color(this.ActiveTabColor, 240); - - float alpha0to1 = (colors.IsDarkTheme ? 20 : 60) / 255.0f; - - this.InactiveTabColor = ResolveColor(colors.PrimaryBackgroundColor, new Color(Color.White, this.SlightShade.alpha)); - - this.SplitterBackground = this.ActiveTabColor.AdjustLightness(0.87).ToColor(); + DefaultThumbView.ThumbColor = new Color(this.Colors.PrimaryTextColor, 30); } public JogControls.MoveButton CreateMoveButton(PrinterConfig printer, string label, PrinterConnection.Axis axis, double movementFeedRate, bool levelingButtons = false) @@ -316,7 +296,7 @@ namespace MatterHackers.MatterControl public Color GetBorderColor(int alpha) { - return new Color(this.Colors.SecondaryTextColor, alpha); + return new Color(this.BorderColor, alpha); } // Compute a fixed color from a source and a target alpha diff --git a/MatterControlLib/ApplicationView/Themes/ActiveTheme.cs b/MatterControlLib/ApplicationView/Themes/ActiveTheme.cs new file mode 100644 index 000000000..5d2eab25b --- /dev/null +++ b/MatterControlLib/ApplicationView/Themes/ActiveTheme.cs @@ -0,0 +1,58 @@ +/* +Copyright (c) 2018, Kevin Pope, John Lewin +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + +using MatterHackers.MatterControl; + +namespace MatterHackers.Agg.UI +{ + public static class ActiveTheme + { + public static RootedObjectEventHandler ThemeChanged = new RootedObjectEventHandler(); + + private static IThemeColors activeTheme = ThemeColors.Create(new Color(172, 25, 61) /* Classic Red */); + + public static IThemeColors Instance + { + get => activeTheme; + set + { + if (value != activeTheme) + { + activeTheme = value; + OnThemeChanged(); + } + } + } + + private static void OnThemeChanged() + { + ThemeChanged?.CallEvents(null, null); + } + } +} \ No newline at end of file diff --git a/MatterControlLib/ApplicationView/Themes/ClassicColorsTheme.cs b/MatterControlLib/ApplicationView/Themes/ClassicColorsTheme.cs new file mode 100644 index 000000000..bbc6fac62 --- /dev/null +++ b/MatterControlLib/ApplicationView/Themes/ClassicColorsTheme.cs @@ -0,0 +1,143 @@ +/* +Copyright (c) 2018, Lars Brubaker, John Lewin +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + +using MatterHackers.Agg; +using MatterHackers.Agg.UI; + +namespace MatterHackers.MatterControl +{ + using System; + using System.Collections.Generic; + using System.Linq; + using Newtonsoft.Json; + + public class ClassicColorsTheme : IColorTheme + { + public ClassicColorsTheme() + { + this.Colors = namedColors.Values.Take(namedColors.Count / 2); + this.DefaultColor = namedColors["Red - Dark"]; + this.DefaultMode = "Dark"; + + this.Modes = new[] { "Dark", "Light" }; + } + + public Color DefaultColor { get; } + public string DefaultMode { get; } + public IEnumerable Colors { get; } + public IEnumerable Modes { get; } + + private static Dictionary namedColors = new Dictionary() + { + //Dark themes + { "Red - Dark", new Color(172, 25, 61) }, + { "Pink - Dark", new Color(220, 79, 173) }, + { "Orange - Dark", new Color(255, 129, 25) }, + { "Green - Dark", new Color(0, 138, 23) }, + { "Blue - Dark", new Color(0, 75, 139) }, + { "Teal - Dark", new Color(0, 130, 153) }, + { "Light Blue - Dark", new Color(93, 178, 255) }, + { "Purple - Dark", new Color(70, 23, 180) }, + { "Magenta - Dark", new Color(140, 0, 149) }, + { "Grey - Dark", new Color(88, 88, 88) }, + + //Light themes + { "Red - Light", new Color(172, 25, 61) }, + { "Pink - Light", new Color(220, 79, 173) }, + { "Orange - Light", new Color(255, 129, 25) }, + { "Green - Light", new Color(0, 138, 23) }, + { "Blue - Light", new Color(0, 75, 139) }, + { "Teal - Light", new Color(0, 130, 153) }, + { "Light Blue - Light", new Color(93, 178, 255) }, + { "Purple - Light", new Color(70, 23, 180) }, + { "Magenta - Light", new Color(140, 0, 149) }, + { "Grey - Light", new Color(88, 88, 88) }, + }; + + public ThemeSet GetTheme(string mode, Color accentColor) + { + bool darkTheme = mode == "Dark"; + Console.WriteLine("Requesting theme for " + accentColor.Html); + var colors = ThemeColors.Create(accentColor, darkTheme); + + Console.WriteLine("Generated: PrimaryAccent: " + colors.PrimaryAccentColor + " source: " + colors.SourceColor); + + return ThemeFromColors(colors, darkTheme); + } + + public static ThemeSet ThemeFromColors(ThemeColors colors, bool darkTheme) + { + var json = JsonConvert.SerializeObject(colors); + + var clonedColors = JsonConvert.DeserializeObject(json); + clonedColors.IsDarkTheme = false; + clonedColors.PrimaryTextColor = new Color("#222"); + clonedColors.PrimaryBackgroundColor = new Color("#fff"); + + return new ThemeSet() + { + Theme = BuildTheme(colors, darkTheme), + MenuTheme = BuildTheme(clonedColors, darkTheme) + }; + } + + private static ThemeConfig BuildTheme(ThemeColors colors, bool darkTheme) + { + var theme = new ThemeConfig(); + + theme.Colors = colors; + + theme.SlightShade = new Color(0, 0, 0, 40); + theme.MinimalShade = new Color(0, 0, 0, 15); + theme.Shade = new Color(0, 0, 0, 120); + theme.DarkShade = new Color(0, 0, 0, 190); + + theme.ActiveTabColor = theme.ResolveColor( + new Color(darkTheme ? "#3E3E3E" : "#BEBEBE"), + new Color( + Color.White, + (colors.IsDarkTheme) ? 3 : 25)); + theme.TabBarBackground = theme.ActiveTabColor.AdjustLightness(0.85).ToColor(); + theme.ThumbnailBackground = theme.MinimalShade; + theme.AccentMimimalOverlay = new Color(theme.Colors.PrimaryAccentColor, 50); + theme.InteractionLayerOverlayColor = new Color(theme.ActiveTabColor, 240); + theme.InactiveTabColor = theme.ResolveColor(theme.ActiveTabColor, new Color(Color.White, theme.MinimalShade.alpha)); + + theme.SplitterBackground = theme.ActiveTabColor.AdjustLightness(0.87).ToColor(); + + theme.BorderColor = new Color(darkTheme ? "#C8C8C8" : "#333"); + + theme.SplashAccentColor = theme.Colors.PrimaryAccentColor; + + theme.PresetColors = new PresetColors(); + + return theme; + } + } +} \ No newline at end of file diff --git a/MatterControlLib/ApplicationView/Themes/IColorTheme.cs b/MatterControlLib/ApplicationView/Themes/IColorTheme.cs new file mode 100644 index 000000000..e354b337d --- /dev/null +++ b/MatterControlLib/ApplicationView/Themes/IColorTheme.cs @@ -0,0 +1,44 @@ +/* +Copyright (c) 2018, John Lewin +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + +using MatterHackers.Agg; + +namespace MatterHackers.MatterControl +{ + using System.Collections.Generic; + + public interface IColorTheme + { + string DefaultMode { get; } + Color DefaultColor { get; } + ThemeSet GetTheme(string mode, Color accentColor); + IEnumerable Colors { get; } + IEnumerable Modes { get; } + } +} \ No newline at end of file diff --git a/MatterControlLib/ApplicationView/Themes/IThemeColors.cs b/MatterControlLib/ApplicationView/Themes/IThemeColors.cs new file mode 100644 index 000000000..4cdedde8c --- /dev/null +++ b/MatterControlLib/ApplicationView/Themes/IThemeColors.cs @@ -0,0 +1,46 @@ +/* +Copyright (c) 2016, Kevin Pope, John Lewin +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + +using System; + +namespace MatterHackers.Agg.UI +{ + public interface IThemeColors + { + bool IsDarkTheme { get; } + + Color PrimaryBackgroundColor { get; } + + Color PrimaryTextColor { get; } + + Color PrimaryAccentColor { get; } + + Color DisabledColor { get; } + } +} \ No newline at end of file diff --git a/MatterControlLib/ApplicationView/Themes/SolarizedTheme.cs b/MatterControlLib/ApplicationView/Themes/SolarizedTheme.cs new file mode 100644 index 000000000..b5c38c65d --- /dev/null +++ b/MatterControlLib/ApplicationView/Themes/SolarizedTheme.cs @@ -0,0 +1,243 @@ +/* +Copyright (c) 2018, John Lewin +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + +using MatterHackers.Agg; +using MatterHackers.Agg.UI; + +namespace MatterHackers.MatterControl +{ + using System.Collections.Generic; + using Agg.Image; + + public class SolarizedTheme : IColorTheme + { + private SolarizedColors solarized = new SolarizedColors(); + + public SolarizedTheme() + { + this.Colors = new[] + { + solarized.Blue, + solarized.Cyan, + solarized.Green, + solarized.Magenta, + solarized.Orange, + solarized.Red, + solarized.Violet, + solarized.Yellow + }; + + this.DefaultColor = solarized.Yellow; + this.DefaultMode = "Dark"; + + this.Modes = new[] { "Dark", "Light" }; + } + + public Color DefaultColor { get; } + public string DefaultMode { get; } + public IEnumerable Colors { get; } + public IEnumerable Modes { get; } + + public ThemeSet GetTheme(string mode, Color accentColor) + { + bool darkTheme = mode == "Dark"; + var baseColors = darkTheme ? solarized.Dark : solarized.Light; + + return new ThemeSet() + { + Theme = new ThemeConfig() + { + Colors = new ThemeColors() + { + IsDarkTheme = darkTheme, + PrimaryBackgroundColor = new Color("#003F69"), + PrimaryTextColor = baseColors.Base0, + PrimaryAccentColor = accentColor, + SourceColor = accentColor + }, + PresetColors = new PresetColors() + { + MaterialPreset = new Color("#FF7F00"), + QualityPreset = new Color("#FFFF00"), + UserOverride = new Color("#445FDC96") + }, + + SlightShade = new Color("#00000028"), + MinimalShade = new Color("#0000000F"), + Shade = new Color("#00000078"), + DarkShade = new Color("#000000BE"), + + ActiveTabColor = baseColors.Base03, + TabBarBackground = baseColors.Base03.Blend(Color.Black, darkTheme ? 0.4 : 0.1), + //TabBarBackground = new Color(darkTheme ? "#00212B" : "#EEE8D5"), + + InactiveTabColor = baseColors.Base02, + InteractionLayerOverlayColor = new Color(baseColors.Base03, 240), + SplitterBackground = baseColors.Base02, + TabBodyBackground = new Color("#00000000"), + ToolbarButtonBackground = new Color("#00000000"), + ThumbnailBackground = new Color("#00000000"), + AccentMimimalOverlay = new Color(accentColor, 80), + BorderColor = baseColors.Base0, + SplashAccentColor = new Color("#eee") + }, + MenuTheme = (darkTheme) ? this.DarkMenu(baseColors, accentColor) : this.LightMenu(baseColors, accentColor) + }; + } + + private ThemeConfig LightMenu(BaseColors baseColors, Color accentColor) + { + var backgroundColor = new Color("#f1f1f1"); + + return new ThemeConfig() + { + Colors = new ThemeColors() + { + IsDarkTheme = false, + PrimaryBackgroundColor = backgroundColor, + PrimaryTextColor = new Color("#555"), + PrimaryAccentColor = accentColor, + SourceColor = accentColor + }, + PresetColors = new PresetColors() + { + MaterialPreset = new Color("#FF7F00"), + QualityPreset = new Color("#FFFF00"), + UserOverride = new Color("#445FDC96") + }, + SlightShade = new Color("#00000028"), + MinimalShade = new Color("#0000000F"), + Shade = new Color("#00000078"), + DarkShade = new Color("#000000BE"), + + ActiveTabColor = backgroundColor, + TabBarBackground = new Color("#B1B1B1"), + InactiveTabColor = new Color("#D0D0D0"), + InteractionLayerOverlayColor = new Color("#D0D0D0F0"), + SplitterBackground = new Color("#B5B5B5"), + TabBodyBackground = new Color("#00000000"), + ToolbarButtonBackground = new Color("#00000000"), + ThumbnailBackground = new Color("#00000000"), + AccentMimimalOverlay = new Color(accentColor, 80), + BorderColor = new Color("#666666"), + }; + } + + private ThemeConfig DarkMenu(BaseColors baseColors, Color accentColor) + { + var backgroundColor = new Color("#2d2f31"); + + return new ThemeConfig() + { + Colors = new ThemeColors() + { + IsDarkTheme = true, + PrimaryBackgroundColor = backgroundColor, + PrimaryTextColor = baseColors.Base1, + PrimaryAccentColor = accentColor, + SourceColor = accentColor + }, + PresetColors = new PresetColors() + { + MaterialPreset = new Color("#FF7F00"), + QualityPreset = new Color("#FFFF00"), + UserOverride = new Color("#445FDC96") + }, + SlightShade = new Color("#00000028"), + MinimalShade = new Color("#0000000F"), + Shade = new Color("#00000078"), + DarkShade = new Color("#000000BE"), + + ActiveTabColor = backgroundColor, + TabBarBackground = new Color("#B1B1B1"), + InactiveTabColor = new Color("#D0D0D0"), + InteractionLayerOverlayColor = new Color("#D0D0D0F0"), + SplitterBackground = new Color("#B5B5B5"), + TabBodyBackground = new Color("#00000000"), + ToolbarButtonBackground = new Color("#00000000"), + ThumbnailBackground = new Color("#00000000"), + AccentMimimalOverlay = new Color(accentColor, 80), + BorderColor = new Color("#c8c8c8"), + }; + } + + public Color GetAdjustedAccentColor(Color accentColor, Color backgroundColor) + { + return ThemeColors.GetAdjustedAccentColor(accentColor, backgroundColor); + } + + private class SolarizedColors + { + public BaseColors Dark { get; } = new BaseColors() + { + Base03 = new Color("#002b36"), + Base02 = new Color("#073642"), + Base01 = new Color("#586e75"), + Base00 = new Color("#657b83"), + Base0 = new Color("#839496"), + Base1 = new Color("#93a1a1"), + Base2 = new Color("#eee8d5"), + Base3 = new Color("#fdf6e3") + }; + + public BaseColors Light { get; } = new BaseColors() + { + Base03 = new Color("#fdf6e3"), + Base02 = new Color("#eee8d5"), + Base01 = new Color("#93a1a1"), + Base00 = new Color("#839496"), + Base0 = new Color("#657b83"), + Base1 = new Color("#586e75"), + Base2 = new Color("#073642"), + Base3 = new Color("#002b36") + }; + + public Color Yellow { get; } = new Color("#b58900"); + public Color Orange { get; } = new Color("#cb4b16"); + public Color Red { get; } = new Color("#dc322f"); + public Color Magenta { get; } = new Color("#d33682"); + public Color Violet { get; } = new Color("#6c71c4"); + public Color Blue { get; } = new Color("#268bd2"); + public Color Cyan { get; } = new Color("#2aa198"); + public Color Green { get; } = new Color("#859900"); + } + + private class BaseColors + { + public Color Base03 { get; set; } + public Color Base02 { get; set; } + public Color Base01 { get; set; } + public Color Base00 { get; set; } + public Color Base0 { get; set; } + public Color Base1 { get; set; } + public Color Base2 { get; set; } + public Color Base3 { get; set; } + } + } +} \ No newline at end of file diff --git a/MatterControlLib/ApplicationView/Themes/ThemeColors.cs b/MatterControlLib/ApplicationView/Themes/ThemeColors.cs new file mode 100644 index 000000000..188267cc8 --- /dev/null +++ b/MatterControlLib/ApplicationView/Themes/ThemeColors.cs @@ -0,0 +1,67 @@ +/* +Copyright (c) 2016, Kevin Pope, John Lewin +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + +using System; + +namespace MatterHackers.Agg.UI +{ + public class ThemeColors: IThemeColors + { + public bool IsDarkTheme { get; set; } + + public Color PrimaryBackgroundColor { get; set; } + + public Color PrimaryTextColor { get; set; } + + public Color PrimaryAccentColor { get; set; } + + public Color SourceColor { get; set; } + + public Color DisabledColor { get; set; } + + public static ThemeColors Create(Color accentColor, bool darkTheme = true) + { + var primaryBackgroundColor = new Color(darkTheme ? "#444" : "#D0D0D0"); + + return new ThemeColors + { + IsDarkTheme = darkTheme, + PrimaryBackgroundColor = primaryBackgroundColor, + PrimaryTextColor = new Color(darkTheme ? "#FFFFFF" : "#222"), + PrimaryAccentColor = GetAdjustedAccentColor(accentColor, primaryBackgroundColor), + SourceColor = accentColor, + }; + } + + public static Color GetAdjustedAccentColor(Color accentColor, Color backgroundColor) + { + return accentColor.AdjustContrast(backgroundColor).ToColor(); + } + } +} \ No newline at end of file diff --git a/MatterControlLib/ApplicationView/WidescreenPanel.cs b/MatterControlLib/ApplicationView/WidescreenPanel.cs index a863a2bd3..e9cd6d121 100644 --- a/MatterControlLib/ApplicationView/WidescreenPanel.cs +++ b/MatterControlLib/ApplicationView/WidescreenPanel.cs @@ -27,14 +27,11 @@ of the authors and should not be interpreted as representing official policies, either expressed or implied, of the FreeBSD Project. */ -using System; -using MatterHackers.Agg; using MatterHackers.Agg.Platform; using MatterHackers.Agg.UI; using MatterHackers.MatterControl.ConfigurationPage; using MatterHackers.MatterControl.CustomWidgets; using MatterHackers.MatterControl.PartPreviewWindow; -using MatterHackers.MatterControl.PrintLibrary; using MatterHackers.VectorMath; namespace MatterHackers.MatterControl @@ -54,7 +51,7 @@ namespace MatterHackers.MatterControl this.AnchorAll(); this.Name = "WidescreenPanel"; - this.BackgroundColor = theme.Colors.PrimaryBackgroundColor; + this.BackgroundColor = theme.ActiveTabColor; // Push TouchScreenMode into GuiWidget GuiWidget.TouchScreenMode = UserSettings.Instance.IsTouchScreen; @@ -83,6 +80,7 @@ namespace MatterHackers.MatterControl HAnchor = HAnchor.Absolute, VAnchor = VAnchor.Fit, Width = 500, + MinimumSize = new Vector2(400, 0) }; var row = new FlowLayoutWidget() diff --git a/MatterControlLib/ConfigurationPage/ApplicationSettings/ApplicationSettingsView.cs b/MatterControlLib/ConfigurationPage/ApplicationSettings/ApplicationSettingsView.cs index 21da71961..e45f3a771 100644 --- a/MatterControlLib/ConfigurationPage/ApplicationSettings/ApplicationSettingsView.cs +++ b/MatterControlLib/ConfigurationPage/ApplicationSettings/ApplicationSettingsView.cs @@ -75,9 +75,6 @@ namespace MatterHackers.MatterControl.ConfigurationPage }; this.AddSettingsRow(updateMatterControl); - this.AddChild(new SettingsItem("Theme".Localize(), new GuiWidget(), theme)); - this.AddChild(this.GetThemeControl()); - var aboutMatterControl = new SettingsItem("About".Localize() + " MatterControl", theme); if (IntPtr.Size == 8) { @@ -130,70 +127,5 @@ namespace MatterHackers.MatterControl.ConfigurationPage this.AddChild(widget); widget.Padding = widget.Padding.Clone(right: 10); } - - private FlowLayoutWidget GetThemeControl() - { - var container = new FlowLayoutWidget(FlowDirection.TopToBottom) - { - Margin = new BorderDouble(left: 30) - }; - - // Determine if we should set the dark or light version of the theme - var activeThemeIndex = ActiveTheme.AvailableThemes.IndexOf(ApplicationController.Instance.Theme.Colors); - - var midPoint = ActiveTheme.AvailableThemes.Count / 2; - - int darkThemeIndex; - int lightThemeIndex; - - bool isLightTheme = activeThemeIndex >= midPoint; - if (isLightTheme) - { - lightThemeIndex = activeThemeIndex; - darkThemeIndex = activeThemeIndex - midPoint; - } - else - { - darkThemeIndex = activeThemeIndex; - lightThemeIndex = activeThemeIndex + midPoint; - } - - var darkPreview = new ThemePreviewButton(ActiveTheme.AvailableThemes[darkThemeIndex], !isLightTheme) - { - HAnchor = HAnchor.Absolute, - VAnchor = VAnchor.Absolute, - Width = 80, - Height = 65, - Margin = new BorderDouble(5, 15, 10, 10) - }; - - var lightPreview = new ThemePreviewButton(ActiveTheme.AvailableThemes[lightThemeIndex], isLightTheme) - { - HAnchor = HAnchor.Absolute, - VAnchor = VAnchor.Absolute, - Width = 80, - Height = 65, - Margin = new BorderDouble(5, 15, 10, 10) - }; - - // Add color selector - container.AddChild(new ThemeColorSelectorWidget(darkPreview, lightPreview) - { - Margin = new BorderDouble(right: 5) - }); - - var themePreviews = new FlowLayoutWidget() - { - HAnchor = HAnchor.Stretch, - VAnchor = VAnchor.Fit - }; - - themePreviews.AddChild(darkPreview); - themePreviews.AddChild(lightPreview); - - container.AddChild(themePreviews); - - return container; - } } } \ No newline at end of file diff --git a/MatterControlLib/ConfigurationPage/ApplicationSettings/ThemeColorPanel.cs b/MatterControlLib/ConfigurationPage/ApplicationSettings/ThemeColorPanel.cs new file mode 100644 index 000000000..88be0aac9 --- /dev/null +++ b/MatterControlLib/ConfigurationPage/ApplicationSettings/ThemeColorPanel.cs @@ -0,0 +1,241 @@ +/* +Copyright (c) 2018, Kevin Pope, John Lewin +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + +using System; +using System.Collections.Generic; +using System.Linq; +using MatterHackers.Agg; +using MatterHackers.Agg.Image; +using MatterHackers.Agg.Platform; +using MatterHackers.Agg.UI; +using MatterHackers.MatterControl.PartPreviewWindow; + +namespace MatterHackers.MatterControl.ConfigurationPage +{ + public class ThemeColorPanel : FlowLayoutWidget + { + private Color lastColor; + private AccentColorsWidget colorSelector; + + private IColorTheme _themeProvider; + private GuiWidget previewButtonPanel; + + public ThemeColorPanel(ThemeConfig activeTheme) + : base (FlowDirection.TopToBottom) + { + string currentProviderName = UserSettings.Instance.get(UserSettingsKey.ThemeName) ?? ""; + + if (AppContext.ThemeProviders.TryGetValue(currentProviderName, out IColorTheme currentProvider)) + { + _themeProvider = currentProvider; + } + else + { + _themeProvider = AppContext.ThemeProviders.Values.First(); + } + + this.SelectionColor = activeTheme.GetBorderColor(80); + + // Add color selector + this.AddChild(colorSelector = new AccentColorsWidget(this) + { + Margin = new BorderDouble(activeTheme.DefaultContainerPadding, 0) + }); + + this.AddChild(previewButtonPanel = new FlowLayoutWidget() + { + HAnchor = HAnchor.Stretch, + VAnchor = VAnchor.Fit, + BackgroundColor = this.SelectionColor, + Padding = new BorderDouble(left: colorSelector.ColorButtons.First().Border.Left) + }); + + this.CreateThemeModeButtons(); + } + + public ImageBuffer CheckMark { get; } = AggContext.StaticData.LoadIcon("426.png", 16, 16, invertImage: true); + + public Color SelectionColor { get; private set; } + + public IColorTheme ThemeProvider + { + get => _themeProvider; + set + { + _themeProvider = value; + + var previewColor = _themeProvider.Colors.First(); + + colorSelector.RebuildColorButtons(); + + this.CreateThemeModeButtons(); + + this.PreviewTheme(previewColor); + } + } + private void CreateThemeModeButtons() + { + previewButtonPanel.CloseAllChildren(); + + var theme = AppContext.Theme; + + var accentColor = theme.Colors.PrimaryAccentColor; + + if (!_themeProvider.Colors.Contains(accentColor)) + { + accentColor = _themeProvider.DefaultColor; + } + + var activeMode = UserSettings.Instance.get(UserSettingsKey.ThemeMode); + + foreach (var mode in _themeProvider.Modes) + { + var themeset = _themeProvider.GetTheme(mode, accentColor); + + previewButtonPanel.AddChild(new ThemePreviewButton(themeset.Theme, this) + { + HAnchor = HAnchor.Absolute, + VAnchor = VAnchor.Absolute, + Width = 80, + Height = 65, + Mode = mode, + Margin = new BorderDouble(theme.DefaultContainerPadding, theme.DefaultContainerPadding, 0, theme.DefaultContainerPadding), + Border = 1, + IsActive = mode == activeMode, + BorderColor = theme.GetBorderColor(20), + }); + } + } + + public void PreviewTheme(Color sourceAccentColor) + { + foreach (var previewButton in previewButtonPanel.Children()) + { + previewButton.PreviewThemeColor(sourceAccentColor); + } + } + + public void SetThemeColor(Color accentColor, string mode = null) + { + lastColor = accentColor; + + foreach (var colorButton in colorSelector.ColorButtons) + { + colorButton.BorderColor = (colorButton.SourceColor == accentColor) ? Color.White : Color.Transparent; + } + + if (mode == null) + { + mode = this.ThemeProvider.DefaultMode; + + var lastMode = UserSettings.Instance.get(UserSettingsKey.ThemeMode); + if (this.ThemeProvider.Modes.Contains(lastMode)) + { + mode = lastMode; + } + } + + Console.WriteLine("Getting/setting theme for " + accentColor.Html); + + AppContext.SetTheme(this.ThemeProvider.GetTheme(mode, accentColor)); + previewButtonPanel.BackgroundColor = this.SelectionColor; + } + + public class AccentColorsWidget : FlowLayoutWidget + { + private int containerHeight = (int)(20 * GuiWidget.DeviceScale); + private ThemeColorPanel themeColorPanel; + + public AccentColorsWidget(ThemeColorPanel themeColorPanel) + { + this.Padding = new BorderDouble(2, 0); + this.themeColorPanel = themeColorPanel; + + this.RebuildColorButtons(); + } + + private List colorButtons = new List(); + + public IEnumerable ColorButtons => colorButtons; + + public void RebuildColorButtons() + { + this.CloseAllChildren(); + + colorButtons.Clear(); + + bool firstItem = true; + + foreach (var color in themeColorPanel.ThemeProvider.Colors) + { + var colorButton = CreateThemeButton(color); + colorButton.Width = containerHeight; + colorButton.BorderColor = (color == AppContext.Theme.Colors.SourceColor) ? themeColorPanel.SelectionColor : Color.Transparent; + + colorButtons.Add(colorButton); + + if (firstItem) + { + firstItem = false; + colorButton.Margin = colorButton.Margin.Clone(left: 0); + } + + this.AddChild(colorButton); + } + } + + public ColorButton CreateThemeButton(Color color) + { + var colorButton = new ColorButton(color) + { + Cursor = Cursors.Hand, + Width = containerHeight, + Height = containerHeight, + Border = 5, + }; + colorButton.Click += (s, e) => + { + themeColorPanel.SetThemeColor(colorButton.BackgroundColor); + }; + + colorButton.MouseEnterBounds += (s, e) => + { + foreach(var button in this.ColorButtons) + { + button.BorderColor = (button == colorButton) ? themeColorPanel.SelectionColor : Color.Transparent; + } + + themeColorPanel.PreviewTheme(colorButton.BackgroundColor); + }; + + return colorButton; + } + } + } +} \ No newline at end of file diff --git a/MatterControlLib/ConfigurationPage/ApplicationSettings/ThemePreviewButton.cs b/MatterControlLib/ConfigurationPage/ApplicationSettings/ThemePreviewButton.cs index 063d904a9..201159774 100644 --- a/MatterControlLib/ConfigurationPage/ApplicationSettings/ThemePreviewButton.cs +++ b/MatterControlLib/ConfigurationPage/ApplicationSettings/ThemePreviewButton.cs @@ -1,5 +1,5 @@ /* -Copyright (c) 2017, John Lewin +Copyright (c) 2018, John Lewin All rights reserved. Redistribution and use in source and binary forms, with or without @@ -28,8 +28,6 @@ either expressed or implied, of the FreeBSD Project. */ using MatterHackers.Agg; -using MatterHackers.Agg.ImageProcessing; -using MatterHackers.Agg.Platform; using MatterHackers.Agg.UI; using MatterHackers.VectorMath; @@ -38,17 +36,24 @@ namespace MatterHackers.MatterControl.ConfigurationPage public class ThemePreviewButton : GuiWidget { private GuiWidget accentColor; + private Color activeColor; private GuiWidget secondaryBackground; private GuiWidget tertiaryBackground; private GuiWidget icon1; private GuiWidget icon2; private GuiWidget icon3; - private string themeName = ""; + private ThemeConfig theme; + private ImageWidget activeIcon; - public ThemePreviewButton(IThemeColors theme, bool isActive) + public ThemePreviewButton(ThemeConfig theme, ThemeColorPanel themeColorPanel) { + this.theme = theme; + activeColor = theme.Colors.SourceColor; + + var primaryAccentColor = theme.Colors.PrimaryAccentColor; + this.Padding = 8; - this.BackgroundColor = theme.PrimaryBackgroundColor; + this.BackgroundColor = theme.ActiveTabColor; this.Cursor = Cursors.Hand; secondaryBackground = new GuiWidget() @@ -57,7 +62,7 @@ namespace MatterHackers.MatterControl.ConfigurationPage VAnchor = VAnchor.Stretch, Margin = new BorderDouble(0), Width = 20, - BackgroundColor = theme.SecondaryBackgroundColor, + BackgroundColor = theme.MinimalShade, }; this.AddChild(secondaryBackground); @@ -67,7 +72,7 @@ namespace MatterHackers.MatterControl.ConfigurationPage VAnchor = VAnchor.Absolute | VAnchor.Top, Height = 6, Margin = new BorderDouble(left: 25), - BackgroundColor = theme.PrimaryAccentColor, + BackgroundColor = primaryAccentColor, }; this.AddChild(accentColor); @@ -78,7 +83,7 @@ namespace MatterHackers.MatterControl.ConfigurationPage Height = 8, Width = 8, Margin = new BorderDouble(left: 6, top: 6), - BackgroundColor = theme.PrimaryAccentColor, + BackgroundColor = primaryAccentColor, }; this.AddChild(icon1); @@ -89,7 +94,7 @@ namespace MatterHackers.MatterControl.ConfigurationPage Height = 8, Width = 8, Margin = new BorderDouble(left: 6, top: 20), - BackgroundColor = theme.PrimaryAccentColor, + BackgroundColor = primaryAccentColor, }; this.AddChild(icon2); @@ -100,7 +105,7 @@ namespace MatterHackers.MatterControl.ConfigurationPage Height = 8, Width = 8, Margin = new BorderDouble(left: 6, top: 34), - BackgroundColor = theme.PrimaryAccentColor, + BackgroundColor = primaryAccentColor, }; this.AddChild(icon3); @@ -110,49 +115,53 @@ namespace MatterHackers.MatterControl.ConfigurationPage VAnchor = VAnchor.Absolute | VAnchor.Top, Height = 37, Margin = new BorderDouble(left: 25, top: 12), - BackgroundColor = theme.TertiaryBackgroundColor, + BackgroundColor = theme.SlightShade, }; this.AddChild(tertiaryBackground); - if (isActive) + this.AddChild(activeIcon = new ImageWidget(themeColorPanel.CheckMark) { - this.AddChild(new ImageWidget(AggContext.StaticData.LoadIcon("426.png", 16, 16, invertImage: true)) - { - HAnchor = HAnchor.Absolute, - VAnchor = VAnchor.Absolute, - OriginRelativeParent = new Vector2(45, 20) - }); - } + HAnchor = HAnchor.Absolute, + VAnchor = VAnchor.Absolute, + OriginRelativeParent = new Vector2(45, 20), + Visible = false + }); - var overlay = new GuiWidget(); - overlay.AnchorAll(); - overlay.Cursor = Cursors.Hand; + var overlay = new GuiWidget + { + VAnchor = VAnchor.Stretch, + HAnchor = HAnchor.Stretch, + Cursor = Cursors.Hand + }; overlay.Click += (s, e) => { - ThemeColorSelectorWidget.SetTheme(this.themeName); + UserSettings.Instance.set(UserSettingsKey.ThemeMode, this.Mode); + + // Activate the theme + themeColorPanel.SetThemeColor(activeColor, this.Mode); }; this.AddChild(overlay); } - public void SetThemeColors(IThemeColors theme) + public bool IsActive { - accentColor.BackgroundColor = theme.PrimaryAccentColor; - icon1.BackgroundColor = theme.PrimaryAccentColor; - icon2.BackgroundColor = theme.PrimaryAccentColor; - icon3.BackgroundColor = theme.PrimaryAccentColor; - - tertiaryBackground.BackgroundColor = theme.TertiaryBackgroundColor; - secondaryBackground.BackgroundColor = theme.SecondaryBackgroundColor; - - this.BackgroundColor = theme.PrimaryBackgroundColor; - this.themeName = theme.Name; + get => activeIcon.Visible; + set => activeIcon.Visible = value; } - public override void OnClick(MouseEventArgs mouseEvent) + public string Mode { get; internal set; } + + public void PreviewThemeColor(Color sourceColor) { - ThemeColorSelectorWidget.SetTheme(this.themeName); - base.OnClick(mouseEvent); + var adjustedAccentColor = sourceColor; + + accentColor.BackgroundColor = adjustedAccentColor; + icon1.BackgroundColor = adjustedAccentColor; + icon2.BackgroundColor = adjustedAccentColor; + icon3.BackgroundColor = adjustedAccentColor; + + activeColor = adjustedAccentColor; } } } \ No newline at end of file diff --git a/MatterControlLib/CustomWidgets/DockingTabControl.cs b/MatterControlLib/CustomWidgets/DockingTabControl.cs index 3691e3862..2f8a81242 100644 --- a/MatterControlLib/CustomWidgets/DockingTabControl.cs +++ b/MatterControlLib/CustomWidgets/DockingTabControl.cs @@ -225,7 +225,7 @@ namespace MatterHackers.MatterControl.CustomWidgets { Name = item.key + " Tab", InactiveTabColor = Color.Transparent, - ActiveTabColor = theme.TabBodyBackground + ActiveTabColor = theme.ActiveTabColor }; tab.CloseClicked += (s, e) => @@ -253,6 +253,7 @@ namespace MatterHackers.MatterControl.CustomWidgets Width = this.ConstrainedWidth, VAnchor = VAnchor.Stretch, HAnchor = HAnchor.Right, + BackgroundColor = theme.ActiveTabColor, SpliterBarColor = theme.SplitterBackground, SplitterWidth = theme.SplitterWidth, }; diff --git a/MatterControlLib/CustomWidgets/ThemeColorSelectorWidget.cs b/MatterControlLib/CustomWidgets/ThemeColorSelectorWidget.cs deleted file mode 100644 index 625738850..000000000 --- a/MatterControlLib/CustomWidgets/ThemeColorSelectorWidget.cs +++ /dev/null @@ -1,144 +0,0 @@ -/* -Copyright (c) 2017, Kevin Pope, John Lewin -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -The views and conclusions contained in the software and documentation are those -of the authors and should not be interpreted as representing official policies, -either expressed or implied, of the FreeBSD Project. -*/ - -using System; -using System.Linq; -using MatterHackers.Agg; -using MatterHackers.Agg.UI; -using MatterHackers.MatterControl.ConfigurationPage; -using MatterHackers.MatterControl.SlicerConfiguration; - -namespace MatterHackers.MatterControl -{ - public class ThemeColorSelectorWidget : FlowLayoutWidget - { - private ThemePreviewButton darkPreviewButton; - private ThemePreviewButton lightPreviewButton; - - private int containerHeight = (int)(30 * GuiWidget.DeviceScale + .5); - private int colorSelectSize = (int)(28 * GuiWidget.DeviceScale + .5); - - public ThemeColorSelectorWidget(ThemePreviewButton darkPreview, ThemePreviewButton lightPreview) - { - this.Padding = new BorderDouble(2, 0); - - this.darkPreviewButton = darkPreview; - this.lightPreviewButton = lightPreview; - - int themeCount = ActiveTheme.AvailableThemes.Count; - - var allThemes = ActiveTheme.AvailableThemes; - - int index = 0; - for (int x = 0; x < themeCount / 2; x++) - { - var themeButton = CreateThemeButton(allThemes[index], index); - themeButton.Width = containerHeight; - - this.AddChild(themeButton); - - index++; - } - - this.Width = containerHeight * (themeCount / 2); - } - - private int hoveredThemeIndex = 0; - private int midPoint = ActiveTheme.AvailableThemes.Count / 2; - - public Button CreateThemeButton(IThemeColors darkTheme, int darkThemeIndex) - { - var normal = new GuiWidget(colorSelectSize, colorSelectSize); - normal.BackgroundColor = darkTheme.SourceColor; - - var hover = new GuiWidget(colorSelectSize, colorSelectSize); - hover.BackgroundColor = darkTheme.SourceColor; - - var pressed = new GuiWidget(colorSelectSize, colorSelectSize); - pressed.BackgroundColor = darkTheme.SourceColor; - - var disabled = new GuiWidget(colorSelectSize, colorSelectSize); - - int lightThemeIndex = darkThemeIndex + midPoint; - var lightTheme = ActiveTheme.AvailableThemes[lightThemeIndex]; - - var colorButton = new Button(0, 0, new ButtonViewStates(normal, hover, pressed, disabled)); - colorButton.Cursor = Cursors.Hand; - colorButton.Click += (s, e) => - { - // Determine if we should set the dark or light version of the theme - var activeThemeIndex = ActiveTheme.AvailableThemes.IndexOf(ActiveTheme.Instance); - - bool useLightTheme = activeThemeIndex >= midPoint; - - SetTheme(darkThemeIndex, useLightTheme); - }; - - colorButton.MouseEnterBounds += (s, e) => - { - darkPreviewButton.SetThemeColors(darkTheme); - lightPreviewButton.SetThemeColors(lightTheme); - - hoveredThemeIndex = darkThemeIndex; - }; - - colorButton.MouseLeaveBounds += (s, e) => - { - // darkPreviewButton.SetThemeColors(ActiveTheme.Instance); - }; - - return colorButton; - } - - private static void SetTheme(int themeIndex, bool useLightTheme) - { - if (useLightTheme) - { - themeIndex += (ActiveTheme.AvailableThemes.Count / 2); - } - - // save it for this printer - SetTheme(ActiveTheme.AvailableThemes[themeIndex].Name); - } - - public static void SetTheme(string themeName) - { - UiThread.RunOnIdle(() => - { - UserSettings.Instance.set(UserSettingsKey.ActiveThemeName, themeName); - - //Set new user selected Default - ActiveTheme.Instance = ActiveTheme.GetThemeColors(themeName); - - // Explicitly fire ReloadAll in response to user interaction - ApplicationController.Instance.ReloadAll(); - }); - } - } -} \ No newline at end of file diff --git a/MatterControlLib/EeProm/EePromRepetierWindow.cs b/MatterControlLib/EeProm/EePromRepetierWindow.cs index a123ea125..2896ab034 100644 --- a/MatterControlLib/EeProm/EePromRepetierWindow.cs +++ b/MatterControlLib/EeProm/EePromRepetierWindow.cs @@ -120,7 +120,7 @@ namespace MatterHackers.MatterControl.EeProm var settingsAreaScrollBox = new ScrollableWidget(true); settingsAreaScrollBox.ScrollArea.HAnchor |= HAnchor.Stretch; settingsAreaScrollBox.AnchorAll(); - settingsAreaScrollBox.BackgroundColor = ActiveTheme.Instance.SecondaryBackgroundColor; + settingsAreaScrollBox.BackgroundColor = theme.MinimalShade; topToBottom.AddChild(settingsAreaScrollBox); settingsColumn = new FlowLayoutWidget(FlowDirection.TopToBottom) diff --git a/MatterControlLib/Library/ExtensionMethods.cs b/MatterControlLib/Library/ExtensionMethods.cs index 2c42ffd51..4295ff63e 100644 --- a/MatterControlLib/Library/ExtensionMethods.cs +++ b/MatterControlLib/Library/ExtensionMethods.cs @@ -89,7 +89,7 @@ namespace MatterHackers.MatterControl.Library public static ImageBuffer AlphaToPrimaryAccent(this ImageBuffer sourceImage) { - return sourceImage.AnyAlphaToColor(ActiveTheme.Instance.PrimaryAccentColor); + return sourceImage.AnyAlphaToColor(AppContext.Theme.Colors.PrimaryAccentColor); } } } diff --git a/MatterControlLib/Library/Widgets/LibraryWidget.cs b/MatterControlLib/Library/Widgets/LibraryWidget.cs index bf83ea412..316a016a8 100644 --- a/MatterControlLib/Library/Widgets/LibraryWidget.cs +++ b/MatterControlLib/Library/Widgets/LibraryWidget.cs @@ -562,7 +562,7 @@ namespace MatterHackers.MatterControl.PrintLibrary PointSize = 8, HAnchor = HAnchor.Right, VAnchor = VAnchor.Bottom, - TextColor = ActiveTheme.Instance.SecondaryTextColor, + TextColor = theme.BorderColor, Margin = new BorderDouble(6), AutoExpandBoundsToText = true, }; diff --git a/MatterControlLib/Library/Widgets/PrintLibraryWidget.cs b/MatterControlLib/Library/Widgets/PrintLibraryWidget.cs index f04d8b950..87cff082f 100644 --- a/MatterControlLib/Library/Widgets/PrintLibraryWidget.cs +++ b/MatterControlLib/Library/Widgets/PrintLibraryWidget.cs @@ -46,6 +46,7 @@ using MatterHackers.MatterControl.Library; using MatterHackers.MatterControl.PartPreviewWindow; using MatterHackers.MatterControl.PrinterCommunication; using MatterHackers.MatterControl.PrintQueue; +using Newtonsoft.Json; namespace MatterHackers.MatterControl.PrintLibrary { @@ -457,7 +458,7 @@ namespace MatterHackers.MatterControl.PrintLibrary PointSize = 8, HAnchor = HAnchor.Right, VAnchor = VAnchor.Bottom, - TextColor = ActiveTheme.Instance.SecondaryTextColor, + TextColor = theme.LightTextColor, Margin = new BorderDouble(6), AutoExpandBoundsToText = true, }; @@ -830,7 +831,7 @@ namespace MatterHackers.MatterControl.PrintLibrary var feedbackWindow = new SavePartsSheetFeedbackWindow( printItems.Count(), printItems.FirstOrDefault()?.Name, - ActiveTheme.Instance.PrimaryBackgroundColor); + theme.ActiveTabColor); var currentPartsInQueue = new PartsSheet(printItems, saveParams.FileName); currentPartsInQueue.UpdateRemainingItems += feedbackWindow.StartingNextPart; diff --git a/MatterControlLib/PartPreviewWindow/GCode2DWidget.cs b/MatterControlLib/PartPreviewWindow/GCode2DWidget.cs index 22dfd0c41..4f763d210 100644 --- a/MatterControlLib/PartPreviewWindow/GCode2DWidget.cs +++ b/MatterControlLib/PartPreviewWindow/GCode2DWidget.cs @@ -70,8 +70,6 @@ namespace MatterHackers.MatterControl.PartPreviewWindow this.printer = printer; options = printer.Bed.RendererOptions; - this.BackgroundColor = ActiveTheme.Instance.PrimaryBackgroundColor; - this.LocalBounds = new RectangleDouble(0, 0, 100, 100); this.AnchorAll(); diff --git a/MatterControlLib/PartPreviewWindow/ItemMaterialButton.cs b/MatterControlLib/PartPreviewWindow/ItemMaterialButton.cs index dfee36d7f..78983efc8 100644 --- a/MatterControlLib/PartPreviewWindow/ItemMaterialButton.cs +++ b/MatterControlLib/PartPreviewWindow/ItemMaterialButton.cs @@ -70,7 +70,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow return materialControl; }; - materialColorButton = new ColorButton(MaterialRendering.Color(initialMaterialIndex, theme.MinimalHighlight)) + materialColorButton = new ColorButton(MaterialRendering.Color(initialMaterialIndex, theme.BorderColor)) { Width = scaledButtonSize, Height = scaledButtonSize, diff --git a/MatterControlLib/PartPreviewWindow/LibraryBrowserPage.cs b/MatterControlLib/PartPreviewWindow/LibraryBrowserPage.cs index 2a6cefb23..015f59bcf 100644 --- a/MatterControlLib/PartPreviewWindow/LibraryBrowserPage.cs +++ b/MatterControlLib/PartPreviewWindow/LibraryBrowserPage.cs @@ -64,14 +64,14 @@ namespace MatterHackers.MatterControl librarySelectorWidget = new ListView(libraryNavContext, new IconListView(theme, 75), theme) { - BackgroundColor = ActiveTheme.Instance.TertiaryBackgroundColor, + BackgroundColor = theme.MinimalShade, ShowItems = true, ContainerFilter = (container) => !container.IsReadOnly, }; // put in the bread crumb widget breadCrumbWidget = new FolderBreadCrumbWidget(librarySelectorWidget, theme); - breadCrumbWidget.BackgroundColor = ActiveTheme.Instance.TertiaryBackgroundColor; + breadCrumbWidget.BackgroundColor = theme.MinimalShade; contentRow.AddChild(breadCrumbWidget); contentRow.BackgroundColor = Color.Transparent; diff --git a/MatterControlLib/PartPreviewWindow/MaterialControls.cs b/MatterControlLib/PartPreviewWindow/MaterialControls.cs index cc2a36d71..accdb1c1f 100644 --- a/MatterControlLib/PartPreviewWindow/MaterialControls.cs +++ b/MatterControlLib/PartPreviewWindow/MaterialControls.cs @@ -68,7 +68,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow var scaledButtonSize = 16 * GuiWidget.DeviceScale; - buttonView.AddChild(new ColorButton(MaterialRendering.Color(extruderIndex, theme.MinimalHighlight)) + buttonView.AddChild(new ColorButton(MaterialRendering.Color(extruderIndex, theme.BorderColor)) { Width = scaledButtonSize, Height = scaledButtonSize, diff --git a/MatterControlLib/PartPreviewWindow/PartPreviewContent.cs b/MatterControlLib/PartPreviewWindow/PartPreviewContent.cs index cbc275e8b..1b28d1e08 100644 --- a/MatterControlLib/PartPreviewWindow/PartPreviewContent.cs +++ b/MatterControlLib/PartPreviewWindow/PartPreviewContent.cs @@ -65,7 +65,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow { VAnchor = VAnchor.Stretch, HAnchor = HAnchor.Stretch, - BackgroundColor = ActiveTheme.Instance.PrimaryBackgroundColor, + BackgroundColor = theme.ActiveTabColor, BorderColor = theme.MinimalShade, Border = new BorderDouble(left: 1), }; @@ -279,9 +279,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow HAnchor = HAnchor.Fit, VAnchor = VAnchor.Fit, BackgroundColor = theme.TabBarBackground, - Border = new BorderDouble(right: 1), - BorderColor = theme.MinimalShade, - Padding = theme.TabbarPadding.Clone(right: 0) + Padding = theme.TabbarPadding.Clone(right: theme.DefaultContainerPadding) }; tabControl.TabBar.ActionArea.AddChild(brandMenu, 0); diff --git a/MatterControlLib/PartPreviewWindow/PartTabPage.cs b/MatterControlLib/PartPreviewWindow/PartTabPage.cs index 1bd8e4133..8aaa12a0a 100644 --- a/MatterControlLib/PartPreviewWindow/PartTabPage.cs +++ b/MatterControlLib/PartPreviewWindow/PartTabPage.cs @@ -152,8 +152,6 @@ namespace MatterHackers.MatterControl.PartPreviewWindow leftToRight.AddChild(view3DContainer); - view3DWidget.BackgroundColor = ActiveTheme.Instance.TertiaryBackgroundColor; - if (sceneContext.World.RotationMatrix == Matrix4X4.Identity) { this.view3DWidget.ResetView(); diff --git a/MatterControlLib/PartPreviewWindow/PopupMenu.cs b/MatterControlLib/PartPreviewWindow/PopupMenu.cs index 8f9d20a14..e6cd602ed 100644 --- a/MatterControlLib/PartPreviewWindow/PopupMenu.cs +++ b/MatterControlLib/PartPreviewWindow/PopupMenu.cs @@ -56,7 +56,6 @@ namespace MatterHackers.MatterControl.PartPreviewWindow this.theme = theme; this.VAnchor = VAnchor.Fit; this.HAnchor = HAnchor.Fit; - this.BackgroundColor = theme.Colors.PrimaryBackgroundColor; } public HorizontalLine CreateHorizontalLine() @@ -429,7 +428,6 @@ namespace MatterHackers.MatterControl.PartPreviewWindow { // Inflate padding to match the target (MenuGutterWidth) after scale operation in assignment this.Padding = new BorderDouble(left: Math.Ceiling(theme.MenuGutterWidth / GuiWidget.DeviceScale) , right: 15); - this.BackgroundColor = theme.Colors.PrimaryBackgroundColor; this.HAnchor = HAnchor.MaxFitOrStretch; this.VAnchor = VAnchor.Fit; this.MinimumSize = new Vector2(150 * GuiWidget.DeviceScale, theme.ButtonHeight); diff --git a/MatterControlLib/PartPreviewWindow/PopupMenuButton.cs b/MatterControlLib/PartPreviewWindow/PopupMenuButton.cs index a6b56b3b1..62ed57e6b 100644 --- a/MatterControlLib/PartPreviewWindow/PopupMenuButton.cs +++ b/MatterControlLib/PartPreviewWindow/PopupMenuButton.cs @@ -42,7 +42,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow public PopupMenuButton(ThemeConfig theme) { this.theme = theme; - this.DisabledColor = new Color(theme.Colors.SecondaryTextColor, 50); + this.DisabledColor = theme.DisabledColor; this.HoverColor = theme.MinimalShade; } @@ -58,7 +58,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow viewWidget.BackgroundColor = Color.Transparent; this.theme = theme; - this.DisabledColor = new Color(theme.Colors.SecondaryTextColor, 50); + this.DisabledColor = theme.DisabledColor; this.HoverColor = theme.ToolbarButtonHover; this.BackgroundColor = theme.ToolbarButtonBackground; @@ -113,7 +113,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow dropArrow, LocalBounds.Right - DropArrow.ArrowHeight * 2 - 2, LocalBounds.Center.Y + DropArrow.ArrowHeight / 2, - this.Enabled ? theme.Colors.SecondaryTextColor : this.DisabledColor); + this.Enabled ? theme.BorderColor : this.DisabledColor); } } diff --git a/MatterControlLib/PartPreviewWindow/RunningTaskRow.cs b/MatterControlLib/PartPreviewWindow/RunningTaskRow.cs index 0e3f197aa..703cf9d28 100644 --- a/MatterControlLib/PartPreviewWindow/RunningTaskRow.cs +++ b/MatterControlLib/PartPreviewWindow/RunningTaskRow.cs @@ -81,7 +81,6 @@ namespace MatterHackers.MatterControl.PartPreviewWindow VAnchor = VAnchor.Absolute | VAnchor.Bottom, FillColor = ActiveTheme.Instance.PrimaryAccentColor, BorderColor = Color.Transparent, - BackgroundColor = ActiveTheme.Instance.TertiaryBackgroundColor, Margin = new BorderDouble(32, 7, theme.ButtonHeight * 2 + 14, 0), }; rowContainer.AddChild(progressBar); diff --git a/MatterControlLib/PartPreviewWindow/SelectedObjectPanel.cs b/MatterControlLib/PartPreviewWindow/SelectedObjectPanel.cs index 8fe24e9fe..ca9f439b9 100644 --- a/MatterControlLib/PartPreviewWindow/SelectedObjectPanel.cs +++ b/MatterControlLib/PartPreviewWindow/SelectedObjectPanel.cs @@ -72,7 +72,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow var toolbar = new LeftClipFlowLayoutWidget() { - BackgroundColor = theme.TabBodyBackground, + BackgroundColor = theme.ActiveTabColor, Padding = theme.ToolbarPadding, HAnchor = HAnchor.Fit, VAnchor = VAnchor.Fit diff --git a/MatterControlLib/PartPreviewWindow/View3D/ColorSwatchSelector.cs b/MatterControlLib/PartPreviewWindow/View3D/ColorSwatchSelector.cs index c4440d52e..2152091e1 100644 --- a/MatterControlLib/PartPreviewWindow/View3D/ColorSwatchSelector.cs +++ b/MatterControlLib/PartPreviewWindow/View3D/ColorSwatchSelector.cs @@ -151,11 +151,11 @@ namespace MatterHackers.MatterControl.PartPreviewWindow for (var i = 0; i < numberOfStripes * 2; i++) { var thickness = ix / numberOfStripes; - + graphics2D.Line( - i * thickness + thickness / 2 - ix, - 0, - i * thickness + thickness / 2, + i * thickness + thickness / 2 - ix, + 0, + i * thickness + thickness / 2, ix, Color.Gray, 0.05); @@ -164,6 +164,8 @@ namespace MatterHackers.MatterControl.PartPreviewWindow base.OnDraw(graphics2D); } + + public Color SourceColor { get; set; } } public static class ColorExtensions diff --git a/MatterControlLib/PartPreviewWindow/View3D/PrinterBar/PrintPopupMenu.cs b/MatterControlLib/PartPreviewWindow/View3D/PrinterBar/PrintPopupMenu.cs index afe824024..85c3a8677 100644 --- a/MatterControlLib/PartPreviewWindow/View3D/PrinterBar/PrintPopupMenu.cs +++ b/MatterControlLib/PartPreviewWindow/View3D/PrinterBar/PrintPopupMenu.cs @@ -73,8 +73,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow var column = new FlowLayoutWidget(FlowDirection.TopToBottom) { - Padding = 10, - BackgroundColor = menuTheme.Colors.PrimaryBackgroundColor + Padding = theme.DefaultContainerPadding, }; column.AddChild(new TextWidget("Options".Localize(), textColor: menuTheme.Colors.PrimaryTextColor) diff --git a/MatterControlLib/PartPreviewWindow/View3D/View3DWidget.cs b/MatterControlLib/PartPreviewWindow/View3D/View3DWidget.cs index 556b36b8c..e002e039d 100644 --- a/MatterControlLib/PartPreviewWindow/View3D/View3DWidget.cs +++ b/MatterControlLib/PartPreviewWindow/View3D/View3DWidget.cs @@ -104,7 +104,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow this.printer = printer; this.theme = theme; this.Name = "View3DWidget"; - this.BackgroundColor = theme.ActiveTabColor; + this.BackgroundColor = theme.ResolveColor(theme.ActiveTabColor, new Color(Color.Black, 20)); this.HAnchor = HAnchor.Stretch; // HAnchor.MaxFitOrStretch, this.VAnchor = VAnchor.Stretch; // VAnchor.MaxFitOrStretch diff --git a/MatterControlLib/PrinterControls/ControlWidgets/MovementControls.cs b/MatterControlLib/PrinterControls/ControlWidgets/MovementControls.cs index 64fca395d..f42b44b1c 100644 --- a/MatterControlLib/PrinterControls/ControlWidgets/MovementControls.cs +++ b/MatterControlLib/PrinterControls/ControlWidgets/MovementControls.cs @@ -275,7 +275,7 @@ namespace MatterHackers.MatterControl.PrinterControls Padding = new BorderDouble(3), HAnchor = HAnchor.Fit, VAnchor = VAnchor.Center, - BackgroundColor = ActiveTheme.Instance.SecondaryBackgroundColor, + BackgroundColor = theme.MinimalShade, Height = 20 }; this.AddChild(zOffsetStreamContainer); @@ -306,7 +306,7 @@ namespace MatterHackers.MatterControl.PrinterControls double zoffset = printerSettings.GetValue(SettingsKey.baby_step_z_offset); bool hasOverriddenZOffset = (zoffset != 0); - zOffsetStreamContainer.BackgroundColor = (allowRemoveButton && hasOverriddenZOffset) ? theme.PresetColors.UserOverride : ActiveTheme.Instance.SecondaryBackgroundColor; + zOffsetStreamContainer.BackgroundColor = (allowRemoveButton && hasOverriddenZOffset) ? theme.PresetColors.UserOverride : theme.MinimalShade; clearZOffsetButton.Visible = allowRemoveButton && hasOverriddenZOffset; zOffsetStreamDisplay.Text = zoffset.ToString("0.##"); diff --git a/MatterControlLib/PrinterControls/TerminalWindow/TerminalWidget.cs b/MatterControlLib/PrinterControls/TerminalWindow/TerminalWidget.cs index c465cc996..87098060f 100644 --- a/MatterControlLib/PrinterControls/TerminalWindow/TerminalWidget.cs +++ b/MatterControlLib/PrinterControls/TerminalWindow/TerminalWidget.cs @@ -101,7 +101,7 @@ namespace MatterHackers.MatterControl textScrollWidget = new TextScrollWidget(printer, printer.Connection.TerminalLog.PrinterLines) { - BackgroundColor = theme.Colors.SecondaryBackgroundColor, + BackgroundColor = theme.MinimalShade, TextColor = theme.Colors.PrimaryTextColor, HAnchor = HAnchor.Stretch, VAnchor = VAnchor.Stretch, diff --git a/MatterControlLib/SettingsManagement/ApplicationSettingsPage.cs b/MatterControlLib/SettingsManagement/ApplicationSettingsPage.cs index c8c2811b2..46f15091c 100644 --- a/MatterControlLib/SettingsManagement/ApplicationSettingsPage.cs +++ b/MatterControlLib/SettingsManagement/ApplicationSettingsPage.cs @@ -28,30 +28,29 @@ either expressed or implied, of the FreeBSD Project. */ using System; -using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using MatterHackers.Agg; -using MatterHackers.Agg.Image; using MatterHackers.Agg.Platform; using MatterHackers.Agg.UI; using MatterHackers.Localizations; using MatterHackers.MatterControl.ConfigurationPage; using MatterHackers.MatterControl.CustomWidgets; using MatterHackers.MatterControl.DataStorage; -using MatterHackers.MatterControl.SlicerConfiguration; using MatterHackers.VectorMath; namespace MatterHackers.MatterControl { public partial class ApplicationSettingsPage : DialogPage { + private ThemeColorPanel themeColorPanel; + public ApplicationSettingsPage() { this.AlwaysOnTopOfMain = true; this.WindowTitle = this.HeaderText = "MatterControl " + "Settings".Localize(); - this.WindowSize = new Vector2(500 * GuiWidget.DeviceScale, 500 * GuiWidget.DeviceScale); + this.WindowSize = new Vector2(700 * GuiWidget.DeviceScale, 600 * GuiWidget.DeviceScale); contentRow.Padding = contentRow.Padding.Clone(top: 0); @@ -283,12 +282,54 @@ namespace MatterHackers.MatterControl this.AddSettingsRow(section, generalPanel); + themeColorPanel = new ThemeColorPanel(theme) + { + HAnchor = HAnchor.Stretch + }; + + var droplist = new DropDownList("Custom", theme.Colors.PrimaryTextColor, maxHeight: 200, pointSize: theme.DefaultFontSize) + { + BorderColor = theme.GetBorderColor(75), + Margin = new BorderDouble(0, 0, 10, 0) + }; + + int i = 0; + + foreach (var item in AppContext.ThemeProviders) + { + var newItem = droplist.AddItem(item.Key); + + if (item.Value == themeColorPanel.ThemeProvider) + { + droplist.SelectedIndex = i; + } + + i++; + } + + droplist.SelectionChanged += (s, e) => + { + if (AppContext.ThemeProviders.TryGetValue(droplist.SelectedValue, out IColorTheme provider)) + { + themeColorPanel.ThemeProvider = provider; + UserSettings.Instance.set(UserSettingsKey.ThemeName, droplist.SelectedValue); + } + }; + + var themeRow = new SettingsItem("Theme".Localize(), droplist, theme); + generalPanel.AddChild(themeRow); + generalPanel.AddChild(themeColorPanel); + + themeColorPanel.Border = themeRow.Border; + themeColorPanel.BorderColor = themeRow.BorderColor; + themeRow.Border = 0; + var advancedPanel = new FlowLayoutWidget(FlowDirection.TopToBottom) { Margin = new BorderDouble(2, 0) }; - var sectionWidget = new SectionWidget("Advanced", advancedPanel, theme, serializationKey: "ApplicationSettings-Advanced", expanded: false) + var sectionWidget = new SectionWidget("Advanced".Localize(), advancedPanel, theme, serializationKey: "ApplicationSettings-Advanced", expanded: false) { Name = "Advanced Section", HAnchor = HAnchor.Stretch, @@ -356,6 +397,18 @@ namespace MatterHackers.MatterControl advancedPanel.Children().First().Border = new BorderDouble(0, 1); } + public void BeforePopup() + { + // Refresh theme mode buttons + string activeMode = UserSettings.Instance.get(UserSettingsKey.ThemeMode); + + foreach (var button in themeColorPanel.Children[1].Children()) + { + button.IsActive = activeMode == button.Mode; + button.PreviewThemeColor(theme.Colors.SourceColor); + } + } + private void AddSettingsRow(GuiWidget widget, GuiWidget container) { container.AddChild(widget); diff --git a/MatterControlLib/SettingsManagement/UserSettings.cs b/MatterControlLib/SettingsManagement/UserSettings.cs index ed93e1638..2e7bf8d04 100644 --- a/MatterControlLib/SettingsManagement/UserSettings.cs +++ b/MatterControlLib/SettingsManagement/UserSettings.cs @@ -66,6 +66,8 @@ namespace MatterHackers.MatterControl public const string SceneTreeRatio = nameof(SceneTreeRatio); public const string SelectedObjectEditorHeight = nameof(SelectedObjectEditorHeight); public const string SelectionTreeViewPanelExpanded = nameof(SelectionTreeViewPanelExpanded); + public const string ThemeName = nameof(ThemeName); + public const string ThemeMode = nameof(ThemeMode); } public class UserSettings diff --git a/MatterControlLib/SetupWizard/DialogPage.cs b/MatterControlLib/SetupWizard/DialogPage.cs index 411b1a796..6931d05a4 100644 --- a/MatterControlLib/SetupWizard/DialogPage.cs +++ b/MatterControlLib/SetupWizard/DialogPage.cs @@ -61,7 +61,7 @@ namespace MatterHackers.MatterControl this.HAnchor = HAnchor.Stretch; this.VAnchor = VAnchor.Stretch; - this.BackgroundColor = theme.Colors.PrimaryBackgroundColor; + this.BackgroundColor = theme.ActiveTabColor; if (cancelButtonText == null) { diff --git a/MatterControlLib/SetupWizard/DialogWindow.cs b/MatterControlLib/SetupWizard/DialogWindow.cs index 5fcb6fac7..e906f7a61 100644 --- a/MatterControlLib/SetupWizard/DialogWindow.cs +++ b/MatterControlLib/SetupWizard/DialogWindow.cs @@ -38,19 +38,18 @@ namespace MatterHackers.MatterControl public class DialogWindow : SystemWindow { private DialogPage activePage; - private EventHandler unregisterEvents; - private static Dictionary allWindows = new Dictionary(); + private ThemeConfig theme; private DialogWindow() : base(500 * GuiWidget.DeviceScale, 500 * GuiWidget.DeviceScale) { - var theme = ApplicationController.Instance.Theme; + theme = ApplicationController.Instance.Theme; this.AlwaysOnTopOfMain = true; this.MinimumSize = new Vector2(200, 200); - this.BackgroundColor = theme.Colors.PrimaryBackgroundColor; + this.BackgroundColor = theme.ActiveTabColor; var defaultPadding = theme.DefaultContainerPadding; this.Padding = new BorderDouble(defaultPadding, defaultPadding, defaultPadding, 2); @@ -141,24 +140,32 @@ namespace MatterHackers.MatterControl public DialogPage ChangeToPage() where PanelType : DialogPage, new() { - PanelType panel = new PanelType(); - panel.DialogWindow = this; - ChangeToPage(panel); + var panel = new PanelType + { + DialogWindow = this + }; + this.ChangeToPage(panel); // in the event of a reload all make sure we rebuild the contents correctly ApplicationController.Instance.DoneReloadingAll.RegisterEvent((s,e) => { + // Normal theme references are safe to hold in widgets because they're rebuild on ReloadAll. DialogWindow + // survives and must refresh its reference on reload + theme = ApplicationController.Instance.Theme; + // fix the main window background color if needed - BackgroundColor = ActiveTheme.Instance.PrimaryBackgroundColor; + this.BackgroundColor = theme.ActiveTabColor; // find out where the contents we put in last time are int thisIndex = GetChildIndex(panel); - RemoveAllChildren(); + this.RemoveAllChildren(); // make new content with the possibly changed theme - PanelType newPanel = new PanelType(); - newPanel.DialogWindow = this; - AddChild(newPanel, thisIndex); + var newPanel = new PanelType + { + DialogWindow = this + }; + this.AddChild(newPanel, thisIndex); panel.CloseOnIdle(); // remember the new content diff --git a/MatterControlLib/SlicerConfiguration/Settings/ProfileManager.cs b/MatterControlLib/SlicerConfiguration/Settings/ProfileManager.cs index b700491b0..6f526d03b 100644 --- a/MatterControlLib/SlicerConfiguration/Settings/ProfileManager.cs +++ b/MatterControlLib/SlicerConfiguration/Settings/ProfileManager.cs @@ -75,6 +75,9 @@ namespace MatterHackers.MatterControl.SlicerConfiguration [JsonIgnore] private string UserProfilesDirectory => GetProfilesDirectoryForUser(this.UserName); + [JsonIgnore] + public string ProfileThemeSetPath => Path.Combine(UserProfilesDirectory, "themeset.json"); + /// /// The user specific path to the Profiles document /// @@ -534,10 +537,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration printerSettings.ID = guid; printerSettings.DocumentVersion = PrinterSettings.LatestVersion; - printerSettings.UserLayer[SettingsKey.printer_name.ToString()] = printerName; - - //If the active printer has no theme we set it to the current theme color - printerSettings.UserLayer[SettingsKey.active_theme_name] = ActiveTheme.Instance.Name; + printerSettings.UserLayer[SettingsKey.printer_name] = printerName; // Add to Profiles - fires ProfileManager.Save due to ObservableCollection event listener Instance.Profiles.Add(new PrinterInfo diff --git a/MatterControlLib/SlicerConfiguration/Settings/SettingsHelpers.cs b/MatterControlLib/SlicerConfiguration/Settings/SettingsHelpers.cs index 6295bdab8..64ddba748 100644 --- a/MatterControlLib/SlicerConfiguration/Settings/SettingsHelpers.cs +++ b/MatterControlLib/SlicerConfiguration/Settings/SettingsHelpers.cs @@ -45,7 +45,6 @@ namespace MatterHackers.MatterControl.SlicerConfiguration public static class SettingsKey { public const string active_quality_key = nameof(active_quality_key); - public const string active_theme_name = nameof(active_theme_name); public const string auto_connect = nameof(auto_connect); public const string auto_release_motors = nameof(auto_release_motors); public const string baby_step_z_offset = nameof(baby_step_z_offset); diff --git a/MatterControlLib/SlicerConfiguration/SliceSettingsWidget.cs b/MatterControlLib/SlicerConfiguration/SliceSettingsWidget.cs index bfe52b3ca..734fe21ed 100644 --- a/MatterControlLib/SlicerConfiguration/SliceSettingsWidget.cs +++ b/MatterControlLib/SlicerConfiguration/SliceSettingsWidget.cs @@ -54,8 +54,6 @@ namespace MatterHackers.MatterControl.SlicerConfiguration : base (FlowDirection.TopToBottom) { this.printer = printer; - this.BackgroundColor = theme.TabBodyBackground; - this.settingsContext = settingsContext; settingsControlBar = new PresetsToolbar(printer, theme) @@ -574,7 +572,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration var row = new FlowLayoutWidget() { - BackgroundColor = theme.Colors.TertiaryBackgroundColor, + BackgroundColor = theme.SlightShade, Padding = new BorderDouble(5), Margin = new BorderDouble(3, 20, 3, 0), HAnchor = HAnchor.Stretch, diff --git a/MatterControlLib/SlicerConfiguration/UIFields/ComPortField.cs b/MatterControlLib/SlicerConfiguration/UIFields/ComPortField.cs index b01907465..8fa2406f7 100644 --- a/MatterControlLib/SlicerConfiguration/UIFields/ComPortField.cs +++ b/MatterControlLib/SlicerConfiguration/UIFields/ComPortField.cs @@ -73,7 +73,6 @@ namespace MatterHackers.MatterControl.SlicerConfiguration Name = "com_port Field", // Prevent droplist interaction when connected Enabled = canChangeComPort, - TextColor = canChangeComPort ? ActiveTheme.Instance.PrimaryTextColor : new Color(ActiveTheme.Instance.PrimaryTextColor, 150), BorderColor = theme.GetBorderColor(75) }; @@ -90,7 +89,6 @@ namespace MatterHackers.MatterControl.SlicerConfiguration { canChangeComPort = !printer.Connection.IsConnected && printer.Connection.CommunicationState != CommunicationStates.AttemptingToConnect; dropdownList.Enabled = canChangeComPort; - dropdownList.TextColor = canChangeComPort ? ActiveTheme.Instance.PrimaryTextColor : new Color(ActiveTheme.Instance.PrimaryTextColor, 150); if (printer.Connection.ComPort != dropdownList.SelectedLabel) { diff --git a/MatterControlLib/SlicerConfiguration/UIFields/IpAddessField.cs b/MatterControlLib/SlicerConfiguration/UIFields/IpAddessField.cs index 6e98cfc87..1138c39f1 100644 --- a/MatterControlLib/SlicerConfiguration/UIFields/IpAddessField.cs +++ b/MatterControlLib/SlicerConfiguration/UIFields/IpAddessField.cs @@ -59,9 +59,8 @@ namespace MatterHackers.MatterControl.SlicerConfiguration printer.Connection.CommunicationStateChanged.RegisterEvent((s, e) => { canChangeComPort = !printer.Connection.IsConnected && printer.Connection.CommunicationState != CommunicationStates.AttemptingToConnect; + dropdownList.TextColor = theme.Colors.PrimaryTextColor; dropdownList.Enabled = canChangeComPort; - dropdownList.TextColor = canChangeComPort ? theme.Colors.PrimaryTextColor : new Color(theme.Colors.PrimaryTextColor, 150); - dropdownList.BorderColor = canChangeComPort ? theme.Colors.SecondaryTextColor : new Color(theme.Colors.SecondaryTextColor, 150); }, ref unregisterEvents); // Release event listener on close diff --git a/MatterControlLib/Utilities/JsonPath.cs b/MatterControlLib/Utilities/JsonPath.cs index 0467610fb..1250d6211 100644 --- a/MatterControlLib/Utilities/JsonPath.cs +++ b/MatterControlLib/Utilities/JsonPath.cs @@ -453,6 +453,7 @@ namespace JsonPath } } + // Invoke property to get value var propertyValue = propertyInfo.GetGetMethod().Invoke(value, null); if (!string.IsNullOrEmpty(typeFilter) && propertyValue is IEnumerable items) diff --git a/Submodules/agg-sharp b/Submodules/agg-sharp index 9b89d41ac..39f80f89d 160000 --- a/Submodules/agg-sharp +++ b/Submodules/agg-sharp @@ -1 +1 @@ -Subproject commit 9b89d41acd249a345b071849db9eca6e213644ab +Subproject commit 39f80f89d4e11b134815db53676eac5d2d7838b2 diff --git a/Tests/MatterControl.Tests/MatterControl/BoundDropListTests.cs b/Tests/MatterControl.Tests/MatterControl/BoundDropListTests.cs index 14e88b6a6..0167d85e7 100644 --- a/Tests/MatterControl.Tests/MatterControl/BoundDropListTests.cs +++ b/Tests/MatterControl.Tests/MatterControl/BoundDropListTests.cs @@ -26,7 +26,7 @@ namespace MatterControl.Tests.MatterControl var theme = new ThemeConfig() { - Colors = ActiveTheme.Instance + Colors = ActiveTheme.Instance as ThemeColors }; // Whitelist on non-OEM builds should contain all printers diff --git a/Tests/MatterControl.Tests/MatterControl/PopupAnchorTests.cs b/Tests/MatterControl.Tests/MatterControl/PopupAnchorTests.cs index 1e35784ee..42a8992b1 100644 --- a/Tests/MatterControl.Tests/MatterControl/PopupAnchorTests.cs +++ b/Tests/MatterControl.Tests/MatterControl/PopupAnchorTests.cs @@ -878,10 +878,7 @@ namespace MatterControl.Tests.MatterControl { this.BackgroundColor = new Color(56, 56, 56); - Theme = new ThemeConfig() - { - Colors = ActiveTheme.Instance - }; + Theme = new ThemeConfig(); this.Padding = new BorderDouble(left: 120, bottom: 10, right: 10, top: 10); diff --git a/Tests/MatterControl.Tests/MatterControl/SliceSettingsFieldTests.cs b/Tests/MatterControl.Tests/MatterControl/SliceSettingsFieldTests.cs index 0e053c282..b176b8d56 100644 --- a/Tests/MatterControl.Tests/MatterControl/SliceSettingsFieldTests.cs +++ b/Tests/MatterControl.Tests/MatterControl/SliceSettingsFieldTests.cs @@ -259,7 +259,6 @@ namespace MatterControl.Tests.MatterControl MatterControlUtilities.OverrideAppDataLocation(TestContext.CurrentContext.ResolveProjectPath(4)); var theme = new ThemeConfig(); - theme.RebuildTheme(ActiveTheme.Instance); var field = new ComPortField(new PrinterConfig(PrinterSettings.Empty), theme); @@ -319,7 +318,7 @@ namespace MatterControl.Tests.MatterControl MatterControlUtilities.OverrideAppDataLocation(TestContext.CurrentContext.ResolveProjectPath(4)); var theme = new ThemeConfig(); - theme.RebuildTheme(ActiveTheme.Instance); + theme.RebuildTheme(); await ValidateAgainstValueMap( (field) => (field.Content as MHTextEditWidget).ActualTextEditWidget.Text,