Refactor the WidgetLayout struct to remove SubLayout and avoid sending LayoutTarget to frontend

This commit is contained in:
Keavon Chambers
2025-12-04 02:44:54 -08:00
parent 4581689d9c
commit 3c4ad8b720
50 changed files with 207 additions and 247 deletions
@@ -34,8 +34,8 @@
</LayoutRow>
<LayoutRow class={`content ${$dialog.title === "Demo Artwork" ? "center" : "" /* TODO: Replace this with a less hacky approach that's compatible with localization/translation */}`}>
<LayoutCol class="column-1">
{#if $dialog.column1.layout.length > 0}
<WidgetLayout layout={$dialog.column1} class="details" />
{#if $dialog.column1.length > 0}
<WidgetLayout layout={$dialog.column1} layoutTarget="DialogColumn1" class="details" />
{/if}
{#if $dialog.panicDetails}
<div class="widget-layout details">
@@ -57,15 +57,15 @@
</div>
{/if}
</LayoutCol>
{#if $dialog.column2.layout.length > 0}
{#if $dialog.column2.length > 0}
<LayoutCol class="column-2">
<WidgetLayout layout={$dialog.column2} class="details" />
<WidgetLayout layout={$dialog.column2} layoutTarget="DialogColumn2" class="details" />
</LayoutCol>
{/if}
</LayoutRow>
<LayoutRow class="footer-area">
{#if $dialog.buttons.layout.length > 0}
<WidgetLayout layout={$dialog.buttons} class="details" />
{#if $dialog.buttons.length > 0}
<WidgetLayout layout={$dialog.buttons} layoutTarget="DialogButtons" class="details" />
{/if}
{#if $dialog.panicDetails}
<TextButton label="Copy Error Log" action={() => navigator.clipboard.writeText($dialog.panicDetails)} />
+3 -3
View File
@@ -2,14 +2,14 @@
import { getContext, onMount, onDestroy } from "svelte";
import type { Editor } from "@graphite/editor";
import { defaultWidgetLayout, patchWidgetLayout, UpdateDataPanelLayout } from "@graphite/messages";
import { patchWidgetLayout, UpdateDataPanelLayout, type LayoutGroup } from "@graphite/messages";
import LayoutCol from "@graphite/components/layout/LayoutCol.svelte";
import WidgetLayout from "@graphite/components/widgets/WidgetLayout.svelte";
const editor = getContext<Editor>("editor");
let dataPanelLayout = defaultWidgetLayout();
let dataPanelLayout: LayoutGroup[] = [];
onMount(() => {
editor.subscriptions.subscribeJsMessage(UpdateDataPanelLayout, (updateDataPanelLayout) => {
@@ -25,7 +25,7 @@
<LayoutCol class="data-panel">
<LayoutCol class="body" scrollableY={true}>
<WidgetLayout layout={dataPanelLayout} />
<WidgetLayout layout={dataPanelLayout} layoutTarget="DataPanel" />
</LayoutCol>
</LayoutCol>
@@ -126,7 +126,7 @@
totalToolRowsFor2Columns,
totalToolRowsFor3Columns,
};
})($document.toolShelfLayout.layout[0]);
})($document.toolShelfLayout[0]);
function dropFile(e: DragEvent) {
const { dataTransfer } = e;
@@ -506,12 +506,12 @@
<LayoutCol class="document" on:dragover={(e) => e.preventDefault()} on:drop={dropFile}>
<LayoutRow class="control-bar" classes={{ "for-graph": $document.graphViewOverlayOpen }} scrollableX={true}>
{#if !$document.graphViewOverlayOpen}
<WidgetLayout layout={$document.documentModeLayout} />
<WidgetLayout layout={$document.toolOptionsLayout} />
<WidgetLayout layout={$document.documentModeLayout} layoutTarget="DocumentMode" />
<WidgetLayout layout={$document.toolOptionsLayout} layoutTarget="ToolOptions" />
<LayoutRow class="spacer" />
<WidgetLayout layout={$document.documentBarLayout} />
<WidgetLayout layout={$document.documentBarLayout} layoutTarget="DocumentBar" />
{:else}
<WidgetLayout layout={$document.nodeGraphControlBarLayout} />
<WidgetLayout layout={$document.nodeGraphControlBarLayout} layoutTarget="NodeGraphControlBar" />
{/if}
</LayoutRow>
<LayoutRow
@@ -526,13 +526,13 @@
<LayoutCol class="tool-shelf">
{#if !$document.graphViewOverlayOpen}
<LayoutCol class="tools" scrollableY={true}>
<WidgetLayout layout={$document.toolShelfLayout} />
<WidgetLayout layout={$document.toolShelfLayout} layoutTarget="ToolShelf" />
</LayoutCol>
{:else}
<LayoutRow class="spacer" />
{/if}
<LayoutCol class="tool-shelf-bottom-widgets">
<WidgetLayout class="working-colors-input-area" layout={$document.workingColorsLayout} />
<WidgetLayout class="working-colors-input-area" layout={$document.workingColorsLayout} layoutTarget="WorkingColors" />
</LayoutCol>
</LayoutCol>
<LayoutCol class="viewport-container">
+8 -9
View File
@@ -4,7 +4,6 @@
import { shortcutAltClick } from "@graphite/../wasm/pkg/graphite_wasm";
import type { Editor } from "@graphite/editor";
import {
defaultWidgetLayout,
patchWidgetLayout,
UpdateDocumentLayerDetails,
UpdateDocumentLayerStructureJs,
@@ -12,7 +11,7 @@
UpdateLayersPanelControlBarRightLayout,
UpdateLayersPanelBottomBarLayout,
} from "@graphite/messages";
import type { ActionShortcut, DataBuffer, LayerPanelEntry } from "@graphite/messages";
import type { ActionShortcut, DataBuffer, LayerPanelEntry, LayoutGroup } from "@graphite/messages";
import type { NodeGraphState } from "@graphite/state-providers/node-graph";
import { operatingSystem } from "@graphite/utility-functions/platform";
import { extractPixelData } from "@graphite/utility-functions/rasterization";
@@ -70,9 +69,9 @@
let layerToClipAltKeyPressed = false;
// Layouts
let layersPanelControlBarLeftLayout = defaultWidgetLayout();
let layersPanelControlBarRightLayout = defaultWidgetLayout();
let layersPanelBottomBarLayout = defaultWidgetLayout();
let layersPanelControlBarLeftLayout: LayoutGroup[] = [];
let layersPanelControlBarRightLayout: LayoutGroup[] = [];
let layersPanelBottomBarLayout: LayoutGroup[] = [];
const altClickKeys: ActionShortcut = shortcutAltClick();
@@ -582,11 +581,11 @@
<LayoutCol class="layers" on:dragleave={() => (dragInPanel = false)}>
<LayoutRow class="control-bar" scrollableX={true}>
<WidgetLayout layout={layersPanelControlBarLeftLayout} />
{#if layersPanelControlBarLeftLayout?.layout?.length > 0 && layersPanelControlBarRightLayout?.layout?.length > 0}
<WidgetLayout layout={layersPanelControlBarLeftLayout} layoutTarget="LayersPanelControlLeftBar" />
{#if layersPanelControlBarLeftLayout?.length > 0 && layersPanelControlBarRightLayout?.length > 0}
<Separator />
{/if}
<WidgetLayout layout={layersPanelControlBarRightLayout} />
<WidgetLayout layout={layersPanelControlBarRightLayout} layoutTarget="LayersPanelControlRightBar" />
</LayoutRow>
<LayoutRow class="list-area" classes={{ "drag-ongoing": Boolean(internalDragState?.active && draggingData) }} scrollableY={true}>
<LayoutCol
@@ -691,7 +690,7 @@
{/if}
</LayoutRow>
<LayoutRow class="bottom-bar" scrollableX={true}>
<WidgetLayout layout={layersPanelBottomBarLayout} />
<WidgetLayout layout={layersPanelBottomBarLayout} layoutTarget="LayersPanelBottomBar" />
</LayoutRow>
</LayoutCol>
@@ -2,14 +2,14 @@
import { getContext, onMount, onDestroy } from "svelte";
import type { Editor } from "@graphite/editor";
import { defaultWidgetLayout, patchWidgetLayout, UpdatePropertiesPanelLayout } from "@graphite/messages";
import { patchWidgetLayout, UpdatePropertiesPanelLayout, type LayoutGroup } from "@graphite/messages";
import LayoutCol from "@graphite/components/layout/LayoutCol.svelte";
import WidgetLayout from "@graphite/components/widgets/WidgetLayout.svelte";
const editor = getContext<Editor>("editor");
let propertiesPanelLayout = defaultWidgetLayout();
let propertiesPanelLayout: LayoutGroup[] = [];
onMount(() => {
editor.subscriptions.subscribeJsMessage(UpdatePropertiesPanelLayout, (updatePropertiesPanelLayout) => {
@@ -25,7 +25,7 @@
<LayoutCol class="properties">
<LayoutCol class="sections" scrollableY={true}>
<WidgetLayout layout={propertiesPanelLayout} />
<WidgetLayout layout={propertiesPanelLayout} layoutTarget="PropertiesPanel" />
</LayoutCol>
</LayoutCol>
@@ -2,7 +2,8 @@
import { getContext, onMount, onDestroy } from "svelte";
import type { Editor } from "@graphite/editor";
import { defaultWidgetLayout, patchWidgetLayout, UpdateWelcomeScreenButtonsLayout } from "@graphite/messages";
import type { LayoutGroup } from "@graphite/messages";
import { patchWidgetLayout, UpdateWelcomeScreenButtonsLayout } from "@graphite/messages";
import { extractPixelData } from "@graphite/utility-functions/rasterization";
import LayoutCol from "@graphite/components/layout/LayoutCol.svelte";
@@ -13,7 +14,7 @@
const editor = getContext<Editor>("editor");
let welcomePanelButtonsLayout = defaultWidgetLayout();
let welcomePanelButtonsLayout: LayoutGroup[] = [];
onMount(() => {
editor.subscriptions.subscribeJsMessage(UpdateWelcomeScreenButtonsLayout, (updateWelcomeScreenButtonsLayout) => {
@@ -68,7 +69,7 @@
<IconLabel icon="GraphiteLogotypeSolid" />
</LayoutRow>
<LayoutRow class="actions">
<WidgetLayout layout={welcomePanelButtonsLayout} />
<WidgetLayout layout={welcomePanelButtonsLayout} layoutTarget="WelcomeScreenButtons" />
</LayoutRow>
</LayoutCol>
</LayoutCol>
@@ -1,26 +1,24 @@
<script lang="ts">
import { isWidgetSpanColumn, isWidgetSpanRow, isWidgetSection, type WidgetLayout, isWidgetTable } from "@graphite/messages";
import { isWidgetSpanColumn, isWidgetSpanRow, isWidgetSection, type LayoutGroup, isWidgetTable, type LayoutTarget } from "@graphite/messages";
import TextLabel from "@graphite/components/widgets/labels/TextLabel.svelte";
import WidgetSection from "@graphite/components/widgets/WidgetSection.svelte";
import WidgetSpan from "@graphite/components/widgets/WidgetSpan.svelte";
import WidgetTable from "@graphite/components/widgets/WidgetTable.svelte";
export let layout: WidgetLayout;
export let layout: LayoutGroup[];
export let layoutTarget: LayoutTarget;
let className = "";
export { className as class };
export let classes: Record<string, boolean> = {};
</script>
{#each layout.layout as layoutGroup}
{#each layout as layoutGroup}
{#if isWidgetSpanRow(layoutGroup) || isWidgetSpanColumn(layoutGroup)}
<WidgetSpan widgetData={layoutGroup} layoutTarget={layout.layoutTarget} class={className} {classes} />
<WidgetSpan widgetData={layoutGroup} {layoutTarget} class={className} {classes} />
{:else if isWidgetSection(layoutGroup)}
<WidgetSection widgetData={layoutGroup} layoutTarget={layout.layoutTarget} class={className} {classes} />
<WidgetSection widgetData={layoutGroup} {layoutTarget} class={className} {classes} />
{:else if isWidgetTable(layoutGroup)}
<WidgetTable widgetData={layoutGroup} unstyled={layoutGroup.unstyled} layoutTarget={layout.layoutTarget} />
{:else}
<TextLabel styles={{ color: "#d6536e" }}>Error: The widget layout that belongs here has an invalid layout group type</TextLabel>
<WidgetTable widgetData={layoutGroup} {layoutTarget} unstyled={layoutGroup.unstyled} />
{/if}
{/each}
@@ -2,7 +2,7 @@
import { getContext } from "svelte";
import type { Editor } from "@graphite/editor";
import { isWidgetSpanRow, isWidgetSpanColumn, isWidgetSection, type WidgetSection as WidgetSectionFromJsMessages } from "@graphite/messages";
import { isWidgetSpanRow, isWidgetSection, type WidgetSection as WidgetSectionFromJsMessages, type LayoutTarget } from "@graphite/messages";
import LayoutCol from "@graphite/components/layout/LayoutCol.svelte";
import IconButton from "@graphite/components/widgets/buttons/IconButton.svelte";
@@ -10,8 +10,7 @@
import WidgetSpan from "@graphite/components/widgets/WidgetSpan.svelte";
export let widgetData: WidgetSectionFromJsMessages;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export let layoutTarget: any; // TODO: Give type
export let layoutTarget: LayoutTarget;
let className = "";
export { className as class };
@@ -64,12 +63,8 @@
{#each widgetData.layout as layoutGroup}
{#if isWidgetSpanRow(layoutGroup)}
<WidgetSpan widgetData={layoutGroup} {layoutTarget} />
{:else if isWidgetSpanColumn(layoutGroup)}
<TextLabel styles={{ color: "#d6536e" }}>Error: The WidgetSpan used here should be a row not a column</TextLabel>
{:else if isWidgetSection(layoutGroup)}
<svelte:self widgetData={layoutGroup} {layoutTarget} />
{:else}
<TextLabel styles={{ color: "#d6536e" }}>Error: The widget that belongs here has an invalid layout group type</TextLabel>
{/if}
{/each}
</LayoutCol>
@@ -2,7 +2,7 @@
import { getContext } from "svelte";
import type { Editor } from "@graphite/editor";
import type { Widget, WidgetSpanColumn, WidgetSpanRow } from "@graphite/messages";
import type { LayoutTarget, Widget, WidgetSpanColumn, WidgetSpanRow } from "@graphite/messages";
import { narrowWidgetProps, isWidgetSpanColumn, isWidgetSpanRow } from "@graphite/messages";
import { debouncer } from "@graphite/utility-functions/debounce";
@@ -34,8 +34,7 @@
const editor = getContext<Editor>("editor");
export let widgetData: WidgetSpanRow | WidgetSpanColumn;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export let layoutTarget: any;
export let layoutTarget: LayoutTarget;
let className = "";
export { className as class };
@@ -162,7 +161,7 @@
{@const popoverButton = narrowWidgetProps(component.props, "PopoverButton")}
{#if popoverButton}
<PopoverButton {...exclude(popoverButton, ["popoverLayout"])}>
<WidgetLayout layout={{ layout: popoverButton.popoverLayout, layoutTarget: layoutTarget }} />
<WidgetLayout layout={popoverButton.popoverLayout} {layoutTarget} />
</PopoverButton>
{/if}
{@const radioInput = narrowWidgetProps(component.props, "RadioInput")}
@@ -1,11 +1,10 @@
<script lang="ts">
import { type WidgetTable as WidgetTableFromJsMessages } from "@graphite/messages";
import { type LayoutTarget, type WidgetTable as WidgetTableFromJsMessages } from "@graphite/messages";
import WidgetSpan from "@graphite/components/widgets/WidgetSpan.svelte";
export let widgetData: WidgetTableFromJsMessages;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export let layoutTarget: any;
export let layoutTarget: LayoutTarget;
export let unstyled = false;
$: columns = widgetData.tableWidgets.length > 0 ? widgetData.tableWidgets[0].length : 0;
@@ -2,14 +2,15 @@
import { getContext, onMount } from "svelte";
import type { Editor } from "@graphite/editor";
import { defaultWidgetLayout, patchWidgetLayout, UpdateStatusBarHintsLayout } from "@graphite/messages";
import type { LayoutGroup } from "@graphite/messages";
import { patchWidgetLayout, UpdateStatusBarHintsLayout } from "@graphite/messages";
import LayoutRow from "@graphite/components/layout/LayoutRow.svelte";
import WidgetLayout from "@graphite/components/widgets/WidgetLayout.svelte";
const editor = getContext<Editor>("editor");
let statusBarHintsLayout = defaultWidgetLayout();
let statusBarHintsLayout: LayoutGroup[] = [];
onMount(() => {
editor.subscriptions.subscribeJsMessage(UpdateStatusBarHintsLayout, (updateStatusBarHintsLayout) => {
@@ -20,7 +21,7 @@
</script>
<LayoutRow class="status-bar">
<WidgetLayout class="hints" layout={statusBarHintsLayout} />
<WidgetLayout class="hints" layout={statusBarHintsLayout} layoutTarget="StatusBarHints" />
</LayoutRow>
<style lang="scss" global>
@@ -2,7 +2,8 @@
import { getContext, onMount } from "svelte";
import type { Editor } from "@graphite/editor";
import { defaultWidgetLayout, patchWidgetLayout, UpdateMenuBarLayout } from "@graphite/messages";
import type { LayoutGroup } from "@graphite/messages";
import { patchWidgetLayout, UpdateMenuBarLayout } from "@graphite/messages";
import type { AppWindowState } from "@graphite/state-providers/app-window";
import LayoutRow from "@graphite/components/layout/LayoutRow.svelte";
@@ -14,7 +15,7 @@
const appWindow = getContext<AppWindowState>("appWindow");
const editor = getContext<Editor>("editor");
let menuBarLayout = defaultWidgetLayout();
let menuBarLayout: LayoutGroup[] = [];
onMount(() => {
editor.subscriptions.subscribeJsMessage(UpdateMenuBarLayout, (updateMenuBarLayout) => {
@@ -28,7 +29,7 @@
<!-- Menu bar -->
<LayoutRow>
{#if $appWindow.platform !== "Mac"}
<WidgetLayout layout={menuBarLayout} />
<WidgetLayout layout={menuBarLayout} layoutTarget="MenuBar" />
{/if}
</LayoutRow>
<!-- Spacer -->