plotly / dash-cytoscape

Interactive network visualization in Python and Dash, powered by Cytoscape.js
https://dash.plot.ly/cytoscape
MIT License
602 stars 119 forks source link

Edge Styling makes edges Unselectable #128

Closed bfraile5 closed 3 years ago

bfraile5 commented 3 years ago

Description

When any styling is applied to a an edge element, it is no longer selectable by the user. I want to design an app with directed edges that can be selected by the user to trigger callback to display info about that relationship. Currently, I have to choose between edge styling (e.g. showing the edge direction with an arrow) or interactivity.

Steps/Code to Reproduce

apply styling to any element in the sample code, here the two node example is slightly edited, and the only edge thats unselectable is the one assigned a styling in the style dictionary. neither events: yes or selectable:yes seem to work, which is what most closely aligns with what i can find in the cytoscape.js documentation

import dash
import dash_cytoscape as cyto
import dash_html_components as html

app = dash.Dash(__name__)

app.layout = html.Div([
    cyto.Cytoscape(
        id='cytoscape-two-nodes',
        layout={'name': 'preset'},
        style={'width': '100%', 'height': '400px'},
        elements=[
            {'data': {'id': 'one', 'label': 'Node 1'}, 'position': {'x': 75, 'y': 75}},
            {'data': {'id': 'two', 'label': 'Node 2'}, 'position': {'x': 200, 'y': 200}},
            {'data': {'id': 'three', 'label': 'Node 3'}, 'position': {'x':200, 'y': 75}},
            {'data': {'source': 'one', 'target': 'two'}, 'classes': 'test'},
            {'data': {'source': 'two', 'target': 'three'}},
            {'data': {'source': 'three', 'target': 'one'}}
        ],
        stylesheet=[
            {
                'selector': '.test',
                'style': {
                    'curve-style': 'taxi',
                    'label': 'bezier',
                    'line-color': 'red',
                    'target-arrow-color': 'blue',
                    'target-arrow-shape': 'triangle',
                    'selectable': 'yes',
                    'events': 'yes'
                }
            },

        ]
    )
])

if __name__ == '__main__':
    app.run_server(debug=True)

Expected Results

I would expect simply changing color or style of an edge would not remove selectability, or if this were the default to allow some keyword in the stylesheet to override the default functionality.

Actual Results

Applying any styling to an edge element makes it such that it cannot be selected by the user mouse-events

Versions

Dash 1.18.1 Dash Core Components 1.1.1 Dash HTML Components 1.14.1 Dash CYTO Components 0.2.0

kinimesi commented 3 years ago

This is the default behavior of Cytoscape.js: if you set the line-color property, then unless you specify what happens on select, it overrides the color of selected edges (and nodes). You need to explicitly specify the color of selected edges (nodes) too.

In you example, you can in fact verify that the red edge is selected after you click on it by opening the console and typing cy.edges(':selected')

If you modify your code as below, the edges will change their color (including the red one) when they are selected:

import dash
import dash_cytoscape as cyto
import dash_html_components as html

app = dash.Dash(__name__)

app.layout = html.Div([
    cyto.Cytoscape(
        id='cytoscape-two-nodes',
        layout={'name': 'preset'},
        style={'width': '100%', 'height': '400px'},
        elements=[
            {'data': {'id': 'one', 'label': 'Node 1'}, 'position': {'x': 75, 'y': 75}},
            {'data': {'id': 'two', 'label': 'Node 2'}, 'position': {'x': 200, 'y': 200}},
            {'data': {'id': 'three', 'label': 'Node 3'}, 'position': {'x':200, 'y': 75}},
            {'data': {'source': 'one', 'target': 'two'}, 'classes': 'test'},
            {'data': {'source': 'two', 'target': 'three'}},
            {'data': {'source': 'three', 'target': 'one'}}
        ],
        stylesheet=[
            {
                'selector': '.test',
                'style': {
                    'curve-style': 'taxi',
                    'label': 'bezier',
                    'line-color': 'red',
                    'target-arrow-color': 'blue',
                    'target-arrow-shape': 'triangle',
                    'selectable': 'yes',
                    'events': 'yes'
                },

            },
            {
                'selector': ':selected',
                'style': {
                    'line-color': 'green',
                },
            }

        ]
    )
])

if __name__ == '__main__':
    app.run_server(debug=True)