[WIP] Allow dragging selections

This commit is contained in:
Enrico Lumetti 2021-03-05 16:11:23 +01:00
parent 393394ed53
commit 9c7ef5a55b
4 changed files with 58 additions and 13 deletions

View File

@ -14,8 +14,6 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
use std::vec::Vec;
use im::{vector, Vector};
use serde::de::{Deserializer, SeqAccess, Visitor};
@ -180,19 +178,29 @@ impl Canvas {
&self.elements
}
/// Find all CanvasElement that intersect with rect
pub fn find_intersections(&self, rect: druid::Rect) -> Vec<usize> {
let mut found_elements = Vec::<usize>::new();
pub fn has_elements_interesecting(&self, rect: druid::Rect) -> bool {
for (i, elem) in self.elements.iter().enumerate() {
// Check if the element intersects the eraser rect
if elem.bounding_box().intersect(rect).area() > 0.0 {
if elem.intersects_rect(rect) {
found_elements.push(i);
return true;
}
}
}
false
}
/// Find all CanvasElement that intersect with rect
pub fn find_elements_intersecting(&self, rect: druid::Rect) -> Vector<usize> {
let found_elements = self.elements.iter().enumerate()
.filter_map(|(i, elem)| {
if elem.bounding_box().intersect(rect).area() > 0.0 {
if elem.intersects_rect(rect) {
return Some(i);
}
}
None
}).collect::<Vector<usize>>();
found_elements
}

View File

@ -24,7 +24,7 @@ pub mod widget;
pub mod migration;
pub mod colors {
use druid::Color;
//use druid::Color;
//pub const SELECTED_STROKE: Color = Color::rgb(10.0, 0.0, 255.0);
}

View File

@ -22,7 +22,7 @@ use crate::tool::CanvasToolParams;
use crate::{DocumentSnapshot, VersionedCanvas};
use druid::widget::prelude::*;
use druid::{Color, Data, Env, Event, PointerType};
use druid::{Color, Data, Env, Event, PointerType, Selector};
#[derive(Clone, Data)]
pub struct CanvasState {
@ -131,12 +131,28 @@ impl CanvasState {
pub struct CanvasWidget;
impl CanvasWidget {
pub const IS_OVER_SELECTION: Selector<bool> = Selector::new("is_over_selection");
}
impl Widget<CanvasState> for CanvasWidget {
fn event(&mut self, ctx: &mut EventCtx, event: &Event, data: &mut CanvasState, env: &Env) {
ctx.request_focus();
let mut toggle_eraser_event = false;
let mut enable_temporary_erasing = false;
match event {
Event::Notification(cmd) => {
cmd.get(CanvasWidget::IS_OVER_SELECTION).map(|is_over_sel| {
if *is_over_sel {
use druid::Cursor;
ctx.set_cursor(&Cursor::OpenHand);
} else {
// TODO: this is not correct. Must check if had modified cursor before
ctx.clear_cursor();
}
});
ctx.set_handled();
}
Event::MouseDown(mouse_event) => {
toggle_eraser_event = true;
enable_temporary_erasing = mouse_event.pointer_type == PointerType::Eraser;

View File

@ -16,6 +16,7 @@
use crate::tool::{CanvasToolParams, CanvasToolType};
use crate::canvas::{Canvas, CanvasElement};
use crate::widget::CanvasWidget;
use crate::VersionedCanvas;
use druid::kurbo::BezPath;
@ -35,6 +36,7 @@ pub enum CanvasToolState {
origin: druid::Point,
current_rect: druid::Rect,
},
DraggingSelection,
ActiveSelection,
}
@ -59,6 +61,14 @@ fn pressed(mouse_event: &MouseEvent) -> bool {
|| mouse_event.button == MouseButton::Left
}
fn is_over_active_selection(mouse_event: &MouseEvent, vcanvas: &VersionedCanvas) -> bool {
let mouse_rect = druid::Rect::from_center_size(mouse_event.pos, (5.0, 5.0));
// TODO(enrico): this can be faster
let intersecting_elements = vcanvas.get().find_elements_intersecting(mouse_rect);
let selected_elements = vcanvas.get().selected_elements();
false
}
impl CanvasToolCtx {
pub fn new(params: CanvasToolParams) -> Self {
CanvasToolCtx {
@ -82,7 +92,7 @@ impl CanvasToolCtx {
pub fn handle_event(
&mut self,
ctx: &EventCtx,
mut ctx: &mut EventCtx,
event: &Event,
mut vcanvas: &mut VersionedCanvas,
env: &Env,
@ -90,7 +100,7 @@ impl CanvasToolCtx {
match self.initial_params.tool_type() {
CanvasToolType::Pen => self.handle_pen_event(&ctx, &event, &mut vcanvas, &env),
CanvasToolType::Eraser => self.handle_erase_event(&ctx, &event, &mut vcanvas, &env),
CanvasToolType::RectangularSelection => self.handle_rectangular_select_event(&ctx, &event, &mut vcanvas, &env),
CanvasToolType::RectangularSelection => self.handle_rectangular_select_event(&mut ctx, &event, &mut vcanvas, &env),
}
}
@ -193,12 +203,23 @@ impl CanvasToolCtx {
pub fn handle_rectangular_select_event(
&mut self,
_ctx: &EventCtx,
ctx: &mut EventCtx,
event: &Event,
vcanvas: &mut VersionedCanvas,
_env: &Env,
) {
match (&mut self.state, event) {
(CanvasToolState::ActiveSelection, Event::MouseMove(mouse_event)) if !pressed(mouse_event) => {
ctx.submit_notification(CanvasWidget::IS_OVER_SELECTION.with(is_over_active_selection(mouse_event, vcanvas)));
}
(CanvasToolState::ActiveSelection, Event::MouseDown(mouse_event)) if pressed(mouse_event)
&& is_over_active_selection(mouse_event, vcanvas) => {
}
(CanvasToolState::DraggingSelection, Event::MouseMove(mouse_event)) if pressed(mouse_event) => {
}
(CanvasToolState::DraggingSelection, Event::MouseUp(mouse_event)) if pressed(mouse_event) => {
}
(CanvasToolState::ActiveSelection, Event::MouseDown(mouse_event)) |
(CanvasToolState::Idle, Event::MouseDown(mouse_event)) if pressed(mouse_event) => {
self.state = CanvasToolState::SelectingRect {
@ -222,7 +243,7 @@ impl CanvasToolCtx {
let p0 = druid::Point::new(bbox.x0, bbox.y0);
let p1 = druid::Point::new(bbox.x1, bbox.y1);
if current_rect.contains(p0) && current_rect.contains(p1) {
return Some(i);
return Some(i);
}
None
}).collect::<Vector<usize>>();