rsdeps

Cargo.lock visualizer (mirror)
Log | Files | Refs | README | LICENSE

commit 66c432e6d16a2f78e1fbd543b083b4031ba7aac5
parent fbf864b32f697fe4f46caf44299522b64a399f17
Author: Andy Khramtsov <>
Date:   Sun, 31 May 2026 17:06:34 +0300

feat: visualize subtree

Diffstat:
Msrc/rsdeps/pages/home.py | 107+++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------
1 file changed, 72 insertions(+), 35 deletions(-)

diff --git a/src/rsdeps/pages/home.py b/src/rsdeps/pages/home.py @@ -457,20 +457,48 @@ def draw_graph_figure( highlight_nodes.add(selected_node) highlight_nodes.update(adjacency_list[selected_node]) + subtree_nodes = set() + + def build_subtree(): + node_buffer = [] + if selected_node: + node_buffer.append(selected_node) + subtree_nodes.add(selected_node) + + graph = {str(node): set() for node in df_graph.nodes["node_id"]} + for arc in df_graph.arcs.iter_rows(named=True): + if arc["target"] is not None: + graph[str(arc["source"])].add(str(arc["target"])) + + while node_buffer: + source = node_buffer.pop() + for target in graph[source]: + if target not in subtree_nodes: + node_buffer.append(target) + subtree_nodes.add(target) + + if subtree: + build_subtree() + edges = EdgeFigData( x=[], y=[], ) + edges_faint = EdgeFigData( + x=[], + y=[], + ) + edges_highlight = EdgeFigData( x=[], y=[], ) - for row in df_graph.arcs.iter_rows(named=True): - if not row["target"]: + for arc in df_graph.arcs.iter_rows(named=True): + if not arc["target"]: continue - source, target = str(row["source"]), str(row["target"]) + source, target = str(arc["source"]), str(arc["target"]) if source in positions and target in positions: source_x, source_y = positions[source] target_x, target_y = positions[target] @@ -481,6 +509,9 @@ def draw_graph_figure( ): edges_highlight.x.extend([source_x, target_x, None]) edges_highlight.y.extend([source_y, target_y, None]) + elif selected_node and (not subtree or source not in subtree_nodes or target not in subtree_nodes): + edges_faint.x.extend([source_x, target_x, None]) + edges_faint.y.extend([source_y, target_y, None]) else: edges.x.extend([source_x, target_x, None]) edges.y.extend([source_y, target_y, None]) @@ -488,56 +519,59 @@ def draw_graph_figure( def build_line_scatter(edge: EdgeFigData, width: float, color: str) -> go.Scatter: return go.Scatter(x=edge.x, y=edge.y, line=dict(width=width, color=color), hoverinfo="skip", mode="lines") - edge_scatter = build_line_scatter(edges, width=1.0, color=colors.line_faint if selected_node else colors.line) + edge_scatter = build_line_scatter(edges, width=1.0, color=colors.line) + edge_scatter_faint = build_line_scatter(edges_faint, width=1.0, color=colors.line_faint) edge_scatter_highlight = build_line_scatter(edges_highlight, width=1.5, color=colors.line_highlight) - nodes = NodeFigData( - x=[], - y=[], - color=[], - label=[], - label_color=[], - hover_text=[], - outline_color=[], - custom_data=[], - ) + def init_nodes(): + return NodeFigData( + x=[], + y=[], + color=[], + label=[], + label_color=[], + hover_text=[], + outline_color=[], + custom_data=[], + ) - nodes_highlight = NodeFigData( - x=[], - y=[], - color=[], - label=[], - label_color=[], - hover_text=[], - outline_color=[], - custom_data=[], - ) + nodes = init_nodes() + nodes_faint = init_nodes() + nodes_highlight = init_nodes() - for row in df_graph.nodes.iter_rows(named=True): - node_id = row["node_id"] + for arc in df_graph.nodes.iter_rows(named=True): + node_id = arc["node_id"] if node_id not in positions: continue - nodes_appending = nodes if (not selected_node) or (node_id not in highlight_nodes) else nodes_highlight + nodes_appending = nodes + + if selected_node: + if node_id in highlight_nodes: + nodes_appending = nodes_highlight + elif subtree and node_id in subtree_nodes: + nodes_appending = nodes + else: + nodes_appending = nodes_faint x, y = positions[node_id] nodes_appending.x.append(x) nodes_appending.y.append(y) - nodes_appending.label.append(row["short_label"]) - nodes_appending.hover_text.append(parse_node_details(row["full_details"])) + nodes_appending.label.append(arc["short_label"]) + nodes_appending.hover_text.append(parse_node_details(arc["full_details"])) nodes_appending.custom_data.append(node_id) - if (not selected_node) or (node_id in highlight_nodes): - nodes_appending.color.append(colors.node_main if row["full_details"]["explicit"] else colors.node) + if nodes_appending == nodes_faint: + nodes_appending.color.append(colors.node_faint) + nodes_appending.label_color.append(colors.text_faint) + nodes_appending.outline_color.append(colors.outline) + else: + nodes_appending.color.append(colors.node_main if arc["full_details"]["explicit"] else colors.node) nodes_appending.label_color.append(colors.text) nodes_appending.outline_color.append( colors.outline_highlight if node_id == selected_node else colors.outline ) - else: - nodes_appending.color.append(colors.node_faint) - nodes_appending.label_color.append(colors.text_faint) - nodes_appending.outline_color.append(colors.outline) def build_node_scatter(node: NodeFigData) -> go.Scatter: return go.Scatter( @@ -568,10 +602,13 @@ def draw_graph_figure( ) node_scatter = build_node_scatter(nodes) + node_scatter_faint = build_node_scatter(nodes_faint) node_scatter_highlight = build_node_scatter(nodes_highlight) fig = go.Figure( data=[ + edge_scatter_faint, + node_scatter_faint, edge_scatter, node_scatter, edge_scatter_highlight,