From 0472268adadd9d0b6986749f76263466a7e86715 Mon Sep 17 00:00:00 2001 From: Doublonmousse <115779707+Doublonmousse@users.noreply.github.com> Date: Mon, 10 Jun 2024 19:44:53 +0200 Subject: [PATCH 01/15] change the tool when hovering over the penpicker --- crates/rnote-ui/data/ui/penpicker.ui | 2 +- crates/rnote-ui/src/penpicker.rs | 41 ++++++++++++++++++++++++++-- 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/crates/rnote-ui/data/ui/penpicker.ui b/crates/rnote-ui/data/ui/penpicker.ui index 587c919c72..8cf0eff069 100644 --- a/crates/rnote-ui/data/ui/penpicker.ui +++ b/crates/rnote-ui/data/ui/penpicker.ui @@ -8,7 +8,7 @@ - + 6 350 true diff --git a/crates/rnote-ui/src/penpicker.rs b/crates/rnote-ui/src/penpicker.rs index 35b82650fd..b115b30702 100644 --- a/crates/rnote-ui/src/penpicker.rs +++ b/crates/rnote-ui/src/penpicker.rs @@ -1,10 +1,11 @@ // Imports use crate::RnAppWindow; use gtk4::{ - glib, glib::clone, prelude::*, subclass::prelude::*, Button, CompositeTemplate, TemplateChild, - ToggleButton, Widget, + gdk, glib, glib::clone, prelude::*, subclass::prelude::*, Box, Button, CompositeTemplate, + EventControllerLegacy, PropagationPhase, TemplateChild, ToggleButton, Widget, }; -use rnote_engine::pens::PenStyle; +use rnote_engine::pens::{PenMode, PenStyle}; +use rnote_engine::WidgetFlags; mod imp { use super::*; @@ -12,6 +13,8 @@ mod imp { #[derive(Default, Debug, CompositeTemplate)] #[template(resource = "/com/github/flxzt/rnote/ui/penpicker.ui")] pub(crate) struct RnPenPicker { + #[template_child] + pub(crate) toolbox: TemplateChild, #[template_child] pub(crate) brush_toggle: TemplateChild, #[template_child] @@ -108,6 +111,38 @@ impl RnPenPicker { pub(crate) fn init(&self, appwindow: &RnAppWindow) { let imp = self.imp(); + // create an event controller + let pointer_controller = EventControllerLegacy::builder() + .name("pointer_controller_toolbar") + .propagation_phase(PropagationPhase::Bubble) + .build(); + + pointer_controller.connect_event(clone!(@weak appwindow => @default-return glib::Propagation::Proceed, move |_,event| { + println!("{:?}",event); + + let mut widget_flags = WidgetFlags::default(); + let is_stylus = event.device_tool().is_some(); + if is_stylus { + let device_tool = event.device_tool().unwrap(); + match device_tool.tool_type() { + gdk::DeviceToolType::Pen => { + // switch the canvas to the pen + widget_flags |= appwindow.active_tab_wrapper().canvas().engine_mut().change_pen_mode(PenMode::Pen); + }, + gdk::DeviceToolType::Eraser => { + // switch the canvas to the eraser + widget_flags |= appwindow.active_tab_wrapper().canvas().engine_mut().change_pen_mode(PenMode::Eraser); + + }, + _ => (), + } + } + appwindow.active_tab_wrapper().canvas().emit_handle_widget_flags(widget_flags); + return glib::Propagation::Proceed + })); + + imp.toolbox.add_controller(pointer_controller); + imp.brush_toggle .connect_toggled(clone!(@weak appwindow => move |brush_toggle| { if brush_toggle.is_active() { From 6a3950f080a03d66df40ed8aa92e3da1167333cb Mon Sep 17 00:00:00 2001 From: Doublonmousse <115779707+Doublonmousse@users.noreply.github.com> Date: Tue, 11 Jun 2024 05:43:49 +0200 Subject: [PATCH 02/15] add a lock to pen styles --- crates/rnote-engine/src/pens/penholder.rs | 5 +++++ crates/rnote-engine/src/pens/penmode.rs | 21 +++++++++++++++++++++ crates/rnote-ui/src/appwindow/actions.rs | 23 +++++++++++++++++++---- crates/rnote-ui/src/penpicker.rs | 2 -- 4 files changed, 45 insertions(+), 6 deletions(-) diff --git a/crates/rnote-engine/src/pens/penholder.rs b/crates/rnote-engine/src/pens/penholder.rs index 66952fbe25..ed0cccaa27 100644 --- a/crates/rnote-engine/src/pens/penholder.rs +++ b/crates/rnote-engine/src/pens/penholder.rs @@ -121,6 +121,11 @@ impl PenHolder { self.pen_mode_state = pen_mode_state; } + /// mutable pen mode state + pub fn pen_mode_state_mut(&mut self) -> &mut PenModeState { + &mut self.pen_mode_state + } + pub fn backlog_policy(&self) -> BacklogPolicy { self.backlog_policy } diff --git a/crates/rnote-engine/src/pens/penmode.rs b/crates/rnote-engine/src/pens/penmode.rs index 53f34f4ef3..663d50b713 100644 --- a/crates/rnote-engine/src/pens/penmode.rs +++ b/crates/rnote-engine/src/pens/penmode.rs @@ -28,6 +28,10 @@ pub struct PenModeState { #[serde(rename = "penmode_eraser_style")] penmode_eraser_style: PenStyle, + //lock styles + penmode_pen_lock: bool, + penmode_eraser_lock: bool, + #[serde(skip)] penmode_pen_style_override: Option, #[serde(skip)] @@ -41,6 +45,9 @@ impl Default for PenModeState { penmode_pen_style: PenStyle::Brush, penmode_eraser_style: PenStyle::Eraser, + penmode_pen_lock: true, + penmode_eraser_lock: true, + penmode_pen_style_override: None, penmode_eraser_style_override: None, } @@ -59,6 +66,20 @@ impl CloneConfig for PenModeState { } impl PenModeState { + pub fn get_lock(&self) -> bool { + match self.pen_mode { + PenMode::Pen => self.penmode_pen_lock, + PenMode::Eraser => self.penmode_eraser_lock, + } + } + + pub fn unlock_pen(&mut self, pen_mode: PenMode) { + match pen_mode { + PenMode::Pen => self.penmode_pen_lock = false, + PenMode::Eraser => self.penmode_eraser_lock = false, + } + } + pub fn current_style_w_override(&self) -> PenStyle { match self.pen_mode { PenMode::Pen => self diff --git a/crates/rnote-ui/src/appwindow/actions.rs b/crates/rnote-ui/src/appwindow/actions.rs index dcf8237777..a03ecad5d5 100644 --- a/crates/rnote-ui/src/appwindow/actions.rs +++ b/crates/rnote-ui/src/appwindow/actions.rs @@ -334,13 +334,28 @@ impl RnAppWindow { // don't change the style if the current style with override is already the same // (e.g. when switched to from the pen button, not by clicking the pen page) if pen_style != canvas.engine_ref().penholder.current_pen_style_w_override() { + let lock_out = canvas.engine_ref().penholder.pen_mode_state().get_lock(); + let active_pen = canvas.engine_ref().penholder.pen_mode_state().pen_mode(); + if lock_out { + // display a popup that can unlock the pen tool + appwindow.overlays().dispatch_toast_w_button_singleton( + &gettext("Tool Locked"), + &gettext("Unlock"), //padlock symbol ? + clone!(@weak canvas => move |_reload_toast | { + canvas.engine_mut().penholder.pen_mode_state_mut().unlock_pen(active_pen); + } + ) + , 2, + &mut None); + // refresh the ui + appwindow.refresh_ui_from_engine(&appwindow.active_tab_wrapper()); + } else { let mut widget_flags = canvas.engine_mut().change_pen_style(pen_style); widget_flags |= canvas.engine_mut().change_pen_style_override(None); appwindow.handle_widget_flags(widget_flags, &canvas); - } - - action.set_state(&pen_style_str.to_variant()); - }), + action.set_state(&pen_style_str.to_variant()); + } + }}), ); // Tab actions diff --git a/crates/rnote-ui/src/penpicker.rs b/crates/rnote-ui/src/penpicker.rs index b115b30702..076c1b216f 100644 --- a/crates/rnote-ui/src/penpicker.rs +++ b/crates/rnote-ui/src/penpicker.rs @@ -118,8 +118,6 @@ impl RnPenPicker { .build(); pointer_controller.connect_event(clone!(@weak appwindow => @default-return glib::Propagation::Proceed, move |_,event| { - println!("{:?}",event); - let mut widget_flags = WidgetFlags::default(); let is_stylus = event.device_tool().is_some(); if is_stylus { From 573ff75b6e1cda8aa8bbb208d114d17e4037a485 Mon Sep 17 00:00:00 2001 From: Doublonmousse <115779707+Doublonmousse@users.noreply.github.com> Date: Sun, 16 Jun 2024 18:13:54 +0200 Subject: [PATCH 03/15] add buttons to the ui - the template has to be changed to accomodate the use of the buttons - the buttons are not yet linked to the settings --- crates/rnote-ui/data/resources.gresource.xml | 1 + crates/rnote-ui/data/ui/penmoderow.ui | 11 ++ crates/rnote-ui/data/ui/settingspanel.ui | 35 +++- crates/rnote-ui/src/settingspanel/mod.rs | 7 + .../rnote-ui/src/settingspanel/penmoderow.rs | 155 ++++++++++++++++++ 5 files changed, 208 insertions(+), 1 deletion(-) create mode 100644 crates/rnote-ui/data/ui/penmoderow.ui create mode 100644 crates/rnote-ui/src/settingspanel/penmoderow.rs diff --git a/crates/rnote-ui/data/resources.gresource.xml b/crates/rnote-ui/data/resources.gresource.xml index a1deb7af1f..65a76910f2 100644 --- a/crates/rnote-ui/data/resources.gresource.xml +++ b/crates/rnote-ui/data/resources.gresource.xml @@ -27,6 +27,7 @@ ui/overlays.ui ui/penpicker.ui ui/penshortcutrow.ui + ui/penmoderow.ui ui/settingspanel.ui ui/shortcuts.ui ui/sidebar.ui diff --git a/crates/rnote-ui/data/ui/penmoderow.ui b/crates/rnote-ui/data/ui/penmoderow.ui new file mode 100644 index 0000000000..854754520c --- /dev/null +++ b/crates/rnote-ui/data/ui/penmoderow.ui @@ -0,0 +1,11 @@ + + + + \ No newline at end of file diff --git a/crates/rnote-ui/data/ui/settingspanel.ui b/crates/rnote-ui/data/ui/settingspanel.ui index e1c205a8e7..effad4f8fc 100644 --- a/crates/rnote-ui/data/ui/settingspanel.ui +++ b/crates/rnote-ui/data/ui/settingspanel.ui @@ -519,6 +519,39 @@ on a drawing pad + + + + Pen/Eraser mode + + + Tool for the pen action + Set/lock the action for the pen + + + + drawing-pad-button-4-symbolic + large + + + + + + + + Tool for the eraser action + Set/lock the action for the pen + + + + drawing-pad-button-4-symbolic + large + + + + + + @@ -552,4 +585,4 @@ on a drawing pad 120 - + \ No newline at end of file diff --git a/crates/rnote-ui/src/settingspanel/mod.rs b/crates/rnote-ui/src/settingspanel/mod.rs index a713869c1f..654c9dd952 100644 --- a/crates/rnote-ui/src/settingspanel/mod.rs +++ b/crates/rnote-ui/src/settingspanel/mod.rs @@ -1,9 +1,12 @@ // Modules +mod penmoderow; mod penshortcutmodels; mod penshortcutrow; // Re-exports +pub(crate) use penmoderow::RnPenModeRow; pub(crate) use penshortcutrow::RnPenShortcutRow; + use rnote_compose::ext::Vector2Ext; // Imports @@ -113,6 +116,10 @@ mod imp { pub(crate) penshortcut_drawing_pad_button_2: TemplateChild, #[template_child] pub(crate) penshortcut_drawing_pad_button_3: TemplateChild, + #[template_child] + pub(crate) lock_pen_mode: TemplateChild, + #[template_child] + pub(crate) lock_eraser_mode: TemplateChild, } #[glib::object_subclass] diff --git a/crates/rnote-ui/src/settingspanel/penmoderow.rs b/crates/rnote-ui/src/settingspanel/penmoderow.rs new file mode 100644 index 0000000000..0df28bed1e --- /dev/null +++ b/crates/rnote-ui/src/settingspanel/penmoderow.rs @@ -0,0 +1,155 @@ +// Imports +use super::penshortcutmodels::{ + ChangePenStyleIconFactory, ChangePenStyleListFactory, ChangePenStyleListModel, +}; +use adw::{prelude::*, subclass::prelude::*}; +use gtk4::{glib, glib::clone, glib::subclass::*, CompositeTemplate}; +use num_traits::ToPrimitive; +use once_cell::sync::Lazy; +use rnote_engine::pens::shortcuts::ShortcutAction; +use rnote_engine::pens::shortcuts::ShortcutMode; +use rnote_engine::pens::PenStyle; +use std::cell::RefCell; + +mod imp { + use super::*; + + #[derive(Debug, CompositeTemplate)] + #[template(resource = "/com/github/flxzt/rnote/ui/penmoderow.ui")] + pub(crate) struct RnPenModeRow { + pub(crate) action: RefCell, + pub(crate) changepenstyle_model: ChangePenStyleListModel, + + #[template_child] + pub(crate) mode: TemplateChild, + } + + impl Default for RnPenModeRow { + fn default() -> Self { + Self { + action: RefCell::new(ShortcutAction::ChangePenStyle { + style: PenStyle::Eraser, + mode: ShortcutMode::Temporary, + }), + changepenstyle_model: ChangePenStyleListModel::default(), + + mode: TemplateChild::default(), + } + } + } + + #[glib::object_subclass] + impl ObjectSubclass for RnPenModeRow { + const NAME: &'static str = "RnPenModeRow"; + type Type = super::RnPenModeRow; + type ParentType = adw::ComboRow; + type Interfaces = (); + + fn class_init(klass: &mut Self::Class) { + klass.bind_template(); + } + + fn instance_init(obj: &glib::subclass::InitializingObject) { + obj.init_template(); + } + } + + impl ObjectImpl for RnPenModeRow { + fn constructed(&self) { + self.parent_constructed(); + let obj = self.obj(); + + let list_factory = ChangePenStyleListFactory::default(); + let icon_factory = ChangePenStyleIconFactory::default(); + + obj.set_model(Some(&*self.changepenstyle_model)); + obj.set_list_factory(Some(&*list_factory)); + obj.set_factory(Some(&*icon_factory)); + + obj.connect_selected_item_notify(move |row| { + let new_pen_style = row.pen_style(); + + match &mut *row.imp().action.borrow_mut() { + ShortcutAction::ChangePenStyle { style, .. } => { + *style = new_pen_style; + } + } + row.emit_by_name::<()>("action-changed", &[]); + }); + + // need to add the switch signal for the switch pen + self.mode.get().connect_active_notify(|_ev| { + println!("button pressed"); + }); + + obj.connect_local( + "action-changed", + false, + clone!(@weak obj as penshortcutrow => @default-return None, move |_values| { + penshortcutrow.update_ui(); + None + }), + ); + } + + fn dispose(&self) { + self.dispose_template(); + while let Some(child) = self.obj().first_child() { + child.unparent(); + } + } + fn signals() -> &'static [Signal] { + static SIGNALS: Lazy> = + Lazy::new(|| vec![Signal::builder("action-changed").build()]); + SIGNALS.as_ref() + } + } + + impl WidgetImpl for RnPenModeRow {} + impl ListBoxRowImpl for RnPenModeRow {} + impl PreferencesRowImpl for RnPenModeRow {} + impl ActionRowImpl for RnPenModeRow {} + impl ComboRowImpl for RnPenModeRow {} +} + +glib::wrapper! { + pub(crate) struct RnPenModeRow(ObjectSubclass) + @extends adw::ComboRow, adw::ActionRow, adw::PreferencesRow, gtk4::ListBoxRow, gtk4::Widget, + @implements gtk4::Accessible, gtk4::Actionable, gtk4::Buildable, gtk4::ConstraintTarget; +} + +impl RnPenModeRow { + #[allow(clippy::new_without_default)] + #[allow(unused)] + pub(crate) fn new() -> Self { + glib::Object::new() + } + + #[allow(unused)] + pub(crate) fn action(&self) -> ShortcutAction { + *self.imp().action.borrow() + } + + #[allow(unused)] + pub(crate) fn set_action(&self, action: ShortcutAction) { + *self.imp().action.borrow_mut() = action; + self.emit_by_name::<()>("action-changed", &[]); + } + + pub(crate) fn pen_style(&self) -> PenStyle { + PenStyle::try_from(self.selected()).unwrap() + } + + pub(crate) fn set_pen_style(&self, style: PenStyle) { + self.set_selected(style.to_u32().unwrap()) + } + + fn update_ui(&self) { + match self.action() { + // either need a new action or something else + ShortcutAction::ChangePenStyle { style, mode: _mode } => { + self.set_pen_style(style); + } + } + } +} From ebf77f10f7a037f3f96b35086a02ed3a00e53652 Mon Sep 17 00:00:00 2001 From: Doublonmousse <115779707+Doublonmousse@users.noreply.github.com> Date: Wed, 19 Jun 2024 13:32:10 +0200 Subject: [PATCH 04/15] add the lock settings to gsettings - added to the gsettings - shoud sync with the toggle TODO - sync the value with the actual lock value - do the same for the pen modes --- crates/rnote-ui/data/app.gschema.xml.in | 8 +++++++ crates/rnote-ui/src/appwindow/appsettings.rs | 12 ++++++++++ crates/rnote-ui/src/appwindow/imp.rs | 22 +++++++++++++++++++ crates/rnote-ui/src/appwindow/mod.rs | 10 +++++++++ crates/rnote-ui/src/settingspanel/mod.rs | 18 +++++++++++++++ .../rnote-ui/src/settingspanel/penmoderow.rs | 4 ++-- 6 files changed, 72 insertions(+), 2 deletions(-) diff --git a/crates/rnote-ui/data/app.gschema.xml.in b/crates/rnote-ui/data/app.gschema.xml.in index 040a243e5e..021da94277 100644 --- a/crates/rnote-ui/data/app.gschema.xml.in +++ b/crates/rnote-ui/data/app.gschema.xml.in @@ -169,5 +169,13 @@ '' the engine configuration + + false + lock the pen tool + + + true + lock the eraser tool + diff --git a/crates/rnote-ui/src/appwindow/appsettings.rs b/crates/rnote-ui/src/appwindow/appsettings.rs index 15fd69d2f5..4835da9fea 100644 --- a/crates/rnote-ui/src/appwindow/appsettings.rs +++ b/crates/rnote-ui/src/appwindow/appsettings.rs @@ -133,6 +133,18 @@ impl RnAppWindow { .get_no_changes() .build(); + // lock pen tool + app_settings + .bind("lock-pen", self, "lock-pen") + .get_no_changes() + .build(); + + // lock eraser tool + app_settings + .bind("lock-eraser", self, "lock-eraser") + .get_no_changes() + .build(); + // colorpicker palette let gdk_color_mapping = |var: &glib::Variant, _: glib::Type| { let color = var.get::<(f64, f64, f64, f64)>()?; diff --git a/crates/rnote-ui/src/appwindow/imp.rs b/crates/rnote-ui/src/appwindow/imp.rs index 0eb74f8bc6..4a74619ab9 100644 --- a/crates/rnote-ui/src/appwindow/imp.rs +++ b/crates/rnote-ui/src/appwindow/imp.rs @@ -25,6 +25,9 @@ pub(crate) struct RnAppWindow { pub(crate) touch_drawing: Cell, pub(crate) focus_mode: Cell, + pub(crate) lock_pen: Cell, + pub(crate) lock_eraser: Cell, + #[template_child] pub(crate) main_header: TemplateChild, #[template_child] @@ -52,6 +55,9 @@ impl Default for RnAppWindow { touch_drawing: Cell::new(false), focus_mode: Cell::new(false), + lock_pen: Cell::new(false), + lock_eraser: Cell::new(false), + main_header: TemplateChild::::default(), split_view: TemplateChild::::default(), sidebar: TemplateChild::::default(), @@ -135,6 +141,12 @@ impl ObjectImpl for RnAppWindow { glib::ParamSpecBoolean::builder("focus-mode") .default_value(false) .build(), + glib::ParamSpecBoolean::builder("lock-pen") + .default_value(false) + .build(), + glib::ParamSpecBoolean::builder("lock-eraser") + .default_value(false) + .build(), ] }); PROPERTIES.as_ref() @@ -149,6 +161,8 @@ impl ObjectImpl for RnAppWindow { "respect-borders" => self.respect_borders.get().to_value(), "touch-drawing" => self.touch_drawing.get().to_value(), "focus-mode" => self.focus_mode.get().to_value(), + "lock-pen" => self.lock_pen.get().to_value(), + "eraser-pen" => self.lock_eraser.get().to_value(), _ => unimplemented!(), } } @@ -212,6 +226,14 @@ impl ObjectImpl for RnAppWindow { self.overlays.colorpicker().set_visible(!focus_mode); self.overlays.sidebar_box().set_visible(!focus_mode); } + "lock-pen" => { + let lock_pen: bool = value.get().expect("The value needs to be of type `bool`"); + self.lock_pen.replace(lock_pen); + } + "lock-eraser" => { + let lock_eraser: bool = value.get().expect("The value needs to be of type `bool`"); + self.lock_eraser.replace(lock_eraser); + } _ => unimplemented!(), } } diff --git a/crates/rnote-ui/src/appwindow/mod.rs b/crates/rnote-ui/src/appwindow/mod.rs index 87b93aba9b..c064e8715f 100644 --- a/crates/rnote-ui/src/appwindow/mod.rs +++ b/crates/rnote-ui/src/appwindow/mod.rs @@ -89,6 +89,16 @@ impl RnAppWindow { self.property::("respect-borders") } + #[allow(unused)] + pub(crate) fn lock_pen(&self) -> bool { + self.property::("lock-pen") + } + + #[allow(unused)] + pub(crate) fn lock_eraser(&self) -> bool { + self.property::("lock-eraser") + } + pub(crate) fn app(&self) -> RnApp { self.application().unwrap().downcast::().unwrap() } diff --git a/crates/rnote-ui/src/settingspanel/mod.rs b/crates/rnote-ui/src/settingspanel/mod.rs index 654c9dd952..1a4002671c 100644 --- a/crates/rnote-ui/src/settingspanel/mod.rs +++ b/crates/rnote-ui/src/settingspanel/mod.rs @@ -582,6 +582,24 @@ impl RnSettingsPanel { } }), ); + + // lock pen + imp.lock_pen_mode + .imp() + .mode + .bind_property("active", appwindow, "lock-pen") + .sync_create() + .bidirectional() + .build(); + + // lock eraser + imp.lock_eraser_mode + .imp() + .mode + .bind_property("active", appwindow, "lock-eraser") + .sync_create() + .bidirectional() + .build(); } fn setup_format(&self, appwindow: &RnAppWindow) { diff --git a/crates/rnote-ui/src/settingspanel/penmoderow.rs b/crates/rnote-ui/src/settingspanel/penmoderow.rs index 0df28bed1e..5f0e5e3a5b 100644 --- a/crates/rnote-ui/src/settingspanel/penmoderow.rs +++ b/crates/rnote-ui/src/settingspanel/penmoderow.rs @@ -130,11 +130,11 @@ impl RnPenModeRow { *self.imp().action.borrow() } - #[allow(unused)] + /* #[allow(unused)] pub(crate) fn set_action(&self, action: ShortcutAction) { *self.imp().action.borrow_mut() = action; self.emit_by_name::<()>("action-changed", &[]); - } + } */ pub(crate) fn pen_style(&self) -> PenStyle { PenStyle::try_from(self.selected()).unwrap() From 4fddb120f90a239fec2ffdcd2b26315d96d29bdc Mon Sep 17 00:00:00 2001 From: Doublonmousse <115779707+Doublonmousse@users.noreply.github.com> Date: Wed, 19 Jun 2024 17:30:38 +0200 Subject: [PATCH 05/15] save lock state, and connect the buttons in the settings to the canvas --- crates/rnote-engine/src/pens/penmode.rs | 13 ++++++++++- crates/rnote-ui/src/appwindow/actions.rs | 3 ++- crates/rnote-ui/src/appwindow/imp.rs | 2 +- crates/rnote-ui/src/settingspanel/mod.rs | 28 ++++++++++++++++++++++++ 4 files changed, 43 insertions(+), 3 deletions(-) diff --git a/crates/rnote-engine/src/pens/penmode.rs b/crates/rnote-engine/src/pens/penmode.rs index 663d50b713..6ae9fd5490 100644 --- a/crates/rnote-engine/src/pens/penmode.rs +++ b/crates/rnote-engine/src/pens/penmode.rs @@ -29,7 +29,9 @@ pub struct PenModeState { penmode_eraser_style: PenStyle, //lock styles + #[serde(rename = "lock_pen")] penmode_pen_lock: bool, + #[serde(rename = "lock_eraser")] penmode_eraser_lock: bool, #[serde(skip)] @@ -45,7 +47,7 @@ impl Default for PenModeState { penmode_pen_style: PenStyle::Brush, penmode_eraser_style: PenStyle::Eraser, - penmode_pen_lock: true, + penmode_pen_lock: false, penmode_eraser_lock: true, penmode_pen_style_override: None, @@ -60,6 +62,8 @@ impl CloneConfig for PenModeState { pen_mode: self.pen_mode, penmode_pen_style: self.penmode_pen_style, penmode_eraser_style: self.penmode_eraser_style, + penmode_pen_lock: self.penmode_pen_lock, + penmode_eraser_lock: self.penmode_eraser_lock, ..Default::default() } } @@ -80,6 +84,13 @@ impl PenModeState { } } + pub fn set_lock(&mut self, pen_mode: PenMode, state: bool) { + match pen_mode { + PenMode::Pen => self.penmode_pen_lock = state, + PenMode::Eraser => self.penmode_eraser_lock = state, + } + } + pub fn current_style_w_override(&self) -> PenStyle { match self.pen_mode { PenMode::Pen => self diff --git a/crates/rnote-ui/src/appwindow/actions.rs b/crates/rnote-ui/src/appwindow/actions.rs index a03ecad5d5..5238d5cfd4 100644 --- a/crates/rnote-ui/src/appwindow/actions.rs +++ b/crates/rnote-ui/src/appwindow/actions.rs @@ -341,8 +341,9 @@ impl RnAppWindow { appwindow.overlays().dispatch_toast_w_button_singleton( &gettext("Tool Locked"), &gettext("Unlock"), //padlock symbol ? - clone!(@weak canvas => move |_reload_toast | { + clone!(@weak canvas, @weak appwindow => move |_reload_toast | { canvas.engine_mut().penholder.pen_mode_state_mut().unlock_pen(active_pen); + appwindow.sidebar().settings_panel().lock_pen_switch().set_state(false); } ) , 2, diff --git a/crates/rnote-ui/src/appwindow/imp.rs b/crates/rnote-ui/src/appwindow/imp.rs index 4a74619ab9..2e983bdaa3 100644 --- a/crates/rnote-ui/src/appwindow/imp.rs +++ b/crates/rnote-ui/src/appwindow/imp.rs @@ -162,7 +162,7 @@ impl ObjectImpl for RnAppWindow { "touch-drawing" => self.touch_drawing.get().to_value(), "focus-mode" => self.focus_mode.get().to_value(), "lock-pen" => self.lock_pen.get().to_value(), - "eraser-pen" => self.lock_eraser.get().to_value(), + "lock-eraser" => self.lock_eraser.get().to_value(), _ => unimplemented!(), } } diff --git a/crates/rnote-ui/src/settingspanel/mod.rs b/crates/rnote-ui/src/settingspanel/mod.rs index 1a4002671c..183b5e87cf 100644 --- a/crates/rnote-ui/src/settingspanel/mod.rs +++ b/crates/rnote-ui/src/settingspanel/mod.rs @@ -351,6 +351,10 @@ impl RnSettingsPanel { self.imp().general_inertial_scrolling_row.clone() } + pub(crate) fn lock_pen_switch(&self) -> gtk4::Switch { + self.imp().lock_pen_mode.imp().mode.clone() + } + pub(crate) fn document_layout(&self) -> Layout { Layout::try_from(self.imp().doc_document_layout_row.get().selected()).unwrap() } @@ -592,6 +596,18 @@ impl RnSettingsPanel { .bidirectional() .build(); + imp.lock_pen_mode.imp().mode.connect_active_notify( + clone!(@weak appwindow => move |switch| { + appwindow + .active_tab_wrapper() + .canvas() + .engine_mut() + .penholder + .pen_mode_state_mut() + .set_lock(rnote_engine::pens::PenMode::Pen,switch.is_active()); + }), + ); + // lock eraser imp.lock_eraser_mode .imp() @@ -600,6 +616,18 @@ impl RnSettingsPanel { .sync_create() .bidirectional() .build(); + + imp.lock_eraser_mode.imp().mode.connect_active_notify( + clone!(@weak appwindow => move |switch| { + appwindow + .active_tab_wrapper() + .canvas() + .engine_mut() + .penholder + .pen_mode_state_mut() + .set_lock(rnote_engine::pens::PenMode::Pen,switch.is_active()); + }), + ); } fn setup_format(&self, appwindow: &RnAppWindow) { From 51a51bad17c960edfc0d4627fd7b0bea2e0900e0 Mon Sep 17 00:00:00 2001 From: Doublonmousse <115779707+Doublonmousse@users.noreply.github.com> Date: Wed, 19 Jun 2024 18:18:59 +0200 Subject: [PATCH 06/15] fix compile and ui issue --- crates/rnote-ui/src/appwindow/actions.rs | 3 ++- crates/rnote-ui/src/settingspanel/mod.rs | 8 ++++++-- crates/rnote-ui/src/settingspanel/penmoderow.rs | 14 +++++++------- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/crates/rnote-ui/src/appwindow/actions.rs b/crates/rnote-ui/src/appwindow/actions.rs index 5238d5cfd4..97a032c766 100644 --- a/crates/rnote-ui/src/appwindow/actions.rs +++ b/crates/rnote-ui/src/appwindow/actions.rs @@ -343,7 +343,8 @@ impl RnAppWindow { &gettext("Unlock"), //padlock symbol ? clone!(@weak canvas, @weak appwindow => move |_reload_toast | { canvas.engine_mut().penholder.pen_mode_state_mut().unlock_pen(active_pen); - appwindow.sidebar().settings_panel().lock_pen_switch().set_state(false); + appwindow.sidebar().settings_panel().set_lock_state(active_pen,false); + appwindow.sidebar().settings_panel().refresh_ui(&appwindow.active_tab_wrapper()); } ) , 2, diff --git a/crates/rnote-ui/src/settingspanel/mod.rs b/crates/rnote-ui/src/settingspanel/mod.rs index 183b5e87cf..c6931fb4fd 100644 --- a/crates/rnote-ui/src/settingspanel/mod.rs +++ b/crates/rnote-ui/src/settingspanel/mod.rs @@ -8,6 +8,7 @@ pub(crate) use penmoderow::RnPenModeRow; pub(crate) use penshortcutrow::RnPenShortcutRow; use rnote_compose::ext::Vector2Ext; +use rnote_engine::pens::PenMode; // Imports use crate::{RnAppWindow, RnCanvasWrapper, RnIconPicker, RnUnitEntry}; @@ -351,8 +352,11 @@ impl RnSettingsPanel { self.imp().general_inertial_scrolling_row.clone() } - pub(crate) fn lock_pen_switch(&self) -> gtk4::Switch { - self.imp().lock_pen_mode.imp().mode.clone() + pub(crate) fn set_lock_state(&self, pen_mode: PenMode, state: bool) { + match pen_mode { + PenMode::Pen => self.imp().lock_pen_mode.get().set_lock_state(state), + PenMode::Eraser => self.imp().lock_eraser_mode.get().set_lock_state(state), + } } pub(crate) fn document_layout(&self) -> Layout { diff --git a/crates/rnote-ui/src/settingspanel/penmoderow.rs b/crates/rnote-ui/src/settingspanel/penmoderow.rs index 5f0e5e3a5b..b7e097a5a4 100644 --- a/crates/rnote-ui/src/settingspanel/penmoderow.rs +++ b/crates/rnote-ui/src/settingspanel/penmoderow.rs @@ -77,11 +77,6 @@ mod imp { row.emit_by_name::<()>("action-changed", &[]); }); - // need to add the switch signal for the switch pen - self.mode.get().connect_active_notify(|_ev| { - println!("button pressed"); - }); - obj.connect_local( "action-changed", false, @@ -130,11 +125,11 @@ impl RnPenModeRow { *self.imp().action.borrow() } - /* #[allow(unused)] + #[allow(unused)] pub(crate) fn set_action(&self, action: ShortcutAction) { *self.imp().action.borrow_mut() = action; self.emit_by_name::<()>("action-changed", &[]); - } */ + } pub(crate) fn pen_style(&self) -> PenStyle { PenStyle::try_from(self.selected()).unwrap() @@ -144,6 +139,11 @@ impl RnPenModeRow { self.set_selected(style.to_u32().unwrap()) } + pub(crate) fn set_lock_state(&self, state: bool) { + self.imp().mode.get().set_state(state); + self.imp().mode.get().set_active(state); + } + fn update_ui(&self) { match self.action() { // either need a new action or something else From 19a6f1654a113bf65261bb72bf33cbdd87244bbc Mon Sep 17 00:00:00 2001 From: Doublonmousse <115779707+Doublonmousse@users.noreply.github.com> Date: Wed, 19 Jun 2024 22:43:10 +0200 Subject: [PATCH 07/15] more links partial implementation of links between the pen choice and the settings button (only in that direction, the reverse still segfaults) --- crates/rnote-engine/src/pens/penmode.rs | 19 +++++++++- crates/rnote-ui/src/settingspanel/mod.rs | 38 +++++++++++++++++++ .../rnote-ui/src/settingspanel/penmoderow.rs | 21 ++++------ 3 files changed, 63 insertions(+), 15 deletions(-) diff --git a/crates/rnote-engine/src/pens/penmode.rs b/crates/rnote-engine/src/pens/penmode.rs index 6ae9fd5490..de195c3688 100644 --- a/crates/rnote-engine/src/pens/penmode.rs +++ b/crates/rnote-engine/src/pens/penmode.rs @@ -1,4 +1,5 @@ use crate::CloneConfig; +use std::cell::RefCell; // Imports use super::PenStyle; @@ -62,8 +63,8 @@ impl CloneConfig for PenModeState { pen_mode: self.pen_mode, penmode_pen_style: self.penmode_pen_style, penmode_eraser_style: self.penmode_eraser_style, - penmode_pen_lock: self.penmode_pen_lock, - penmode_eraser_lock: self.penmode_eraser_lock, + penmode_pen_lock: self.penmode_pen_lock.clone(), + penmode_eraser_lock: self.penmode_eraser_lock.clone(), ..Default::default() } } @@ -114,6 +115,20 @@ impl PenModeState { } } + pub fn get_style(&self, penmode: PenMode) -> PenStyle { + match penmode { + PenMode::Pen => self.penmode_pen_style, + PenMode::Eraser => self.penmode_eraser_style, + } + } + + pub fn set_style_single_mode(&mut self, mode: PenMode, style: PenStyle) { + match mode { + PenMode::Pen => self.penmode_pen_style = style, + PenMode::Eraser => self.penmode_eraser_style = style, + } + } + pub fn set_style(&mut self, style: PenStyle) { match self.pen_mode { PenMode::Pen => self.penmode_pen_style = style, diff --git a/crates/rnote-ui/src/settingspanel/mod.rs b/crates/rnote-ui/src/settingspanel/mod.rs index c6931fb4fd..7d565b7bee 100644 --- a/crates/rnote-ui/src/settingspanel/mod.rs +++ b/crates/rnote-ui/src/settingspanel/mod.rs @@ -374,6 +374,7 @@ impl RnSettingsPanel { self.refresh_format_ui(active_tab); self.refresh_doc_ui(active_tab); self.refresh_shortcuts_ui(active_tab); + self.refresh_locks_ui(active_tab); } fn refresh_general_ui(&self, active_tab: &RnCanvasWrapper) { @@ -468,6 +469,27 @@ impl RnSettingsPanel { }); } + fn refresh_locks_ui(&self, active_tab: &RnCanvasWrapper) { + let imp = self.imp(); + let canvas = active_tab.canvas(); + + imp.lock_pen_mode.set_action( + canvas + .engine_ref() + .penholder + .pen_mode_state() + .get_style(PenMode::Pen), + ); + + imp.lock_eraser_mode.set_action( + canvas + .engine_ref() + .penholder + .pen_mode_state() + .get_style(PenMode::Eraser), + ); + } + pub(crate) fn init(&self, appwindow: &RnAppWindow) { self.setup_general(appwindow); self.setup_format(appwindow); @@ -883,6 +905,22 @@ impl RnSettingsPanel { appwindow.active_tab_wrapper().canvas().engine_mut().penholder.register_shortcut(ShortcutKey::DrawingPadButton3, action); None })); + + let lock_pen = imp.lock_pen_mode.get(); + let lock_eraser = imp.lock_eraser_mode.get(); + + imp.lock_pen_mode.connect_local("action-changed",false, clone!(@weak lock_pen, @weak appwindow => @default-return None, move |_values| { + let action = lock_pen.action(); + // BorrowMut with this ... + appwindow.active_tab_wrapper().canvas().engine_mut().penholder.pen_mode_state_mut().set_style_single_mode(PenMode::Pen, action); + None + })); + + imp.lock_eraser_mode.connect_local("action-changed",false, clone!(@weak lock_pen, @weak appwindow => @default-return None, move |_values| { + let action = lock_eraser.action(); + appwindow.active_tab_wrapper().canvas().engine_mut().penholder.pen_mode_state_mut().set_style_single_mode(PenMode::Eraser, action); + None + })); } fn revert_format(&self, appwindow: &RnAppWindow) { diff --git a/crates/rnote-ui/src/settingspanel/penmoderow.rs b/crates/rnote-ui/src/settingspanel/penmoderow.rs index b7e097a5a4..17b5cb264a 100644 --- a/crates/rnote-ui/src/settingspanel/penmoderow.rs +++ b/crates/rnote-ui/src/settingspanel/penmoderow.rs @@ -6,8 +6,6 @@ use adw::{prelude::*, subclass::prelude::*}; use gtk4::{glib, glib::clone, glib::subclass::*, CompositeTemplate}; use num_traits::ToPrimitive; use once_cell::sync::Lazy; -use rnote_engine::pens::shortcuts::ShortcutAction; -use rnote_engine::pens::shortcuts::ShortcutMode; use rnote_engine::pens::PenStyle; use std::cell::RefCell; @@ -17,7 +15,7 @@ mod imp { #[derive(Debug, CompositeTemplate)] #[template(resource = "/com/github/flxzt/rnote/ui/penmoderow.ui")] pub(crate) struct RnPenModeRow { - pub(crate) action: RefCell, + pub(crate) action: RefCell, pub(crate) changepenstyle_model: ChangePenStyleListModel, #[template_child] @@ -27,10 +25,7 @@ mod imp { impl Default for RnPenModeRow { fn default() -> Self { Self { - action: RefCell::new(ShortcutAction::ChangePenStyle { - style: PenStyle::Eraser, - mode: ShortcutMode::Temporary, - }), + action: RefCell::new(PenStyle::Eraser), changepenstyle_model: ChangePenStyleListModel::default(), mode: TemplateChild::default(), @@ -70,10 +65,11 @@ mod imp { let new_pen_style = row.pen_style(); match &mut *row.imp().action.borrow_mut() { - ShortcutAction::ChangePenStyle { style, .. } => { - *style = new_pen_style; + current_style => { + *current_style = new_pen_style; } } + row.emit_by_name::<()>("action-changed", &[]); }); @@ -121,12 +117,12 @@ impl RnPenModeRow { } #[allow(unused)] - pub(crate) fn action(&self) -> ShortcutAction { + pub(crate) fn action(&self) -> PenStyle { *self.imp().action.borrow() } #[allow(unused)] - pub(crate) fn set_action(&self, action: ShortcutAction) { + pub(crate) fn set_action(&self, action: PenStyle) { *self.imp().action.borrow_mut() = action; self.emit_by_name::<()>("action-changed", &[]); } @@ -146,8 +142,7 @@ impl RnPenModeRow { fn update_ui(&self) { match self.action() { - // either need a new action or something else - ShortcutAction::ChangePenStyle { style, mode: _mode } => { + style => { self.set_pen_style(style); } } From 032f7539c5f006db92fd9b4b0eac4b2d98f8c53c Mon Sep 17 00:00:00 2001 From: Doublonmousse <115779707+Doublonmousse@users.noreply.github.com> Date: Thu, 20 Jun 2024 12:43:17 +0200 Subject: [PATCH 08/15] Settings -> canvas links plus a couple of bug fixes --- crates/rnote-engine/src/engine/mod.rs | 16 +++++++++ crates/rnote-engine/src/pens/penholder.rs | 38 ++++++++++++++++++++ crates/rnote-engine/src/pens/penmode.rs | 1 - crates/rnote-ui/src/appwindow/actions.rs | 42 ++++++++++++++++++++++- crates/rnote-ui/src/appwindow/imp.rs | 2 +- crates/rnote-ui/src/settingspanel/mod.rs | 28 +++++++++------ 6 files changed, 113 insertions(+), 14 deletions(-) diff --git a/crates/rnote-engine/src/engine/mod.rs b/crates/rnote-engine/src/engine/mod.rs index 0d4e4ff653..c0cca51d9b 100644 --- a/crates/rnote-engine/src/engine/mod.rs +++ b/crates/rnote-engine/src/engine/mod.rs @@ -525,6 +525,22 @@ impl Engine { ) } + /// Change the pen or earser style. + pub fn change_pen_eraser_style(&mut self, mode: PenMode, new_style: PenStyle) -> WidgetFlags { + self.penholder.change_style_single_mode( + mode, + new_style, + &mut EngineViewMut { + tasks_tx: self.engine_tasks_tx(), + pens_config: &mut self.pens_config, + document: &mut self.document, + store: &mut self.store, + camera: &mut self.camera, + audioplayer: &mut self.audioplayer, + }, + ) + } + /// Change the pen style (temporary) override. pub fn change_pen_style_override( &mut self, diff --git a/crates/rnote-engine/src/pens/penholder.rs b/crates/rnote-engine/src/pens/penholder.rs index ed0cccaa27..38603fffbd 100644 --- a/crates/rnote-engine/src/pens/penholder.rs +++ b/crates/rnote-engine/src/pens/penholder.rs @@ -167,6 +167,21 @@ impl PenHolder { widget_flags } + /// Change the pen or eraser style. + pub fn change_style_single_mode( + &mut self, + mode: PenMode, + new_style: PenStyle, + engine_view: &mut EngineViewMut, + ) -> WidgetFlags { + let widget_flags = self.change_style_pen_eraser_int(new_style, mode, engine_view); + // When the style is changed externally, the toggle mode / internal states are reset + self.toggle_pen_style = None; + self.prev_shortcut_key = None; + + widget_flags + } + /// Change the style override. pub fn change_style_override( &mut self, @@ -357,6 +372,29 @@ impl PenHolder { widget_flags } + /// Internal method for changing the pen/eraser style, without some of the side effects that are happening in the public + /// method. + fn change_style_pen_eraser_int( + &mut self, + new_style: PenStyle, + mode: PenMode, + engine_view: &mut EngineViewMut, + ) -> WidgetFlags { + let mut widget_flags = WidgetFlags::default(); + + if self.pen_mode_state.get_style(mode) != new_style { + // Deselecting when changing the style + let all_strokes = engine_view.store.selection_keys_as_rendered(); + engine_view.store.set_selected_keys(&all_strokes, false); + + self.pen_mode_state.set_style_single_mode(mode, new_style); + widget_flags |= self.reinstall_pen_current_style(engine_view); + widget_flags.refresh_ui = true; + } + + widget_flags + } + /// Handles the pen event in the global scope if the current pen has not handled it. /// /// Used to implement things like nudging the view, react to pressed buttons that weren't handled by th pen, .. diff --git a/crates/rnote-engine/src/pens/penmode.rs b/crates/rnote-engine/src/pens/penmode.rs index de195c3688..5e0a549f2b 100644 --- a/crates/rnote-engine/src/pens/penmode.rs +++ b/crates/rnote-engine/src/pens/penmode.rs @@ -1,5 +1,4 @@ use crate::CloneConfig; -use std::cell::RefCell; // Imports use super::PenStyle; diff --git a/crates/rnote-ui/src/appwindow/actions.rs b/crates/rnote-ui/src/appwindow/actions.rs index 97a032c766..d20cf953dc 100644 --- a/crates/rnote-ui/src/appwindow/actions.rs +++ b/crates/rnote-ui/src/appwindow/actions.rs @@ -10,6 +10,7 @@ use p2d::bounding_volume::BoundingVolume; use rnote_compose::penevent::ShortcutKey; use rnote_compose::SplitOrder; use rnote_engine::engine::StrokeContent; +use rnote_engine::pens::PenMode; use rnote_engine::pens::PenStyle; use rnote_engine::strokes::resize::{ImageSizeOption, Resize}; use rnote_engine::{Camera, Engine}; @@ -91,6 +92,11 @@ impl RnAppWindow { &String::from("brush").to_variant(), ); self.add_action(&action_pen_style); + let action_change_pen_styles = gio::SimpleAction::new( + "pen-styles", + Some(&<(String, String)>::static_variant_type()), + ); + self.add_action(&action_change_pen_styles); let action_undo_stroke = gio::SimpleAction::new("undo", None); self.add_action(&action_undo_stroke); let action_redo_stroke = gio::SimpleAction::new("redo", None); @@ -340,7 +346,7 @@ impl RnAppWindow { // display a popup that can unlock the pen tool appwindow.overlays().dispatch_toast_w_button_singleton( &gettext("Tool Locked"), - &gettext("Unlock"), //padlock symbol ? + &gettext("Unlock"), clone!(@weak canvas, @weak appwindow => move |_reload_toast | { canvas.engine_mut().penholder.pen_mode_state_mut().unlock_pen(active_pen); appwindow.sidebar().settings_panel().set_lock_state(active_pen,false); @@ -360,6 +366,40 @@ impl RnAppWindow { }}), ); + // action to change pen or eraser style (activated from the settings panel) + action_change_pen_styles.connect_activate( + clone!(@weak self as appwindow => move |_action,target| { + let (pen_type_str,tool_str) = target.unwrap().get::<(String,String)>().unwrap(); + + let pen_mode = match pen_type_str.as_str() { + "pen" => PenMode::Pen, + "eraser" => PenMode::Eraser, + other => { + tracing::error!("the pen style does not exist (either `pen` or `eraser` should be given as string, got {other:}"); + return; + } + }; + + let pen_style = match PenStyle::from_str(tool_str.as_str()) { + Ok(s) => s, + Err(e) => { + tracing::error!("Activated pen-style action with invalid target, Err: {e:}"); + return; + } + }; + let canvas = appwindow.active_tab_wrapper().canvas(); + + // Changes the underlying values only if they are different from the current ones + // This prevents circular calls between the settings panel and the canvas + let current_pen = canvas.engine_ref().penholder.pen_mode_state().get_style(pen_mode); + if current_pen != pen_style { + let mut widget_flags = canvas.engine_mut().change_pen_eraser_style(pen_mode,pen_style); + widget_flags |= canvas.engine_mut().change_pen_style_override(None); + appwindow.handle_widget_flags(widget_flags, &canvas); + } + }), + ); + // Tab actions action_active_tab_move_left.connect_activate( clone!(@weak self as appwindow => move |_, _| { diff --git a/crates/rnote-ui/src/appwindow/imp.rs b/crates/rnote-ui/src/appwindow/imp.rs index 2e983bdaa3..fdf6ebe8a1 100644 --- a/crates/rnote-ui/src/appwindow/imp.rs +++ b/crates/rnote-ui/src/appwindow/imp.rs @@ -145,7 +145,7 @@ impl ObjectImpl for RnAppWindow { .default_value(false) .build(), glib::ParamSpecBoolean::builder("lock-eraser") - .default_value(false) + .default_value(true) .build(), ] }); diff --git a/crates/rnote-ui/src/settingspanel/mod.rs b/crates/rnote-ui/src/settingspanel/mod.rs index 7d565b7bee..c0257c978b 100644 --- a/crates/rnote-ui/src/settingspanel/mod.rs +++ b/crates/rnote-ui/src/settingspanel/mod.rs @@ -651,7 +651,7 @@ impl RnSettingsPanel { .engine_mut() .penholder .pen_mode_state_mut() - .set_lock(rnote_engine::pens::PenMode::Pen,switch.is_active()); + .set_lock(rnote_engine::pens::PenMode::Eraser,switch.is_active()); }), ); } @@ -909,17 +909,23 @@ impl RnSettingsPanel { let lock_pen = imp.lock_pen_mode.get(); let lock_eraser = imp.lock_eraser_mode.get(); - imp.lock_pen_mode.connect_local("action-changed",false, clone!(@weak lock_pen, @weak appwindow => @default-return None, move |_values| { - let action = lock_pen.action(); - // BorrowMut with this ... - appwindow.active_tab_wrapper().canvas().engine_mut().penholder.pen_mode_state_mut().set_style_single_mode(PenMode::Pen, action); - None - })); + imp.lock_pen_mode.connect_local( + "action-changed", + false, + clone!(@weak lock_pen, @weak appwindow => @default-return None, move |_values| { + let action = lock_pen.action(); + adw::prelude::ActionGroupExt::activate_action(&appwindow, "pen-styles", Some(&("pen",action.to_string()).to_variant())); + None + }), + ); - imp.lock_eraser_mode.connect_local("action-changed",false, clone!(@weak lock_pen, @weak appwindow => @default-return None, move |_values| { - let action = lock_eraser.action(); - appwindow.active_tab_wrapper().canvas().engine_mut().penholder.pen_mode_state_mut().set_style_single_mode(PenMode::Eraser, action); - None + imp.lock_eraser_mode.connect_local( + "action-changed", + false, + clone!(@weak lock_eraser, @weak appwindow => @default-return None, move |_values| { + let action = lock_eraser.action(); + adw::prelude::ActionGroupExt::activate_action(&appwindow, "pen-styles", Some(&("eraser",action.to_string()).to_variant())); + None })); } From 20b7a710e147cb9c88a46ac1c9070f1dea424fcb Mon Sep 17 00:00:00 2001 From: Doublonmousse <115779707+Doublonmousse@users.noreply.github.com> Date: Sat, 22 Jun 2024 20:12:08 +0200 Subject: [PATCH 09/15] update icons --- .../scalable/actions/stylus-pen-symbolic.svg | 35 +++++++++++++++++++ crates/rnote-ui/data/meson.build | 1 + crates/rnote-ui/data/resources.gresource.xml | 1 + crates/rnote-ui/data/ui/settingspanel.ui | 7 ++-- 4 files changed, 39 insertions(+), 5 deletions(-) create mode 100644 crates/rnote-ui/data/icons/scalable/actions/stylus-pen-symbolic.svg diff --git a/crates/rnote-ui/data/icons/scalable/actions/stylus-pen-symbolic.svg b/crates/rnote-ui/data/icons/scalable/actions/stylus-pen-symbolic.svg new file mode 100644 index 0000000000..94b652ca16 --- /dev/null +++ b/crates/rnote-ui/data/icons/scalable/actions/stylus-pen-symbolic.svg @@ -0,0 +1,35 @@ + + + + + + + + + + + + + diff --git a/crates/rnote-ui/data/meson.build b/crates/rnote-ui/data/meson.build index 6993e594ba..345e7f76c2 100644 --- a/crates/rnote-ui/data/meson.build +++ b/crates/rnote-ui/data/meson.build @@ -204,6 +204,7 @@ rnote_ui_gresources_icons_files = files( 'icons/scalable/actions/drawing-pad-button-2-symbolic.svg', 'icons/scalable/actions/drawing-pad-button-3-symbolic.svg', 'icons/scalable/actions/drawing-pad-button-4-symbolic.svg', + 'icons/scalable/actions/stylus-pen-symbolic.svg', 'icons/scalable/actions/edit-redo-symbolic.svg', 'icons/scalable/actions/edit-symbolic.svg', 'icons/scalable/actions/edit-undo-symbolic.svg', diff --git a/crates/rnote-ui/data/resources.gresource.xml b/crates/rnote-ui/data/resources.gresource.xml index 65a76910f2..4fba388a68 100644 --- a/crates/rnote-ui/data/resources.gresource.xml +++ b/crates/rnote-ui/data/resources.gresource.xml @@ -74,6 +74,7 @@ icons/scalable/actions/drawing-pad-button-2-symbolic.svg icons/scalable/actions/drawing-pad-button-3-symbolic.svg icons/scalable/actions/drawing-pad-button-4-symbolic.svg + icons/scalable/actions/stylus-pen-symbolic.svg icons/scalable/actions/edit-redo-symbolic.svg icons/scalable/actions/edit-symbolic.svg icons/scalable/actions/edit-undo-symbolic.svg diff --git a/crates/rnote-ui/data/ui/settingspanel.ui b/crates/rnote-ui/data/ui/settingspanel.ui index effad4f8fc..4f6f683ffe 100644 --- a/crates/rnote-ui/data/ui/settingspanel.ui +++ b/crates/rnote-ui/data/ui/settingspanel.ui @@ -527,10 +527,9 @@ on a drawing pad Tool for the pen action Set/lock the action for the pen - - drawing-pad-button-4-symbolic + stylus-pen-symbolic large @@ -538,13 +537,11 @@ on a drawing pad - Tool for the eraser action Set/lock the action for the pen - - drawing-pad-button-4-symbolic + stylus-button-eraser-symbolic large From 5e95a0b831f818a5fcb5f6a7bd24d720f3774955 Mon Sep 17 00:00:00 2001 From: Doublonmousse <115779707+Doublonmousse@users.noreply.github.com> Date: Sat, 22 Jun 2024 20:42:21 +0200 Subject: [PATCH 10/15] remove duplicate functions --- crates/rnote-engine/src/engine/import.rs | 6 +-- crates/rnote-engine/src/engine/mod.rs | 21 ++------- crates/rnote-engine/src/pens/penholder.rs | 52 ++++------------------- crates/rnote-engine/src/pens/penmode.rs | 11 +---- crates/rnote-ui/src/appwindow/actions.rs | 4 +- 5 files changed, 18 insertions(+), 76 deletions(-) diff --git a/crates/rnote-engine/src/engine/import.rs b/crates/rnote-engine/src/engine/import.rs index c4beefff3e..f49e1bc769 100644 --- a/crates/rnote-engine/src/engine/import.rs +++ b/crates/rnote-engine/src/engine/import.rs @@ -386,7 +386,7 @@ impl Engine { self.store.set_selected_keys(&all_strokes, false); if select { - widget_flags |= self.change_pen_style(PenStyle::Selector); + widget_flags |= self.change_pen_style(PenStyle::Selector, None); } if adjust_document { @@ -426,7 +426,7 @@ impl Engine { let all_strokes = self.store.stroke_keys_as_rendered(); self.store.set_selected_keys(&all_strokes, false); - widget_flags |= self.change_pen_style(PenStyle::Typewriter); + widget_flags |= self.change_pen_style(PenStyle::Typewriter, None); if let Pen::Typewriter(typewriter) = self.penholder.current_pen_mut() { widget_flags |= typewriter.insert_text( @@ -463,7 +463,7 @@ impl Engine { // even though changing the pen style deselects too, but only when the pen is actually different. let all_strokes = self.store.stroke_keys_as_rendered(); self.store.set_selected_keys(&all_strokes, false); - widget_flags |= self.change_pen_style(PenStyle::Selector); + widget_flags |= self.change_pen_style(PenStyle::Selector, None); // calculate ratio let ratio = match resize { diff --git a/crates/rnote-engine/src/engine/mod.rs b/crates/rnote-engine/src/engine/mod.rs index c0cca51d9b..8c93489e0a 100644 --- a/crates/rnote-engine/src/engine/mod.rs +++ b/crates/rnote-engine/src/engine/mod.rs @@ -511,25 +511,10 @@ impl Engine { } /// Change the pen style. - pub fn change_pen_style(&mut self, new_style: PenStyle) -> WidgetFlags { + pub fn change_pen_style(&mut self, new_style: PenStyle, mode: Option) -> WidgetFlags { self.penholder.change_style( new_style, - &mut EngineViewMut { - tasks_tx: self.engine_tasks_tx(), - pens_config: &mut self.pens_config, - document: &mut self.document, - store: &mut self.store, - camera: &mut self.camera, - audioplayer: &mut self.audioplayer, - }, - ) - } - - /// Change the pen or earser style. - pub fn change_pen_eraser_style(&mut self, mode: PenMode, new_style: PenStyle) -> WidgetFlags { - self.penholder.change_style_single_mode( mode, - new_style, &mut EngineViewMut { tasks_tx: self.engine_tasks_tx(), pens_config: &mut self.pens_config, @@ -826,7 +811,7 @@ impl Engine { } pub fn select_all_strokes(&mut self) -> WidgetFlags { - let widget_flags = self.change_pen_style(PenStyle::Selector); + let widget_flags = self.change_pen_style(PenStyle::Selector, None); self.store .set_selected_keys(&self.store.stroke_keys_as_rendered(), true); widget_flags @@ -837,7 +822,7 @@ impl Engine { } pub fn deselect_all_strokes(&mut self) -> WidgetFlags { - let widget_flags = self.change_pen_style(PenStyle::Selector); + let widget_flags = self.change_pen_style(PenStyle::Selector, None); self.store .set_selected_keys(&self.store.selection_keys_as_rendered(), false); widget_flags diff --git a/crates/rnote-engine/src/pens/penholder.rs b/crates/rnote-engine/src/pens/penholder.rs index 38603fffbd..ef16582079 100644 --- a/crates/rnote-engine/src/pens/penholder.rs +++ b/crates/rnote-engine/src/pens/penholder.rs @@ -157,24 +157,10 @@ impl PenHolder { pub fn change_style( &mut self, new_style: PenStyle, + mode: Option, engine_view: &mut EngineViewMut, ) -> WidgetFlags { - let widget_flags = self.change_style_int(new_style, engine_view); - // When the style is changed externally, the toggle mode / internal states are reset - self.toggle_pen_style = None; - self.prev_shortcut_key = None; - - widget_flags - } - - /// Change the pen or eraser style. - pub fn change_style_single_mode( - &mut self, - mode: PenMode, - new_style: PenStyle, - engine_view: &mut EngineViewMut, - ) -> WidgetFlags { - let widget_flags = self.change_style_pen_eraser_int(new_style, mode, engine_view); + let widget_flags = self.change_style_int(new_style, mode, engine_view); // When the style is changed externally, the toggle mode / internal states are reset self.toggle_pen_style = None; self.prev_shortcut_key = None; @@ -297,7 +283,7 @@ impl PenHolder { } ShortcutMode::Permanent => { self.toggle_pen_style = None; - widget_flags |= self.change_style_int(style, engine_view); + widget_flags |= self.change_style_int(style, None, engine_view); } ShortcutMode::Toggle => { if let Some(toggle_pen_style) = self.toggle_pen_style { @@ -308,15 +294,15 @@ impl PenHolder { .map(|k| k != shortcut_key) .unwrap_or(true) { - widget_flags |= self.change_style_int(style, engine_view); + widget_flags |= self.change_style_int(style, None, engine_view); } else { self.toggle_pen_style = None; widget_flags |= - self.change_style_int(toggle_pen_style, engine_view); + self.change_style_int(toggle_pen_style, None, engine_view); } } else { self.toggle_pen_style = Some(self.current_pen_style()); - widget_flags |= self.change_style_int(style, engine_view); + widget_flags |= self.change_style_int(style, None, engine_view); } } ShortcutMode::Disabled => {} @@ -355,6 +341,7 @@ impl PenHolder { fn change_style_int( &mut self, new_style: PenStyle, + mode: Option, engine_view: &mut EngineViewMut, ) -> WidgetFlags { let mut widget_flags = WidgetFlags::default(); @@ -364,30 +351,7 @@ impl PenHolder { let all_strokes = engine_view.store.selection_keys_as_rendered(); engine_view.store.set_selected_keys(&all_strokes, false); - self.pen_mode_state.set_style(new_style); - widget_flags |= self.reinstall_pen_current_style(engine_view); - widget_flags.refresh_ui = true; - } - - widget_flags - } - - /// Internal method for changing the pen/eraser style, without some of the side effects that are happening in the public - /// method. - fn change_style_pen_eraser_int( - &mut self, - new_style: PenStyle, - mode: PenMode, - engine_view: &mut EngineViewMut, - ) -> WidgetFlags { - let mut widget_flags = WidgetFlags::default(); - - if self.pen_mode_state.get_style(mode) != new_style { - // Deselecting when changing the style - let all_strokes = engine_view.store.selection_keys_as_rendered(); - engine_view.store.set_selected_keys(&all_strokes, false); - - self.pen_mode_state.set_style_single_mode(mode, new_style); + self.pen_mode_state.set_style(new_style, mode); widget_flags |= self.reinstall_pen_current_style(engine_view); widget_flags.refresh_ui = true; } diff --git a/crates/rnote-engine/src/pens/penmode.rs b/crates/rnote-engine/src/pens/penmode.rs index 5e0a549f2b..410a1ea8f0 100644 --- a/crates/rnote-engine/src/pens/penmode.rs +++ b/crates/rnote-engine/src/pens/penmode.rs @@ -121,15 +121,8 @@ impl PenModeState { } } - pub fn set_style_single_mode(&mut self, mode: PenMode, style: PenStyle) { - match mode { - PenMode::Pen => self.penmode_pen_style = style, - PenMode::Eraser => self.penmode_eraser_style = style, - } - } - - pub fn set_style(&mut self, style: PenStyle) { - match self.pen_mode { + pub fn set_style(&mut self, style: PenStyle, mode: Option) { + match mode.unwrap_or(self.pen_mode) { PenMode::Pen => self.penmode_pen_style = style, PenMode::Eraser => self.penmode_eraser_style = style, } diff --git a/crates/rnote-ui/src/appwindow/actions.rs b/crates/rnote-ui/src/appwindow/actions.rs index d20cf953dc..c481d6060e 100644 --- a/crates/rnote-ui/src/appwindow/actions.rs +++ b/crates/rnote-ui/src/appwindow/actions.rs @@ -358,7 +358,7 @@ impl RnAppWindow { // refresh the ui appwindow.refresh_ui_from_engine(&appwindow.active_tab_wrapper()); } else { - let mut widget_flags = canvas.engine_mut().change_pen_style(pen_style); + let mut widget_flags = canvas.engine_mut().change_pen_style(pen_style, Some(active_pen)); widget_flags |= canvas.engine_mut().change_pen_style_override(None); appwindow.handle_widget_flags(widget_flags, &canvas); action.set_state(&pen_style_str.to_variant()); @@ -393,7 +393,7 @@ impl RnAppWindow { // This prevents circular calls between the settings panel and the canvas let current_pen = canvas.engine_ref().penholder.pen_mode_state().get_style(pen_mode); if current_pen != pen_style { - let mut widget_flags = canvas.engine_mut().change_pen_eraser_style(pen_mode,pen_style); + let mut widget_flags = canvas.engine_mut().change_pen_style(pen_style,Some(pen_mode)); widget_flags |= canvas.engine_mut().change_pen_style_override(None); appwindow.handle_widget_flags(widget_flags, &canvas); } From f7dae71f92d74329fef171cc264c097ddbbdf49c Mon Sep 17 00:00:00 2001 From: Doublonmousse <115779707+Doublonmousse@users.noreply.github.com> Date: Sat, 22 Jun 2024 20:51:19 +0200 Subject: [PATCH 11/15] update to use durations for toasts --- crates/rnote-ui/src/appwindow/actions.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/crates/rnote-ui/src/appwindow/actions.rs b/crates/rnote-ui/src/appwindow/actions.rs index c481d6060e..c83c55b6a6 100644 --- a/crates/rnote-ui/src/appwindow/actions.rs +++ b/crates/rnote-ui/src/appwindow/actions.rs @@ -16,6 +16,7 @@ use rnote_engine::strokes::resize::{ImageSizeOption, Resize}; use rnote_engine::{Camera, Engine}; use std::path::PathBuf; use std::str::FromStr; +use std::time::Duration; use std::time::Instant; const CLIPBOARD_INPUT_STREAM_BUFSIZE: usize = 4096; @@ -352,8 +353,8 @@ impl RnAppWindow { appwindow.sidebar().settings_panel().set_lock_state(active_pen,false); appwindow.sidebar().settings_panel().refresh_ui(&appwindow.active_tab_wrapper()); } - ) - , 2, + ), + Some(Duration::from_secs(2)), &mut None); // refresh the ui appwindow.refresh_ui_from_engine(&appwindow.active_tab_wrapper()); From 5c3faf226a5ba41fff8f72ffeb15fb35ecf3dd82 Mon Sep 17 00:00:00 2001 From: Doublonmousse <115779707+Doublonmousse@users.noreply.github.com> Date: Sat, 22 Jun 2024 21:52:51 +0200 Subject: [PATCH 12/15] fix clippy warnings --- crates/rnote-engine/src/pens/penmode.rs | 4 ++-- crates/rnote-ui/src/settingspanel/penmoderow.rs | 14 ++++++-------- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/crates/rnote-engine/src/pens/penmode.rs b/crates/rnote-engine/src/pens/penmode.rs index 410a1ea8f0..3f2b63c8c2 100644 --- a/crates/rnote-engine/src/pens/penmode.rs +++ b/crates/rnote-engine/src/pens/penmode.rs @@ -62,8 +62,8 @@ impl CloneConfig for PenModeState { pen_mode: self.pen_mode, penmode_pen_style: self.penmode_pen_style, penmode_eraser_style: self.penmode_eraser_style, - penmode_pen_lock: self.penmode_pen_lock.clone(), - penmode_eraser_lock: self.penmode_eraser_lock.clone(), + penmode_pen_lock: self.penmode_pen_lock, + penmode_eraser_lock: self.penmode_eraser_lock, ..Default::default() } } diff --git a/crates/rnote-ui/src/settingspanel/penmoderow.rs b/crates/rnote-ui/src/settingspanel/penmoderow.rs index 17b5cb264a..be14f01975 100644 --- a/crates/rnote-ui/src/settingspanel/penmoderow.rs +++ b/crates/rnote-ui/src/settingspanel/penmoderow.rs @@ -64,10 +64,9 @@ mod imp { obj.connect_selected_item_notify(move |row| { let new_pen_style = row.pen_style(); - match &mut *row.imp().action.borrow_mut() { - current_style => { - *current_style = new_pen_style; - } + let current_style = &mut *row.imp().action.borrow_mut(); + { + *current_style = new_pen_style; } row.emit_by_name::<()>("action-changed", &[]); @@ -141,10 +140,9 @@ impl RnPenModeRow { } fn update_ui(&self) { - match self.action() { - style => { - self.set_pen_style(style); - } + let style = self.action(); + { + self.set_pen_style(style); } } } From 5d43a7f06ca29f3aa139d5f982307396fadaae01 Mon Sep 17 00:00:00 2001 From: Doublonmousse <115779707+Doublonmousse@users.noreply.github.com> Date: Sun, 14 Jul 2024 18:42:17 +0200 Subject: [PATCH 13/15] defensive borrows and debug traces Temporary to find what's going on --- crates/rnote-ui/src/appwindow/actions.rs | 4 +- crates/rnote-ui/src/canvas/mod.rs | 7 ++- crates/rnote-ui/src/settingspanel/mod.rs | 15 +++++- .../rnote-ui/src/settingspanel/penmoderow.rs | 47 ++++++++++++------- 4 files changed, 52 insertions(+), 21 deletions(-) diff --git a/crates/rnote-ui/src/appwindow/actions.rs b/crates/rnote-ui/src/appwindow/actions.rs index c83c55b6a6..ebe6307841 100644 --- a/crates/rnote-ui/src/appwindow/actions.rs +++ b/crates/rnote-ui/src/appwindow/actions.rs @@ -359,6 +359,7 @@ impl RnAppWindow { // refresh the ui appwindow.refresh_ui_from_engine(&appwindow.active_tab_wrapper()); } else { + tracing::debug!("engine mut 1 (ok)"); let mut widget_flags = canvas.engine_mut().change_pen_style(pen_style, Some(active_pen)); widget_flags |= canvas.engine_mut().change_pen_style_override(None); appwindow.handle_widget_flags(widget_flags, &canvas); @@ -393,7 +394,8 @@ impl RnAppWindow { // Changes the underlying values only if they are different from the current ones // This prevents circular calls between the settings panel and the canvas let current_pen = canvas.engine_ref().penholder.pen_mode_state().get_style(pen_mode); - if current_pen != pen_style { + if current_pen != pen_style && canvas.try_engine_mut().is_ok() { + tracing::debug!("engine mut 2 (ok)"); let mut widget_flags = canvas.engine_mut().change_pen_style(pen_style,Some(pen_mode)); widget_flags |= canvas.engine_mut().change_pen_style_override(None); appwindow.handle_widget_flags(widget_flags, &canvas); diff --git a/crates/rnote-ui/src/canvas/mod.rs b/crates/rnote-ui/src/canvas/mod.rs index 3a24367326..cc4ddb0335 100644 --- a/crates/rnote-ui/src/canvas/mod.rs +++ b/crates/rnote-ui/src/canvas/mod.rs @@ -26,7 +26,7 @@ use rnote_engine::ext::GraphenePointExt; use rnote_engine::ext::GrapheneRectExt; use rnote_engine::Camera; use rnote_engine::{Engine, WidgetFlags}; -use std::cell::{Cell, Ref, RefCell, RefMut}; +use std::cell::{BorrowMutError, Cell, Ref, RefCell, RefMut}; use std::path::Path; use std::time::Duration; @@ -760,6 +760,11 @@ impl RnCanvas { self.imp().engine.borrow_mut() } + /// mutable borrow with error handling + pub(crate) fn try_engine_mut(&self) -> Result, BorrowMutError> { + self.imp().engine.try_borrow_mut() + } + /// Abort the engine task handler. /// /// Because the installed engine task handler holds a reference to the canvas, diff --git a/crates/rnote-ui/src/settingspanel/mod.rs b/crates/rnote-ui/src/settingspanel/mod.rs index b785aa5146..fc4f4ab8e7 100644 --- a/crates/rnote-ui/src/settingspanel/mod.rs +++ b/crates/rnote-ui/src/settingspanel/mod.rs @@ -24,6 +24,7 @@ use rnote_engine::document::background::PatternStyle; use rnote_engine::document::format::{self, Format, PredefinedFormat}; use rnote_engine::document::Layout; use rnote_engine::ext::GdkRGBAExt; +use rnote_engine::pens::PenStyle; use std::cell::RefCell; mod imp { @@ -914,7 +915,12 @@ impl RnSettingsPanel { false, clone!(@weak lock_pen, @weak appwindow => @default-return None, move |_values| { let action = lock_pen.action(); - adw::prelude::ActionGroupExt::activate_action(&appwindow, "pen-styles", Some(&("pen",action.to_string()).to_variant())); + match action { + Ok(value) => adw::prelude::ActionGroupExt::activate_action(&appwindow, "pen-styles", Some(&("pen",value.to_string()).to_variant())), + Err(e) => { + tracing::debug!("error getting the lock pen action L921 {:?}",e); + } + } None }), ); @@ -924,7 +930,12 @@ impl RnSettingsPanel { false, clone!(@weak lock_eraser, @weak appwindow => @default-return None, move |_values| { let action = lock_eraser.action(); - adw::prelude::ActionGroupExt::activate_action(&appwindow, "pen-styles", Some(&("eraser",action.to_string()).to_variant())); + match action { + Ok(value) => { + adw::prelude::ActionGroupExt::activate_action(&appwindow, "pen-styles", Some(&("eraser",value.to_string()).to_variant())); + }, + Err(e) => tracing::debug!("error getting action eraser L937 {:?}",e), + } None })); } diff --git a/crates/rnote-ui/src/settingspanel/penmoderow.rs b/crates/rnote-ui/src/settingspanel/penmoderow.rs index be14f01975..f3d7fe268d 100644 --- a/crates/rnote-ui/src/settingspanel/penmoderow.rs +++ b/crates/rnote-ui/src/settingspanel/penmoderow.rs @@ -7,7 +7,10 @@ use gtk4::{glib, glib::clone, glib::subclass::*, CompositeTemplate}; use num_traits::ToPrimitive; use once_cell::sync::Lazy; use rnote_engine::pens::PenStyle; -use std::cell::RefCell; +use std::{ + borrow::BorrowMut, + cell::{BorrowError, RefCell}, +}; mod imp { use super::*; @@ -61,16 +64,17 @@ mod imp { obj.set_list_factory(Some(&*list_factory)); obj.set_factory(Some(&*icon_factory)); - obj.connect_selected_item_notify(move |row| { - let new_pen_style = row.pen_style(); + // obj.connect_selected_item_notify(move |row| { + // let new_pen_style = row.pen_style(); - let current_style = &mut *row.imp().action.borrow_mut(); - { - *current_style = new_pen_style; - } + // // is this the one taking the action hostage ? + // let current_style = &mut *row.imp().action.borrow_mut(); + // { + // *current_style = new_pen_style; + // } - row.emit_by_name::<()>("action-changed", &[]); - }); + // row.emit_by_name::<()>("action-changed", &[]); + // }); obj.connect_local( "action-changed", @@ -115,15 +119,24 @@ impl RnPenModeRow { glib::Object::new() } - #[allow(unused)] - pub(crate) fn action(&self) -> PenStyle { - *self.imp().action.borrow() + pub(crate) fn action(&self) -> Result { + match self.imp().action.try_borrow() { + Ok(val) => Ok(*val), + Err(e) => Err(e), + } } #[allow(unused)] pub(crate) fn set_action(&self, action: PenStyle) { - *self.imp().action.borrow_mut() = action; - self.emit_by_name::<()>("action-changed", &[]); + match self.imp().action.try_borrow_mut() { + Ok(mut value) => { + *value = action; + self.emit_by_name::<()>("action-changed", &[]); + } + Err(e) => { + tracing::debug!("Error borrowing action L136 {:?}", e) + } + } } pub(crate) fn pen_style(&self) -> PenStyle { @@ -140,9 +153,9 @@ impl RnPenModeRow { } fn update_ui(&self) { - let style = self.action(); - { - self.set_pen_style(style); + match self.action() { + Ok(style) => self.set_pen_style(style), + Err(e) => tracing::error!("error borrowing action L157, {:?}", e), } } } From dc9ffe5c8092a53d580a9f8ed4c3ead4d3f922b8 Mon Sep 17 00:00:00 2001 From: Doublonmousse <115779707+Doublonmousse@users.noreply.github.com> Date: Mon, 15 Jul 2024 21:51:47 +0200 Subject: [PATCH 14/15] fixed borrowmut errors --- crates/rnote-ui/src/appwindow/actions.rs | 12 ++-- crates/rnote-ui/src/canvas/mod.rs | 7 +- crates/rnote-ui/src/settingspanel/mod.rs | 19 ++---- .../rnote-ui/src/settingspanel/penmoderow.rs | 68 ++++++++----------- 4 files changed, 41 insertions(+), 65 deletions(-) diff --git a/crates/rnote-ui/src/appwindow/actions.rs b/crates/rnote-ui/src/appwindow/actions.rs index ebe6307841..392d73b9a0 100644 --- a/crates/rnote-ui/src/appwindow/actions.rs +++ b/crates/rnote-ui/src/appwindow/actions.rs @@ -346,8 +346,8 @@ impl RnAppWindow { if lock_out { // display a popup that can unlock the pen tool appwindow.overlays().dispatch_toast_w_button_singleton( - &gettext("Tool Locked"), - &gettext("Unlock"), + &gettext("Tool Locked"), + &gettext("Unlock"), clone!(@weak canvas, @weak appwindow => move |_reload_toast | { canvas.engine_mut().penholder.pen_mode_state_mut().unlock_pen(active_pen); appwindow.sidebar().settings_panel().set_lock_state(active_pen,false); @@ -377,7 +377,7 @@ impl RnAppWindow { "pen" => PenMode::Pen, "eraser" => PenMode::Eraser, other => { - tracing::error!("the pen style does not exist (either `pen` or `eraser` should be given as string, got {other:}"); + tracing::error!("the pen style does not exist (either `pen` or `eraser` should be given as string, got {other:}"); return; } }; @@ -394,13 +394,15 @@ impl RnAppWindow { // Changes the underlying values only if they are different from the current ones // This prevents circular calls between the settings panel and the canvas let current_pen = canvas.engine_ref().penholder.pen_mode_state().get_style(pen_mode); - if current_pen != pen_style && canvas.try_engine_mut().is_ok() { + if current_pen != pen_style { tracing::debug!("engine mut 2 (ok)"); let mut widget_flags = canvas.engine_mut().change_pen_style(pen_style,Some(pen_mode)); widget_flags |= canvas.engine_mut().change_pen_style_override(None); appwindow.handle_widget_flags(widget_flags, &canvas); + } else { + tracing::debug!("same pen as the current one, aborting"); } - }), + }) ); // Tab actions diff --git a/crates/rnote-ui/src/canvas/mod.rs b/crates/rnote-ui/src/canvas/mod.rs index cc4ddb0335..3a24367326 100644 --- a/crates/rnote-ui/src/canvas/mod.rs +++ b/crates/rnote-ui/src/canvas/mod.rs @@ -26,7 +26,7 @@ use rnote_engine::ext::GraphenePointExt; use rnote_engine::ext::GrapheneRectExt; use rnote_engine::Camera; use rnote_engine::{Engine, WidgetFlags}; -use std::cell::{BorrowMutError, Cell, Ref, RefCell, RefMut}; +use std::cell::{Cell, Ref, RefCell, RefMut}; use std::path::Path; use std::time::Duration; @@ -760,11 +760,6 @@ impl RnCanvas { self.imp().engine.borrow_mut() } - /// mutable borrow with error handling - pub(crate) fn try_engine_mut(&self) -> Result, BorrowMutError> { - self.imp().engine.try_borrow_mut() - } - /// Abort the engine task handler. /// /// Because the installed engine task handler holds a reference to the canvas, diff --git a/crates/rnote-ui/src/settingspanel/mod.rs b/crates/rnote-ui/src/settingspanel/mod.rs index fc4f4ab8e7..e06f65be2f 100644 --- a/crates/rnote-ui/src/settingspanel/mod.rs +++ b/crates/rnote-ui/src/settingspanel/mod.rs @@ -24,7 +24,6 @@ use rnote_engine::document::background::PatternStyle; use rnote_engine::document::format::{self, Format, PredefinedFormat}; use rnote_engine::document::Layout; use rnote_engine::ext::GdkRGBAExt; -use rnote_engine::pens::PenStyle; use std::cell::RefCell; mod imp { @@ -914,13 +913,8 @@ impl RnSettingsPanel { "action-changed", false, clone!(@weak lock_pen, @weak appwindow => @default-return None, move |_values| { - let action = lock_pen.action(); - match action { - Ok(value) => adw::prelude::ActionGroupExt::activate_action(&appwindow, "pen-styles", Some(&("pen",value.to_string()).to_variant())), - Err(e) => { - tracing::debug!("error getting the lock pen action L921 {:?}",e); - } - } + let action = lock_pen.get_action(); + adw::prelude::ActionGroupExt::activate_action(&appwindow, "pen-styles", Some(&("pen",action.to_string()).to_variant())); None }), ); @@ -929,13 +923,8 @@ impl RnSettingsPanel { "action-changed", false, clone!(@weak lock_eraser, @weak appwindow => @default-return None, move |_values| { - let action = lock_eraser.action(); - match action { - Ok(value) => { - adw::prelude::ActionGroupExt::activate_action(&appwindow, "pen-styles", Some(&("eraser",value.to_string()).to_variant())); - }, - Err(e) => tracing::debug!("error getting action eraser L937 {:?}",e), - } + let action = lock_eraser.get_action(); + adw::prelude::ActionGroupExt::activate_action(&appwindow, "pen-styles", Some(&("eraser",action.to_string()).to_variant())); None })); } diff --git a/crates/rnote-ui/src/settingspanel/penmoderow.rs b/crates/rnote-ui/src/settingspanel/penmoderow.rs index f3d7fe268d..5b7b1aa6da 100644 --- a/crates/rnote-ui/src/settingspanel/penmoderow.rs +++ b/crates/rnote-ui/src/settingspanel/penmoderow.rs @@ -3,14 +3,11 @@ use super::penshortcutmodels::{ ChangePenStyleIconFactory, ChangePenStyleListFactory, ChangePenStyleListModel, }; use adw::{prelude::*, subclass::prelude::*}; -use gtk4::{glib, glib::clone, glib::subclass::*, CompositeTemplate}; +use gtk4::{glib, glib::subclass::*, CompositeTemplate}; use num_traits::ToPrimitive; use once_cell::sync::Lazy; use rnote_engine::pens::PenStyle; -use std::{ - borrow::BorrowMut, - cell::{BorrowError, RefCell}, -}; +use std::cell::RefCell; mod imp { use super::*; @@ -64,26 +61,28 @@ mod imp { obj.set_list_factory(Some(&*list_factory)); obj.set_factory(Some(&*icon_factory)); - // obj.connect_selected_item_notify(move |row| { - // let new_pen_style = row.pen_style(); - - // // is this the one taking the action hostage ? - // let current_style = &mut *row.imp().action.borrow_mut(); - // { - // *current_style = new_pen_style; - // } - - // row.emit_by_name::<()>("action-changed", &[]); - // }); - - obj.connect_local( - "action-changed", - false, - clone!(@weak obj as penshortcutrow => @default-return None, move |_values| { - penshortcutrow.update_ui(); - None - }), - ); + obj.connect_selected_item_notify(move |row| { + let new_pen_style = row.pen_style(); + let trigger_action: bool = { + let current_style_res = row.imp().action.try_borrow_mut(); + match current_style_res { + Ok(mut current_style) => { + // when set from the canvas, both are changed at the same time + // it's not the case when a user change the selection + if *current_style != new_pen_style { + *current_style = new_pen_style; + true + } else { + false + } + } + Err(_) => false, // already used somewhere else, aborting + } + }; + if trigger_action { + row.emit_by_name::<()>("action-changed", &[]); + } + }); } fn dispose(&self) { @@ -119,19 +118,17 @@ impl RnPenModeRow { glib::Object::new() } - pub(crate) fn action(&self) -> Result { - match self.imp().action.try_borrow() { - Ok(val) => Ok(*val), - Err(e) => Err(e), - } + /// get the action immutably + pub(crate) fn get_action(&self) -> PenStyle { + *self.imp().action.borrow() } - #[allow(unused)] + /// incoming change of state (from the canvas to the settings panel) pub(crate) fn set_action(&self, action: PenStyle) { match self.imp().action.try_borrow_mut() { Ok(mut value) => { *value = action; - self.emit_by_name::<()>("action-changed", &[]); + self.set_pen_style(action); } Err(e) => { tracing::debug!("Error borrowing action L136 {:?}", e) @@ -151,11 +148,4 @@ impl RnPenModeRow { self.imp().mode.get().set_state(state); self.imp().mode.get().set_active(state); } - - fn update_ui(&self) { - match self.action() { - Ok(style) => self.set_pen_style(style), - Err(e) => tracing::error!("error borrowing action L157, {:?}", e), - } - } } From 5deb6488a711bd252b92b8e941c1bad478b46efd Mon Sep 17 00:00:00 2001 From: Doublonmousse <115779707+Doublonmousse@users.noreply.github.com> Date: Mon, 15 Jul 2024 21:53:12 +0200 Subject: [PATCH 15/15] remove debug traces --- crates/rnote-ui/src/appwindow/actions.rs | 2 -- crates/rnote-ui/src/settingspanel/penmoderow.rs | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/crates/rnote-ui/src/appwindow/actions.rs b/crates/rnote-ui/src/appwindow/actions.rs index 392d73b9a0..24f0a9ef5b 100644 --- a/crates/rnote-ui/src/appwindow/actions.rs +++ b/crates/rnote-ui/src/appwindow/actions.rs @@ -359,7 +359,6 @@ impl RnAppWindow { // refresh the ui appwindow.refresh_ui_from_engine(&appwindow.active_tab_wrapper()); } else { - tracing::debug!("engine mut 1 (ok)"); let mut widget_flags = canvas.engine_mut().change_pen_style(pen_style, Some(active_pen)); widget_flags |= canvas.engine_mut().change_pen_style_override(None); appwindow.handle_widget_flags(widget_flags, &canvas); @@ -395,7 +394,6 @@ impl RnAppWindow { // This prevents circular calls between the settings panel and the canvas let current_pen = canvas.engine_ref().penholder.pen_mode_state().get_style(pen_mode); if current_pen != pen_style { - tracing::debug!("engine mut 2 (ok)"); let mut widget_flags = canvas.engine_mut().change_pen_style(pen_style,Some(pen_mode)); widget_flags |= canvas.engine_mut().change_pen_style_override(None); appwindow.handle_widget_flags(widget_flags, &canvas); diff --git a/crates/rnote-ui/src/settingspanel/penmoderow.rs b/crates/rnote-ui/src/settingspanel/penmoderow.rs index 5b7b1aa6da..1113782766 100644 --- a/crates/rnote-ui/src/settingspanel/penmoderow.rs +++ b/crates/rnote-ui/src/settingspanel/penmoderow.rs @@ -131,7 +131,7 @@ impl RnPenModeRow { self.set_pen_style(action); } Err(e) => { - tracing::debug!("Error borrowing action L136 {:?}", e) + tracing::debug!("Error borrowing action {:?}", e) } } }