From 5c2718e48509347a5e083eb1b34e4153492c60ba Mon Sep 17 00:00:00 2001 From: Kaz Date: Fri, 1 Mar 2024 06:41:04 -0800 Subject: [PATCH 1/4] New menuVisible logic --- app/gui2/mock/providers.ts | 1 + .../src/components/GraphEditor/GraphNode.vue | 41 ++++++++----------- app/gui2/src/composables/selection.ts | 1 + 3 files changed, 18 insertions(+), 25 deletions(-) diff --git a/app/gui2/mock/providers.ts b/app/gui2/mock/providers.ts index 5100853d8bca..9845731a5550 100644 --- a/app/gui2/mock/providers.ts +++ b/app/gui2/mock/providers.ts @@ -30,6 +30,7 @@ export const graphSelection: GraphSelection = { hoveredNode: undefined, hoveredPort: undefined, isSelected: () => false, + isChanging: false, mouseHandler: () => false, selectAll: () => {}, selected: new Set(), diff --git a/app/gui2/src/components/GraphEditor/GraphNode.vue b/app/gui2/src/components/GraphEditor/GraphNode.vue index cb399e6cb981..83783d3f79de 100644 --- a/app/gui2/src/components/GraphEditor/GraphNode.vue +++ b/app/gui2/src/components/GraphEditor/GraphNode.vue @@ -87,14 +87,6 @@ const contentNode = ref() const nodeSize = useResizeObserver(rootNode) const baseNodeSize = computed(() => new Vec2(contentNode.value?.scrollWidth ?? 0, nodeSize.value.y)) -/// Menu can be full, partial or off -enum MenuState { - Full, - Partial, - Off, -} -const menuVisible = ref(MenuState.Off) - const error = computed(() => { const externalId = graph.db.idToExternal(nodeId.value) if (!externalId) return @@ -121,12 +113,19 @@ const warning = computed(() => { }) const isSelected = computed(() => nodeSelection?.isSelected(nodeId.value) ?? false) -const isOnlyOneSelected = computed(() => isSelected.value && nodeSelection?.selected.size === 1) -watch(isSelected, (selected) => { - if (!selected) { - menuVisible.value = MenuState.Off - } +const isOnlyOneSelected = computed( + () => isSelected.value && nodeSelection?.selected.size === 1 && !nodeSelection.isChanging, +) + +const menuVisible = isOnlyOneSelected +const menuFull = ref(false) +watch(menuVisible, (visible) => { + if (!visible) menuFull.value = false }) +function openFullMenu() { + menuFull.value = true + nodeSelection?.setSelection(new Set([nodeId.value])) +} const isDocsVisible = ref(false) const visualizationWidth = computed(() => props.node.vis?.width ?? null) @@ -180,7 +179,6 @@ const dragPointer = usePointer((pos, event, type) => { ) { nodeSelection?.handleSelectionOf(event, new Set([nodeId.value])) handleNodeClick(event) - menuVisible.value = MenuState.Partial } startEvent = null startEpochMs.value = 0 @@ -362,13 +360,6 @@ function portGroupStyle(port: PortData) { } } -function openFullMenu() { - if (!nodeSelection?.isSelected(nodeId.value)) { - nodeSelection?.setSelection(new Set([nodeId.value])) - } - menuVisible.value = MenuState.Full -} - const documentation = computed(() => props.node.documentation) @@ -400,12 +391,12 @@ const documentation = computed(() => props.node.documentatio {{ node.pattern?.code() ?? '' }} @@ -414,7 +405,7 @@ const documentation = computed(() => props.node.documentatio :nodeSize="baseNodeSize" :scale="navigator?.scale ?? 1" :nodePosition="props.node.position" - :isCircularMenuVisible="menuVisible === MenuState.Full || menuVisible === MenuState.Partial" + :isCircularMenuVisible="menuVisible" :currentType="node.vis?.identifier" :isFullscreen="isVisualizationFullscreen" :dataSource="{ type: 'node', nodeId: externalId }" @@ -452,7 +443,7 @@ const documentation = computed(() => props.node.documentatio diff --git a/app/gui2/src/composables/selection.ts b/app/gui2/src/composables/selection.ts index 1a8e1ff9b2e3..5f047d6c1009 100644 --- a/app/gui2/src/composables/selection.ts +++ b/app/gui2/src/composables/selection.ts @@ -148,6 +148,7 @@ export function useSelection( }, deselectAll: () => selected.clear(), isSelected: (element: T) => selected.has(element), + isChanging: computed(() => anchor.value != null), setSelection, handleSelectionOf, hoveredNode, From b6b437b693d365f62ba8e0f4ecd29bdc02cb474f Mon Sep 17 00:00:00 2001 From: Kaz Date: Fri, 1 Mar 2024 08:00:54 -0800 Subject: [PATCH 2/4] Hide placeholders unless sole selected node, required argument, or requested by dynamic config --- app/gui2/e2e/widgets.spec.ts | 8 +++++++ .../src/components/GraphEditor/GraphNode.vue | 1 + .../components/GraphEditor/NodeWidgetTree.vue | 2 ++ .../GraphEditor/widgets/WidgetApplication.vue | 21 ++++++++++++++++++- .../GraphEditor/widgets/WidgetFunction.vue | 2 ++ app/gui2/src/providers/widgetTree.ts | 2 ++ app/gui2/src/util/callTree.ts | 11 +++++++++- 7 files changed, 45 insertions(+), 2 deletions(-) diff --git a/app/gui2/e2e/widgets.spec.ts b/app/gui2/e2e/widgets.spec.ts index ca33d5a357a7..57f3925e5191 100644 --- a/app/gui2/e2e/widgets.spec.ts +++ b/app/gui2/e2e/widgets.spec.ts @@ -60,6 +60,10 @@ test('Selection widgets in Data.read node', async ({ page }) => { // Check initially visible arguments const node = locate.graphNodeByBinding(page, 'data') const argumentNames = node.locator('.WidgetArgumentName') + await expect(argumentNames).toHaveCount(1) + + // Check arguments after selecting node + await node.click() await expect(argumentNames).toHaveCount(3) // Set value on `on_problems` (static drop-down) @@ -129,6 +133,10 @@ test('Managing aggregates in `aggregate` node', async ({ page }) => { // Check initially visible arguments const node = locate.graphNodeByBinding(page, 'aggregated') const argumentNames = node.locator('.WidgetArgumentName') + await expect(argumentNames).toHaveCount(1) + + // Check arguments after selecting node + await node.click() await expect(argumentNames).toHaveCount(3) // Add first aggregate diff --git a/app/gui2/src/components/GraphEditor/GraphNode.vue b/app/gui2/src/components/GraphEditor/GraphNode.vue index 83783d3f79de..35083440a710 100644 --- a/app/gui2/src/components/GraphEditor/GraphNode.vue +++ b/app/gui2/src/components/GraphEditor/GraphNode.vue @@ -436,6 +436,7 @@ const documentation = computed(() => props.node.documentatio :icon="icon" :connectedSelfArgumentId="connectedSelfArgumentId" :potentialSelfArgumentId="potentialSelfArgumentId" + :extended="isOnlyOneSelected" @openFullMenu="openFullMenu" /> diff --git a/app/gui2/src/components/GraphEditor/NodeWidgetTree.vue b/app/gui2/src/components/GraphEditor/NodeWidgetTree.vue index b841b2557094..d043fbaf44b2 100644 --- a/app/gui2/src/components/GraphEditor/NodeWidgetTree.vue +++ b/app/gui2/src/components/GraphEditor/NodeWidgetTree.vue @@ -15,6 +15,7 @@ const props = defineProps<{ icon: Icon connectedSelfArgumentId: Ast.AstId | undefined potentialSelfArgumentId: Ast.AstId | undefined + extended: boolean }>() const emit = defineEmits<{ openFullMenu: [] @@ -69,6 +70,7 @@ provideWidgetTree( toRef(props, 'icon'), toRef(props, 'connectedSelfArgumentId'), toRef(props, 'potentialSelfArgumentId'), + toRef(props, 'extended'), layoutTransitions.active, () => { emit('openFullMenu') diff --git a/app/gui2/src/components/GraphEditor/widgets/WidgetApplication.vue b/app/gui2/src/components/GraphEditor/widgets/WidgetApplication.vue index 8da01424979b..2ba22aa2b6ce 100644 --- a/app/gui2/src/components/GraphEditor/widgets/WidgetApplication.vue +++ b/app/gui2/src/components/GraphEditor/widgets/WidgetApplication.vue @@ -1,11 +1,13 @@