mirror of
https://github.com/cyanfish/naps2.git
synced 2024-10-26 09:01:36 +03:00
607 lines
24 KiB
C#
607 lines
24 KiB
C#
using System.Collections.Immutable;
|
|
using System.ComponentModel;
|
|
using System.Threading;
|
|
using Eto.Drawing;
|
|
using Eto.Forms;
|
|
using NAPS2.EtoForms.Desktop;
|
|
using NAPS2.EtoForms.Layout;
|
|
using NAPS2.EtoForms.Notifications;
|
|
using NAPS2.EtoForms.Widgets;
|
|
using NAPS2.ImportExport.Images;
|
|
using NAPS2.Scan;
|
|
|
|
namespace NAPS2.EtoForms.Ui;
|
|
|
|
public abstract class DesktopForm : EtoFormBase
|
|
{
|
|
private readonly DesktopKeyboardShortcuts _keyboardShortcuts;
|
|
private readonly NotificationManager _notificationManager;
|
|
private readonly CultureHelper _cultureHelper;
|
|
protected readonly ColorScheme _colorScheme;
|
|
protected readonly IProfileManager _profileManager;
|
|
protected readonly ThumbnailController _thumbnailController;
|
|
private readonly UiThumbnailProvider _thumbnailProvider;
|
|
protected readonly DesktopController _desktopController;
|
|
protected readonly IDesktopScanController _desktopScanController;
|
|
private readonly ImageListActions _imageListActions;
|
|
private readonly DesktopFormProvider _desktopFormProvider;
|
|
private readonly IDesktopSubFormController _desktopSubFormController;
|
|
private readonly ImageTransfer _imageTransfer = new();
|
|
private readonly Lazy<DesktopCommands> _commands;
|
|
private readonly Sidebar _sidebar;
|
|
protected readonly IIconProvider _iconProvider;
|
|
|
|
protected readonly ListProvider<Command> _scanMenuCommands = new();
|
|
private readonly ListProvider<Command> _languageMenuCommands = new();
|
|
private readonly ContextMenu _contextMenu = new();
|
|
|
|
private readonly NotificationArea _notificationArea;
|
|
protected IListView<UiImage> _listView;
|
|
private ImageListSyncer? _imageListSyncer;
|
|
|
|
public DesktopForm(
|
|
Naps2Config config,
|
|
DesktopKeyboardShortcuts keyboardShortcuts,
|
|
NotificationManager notificationManager,
|
|
CultureHelper cultureHelper,
|
|
ColorScheme colorScheme,
|
|
IProfileManager profileManager,
|
|
UiImageList imageList,
|
|
ThumbnailController thumbnailController,
|
|
UiThumbnailProvider thumbnailProvider,
|
|
DesktopController desktopController,
|
|
IDesktopScanController desktopScanController,
|
|
ImageListActions imageListActions,
|
|
ImageListViewBehavior imageListViewBehavior,
|
|
DesktopFormProvider desktopFormProvider,
|
|
IDesktopSubFormController desktopSubFormController,
|
|
Lazy<DesktopCommands> commands,
|
|
Sidebar sidebar,
|
|
IIconProvider iconProvider) : base(config)
|
|
{
|
|
Icon = Icons.favicon.ToEtoIcon();
|
|
|
|
_keyboardShortcuts = keyboardShortcuts;
|
|
_notificationManager = notificationManager;
|
|
_cultureHelper = cultureHelper;
|
|
_colorScheme = colorScheme;
|
|
_profileManager = profileManager;
|
|
ImageList = imageList;
|
|
_thumbnailController = thumbnailController;
|
|
_thumbnailProvider = thumbnailProvider;
|
|
_desktopController = desktopController;
|
|
_desktopScanController = desktopScanController;
|
|
_imageListActions = imageListActions;
|
|
_desktopFormProvider = desktopFormProvider;
|
|
_desktopSubFormController = desktopSubFormController;
|
|
_sidebar = sidebar;
|
|
_iconProvider = iconProvider;
|
|
_commands = commands;
|
|
|
|
_desktopFormProvider.DesktopForm = this;
|
|
_keyboardShortcuts.Assign(Commands);
|
|
CreateToolbarsAndMenus();
|
|
UpdateScanButton();
|
|
UpdateProfilesToolbar();
|
|
InitLanguageDropdown();
|
|
|
|
_listView = EtoPlatform.Current.CreateListView(imageListViewBehavior);
|
|
_listView.Selection = ImageList.Selection;
|
|
_listView.ItemClicked += ListViewItemClicked;
|
|
_listView.Drop += ListViewDrop;
|
|
_listView.SelectionChanged += ListViewSelectionChanged;
|
|
_listView.ImageSize = new Size(_thumbnailController.VisibleSize, _thumbnailController.VisibleSize);
|
|
_listView.ContextMenu = _contextMenu;
|
|
|
|
// TODO: Fix Eto so that we don't need to set an item here (otherwise the first time we right click nothing happens)
|
|
_contextMenu.Items.Add(Commands.SelectAll);
|
|
_contextMenu.Opening += OpeningContextMenu;
|
|
EtoPlatform.Current.AttachMouseWheelEvent(_listView.Control, ListViewMouseWheel);
|
|
EtoPlatform.Current.AttachMouseMoveEvent(_listView.Control, ListViewMouseMove);
|
|
EtoPlatform.Current.HandleKeyDown(this, _keyboardShortcuts.Perform);
|
|
EtoPlatform.Current.HandleKeyDown(_listView.Control, _keyboardShortcuts.Perform);
|
|
|
|
//
|
|
// Shown += FDesktop_Shown;
|
|
// Closing += FDesktop_Closing;
|
|
// Closed += FDesktop_Closed;
|
|
_thumbnailController.ListView = _listView;
|
|
_thumbnailController.ThumbnailSizeChanged += ThumbnailController_ThumbnailSizeChanged;
|
|
EtoPlatform.Current.AttachDpiDependency(this, scale => _thumbnailController.Oversample = scale);
|
|
ImageList.SelectionChanged += ImageList_SelectionChanged;
|
|
ImageList.ImagesUpdated += ImageList_ImagesUpdated;
|
|
ImageList.ImagesThumbnailInvalidated += ImageList_ImagesThumbnailInvalidated;
|
|
_profileManager.ProfilesUpdated += ProfileManager_ProfilesUpdated;
|
|
_notificationArea = new NotificationArea(_notificationManager, LayoutController);
|
|
}
|
|
|
|
protected override void BuildLayout()
|
|
{
|
|
FormStateController.AutoLayoutSize = false;
|
|
FormStateController.DefaultClientSize = new Size(1210, 600);
|
|
EtoPlatform.Current.AttachDpiDependency(this, _ =>
|
|
MinimumSize = Size.Round(new SizeF(600, 300) * EtoPlatform.Current.GetLayoutScaleFactor(this)));
|
|
|
|
LayoutController.RootPadding = 0;
|
|
LayoutController.Content = L.LeftPanel(
|
|
Config.Get(c => c.HiddenButtons).HasFlag(ToolbarButtons.Sidebar)
|
|
? C.None()
|
|
: _sidebar.CreateView(this),
|
|
L.Overlay(
|
|
// For WinForms, we add 1px of top padding to give us room to draw a border above the listview
|
|
_listView.Control.Padding(top: EtoPlatform.Current.IsWinForms ? 1 : 0),
|
|
L.Column(
|
|
C.Filler(),
|
|
L.Row(
|
|
GetControlButtons(),
|
|
C.Filler(),
|
|
_notificationArea.Content)
|
|
).Padding(8)
|
|
).Scale()
|
|
).SizeConfig(
|
|
() => Config.Get(c => c.SidebarWidth),
|
|
width => Config.User.Set(c => c.SidebarWidth, width));
|
|
}
|
|
|
|
private void OpeningContextMenu(object? sender, EventArgs e)
|
|
{
|
|
_contextMenu.Items.Clear();
|
|
if (!EtoPlatform.Current.IsMac)
|
|
{
|
|
// TODO: Can't do this on Mac yet as it disables the menu item indefinitely
|
|
Commands.Paste.Enabled = _imageTransfer.IsInClipboard() || Clipboard.Instance.ContainsImage;
|
|
}
|
|
if (ImageList.Selection.Any())
|
|
{
|
|
// TODO: Is this memory leaking (because of event handlers) when commands are converted to menuitems?
|
|
_contextMenu.Items.AddRange(
|
|
[
|
|
C.ButtonMenuItem(this, Commands.ViewImage),
|
|
new SeparatorMenuItem(),
|
|
C.ButtonMenuItem(this, Commands.SelectAll),
|
|
C.ButtonMenuItem(this, Commands.Copy),
|
|
C.ButtonMenuItem(this, Commands.Paste),
|
|
new SeparatorMenuItem(),
|
|
C.ButtonMenuItem(this, Commands.Undo),
|
|
C.ButtonMenuItem(this, Commands.Redo),
|
|
new SeparatorMenuItem(),
|
|
C.ButtonMenuItem(this, Commands.Delete)
|
|
]);
|
|
}
|
|
else
|
|
{
|
|
_contextMenu.Items.AddRange(
|
|
[
|
|
C.ButtonMenuItem(this, Commands.SelectAll),
|
|
C.ButtonMenuItem(this, Commands.Paste),
|
|
new SeparatorMenuItem(),
|
|
C.ButtonMenuItem(this, Commands.Undo),
|
|
C.ButtonMenuItem(this, Commands.Redo)
|
|
]);
|
|
}
|
|
}
|
|
|
|
private void ImageList_SelectionChanged(object? sender, EventArgs e)
|
|
{
|
|
Invoker.Current.InvokeDispatch(() =>
|
|
{
|
|
UpdateToolbar();
|
|
_listView.Selection = ImageList.Selection;
|
|
});
|
|
}
|
|
|
|
private void ImageList_ImagesUpdated(object? sender, ImageListEventArgs e)
|
|
{
|
|
Invoker.Current.InvokeDispatch(UpdateToolbar);
|
|
}
|
|
|
|
private void ImageList_ImagesThumbnailInvalidated(object? sender, ImageListEventArgs e)
|
|
{
|
|
Invoker.Current.InvokeDispatch(UpdateToolbar);
|
|
}
|
|
|
|
private void ProfileManager_ProfilesUpdated(object? sender, EventArgs e)
|
|
{
|
|
UpdateScanButton();
|
|
UpdateProfilesToolbar();
|
|
}
|
|
|
|
private void ThumbnailController_ThumbnailSizeChanged(object? sender, EventArgs e)
|
|
{
|
|
SetThumbnailSpacing(_thumbnailController.VisibleSize, EtoPlatform.Current.GetScaleFactor(this));
|
|
UpdateToolbar();
|
|
}
|
|
|
|
protected UiImageList ImageList { get; }
|
|
protected DesktopCommands Commands => _commands.Value;
|
|
|
|
protected override void OnLoad(EventArgs e)
|
|
{
|
|
base.OnLoad(e);
|
|
_imageListSyncer = new ImageListSyncer(ImageList, _listView.ApplyDiffs, SynchronizationContext.Current!);
|
|
EtoPlatform.Current.AttachDpiDependency(_listView.Control,
|
|
scale => SetThumbnailSpacing(_thumbnailController.VisibleSize, scale));
|
|
_desktopController.PreInitialize();
|
|
}
|
|
|
|
protected override async void OnShown(EventArgs e)
|
|
{
|
|
base.OnShown(e);
|
|
UpdateToolbar();
|
|
await _desktopController.Initialize();
|
|
}
|
|
|
|
protected override void OnClosing(CancelEventArgs e)
|
|
{
|
|
if (!_desktopController.PrepareForClosing(true))
|
|
{
|
|
e.Cancel = true;
|
|
}
|
|
}
|
|
|
|
protected override void OnClosed(EventArgs e)
|
|
{
|
|
base.OnClosed(e);
|
|
_desktopController.Cleanup();
|
|
|
|
// TODO: Make sure we don't have any remaining memory leaks (toolbars? commands?)
|
|
_thumbnailController.ThumbnailSizeChanged -= ThumbnailController_ThumbnailSizeChanged;
|
|
ImageList.SelectionChanged -= ImageList_SelectionChanged;
|
|
ImageList.ImagesUpdated -= ImageList_ImagesUpdated;
|
|
ImageList.ImagesThumbnailInvalidated -= ImageList_ImagesThumbnailInvalidated;
|
|
_profileManager.ProfilesUpdated -= ProfileManager_ProfilesUpdated;
|
|
_notificationArea.Dispose();
|
|
_imageListSyncer?.Dispose();
|
|
}
|
|
|
|
protected virtual void CreateToolbarsAndMenus()
|
|
{
|
|
ToolBar = new ToolBar();
|
|
ConfigureToolbars();
|
|
|
|
var hiddenButtons = Config.Get(c => c.HiddenButtons);
|
|
|
|
if (!hiddenButtons.HasFlag(ToolbarButtons.Scan))
|
|
CreateToolbarButtonWithMenu(Commands.Scan, DesktopToolbarMenuType.Scan, new MenuProvider()
|
|
.Dynamic(_scanMenuCommands)
|
|
.Separator()
|
|
.Append(Commands.NewProfile)
|
|
.Append(Commands.BatchScan)
|
|
.Append(Config.Get(c => c.DisableScannerSharing) ? null : Commands.ScannerSharing));
|
|
if (!hiddenButtons.HasFlag(ToolbarButtons.Profiles))
|
|
CreateToolbarButton(Commands.Profiles);
|
|
if (!hiddenButtons.HasFlag(ToolbarButtons.Ocr))
|
|
CreateToolbarButton(Commands.Ocr);
|
|
if (!hiddenButtons.HasFlag(ToolbarButtons.Import))
|
|
CreateToolbarButton(Commands.Import);
|
|
CreateToolbarSeparator();
|
|
if (!hiddenButtons.HasFlag(ToolbarButtons.SavePdf))
|
|
CreateToolbarButtonWithMenu(Commands.SavePdf, DesktopToolbarMenuType.SavePdf, new MenuProvider()
|
|
.Append(Commands.SaveAllPdf)
|
|
.Append(Commands.SaveSelectedPdf)
|
|
.Separator()
|
|
.Append(Commands.PdfSettings));
|
|
if (!hiddenButtons.HasFlag(ToolbarButtons.SaveImages))
|
|
CreateToolbarButtonWithMenu(Commands.SaveImages, DesktopToolbarMenuType.SaveImages, new MenuProvider()
|
|
.Append(Commands.SaveAllImages)
|
|
.Append(Commands.SaveSelectedImages)
|
|
.Separator()
|
|
.Append(Commands.ImageSettings));
|
|
if (!hiddenButtons.HasFlag(ToolbarButtons.EmailPdf) && PlatformCompat.System.CanEmail)
|
|
CreateToolbarButtonWithMenu(Commands.EmailPdf, DesktopToolbarMenuType.EmailPdf, new MenuProvider()
|
|
.Append(Commands.EmailAll)
|
|
.Append(Commands.EmailSelected)
|
|
.Separator()
|
|
.Append(Commands.EmailSettings)
|
|
.Append(Commands.PdfSettings));
|
|
if (!hiddenButtons.HasFlag(ToolbarButtons.Print) && PlatformCompat.System.CanPrint)
|
|
CreateToolbarButton(Commands.Print);
|
|
CreateToolbarSeparator();
|
|
if (!hiddenButtons.HasFlag(ToolbarButtons.Image))
|
|
CreateToolbarMenu(Commands.ImageMenu, new MenuProvider()
|
|
.Append(Commands.ViewImage)
|
|
.Separator()
|
|
.Append(Commands.Crop)
|
|
.Append(Commands.BrightCont)
|
|
.Append(Commands.HueSat)
|
|
.Append(Commands.BlackWhite)
|
|
.Append(Commands.Sharpen)
|
|
.Append(Commands.DocumentCorrection)
|
|
.Separator()
|
|
.Append(Commands.Split)
|
|
.Append(Commands.Combine)
|
|
.Separator()
|
|
.Append(Commands.ResetImage));
|
|
if (!hiddenButtons.HasFlag(ToolbarButtons.Rotate))
|
|
CreateToolbarMenu(Commands.RotateMenu, GetRotateMenuProvider());
|
|
if (!hiddenButtons.HasFlag(ToolbarButtons.Move))
|
|
CreateToolbarStackedButtons(Commands.MoveUp, Commands.MoveDown);
|
|
if (!hiddenButtons.HasFlag(ToolbarButtons.Reorder))
|
|
CreateToolbarMenu(Commands.ReorderMenu, new MenuProvider()
|
|
.Append(Commands.Interleave)
|
|
.Append(Commands.Deinterleave)
|
|
.Separator()
|
|
.Append(Commands.AltInterleave)
|
|
.Append(Commands.AltDeinterleave)
|
|
.Separator()
|
|
.SubMenu(Commands.ReverseMenu, new MenuProvider()
|
|
.Append(Commands.ReverseAll)
|
|
.Append(Commands.ReverseSelected)));
|
|
CreateToolbarSeparator();
|
|
if (!hiddenButtons.HasFlag(ToolbarButtons.Delete))
|
|
CreateToolbarButton(Commands.Delete);
|
|
if (!hiddenButtons.HasFlag(ToolbarButtons.Clear))
|
|
CreateToolbarButton(Commands.ClearAll);
|
|
CreateToolbarSeparator();
|
|
if (!hiddenButtons.HasFlag(ToolbarButtons.Language))
|
|
CreateToolbarMenu(Commands.LanguageMenu, GetLanguageMenuProvider());
|
|
MaybeCreateToolbarStackedButtons(
|
|
Commands.Settings, !hiddenButtons.HasFlag(ToolbarButtons.Settings),
|
|
Commands.About, !hiddenButtons.HasFlag(ToolbarButtons.About));
|
|
}
|
|
|
|
private void MaybeCreateToolbarStackedButtons(Command command1, bool show1, Command command2, bool show2)
|
|
{
|
|
if (show1 && show2)
|
|
{
|
|
CreateToolbarStackedButtons(command1, command2);
|
|
}
|
|
else if (show1)
|
|
{
|
|
CreateToolbarButton(command1);
|
|
}
|
|
else if (show2)
|
|
{
|
|
CreateToolbarButton(command2);
|
|
}
|
|
}
|
|
|
|
public virtual void ShowToolbarMenu(DesktopToolbarMenuType menuType)
|
|
{
|
|
}
|
|
|
|
protected MenuProvider GetRotateMenuProvider() =>
|
|
new MenuProvider()
|
|
.Append(Commands.RotateLeft)
|
|
.Append(Commands.RotateRight)
|
|
.Append(Commands.Flip)
|
|
.Append(Commands.Deskew)
|
|
.Append(Commands.CustomRotate);
|
|
|
|
protected MenuProvider GetLanguageMenuProvider()
|
|
{
|
|
return new MenuProvider().Dynamic(_languageMenuCommands);
|
|
}
|
|
|
|
protected virtual void ConfigureToolbars()
|
|
{
|
|
}
|
|
|
|
protected virtual void UpdateProfilesToolbar()
|
|
{
|
|
}
|
|
|
|
public virtual void PlaceProfilesToolbar()
|
|
{
|
|
}
|
|
|
|
protected virtual void CreateToolbarButton(Command command) => throw new InvalidOperationException();
|
|
|
|
protected virtual void CreateToolbarButtonWithMenu(Command command, DesktopToolbarMenuType menuType,
|
|
MenuProvider menu) =>
|
|
throw new InvalidOperationException();
|
|
|
|
protected virtual void CreateToolbarMenu(Command command, MenuProvider menu) =>
|
|
throw new InvalidOperationException();
|
|
|
|
protected virtual void CreateToolbarStackedButtons(Command command1, Command command2) =>
|
|
throw new InvalidOperationException();
|
|
|
|
protected virtual void CreateToolbarSeparator() => throw new InvalidOperationException();
|
|
|
|
// TODO: Can we generalize this kind of logic?
|
|
protected SubMenuItem CreateSubMenu(Command menuCommand, MenuProvider menuProvider)
|
|
{
|
|
var menuItem = new SubMenuItem
|
|
{
|
|
Text = menuCommand.MenuText
|
|
};
|
|
EtoPlatform.Current.AttachDpiDependency(this,
|
|
scale => menuItem.Image = ((ActionCommand) menuCommand).GetIconImage(scale));
|
|
menuProvider.Handle(subItems =>
|
|
{
|
|
menuItem.Items.Clear();
|
|
foreach (var subItem in subItems)
|
|
{
|
|
switch (subItem)
|
|
{
|
|
case MenuProvider.CommandItem { Command: var command }:
|
|
menuItem.Items.Add(C.ButtonMenuItem(this, (ActionCommand) command));
|
|
break;
|
|
case MenuProvider.SeparatorItem:
|
|
menuItem.Items.Add(new SeparatorMenuItem());
|
|
break;
|
|
case MenuProvider.SubMenuItem { Command: var command, MenuProvider: var subMenuProvider }:
|
|
menuItem.Items.Add(CreateSubMenu(command, subMenuProvider));
|
|
break;
|
|
}
|
|
}
|
|
});
|
|
return menuItem;
|
|
}
|
|
|
|
protected virtual LayoutElement GetControlButtons()
|
|
{
|
|
return L.Row(GetSidebarButton(), GetZoomButtons());
|
|
}
|
|
|
|
protected LayoutElement GetSidebarButton()
|
|
{
|
|
if (Config.Get(c => c.HiddenButtons).HasFlag(ToolbarButtons.Sidebar))
|
|
{
|
|
return C.None();
|
|
}
|
|
var toggleSidebar = C.ImageButton(Commands.ToggleSidebar);
|
|
EtoPlatform.Current.ConfigureZoomButton(toggleSidebar, "application_side_list_small");
|
|
return toggleSidebar.AlignTrailing();
|
|
}
|
|
|
|
protected LayoutElement GetZoomButtons()
|
|
{
|
|
var zoomIn = C.ImageButton(Commands.ZoomIn);
|
|
EtoPlatform.Current.ConfigureZoomButton(zoomIn, "zoom_in_small");
|
|
var zoomOut = C.ImageButton(Commands.ZoomOut);
|
|
EtoPlatform.Current.ConfigureZoomButton(zoomOut, "zoom_out_small");
|
|
return L.Row(zoomOut.AlignTrailing(), zoomIn.AlignTrailing()).Spacing(-1);
|
|
}
|
|
|
|
private void InitLanguageDropdown()
|
|
{
|
|
_languageMenuCommands.Value = _cultureHelper.GetAvailableCultures().Select(x =>
|
|
new ActionCommand(() => SetCulture(x.langCode))
|
|
{
|
|
MenuText = x.langName
|
|
}).ToImmutableList<Command>();
|
|
}
|
|
|
|
protected virtual void SetCulture(string cultureId)
|
|
{
|
|
_desktopController.Suspend();
|
|
try
|
|
{
|
|
Config.User.Set(c => c.Culture, cultureId);
|
|
_cultureHelper.SetCulturesFromConfig();
|
|
FormStateController.DoSaveFormState();
|
|
var newDesktop = FormFactory.Create<DesktopForm>();
|
|
newDesktop.Show();
|
|
Application.Instance.MainForm = newDesktop;
|
|
Close();
|
|
}
|
|
finally
|
|
{
|
|
_desktopController.Resume();
|
|
}
|
|
// TODO: If we make any other forms non-modal, we will need to refresh them too
|
|
}
|
|
|
|
protected virtual void UpdateToolbar()
|
|
{
|
|
// Top-level toolbar items
|
|
Commands.ImageMenu.Enabled =
|
|
Commands.RotateMenu.Enabled = Commands.MoveUp.Enabled = Commands.MoveDown.Enabled =
|
|
Commands.Delete.Enabled = ImageList.Selection.Any();
|
|
Commands.SavePdf.Enabled = Commands.SaveImages.Enabled = Commands.ClearAll.Enabled =
|
|
Commands.ReorderMenu.Enabled =
|
|
Commands.EmailPdf.Enabled = Commands.Print.Enabled = ImageList.Images.Any();
|
|
|
|
// "All" dropdown items
|
|
Commands.SaveAllPdf.Text = Commands.SaveAllImages.Text = Commands.EmailAll.Text =
|
|
Commands.ReverseAll.Text = string.Format(MiscResources.AllCount, ImageList.Images.Count);
|
|
Commands.SaveAllPdf.Enabled = Commands.SaveAllImages.Enabled = Commands.EmailAll.Enabled =
|
|
Commands.ReverseAll.Enabled = ImageList.Images.Any();
|
|
|
|
// "Selected" dropdown items
|
|
Commands.SaveSelectedPdf.Text = Commands.SaveSelectedImages.Text = Commands.EmailSelected.Text =
|
|
Commands.ReverseSelected.Text = string.Format(MiscResources.SelectedCount, ImageList.Selection.Count);
|
|
Commands.SaveSelectedPdf.Enabled = Commands.SaveSelectedImages.Enabled = Commands.EmailSelected.Enabled =
|
|
Commands.ReverseSelected.Enabled = ImageList.Selection.Any();
|
|
|
|
// Other
|
|
Commands.SelectAll.Enabled = ImageList.Images.Any();
|
|
Commands.Undo.Enabled = ImageList.CanUndo;
|
|
Commands.Redo.Enabled = ImageList.CanRedo;
|
|
// TODO: Set undo/redo text here (e.g. "Undo Brightness/Contrast" instead of just "Undo")
|
|
Commands.ZoomIn.Enabled = ImageList.Images.Any() && _thumbnailController.VisibleSize < ThumbnailSizes.MAX_SIZE;
|
|
Commands.ZoomOut.Enabled = ImageList.Images.Any() && _thumbnailController.VisibleSize > ThumbnailSizes.MIN_SIZE;
|
|
Commands.NewProfile.Enabled =
|
|
!(Config.Get(c => c.NoUserProfiles) && _profileManager.Profiles.Any(x => x.IsLocked));
|
|
Commands.Combine.Enabled = ImageList.Images.Count > 1;
|
|
}
|
|
|
|
private void UpdateScanButton()
|
|
{
|
|
var defaultProfile = _profileManager.DefaultProfile;
|
|
UpdateTitle(defaultProfile);
|
|
var commandList = _profileManager.Profiles.Select(profile =>
|
|
new ActionCommand(() => _desktopScanController.ScanWithProfile(profile))
|
|
{
|
|
// TODO: Does this need to change on non-WinForms?
|
|
MenuText = profile.DisplayName.Replace("&", "&&"),
|
|
IconName = profile == defaultProfile ? "accept_small" : null
|
|
})
|
|
.ToImmutableList<Command>();
|
|
for (int i = 0; i < commandList.Count; i++)
|
|
{
|
|
_keyboardShortcuts.AssignProfileShortcut(i + 1, commandList[i]);
|
|
}
|
|
_scanMenuCommands.Value = commandList;
|
|
}
|
|
|
|
protected virtual void UpdateTitle(ScanProfile? defaultProfile)
|
|
{
|
|
Title = string.Format(UiStrings.Naps2TitleFormat, defaultProfile?.DisplayName ?? UiStrings.Naps2FullName);
|
|
}
|
|
|
|
private void ListViewMouseWheel(object? sender, MouseEventArgs e)
|
|
{
|
|
if (e.Modifiers.HasFlag(Keys.Control))
|
|
{
|
|
_thumbnailController.StepSize(e.Delta.Height);
|
|
e.Handled = true;
|
|
}
|
|
}
|
|
|
|
private void ListViewMouseMove(object? sender, MouseEventArgs e)
|
|
{
|
|
_notificationManager.StartTimers();
|
|
}
|
|
|
|
protected virtual void SetThumbnailSpacing(int thumbnailSize, float scale)
|
|
{
|
|
}
|
|
|
|
private void ListViewItemClicked(object? sender, EventArgs e) => _desktopSubFormController.ShowViewerForm();
|
|
|
|
private void ListViewSelectionChanged(object? sender, EventArgs e)
|
|
{
|
|
ImageList.UpdateSelection(_listView.Selection);
|
|
UpdateToolbar();
|
|
}
|
|
|
|
private void ListViewDrop(object? sender, DropEventArgs args)
|
|
{
|
|
if (args.CustomData != null)
|
|
{
|
|
var data = _imageTransfer.FromBinaryData(args.CustomData);
|
|
if (data.ProcessId == Process.GetCurrentProcess().Id)
|
|
{
|
|
DragMoveImages(args.Position);
|
|
}
|
|
else
|
|
{
|
|
_desktopController.ImportDirect(data, false);
|
|
}
|
|
}
|
|
else if (args.FilePaths != null)
|
|
{
|
|
_desktopController.ImportFiles(args.FilePaths);
|
|
}
|
|
}
|
|
|
|
private void DragMoveImages(int position)
|
|
{
|
|
if (!ImageList.Selection.Any())
|
|
{
|
|
return;
|
|
}
|
|
if (position != -1)
|
|
{
|
|
_imageListActions.MoveTo(position);
|
|
}
|
|
}
|
|
|
|
public void ToggleSidebar()
|
|
{
|
|
_sidebar.ToggleVisibility();
|
|
}
|
|
} |