mirror of
https://github.com/cyanfish/naps2.git
synced 2024-09-19 03:37:38 +03:00
WIP: PreviewForm eto migration and mac customization
This commit is contained in:
parent
6dfb90e266
commit
ebef67fedd
@ -18,6 +18,8 @@ public class MacIconProvider : IIconProvider
|
|||||||
{ "arrow_switch_small", "arrow.2.squarepath" },
|
{ "arrow_switch_small", "arrow.2.squarepath" },
|
||||||
{ "arrow_up_small", "arrow.up" },
|
{ "arrow_up_small", "arrow.up" },
|
||||||
{ "arrow_down_small", "arrow.down" },
|
{ "arrow_down_small", "arrow.down" },
|
||||||
|
{ "arrow_left", "arrow.left" },
|
||||||
|
{ "arrow_right", "arrow.right" },
|
||||||
{ "transform_crop", "crop" },
|
{ "transform_crop", "crop" },
|
||||||
{ "contrast_with_sun", "sun.max" },
|
{ "contrast_with_sun", "sun.max" },
|
||||||
{ "color_management", "paintpalette" },
|
{ "color_management", "paintpalette" },
|
||||||
|
@ -1,13 +1,18 @@
|
|||||||
|
using Eto.Mac.Forms.ToolBar;
|
||||||
|
|
||||||
namespace NAPS2.EtoForms.Mac;
|
namespace NAPS2.EtoForms.Mac;
|
||||||
|
|
||||||
public class MacToolbarDelegate : NSToolbarDelegate
|
public class MacToolbarDelegate : NSToolbarDelegate
|
||||||
{
|
{
|
||||||
private readonly string[] _identifiers;
|
private readonly string[] _identifiers;
|
||||||
|
private string[] _selectableIdentifiers;
|
||||||
private readonly Dictionary<string, MacToolbarEntry> _entryMap;
|
private readonly Dictionary<string, MacToolbarEntry> _entryMap;
|
||||||
|
|
||||||
public MacToolbarDelegate(List<MacToolbarEntry> entries)
|
public MacToolbarDelegate(List<MacToolbarEntry> entries)
|
||||||
{
|
{
|
||||||
_identifiers = entries.Select(x => x.Identifier).ToArray();
|
_identifiers = entries.Select(x => x.Identifier).ToArray();
|
||||||
|
_selectableIdentifiers = entries.Where(x => x.Item is not ToolBarHandler.DividerToolbarItem)
|
||||||
|
.Select(x => x.Identifier).ToArray();
|
||||||
_entryMap = entries.ToDictionary(x => x.Identifier);
|
_entryMap = entries.ToDictionary(x => x.Identifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -19,7 +24,7 @@ public class MacToolbarDelegate : NSToolbarDelegate
|
|||||||
|
|
||||||
public override string[] AllowedItemIdentifiers(NSToolbar toolbar) => _identifiers;
|
public override string[] AllowedItemIdentifiers(NSToolbar toolbar) => _identifiers;
|
||||||
public override string[] DefaultItemIdentifiers(NSToolbar toolbar) => _identifiers;
|
public override string[] DefaultItemIdentifiers(NSToolbar toolbar) => _identifiers;
|
||||||
public override string[] SelectableItemIdentifiers(NSToolbar toolbar) => _identifiers;
|
public override string[] SelectableItemIdentifiers(NSToolbar toolbar) => _selectableIdentifiers;
|
||||||
|
|
||||||
public override NSToolbarItem? WillInsertItem(NSToolbar toolbar, string itemIdentifier, bool willBeInserted)
|
public override NSToolbarItem? WillInsertItem(NSToolbar toolbar, string itemIdentifier, bool willBeInserted)
|
||||||
{
|
{
|
||||||
|
@ -1,11 +1,17 @@
|
|||||||
using Eto.Forms;
|
using Eto.Forms;
|
||||||
using Eto.Mac;
|
using Eto.Mac;
|
||||||
|
using Eto.Mac.Forms.ToolBar;
|
||||||
|
|
||||||
namespace NAPS2.EtoForms.Mac;
|
namespace NAPS2.EtoForms.Mac;
|
||||||
|
|
||||||
public record MacToolbarEntry(string Identifier, NSToolbarItem Item)
|
public record MacToolbarEntry(string Identifier, NSToolbarItem? Item)
|
||||||
{
|
{
|
||||||
public static NSToolbarItem CreateItem(Command command, string? title = null, string? tooltip = null)
|
public static NSToolbarItem CreateSeparator()
|
||||||
|
{
|
||||||
|
return new ToolBarHandler.DividerToolbarItem(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static NSToolbarItem CreateItem(Command command, string? title = null, string? tooltip = null, bool nav = false)
|
||||||
{
|
{
|
||||||
return new NSToolbarItem
|
return new NSToolbarItem
|
||||||
{
|
{
|
||||||
@ -13,7 +19,8 @@ public record MacToolbarEntry(string Identifier, NSToolbarItem Item)
|
|||||||
Title = title ?? "",
|
Title = title ?? "",
|
||||||
Label = command.ToolBarText ?? "",
|
Label = command.ToolBarText ?? "",
|
||||||
ToolTip = tooltip ?? command.ToolBarText ?? "",
|
ToolTip = tooltip ?? command.ToolBarText ?? "",
|
||||||
Bordered = true
|
Bordered = true,
|
||||||
|
Navigational = nav
|
||||||
}.WithAction(command.Execute);
|
}.WithAction(command.Execute);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
62
NAPS2.Lib.Mac/EtoForms/Ui/MacPreviewForm.cs
Normal file
62
NAPS2.Lib.Mac/EtoForms/Ui/MacPreviewForm.cs
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
using Eto.Forms;
|
||||||
|
using NAPS2.EtoForms.Mac;
|
||||||
|
|
||||||
|
namespace NAPS2.EtoForms.Ui;
|
||||||
|
|
||||||
|
public class MacPreviewForm : PreviewForm
|
||||||
|
{
|
||||||
|
public MacPreviewForm(Naps2Config config, DesktopCommands desktopCommands, UiImageList imageList,
|
||||||
|
IIconProvider iconProvider) : base(config, desktopCommands, imageList, iconProvider)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void CreateToolbar()
|
||||||
|
{
|
||||||
|
var toolbar = new NSToolbar("naps2.preview.toolbar");
|
||||||
|
toolbar.Delegate = new MacToolbarDelegate(CreateMacToolbarEntries());
|
||||||
|
toolbar.AllowsUserCustomization = true;
|
||||||
|
// toolbar.AutosavesConfiguration = true;
|
||||||
|
toolbar.DisplayMode = NSToolbarDisplayMode.Icon;
|
||||||
|
|
||||||
|
var window = this.ToNative();
|
||||||
|
window.Toolbar = toolbar;
|
||||||
|
if (OperatingSystem.IsMacOSVersionAtLeast(11))
|
||||||
|
{
|
||||||
|
window.ToolbarStyle = NSWindowToolbarStyle.Unified;
|
||||||
|
}
|
||||||
|
window.StyleMask |= NSWindowStyle.UnifiedTitleAndToolbar;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void UpdatePage()
|
||||||
|
{
|
||||||
|
var window = this.ToNative();
|
||||||
|
if (OperatingSystem.IsMacOSVersionAtLeast(11))
|
||||||
|
{
|
||||||
|
window.Subtitle = string.Format(UiStrings.XOfY, ImageIndex + 1, ImageList.Images.Count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<MacToolbarEntry> CreateMacToolbarEntries()
|
||||||
|
{
|
||||||
|
return new List<MacToolbarEntry>
|
||||||
|
{
|
||||||
|
new("prev", MacToolbarEntry.CreateItem(GoToPrevCommand, nav: true)),
|
||||||
|
new("next", MacToolbarEntry.CreateItem(GoToNextCommand, nav: true)),
|
||||||
|
new("rotate", MacToolbarEntry.CreateMenuItem(Commands.RotateMenu, new MenuProvider()
|
||||||
|
.Append(Commands.RotateLeft)
|
||||||
|
.Append(Commands.RotateRight)
|
||||||
|
.Append(Commands.Flip)
|
||||||
|
.Append(Commands.Deskew)
|
||||||
|
.Append(Commands.CustomRotate))),
|
||||||
|
new("crop", MacToolbarEntry.CreateItem(Commands.Crop)),
|
||||||
|
new("brightcont", MacToolbarEntry.CreateItem(Commands.BrightCont)),
|
||||||
|
new("huesat", MacToolbarEntry.CreateItem(Commands.HueSat)),
|
||||||
|
new("blackwhite", MacToolbarEntry.CreateItem(Commands.BlackWhite)),
|
||||||
|
new("sharpen", MacToolbarEntry.CreateItem(Commands.Sharpen)),
|
||||||
|
new("sep0", MacToolbarEntry.CreateSeparator()),
|
||||||
|
new("save", MacToolbarEntry.CreateItem(Commands.SaveSelected)),
|
||||||
|
new("sep1", MacToolbarEntry.CreateSeparator()),
|
||||||
|
new("delete", MacToolbarEntry.CreateItem(Commands.Delete)),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -36,6 +36,7 @@ public class MacModule : Module
|
|||||||
builder.RegisterType<MacIconProvider>().As<IIconProvider>();
|
builder.RegisterType<MacIconProvider>().As<IIconProvider>();
|
||||||
|
|
||||||
builder.RegisterType<MacDesktopForm>().As<DesktopForm>();
|
builder.RegisterType<MacDesktopForm>().As<DesktopForm>();
|
||||||
|
builder.RegisterType<MacPreviewForm>().As<PreviewForm>();
|
||||||
|
|
||||||
EtoPlatform.Current = new MacEtoPlatform();
|
EtoPlatform.Current = new MacEtoPlatform();
|
||||||
// Log.EventLogger = new WindowsEventLogger(Kernel!.Get<Naps2Config>());
|
// Log.EventLogger = new WindowsEventLogger(Kernel!.Get<Naps2Config>());
|
||||||
|
@ -6,11 +6,13 @@ public class StubDesktopSubFormController : IDesktopSubFormController
|
|||||||
{
|
{
|
||||||
private readonly IFormFactory _formFactory;
|
private readonly IFormFactory _formFactory;
|
||||||
private readonly DesktopImagesController _desktopImagesController;
|
private readonly DesktopImagesController _desktopImagesController;
|
||||||
|
private readonly UiImageList _imageList;
|
||||||
|
|
||||||
public StubDesktopSubFormController(IFormFactory formFactory, DesktopImagesController desktopImagesController)
|
public StubDesktopSubFormController(IFormFactory formFactory, DesktopImagesController desktopImagesController, UiImageList imageList)
|
||||||
{
|
{
|
||||||
_formFactory = formFactory;
|
_formFactory = formFactory;
|
||||||
_desktopImagesController = desktopImagesController;
|
_desktopImagesController = desktopImagesController;
|
||||||
|
_imageList = imageList;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ShowCropForm()
|
public void ShowCropForm()
|
||||||
@ -55,6 +57,13 @@ public class StubDesktopSubFormController : IDesktopSubFormController
|
|||||||
|
|
||||||
public void ShowViewerForm()
|
public void ShowViewerForm()
|
||||||
{
|
{
|
||||||
|
var selected = _imageList.Selection.FirstOrDefault();
|
||||||
|
if (selected != null)
|
||||||
|
{
|
||||||
|
using var viewer = _formFactory.Create<PreviewForm>();
|
||||||
|
viewer.CurrentImage = selected;
|
||||||
|
viewer.ShowModal();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ShowPdfSettingsForm()
|
public void ShowPdfSettingsForm()
|
||||||
|
184
NAPS2.Lib/EtoForms/Ui/PreviewForm.cs
Normal file
184
NAPS2.Lib/EtoForms/Ui/PreviewForm.cs
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
using Eto.Drawing;
|
||||||
|
using Eto.Forms;
|
||||||
|
|
||||||
|
namespace NAPS2.EtoForms.Ui;
|
||||||
|
|
||||||
|
public class PreviewForm : EtoDialogBase
|
||||||
|
{
|
||||||
|
private readonly DesktopCommands _desktopCommands;
|
||||||
|
|
||||||
|
private readonly ImageView _imageView = new();
|
||||||
|
private UiImage? _currentImage;
|
||||||
|
|
||||||
|
public PreviewForm(Naps2Config config, DesktopCommands desktopCommands, UiImageList imageList,
|
||||||
|
IIconProvider iconProvider) : base(config)
|
||||||
|
{
|
||||||
|
_desktopCommands = desktopCommands;
|
||||||
|
ImageList = imageList;
|
||||||
|
|
||||||
|
Title = UiStrings.PreviewFormTitle;
|
||||||
|
Icon = Icons.picture.ToEtoIcon();
|
||||||
|
|
||||||
|
FormStateController.AutoLayoutSize = false;
|
||||||
|
FormStateController.DefaultClientSize = new Size(800, 600);
|
||||||
|
LayoutController.RootPadding = 0;
|
||||||
|
LayoutController.Content = _imageView;
|
||||||
|
|
||||||
|
GoToPrevCommand = new ActionCommand(() => GoTo(ImageIndex - 1))
|
||||||
|
{
|
||||||
|
Text = UiStrings.Previous,
|
||||||
|
Image = iconProvider.GetIcon("arrow_left")
|
||||||
|
};
|
||||||
|
GoToNextCommand = new ActionCommand(() => GoTo(ImageIndex + 1))
|
||||||
|
{
|
||||||
|
Text = UiStrings.Next,
|
||||||
|
Image = iconProvider.GetIcon("arrow_right")
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected DesktopCommands Commands { get; set; } = null!;
|
||||||
|
protected ActionCommand GoToPrevCommand { get; }
|
||||||
|
protected ActionCommand GoToNextCommand { get; }
|
||||||
|
|
||||||
|
protected UiImageList ImageList { get; }
|
||||||
|
|
||||||
|
public UiImage CurrentImage
|
||||||
|
{
|
||||||
|
get => _currentImage ?? throw new InvalidOperationException();
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_currentImage != null)
|
||||||
|
{
|
||||||
|
_currentImage.ThumbnailInvalidated -= ImageThumbnailInvalidated;
|
||||||
|
}
|
||||||
|
_currentImage = value;
|
||||||
|
Commands = _desktopCommands.WithSelection(ListSelection.Of(_currentImage));
|
||||||
|
_currentImage.ThumbnailInvalidated += ImageThumbnailInvalidated;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ImageThumbnailInvalidated(object? sender, EventArgs e)
|
||||||
|
{
|
||||||
|
Invoker.Current.SafeInvoke(() => UpdateImage().AssertNoAwait());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int ImageIndex
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var index = ImageList!.Images.IndexOf(CurrentImage);
|
||||||
|
if (index == -1)
|
||||||
|
{
|
||||||
|
index = 0;
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnLoad(EventArgs eventArgs)
|
||||||
|
{
|
||||||
|
base.OnLoad(eventArgs);
|
||||||
|
// TODO: Implement
|
||||||
|
// _tbPageCurrent.Visible = PlatformCompat.Runtime.IsToolbarTextboxSupported;
|
||||||
|
// if (Config.Get(c => c.HiddenButtons).HasFlag(ToolbarButtons.SavePdf))
|
||||||
|
// {
|
||||||
|
// _toolStrip1.Items.Remove(_tsSavePdf);
|
||||||
|
// }
|
||||||
|
// if (Config.Get(c => c.HiddenButtons).HasFlag(ToolbarButtons.SaveImages))
|
||||||
|
// {
|
||||||
|
// _toolStrip1.Items.Remove(_tsSaveImage);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// TODO: Implement mouse and keyboard controls
|
||||||
|
// AssignKeyboardShortcuts();
|
||||||
|
|
||||||
|
// TODO: We should definitely start with separate image forms, but it might be fairly trivial to, when opened
|
||||||
|
// from the preview form, have the temporary rendering be propagated back to the viewer form and have the
|
||||||
|
// dialog only show the editing controls. So it feels more like an image editor. Clicking e.g. "Crop" in the
|
||||||
|
// desktop form should still open the full image editing form (for now at least).
|
||||||
|
CreateToolbar();
|
||||||
|
|
||||||
|
UpdatePage();
|
||||||
|
UpdateImage().AssertNoAwait();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void CreateToolbar()
|
||||||
|
{
|
||||||
|
ToolBar = new ToolBar
|
||||||
|
{
|
||||||
|
Items =
|
||||||
|
{
|
||||||
|
new DropDownToolItem
|
||||||
|
{
|
||||||
|
Image = Commands.RotateMenu.Image,
|
||||||
|
Items =
|
||||||
|
{
|
||||||
|
Commands.RotateLeft,
|
||||||
|
Commands.RotateRight,
|
||||||
|
Commands.Flip,
|
||||||
|
Commands.Deskew,
|
||||||
|
Commands.CustomRotate
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Commands.Crop,
|
||||||
|
Commands.BrightCont,
|
||||||
|
Commands.HueSat,
|
||||||
|
Commands.BlackWhite,
|
||||||
|
Commands.Sharpen,
|
||||||
|
new SeparatorToolItem(),
|
||||||
|
Commands.SaveSelectedPdf,
|
||||||
|
Commands.SaveSelectedImages,
|
||||||
|
new SeparatorToolItem(),
|
||||||
|
Commands.Delete
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task GoTo(int index)
|
||||||
|
{
|
||||||
|
lock (ImageList)
|
||||||
|
{
|
||||||
|
if (index == ImageIndex || index < 0 || index >= ImageList.Images.Count)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
CurrentImage = ImageList.Images[index];
|
||||||
|
ImageList.UpdateSelection(ListSelection.Of(CurrentImage));
|
||||||
|
}
|
||||||
|
UpdatePage();
|
||||||
|
await UpdateImage();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void UpdatePage()
|
||||||
|
{
|
||||||
|
// TODO: Implement
|
||||||
|
// _tbPageCurrent.Text = (ImageIndex + 1).ToString(CultureInfo.CurrentCulture);
|
||||||
|
// _lblPageTotal.Text = string.Format(MiscResources.OfN, _imageList.Images.Count);
|
||||||
|
// if (!PlatformCompat.Runtime.IsToolbarTextboxSupported)
|
||||||
|
// {
|
||||||
|
// _lblPageTotal.Text = _tbPageCurrent.Text + ' ' + _lblPageTotal.Text;
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task UpdateImage()
|
||||||
|
{
|
||||||
|
// TODO: Implement
|
||||||
|
// _tiffViewer1.Image?.Dispose();
|
||||||
|
// _tiffViewer1.Image = null;
|
||||||
|
using var imageToRender = CurrentImage.GetClonedImage();
|
||||||
|
_imageView.Image = imageToRender.Render().ToEtoImage();
|
||||||
|
// _tiffViewer1.Image = imageToRender.RenderToBitmap();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing)
|
||||||
|
{
|
||||||
|
// TODO: Implement
|
||||||
|
// _components?.Dispose();
|
||||||
|
// _tiffViewer1?.Image?.Dispose();
|
||||||
|
// _tiffViewer1?.Dispose();
|
||||||
|
}
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
}
|
24
NAPS2.Lib/Lang/Resources/UiStrings.Designer.cs
generated
24
NAPS2.Lib/Lang/Resources/UiStrings.Designer.cs
generated
@ -674,5 +674,29 @@ namespace NAPS2.Lang.Resources {
|
|||||||
return ResourceManager.GetString("DownloadProgressFormTitle", resourceCulture);
|
return ResourceManager.GetString("DownloadProgressFormTitle", resourceCulture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static string PreviewFormTitle {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("PreviewFormTitle", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static string Next {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Next", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static string Previous {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Previous", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static string XOfY {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("XOfY", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -432,4 +432,16 @@
|
|||||||
<data name="DownloadProgressFormTitle" xml:space="preserve">
|
<data name="DownloadProgressFormTitle" xml:space="preserve">
|
||||||
<value>Download Progress</value>
|
<value>Download Progress</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="PreviewFormTitle" xml:space="preserve">
|
||||||
|
<value>Preview</value>
|
||||||
|
</data>
|
||||||
|
<data name="Next" xml:space="preserve">
|
||||||
|
<value>Next</value>
|
||||||
|
</data>
|
||||||
|
<data name="Previous" xml:space="preserve">
|
||||||
|
<value>Previous</value>
|
||||||
|
</data>
|
||||||
|
<data name="XOfY" xml:space="preserve">
|
||||||
|
<value>{0} of {1}</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
Loading…
Reference in New Issue
Block a user