From b03a8a0d2a58ea6a9ad4dabb7f9f026ca82cfa32 Mon Sep 17 00:00:00 2001 From: Samuel Pastva Date: Mon, 22 Jan 2024 10:33:50 +0100 Subject: [PATCH] Add an optional layout data argument to `addVariable` that is applied within the same action. --- .../app/state/editor/_state_editor_session.rs | 4 ++ src/aeon_events.ts | 38 +++++++++++++++++-- .../root-component/root-component.ts | 8 +++- 3 files changed, 45 insertions(+), 5 deletions(-) diff --git a/src-tauri/src/app/state/editor/_state_editor_session.rs b/src-tauri/src/app/state/editor/_state_editor_session.rs index a4bb95f..005b71a 100644 --- a/src-tauri/src/app/state/editor/_state_editor_session.rs +++ b/src-tauri/src/app/state/editor/_state_editor_session.rs @@ -46,6 +46,7 @@ impl EditorSession { while let Some(event) = to_perform.pop() { let event_path = event.path.iter().map(|it| it.as_str()).collect::>(); + debug!("Executing event: `{:?}`.", event_path); let result = match self.perform_event(&event, &event_path) { Ok(result) => result, Err(error) => { @@ -107,6 +108,9 @@ impl EditorSession { perform.push(p); reverse.push(r); } + // Obviously, the "reverse" events need to be execute in the opposite order + // compared to the "perform" events. + reverse.reverse(); let perform = UserAction { events: perform }; let reverse = UserAction { events: reverse }; if !self.undo_stack.do_action(perform, reverse) { diff --git a/src/aeon_events.ts b/src/aeon_events.ts index ae78ccb..1c93676 100644 --- a/src/aeon_events.ts +++ b/src/aeon_events.ts @@ -65,7 +65,7 @@ interface AeonState { /** VariableData for a newly created variable. */ variableCreated: Observable /** Create new variable with given ID and name. If only ID string is given, it is used for both ID and name. */ - addVariable: (varId: string, varName: string) => void + addVariable: (varId: string, varName?: string, position?: LayoutNodeDataPrototype | LayoutNodeDataPrototype[]) => void /** VariableData of a removed variable. */ variableRemoved: Observable /** Remove a variable with given ID. */ @@ -143,6 +143,16 @@ export interface LayoutNodeData { py: number } +/** + * The same as `LayoutNodeData`, but does not have a fixed variable ID because + * it is associated with a variable that does not have an ID yet. + */ +export interface LayoutNodeDataPrototype { + layout: string + px: number + py: number +} + /** A function that is notified when a state value changes. */ export type OnStateValue = (value: T) => void @@ -577,14 +587,36 @@ export const aeonState: AeonState = { layoutRemoved: new Observable(['model', 'layout', 'remove']), nodePositionChanged: new Observable(['model', 'layout', 'update_position']), - addVariable (varId: string, varName: string = ''): void { + addVariable ( + varId: string, + varName: string = '', + position: LayoutNodeDataPrototype | LayoutNodeDataPrototype[] = [] + ): void { if (varName === '') { varName = varId } - aeonEvents.emitAction({ + const actions = [] + // First action creates the variable. + actions.push({ path: ['model', 'variable', 'add'], payload: JSON.stringify({ id: varId, name: varName }) }) + // Subsequent actions position it in one or more layouts. + if (!Array.isArray(position)) { + position = [position] + } + for (const p of position) { + actions.push({ + path: ['model', 'layout', p.layout, 'update_position'], + payload: JSON.stringify({ + layout: p.layout, + variable: varId, + px: p.px, + py: p.py + }) + }) + } + aeonEvents.emitAction(actions) }, removeVariable (varId: string): void { aeonEvents.emitAction({ diff --git a/src/html/component/root-component/root-component.ts b/src/html/component/root-component/root-component.ts index 0971649..0f90f46 100644 --- a/src/html/component/root-component/root-component.ts +++ b/src/html/component/root-component/root-component.ts @@ -92,8 +92,12 @@ class RootComponent extends LitElement { private addVariable (event: Event): void { const details = (event as CustomEvent).detail - aeonState.model.addVariable(details.id, details.name) - aeonState.model.changeNodePosition(LAYOUT, details.id, details.position.x, details.position.y) + const position = { + layout: LAYOUT, + px: details.position.x, + py: details.position.y + } + aeonState.model.addVariable(details.id, details.name, position) } #onVariableCreated (data: VariableData): void {