graphite 0.3.0 copy "graphite: ^0.3.0" to clipboard
graphite: ^0.3.0 copied to clipboard

Flutter widget to easily draw direct graphs, trees, flowcharts. Includes gesture API to create graphs interactions.

example/lib/main.dart

import 'dart:ui';
import 'dart:math' as math;

import 'package:flutter/material.dart';
import 'package:graphite/core/matrix.dart';
import 'package:graphite/core/typings.dart';
import 'package:graphite/graphite.dart';

void main() => runApp(MyApp());
const presetBasic = '[{"id":"A","next":["B"]},{"id":"B","next":["C","D","E"]},'
    '{"id":"C","next":["F"]},{"id":"D","next":["J"]},{"id":"E","next":["J"]},'
    '{"id":"J","next":["I"]},{"id":"I","next":["H"]},{"id":"F","next":["K"]},'
    '{"id":"K","next":["L"]},{"id":"H","next":["L"]},{"id":"L","next":["P"]},'
    '{"id":"P","next":["M","N"]},{"id":"M","next":[]},{"id":"N","next":[]}]';

const presetComplex = '[{"id":"A","next":["B"]},{"id":"U","next":["G"]},'
    '{"id":"B","next":["C","D","E","F","M"]},{"id":"C","next":["G"]},'
    '{"id":"D","next":["H"]},{"id":"E","next":["H"]},{"id":"F","next":["N","O"]},'
    '{"id":"N","next":["I"]},{"id":"O","next":["P"]},{"id":"P","next":["I"]},'
    '{"id":"M","next":["L"]},{"id":"G","next":["I"]},{"id":"H","next":["J"]},'
    '{"id":"I","next":[]},{"id":"J","next":["K"]},'
    '{"id":"K","next":["L"]},{"id":"L","next":[]}]';

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Graphite',
      theme: ThemeData(
        primarySwatch: Colors.teal,
      ),
      home: BasicPage(),
      routes: routes,
    );
  }
}

class BasicPage extends StatefulWidget {
  BasicPage({Key key}) : super(key: key);
  @override
  _BasicPageState createState() => _BasicPageState();
}

class _BasicPageState extends State<BasicPage> {
  int _selectedIndex = 0;
  void _onItemTapped(int index) {
    setState(() {
      _selectedIndex = index;
    });
    Navigator.push(
        context,
        PageRouteBuilder(
            transitionDuration: Duration(seconds: 1),
            pageBuilder: (_, __, ___) =>
                index == 0 ? BasicPage() : CustomPage()));
  }

  @override
  Widget build(BuildContext context) {
    var list = nodeInputFromJson(presetBasic);
    return Scaffold(
      appBar: AppBar(
          leading: Icon(Icons.view_module), title: Text('Basic Example')),
      body: DirectGraph(
        list: list,
        cellWidth: 136.0,
        cellPadding: 24.0,
        contactEdgesDistance: 10.0,
        orientation: MatrixOrientation.Vertical,
      ),
      bottomNavigationBar: BottomNavigationBar(
        items: const <BottomNavigationBarItem>[
          BottomNavigationBarItem(
            icon: Icon(Icons.view_module),
            title: Text('Basic'),
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.view_comfy),
            title: Text('Custom'),
          ),
        ],
        currentIndex: _selectedIndex,
        selectedItemColor: Colors.teal[800],
        onTap: _onItemTapped,
      ),
    );
  }
}

class CustomPage extends StatefulWidget {
  CustomPage({Key key}) : super(key: key);
  @override
  _CustomPageState createState() {
    return _CustomPageState();
  }
}

class _CustomPageState extends State<CustomPage> {
  List<NodeInput> list = nodeInputFromJson(presetComplex);
  int _selectedIndex = 1;
  Map<String, bool> selected = {};
  void _onItemSelected(String nodeId) {
    setState(() {
      selected[nodeId] =
          selected[nodeId] == null || !selected[nodeId] ? true : false;
    });
  }

  void _onItemTapped(int index) {
    setState(() {
      _selectedIndex = index;
    });
    var nextPage = index == 0 ? BasicPage : CustomPage;
    Navigator.push(
        context,
        PageRouteBuilder(
            transitionDuration: Duration(seconds: 1),
            pageBuilder: (_, __, ___) =>
                index == 0 ? BasicPage() : CustomPage()));
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.grey[200],
      appBar: AppBar(
          leading: Icon(Icons.view_comfy), title: Text('Custom Example')),
      body: DirectGraph(
        list: list,
        cellWidth: 104.0,
        cellPadding: 14.0,
        contactEdgesDistance: 5.0,
        orientation: MatrixOrientation.Vertical,
        pathBuilder: customEdgePathBuilder,
        builder: (ctx, node) {
          return Card(
            child: Center(
              child: Text(
                node.id,
                style: selected[node.id] ?? false
                    ? TextStyle(
                        fontSize: 20.0,
                        fontWeight: FontWeight.bold,
                        color: Colors.red)
                    : TextStyle(fontSize: 20.0),
              ),
            ),
          );
        },
        paintBuilder: (edge) {
          var p = Paint()
            ..color = Colors.blueGrey
            ..style = PaintingStyle.stroke
            ..strokeCap = StrokeCap.round
            ..strokeJoin = StrokeJoin.round
            ..strokeWidth = 2;
          if ((selected[edge.from.id] ?? false) &&
              (selected[edge.to.id] ?? false)) {
            p.color = Colors.red;
          }
          return p;
        },
        onNodeTapDown: (_, node) {
          _onItemSelected(node.id);
        },
      ),
      bottomNavigationBar: BottomNavigationBar(
        items: const <BottomNavigationBarItem>[
          BottomNavigationBarItem(
            icon: Icon(Icons.view_module),
            label: 'Basic',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.view_comfy),
            label: 'Custom',
          ),
        ],
        currentIndex: _selectedIndex,
        selectedItemColor: Colors.teal[800],
        onTap: _onItemTapped,
      ),
    );
  }
}

final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
  '/home': (BuildContext context) => BasicPage(),
  '/complex': (BuildContext context) => CustomPage(),
};

Path customEdgePathBuilder(List<List<double>> points) {
  var path = Path();
  path.moveTo(points[0][0], points[0][1]);
  points.sublist(1).forEach((p) {
    path.lineTo(p[0], p[1]);
  });
  return path;
}
128
likes
100
pub points
90%
popularity

Publisher

unverified uploader

Flutter widget to easily draw direct graphs, trees, flowcharts. Includes gesture API to create graphs interactions.

Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (LICENSE)

Dependencies

arrow_path, flutter, touchable

More

Packages that depend on graphite