Skip to content
Snippets Groups Projects
Commit 10eada3d authored by Maximilian Giller's avatar Maximilian Giller :squid:
Browse files

Adjusted shortcuts and added proper handling for selecting more than one node

parent 40a1c3af
No related branches found
No related tags found
No related merge requests found
Pipeline #56942 failed
......@@ -96,7 +96,7 @@ export class Editor extends React.PureComponent<propTypes, stateTypes> {
this.handleLinkCanvasObject = this.handleLinkCanvasObject.bind(this);
this.handleBackgroundClick = this.handleBackgroundClick.bind(this);
this.handleNodeDrag = this.handleNodeDrag.bind(this);
this.handleLinkClick = this.handleLinkClick.bind(this);
this.handleElementRightClick = this.handleElementRightClick.bind(this);
this.selectNode = this.selectNode.bind(this);
this.handleResize = this.handleResize.bind(this);
this.handleBoxSelect = this.handleBoxSelect.bind(this);
......@@ -337,10 +337,9 @@ export class Editor extends React.PureComponent<propTypes, stateTypes> {
} else if (element.link) {
// Is link
// Is it one of the adjacent links?
const found = this.selectedNodes.find((node: Node) =>
return this.selectedNodes.some((node: Node) =>
node.links.find(element.equals)
);
return found !== undefined;
} else {
return false;
}
......@@ -366,16 +365,7 @@ export class Editor extends React.PureComponent<propTypes, stateTypes> {
* @param node Single node to select, or undefined.
*/
private selectNode(node: Node) {
if (node === undefined) {
this.setState({
selectedNodes: undefined,
});
return;
}
this.setState({
selectedNodes: [node],
});
this.selectNodes([node]);
}
/**
......@@ -383,11 +373,6 @@ export class Editor extends React.PureComponent<propTypes, stateTypes> {
* @param nodes Multiple nodes to mark as selected.
*/
private selectNodes(nodes: Node[]) {
if (nodes.length <= 0) {
this.setState(undefined);
return;
}
this.setState({
selectedNodes: nodes,
});
......@@ -402,10 +387,13 @@ export class Editor extends React.PureComponent<propTypes, stateTypes> {
}
// Remove undefines
const selectedNodes = this.state.selectedNodes.filter(
let selectedNodes = this.state.selectedNodes.filter(
(n: Node) => n !== undefined
);
// Remove duplicates
selectedNodes = [...new Set(selectedNodes)];
if (selectedNodes.length > 0) {
return selectedNodes;
}
......@@ -416,20 +404,17 @@ export class Editor extends React.PureComponent<propTypes, stateTypes> {
private handleNodeClick(node: Node) {
this.graphInFocus = true;
if (this.state.keys["Shift"]) {
// Connect to clicked node as parent while shift is pressed
if (this.state.keys["Control"]) {
// Connect to clicked node as parent while control is pressed
if (this.selectedNodes == undefined) {
// Have no node connected, so select
this.selectNode(node);
} else if (!this.selectedNodes.includes(node)) {
// Already have *other* node/s selected, so connect
this.selectedNodes.forEach((selectedNode: Node) =>
node.connect(selectedNode)
);
this.connectSelectionToNode(node);
}
} else if (this.state.keys["Control"]) {
// Delete node when control is pressed
node.delete();
} else if (this.state.keys["Shift"]) {
this.toggleNodeSelection(node);
} else {
// By default, simply select node
this.selectNode(node);
......@@ -437,6 +422,52 @@ export class Editor extends React.PureComponent<propTypes, stateTypes> {
this.forceUpdate();
}
private connectSelectionToNode(node: Node) {
if (this.selectedNodes === undefined) {
return;
}
if (this.selectedNodes.length == 1) {
node.connect(this.selectedNodes[0]);
return;
}
// More than one new link => custom save point handling
try {
this.state.graph.disableStoring();
this.selectedNodes.forEach((selectedNode: Node) =>
node.connect(selectedNode)
);
} finally {
this.state.graph.enableStoring();
this.state.graph.storeCurrentData(
"Added " +
this.selectedNodes.length +
" links on [" +
node.toString() +
"]"
);
}
}
private toggleNodeSelection(node: Node) {
// Convert selection to array as basis
let selection = this.selectedNodes;
if (selection === undefined) {
selection = [];
}
// Add/Remove node
if (selection.includes(node)) {
// Remove node from selection
selection = selection.filter((n: Node) => !n.equals(node));
} else {
// Add node to selection
selection.push(node);
}
this.selectNodes(selection);
}
private handleNodeCanvasObject(node: Node, ctx: any, globalScale: any) {
// add ring just for highlighted nodes
if (this.isHighlighted(node)) {
......@@ -491,7 +522,7 @@ export class Editor extends React.PureComponent<propTypes, stateTypes> {
const isNodeRelatedToSelection: boolean =
this.selectedNodes === undefined ||
this.isHighlighted(node) ||
!!this.selectedNodes.find((selectedNode: Node) =>
this.selectedNodes.some((selectedNode: Node) =>
selectedNode.neighbors.includes(node)
);
......@@ -561,7 +592,10 @@ export class Editor extends React.PureComponent<propTypes, stateTypes> {
private handleNodeDrag(node: Node) {
this.graphInFocus = true;
this.selectNode(node);
if (!this.selectedNodes || !this.selectedNodes.includes(node)) {
this.selectNode(node);
}
// Should run connect logic?
if (!this.state.connectOnDrag) {
......@@ -585,14 +619,14 @@ export class Editor extends React.PureComponent<propTypes, stateTypes> {
this.forceUpdate();
}
private handleLinkClick(link: Link) {
/**
* Processes right-click event on graph elements by deleting them.
*/
private handleElementRightClick(element: GraphElement) {
this.graphInFocus = true;
if (this.state.keys["Control"]) {
// Delete link when control is pressed
link.delete();
this.forceUpdate();
}
element.delete();
this.forceUpdate();
}
private handleEngineStop() {
......@@ -612,7 +646,7 @@ export class Editor extends React.PureComponent<propTypes, stateTypes> {
return;
}
this.selectNodes(selectedNodes);
this.selectNodes(selectedNodes.concat(this.selectedNodes));
}
render(): React.ReactNode {
......@@ -658,7 +692,12 @@ export class Editor extends React.PureComponent<propTypes, stateTypes> {
linkCanvasObjectMode={() => "replace"}
nodeColor={(node: Node) => node.type.color}
onNodeDrag={this.handleNodeDrag}
onLinkClick={this.handleLinkClick}
onLinkRightClick={
this.handleElementRightClick
}
onNodeRightClick={
this.handleElementRightClick
}
onBackgroundClick={(event: any) =>
this.handleBackgroundClick(
event,
......@@ -736,14 +775,17 @@ export class Editor extends React.PureComponent<propTypes, stateTypes> {
<ul className="instructions">
<li>Click background to create node</li>
<li>
SHIFT+Click and drag on background to select and
edit multiple nodes
SHIFT+Click and drag on background to add nodes
to selection
</li>
<li>CTRL+Click background to clear selection</li>
<li>Click node to select and edit</li>
<li>CTRL+Click node to delete</li>
<li>CTRL+Click link to delete</li>
<li>SHIFT+Click a second node to connect</li>
<li>
SHIFT+Click node to add or remove from selection
</li>
<li>CTRL+Click another node to connect</li>
<li>Right-Click node to delete</li>
<li>Right-Click link to delete</li>
{this.state.connectOnDrag ? (
<li>
Drag node close to other node to connect
......@@ -751,7 +793,7 @@ export class Editor extends React.PureComponent<propTypes, stateTypes> {
) : (
""
)}
<li>DELETE to delete selected node</li>
<li>DELETE to delete selected nodes</li>
<li>ESCAPE to clear selection</li>
</ul>
</div>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment