MVP eyedropper tool for fill colors (#300)

* Implement eyedropper for layer fill colors

* Add shortcut for eyedropper

* Add right mouse sampling for secondary color
This commit is contained in:
Henry Sloan 2021-07-24 18:29:32 -04:00 committed by GitHub
parent e78d598a37
commit da8422786b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 49 additions and 5 deletions

View file

@ -65,7 +65,7 @@
<ShelfItemInput :icon="'LayoutSelectTool'" title="Select Tool (V)" :active="activeTool === 'Select'" @click="selectTool('Select')" />
<ShelfItemInput :icon="'LayoutCropTool'" title="Crop Tool" :active="activeTool === 'Crop'" @click="'tool not implemented' || selectTool('Crop')" />
<ShelfItemInput :icon="'LayoutNavigateTool'" title="Navigate Tool (Z)" :active="activeTool === 'Navigate'" @click="'tool not implemented' || selectTool('Navigate')" />
<ShelfItemInput :icon="'LayoutEyedropperTool'" title="Eyedropper Tool (I)" :active="activeTool === 'Eyedropper'" @click="'tool not implemented' || selectTool('Eyedropper')" />
<ShelfItemInput :icon="'LayoutEyedropperTool'" title="Eyedropper Tool (I)" :active="activeTool === 'Eyedropper'" @click="selectTool('Eyedropper')" />
<Separator :type="SeparatorType.Section" :direction="SeparatorDirection.Vertical" />

View file

@ -19,6 +19,9 @@ impl Fill {
pub fn new(color: Color) -> Self {
Self { color: Some(color) }
}
pub fn color(&self) -> Option<Color> {
self.color
}
pub fn none() -> Self {
Self { color: None }
}
@ -41,6 +44,12 @@ impl Stroke {
pub fn new(color: Color, width: f32) -> Self {
Self { color, width }
}
pub fn color(&self) -> Color {
self.color
}
pub fn width(&self) -> f32 {
self.width
}
pub fn render(&self) -> String {
format!(r##" stroke="#{}"{} stroke-width="{}""##, self.color.rgb_hex(), format_opacity("stroke", self.color.a()), self.width)
}

View file

@ -122,6 +122,9 @@ impl Default for Mapping {
entry! {action=SelectMessage::DragStop, key_up=Lmb},
entry! {action=SelectMessage::Abort, key_down=Rmb},
entry! {action=SelectMessage::Abort, key_down=KeyEscape},
// Eyedropper
entry! {action=EyedropperMessage::LeftMouseDown, key_down=Lmb},
entry! {action=EyedropperMessage::RightMouseDown, key_down=Rmb},
// Rectangle
entry! {action=RectangleMessage::Center, key_down=KeyAlt},
entry! {action=RectangleMessage::UnCenter, key_up=KeyAlt},
@ -181,6 +184,7 @@ impl Default for Mapping {
entry! {action=ToolMessage::SelectTool(ToolType::Line), key_down=KeyL},
entry! {action=ToolMessage::SelectTool(ToolType::Pen), key_down=KeyP},
entry! {action=ToolMessage::SelectTool(ToolType::Shape), key_down=KeyY},
entry! {action=ToolMessage::SelectTool(ToolType::Eyedropper), key_down=KeyI},
entry! {action=ToolMessage::ResetColors, key_down=KeyX, modifiers=[KeyShift, KeyControl]},
entry! {action=ToolMessage::SwapColors, key_down=KeyX, modifiers=[KeyShift]},
// Document Actions

View file

@ -1,5 +1,8 @@
use crate::consts::SELECTION_TOLERANCE;
use crate::frontend::FrontendMessage;
use crate::message_prelude::*;
use crate::tool::ToolActionHandlerData;
use crate::tool::{ToolActionHandlerData, ToolMessage};
use glam::DVec2;
#[derive(Default)]
pub struct Eyedropper;
@ -7,12 +10,40 @@ pub struct Eyedropper;
#[impl_message(Message, ToolMessage, Eyedropper)]
#[derive(PartialEq, Clone, Debug)]
pub enum EyedropperMessage {
MouseMove,
LeftMouseDown,
RightMouseDown,
}
impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for Eyedropper {
fn process_action(&mut self, action: ToolMessage, data: ToolActionHandlerData<'a>, responses: &mut VecDeque<Message>) {
todo!("{}::handle_input {:?} {:?} {:?} ", module_path!(), action, data, responses);
let mouse_pos = data.2.mouse.position;
let (x, y) = (mouse_pos.x as f64, mouse_pos.y as f64);
let (point_1, point_2) = (
DVec2::new(x - SELECTION_TOLERANCE, y - SELECTION_TOLERANCE),
DVec2::new(x + SELECTION_TOLERANCE, y + SELECTION_TOLERANCE),
);
let quad = [
DVec2::new(point_1.x, point_1.y),
DVec2::new(point_2.x, point_1.y),
DVec2::new(point_2.x, point_2.y),
DVec2::new(point_1.x, point_2.y),
];
if let Some(path) = data.0.document.intersects_quad_root(quad).last() {
if let Ok(layer) = data.0.document.layer(path) {
if let Some(fill) = layer.style.fill() {
if let Some(color) = fill.color() {
let (primary, secondary) = match action {
ToolMessage::Eyedropper(EyedropperMessage::LeftMouseDown) => (color, data.1.secondary_color),
ToolMessage::Eyedropper(EyedropperMessage::RightMouseDown) => (data.1.primary_color, color),
_ => (data.1.primary_color, data.1.secondary_color),
};
responses.push_back(FrontendMessage::UpdateWorkingColors { primary, secondary }.into());
}
}
}
}
}
advertise_actions!();
advertise_actions!(EyedropperMessageDiscriminant; LeftMouseDown, RightMouseDown);
}