From df2f3803f4116c8bf23e39c071241033293ea11e Mon Sep 17 00:00:00 2001
From: Andy McFadden
Date: Sat, 12 Oct 2019 17:23:32 -0700
Subject: [PATCH] SourceGen After Dark
Most of SourceGen uses standard WPF controls, which get their default
style from the system theme. The main disassembly list uses a
custom style, and always looks like the Windows default theme.
Some people greatly prefer white text on a black background, so we
now provide a way to get that. This also requires muting the colors
used for Notes, since those were chosen to contrast with black text.
This does not affect anything other than the ListView used for
code, because everything else can be set through the Windows
"personalization" interface. We might want to change the way the
Notes window looks though, to avoid having glowing bookmarks on
the side.
---
SourceGen/AppSettings.cs | 3 +-
SourceGen/LineListGen.cs | 16 +++++---
SourceGen/MainController.cs | 26 ++++++++++++
SourceGen/Res/Theme_Dark.xaml | 51 +++++++++++++++++++++++
SourceGen/Res/Theme_Light.xaml | 44 ++++++++++++++++++++
SourceGen/RuntimeData/Help/settings.html | 8 ++++
SourceGen/SourceGen.csproj | 8 ++++
SourceGen/WpfGui/CodeListItemStyle.xaml | 52 ++++++++++++------------
SourceGen/WpfGui/EditAppSettings.xaml | 4 +-
SourceGen/WpfGui/EditAppSettings.xaml.cs | 9 ++++
SourceGen/WpfGui/MainWindow.xaml | 4 +-
SourceGen/WpfGui/MainWindow.xaml.cs | 48 ++++++++++++++++++++++
12 files changed, 238 insertions(+), 35 deletions(-)
create mode 100644 SourceGen/Res/Theme_Dark.xaml
create mode 100644 SourceGen/Res/Theme_Light.xaml
diff --git a/SourceGen/AppSettings.cs b/SourceGen/AppSettings.cs
index 3d8b53f..8d06140 100644
--- a/SourceGen/AppSettings.cs
+++ b/SourceGen/AppSettings.cs
@@ -69,9 +69,10 @@ namespace SourceGen {
public const string CLIP_LINE_FORMAT = "clip-line-format";
- // Main project view settings.
public const string PRVW_RECENT_PROJECT_LIST = "prvw-recent-project-list";
+ public const string SKIN_DARK_COLOR_SCHEME = "skin-dark-color-scheme";
+
// Symbol-list window options.
public const string SYMWIN_SHOW_USER = "symwin-show-user";
public const string SYMWIN_SHOW_AUTO = "symwin-show-auto";
diff --git a/SourceGen/LineListGen.cs b/SourceGen/LineListGen.cs
index 724dd9b..8c273e0 100644
--- a/SourceGen/LineListGen.cs
+++ b/SourceGen/LineListGen.cs
@@ -28,6 +28,11 @@ namespace SourceGen {
/// Converts file data and Anattrib contents into a series of strings and format metadata.
///
public class LineListGen {
+ ///
+ /// Color multiplier for Notes.
+ ///
+ public float NoteColorMultiplier { get; set; } = 1.0f;
+
///
/// List of display lines.
///
@@ -815,7 +820,7 @@ namespace SourceGen {
out MultiLineComment headerComment)) {
List formatted = headerComment.FormatText(formatter, string.Empty);
StringListToLines(formatted, Line.HEADER_COMMENT_OFFSET, Line.Type.LongComment,
- CommonWPF.Helper.ZeroColor, tmpLines);
+ CommonWPF.Helper.ZeroColor, 1.0f, tmpLines);
}
// Format symbols.
@@ -920,12 +925,12 @@ namespace SourceGen {
if (mProject.Notes.TryGetValue(offset, out MultiLineComment noteData)) {
List formatted = noteData.FormatText(mFormatter, "NOTE: ");
StringListToLines(formatted, offset, Line.Type.Note,
- noteData.BackgroundColor, lines);
+ noteData.BackgroundColor, NoteColorMultiplier, lines);
}
if (mProject.LongComments.TryGetValue(offset, out MultiLineComment longComment)) {
List formatted = longComment.FormatText(mFormatter, string.Empty);
StringListToLines(formatted, offset, Line.Type.LongComment,
- longComment.BackgroundColor, lines);
+ longComment.BackgroundColor, NoteColorMultiplier, lines);
}
// Local variable tables come next. Defer rendering.
@@ -1115,10 +1120,11 @@ namespace SourceGen {
/// Background color (for Notes).
/// Line list to add data to.
private static void StringListToLines(List list, int offset, Line.Type lineType,
- Color color, List lines) {
+ Color color, float mult, List lines) {
foreach (string str in list) {
Line line = new Line(offset, 0, lineType);
- FormattedParts parts = FormattedParts.CreateNote(str, color);
+ FormattedParts parts = FormattedParts.CreateNote(str,
+ Color.Multiply(color, mult));
line.Parts = parts;
line.BackgroundColor = color;
lines.Add(line);
diff --git a/SourceGen/MainController.cs b/SourceGen/MainController.cs
index dfd842a..8f508dd 100644
--- a/SourceGen/MainController.cs
+++ b/SourceGen/MainController.cs
@@ -162,6 +162,11 @@ namespace SourceGen {
///
private int mTargetHighlightIndex = -1;
+ ///
+ /// Code list color scheme.
+ ///
+ private MainWindow.ColorScheme mColorScheme = MainWindow.ColorScheme.Light;
+
///
/// CPU definition used when the Formatter was created. If the CPU choice or
/// inclusion of undocumented opcodes changes, we need to wipe the formatter.
@@ -517,6 +522,18 @@ namespace SourceGen {
// Unpack the recent-project list.
UnpackRecentProjectList();
+ // Set the color scheme.
+ bool useDark = settings.GetBool(AppSettings.SKIN_DARK_COLOR_SCHEME, false);
+ if (useDark) {
+ mColorScheme = MainWindow.ColorScheme.Dark;
+ } else {
+ mColorScheme = MainWindow.ColorScheme.Light;
+ }
+ mMainWin.SetColorScheme(mColorScheme);
+ if (CodeLineList != null) {
+ SetCodeLineListColorMultiplier();
+ }
+
// Enable the DEBUG menu if configured.
mMainWin.ShowDebugMenu =
AppSettings.Global.GetBool(AppSettings.DEBUG_MENU_ENABLED, false);
@@ -531,6 +548,14 @@ namespace SourceGen {
}
}
+ private void SetCodeLineListColorMultiplier() {
+ if (mColorScheme == MainWindow.ColorScheme.Dark) {
+ CodeLineList.NoteColorMultiplier = 0.6f;
+ } else {
+ CodeLineList.NoteColorMultiplier = 1.0f;
+ }
+ }
+
private void UnpackRecentProjectList() {
RecentProjectPaths.Clear();
@@ -670,6 +695,7 @@ namespace SourceGen {
private void FinishPrep() {
CodeLineList = new LineListGen(mProject, mMainWin.CodeDisplayList,
mOutputFormatter, mPseudoOpNames);
+ SetCodeLineListColorMultiplier();
string messages = mProject.LoadExternalFiles();
if (messages.Length != 0) {
diff --git a/SourceGen/Res/Theme_Dark.xaml b/SourceGen/Res/Theme_Dark.xaml
new file mode 100644
index 0000000..a0a44df
--- /dev/null
+++ b/SourceGen/Res/Theme_Dark.xaml
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+ #FF787D7F
+ #FF6A787F
+ #FF6C7A7F
+ #FF4D6E7D
+ #FF777777
+ #FF6E6E6E
+ #FF757C7F
+ #FF64767E
+
+ #FF6C7F7A
+ #FF4D7D6E
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/SourceGen/Res/Theme_Light.xaml b/SourceGen/Res/Theme_Light.xaml
new file mode 100644
index 0000000..86ceb88
--- /dev/null
+++ b/SourceGen/Res/Theme_Light.xaml
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+ #FFF1FBFF
+ #FFD5F1FE
+ #FFD9F4FF
+ #FF9BDDFB
+ #FFEEEDED
+ #FFDDDDDD
+ #FFEAF9FF
+ #FFC9EDFD
+
+ #FFD9FFF4
+ #FF9BFBDD
+
+
+
+
+
+
+
+
+
diff --git a/SourceGen/RuntimeData/Help/settings.html b/SourceGen/RuntimeData/Help/settings.html
index 2922187..744d1a1 100644
--- a/SourceGen/RuntimeData/Help/settings.html
+++ b/SourceGen/RuntimeData/Help/settings.html
@@ -65,6 +65,14 @@ hex data in the code list "bytes" column from dense (20edfd
)
to spaced (20 ed fd
). This also affects the format of
clipboard copies and exports.
+Check "use 'dark' color scheme" to change the main disassembly list
+to use white text on a black background, and mute the Note highlight
+colors.
+(Most of the GUI uses standard Windows controls that take their colors
+from the system theme, but the disassembly list uses a custom style. You
+can change the rest of the UI from the Windows display "personalization"
+controls.)
+
diff --git a/SourceGen/SourceGen.csproj b/SourceGen/SourceGen.csproj
index d5fd7ef..61dd22b 100644
--- a/SourceGen/SourceGen.csproj
+++ b/SourceGen/SourceGen.csproj
@@ -237,6 +237,14 @@
+
+ Designer
+ MSBuild:Compile
+
+
+ Designer
+ MSBuild:Compile
+
Designer
MSBuild:Compile
diff --git a/SourceGen/WpfGui/CodeListItemStyle.xaml b/SourceGen/WpfGui/CodeListItemStyle.xaml
index 299bbc9..422ffed 100644
--- a/SourceGen/WpfGui/CodeListItemStyle.xaml
+++ b/SourceGen/WpfGui/CodeListItemStyle.xaml
@@ -15,8 +15,8 @@ limitations under the License.
-->
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
@@ -263,7 +263,7 @@ See also https://github.com/fadden/DisasmUiTest
-
+
diff --git a/SourceGen/WpfGui/EditAppSettings.xaml b/SourceGen/WpfGui/EditAppSettings.xaml
index ee40568..c67de58 100644
--- a/SourceGen/WpfGui/EditAppSettings.xaml
+++ b/SourceGen/WpfGui/EditAppSettings.xaml
@@ -129,8 +129,10 @@ limitations under the License.
-
+
diff --git a/SourceGen/WpfGui/EditAppSettings.xaml.cs b/SourceGen/WpfGui/EditAppSettings.xaml.cs
index 7eaf3f5..6b5d36c 100644
--- a/SourceGen/WpfGui/EditAppSettings.xaml.cs
+++ b/SourceGen/WpfGui/EditAppSettings.xaml.cs
@@ -414,6 +414,15 @@ namespace SourceGen.WpfGui {
}
}
+ public bool DarkColorScheme {
+ get { return mSettings.GetBool(AppSettings.SKIN_DARK_COLOR_SCHEME, false); }
+ set {
+ mSettings.SetBool(AppSettings.SKIN_DARK_COLOR_SCHEME, value);
+ OnPropertyChanged();
+ IsDirty = true;
+ }
+ }
+
public bool EnableDebugMenu {
get { return mSettings.GetBool(AppSettings.DEBUG_MENU_ENABLED, false); }
set {
diff --git a/SourceGen/WpfGui/MainWindow.xaml b/SourceGen/WpfGui/MainWindow.xaml
index 8c40748..f131d92 100644
--- a/SourceGen/WpfGui/MainWindow.xaml
+++ b/SourceGen/WpfGui/MainWindow.xaml
@@ -33,10 +33,10 @@ limitations under the License.
-
-
+
+
diff --git a/SourceGen/WpfGui/MainWindow.xaml.cs b/SourceGen/WpfGui/MainWindow.xaml.cs
index 5a5869c..63518b2 100644
--- a/SourceGen/WpfGui/MainWindow.xaml.cs
+++ b/SourceGen/WpfGui/MainWindow.xaml.cs
@@ -157,6 +157,12 @@ namespace SourceGen.WpfGui {
// Handle to protected ListView.SetSelectedItems() method
private MethodInfo listViewSetSelectedItems;
+ // Color theme.
+ public enum ColorScheme { Unknown = 0, Light, Dark };
+ private ColorScheme mColorScheme;
+ private ResourceDictionary mLightTheme;
+ private ResourceDictionary mDarkTheme;
+
public MainWindow() {
Debug.WriteLine("START at " + DateTime.Now.ToLocalTime());
@@ -173,6 +179,16 @@ namespace SourceGen.WpfGui {
this.DataContext = this;
+ mLightTheme = new ResourceDictionary() {
+ Source = new Uri("/Res/Theme_Light.xaml", UriKind.Relative)
+ };
+ mDarkTheme = new ResourceDictionary() {
+ Source = new Uri("/Res/Theme_Dark.xaml", UriKind.Relative)
+ };
+ Resources.MergedDictionaries.Add(mLightTheme);
+ mColorScheme = ColorScheme.Light;
+
+
CodeDisplayList = new DisplayList();
codeListView.ItemsSource = CodeDisplayList;
// https://dlaa.me/blog/post/9425496 to re-auto-size after data added (this may
@@ -421,6 +437,38 @@ namespace SourceGen.WpfGui {
}
}
+ ///
+ /// Sets the primary color scheme.
+ ///
+ ///
+ /// H/T http://www.markodevcic.com/post/changing_wpf_themes_dynamically
+ ///
+ public void SetColorScheme(ColorScheme newScheme) {
+ if (mColorScheme == newScheme) {
+ // nothing to do
+ return;
+ }
+
+ ResourceDictionary oldDict, newDict;
+
+ if (mColorScheme == ColorScheme.Light) {
+ oldDict = mLightTheme;
+ } else {
+ oldDict = mDarkTheme;
+ }
+ if (newScheme == ColorScheme.Light) {
+ newDict = mLightTheme;
+ } else {
+ newDict = mDarkTheme;
+ }
+ Debug.WriteLine("Changing color scheme from " + mColorScheme + " to " + newScheme +
+ " (dict count=" + Resources.MergedDictionaries.Count + ")");
+
+ Resources.MergedDictionaries.Remove(oldDict);
+ Resources.MergedDictionaries.Add(newDict);
+ mColorScheme = newScheme;
+ }
+
#region Window placement
//