Add a stroke width option to the Line Tool (#355)

* Add a stroke width option to the Line Tool

* Fix title case for line options

* Add px unit to line stroke width

* Add stroke width to pen tool

* Rename stroke width to weight

* Change number input width to min-width

* Remove the word "stroke" from "stroke weight"
This commit is contained in:
Henry Sloan 2021-08-23 21:55:59 -04:00 committed by Keavon Chambers
parent 0a7c6df222
commit 44f244fb5f
5 changed files with 33 additions and 8 deletions

View File

@ -5,6 +5,8 @@ pub enum ToolOptions {
Select { append_mode: SelectAppendMode }, Select { append_mode: SelectAppendMode },
Ellipse, Ellipse,
Shape { shape_type: ShapeType }, Shape { shape_type: ShapeType },
Line { weight: u32 },
Pen { weight: u32 },
} }
#[derive(Debug, Clone, Copy, Eq, PartialEq, Serialize, Deserialize, Hash)] #[derive(Debug, Clone, Copy, Eq, PartialEq, Serialize, Deserialize, Hash)]

View File

@ -1,7 +1,7 @@
use crate::consts::LINE_ROTATE_SNAP_ANGLE; use crate::consts::LINE_ROTATE_SNAP_ANGLE;
use crate::input::keyboard::Key; use crate::input::keyboard::Key;
use crate::input::{mouse::ViewportPosition, InputPreprocessor}; use crate::input::{mouse::ViewportPosition, InputPreprocessor};
use crate::tool::{DocumentToolData, Fsm, ToolActionHandlerData}; use crate::tool::{DocumentToolData, Fsm, ToolActionHandlerData, ToolOptions, ToolType};
use crate::{document::DocumentMessageHandler, message_prelude::*}; use crate::{document::DocumentMessageHandler, message_prelude::*};
use glam::{DAffine2, DVec2}; use glam::{DAffine2, DVec2};
use graphene::{layers::style, Operation}; use graphene::{layers::style, Operation};
@ -50,6 +50,7 @@ struct LineToolData {
drag_start: ViewportPosition, drag_start: ViewportPosition,
drag_current: ViewportPosition, drag_current: ViewportPosition,
angle: f64, angle: f64,
weight: u32,
path: Option<Vec<LayerId>>, path: Option<Vec<LayerId>>,
} }
@ -75,12 +76,17 @@ impl Fsm for LineToolFsmState {
data.path = Some(vec![generate_uuid()]); data.path = Some(vec![generate_uuid()]);
responses.push_back(DocumentMessage::DeselectAllLayers.into()); responses.push_back(DocumentMessage::DeselectAllLayers.into());
data.weight = match tool_data.tool_options.get(&ToolType::Line) {
Some(&ToolOptions::Line { weight }) => weight,
_ => 5,
};
responses.push_back( responses.push_back(
Operation::AddLine { Operation::AddLine {
path: data.path.clone().unwrap(), path: data.path.clone().unwrap(),
insert_index: -1, insert_index: -1,
transform: DAffine2::ZERO.to_cols_array(), transform: DAffine2::ZERO.to_cols_array(),
style: style::PathStyle::new(Some(style::Stroke::new(tool_data.primary_color, 5.)), None), style: style::PathStyle::new(Some(style::Stroke::new(tool_data.primary_color, data.weight as f32)), None),
} }
.into(), .into(),
); );

View File

@ -1,5 +1,5 @@
use crate::input::InputPreprocessor; use crate::input::InputPreprocessor;
use crate::tool::{DocumentToolData, Fsm, ToolActionHandlerData}; use crate::tool::{DocumentToolData, Fsm, ToolActionHandlerData, ToolOptions, ToolType};
use crate::{document::DocumentMessageHandler, message_prelude::*}; use crate::{document::DocumentMessageHandler, message_prelude::*};
use glam::DAffine2; use glam::DAffine2;
use graphene::{layers::style, Operation}; use graphene::{layers::style, Operation};
@ -49,6 +49,7 @@ impl Default for PenToolFsmState {
struct PenToolData { struct PenToolData {
points: Vec<DAffine2>, points: Vec<DAffine2>,
next_point: DAffine2, next_point: DAffine2,
weight: u32,
path: Option<Vec<LayerId>>, path: Option<Vec<LayerId>>,
} }
@ -79,6 +80,11 @@ impl Fsm for PenToolFsmState {
data.points.push(pos); data.points.push(pos);
data.next_point = pos; data.next_point = pos;
data.weight = match tool_data.tool_options.get(&ToolType::Pen) {
Some(&ToolOptions::Pen { weight }) => weight,
_ => 5,
};
Dragging Dragging
} }
(Dragging, DragStop) => { (Dragging, DragStop) => {
@ -140,7 +146,7 @@ fn make_operation(data: &PenToolData, tool_data: &DocumentToolData, show_preview
insert_index: -1, insert_index: -1,
transform: DAffine2::IDENTITY.to_cols_array(), transform: DAffine2::IDENTITY.to_cols_array(),
points, points,
style: style::PathStyle::new(Some(style::Stroke::new(tool_data.primary_color, 5.)), Some(style::Fill::none())), style: style::PathStyle::new(Some(style::Stroke::new(tool_data.primary_color, data.weight as f32)), Some(style::Fill::none())),
} }
.into(), .into(),
] ]

View File

@ -19,7 +19,7 @@
<style lang="scss"> <style lang="scss">
.number-input { .number-input {
width: 80px; min-width: 80px;
height: 24px; height: 24px;
position: relative; position: relative;
border-radius: 2px; border-radius: 2px;
@ -38,7 +38,8 @@
input { input {
flex: 1 1 100%; flex: 1 1 100%;
width: 100%; width: 0;
min-width: 30px;
height: 18px; height: 18px;
line-height: 18px; line-height: 18px;
margin: 0 8px; margin: 0 8px;

View File

@ -41,7 +41,7 @@ export default defineComponent({
}, },
computed: {}, computed: {},
methods: { methods: {
async setToolOptions(newValue: number) { async setShapeOptions(newValue: number) {
// TODO: Each value-input widget (i.e. not a button) should map to a field in an options struct, // TODO: Each value-input widget (i.e. not a button) should map to a field in an options struct,
// and updating a widget should send the whole updated struct to the backend. // and updating a widget should send the whole updated struct to the backend.
// Later, it could send a single-field update to the backend. // Later, it could send a single-field update to the backend.
@ -50,6 +50,14 @@ export default defineComponent({
// eslint-disable-next-line camelcase // eslint-disable-next-line camelcase
(await wasm).set_tool_options(this.$props.activeTool || "", { Shape: { shape_type: { Polygon: { vertices: newValue } } } }); (await wasm).set_tool_options(this.$props.activeTool || "", { Shape: { shape_type: { Polygon: { vertices: newValue } } } });
}, },
async setLineOptions(newValue: number) {
// eslint-disable-next-line camelcase
(await wasm).set_tool_options(this.$props.activeTool || "", { Line: { weight: newValue } });
},
async setPenOptions(newValue: number) {
// eslint-disable-next-line camelcase
(await wasm).set_tool_options(this.$props.activeTool || "", { Pen: { weight: newValue } });
},
async sendToolMessage(message: string | object) { async sendToolMessage(message: string | object) {
(await wasm).send_tool_message(this.$props.activeTool || "", message); (await wasm).send_tool_message(this.$props.activeTool || "", message);
}, },
@ -126,7 +134,9 @@ export default defineComponent({
props: {}, props: {},
}, },
], ],
Shape: [{ kind: "NumberInput", callback: this.setToolOptions, props: { value: 6, min: 3, isInteger: true, label: "Sides" } }], Shape: [{ kind: "NumberInput", callback: this.setShapeOptions, props: { value: 6, min: 3, isInteger: true, label: "Sides" } }],
Line: [{ kind: "NumberInput", callback: this.setLineOptions, props: { value: 5, min: 1, isInteger: true, unit: " px", label: "Weight" } }],
Pen: [{ kind: "NumberInput", callback: this.setPenOptions, props: { value: 5, min: 1, isInteger: true, unit: " px", label: "Weight" } }],
}; };
return { return {