[WIP] Allow dragging selections
This commit is contained in:
parent
393394ed53
commit
9c7ef5a55b
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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>>();
|
||||
|
|
|
|||
Loading…
Reference in New Issue