mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-28 01:38:11 +08:00
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:
committed by
Keavon Chambers
parent
03c5847d7e
commit
7d3239ecac
@@ -65,7 +65,7 @@
|
|||||||
<ShelfItemInput :icon="'LayoutSelectTool'" title="Select Tool (V)" :active="activeTool === 'Select'" @click="selectTool('Select')" />
|
<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="'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="'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" />
|
<Separator :type="SeparatorType.Section" :direction="SeparatorDirection.Vertical" />
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,9 @@ impl Fill {
|
|||||||
pub fn new(color: Color) -> Self {
|
pub fn new(color: Color) -> Self {
|
||||||
Self { color: Some(color) }
|
Self { color: Some(color) }
|
||||||
}
|
}
|
||||||
|
pub fn color(&self) -> Option<Color> {
|
||||||
|
self.color
|
||||||
|
}
|
||||||
pub fn none() -> Self {
|
pub fn none() -> Self {
|
||||||
Self { color: None }
|
Self { color: None }
|
||||||
}
|
}
|
||||||
@@ -41,6 +44,12 @@ impl Stroke {
|
|||||||
pub fn new(color: Color, width: f32) -> Self {
|
pub fn new(color: Color, width: f32) -> Self {
|
||||||
Self { color, width }
|
Self { color, width }
|
||||||
}
|
}
|
||||||
|
pub fn color(&self) -> Color {
|
||||||
|
self.color
|
||||||
|
}
|
||||||
|
pub fn width(&self) -> f32 {
|
||||||
|
self.width
|
||||||
|
}
|
||||||
pub fn render(&self) -> String {
|
pub fn render(&self) -> String {
|
||||||
format!(r##" stroke="#{}"{} stroke-width="{}""##, self.color.rgb_hex(), format_opacity("stroke", self.color.a()), self.width)
|
format!(r##" stroke="#{}"{} stroke-width="{}""##, self.color.rgb_hex(), format_opacity("stroke", self.color.a()), self.width)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -122,6 +122,9 @@ impl Default for Mapping {
|
|||||||
entry! {action=SelectMessage::DragStop, key_up=Lmb},
|
entry! {action=SelectMessage::DragStop, key_up=Lmb},
|
||||||
entry! {action=SelectMessage::Abort, key_down=Rmb},
|
entry! {action=SelectMessage::Abort, key_down=Rmb},
|
||||||
entry! {action=SelectMessage::Abort, key_down=KeyEscape},
|
entry! {action=SelectMessage::Abort, key_down=KeyEscape},
|
||||||
|
// Eyedropper
|
||||||
|
entry! {action=EyedropperMessage::LeftMouseDown, key_down=Lmb},
|
||||||
|
entry! {action=EyedropperMessage::RightMouseDown, key_down=Rmb},
|
||||||
// Rectangle
|
// Rectangle
|
||||||
entry! {action=RectangleMessage::Center, key_down=KeyAlt},
|
entry! {action=RectangleMessage::Center, key_down=KeyAlt},
|
||||||
entry! {action=RectangleMessage::UnCenter, key_up=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::Line), key_down=KeyL},
|
||||||
entry! {action=ToolMessage::SelectTool(ToolType::Pen), key_down=KeyP},
|
entry! {action=ToolMessage::SelectTool(ToolType::Pen), key_down=KeyP},
|
||||||
entry! {action=ToolMessage::SelectTool(ToolType::Shape), key_down=KeyY},
|
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::ResetColors, key_down=KeyX, modifiers=[KeyShift, KeyControl]},
|
||||||
entry! {action=ToolMessage::SwapColors, key_down=KeyX, modifiers=[KeyShift]},
|
entry! {action=ToolMessage::SwapColors, key_down=KeyX, modifiers=[KeyShift]},
|
||||||
// Document Actions
|
// Document Actions
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
|
use crate::consts::SELECTION_TOLERANCE;
|
||||||
|
use crate::frontend::FrontendMessage;
|
||||||
use crate::message_prelude::*;
|
use crate::message_prelude::*;
|
||||||
use crate::tool::ToolActionHandlerData;
|
use crate::tool::{ToolActionHandlerData, ToolMessage};
|
||||||
|
use glam::DVec2;
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct Eyedropper;
|
pub struct Eyedropper;
|
||||||
@@ -7,12 +10,40 @@ pub struct Eyedropper;
|
|||||||
#[impl_message(Message, ToolMessage, Eyedropper)]
|
#[impl_message(Message, ToolMessage, Eyedropper)]
|
||||||
#[derive(PartialEq, Clone, Debug)]
|
#[derive(PartialEq, Clone, Debug)]
|
||||||
pub enum EyedropperMessage {
|
pub enum EyedropperMessage {
|
||||||
MouseMove,
|
LeftMouseDown,
|
||||||
|
RightMouseDown,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for Eyedropper {
|
impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for Eyedropper {
|
||||||
fn process_action(&mut self, action: ToolMessage, data: ToolActionHandlerData<'a>, responses: &mut VecDeque<Message>) {
|
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);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user