@antv/x6
Version:
JavaScript diagramming library that uses SVG and HTML for rendering
146 lines (124 loc) • 3.58 kB
text/typescript
import { Dom, disposable } from '../common'
import type { KeyValue } from '../common'
import { highlighterCheck, highlighterRegistry } from '../registry'
import type {
HighlighterDefinition,
HighlighterManualItem,
HighlighterNativeItem,
} from '../registry'
import type { CellView } from '../view'
import type { CellViewHighlightOptions } from '../view/cell/type'
import { Base } from './base'
import type { EventArgs } from './events'
interface Cache {
highlighter: HighlighterDefinition<KeyValue>
cellView: CellView
magnet: Element
args: KeyValue
}
export type HighlightManagerOptions =
| HighlighterNativeItem
| HighlighterManualItem
export class HighlightManager extends Base {
protected readonly highlights: KeyValue<Cache> = {}
protected init() {
this.startListening()
}
protected startListening() {
this.graph.on('cell:highlight', this.onCellHighlight, this)
this.graph.on('cell:unhighlight', this.onCellUnhighlight, this)
}
protected stopListening() {
this.graph.off('cell:highlight', this.onCellHighlight, this)
this.graph.off('cell:unhighlight', this.onCellUnhighlight, this)
}
protected onCellHighlight({
view: cellView,
magnet,
options = {},
}: EventArgs['cell:highlight']) {
const resolved = this.resolveHighlighter(options)
if (!resolved) {
return
}
const key = this.getHighlighterId(magnet, resolved)
if (!this.highlights[key]) {
const highlighter = resolved.highlighter
highlighter.highlight(cellView, magnet, { ...resolved.args })
this.highlights[key] = {
cellView,
magnet,
highlighter,
args: resolved.args,
}
}
}
protected onCellUnhighlight({
magnet,
options = {},
}: EventArgs['cell:unhighlight']) {
const resolved = this.resolveHighlighter(options)
if (!resolved) {
return
}
const id = this.getHighlighterId(magnet, resolved)
this.unhighlight(id)
}
protected resolveHighlighter(options: CellViewHighlightOptions) {
const graphOptions = this.options
let highlighterDef: string | undefined | HighlighterManualItem =
options.highlighter
if (highlighterDef == null) {
// check for built-in types
const type = options.type
highlighterDef =
(type && graphOptions.highlighting[type]) ||
graphOptions.highlighting.default
}
if (highlighterDef == null) {
return null
}
const def: HighlighterManualItem =
typeof highlighterDef === 'string'
? {
name: highlighterDef,
}
: highlighterDef
const name = def.name
const highlighter = highlighterRegistry.get(name)
if (highlighter == null) {
return highlighterRegistry.onNotFound(name)
}
highlighterCheck(name, highlighter)
return {
name,
highlighter,
args: def.args || {},
}
}
protected getHighlighterId(
magnet: Element,
options: NonNullable<
ReturnType<typeof HighlightManager.prototype.resolveHighlighter>
>,
) {
Dom.ensureId(magnet)
return options.name + magnet.id + JSON.stringify(options.args)
}
protected unhighlight(id: string) {
const highlight = this.highlights[id]
if (highlight) {
highlight.highlighter.unhighlight(
highlight.cellView,
highlight.magnet,
highlight.args,
)
delete this.highlights[id]
}
}
dispose() {
Object.keys(this.highlights).forEach((id) => this.unhighlight(id))
this.stopListening()
}
}