Skip to content

Commit

Permalink
Merge ef54b65 into 1050857
Browse files Browse the repository at this point in the history
  • Loading branch information
gujinyue1010 committed Apr 18, 2020
2 parents 1050857 + ef54b65 commit fd98a8f
Show file tree
Hide file tree
Showing 8 changed files with 206 additions and 74 deletions.
8 changes: 4 additions & 4 deletions packages/x6/src/change/selection-change.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,14 @@ export class SelectionChange implements IChange {
this.added.forEach(cell => this.selection.doAddCell(cell))
}

const tmp = this.added
this.added = this.removed
this.removed = tmp

this.selection.graph.trigger('selection:changed', {
added: this.added,
removed: this.removed,
selected: this.selection.cells.slice(),
})

const tmp = this.added
this.added = this.removed
this.removed = tmp
}
}
159 changes: 123 additions & 36 deletions packages/x6/src/entity/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,22 @@ import {
} from 'utility-types'
import { FunctionExt } from '../util'

export class Events<M extends Events.EventArgs = any> {
export class Events<NameArgsMap extends Events.NameArgsMap = any> {
private listeners: { [name: string]: any[] } = {}

on<N extends Events.EventKeys<M>>(
name: N,
handler: Events.Handler<M[N]>,
on<Name extends Events.EventNames<NameArgsMap>>(
name: Name,
handler: Events.Handler<NameArgsMap[Name]>,
context?: any,
): this
on<Name extends Events.UnknownNames<NameArgsMap>>(
name: Name,
handler: Events.Handler<any>,
context?: any,
): this
on<Name extends Events.EventNames<NameArgsMap>>(
name: Name,
handler: Events.Handler<NameArgsMap[Name]>,
context?: any,
) {
if (handler == null) {
Expand All @@ -27,9 +37,19 @@ export class Events<M extends Events.EventArgs = any> {
return this
}

once<N extends Events.EventKeys<M>>(
name: N,
handler: Events.Handler<M[N]>,
once<Name extends Events.EventNames<NameArgsMap>>(
name: Name,
handler: Events.Handler<NameArgsMap[Name]>,
context?: any,
): this
once<Name extends Events.UnknownNames<NameArgsMap>>(
name: Name,
handler: Events.Handler<any>,
context?: any,
): this
once<Name extends Events.EventNames<NameArgsMap>>(
name: Name,
handler: Events.Handler<NameArgsMap[Name]>,
context?: any,
) {
const cb = (...args: any) => {
Expand All @@ -40,9 +60,32 @@ export class Events<M extends Events.EventArgs = any> {
return this.on(name, cb as any, this)
}

off<N extends Events.EventKeys<M>>(
name?: N | null,
handler?: Events.Handler<M[N]> | null,
off(): this
off(name: null, handler: Events.Handler<any>): this
off(name: null, handler: null, context: any): this
off<Name extends Events.EventNames<NameArgsMap>>(name: Name): this
off<Name extends Events.EventNames<NameArgsMap>>(
name: Name,
handler: Events.Handler<NameArgsMap[Name]>,
): this
off<Name extends Events.EventNames<NameArgsMap>>(
name: Name,
handler: Events.Handler<NameArgsMap[Name]>,
context: any,
): this
off<Name extends Events.UnknownNames<NameArgsMap>>(name: Name): this
off<Name extends Events.UnknownNames<NameArgsMap>>(
name: Name,
handler: Events.Handler<any>,
): this
off<Name extends Events.UnknownNames<NameArgsMap>>(
name: Name,
handler: Events.Handler<any>,
context: any,
): this
off(
name?: string | null,
handler?: Events.Handler<any> | null,
context?: any,
) {
// remove all events.
Expand Down Expand Up @@ -81,67 +124,111 @@ export class Events<M extends Events.EventArgs = any> {
return this
}

trigger<N extends Events.OptionalNormalKeys<M>>(name: N): boolean
trigger<N extends Events.RequiredNormalKeys<M>>(name: N, args: M[N]): boolean
trigger<N extends Events.KeysWithArrayValue<M>>(
name: N,
...args: M[N]
): boolean
trigger<N extends Events.OtherKeys<M>>(name: N, args?: M[N]): boolean
trigger<N extends Events.OtherKeys<M>>(name: N, ...args: M[N]): boolean
trigger<N extends Events.EventKeys<M>>(name: N, ...args: M[N]) {
trigger<Name extends Events.OptionalNormalNames<NameArgsMap>>(
name: Name,
): Events.TriggerResult
trigger<Name extends Events.RequiredNormalNames<NameArgsMap>>(
name: Name,
args: NameArgsMap[Name],
): Events.TriggerResult
trigger<Name extends Events.NamesWithArrayArgs<NameArgsMap>>(
name: Name,
...args: NameArgsMap[Name]
): Events.TriggerResult
trigger<Name extends Events.OtherNames<NameArgsMap>>(
name: Name,
args?: NameArgsMap[Name],
): Events.TriggerResult
trigger<Name extends Events.OtherNames<NameArgsMap>>(
name: Name,
...args: NameArgsMap[Name]
): Events.TriggerResult
trigger<Name extends Events.UnknownNames<NameArgsMap>>(
name: Name,
...args: any[]
): Events.TriggerResult
trigger<Name extends Events.EventNames<NameArgsMap>>(
name: Name,
...args: NameArgsMap[Name]
) {
const cache = this.listeners[name]
if (cache != null) {
return Private.call(cache, args)
}

return true
return Promise.resolve(true)
}
}

export namespace Events {
export type Handler<A> = A extends null | undefined
export type Handler<Args> = Args extends null | undefined
? () => any
: A extends any[]
? (...args: A) => any
: (args: A) => any
: Args extends any[]
? (...args: Args) => any
: (args: Args) => any

export type TriggerResult = boolean | Promise<boolean>

export type NameArgsMap = { [key: string]: any }

export type EventArgs = { [key: string]: any }
export type EventKeys<M extends EventArgs> = Extract<keyof M, string>
export type EventNames<M extends NameArgsMap> = Extract<keyof M, string>

/**
* Get union type of keys from `M` that value matching `any[]`.
*/
export type KeysWithArrayValue<M extends EventArgs> = RequiredKeys<
export type NamesWithArrayArgs<M extends NameArgsMap> = RequiredKeys<
PickByValue<M, any[]>
>

export type NotArrayValueMap<M extends EventArgs> = OmitByValue<M, any[]>
export type NotArrayValueMap<M extends NameArgsMap> = OmitByValue<M, any[]>

export type OptionalNormalKeys<M extends EventArgs> = OptionalKeys<
export type OptionalNormalNames<M extends NameArgsMap> = OptionalKeys<
NotArrayValueMap<M>
>

export type RequiredNormalKeys<M extends EventArgs> = RequiredKeys<
export type RequiredNormalNames<M extends NameArgsMap> = RequiredKeys<
NotArrayValueMap<M>
>

export type OtherKeys<M extends EventArgs> = EventKeys<
export type OtherNames<M extends NameArgsMap> = EventNames<
PickByValue<M, undefined>
>

export type UnknownNames<M extends NameArgsMap> = Exclude<
string,
EventNames<M>
>
}

namespace Private {
export function call<A>(list: any[], args?: A) {
let pass = true
function isAsync(obj: any) {
return obj != null && (obj instanceof Promise || isAsyncLink(obj))
}

function isAsyncLink(obj: any) {
return typeof obj === 'object' && obj.then && typeof obj.then === 'function'
}

export function call<Args>(list: any[], args?: Args) {
const results: any[] = []
for (let i = 0, l = list.length; i < l; i += 2) {
const handler = list[i]
const context = list[i + 1]
const params = Array.isArray(args) ? args : [args]
pass = FunctionExt.invoke(handler, params, context) !== false && pass
const ret = FunctionExt.invoke<any>(handler, params, context)
results.push(ret)
}

const hasAsync = results.some(res => isAsync(res))
if (hasAsync) {
const deferres = results.map(res =>
isAsync(res) ? res : Promise.resolve(res !== false),
)

return Promise.all(deferres).then(arr =>
arr.reduce<boolean>((memo, item) => item !== false && memo, true),
)
}

return pass
return results.every(res => res !== false)
}
}
17 changes: 14 additions & 3 deletions packages/x6/src/graph/connection-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,27 @@ export class ConnectionManager extends BaseManager {
) {
this.model.batchUpdate(() => {
const previous = this.model.getTerminal(edge, isSource)
this.graph.trigger('cell:connecting', {
const result = this.graph.trigger('cell:connecting', {
edge,
terminal,
isSource,
anchor,
previous,
})

this.cellConnected(edge, terminal, isSource, anchor)
const connect = () => this.cellConnected(edge, terminal, isSource, anchor)
if (typeof result === 'boolean') {
if (result) {
connect()
}
} else {
result.then(res => {
if (res) {
connect()
}
})
}
})

return edge
}

Expand Down
42 changes: 32 additions & 10 deletions packages/x6/src/graph/creation-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,15 +106,29 @@ export class CreationManager extends BaseManager {
target?: Cell,
) {
this.model.batchUpdate(() => {
this.graph.trigger('cells:adding', {
const result = this.graph.trigger('cells:adding', {
cells,
parent,
index,
source,
target,
})

this.cellsAdded(cells, parent, index, source, target, false, true)
const add = () =>
this.cellsAdded(cells, parent, index, source, target, false, true)

// user can control if the cells should be added
if (typeof result === 'boolean') {
if (result) {
add()
}
} else {
result.then(res => {
if (res) {
add()
}
})
}
})

return cells
Expand Down Expand Up @@ -200,16 +214,12 @@ export class CreationManager extends BaseManager {

// Sets the source terminal
if (sourceNode != null) {
this.graph.connectionManager.cellConnected(
cells[i],
sourceNode,
true,
)
this.graph.connectionManager.connectCell(cells[i], sourceNode, true)
}

// Sets the target terminal
if (targetNode != null) {
this.graph.connectionManager.cellConnected(
this.graph.connectionManager.connectCell(
cells[i],
targetNode,
false,
Expand Down Expand Up @@ -312,11 +322,23 @@ export class CreationManager extends BaseManager {
}

this.model.batchUpdate(() => {
this.graph.trigger('cells:removing', {
const result = this.graph.trigger('cells:removing', {
includeEdges,
cells: removing,
})
this.cellsRemoved(removing)
// user can control if the cells should be removed
const remove = () => this.cellsRemoved(removing)
if (typeof result === 'boolean') {
if (result) {
remove()
}
} else {
result.then(res => {
if (res) {
remove()
}
})
}
})

return removing
Expand Down
6 changes: 4 additions & 2 deletions packages/x6/src/handler/edge/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1693,8 +1693,10 @@ export class EdgeHandler extends MouseHandler {

@MouseHandler.dispose()
dispose() {
this.state.view.graph.off('escape', this.escapeHandler)
this.escapeHandler = null
if (this.escapeHandler != null) {
this.state.view.graph.off('escape', this.escapeHandler)
this.escapeHandler = null
}

this.marker.dispose()
this.anchorHandler.dispose()
Expand Down
19 changes: 13 additions & 6 deletions packages/x6/src/handler/moving/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -234,13 +234,20 @@ export class MovingHandler extends MouseHandler {
dispose() {
this.graph.removeHandler(this)

this.graph.off('pan', this.onPan)
this.graph.off('escape', this.onEscape)
this.graph.model.off('change', this.onRefresh)
if (this.onPan) {
this.graph.off('pan', this.onPan)
this.onPan = null
}

if (this.onEscape) {
this.graph.off('escape', this.onEscape)
this.onEscape = null
}

this.onPan = null
this.onEscape = null
this.onRefresh = null
if (this.onRefresh) {
this.graph.model.off('change', this.onRefresh)
this.onRefresh = null
}

this.preview.dispose()
}
Expand Down

0 comments on commit fd98a8f

Please sign in to comment.