GraphView

repository·master·Indexed 19 days ago

https://github.com/nabil6391/graphview

A Flutter library for visualizing complex data structures including trees, directed graphs, layered graphs, mindmaps, and radial layouts. It features multiple layout algorithms (such as BuchheimWalker, FruchtermanReingold, and Sugiyama), node animations, and interactive navigation via GraphViewController for zooming, panning, and expanding or collapsing nodes.

Tokens
11.6K
Snippets
35
Records
43
Agent score
65%

What's inside GraphView

  1. Available Graph Layout Algorithms

    master

    GraphView supports several layout algorithms depending on your data structure:

    • Tree (BuchheimWalkerAlgorithm): Uses Walker's algorithm. Configure via BuchheimWalkerConfiguration (supports ORIENTATION_LEFT_RIGHT, ORIENTATION_RIGHT_LEFT, ORIENTATION_TOP_BOTTOM, ORIENTATION_BOTTOM_TOP).
    • Tidier Tree (TidierTreeLayoutAlgorithm): Improved tree layout for better spacing in complex hierarchies.
    • Directed Graph (FruchtermanReingoldAlgorithm): Simulates attraction/repulsion forces; ideal for social networks or clusters.
    • Layered Graph (SugiyamaAlgorithm): For multilayer graphs with hierarchical structures. Configure via SugiyamaConfiguration.
    • Balloon Layout (BalloonLayoutAlgorithm): Arranges children in circular patterns around parents.
    • Circular Layout (CircleLayoutAlgorithm): Arranges all nodes in a circle; includes edge crossing reduction.
    • Radial Tree Layout (RadialTreeLayoutAlgorithm): Converts trees into radial/polar coordinates.
    • Mindmap Layout (MindmapAlgorithm): Distributes child nodes on the left and right sides of the root.
  2. Basic Setup of GraphView

    master

    To use GraphView, you must instantiate a Graph object and pass it to a GraphView widget. It is recommended to use GraphView.builder for enhanced features like animations and auto-zooming. GraphView works best when wrapped in a zoom-capable widget like Flutter's InteractiveViewer.

    To create a graph, define your nodes and edges using graph.addEdge(). You can specify custom Paint objects for individual edges to control color and thickness.

    import 'package:flutter/material.dart';
    import 'package:graphview/GraphView.dart';
    
    // 1. Initialize Graph
    final Graph graph = Graph()..isTree = true;
    
    // 2. Define Nodes
    final node1 = Node.Id(1);
    final node2 = Node.Id(2);
    
    // 3. Add Edges (with optional custom paint)
    graph.addEdge(node1, node2, paint: Paint()..color = Colors.red..strokeWidth = 2);
    
    // 4. Display using GraphView.builder
    GraphView.builder(
      graph: graph,
      algorithm: BuchheimWalkerAlgorithm(BuchheimWalkerConfiguration(), TreeEdgeRenderer(BuchheimWalkerConfiguration())),
      builder: (Node node) {
        return Text('Node ${node.key?.value}');
      },
    )
  3. Understand Sugiyama node ordering and crossing minimization

    master

    To reduce visual clutter, the SugiyamaAlgorithm performs node ordering within each layer to minimize edge crossings. This is an expensive operation performed during the run method.

    It uses two main techniques:

    1. Median Heuristic: Reorders nodes in a layer based on the median position of their neighbors in the adjacent layer.
    2. Transpose Heuristic: Fine-tunes the ordering by swapping adjacent nodes. Depending on the crossMinimizationStrategy configured, it uses either:
      • transposeSimple: A basic approach that swaps nodes if it reduces crossings.
      • transposeAccumulator: A more advanced approach using an AccumulatorTree to efficiently calculate crossing counts during trial swaps.
  4. How the Eiglsperger algorithm handles edge bend points

    master

    During the layout process, the Eiglsperger algorithm uses 'dummy' nodes to facilitate layered placement. The denormalize() phase is responsible for cleaning up these nodes and ensuring edges look natural.

    When a dummy node is encountered, the algorithm:

    1. Identifies the predecessor and successor nodes.
    2. Creates bendPoints for the edge connecting the predecessor and successor.
    3. Calculates coordinates based on the dummy node's position to create a smooth bend.
    4. Removes the dummy node from the graph.
    5. Re-adds the edge with EiglspergerEdgeData containing the calculated bendPoints.

    This ensures that even though the layout logic uses intermediate nodes, the final rendered graph shows continuous, articulated edges rather than a series of disconnected segments.

  5. Understand Sugiyama layering strategies

    master

    The SugiyamaAlgorithm supports several strategies for assigning nodes to layers, which affects the visual hierarchy and density of the graph:

    • Top-Down (LayeringStrategy.topDown): Assigns layers by iteratively finding root nodes (nodes with no predecessors) and removing them from the graph.
    • Longest Path (LayeringStrategy.longestPath): Assigns nodes to layers based on the longest path from a source, often resulting in fewer layers.
    • Coffman-Graham (LayeringStrategy.coffmanGraham): A strategy that uses in-degree and lambda values to assign nodes to layers, aiming to minimize the number of layers while respecting constraints.
    • Network Simplex (LayeringStrategy.networkSimplex): Starts with a longest-path assignment and iteratively optimizes by attempting to move nodes to different layers to minimize edge span.
  6. Use GraphView for displaying graph structures

    master

    GraphView is a Flutter library for displaying data in various graph structures, including trees, directed graphs, layered graphs, mindmaps, and radial layouts.

    There are two primary ways to use the widget:

    1. GraphView(...) (Default constructor): Best for non-interactive graphs embedded in scrollable layouts. It provides a static view of the graph.
    2. GraphView.builder(...): Designed for interactive graphs. It enables pan/zoom via InteractiveViewer, supports node collapse/expand functionality, and allows programmatic navigation using a GraphViewController.
    ```dart
    // Example of a basic GraphView
    GraphView(
      graph: myGraph,
      algorithm: myAlgorithm,
      builder: (node) => MyNodeWidget(node),
    );
  7. Customize Node Rendering with the builder pattern

    master

    The builder property in GraphView.builder allows you to map a Node to any Flutter widget. You can use the node's key (often an ID) to decide which widget to render.

    When using Node.Id(id), the value can be retrieved via node.key?.value.

    builder: (Node node) {
      var id = node.key?.value as int;
      if (id == 2) {
        return rectangleWidget(id);
      } else {
        return circleWidget(id);
      }
    }
  8. Navigate and control the Graph camera

    master

    Use the GraphViewController to programmatically move the camera or refresh the layout:

    • jumpToNode(ValueKey('nodeId')): Instantly moves the view to a specific node.
    • animateToNode(ValueKey('nodeId')): Smoothly scrolls/pans to a specific node.
    • zoomToFit(): Zooms the view so all nodes are visible.
    • resetView(): Returns the view to the origin.
    • forceRecalculation(): Forces the layout algorithm to run again.
    // Animate to a specific node by its key
    controller.animateToNode(ValueKey('node_123'));
    
    // Zoom out to see everything
    controller.zoomToFit();
    
    // Reset view
    controller.resetView();
  9. Manage Node Expand/Collapse with GraphViewController

    master

    You can control the visibility of hierarchical nodes using a GraphViewController. This allows you to create interactive trees where users can drill down into data.

    • collapseNode(graph, node, {bool animate = true}): Hides the children of a node.
    • expandNode(graph, node, {bool animate = true}): Shows the children of a node.
    • toggleNodeExpanded(graph, node, {bool animate = true}): Toggles the current state.
    • isNodeCollapsed(node): Returns true if the node is currently collapsed.
    • setInitiallyCollapsedNodes([nodes]): Sets a list of nodes to be collapsed when the graph is first loaded.
    final controller = GraphViewController();
    
    // Collapse a node
    controller.collapseNode(graph, node, animate: true);
    
    // Expand a node
    controller.expandNode(graph, node, animate: true);
    
    // Toggle state
    controller.toggleNodeExpanded(graph, node, animate: true);
    
    // Check state
    bool isCollapsed = controller.isNodeCollapsed(node);
  10. Use GraphView.builder for advanced features

    master

    The GraphView.builder constructor provides several high-level configuration options for a better user experience:

    • graph: The Graph instance.
    • algorithm: The layout algorithm instance.
    • controller: A GraphViewController for programmatic control.
    • animated: Set to true to enable smooth transitions.
    • autoZoomToFit: Automatically adjusts zoom level to show all nodes.
    • initialNode: A ValueKey to jump to a specific node on initialization.
    • panAnimationDuration: Duration for pan animations.
    • toggleAnimationDuration: Duration for expand/collapse animations.
    • centerGraph: Centers the graph in the viewport.
    • builder: A callback function (Node node) => Widget used to render custom widgets for each node.
    GraphView.builder(
      graph: graph,
      algorithm: BuchheimWalkerAlgorithm(config, TreeEdgeRenderer(config)),
      controller: controller,
      animated: true,
      autoZoomToFit: true,
      initialNode: ValueKey('startNode'),
      panAnimationDuration: Duration(milliseconds: 600),
      toggleAnimationDuration: Duration(milliseconds: 400),
      centerGraph: true,
      builder: (Node node) {
        return YourCustomWidget(node);
      },
    )
  11. Configure Sugiyama Algorithm cycle removal strategies

    master

    The Sugiyama algorithm (used for layered graph layouts) supports two different strategies for handling cycles in the graph via the cycleRemovalStrategy configuration option. Choosing the right strategy affects how the algorithm identifies and temporarily reverses edges to create a Directed Acyclic Graph (DAG) for layering.

    Available strategies:

    • CycleRemovalStrategy.dfs: Uses a Depth-First Search approach for recursive cycle removal.
    • CycleRemovalStrategy.greedy: Uses a greedy approach that identifies feedback arcs based on node degrees (out-degree minus in-degree).
    // Example of how strategies are applied via configuration
    // (Note: The exact configuration object structure depends on the parent class/setup)
    configuration.cycleRemovalStrategy = CycleRemovalStrategy.greedy;
  12. Configure Sugiyama Algorithm orientation

    master

    The getPosition method in the Sugiyama implementation uses an orientation value from the configuration to determine how node coordinates are transformed into the final layout offset. This allows the graph to be oriented in different directions (e.g., top-to-bottom, left-to-right, etc.).

    Supported orientation values:

    • 1: Custom transformation (likely horizontal/vertical variant)
    • 2: Custom transformation (likely vertical/horizontal variant)
    • 3: Custom transformation
    • 4: Custom transformation
    • default: Returns Offset(0, 0)