From 241d4342e4d602139d85f8fe30af48146fa68a73 Mon Sep 17 00:00:00 2001 From: dg Date: Fri, 31 Mar 2023 22:11:40 +0000 Subject: [PATCH] Make exclusivity groups work in the GUI. --- lib/config.proto | 59 +++++++++++++++++++++----------------- src/formats/_apple2.textpb | 3 ++ src/gui/mainwindow.cc | 59 +++++++++++++++++++++++++++++++++++++- 3 files changed, 94 insertions(+), 27 deletions(-) diff --git a/lib/config.proto b/lib/config.proto index 31b3560b..c523384d 100644 --- a/lib/config.proto +++ b/lib/config.proto @@ -13,37 +13,44 @@ import "lib/common.proto"; import "lib/layout.proto"; // NEXT_TAG: 21 -message ConfigProto { - optional string comment = 8; - optional bool is_extension = 13; - repeated string include = 19; +message ConfigProto +{ + optional string comment = 8; + optional bool is_extension = 13; + repeated string include = 19; - optional LayoutProto layout = 18; + optional LayoutProto layout = 18; - optional ImageReaderProto image_reader = 12; - optional ImageWriterProto image_writer = 9; - - optional FluxSourceProto flux_source = 10; - optional FluxSinkProto flux_sink = 11; - optional DriveProto drive = 15; + optional ImageReaderProto image_reader = 12; + optional ImageWriterProto image_writer = 9; - optional EncoderProto encoder = 3; - optional DecoderProto decoder = 4; - optional UsbProto usb = 5; + optional FluxSourceProto flux_source = 10; + optional FluxSinkProto flux_sink = 11; + optional DriveProto drive = 15; - optional RangeProto tracks = 6; - optional RangeProto heads = 7; - optional int32 tpi = 16 [ (help) = "TPI of image; if 0, use TPI of drive" ]; + optional EncoderProto encoder = 3; + optional DecoderProto decoder = 4; + optional UsbProto usb = 5; - optional FilesystemProto filesystem = 17; - - repeated OptionProto option = 20; + optional RangeProto tracks = 6; + optional RangeProto heads = 7; + optional int32 tpi = 16 [ (help) = "TPI of image; if 0, use TPI of drive" ]; + + optional FilesystemProto filesystem = 17; + + repeated OptionProto option = 20; } -message OptionProto { - optional string name = 1 [(help) = "Option name" ]; - optional string comment = 2 [(help) = "Help text for option" ]; - optional string message = 3 [(help) = "Message to display when option is in use" ]; - optional ConfigProto config = 4 [(help) = "Option data", (recurse) = false ]; +message OptionProto +{ + optional string name = 1 [ (help) = "option name" ]; + optional string comment = 2 [ (help) = "help text for option" ]; + optional string message = 3 + [ (help) = "message to display when option is in use" ]; + optional string exclusivity_group = 5 [ + (help) = + "options with the same group cannot be selected at the same time" + ]; + optional ConfigProto config = 4 + [ (help) = "option data", (recurse) = false ]; } - diff --git a/src/formats/_apple2.textpb b/src/formats/_apple2.textpb index 987ea09b..d919c596 100644 --- a/src/formats/_apple2.textpb +++ b/src/formats/_apple2.textpb @@ -17,6 +17,7 @@ option { name: "appledos" comment: "use AppleDOS soft sector skew for filesystem access and images" message: "compensating for AppleDOS soft sector skew" + exclusivity_group: "format" config { image_reader { @@ -60,6 +61,7 @@ option { name: "prodos" comment: "use ProDOS soft sector skew for filesystem access and images" message: "compensating for ProDOS soft sector skew" + exclusivity_group: "format" config { image_reader { @@ -103,6 +105,7 @@ option { name: "cpm" comment: "use CP/M soft sector skew for filesystem access and images" message: "compensating for CP/M soft sector skew" + exclusivity_group: "format" config { image_reader { diff --git a/src/gui/mainwindow.cc b/src/gui/mainwindow.cc index 751dedd3..75587cbc 100644 --- a/src/gui/mainwindow.cc +++ b/src/gui/mainwindow.cc @@ -1686,13 +1686,69 @@ public: _formatNames[formatChoice->GetSelection()]; FlagGroup::parseConfigFile(formatName, formats); + std::set exclusivityGroups; + for (auto& option : config.option()) + { + if (option.has_exclusivity_group()) + exclusivityGroups.insert(option.exclusivity_group()); + } + if (config.option().empty()) sizer->Add(new wxStaticText(formatOptionsContainer, wxID_ANY, "(no options for this format)")); else + { + /* Add grouped radiobuttons for anything in an exclusivity + * group. */ + + for (auto& group : exclusivityGroups) + { + bool first = true; + for (auto& option : config.option()) + { + if (option.exclusivity_group() != group) + continue; + + auto* rb = new wxRadioButton(formatOptionsContainer, + wxID_ANY, + option.comment()); + auto key = + std::make_pair(formatName, option.name()); + sizer->Add(rb); + + rb->Bind(wxEVT_RADIOBUTTON, + [=](wxCommandEvent& e) + { + for (auto& option : config.option()) + { + if (option.exclusivity_group() == group) + _formatOptions.erase(std::make_pair( + formatName, option.name())); + } + + _formatOptions.insert(key); + + OnControlsChanged(e); + }); + + if (_formatOptions.find(key) != + _formatOptions.end()) + rb->SetValue(true); + + if (first) + rb->SetExtraStyle(wxRB_GROUP); + first = false; + } + } + + /* Anything that's _not_ in a group gets a checkbox. */ + for (auto& option : config.option()) { + if (option.has_exclusivity_group()) + continue; + auto* choice = new wxCheckBox( formatOptionsContainer, wxID_ANY, option.comment()); auto key = std::make_pair(formatName, option.name()); @@ -1702,7 +1758,7 @@ public: choice->SetValue(true); choice->Bind(wxEVT_CHECKBOX, - [this, choice, key](wxCommandEvent& e) + [=](wxCommandEvent& e) { if (choice->GetValue()) _formatOptions.insert(key); @@ -1712,6 +1768,7 @@ public: OnControlsChanged(e); }); } + } } formatOptionsContainer->SetSizerAndFit(sizer);