Skip to content

Commit 788f8db

Browse files
committed
Remake node type icons (closes #483); color picker cleanup
1 parent 8a05712 commit 788f8db

File tree

12 files changed

+101
-63
lines changed

12 files changed

+101
-63
lines changed

editor/src/document/properties_panel_message_handler.rs

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ impl MessageHandler<PropertiesPanelMessage, &GrapheneDocument> for PropertiesPan
162162
ModifyStroke { color, weight } => {
163163
let path = self.active_path.clone().expect("Received update for properties panel with no active layer");
164164
let layer = graphene_document.layer(&path).unwrap();
165-
if let Some(color) = Color::from_rgba_str(&color).or(Color::from_rgb_str(&color)) {
165+
if let Some(color) = Color::from_rgba_str(&color).or_else(|| Color::from_rgb_str(&color)) {
166166
let stroke = Stroke::new(color, weight as f32);
167167
responses.push_back(Operation::SetLayerStroke { path, stroke }.into())
168168
} else {
@@ -214,15 +214,15 @@ fn register_layer_properties(layer: &Layer, responses: &mut VecDeque<Message>) {
214214
widgets: vec![
215215
match &layer.data {
216216
LayerDataType::Folder(_) => WidgetHolder::new(Widget::IconLabel(IconLabel {
217-
icon: "NodeTypeFolder".into(),
217+
icon: "NodeFolder".into(),
218218
gap_after: true,
219219
})),
220220
LayerDataType::Shape(_) => WidgetHolder::new(Widget::IconLabel(IconLabel {
221-
icon: "NodeTypePath".into(),
221+
icon: "NodePath".into(),
222222
gap_after: true,
223223
})),
224224
LayerDataType::Text(_) => WidgetHolder::new(Widget::IconLabel(IconLabel {
225-
icon: "NodeTypePath".into(),
225+
icon: "NodeText".into(),
226226
gap_after: true,
227227
})),
228228
},
@@ -258,7 +258,7 @@ fn register_layer_properties(layer: &Layer, responses: &mut VecDeque<Message>) {
258258
vec![]
259259
}
260260
LayerDataType::Shape(shape) => {
261-
if let Some(fill_layout) = node_section_fill(&shape.style.fill()) {
261+
if let Some(fill_layout) = node_section_fill(shape.style.fill()) {
262262
vec![node_section_transform(layer), fill_layout, node_section_stroke(&shape.style.stroke().unwrap_or_default())]
263263
} else {
264264
vec![node_section_transform(layer), node_section_stroke(&shape.style.stroke().unwrap_or_default())]
@@ -267,7 +267,7 @@ fn register_layer_properties(layer: &Layer, responses: &mut VecDeque<Message>) {
267267
LayerDataType::Text(text) => {
268268
vec![
269269
node_section_transform(layer),
270-
node_section_fill(&text.style.fill()).expect("Text should have fill"),
270+
node_section_fill(text.style.fill()).expect("Text should have fill"),
271271
node_section_stroke(&text.style.stroke().unwrap_or_default()),
272272
]
273273
}
@@ -421,13 +421,13 @@ fn node_section_fill(fill: &Fill) -> Option<LayoutRow> {
421421
..TextLabel::default()
422422
})),
423423
WidgetHolder::new(Widget::Separator(Separator {
424-
separator_type: SeparatorType::Related,
424+
separator_type: SeparatorType::Unrelated,
425425
direction: SeparatorDirection::Horizontal,
426426
})),
427427
WidgetHolder::new(Widget::ColorInput(ColorInput {
428428
value: color.rgba_hex(),
429429
on_update: WidgetCallback::new(|text_input: &ColorInput| {
430-
if let Some(color) = Color::from_rgba_str(&text_input.value).or(Color::from_rgb_str(&text_input.value)) {
430+
if let Some(color) = Color::from_rgba_str(&text_input.value).or_else(|| Color::from_rgb_str(&text_input.value)) {
431431
let new_fill = Fill::Solid(color);
432432
PropertiesPanelMessage::ModifyFill { fill: new_fill }.into()
433433
} else {
@@ -452,13 +452,13 @@ fn node_section_fill(fill: &Fill) -> Option<LayoutRow> {
452452
..TextLabel::default()
453453
})),
454454
WidgetHolder::new(Widget::Separator(Separator {
455-
separator_type: SeparatorType::Related,
455+
separator_type: SeparatorType::Unrelated,
456456
direction: SeparatorDirection::Horizontal,
457457
})),
458458
WidgetHolder::new(Widget::ColorInput(ColorInput {
459459
value: gradient_1.positions[0].1.rgba_hex(),
460460
on_update: WidgetCallback::new(move |text_input: &ColorInput| {
461-
if let Some(color) = Color::from_rgba_str(&text_input.value).or(Color::from_rgb_str(&text_input.value)) {
461+
if let Some(color) = Color::from_rgba_str(&text_input.value).or_else(|| Color::from_rgb_str(&text_input.value)) {
462462
let mut new_gradient = (*gradient_1).clone();
463463
new_gradient.positions[0].1 = color;
464464
PropertiesPanelMessage::ModifyFill {
@@ -480,13 +480,13 @@ fn node_section_fill(fill: &Fill) -> Option<LayoutRow> {
480480
..TextLabel::default()
481481
})),
482482
WidgetHolder::new(Widget::Separator(Separator {
483-
separator_type: SeparatorType::Related,
483+
separator_type: SeparatorType::Unrelated,
484484
direction: SeparatorDirection::Horizontal,
485485
})),
486486
WidgetHolder::new(Widget::ColorInput(ColorInput {
487487
value: gradient_2.positions[1].1.rgba_hex(),
488488
on_update: WidgetCallback::new(move |text_input: &ColorInput| {
489-
if let Some(color) = Color::from_rgba_str(&text_input.value).or(Color::from_rgb_str(&text_input.value)) {
489+
if let Some(color) = Color::from_rgba_str(&text_input.value).or_else(|| Color::from_rgb_str(&text_input.value)) {
490490
let mut new_gradient = (*gradient_2).clone();
491491
new_gradient.positions[1].1 = color;
492492
PropertiesPanelMessage::ModifyFill {
@@ -521,7 +521,7 @@ fn node_section_stroke(stroke: &Stroke) -> LayoutRow {
521521
..TextLabel::default()
522522
})),
523523
WidgetHolder::new(Widget::Separator(Separator {
524-
separator_type: SeparatorType::Related,
524+
separator_type: SeparatorType::Unrelated,
525525
direction: SeparatorDirection::Horizontal,
526526
})),
527527
WidgetHolder::new(Widget::ColorInput(ColorInput {
@@ -544,7 +544,7 @@ fn node_section_stroke(stroke: &Stroke) -> LayoutRow {
544544
..TextLabel::default()
545545
})),
546546
WidgetHolder::new(Widget::Separator(Separator {
547-
separator_type: SeparatorType::Related,
547+
separator_type: SeparatorType::Unrelated,
548548
direction: SeparatorDirection::Horizontal,
549549
})),
550550
WidgetHolder::new(Widget::NumberInput(NumberInput {
Lines changed: 4 additions & 0 deletions
Loading
Lines changed: 3 additions & 0 deletions
Loading
Lines changed: 3 additions & 0 deletions
Loading

frontend/assets/24px-full-color/node-type-folder.svg

Lines changed: 0 additions & 26 deletions
This file was deleted.

frontend/assets/24px-full-color/node-type-path.svg

Lines changed: 0 additions & 4 deletions
This file was deleted.

frontend/src/App.vue

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
--color-e-nearwhite-rgb: 238, 238, 238;
5454
--color-f-white: #fff;
5555
--color-f-white-rgb: 255, 255, 255;
56+
5657
--color-accent: #3194d6;
5758
--color-accent-rgb: 49, 148, 214;
5859
--color-accent-hover: #49a5e2;
@@ -62,6 +63,11 @@
6263
6364
--color-data-raster: #e4bb72;
6465
--color-data-raster-rgb: 228, 187, 114;
66+
67+
--color-node-background: #f1decd;
68+
--color-node-background-rgb: 241, 222, 205;
69+
--color-node-icon: #473a3a;
70+
--color-node-icon-rgb: 71, 58, 58;
6571
}
6672
6773
html,

frontend/src/components/panels/LayerTree.vue

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
<LayoutRow></LayoutRow>
3333
<LayoutRow>
3434
<!-- TODO: Remember to make these tooltip input hints customized to macOS also -->
35-
<IconButton :action="createEmptyFolder" :icon="'NewLayer'" title="New Folder (Ctrl+Shift+N)" :size="16" />
35+
<IconButton :action="createEmptyFolder" :icon="'NodeFolder'" title="New Folder (Ctrl+Shift+N)" :size="16" />
3636
<IconButton :action="deleteSelectedLayers" :icon="'Trash'" title="Delete Selected (Del)" :size="16" />
3737
</LayoutRow>
3838
</LayoutRow>
@@ -74,8 +74,9 @@
7474
:title="`${listing.entry.name}\n${devMode ? 'Layer Path: ' + listing.entry.path.join(' / ') : ''}`"
7575
>
7676
<LayoutRow class="layer-type-icon">
77-
<IconLabel v-if="listing.entry.layer_type === 'Folder'" :icon="'NodeTypeFolder'" title="Folder" />
78-
<IconLabel v-else :icon="'NodeTypePath'" title="Path" />
77+
<IconLabel v-if="listing.entry.layer_type === 'Folder'" :icon="'NodeFolder'" title="Folder" />
78+
<IconLabel v-else-if="listing.entry.layer_type === 'Shape'" :icon="'NodePath'" title="Path" />
79+
<IconLabel v-else-if="listing.entry.layer_type === 'Text'" :icon="'NodeText'" title="Path" />
7980
</LayoutRow>
8081
<LayoutRow class="layer-name" @dblclick="() => onEditLayerName(listing)">
8182
<input
@@ -142,7 +143,7 @@
142143
flex: 0 0 auto;
143144
align-items: center;
144145
position: relative;
145-
height: 36px;
146+
height: 32px;
146147
margin: 0 4px;
147148
border-bottom: 1px solid var(--color-4-dimgray);
148149
@@ -217,6 +218,12 @@
217218
.layer-type-icon {
218219
flex: 0 0 auto;
219220
margin: 0 4px;
221+
222+
.icon-label {
223+
border-radius: 2px;
224+
background: var(--color-node-background);
225+
fill: var(--color-node-icon);
226+
}
220227
}
221228
222229
.layer-name {
@@ -260,10 +267,10 @@
260267
}
261268
262269
.thumbnail {
263-
height: calc(100% - 4px);
270+
width: 36px;
271+
height: 24px;
264272
margin: 2px 0;
265273
margin-left: 4px;
266-
width: 64px;
267274
background: white;
268275
border-radius: 2px;
269276
flex: 0 0 auto;

frontend/src/components/panels/Properties.vue

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,20 @@
2121
.options-bar {
2222
height: 32px;
2323
flex: 0 0 auto;
24+
25+
.widget-row > .icon-label:first-of-type {
26+
border-radius: 2px;
27+
background: var(--color-node-background);
28+
fill: var(--color-node-icon);
29+
}
2430
}
2531
2632
.sections {
2733
flex: 1 1 100%;
34+
35+
.widget-section + .widget-section {
36+
margin-top: 1px;
37+
}
2838
}
2939
}
3040
</style>

frontend/src/components/widgets/inputs/ColorInput.vue

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
<template>
22
<LayoutRow class="color-input">
3-
<TextInput :value="value" :label="label" :disabled="disabled" @commitText="(value: string) => textInputUpdated(value)" :center="true" />
3+
<TextInput :value="displayValue" :label="label" :disabled="disabled" @commitText="(value: string) => textInputUpdated(value)" :center="true" />
44
<Separator :type="'Related'" />
55
<LayoutRow class="swatch">
6-
<button class="swatch-button" @click="() => menuOpen()" :style="{ background: `#${value}` }"></button>
6+
<button class="swatch-button" @click="() => menuOpen()" :style="`--swatch-color: #${value}`"></button>
77
<FloatingMenu :type="'Popover'" :direction="'Bottom'" horizontal ref="colorFloatingMenu">
88
<ColorPicker @update:color="(color) => colorPickerUpdated(color)" :color="color" />
99
</FloatingMenu>
@@ -22,6 +22,7 @@
2222
position: relative;
2323
2424
.swatch-button {
25+
--swatch-color: #ffffff;
2526
height: 24px;
2627
width: 24px;
2728
bottom: 0;
@@ -30,6 +31,19 @@
3031
outline: none;
3132
border: none;
3233
border-radius: 2px;
34+
background: linear-gradient(45deg, #cccccc 25%, transparent 25%, transparent 75%, #cccccc 75%), linear-gradient(45deg, #cccccc 25%, transparent 25%, transparent 75%, #cccccc 75%),
35+
linear-gradient(#ffffff, #ffffff);
36+
background-size: 16px 16px;
37+
background-position: 0 0, 8px 8px;
38+
overflow: hidden;
39+
40+
&::before {
41+
content: "";
42+
display: block;
43+
width: 100%;
44+
height: 100%;
45+
background: var(--swatch-color);
46+
}
3347
}
3448
3549
.floating-menu {
@@ -67,6 +81,11 @@ export default defineComponent({
6781
const a = parseInt(this.value.slice(6, 8), 16);
6882
return { r, g, b, a: a / 255 };
6983
},
84+
displayValue() {
85+
const value = this.value.toLowerCase();
86+
const shortenedIfOpaque = value.slice(-2) === "ff" ? value.slice(0, 6) : value;
87+
return `#${shortenedIfOpaque}`;
88+
},
7089
},
7190
methods: {
7291
colorPickerUpdated(color: RGBA) {
@@ -76,9 +95,22 @@ export default defineComponent({
7695
this.$emit("update:value", newValue);
7796
},
7897
textInputUpdated(newValue: string) {
79-
if ((newValue.length !== 6 && newValue.length !== 8) || !newValue.match(/[A-F,a-f,0-9]*/)) return;
98+
const sanitizedMatch = newValue.match(/^\s*#?([0-9a-fA-F]{8}|[0-9a-fA-F]{6}|[0-9a-fA-F]{3})\s*$/);
99+
if (!sanitizedMatch) return;
80100
81-
this.$emit("update:value", newValue);
101+
let sanitized;
102+
const match = sanitizedMatch[1];
103+
if (match.length === 3) {
104+
sanitized = match
105+
.split("")
106+
.map((byte) => `${byte}${byte}`)
107+
.concat("ff")
108+
.join("");
109+
} else if (match.length === 6) sanitized = `${match}ff`;
110+
else if (match.length === 8) sanitized = match;
111+
else return;
112+
113+
this.$emit("update:value", sanitized);
82114
},
83115
menuOpen() {
84116
(this.$refs.colorFloatingMenu as typeof FloatingMenu).setOpen();

frontend/src/dispatcher/js-messages.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,7 @@ export class LayerMetadata {
369369
selected!: boolean;
370370
}
371371

372-
export type LayerType = "Folder" | "Shape" | "Circle" | "Rect" | "Line" | "PolyLine" | "Ellipse";
372+
export type LayerType = "Folder" | "Shape" | "Text";
373373

374374
export class IndexedDbDocumentDetails extends DocumentDetails {
375375
@Transform(({ value }: { value: BigInt }) => value.toString())

0 commit comments

Comments
 (0)