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_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" },
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
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<MacDesktopForm>().As<DesktopForm>();
|
||||
builder.RegisterType<MacPreviewForm>().As<PreviewForm>();
|
||||
|
||||
EtoPlatform.Current = new MacEtoPlatform();
|
||||
// Log.EventLogger = new WindowsEventLogger(Kernel!.Get<Naps2Config>());
|
||||
|
@ -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()
|
||||
|
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);
|
||||
}
|
||||
}
|
||||
|
||||
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">
|
||||
<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>
|
Loading…
Reference in New Issue
Block a user