diff --git a/UndertaleModTool/App.xaml b/UndertaleModTool/App.xaml index c7bce7b24..aeea355ce 100644 --- a/UndertaleModTool/App.xaml +++ b/UndertaleModTool/App.xaml @@ -4,10 +4,19 @@ xmlns:local="clr-namespace:UndertaleModTool" StartupUri="MainWindow.xaml"> - - - - - + + + + + + + + + + + + + + diff --git a/UndertaleModTool/Controls/AudioFileReference.xaml b/UndertaleModTool/Controls/AudioFileReference.xaml index 4659c643e..fc9994d80 100644 --- a/UndertaleModTool/Controls/AudioFileReference.xaml +++ b/UndertaleModTool/Controls/AudioFileReference.xaml @@ -7,9 +7,9 @@ mc:Ignorable="d" d:DesignHeight="20" d:DesignWidth="300"> - - - + + + @@ -18,9 +18,9 @@ - + - - - + - - - + + + diff --git a/UndertaleModTool/Controls/ColorPicker.xaml b/UndertaleModTool/Controls/ColorPicker.xaml index f5f63ef3d..98df47667 100644 --- a/UndertaleModTool/Controls/ColorPicker.xaml +++ b/UndertaleModTool/Controls/ColorPicker.xaml @@ -24,7 +24,7 @@ - + diff --git a/UndertaleModTool/Controls/System/ButtonDark.cs b/UndertaleModTool/Controls/System/ButtonDark.cs deleted file mode 100644 index 75d5fd9c9..000000000 --- a/UndertaleModTool/Controls/System/ButtonDark.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Windows; -using System.Windows.Media; - -namespace UndertaleModTool -{ - /// - /// A standard button which compatible with the dark mode. - /// - public partial class ButtonDark : System.Windows.Controls.Button - { - // Setting "Foreground" implicitly breaks internal "IsEnabled" style trigger, - // so this has to be handled manually. - private static readonly SolidColorBrush disabledTextBrush = new(Color.FromArgb(255, 131, 131, 131)); - - /// Initializes a new instance of the button. - public ButtonDark() - { - // Even though this will be called again in "OnPropertyChanged()", it's required. - SetResourceReference(ForegroundProperty, "CustomTextBrush"); - } - - /// - protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e) - { - if (e.Property == IsEnabledProperty) - { - if ((bool)e.NewValue) - SetResourceReference(ForegroundProperty, "CustomTextBrush"); - else - Foreground = disabledTextBrush; - } - - base.OnPropertyChanged(e); - } - } -} diff --git a/UndertaleModTool/Controls/System/ComboBoxDark.cs b/UndertaleModTool/Controls/System/ComboBoxDark.cs deleted file mode 100644 index 164383a22..000000000 --- a/UndertaleModTool/Controls/System/ComboBoxDark.cs +++ /dev/null @@ -1,52 +0,0 @@ -using System; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Controls.Primitives; -using System.Windows.Media; - -namespace UndertaleModTool -{ - /// - /// A standard combo box which compatible with the dark mode. - /// - public partial class ComboBoxDark : ComboBox - { - // Setting "Foreground" implicitly breaks internal "IsEnabled" style trigger, - // so this has to be handled manually. - private static readonly SolidColorBrush disabledTextBrush = new(Color.FromArgb(255, 131, 131, 131)); - - /// Initializes a new instance of the combo box. - public ComboBoxDark() - { - // Even though this will be called again in "OnPropertyChanged()", it's required. - SetResourceReference(ForegroundProperty, "CustomTextBrush"); - - Loaded += ComboBox_Loaded; - } - - private void ComboBox_Loaded(object sender, RoutedEventArgs e) - { - Popup popup = MainWindow.FindVisualChild(this); - var content = MainWindow.FindVisualChild(popup?.Child); - if (content is null) - return; - - // Change text color of dropdown items - content.SetResourceReference(ForegroundProperty, SystemColors.ControlTextBrushKey); - } - - /// - protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e) - { - if (e.Property == IsEnabledProperty) - { - if ((bool)e.NewValue) - SetResourceReference(ForegroundProperty, "CustomTextBrush"); - else - Foreground = disabledTextBrush; - } - - base.OnPropertyChanged(e); - } - } -} diff --git a/UndertaleModTool/Controls/System/ContextMenuDark.cs b/UndertaleModTool/Controls/System/ContextMenuDark.cs deleted file mode 100644 index acf9e67b4..000000000 --- a/UndertaleModTool/Controls/System/ContextMenuDark.cs +++ /dev/null @@ -1,110 +0,0 @@ -using ICSharpCode.AvalonEdit.Editing; -using System; -using System.Collections.Generic; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Controls.Primitives; -using System.Windows.Media; -using System.Windows.Shapes; - -namespace UndertaleModTool -{ - /// - /// A standard context menu which compatible with the dark mode. - /// - public partial class ContextMenuDark : ContextMenu - { - private static readonly Brush separatorDarkBrush = new SolidColorBrush(Color.FromArgb(255, 60, 60, 60)); - private static readonly Rectangle[] rectList = new Rectangle[3]; - - /// Initializes a new instance of the context menu. - public ContextMenuDark() - { - Loaded += ContextMenuDark_Loaded; - } - - private Rectangle[] GetSortedRectList(DependencyObject parent) - { - int childCount = VisualTreeHelper.GetChildrenCount(parent); - int rectCount = 0; - for (int i = 0; i < childCount; i++) - { - if (rectCount > 3) - break; - - var rect = VisualTreeHelper.GetChild(parent, i) as Rectangle; - if (rect is null) - continue; - rectList[rectCount++] = rect; - } - if (rectCount != 3) - return null; - - Array.Sort(rectList, (x, y) => x.Margin.Left.CompareTo(y.Margin.Left)); - return rectList; - } - private void ContextMenuDark_Loaded(object sender, RoutedEventArgs e) - { - if (Tag is int v) - { - // If the object is the same and the style is also the same - // (0 - light mode, 1 - dark mode) - if (v == 0 && !Settings.Instance.EnableDarkMode - || v == 1 && Settings.Instance.EnableDarkMode) - return; - } - - Border border = MainWindow.FindVisualChild(this); - if (border is null) - return; - - if (Tag is null) - border.SetResourceReference(BackgroundProperty, SystemColors.MenuBrushKey); - - var parent = MainWindow.FindVisualChild(border)?.Parent; - if (parent is null) - return; - - if (Settings.Instance.EnableDarkMode) - { - var rects = GetSortedRectList(parent); - if (rects is null) - return; - - // Leave only the last rectangle on the right visible, - // and also change its color - for (int i = 0; i < 2; i++) - { - var rect = rects[i]; - - rect.Tag = rect.Fill; - rect.Fill = Brushes.Transparent; - } - rects[2].Tag = rects[2].Fill; - rects[2].Fill = separatorDarkBrush; - - Tag = 1; - } - else - { - var rects = GetSortedRectList(parent); - if (rects is null) - return; - - if (rects[0].Tag is not null) - { - // Restore rectangles state - for (int i = 0; i < 3; i++) - { - var rect = rects[i]; - - rect.Fill = rect.Tag as Brush; - rect.Tag = null; - } - } - - Tag = 0; - } - } - } -} diff --git a/UndertaleModTool/Controls/System/DataGridDark.cs b/UndertaleModTool/Controls/System/DataGridDark.cs deleted file mode 100644 index 8591c86b0..000000000 --- a/UndertaleModTool/Controls/System/DataGridDark.cs +++ /dev/null @@ -1,61 +0,0 @@ -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Controls.Primitives; -using System.Windows.Threading; - -namespace UndertaleModTool -{ - /// - /// A standard data grid which compatible with the dark mode. - /// - public partial class DataGridDark : DataGrid - { - /// Initializes a new instance of the data grid. - public DataGridDark() - { - Loaded += DataGrid_Loaded; - AddingNewItem += DataGrid_AddingNewItem; - } - - private void DataGrid_AddingNewItem(object sender, AddingNewItemEventArgs e) - { - _ = Task.Run(() => - { - Dispatcher.Invoke(() => - { - UpdateLayout(); - CommitEdit(DataGridEditingUnit.Row, true); - }); - }); - } - - private void DataGrid_Loaded(object sender, RoutedEventArgs e) - { - var pres = MainWindow.FindVisualChild(this); - if (pres is null) - return; - - pres.SetResourceReference(ForegroundProperty, "CustomTextBrush"); - } - - protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e) - { - if (e.Property == VisibilityProperty) - { - if ((Visibility)e.NewValue == Visibility.Visible) - { - base.OnPropertyChanged(e); - UpdateLayout(); - - var pres = MainWindow.FindVisualChild(this); - pres?.SetResourceReference(ForegroundProperty, "CustomTextBrush"); - - return; - } - } - - base.OnPropertyChanged(e); - } - } -} diff --git a/UndertaleModTool/Controls/System/MenuItemDark.cs b/UndertaleModTool/Controls/System/MenuItemDark.cs deleted file mode 100644 index e7fba888e..000000000 --- a/UndertaleModTool/Controls/System/MenuItemDark.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Controls.Primitives; -using System.Windows.Media; -using System.Windows.Shapes; - -namespace UndertaleModTool -{ - /// - /// A standard menu item which compatible with the dark mode. - /// - public partial class MenuItemDark : MenuItem - { - /// Initializes a new instance of the menu item. - public MenuItemDark() - { - Loaded += MenuItemDark_Loaded; - } - - private void MenuItemDark_Loaded(object sender, RoutedEventArgs e) - { - Popup popup = MainWindow.FindVisualChild(this); - var content = popup?.Child as Border; - if (content is null) - return; - - content.SetResourceReference(BackgroundProperty, SystemColors.MenuBrushKey); - } - - /// - public override void OnApplyTemplate() - { - var rightArrow = MainWindow.FindVisualChild(this, "RightArrow"); - rightArrow?.SetResourceReference(Path.FillProperty, SystemColors.MenuTextBrushKey); - - base.OnApplyTemplate(); - } - } -} diff --git a/UndertaleModTool/Controls/System/RepeatButtonDark.cs b/UndertaleModTool/Controls/System/RepeatButtonDark.cs deleted file mode 100644 index 39a0edef9..000000000 --- a/UndertaleModTool/Controls/System/RepeatButtonDark.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Windows; -using System.Windows.Media; - -namespace UndertaleModTool -{ - /// - /// A standard repeat button which compatible with the dark mode. - /// - public partial class RepeatButtonDark : System.Windows.Controls.Primitives.RepeatButton - { - // Setting "Foreground" implicitly breaks internal "IsEnabled" style trigger, - // so this has to be handled manually. - private static readonly SolidColorBrush disabledTextBrush = new(Color.FromArgb(255, 131, 131, 131)); - - /// Initializes a new instance of the button. - public RepeatButtonDark() - { - // Even though this will be called again in "OnPropertyChanged()", it's required. - SetResourceReference(ForegroundProperty, "CustomTextBrush"); - } - - /// - protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e) - { - if (e.Property == IsEnabledProperty) - { - if ((bool)e.NewValue) - SetResourceReference(ForegroundProperty, "CustomTextBrush"); - else - Foreground = disabledTextBrush; - } - - base.OnPropertyChanged(e); - } - } -} diff --git a/UndertaleModTool/Controls/System/TabControlDark.cs b/UndertaleModTool/Controls/System/TabControlDark.cs deleted file mode 100644 index 30818c582..000000000 --- a/UndertaleModTool/Controls/System/TabControlDark.cs +++ /dev/null @@ -1,99 +0,0 @@ -using System; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Media; - -namespace UndertaleModTool -{ - /// - /// A standard tab control which compatible with the dark mode. - /// - public partial class TabControlDark : TabControl - { - /// Initializes a new instance of the tab control. - public TabControlDark() - { - Loaded += TabControlDark_Loaded; - } - - private void TabControlDark_Loaded(object sender, RoutedEventArgs e) - { - SetDarkMode(Settings.Instance is not null ? Settings.Instance.EnableDarkMode : false); - } - - /// - protected override DependencyObject GetContainerForItemOverride() - { - return new TabItemDark(); - } - - public void SetDarkMode(bool enable) - { - foreach (var item in MainWindow.FindVisualChildren(this)) - item.SetDarkMode(enable); - } - } - - /// - /// A standard tab item which compatible with the dark mode. - /// - public partial class TabItemDark : TabItem - { - private static readonly SolidColorBrush itemHighlightDarkBrush = new(Color.FromArgb(255, 48, 48, 60)); - private static readonly Brush itemInactiveBrush = new LinearGradientBrush( - new GradientStopCollection() - { - new GradientStop(Color.FromArgb(255, 240, 240, 240), 0), - new GradientStop(Color.FromArgb(255, 229, 229, 229), 1) - }, new(0, 0), new(1, 0) - ); - private static readonly Brush itemInactiveDarkBrush = new LinearGradientBrush( - new GradientStopCollection() - { - new GradientStop(Color.FromArgb(255, 15, 15, 15), 0), - new GradientStop(Color.FromArgb(255, 26, 26, 26), 1) - }, new(0, 0), new(1, 0) - ); - private Border border; - - /// Initializes a new instance of the tab item. - public TabItemDark() - { - SetResourceReference(ForegroundProperty, SystemColors.WindowTextBrushKey); - - Loaded += TabItemDark_Loaded; - } - - private void TabItemDark_Loaded(object sender, RoutedEventArgs e) - { - border = MainWindow.FindVisualChild(this); - if (Environment.OSVersion.Version.Major >= 10) - { - Border innerBd = MainWindow.FindVisualChild(this, "innerBorder"); - innerBd?.SetResourceReference(BackgroundProperty, SystemColors.WindowBrushKey); - } - - SetDarkMode(Settings.Instance.EnableDarkMode); - } - - public void SetDarkMode(bool enable) - { - Background = enable ? itemInactiveDarkBrush : itemInactiveBrush; - } - - /// - protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e) - { - if (e.Property == IsMouseOverProperty - && Settings.Instance.EnableDarkMode) - { - if ((bool)e.NewValue) - border?.SetValue(BackgroundProperty, itemHighlightDarkBrush); - else - border?.ClearValue(BackgroundProperty); - } - - base.OnPropertyChanged(e); - } - } -} diff --git a/UndertaleModTool/Controls/System/TextBoxDark.cs b/UndertaleModTool/Controls/System/TextBoxDark.cs deleted file mode 100644 index 1e24f5120..000000000 --- a/UndertaleModTool/Controls/System/TextBoxDark.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System.Windows.Controls; - -namespace UndertaleModTool -{ - /// - /// A standard text box which compatible with the dark mode. - /// - public partial class TextBoxDark : TextBox - { - /// Initializes a new instance of the text box. - public TextBoxDark() - { - SetResourceReference(ContextMenuProperty, "textBoxContextMenu"); - } - } -} diff --git a/UndertaleModTool/Controls/UndertaleObjectReference.xaml b/UndertaleModTool/Controls/UndertaleObjectReference.xaml index 1b5a72305..46632837f 100644 --- a/UndertaleModTool/Controls/UndertaleObjectReference.xaml +++ b/UndertaleModTool/Controls/UndertaleObjectReference.xaml @@ -9,10 +9,10 @@ d:DesignHeight="20" d:DesignWidth="300" Name="objectReference"> - + - + @@ -21,11 +21,11 @@ - - - - + + + diff --git a/UndertaleModTool/Controls/UndertaleRoomRenderer.xaml b/UndertaleModTool/Controls/UndertaleRoomRenderer.xaml index 54730b5e8..8ee6d8222 100644 --- a/UndertaleModTool/Controls/UndertaleRoomRenderer.xaml +++ b/UndertaleModTool/Controls/UndertaleRoomRenderer.xaml @@ -50,7 +50,7 @@ - + diff --git a/UndertaleModTool/Controls/UndertaleStringReference.xaml b/UndertaleModTool/Controls/UndertaleStringReference.xaml index 128830474..938683bfc 100644 --- a/UndertaleModTool/Controls/UndertaleStringReference.xaml +++ b/UndertaleModTool/Controls/UndertaleStringReference.xaml @@ -7,22 +7,22 @@ mc:Ignorable="d" d:DesignHeight="20" d:DesignWidth="300"> - + - + - - - - + + diff --git a/UndertaleModTool/Editors/UndertaleBackgroundEditor.xaml b/UndertaleModTool/Editors/UndertaleBackgroundEditor.xaml index ee24b895f..f30c16dbe 100644 --- a/UndertaleModTool/Editors/UndertaleBackgroundEditor.xaml +++ b/UndertaleModTool/Editors/UndertaleBackgroundEditor.xaml @@ -59,50 +59,40 @@ Unknown Always 2 - + Tile Width - + Tile Height - + Output Border X - + Output Border Y - + Tile Columns - + Items/frames per tile - + Tile Count - + Unknown Always Zero - + Frame Time (microseconds) - + Tile IDs - - - - @@ -177,7 +175,7 @@ - Save changes + diff --git a/UndertaleModTool/Editors/UndertaleFontEditor/UndertaleFontEditor.xaml b/UndertaleModTool/Editors/UndertaleFontEditor/UndertaleFontEditor.xaml index 9bd05cd80..1b5bc2fe7 100644 --- a/UndertaleModTool/Editors/UndertaleFontEditor/UndertaleFontEditor.xaml +++ b/UndertaleModTool/Editors/UndertaleFontEditor/UndertaleFontEditor.xaml @@ -11,7 +11,7 @@ - - - + @@ -311,10 +301,10 @@ - - - - + + + + @@ -330,7 +320,7 @@ - + @@ -345,19 +335,19 @@ - + - + - - - - + - + - + @@ -450,7 +430,7 @@ Note that the glyphs need to be specified in ascending order. Press the button below to sort them appropriately. - @@ -458,7 +438,7 @@ of an existing glyph, you should update the font range. Press the button below to do that. - diff --git a/UndertaleModTool/Editors/UndertaleFunctionEditor.xaml b/UndertaleModTool/Editors/UndertaleFunctionEditor.xaml index d006fec48..2efe373b0 100644 --- a/UndertaleModTool/Editors/UndertaleFunctionEditor.xaml +++ b/UndertaleModTool/Editors/UndertaleFunctionEditor.xaml @@ -21,6 +21,6 @@ Name string ID - + diff --git a/UndertaleModTool/Editors/UndertaleGameEndEditor.xaml b/UndertaleModTool/Editors/UndertaleGameEndEditor.xaml index 351fd6570..153769602 100644 --- a/UndertaleModTool/Editors/UndertaleGameEndEditor.xaml +++ b/UndertaleModTool/Editors/UndertaleGameEndEditor.xaml @@ -11,19 +11,9 @@ - + - - - @@ -382,8 +360,8 @@ - - + + @@ -394,8 +372,8 @@ - - + + @@ -406,8 +384,8 @@ - - + + @@ -435,7 +413,7 @@ - + @@ -444,7 +422,7 @@ - + @@ -453,7 +431,7 @@ - + @@ -462,7 +440,7 @@ - + @@ -479,7 +457,7 @@ - + @@ -487,7 +465,7 @@ - + @@ -500,12 +478,12 @@ - + - + diff --git a/UndertaleModTool/Editors/UndertaleGeneralInfoEditor.xaml b/UndertaleModTool/Editors/UndertaleGeneralInfoEditor.xaml index 9502b18e2..253e5078b 100644 --- a/UndertaleModTool/Editors/UndertaleGeneralInfoEditor.xaml +++ b/UndertaleModTool/Editors/UndertaleGeneralInfoEditor.xaml @@ -59,10 +59,10 @@ PreviewMouseLeftButtonDown="DebuggerCheckBox_PreviewMouseLeftButtonDown"/> Bytecode version - + Unknown - + FileName @@ -71,16 +71,16 @@ Last object ID - + Last tile ID - + Game ID - + DirectPlay GUID - + Name @@ -96,13 +96,13 @@ - + - + - + - + Default window size @@ -112,22 +112,22 @@ - + - + Flags - + License MD5 - + License CRC32 - + Timestamp - @@ -139,42 +139,32 @@ - + Display name Active targets - + Function classifications - + Steam AppID - + Debugger port - + Room order - - - @@ -91,10 +88,10 @@ - + - + @@ -107,10 +104,10 @@ - + - + @@ -123,10 +120,10 @@ - + - + @@ -139,10 +136,10 @@ - + - + @@ -151,20 +148,20 @@ - + - + - @@ -278,11 +275,11 @@ - + - + @@ -291,9 +288,9 @@ - + - + @@ -315,12 +312,12 @@ - + - + @@ -329,9 +326,9 @@ - + - + @@ -340,9 +337,9 @@ - + - + @@ -353,13 +350,12 @@ - - - + + - @@ -392,14 +388,6 @@ - - @@ -84,21 +84,21 @@ - - - @@ -108,13 +108,13 @@ - - + + - - + + - - - + + - - + - - + + - + - - + + - - + + - + - - @@ -390,23 +385,23 @@ - - + + + + + @@ -499,14 +494,14 @@ - - + - - + - + @@ -567,12 +562,12 @@ - + + diff --git a/UndertaleModTool/MainWindow.xaml.cs b/UndertaleModTool/MainWindow.xaml.cs index 09a8af552..844d9d2eb 100644 --- a/UndertaleModTool/MainWindow.xaml.cs +++ b/UndertaleModTool/MainWindow.xaml.cs @@ -207,24 +207,6 @@ public void RaiseOnSelectedChanged() public static string Version = Assembly.GetExecutingAssembly().GetName().Version.ToString(); #endif - private static readonly Color darkColor = Color.FromArgb(255, 32, 32, 32); - private static readonly Color darkLightColor = Color.FromArgb(255, 48, 48, 48); - private static readonly Color whiteColor = Color.FromArgb(255, 222, 222, 222); - private static readonly SolidColorBrush grayTextBrush = new(Color.FromArgb(255, 179, 179, 179)); - private static readonly SolidColorBrush inactiveSelectionBrush = new(Color.FromArgb(255, 212, 212, 212)); - private static readonly Dictionary appDarkStyle = new() - { - { SystemColors.WindowTextBrushKey, new SolidColorBrush(whiteColor) }, - { SystemColors.ControlTextBrushKey, new SolidColorBrush(whiteColor) }, - { SystemColors.WindowBrushKey, new SolidColorBrush(darkColor) }, - { SystemColors.ControlBrushKey, new SolidColorBrush(darkLightColor) }, - { SystemColors.ControlLightBrushKey, new SolidColorBrush(Color.FromArgb(255, 60, 60, 60)) }, - { SystemColors.MenuTextBrushKey, new SolidColorBrush(whiteColor) }, - { SystemColors.MenuBrushKey, new SolidColorBrush(darkLightColor) }, - { SystemColors.GrayTextBrushKey, new SolidColorBrush(Color.FromArgb(255, 136, 136, 136)) }, - { SystemColors.InactiveSelectionHighlightBrushKey, new SolidColorBrush(Color.FromArgb(255, 112, 112, 112)) } - }; - public MainWindow() { InitializeComponent(); @@ -252,11 +234,6 @@ public MainWindow() typeof(ImageMagick.MagickImage).GetTypeInfo().Assembly) .WithEmitDebugInformation(true); //when script throws an exception, add a exception location (line number) }); - - var resources = Application.Current.Resources; - resources["CustomTextBrush"] = SystemColors.ControlTextBrush; - resources[SystemColors.GrayTextBrushKey] = grayTextBrush; - resources[SystemColors.InactiveSelectionHighlightBrushKey] = inactiveSelectionBrush; } /// @@ -347,11 +324,9 @@ private void Window_IsVisibleChanged(object sender, DependencyPropertyChangedEve return; Settings.Load(); - if (Settings.Instance.EnableDarkMode) - { - SetDarkMode(true, true); - SetDarkTitleBarForWindow(this, true, false); - } + + SetDarkMode(Settings.Instance.EnableDarkMode, true); + SetDarkTitleBarForWindow(this, Settings.Instance.EnableDarkMode, false); } private async void Window_Loaded(object sender, RoutedEventArgs e) { @@ -567,37 +542,13 @@ public async Task ListenChildConnection(string key) public static void SetDarkMode(bool enable, bool isStartup = false) { - var resources = Application.Current.Resources; - - var mainWindow = Application.Current.MainWindow as MainWindow; - mainWindow.TabController.SetDarkMode(enable); - if (enable) { - foreach (var pair in appDarkStyle) - resources[pair.Key] = pair.Value; - - Windows.TextInput.BGColor = System.Drawing.Color.FromArgb(darkColor.R, - darkColor.G, - darkColor.B); - Windows.TextInput.TextBoxBGColor = System.Drawing.Color.FromArgb(darkLightColor.R, - darkLightColor.G, - darkLightColor.B); - Windows.TextInput.TextColor = System.Drawing.Color.FromArgb(whiteColor.R, - whiteColor.G, - whiteColor.B); + Theme.WPF.Themes.ThemesController.SetTheme(Theme.WPF.Themes.ThemeType.DeepDark); } else { - foreach (ResourceKey key in appDarkStyle.Keys) - resources.Remove(key); - - resources[SystemColors.GrayTextBrushKey] = grayTextBrush; - resources[SystemColors.InactiveSelectionHighlightBrushKey] = inactiveSelectionBrush; - - Windows.TextInput.BGColor = System.Drawing.SystemColors.Window; - Windows.TextInput.TextBoxBGColor = System.Drawing.SystemColors.ControlLight; - Windows.TextInput.TextColor = System.Drawing.SystemColors.ControlText; + Theme.WPF.Themes.ThemesController.SetTheme(Theme.WPF.Themes.ThemeType.LightTheme); } if (!isStartup) @@ -2200,7 +2151,7 @@ private void MenuItem_RunScript_SubmenuOpened(object sender, RoutedEventArgs e, var subDirName = subDirectory.Name; // In addition to the _ comment from above, we also need to add at least one item, so that WPF uses this as a submenuitem - MenuItemDark subItem = new() {Header = subDirName.Replace("_", "__"), Items = {new MenuItem {Header = "(loading...)", IsEnabled = false}}}; + MenuItem subItem = new() {Header = subDirName.Replace("_", "__"), Items = {new MenuItem {Header = "(loading...)", IsEnabled = false}}}; subItem.SubmenuOpened += (o, args) => MenuItem_RunScript_SubmenuOpened(o, args, subDirectory.FullName); item.Items.Add(subItem); } @@ -2214,15 +2165,6 @@ private void MenuItem_RunScript_SubmenuOpened(object sender, RoutedEventArgs e, } item.UpdateLayout(); - Popup popup = FindVisualChild(item); - var content = popup?.Child as Border; - if (content is not null) - { - if (Settings.Instance.EnableDarkMode) - content.Background = appDarkStyle[SystemColors.MenuBrushKey] as SolidColorBrush; - else - content.Background = SystemColors.MenuBrush; - } // If we're at the complete root, we need to add the "Run other script" button as well if (item.Name != "RootScriptItem") return; @@ -3926,7 +3868,7 @@ private void TabItem_MouseUp(object sender, MouseButtonEventArgs e) // source - https://stackoverflow.com/a/10738247/12136394 private void TabItem_PreviewMouseMove(object sender, MouseEventArgs e) { - if (e.Source is not TabItemDark tabItem || e.OriginalSource is Button) + if (e.Source is not TabItem tabItem || e.OriginalSource is Button) return; if (Mouse.PrimaryDevice.LeftButton == MouseButtonState.Pressed) @@ -3950,8 +3892,8 @@ private void TabItem_PreviewMouseMove(object sender, MouseEventArgs e) } private void TabItem_Drop(object sender, DragEventArgs e) { - if (e.Source is TabItemDark tabItemTarget && - e.Data.GetData(typeof(TabItemDark)) is TabItemDark tabItemSource && + if (e.Source is TabItem tabItemTarget && + e.Data.GetData(typeof(TabItem)) is TabItem tabItemSource && !tabItemTarget.Equals(tabItemSource)) { int sourceIndex = tabItemSource.TabIndex; diff --git a/UndertaleModTool/Themes/Attached/CornerRadiusHelper.cs b/UndertaleModTool/Themes/Attached/CornerRadiusHelper.cs new file mode 100644 index 000000000..ce8912d22 --- /dev/null +++ b/UndertaleModTool/Themes/Attached/CornerRadiusHelper.cs @@ -0,0 +1,13 @@ +using System.Windows; + +namespace Theme.WPF.Themes.Attached +{ + public static class CornerRadiusHelper + { + public static readonly DependencyProperty ValueProperty = DependencyProperty.RegisterAttached("Value", typeof(CornerRadius), typeof(CornerRadiusHelper), new PropertyMetadata(new CornerRadius(0))); + + public static void SetValue(DependencyObject element, CornerRadius value) => element.SetValue(ValueProperty, value); + + public static CornerRadius GetValue(DependencyObject element) => (CornerRadius) element.GetValue(ValueProperty); + } +} \ No newline at end of file diff --git a/UndertaleModTool/Themes/Attached/HorizontalScrolling.cs b/UndertaleModTool/Themes/Attached/HorizontalScrolling.cs new file mode 100644 index 000000000..e1c32d8ea --- /dev/null +++ b/UndertaleModTool/Themes/Attached/HorizontalScrolling.cs @@ -0,0 +1,167 @@ +using System; +using System.ComponentModel; +using System.Runtime.InteropServices; +using System.Security; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Media3D; + +namespace Theme.WPF.Themes.Attached +{ + public static class HorizontalScrolling + { + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true, BestFitMapping = false)] + private static extern bool SystemParametersInfo(int nAction, int nParam, ref int value, int ignore); + + private static bool hasCachedScrollChars; + private static int scrollChars; + + public static int ScrollChars + { + [SecurityCritical] + get + { + if (hasCachedScrollChars) + return scrollChars; + + if (!SystemParametersInfo(108, 0, ref scrollChars, 0)) + throw new Win32Exception(); + + hasCachedScrollChars = true; + return scrollChars; + } + } + + + public static readonly DependencyProperty UseHorizontalScrollingProperty = DependencyProperty.RegisterAttached("UseHorizontalScrolling", typeof(bool), typeof(HorizontalScrolling), new PropertyMetadata(false, OnUseHorizontalScrollWheelPropertyChanged)); + public static readonly DependencyProperty IsRequireShiftForHorizontalScrollProperty = DependencyProperty.RegisterAttached("IsRequireShiftForHorizontalScroll", typeof(bool), typeof(HorizontalScrolling), new PropertyMetadata(true)); + public static readonly DependencyProperty ForceHorizontalScrollingProperty = DependencyProperty.RegisterAttached("ForceHorizontalScrolling", typeof(bool), typeof(HorizontalScrolling), new PropertyMetadata(false)); + public static readonly DependencyProperty HorizontalScrollingAmountProperty = DependencyProperty.RegisterAttached("HorizontalScrollingAmount", typeof(int), typeof(HorizontalScrolling), new PropertyMetadata(ScrollChars)); + + public static void SetUseHorizontalScrolling(DependencyObject element, bool value) => element.SetValue(UseHorizontalScrollingProperty, value); + public static bool GetUseHorizontalScrolling(DependencyObject element) => (bool) element.GetValue(UseHorizontalScrollingProperty); + + public static void SetIsRequireShiftForHorizontalScroll(DependencyObject element, bool value) => element.SetValue(IsRequireShiftForHorizontalScrollProperty, value); + public static bool GetIsRequireShiftForHorizontalScroll(DependencyObject element) => (bool) element.GetValue(IsRequireShiftForHorizontalScrollProperty); + + public static bool GetForceHorizontalScrolling(DependencyObject d) => (bool) d.GetValue(ForceHorizontalScrollingProperty); + public static void SetForceHorizontalScrolling(DependencyObject d, bool value) => d.SetValue(ForceHorizontalScrollingProperty, value); + + public static int GetHorizontalScrollingAmount(DependencyObject d) => (int) d.GetValue(HorizontalScrollingAmountProperty); + public static void SetHorizontalScrollingAmount(DependencyObject d, int value) => d.SetValue(HorizontalScrollingAmountProperty, value); + + private static void OnUseHorizontalScrollWheelPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + if (d is UIElement element) + { + element.PreviewMouseWheel -= OnPreviewMouseWheel; + if ((bool) e.NewValue) + { + element.PreviewMouseWheel += OnPreviewMouseWheel; + } + } + else + { + throw new Exception("Attached property must be used with UIElement"); + } + } + + private static void OnPreviewMouseWheel(object sender, MouseWheelEventArgs e) + { + if (sender is UIElement element && e.Delta != 0) + { + ScrollViewer scroller = FindVisualChild(element); + if (scroller == null) + { + return; + } + + if (GetIsRequireShiftForHorizontalScroll(element) && scroller.HorizontalScrollBarVisibility == ScrollBarVisibility.Disabled) + { + return; + } + + int amount = GetHorizontalScrollingAmount(element); + if (amount < 1) + { + amount = 3; + } + + if (Keyboard.Modifiers == ModifierKeys.Shift || Mouse.MiddleButton == MouseButtonState.Pressed || GetForceHorizontalScrolling(element)) + { + int count = (e.Delta / 120) * amount; + if (e.Delta < 0) + { + for (int i = -count; i > 0; i--) + { + scroller.LineRight(); + } + } + else + { + for (int i = 0; i < count; i++) + { + scroller.LineLeft(); + } + } + + e.Handled = true; + } + } + } + + // https://github.com/AngryCarrot789/SharpPad/blob/master/SharpPad/Utils/Visuals/VisualTreeUtils.cs + + public static T FindVisualChild(DependencyObject obj, bool includeSelf = true) where T : class + { + if (obj == null) + return null; + if (includeSelf && obj is T t) + return t; + return FindVisualChildInternal(obj); + } + + private static T FindVisualChildInternal(DependencyObject obj) where T : class + { + int count, i; + if (obj is ContentControl) + { + DependencyObject child = ((ContentControl) obj).Content as DependencyObject; + if (child is T t) + { + return t; + } + else + { + return child != null ? FindVisualChildInternal(child) : null; + } + } + else if ((obj is Visual || obj is Visual3D) && (count = VisualTreeHelper.GetChildrenCount(obj)) > 0) + { + for (i = 0; i < count;) + { + DependencyObject child = VisualTreeHelper.GetChild(obj, i++); + if (child is T t) + { + return t; + } + } + + for (i = 0; i < count;) + { + T child = FindVisualChildInternal(VisualTreeHelper.GetChild(obj, i++)); + if (child != null) + { + return child; + } + } + } + + return null; + } + } +} \ No newline at end of file diff --git a/UndertaleModTool/Themes/Attached/MenuHelper.cs b/UndertaleModTool/Themes/Attached/MenuHelper.cs new file mode 100644 index 000000000..208e819ba --- /dev/null +++ b/UndertaleModTool/Themes/Attached/MenuHelper.cs @@ -0,0 +1,19 @@ +using System.Windows; + +namespace Theme.WPF.Themes.Attached +{ + public static class MenuHelper + { + public static readonly DependencyProperty UseStretchedContentProperty = DependencyProperty.RegisterAttached("UseStretchedContent", typeof(bool), typeof(MenuHelper), new PropertyMetadata(false)); + + public static void SetUseStretchedContent(DependencyObject element, bool value) + { + element.SetValue(UseStretchedContentProperty, value); + } + + public static bool GetUseStretchedContent(DependencyObject element) + { + return (bool) element.GetValue(UseStretchedContentProperty); + } + } +} \ No newline at end of file diff --git a/UndertaleModTool/Themes/Attached/PasswordBoxHelper.cs b/UndertaleModTool/Themes/Attached/PasswordBoxHelper.cs new file mode 100644 index 000000000..ea751dea2 --- /dev/null +++ b/UndertaleModTool/Themes/Attached/PasswordBoxHelper.cs @@ -0,0 +1,64 @@ +using System; +using System.Windows; +using System.Windows.Controls; + +namespace Theme.WPF.Themes.Attached +{ + public class PasswordBoxHelper + { + public static readonly DependencyProperty ListenToLengthProperty = + DependencyProperty.RegisterAttached( + "ListenToLength", + typeof(bool), + typeof(PasswordBoxHelper), + new FrameworkPropertyMetadata(false, PropertyChangedCallback)); + + private static void PropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + if (d is PasswordBox box) + { + box.PasswordChanged -= BoxOnPasswordChanged; + if (e.NewValue != null && (bool) e.NewValue) + { + box.PasswordChanged += BoxOnPasswordChanged; + } + } + else + { + throw new Exception("DependencyObject is not a password box. It is '" + (d == null ? "null" : d.GetType().Name) + '\''); + } + } + + public static readonly DependencyProperty InputLengthProperty = + DependencyProperty.RegisterAttached( + "InputLength", + typeof(int), + typeof(PasswordBoxHelper), + new FrameworkPropertyMetadata(0)); + + public static bool GetListenToLength(PasswordBox box) + { + return (bool) box.GetValue(ListenToLengthProperty); + } + + public static void SetListenToLength(PasswordBox box, bool value) + { + box.SetValue(ListenToLengthProperty, value); + } + + public static int GetInputLength(PasswordBox box) + { + return (int) box.GetValue(InputLengthProperty); + } + + public static void SetInputLength(PasswordBox box, int value) + { + box.SetValue(InputLengthProperty, value); + } + + private static void BoxOnPasswordChanged(object sender, RoutedEventArgs e) + { + SetInputLength((PasswordBox) sender, ((PasswordBox) sender).SecurePassword.Length); + } + } +} \ No newline at end of file diff --git a/UndertaleModTool/Themes/Attached/TextBoxAutoSelect.cs b/UndertaleModTool/Themes/Attached/TextBoxAutoSelect.cs new file mode 100644 index 000000000..2772ece86 --- /dev/null +++ b/UndertaleModTool/Themes/Attached/TextBoxAutoSelect.cs @@ -0,0 +1,45 @@ +using System.Windows; +using System.Windows.Controls; +using System.Windows.Controls.Primitives; + +namespace Theme.WPF.Themes.Attached +{ + public static class TextBoxAutoSelect + { + private static readonly RoutedEventHandler Handler = ControlOnLoaded; + + public static readonly DependencyProperty IsEnabledProperty = DependencyProperty.RegisterAttached("IsEnabled", typeof(bool), typeof(TextBoxAutoSelect), new PropertyMetadata(false, PropertyChangedCallback)); + + private static void PropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + if (d is Control control) + { + control.Loaded += Handler; + } + } + + private static void ControlOnLoaded(object sender, RoutedEventArgs e) + { + if (sender is Control control) + { + control.Focus(); + if (control is TextBoxBase textbox) + { + textbox.SelectAll(); + } + + control.Loaded -= Handler; + } + } + + public static void SetIsEnabled(DependencyObject element, bool value) + { + element.SetValue(IsEnabledProperty, value); + } + + public static bool GetIsEnabled(DependencyObject element) + { + return (bool) element.GetValue(IsEnabledProperty); + } + } +} \ No newline at end of file diff --git a/UndertaleModTool/Themes/Attached/TextHinting.cs b/UndertaleModTool/Themes/Attached/TextHinting.cs new file mode 100644 index 000000000..3239dbce0 --- /dev/null +++ b/UndertaleModTool/Themes/Attached/TextHinting.cs @@ -0,0 +1,40 @@ +using System; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Controls.Primitives; + +namespace Theme.WPF.Themes.Attached +{ + /// + /// An attached property class for showing a hint when a text box is empty. Set the text box's Tag property to the text + /// + public static class TextHinting + { + public static readonly DependencyProperty ShowWhenFocusedProperty = + DependencyProperty.RegisterAttached( + "ShowWhenFocused", + typeof(bool), + typeof(TextHinting), + new FrameworkPropertyMetadata(false)); + + public static void SetShowWhenFocused(Control control, bool value) + { + if (control is TextBoxBase || control is PasswordBox) + { + control.SetValue(ShowWhenFocusedProperty, value); + } + + throw new ArgumentException("Control was not a textbox", nameof(control)); + } + + public static bool GetShowWhenFocused(Control control) + { + if (control is TextBoxBase || control is PasswordBox) + { + return (bool) control.GetValue(ShowWhenFocusedProperty); + } + + throw new ArgumentException("Control was not a textbox", nameof(control)); + } + } +} \ No newline at end of file diff --git a/UndertaleModTool/Themes/ColourDictionaries/DeepDark.xaml b/UndertaleModTool/Themes/ColourDictionaries/DeepDark.xaml new file mode 100644 index 000000000..fabc130ae --- /dev/null +++ b/UndertaleModTool/Themes/ColourDictionaries/DeepDark.xaml @@ -0,0 +1,189 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/UndertaleModTool/Themes/ColourDictionaries/LightTheme.xaml b/UndertaleModTool/Themes/ColourDictionaries/LightTheme.xaml new file mode 100644 index 000000000..7cd17ff5c --- /dev/null +++ b/UndertaleModTool/Themes/ColourDictionaries/LightTheme.xaml @@ -0,0 +1,190 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/UndertaleModTool/Themes/ControlColours.xaml b/UndertaleModTool/Themes/ControlColours.xaml new file mode 100644 index 000000000..72f110064 --- /dev/null +++ b/UndertaleModTool/Themes/ControlColours.xaml @@ -0,0 +1,284 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/UndertaleModTool/Themes/Controls.xaml b/UndertaleModTool/Themes/Controls.xaml new file mode 100644 index 000000000..ac1ca6cee --- /dev/null +++ b/UndertaleModTool/Themes/Controls.xaml @@ -0,0 +1,5456 @@ + + Fade + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/UndertaleModTool/Themes/Controls.xaml.cs b/UndertaleModTool/Themes/Controls.xaml.cs new file mode 100644 index 000000000..a8340acb6 --- /dev/null +++ b/UndertaleModTool/Themes/Controls.xaml.cs @@ -0,0 +1,49 @@ +using System.Windows; + +namespace Theme.WPF.Themes +{ + public partial class Controls + { + private void CloseWindow_Event(object sender, RoutedEventArgs e) + { + if (e.Source != null) + this.CloseWind(Window.GetWindow((FrameworkElement) e.Source)); + } + + private void AutoMinimize_Event(object sender, RoutedEventArgs e) + { + if (e.Source != null) + this.MaximizeRestore(Window.GetWindow((FrameworkElement) e.Source)); + } + + private void Minimize_Event(object sender, RoutedEventArgs e) + { + if (e.Source != null) + this.MinimizeWind(Window.GetWindow((FrameworkElement) e.Source)); + } + + public void CloseWind(Window window) => window?.Close(); + + public void MaximizeRestore(Window window) + { + if (window == null) + return; + switch (window.WindowState) + { + case WindowState.Normal: + window.WindowState = WindowState.Maximized; + break; + case WindowState.Minimized: + case WindowState.Maximized: + window.WindowState = WindowState.Normal; + break; + } + } + + public void MinimizeWind(Window window) + { + if (window != null) + window.WindowState = WindowState.Minimized; + } + } +} \ No newline at end of file diff --git a/UndertaleModTool/Themes/ScrollViewerInnerBorderThicknessConverter.cs b/UndertaleModTool/Themes/ScrollViewerInnerBorderThicknessConverter.cs new file mode 100644 index 000000000..8caf765ac --- /dev/null +++ b/UndertaleModTool/Themes/ScrollViewerInnerBorderThicknessConverter.cs @@ -0,0 +1,43 @@ +using System; +using System.Globalization; +using System.Windows; +using System.Windows.Data; + +namespace Theme.WPF.Themes +{ + public class ScrollViewerInnerBorderThicknessConverter : IMultiValueConverter + { + public static ScrollViewerInnerBorderThicknessConverter Instance { get; } = new ScrollViewerInnerBorderThicknessConverter(); + + public double Left { get; } = 0.0; + public double Top { get; } = 0.0; + public double RightVisible { get; } = 1.0; + public double RightNotVisible { get; } = 0.0; + public double BottomVisible { get; } = 1.0; + public double BottomNotVisible { get; } = 0.0; + + public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) + { + if (values == null || values.Length != 2) + { + throw new Exception("Need 2 values for this converter: bottom and right scroll bar visibility values"); + } + + if (!(values[0] is Visibility bottomBar)) + throw new Exception("Bottom bar value is not a visibility: " + values[0]); + if (!(values[1] is Visibility rightBar)) + throw new Exception("Right bar value is not a visibility: " + values[1]); + + return new Thickness( + this.Left, + this.Top, + rightBar == Visibility.Visible ? this.RightVisible : this.RightNotVisible, + bottomBar == Visibility.Visible ? this.BottomVisible : this.BottomNotVisible); + } + + public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) + { + throw new Exception("no"); + } + } +} \ No newline at end of file diff --git a/UndertaleModTool/Themes/ThemeType.cs b/UndertaleModTool/Themes/ThemeType.cs new file mode 100644 index 000000000..25d5d8f79 --- /dev/null +++ b/UndertaleModTool/Themes/ThemeType.cs @@ -0,0 +1,33 @@ +using System; + +namespace Theme.WPF.Themes +{ + public enum ThemeType + { + None, + SoftDark, + RedBlackTheme, + DeepDark, + GreyTheme, + DarkGreyTheme, + LightTheme, + } + + public static class ThemeTypeExtension + { + public static string GetName(this ThemeType type) + { + switch (type) + { + case ThemeType.None: return null; + case ThemeType.SoftDark: return "SoftDark"; + case ThemeType.RedBlackTheme: return "RedBlackTheme"; + case ThemeType.DeepDark: return "DeepDark"; + case ThemeType.GreyTheme: return "GreyTheme"; + case ThemeType.DarkGreyTheme: return "DarkGreyTheme"; + case ThemeType.LightTheme: return "LightTheme"; + default: throw new ArgumentOutOfRangeException(nameof(type), type, null); + } + } + } +} \ No newline at end of file diff --git a/UndertaleModTool/Themes/ThemesController.cs b/UndertaleModTool/Themes/ThemesController.cs new file mode 100644 index 000000000..72e0462fa --- /dev/null +++ b/UndertaleModTool/Themes/ThemesController.cs @@ -0,0 +1,69 @@ +using System; +using System.Collections.ObjectModel; +using System.Windows; +using System.Windows.Media; + +namespace Theme.WPF.Themes +{ + public static class ThemesController + { + public static ThemeType CurrentTheme { get; set; } = ThemeType.LightTheme; + + static ResourceDictionary ColourDictionary = null; + static ResourceDictionary ControlColours = null; + static ResourceDictionary Controls = null; + + public static void SetTheme(ThemeType theme) + { + //Theme.WPF.Themes.ThemesController.SetTheme(Theme.WPF.Themes.ThemeType.None) + string themeName = theme.GetName(); + //if (string.IsNullOrEmpty(themeName)) + //{ + // return; + //} + + Controls = new ResourceDictionary() { Source = new Uri("Themes/Controls.xaml", UriKind.Relative) }; + + if (theme == ThemeType.None) + { + if (CurrentTheme != ThemeType.None) + { + Application.Current.Resources.MergedDictionaries.RemoveAt(2); + Application.Current.Resources.MergedDictionaries.RemoveAt(1); + Application.Current.Resources.MergedDictionaries.RemoveAt(0); + } + } + else + { + ColourDictionary = new ResourceDictionary() { Source = new Uri($"Themes/ColourDictionaries/{themeName}.xaml", UriKind.Relative) }; + ControlColours = new ResourceDictionary() { Source = new Uri("Themes/ControlColours.xaml", UriKind.Relative) }; + + if (CurrentTheme == ThemeType.None) + { + Application.Current.Resources.MergedDictionaries.Insert(0, ColourDictionary); + } + else + { + Application.Current.Resources.MergedDictionaries.RemoveAt(2); + Application.Current.Resources.MergedDictionaries.RemoveAt(1); + Application.Current.Resources.MergedDictionaries[0] = ColourDictionary; + } + + Application.Current.Resources.MergedDictionaries.Insert(1, ControlColours); + Application.Current.Resources.MergedDictionaries.Insert(2, Controls); + } + + CurrentTheme = theme; + } + + public static object GetResource(object key) + { + return ColourDictionary[key]; + } + + public static SolidColorBrush GetBrush(string name) + { + return GetResource(name) is SolidColorBrush brush ? brush : new SolidColorBrush(Colors.White); + } + } +} \ No newline at end of file diff --git a/UndertaleModTool/Themes/readme.md b/UndertaleModTool/Themes/readme.md new file mode 100644 index 000000000..14b4aa34a --- /dev/null +++ b/UndertaleModTool/Themes/readme.md @@ -0,0 +1,64 @@ +# New Theme Library + +I decided to upgrade the theme library so that, instead of having each theme +contain all of the control styles, there is instead just a global style file. + +I may extract them into their own files at some point, e.g. ButtonStyles.xaml, +ListBoxStyles.xaml, etc, just so that it's easier to find stuff + +## Adjustable styles + +- You can switch between a thin and thick scroll bar style. In `Controls.xaml`, search + for the text: "Switch between automatic thin and thick scroll bars here" and change the + BasedOn part between `ScrollBarStyle_THIN` and `ScrollBarStyle_THICK` + +# Files and file structures + +## Controls.xaml + +Contains all of the control styles. This is a big file, so it might take a while +for code analysis to load for Rider + +## ControlColours.xaml + +This is where I (mostly attempted to) keep control-specific brushes and stuff. +However, I still sometimes used the resource keys directly, which is fine because each theme +should contain the exact same resource key names, but their colours should change + +I may attempt to make a "LightThemeControlColours" and "DarkThemeControlColours", because sometimes +there are colour differences between light and dark themes that just might not work out and will look weird + +## Colour Dictionaries + +These stores all of the colour keys that are accessed throughout the application. + +- All colours are prefixed with "AColour". The 'A' at the start is just for quick searching. +- All brushes are prefixed with "ABrush", the 'A' used for the same reason as colours. + +Foreground has a static, deeper and disabled colour. +Static for regular text colour +Deeper is just a slightly darker/less visible colour +Disabled is a much darker/less visible colour + +Glyphs have static, disabled, mouse over/down, selected + inactive selected colours. +There's also a colourful glyph which has the same keys but with "Colourful" added + +### Tones + +Tones are the different colour phases for different controls. The lower tone number +means darker (in dark themes) and typically lighter in light themes + +Accent tones follow the same rules but they use a colour instead of +moving towards black or white (for dark/light themes) + +Tone 0, 1, 2 and 3 are useful for containers/panels (e.g. Grid or a Border that +contains a Grid, DockPanels, etc.) + +The rest of the tones are used for standard controls (e.g. buttons). Most controls +use Tone 4 and 5, but some may use higher tones. You can obviously changes this +if you want and make a button use a higher tone in order to stand out more + +> All Color keys have a corresponding SolidColourBrush key +> (e.g. "AColour.Glyph.Static" -> "ABrush.Glyph.Static"), which is useful +> if you want to animate a colour which I think requires Colour not Brush +> (that might be gradients though, can't remember) diff --git a/UndertaleModTool/Windows/ClickableTextOutput.xaml b/UndertaleModTool/Windows/ClickableTextOutput.xaml index bdb6dd16e..aeb4513f4 100644 --- a/UndertaleModTool/Windows/ClickableTextOutput.xaml +++ b/UndertaleModTool/Windows/ClickableTextOutput.xaml @@ -6,11 +6,12 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:UndertaleModTool" mc:Ignorable="d" - Title="ClickableTextOutput" Height="540" Width="536" MinHeight="160" MinWidth="210"> + Title="ClickableTextOutput" Height="540" Width="536" MinHeight="160" MinWidth="210" + Style="{DynamicResource DefaultWindowStyle}"> - - - + + + @@ -22,9 +23,6 @@ Margin="0,-3,0,0" Grid.RowSpan="2"/> - - - - + - - - - + - - - - + +