Coder Social home page Coder Social logo

nabil6391 / graphview Goto Github PK

View Code? Open in Web Editor NEW
415.0 11.0 115.0 708 KB

Flutter GraphView is used to display data in graph structures. It can display Tree layout, Directed and Layered graph. Useful for Family Tree, Hierarchy View.

License: MIT License

Dart 100.00%
flutter tree treeview tree-structure graph graph-view graph-structures family-tree hierarchy hierarchy-viewer

graphview's People

Contributors

emmby avatar frezyx avatar jouby avatar julianbissekkou avatar krishna-devolo avatar nabil6391 avatar tarektolba1 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

graphview's Issues

Index out of range

I'm not sure if this is exactly related, but this is what happens. I am moving from 0.6.1 - 0.6.5, the orientation works fantastically, thank you. But there seems to be something going when changing out edges and nodes.

I am driving this from a database. Data comes in, map to a list of objects that define the nodes and arrows.

With 0.6.1 this works fine, as I am not sure what nodes I will be drawing each time, they all go away, along with the edges:

graph.edges.clear();
graph.nodes.clear();

I have also done this:

List<gv.Edge> edges = [];
graph.edges.forEach((element) {edges.add(element);});
graph.removeEdges(edges);

List<gv.Node> nodes = [];
graph.nodes.forEach((element) {nodes.add(element);});
graph.removeNodes(nodes);

Both works great for 0.6.1

But, 0.6.5 I get the attached error
Screenshot (277)

Length of edges

Hello,
how I can resize the length of edges? Graphs don't enter into the web page

import issues

First of thank you very much for putting effort and sharing with us. I may not be the best tester but I found some issues with importing stuff over. I have got the dependency of graphview: ^0.6.7

so there are some screenshots may help you to see what I mean. all of them giving error except one.

btw this code straight from your example section on pub.dev
1
2
3

Does this not work with mobile?

I am running copy and paste of code at usage section and I am running into following error

Click to expand error
════════ Exception caught by rendering library ═════════════════════════════════════════════════════
The following assertion was thrown during performLayout():
RenderCustomLayoutBox does not meet its constraints.

Constraints: BoxConstraints(0.0<=w<=390.0, 0.0<=h<=Infinity)
Size: Size(865.0, 646.0)

If you are not writing your own RenderBox subclass, then this is not your fault. Contact support: https://github.com/flutter/flutter/issues/new?template=BUG.md

The relevant error-causing widget was: 
  GraphView file:///Users/jihochoi/Documents/outsource/spinor%20media/projects/kinshealthcare_flutter/lib/components/graph_view/family_graph_view.dart:82:24
When the exception was thrown, this was the stack: 
#0      RenderBox.debugAssertDoesMeetConstraints.<anonymous closure> (package:flutter/src/rendering/box.dart:2069:9)
#1      RenderBox.debugAssertDoesMeetConstraints (package:flutter/src/rendering/box.dart:2128:6)
#2      RenderBox.size=.<anonymous closure> (package:flutter/src/rendering/box.dart:1846:7)
#3      RenderBox.size= (package:flutter/src/rendering/box.dart:1848:6)
#4      RenderCustomLayoutBox.performLayout (package:graphview/GraphView.dart:131:5)
...
The following RenderObject was being processed when the exception was fired: RenderCustomLayoutBox#76b18 relayoutBoundary=up10 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...  parentData: <none> (can use size)
...  constraints: BoxConstraints(0.0<=w<=390.0, 0.0<=h<=Infinity)
...  size: Size(865.0, 646.0)
...  graph: Instance of 'Graph'
...  algorithm: Instance of 'BuchheimWalkerAlgorithm'
...  paint: Paint(PaintingStyle.stroke 1.0 StrokeJoin.miter up to 0.0; Color(0xff4caf50))
RenderObject: RenderCustomLayoutBox#76b18 relayoutBoundary=up10 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
  parentData: <none> (can use size)
  constraints: BoxConstraints(0.0<=w<=390.0, 0.0<=h<=Infinity)
  size: Size(865.0, 646.0)
  graph: Instance of 'Graph'
  algorithm: Instance of 'BuchheimWalkerAlgorithm'
  paint: Paint(PaintingStyle.stroke 1.0 StrokeJoin.miter up to 0.0; Color(0xff4caf50))
...  child 1: RenderSemanticsAnnotations#8e34a relayoutBoundary=up11 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...    parentData: offset=Offset(0.0, 0.0) (can use size)
...    constraints: BoxConstraints(0.0<=w<=390.0, 0.0<=h<=Infinity)
...    size: Size(78.0, 49.0)
...    child: RenderMouseRegion#7c4d3 relayoutBoundary=up12 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...      parentData: <none> (can use size)
...      constraints: BoxConstraints(0.0<=w<=390.0, 0.0<=h<=Infinity)
...      size: Size(78.0, 49.0)
...      listeners: enter, exit
...      cursor: SystemMouseCursor(click)
...      child: RenderSemanticsGestureHandler#1272b relayoutBoundary=up13 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...        parentData: <none> (can use size)
...        constraints: BoxConstraints(0.0<=w<=390.0, 0.0<=h<=Infinity)
...        size: Size(78.0, 49.0)
...        gestures: tap
...        child: RenderPointerListener#cf12a relayoutBoundary=up14 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...          parentData: <none> (can use size)
...          constraints: BoxConstraints(0.0<=w<=390.0, 0.0<=h<=Infinity)
...          size: Size(78.0, 49.0)
...          behavior: opaque
...          listeners: down
...  child 2: RenderSemanticsAnnotations#4744a relayoutBoundary=up11 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...    parentData: offset=Offset(0.0, 0.0) (can use size)
...    constraints: BoxConstraints(0.0<=w<=390.0, 0.0<=h<=Infinity)
...    size: Size(80.0, 49.0)
...    child: RenderMouseRegion#924bf relayoutBoundary=up12 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...      parentData: <none> (can use size)
...      constraints: BoxConstraints(0.0<=w<=390.0, 0.0<=h<=Infinity)
...      size: Size(80.0, 49.0)
...      listeners: enter, exit
...      cursor: SystemMouseCursor(click)
...      child: RenderSemanticsGestureHandler#f6791 relayoutBoundary=up13 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...        parentData: <none> (can use size)
...        constraints: BoxConstraints(0.0<=w<=390.0, 0.0<=h<=Infinity)
...        size: Size(80.0, 49.0)
...        gestures: tap
...        child: RenderPointerListener#81a84 relayoutBoundary=up14 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...          parentData: <none> (can use size)
...          constraints: BoxConstraints(0.0<=w<=390.0, 0.0<=h<=Infinity)
...          size: Size(80.0, 49.0)
...          behavior: opaque
...          listeners: down
...  child 3: RenderSemanticsAnnotations#67690 relayoutBoundary=up11 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...    parentData: offset=Offset(0.0, 0.0) (can use size)
...    constraints: BoxConstraints(0.0<=w<=390.0, 0.0<=h<=Infinity)
...    size: Size(80.0, 49.0)
...    child: RenderMouseRegion#7f2dd relayoutBoundary=up12 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...      parentData: <none> (can use size)
...      constraints: BoxConstraints(0.0<=w<=390.0, 0.0<=h<=Infinity)
...      size: Size(80.0, 49.0)
...      listeners: enter, exit
...      cursor: SystemMouseCursor(click)
...      child: RenderSemanticsGestureHandler#6f7ed relayoutBoundary=up13 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...        parentData: <none> (can use size)
...        constraints: BoxConstraints(0.0<=w<=390.0, 0.0<=h<=Infinity)
...        size: Size(80.0, 49.0)
...        gestures: tap
...        child: RenderPointerListener#0abab relayoutBoundary=up14 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...          parentData: <none> (can use size)
...          constraints: BoxConstraints(0.0<=w<=390.0, 0.0<=h<=Infinity)
...          size: Size(80.0, 49.0)
...          behavior: opaque
...          listeners: down
...  child 4: RenderSemanticsAnnotations#dfefa relayoutBoundary=up11 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...    parentData: offset=Offset(0.0, 0.0) (can use size)
...    constraints: BoxConstraints(0.0<=w<=390.0, 0.0<=h<=Infinity)
...    size: Size(81.0, 49.0)
...    child: RenderMouseRegion#8f253 relayoutBoundary=up12 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...      parentData: <none> (can use size)
...      constraints: BoxConstraints(0.0<=w<=390.0, 0.0<=h<=Infinity)
...      size: Size(81.0, 49.0)
...      listeners: enter, exit
...      cursor: SystemMouseCursor(click)
...      child: RenderSemanticsGestureHandler#2d73d relayoutBoundary=up13 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...        parentData: <none> (can use size)
...        constraints: BoxConstraints(0.0<=w<=390.0, 0.0<=h<=Infinity)
...        size: Size(81.0, 49.0)
...        gestures: tap
...        child: RenderPointerListener#2a252 relayoutBoundary=up14 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...          parentData: <none> (can use size)
...          constraints: BoxConstraints(0.0<=w<=390.0, 0.0<=h<=Infinity)
...          size: Size(81.0, 49.0)
...          behavior: opaque
...          listeners: down
...  child 5: RenderSemanticsAnnotations#074c1 relayoutBoundary=up11 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...    parentData: offset=Offset(0.0, 0.0) (can use size)
...    constraints: BoxConstraints(0.0<=w<=390.0, 0.0<=h<=Infinity)
...    size: Size(80.0, 49.0)
...    child: RenderMouseRegion#5d144 relayoutBoundary=up12 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...      parentData: <none> (can use size)
...      constraints: BoxConstraints(0.0<=w<=390.0, 0.0<=h<=Infinity)
...      size: Size(80.0, 49.0)
...      listeners: enter, exit
...      cursor: SystemMouseCursor(click)
...      child: RenderSemanticsGestureHandler#d329f relayoutBoundary=up13 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...        parentData: <none> (can use size)
...        constraints: BoxConstraints(0.0<=w<=390.0, 0.0<=h<=Infinity)
...        size: Size(80.0, 49.0)
...        gestures: tap
...        child: RenderPointerListener#ee855 relayoutBoundary=up14 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...          parentData: <none> (can use size)
...          constraints: BoxConstraints(0.0<=w<=390.0, 0.0<=h<=Infinity)
...          size: Size(80.0, 49.0)
...          behavior: opaque
...          listeners: down
...  child 6: RenderSemanticsAnnotations#ec174 relayoutBoundary=up11 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...    parentData: offset=Offset(0.0, 0.0) (can use size)
...    constraints: BoxConstraints(0.0<=w<=390.0, 0.0<=h<=Infinity)
...    size: Size(81.0, 49.0)
...    child: RenderMouseRegion#10b2e relayoutBoundary=up12 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...      parentData: <none> (can use size)
...      constraints: BoxConstraints(0.0<=w<=390.0, 0.0<=h<=Infinity)
...      size: Size(81.0, 49.0)
...      listeners: enter, exit
...      cursor: SystemMouseCursor(click)
...      child: RenderSemanticsGestureHandler#c42e5 relayoutBoundary=up13 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...        parentData: <none> (can use size)
...        constraints: BoxConstraints(0.0<=w<=390.0, 0.0<=h<=Infinity)
...        size: Size(81.0, 49.0)
...        gestures: tap
...        child: RenderPointerListener#a2b48 relayoutBoundary=up14 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...          parentData: <none> (can use size)
...          constraints: BoxConstraints(0.0<=w<=390.0, 0.0<=h<=Infinity)
...          size: Size(81.0, 49.0)
...          behavior: opaque
...          listeners: down
...  child 7: RenderSemanticsAnnotations#60ba8 relayoutBoundary=up11 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...    parentData: offset=Offset(0.0, 0.0) (can use size)
...    constraints: BoxConstraints(0.0<=w<=390.0, 0.0<=h<=Infinity)
...    size: Size(81.0, 49.0)
...    child: RenderMouseRegion#ff7a2 relayoutBoundary=up12 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...      parentData: <none> (can use size)
...      constraints: BoxConstraints(0.0<=w<=390.0, 0.0<=h<=Infinity)
...      size: Size(81.0, 49.0)
...      listeners: enter, exit
...      cursor: SystemMouseCursor(click)
...      child: RenderSemanticsGestureHandler#4bd87 relayoutBoundary=up13 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...        parentData: <none> (can use size)
...        constraints: BoxConstraints(0.0<=w<=390.0, 0.0<=h<=Infinity)
...        size: Size(81.0, 49.0)
...        gestures: tap
...        child: RenderPointerListener#d3f16 relayoutBoundary=up14 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...          parentData: <none> (can use size)
...          constraints: BoxConstraints(0.0<=w<=390.0, 0.0<=h<=Infinity)
...          size: Size(81.0, 49.0)
...          behavior: opaque
...          listeners: down
...  child 8: RenderSemanticsAnnotations#1114b relayoutBoundary=up11 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...    parentData: offset=Offset(0.0, 0.0) (can use size)
...    constraints: BoxConstraints(0.0<=w<=390.0, 0.0<=h<=Infinity)
...    size: Size(80.0, 49.0)
...    child: RenderMouseRegion#dbb21 relayoutBoundary=up12 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...      parentData: <none> (can use size)
...      constraints: BoxConstraints(0.0<=w<=390.0, 0.0<=h<=Infinity)
...      size: Size(80.0, 49.0)
...      listeners: enter, exit
...      cursor: SystemMouseCursor(click)
...      child: RenderSemanticsGestureHandler#0f2c6 relayoutBoundary=up13 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...        parentData: <none> (can use size)
...        constraints: BoxConstraints(0.0<=w<=390.0, 0.0<=h<=Infinity)
...        size: Size(80.0, 49.0)
...        gestures: tap
...        child: RenderPointerListener#2341c relayoutBoundary=up14 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...          parentData: <none> (can use size)
...          constraints: BoxConstraints(0.0<=w<=390.0, 0.0<=h<=Infinity)
...          size: Size(80.0, 49.0)
...          behavior: opaque
...          listeners: down
...  child 9: RenderSemanticsAnnotations#4f4f2 relayoutBoundary=up11 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...    parentData: offset=Offset(0.0, 0.0) (can use size)
...    constraints: BoxConstraints(0.0<=w<=390.0, 0.0<=h<=Infinity)
...    size: Size(81.0, 49.0)
...    child: RenderMouseRegion#3abcb relayoutBoundary=up12 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...      parentData: <none> (can use size)
...      constraints: BoxConstraints(0.0<=w<=390.0, 0.0<=h<=Infinity)
...      size: Size(81.0, 49.0)
...      listeners: enter, exit
...      cursor: SystemMouseCursor(click)
...      child: RenderSemanticsGestureHandler#5b7a5 relayoutBoundary=up13 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...        parentData: <none> (can use size)
...        constraints: BoxConstraints(0.0<=w<=390.0, 0.0<=h<=Infinity)
...        size: Size(81.0, 49.0)
...        gestures: tap
...        child: RenderPointerListener#4e610 relayoutBoundary=up14 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...          parentData: <none> (can use size)
...          constraints: BoxConstraints(0.0<=w<=390.0, 0.0<=h<=Infinity)
...          size: Size(81.0, 49.0)
...          behavior: opaque
...          listeners: down
...  child 10: RenderSemanticsAnnotations#599e0 relayoutBoundary=up11 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...    parentData: offset=Offset(0.0, 0.0) (can use size)
...    constraints: BoxConstraints(0.0<=w<=390.0, 0.0<=h<=Infinity)
...    size: Size(87.0, 49.0)
...    child: RenderMouseRegion#a6f82 relayoutBoundary=up12 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...      parentData: <none> (can use size)
...      constraints: BoxConstraints(0.0<=w<=390.0, 0.0<=h<=Infinity)
...      size: Size(87.0, 49.0)
...      listeners: enter, exit
...      cursor: SystemMouseCursor(click)
...      child: RenderSemanticsGestureHandler#9ef20 relayoutBoundary=up13 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...        parentData: <none> (can use size)
...        constraints: BoxConstraints(0.0<=w<=390.0, 0.0<=h<=Infinity)
...        size: Size(87.0, 49.0)
...        gestures: tap
...        child: RenderPointerListener#9ef0a relayoutBoundary=up14 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...          parentData: <none> (can use size)
...          constraints: BoxConstraints(0.0<=w<=390.0, 0.0<=h<=Infinity)
...          size: Size(87.0, 49.0)
...          behavior: opaque
...          listeners: down
...  child 11: RenderSemanticsAnnotations#d5ab0 relayoutBoundary=up11 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...    parentData: offset=Offset(0.0, 0.0) (can use size)
...    constraints: BoxConstraints(0.0<=w<=390.0, 0.0<=h<=Infinity)
...    size: Size(85.0, 49.0)
...    child: RenderMouseRegion#441e9 relayoutBoundary=up12 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...      parentData: <none> (can use size)
...      constraints: BoxConstraints(0.0<=w<=390.0, 0.0<=h<=Infinity)
...      size: Size(85.0, 49.0)
...      listeners: enter, exit
...      cursor: SystemMouseCursor(click)
...      child: RenderSemanticsGestureHandler#0c16e relayoutBoundary=up13 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...        parentData: <none> (can use size)
...        constraints: BoxConstraints(0.0<=w<=390.0, 0.0<=h<=Infinity)
...        size: Size(85.0, 49.0)
...        gestures: tap
...        child: RenderPointerListener#e7c7b relayoutBoundary=up14 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...          parentData: <none> (can use size)
...          constraints: BoxConstraints(0.0<=w<=390.0, 0.0<=h<=Infinity)
...          size: Size(85.0, 49.0)
...          behavior: opaque
...          listeners: down
...  child 12: RenderSemanticsAnnotations#aa3ca relayoutBoundary=up11 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...    parentData: offset=Offset(0.0, 0.0) (can use size)
...    constraints: BoxConstraints(0.0<=w<=390.0, 0.0<=h<=Infinity)
...    size: Size(87.0, 49.0)
...    child: RenderMouseRegion#4f9c8 relayoutBoundary=up12 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...      parentData: <none> (can use size)
...      constraints: BoxConstraints(0.0<=w<=390.0, 0.0<=h<=Infinity)
...      size: Size(87.0, 49.0)
...      listeners: enter, exit
...      cursor: SystemMouseCursor(click)
...      child: RenderSemanticsGestureHandler#6bf26 relayoutBoundary=up13 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...        parentData: <none> (can use size)
...        constraints: BoxConstraints(0.0<=w<=390.0, 0.0<=h<=Infinity)
...        size: Size(87.0, 49.0)
...        gestures: tap
...        child: RenderPointerListener#b7e2d relayoutBoundary=up14 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
...          parentData: <none> (can use size)
...          constraints: BoxConstraints(0.0<=w<=390.0, 0.0<=h<=Infinity)
...          size: Size(87.0, 49.0)
...          behavior: opaque
...          listeners: down
════════════════════════════════════════════════════════════════════════════════════════════════════

════════ Exception caught by rendering library ═════════════════════════════════════════════════════
RenderTransform does not meet its constraints.
The relevant error-causing widget was: 
  InteractiveViewer file:///Users/jihochoi/Documents/outsource/spinor%20media/projects/kinshealthcare_flutter/lib/components/graph_view/family_graph_view.dart:77:13
════════════════════════════════════════════════════════════════════════════════════════════════════

my flutter doctor is below and trying to run it on ios simulator

[✓] Flutter (Channel stable, 1.22.4, on Mac OS X 10.15.7 19H114 darwin-x64, locale en-KR)
 
[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
[✓] Xcode - develop for iOS and macOS (Xcode 12.3)
[!] Android Studio (version 4.1)
    ✗ Flutter plugin not installed; this adds Flutter specific functionality.
    ✗ Dart plugin not installed; this adds Dart specific functionality.
[✓] IntelliJ IDEA Ultimate Edition (version 2020.2.1)
[!] VS Code (version 1.49.0)
    ✗ Flutter extension not installed; install from
      https://marketplace.visualstudio.com/items?itemName=Dart-Code.flutter
[✓] Connected device (1 available)

Displaying big json take too long time

Not critical, but when I am trying to display big graph (40KB json). But displaying take too long time. For example graph visjs.github.io/vis-network doing it much faster.
data.txt

copy-paste example:

import 'dart:html';
import 'dart:math';

import 'package:flutter/material.dart';
import 'package:graph_page/service/service.dart'; // only it need be added to get it work
import 'package:graphview/GraphView.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) => MaterialApp(
        home: LayeredGraphViewPage(),
      );
}

class LayeredGraphViewPage extends StatefulWidget {
  @override
  _LayeredGraphViewPageState createState() => _LayeredGraphViewPageState();
}

class _LayeredGraphViewPageState extends State<LayeredGraphViewPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Container(
      height: MediaQuery.of(context).size.height,
      color: Colors.amber[100],
      margin: const EdgeInsets.all(10.0),
      child: Row(
        children: [
           Container(
             width: 150,
            color: Colors.blue[100],
            child: Column(children: [
              ElevatedButton(onPressed: () { 

                    var data = TenderData.getGraphData(); // need to add this to get it work
                    // print(data['edges']);
                    data['edges']!.forEach((element) {
                        var fromNodeId = element['from'];
                        var toNodeId = element['to'];
                        graph.addEdge(Node.Id(fromNodeId), Node.Id(toNodeId));
                      });
                    setState(() {});

               }, child: Text("get data"),),
              Text("some text"),

            ],)
           
          ), 
          Expanded(child: Container(
            color: Colors.yellow[100],
             child: InteractiveViewer(
               constrained: false,
               boundaryMargin: EdgeInsets.all(100),
               minScale: 0.01,
               maxScale: 5.6,
               child: GraphView(
                 graph: graph,
                algorithm: SugiyamaAlgorithm(builder),
                 paint: Paint()
                   ..color = Colors.green
                   ..strokeWidth = 1
                   ..style = PaintingStyle.stroke,
                 builder: (Node node) {
                   // I can decide what widget should be shown here based on the id
                   var a = node.key!.value as int;
                   return rectangleWidget(node);
                 },
               )),
          
          ))
        ],
      ),
    ));
  }

  Random r = Random();

  Widget rectangleWidget(Node a) {
    return InkWell(
      onTap: () {
        print('clicked');
      },
      child: Container(
          padding: EdgeInsets.all(16),
          decoration: BoxDecoration(
            borderRadius: BorderRadius.circular(4),


          border: Border.all(
          color: Colors.black,
          width: 5,
        ),


          ),
          child: Text('Node ${a}')),
    );
  }

 final Graph graph = Graph();

 SugiyamaConfiguration builder = SugiyamaConfiguration();

  @override
  void initState() {
    final node1 = Node.Id(1);
    final node2 = Node.Id(2);
    graph.addEdge(node1, node2);

    
    builder
      ..nodeSeparation = (15)
      ..levelSeparation = (15)
      ..orientation = SugiyamaConfiguration.ORIENTATION_LEFT_RIGHT;    

  }
}

how can i solve this EXCEPTION

══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
The following assertion was thrown while applying parent data.:
Incorrect use of ParentDataWidget.
The ParentDataWidget Expanded(flex: 1) wants to apply ParentData of type FlexParentData to a
RenderObject, which has been set up to accept ParentData of incompatible type ParentData.
Usually, this means that the Expanded widget has the wrong ancestor RenderObjectWidget. Typically,
Expanded widgets are placed directly inside Flex widgets.
The offending Expanded is currently placed inside a ConstrainedBox widget.
The ownership chain for the RenderObject that received the incompatible parent data was:
Listener-[GlobalKey#d4799] ← InteractiveViewer ← Expanded ← Consumer ←
_InheritedProviderScope ← ChangeNotifierProvider ←
ProviderWidget ← ConstrainedBox ← Container ← MediaQuery ← ⋯

                When the exception was thrown, this was the stack:
                #0      RenderObjectElement._updateParentData.<anonymous closure> (package:flutter/src/widgets/framework.dart:5626:11)
                #1      RenderObjectElement._updateParentData (package:flutter/src/widgets/framework.dart:5642:6)
                #2      RenderObjectElement.attachRenderObject (package:flutter/src/widgets/framework.dart:5664:7)
                #3      RenderObjectElement.mount (package:flutter/src/widgets/framework.dart:5357:5)
                #4      SingleChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:5973:11)
                ...     Normal element mounting (21 frames)
                #25     SingleChildWidgetElementMixin.mount (package:nested/nested.dart:222:11)
                #26     Element.inflateWidget (package:flutter/src/widgets/framework.dart:3541:14)
                #27     Element.updateChild (package:flutter/src/widgets/framework.dart:3306:18)
                #28     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4520:16)
                #29     _InheritedProviderScopeElement.performRebuild (package:provider/src/inherited_provider.dart:426:11)
                #30     Element.rebuild (package:flutter/src/widgets/framework.dart:4189:5)
                #31     ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:4474:5)
                #32     ComponentElement.mount (package:flutter/src/widgets/framework.dart:4469:5)
                ...     Normal element mounting (7 frames)
                #39     SingleChildWidgetElementMixin.mount (package:nested/nested.dart:222:11)
                ...     Normal element mounting (59 frames)
                #98     Element.inflateWidget (package:flutter/src/widgets/framework.dart:3541:14)
                #99     MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:6094:32)
                ...     Normal element mounting (7 frames)
                #106    Element.inflateWidget (package:flutter/src/widgets/framework.dart:3541:14)
                #107    MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:6094:32)
                ...     Normal element mounting (19 frames)
                #126    Element.inflateWidget (package:flutter/src/widgets/framework.dart:3541:14)
                #127    MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:6094:32)
                ...     Normal element mounting (91 frames)
                #218    Element.inflateWidget (package:flutter/src/widgets/framework.dart:3541:14)
                #219    MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:6094:32)
                ...     Normal element mounting (244 frames)
                #463    Element.inflateWidget (package:flutter/src/widgets/framework.dart:3541:14)
                #464    MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:6094:32)
                ...     Normal element mounting (320 frames)
                #784    Element.inflateWidget (package:flutter/src/widgets/framework.dart:3541:14)
                #785    Element.updateChild (package:flutter/src/widgets/framework.dart:3306:18)
                #786    _LayoutBuilderElement._layout.<anonymous closure> (package:flutter/src/widgets/layout_builder.dart:136:18)
                #787    BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2647:19)
                #788    _LayoutBuilderElement._layout (package:flutter/src/widgets/layout_builder.dart:118:12)
                #789    RenderObject.invokeLayoutCallback.<anonymous closure> (package:flutter/src/rendering/object.dart:1894:59)
                #790    PipelineOwner._enableMutationsToDirtySubtrees (package:flutter/src/rendering/object.dart:915:15)
                #791    RenderObject.invokeLayoutCallback (package:flutter/src/rendering/object.dart:1894:14)
                #792    RenderConstrainedLayoutBuilder.rebuildIfNecessary (package:flutter/src/widgets/layout_builder.dart:225:7)
                #793    _RenderLayoutBuilder.performLayout (package:flutter/src/widgets/layout_builder.dart:360:5)
                #794    RenderObject.layout (package:flutter/src/rendering/object.dart:1784:7)
                #795    _RenderLayoutBuilder.performLayout (package:flutter/src/widgets/layout_builder.dart:362:14)
                #796    RenderObject.layout (package:flutter/src/rendering/object.dart:1784:7)
                #797    RenderView.performLayout (package:flutter/src/rendering/view.dart:153:14)
                #798    RenderObject._layoutWithoutResize (package:flutter/src/rendering/object.dart:1641:7)
                #799    PipelineOwner.flushLayout (package:flutter/src/rendering/object.dart:884:18)
                #800    RendererBinding.drawFrame (package:flutter/src/rendering/binding.dart:453:19)
                #801    WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:874:13)
                #802    RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:319:5)
                #803    SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1144:15)
                #804    SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1082:9)
                #805    SchedulerBinding.scheduleWarmUpFrame.<anonymous closure> (package:flutter/src/scheduler/binding.dart:865:7)
                (elided 11 frames from class _RawReceivePortImpl, class _Timer, dart:async, and dart:async-patch)
                ════════════════════════════════════════════════════════════════════════════════════════════════════

Possible error in NodeCluster.offset() method in NodeCluster class.

It looks to me as if there is an error in setting the offset of the rect property in the offset() method in the NodeCluster class.

The code currently reads

    nodes.forEach((node) {
      node.position = (node.position + Offset(xDiff, yDiff));
    });

    rect.translate(xDiff, yDiff);
  }

This, I suggest, is incorrect as the translate() method of the Dart Rect object returns a new Rect object, not modifying the original Rect.

Thus, I believe the code should read


    nodes.forEach((node) {
      node.position = (node.position + Offset(xDiff, yDiff));
    });

    rect = rect.translate(xDiff, yDiff);
    
  }

Builder with ID

Node* getNodeUsingId(int* id) expects an int id vs (new) Node* Node.Id(dynamic id) expects dynamic. Making it dynamic would let us use even a string as an id for the node. Can you please fix this discrepancy? Also, when will this version be available in null safety.

How to add a directed edge in Tree graph?

I would like to add a directed edge in a tree graph using Buchheim Walker algorithm.

This would be just a standard tree but with directed edges. Is it possible? If so, can a example be provided?

I tried to change the line:
algorithm: BuchheimWalkerAlgorithm(builder, TreeEdgeRenderer(builder)),
for:
algorithm: FruchtermanReingoldAlgorithm(),

and it kinda worked, except that it lost the rectangular edges.

Graph so big nothing is visible unless zooming out, centering around `Layout.setFocusedNode` could be a fix

Made a video of how the graph looks: https://youtu.be/-oLNpC1voJs

You can see that the top left corner of the graph view (where the graph view seems to always start) is empty, often with every nodes and edge off-screen.

I had to zoom out alot to be able to start seeing some graph data. If we could "focus" on the focusedNode we'd guarantee that this wouldn't happen.

Any other suggestions on making this work so it doesn't look to the user as though there is no graph?

Update paint without updating graphView

Hello!

Is there a way to update the color of the pain without refreshing the whole GraphView?
Right now when I need to highlight some flow - I remove all nodes and all edges and add a new one with proper pain.

But it would be nice to add some possibility to refresh color (maybe the node itself as well) without full recreation.
It probably might be achievable with the builder method.

Use BuchheimWalkerConfiguration to show tree merge node has problem

I use BuchheimWalkerConfiguration like this, there are 2 branch and one merge node, it's OK

`graph.addEdge(node1, node2, paint: Paint()..color = Colors.red);
graph.addEdge(node2, node6);
graph.addEdge(node6, node5);

graph.addEdge(node2, node3);
graph.addEdge(node3, node4);
graph.addEdge(node4, node5);`
image

but if i change the order like this, it will show wrong connect line

`graph.addEdge(node1, node2, paint: Paint()..color = Colors.red);
graph.addEdge(node2, node3);
graph.addEdge(node3, node4);
graph.addEdge(node4, node5);

graph.addEdge(node2, node6);
graph.addEdge(node6, node5);`
image

Add option to center `InteractiveViewer` at a node

We are really enjoying your package and it works great!

It would be nice to have to option to center the InteractiveViewer to a specific node.
TransformationController already provides the option to move the viewer around but we still need to know the position of a node to be able to generate the correct Matrix4.

Do you have an idea how this can be done?

create family tree view using BuchheimWalkerAlgorithm?

Hi Brother!,
I'm creating a family tree using BuchheimWalkerAlgorithm, it is possible to get this type of output with separate nodes. Like father mother on the different node but nearest position. Connect from 2 nodes to 1 node.
Screenshot_1630301227

Help me to find out.
Thank You!

Uneven rendering using the Sugiyama Configuration

I was trying to make a graph using the sugiyama configuration, but in many cases, the result was not as I expected it to be. I was expecting a layer-wise graph with even layering as shown below.

image

But, instead, i get a layout as
image
It isnt that prominent for larger graphs, but it is still there. Maybe its the way the graph is rendered, or its dependent on the algorithm, i'm not sure.
Was hoping if you know any workaround or fix, would be great!
Thanks

Improve performance of `SugiyamaAlgorithm`

Thanks again for taking the time to hop on a call with me and discuss potential performance fixes.
I reduced the iterations in nodeOrdering to 3 and then I did some research to see what else takes the most time.

image

As you can see crossingb and assignX takes most of the time.
I checked the graphview android lib to see if they made any performance adjustments, but there are none.

I tried to optimize both methods but I don't have enough knowledge about the algorithm so I need some help here.
@nabil6391 It would be a help if you could explain what the implementation exactly does and how a fix could look like so I can help.

Do not accept Strings as keys for nodes and edges

My data is not int-based. Because some of real data have leading zero. The graphview crush on next data:

    var json = {
      "nodes": [
        {"id": "01", "label": 'circle'},
        {"id": "02", "label": 'ellipse'},
        {"id": "03", "label": 'database'},
        {"id": "04", "label": 'box'},
        {"id": "05", "label": 'diamond'},
        {"id": "06", "label": 'dot'},
        {"id": "07", "label": 'square'},
        {"id": "08", "label": 'triangle'},
      ],
      "edges": [
        {"from": "01", "to": "02"},
        {"from": "02", "to": "03"},
        {"from": "02", "to": "04"},
        {"from": "02", "to": "05"},
        {"from": "05", "to": "06"},
        {"from": "05", "to": "07"},
        {"from": "06", "to": "08"}
      ]
    };

error:

    The following TypeErrorImpl was thrown building GraphView$(dirty, state: _GraphViewState#a4f6c):
Expected a value of type 'int', but got one of type 'String'

I tried change to:

var a = node.key!.value.toString();

But got error:

Node{position: Offset(0.0, 0.0), key: [<1>], _size: Size(77.0, 48.0)} is not connected to primary ancestor
Node{position: Offset(0.0, 0.0), key: [<2>], _size: Size(77.0, 48.0)} is not connected to primary ancestor

Handle disconnected nodes

Is there a way to handle for nodes that aren't connected to the main branch? I guess I'm asking whether it is possible to show two disconnected networks in the same interactive viewer. Currently if not all nodes are connected they are drawn on top of each other.

Adjustment for Phone

Hi,

Currently I'm trying to graph a Top to Bottom diagram. I'm having trouble to make the nodes visible on a phone, they are somewhere else placed on the screen. The picture is the example of TreeViewPage without changes

Phone: Galaxy S10
Android: 10

Phone

On the contrary on a Android Tablet works just fine with Android 9

Tablet

What I need to change/configure to fix the Phone view?

Regards,
William

How to stop the graph from reorganizing

Hello Nabil,

I am using GraphView in one of my projects and found it awesome. But I have a question not exactly an issue because I might be missing something. The question is - Each time the graph is refreshed it rearranges itself which becomes quite awkward when the graph is large as visually finding the nodes becomes quite daunting using FruchtermanReingold algorithm. I tried setting the x and y values of the nodes but it is apparently having no effect.

Regards,
Pankaj

Size Issue with SugiyamaAlgorithm

There seems to be a positioning / size issue with the SugiyamaAlgorithm.

The setup looks like:

final _graph = Graph()..isTree = true

GraphView(
                graph: _graph,
                algorithm: SugiyamaAlgorithm(SugiyamaConfiguration()
    ..nodeSeparation = 40
    ..levelSeparation = 50),
                builder: (node) {
                //_buildEdge returns a random value between 100 and 300 
                  return _buildEdge(payload!);
                },
              ),

Check out the screenshot.

Bildschirmfoto 2021-08-04 um 16 03 11

Do you need any additional information from my side?

The jank

Hey buddy,when my data list more than 100,i find a jank frame. BuchheimWalkerAlgorithm run() takes 700+ ms, how can i solve this problem, thx

jank

How to center tree on the canvas ?

I am using this plugin to display Family tree. And it does not center when displayed.

I need to center horizontally like this on small tree and big family tree when first displayed :

How to do it ?

Color edges

Is there a way to customize the color or line width/style of the edges? Can I for example create an edge that is a dashed red line?

Graphs Larger Than Container Size Throw Exception

When you try to display a graph whose nominal size is larger than the available display size, an exception gets thrown due to an assertion failure ("A renderflex overflowed by x pixels ..."), and Flutter shows a border with yellow/black diagonal stripes on the offending side. Enlarging the window gets rid of it; shrinking the window gets it back. I haven't found an easy workaround yet.

Nodes and edges not rendering correctly when generated dynamically.

Hello, thanks for this great package.
Just a little query though. The package works great when the nodes and edges are created statically, but the edges are created one over another when the nodes and edges are created inside a for loop. Maybe I am missing something, can you please demonstrate how to create the nodes and edges dynamically and update the documentation. Will be of so much help. Thanks.

TreeEdgeRenderer Doesn't Pick Up Customized Edge Paint

For the edges leaving a given node, TreeEdgeRenderer uses a customized paint from the first input edge of the node, if specified, and otherwise uses the default edge paint. So, for example, if you customize all the edges individually to use an indigo color, but leave the global default as is (black), the tree will have black edges from the root node to the next level, but indigo edges elsewhere.

The fix is trivial. When painting the path from a node to each child, just use the paint specified for that edge, if any, otherwise the global default edge paint.

Not able to connect from 2 node to 1 node

I tried to build a graph for family tree, requirement is from father and mother i need to conenct to child(2 node to 1) using BuchheimWalkerConfiguration algorith, but I'm not able to connect like that.

Add edge without shifting other nodes?

I'm implementing a drag and drop interface and I'm noticing that nodes tend to shift positions as edges are created. Is there a way to fix the position of the existing node when using it to create a new edge?

Great library btw!

screen-20201024-140652

mouse_tracker.dart error and complete freeze

I am using the graph view inside one of my views and struggle getting it to work without freezing.
I get a massive load of errors while the mouse is over the graph:

════════ Exception caught by scheduler library ═════════════════════════════════
'package:flutter/src/rendering/mouse_tracker.dart': Failed assertion: line 201 pos 12: '!_debugDuringDeviceUpdate': is not true.
════════════════════════════════════════════════════════════════════════════════
[ERROR:flutter/lib/ui/ui_dart_state.cc(199)] Unhandled Exception: 'package:flutter/src/rendering/mouse_tracker.dart': Failed assertion: line 201 pos 12: '!_debugDuringDeviceUpdate': is not true.
#0      _AssertionError._doThrowNew (dart:core-patch/errors_patch.dart:46:39)
#1      _AssertionError._throwNew (dart:core-patch/errors_patch.dart:36:5)
#2      MouseTracker._deviceUpdatePhase
package:flutter/…/rendering/mouse_tracker.dart:201
#3      MouseTracker.updateWithEvent.<anonymous closure>
package:flutter/…/rendering/mouse_tracker.dart:309
#4      MouseTracker._monitorMouseConnection
package:flutter/…/rendering/mouse_tracker.dart:190

My code for the view:

@override
  Widget build(BuildContext context) {
    return ViewModelBuilder<TechTreeViewModel>.reactive(
      builder: (context, model, snapshot) => ScaffoldBase(
        body: 

// I just tried to see if this is caused by unbound sizes... its not
SizedBox(
          height: 400,
          width: 400,
          child: InteractiveViewer(
            constrained: false,
            scaleEnabled: false,
            maxScale: 1,
            minScale: 1,
            boundaryMargin: EdgeInsets.all(100),
            child: GraphView(
              algorithm: BuchheimWalkerAlgorithm(
                model.builder,
                TreeEdgeRenderer(model.builder),
              ),
              graph: model.graph,
              paint: Paint()
                ..color = Colors.green
                ..strokeWidth = 1
                ..style = PaintingStyle.stroke,
              builder: (Node node) {
                if (node.key.value is TechTreeConditionNode) {
                  return conditionNode(node.key.value);
                } else if (node.key.value is TechTreeTechnologyNode) {
                  return rootNode(node.key.value);
                }

                return Container(
                  width: 100,
                  height: 100,
                );
              },
            ),
          ),
        ),
      ),
    );
  }

  

  Widget rootNode(TechTreeTechnologyNode nodeModel) {
    return InkWell(
      child: Container(
        height: 100,
        width: 200,
        padding: EdgeInsets.all(16),
        child: Column(
          children: [
            Text(nodeModel.technology.name),
          ],
        ),
      ),
    );
  }

And inside my ViewModel:

  Graph graph;
  BuchheimWalkerConfiguration builder;

  TechTreeViewModel( ) {
    graph = Graph()..isTree = true;
    builder = new BuchheimWalkerConfiguration();
  }

I tried to find out, what is causing this issue, but haven't found anything. If you need more info, please let me know

Paint is not always complete

I noticed with some graphs when you zoom you lose part of the painting:

This is with graphview: ^0.6.5
Flutter (Channel beta, 1.24.0-10.2.pre, on Microsoft Windows [Version 10.0.19041.685], locale en-US)

Screenshot (231)

Screenshot (230)

Null safety

Hi !

I like this package and was wondering if there's plans for supporting null safety. I can also start a PR if you'd like.

Thanks

Issue with SugiyamaAlgorithm when introducing circular dependency between nodes

Not sure if this is related to the circular dependency, but I've only seen this issue occur in such scenarios. I had two nodes FTA and EFTA, with FTA pointing to EFTA. When I added a new node % Auto Accept Bookings, the edge was not rendered correctly (as can be seen in the image below).

No exceptions or errors were thrown

image

RenderCustomLayoutBox does not meet its constraints on empty initState

copy-paste example:

import 'dart:html';
import 'dart:math';

import 'package:flutter/material.dart';
import 'package:graph_page/service/service.dart';
import 'package:graphview/GraphView.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) => MaterialApp(
        home: TreeViewPage(),
      );
}

class TreeViewPage extends StatefulWidget {
  @override
  _TreeViewPageState createState() => _TreeViewPageState();
}

class _TreeViewPageState extends State<TreeViewPage> {
  @override
  Widget build(BuildContext context) {
    var appBar = AppBar();
    return Scaffold(
      body: Row(
      crossAxisAlignment: CrossAxisAlignment.stretch,
      children: [
        Expanded(
          child: Container(
            color: Colors.blue[100],
            child: Text("sdfsf"),
          ),
        ),
        Expanded(
          flex: 4,
          child: Container(
            color: Colors.green[100],
            child: InteractiveViewer(
                  constrained: false,
                  boundaryMargin: EdgeInsets.all(100),
                  minScale: 0.01,
                  maxScale: 5.6,
                  child: GraphView(
                    graph: graph,
                    algorithm: BuchheimWalkerAlgorithm(
                        builder, TreeEdgeRenderer(builder)),
                    paint: Paint()
                      ..color = Colors.green
                      ..strokeWidth = 1
                      ..style = PaintingStyle.stroke,
                    builder: (Node node) {
                      // I can decide what widget should be shown here based on the id
                      var a = node.key!.value as int;
                      return rectangleWidget(a);
                    },
                  )),
          ),
        ),
      ],

    ));
  }

  Random r = Random();

  Widget rectangleWidget(int a) {
    return InkWell(
      onTap: () {
        print('clicked');
      },
      child: Container(
          padding: EdgeInsets.all(16),
          decoration: BoxDecoration(
            borderRadius: BorderRadius.circular(4),

            boxShadow: [
              BoxShadow(
                color: Colors.red,
                blurRadius: 15.0, // soften the shadow
                spreadRadius: 5.0, //extend the shadow
              )
            ],

            // boxShadow: [
            //   BoxShadow(color: Colors.blue[100]!, spreadRadius: 1),
            // ],
          ),
          child: Text('Node ${a}')),
    );
  }

  final Graph graph = Graph()..isTree = true;
  BuchheimWalkerConfiguration builder = BuchheimWalkerConfiguration();

  @override
  void initState() {
    // final node1 = Node.Id(1);
    // final node2 = Node.Id(2);
    // graph.addEdge(node1, node2);

    /*
    final node1 = Node.Id(1);
    final node2 = Node.Id(2);
    final node3 = Node.Id(3);
    final node4 = Node.Id(4);
    final node5 = Node.Id(5);
    final node6 = Node.Id(6);
    final node8 = Node.Id(7);
    final node7 = Node.Id(8);
    final node9 = Node.Id(9);
    final node10 = Node(rectangleWidget(10));  //using deprecated mechanism of directly placing the widget here
    final node11 = Node(rectangleWidget(11));
    final node12 = Node(rectangleWidget(12));

    graph.addEdge(node1, node2);
    graph.addEdge(node1, node3, paint: Paint()..color = Colors.red);
    graph.addEdge(node1, node4, paint: Paint()..color = Colors.blue);
    graph.addEdge(node2, node5);
    graph.addEdge(node2, node6);
    graph.addEdge(node6, node7, paint: Paint()..color = Colors.red);
    graph.addEdge(node6, node8, paint: Paint()..color = Colors.red);
    graph.addEdge(node4, node9);
    graph.addEdge(node4, node10, paint: Paint()..color = Colors.black);
    graph.addEdge(node4, node11, paint: Paint()..color = Colors.red);
    graph.addEdge(node11, node12);
  */
    builder
      ..siblingSeparation = (100)
      ..levelSeparation = (150)
      ..subtreeSeparation = (150)
      ..orientation = (BuchheimWalkerConfiguration.ORIENTATION_TOP_BOTTOM);
  }
}

error:

The following assertion was thrown during performLayout():
RenderCustomLayoutBox does not meet its constraints.

Constraints: BoxConstraints(w=947.2, h=937.6)
Size: Size(77.0, 246.0)

If you are not writing your own RenderBox subclass, then this is not your fault. Contact support: https://github.com/flutter/flutter/issues/new?template=2_bug.md

The relevant error-causing widget was
_GraphView
C:\…\lib\GraphView.dart:57

Upgrade to 1.26.0-17.8.pre

Since upgrading to beta 1.26.0-17.8.pre this last weekend I've noticed, not always, and some what randomly the following error in the terminal when calling GraphView with the SugiyamaAlgorithm. It doesn't seem to effect the running app:

======== Exception caught by rendering library =====================================================
The following IndexError was thrown during performLayout():
RangeError (index): Index out of range: index should be less than 1: 1

The relevant error-causing widget was:
GraphView$ file:///C:/source/AndroidStudioProjects/orpheus/lib/screens/parking_lot/forced_direction_view.dart:65:14
When the exception was thrown, this was the stack:
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/internal/js_dev_runtime/private/ddc_runtime/errors.dart 236:49 throw
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/private/js_array.dart 581:7 _get]
packages/graphview/layered/SugiyamaAlgorithm.dart 564:49 verticalAlignment
packages/graphview/layered/SugiyamaAlgorithm.dart 375:9 assignX
packages/graphview/layered/SugiyamaAlgorithm.dart 329:5 coordinateAssignment
...
The following RenderObject was being processed when the exception was fired: RenderCustomLayoutBox#68954 relayoutBoundary=up2 NEEDS-LAYOUT NEEDS-PAINT
... parentData: (can use size)
... constraints: BoxConstraints(unconstrained)
... size: Size(1125.0, 232.5)
... graph: Instance of 'Graph'
... algorithm: Instance of 'SugiyamaAlgorithm'
... paint: Instance of 'CkPaint'
RenderObject: RenderCustomLayoutBox#68954 relayoutBoundary=up2 NEEDS-LAYOUT NEEDS-PAINT
parentData: (can use size)
constraints: BoxConstraints(unconstrained)
size: Size(1125.0, 232.5)
graph: Instance of 'Graph'
algorithm: Instance of 'SugiyamaAlgorithm'
paint: Instance of 'CkPaint'
... child 1: RenderSemanticsGestureHandler#6614d relayoutBoundary=up3
... parentData: offset=Offset(10.0, 62.5) (can use size)
... constraints: BoxConstraints(unconstrained)
... size: Size(30.0, 30.0)
... gestures: tap
... child: RenderPointerListener#dd099 relayoutBoundary=up4
... parentData: (can use size)
... constraints: BoxConstraints(unconstrained)
... size: Size(30.0, 30.0)
... behavior: deferToChild
... listeners: down
... child: RenderConstrainedBox#3bbfd relayoutBoundary=up5
... parentData: (can use size)
... constraints: BoxConstraints(unconstrained)
... size: Size(30.0, 30.0)
... additionalConstraints: BoxConstraints(w=30.0, h=30.0)
... child: RenderDecoratedBox#1958c
... parentData: (can use size)
... constraints: BoxConstraints(w=30.0, h=30.0)
... size: Size(30.0, 30.0)
... decoration: BoxDecoration
... color: Color(0xffffffff)
... image: DecorationImage(AssetImage(bundle: null, name: "assets/process.png"), BoxFit.fill, Alignment.center, scale: 1)
... border: Border.all(BorderSide(Color(0xff000000), 1.0, BorderStyle.solid))
... borderRadius: BorderRadius.circular(5.0)
... boxShadow: BoxShadow(Color(0xff000000), Offset(4.0, 4.0), 4.0, 0.0)
... configuration: ImageConfiguration(bundle: PlatformAssetBundle#589c7(), devicePixelRatio: 1.0, locale: en_US, textDirection: TextDirection.ltr, platform: windows)
... child 2: RenderSemanticsGestureHandler#a7315 relayoutBoundary=up3
... parentData: offset=Offset(115.0, 62.5) (can use size)
... constraints: BoxConstraints(unconstrained)
... size: Size(30.0, 30.0)
... gestures: tap
... child: RenderPointerListener#f1907 relayoutBoundary=up4
... parentData: (can use size)
... constraints: BoxConstraints(unconstrained)
... size: Size(30.0, 30.0)
... behavior: deferToChild
... listeners: down
... child: RenderConstrainedBox#3bd74 relayoutBoundary=up5
... parentData: (can use size)
... constraints: BoxConstraints(unconstrained)
... size: Size(30.0, 30.0)
... additionalConstraints: BoxConstraints(w=30.0, h=30.0)
... child: RenderDecoratedBox#a9207
... parentData: (can use size)
... constraints: BoxConstraints(w=30.0, h=30.0)
... size: Size(30.0, 30.0)
... decoration: BoxDecoration
... color: Color(0xffffffff)
... image: DecorationImage(AssetImage(bundle: null, name: "assets/process.png"), BoxFit.fill, Alignment.center, scale: 1)
... border: Border.all(BorderSide(Color(0xff000000), 1.0, BorderStyle.solid))
... borderRadius: BorderRadius.circular(5.0)
... boxShadow: BoxShadow(Color(0xff000000), Offset(4.0, 4.0), 4.0, 0.0)
... configuration: ImageConfiguration(bundle: PlatformAssetBundle#589c7(), devicePixelRatio: 1.0, locale: en_US, textDirection: TextDirection.ltr, platform: windows)
... child 3: RenderSemanticsGestureHandler#7319b relayoutBoundary=up3
... parentData: offset=Offset(220.0, 62.5) (can use size)
... constraints: BoxConstraints(unconstrained)
... size: Size(30.0, 30.0)
... gestures: tap
... child: RenderPointerListener#42246 relayoutBoundary=up4
... parentData: (can use size)
... constraints: BoxConstraints(unconstrained)
... size: Size(30.0, 30.0)
... behavior: deferToChild
... listeners: down
... child: RenderConstrainedBox#5b69f relayoutBoundary=up5
... parentData: (can use size)
... constraints: BoxConstraints(unconstrained)
... size: Size(30.0, 30.0)
... additionalConstraints: BoxConstraints(w=30.0, h=30.0)
... child: RenderDecoratedBox#c1f06
... parentData: (can use size)
... constraints: BoxConstraints(w=30.0, h=30.0)
... size: Size(30.0, 30.0)
... decoration: BoxDecoration
... color: MaterialColor(primary value: Color(0xffffeb3b))
... image: DecorationImage(AssetImage(bundle: null, name: "assets/process.png"), BoxFit.fill, Alignment.center, scale: 1)
... border: Border.all(BorderSide(Color(0xff000000), 1.0, BorderStyle.solid))
... borderRadius: BorderRadius.circular(5.0)
... boxShadow: BoxShadow(MaterialColor(primary value: Color(0xffffeb3b)), Offset(10.0, 10.0), 10.0, 0.0)
... configuration: ImageConfiguration(bundle: PlatformAssetBundle#589c7(), devicePixelRatio: 1.0, locale: en_US, textDirection: TextDirection.ltr, platform: windows)

Add a feature to see the all nodes

Allow the user to see the all nodes to allow him to have a perpective of everything. I am having this issue where I can't zoom out more.

Screenshot 2020-09-11 at 22 49 58

Is it possible to call removeNode on a node with successors?

Hi when I try to call graph.removeNode() on a node with successors I get the following error:

The following JSNoSuchMethodError was thrown during performLayout():
NoSuchMethodError: invalid member on null: 'depth'

Should graph.removeNode() be able to handle nodes with successors? Or am I supposed to call removeNode() on all the deepest nodes first and work my way up from there?

I am using the TreeEdgeRenderer inside my GraphView based on the pub.dev example: https://pub.dev/packages/graphview#usage

Here is my code in case this is a bug instead of improper usage of removeNode() on my part.

This is my initState method:

  @override
  void initState() {
    super.initState();
    myGraph = Graph();

    final organisation = Organisation();
    final firstNode = Node(
      OrganisationCard(
        organisation,
        addNodeToOrg: (Node node, Organisation org) {
          myGraph.addEdge(
            myGraph.getNodeUsingKey(ObjectKey(org)),
            node,
          );
          setState(() {});
        },
        hideNodes: (List<Node> nodes) {
          myGraph.removeNodes(nodes);
          setState(() {});
        },
        expanded: true,
      ),
      key: ObjectKey(organisation),
    );

    myGraph.addNode(firstNode);

    builder = BuchheimWalkerConfiguration()
      ..siblingSeparation = (50)
      ..levelSeparation = (50)
      ..subtreeSeparation = (50)
      ..orientation = BuchheimWalkerConfiguration.DEFAULT_ORIENTATION;
  }

This is my Build method:

  @override
  Widget build(BuildContext context) {
    return Screen(
      title: Text('Organisations'),
      body: Center(
        child: SingleChildScrollView(
          scrollDirection: Axis.horizontal,
          child: SingleChildScrollView(
            child: Padding(
              padding: const EdgeInsets.only(
                right: 16.0,
                bottom: 16.0,
              ),
              child: GraphView(
                algorithm: BuchheimWalkerAlgorithm(
                  builder,
                  TreeEdgeRenderer(builder),
                ),
                graph: myGraph,
                paint: Paint()
                  ..color = Theme.of(context).primaryIconTheme.color
                  ..strokeWidth = 1
                  ..style = PaintingStyle.fill,
              ),
            ),
          ),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.search_rounded),
        onPressed: () {},
      ),
    );
  }

And this is my OrganisationCard widget that's used inside the Nodes:

class OrganisationCard extends StatefulWidget {
  final Organisation organisation;

  final void Function(Node node, Organisation org) addNodeToOrg;
  final void Function(List<Node> nodes) hideNodes;

  final bool expanded;

  OrganisationCard(
    this.organisation, {
    @required this.addNodeToOrg,
    @required this.hideNodes,
    this.expanded = false,
  })  : assert(addNodeToOrg != null),
        assert(hideNodes != null);

  @override
  State<StatefulWidget> createState() {
    return OrganisationCardState();
  }
}

enum popupOptions { expand, add }

class OrganisationCardState extends State<OrganisationCard> {
  List<Organisation> subOrganisations;

  final subOrganisationNodes = <Node>[];

  bool expanded;

  bool hasBeenExpanded = false;

  Node organisationToNode(Organisation organisation) => Node(
        OrganisationCard(
          organisation,
          addNodeToOrg: widget.addNodeToOrg,
          hideNodes: widget.hideNodes,
        ),
        key: ObjectKey(organisation),
      );

  void expand() {
    if (!hasBeenExpanded) {
      subOrganisationNodes.addAll(
        subOrganisations.map<Node>(organisationToNode).toList(),
      );
      hasBeenExpanded = true;
    }

    subOrganisationNodes.forEach(
      (node) => widget.addNodeToOrg(node, widget.organisation),
    );
  }

  @override
  void initState() {
    super.initState();
    expanded = widget.expanded;

    //TODO: This class should either use the subOrganisations list from
    // widget.organisation or generate subOrganisations based on data from
    // widget.organisation once the `Organisation` class has been implemented
    subOrganisations = [
      Organisation(),
      Organisation(),
      Organisation(),
    ];

    if (expanded) {
      WidgetsBinding.instance.addPostFrameCallback((_) => expand());
    }
  }

  @override
  Widget build(BuildContext context) {
    const double maxTextWidth = 150;
    const double maxTextHeight = 60;

    return RoundedContainer(
      child: Material(
        color: Colors.transparent,
        child: InkWell(
          customBorder: RoundedRectangleBorder(
            borderRadius: BorderRadius.all(
              Radius.circular(10),
            ),
          ),
          child: Padding(
            padding: EdgeInsets.only(left: 5),
            child: Row(
              children: [
                ConstrainedBox(
                  constraints: BoxConstraints(
                    maxWidth: maxTextWidth,
                    maxHeight: maxTextHeight,
                  ),
                  child: Container(
                    width: maxTextWidth,
                    height: maxTextHeight,
                    child: Center(
                      child: Text(
                        'Mobiléa',
                        style: Theme.of(context).textTheme.subtitle2,
                        softWrap: true,
                      ),
                    ),
                  ),
                ),
                PopupMenuButton(
                  icon: Icon(
                    Icons.more_vert_rounded,
                    size: 18,
                  ),
                  onSelected: (option) {
                    when(option, {
                      popupOptions.expand: () {
                        if (expanded) {
                          widget.hideNodes(subOrganisationNodes);
                        } else {
                          expand();
                        }
                        setState(() => expanded = !expanded);
                      },
                      popupOptions.add: () {
                        //TODO: Show dialog that gets the user input thats required
                        // to construct an `Organisation` instance once
                        // `Organisation` has been implemented.
                        //TODO: Call some bloc to post newOrganisation to backend.
                        final newOrganisation = Organisation();
                        final node = organisationToNode(newOrganisation);

                        subOrganisations.add(newOrganisation);
                        subOrganisationNodes.add(node);

                        if (expanded) {
                          widget.addNodeToOrg(
                            node,
                            widget.organisation,
                          );
                        }
                      },
                    });
                  },
                  itemBuilder: (context) => <PopupMenuEntry<popupOptions>>[
                    PopupMenuItem<popupOptions>(
                      value: popupOptions.expand,
                      child: Text(expanded ? 'Shrink' : 'Expand'),
                    ),
                    PopupMenuItem<popupOptions>(
                      value: popupOptions.add,
                      child: Text('Add'),
                    ),
                  ],
                ),
              ],
            ),
          ),
          onTap: () => Navigator.of(context).pushNamed('/organisation'),
        ),
      ),
    );
  }
}

Feature request: Create graph based on data entries and provide builder argument

Hi, thanks for building and maintaining such a great package.

I wonder if it would be possible to allow generating a graph based on purely data classes and not widgets.

Here's what I mean. Now nodes need to be created with widgets as their arguments:

final node = Node(
  MyWidget(
    data: data,
  ),
  key: Key(data.id),
);
graph.addNode(node);

What I would love to see is to be able to just provide some data or id:

final node = NodeData(
  id: data.id
);
graph.addNode(node);

And then when creating a GraphView I would be able to provide builder:

GraphView(
  graph: graph,
  algorithm: g.BuchheimWalkerAlgorithm(
    g.BuchheimWalkerConfiguration(),
    g.TreeEdgeRenderer(builder),
  builder: (data){
    // I can decide what widget should be shown here
    return MyWidget(data: data);
  }
),

This would simplify populating graph data and would abstract Flutter/material dependencies

1.0.0.-nullsafety - Keys aren't being recorded

Take:

Node getNode(ContentGraphDto content) {
return Node(
InkWell(
child: Container(
height: 150,
width: 250,
child: Text(content.name),
),
),
key: ObjectKey(content),
);
}

when inspecting the result of this function, you'll note that the key is ValueKey with a number in it and not the objectkey that was passed.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.