diff --git a/README.md b/README.md index 5df18fe..5784c82 100644 --- a/README.md +++ b/README.md @@ -276,11 +276,13 @@ Options: --auto-copy Automatically copy to clipboard after every annotation change (NEXTRELEASE) --actions-on-enter - Actions to perform when pressing Enter [possible values: save-to-clipboard, save-to-file, save-to-file-as, copy-filepath-to-clipboard, exit] + Actions to perform when pressing Enter [possible values: save-to-clipboard, save-to-file, save-to-file-as, copy-filepath-to-clipboard, exit, undo] --actions-on-escape - Actions to perform when pressing Escape [possible values: save-to-clipboard, save-to-file, save-to-file-as, copy-filepath-to-clipboard, exit] + Actions to perform when pressing Escape [possible values: save-to-clipboard, save-to-file, save-to-file-as, copy-filepath-to-clipboard, exit, undo] --actions-on-right-click - Actions to perform when hitting the copy Button [possible values: save-to-clipboard, save-to-file, save-to-file-as, copy-filepath-to-clipboard, exit] + Actions to perform when hitting the copy Button [possible values: save-to-clipboard, save-to-file, save-to-file-as, copy-filepath-to-clipboard, exit, undo] + --actions-on-double-click + Actions to perform on double-click (NEXTRELEASE) [possible values: save-to-clipboard, save-to-file, save-to-file-as, copy-filepath-to-clipboard, exit, undo] -d, --default-hide-toolbars Hide toolbars by default --focus-toggles-toolbars @@ -316,7 +318,7 @@ Options: --right-click-copy Right click to copy. Preferably use the `action_on_right_click` option instead --action-on-enter - Action to perform when pressing Enter. Preferably use the `actions_on_enter` option instead [possible values: save-to-clipboard, save-to-file, save-to-file-as, copy-filepath-to-clipboard, exit] + Action to perform when pressing Enter. Preferably use the `actions_on_enter` option instead [possible values: save-to-clipboard, save-to-file, save-to-file-as, copy-filepath-to-clipboard, exit, undo] -h, --help Print help -V, --version diff --git a/cli/src/command_line.rs b/cli/src/command_line.rs index cdc5eec..f41cb75 100644 --- a/cli/src/command_line.rs +++ b/cli/src/command_line.rs @@ -90,6 +90,10 @@ pub struct CommandLine { #[arg(long, value_delimiter = ',')] pub actions_on_right_click: Option>, + /// Actions to perform on double-click (NEXTRELEASE) + #[arg(long, value_delimiter = ',')] + pub actions_on_double_click: Option>, + /// Hide toolbars by default #[arg(short, long)] pub default_hide_toolbars: bool, @@ -232,6 +236,7 @@ pub enum Action { SaveToFileAs, CopyFilepathToClipboard, Exit, + Undo, } #[derive(Debug, Clone, Copy, Default, ValueEnum)] diff --git a/src/configuration.rs b/src/configuration.rs index 9948762..02b1dbb 100644 --- a/src/configuration.rs +++ b/src/configuration.rs @@ -54,6 +54,7 @@ pub struct Configuration { actions_on_enter: Vec, actions_on_escape: Vec, actions_on_right_click: Vec, + actions_on_double_click: Vec, color_palette: ColorPalette, default_hide_toolbars: bool, focus_toggles_toolbars: bool, @@ -232,6 +233,7 @@ pub enum Action { SaveToFileAs, CopyFilepathToClipboard, Exit, + Undo, } impl From for Action { @@ -242,6 +244,7 @@ impl From for Action { CommandLineAction::SaveToFileAs => Self::SaveToFileAs, CommandLineAction::CopyFilepathToClipboard => Self::CopyFilepathToClipboard, CommandLineAction::Exit => Self::Exit, + CommandLineAction::Undo => Self::Undo, } } } @@ -321,6 +324,9 @@ impl Configuration { if let Some(v) = general.actions_on_right_click { self.actions_on_right_click = v; } + if let Some(v) = general.actions_on_double_click { + self.actions_on_double_click = v; + } if let Some(v) = general.default_hide_toolbars { self.default_hide_toolbars = v; } @@ -457,6 +463,9 @@ impl Configuration { if let Some(v) = command_line.actions_on_right_click { self.actions_on_right_click = v.iter().cloned().map(Into::into).collect(); } + if let Some(v) = command_line.actions_on_double_click { + self.actions_on_double_click = v.iter().cloned().map(Into::into).collect(); + } if let Some(v) = command_line.font_family { self.font.family = Some(v); } @@ -587,6 +596,10 @@ impl Configuration { self.actions_on_right_click.clone() } + pub fn actions_on_double_click(&self) -> Vec { + self.actions_on_double_click.clone() + } + pub fn color_palette(&self) -> &ColorPalette { &self.color_palette } @@ -677,6 +690,7 @@ impl Default for Configuration { actions_on_enter: vec![], actions_on_escape: vec![Action::Exit], actions_on_right_click: vec![], + actions_on_double_click: vec![], color_palette: ColorPalette::default(), default_hide_toolbars: false, focus_toggles_toolbars: false, @@ -765,6 +779,7 @@ struct ConfigurationFileGeneral { actions_on_enter: Option>, actions_on_escape: Option>, actions_on_right_click: Option>, + actions_on_double_click: Option>, default_hide_toolbars: Option, focus_toggles_toolbars: Option, default_fill_shapes: Option, diff --git a/src/sketch_board.rs b/src/sketch_board.rs index b63c7de..65cc2f4 100644 --- a/src/sketch_board.rs +++ b/src/sketch_board.rs @@ -193,12 +193,9 @@ impl InputEvent { if let InputEvent::Mouse(me) = self { match me.type_ { MouseEventType::Click => { - if me.button == MouseButton::Secondary { - renderer.request_render(&APP_CONFIG.read().actions_on_right_click()); - None - } else { - None - } + // Right-click and double-click are handled in update() where + // we have access to handle_undo() and full SketchBoard state. + None } MouseEventType::EndDrag | MouseEventType::UpdateDrag => { if me.button == MouseButton::Middle { @@ -285,6 +282,25 @@ impl SketchBoard { rv } + fn process_actions(&mut self, actions: &[Action]) -> ToolUpdateResult { + let mut render_actions = Vec::new(); + for action in actions { + match action { + Action::Undo => { + if !matches!(self.handle_undo(), ToolUpdateResult::Unmodified) { + return ToolUpdateResult::Redraw; + } + } + other => render_actions.push(*other), + } + } + if render_actions.is_empty() { + ToolUpdateResult::Unmodified + } else { + self.handle_action(&render_actions) + } + } + fn handle_render_result_with_pixbuf( &self, pix_buf: Option, @@ -1100,7 +1116,29 @@ impl Component for SketchBoard { ToolUpdateResult::StopPropagation | ToolUpdateResult::RedrawAndStopPropagation => active_tool_result, _ => { - if let Some(result) = ie.handle_mouse_event(&self.renderer) { + if let InputEvent::Mouse(ref me) = ie { + if me.type_ == MouseEventType::Click + && me.button == MouseButton::Secondary + { + self.process_actions( + &APP_CONFIG.read().actions_on_right_click(), + ) + } else if me.type_ == MouseEventType::Click + && me.button == MouseButton::Primary + && me.n_pressed >= 2 + { + let actions = APP_CONFIG.read().actions_on_double_click(); + if actions.is_empty() { + self.process_actions(&APP_CONFIG.read().actions_on_enter()) + } else { + self.process_actions(&actions) + } + } else if let Some(result) = ie.handle_mouse_event(&self.renderer) { + result + } else { + active_tool_result + } + } else if let Some(result) = ie.handle_mouse_event(&self.renderer) { result } else { active_tool_result