Skip to content

New: Add state setters with options - #95

Merged
AlexIchenskiy merged 5 commits into
new/add-setters-and-gettersfrom
new/add-state-setters-with-options
Mar 20, 2024
Merged

New: Add state setters with options#95
AlexIchenskiy merged 5 commits into
new/add-setters-and-gettersfrom
new/add-state-setters-with-options

Conversation

@AlexIchenskiy

Copy link
Copy Markdown
Collaborator

Resolves #68

As an enhancement to the freshly implemented getters and setters, this PR introduces a new way to set the state of nodes and edges using objects that specify state with additional parameters such as isSingle and isToggle. Now, it is possible to use both the regular setter:

node.setState(state)

and the new setter:

node.setState({ state: GraphObjectState.SELECTED, options: { isSingle: true } })
edge.setState({ state: GraphObjectState.SELECTED, options: { isSingle: false, isToggle: true } })

and so on. This provides more customization flexibility to the user, with default values for these parameters set to false. It should be easily extendable for adding even more options.

@AlexIchenskiy AlexIchenskiy self-assigned this Mar 11, 2024
Comment thread src/models/graph.ts
if (data.type === 'node' && data.options.isSingle) {
const nodes = this._nodes.getAll();

for (let i = 0; i < nodes.length; i++) {

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like these iterations through all nodes/edges can be slow. Any ideas? And do we want to clear the state of all nodes/edges or only the adjusting ones?

@cizl cizl Mar 12, 2024

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about using hash maps? Obviously, this would require a lot of code change. Just starting a discussion, I don't think it's doable right now.

For the second question, I would say only the ones that are being adjusted.

@cizl cizl Mar 12, 2024

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or maybe to supplement this nodes array we can keep an index where nodeIndex[node.id] === nodes.findIndex((el) => el.id === node.id)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you suggesting storing nodes in a hashmap? As far as I know, retrieving elements from an array by a known index is O(1) complexity, so iterating through an array vs a hashmap (which also has O(1) complexity for retrieving element by key) may not make a big difference here. I might have misunderstood your point, or perhaps I missed something, so feel free to clarify it further :)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If all nodes are in state X, and you want to clear them up if they are not node with ID 1, you still need to to N - 1 updates. So hash maps or any other structure won't help there, you already have the fastest structure, an array.

But, you can do this and increase the memory footprint: I am not sure if it makes sense to go into this right now, but this would be the plan:

  • Graph keeps a structure of nodes/edges by state, so each state has a structure of nodes and edges (probably just id) - a set of a map.
  • States in nodes and edges are just views, readonly
  • When state is updated in node, edge it is just updated in the graph

This way, if you have isSingle: true, graph, as an owner of the data can then literally take all selected nodes from a set or a map, clear those states and set the new node as single selected. This would improve the speed, but it would worse the memory footprint and code simplitiy because owner of the state becomes the graph, not graph objects (node/edge).

I would keep this as is and fix only if we see that it hurts performance.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I misunderstood the functionality. I saw === instead of !==. I thought you were trying to clear the state of anode with a specific id.

Comment thread src/models/edge.ts Outdated
Comment on lines +428 to +432
if (options && options.isToggle) {
this._toggleState(result.state);
} else {
this._state = result.state;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Either have this._state = <function that handles options in general>(results.state) where function doesn't mutate the state, but returns what the new state should be, or keep this as is, but still change the toggleState to not mutate the this._state because I don't see a reason why it should. The best functions are the clean ones, which do not mutate state (if it is possible to make them).

Comment thread src/models/edge.ts Outdated
Comment on lines +423 to +426
if (typeof result === 'number') {
this._state = result;
} else if (typeof result === 'object') {
const options = result.options;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For these checks, please use utils/type.utils.ts because of:

  • cleaner code, isNumber vs `typeof x === 'number'
  • handles edge cases, isPlainObject vs typeof result === 'object' (edge case is: typeof null will return 'object').

Comment thread src/models/node.ts Outdated
result = arg;
}

if (typeof result === 'number') {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comments as for edges.

Comment thread src/models/state.ts
Comment on lines +10 to +13
export interface IGraphObjectStateOptions {
isToggle?: boolean;
isSingle?: boolean;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In these cases, when it is options, it would be best not to have optionals here, but where you use it, line 17: Partial<IGraphObjectStateOptions> where options can also be optional, e.g. options?: Partial<...>.

If you move external logic (having optional params) too deep into the type, it is harder to handle that in some other cases. E.g. if you wish to create default params, you could then just say: const default: IGraphObjectStateOptions = { ... } and you would be forced to define both. If you would use options from Parameters you would see that this object is optional here with all its children. The context of when is something optional, when it isn't is being kept.

Comment thread src/models/graph.ts
if (data.type === 'node' && data.options.isSingle) {
const nodes = this._nodes.getAll();

for (let i = 0; i < nodes.length; i++) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If all nodes are in state X, and you want to clear them up if they are not node with ID 1, you still need to to N - 1 updates. So hash maps or any other structure won't help there, you already have the fastest structure, an array.

But, you can do this and increase the memory footprint: I am not sure if it makes sense to go into this right now, but this would be the plan:

  • Graph keeps a structure of nodes/edges by state, so each state has a structure of nodes and edges (probably just id) - a set of a map.
  • States in nodes and edges are just views, readonly
  • When state is updated in node, edge it is just updated in the graph

This way, if you have isSingle: true, graph, as an owner of the data can then literally take all selected nodes from a set or a map, clear those states and set the new node as single selected. This would improve the speed, but it would worse the memory footprint and code simplitiy because owner of the state becomes the graph, not graph objects (node/edge).

I would keep this as is and fix only if we see that it hurts performance.

Comment thread src/models/graph.ts
Comment on lines +381 to +382
if (data && 'type' in data && 'options' in data && 'isSingle' in data.options) {
if (data.type === 'node' && data.options.isSingle) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you maybe simplify this to if (data && data.options?.isSingle && data.type === 'node')?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe it could be possible, but only after reworking IObserverDataPayload into a more generic solution as you mentioned here. Currently, I am using some sort of custom type guard because of the interfaces used in that payload

@AlexIchenskiy AlexIchenskiy added this to the v1.0.0 milestone Mar 18, 2024
Comment thread src/models/edge.ts
this.notifyListeners();
}

private _handleState(state: number, options?: Partial<IGraphObjectStateOptions>): number {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is nitpicking really, but maybe getNextState would be a better name.

@AlexIchenskiy
AlexIchenskiy merged commit c9de1cf into new/add-setters-and-getters Mar 20, 2024
@AlexIchenskiy
AlexIchenskiy deleted the new/add-state-setters-with-options branch March 20, 2024 14:24
AlexIchenskiy added a commit that referenced this pull request Mar 27, 2024
* 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
AlexIchenskiy added a commit that referenced this pull request Mar 27, 2024
* 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 <davidlozic@gmail.com>

* 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 <davidlozic@gmail.com>
Co-authored-by: Oleksandr Ichenskyi <55350107+AlexIchenskiy@users.noreply.github.com>
Co-authored-by: AlexIchenskiy <aichenskiy@gmail.com>
tonilastre added a commit that referenced this pull request Jul 28, 2026
… tooling

* Fix: Fix multiple maps issue (#33)

* Chore: Update package.json version

* New: Change the API to handle OrbView and OrbMapView (#34)

* New: Change the API to handle OrbView and OrbMapView

* New: Change the API for select/hover strategies

* Chore: Release/1.0.0

* New: Add support to get selected/hovered nodes and edges (#61)

* New: Added support to get selected nodes and edges

* New: Added support to get hovered nodes and edges

---------

Co-authored-by: Abhinav Singh Parmar <abhinavparmar147@gmail.com>

* New: Add support for enabling and disabling dragging of nodes (fixes #62) (#69)

* New: Add feature to enable/disable node dragging (fixes #62)

* New: Added support to modify interaction from setSettings

* New: Updated documentation for interaction property

* New: Add feature to enable/disable zoom (fixes #62)

* NEW: Updated documentation for interaction property

* NEW: Updated documentation to include isDragEnabled

* New: Add support for custom edge line style (#77)

* New Added support for custom edges

* Refactor: Streamline edge rendering code and optimize line style handling

* New: Add support for handling device pixel ratio (#45)

* Chore: Move container and canvas creation from the view to the renderer

* New: Add devicePixelRatio render property and handler

* Fix: Add default DPR for older browsers

* Chore: Remove useless check for automatic DPR

* New: Add new simulator (#56) (#57)

* 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 <davidlozic@gmail.com>

* 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 <davidlozic@gmail.com>
Co-authored-by: Oleksandr Ichenskyi <55350107+AlexIchenskiy@users.noreply.github.com>
Co-authored-by: AlexIchenskiy <aichenskiy@gmail.com>

* New: Add zoom in and out functions (#100)

* Fix: Skip unnecessary listener notify on set style

* Fix: remove unnecessary rerender on state change

* Chore: Update documentation

* Fix: Node/edge getter performance issue

* Chore: Add data change docs example

* Fix: Docs typos

* Fix: Disable source map generation (#105)

* New: Add tree layout (#107)

* New: Add new layouts

* New: Add layout options

* Chore: Make layout dynamically changeable

* Chore: Update docs

* Fix: Naming typo

* Chore: Refactor layouts

* New: Enable layout node add/remove

* Chore: Improve behavior for recurrent nodes

* Chore: Move some simulator settings to layout

* Chore: Refactor code quality and performance

* Fix: Layout behavior on change

* Chore: Add recenter on layout change

* Fix: Layout change behavior

* Fix: Simulation behavior on data deletion

* Chore: Add recenter on layout change

* Fix: Change layout engine logic (#108)

* Fix: Change layout engine logic

* New: Add simulation cancellation logic

* Chore: Remove leftover code

* Fix: Hierarchical layout recenter logic

* Chore: Refactor package versions and code logic

* Fix: Refactor function types

* New: Add multiselect (#110)

* New: Add multiselect

* Chore: Simplify logic

* Chore: Update package.json

* New: Add SVG export (#111)

* New: Add SVG export

* Chore: Refactor code quality

* New: Add WebGL renderer (#109)

* New: Add WebGL renderer

* New: Add naive WebGL force layout computation

* New: Add WebGL improved node/shape geometry options

* New: Add labels and node images

* Fix: GPU drag behavior

* Chore: Remove leftover comments

* Fix: WebGL renderer style invalidating

* Chore: Refactor code quality

* Chore: Add WebGL example and docs

* New: Add docs page (#112)

* New: Add docs page

* New: Add more docs examples

* Update .github/workflows/docs.yml

---------

Co-authored-by: Toni <toni.lastre@memgraph.io>

* Chore: Finish up the release process

* Chore: Fix sync between package.json files

* Chore: Add new package-lock.json

---------

Co-authored-by: David <davidlozic@gmail.com>
Co-authored-by: Abhinv Singh Parmar <abhi171b010@gmail.com>
Co-authored-by: Abhinav Singh Parmar <abhinavparmar147@gmail.com>
Co-authored-by: Abhinv Singh Parmar <abhinav.parmar@infosys.com>
Co-authored-by: Oleksandr Ichenskyi <55350107+AlexIchenskiy@users.noreply.github.com>
Co-authored-by: AlexIchenskiy <aichenskiy@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants