Revise theme support
This commit is contained in:
parent
7ba684ef8d
commit
ee936efb8a
57 changed files with 1562 additions and 458 deletions
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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<ThemePreviewButton>())
|
||||
{
|
||||
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<ColorButton> colorButtons = new List<ColorButton>();
|
||||
|
||||
public IEnumerable<ColorButton> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue