11<template >
22 <div class =" tool-options" >
3- <template v-for =" (option , index ) in toolOptions [activeTool ] || [] " :key =" index " >
3+ <template v-for =" (option , index ) in toolOptionsWidgets [activeTool ] || [] " :key =" index " >
44 <!-- TODO: Use `<component :is="" v-bind="attributesObject"></component>` to avoid all the separate components with `v-if` -->
55 <IconButton v-if =" option .kind === ' IconButton' " :action =" () => handleIconButtonAction (option ) " :title =" option .tooltip " v-bind =" option .props " />
66 <PopoverButton v-if =" option .kind === ' PopoverButton' " :title =" option .tooltip " :action =" option .callback " v-bind =" option .props " >
77 <h3 >{{ option.popover.title }}</h3 >
88 <p >{{ option.popover.text }}</p >
99 </PopoverButton >
10- <NumberInput v-if =" option .kind === ' NumberInput' " v-model :value =" option .props .value " @update :value =" option .callback " :title =" option .tooltip " v-bind =" option .props " />
10+ <NumberInput
11+ v-if =" option .kind === ' NumberInput' "
12+ @update :value =" (value ) => updateToolOptions (option .optionPath , value ) "
13+ :title =" option .tooltip "
14+ :value =" getToolOption (option .optionPath )"
15+ v-bind =" option .props "
16+ />
1117 <Separator v-if =" option .kind === ' Separator' " v-bind =" option .props " />
1218 </template >
1319 </div >
2329 </style >
2430
2531<script lang="ts">
26- import { defineComponent } from " vue" ;
32+ import { defineComponent , PropType } from " vue" ;
2733
2834import { comingSoon } from " @/utilities/errors" ;
2935import { WidgetRow , SeparatorType , IconButtonWidget } from " @/components/widgets/widgets" ;
@@ -38,28 +44,36 @@ const wasm = import("@/../wasm/pkg");
3844export default defineComponent ({
3945 props: {
4046 activeTool: { type: String },
47+ activeToolOptions: { type: Object as PropType <Record <string , object >> },
4148 },
42- computed: {},
4349 methods: {
44- async setShapeOptions(newValue : number ) {
45- // TODO: Each value-input widget (i.e. not a button) should map to a field in an options struct,
46- // and updating a widget should send the whole updated struct to the backend.
47- // Later, it could send a single-field update to the backend.
48-
49- // This is a placeholder call, using the Shape tool as an example
50- // eslint-disable-next-line camelcase
51- (await wasm ).set_tool_options (this .$props .activeTool || " " , { Shape: { shape_type: { Polygon: { vertices: newValue } } } });
50+ async updateToolOptions(path : string [], newValue : number ) {
51+ this .setToolOption (path , newValue );
52+ (await wasm ).set_tool_options (this .activeTool || " " , this .activeToolOptions );
5253 },
53- async setLineOptions(newValue : number ) {
54- // eslint-disable-next-line camelcase
55- (await wasm ).set_tool_options (this .$props .activeTool || " " , { Line: { weight: newValue } });
54+ async sendToolMessage(message : string | object ) {
55+ (await wasm ).send_tool_message (this .activeTool || " " , message );
5656 },
57- async setPenOptions(newValue : number ) {
58- // eslint-disable-next-line camelcase
59- (await wasm ).set_tool_options (this .$props .activeTool || " " , { Pen: { weight: newValue } });
57+ // Traverses the given path and returns the direct parent of the option
58+ getRecordContainingOption(optionPath : string []): Record <string , number > {
59+ const allButLast = optionPath .slice (0 , - 1 );
60+ let currentRecord = this .activeToolOptions as Record <string , object | number >;
61+ [this .activeTool || " " , ... allButLast ].forEach ((attr ) => {
62+ currentRecord = currentRecord [attr ] as Record <string , object | number >;
63+ });
64+ return currentRecord as Record <string , number >;
6065 },
61- async sendToolMessage(message : string | object ) {
62- (await wasm ).send_tool_message (this .$props .activeTool || " " , message );
66+ // Traverses the given path into the active tool's option struct, and sets the value at the path tail
67+ setToolOption(optionPath : string [], newValue : number ) {
68+ const last = optionPath .slice (- 1 )[0 ];
69+ const recordContainingOption = this .getRecordContainingOption (optionPath );
70+ recordContainingOption [last ] = newValue ;
71+ },
72+ // Traverses the given path into the active tool's option struct, and returns the value at the path tail
73+ getToolOption(optionPath : string []): number {
74+ const last = optionPath .slice (- 1 )[0 ];
75+ const recordContainingOption = this .getRecordContainingOption (optionPath );
76+ return recordContainingOption [last ];
6377 },
6478 handleIconButtonAction(option : IconButtonWidget ) {
6579 if (option .message ) {
@@ -76,7 +90,7 @@ export default defineComponent({
7690 },
7791 },
7892 data() {
79- const toolOptions : Record <string , WidgetRow > = {
93+ const toolOptionsWidgets : Record <string , WidgetRow > = {
8094 Select: [
8195 { kind: " IconButton" , message: { Align: [" X" , " Min" ] }, tooltip: " Align Left" , props: { icon: " AlignLeft" , size: 24 } },
8296 { kind: " IconButton" , message: { Align: [" X" , " Center" ] }, tooltip: " Align Horizontal Center" , props: { icon: " AlignHorizontalCenter" , size: 24 } },
@@ -134,13 +148,13 @@ export default defineComponent({
134148 props: {},
135149 },
136150 ],
137- Shape: [{ kind: " NumberInput" , callback: this . setShapeOptions , props: { value: 6 , min: 3 , isInteger: true , label: " Sides" } }],
138- Line: [{ kind: " NumberInput" , callback: this . setLineOptions , props: { value: 5 , min: 1 , isInteger: true , unit: " px" , label: " Weight" } }],
139- Pen: [{ kind: " NumberInput" , callback: this . setPenOptions , props: { value: 5 , min: 1 , isInteger: true , unit: " px" , label: " Weight" } }],
151+ Shape: [{ kind: " NumberInput" , optionPath: [ " shape_type " , " Polygon " , " vertices " ], props: { min: 3 , isInteger: true , label: " Sides" } }],
152+ Line: [{ kind: " NumberInput" , optionPath: [ " weight " ] , props: { min: 1 , isInteger: true , unit: " px" , label: " Weight" } }],
153+ Pen: [{ kind: " NumberInput" , optionPath: [ " weight " ] , props: { min: 1 , isInteger: true , unit: " px" , label: " Weight" } }],
140154 };
141155
142156 return {
143- toolOptions ,
157+ toolOptionsWidgets ,
144158 SeparatorType ,
145159 comingSoon ,
146160 };
0 commit comments