UNPKG

@gravity-ui/graph

Version:

Modern graph editor component

146 lines (145 loc) 5.65 kB
import { batch, computed, signal } from "@preact/signals-core"; import { selectBlockById } from "../../store/block/selectors"; import { ESelectionStrategy } from "../../utils/types/types"; import { ConnectionState } from "./ConnectionState"; export class ConnectionsStore { constructor(rootStore, graph) { this.rootStore = rootStore; this.graph = graph; this.$connections = computed(() => { return Array.from(this.$connectionsMap.value.values()); }); this.$connectionsMap = signal(new Map()); this.selectedConnections = new Set(); this.$selectedConnections = computed(() => { return new Set(this.$connections.value.filter((connection) => connection.isSelected())); }); } getBlock(id) { return selectBlockById(this.graph, id); } setSelection(connection, selected, params) { const state = connection instanceof ConnectionState ? connection : this.$connectionsMap.value.get(connection); if (state) { if (selected !== Boolean(state.$state.value.selected)) { if (!params?.ignoreChange) { state.updateConnection({ selected, }); } return true; } } return false; } updateConnections(connections) { this.$connectionsMap.value = connections.reduce((acc, connection) => { const c = this.getOrCreateConnection(connection); acc.set(c.id, c); return acc; }, this.$connectionsMap.value); } setConnections(connections) { this.$connectionsMap.value = new Map(connections.map((connection) => { const c = this.getOrCreateConnection(connection); return [c.id, c]; })); } getOrCreateConnection(connections) { const id = ConnectionState.getConnectionId(connections); if (this.$connectionsMap.value.has(id)) { const c = this.$connectionsMap.value.get(id); c.updateConnection(connections); return c; } return new ConnectionState(this, connections); } addConnection(connection) { const newConnection = new ConnectionState(this, connection); this.$connectionsMap.value.set(newConnection.id, newConnection); this.notifyConnectionMapChanged(); return newConnection.id; } notifyConnectionMapChanged() { this.$connectionsMap.value = new Map(this.$connectionsMap.value); } deleteConnections(connections) { connections.forEach((c) => { this.$connectionsMap.value.delete(c.id); }); this.notifyConnectionMapChanged(); } deleteSelectedConnections() { this.$connections.value.forEach((c) => { if (c.$state.value.selected) { this.$connectionsMap.value.delete(c.id); } }); this.notifyConnectionMapChanged(); } computeSelectionChange(ids, selected, strategy = ESelectionStrategy.REPLACE) { const list = new Set(this.$selectedConnections.value); let add; let removed; if (!selected) { removed = new Set(this.getConnections(ids).filter((connection) => { if (this.setSelection(connection, false, { ignoreChange: true })) { list.delete(connection); return true; } return false; })); } else { if (strategy === ESelectionStrategy.REPLACE) { removed = new Set(Array.from(this.$selectedConnections.value).filter((connection) => { return this.setSelection(connection, false, { ignoreChange: true }); })); list.clear(); } add = new Set(this.getConnections(ids).filter((connection) => { if (this.setSelection(connection.id, true, { ignoreChange: true }) || strategy === ESelectionStrategy.REPLACE) { removed?.delete(connection); list.add(connection); return true; } return false; })); } return { add: Array.from(add || []), removed: Array.from(removed || []), list: Array.from(list) }; } setConnectionsSelection(ids, selected, strategy = ESelectionStrategy.REPLACE) { const { add, removed, list } = this.computeSelectionChange(ids, selected, strategy); if (add.length || removed.length) { this.graph.executеDefaultEventAction("connection-selection-change", { list: list.map((c) => c.asTConnection()), changes: { add: add.map((c) => c.asTConnection()), removed: removed.map((c) => c.asTConnection()), }, }, () => { batch(() => { removed.forEach((c) => this.setSelection(c.id, false)); add.forEach((c) => this.setSelection(c.id, true)); }); }); } } toJSON() { return this.$connections.value.map((c) => c.asTConnection()); } resetSelection() { this.setConnectionsSelection([], false); } getConnections(ids) { if (!ids || !ids.length) { return this.$connections.value; } const map = this.$connectionsMap.value; return ids.map((id) => map.get(id)).filter(Boolean); } reset() { this.setConnections([]); } }