mirror of
https://github.com/cyanfish/naps2.git
synced 2024-09-11 15:26:55 +03:00
WIP: Cross-platform notifications
This commit is contained in:
parent
ef05940838
commit
bb195cb5d0
@ -5,6 +5,7 @@ using Gdk;
|
||||
using Gtk;
|
||||
using NAPS2.EtoForms.Desktop;
|
||||
using NAPS2.EtoForms.Gtk;
|
||||
using NAPS2.EtoForms.Notifications;
|
||||
using NAPS2.EtoForms.Widgets;
|
||||
using NAPS2.ImportExport.Images;
|
||||
using Command = Eto.Forms.Command;
|
||||
@ -23,7 +24,7 @@ public class GtkDesktopForm : DesktopForm
|
||||
public GtkDesktopForm(
|
||||
Naps2Config config,
|
||||
DesktopKeyboardShortcuts keyboardShortcuts,
|
||||
INotificationManager notify,
|
||||
NotificationManager notificationManager,
|
||||
CultureHelper cultureHelper,
|
||||
ColorScheme colorScheme,
|
||||
IProfileManager profileManager,
|
||||
@ -38,7 +39,7 @@ public class GtkDesktopForm : DesktopForm
|
||||
DesktopFormProvider desktopFormProvider,
|
||||
IDesktopSubFormController desktopSubFormController,
|
||||
DesktopCommands commands)
|
||||
: base(config, keyboardShortcuts, notify, cultureHelper, colorScheme, profileManager,
|
||||
: base(config, keyboardShortcuts, notificationManager, cultureHelper, colorScheme, profileManager,
|
||||
imageList, imageTransfer, thumbnailController, thumbnailProvider, desktopController, desktopScanController,
|
||||
imageListActions, imageListViewBehavior, desktopFormProvider, desktopSubFormController, commands)
|
||||
{
|
||||
|
@ -4,7 +4,6 @@ using NAPS2.EtoForms.Gtk;
|
||||
using NAPS2.EtoForms.Ui;
|
||||
using NAPS2.Images.Gtk;
|
||||
using NAPS2.ImportExport;
|
||||
using NAPS2.Update;
|
||||
|
||||
namespace NAPS2.Modules;
|
||||
|
||||
@ -14,7 +13,6 @@ public class GtkModule : GuiModule
|
||||
{
|
||||
base.Load(builder);
|
||||
|
||||
builder.RegisterType<StubNotificationManager>().As<INotificationManager>().SingleInstance();
|
||||
builder.RegisterType<GtkScannedImagePrinter>().As<IScannedImagePrinter>();
|
||||
builder.RegisterType<GtkDarkModeProvider>().As<IDarkModeProvider>();
|
||||
builder.RegisterType<GtkImageContext>().As<ImageContext>();
|
||||
@ -26,30 +24,3 @@ public class GtkModule : GuiModule
|
||||
EtoPlatform.Current = new GtkEtoPlatform();
|
||||
}
|
||||
}
|
||||
|
||||
public class StubNotificationManager : INotificationManager
|
||||
{
|
||||
public void PdfSaved(string path)
|
||||
{
|
||||
}
|
||||
|
||||
public void ImagesSaved(int imageCount, string path)
|
||||
{
|
||||
}
|
||||
|
||||
public void DonatePrompt()
|
||||
{
|
||||
}
|
||||
|
||||
public void OperationProgress(OperationProgress opModalProgress, IOperation op)
|
||||
{
|
||||
}
|
||||
|
||||
public void UpdateAvailable(IUpdateChecker updateChecker, UpdateInfo update)
|
||||
{
|
||||
}
|
||||
|
||||
public void Rebuild()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ using Eto.Forms;
|
||||
using NAPS2.EtoForms.Desktop;
|
||||
using NAPS2.EtoForms.Layout;
|
||||
using NAPS2.EtoForms.Mac;
|
||||
using NAPS2.EtoForms.Notifications;
|
||||
using NAPS2.EtoForms.Widgets;
|
||||
using NAPS2.ImportExport.Images;
|
||||
using NAPS2.Scan;
|
||||
@ -14,7 +15,7 @@ public class MacDesktopForm : DesktopForm
|
||||
public MacDesktopForm(
|
||||
Naps2Config config,
|
||||
DesktopKeyboardShortcuts keyboardShortcuts,
|
||||
INotificationManager notify,
|
||||
NotificationManager notificationManager,
|
||||
CultureHelper cultureHelper,
|
||||
ColorScheme colorScheme,
|
||||
IProfileManager profileManager,
|
||||
@ -29,7 +30,7 @@ public class MacDesktopForm : DesktopForm
|
||||
DesktopFormProvider desktopFormProvider,
|
||||
IDesktopSubFormController desktopSubFormController,
|
||||
DesktopCommands commands)
|
||||
: base(config, keyboardShortcuts, notify, cultureHelper, colorScheme, profileManager,
|
||||
: base(config, keyboardShortcuts, notificationManager, cultureHelper, colorScheme, profileManager,
|
||||
imageList, imageTransfer, thumbnailController, thumbnailProvider, desktopController, desktopScanController,
|
||||
imageListActions, imageListViewBehavior, desktopFormProvider, desktopSubFormController, commands)
|
||||
{
|
||||
|
@ -5,8 +5,6 @@ using NAPS2.EtoForms.Ui;
|
||||
using NAPS2.Images.Mac;
|
||||
using NAPS2.ImportExport;
|
||||
using NAPS2.ImportExport.Email;
|
||||
using NAPS2.Pdf;
|
||||
using NAPS2.Update;
|
||||
|
||||
namespace NAPS2.Modules;
|
||||
|
||||
@ -16,7 +14,6 @@ public class MacModule : GuiModule
|
||||
{
|
||||
base.Load(builder);
|
||||
|
||||
builder.RegisterType<StubNotificationManager>().As<INotificationManager>().SingleInstance();
|
||||
builder.RegisterType<MacScannedImagePrinter>().As<IScannedImagePrinter>();
|
||||
builder.RegisterType<AppleMailEmailProvider>().As<IAppleMailEmailProvider>();
|
||||
builder.RegisterType<MacDarkModeProvider>().As<IDarkModeProvider>();
|
||||
@ -30,39 +27,3 @@ public class MacModule : GuiModule
|
||||
EtoPlatform.Current = new MacEtoPlatform();
|
||||
}
|
||||
}
|
||||
|
||||
public class StubNotificationManager : INotificationManager
|
||||
{
|
||||
public void PdfSaved(string path)
|
||||
{
|
||||
}
|
||||
|
||||
public void ImagesSaved(int imageCount, string path)
|
||||
{
|
||||
}
|
||||
|
||||
public void DonatePrompt()
|
||||
{
|
||||
}
|
||||
|
||||
public void OperationProgress(OperationProgress opModalProgress, IOperation op)
|
||||
{
|
||||
}
|
||||
|
||||
public void UpdateAvailable(IUpdateChecker updateChecker, UpdateInfo update)
|
||||
{
|
||||
}
|
||||
|
||||
public void Rebuild()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class StubPdfPasswordProvider : IPdfPasswordProvider
|
||||
{
|
||||
public bool ProvidePassword(string fileName, int attemptCount, out string password)
|
||||
{
|
||||
password = null!;
|
||||
return false;
|
||||
}
|
||||
}
|
@ -1,6 +1,8 @@
|
||||
using Moq;
|
||||
using NAPS2.EtoForms;
|
||||
using NAPS2.EtoForms.Desktop;
|
||||
using NAPS2.EtoForms.Notifications;
|
||||
using NAPS2.EtoForms.Widgets;
|
||||
using NAPS2.ImportExport;
|
||||
using NAPS2.ImportExport.Images;
|
||||
using NAPS2.Platform.Windows;
|
||||
@ -27,7 +29,7 @@ public class DesktopControllerTests : ContextualTests
|
||||
private readonly Mock<IOperationFactory> _operationFactory;
|
||||
private readonly StillImage _stillImage;
|
||||
private readonly Mock<IUpdateChecker> _updateChecker;
|
||||
private readonly Mock<INotificationManager> _notificationManager;
|
||||
private readonly Mock<Notify> _notify;
|
||||
private readonly ImageTransfer _imageTransfer;
|
||||
private readonly ImageClipboard _imageClipboard;
|
||||
private readonly Mock<IExportController> _exportHelper;
|
||||
@ -51,7 +53,7 @@ public class DesktopControllerTests : ContextualTests
|
||||
_operationFactory = new Mock<IOperationFactory>();
|
||||
_stillImage = new StillImage();
|
||||
_updateChecker = new Mock<IUpdateChecker>();
|
||||
_notificationManager = new Mock<INotificationManager>();
|
||||
_notify = new Mock<Notify>();
|
||||
_imageTransfer = new ImageTransfer();
|
||||
_imageClipboard = new ImageClipboard();
|
||||
_exportHelper = new Mock<IExportController>();
|
||||
@ -72,11 +74,11 @@ public class DesktopControllerTests : ContextualTests
|
||||
_operationFactory.Object,
|
||||
_stillImage,
|
||||
_updateChecker.Object,
|
||||
_notificationManager.Object,
|
||||
_notify.Object,
|
||||
_imageTransfer,
|
||||
_imageClipboard,
|
||||
new ImageListActions(_imageList, _operationFactory.Object, _operationProgress.Object,
|
||||
_config, _thumbnailController, _exportHelper.Object, _notificationManager.Object),
|
||||
_config, _thumbnailController, _exportHelper.Object, _notify.Object),
|
||||
_dialogHelper.Object,
|
||||
_desktopImagesController,
|
||||
_desktopScanController.Object,
|
||||
@ -105,7 +107,7 @@ public class DesktopControllerTests : ContextualTests
|
||||
|
||||
Assert.True(_config.Get(c => c.HasBeenRun));
|
||||
DateAsserts.Recent(TimeSpan.FromMilliseconds(1000), _config.Get(c => c.FirstRunDate));
|
||||
_notificationManager.VerifyNoOtherCalls();
|
||||
_notify.VerifyNoOtherCalls();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@ -119,7 +121,7 @@ public class DesktopControllerTests : ContextualTests
|
||||
|
||||
Assert.True(_config.Get(c => c.HasBeenRun));
|
||||
Assert.Equal(firstRunDate, _config.Get(c => c.FirstRunDate));
|
||||
_notificationManager.VerifyNoOtherCalls();
|
||||
_notify.VerifyNoOtherCalls();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@ -131,7 +133,7 @@ public class DesktopControllerTests : ContextualTests
|
||||
|
||||
await _desktopController.Initialize();
|
||||
|
||||
_notificationManager.Verify(x => x.DonatePrompt());
|
||||
_notify.Verify(x => x.DonatePrompt());
|
||||
Assert.True(_config.Get(c => c.HasBeenPromptedForDonation));
|
||||
DateAsserts.Recent(TimeSpan.FromMilliseconds(1000), _config.Get(c => c.LastDonatePromptDate));
|
||||
}
|
||||
@ -150,7 +152,7 @@ public class DesktopControllerTests : ContextualTests
|
||||
|
||||
Assert.True(_config.Get(c => c.HasBeenPromptedForDonation));
|
||||
Assert.Equal(donatePromptDate, _config.Get(c => c.LastDonatePromptDate));
|
||||
_notificationManager.VerifyNoOtherCalls();
|
||||
_notify.VerifyNoOtherCalls();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@ -187,7 +189,7 @@ public class DesktopControllerTests : ContextualTests
|
||||
DateAsserts.Recent(TimeSpan.FromMilliseconds(1000), _config.Get(c => c.LastUpdateCheckDate));
|
||||
_updateChecker.Verify(x => x.CheckForUpdates());
|
||||
_updateChecker.VerifyNoOtherCalls();
|
||||
_notificationManager.VerifyNoOtherCalls();
|
||||
_notify.VerifyNoOtherCalls();
|
||||
}
|
||||
|
||||
[Fact(Skip = "flaky")]
|
||||
@ -204,9 +206,9 @@ public class DesktopControllerTests : ContextualTests
|
||||
Assert.True(_config.Get(c => c.HasCheckedForUpdates));
|
||||
DateAsserts.Recent(TimeSpan.FromMilliseconds(1000), _config.Get(c => c.LastUpdateCheckDate));
|
||||
_updateChecker.Verify(x => x.CheckForUpdates());
|
||||
_notificationManager.Verify(x => x.UpdateAvailable(_updateChecker.Object, mockUpdateInfo));
|
||||
_notify.Verify(x => x.UpdateAvailable(_updateChecker.Object, mockUpdateInfo));
|
||||
_updateChecker.VerifyNoOtherCalls();
|
||||
_notificationManager.VerifyNoOtherCalls();
|
||||
_notify.VerifyNoOtherCalls();
|
||||
}
|
||||
|
||||
[Fact(Skip = "flaky")]
|
||||
@ -221,7 +223,7 @@ public class DesktopControllerTests : ContextualTests
|
||||
Assert.False(_config.Get(c => c.HasCheckedForUpdates));
|
||||
Assert.Null(_config.Get(c => c.LastUpdateCheckDate));
|
||||
_updateChecker.VerifyNoOtherCalls();
|
||||
_notificationManager.VerifyNoOtherCalls();
|
||||
_notify.VerifyNoOtherCalls();
|
||||
}
|
||||
|
||||
[Fact(Skip = "flaky")]
|
||||
@ -238,7 +240,7 @@ public class DesktopControllerTests : ContextualTests
|
||||
Assert.True(_config.Get(c => c.HasCheckedForUpdates));
|
||||
Assert.Equal(updateCheckDate, _config.Get(c => c.LastUpdateCheckDate));
|
||||
_updateChecker.VerifyNoOtherCalls();
|
||||
_notificationManager.VerifyNoOtherCalls();
|
||||
_notify.VerifyNoOtherCalls();
|
||||
}
|
||||
|
||||
[Fact(Skip = "flaky")]
|
||||
@ -258,8 +260,8 @@ public class DesktopControllerTests : ContextualTests
|
||||
Assert.True(_config.Get(c => c.HasCheckedForUpdates));
|
||||
DateAsserts.Recent(TimeSpan.FromMilliseconds(1000), _config.Get(c => c.LastUpdateCheckDate));
|
||||
_updateChecker.Verify(x => x.CheckForUpdates());
|
||||
_notificationManager.Verify(x => x.UpdateAvailable(_updateChecker.Object, mockUpdateInfo));
|
||||
_notify.Verify(x => x.UpdateAvailable(_updateChecker.Object, mockUpdateInfo));
|
||||
_updateChecker.VerifyNoOtherCalls();
|
||||
_notificationManager.VerifyNoOtherCalls();
|
||||
_notify.VerifyNoOtherCalls();
|
||||
}
|
||||
}
|
@ -5,6 +5,7 @@ using Eto.WinForms;
|
||||
using Eto.WinForms.Forms.ToolBar;
|
||||
using NAPS2.EtoForms.Desktop;
|
||||
using NAPS2.EtoForms.Layout;
|
||||
using NAPS2.EtoForms.Notifications;
|
||||
using NAPS2.EtoForms.Widgets;
|
||||
using NAPS2.EtoForms.WinForms;
|
||||
using NAPS2.ImportExport.Images;
|
||||
@ -26,7 +27,7 @@ public class WinFormsDesktopForm : DesktopForm
|
||||
public WinFormsDesktopForm(
|
||||
Naps2Config config,
|
||||
DesktopKeyboardShortcuts keyboardShortcuts,
|
||||
INotificationManager notify,
|
||||
NotificationManager notificationManager,
|
||||
CultureHelper cultureHelper,
|
||||
ColorScheme colorScheme,
|
||||
IProfileManager profileManager,
|
||||
@ -41,7 +42,7 @@ public class WinFormsDesktopForm : DesktopForm
|
||||
DesktopFormProvider desktopFormProvider,
|
||||
IDesktopSubFormController desktopSubFormController,
|
||||
DesktopCommands commands)
|
||||
: base(config, keyboardShortcuts, notify, cultureHelper, colorScheme, profileManager,
|
||||
: base(config, keyboardShortcuts, notificationManager, cultureHelper, colorScheme, profileManager,
|
||||
imageList, imageTransfer, thumbnailController, thumbnailProvider, desktopController, desktopScanController,
|
||||
imageListActions, imageListViewBehavior, desktopFormProvider, desktopSubFormController, commands)
|
||||
{
|
||||
@ -98,7 +99,7 @@ public class WinFormsDesktopForm : DesktopForm
|
||||
FlatStyle = wf.FlatStyle.Flat
|
||||
};
|
||||
return L.Overlay(
|
||||
mouseCatcher.ToEto(),
|
||||
L.Row(mouseCatcher.ToEto().AlignTrailing()),
|
||||
base.GetZoomButtons()
|
||||
);
|
||||
}
|
||||
|
@ -13,7 +13,6 @@ public class WinFormsModule : GuiModule
|
||||
{
|
||||
base.Load(builder);
|
||||
|
||||
builder.RegisterType<NotificationManager>().As<INotificationManager>().SingleInstance();
|
||||
builder.RegisterType<PrintDocumentPrinter>().As<IScannedImagePrinter>();
|
||||
builder.RegisterType<WinFormsDarkModeProvider>().As<IDarkModeProvider>().SingleInstance();
|
||||
|
||||
|
@ -1,12 +0,0 @@
|
||||
namespace NAPS2.WinForms;
|
||||
|
||||
public class DonatePromptNotifyWidget : NotifyWidget
|
||||
{
|
||||
public DonatePromptNotifyWidget()
|
||||
: base(MiscResources.DonatePrompt, MiscResources.Donate, "https://www.naps2.com/donate", null)
|
||||
{
|
||||
hideTimer.Interval = 60 * 1000;
|
||||
}
|
||||
|
||||
public override NotifyWidgetBase Clone() => new DonatePromptNotifyWidget();
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
namespace NAPS2.WinForms;
|
||||
|
||||
public class ImagesSavedNotifyWidget : NotifyWidget
|
||||
{
|
||||
private readonly int _imageCount;
|
||||
private readonly string _path;
|
||||
|
||||
public ImagesSavedNotifyWidget(int imageCount, string path)
|
||||
: base(string.Format(MiscResources.ImagesSaved, imageCount), Path.GetFileName(path), path, Path.GetDirectoryName(path))
|
||||
{
|
||||
_imageCount = imageCount;
|
||||
_path = path;
|
||||
}
|
||||
|
||||
public override NotifyWidgetBase Clone() => new ImagesSavedNotifyWidget(_imageCount, _path);
|
||||
}
|
@ -1,140 +0,0 @@
|
||||
using System.Drawing;
|
||||
using Eto.Forms;
|
||||
using NAPS2.EtoForms;
|
||||
using NAPS2.EtoForms.Desktop;
|
||||
using NAPS2.Update;
|
||||
using wf = System.Windows.Forms;
|
||||
|
||||
namespace NAPS2.WinForms;
|
||||
|
||||
public class NotificationManager : INotificationManager
|
||||
{
|
||||
private const int PADDING_X = 25, PADDING_Y = 25;
|
||||
private const int SPACING_Y = 20;
|
||||
|
||||
private readonly Naps2Config _config;
|
||||
private readonly List<NotifyWidgetBase?> _slots = new();
|
||||
private wf.Form? _parentForm;
|
||||
|
||||
public NotificationManager(Naps2Config config, DesktopFormProvider desktopFormProvider)
|
||||
{
|
||||
_config = config;
|
||||
desktopFormProvider.DesktopFormChanged += (_, _) =>
|
||||
{
|
||||
if (_parentForm != null)
|
||||
{
|
||||
_parentForm.Resize -= parentForm_Resize;
|
||||
}
|
||||
_parentForm = desktopFormProvider.DesktopForm.ToNative();
|
||||
_parentForm.Resize += parentForm_Resize;
|
||||
};
|
||||
}
|
||||
|
||||
public void PdfSaved(string path)
|
||||
{
|
||||
Show(new PdfSavedNotifyWidget(path));
|
||||
}
|
||||
|
||||
public void ImagesSaved(int imageCount, string path)
|
||||
{
|
||||
if (imageCount == 1)
|
||||
{
|
||||
Show(new OneImageSavedNotifyWidget(path));
|
||||
}
|
||||
else if (imageCount > 1)
|
||||
{
|
||||
Show(new ImagesSavedNotifyWidget(imageCount, path));
|
||||
}
|
||||
}
|
||||
|
||||
public void DonatePrompt()
|
||||
{
|
||||
Show(new DonatePromptNotifyWidget());
|
||||
}
|
||||
|
||||
public void OperationProgress(OperationProgress opModalProgress, IOperation op)
|
||||
{
|
||||
Show(new OperationProgressNotifyWidget(opModalProgress, op));
|
||||
}
|
||||
|
||||
public void UpdateAvailable(IUpdateChecker updateChecker, UpdateInfo update)
|
||||
{
|
||||
Show(new UpdateAvailableNotifyWidget(updateChecker, update));
|
||||
}
|
||||
|
||||
public void Rebuild()
|
||||
{
|
||||
var old = _slots.ToList();
|
||||
_slots.Clear();
|
||||
for (int i = 0; i < old.Count; i++)
|
||||
{
|
||||
var slot = old[i];
|
||||
if (slot != null)
|
||||
{
|
||||
Show(slot.Clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Show(NotifyWidgetBase n)
|
||||
{
|
||||
if (_config.Get(c => c.DisableSaveNotifications) && n is NotifyWidget)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Invoker.Current.Invoke(() =>
|
||||
{
|
||||
int slot = FillNextSlot(n);
|
||||
n.Location = GetPosition(n, slot);
|
||||
n.Resize += parentForm_Resize;
|
||||
n.BringToFront();
|
||||
n.HideNotify += (sender, args) => ClearSlot(n);
|
||||
n.ShowNotify();
|
||||
});
|
||||
}
|
||||
|
||||
private void parentForm_Resize(object? sender, EventArgs e)
|
||||
{
|
||||
for (int i = 0; i < _slots.Count; i++)
|
||||
{
|
||||
var slot = _slots[i];
|
||||
if (slot != null)
|
||||
{
|
||||
slot.Location = GetPosition(slot, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ClearSlot(NotifyWidgetBase n)
|
||||
{
|
||||
var index = _slots.IndexOf(n);
|
||||
if (index != -1)
|
||||
{
|
||||
_parentForm!.Controls.Remove(n);
|
||||
_slots[index] = null;
|
||||
}
|
||||
}
|
||||
|
||||
private int FillNextSlot(NotifyWidgetBase n)
|
||||
{
|
||||
var index = _slots.IndexOf(null);
|
||||
if (index == -1)
|
||||
{
|
||||
index = _slots.Count;
|
||||
_slots.Add(n);
|
||||
}
|
||||
else
|
||||
{
|
||||
_slots[index] = n;
|
||||
}
|
||||
_parentForm!.Controls.Add(n);
|
||||
return index;
|
||||
}
|
||||
|
||||
private Point GetPosition(NotifyWidgetBase n, int slot)
|
||||
{
|
||||
return new Point(_parentForm!.ClientSize.Width - n.Width - PADDING_X,
|
||||
_parentForm.ClientSize.Height - n.Height - PADDING_Y - (n.Height + SPACING_Y) * slot);
|
||||
}
|
||||
}
|
112
NAPS2.Lib.WinForms/WinForms/NotifyWidget.Designer.cs
generated
112
NAPS2.Lib.WinForms/WinForms/NotifyWidget.Designer.cs
generated
@ -1,112 +0,0 @@
|
||||
using Eto.WinForms;
|
||||
using NAPS2.EtoForms;
|
||||
|
||||
namespace NAPS2.WinForms
|
||||
{
|
||||
partial class NotifyWidget
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Component Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.components = new System.ComponentModel.Container();
|
||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(NotifyWidget));
|
||||
this.lblTitle = new System.Windows.Forms.Label();
|
||||
this.linkLabel1 = new System.Windows.Forms.LinkLabel();
|
||||
this.btnClose = new System.Windows.Forms.Button();
|
||||
this.hideTimer = new System.Windows.Forms.Timer(this.components);
|
||||
this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components);
|
||||
this.openFolderToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.contextMenuStrip1.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// lblTitle
|
||||
//
|
||||
resources.ApplyResources(this.lblTitle, "lblTitle");
|
||||
this.lblTitle.Name = "lblTitle";
|
||||
//
|
||||
// linkLabel1
|
||||
//
|
||||
resources.ApplyResources(this.linkLabel1, "linkLabel1");
|
||||
this.linkLabel1.AutoEllipsis = true;
|
||||
this.linkLabel1.Name = "linkLabel1";
|
||||
this.linkLabel1.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel1_LinkClicked);
|
||||
//
|
||||
// btnClose
|
||||
//
|
||||
resources.ApplyResources(this.btnClose, "btnClose");
|
||||
this.btnClose.Cursor = System.Windows.Forms.Cursors.Hand;
|
||||
this.btnClose.FlatAppearance.BorderSize = 0;
|
||||
this.btnClose.Image = global::NAPS2.Icons.close.ToBitmap();
|
||||
this.btnClose.Name = "btnClose";
|
||||
this.btnClose.UseVisualStyleBackColor = true;
|
||||
this.btnClose.Click += new System.EventHandler(this.btnClose_Click);
|
||||
//
|
||||
// hideTimer
|
||||
//
|
||||
this.hideTimer.Interval = 5000;
|
||||
this.hideTimer.Tick += new System.EventHandler(this.hideTimer_Tick);
|
||||
//
|
||||
// contextMenuStrip1
|
||||
//
|
||||
this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.openFolderToolStripMenuItem});
|
||||
this.contextMenuStrip1.Name = "contextMenuStrip1";
|
||||
resources.ApplyResources(this.contextMenuStrip1, "contextMenuStrip1");
|
||||
//
|
||||
// openFolderToolStripMenuItem
|
||||
//
|
||||
this.openFolderToolStripMenuItem.Name = "openFolderToolStripMenuItem";
|
||||
resources.ApplyResources(this.openFolderToolStripMenuItem, "openFolderToolStripMenuItem");
|
||||
this.openFolderToolStripMenuItem.Click += new System.EventHandler(this.openFolderToolStripMenuItem_Click);
|
||||
//
|
||||
// NotifyWidget
|
||||
//
|
||||
resources.ApplyResources(this, "$this");
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(234)))), ((int)(((byte)(234)))), ((int)(((byte)(234)))));
|
||||
this.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
|
||||
this.Controls.Add(this.btnClose);
|
||||
this.Controls.Add(this.linkLabel1);
|
||||
this.Controls.Add(this.lblTitle);
|
||||
this.Name = "NotifyWidget";
|
||||
this.MouseEnter += new System.EventHandler(this.NotifyWidget_MouseEnter);
|
||||
this.MouseLeave += new System.EventHandler(this.NotifyWidget_MouseLeave);
|
||||
this.contextMenuStrip1.ResumeLayout(false);
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
protected System.Windows.Forms.Label lblTitle;
|
||||
private System.Windows.Forms.LinkLabel linkLabel1;
|
||||
private System.Windows.Forms.Button btnClose;
|
||||
protected System.Windows.Forms.Timer hideTimer;
|
||||
private System.Windows.Forms.ContextMenuStrip contextMenuStrip1;
|
||||
private System.Windows.Forms.ToolStripMenuItem openFolderToolStripMenuItem;
|
||||
}
|
||||
}
|
@ -1,98 +0,0 @@
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace NAPS2.WinForms;
|
||||
|
||||
public partial class NotifyWidget : NotifyWidgetBase
|
||||
{
|
||||
private readonly string? _linkTarget;
|
||||
private readonly string? _folderTarget;
|
||||
|
||||
public NotifyWidget(string title, string linkLabel, string? linkTarget, string? folderTarget)
|
||||
{
|
||||
_linkTarget = linkTarget;
|
||||
_folderTarget = folderTarget;
|
||||
InitializeComponent();
|
||||
|
||||
lblTitle.Text = title;
|
||||
linkLabel1.Text = linkLabel;
|
||||
|
||||
if (lblTitle.Width > Width - 35)
|
||||
{
|
||||
Width = lblTitle.Width + 35;
|
||||
}
|
||||
if (lblTitle.Height > Height - 35)
|
||||
{
|
||||
Height = lblTitle.Height + 35;
|
||||
}
|
||||
|
||||
if (folderTarget == null)
|
||||
{
|
||||
contextMenuStrip1.Enabled = false;
|
||||
}
|
||||
|
||||
openFolderToolStripMenuItem.Text = UiStrings.OpenFolder;
|
||||
}
|
||||
|
||||
private void hideTimer_Tick(object sender, EventArgs e)
|
||||
{
|
||||
DoHideNotify();
|
||||
}
|
||||
|
||||
protected void DoHideNotify()
|
||||
{
|
||||
InvokeHideNotify();
|
||||
hideTimer.Stop();
|
||||
}
|
||||
|
||||
private void btnClose_Click(object sender, EventArgs e)
|
||||
{
|
||||
DoHideNotify();
|
||||
}
|
||||
|
||||
private void NotifyWidget_MouseEnter(object sender, EventArgs e)
|
||||
{
|
||||
hideTimer.Stop();
|
||||
}
|
||||
|
||||
private void NotifyWidget_MouseLeave(object sender, EventArgs e)
|
||||
{
|
||||
hideTimer.Start();
|
||||
}
|
||||
|
||||
public override void ShowNotify()
|
||||
{
|
||||
hideTimer.Start();
|
||||
}
|
||||
|
||||
protected virtual void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
|
||||
{
|
||||
if (_linkTarget == null)
|
||||
{
|
||||
Log.Error("Link target should not be null");
|
||||
return;
|
||||
}
|
||||
if (e.Button == MouseButtons.Right)
|
||||
{
|
||||
contextMenuStrip1.Show(linkLabel1, linkLabel1.Location);
|
||||
}
|
||||
else
|
||||
{
|
||||
Process.Start(new ProcessStartInfo
|
||||
{
|
||||
UseShellExecute = true,
|
||||
FileName = _linkTarget,
|
||||
Verb = "open"
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void openFolderToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
Process.Start(new ProcessStartInfo
|
||||
{
|
||||
UseShellExecute = true,
|
||||
FileName = _folderTarget,
|
||||
Verb = "open"
|
||||
});
|
||||
}
|
||||
}
|
@ -1,261 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<assembly alias="mscorlib" name="mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||
<data name="lblTitle.AutoSize" type="System.Boolean, mscorlib">
|
||||
<value>True</value>
|
||||
</data>
|
||||
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<data name="lblTitle.Font" type="System.Drawing.Font, System.Drawing">
|
||||
<value>Microsoft Sans Serif, 8.25pt, style=Bold</value>
|
||||
</data>
|
||||
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||
<data name="lblTitle.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms">
|
||||
<value>NoControl</value>
|
||||
</data>
|
||||
<data name="lblTitle.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>7, 8</value>
|
||||
</data>
|
||||
<data name="lblTitle.MaximumSize" type="System.Drawing.Size, System.Drawing">
|
||||
<value>200, 0</value>
|
||||
</data>
|
||||
<data name="lblTitle.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>0, 13</value>
|
||||
</data>
|
||||
<data name="lblTitle.TabIndex" type="System.Int32, mscorlib">
|
||||
<value>0</value>
|
||||
</data>
|
||||
<data name=">>lblTitle.Name" xml:space="preserve">
|
||||
<value>lblTitle</value>
|
||||
</data>
|
||||
<data name=">>lblTitle.Type" xml:space="preserve">
|
||||
<value>System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name=">>lblTitle.Parent" xml:space="preserve">
|
||||
<value>$this</value>
|
||||
</data>
|
||||
<data name=">>lblTitle.ZOrder" xml:space="preserve">
|
||||
<value>3</value>
|
||||
</data>
|
||||
<data name="linkLabel1.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
|
||||
<value>Bottom, Left, Right</value>
|
||||
</data>
|
||||
<data name="linkLabel1.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>7, 27</value>
|
||||
</data>
|
||||
<data name="linkLabel1.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>150, 13</value>
|
||||
</data>
|
||||
<data name="linkLabel1.TabIndex" type="System.Int32, mscorlib">
|
||||
<value>1</value>
|
||||
</data>
|
||||
<data name=">>linkLabel1.Name" xml:space="preserve">
|
||||
<value>linkLabel1</value>
|
||||
</data>
|
||||
<data name=">>linkLabel1.Type" xml:space="preserve">
|
||||
<value>System.Windows.Forms.LinkLabel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name=">>linkLabel1.Parent" xml:space="preserve">
|
||||
<value>$this</value>
|
||||
</data>
|
||||
<data name=">>linkLabel1.ZOrder" xml:space="preserve">
|
||||
<value>2</value>
|
||||
</data>
|
||||
<data name="btnClose.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
|
||||
<value>Top, Right</value>
|
||||
</data>
|
||||
<data name="btnClose.FlatStyle" type="System.Windows.Forms.FlatStyle, System.Windows.Forms">
|
||||
<value>Flat</value>
|
||||
</data>
|
||||
<data name="btnClose.Font" type="System.Drawing.Font, System.Drawing">
|
||||
<value>Microsoft Sans Serif, 12pt</value>
|
||||
</data>
|
||||
<data name="btnClose.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>132, 4</value>
|
||||
</data>
|
||||
<data name="btnClose.Padding" type="System.Windows.Forms.Padding, System.Windows.Forms">
|
||||
<value>0, 0, 1, 1</value>
|
||||
</data>
|
||||
<data name="btnClose.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>20, 20</value>
|
||||
</data>
|
||||
<data name="btnClose.TabIndex" type="System.Int32, mscorlib">
|
||||
<value>2</value>
|
||||
</data>
|
||||
<data name=">>btnClose.Name" xml:space="preserve">
|
||||
<value>btnClose</value>
|
||||
</data>
|
||||
<data name=">>btnClose.Type" xml:space="preserve">
|
||||
<value>System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name=">>btnClose.Parent" xml:space="preserve">
|
||||
<value>$this</value>
|
||||
</data>
|
||||
<data name=">>btnClose.ZOrder" xml:space="preserve">
|
||||
<value>1</value>
|
||||
</data>
|
||||
<metadata name="hideTimer.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>17, 17</value>
|
||||
</metadata>
|
||||
<metadata name="contextMenuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>123, 17</value>
|
||||
</metadata>
|
||||
<data name="contextMenuStrip1.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>140, 26</value>
|
||||
</data>
|
||||
<data name=">>contextMenuStrip1.Name" xml:space="preserve">
|
||||
<value>contextMenuStrip1</value>
|
||||
</data>
|
||||
<data name=">>contextMenuStrip1.Type" xml:space="preserve">
|
||||
<value>System.Windows.Forms.ContextMenuStrip, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name="openFolderToolStripMenuItem.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>139, 22</value>
|
||||
</data>
|
||||
<data name="openFolderToolStripMenuItem.Text" xml:space="preserve">
|
||||
<value>Open Folder</value>
|
||||
</data>
|
||||
<metadata name="$this.Localizable" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>True</value>
|
||||
</metadata>
|
||||
<data name="$this.AutoScaleDimensions" type="System.Drawing.SizeF, System.Drawing">
|
||||
<value>6, 13</value>
|
||||
</data>
|
||||
<data name="$this.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>156, 46</value>
|
||||
</data>
|
||||
<data name=">>hideTimer.Name" xml:space="preserve">
|
||||
<value>hideTimer</value>
|
||||
</data>
|
||||
<data name=">>hideTimer.Type" xml:space="preserve">
|
||||
<value>System.Windows.Forms.Timer, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name=">>openFolderToolStripMenuItem.Name" xml:space="preserve">
|
||||
<value>openFolderToolStripMenuItem</value>
|
||||
</data>
|
||||
<data name=">>openFolderToolStripMenuItem.Type" xml:space="preserve">
|
||||
<value>System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name=">>$this.Name" xml:space="preserve">
|
||||
<value>NotifyWidget</value>
|
||||
</data>
|
||||
<data name=">>$this.Type" xml:space="preserve">
|
||||
<value>System.Windows.Forms.UserControl, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
</root>
|
@ -1,19 +0,0 @@
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace NAPS2.WinForms;
|
||||
|
||||
public class NotifyWidgetBase : UserControl
|
||||
{
|
||||
public event EventHandler? HideNotify;
|
||||
|
||||
protected void InvokeHideNotify()
|
||||
{
|
||||
Invoker.Current.Invoke(() => HideNotify?.Invoke(this, EventArgs.Empty));
|
||||
}
|
||||
|
||||
public virtual void ShowNotify()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual NotifyWidgetBase Clone() => throw new NotImplementedException();
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
namespace NAPS2.WinForms;
|
||||
|
||||
public class OneImageSavedNotifyWidget : NotifyWidget
|
||||
{
|
||||
private readonly string _path;
|
||||
|
||||
public OneImageSavedNotifyWidget(string path)
|
||||
: base(MiscResources.ImageSaved, Path.GetFileName(path), path, Path.GetDirectoryName(path))
|
||||
{
|
||||
_path = path;
|
||||
}
|
||||
|
||||
public override NotifyWidgetBase Clone() => new OneImageSavedNotifyWidget(_path);
|
||||
}
|
@ -1,99 +0,0 @@
|
||||
namespace NAPS2.WinForms
|
||||
{
|
||||
partial class OperationProgressNotifyWidget
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Component Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.components = new System.ComponentModel.Container();
|
||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(OperationProgressNotifyWidget));
|
||||
this.lblTitle = new System.Windows.Forms.Label();
|
||||
this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components);
|
||||
this.cancelToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.progressBar = new System.Windows.Forms.ProgressBar();
|
||||
this.lblNumber = new System.Windows.Forms.Label();
|
||||
this.contextMenuStrip1.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// lblTitle
|
||||
//
|
||||
resources.ApplyResources(this.lblTitle, "lblTitle");
|
||||
this.lblTitle.Name = "lblTitle";
|
||||
this.lblTitle.MouseClick += new System.Windows.Forms.MouseEventHandler(this.OperationProgressNotifyWidget_Click);
|
||||
//
|
||||
// contextMenuStrip1
|
||||
//
|
||||
this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.cancelToolStripMenuItem});
|
||||
this.contextMenuStrip1.Name = "contextMenuStrip1";
|
||||
resources.ApplyResources(this.contextMenuStrip1, "contextMenuStrip1");
|
||||
//
|
||||
// cancelToolStripMenuItem
|
||||
//
|
||||
this.cancelToolStripMenuItem.Name = "cancelToolStripMenuItem";
|
||||
resources.ApplyResources(this.cancelToolStripMenuItem, "cancelToolStripMenuItem");
|
||||
this.cancelToolStripMenuItem.Click += new System.EventHandler(this.cancelToolStripMenuItem_Click);
|
||||
//
|
||||
// progressBar
|
||||
//
|
||||
resources.ApplyResources(this.progressBar, "progressBar");
|
||||
this.progressBar.MarqueeAnimationSpeed = 50;
|
||||
this.progressBar.Name = "progressBar";
|
||||
this.progressBar.Style = System.Windows.Forms.ProgressBarStyle.Continuous;
|
||||
this.progressBar.MouseClick += new System.Windows.Forms.MouseEventHandler(this.OperationProgressNotifyWidget_Click);
|
||||
//
|
||||
// lblNumber
|
||||
//
|
||||
resources.ApplyResources(this.lblNumber, "lblNumber");
|
||||
this.lblNumber.Name = "lblNumber";
|
||||
//
|
||||
// OperationProgressNotifyWidget
|
||||
//
|
||||
resources.ApplyResources(this, "$this");
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(234)))), ((int)(((byte)(234)))), ((int)(((byte)(234)))));
|
||||
this.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
|
||||
this.ContextMenuStrip = this.contextMenuStrip1;
|
||||
this.Controls.Add(this.lblNumber);
|
||||
this.Controls.Add(this.progressBar);
|
||||
this.Controls.Add(this.lblTitle);
|
||||
this.Name = "OperationProgressNotifyWidget";
|
||||
this.MouseClick += new System.Windows.Forms.MouseEventHandler(this.OperationProgressNotifyWidget_Click);
|
||||
this.contextMenuStrip1.ResumeLayout(false);
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
protected System.Windows.Forms.Label lblTitle;
|
||||
private System.Windows.Forms.ContextMenuStrip contextMenuStrip1;
|
||||
private System.Windows.Forms.ToolStripMenuItem cancelToolStripMenuItem;
|
||||
private System.Windows.Forms.ProgressBar progressBar;
|
||||
private System.Windows.Forms.Label lblNumber;
|
||||
}
|
||||
}
|
@ -1,74 +0,0 @@
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace NAPS2.WinForms;
|
||||
|
||||
public partial class OperationProgressNotifyWidget : NotifyWidgetBase
|
||||
{
|
||||
private readonly OperationProgress _operationProgress;
|
||||
private readonly IOperation _op;
|
||||
|
||||
public OperationProgressNotifyWidget(OperationProgress operationProgress, IOperation op)
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
_operationProgress = operationProgress;
|
||||
_op = op;
|
||||
|
||||
cancelToolStripMenuItem.Text = UiStrings.Cancel;
|
||||
cancelToolStripMenuItem.Visible = op.AllowCancel;
|
||||
op.StatusChanged += Op_StatusChanged;
|
||||
op.Finished += Op_Finished;
|
||||
}
|
||||
|
||||
public override void ShowNotify() => DisplayProgress();
|
||||
|
||||
public override NotifyWidgetBase Clone() => new OperationProgressNotifyWidget(_operationProgress, _op);
|
||||
|
||||
private void DisplayProgress()
|
||||
{
|
||||
var lblNumberRight = lblNumber.Right;
|
||||
WinFormsOperationProgress.RenderStatus(_op, lblTitle, lblNumber, progressBar);
|
||||
if (_op.Status?.IndeterminateProgress != true)
|
||||
{
|
||||
// Don't display the number if the progress bar is precise
|
||||
// Otherwise, the widget will be too cluttered
|
||||
// The number is only shown for OcrOperation at the moment
|
||||
lblNumber.Text = "";
|
||||
}
|
||||
lblNumber.Left = lblNumberRight - lblNumber.Width;
|
||||
Width = Math.Max(Width, lblTitle.Width + lblNumber.Width + 22);
|
||||
Height = Math.Max(Height, lblTitle.Height + 35);
|
||||
}
|
||||
|
||||
private void DoHideNotify()
|
||||
{
|
||||
_op.StatusChanged -= Op_StatusChanged;
|
||||
_op.Finished -= Op_Finished;
|
||||
InvokeHideNotify();
|
||||
}
|
||||
|
||||
private void Op_StatusChanged(object? sender, EventArgs e)
|
||||
{
|
||||
Invoker.Current.Invoke(DisplayProgress);
|
||||
}
|
||||
|
||||
private void Op_Finished(object? sender, EventArgs e)
|
||||
{
|
||||
DoHideNotify();
|
||||
}
|
||||
|
||||
private void cancelToolStripMenuItem_Click(object? sender, EventArgs e)
|
||||
{
|
||||
_op.Cancel();
|
||||
cancelToolStripMenuItem.Enabled = false;
|
||||
}
|
||||
|
||||
private void OperationProgressNotifyWidget_Click(object? sender, MouseEventArgs e)
|
||||
{
|
||||
if (e.Button == MouseButtons.Left)
|
||||
{
|
||||
DoHideNotify();
|
||||
_operationProgress.ShowModalProgress(_op);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,246 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<assembly alias="mscorlib" name="mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||
<data name="lblTitle.AutoSize" type="System.Boolean, mscorlib">
|
||||
<value>True</value>
|
||||
</data>
|
||||
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||
<data name="lblTitle.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms">
|
||||
<value>NoControl</value>
|
||||
</data>
|
||||
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<data name="lblTitle.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>7, 8</value>
|
||||
</data>
|
||||
<data name="lblTitle.MaximumSize" type="System.Drawing.Size, System.Drawing">
|
||||
<value>200, 0</value>
|
||||
</data>
|
||||
<data name="lblTitle.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>0, 13</value>
|
||||
</data>
|
||||
<data name="lblTitle.TabIndex" type="System.Int32, mscorlib">
|
||||
<value>0</value>
|
||||
</data>
|
||||
<data name=">>lblTitle.Name" xml:space="preserve">
|
||||
<value>lblTitle</value>
|
||||
</data>
|
||||
<data name=">>lblTitle.Type" xml:space="preserve">
|
||||
<value>System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name=">>lblTitle.Parent" xml:space="preserve">
|
||||
<value>$this</value>
|
||||
</data>
|
||||
<data name=">>lblTitle.ZOrder" xml:space="preserve">
|
||||
<value>3</value>
|
||||
</data>
|
||||
<metadata name="contextMenuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>123, 17</value>
|
||||
</metadata>
|
||||
<data name="cancelToolStripMenuItem.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>110, 22</value>
|
||||
</data>
|
||||
<data name="cancelToolStripMenuItem.Text" xml:space="preserve">
|
||||
<value>Cancel</value>
|
||||
</data>
|
||||
<data name="contextMenuStrip1.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>111, 26</value>
|
||||
</data>
|
||||
<data name=">>contextMenuStrip1.Name" xml:space="preserve">
|
||||
<value>contextMenuStrip1</value>
|
||||
</data>
|
||||
<data name=">>contextMenuStrip1.Type" xml:space="preserve">
|
||||
<value>System.Windows.Forms.ContextMenuStrip, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name="progressBar.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
|
||||
<value>Bottom, Left, Right</value>
|
||||
</data>
|
||||
<data name="progressBar.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>7, 26</value>
|
||||
</data>
|
||||
<data name="progressBar.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>138, 11</value>
|
||||
</data>
|
||||
<data name="progressBar.TabIndex" type="System.Int32, mscorlib">
|
||||
<value>3</value>
|
||||
</data>
|
||||
<data name=">>progressBar.Name" xml:space="preserve">
|
||||
<value>progressBar</value>
|
||||
</data>
|
||||
<data name=">>progressBar.Type" xml:space="preserve">
|
||||
<value>System.Windows.Forms.ProgressBar, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name=">>progressBar.Parent" xml:space="preserve">
|
||||
<value>$this</value>
|
||||
</data>
|
||||
<data name=">>progressBar.ZOrder" xml:space="preserve">
|
||||
<value>2</value>
|
||||
</data>
|
||||
<data name="lblNumber.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
|
||||
<value>Top, Right</value>
|
||||
</data>
|
||||
<data name="lblNumber.AutoSize" type="System.Boolean, mscorlib">
|
||||
<value>True</value>
|
||||
</data>
|
||||
<data name="lblNumber.Location" type="System.Drawing.Point, System.Drawing">
|
||||
<value>145, 8</value>
|
||||
</data>
|
||||
<data name="lblNumber.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>0, 13</value>
|
||||
</data>
|
||||
<data name="lblNumber.TabIndex" type="System.Int32, mscorlib">
|
||||
<value>4</value>
|
||||
</data>
|
||||
<data name="lblNumber.TextAlign" type="System.Drawing.ContentAlignment, System.Drawing">
|
||||
<value>TopRight</value>
|
||||
</data>
|
||||
<data name=">>lblNumber.Name" xml:space="preserve">
|
||||
<value>lblNumber</value>
|
||||
</data>
|
||||
<data name=">>lblNumber.Type" xml:space="preserve">
|
||||
<value>System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name=">>lblNumber.Parent" xml:space="preserve">
|
||||
<value>$this</value>
|
||||
</data>
|
||||
<data name=">>lblNumber.ZOrder" xml:space="preserve">
|
||||
<value>0</value>
|
||||
</data>
|
||||
<metadata name="$this.Localizable" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>True</value>
|
||||
</metadata>
|
||||
<data name="$this.AutoScaleDimensions" type="System.Drawing.SizeF, System.Drawing">
|
||||
<value>6, 13</value>
|
||||
</data>
|
||||
<data name="$this.Size" type="System.Drawing.Size, System.Drawing">
|
||||
<value>150, 40</value>
|
||||
</data>
|
||||
<data name=">>cancelToolStripMenuItem.Name" xml:space="preserve">
|
||||
<value>cancelToolStripMenuItem</value>
|
||||
</data>
|
||||
<data name=">>cancelToolStripMenuItem.Type" xml:space="preserve">
|
||||
<value>System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name=">>$this.Name" xml:space="preserve">
|
||||
<value>OperationProgressNotifyWidget</value>
|
||||
</data>
|
||||
<data name=">>$this.Type" xml:space="preserve">
|
||||
<value>NAPS2.WinForms.NotifyWidgetBase, NAPS2.Core, Version=6.0.1.27018, Culture=neutral, PublicKeyToken=null</value>
|
||||
</data>
|
||||
</root>
|
@ -1,14 +0,0 @@
|
||||
namespace NAPS2.WinForms;
|
||||
|
||||
public class PdfSavedNotifyWidget : NotifyWidget
|
||||
{
|
||||
private readonly string _path;
|
||||
|
||||
public PdfSavedNotifyWidget(string path)
|
||||
: base(MiscResources.PdfSaved, Path.GetFileName(path), path, Path.GetDirectoryName(path))
|
||||
{
|
||||
_path = path;
|
||||
}
|
||||
|
||||
public override NotifyWidgetBase Clone() => new PdfSavedNotifyWidget(_path);
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
using System.Windows.Forms;
|
||||
using NAPS2.Update;
|
||||
|
||||
namespace NAPS2.WinForms;
|
||||
|
||||
public class UpdateAvailableNotifyWidget : NotifyWidget
|
||||
{
|
||||
private readonly IUpdateChecker _updateChecker;
|
||||
private readonly UpdateInfo _update;
|
||||
|
||||
public UpdateAvailableNotifyWidget(IUpdateChecker updateChecker, UpdateInfo update)
|
||||
: base(MiscResources.UpdateAvailable, string.Format(MiscResources.Install, update.Name), null, null)
|
||||
{
|
||||
_updateChecker = updateChecker;
|
||||
_update = update;
|
||||
|
||||
hideTimer.Interval = 60 * 1000;
|
||||
}
|
||||
|
||||
public override NotifyWidgetBase Clone() => new UpdateAvailableNotifyWidget(_updateChecker, _update);
|
||||
|
||||
protected override void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
|
||||
{
|
||||
_updateChecker.StartUpdate(_update);
|
||||
DoHideNotify();
|
||||
}
|
||||
}
|
@ -1,132 +0,0 @@
|
||||
using System.Collections.Immutable;
|
||||
using System.Windows.Forms;
|
||||
using NAPS2.EtoForms;
|
||||
using NAPS2.EtoForms.Ui;
|
||||
|
||||
namespace NAPS2.WinForms;
|
||||
|
||||
public class WinFormsOperationProgress : OperationProgress
|
||||
{
|
||||
private readonly IFormFactory _formFactory;
|
||||
private readonly INotificationManager _notificationManager;
|
||||
private readonly Naps2Config _config;
|
||||
|
||||
private readonly HashSet<IOperation> _activeOperations = new HashSet<IOperation>();
|
||||
|
||||
public WinFormsOperationProgress(IFormFactory formFactory, INotificationManager notificationManager, Naps2Config config)
|
||||
{
|
||||
_formFactory = formFactory;
|
||||
_notificationManager = notificationManager;
|
||||
_config = config;
|
||||
}
|
||||
|
||||
public override void Attach(IOperation op)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
if (!_activeOperations.Contains(op))
|
||||
{
|
||||
_activeOperations.Add(op);
|
||||
op.Finished += (sender, args) => _activeOperations.Remove(op);
|
||||
if (op.IsFinished) _activeOperations.Remove(op);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void ShowProgress(IOperation op)
|
||||
{
|
||||
if (_config.Get(c => c.BackgroundOperations).Contains(op.GetType().Name))
|
||||
{
|
||||
ShowBackgroundProgress(op);
|
||||
}
|
||||
else
|
||||
{
|
||||
ShowModalProgress(op);
|
||||
}
|
||||
}
|
||||
|
||||
public override void ShowModalProgress(IOperation op)
|
||||
{
|
||||
Attach(op);
|
||||
|
||||
var bgOps = _config.Get(c => c.BackgroundOperations) ?? ImmutableHashSet<string>.Empty;
|
||||
bgOps = bgOps.Remove(op.GetType().Name);
|
||||
_config.User.Set(c => c.BackgroundOperations, bgOps);
|
||||
|
||||
if (!op.IsFinished)
|
||||
{
|
||||
var form = _formFactory.Create<ProgressForm>();
|
||||
form.Operation = op;
|
||||
form.ShowModal();
|
||||
}
|
||||
|
||||
if (!op.IsFinished)
|
||||
{
|
||||
ShowBackgroundProgress(op);
|
||||
}
|
||||
}
|
||||
|
||||
public override void ShowBackgroundProgress(IOperation op)
|
||||
{
|
||||
Attach(op);
|
||||
|
||||
var bgOps = _config.Get(c => c.BackgroundOperations) ?? ImmutableHashSet<string>.Empty;
|
||||
bgOps = bgOps.Add(op.GetType().Name);
|
||||
_config.User.Set(c => c.BackgroundOperations, bgOps);
|
||||
|
||||
if (!op.IsFinished)
|
||||
{
|
||||
Invoker.Current.Invoke(() => _notificationManager.OperationProgress(this, op));
|
||||
}
|
||||
}
|
||||
|
||||
public static void RenderStatus(IOperation op, Label textLabel, Label numberLabel, ProgressBar progressBar)
|
||||
{
|
||||
var status = op.Status ?? new OperationStatus();
|
||||
textLabel.Text = status.StatusText;
|
||||
progressBar.Style = status.MaxProgress == 1 || status.IndeterminateProgress
|
||||
? ProgressBarStyle.Marquee
|
||||
: ProgressBarStyle.Continuous;
|
||||
if (status.MaxProgress == 1 || status.ProgressType == OperationProgressType.None)
|
||||
{
|
||||
numberLabel.Text = "";
|
||||
}
|
||||
else if (status.MaxProgress == 0)
|
||||
{
|
||||
numberLabel.Text = "";
|
||||
progressBar.Maximum = 1;
|
||||
progressBar.Value = 0;
|
||||
}
|
||||
else if (status.ProgressType == OperationProgressType.BarOnly)
|
||||
{
|
||||
numberLabel.Text = "";
|
||||
progressBar.Maximum = status.MaxProgress;
|
||||
progressBar.Value = status.CurrentProgress;
|
||||
}
|
||||
else
|
||||
{
|
||||
numberLabel.Text = status.ProgressType == OperationProgressType.MB
|
||||
? string.Format(MiscResources.SizeProgress, (status.CurrentProgress / 1000000.0).ToString("f1"), (status.MaxProgress / 1000000.0).ToString("f1"))
|
||||
: string.Format(MiscResources.ProgressFormat, status.CurrentProgress, status.MaxProgress);
|
||||
progressBar.Maximum = status.MaxProgress;
|
||||
progressBar.Value = status.CurrentProgress;
|
||||
}
|
||||
// Force the progress bar to render immediately
|
||||
if (progressBar.Value < progressBar.Maximum)
|
||||
{
|
||||
progressBar.Value += 1;
|
||||
progressBar.Value -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
public override List<IOperation> ActiveOperations
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_activeOperations)
|
||||
{
|
||||
return _activeOperations.ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
using System.Threading;
|
||||
using Eto.Forms;
|
||||
using NAPS2.EtoForms.Notifications;
|
||||
using NAPS2.EtoForms.Widgets;
|
||||
using NAPS2.ImportExport;
|
||||
using NAPS2.ImportExport.Images;
|
||||
using NAPS2.Platform.Windows;
|
||||
@ -22,7 +24,7 @@ public class DesktopController
|
||||
private readonly IOperationFactory _operationFactory;
|
||||
private readonly StillImage _stillImage;
|
||||
private readonly IUpdateChecker _updateChecker;
|
||||
private readonly INotificationManager _notify;
|
||||
private readonly Notify _notify;
|
||||
private readonly ImageTransfer _imageTransfer;
|
||||
private readonly ImageClipboard _imageClipboard;
|
||||
private readonly ImageListActions _imageListActions;
|
||||
@ -41,7 +43,7 @@ public class DesktopController
|
||||
RecoveryStorageManager recoveryStorageManager, ThumbnailController thumbnailController,
|
||||
OperationProgress operationProgress, Naps2Config config, IOperationFactory operationFactory,
|
||||
StillImage stillImage,
|
||||
IUpdateChecker updateChecker, INotificationManager notify, ImageTransfer imageTransfer,
|
||||
IUpdateChecker updateChecker, Notify notify, ImageTransfer imageTransfer,
|
||||
ImageClipboard imageClipboard, ImageListActions imageListActions,
|
||||
DialogHelper dialogHelper,
|
||||
DesktopImagesController desktopImagesController, IDesktopScanController desktopScanController,
|
||||
|
@ -1,3 +1,5 @@
|
||||
using NAPS2.EtoForms.Notifications;
|
||||
using NAPS2.EtoForms.Widgets;
|
||||
using NAPS2.ImportExport;
|
||||
|
||||
namespace NAPS2.EtoForms.Desktop;
|
||||
@ -10,11 +12,11 @@ public class ImageListActions
|
||||
private readonly Naps2Config _config;
|
||||
private readonly ThumbnailController _thumbnailController;
|
||||
private readonly IExportController _exportController;
|
||||
private readonly INotificationManager _notify;
|
||||
private readonly Notify _notify;
|
||||
|
||||
public ImageListActions(UiImageList imageList, IOperationFactory operationFactory,
|
||||
OperationProgress operationProgress, Naps2Config config, ThumbnailController thumbnailController,
|
||||
IExportController exportController, INotificationManager notify)
|
||||
IExportController exportController, Notify notify)
|
||||
{
|
||||
_imageList = imageList;
|
||||
_operationFactory = operationFactory;
|
||||
|
@ -1,20 +1,22 @@
|
||||
using Eto.Forms;
|
||||
using NAPS2.EtoForms.Notifications;
|
||||
using NAPS2.EtoForms.Ui;
|
||||
using NAPS2.EtoForms.Widgets;
|
||||
|
||||
namespace NAPS2.EtoForms;
|
||||
|
||||
public class EtoOperationProgress : OperationProgress
|
||||
{
|
||||
private readonly IFormFactory _formFactory;
|
||||
private readonly INotificationManager _notificationManager;
|
||||
private readonly Notify _notify;
|
||||
private readonly Naps2Config _config;
|
||||
|
||||
private readonly HashSet<IOperation> _activeOperations = new();
|
||||
|
||||
public EtoOperationProgress(IFormFactory formFactory, INotificationManager notificationManager, Naps2Config config)
|
||||
public EtoOperationProgress(IFormFactory formFactory, Notify notify, Naps2Config config)
|
||||
{
|
||||
_formFactory = formFactory;
|
||||
_notificationManager = notificationManager;
|
||||
_notify = notify;
|
||||
_config = config;
|
||||
}
|
||||
|
||||
@ -78,7 +80,7 @@ public class EtoOperationProgress : OperationProgress
|
||||
|
||||
if (!op.IsFinished)
|
||||
{
|
||||
Invoker.Current.Invoke(() => _notificationManager.OperationProgress(this, op));
|
||||
Invoker.Current.Invoke(() => _notify.OperationProgress(this, op));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,11 +0,0 @@
|
||||
using NAPS2.Update;
|
||||
|
||||
namespace NAPS2.EtoForms;
|
||||
|
||||
public interface INotificationManager : ISaveNotify
|
||||
{
|
||||
void DonatePrompt();
|
||||
void OperationProgress(OperationProgress opModalProgress, IOperation op);
|
||||
void UpdateAvailable(IUpdateChecker updateChecker, UpdateInfo update);
|
||||
void Rebuild();
|
||||
}
|
60
NAPS2.Lib/EtoForms/Notifications/CloseButton.cs
Normal file
60
NAPS2.Lib/EtoForms/Notifications/CloseButton.cs
Normal file
@ -0,0 +1,60 @@
|
||||
using Eto.Drawing;
|
||||
using Eto.Forms;
|
||||
|
||||
namespace NAPS2.EtoForms.Notifications;
|
||||
|
||||
public class CloseButton : Drawable
|
||||
{
|
||||
private const int CLOSE_BUTTON_PADDING = 5;
|
||||
private static readonly Pen CloseButtonPen = new(new Color(0.7f, 0.7f, 0.7f), 3);
|
||||
private static readonly Color DefaultBackground = new(0.95f, 0.95f, 0.95f);
|
||||
private static readonly Color ActiveBackground = new(0.8f, 0.8f, 0.8f);
|
||||
private static readonly Color HoverBackground = new(0.87f, 0.87f, 0.87f);
|
||||
|
||||
private bool _hover;
|
||||
private bool _active;
|
||||
|
||||
public CloseButton()
|
||||
{
|
||||
Cursor = Cursors.Pointer;
|
||||
Paint += OnPaint;
|
||||
MouseEnter += (_, _) =>
|
||||
{
|
||||
_hover = true;
|
||||
Invalidate();
|
||||
};
|
||||
MouseLeave += (_, _) =>
|
||||
{
|
||||
_hover = false;
|
||||
Invalidate();
|
||||
};
|
||||
MouseDown += (_, _) =>
|
||||
{
|
||||
_active = true;
|
||||
Invalidate();
|
||||
};
|
||||
MouseUp += (_, _) =>
|
||||
{
|
||||
var actualHover = new Rectangle(0, 0, Width, Height).Contains(Point.Round(PointFromScreen(Mouse.Position)));
|
||||
if (_active && _hover && actualHover)
|
||||
{
|
||||
Click?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
_active = false;
|
||||
Invalidate();
|
||||
};
|
||||
}
|
||||
|
||||
private void OnPaint(object? sender, PaintEventArgs e)
|
||||
{
|
||||
var clearColor = _active && _hover ? ActiveBackground : _hover ? HoverBackground : DefaultBackground;
|
||||
e.Graphics.Clear(clearColor);
|
||||
var w = e.ClipRectangle.Width;
|
||||
var h = e.ClipRectangle.Height;
|
||||
var p = CLOSE_BUTTON_PADDING;
|
||||
e.Graphics.DrawLine(CloseButtonPen, p - 1, p - 1, w - p, h - p);
|
||||
e.Graphics.DrawLine(CloseButtonPen, w - p, p - 1, p - 1, h - p);
|
||||
}
|
||||
|
||||
public event EventHandler? Click;
|
||||
}
|
17
NAPS2.Lib/EtoForms/Notifications/DonateNotification.cs
Normal file
17
NAPS2.Lib/EtoForms/Notifications/DonateNotification.cs
Normal file
@ -0,0 +1,17 @@
|
||||
namespace NAPS2.EtoForms.Notifications;
|
||||
|
||||
public class DonateNotification : LinkNotification
|
||||
{
|
||||
private const string DONATE_URL = "https://www.naps2.com/donate";
|
||||
|
||||
public DonateNotification() : base(MiscResources.DonatePrompt, MiscResources.Donate, DONATE_URL, null)
|
||||
{
|
||||
HideTimeout = HIDE_LONG;
|
||||
}
|
||||
|
||||
protected override void LinkClick()
|
||||
{
|
||||
base.LinkClick();
|
||||
Manager!.Hide(this);
|
||||
}
|
||||
}
|
60
NAPS2.Lib/EtoForms/Notifications/LinkNotification.cs
Normal file
60
NAPS2.Lib/EtoForms/Notifications/LinkNotification.cs
Normal file
@ -0,0 +1,60 @@
|
||||
using Eto.Drawing;
|
||||
using Eto.Forms;
|
||||
using NAPS2.EtoForms.Layout;
|
||||
|
||||
namespace NAPS2.EtoForms.Notifications;
|
||||
|
||||
public class LinkNotification : Notification
|
||||
{
|
||||
private readonly string? _linkTarget;
|
||||
private readonly string? _folderTarget;
|
||||
|
||||
private readonly Label _label = new() { BackgroundColor = BackgroundColor };
|
||||
private readonly LinkButton _link = new() { BackgroundColor = BackgroundColor };
|
||||
private readonly ContextMenu _contextMenu = new();
|
||||
|
||||
protected LinkNotification(string title, string linkLabel, string? linkTarget, string? folderTarget)
|
||||
{
|
||||
_label.Text = title;
|
||||
_label.Font = new Font(_label.Font.Family, _label.Font.Size, FontStyle.Bold);
|
||||
_link.Text = linkLabel;
|
||||
_linkTarget = linkTarget;
|
||||
_folderTarget = folderTarget;
|
||||
|
||||
if (_folderTarget != null)
|
||||
{
|
||||
_contextMenu.Items.Add(new ActionCommand(OpenFolder) { Text = UiStrings.OpenFolder });
|
||||
}
|
||||
|
||||
_link.Click += (_, _) => LinkClick();
|
||||
_link.MouseUp += (_, args) =>
|
||||
{
|
||||
if (args.Buttons == MouseButtons.Alternate)
|
||||
{
|
||||
LinkRightClick();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected override LayoutElement PrimaryContent => _label;
|
||||
|
||||
protected override LayoutElement SecondaryContent => _link;
|
||||
|
||||
protected virtual void LinkClick()
|
||||
{
|
||||
ProcessHelper.OpenFile(_linkTarget!);
|
||||
}
|
||||
|
||||
protected virtual void LinkRightClick()
|
||||
{
|
||||
if (_folderTarget != null)
|
||||
{
|
||||
_contextMenu.Show(_link);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void OpenFolder()
|
||||
{
|
||||
ProcessHelper.OpenFolder(_folderTarget!);
|
||||
}
|
||||
}
|
121
NAPS2.Lib/EtoForms/Notifications/Notification.cs
Normal file
121
NAPS2.Lib/EtoForms/Notifications/Notification.cs
Normal file
@ -0,0 +1,121 @@
|
||||
using System.Threading;
|
||||
using Eto.Drawing;
|
||||
using Eto.Forms;
|
||||
using NAPS2.EtoForms.Layout;
|
||||
|
||||
namespace NAPS2.EtoForms.Notifications;
|
||||
|
||||
public abstract class Notification : IDisposable
|
||||
{
|
||||
// TODO: Get from color scheme
|
||||
protected static readonly Color BackgroundColor = new(0.95f, 0.95f, 0.95f);
|
||||
private static readonly Color BorderColor = new(0.7f, 0.7f, 0.7f);
|
||||
private const int BORDER_RADIUS = 7;
|
||||
private const int CLOSE_BUTTON_SIZE = 18;
|
||||
|
||||
protected const int HIDE_LONG = 60 * 1000;
|
||||
protected const int HIDE_SHORT = 5 * 1000;
|
||||
|
||||
protected int HideTimeout { get; set; }
|
||||
|
||||
protected bool ShowClose { get; set; } = true;
|
||||
|
||||
public NotificationManager? Manager { get; set; }
|
||||
|
||||
protected abstract LayoutElement PrimaryContent { get; }
|
||||
|
||||
protected abstract LayoutElement SecondaryContent { get; }
|
||||
|
||||
public LayoutElement CreateView()
|
||||
{
|
||||
var drawable = new Drawable();
|
||||
drawable.Paint += DrawableOnPaint;
|
||||
var closeButton = new CloseButton();
|
||||
closeButton.Click += (_, _) => Manager!.Hide(this);
|
||||
drawable.MouseUp += (_, _) => NotificationClicked();
|
||||
drawable.Load += (_, _) => SetUpHideTimeout(drawable);
|
||||
return L.Overlay(
|
||||
drawable,
|
||||
L.Column(
|
||||
L.Row(
|
||||
PrimaryContent,
|
||||
ShowClose ? C.Spacer().Width(CLOSE_BUTTON_SIZE) : C.None()),
|
||||
SecondaryContent
|
||||
).Padding(10, 8, 10, 8),
|
||||
ShowClose
|
||||
? L.Column(
|
||||
L.Row(
|
||||
C.Filler(),
|
||||
closeButton.Size(CLOSE_BUTTON_SIZE, CLOSE_BUTTON_SIZE)
|
||||
),
|
||||
C.Filler()
|
||||
).Padding(5, 5, 5, 5)
|
||||
: C.None());
|
||||
}
|
||||
|
||||
private void SetUpHideTimeout(Control control)
|
||||
{
|
||||
Timer CreateTimer()
|
||||
{
|
||||
return new Timer(_ =>
|
||||
{
|
||||
Manager!.Hide(this);
|
||||
}, null, HideTimeout, -1);
|
||||
}
|
||||
|
||||
if (HideTimeout > 0)
|
||||
{
|
||||
// Don't start the timer until the user is interacting with the window
|
||||
void StartTimer(object? sender, EventArgs e)
|
||||
{
|
||||
Manager!.TimersStarting -= StartTimer;
|
||||
control.ParentWindow.MouseMove -= StartTimer;
|
||||
var timer = CreateTimer();
|
||||
control.MouseEnter += (_, _) => timer.Dispose();
|
||||
control.MouseLeave += (_, _) => timer = CreateTimer();
|
||||
}
|
||||
Manager!.TimersStarting += StartTimer;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void NotificationClicked()
|
||||
{
|
||||
}
|
||||
|
||||
private static void DrawableOnPaint(object? sender, PaintEventArgs e)
|
||||
{
|
||||
var w = e.ClipRectangle.Width;
|
||||
var h = e.ClipRectangle.Height;
|
||||
var r = BORDER_RADIUS;
|
||||
var d = r * 2;
|
||||
var q = r / 2;
|
||||
// TODO: Color scheme background
|
||||
e.Graphics.Clear(Colors.White);
|
||||
// Corners
|
||||
e.Graphics.FillEllipse(BackgroundColor, -1, -1, d, d);
|
||||
e.Graphics.FillEllipse(BackgroundColor, w - d, -1, d, d);
|
||||
e.Graphics.FillEllipse(BackgroundColor, -1, h - d, d, d);
|
||||
e.Graphics.FillEllipse(BackgroundColor, w - d, h - d, d, d);
|
||||
// Corner borders
|
||||
e.Graphics.DrawEllipse(BorderColor, -1, -1, d, d);
|
||||
e.Graphics.DrawEllipse(BorderColor, w - d, -1, d, d);
|
||||
e.Graphics.DrawEllipse(BorderColor, -1, h - d, d, d);
|
||||
e.Graphics.DrawEllipse(BorderColor, w - d, h - d, d, d);
|
||||
// Middle
|
||||
e.Graphics.FillRectangle(BackgroundColor, r, r, w - d, h - d);
|
||||
// Sides
|
||||
e.Graphics.FillRectangle(BackgroundColor, 0, r, r, h - d);
|
||||
e.Graphics.FillRectangle(BackgroundColor, r, 0, w - d, r);
|
||||
e.Graphics.FillRectangle(BackgroundColor, w - r, r, r, h - d);
|
||||
e.Graphics.FillRectangle(BackgroundColor, r, h - r, w - d, r);
|
||||
// Side borders
|
||||
e.Graphics.DrawLine(BorderColor, 0, q, 0, h - q);
|
||||
e.Graphics.DrawLine(BorderColor, q, 0, w - q, 0);
|
||||
e.Graphics.DrawLine(BorderColor, w - 1, q, w - 1, h - q);
|
||||
e.Graphics.DrawLine(BorderColor, q, h - 1, w - q, h - 1);
|
||||
}
|
||||
|
||||
public virtual void Dispose()
|
||||
{
|
||||
}
|
||||
}
|
36
NAPS2.Lib/EtoForms/Notifications/NotificationManager.cs
Normal file
36
NAPS2.Lib/EtoForms/Notifications/NotificationManager.cs
Normal file
@ -0,0 +1,36 @@
|
||||
using NAPS2.EtoForms.Layout;
|
||||
|
||||
namespace NAPS2.EtoForms.Notifications;
|
||||
|
||||
public class NotificationManager
|
||||
{
|
||||
private readonly Dictionary<Notification, LayoutElement> _items = new();
|
||||
|
||||
public LayoutColumn Column { get; } = L.Column(C.Filler()).Spacing(20).Padding(15);
|
||||
|
||||
public event EventHandler? Updated;
|
||||
|
||||
public event EventHandler? TimersStarting;
|
||||
|
||||
public void Show(Notification notification)
|
||||
{
|
||||
notification.Manager = this;
|
||||
var item = notification.CreateView();
|
||||
_items[notification] = item;
|
||||
Column.Children.Add(item);
|
||||
Updated?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
public void Hide(Notification notification)
|
||||
{
|
||||
if (!_items.ContainsKey(notification)) return;
|
||||
Column.Children.Remove(_items[notification]);
|
||||
Updated?.Invoke(this, EventArgs.Empty);
|
||||
notification.Dispose();
|
||||
}
|
||||
|
||||
public void StartTimers()
|
||||
{
|
||||
TimersStarting?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
41
NAPS2.Lib/EtoForms/Notifications/Notify.cs
Normal file
41
NAPS2.Lib/EtoForms/Notifications/Notify.cs
Normal file
@ -0,0 +1,41 @@
|
||||
using NAPS2.Update;
|
||||
|
||||
namespace NAPS2.EtoForms.Notifications;
|
||||
|
||||
public class Notify : ISaveNotify
|
||||
{
|
||||
private readonly NotificationManager _notificationManager;
|
||||
|
||||
public Notify(NotificationManager notificationManager)
|
||||
{
|
||||
_notificationManager = notificationManager;
|
||||
}
|
||||
|
||||
public void PdfSaved(string path)
|
||||
{
|
||||
_notificationManager.Show(new SaveNotification(MiscResources.PdfSaved, path));
|
||||
}
|
||||
|
||||
public void ImagesSaved(int imageCount, string path)
|
||||
{
|
||||
var title = imageCount == 1
|
||||
? MiscResources.ImageSaved
|
||||
: string.Format(MiscResources.ImagesSaved, imageCount);
|
||||
_notificationManager.Show(new SaveNotification(title, path));
|
||||
}
|
||||
|
||||
public void DonatePrompt()
|
||||
{
|
||||
_notificationManager.Show(new DonateNotification());
|
||||
}
|
||||
|
||||
public void OperationProgress(OperationProgress progress, IOperation op)
|
||||
{
|
||||
_notificationManager.Show(new ProgressNotification(progress, op));
|
||||
}
|
||||
|
||||
public void UpdateAvailable(IUpdateChecker updateChecker, UpdateInfo update)
|
||||
{
|
||||
_notificationManager.Show(new UpdateNotification(updateChecker, update));
|
||||
}
|
||||
}
|
72
NAPS2.Lib/EtoForms/Notifications/ProgressNotification.cs
Normal file
72
NAPS2.Lib/EtoForms/Notifications/ProgressNotification.cs
Normal file
@ -0,0 +1,72 @@
|
||||
using Eto.Forms;
|
||||
using NAPS2.EtoForms.Layout;
|
||||
|
||||
namespace NAPS2.EtoForms.Notifications;
|
||||
|
||||
public class ProgressNotification : Notification
|
||||
{
|
||||
private readonly OperationProgress _operationProgress;
|
||||
private readonly IOperation _op;
|
||||
|
||||
private readonly Label _textLabel = new();
|
||||
private readonly Label _numberLabel = new();
|
||||
private readonly ProgressBar _progressBar = new();
|
||||
private readonly LayoutVisibility _numberVis = new(true);
|
||||
|
||||
public ProgressNotification(OperationProgress operationProgress, IOperation op)
|
||||
{
|
||||
_operationProgress = operationProgress;
|
||||
_op = op;
|
||||
|
||||
ShowClose = false;
|
||||
op.StatusChanged += OnStatusChanged;
|
||||
op.Finished += OnFinished;
|
||||
if (op.IsFinished)
|
||||
{
|
||||
Invoker.Current.Invoke(() => Manager?.Hide(this));
|
||||
}
|
||||
_textLabel.MouseUp += (_, _) => NotificationClicked();
|
||||
_numberLabel.MouseUp += (_, _) => NotificationClicked();
|
||||
_progressBar.MouseUp += (_, _) => NotificationClicked();
|
||||
UpdateStatus();
|
||||
}
|
||||
|
||||
private void OnStatusChanged(object? sender, EventArgs eventArgs)
|
||||
{
|
||||
Invoker.Current.Invoke(UpdateStatus);
|
||||
}
|
||||
|
||||
private void OnFinished(object? sender, EventArgs e)
|
||||
{
|
||||
Invoker.Current.Invoke(() => Manager?.Hide(this));
|
||||
}
|
||||
|
||||
private void UpdateStatus()
|
||||
{
|
||||
EtoOperationProgress.RenderStatus(_op, _textLabel, _numberLabel, _progressBar);
|
||||
// Don't display the number if the progress bar is precise
|
||||
// Otherwise, the widget will be too cluttered
|
||||
// The number is only shown for OcrOperation at the moment
|
||||
_numberVis.IsVisible = _op.Status?.IndeterminateProgress == true;
|
||||
}
|
||||
|
||||
protected override void NotificationClicked()
|
||||
{
|
||||
Manager!.Hide(this);
|
||||
_operationProgress.ShowModalProgress(_op);
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
base.Dispose();
|
||||
_op.StatusChanged -= OnStatusChanged;
|
||||
_op.Finished -= OnFinished;
|
||||
}
|
||||
|
||||
protected override LayoutElement PrimaryContent => L.Row(
|
||||
_textLabel,
|
||||
C.Filler().Visible(_numberVis),
|
||||
_numberLabel.Visible(_numberVis));
|
||||
|
||||
protected override LayoutElement SecondaryContent => _progressBar.MaxHeight(10);
|
||||
}
|
10
NAPS2.Lib/EtoForms/Notifications/SaveNotification.cs
Normal file
10
NAPS2.Lib/EtoForms/Notifications/SaveNotification.cs
Normal file
@ -0,0 +1,10 @@
|
||||
namespace NAPS2.EtoForms.Notifications;
|
||||
|
||||
public class SaveNotification : LinkNotification
|
||||
{
|
||||
public SaveNotification(string message, string path)
|
||||
: base(message, Path.GetFileName(path), path, Path.GetDirectoryName(path))
|
||||
{
|
||||
HideTimeout = HIDE_SHORT;
|
||||
}
|
||||
}
|
26
NAPS2.Lib/EtoForms/Notifications/UpdateNotification.cs
Normal file
26
NAPS2.Lib/EtoForms/Notifications/UpdateNotification.cs
Normal file
@ -0,0 +1,26 @@
|
||||
using NAPS2.Update;
|
||||
|
||||
namespace NAPS2.EtoForms.Notifications;
|
||||
|
||||
public class UpdateNotification : LinkNotification
|
||||
{
|
||||
private readonly IUpdateChecker _updateChecker;
|
||||
private readonly UpdateInfo _update;
|
||||
|
||||
public UpdateNotification(IUpdateChecker updateChecker, UpdateInfo update)
|
||||
: base(
|
||||
MiscResources.UpdateAvailable,
|
||||
string.Format(MiscResources.Install, update.Name),
|
||||
null, null)
|
||||
{
|
||||
_updateChecker = updateChecker;
|
||||
_update = update;
|
||||
HideTimeout = HIDE_LONG;
|
||||
}
|
||||
|
||||
protected override void LinkClick()
|
||||
{
|
||||
_updateChecker.StartUpdate(_update);
|
||||
Manager!.Hide(this);
|
||||
}
|
||||
}
|
@ -5,6 +5,7 @@ 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;
|
||||
@ -14,7 +15,7 @@ namespace NAPS2.EtoForms.Ui;
|
||||
public abstract class DesktopForm : EtoFormBase
|
||||
{
|
||||
private readonly DesktopKeyboardShortcuts _keyboardShortcuts;
|
||||
private readonly INotificationManager _notify;
|
||||
private readonly NotificationManager _notificationManager;
|
||||
private readonly CultureHelper _cultureHelper;
|
||||
protected readonly ColorScheme _colorScheme;
|
||||
private readonly IProfileManager _profileManager;
|
||||
@ -37,7 +38,7 @@ public abstract class DesktopForm : EtoFormBase
|
||||
public DesktopForm(
|
||||
Naps2Config config,
|
||||
DesktopKeyboardShortcuts keyboardShortcuts,
|
||||
INotificationManager notify,
|
||||
NotificationManager notificationManager,
|
||||
CultureHelper cultureHelper,
|
||||
ColorScheme colorScheme,
|
||||
IProfileManager profileManager,
|
||||
@ -54,7 +55,7 @@ public abstract class DesktopForm : EtoFormBase
|
||||
DesktopCommands commands) : base(config)
|
||||
{
|
||||
_keyboardShortcuts = keyboardShortcuts;
|
||||
_notify = notify;
|
||||
_notificationManager = notificationManager;
|
||||
_cultureHelper = cultureHelper;
|
||||
_colorScheme = colorScheme;
|
||||
_profileManager = profileManager;
|
||||
@ -95,6 +96,7 @@ public abstract class DesktopForm : EtoFormBase
|
||||
KeyDown += OnKeyDown;
|
||||
_listView.Control.KeyDown += OnKeyDown;
|
||||
_listView.Control.MouseWheel += ListViewMouseWheel;
|
||||
_listView.Control.MouseMove += ListViewMouseMove;
|
||||
|
||||
//
|
||||
// Shown += FDesktop_Shown;
|
||||
@ -107,6 +109,7 @@ public abstract class DesktopForm : EtoFormBase
|
||||
ImageList.SelectionChanged += ImageList_SelectionChanged;
|
||||
ImageList.ImagesUpdated += ImageList_ImagesUpdated;
|
||||
_profileManager.ProfilesUpdated += ProfileManager_ProfilesUpdated;
|
||||
_notificationManager.Updated += (_, _) => LayoutController.Invalidate();
|
||||
}
|
||||
|
||||
protected override void BuildLayout()
|
||||
@ -121,7 +124,10 @@ public abstract class DesktopForm : EtoFormBase
|
||||
GetMainContent(),
|
||||
L.Column(
|
||||
C.Filler(),
|
||||
L.Row(GetZoomButtons(), C.Filler())
|
||||
L.Row(
|
||||
GetZoomButtons(),
|
||||
C.Filler(),
|
||||
_notificationManager.Column)
|
||||
).Padding(10)
|
||||
);
|
||||
|
||||
@ -382,7 +388,7 @@ public abstract class DesktopForm : EtoFormBase
|
||||
EtoPlatform.Current.ConfigureZoomButton(zoomIn);
|
||||
var zoomOut = C.ImageButton(Commands.ZoomOut);
|
||||
EtoPlatform.Current.ConfigureZoomButton(zoomOut);
|
||||
return L.Row(zoomOut, zoomIn).Spacing(-1);
|
||||
return L.Row(zoomOut.AlignTrailing(), zoomIn.AlignTrailing()).Spacing(-1);
|
||||
}
|
||||
|
||||
private void InitLanguageDropdown()
|
||||
@ -486,6 +492,11 @@ public abstract class DesktopForm : EtoFormBase
|
||||
}
|
||||
}
|
||||
|
||||
private void ListViewMouseMove(object? sender, MouseEventArgs e)
|
||||
{
|
||||
_notificationManager.StartTimers();
|
||||
}
|
||||
|
||||
protected virtual void SetThumbnailSpacing(int thumbnailSize)
|
||||
{
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
using Autofac;
|
||||
using NAPS2.EtoForms;
|
||||
using NAPS2.EtoForms.Desktop;
|
||||
using NAPS2.EtoForms.Notifications;
|
||||
using NAPS2.EtoForms.Widgets;
|
||||
using NAPS2.ImportExport;
|
||||
using NAPS2.Pdf;
|
||||
using NAPS2.Scan;
|
||||
@ -20,7 +22,8 @@ public class GuiModule : Module
|
||||
builder.RegisterType<EtoDialogHelper>().As<DialogHelper>();
|
||||
builder.RegisterType<EtoDevicePrompt>().As<IDevicePrompt>();
|
||||
builder.RegisterType<EtoPdfPasswordProvider>().As<IPdfPasswordProvider>();
|
||||
builder.Register<ISaveNotify>(ctx => ctx.Resolve<INotificationManager>());
|
||||
builder.RegisterType<NotificationManager>().AsSelf().SingleInstance();
|
||||
builder.Register<ISaveNotify>(ctx => ctx.Resolve<Notify>());
|
||||
builder.RegisterType<DesktopController>().AsSelf().SingleInstance();
|
||||
builder.RegisterType<UpdateChecker>().As<IUpdateChecker>();
|
||||
builder.RegisterType<ExportController>().As<IExportController>();
|
||||
|
@ -4,6 +4,18 @@ public static class ProcessHelper
|
||||
{
|
||||
public static void OpenUrl(string url) => Process.Start(new ProcessStartInfo(url) { UseShellExecute = true });
|
||||
|
||||
public static void OpenFile(string file)
|
||||
{
|
||||
Process.Start(new ProcessStartInfo
|
||||
{
|
||||
UseShellExecute = true,
|
||||
FileName = file,
|
||||
Verb = "open"
|
||||
});
|
||||
}
|
||||
|
||||
public static void OpenFolder(string folder) => OpenFile(folder);
|
||||
|
||||
public static bool IsSuccessful(string command, string args, int timeoutMs)
|
||||
{
|
||||
try
|
||||
|
Loading…
Reference in New Issue
Block a user