Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

logic changes for selection cancellation #1139

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
10 changes: 10 additions & 0 deletions crates/rnote-engine/src/engine/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -857,6 +857,16 @@ impl Engine {
| self.update_rendering_current_viewport()
}

pub fn cancel_selection_temporary_pen(&self) -> bool {
let selection_keys = self.store.selection_keys_as_rendered();
!selection_keys.is_empty()
&& self
.penholder
.pen_mode_state()
.take_style_override()
.is_some()
}

pub fn trash_selection(&mut self) -> WidgetFlags {
let selection_keys = self.store.selection_keys_as_rendered();
self.store.set_trashed_keys(&selection_keys, true);
Expand Down
23 changes: 23 additions & 0 deletions crates/rnote-engine/src/pens/brush.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use rnote_compose::builders::{
use rnote_compose::eventresult::{EventPropagation, EventResult};
use rnote_compose::penevent::{PenEvent, PenProgress};
use rnote_compose::penpath::{Element, Segment};
use rnote_compose::shapes::Shapeable;
use rnote_compose::Constraints;
use std::time::Instant;

Expand Down Expand Up @@ -229,6 +230,28 @@ impl PenBehaviour for Brush {
);
}

// remove strokes that follow a selection cancellation if they are large
// hence we can write after selecting strokes but we won't leave tiny spots
// behind
let volume = engine_view
.store
.get_stroke_ref(*current_stroke_key)
.unwrap()
.bounds()
.volume();
if engine_view.store.get_cancelled_state()
&& volume
< 4.0
Doublonmousse marked this conversation as resolved.
Show resolved Hide resolved
* engine_view
.pens_config
.brush_config
.get_stroke_width()
.powi(2)
{
tracing::debug!("VOLUME {volume}");
engine_view.store.remove_stroke(*current_stroke_key);
}

// Finish up the last stroke
engine_view
.store
Expand Down
7 changes: 5 additions & 2 deletions crates/rnote-engine/src/pens/eraser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,11 @@ impl PenBehaviour for Eraser {

let event_result = match (&mut self.state, event) {
(EraserState::Up | EraserState::Proximity { .. }, PenEvent::Down { element, .. }) => {
widget_flags |= erase(element, engine_view);
self.state = EraserState::Down(element);
if !engine_view.store.get_cancelled_state() {
widget_flags |= erase(element, engine_view);
self.state = EraserState::Down(element);
// this means we need one more up/down event here to activate the eraser
}
EventResult {
handled: true,
propagate: EventPropagation::Stop,
Expand Down
8 changes: 7 additions & 1 deletion crates/rnote-engine/src/pens/penholder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -248,11 +248,17 @@ impl PenHolder {
widget_flags |= wf | self.handle_pen_progress(event_result.progress, engine_view);

if !event_result.handled {
let (propagate, wf) = self.handle_pen_event_global(event, now, engine_view);
let (propagate, wf) = self.handle_pen_event_global(event.clone(), now, engine_view);
event_result.propagate |= propagate;
widget_flags |= wf;
}

// reset the state
match event {
PenEvent::Up { .. } => engine_view.store.set_cancelled_state(false),
_ => (),
}

// Always redraw after handling a pen event
widget_flags.redraw = true;

Expand Down
8 changes: 8 additions & 0 deletions crates/rnote-engine/src/pens/pensconfig/brushconfig.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,4 +148,12 @@ impl BrushConfig {
}
}
}

pub(crate) fn get_stroke_width(&self) -> f64 {
match &self.style {
BrushStyle::Marker => self.marker_options.stroke_width,
BrushStyle::Solid => self.solid_options.stroke_width,
BrushStyle::Textured => self.textured_options.stroke_width,
}
}
}
7 changes: 7 additions & 0 deletions crates/rnote-engine/src/pens/pensconfig/shaperconfig.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,4 +91,11 @@ impl ShaperConfig {
}
}
}

pub(crate) fn get_stroke_width(&self) -> f64 {
match &self.style {
ShaperStyle::Smooth => self.smooth_options.stroke_width,
ShaperStyle::Rough => self.rough_options.stroke_width,
}
}
}
7 changes: 7 additions & 0 deletions crates/rnote-engine/src/pens/selector/penevents.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,9 +180,16 @@ impl Selector {
};
} else {
// when clicking outside the selection bounds, reset
tracing::debug!("cancelling the selection");
engine_view.store.set_selected_keys(selection, false);
self.state = SelectorState::Idle;

// we create a new engine variable that indicates that the pen event is one from the same
// event sequence that the one that cancelled the selection
// this is done by setting this variable to true here and
// removing it on a pen up event (and doing more things if this variable is true on a pen up)
Doublonmousse marked this conversation as resolved.
Show resolved Hide resolved
engine_view.store.set_cancelled_state(true);

progress = PenProgress::Finished;
}
}
Expand Down
61 changes: 41 additions & 20 deletions crates/rnote-engine/src/pens/shaper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::strokes::ShapeStroke;
use crate::strokes::Stroke;
use crate::{DrawableOnDoc, WidgetFlags};
use p2d::bounding_volume::Aabb;
use p2d::bounding_volume::BoundingVolume;
use piet::RenderContext;
use rnote_compose::builders::buildable::{Buildable, BuilderCreator, BuilderProgress};
use rnote_compose::builders::{ArrowBuilder, GridBuilder, PolygonBuilder, PolylineBuilder};
Expand All @@ -16,6 +17,7 @@ use rnote_compose::builders::{
use rnote_compose::eventresult::{EventPropagation, EventResult};
use rnote_compose::penevent::{KeyboardKey, ModifierKey, PenEvent, PenProgress};
use rnote_compose::penpath::Element;
use rnote_compose::shapes::Shapeable;
use rnote_compose::Shape;
use std::time::Instant;

Expand Down Expand Up @@ -67,15 +69,19 @@ impl PenBehaviour for Shaper {

let event_result = match (&mut self.state, event) {
(ShaperState::Idle, PenEvent::Down { element, .. }) => {
engine_view.pens_config.shaper_config.new_style_seeds();
if !engine_view.store.get_cancelled_state() {
// here we need an additional up/down event after a selection
// cancellation
engine_view.pens_config.shaper_config.new_style_seeds();

self.state = ShaperState::BuildShape {
builder: new_builder(
engine_view.pens_config.shaper_config.builder_type,
element,
now,
),
};
self.state = ShaperState::BuildShape {
builder: new_builder(
engine_view.pens_config.shaper_config.builder_type,
element,
now,
),
};
}

EventResult {
handled: true,
Expand Down Expand Up @@ -153,18 +159,33 @@ impl PenBehaviour for Shaper {
.shaper_config
.gen_style_for_current_options();

let shapes_emitted = !shapes.is_empty();
for shape in shapes {
let key = engine_view.store.insert_stroke(
Stroke::ShapeStroke(ShapeStroke::new(shape, style.clone())),
None,
);
style.advance_seed();
engine_view.store.regenerate_rendering_for_stroke(
key,
engine_view.camera.viewport(),
engine_view.camera.image_scale(),
);
// calculate the bounds
let bound_condition = shapes
.iter()
.map(|x| x.bounds())
.reduce(|acc, x| acc.merged(&x))
.unwrap_or(Aabb::new_invalid())
.volume()
> engine_view
.pens_config
.shaper_config
.get_stroke_width()
.powi(2);
Doublonmousse marked this conversation as resolved.
Show resolved Hide resolved

let shapes_emitted = !shapes.is_empty() && bound_condition;
if shapes_emitted {
for shape in shapes {
let key = engine_view.store.insert_stroke(
Stroke::ShapeStroke(ShapeStroke::new(shape, style.clone())),
None,
);
style.advance_seed();
engine_view.store.regenerate_rendering_for_stroke(
key,
engine_view.camera.viewport(),
engine_view.camera.image_scale(),
);
}
}

self.state = ShaperState::Idle;
Expand Down
16 changes: 15 additions & 1 deletion crates/rnote-engine/src/pens/typewriter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use crate::{AudioPlayer, Camera, DrawableOnDoc, WidgetFlags};
use futures::channel::oneshot;
use p2d::bounding_volume::{Aabb, BoundingVolume};
use piet::RenderContext;
use rnote_compose::eventresult::EventPropagation;
use rnote_compose::ext::{AabbExt, Vector2Ext};
use rnote_compose::penevent::{KeyboardKey, PenEvent, PenProgress, PenState};
use rnote_compose::shapes::Shapeable;
Expand Down Expand Up @@ -359,7 +360,20 @@ impl PenBehaviour for Typewriter {
PenEvent::Down {
element,
modifier_keys,
} => self.handle_pen_event_down(element, modifier_keys, now, engine_view),
} => {
if !engine_view.store.get_cancelled_state() {
self.handle_pen_event_down(element, modifier_keys, now, engine_view)
} else {
(
EventResult {
handled: true,
propagate: EventPropagation::Stop,
progress: PenProgress::InProgress,
},
WidgetFlags::default(),
)
}
}
PenEvent::Up {
element,
modifier_keys,
Expand Down
13 changes: 13 additions & 0 deletions crates/rnote-engine/src/store/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ pub struct StrokeStore {
/// The index of the current live document in the history stack.
#[serde(skip)]
live_index: usize,
#[serde(skip)]
canceled_selection: bool,
/// An rtree backed by the slotmap store, for faster spatial queries.
///
/// Needs to be updated with `update_with_key()` when strokes changed their geometry or position!
Expand All @@ -109,6 +111,7 @@ impl Default for StrokeStore {
// Start off with state in the history
history: VecDeque::from(vec![HistoryEntry::default()]),
live_index: 0,
canceled_selection: false,

key_tree: KeyTree::default(),

Expand Down Expand Up @@ -367,4 +370,14 @@ impl StrokeStore {

widget_flags
}

/// set the active state for the cancelled selection
pub fn set_cancelled_state(&mut self, state: bool) {
self.canceled_selection = state
}

/// get the active state for the cancelled selection
pub fn get_cancelled_state(&self) -> bool {
self.canceled_selection
}
}
16 changes: 14 additions & 2 deletions crates/rnote-ui/src/appwindow/actions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use gtk4::{
UriLauncher, Window,
};
use p2d::bounding_volume::BoundingVolume;
use rnote_compose::penevent::ShortcutKey;
use rnote_compose::penevent::{KeyboardKey, ShortcutKey};
use rnote_compose::SplitOrder;
use rnote_engine::engine::StrokeContent;
use rnote_engine::pens::PenStyle;
Expand Down Expand Up @@ -406,7 +406,19 @@ impl RnAppWindow {
// Trash Selection
action_selection_trash.connect_activate(clone!(@weak self as appwindow => move |_, _| {
let canvas = appwindow.active_tab_wrapper().canvas();
let widget_flags = canvas.engine_mut().trash_selection();
// check if we have a selector as a temporary tool and need to change the pen
let cancel_selection = canvas.engine_ref().cancel_selection_temporary_pen();
let widget_flags = if cancel_selection {
// trigger an event for a KeyboardPress::Delete
let (_, widget_flags) = canvas.engine_mut().handle_pen_event(
rnote_compose::PenEvent::KeyPressed { keyboard_key: KeyboardKey::Delete, modifier_keys: vec![] },
None,
Instant::now()
);
widget_flags
} else {
canvas.engine_mut().trash_selection()
};
Doublonmousse marked this conversation as resolved.
Show resolved Hide resolved
appwindow.handle_widget_flags(widget_flags, &canvas);
}));

Expand Down
Loading