Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 1.2k
Options bar widgets for tools to control tool behavior#283
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
3203f7b8e56a278ea6fd82fe1d605edfa41607ac6099b26c921a1046651161f6177c0e56c1c2ff832166d328dc8File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,134 @@ | ||
| <template> | ||
| <div class="tool-options"> | ||
| <template v-for="(option, index) in optionsMap.get(activeTool) || []" :key="index"> | ||
| <IconButton v-if="option.kind === 'icon_button'" :icon="option.icon" :size="24" :title="option.title" /> | ||
| <Separator v-if="option.kind === 'separator'" :type="option.type" /> | ||
| <PopoverButton v-if="option.kind === 'popover_button'"> | ||
| <h3>{{ option.title }}</h3> | ||
| <p>{{ option.placeholderText }}</p> | ||
| </PopoverButton> | ||
| <NumberInput v-if="option.kind === 'number_input'" :callback="option.callback" :initialValue="option.initial" :step="option.step" :min="option.min" :updateOnCallback="true" /> | ||
| </template> | ||
| </div> | ||
| </template> | ||
| <style lang="scss"> | ||
| .tool-options { | ||
| height: 100%; | ||
| flex: 0 0 auto; | ||
| display: flex; | ||
| align-items: center; | ||
| } | ||
| </style> | ||
| <script lang="ts"> | ||
| import { defineComponent } from "vue"; | ||
| import Separator, { SeparatorType } from "@/components/widgets/separators/Separator.vue"; | ||
| import IconButton from "@/components/widgets/buttons/IconButton.vue"; | ||
| import PopoverButton from "@/components/widgets/buttons/PopoverButton.vue"; | ||
| import NumberInput from "@/components/widgets/inputs/NumberInput.vue"; | ||
| const wasm = import("@/../wasm/pkg"); | ||
| type ToolOptionsList = Array<ToolOptions>; | ||
| type ToolOptionsMap = Map<string, ToolOptionsList>; | ||
| type ToolOptions = IconButtonOption | SeparatorOption | PopoverButtonOption | NumberInputOption; | ||
| interface IconButtonOption { | ||
| kind: "icon_button"; | ||
| icon: string; | ||
| title: string; | ||
| } | ||
| interface SeparatorOption { | ||
| kind: "separator"; | ||
| type: SeparatorType; | ||
| } | ||
| interface PopoverButtonOption { | ||
| kind: "popover_button"; | ||
| title: string; | ||
| placeholderText: string; | ||
| } | ||
| interface NumberInputOption { | ||
| kind: "number_input"; | ||
| initial: number; | ||
| step: number; | ||
| min?: number; | ||
| callback?: Function; | ||
| } | ||
| export default defineComponent({ | ||
| props: { | ||
| activeTool: { type: String }, | ||
| }, | ||
| computed: {}, | ||
| methods: { | ||
| async setToolOptions(newValue: number) { | ||
| // 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. | ||
| // Later, it could send a single-field update to the backend. | ||
| const { set_tool_options } = await wasm; | ||
| // This is a placeholder call, using the Shape tool as an example | ||
| set_tool_options(this.$props.activeTool || "", { Shape: { shape_type: { Polygon: { vertices: newValue } } } }); | ||
| }, | ||
| }, | ||
| data() { | ||
| const optionsMap: ToolOptionsMap = new Map([ | ||
| [ | ||
| "Select", | ||
| [ | ||
| { kind: "icon_button", icon: "AlignHorizontalLeft", title: "Horizontal Align Left" }, | ||
| { kind: "icon_button", icon: "AlignHorizontalCenter", title: "Horizontal Align Center" }, | ||
| { kind: "icon_button", icon: "AlignHorizontalRight", title: "Horizontal Align Right" }, | ||
| { kind: "separator", type: SeparatorType.Unrelated }, | ||
| { kind: "icon_button", icon: "AlignVerticalTop", title: "Vertical Align Top" }, | ||
| { kind: "icon_button", icon: "AlignVerticalCenter", title: "Vertical Align Center" }, | ||
| { kind: "icon_button", icon: "AlignVerticalBottom", title: "Vertical Align Bottom" }, | ||
| { kind: "separator", type: SeparatorType.Related }, | ||
| { kind: "popover_button", title: "Align", placeholderText: "More alignment-related buttons will be here" }, | ||
| { kind: "separator", type: SeparatorType.Section }, | ||
| { kind: "icon_button", icon: "FlipHorizontal", title: "Flip Horizontal" }, | ||
| { kind: "icon_button", icon: "FlipVertical", title: "Flip Vertical" }, | ||
| { kind: "separator", type: SeparatorType.Related }, | ||
| { kind: "popover_button", title: "Flip", placeholderText: "More flip-related buttons will be here" }, | ||
| { kind: "separator", type: SeparatorType.Section }, | ||
| { kind: "icon_button", icon: "BooleanUnion", title: "Boolean Union" }, | ||
| { kind: "icon_button", icon: "BooleanSubtractFront", title: "Boolean Subtract Front" }, | ||
| { kind: "icon_button", icon: "BooleanSubtractBack", title: "Boolean Subtract Back" }, | ||
| { kind: "icon_button", icon: "BooleanIntersect", title: "Boolean Intersect" }, | ||
| { kind: "icon_button", icon: "BooleanDifference", title: "Boolean Difference" }, | ||
| { kind: "separator", type: SeparatorType.Related }, | ||
| { kind: "popover_button", title: "Boolean", placeholderText: "More boolean-related buttons will be here" }, | ||
| ], | ||
| ], | ||
| ["Shape", [{ kind: "number_input", initial: 6, step: 1, min: 3, callback: this.setToolOptions }]], | ||
| ]); | ||
| return { | ||
| optionsMap, | ||
| SeparatorType, | ||
| }; | ||
| }, | ||
| components: { | ||
| Separator, | ||
| IconButton, | ||
| PopoverButton, | ||
| NumberInput, | ||
| }, | ||
| }); | ||
| </script> | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| use serde::{Deserialize, Serialize}; | ||
| #[derive(Debug, Clone, Copy, Eq, PartialEq, Serialize, Deserialize)] | ||
| pub enum ToolOptions { | ||
| Select { append_mode: SelectAppendMode }, | ||
| Ellipse, | ||
| Shape { shape_type: ShapeType }, | ||
| } | ||
| #[derive(Debug, Clone, Copy, Eq, PartialEq, Serialize, Deserialize)] | ||
| pub enum SelectAppendMode { | ||
| New, | ||
| Add, | ||
| Subtract, | ||
| Intersect, | ||
| } | ||
| #[derive(Debug, Clone, Copy, Eq, PartialEq, Serialize, Deserialize)] | ||
| pub enum ShapeType { | ||
| Star { vertices: u32 }, | ||
| Polygon { vertices: u32 }, | ||
| } |
This file was deleted.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.