@@ -415,65 +415,61 @@ def _handle_msg(self, msg: dict[str, Any]) -> None:
415415 """Handle sync messages from the frontend."""
416416 if not isinstance (msg , dict ):
417417 return
418- msg_type = msg .get ("type" )
419- if msg_type == "sync" :
420- nodes = msg .get ("nodes" )
421- edges = msg .get ("edges" )
422- if nodes is not None :
423- self .nodes = nodes
424- if edges is not None :
425- self .edges = edges
426- self ._emit (msg_type , msg )
427- elif msg_type == "node_moved" :
428- node_id = msg .get ("node_id" )
429- position = msg .get ("position" )
430- if node_id is None or position is None :
418+ match msg .get ("type" ):
419+ case "sync" :
420+ nodes = msg .get ("nodes" )
421+ edges = msg .get ("edges" )
422+ if nodes is not None :
423+ self .nodes = nodes
424+ if edges is not None :
425+ self .edges = edges
426+ self ._emit ("sync" , msg )
427+ case "node_moved" :
428+ node_id = msg .get ("node_id" )
429+ position = msg .get ("position" )
430+ if node_id is None or position is None :
431+ return
432+ for node in self .nodes :
433+ if node .get ("id" ) == node_id :
434+ node ["position" ] = position
435+ self ._emit ("node_moved" , msg )
436+ case "selection_changed" :
437+ node_ids = msg .get ("nodes" ) or []
438+ edge_ids = msg .get ("edges" ) or []
439+ for node in self .nodes :
440+ node ["selected" ] = node .get ("id" ) in node_ids
441+ for edge in self .edges :
442+ edge ["selected" ] = edge .get ("id" ) in edge_ids
443+ self .selection = {"nodes" : list (node_ids ), "edges" : list (edge_ids )}
444+ self ._emit ("selection_changed" , msg )
445+ case "edge_added" :
446+ edge = msg .get ("edge" )
447+ if edge is None :
448+ return
449+ self .add_edge (edge )
450+ self ._emit ("edge_added" , msg )
451+ case "node_deleted" :
452+ node_ids = msg .get ("node_ids" ) or []
453+ if msg .get ("node_id" ):
454+ node_ids = list (set (node_ids ) | {msg .get ("node_id" )})
455+ for node_id in node_ids :
456+ self .remove_node (node_id )
457+ self ._emit ("node_deleted" , msg )
458+ case "edge_deleted" :
459+ edge_ids = msg .get ("edge_ids" ) or []
460+ if msg .get ("edge_id" ):
461+ edge_ids = list (set (edge_ids ) | {msg .get ("edge_id" )})
462+ for edge_id in edge_ids :
463+ self .remove_edge (edge_id )
464+ self ._emit ("edge_deleted" , msg )
465+ case "node_clicked" :
466+ node_id = msg .get ("node_id" )
467+ if node_id is None :
468+ return
469+ self ._build_toolbar_for_node (node_id )
470+ self ._emit ("node_clicked" , msg )
471+ case _:
431472 return
432- for node in self .nodes :
433- if node .get ("id" ) == node_id :
434- node ["position" ] = position
435- self ._emit (msg_type , msg )
436- elif msg_type == "selection_changed" :
437- node_ids = msg .get ("nodes" ) or []
438- edge_ids = msg .get ("edges" ) or []
439- for node in self .nodes :
440- node ["selected" ] = node .get ("id" ) in node_ids
441- for edge in self .edges :
442- edge ["selected" ] = edge .get ("id" ) in edge_ids
443- self .selection = {"nodes" : list (node_ids ), "edges" : list (edge_ids )}
444- self ._emit (msg_type , msg )
445- elif msg_type == "edge_added" :
446- edge = msg .get ("edge" )
447- if edge is None :
448- return
449- self .add_edge (edge )
450- self ._emit (msg_type , msg )
451- elif msg_type == "node_deleted" :
452- node_ids = msg .get ("node_ids" ) or []
453- if msg .get ("node_id" ):
454- node_ids = list (set (node_ids ) | {msg .get ("node_id" )})
455- for node_id in node_ids :
456- self .remove_node (node_id )
457- self ._emit (msg_type , msg )
458- elif msg_type == "edge_deleted" :
459- edge_ids = msg .get ("edge_ids" ) or []
460- if msg .get ("edge_id" ):
461- edge_ids = list (set (edge_ids ) | {msg .get ("edge_id" )})
462- for edge_id in edge_ids :
463- self .remove_edge (edge_id )
464- self ._emit (msg_type , msg )
465- elif msg_type == "node_clicked" :
466- node_id = msg .get ("node_id" )
467- if node_id is None :
468- return
469- self ._build_toolbar_for_node (node_id )
470- self ._emit (msg_type , msg )
471- elif msg_type == "toolbar_opened" :
472- node_id = msg .get ("node_id" )
473- if node_id is None :
474- return
475- self ._build_toolbar_for_node (node_id )
476- self ._emit (msg_type , msg )
477473
478474 def remove_node (self , node_id : str ) -> None :
479475 """Remove a node and any connected edges.
@@ -626,22 +622,33 @@ def from_networkx(
626622 position = {"x" : position [0 ], "y" : position [1 ]}
627623 node_data = dict (attrs )
628624 node_data .pop ("type" , None )
625+ embedded_data = node_data .pop ("data" , None )
626+ if isinstance (embedded_data , dict ):
627+ node_data = {** embedded_data , ** node_data }
629628 nodes .append ({"id" : str (node_id ), "position" : position , "type" : node_type , "data" : node_data })
630- for source , target , key , attrs in graph .edges (keys = True , data = True ):
629+ if graph .is_multigraph ():
630+ edge_iter = graph .edges (keys = True , data = True )
631+ else :
632+ edge_iter = ((source , target , None , attrs ) for source , target , attrs in graph .edges (data = True ))
633+ for source , target , key , attrs in edge_iter :
631634 edge_data = dict (attrs )
635+ embedded_edge_data = edge_data .pop ("data" , None )
636+ if isinstance (embedded_edge_data , dict ):
637+ edge_data = {** embedded_edge_data , ** edge_data }
632638 label = edge_data .pop ("label" , None )
633639 edge_type = edge_data .pop ("type" , None )
634640 edge_id = key if key is not None else f"{ source } ->{ target } "
635- edges .append (
636- {
637- "id" : str (edge_id ),
638- "source" : str (source ),
639- "target" : str (target ),
640- "label" : label ,
641- "type" : edge_type ,
642- "data" : edge_data ,
643- }
644- )
641+ edge = {
642+ "id" : str (edge_id ),
643+ "source" : str (source ),
644+ "target" : str (target ),
645+ "data" : edge_data ,
646+ }
647+ if label is not None :
648+ edge ["label" ] = label
649+ if edge_type is not None :
650+ edge ["type" ] = edge_type
651+ edges .append (edge )
645652 return cls (nodes = nodes , edges = edges )
646653
647654 def on (self , event_type : str , callback ) -> None :
0 commit comments