Dark mode wip

This commit is contained in:
Ben Olden-Cooligan 2023-03-11 13:41:22 -08:00
parent 1ddcf2109d
commit bcf7f13b2b
17 changed files with 137 additions and 13 deletions

View File

@ -0,0 +1,8 @@
namespace NAPS2.EtoForms.Gtk;
public class GtkDarkModeProvider : IDarkModeProvider
{
public bool IsDarkModeEnabled { get; }
public event EventHandler? DarkModeChanged;
}

View File

@ -5,6 +5,7 @@ using Gdk;
using Gtk;
using NAPS2.EtoForms.Desktop;
using NAPS2.EtoForms.Gtk;
using NAPS2.EtoForms.Widgets;
using NAPS2.ImportExport.Images;
using Command = Eto.Forms.Command;
@ -24,6 +25,7 @@ public class GtkDesktopForm : DesktopForm
DesktopKeyboardShortcuts keyboardShortcuts,
INotificationManager notify,
CultureHelper cultureHelper,
ColorScheme colorScheme,
IProfileManager profileManager,
UiImageList imageList,
ImageTransfer imageTransfer,
@ -32,12 +34,13 @@ public class GtkDesktopForm : DesktopForm
DesktopController desktopController,
IDesktopScanController desktopScanController,
ImageListActions imageListActions,
ImageListViewBehavior imageListViewBehavior,
DesktopFormProvider desktopFormProvider,
IDesktopSubFormController desktopSubFormController,
DesktopCommands commands)
: base(config, keyboardShortcuts, notify, cultureHelper, profileManager,
: base(config, keyboardShortcuts, notify, cultureHelper, colorScheme, profileManager,
imageList, imageTransfer, thumbnailController, thumbnailProvider, desktopController, desktopScanController,
imageListActions, desktopFormProvider, desktopSubFormController, commands)
imageListActions, imageListViewBehavior, desktopFormProvider, desktopSubFormController, commands)
{
var cssProvider = new CssProvider();
cssProvider.LoadFromData(@"

View File

@ -16,6 +16,7 @@ public class GtkModule : GuiModule
builder.RegisterType<StubNotificationManager>().As<INotificationManager>().SingleInstance();
builder.RegisterType<StubScannedImagePrinter>().As<IScannedImagePrinter>();
builder.RegisterType<GtkDarkModeProvider>().As<IDarkModeProvider>();
builder.RegisterType<GtkImageContext>().As<ImageContext>();
builder.RegisterType<GtkImageContext>().AsSelf();

View File

@ -0,0 +1,8 @@
namespace NAPS2.EtoForms.Mac;
public class MacDarkModeProvider : IDarkModeProvider
{
public bool IsDarkModeEnabled { get; }
public event EventHandler? DarkModeChanged;
}

View File

@ -3,6 +3,7 @@ using Eto.Forms;
using NAPS2.EtoForms.Desktop;
using NAPS2.EtoForms.Layout;
using NAPS2.EtoForms.Mac;
using NAPS2.EtoForms.Widgets;
using NAPS2.ImportExport.Images;
using NAPS2.Scan;
@ -15,6 +16,7 @@ public class MacDesktopForm : DesktopForm
DesktopKeyboardShortcuts keyboardShortcuts,
INotificationManager notify,
CultureHelper cultureHelper,
ColorScheme colorScheme,
IProfileManager profileManager,
UiImageList imageList,
ImageTransfer imageTransfer,
@ -23,12 +25,13 @@ public class MacDesktopForm : DesktopForm
DesktopController desktopController,
IDesktopScanController desktopScanController,
ImageListActions imageListActions,
ImageListViewBehavior imageListViewBehavior,
DesktopFormProvider desktopFormProvider,
IDesktopSubFormController desktopSubFormController,
DesktopCommands commands)
: base(config, keyboardShortcuts, notify, cultureHelper, profileManager,
: base(config, keyboardShortcuts, notify, cultureHelper, colorScheme, profileManager,
imageList, imageTransfer, thumbnailController, thumbnailProvider, desktopController, desktopScanController,
imageListActions, desktopFormProvider, desktopSubFormController, commands)
imageListActions, imageListViewBehavior, desktopFormProvider, desktopSubFormController, commands)
{
// For retina screens
_thumbnailController.Oversample = 2.0;

View File

@ -17,6 +17,7 @@ public class MacModule : GuiModule
builder.RegisterType<StubNotificationManager>().As<INotificationManager>().SingleInstance();
builder.RegisterType<StubScannedImagePrinter>().As<IScannedImagePrinter>();
builder.RegisterType<MacDarkModeProvider>().As<IDarkModeProvider>();
builder.RegisterType<MacImageContext>().As<ImageContext>();
builder.RegisterType<MacImageContext>().AsSelf();
builder.RegisterType<MacIconProvider>().As<IIconProvider>();

View File

@ -5,6 +5,7 @@ using Eto.WinForms;
using Eto.WinForms.Forms.ToolBar;
using NAPS2.EtoForms.Desktop;
using NAPS2.EtoForms.Layout;
using NAPS2.EtoForms.Widgets;
using NAPS2.EtoForms.WinForms;
using NAPS2.ImportExport.Images;
using NAPS2.WinForms;
@ -27,6 +28,7 @@ public class WinFormsDesktopForm : DesktopForm
DesktopKeyboardShortcuts keyboardShortcuts,
INotificationManager notify,
CultureHelper cultureHelper,
ColorScheme colorScheme,
IProfileManager profileManager,
UiImageList imageList,
ImageTransfer imageTransfer,
@ -35,12 +37,13 @@ public class WinFormsDesktopForm : DesktopForm
DesktopController desktopController,
IDesktopScanController desktopScanController,
ImageListActions imageListActions,
ImageListViewBehavior imageListViewBehavior,
DesktopFormProvider desktopFormProvider,
IDesktopSubFormController desktopSubFormController,
DesktopCommands commands)
: base(config, keyboardShortcuts, notify, cultureHelper, profileManager,
: base(config, keyboardShortcuts, notify, cultureHelper, colorScheme, profileManager,
imageList, imageTransfer, thumbnailController, thumbnailProvider, desktopController, desktopScanController,
imageListActions, desktopFormProvider, desktopSubFormController, commands)
imageListActions, imageListViewBehavior, desktopFormProvider, desktopSubFormController, commands)
{
_form = this.ToNative();
_form.FormClosing += OnFormClosing;

View File

@ -0,0 +1,47 @@
using System.Windows.Forms;
using Microsoft.Win32;
namespace NAPS2.EtoForms.WinForms;
public class WinFormsDarkModeProvider : IDarkModeProvider, IMessageFilter
{
private const int WM_SETTINGCHANGE = 0x1A;
private const int WM_REFLECT = 0x2000;
private bool? _value;
public WinFormsDarkModeProvider()
{
Application.AddMessageFilter(this);
}
public bool IsDarkModeEnabled => _value ??= ReadDarkMode();
private bool ReadDarkMode()
{
try
{
using var key =
Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize");
return Equals(key?.GetValue("AppsUseLightTheme"), 0);
}
catch (Exception)
{
return false;
}
}
public event EventHandler? DarkModeChanged;
public bool PreFilterMessage(ref Message m)
{
if (m.Msg is WM_SETTINGCHANGE or (WM_SETTINGCHANGE | WM_REFLECT))
{
// TODO: Maybe we can narrow down the changed setting based on lParam?
// https://learn.microsoft.com/en-us/windows/win32/winmsg/wm-settingchange
_value = null;
DarkModeChanged?.Invoke(this, EventArgs.Empty);
}
return false;
}
}

View File

@ -15,6 +15,7 @@ public class WinFormsModule : GuiModule
builder.RegisterType<NotificationManager>().As<INotificationManager>().SingleInstance();
builder.RegisterType<PrintDocumentPrinter>().As<IScannedImagePrinter>();
builder.RegisterType<WinFormsDarkModeProvider>().As<IDarkModeProvider>().SingleInstance();
builder.RegisterType<WinFormsDesktopForm>().As<DesktopForm>();

View File

@ -0,0 +1,22 @@
using Eto.Drawing;
namespace NAPS2.EtoForms;
public class ColorScheme
{
private static readonly Color DarkGray = Color.FromRgb(0x262626);
private readonly IDarkModeProvider _darkModeProvider;
public ColorScheme(IDarkModeProvider darkModeProvider)
{
_darkModeProvider = darkModeProvider;
_darkModeProvider.DarkModeChanged += (_, _) => ColorSchemeChanged?.Invoke(this, EventArgs.Empty);
}
public Color ForegroundColor => _darkModeProvider.IsDarkModeEnabled ? Colors.White : Colors.Black;
public Color BackgroundColor => _darkModeProvider.IsDarkModeEnabled ? DarkGray : Colors.White;
public event EventHandler? ColorSchemeChanged;
}

View File

@ -0,0 +1,8 @@
namespace NAPS2.EtoForms;
public interface IDarkModeProvider
{
bool IsDarkModeEnabled { get; }
event EventHandler? DarkModeChanged;
}

View File

@ -16,6 +16,7 @@ public abstract class DesktopForm : EtoFormBase
private readonly DesktopKeyboardShortcuts _keyboardShortcuts;
private readonly INotificationManager _notify;
private readonly CultureHelper _cultureHelper;
protected readonly ColorScheme _colorScheme;
private readonly IProfileManager _profileManager;
private readonly ImageTransfer _imageTransfer;
protected readonly ThumbnailController _thumbnailController;
@ -38,6 +39,7 @@ public abstract class DesktopForm : EtoFormBase
DesktopKeyboardShortcuts keyboardShortcuts,
INotificationManager notify,
CultureHelper cultureHelper,
ColorScheme colorScheme,
IProfileManager profileManager,
UiImageList imageList,
ImageTransfer imageTransfer,
@ -46,6 +48,7 @@ public abstract class DesktopForm : EtoFormBase
DesktopController desktopController,
IDesktopScanController desktopScanController,
ImageListActions imageListActions,
ImageListViewBehavior imageListViewBehavior,
DesktopFormProvider desktopFormProvider,
IDesktopSubFormController desktopSubFormController,
DesktopCommands commands) : base(config)
@ -53,6 +56,7 @@ public abstract class DesktopForm : EtoFormBase
_keyboardShortcuts = keyboardShortcuts;
_notify = notify;
_cultureHelper = cultureHelper;
_colorScheme = colorScheme;
_profileManager = profileManager;
ImageList = imageList;
_imageTransfer = imageTransfer;
@ -71,7 +75,7 @@ public abstract class DesktopForm : EtoFormBase
UpdateScanButton();
InitLanguageDropdown();
_listView = EtoPlatform.Current.CreateListView(new ImageListViewBehavior(_thumbnailProvider, _imageTransfer));
_listView = EtoPlatform.Current.CreateListView(imageListViewBehavior);
_listView.Selection = ImageList.Selection;
_listView.ItemClicked += ListViewItemClicked;
_listView.Drop += ListViewDrop;
@ -120,6 +124,14 @@ public abstract class DesktopForm : EtoFormBase
L.Row(GetZoomButtons(), C.Filler())
).Padding(10)
);
UpdateColors();
// TODO: Memory leak?
_colorScheme.ColorSchemeChanged += (_, _) => UpdateColors();
}
protected virtual void UpdateColors()
{
}
private void OpeningContextMenu(object? sender, EventArgs e)

View File

@ -10,14 +10,15 @@ public class OcrDownloadForm : EtoDialogBase
{
private readonly TesseractLanguageManager _tesseractLanguageManager;
private readonly IListView<Language> _languageList =
EtoPlatform.Current.CreateListView(new OcrLanguagesListViewBehavior());
private readonly IListView<Language> _languageList;
private readonly Label _downloadSize = new();
private readonly Button _downloadButton;
public OcrDownloadForm(Naps2Config config, TesseractLanguageManager tesseractLanguageManager) : base(config)
public OcrDownloadForm(Naps2Config config, TesseractLanguageManager tesseractLanguageManager,
OcrLanguagesListViewBehavior ocrLanguagesListViewBehavior) : base(config)
{
_tesseractLanguageManager = tesseractLanguageManager;
_languageList = EtoPlatform.Current.CreateListView(ocrLanguagesListViewBehavior);
var initialSelection = new HashSet<string>();
// TODO: We used to select old installed languages here, maybe we could do it again if we get new lang data

View File

@ -10,10 +10,12 @@ public class ImageListViewBehavior : ListViewBehavior<UiImage>
private readonly UiThumbnailProvider _thumbnailProvider;
private readonly ImageTransfer _imageTransfer;
public ImageListViewBehavior(UiThumbnailProvider thumbnailProvider, ImageTransfer imageTransfer)
public ImageListViewBehavior(UiThumbnailProvider thumbnailProvider, ImageTransfer imageTransfer,
ColorScheme colorScheme)
{
_thumbnailProvider = thumbnailProvider;
_imageTransfer = imageTransfer;
ColorScheme = colorScheme;
MultiSelect = true;
ShowLabels = false;
ScrollOnDrag = true;

View File

@ -5,6 +5,8 @@ namespace NAPS2.EtoForms.Widgets;
public abstract class ListViewBehavior<T> where T : notnull
{
public ColorScheme ColorScheme { get; protected set; }
public bool MultiSelect { get; protected set; }
public bool ShowLabels { get; protected set; }

View File

@ -4,8 +4,9 @@ namespace NAPS2.EtoForms.Widgets;
public class OcrLanguagesListViewBehavior : ListViewBehavior<Language>
{
public OcrLanguagesListViewBehavior()
public OcrLanguagesListViewBehavior(ColorScheme colorScheme)
{
ColorScheme = colorScheme;
ShowLabels = true;
Checkboxes = true;
}

View File

@ -9,9 +9,10 @@ public class ProfileListViewBehavior : ListViewBehavior<ScanProfile>
{
private readonly ProfileTransfer _profileTransfer;
public ProfileListViewBehavior(ProfileTransfer profileTransfer)
public ProfileListViewBehavior(ProfileTransfer profileTransfer, ColorScheme colorScheme)
{
_profileTransfer = profileTransfer;
ColorScheme = colorScheme;
MultiSelect = false;
ShowLabels = true;
ScrollOnDrag = false;