WIP: PreviewForm eto migration and mac customization

This commit is contained in:
Ben Olden-Cooligan 2022-11-07 16:35:34 -08:00
parent 6dfb90e266
commit ebef67fedd
9 changed files with 311 additions and 5 deletions

View File

@ -18,6 +18,8 @@ public class MacIconProvider : IIconProvider
{ "arrow_switch_small", "arrow.2.squarepath" },
{ "arrow_up_small", "arrow.up" },
{ "arrow_down_small", "arrow.down" },
{ "arrow_left", "arrow.left" },
{ "arrow_right", "arrow.right" },
{ "transform_crop", "crop" },
{ "contrast_with_sun", "sun.max" },
{ "color_management", "paintpalette" },

View File

@ -1,13 +1,18 @@
using Eto.Mac.Forms.ToolBar;
namespace NAPS2.EtoForms.Mac;
public class MacToolbarDelegate : NSToolbarDelegate
{
private readonly string[] _identifiers;
private string[] _selectableIdentifiers;
private readonly Dictionary<string, MacToolbarEntry> _entryMap;
public MacToolbarDelegate(List<MacToolbarEntry> entries)
{
_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);
}
@ -19,7 +24,7 @@ public class MacToolbarDelegate : NSToolbarDelegate
public override string[] AllowedItemIdentifiers(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)
{

View File

@ -1,11 +1,17 @@
using Eto.Forms;
using Eto.Mac;
using Eto.Mac.Forms.ToolBar;
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
{
@ -13,7 +19,8 @@ public record MacToolbarEntry(string Identifier, NSToolbarItem Item)
Title = title ?? "",
Label = command.ToolBarText ?? "",
ToolTip = tooltip ?? command.ToolBarText ?? "",
Bordered = true
Bordered = true,
Navigational = nav
}.WithAction(command.Execute);
}

View 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)),
};
}
}

View File

@ -36,6 +36,7 @@ public class MacModule : Module
builder.RegisterType<MacIconProvider>().As<IIconProvider>();
builder.RegisterType<MacDesktopForm>().As<DesktopForm>();
builder.RegisterType<MacPreviewForm>().As<PreviewForm>();
EtoPlatform.Current = new MacEtoPlatform();
// Log.EventLogger = new WindowsEventLogger(Kernel!.Get<Naps2Config>());

View File

@ -6,11 +6,13 @@ public class StubDesktopSubFormController : IDesktopSubFormController
{
private readonly IFormFactory _formFactory;
private readonly DesktopImagesController _desktopImagesController;
private readonly UiImageList _imageList;
public StubDesktopSubFormController(IFormFactory formFactory, DesktopImagesController desktopImagesController)
public StubDesktopSubFormController(IFormFactory formFactory, DesktopImagesController desktopImagesController, UiImageList imageList)
{
_formFactory = formFactory;
_desktopImagesController = desktopImagesController;
_imageList = imageList;
}
public void ShowCropForm()
@ -55,6 +57,13 @@ public class StubDesktopSubFormController : IDesktopSubFormController
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()

View 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);
}
}

View File

@ -674,5 +674,29 @@ namespace NAPS2.Lang.Resources {
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);
}
}
}
}

View File

@ -432,4 +432,16 @@
<data name="DownloadProgressFormTitle" xml:space="preserve">
<value>Download Progress</value>
</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>