refactor(egui): move action definitions to a separate file

This commit is contained in:
Mikolaj Wielgus 2024-10-14 01:34:59 +02:00
parent 894326e3d5
commit 90afd70f2a
3 changed files with 225 additions and 98 deletions

View File

@ -0,0 +1,170 @@
use crate::{
action::{Action, Switch, Trigger},
translator::Translator,
};
pub struct FileActions {
pub open_design: Trigger,
pub export_session: Trigger,
pub import_history: Trigger,
pub export_history: Trigger,
pub quit: Trigger,
}
impl FileActions {
pub fn new(tr: &Translator) -> Self {
Self {
open_design: Trigger::new(Action::new(
tr.text("tr-menu-file-open"),
egui::Modifiers::CTRL,
egui::Key::O,
)),
export_session: Trigger::new(Action::new(
tr.text("tr-menu-file-export-session-file"),
egui::Modifiers::CTRL,
egui::Key::S,
)),
import_history: Trigger::new(Action::new(
tr.text("tr-menu-file-import-history"),
egui::Modifiers::CTRL,
egui::Key::I,
)),
export_history: Trigger::new(Action::new(
tr.text("tr-menu-file-export-history"),
egui::Modifiers::CTRL,
egui::Key::E,
)),
quit: Trigger::new(Action::new(
tr.text("tr-menu-file-quit"),
egui::Modifiers::CTRL,
egui::Key::Q,
)),
}
}
}
pub struct EditActions {
pub undo: Trigger,
pub redo: Trigger,
pub abort: Trigger,
pub remove_bands: Trigger,
}
impl EditActions {
pub fn new(tr: &Translator) -> Self {
Self {
undo: Trigger::new(Action::new(
tr.text("tr-menu-edit-undo"),
egui::Modifiers::CTRL,
egui::Key::Z,
)),
redo: Trigger::new(Action::new(
tr.text("tr-menu-edit-redo"),
egui::Modifiers::CTRL,
egui::Key::Y,
)),
abort: Trigger::new(Action::new(
tr.text("tr-menu-edit-abort"),
egui::Modifiers::NONE,
egui::Key::Escape,
)),
remove_bands: Trigger::new(Action::new(
tr.text("tr-menu-edit-remove-bands"),
egui::Modifiers::NONE,
egui::Key::Delete,
)),
}
}
}
pub struct PlaceActions {
pub place_via: Switch,
}
impl PlaceActions {
pub fn new(tr: &Translator) -> Self {
Self {
place_via: Switch::new(Action::new(
tr.text("tr-menu-place-place-via"),
egui::Modifiers::CTRL,
egui::Key::P,
)),
}
}
}
pub struct RouteActions {
pub autoroute: Trigger,
}
impl RouteActions {
pub fn new(tr: &Translator) -> Self {
Self {
autoroute: Trigger::new(Action::new(
tr.text("tr-menu-route-autoroute"),
egui::Modifiers::CTRL,
egui::Key::A,
)),
}
}
}
pub struct InspectActions {
pub compare_detours: Trigger,
pub measure_length: Trigger,
}
impl InspectActions {
pub fn new(tr: &Translator) -> Self {
Self {
compare_detours: Trigger::new(Action::new(
tr.text("tr-menu-inspect-compare-detours"),
egui::Modifiers::NONE,
egui::Key::Minus,
)),
measure_length: Trigger::new(Action::new(
tr.text("tr-menu-inspect-measure-length"),
egui::Modifiers::NONE,
egui::Key::Plus,
)),
}
}
}
pub struct HelpActions {
pub online_documentation: Trigger,
}
impl HelpActions {
pub fn new(tr: &Translator) -> Self {
Self {
online_documentation: Trigger::new(Action::new(
tr.text("tr-menu-help-online-documentation"),
egui::Modifiers::NONE,
egui::Key::F1,
)),
}
}
}
pub struct Actions {
pub file: FileActions,
pub edit: EditActions,
pub place: PlaceActions,
pub route: RouteActions,
pub inspect: InspectActions,
pub help: HelpActions,
}
impl Actions {
pub fn new(tr: &Translator) -> Self {
Self {
file: FileActions::new(tr),
edit: EditActions::new(tr),
place: PlaceActions::new(tr),
route: RouteActions::new(tr),
inspect: InspectActions::new(tr),
help: HelpActions::new(tr),
}
}
}

View File

@ -1,6 +1,7 @@
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release
mod action; mod action;
mod actions;
mod app; mod app;
mod config; mod config;
mod error_dialog; mod error_dialog;

View File

@ -15,6 +15,7 @@ use topola::{
use crate::{ use crate::{
action::{Action, Switch, Trigger}, action::{Action, Switch, Trigger},
actions::Actions,
app::{execute, handle_file}, app::{execute, handle_file},
translator::Translator, translator::Translator,
viewport::Viewport, viewport::Viewport,
@ -60,76 +61,7 @@ impl MenuBar {
viewport: &mut Viewport, viewport: &mut Viewport,
maybe_workspace: Option<&mut Workspace>, maybe_workspace: Option<&mut Workspace>,
) -> Result<(), InvokerError> { ) -> Result<(), InvokerError> {
let mut open_design = Trigger::new(Action::new( let mut actions = Actions::new(tr);
tr.text("tr-menu-file-open"),
egui::Modifiers::CTRL,
egui::Key::O,
));
let mut export_session = Trigger::new(Action::new(
tr.text("tr-menu-file-export-session-file"),
egui::Modifiers::CTRL,
egui::Key::S,
));
let mut import_history = Trigger::new(Action::new(
tr.text("tr-menu-file-import-history"),
egui::Modifiers::CTRL,
egui::Key::I,
));
let mut export_history = Trigger::new(Action::new(
tr.text("tr-menu-file-export-history"),
egui::Modifiers::CTRL,
egui::Key::E,
));
let mut quit = Trigger::new(Action::new(
tr.text("tr-menu-file-quit"),
egui::Modifiers::CTRL,
egui::Key::Q,
));
let mut undo = Trigger::new(Action::new(
tr.text("tr-menu-edit-undo"),
egui::Modifiers::CTRL,
egui::Key::Z,
));
let mut redo = Trigger::new(Action::new(
tr.text("tr-menu-edit-redo"),
egui::Modifiers::CTRL,
egui::Key::Y,
));
let mut abort = Trigger::new(Action::new(
tr.text("tr-menu-edit-abort"),
egui::Modifiers::NONE,
egui::Key::Escape,
));
let mut remove_bands = Trigger::new(Action::new(
tr.text("tr-menu-edit-remove-bands"),
egui::Modifiers::NONE,
egui::Key::Delete,
));
let mut place_via = Switch::new(Action::new(
tr.text("tr-menu-place-place-via"),
egui::Modifiers::CTRL,
egui::Key::P,
));
let mut autoroute = Trigger::new(Action::new(
tr.text("tr-menu-route-autoroute"),
egui::Modifiers::CTRL,
egui::Key::A,
));
let mut compare_detours = Trigger::new(Action::new(
tr.text("tr-menu-inspect-compare-detours"),
egui::Modifiers::NONE,
egui::Key::Minus,
));
let mut measure_length = Trigger::new(Action::new(
tr.text("tr-menu-inspect-measure-length"),
egui::Modifiers::NONE,
egui::Key::Plus,
));
let mut online_documentation = Trigger::new(Action::new(
tr.text("tr-menu-help-online-documentation"),
egui::Modifiers::NONE,
egui::Key::F1,
));
let online_documentation_url = "https://topola.codeberg.page/doc/"; let online_documentation_url = "https://topola.codeberg.page/doc/";
let workspace_activities_enabled = match &maybe_workspace { let workspace_activities_enabled = match &maybe_workspace {
@ -147,37 +79,37 @@ impl MenuBar {
.show(ctx, |ui| { .show(ctx, |ui| {
egui::menu::bar(ui, |ui| { egui::menu::bar(ui, |ui| {
ui.menu_button(tr.text("tr-menu-file"), |ui| { ui.menu_button(tr.text("tr-menu-file"), |ui| {
open_design.button(ctx, ui); actions.file.open_design.button(ctx, ui);
//ui.add_enabled_ui(maybe_workspace.is_some(), |ui| { //ui.add_enabled_ui(maybe_workspace.is_some(), |ui| {
export_session.button(ctx, ui); actions.file.export_session.button(ctx, ui);
ui.separator(); ui.separator();
import_history.button(ctx, ui); actions.file.import_history.button(ctx, ui);
export_history.button(ctx, ui); actions.file.export_history.button(ctx, ui);
//}); //});
ui.separator(); ui.separator();
// "Quit" button wouldn't work on a Web page. // "Quit" button wouldn't work on a Web page.
if !cfg!(target_arch = "wasm32") { if !cfg!(target_arch = "wasm32") {
quit.button(ctx, ui); actions.file.quit.button(ctx, ui);
} }
}); });
ui.menu_button(tr.text("tr-menu-edit"), |ui| { ui.menu_button(tr.text("tr-menu-edit"), |ui| {
ui.add_enabled_ui(maybe_workspace.is_some(), |ui| { ui.add_enabled_ui(maybe_workspace.is_some(), |ui| {
undo.button(ctx, ui); actions.edit.undo.button(ctx, ui);
redo.button(ctx, ui); actions.edit.redo.button(ctx, ui);
ui.separator(); ui.separator();
abort.button(ctx, ui); actions.edit.abort.button(ctx, ui);
ui.separator(); ui.separator();
//ui.add_enabled_ui(workspace_activities_enabled, |ui| { //ui.add_enabled_ui(workspace_activities_enabled, |ui| {
remove_bands.button(ctx, ui); actions.edit.remove_bands.button(ctx, ui);
//}); //});
}); });
}); });
@ -191,14 +123,18 @@ impl MenuBar {
ui.menu_button(tr.text("tr-menu-place"), |ui| { ui.menu_button(tr.text("tr-menu-place"), |ui| {
ui.add_enabled_ui(maybe_workspace.is_some(), |ui| { ui.add_enabled_ui(maybe_workspace.is_some(), |ui| {
place_via.toggle_widget(ctx, ui, &mut self.is_placing_via); actions.place.place_via.toggle_widget(
ctx,
ui,
&mut self.is_placing_via,
);
}); });
}); });
ui.menu_button(tr.text("tr-menu-route"), |ui| { ui.menu_button(tr.text("tr-menu-route"), |ui| {
ui.add_enabled_ui(maybe_workspace.is_some(), |ui| { ui.add_enabled_ui(maybe_workspace.is_some(), |ui| {
//ui.add_enabled_ui(workspace_activities_enabled, |ui| { //ui.add_enabled_ui(workspace_activities_enabled, |ui| {
autoroute.button(ctx, ui); actions.route.autoroute.button(ctx, ui);
//}); //});
ui.separator(); ui.separator();
@ -224,13 +160,17 @@ impl MenuBar {
ui.menu_button(tr.text("tr-menu-inspect"), |ui| { ui.menu_button(tr.text("tr-menu-inspect"), |ui| {
ui.add_enabled_ui(workspace_activities_enabled, |ui| { ui.add_enabled_ui(workspace_activities_enabled, |ui| {
compare_detours.button(ctx, ui); actions.inspect.compare_detours.button(ctx, ui);
measure_length.button(ctx, ui); actions.inspect.measure_length.button(ctx, ui);
}); });
}); });
ui.menu_button(tr.text("tr-menu-help"), |ui| { ui.menu_button(tr.text("tr-menu-help"), |ui| {
online_documentation.hyperlink(ctx, ui, online_documentation_url); actions.help.online_documentation.hyperlink(
ctx,
ui,
online_documentation_url,
);
}); });
ui.separator(); ui.separator();
@ -238,7 +178,7 @@ impl MenuBar {
egui::widgets::global_theme_preference_buttons(ui); egui::widgets::global_theme_preference_buttons(ui);
}); });
if open_design.consume_key_triggered(ctx, ui) { if actions.file.open_design.consume_key_triggered(ctx, ui) {
// NOTE: On Linux, this requires Zenity to be installed on your system. // NOTE: On Linux, this requires Zenity to be installed on your system.
let ctx = ctx.clone(); let ctx = ctx.clone();
let task = rfd::AsyncFileDialog::new().pick_file(); let task = rfd::AsyncFileDialog::new().pick_file();
@ -253,15 +193,19 @@ impl MenuBar {
ctx.request_repaint(); ctx.request_repaint();
} }
}); });
} else if quit.consume_key_triggered(ctx, ui) { } else if actions.file.quit.consume_key_triggered(ctx, ui) {
ctx.send_viewport_cmd(egui::ViewportCommand::Close); ctx.send_viewport_cmd(egui::ViewportCommand::Close);
} else if online_documentation.consume_key_triggered(ctx, ui) { } else if actions
.help
.online_documentation
.consume_key_triggered(ctx, ui)
{
ui.ctx().open_url(egui::OpenUrl { ui.ctx().open_url(egui::OpenUrl {
url: String::from(online_documentation_url), url: String::from(online_documentation_url),
new_tab: true, new_tab: true,
}); });
} else if let Some(workspace) = maybe_workspace { } else if let Some(workspace) = maybe_workspace {
if export_session.consume_key_triggered(ctx, ui) { if actions.file.export_session.consume_key_triggered(ctx, ui) {
let ctx = ui.ctx().clone(); let ctx = ui.ctx().clone();
let board = workspace.interactor.invoker().autorouter().board(); let board = workspace.interactor.invoker().autorouter().board();
@ -287,7 +231,7 @@ impl MenuBar {
ctx.request_repaint(); ctx.request_repaint();
} }
}); });
} else if import_history.consume_key_triggered(ctx, ui) { } else if actions.file.import_history.consume_key_triggered(ctx, ui) {
let ctx = ctx.clone(); let ctx = ctx.clone();
let task = rfd::AsyncFileDialog::new().pick_file(); let task = rfd::AsyncFileDialog::new().pick_file();
let history_sender = workspace.history_channel.0.clone(); let history_sender = workspace.history_channel.0.clone();
@ -305,7 +249,7 @@ impl MenuBar {
ctx.request_repaint(); ctx.request_repaint();
} }
}); });
} else if export_history.consume_key_triggered(ctx, ui) { } else if actions.file.export_history.consume_key_triggered(ctx, ui) {
let ctx = ctx.clone(); let ctx = ctx.clone();
let task = rfd::AsyncFileDialog::new().save_file(); let task = rfd::AsyncFileDialog::new().save_file();
@ -322,13 +266,17 @@ impl MenuBar {
ctx.request_repaint(); ctx.request_repaint();
} }
}); });
} else if undo.consume_key_triggered(ctx, ui) { } else if actions.edit.undo.consume_key_triggered(ctx, ui) {
workspace.interactor.undo(); workspace.interactor.undo();
} else if redo.consume_key_triggered(ctx, ui) { } else if actions.edit.redo.consume_key_triggered(ctx, ui) {
workspace.interactor.redo(); workspace.interactor.redo();
} else if abort.consume_key_triggered(ctx, ui) { } else if actions.edit.abort.consume_key_triggered(ctx, ui) {
workspace.interactor.abort() workspace.interactor.abort()
} else if place_via.consume_key_enabled(ctx, ui, &mut self.is_placing_via) { } else if actions.place.place_via.consume_key_enabled(
ctx,
ui,
&mut self.is_placing_via,
) {
} else if workspace_activities_enabled { } else if workspace_activities_enabled {
let mut schedule = |op: fn(Selection, AutorouterOptions) -> Command| { let mut schedule = |op: fn(Selection, AutorouterOptions) -> Command| {
let selection = workspace.overlay.take_selection(); let selection = workspace.overlay.take_selection();
@ -337,19 +285,27 @@ impl MenuBar {
.schedule(op(selection, self.autorouter_options)); .schedule(op(selection, self.autorouter_options));
Ok::<(), InvokerError>(()) Ok::<(), InvokerError>(())
}; };
if remove_bands.consume_key_triggered(ctx, ui) { if actions.edit.remove_bands.consume_key_triggered(ctx, ui) {
schedule(|selection, _| { schedule(|selection, _| {
Command::RemoveBands(selection.band_selection) Command::RemoveBands(selection.band_selection)
})?; })?;
} else if autoroute.consume_key_triggered(ctx, ui) { } else if actions.route.autoroute.consume_key_triggered(ctx, ui) {
schedule(|selection, opts| { schedule(|selection, opts| {
Command::Autoroute(selection.pin_selection, opts) Command::Autoroute(selection.pin_selection, opts)
})?; })?;
} else if compare_detours.consume_key_triggered(ctx, ui) { } else if actions
.inspect
.compare_detours
.consume_key_triggered(ctx, ui)
{
schedule(|selection, opts| { schedule(|selection, opts| {
Command::CompareDetours(selection.pin_selection, opts) Command::CompareDetours(selection.pin_selection, opts)
})?; })?;
} else if measure_length.consume_key_triggered(ctx, ui) { } else if actions
.inspect
.measure_length
.consume_key_triggered(ctx, ui)
{
schedule(|selection, _| { schedule(|selection, _| {
Command::MeasureLength(selection.band_selection) Command::MeasureLength(selection.band_selection)
})?; })?;