Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhancement: handle nodeless centering and live running state #437

Merged
merged 3 commits into from
Mar 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 31 additions & 3 deletions src/factories/flowRunState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { RunGraphStateEvent } from '@/models/states'
import { waitForApplication, waitForViewport } from '@/objects'
import { waitForConfig } from '@/objects/config'
import { emitter } from '@/objects/events'
import { waitForRunData } from '@/objects/nodes'
import { waitForScale } from '@/objects/scale'
import { isSelected, selectItem } from '@/objects/selection'
import { layout } from '@/objects/settings'
Expand All @@ -25,6 +26,7 @@ export async function flowRunStateFactory(state: RunGraphStateEvent, options?: F
const application = await waitForApplication()
const viewport = await waitForViewport()
const config = await waitForConfig()
const data = await waitForRunData()
let scale = await waitForScale()

const element = new Container()
Expand Down Expand Up @@ -73,12 +75,20 @@ export async function flowRunStateFactory(state: RunGraphStateEvent, options?: F
}
})

if (state.type === 'RUNNING' && !data.end_time) {
startTicking()
}

function render(newOptions?: FlowRunStateFactoryOptions): void {
if (newOptions) {
const { end: newEnd } = newOptions
end = newEnd
}

if (data.end_time) {
stopTicking()
}

if (!layout.isTemporal()) {
element.visible = false
return
Expand All @@ -95,9 +105,15 @@ export async function flowRunStateFactory(state: RunGraphStateEvent, options?: F

const x = Math.max(scale(state.timestamp) * viewport.scale._x + viewport.worldTransform.tx, 0)

const width = end
? scale(end) * viewport.scale._x + viewport.worldTransform.tx - x
: application.screen.width - x
let width = 0

if (state.type === 'RUNNING' && !data.end_time) {
width = scale(new Date()) * viewport.scale._x + viewport.worldTransform.tx - x
} else if (end) {
width = scale(end) * viewport.scale._x + viewport.worldTransform.tx - x
} else {
width = application.screen.width - x
}

return {
x,
Expand Down Expand Up @@ -134,6 +150,18 @@ export async function flowRunStateFactory(state: RunGraphStateEvent, options?: F
area.alpha = flowStateAreaAlpha
}

function startTicking(): void {
application.ticker.add(tick)
}

function stopTicking(): void {
application.ticker.remove(tick)
}

function tick(): void {
render()
}

return {
element,
render,
Expand Down
67 changes: 60 additions & 7 deletions src/objects/viewport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { waitForApplication } from '@/objects/application'
import { waitForConfig } from '@/objects/config'
import { cull, uncull } from '@/objects/culling'
import { emitter, waitForEvent } from '@/objects/events'
import { waitForRunData } from '@/objects/nodes'
import { waitForScale } from '@/objects/scale'
import { waitForSettings } from '@/objects/settings'
import { waitForStage } from '@/objects/stage'
Expand Down Expand Up @@ -70,26 +71,43 @@ type CenterViewportParameters = {

export async function centerViewport({ animate }: CenterViewportParameters = {}): Promise<void> {
const viewport = await waitForViewport()
const config = await waitForConfig()

const container = viewport.getChildByName(DEFAULT_NODES_CONTAINER_NAME)

if (!container) {
throw new Error('Nodes container not found')
}

const guidesOffset = config.styles.guideTextSize + config.styles.guideTextTopPadding

uncull()
const { x, y, width, height } = container.getLocalBounds()
const widthWithGap = width + config.styles.columnGap * 2
const heightWithGap = height + config.styles.rowGap * 2 + guidesOffset * 2
const scale = viewport.findFit(widthWithGap, heightWithGap)

// if the container doesn't have a size we cannot do anything here
// if the container doesn't have a size attempt to center to flow state
if (!width || !height) {
centerViewportOnStartAndEnd({ animate })

return
}

centerViewportOnNodes({ x, y, width, height, animate })
}

type CenterViewportOnNodesParameters = {
x: number,
y: number,
width: number,
height: number,
animate?: boolean,
}

async function centerViewportOnNodes({ x, y, width, height, animate }: CenterViewportOnNodesParameters): Promise<void> {
const config = await waitForConfig()
const viewport = await waitForViewport()

const guidesOffset = config.styles.guideTextSize + config.styles.guideTextTopPadding
const widthWithGap = width + config.styles.columnGap * 2
const heightWithGap = height + config.styles.rowGap * 2 + guidesOffset * 2
const scale = viewport.findFit(widthWithGap, heightWithGap)

viewport.animate({
position: {
x: x + width / 2,
Expand All @@ -104,7 +122,42 @@ export async function centerViewport({ animate }: CenterViewportParameters = {})
updateViewportDateRange()
},
})
}

async function centerViewportOnStartAndEnd({ animate }: CenterViewportParameters): Promise<void> {
const data = await waitForRunData()
const config = await waitForConfig()
const viewport = await waitForViewport()
const graphScale = await waitForScale()

let startX = graphScale(data.start_time) - config.styles.columnGap
let endX = graphScale(data.end_time ?? new Date()) + config.styles.columnGap

if (startX > endX) {
const temp = startX

startX = endX
endX = temp
}

const width = endX - startX
const x = startX + width / 2
const scale = viewport.findFit(width, 0)

viewport.animate({
position: {
x,
y: 0,
},
scale,
time: animate ? config.animationDuration : 0,
ease: 'easeInOutQuad',
removeOnInterrupt: true,
callbackOnComplete: () => {
cull()
updateViewportDateRange()
},
})
}

export async function waitForViewport(): Promise<Viewport> {
Expand Down
6 changes: 5 additions & 1 deletion src/utilities/getInitialHorizontalScaleMultiplier.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,12 @@ export function getInitialHorizontalScaleMultiplier({ start_time, end_time, node

const nodeHeight = config.styles.nodeHeight + config.styles.rowGap
const apxConcurrencyFactor = 0.5
const emptyNodesHeightMultiplier = 4

const apxNodesHeight = nodes.size > 0
? nodes.size * nodeHeight * apxConcurrencyFactor
: nodeHeight * emptyNodesHeightMultiplier

const apxNodesHeight = nodes.size * nodeHeight * apxConcurrencyFactor
const widthWeWant = apxNodesHeight * aspectRatio

const idealMultiplier = widthWeWant / (seconds * DEFAULT_TIME_COLUMN_SIZE_PIXELS)
Expand Down