Skip to content

Commit

Permalink
WIP: New device selection form
Browse files Browse the repository at this point in the history
  • Loading branch information
cyanfish committed Aug 1, 2024
1 parent 401885d commit 95bf090
Show file tree
Hide file tree
Showing 14 changed files with 439 additions and 263 deletions.
3 changes: 3 additions & 0 deletions NAPS2.Lib/Config/CommonConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ public class CommonConfig
[Common]
public bool AlwaysRememberDevice { get; set; }

[Common]
public bool DeviceListAsTextOnly { get; set; }

[Common]
public bool NoUpdatePrompt { get; set; }

Expand Down
46 changes: 9 additions & 37 deletions NAPS2.Lib/EtoForms/EtoDevicePrompt.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
using System.Threading;
using NAPS2.EtoForms.Ui;
using NAPS2.EtoForms.Ui;
using NAPS2.Scan;
using NAPS2.Scan.Exceptions;

namespace NAPS2.EtoForms;

Expand All @@ -16,41 +14,15 @@ public EtoDevicePrompt(IFormFactory formFactory, ScanningContext scanningContext
_scanningContext = scanningContext;
}

public async Task<ScanDevice?> PromptForDevice(ScanOptions options)
public Task<ScanDevice?> PromptForDevice(ScanOptions options)
{
// TWAIN and WIA get devices very fast (<1s) so it's better UX to just wait until we load the devices before
// showing the selection dialog.
// On the other hand, SANE can take a long time (10s), and Apple/ESCL wait a couple seconds for potential
// network responses, so it's better to show the selection dialog and lazily populate it.
bool waitForDevices = options.Driver is Driver.Wia or Driver.Twain;
if (waitForDevices)
// TODO: Extension method or something to turn InvokeGet into Task<T>?
return Task.FromResult(Invoker.Current.InvokeGet(() =>
{
var deviceList = await new ScanController(_scanningContext).GetDeviceList(options);
if (deviceList.Count == 0)
{
throw new NoDevicesFoundException();
}
return Invoker.Current.InvokeGet(() =>
{
var deviceForm = _formFactory.Create<SelectDeviceForm>();
deviceForm.DeviceList = deviceList;
deviceForm.ShowModal();
return deviceForm.SelectedDevice;
});
}
else
{
var cts = new CancellationTokenSource();
var devices = new ScanController(_scanningContext).GetDevices(options, cts.Token);
return Invoker.Current.InvokeGet(() =>
{
var deviceForm = _formFactory.Create<SelectDeviceForm>();
deviceForm.AsyncDevices = devices;
deviceForm.AsyncCancelToken = cts.Token;
deviceForm.ShowModal();
cts.Cancel();
return deviceForm.SelectedDevice;
});
}
var deviceForm = _formFactory.Create<SelectDeviceForm>();
deviceForm.ScanOptions = options;
deviceForm.ShowModal();
return deviceForm.SelectedDevice;
}));
}
}
16 changes: 16 additions & 0 deletions NAPS2.Lib/EtoForms/EtoExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,20 @@ public static void Fill(this IMemoryImage image, Color color)
{
new FillColorImageOp((byte) color.Rb, (byte) color.Gb, (byte) color.Bb, (byte) color.Ab).Perform(image);
}

public static Image PadTo(this Image image, Size size)
{
bool fits = image.Width <= size.Width && image.Height <= size.Height;
bool needsPadding = image.Height < size.Height || image.Width < size.Width;
if (fits && needsPadding)
{
var newImage = new Bitmap(size.Width, size.Height, PixelFormat.Format32bppRgba);
using var graphics = new Graphics(newImage);
graphics.Clear(Colors.Transparent);
graphics.DrawImage(image, (size.Width - image.Width) / 2f, (size.Height - image.Height) / 2f);
image.Dispose();
return newImage;
}
return image;
}
}
132 changes: 32 additions & 100 deletions NAPS2.Lib/EtoForms/Ui/EditProfileForm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
using NAPS2.EtoForms.Layout;
using NAPS2.EtoForms.Widgets;
using NAPS2.Scan;
using NAPS2.Scan.Exceptions;
using NAPS2.Scan.Internal;

namespace NAPS2.EtoForms.Ui;
Expand All @@ -16,12 +15,10 @@ public class EditProfileForm : EtoDialogBase
private readonly ProfileNameTracker _profileNameTracker;

private readonly TextBox _displayName = new();
private readonly RadioButton _wiaDriver;
private readonly RadioButton _twainDriver;
private readonly RadioButton _appleDriver;
private readonly RadioButton _saneDriver;
private readonly RadioButton _esclDriver;
private readonly TextBox _deviceName = new() { Enabled = false };
private readonly ImageView _deviceIcon = new();
private readonly Label _deviceName = new();
private readonly Label _deviceDriver = new();
private readonly LayoutVisibility _deviceVis = new(false);
private readonly Button _chooseDevice = new() { Text = UiStrings.ChooseDevice };
private readonly RadioButton _predefinedSettings;
private readonly RadioButton _nativeUi;
Expand Down Expand Up @@ -51,20 +48,9 @@ public EditProfileForm(Naps2Config config, IScanPerformer scanPerformer, ErrorOu
_scanPerformer = scanPerformer;
_errorOutput = errorOutput;
_profileNameTracker = profileNameTracker;

_wiaDriver = new RadioButton { Text = UiStrings.WiaDriver };
_twainDriver = new RadioButton(_wiaDriver) { Text = UiStrings.TwainDriver };
_appleDriver = new RadioButton(_wiaDriver) { Text = UiStrings.AppleDriver };
_saneDriver = new RadioButton(_wiaDriver) { Text = UiStrings.SaneDriver };
_esclDriver = new RadioButton(_wiaDriver) { Text = UiStrings.EsclDriver };
_predefinedSettings = new RadioButton { Text = UiStrings.UsePredefinedSettings };
_nativeUi = new RadioButton(_predefinedSettings) { Text = UiStrings.UseNativeUi };
_pageSize.SelectedIndexChanged += PageSize_SelectedIndexChanged;
_wiaDriver.CheckedChanged += Driver_CheckedChanged;
_twainDriver.CheckedChanged += Driver_CheckedChanged;
_appleDriver.CheckedChanged += Driver_CheckedChanged;
_saneDriver.CheckedChanged += Driver_CheckedChanged;
_esclDriver.CheckedChanged += Driver_CheckedChanged;
_predefinedSettings.CheckedChanged += PredefinedSettings_CheckedChanged;
_nativeUi.CheckedChanged += NativeUi_CheckedChanged;

Expand All @@ -77,51 +63,27 @@ public EditProfileForm(Naps2Config config, IScanPerformer scanPerformer, ErrorOu

protected override void BuildLayout()
{
// TODO: Don't show if only one driver is available
var driverElements = new List<LayoutElement>();
if (PlatformCompat.System.IsWiaDriverSupported)
{
driverElements.Add(_wiaDriver.Scale());
}
if (PlatformCompat.System.IsTwainDriverSupported)
{
driverElements.Add(_twainDriver.Scale());
}
if (PlatformCompat.System.IsAppleDriverSupported)
{
driverElements.Add(_appleDriver.Scale());
}
if (PlatformCompat.System.IsSaneDriverSupported)
{
driverElements.Add(_saneDriver.Scale());
}
if (PlatformCompat.System.IsEsclDriverSupported)
{
driverElements.Add(_esclDriver.Scale());
}

Title = UiStrings.EditProfileFormTitle;
Icon = new Icon(1f, Icons.blueprints_small.ToEtoImage());

FormStateController.DefaultExtraLayoutSize = new Size(60, 0);
FormStateController.FixedHeightLayout = true;

LayoutController.Content = L.Column(
L.Row(
L.Column(
C.Label(UiStrings.DisplayNameLabel),
_displayName,
L.Row(
driverElements.ToArray()
),
C.Spacer(),
C.Label(UiStrings.DeviceLabel),
L.Row(
_deviceName.Scale(),
_chooseDevice
)
).Scale(),
new ImageView { Image = Icons.scanner_48.ToEtoImage() }
C.Label(UiStrings.DisplayNameLabel),
_displayName,
C.Spacer(),
L.GroupBox(UiStrings.DeviceLabel,
L.Row(
_deviceIcon.Visible(_deviceVis).AlignCenter(),
L.Column(
C.Filler(),
_deviceName,
_deviceDriver,
C.Filler()
).Spacing(5).Visible(_deviceVis).Scale(),
_chooseDevice.AlignCenter()
)
),
C.Spacer(),
PlatformCompat.System.IsWiaDriverSupported || PlatformCompat.System.IsTwainDriverSupported
Expand Down Expand Up @@ -183,42 +145,22 @@ public ScanDevice? CurrentDevice
{
_currentDevice = value;
_deviceName.Text = value?.Name ?? "";
}
}

private Driver DeviceDriver
{
get => _twainDriver.Checked ? Driver.Twain
: _wiaDriver.Checked ? Driver.Wia
: _appleDriver.Checked ? Driver.Apple
: _saneDriver.Checked ? Driver.Sane
: _esclDriver.Checked ? Driver.Escl
: ScanOptionsValidator.SystemDefaultDriver;
set
{
if (value == Driver.Twain)
{
_twainDriver.Checked = true;
}
else if (value == Driver.Wia)
{
_wiaDriver.Checked = true;
}
else if (value == Driver.Apple)
{
_appleDriver.Checked = true;
}
else if (value == Driver.Sane)
{
_saneDriver.Checked = true;
}
else if (value == Driver.Escl)
_deviceDriver.Text = value?.Driver switch
{
_esclDriver.Checked = true;
}
Driver.Wia => UiStrings.WiaDriver,
Driver.Twain => UiStrings.TwainDriver,
Driver.Sane => UiStrings.SaneDriver,
Driver.Escl => UiStrings.EsclDriver,
Driver.Apple => UiStrings.AppleDriver,
_ => ""
};
_deviceVis.IsVisible = _deviceName.Text.Length > 0;
_deviceIcon.Image = Icons.device.ToEtoImage();
}
}

private Driver DeviceDriver { get; set; }

protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
Expand Down Expand Up @@ -268,6 +210,8 @@ private async void ChooseDevice(object? sender, EventArgs args)
_displayName.Text = device.Name;
}
CurrentDevice = device;
DeviceDriver = device.Driver;
UpdateEnabledControls();
}
}

Expand Down Expand Up @@ -439,8 +383,6 @@ private void UpdateEnabledControls()
bool settingsEnabled = !locked && (_predefinedSettings.Checked || !canUseNativeUi);

_displayName.Enabled = !locked;
_wiaDriver.Enabled = _twainDriver.Enabled =
_appleDriver.Enabled = _saneDriver.Enabled = _esclDriver.Enabled = !locked;
_chooseDevice.Enabled = !deviceLocked;
_predefinedSettings.Enabled = _nativeUi.Enabled = !locked;

Expand All @@ -463,16 +405,6 @@ private void UpdateEnabledControls()
}
}

private void Driver_CheckedChanged(object? sender, EventArgs e)
{
if (((RadioButton) sender!).Checked && !_suppressChangeEvent)
{
ScanProfile.Device = null;
CurrentDevice = null;
UpdateEnabledControls();
}
}

private int _lastPageSizeIndex = -1;
private PageSizeListItem? _lastPageSizeItem;

Expand Down
Loading

0 comments on commit 95bf090

Please sign in to comment.