Use a BuildLayout method pattern

This helps organize logic a bit and better handles cases where forms have parameters.
This commit is contained in:
Ben Olden-Cooligan 2022-12-10 11:36:54 -08:00
parent 3b02a34d33
commit 7ca1cf7ef5
21 changed files with 204 additions and 155 deletions

View File

@ -19,6 +19,14 @@ public abstract class EtoDialogBase : Dialog, IFormBase
LayoutController.Invalidated += (_, _) => FormStateController.UpdateLayoutSize(LayoutController);
}
protected abstract void BuildLayout();
protected override void OnPreLoad(EventArgs e)
{
BuildLayout();
base.OnPreLoad(e);
}
// TODO: PR for Eto to integrate this
public new Icon Icon
{

View File

@ -17,6 +17,14 @@ public abstract class EtoFormBase : Form, IFormBase
LayoutController.Invalidated += (_, _) => FormStateController.UpdateLayoutSize(LayoutController);
}
protected abstract void BuildLayout();
protected override void OnPreLoad(EventArgs e)
{
BuildLayout();
base.OnPreLoad(e);
}
public FormStateController FormStateController { get; }
public LayoutController LayoutController { get; } = new();

View File

@ -25,11 +25,6 @@ public class AboutForm : EtoDialogBase
{
_updateChecker = updateChecker;
Title = UiStrings.AboutFormTitle;
Icon = new Icon(1f, Icons.information_small.ToEtoImage());
FormStateController.Resizable = false;
FormStateController.RestoreFormState = false;
_donateButton = EtoPlatform.Current.AccessibleImageButton(
Icons.btn_donate_LG.ToEtoImage(),
UiStrings.Donate,
@ -39,11 +34,16 @@ public class AboutForm : EtoDialogBase
_updatePanel = new Panel();
UpdateControls();
BuildLayout();
}
private void BuildLayout()
protected override void BuildLayout()
{
Title = UiStrings.AboutFormTitle;
Icon = new Icon(1f, Icons.information_small.ToEtoImage());
FormStateController.Resizable = false;
FormStateController.RestoreFormState = false;
LayoutController.DefaultSpacing = 2;
LayoutController.Content = L.Row(
L.Column(new ImageView { Image = Icons.scanner_128.ToEtoImage() }).Padding(right: 4),

View File

@ -13,12 +13,17 @@ public class AuthorizeForm : EtoDialogBase
public AuthorizeForm(Naps2Config config, ErrorOutput errorOutput) : base(config)
{
_errorOutput = errorOutput;
}
protected override void BuildLayout()
{
Title = UiStrings.AuthorizeFormTitle;
Icon = new Icon(1f, Icons.key_small.ToEtoImage());
FormStateController.FixedHeightLayout = true;
FormStateController.RestoreFormState = false;
FormStateController.Resizable = false;
LayoutController.Content = L.Row(
C.Label(UiStrings.WaitingForAuthorization).Padding(right: 30),
C.CancelButton(this)

View File

@ -66,7 +66,6 @@ public abstract class DesktopForm : EtoFormBase
// PostInitializeComponent();
//
Icon = Icons.favicon.ToEtoIcon();
CreateToolbarsAndMenus();
UpdateScanButton();
InitLanguageDropdown();
@ -89,17 +88,6 @@ public abstract class DesktopForm : EtoFormBase
_listView.Control.KeyDown += OnKeyDown;
_listView.Control.MouseWheel += ListViewMouseWheel;
LayoutController.RootPadding = 0;
FormStateController.AutoLayoutSize = false;
FormStateController.DefaultClientSize = new Size(1210, 600);
LayoutController.Content = L.Overlay(
GetMainContent(),
L.Column(
C.Filler(),
L.Row(GetZoomButtons(), C.Filler())
).Padding(10)
);
//
// Shown += FDesktop_Shown;
// Closing += FDesktop_Closing;
@ -113,6 +101,23 @@ public abstract class DesktopForm : EtoFormBase
_profileManager.ProfilesUpdated += ProfileManager_ProfilesUpdated;
}
protected override void BuildLayout()
{
Icon = Icons.favicon.ToEtoIcon();
FormStateController.AutoLayoutSize = false;
FormStateController.DefaultClientSize = new Size(1210, 600);
LayoutController.RootPadding = 0;
LayoutController.Content = L.Overlay(
GetMainContent(),
L.Column(
C.Filler(),
L.Row(GetZoomButtons(), C.Filler())
).Padding(10)
);
}
private void OpeningContextMenu(object? sender, EventArgs e)
{
_contextMenu.Items.Clear();

View File

@ -28,15 +28,19 @@ public class DownloadProgressForm : EtoDialogBase
public DownloadProgressForm(Naps2Config config) : base(config)
{
FormStateController.RestoreFormState = false;
Title = UiStrings.DownloadProgressFormTitle;
Icon = new Icon(1f, Icons.text_small.ToEtoImage());
// TODO: Is this needed for net462?
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
_client.DownloadFileCompleted += client_DownloadFileCompleted;
_client.DownloadProgressChanged += client_DownloadProgressChanged;
}
protected override void BuildLayout()
{
Title = UiStrings.DownloadProgressFormTitle;
Icon = new Icon(1f, Icons.text_small.ToEtoImage());
FormStateController.RestoreFormState = false;
LayoutController.Content = L.Column(
_totalStatus,

View File

@ -48,8 +48,6 @@ public class EditProfileForm : EtoDialogBase
_scanPerformer = scanPerformer;
_errorOutput = errorOutput;
_profileNameTracker = profileNameTracker;
Title = UiStrings.EditProfileFormTitle;
Icon = new Icon(1f, Icons.blueprints_small.ToEtoImage());
_wiaDriver = new RadioButton { Text = UiStrings.WiaDriver };
_twainDriver = new RadioButton(_wiaDriver) { Text = UiStrings.TwainDriver };
@ -67,6 +65,15 @@ public class EditProfileForm : EtoDialogBase
_ok.Click += Ok_Click;
_cancel.Click += Cancel_Click;
_chooseDevice.Click += ChooseDevice;
_enableAutoSave.CheckedChanged += EnableAutoSave_CheckedChanged;
_autoSaveSettings.Click += AutoSaveSettings_LinkClicked;
_advanced.Click += Advanced_Click;
_deviceName.KeyDown += DeviceName_KeyDown;
}
protected override void BuildLayout()
{
// TODO: Don't show if only one driver is available
var driverElements = new List<LayoutElement>();
if (PlatformCompat.System.IsWiaDriverSupported)
@ -86,14 +93,12 @@ public class EditProfileForm : EtoDialogBase
driverElements.Add(_saneDriver.XScale());
}
_chooseDevice.Click += ChooseDevice;
_enableAutoSave.CheckedChanged += EnableAutoSave_CheckedChanged;
_autoSaveSettings.Click += AutoSaveSettings_LinkClicked;
_advanced.Click += Advanced_Click;
_deviceName.KeyDown += DeviceName_KeyDown;
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(

View File

@ -24,8 +24,6 @@ public class EmailProviderForm : EtoDialogBase
_systemEmailClients = systemEmailClients;
_gmailOauthProvider = gmailOauthProvider;
_outlookWebOauthProvider = outlookWebOauthProvider;
Title = UiStrings.EmailProviderFormTitle;
Icon = new Icon(1f, Icons.email_small.ToEtoImage());
_providerWidgets = new List<EmailProviderWidget>();
#if NET6_0_OR_GREATER
@ -93,8 +91,15 @@ public class EmailProviderForm : EtoDialogBase
_providerWidgets.Remove(defaultWidget);
_providerWidgets.Insert(0, defaultWidget);
}
}
protected override void BuildLayout()
{
Title = UiStrings.EmailProviderFormTitle;
Icon = new Icon(1f, Icons.email_small.ToEtoImage());
FormStateController.FixedHeightLayout = true;
LayoutController.DefaultSpacing = 0;
LayoutController.Content = L.Column(
_providerWidgets.Select(x => C.Button(new ActionCommand(x.ClickAction)

View File

@ -20,17 +20,22 @@ public class EmailSettingsForm : EtoDialogBase
public EmailSettingsForm(Naps2Config config, SystemEmailClients systemEmailClients) : base(config)
{
_systemEmailClients = systemEmailClients;
Title = UiStrings.EmailSettingsFormTitle;
Icon = new Icon(1f, Icons.email_small.ToEtoImage());
UpdateValues(Config);
UpdateProvider(Config);
_restoreDefaults.Click += RestoreDefaults_Click;
_placeholders.Click += Placeholders_Click;
}
protected override void BuildLayout()
{
Title = UiStrings.EmailSettingsFormTitle;
Icon = new Icon(1f, Icons.email_small.ToEtoImage());
FormStateController.DefaultExtraLayoutSize = new Size(60, 0);
FormStateController.FixedHeightLayout = true;
LayoutController.Content = L.Column(
L.GroupBox(
UiStrings.Provider,

View File

@ -5,22 +5,26 @@ namespace NAPS2.EtoForms.Ui;
public class ErrorForm : EtoDialogBase
{
private readonly ImageView _image = new() { Image = Icons.exclamation.ToEtoImage() };
private readonly Label _message = new();
private readonly TextArea _details = new() { ReadOnly = true };
private readonly LayoutVisibility _detailsVisibility = new(false);
public ErrorForm(Naps2Config config)
: base(config)
{
}
protected override void BuildLayout()
{
Title = UiStrings.ErrorFormTitle;
FormStateController.RestoreFormState = false;
var image = new ImageView { Image = Icons.exclamation.ToEtoImage() };
FormStateController.FixedHeightLayout = true;
LayoutController.Content = L.Column(
L.Row(
image.AlignCenter().Padding(right: 5),
_image.AlignCenter().Padding(right: 5),
_message.Wrap(350).NaturalWidth(350).AlignCenter().XScale()
),
L.Row(

View File

@ -22,8 +22,29 @@ public abstract class ImageFormBase : EtoDialogBase
_thumbnailController = thumbnailController;
_revert.Click += Revert;
_renderThrottle = new RefreshThrottle(RenderImage);
FormStateController.DefaultExtraLayoutSize = new Size(400, 400);
Overlay.Paint += PaintOverlay;
FormStateController.DefaultExtraLayoutSize = new Size(400, 400);
}
protected override void BuildLayout()
{
foreach (var slider in Sliders)
{
slider.ValueChanged += UpdatePreviewBox;
}
LayoutController.Content = L.Column(
Overlay.YScale(),
CreateControls(),
SelectedImages is { Count: > 1 } ? _applyToSelected : C.None(),
L.Row(
_revert,
C.Filler(),
L.OkCancel(
C.OkButton(this, beforeClose: Apply),
C.CancelButton(this))
)
);
}
protected int ImageHeight { get; set; }
@ -133,29 +154,6 @@ public abstract class ImageFormBase : EtoDialogBase
{
}
protected override void OnPreLoad(EventArgs e)
{
foreach (var slider in Sliders)
{
slider.ValueChanged += UpdatePreviewBox;
}
LayoutController.Content = L.Column(
Overlay.YScale(),
CreateControls(),
SelectedImages is { Count: > 1 } ? _applyToSelected : C.None(),
L.Row(
_revert,
C.Filler(),
L.OkCancel(
C.OkButton(this, beforeClose: Apply),
C.CancelButton(this))
)
);
base.OnPreLoad(e);
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);

View File

@ -22,8 +22,6 @@ public class ImageSettingsForm : EtoDialogBase
public ImageSettingsForm(Naps2Config config, DialogHelper dialogHelper) : base(config)
{
_dialogHelper = dialogHelper;
Title = UiStrings.ImageSettingsFormTitle;
Icon = new Icon(1f, Icons.picture_small.ToEtoImage());
UpdateValues(Config);
UpdateEnabled();
@ -32,9 +30,16 @@ public class ImageSettingsForm : EtoDialogBase
_defaultFilePath.TextChanged += DefaultFilePath_TextChanged;
_placeholders.Click += Placeholders_Click;
_chooseFolder.Click += ChooseFolder_Click;
}
protected override void BuildLayout()
{
Title = UiStrings.ImageSettingsFormTitle;
Icon = new Icon(1f, Icons.picture_small.ToEtoImage());
FormStateController.DefaultExtraLayoutSize = new Size(60, 0);
FormStateController.FixedHeightLayout = true;
LayoutController.Content = L.Column(
C.Label(UiStrings.DefaultFilePathLabel),
L.Row(

View File

@ -18,10 +18,6 @@ public class OcrDownloadForm : EtoDialogBase
{
_tesseractLanguageManager = tesseractLanguageManager;
Title = UiStrings.OcrDownloadFormTitle;
Icon = new Icon(1f, Icons.text_small.ToEtoImage());
FormStateController.RestoreFormState = false;
var initialSelection = new HashSet<string>();
// TODO: We used to select old installed languages here, maybe we could do it again if we get new lang data
if (!_tesseractLanguageManager.InstalledLanguages.Any())
@ -40,8 +36,16 @@ public class OcrDownloadForm : EtoDialogBase
_languageList.SelectionChanged += (_, _) => UpdateView();
UpdateView();
}
protected override void BuildLayout()
{
Title = UiStrings.OcrDownloadFormTitle;
Icon = new Icon(1f, Icons.text_small.ToEtoImage());
FormStateController.RestoreFormState = false;
FormStateController.DefaultExtraLayoutSize = new Size(300, 300);
LayoutController.Content = L.Column(
C.Label(UiStrings.OcrDownloadSummaryText),
C.Spacer(),

View File

@ -19,10 +19,6 @@ public class OcrSetupForm : EtoDialogBase
{
_tesseractLanguageManager = tesseractLanguageManager;
Title = UiStrings.OcrSetupFormTitle;
Icon = new Icon(1f, Icons.text_small.ToEtoImage());
FormStateController.Resizable = false;
_enableOcr.CheckedChanged += EnableOcr_CheckedChanged;
_moreLanguages.Click += MoreLanguages_Click;
@ -36,6 +32,14 @@ public class OcrSetupForm : EtoDialogBase
_ocrAfterScanning.Checked = Config.Get(c => c.OcrAfterScanning);
UpdateView();
}
protected override void BuildLayout()
{
Title = UiStrings.OcrSetupFormTitle;
Icon = new Icon(1f, Icons.text_small.ToEtoImage());
FormStateController.Resizable = false;
LayoutController.Content = L.Column(
_enableOcr,
@ -54,7 +58,7 @@ public class OcrSetupForm : EtoDialogBase
C.Filler(),
L.OkCancel(
C.OkButton(this, Save),
// TODO: Should we allow Esc to close the window if there are unsaved changes?
// TODO: Should we allow Esc to close the window if there are unsaved changes?
C.CancelButton(this))
)
);

View File

@ -49,8 +49,6 @@ public class PdfSettingsForm : EtoDialogBase
public PdfSettingsForm(Naps2Config config, DialogHelper dialogHelper) : base(config)
{
_dialogHelper = dialogHelper;
Title = UiStrings.PdfSettingsFormTitle;
Icon = new Icon(1f, Icons.file_extension_pdf_small.ToEtoImage());
UpdateValues(Config);
UpdateEnabled();
@ -60,9 +58,16 @@ public class PdfSettingsForm : EtoDialogBase
_encryptPdf.CheckedChanged += EncryptPdf_CheckedChanged;
_placeholders.Click += Placeholders_Click;
_chooseFolder.Click += ChooseFolder_Click;
}
protected override void BuildLayout()
{
Title = UiStrings.PdfSettingsFormTitle;
Icon = new Icon(1f, Icons.file_extension_pdf_small.ToEtoImage());
FormStateController.DefaultExtraLayoutSize = new Size(60, 0);
FormStateController.FixedHeightLayout = true;
LayoutController.Content = L.Column(
C.Label(UiStrings.DefaultFilePathLabel),
// TODO: Maybe make a widget for this kind of file picker

View File

@ -7,15 +7,7 @@ namespace NAPS2.EtoForms.Ui;
public class PlaceholdersForm : EtoDialogBase
{
private readonly TextBox _fileName = new();
private readonly Label _preview = new() { Text = " " };
public PlaceholdersForm(Naps2Config config) : base(config)
{
Title = UiStrings.PlaceholdersFormTitle;
var placeholders = new (string val, string text)[]
{
private static readonly (string val, string text)[] PlaceholderButtons = {
(Placeholders.YEAR_4_DIGITS, UiStrings.Year4Digit),
(Placeholders.YEAR_2_DIGITS, UiStrings.Year2Digit),
(Placeholders.MONTH_2_DIGITS, UiStrings.Month2Digit),
@ -29,12 +21,23 @@ public class PlaceholdersForm : EtoDialogBase
(Placeholders.NUMBER_1_DIGIT, UiStrings.AutoIncrementing1Digit)
};
private readonly TextBox _fileName = new();
private readonly Label _preview = new() { Text = " " };
public PlaceholdersForm(Naps2Config config) : base(config)
{
// TODO: Ellipsis aren't working, presumably because Eto uses custom label rendering on WinForms
EtoPlatform.Current.ConfigureEllipsis(_preview);
_fileName.TextChanged += FileName_TextChanged;
}
protected override void BuildLayout()
{
Title = UiStrings.PlaceholdersFormTitle;
FormStateController.DefaultExtraLayoutSize = new Size(60, 0);
FormStateController.FixedHeightLayout = true;
LayoutController.Content = L.Column(
C.Label(UiStrings.FileNameLabel),
_fileName,
@ -49,7 +52,7 @@ public class PlaceholdersForm : EtoDialogBase
L.GroupBox(
UiStrings.Placeholders,
L.Column(
placeholders.Select(x => L.Row(
PlaceholderButtons.Select(x => L.Row(
C.Button(x.val, () => Add(x.val)),
C.Label(x.text)
)).Expand(),

View File

@ -16,14 +16,6 @@ public class PreviewForm : EtoDialogBase
_desktopCommands = desktopCommands;
ImageList = imageList;
Title = UiStrings.PreviewFormTitle;
Icon = new Icon(1f, Icons.picture.ToEtoImage());
FormStateController.AutoLayoutSize = false;
FormStateController.DefaultClientSize = new Size(800, 600);
LayoutController.RootPadding = 0;
LayoutController.Content = _imageView;
GoToPrevCommand = new ActionCommand(() => GoTo(ImageIndex - 1))
{
Text = UiStrings.Previous,
@ -36,6 +28,18 @@ public class PreviewForm : EtoDialogBase
};
}
protected override void BuildLayout()
{
Title = UiStrings.PreviewFormTitle;
Icon = new Icon(1f, Icons.picture.ToEtoImage());
FormStateController.AutoLayoutSize = false;
FormStateController.DefaultClientSize = new Size(800, 600);
LayoutController.RootPadding = 0;
LayoutController.Content = _imageView;
}
protected DesktopCommands Commands { get; set; } = null!;
protected ActionCommand GoToPrevCommand { get; }
protected ActionCommand GoToNextCommand { get; }

View File

@ -36,9 +36,6 @@ public class ProfilesForm : EtoDialogBase
_profileTransfer = profileTransfer;
_thumbnailController = thumbnailController;
Title = UiStrings.ProfilesFormTitle;
Icon = new Icon(1f, Icons.blueprints_small.ToEtoImage());
// TODO: Do this only in WinForms (?)
// switch (Handler)
// {
@ -119,13 +116,15 @@ public class ProfilesForm : EtoDialogBase
ContextMenu.AddItems(
new ButtonMenuItem(_deleteCommand));
ContextMenu.Opening += ContextMenuOpening;
BuildLayout();
}
private void BuildLayout()
protected override void BuildLayout()
{
Title = UiStrings.ProfilesFormTitle;
Icon = new Icon(1f, Icons.blueprints_small.ToEtoImage());
FormStateController.DefaultExtraLayoutSize = new Size(200, 0);
LayoutController.Content = L.Column(
L.Row(
_listView.Control.XScale(),

View File

@ -19,12 +19,15 @@ public class ProgressForm : EtoDialogBase
public ProgressForm(Naps2Config config) : base(config)
{
FormStateController.RestoreFormState = false;
_cancel.Click += Cancel_Click;
_runInBg.Click += RunInBg_Click;
Size = new Size();
}
protected override void BuildLayout()
{
FormStateController.RestoreFormState = false;
LayoutController.Content = L.Column(
_status,

View File

@ -11,24 +11,24 @@ public class RecoverForm : EtoDialogBase
public RecoverForm(Naps2Config config) : base(config)
{
FormStateController.SaveFormState = false;
FormStateController.RestoreFormState = false;
Title = UiStrings.RecoverFormTitle;
// FormStateController.Resizable = false;
}
protected override void OnPreLoad(EventArgs e)
protected override void BuildLayout()
{
Title = UiStrings.RecoverFormTitle;
FormStateController.SaveFormState = false;
FormStateController.RestoreFormState = false;
// FormStateController.Resizable = false;
var recoverButton = C.DialogButton(this, UiStrings.Recover,
beforeClose: () => SelectedAction = RecoverAction.Recover);
var deleteButton = C.DialogButton(this, UiStrings.Delete,
beforeClose: () => SelectedAction = RecoverAction.Delete);
var notNowButton = C.CancelButton(this, UiStrings.NotNow);
MinimumSize = new Size(350, 0);
LayoutController.Content = L.Column(
_prompt.Wrap(400),
_prompt.Wrap(400).MinWidth(300),
C.Filler(),
L.Row(
recoverButton.XScale().Height(32),
@ -36,7 +36,6 @@ public class RecoverForm : EtoDialogBase
notNowButton.XScale().Height(32)
)
);
base.OnPreLoad(e);
}
public RecoverAction SelectedAction { get; private set; }

View File

@ -7,45 +7,13 @@ namespace NAPS2.EtoForms.Ui;
public class SelectDeviceForm : EtoDialogBase
{
private readonly ListBox _devices;
private readonly ListBox _devices = new();
public SelectDeviceForm(Naps2Config config) : base(config)
{
FormStateController.SaveFormState = false;
FormStateController.RestoreFormState = false;
var selectButton = new Button
{
Text = UiStrings.Select
};
DefaultButton = selectButton;
var cancelButton = new Button
{
Text = UiStrings.Cancel
};
AbortButton = cancelButton;
_devices = new ListBox();
selectButton.Click += Select_Click;
cancelButton.Click += Cancel_Click;
Title = UiStrings.SelectSource;
FormStateController.DefaultExtraLayoutSize = new Size(50, 0);
LayoutController.Content = L.Row(
_devices.NaturalSize(150, 100).XScale(),
L.Column(
selectButton,
cancelButton
)
);
}
public List<ScanDevice> DeviceList { get; set; } = null!;
public ScanDevice? SelectedDevice { get; private set; }
protected override void OnPreLoad(EventArgs e)
protected override void BuildLayout()
{
foreach (var device in DeviceList)
{
@ -59,13 +27,27 @@ public class SelectDeviceForm : EtoDialogBase
{
_devices.SelectedIndex = 0;
}
// TODO: Re-order things so we don't need to do this twice
// Just need to be careful not to break things cross-platform
FormStateController.UpdateLayoutSize(LayoutController);
base.OnPreLoad(e);
Title = UiStrings.SelectSource;
FormStateController.SaveFormState = false;
FormStateController.RestoreFormState = false;
FormStateController.DefaultExtraLayoutSize = new Size(50, 0);
LayoutController.Content = L.Row(
_devices.NaturalSize(150, 100).XScale(),
L.Column(
C.OkButton(this, SelectDevice, UiStrings.Select),
C.CancelButton(this)
)
);
}
private void Select_Click(object? sender, EventArgs e)
public List<ScanDevice> DeviceList { get; set; } = null!;
public ScanDevice? SelectedDevice { get; private set; }
private void SelectDevice()
{
if (_devices.SelectedValue == null)
{
@ -73,11 +55,5 @@ public class SelectDeviceForm : EtoDialogBase
return;
}
SelectedDevice = DeviceList.FirstOrDefault(x => x.ID == _devices.SelectedKey);
Close();
}
private void Cancel_Click(object? sender, EventArgs e)
{
Close();
}
}