Skip to content

Commit

Permalink
New: Add new simulator (#56) (#57)
Browse files Browse the repository at this point in the history
* New: Add new simulator (#56)

* New: Add simulator scenarios for manual testing
* New: Refactor simulator (WIP)
* New: Add progress overlay, Update descriptions
* Fix: Introduce new simulator event, Fix main-thread behavior
* Fix: Rearrange class methods based on visibility
* Fix: Improve naming
* Chore(release): 0.2.0
* Fix: Tweak simulator, adjust API slightly
* Fix: Temporarily patch some physics behavior
* Fix: Adjust re-heating parameters
* Fix: tweak physics behavior -> immediately stop sim when disabling
* Chore: Remove the beta from release branches

---------

Co-authored-by: dlozic <[email protected]>

* New: Add zoom and recenter functions (#74)

* New: Add zoom and recenter functions

* Fix: Reduce excessive recentering (#75)

* Fix: Remove excessive recenterings
* Fix: Remove unused code

* Fix: New simulator (#92)

* Chore: Refactor naming

* New: Add new events

* Chore: Refactor code styling

* Docs: Remove unused flags

* Chore: Remove unused simulation functions

* Chore: Refactor view render function calls

* Chore: Add missing tests

* New: Add removal functions (#96)

* New: Add removal functions

* Fix: Add missing callback data

* Chore: Refactor remove return values

* Chore: Refactor remove function type usage

* Fix: Default settings for node placement (#98)

* New: Add properties setters and getters (#93)

* New: Add node properties setters

* New: Add edge properties setters

* New: Add properties getters

* New: Add patch for nodes and edges

* Fix: Make getters return copies

* Fix: Edge factory listeners copying

* Fix: Jest outdated tests

* Fix: Github actions node version

* Chore: Refactor observer interface

* Chore: Refactor node/edge constructor settings

* Chore: Refactor node/edge function grouping

* Chore: Refactor node/edge function grouping

* Fix: Listeners behaviour

* Chore: Refactor property copying

* Chore: Refactor subject implementation

* Fix: Set position behaviour on node drag

* Chore: Upgrade node version

* Chore: Refactor function type check

* Fix: Remove listener behaviour

* Chore: Refactor util naming

* Chore: Remove unused type assertion

* Chore: Refactor position setter options

* Chore: Refactor property patch function

* Fix: Set map node position behaviour

* Chore: Refactor simulator data patching

* Chore: Change observers to callbacks

* New: Add state setters with options (#95)

* New: Add state setters with options

* Chore: Remove leftover comments

* Chore: Refactor state setter logic

* Chore: Refactor state types

* Fix: Rename merged function usage

* Fix: Merged variable naming

* Chore: Fix tests

---------

Co-authored-by: dlozic <[email protected]>
Co-authored-by: Oleksandr Ichenskyi <[email protected]>
Co-authored-by: AlexIchenskiy <[email protected]>
  • Loading branch information
4 people authored Mar 27, 2024
1 parent cdb3a6d commit 2530739
Show file tree
Hide file tree
Showing 45 changed files with 5,722 additions and 12,757 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
- uses: actions/checkout@v1
- uses: actions/setup-node@v1
with:
node-version: "16.x"
node-version: "18.x"

- name: 'Install'
run: npm ci
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
- uses: actions/checkout@v1
- uses: actions/setup-node@v1
with:
node-version: "16.x"
node-version: "18.x"

- name: 'Install'
run: npm ci
Expand Down
6 changes: 3 additions & 3 deletions .releaserc
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
}],
"@semantic-release/changelog",
"@semantic-release/npm",
'@semantic-release/github',
"@semantic-release/github",
["@semantic-release/git", {
"assets": ["package.json", "CHANGELOG.md"],
"message": "Chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
}],
],
}]
]
}
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Orb is a graph visualization library. Read more about Orb in the following guide
* [Styling nodes and edges](./docs/styles.md)
* [Handling events](./docs/events.md)
* Using different views
* [Default view](./docs/view-default.md)
* [Default view](./docs/view-default.md)
* [Map view](./docs/view-map.md)

## Install
Expand Down Expand Up @@ -106,7 +106,7 @@ free to check other JavaScript examples in `examples/` directory.
<div id="graph"></div>
<script>
const container = document.getElementById("graph");
const nodes = [
{ id: 1, label: "Orb" },
{ id: 2, label: "Graph" },
Expand All @@ -116,13 +116,13 @@ free to check other JavaScript examples in `examples/` directory.
{ id: 1, start: 1, end: 2, label: "DRAWS" },
{ id: 2, start: 2, end: 3, label: "ON" },
];
// First `Orb` is just a namespace of the JS package
// First `Orb` is just a namespace of the JS package
const orb = new Orb.OrbView(container);
// Initialize nodes and edges
orb.data.setup({ nodes, edges });
// Render and recenter the view
orb.render(() => {
orb.recenter();
Expand Down
35 changes: 20 additions & 15 deletions docs/view-default.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ interface IOrbViewSettings {
zoomFitTransitionMs: number;
isOutOfBoundsDragEnabled: boolean;
areCoordinatesRounded: boolean;
isSimulationAnimated: boolean;
areCollapsedContainerDimensionsAllowed: boolean;
}
```

Expand Down Expand Up @@ -164,7 +164,7 @@ const defaultSettings = {
zoomFitTransitionMs: 200,
isOutOfBoundsDragEnabled: false,
areCoordinatesRounded: true,
isSimulationAnimated: true,
areCollapsedContainerDimensionsAllowed: false;
}
```

Expand Down Expand Up @@ -295,22 +295,22 @@ Disabled by default (`false`).

The optional property `strategy` has two properties that you can enable/disable:

* `isDefaultSelectEnabled` - when `true`, the default selection strategy is used on mouse click:
* If there is a node at the mouse click point, the node, its edges, and adjacent nodes will change
- `isDefaultSelectEnabled` - when `true`, the default selection strategy is used on mouse click:
- If there is a node at the mouse click point, the node, its edges, and adjacent nodes will change
its state to `GraphObjectState.SELECTED`. Style properties that end with `...Selected` will be
applied to all the selected objects (e.g. `borderColorSelected`).
* If there is an edge at the mouse click point, the edge and its starting and ending nodes will change
- If there is an edge at the mouse click point, the edge and its starting and ending nodes will change
its state to `GraphObjectState.SELECTED`.
* `isDefaultHoverEnabled` - when `true`, the default hover strategy is used on mouse move:
* If there is a node at the mouse pointer, the node, its edges, and adjacent nodes will change its state to
- `isDefaultHoverEnabled` - when `true`, the default hover strategy is used on mouse move:
- If there is a node at the mouse pointer, the node, its edges, and adjacent nodes will change its state to
`GraphObjectState.HOVERED`. Style properties that end with `...Hovered` will be applied to all the
hovered objects (e.g. `borderColorHovered`).

With property `strategy` you can disable the above behavior and implement your select/hover strategy on
top of events `OrbEventType.MOUSE_CLICK` and `OrbEventType.MOUSE_MOVE`, e.g:

```typescript
import { isNode, OrbEventType, GraphObjectState } from '@memgraph/orb';
import { isNode, OrbEventType, GraphObjectState } from "@memgraph/orb";

// Disable default select and hover strategy
orb.setSettings({
Expand All @@ -335,7 +335,9 @@ orb.events.on(OrbEventType.MOUSE_CLICK, (event) => {
// Clicked on unselected node
if (event.subject && isNode(event.subject) && !event.subject.isSelected()) {
// Deselect the previously selected nodes
orb.data.getNodes((node) => node.isSelected()).forEach((node) => node.clearState());
orb.data
.getNodes((node) => node.isSelected())
.forEach((node) => node.clearState());
// Select the new node
event.subject.state = GraphObjectState.SELECTED;
orb.render();
Expand All @@ -347,9 +349,9 @@ orb.events.on(OrbEventType.MOUSE_CLICK, (event) => {

The optional property `interaction` has two properties that you can enable/disable:

* `isDragEnabled` - property controls the dragging behavior within the application. When it is set to `true`, dragging is enabled, allowing users to interact with nodes and edges by dragging them to different positions within the graph. On the other hand, when `isDragEnabled`` is set to false, dragging functionality is disabled, preventing users from moving or repositioning nodes and edges through dragging interactions.
- `isDragEnabled` - property controls the dragging behavior within the application. When it is set to `true`, dragging is enabled, allowing users to interact with nodes and edges by dragging them to different positions within the graph. On the other hand, when `isDragEnabled`` is set to false, dragging functionality is disabled, preventing users from moving or repositioning nodes and edges through dragging interactions.

* `isZoomEnabled` - This property controls the zooming behavior within the application. Setting it to `true` enables zooming, allowing users to interactively zoom in and out of the graph. Setting it to `false` disables zooming, restricting the user's ability to change the zoom level.
- `isZoomEnabled` - This property controls the zooming behavior within the application. Setting it to `true` enables zooming, allowing users to interactively zoom in and out of the graph. Setting it to `false` disables zooming, restricting the user's ability to change the zoom level.

These properties provide a straightforward way to enable or disable dragging and zooming features based on the needs and requirements of your application. By toggling the values of isDragEnabled and isZoomEnabled, you can easily control the interactivity options available to users. e.g:

Expand Down Expand Up @@ -378,11 +380,14 @@ Disabled by default (`false`).

Rounds node coordinates to integer values. Slightly improves performance. Enabled by default (`true`).

### Property `isSimulationAnimated`
### Property `areCollapsedContainerDimensionsAllowed`

Shows the process of simulation where the nodes are moved by the physics engine until they
converge to a stable position. If disabled, the graph will suddenly appear in its final position.
Enabled by default (`true`).
Enables setting the dimensions of the Orb container element to zero.
If the container element of Orb has collapsed dimensions (`width: 0;` or `height: 0;`),
Orb will expand the container by setting the values to `100%`.
If that doesn't work (the parent of the container also has collapsed dimensions),
Orb will set an arbitrary fixed dimension to the container.
Disabled by default (`false`).

## Settings

Expand Down
6 changes: 3 additions & 3 deletions examples/example-custom-styled-graph.html
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,11 @@ <h1>Example 2 - Basic + Custom default style</h1>
colorHover: '#e7644e',
colorSelected: '#e7644e',
fontSize: 3,
label: node.data.label,
label: node.getData().label,
size: 6,
};

if (node.data.label === 'Node A') {
if (node.getData().label === 'Node A') {
return {
...basicStyle,
size: 10,
Expand All @@ -84,7 +84,7 @@ <h1>Example 2 - Basic + Custom default style</h1>
width: 0.3,
widthHover: 0.9,
widthSelected: 0.9,
label: edge.data.label,
label: edge.getData().label,
};
},
});
Expand Down
6 changes: 3 additions & 3 deletions examples/example-fixed-coordinates-graph.html
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ <h1>Example 3 - Fixed coordinates</h1>
];

const orb = new Orb.OrbView(container, {
getPosition: (node) => ({ x: node.data.x, y: node.data.y })
getPosition: (node) => ({ x: node.getData().x, y: node.getData().y })
});

// Initialize nodes and edges
Expand All @@ -59,7 +59,7 @@ <h1>Example 3 - Fixed coordinates</h1>
colorHover: '#e7644e',
colorSelected: '#e7644e',
fontSize: 3,
label: node.data.label,
label: node.getData().label,
size: 6,
};
},
Expand All @@ -72,7 +72,7 @@ <h1>Example 3 - Fixed coordinates</h1>
width: 0.3,
widthHover: 0.9,
widthSelected: 0.9,
label: edge.data.label,
label: edge.getData().label,
};
},
});
Expand Down
8 changes: 4 additions & 4 deletions examples/example-graph-data-changes.html
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ <h1>Example 5 - Dynamics</h1>
colorHover: '#e7644e',
colorSelected: '#e7644e',
fontSize: 3,
label: node.data.label,
label: node.getData().label,
size: 6,
};
},
Expand All @@ -70,7 +70,7 @@ <h1>Example 5 - Dynamics</h1>
width: 0.3,
widthHover: 0.9,
widthSelected: 0.9,
label: edge.data.label,
label: edge.getData().label,
};
},
});
Expand All @@ -97,7 +97,7 @@ <h1>Example 5 - Dynamics</h1>
if (currentNodes.length) {
const newEdge = {
id: n,
start: currentNodes[Math.floor(Math.random() * currentNodes.length)].id,
start: currentNodes[Math.floor(Math.random() * currentNodes.length)].getId(),
end: n,
label: `Edge ${n} (new)`
};
Expand All @@ -115,7 +115,7 @@ <h1>Example 5 - Dynamics</h1>

orb.events.on(Orb.OrbEventType.NODE_CLICK, (event) => {
console.log('Node clicked: ', event.node);
orb.data.remove({ nodeIds: [event.node.id] });
orb.data.remove({ nodeIds: [event.node.getId()] });
orb.render();
});

Expand Down
18 changes: 9 additions & 9 deletions examples/example-graph-events.html
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ <h1>Example 4 - Events</h1>
colorHover: '#e7644e',
colorSelected: '#e7644e',
fontSize: 3,
label: node.data.label,
label: node.getData().label,
size: 6,
};
},
Expand All @@ -78,7 +78,7 @@ <h1>Example 4 - Events</h1>
width: 0.3,
widthHover: 0.9,
widthSelected: 0.9,
label: edge.data.label,
label: edge.getData().label,
};
},
});
Expand All @@ -103,27 +103,27 @@ <h1>Example 4 - Events</h1>

orb.events.on(Orb.OrbEventType.NODE_CLICK, (event) => {
console.log('Event: node-click', event);
output.innerHTML = `<b>${event.node.data.label}</b> clicked!`;
output.innerHTML = `<b>${event.node.getData().label}</b> clicked!`;
});
orb.events.on(Orb.OrbEventType.NODE_HOVER, (event) => {
console.log('Event: node-hover', event);
output.innerHTML = `<b>${event.node.data.label}</b> hovered!`;
output.innerHTML = `<b>${event.node.getData().label}</b> hovered!`;
});
orb.events.on(Orb.OrbEventType.EDGE_CLICK, (event) => {
console.log('Event: edge-click', event);
output.innerHTML = `Edge with id <b>${event.edge.data.id}</b> clicked!`;
output.innerHTML = `Edge with id <b>${event.edge.getData().id}</b> clicked!`;
});

orb.events.on(Orb.OrbEventType.NODE_RIGHT_CLICK, (data) => {
data.event.preventDefault();
console.log("Event: node-right-click", data);
output.innerHTML = `<b>${data.node.data.label}</b> right clicked!`;
output.innerHTML = `<b>${data.node.getData().label}</b> right clicked!`;
})

orb.events.on(Orb.OrbEventType.EDGE_RIGHT_CLICK, (data) => {
data.event.preventDefault();
console.log("Event: edge-right-click", data);
output.innerHTML = `Edge with id <b>${data.edge.data.id}</b> right clicked!`;
output.innerHTML = `Edge with id <b>${data.edge.getData().id}</b> right clicked!`;
})

orb.events.on(Orb.OrbEventType.MOUSE_RIGHT_CLICK, (data) => {
Expand All @@ -136,12 +136,12 @@ <h1>Example 4 - Events</h1>

orb.events.on(Orb.OrbEventType.NODE_DOUBLE_CLICK, (data) => {
console.log("Event: node-double-click", data);
output.innerHTML = `<b>${data.node.data.label}</b> double clicked!`;
output.innerHTML = `<b>${data.node.getData().label}</b> double clicked!`;
})

orb.events.on(Orb.OrbEventType.EDGE_DOUBLE_CLICK, (data) => {
console.log("Event: edge-double-click", data);
output.innerHTML = `Edge with id <b>${data.edge.data.id}</b> double clicked!`;
output.innerHTML = `Edge with id <b>${data.edge.getData().id}</b> double clicked!`;
})

orb.events.on(Orb.OrbEventType.MOUSE_DOUBLE_CLICK, (data) => {
Expand Down
6 changes: 3 additions & 3 deletions examples/example-graph-on-map.html
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ <h1>Example 6 - Map</h1>
];

const orb = new Orb.OrbMapView(container, {
getGeoPosition: (node) => ({ lat: node.data.lat, lng: node.data.lng, }),
getGeoPosition: (node) => ({ lat: node.getData().lat, lng: node.getData().lng, }),
});

// Assign a basic style
Expand All @@ -58,7 +58,7 @@ <h1>Example 6 - Map</h1>
colorHover: '#e7644e',
colorSelected: '#e7644e',
fontSize: 10,
label: node.data.label,
label: node.getData().label,
size: 6,
};
},
Expand All @@ -71,7 +71,7 @@ <h1>Example 6 - Map</h1>
width: 1,
widthHover: 0.9,
widthSelected: 0.9,
label: edge.data.label,
label: edge.getData().label,
};
},
});
Expand Down
6 changes: 3 additions & 3 deletions examples/playground.html
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
colorHover: '#e7644e',
colorSelected: '#e7644e',
fontSize: 3,
label: node.data.labels[0],
label: node.getData().labels[0],
size: 6,
};
},
Expand All @@ -54,15 +54,15 @@
width: 0.3,
widthHover: 0.9,
widthSelected: 0.9,
label: edge.data.label,
label: edge.getData().label,
};
},
};
};

const getOrbMapView = (container) => {
const view = new Orb.OrbMapView(container, {
getGeoPosition: (node) => ({ lat: node.data.lat, lng: node.data.lng, }),
getGeoPosition: (node) => ({ lat: node.getData().lat, lng: node.getData().lng, }),
});

// Assign a basic style
Expand Down
Loading

0 comments on commit 2530739

Please sign in to comment.