Skip to content

Commit

Permalink
Set of GUI2 widgets fixes (#8749)
Browse files Browse the repository at this point in the history
Implements first two points of #8745

1. The fix for drop-down was simple, just stop click propagation
2. The fix for connections was much more complicated. It turned out, that it's about keeping track of hovered ports; when picking an option in WidgetSelection makes the drop-down disappear - but that won't emit `pointerleave` event, so the port was still deemed hovered. Changed the mechanism for tracking hovered port to more "centralized" one.
  • Loading branch information
farmaazon authored Jan 15, 2024
1 parent 5b91f16 commit b28b743
Show file tree
Hide file tree
Showing 7 changed files with 21 additions and 22 deletions.
2 changes: 0 additions & 2 deletions app/gui2/mock/providers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@ export const graphSelection: GraphSelection = {
events: {} as any,
anchor: undefined,
deselectAll: () => {},
addHoveredPort: () => new Set(),
removeHoveredPort: () => false,
handleSelectionOf: () => {},
hoveredNode: undefined,
hoveredPort: undefined,
Expand Down
2 changes: 1 addition & 1 deletion app/gui2/playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ export default defineConfig({
env: {
E2E: 'true',
},
command: 'vite build && vite preview',
command: 'npx vite build && npx vite preview',
port: 4173,
// We use our special, mocked version of server, thus do not want to re-use user's one.
reuseExistingServer: false,
Expand Down
1 change: 1 addition & 0 deletions app/gui2/src/components/GraphEditor/NodeWidget.vue
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ const spanStart = computed(() => {
:input="props.input"
:nesting="nesting"
:data-span-start="spanStart"
:data-port="props.input.portId"
@update="updateHandler"
/>
<span
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,13 +120,15 @@ const visualizationData = project.useVisualizationData(visualizationConfig)
const widgetConfiguration = computed(() => {
if (props.input.dynamicConfig?.kind === 'FunctionCall') return props.input.dynamicConfig
const data = visualizationData.value
if (data != null && data.ok) {
if (data?.ok) {
const parseResult = argsWidgetConfigurationSchema.safeParse(data.value)
if (parseResult.success) {
return functionCallConfiguration(parseResult.data)
} else {
console.error('Unable to parse widget configuration.', data, parseResult.error)
}
} else if (data != null && !data.ok) {
data.error.log('Cannot load dynamic configuration')
}
return undefined
})
Expand Down
13 changes: 1 addition & 12 deletions app/gui2/src/components/GraphEditor/widgets/WidgetPort.vue
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import {
nextTick,
onUpdated,
proxyRefs,
ref,
shallowRef,
toRef,
watch,
Expand All @@ -35,7 +34,7 @@ const navigator = injectGraphNavigator()
const tree = injectWidgetTree()
const selection = injectGraphSelection(true)
const isHovered = ref(false)
const isHovered = computed(() => selection?.hoveredPort === props.input.portId)
const hasConnection = computed(
() => graph.db.connections.reverseLookup(portId.value as ExprId).size > 0,
Expand All @@ -48,14 +47,6 @@ const connected = computed(() => hasConnection.value || isCurrentEdgeHoverTarget
const rootNode = shallowRef<HTMLElement>()
const nodeSize = useResizeObserver(rootNode, false)
watchEffect((onCleanup) => {
if (selection != null && isHovered.value === true) {
const id = portId.value
selection.addHoveredPort(id)
onCleanup(() => selection.removeHoveredPort(id))
}
})
// Compute the scene-space bounding rectangle of the expression's widget. Those bounds are later
// used for edge positioning. Querying and updating those bounds is relatively expensive, so we only
// do it when the node has any potential for being used as an edge source or target. This is true
Expand Down Expand Up @@ -155,8 +146,6 @@ export const widgetDefinition = defineWidget(WidgetInput.isAstOrPlaceholder, {
}"
:data-id="portId"
:data-h="randSlice"
@pointerenter="isHovered = true"
@pointerleave="isHovered = false"
>
<NodeWidget :input="innerWidget" />
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ export const widgetDefinition = defineWidget(WidgetInput.isAstOrPlaceholder, {
</script>

<template>
<div class="WidgetSelection" @pointerdown="toggleDropdownWidget">
<div class="WidgetSelection" @pointerdown.stop="toggleDropdownWidget">
<NodeWidget :input="innerWidgetInput" />
<DropdownWidget
v-if="showDropdownWidget"
Expand Down
19 changes: 14 additions & 5 deletions app/gui2/src/composables/selection.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/** @file A Vue composable for keeping track of selected DOM elements. */

import { selectionMouseBindings } from '@/bindings'
import { usePointer } from '@/composables/events'
import { useEvent, usePointer } from '@/composables/events'
import type { NavigatorComposable } from '@/composables/navigator'
import type { PortId } from '@/providers/portInfo.ts'
import type { Rect } from '@/util/data/rect'
Expand All @@ -23,8 +23,19 @@ export function useSelection<T>(
const initiallySelected = new Set<T>()
const selected = reactive(new Set<T>())
const hoveredNode = ref<ExprId>()
const hoveredPorts = reactive(new Set<PortId>())
const hoveredPort = computed(() => [...hoveredPorts].pop())
const hoveredPort = ref<PortId>()

useEvent(document, 'pointerover', (event) => {
if (event.target instanceof Element) {
const widgetPort = event.target.closest('.WidgetPort')
hoveredPort.value =
widgetPort instanceof HTMLElement &&
'port' in widgetPort.dataset &&
typeof widgetPort.dataset.port === 'string'
? (widgetPort.dataset.port as PortId)
: undefined
}
})

function readInitiallySelected() {
initiallySelected.clear()
Expand Down Expand Up @@ -137,8 +148,6 @@ export function useSelection<T>(
hoveredPort,
mouseHandler: selectionEventHandler,
events: pointer.events,
addHoveredPort: (port: PortId) => hoveredPorts.add(port),
removeHoveredPort: (port: PortId) => hoveredPorts.delete(port),
})
}

Expand Down

0 comments on commit b28b743

Please sign in to comment.