You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@beam.apache.org by pa...@apache.org on 2022/03/03 20:07:31 UTC

[beam] branch master updated: [BEAM-13999] playground - support vertical orientation for graph

This is an automated email from the ASF dual-hosted git repository.

pabloem pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/beam.git


The following commit(s) were added to refs/heads/master by this push:
     new 43804b5  [BEAM-13999] playground - support vertical orientation for graph
     new fa5fffd  Merge pull request #16963 from [BEAM-13999] [Playground] support vertical orientation for graph
43804b5 is described below

commit 43804b5b67c91554749b7400437ffa48fcd3c3ac
Author: Aydar Farrakhov <st...@gmail.com>
AuthorDate: Mon Feb 28 17:08:54 2022 +0300

    [BEAM-13999] playground - support vertical orientation for graph
---
 .../modules/graph/graph_builder/canvas_drawer.dart |  11 +-
 .../modules/graph/graph_builder/graph_builder.dart |  25 +++--
 .../graph/graph_builder/painters/edge_painter.dart | 118 ++++++++++++++++++---
 .../graph_builder/painters/graph_painter.dart      |  18 +++-
 .../lib/modules/output/components/graph.dart       |  15 ++-
 .../lib/modules/output/components/output_area.dart |  22 ++--
 6 files changed, 172 insertions(+), 37 deletions(-)

diff --git a/playground/frontend/lib/modules/graph/graph_builder/canvas_drawer.dart b/playground/frontend/lib/modules/graph/graph_builder/canvas_drawer.dart
index df870aa..59cbda7 100644
--- a/playground/frontend/lib/modules/graph/graph_builder/canvas_drawer.dart
+++ b/playground/frontend/lib/modules/graph/graph_builder/canvas_drawer.dart
@@ -104,7 +104,7 @@ class CanvasDrawer {
     canvas.drawCircle(Offset(x1, y1), radius, linePaint);
   }
 
-  drawArrow(double x1, double y1) {
+  drawRightArrow(double x1, double y1) {
     final path = Path();
     path.moveTo(x1 - kArrowSize, y1 - kArrowSize);
     path.lineTo(x1 + kArrowSize, y1);
@@ -113,6 +113,15 @@ class CanvasDrawer {
     canvas.drawPath(path, linePaint);
   }
 
+  drawBottomArrow(double x1, double y1) {
+    final path = Path();
+    path.moveTo(x1 - kArrowSize, y1);
+    path.lineTo(x1, y1 + kArrowSize);
+    path.lineTo(x1 + kArrowSize, y1);
+    path.lineTo(x1 - kArrowSize, y1);
+    canvas.drawPath(path, linePaint);
+  }
+
   drawRect(
       double left,
       double top,
diff --git a/playground/frontend/lib/modules/graph/graph_builder/graph_builder.dart b/playground/frontend/lib/modules/graph/graph_builder/graph_builder.dart
index 1c78b4f..53901aa 100644
--- a/playground/frontend/lib/modules/graph/graph_builder/graph_builder.dart
+++ b/playground/frontend/lib/modules/graph/graph_builder/graph_builder.dart
@@ -60,7 +60,7 @@ abstract class GraphBuilder {
 
   void parseNextLine(String line);
 
-  GraphPainter getPainter() {
+  GraphPainter getPainter(GraphDirection direction) {
     final List<Node> nodeElements = elements
         .where((element) => element.type == NodeType.node)
         .toList()
@@ -80,14 +80,21 @@ abstract class GraphBuilder {
     );
 
     return GraphPainter(
+      direction: direction,
       elementsPainter: elements
           .where((element) => element.type == NodeType.node)
-          .map<NodeElementPainter>((element) => NodeElementPainter(
-                element: element as Node,
-                row: nodeToCellMap[element.name]!.row,
-                column: nodeToCellMap[element.name]!.column,
-              ))
-          .toList(),
+          .map<NodeElementPainter>((element) {
+        final cell = nodeToCellMap[element.name]!;
+        final row =
+            direction == GraphDirection.horizontal ? cell.row : cell.column;
+        final column =
+            direction == GraphDirection.horizontal ? cell.column : cell.row;
+        return NodeElementPainter(
+          element: element as Node,
+          row: row,
+          column: column,
+        );
+      }).toList(),
       edges: edges.map((e) => EdgePainter(e)).toList(),
     );
   }
@@ -237,8 +244,8 @@ class PythonGraphBuilder extends GraphBuilder {
     if (elementsMap[name] != null) {
       return;
     }
-    final label =
-        name.replaceFirst(kPythonDefaultCollectionLabel, kPythonCollectionLabel);
+    final label = name.replaceFirst(
+        kPythonDefaultCollectionLabel, kPythonCollectionLabel);
     Node node = Node(label: label, depth: 1, name: name);
     elementsMap[name] = node;
     elements.add(node);
diff --git a/playground/frontend/lib/modules/graph/graph_builder/painters/edge_painter.dart b/playground/frontend/lib/modules/graph/graph_builder/painters/edge_painter.dart
index 63be832..d676105 100644
--- a/playground/frontend/lib/modules/graph/graph_builder/painters/edge_painter.dart
+++ b/playground/frontend/lib/modules/graph/graph_builder/painters/edge_painter.dart
@@ -20,22 +20,43 @@ import 'dart:math';
 import 'package:collection/collection.dart';
 import 'package:playground/constants/sizes.dart';
 import 'package:playground/modules/graph/graph_builder/canvas_drawer.dart';
+import 'package:playground/modules/graph/graph_builder/painters/graph_painter.dart';
 import 'package:playground/modules/graph/graph_builder/painters/node_painter.dart';
 import 'package:playground/modules/graph/models/graph.dart';
 
+const kEdgeSpacing = 2 * kXlSpacing;
+
 class EdgePainter {
   final Edge edge;
 
   EdgePainter(this.edge);
 
   void paint(
-      CanvasDrawer drawer,
-      Map<String, NodeElementPainter> elementsMap,
-      Map<int, double> rowStarts,
-      Map<int, double> columnStarts,
-      Map<int, double> rowSizes,
-      Map<int, double> columnSizes,
-      ) {
+    CanvasDrawer drawer,
+    Map<String, NodeElementPainter> elementsMap,
+    Map<int, double> rowStarts,
+    Map<int, double> columnStarts,
+    Map<int, double> rowSizes,
+    Map<int, double> columnSizes,
+    GraphDirection direction,
+  ) {
+    if (direction == GraphDirection.vertical) {
+      _drawVertical(
+          drawer, elementsMap, rowStarts, columnStarts, rowSizes, columnSizes);
+    } else {
+      _drawHorizontal(
+          drawer, elementsMap, rowStarts, columnStarts, rowSizes, columnSizes);
+    }
+  }
+
+  _drawHorizontal(
+    CanvasDrawer drawer,
+    Map<String, NodeElementPainter> elementsMap,
+    Map<int, double> rowStarts,
+    Map<int, double> columnStarts,
+    Map<int, double> rowSizes,
+    Map<int, double> columnSizes,
+  ) {
     final startNode = elementsMap[edge.startId]!;
     final endNode = elementsMap[edge.endId]!;
     final startColumn = startNode.column;
@@ -48,16 +69,16 @@ class EdgePainter {
     var y = startNode.top! + startNode.size!.height / 2;
     drawer.drawCircle(x, y, 4.0);
     movePoints.add(Point(x, y));
-    // 1. Go to the closest border
-    x = columnStarts[startColumn]! + columnSizes[startColumn]! + 2 * kXlSpacing;
+    // 1. Go to the closest border (right)
+    x = columnStarts[startColumn]! + columnSizes[startColumn]! + kEdgeSpacing;
     movePoints.add(Point(x, y));
 
     // 2. Go to the correct row
-    y = rowStarts[endRow]! + rowSizes[endRow]! + 2 * kXlSpacing;
+    y = rowStarts[endRow]! + rowSizes[endRow]! + kEdgeSpacing;
     movePoints.add(Point(x, y));
 
     // 3. Go to the correct column
-    x = columnStarts[endColumn]! - 2 * kXlSpacing;
+    x = columnStarts[endColumn]! - kEdgeSpacing;
     movePoints.add(Point(x, y));
 
     // 4. Go to the middle of the row
@@ -87,14 +108,83 @@ class EdgePainter {
       optimizedMovePoints.add(element);
     });
 
-    drawer.drawArrow(
+    drawer.drawRightArrow(
         optimizedMovePoints[0].x + kXlSpacing, optimizedMovePoints[0].y);
 
-    optimizedMovePoints.forEachIndexed((index, point) {
+    _drawLine(drawer, optimizedMovePoints);
+  }
+
+  _drawVertical(
+    CanvasDrawer drawer,
+    Map<String, NodeElementPainter> elementsMap,
+    Map<int, double> rowStarts,
+    Map<int, double> columnStarts,
+    Map<int, double> rowSizes,
+    Map<int, double> columnSizes,
+  ) {
+    final startNode = elementsMap[edge.startId]!;
+    final endNode = elementsMap[edge.endId]!;
+    final startRow = startNode.row;
+    final endColumn = endNode.column;
+    final endRow = endNode.row;
+
+    final List<Point<double>> movePoints = [];
+
+    var x = startNode.left! + startNode.size!.width / 2;
+    var y = startNode.top! + rowSizes[startRow]!;
+    drawer.drawCircle(x, y, 4.0);
+    movePoints.add(Point(x, y));
+    // 1. Go to the closest border (bottom)
+    y = rowStarts[startRow]! + rowSizes[startRow]! + kEdgeSpacing;
+    movePoints.add(Point(x, y));
+
+    // 2. Go to the correct column
+    x = columnStarts[endColumn]! + columnSizes[endColumn]! + kEdgeSpacing;
+    movePoints.add(Point(x, y));
+
+    // 3. Go to the correct row
+    y = rowStarts[endRow]! - kEdgeSpacing;
+    movePoints.add(Point(x, y));
+
+    // 4. Go to the middle of the column
+    x = columnStarts[endColumn]! + endNode.size!.width / 2;
+    movePoints.add(Point(x, y));
+
+    // 5. Go to the element
+    y = rowStarts[endRow]!;
+    movePoints.add(Point(x, y));
+    drawer.drawCircle(x, y, 4.0);
+
+    List<Point<double>> optimizedMovePoints = [];
+
+    movePoints.forEachIndexed((index, element) {
+      if (index == 0 || index == movePoints.length - 1) {
+        optimizedMovePoints.add(element);
+        return;
+      }
+      if (movePoints[index - 1].x == movePoints[index].x &&
+          movePoints[index].x == movePoints[index + 1].x) {
+        return;
+      }
+      if (movePoints[index - 1].y == movePoints[index].y &&
+          movePoints[index].y == movePoints[index + 1].y) {
+        return;
+      }
+      optimizedMovePoints.add(element);
+    });
+
+    drawer.drawBottomArrow(
+        optimizedMovePoints[0].x, optimizedMovePoints[0].y + kXlSpacing);
+
+    _drawLine(drawer, optimizedMovePoints);
+  }
+
+  _drawLine(CanvasDrawer drawer, List<Point<double>> points) {
+    points.forEachIndexed((index, point) {
       if (index == 0) {
         return;
       }
-      final prevPoint = optimizedMovePoints[index - 1];
+      final prevPoint = points[index - 1];
       if (edge.isPrimary) {
         drawer.drawLine(prevPoint.x, prevPoint.y, point.x, point.y);
       } else {
diff --git a/playground/frontend/lib/modules/graph/graph_builder/painters/graph_painter.dart b/playground/frontend/lib/modules/graph/graph_builder/painters/graph_painter.dart
index 7e846c4..81d5635 100644
--- a/playground/frontend/lib/modules/graph/graph_builder/painters/graph_painter.dart
+++ b/playground/frontend/lib/modules/graph/graph_builder/painters/graph_painter.dart
@@ -25,9 +25,12 @@ import 'package:playground/modules/graph/graph_builder/painters/edge_painter.dar
 import 'package:playground/modules/graph/graph_builder/painters/node_painter.dart';
 import 'package:playground/modules/graph/models/graph.dart';
 
+enum GraphDirection { vertical, horizontal }
+
 class GraphPainter {
   final List<NodeElementPainter> elementsPainter;
   final List<EdgePainter> edges;
+  final GraphDirection direction;
   final Map<String, NodeElementPainter> elementsMap = {};
   final Map<int, double> rowSizes = {};
   final Map<int, double> columnSizes = {};
@@ -43,7 +46,11 @@ class GraphPainter {
     return Size(width, height);
   }
 
-  GraphPainter({required this.elementsPainter, required this.edges}) {
+  GraphPainter({
+    required this.elementsPainter,
+    required this.edges,
+    required this.direction,
+  }) {
     for (var element in elementsPainter) {
       elementsMap[element.element.name] = element;
     }
@@ -80,7 +87,14 @@ class GraphPainter {
     });
     for (var element in edges) {
       element.paint(
-          drawer, elementsMap, rowStarts, columnStarts, rowSizes, columnSizes);
+        drawer,
+        elementsMap,
+        rowStarts,
+        columnStarts,
+        rowSizes,
+        columnSizes,
+        direction,
+      );
     }
   }
 }
diff --git a/playground/frontend/lib/modules/output/components/graph.dart b/playground/frontend/lib/modules/output/components/graph.dart
index 62a9596..01fcfbd 100644
--- a/playground/frontend/lib/modules/output/components/graph.dart
+++ b/playground/frontend/lib/modules/output/components/graph.dart
@@ -42,11 +42,13 @@ class GraphCustomPainter extends CustomPainter {
 class GraphTab extends StatefulWidget {
   final String graph;
   final SDK sdk;
+  final GraphDirection direction;
 
   const GraphTab({
     Key? key,
     required this.graph,
     required this.sdk,
+    required this.direction,
   }) : super(key: key);
 
   @override
@@ -59,17 +61,20 @@ class _GraphTabState extends State<GraphTab> {
   @override
   void initState() {
     if (widget.graph.isNotEmpty) {
-      graphPainter =
-          GraphBuilder.parseDot(widget.graph, widget.sdk)?.getPainter();
+      graphPainter = GraphBuilder.parseDot(widget.graph, widget.sdk)
+          ?.getPainter(widget.direction);
     }
     super.initState();
   }
 
   @override
   void didUpdateWidget(GraphTab oldWidget) {
-    if (widget.graph.isNotEmpty && oldWidget.graph != widget.graph) {
-      graphPainter =
-          GraphBuilder.parseDot(widget.graph, widget.sdk)?.getPainter();
+    final graphChanged =
+        widget.graph.isNotEmpty && oldWidget.graph != widget.graph;
+    final directionChanged = widget.direction != oldWidget.direction;
+    if (graphChanged || directionChanged) {
+      graphPainter = GraphBuilder.parseDot(widget.graph, widget.sdk)
+          ?.getPainter(widget.direction);
     }
     if (widget.graph.isEmpty) {
       graphPainter = null;
diff --git a/playground/frontend/lib/modules/output/components/output_area.dart b/playground/frontend/lib/modules/output/components/output_area.dart
index 8ab9763..2bc9af8 100644
--- a/playground/frontend/lib/modules/output/components/output_area.dart
+++ b/playground/frontend/lib/modules/output/components/output_area.dart
@@ -17,8 +17,11 @@
  */
 
 import 'package:flutter/material.dart';
+import 'package:playground/modules/graph/graph_builder/painters/graph_painter.dart';
 import 'package:playground/modules/output/components/graph.dart';
 import 'package:playground/modules/output/components/output_result.dart';
+import 'package:playground/modules/output/models/output_placement.dart';
+import 'package:playground/modules/output/models/output_placement_state.dart';
 import 'package:playground/pages/playground/states/playground_state.dart';
 import 'package:provider/provider.dart';
 
@@ -36,24 +39,25 @@ class OutputArea extends StatelessWidget {
   Widget build(BuildContext context) {
     return Container(
       color: Theme.of(context).backgroundColor,
-      child: Consumer<PlaygroundState>(
-        builder: (context, state, child) {
+      child: Consumer2<PlaygroundState, OutputPlacementState>(
+        builder: (context, playgroundState, placementState, child) {
           return TabBarView(
             controller: tabController,
             physics: const NeverScrollableScrollPhysics(),
             children: <Widget>[
               OutputResult(
-                text: state.result?.output ?? '',
+                text: playgroundState.result?.output ?? '',
                 isSelected: tabController.index == 0,
               ),
               OutputResult(
-                text: state.result?.log ?? '',
+                text: playgroundState.result?.log ?? '',
                 isSelected: tabController.index == 1,
               ),
               if (showGraph)
                 GraphTab(
-                  graph: state.result?.graph ?? '',
-                  sdk: state.sdk,
+                  graph: playgroundState.result?.graph ?? '',
+                  sdk: playgroundState.sdk,
+                  direction: _getGraphDirection(placementState.placement),
                 ),
             ],
           );
@@ -61,4 +65,10 @@ class OutputArea extends StatelessWidget {
       ),
     );
   }
+
+  GraphDirection _getGraphDirection(OutputPlacement placement) {
+    return placement == OutputPlacement.bottom
+        ? GraphDirection.horizontal
+        : GraphDirection.vertical;
+  }
 }