mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2025-08-04 13:30:48 +00:00
Add Snapping Options to the Snap Dropdown Menu (#1321)
* [wip]feat: add snapping options
* [wip]fix: use svelte component for optionsWidget
* fix: use apt PopoverButton types
* refactor: minor formatting improvements
* Fix popover layout
* [wip]feat: attempt implementing CheckboxInputData struct
* fix: use correct Checkbox struct 's default method
* fix: revert adding CheckboxInputData struct
- This reverts commit 2a481887fc
.
* feat: use checkboxes for snapping options
* feat: add label to dropdown checkbox elements
* fix: separate Snap dropdown menu elements
- move each element into separate row
* [wip]feat: modularize snapping states
- maintain individual snapping states for document
* fix: snapping checkboxes' behavior
- checkboxes now update internal snapping state
* refactor: update snap states individually
- this prevents out-of-sync states
- enables reusing existing snap state object
* feat: snap to boxes and nodes conditionally
* [wip]feat: attempt to invert checkbox on update
- attempt implementing mutable WidgetCallback struct
- attempt using above struct to invert checkbox state on update
* Fix widget diffing
* refactor: remove unused code
* feat: align checkboxes consistently with labels
* feat: use separators to stylize snapping menu
- removes need for custom CSS and label property
- ensures consistency across the application
* refactor: remove unneeded css
---------
Co-authored-by: hypercube <0hypercube@gmail.com>, TrueDoctor <dennis@kobert.dev>
This commit is contained in:
parent
4c9daadb01
commit
743803ce04
12 changed files with 204 additions and 41 deletions
|
@ -1,5 +1,5 @@
|
|||
<script lang="ts">
|
||||
import { isWidgetColumn, isWidgetRow, isWidgetSection, type WidgetLayout } from "@graphite/wasm-communication/messages";
|
||||
import { isWidgetColumn, isWidgetRow, isWidgetSection, LayoutGroup, type WidgetLayout } from "@graphite/wasm-communication/messages";
|
||||
|
||||
import WidgetSection from "@graphite/components/widgets/groups/WidgetSection.svelte";
|
||||
import WidgetRow from "@graphite/components/widgets/WidgetRow.svelte";
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
import { isWidgetColumn, isWidgetRow, type WidgetColumn, type WidgetRow } from "@graphite/wasm-communication/messages";
|
||||
|
||||
import PivotAssist from "@graphite/components/widgets/assists/PivotAssist.svelte";
|
||||
import WidgetLayout from "@graphite/components/widgets/WidgetLayout.svelte";
|
||||
import BreadcrumbTrailButtons from "@graphite/components/widgets/buttons/BreadcrumbTrailButtons.svelte";
|
||||
import IconButton from "@graphite/components/widgets/buttons/IconButton.svelte";
|
||||
import ParameterExposeButton from "@graphite/components/widgets/buttons/ParameterExposeButton.svelte";
|
||||
|
@ -138,9 +139,13 @@
|
|||
{/if}
|
||||
{@const popoverButton = narrowWidgetProps(component.props, "PopoverButton")}
|
||||
{#if popoverButton}
|
||||
<PopoverButton {...exclude(popoverButton, ["header", "text"])}>
|
||||
<PopoverButton {...exclude(popoverButton, ["header", "text", "optionsWidget"])}>
|
||||
<TextLabel bold={true}>{popoverButton.header}</TextLabel>
|
||||
<TextLabel multiline={true}>{popoverButton.text}</TextLabel>
|
||||
{#if popoverButton.optionsWidget}
|
||||
<WidgetLayout layout={{ layout: popoverButton.optionsWidget, layoutTarget: layoutTarget }} />
|
||||
{:else}
|
||||
<TextLabel multiline={true}>{popoverButton.text}</TextLabel>
|
||||
{/if}
|
||||
</PopoverButton>
|
||||
{/if}
|
||||
{@const radioInput = narrowWidgetProps(component.props, "RadioInput")}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
<script lang="ts">
|
||||
import type { IconName } from "@graphite/utility-functions/icons";
|
||||
|
||||
import FloatingMenu from "@graphite/components/layout/FloatingMenu.svelte";
|
||||
import LayoutRow from "@graphite/components/layout/LayoutRow.svelte";
|
||||
import IconButton from "@graphite/components/widgets/buttons/IconButton.svelte";
|
||||
|
@ -8,6 +7,7 @@
|
|||
export let icon: IconName = "DropdownArrow";
|
||||
export let tooltip: string | undefined = undefined;
|
||||
export let disabled = false;
|
||||
|
||||
// Callbacks
|
||||
export let action: (() => void) | undefined = undefined;
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
|||
|
||||
<LayoutRow class="popover-button">
|
||||
<IconButton classes={{ open }} {disabled} action={() => onClick()} icon={icon || "DropdownArrow"} size={16} {tooltip} data-floating-menu-spawner />
|
||||
|
||||
<FloatingMenu {open} on:open={({ detail }) => (open = detail)} type="Popover" direction="Bottom">
|
||||
<slot />
|
||||
</FloatingMenu>
|
||||
|
|
|
@ -499,15 +499,15 @@ export class UpdateMouseCursor extends JsMessage {
|
|||
readonly cursor!: MouseCursorIcon;
|
||||
}
|
||||
|
||||
export class TriggerLoadAutoSaveDocuments extends JsMessage {}
|
||||
export class TriggerLoadAutoSaveDocuments extends JsMessage { }
|
||||
|
||||
export class TriggerLoadPreferences extends JsMessage {}
|
||||
export class TriggerLoadPreferences extends JsMessage { }
|
||||
|
||||
export class TriggerOpenDocument extends JsMessage {}
|
||||
export class TriggerOpenDocument extends JsMessage { }
|
||||
|
||||
export class TriggerImport extends JsMessage {}
|
||||
export class TriggerImport extends JsMessage { }
|
||||
|
||||
export class TriggerPaste extends JsMessage {}
|
||||
export class TriggerPaste extends JsMessage { }
|
||||
|
||||
export class TriggerCopyToClipboardBlobUrl extends JsMessage {
|
||||
readonly blobUrl!: string;
|
||||
|
@ -546,7 +546,7 @@ export class TriggerRasterizeRegionBelowLayer extends JsMessage {
|
|||
readonly size!: [number, number];
|
||||
}
|
||||
|
||||
export class TriggerRefreshBoundsOfViewports extends JsMessage {}
|
||||
export class TriggerRefreshBoundsOfViewports extends JsMessage { }
|
||||
|
||||
export class TriggerRevokeBlobUrl extends JsMessage {
|
||||
readonly url!: string;
|
||||
|
@ -556,7 +556,7 @@ export class TriggerSavePreferences extends JsMessage {
|
|||
readonly preferences!: Record<string, unknown>;
|
||||
}
|
||||
|
||||
export class DocumentChanged extends JsMessage {}
|
||||
export class DocumentChanged extends JsMessage { }
|
||||
|
||||
export class UpdateDocumentLayerTreeStructureJs extends JsMessage {
|
||||
constructor(readonly layerId: bigint, readonly children: UpdateDocumentLayerTreeStructureJs[]) {
|
||||
|
@ -649,7 +649,7 @@ export class UpdateImageData extends JsMessage {
|
|||
readonly imageData!: ImaginateImageData[];
|
||||
}
|
||||
|
||||
export class DisplayRemoveEditableTextbox extends JsMessage {}
|
||||
export class DisplayRemoveEditableTextbox extends JsMessage { }
|
||||
|
||||
export class UpdateDocumentLayerDetails extends JsMessage {
|
||||
@Type(() => LayerPanelEntry)
|
||||
|
@ -700,7 +700,7 @@ export class ImaginateImageData {
|
|||
readonly transform!: Float64Array;
|
||||
}
|
||||
|
||||
export class DisplayDialogDismiss extends JsMessage {}
|
||||
export class DisplayDialogDismiss extends JsMessage { }
|
||||
|
||||
export class Font {
|
||||
fontFamily!: string;
|
||||
|
@ -719,7 +719,7 @@ export class TriggerVisitLink extends JsMessage {
|
|||
url!: string;
|
||||
}
|
||||
|
||||
export class TriggerTextCommit extends JsMessage {}
|
||||
export class TriggerTextCommit extends JsMessage { }
|
||||
|
||||
export class TriggerTextCopy extends JsMessage {
|
||||
readonly copyText!: string;
|
||||
|
@ -729,7 +729,7 @@ export class TriggerAboutGraphiteLocalizedCommitDate extends JsMessage {
|
|||
readonly commitDate!: string;
|
||||
}
|
||||
|
||||
export class TriggerViewportResize extends JsMessage {}
|
||||
export class TriggerViewportResize extends JsMessage { }
|
||||
|
||||
// WIDGET PROPS
|
||||
|
||||
|
@ -774,7 +774,7 @@ type MenuEntryCommon = {
|
|||
export type MenuBarEntry = MenuEntryCommon & {
|
||||
action: Widget;
|
||||
children?: MenuBarEntry[][];
|
||||
disabled?: boolean,
|
||||
disabled?: boolean,
|
||||
};
|
||||
|
||||
// An entry in the all-encompassing MenuList component which defines all types of menus ranging from `MenuBarInput` to `DropdownInput` widgets
|
||||
|
@ -931,6 +931,8 @@ export class PopoverButton extends WidgetProps {
|
|||
|
||||
@Transform(({ value }: { value: string }) => value || undefined)
|
||||
tooltip!: string | undefined;
|
||||
|
||||
optionsWidget: LayoutGroup[] | undefined;
|
||||
}
|
||||
|
||||
export type RadioEntryData = {
|
||||
|
@ -1126,6 +1128,10 @@ function hoistWidgetHolder(widgetHolder: any): Widget {
|
|||
const props = widgetHolder.widget[kind];
|
||||
props.kind = kind;
|
||||
|
||||
if (kind === "PopoverButton") {
|
||||
props.optionsWidget = props.optionsWidget.map(createLayoutGroup);
|
||||
}
|
||||
|
||||
const { widgetId } = widgetHolder;
|
||||
|
||||
return plainToClass(Widget, { props, widgetId });
|
||||
|
@ -1173,6 +1179,9 @@ export function patchWidgetLayout(/* mut */ layout: WidgetLayout, updates: Widge
|
|||
if ("rowWidgets" in targetLayout) return targetLayout.rowWidgets[index];
|
||||
if ("layout" in targetLayout) return targetLayout.layout[index];
|
||||
if (targetLayout instanceof Widget) {
|
||||
if (targetLayout.props.kind === "PopoverButton" && targetLayout.props instanceof PopoverButton && targetLayout.props.optionsWidget) {
|
||||
return targetLayout.props.optionsWidget[index];
|
||||
}
|
||||
// eslint-disable-next-line no-console
|
||||
console.error("Tried to index widget");
|
||||
return targetLayout;
|
||||
|
@ -1258,25 +1267,25 @@ function createLayoutGroup(layoutGroup: any): LayoutGroup {
|
|||
}
|
||||
|
||||
// WIDGET LAYOUTS
|
||||
export class UpdateDialogDetails extends WidgetDiffUpdate {}
|
||||
export class UpdateDialogDetails extends WidgetDiffUpdate { }
|
||||
|
||||
export class UpdateDocumentModeLayout extends WidgetDiffUpdate {}
|
||||
export class UpdateDocumentModeLayout extends WidgetDiffUpdate { }
|
||||
|
||||
export class UpdateToolOptionsLayout extends WidgetDiffUpdate {}
|
||||
export class UpdateToolOptionsLayout extends WidgetDiffUpdate { }
|
||||
|
||||
export class UpdateDocumentBarLayout extends WidgetDiffUpdate {}
|
||||
export class UpdateDocumentBarLayout extends WidgetDiffUpdate { }
|
||||
|
||||
export class UpdateToolShelfLayout extends WidgetDiffUpdate {}
|
||||
export class UpdateToolShelfLayout extends WidgetDiffUpdate { }
|
||||
|
||||
export class UpdateWorkingColorsLayout extends WidgetDiffUpdate {}
|
||||
export class UpdateWorkingColorsLayout extends WidgetDiffUpdate { }
|
||||
|
||||
export class UpdatePropertyPanelOptionsLayout extends WidgetDiffUpdate {}
|
||||
export class UpdatePropertyPanelOptionsLayout extends WidgetDiffUpdate { }
|
||||
|
||||
export class UpdatePropertyPanelSectionsLayout extends WidgetDiffUpdate {}
|
||||
export class UpdatePropertyPanelSectionsLayout extends WidgetDiffUpdate { }
|
||||
|
||||
export class UpdateLayerTreeOptionsLayout extends WidgetDiffUpdate {}
|
||||
export class UpdateLayerTreeOptionsLayout extends WidgetDiffUpdate { }
|
||||
|
||||
export class UpdateNodeGraphBarLayout extends WidgetDiffUpdate {}
|
||||
export class UpdateNodeGraphBarLayout extends WidgetDiffUpdate { }
|
||||
|
||||
export class UpdateMenuBarLayout extends JsMessage {
|
||||
layoutTarget!: unknown;
|
||||
|
@ -1301,7 +1310,7 @@ function createMenuLayoutRecursive(children: any[][]): MenuBarEntry[][] {
|
|||
...entry,
|
||||
action: hoistWidgetHolders([entry.action])[0],
|
||||
children: entry.children ? createMenuLayoutRecursive(entry.children) : undefined,
|
||||
disabled: entry.disabled ?? false,
|
||||
disabled: entry.disabled ?? false,
|
||||
}))
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue