Mutually exclusive thumbnail mode selection in UI

Implement mutually exclusive logic for thumbnail display modes in DataModel and MainForm. Add ThumbnailMode property for authoritative state. Replace radio button bindings with event handlers. Synchronize UI with model changes. Explicitly map thumbnail flags to PicSettings. Force WinForms startup, disabling WPF branch.
This commit is contained in:
MaddoScientisto 2026-02-16 18:58:15 +01:00
commit 214e540170
4 changed files with 229 additions and 16 deletions

View file

@ -836,8 +836,22 @@ namespace ImageCatalog_2
get => _showPhotoNumber;
set
{
if (_showPhotoNumber == value) return;
_showPhotoNumber = value;
if (value)
{
// ensure mutually exclusive choices
_addTimeToThumbnails = false;
_addTextToThumbnails = false;
_addNumberAndTimeToThumbnails = false;
_addRaceTimeToThumbnails = false;
NotifyPropertyChanged(nameof(AddTimeToThumbnails));
NotifyPropertyChanged(nameof(AddTextToThumbnails));
NotifyPropertyChanged(nameof(AddNumberAndTimeToThumbnails));
NotifyPropertyChanged(nameof(AddRaceTimeToThumbnails));
}
NotifyPropertyChanged();
NotifyPropertyChanged(nameof(ThumbnailMode));
}
}
@ -949,7 +963,20 @@ namespace ImageCatalog_2
get => _addTimeToThumbnails;
set
{
if (_addTimeToThumbnails == value) return;
_addTimeToThumbnails = value;
if (value)
{
// ensure mutually exclusive choices
_addTextToThumbnails = false;
_showPhotoNumber = false;
_addNumberAndTimeToThumbnails = false;
_addRaceTimeToThumbnails = false;
NotifyPropertyChanged(nameof(AddTextToThumbnails));
NotifyPropertyChanged(nameof(ShowPhotoNumber));
NotifyPropertyChanged(nameof(AddNumberAndTimeToThumbnails));
NotifyPropertyChanged(nameof(AddRaceTimeToThumbnails));
}
NotifyPropertyChanged();
}
}
@ -1004,7 +1031,20 @@ namespace ImageCatalog_2
get => _addTextToThumbnails;
set
{
if (_addTextToThumbnails == value) return;
_addTextToThumbnails = value;
if (value)
{
// ensure mutually exclusive choices
_addTimeToThumbnails = false;
_showPhotoNumber = false;
_addNumberAndTimeToThumbnails = false;
_addRaceTimeToThumbnails = false;
NotifyPropertyChanged(nameof(AddTimeToThumbnails));
NotifyPropertyChanged(nameof(ShowPhotoNumber));
NotifyPropertyChanged(nameof(AddNumberAndTimeToThumbnails));
NotifyPropertyChanged(nameof(AddRaceTimeToThumbnails));
}
NotifyPropertyChanged();
}
}
@ -1015,7 +1055,20 @@ namespace ImageCatalog_2
get => _addRaceTimeToThumbnails;
set
{
if (_addRaceTimeToThumbnails == value) return;
_addRaceTimeToThumbnails = value;
if (value)
{
// ensure mutually exclusive choices
_addTimeToThumbnails = false;
_addTextToThumbnails = false;
_showPhotoNumber = false;
_addNumberAndTimeToThumbnails = false;
NotifyPropertyChanged(nameof(AddTimeToThumbnails));
NotifyPropertyChanged(nameof(AddTextToThumbnails));
NotifyPropertyChanged(nameof(ShowPhotoNumber));
NotifyPropertyChanged(nameof(AddNumberAndTimeToThumbnails));
}
NotifyPropertyChanged();
}
}
@ -1026,11 +1079,79 @@ namespace ImageCatalog_2
get => _addNumberAndTimeToThumbnails;
set
{
if (_addNumberAndTimeToThumbnails == value) return;
_addNumberAndTimeToThumbnails = value;
if (value)
{
// ensure mutually exclusive choices
_addTimeToThumbnails = false;
_addTextToThumbnails = false;
_showPhotoNumber = false;
_addRaceTimeToThumbnails = false;
NotifyPropertyChanged(nameof(AddTimeToThumbnails));
NotifyPropertyChanged(nameof(AddTextToThumbnails));
NotifyPropertyChanged(nameof(ShowPhotoNumber));
NotifyPropertyChanged(nameof(AddRaceTimeToThumbnails));
}
NotifyPropertyChanged();
}
}
// Single authoritative thumbnail mode string to avoid conflicting bindings
// Possible values: "None", "Text", "Time", "Number", "NumberAndTime", "RaceTime"
public string ThumbnailMode
{
get
{
if (AddTextToThumbnails) return "Text";
if (AddTimeToThumbnails) return "Time";
if (ShowPhotoNumber) return "Number";
if (AddNumberAndTimeToThumbnails) return "NumberAndTime";
if (AddRaceTimeToThumbnails) return "RaceTime";
return "None";
}
set
{
var current = ThumbnailMode;
if (string.Equals(current, value, StringComparison.OrdinalIgnoreCase)) return;
// Set the boolean flags via their public setters so mutual-exclusion logic runs
switch ((value ?? string.Empty).ToLowerInvariant())
{
case "text":
AddTextToThumbnails = true;
break;
case "time":
AddTimeToThumbnails = true;
break;
case "number":
ShowPhotoNumber = true;
break;
case "numberandtime":
AddNumberAndTimeToThumbnails = true;
break;
case "racetime":
AddRaceTimeToThumbnails = true;
break;
default:
// clear all
_addTimeToThumbnails = false;
_addTextToThumbnails = false;
_showPhotoNumber = false;
_addRaceTimeToThumbnails = false;
_addNumberAndTimeToThumbnails = false;
NotifyPropertyChanged(nameof(AddTimeToThumbnails));
NotifyPropertyChanged(nameof(AddTextToThumbnails));
NotifyPropertyChanged(nameof(ShowPhotoNumber));
NotifyPropertyChanged(nameof(AddRaceTimeToThumbnails));
NotifyPropertyChanged(nameof(AddNumberAndTimeToThumbnails));
break;
}
NotifyPropertyChanged(nameof(ThumbnailMode));
}
}
// Image processing progress and status
private string _processingStatus = "";
public string ProcessingStatus
@ -1132,6 +1253,24 @@ namespace ImageCatalog_2
// Update PicSettings from DataModel using AutoMapper
_mapper.Map(this, _picSettings);
// Explicitly ensure thumbnail-related flags are applied to PicSettings
// because AutoMapper may not map differently-named properties.
try
{
_picSettings.AggiungiScritteMiniature = this.AddTextToThumbnails;
_picSettings.UsaOrarioMiniatura = this.AddTimeToThumbnails;
_picSettings.AggNumTempMin = this.AddNumberAndTimeToThumbnails;
_picSettings.AggTempoGaraMin = this.AddRaceTimeToThumbnails;
_picSettings.CreaMiniature = this.CreateThumbnails;
_picSettings.LarghezzaSmall = this.ThumbnailWidth;
_picSettings.AltezzaSmall = this.ThumbnailHeight;
_picSettings.DimMin = this.FontSizeThumbnail;
_picSettings.JpegQualityMin = this.JpegQualityThumbnail;
}
catch
{
// Best-effort; do not fail processing on mapping issues
}
var imageCreationOptions = new ImageCreationStuff.Options
{

View file

@ -1404,6 +1404,7 @@ namespace ImageCatalog
// RadioButton4
//
RadioButton4.AutoSize = true;
RadioButton4.DataBindings.Add(new Binding("Checked", bindingSource1, "AddTimeToThumbnails", true, DataSourceUpdateMode.OnPropertyChanged));
RadioButton4.Location = new Point(30, 93);
RadioButton4.Margin = new Padding(6, 8, 6, 8);
RadioButton4.Name = "RadioButton4";
@ -1416,6 +1417,7 @@ namespace ImageCatalog
// RadioButton6
//
RadioButton6.AutoSize = true;
RadioButton6.DataBindings.Add(new Binding("Checked", bindingSource1, "ShowPhotoNumber", true, DataSourceUpdateMode.OnPropertyChanged));
RadioButton6.Location = new Point(258, 38);
RadioButton6.Margin = new Padding(6, 8, 6, 8);
RadioButton6.Name = "RadioButton6";

View file

@ -83,6 +83,55 @@ public partial class MainForm
// Watch for model changes so we can reflect external updates
Model.PropertyChanged += Model_PropertyChanged;
// Fix thumbnail radio buttons: clear designer bindings to avoid binding vs click conflicts
RadioButton3.DataBindings.Clear();
RadioButton4.DataBindings.Clear();
RadioButton5.DataBindings.Clear();
RadioButton6.DataBindings.Clear();
RadioButton7.DataBindings.Clear();
// Initialize radio state from model (thumbnail options)
try
{
_suppressRadioUpdates = true;
RadioButton3.Checked = Model.AddTextToThumbnails;
RadioButton4.Checked = Model.AddTimeToThumbnails;
RadioButton6.Checked = Model.ShowPhotoNumber;
RadioButton7.Checked = Model.AddNumberAndTimeToThumbnails;
RadioButton5.Checked = Model.AddRaceTimeToThumbnails;
}
finally
{
_suppressRadioUpdates = false;
}
// Use CheckedChanged handlers to set the authoritative ThumbnailMode on the model
RadioButton3.CheckedChanged += (s, ev) =>
{
if (_suppressRadioUpdates) return;
if (RadioButton3.Checked) Model.ThumbnailMode = "Text";
};
RadioButton4.CheckedChanged += (s, ev) =>
{
if (_suppressRadioUpdates) return;
if (RadioButton4.Checked) Model.ThumbnailMode = "Time";
};
RadioButton6.CheckedChanged += (s, ev) =>
{
if (_suppressRadioUpdates) return;
if (RadioButton6.Checked) Model.ThumbnailMode = "Number";
};
RadioButton7.CheckedChanged += (s, ev) =>
{
if (_suppressRadioUpdates) return;
if (RadioButton7.Checked) Model.ThumbnailMode = "NumberAndTime";
};
RadioButton5.CheckedChanged += (s, ev) =>
{
if (_suppressRadioUpdates) return;
if (RadioButton5.Checked) Model.ThumbnailMode = "RaceTime";
};
// Save user preferences on form close instead of immediately when dialogs are used
this.FormClosing += MainForm_FormClosing;
@ -135,6 +184,29 @@ public partial class MainForm
_suppressRadioUpdates = false;
}
}
// Thumbnail mode changes - reflect back to radio buttons
if (e.PropertyName == nameof(Model.ThumbnailMode) ||
e.PropertyName == nameof(Model.AddTextToThumbnails) ||
e.PropertyName == nameof(Model.AddTimeToThumbnails) ||
e.PropertyName == nameof(Model.ShowPhotoNumber) ||
e.PropertyName == nameof(Model.AddNumberAndTimeToThumbnails) ||
e.PropertyName == nameof(Model.AddRaceTimeToThumbnails))
{
try
{
_suppressRadioUpdates = true;
RadioButton3.Checked = Model.AddTextToThumbnails;
RadioButton4.Checked = Model.AddTimeToThumbnails;
RadioButton6.Checked = Model.ShowPhotoNumber;
RadioButton7.Checked = Model.AddNumberAndTimeToThumbnails;
RadioButton5.Checked = Model.AddRaceTimeToThumbnails;
}
finally
{
_suppressRadioUpdates = false;
}
}
}
protected void BindControls()

View file

@ -79,24 +79,24 @@ static class Program
// the block below and comment out the WPF branch.
// -----------------------------------------------------------------------------
// // Force WinForms UI (uncomment to enable)
// var mainForm = serviceProvider.GetRequiredService<MainForm>();
// // If you want to set the DataModel explicitly on the WinForms form use the lines below
// // var mainViewModel = serviceProvider.GetRequiredService<DataModel>();
// // mainForm.Model = mainViewModel;
// Application.Run(mainForm);
var mainForm = serviceProvider.GetRequiredService<MainForm>();
// If you want to set the DataModel explicitly on the WinForms form use the lines below
// var mainViewModel = serviceProvider.GetRequiredService<DataModel>();
// mainForm.Model = mainViewModel;
Application.Run(mainForm);
// -----------------------------------------------------------------------------
if (serviceProvider.GetService(typeof(ImageCatalog_2.MainWindow)) is ImageCatalog_2.MainWindow wpfMain)
{
// Start WPF app
var app = new System.Windows.Application();
app.Run(wpfMain);
}
else
{
var mainForm = serviceProvider.GetRequiredService<MainForm>();
Application.Run(mainForm);
}
//if (serviceProvider.GetService(typeof(ImageCatalog_2.MainWindow)) is ImageCatalog_2.MainWindow wpfMain)
//{
// // Start WPF app
// var app = new System.Windows.Application();
// app.Run(wpfMain);
//}
//else
//{
// var mainForm = serviceProvider.GetRequiredService<MainForm>();
// Application.Run(mainForm);
//}
}
private static void ConfigureServices(ServiceCollection services)