UNPKG

@antv/x6

Version:

JavaScript diagramming library that uses SVG and HTML for rendering.

268 lines (227 loc) 6.48 kB
import { ModifierKey } from '../types' import { Selection } from '../addon/selection' import { Collection } from '../model/collection' import { Cell } from '../model/cell' import { EventArgs } from './events' import { Base } from './base' export class SelectionManager extends Base { public widget: Selection private movedMap = new WeakMap<Cell, boolean>() private unselectMap = new WeakMap<Cell, boolean>() protected get widgetOptions() { return this.options.selecting } get rubberbandDisabled() { return ( this.widgetOptions.enabled !== true || this.widgetOptions.rubberband !== true ) } public get disabled() { return this.widgetOptions.enabled !== true } public get length() { return this.widget.length } public get cells() { return this.widget.cells } protected init() { this.widget = this.graph.hook.createSelection() this.startListening() } protected startListening() { this.graph.on('blank:mousedown', this.onBlankMouseDown, this) this.graph.on('blank:click', this.onBlankClick, this) this.graph.on('cell:mousemove', this.onCellMouseMove, this) this.graph.on('cell:mouseup', this.onCellMouseUp, this) this.widget.on('box:mousedown', this.onBoxMouseDown, this) } protected stopListening() { this.graph.off('blank:mousedown', this.onBlankMouseDown, this) this.graph.off('blank:click', this.onBlankClick, this) this.graph.off('cell:mousemove', this.onCellMouseMove, this) this.graph.off('cell:mouseup', this.onCellMouseUp, this) this.widget.off('box:mousedown', this.onBoxMouseDown, this) } protected onBlankMouseDown({ e }: EventArgs['blank:mousedown']) { if ( this.allowRubberband(e, true) || (this.allowRubberband(e) && !this.graph.scroller.allowPanning(e, true) && !this.graph.panning.allowPanning(e, true)) ) { this.startRubberband(e) } } protected onBlankClick() { this.clean() } allowRubberband(e: JQuery.MouseDownEvent, strict?: boolean) { return ( !this.rubberbandDisabled && ModifierKey.isMatch(e, this.widgetOptions.modifiers, strict) && this.graph.hook.allowRubberband(e) ) } protected onCellMouseMove({ cell }: EventArgs['cell:mousemove']) { this.movedMap.set(cell, true) } protected onCellMouseUp({ e, cell }: EventArgs['cell:mouseup']) { const options = this.widgetOptions let disabled = this.disabled if (!disabled && this.movedMap.has(cell)) { disabled = options.selectCellOnMoved === false if (!disabled) { disabled = options.selectNodeOnMoved === false && cell.isNode() } if (!disabled) { disabled = options.selectEdgeOnMoved === false && cell.isEdge() } } if (!disabled) { if (options.multiple === false || (!e.ctrlKey && !e.metaKey)) { this.reset(cell) } else if (this.unselectMap.has(cell)) { this.unselectMap.delete(cell) } else if (this.isSelected(cell)) { this.unselect(cell) } else { this.select(cell) } } this.movedMap.delete(cell) } protected onBoxMouseDown({ e, cell }: Selection.EventArgs['box:mousedown']) { if (!this.disabled) { if (this.widgetOptions.multiple !== false && (e.ctrlKey || e.metaKey)) { this.unselect(cell) this.unselectMap.set(cell, true) } } } isEmpty() { return this.length <= 0 } isSelected(cell: Cell | string) { return this.widget.isSelected(cell) } protected getCells(cells: Cell | string | (Cell | string)[]) { return (Array.isArray(cells) ? cells : [cells]) .map((cell) => typeof cell === 'string' ? this.graph.getCellById(cell) : cell, ) .filter((cell) => cell != null) } select( cells: Cell | string | (Cell | string)[], options: Collection.AddOptions = {}, ) { const selected = this.getCells(cells) if (selected.length) { if (this.isMultiple()) { this.widget.select(selected, options) } else { this.reset(selected.slice(0, 1), options) } } return this } unselect( cells: Cell | string | (Cell | string)[], options: Collection.RemoveOptions = {}, ) { this.widget.unselect(this.getCells(cells), options) return this } reset( cells?: Cell | string | (Cell | string)[], options: Collection.SetOptions = {}, ) { this.widget.reset(cells ? this.getCells(cells) : [], options) return this } clean() { this.widget.clean() return this } enable() { if (this.disabled) { this.widgetOptions.enabled = true } return this } disable() { if (!this.disabled) { this.widgetOptions.enabled = false } return this } startRubberband(e: JQuery.MouseDownEvent) { if (!this.rubberbandDisabled) { this.widget.startSelecting(e) } return this } enableRubberband() { if (this.rubberbandDisabled) { this.widgetOptions.rubberband = true // if ( // ModifierKey.equals( // this.graph.options.scroller.modifiers, // this.graph.options.selecting.modifiers, // ) // ) { // this.graph.scroller.disablePanning() // } } return this } disableRubberband() { if (!this.rubberbandDisabled) { this.widgetOptions.rubberband = false } return this } isMultiple() { return this.widgetOptions.multiple !== false } enableMultiple() { this.widgetOptions.multiple = true return this } disableMultiple() { this.widgetOptions.multiple = false return this } setModifiers(modifiers?: string | ModifierKey[] | null) { this.widgetOptions.modifiers = modifiers return this } setContent(content?: Selection.Content) { this.widget.setContent(content) return this } setFilter(filter?: Selection.Filter) { this.widget.setFilter(filter) return this } @Base.dispose() dispose() { this.stopListening() this.widget.dispose() } } export namespace SelectionManager { export interface Options extends Selection.CommonOptions { enabled?: boolean rubberband?: boolean modifiers?: string | ModifierKey[] | null multiple?: boolean selectCellOnMoved?: boolean selectNodeOnMoved?: boolean selectEdgeOnMoved?: boolean } export type Filter = Selection.Filter export type Content = Selection.Content }