src/Tools/Graphview/shapes.scala
changeset 75393 87ebf5a50283
parent 73359 d8a0e996614b
child 75424 5f8f0bf8c72c
equal deleted inserted replaced
75388:b3ca4a6ed74b 75393:87ebf5a50283
    13 import java.awt.{BasicStroke, Graphics2D, Shape}
    13 import java.awt.{BasicStroke, Graphics2D, Shape}
    14 import java.awt.geom.{AffineTransform, GeneralPath, Path2D, Rectangle2D,
    14 import java.awt.geom.{AffineTransform, GeneralPath, Path2D, Rectangle2D,
    15   RoundRectangle2D, PathIterator}
    15   RoundRectangle2D, PathIterator}
    16 
    16 
    17 
    17 
    18 object Shapes
    18 object Shapes {
    19 {
       
    20   private val default_stroke =
    19   private val default_stroke =
    21     new BasicStroke(1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND)
    20     new BasicStroke(1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND)
    22 
    21 
    23   def shape(info: Layout.Info): Rectangle2D.Double =
    22   def shape(info: Layout.Info): Rectangle2D.Double =
    24     new Rectangle2D.Double(info.x - info.width2, info.y - info.height2, info.width, info.height)
    23     new Rectangle2D.Double(info.x - info.width2, info.y - info.height2, info.width, info.height)
    25 
    24 
    26   def highlight_node(gfx: Graphics2D, graphview: Graphview, node: Graph_Display.Node): Unit =
    25   def highlight_node(gfx: Graphics2D, graphview: Graphview, node: Graph_Display.Node): Unit = {
    27   {
       
    28     val metrics = graphview.metrics
    26     val metrics = graphview.metrics
    29     val extra = metrics.char_width
    27     val extra = metrics.char_width
    30     val info = graphview.layout.get_node(node)
    28     val info = graphview.layout.get_node(node)
    31 
    29 
    32     gfx.setColor(graphview.highlight_color)
    30     gfx.setColor(graphview.highlight_color)
    35       info.y - info.height2 - extra,
    33       info.y - info.height2 - extra,
    36       info.width + 2 * extra,
    34       info.width + 2 * extra,
    37       info.height + 2 * extra))
    35       info.height + 2 * extra))
    38   }
    36   }
    39 
    37 
    40   def paint_node(gfx: Graphics2D, graphview: Graphview, node: Graph_Display.Node): Unit =
    38   def paint_node(gfx: Graphics2D, graphview: Graphview, node: Graph_Display.Node): Unit = {
    41   {
       
    42     val metrics = graphview.metrics
    39     val metrics = graphview.metrics
    43     val info = graphview.layout.get_node(node)
    40     val info = graphview.layout.get_node(node)
    44     val c = graphview.node_color(node)
    41     val c = graphview.node_color(node)
    45     val s = shape(info)
    42     val s = shape(info)
    46 
    43 
    64       gfx.drawString(Word.bidi_override(line), x, y)
    61       gfx.drawString(Word.bidi_override(line), x, y)
    65       y += metrics.height.ceil.toInt
    62       y += metrics.height.ceil.toInt
    66     }
    63     }
    67   }
    64   }
    68 
    65 
    69   def paint_dummy(gfx: Graphics2D, graphview: Graphview, info: Layout.Info): Unit =
    66   def paint_dummy(gfx: Graphics2D, graphview: Graphview, info: Layout.Info): Unit = {
    70   {
       
    71     gfx.setStroke(default_stroke)
    67     gfx.setStroke(default_stroke)
    72     gfx.setColor(graphview.dummy_color)
    68     gfx.setColor(graphview.dummy_color)
    73     gfx.draw(shape(info))
    69     gfx.draw(shape(info))
    74   }
    70   }
    75 
    71 
    76   object Straight_Edge
    72   object Straight_Edge {
    77   {
    73     def paint(gfx: Graphics2D, graphview: Graphview, edge: Graph_Display.Edge): Unit = {
    78     def paint(gfx: Graphics2D, graphview: Graphview, edge: Graph_Display.Edge): Unit =
       
    79     {
       
    80       val p = graphview.layout.get_node(edge._1)
    74       val p = graphview.layout.get_node(edge._1)
    81       val q = graphview.layout.get_node(edge._2)
    75       val q = graphview.layout.get_node(edge._2)
    82       val ds =
    76       val ds = {
    83       {
       
    84         val a = p.y min q.y
    77         val a = p.y min q.y
    85         val b = p.y max q.y
    78         val b = p.y max q.y
    86         graphview.layout.dummies_iterator(edge).filter(d => a < d.y && d.y < b).toList
    79         graphview.layout.dummies_iterator(edge).filter(d => a < d.y && d.y < b).toList
    87       }
    80       }
    88       val path = new GeneralPath(Path2D.WIND_EVEN_ODD, ds.length + 2)
    81       val path = new GeneralPath(Path2D.WIND_EVEN_ODD, ds.length + 2)
    99 
    92 
   100       if (graphview.show_arrow_heads) Arrow_Head.paint(gfx, path, Shapes.shape(q))
    93       if (graphview.show_arrow_heads) Arrow_Head.paint(gfx, path, Shapes.shape(q))
   101     }
    94     }
   102   }
    95   }
   103 
    96 
   104   object Cardinal_Spline_Edge
    97   object Cardinal_Spline_Edge {
   105   {
       
   106     private val slack = 0.1
    98     private val slack = 0.1
   107 
    99 
   108     def paint(gfx: Graphics2D, graphview: Graphview, edge: Graph_Display.Edge): Unit =
   100     def paint(gfx: Graphics2D, graphview: Graphview, edge: Graph_Display.Edge): Unit = {
   109     {
       
   110       val p = graphview.layout.get_node(edge._1)
   101       val p = graphview.layout.get_node(edge._1)
   111       val q = graphview.layout.get_node(edge._2)
   102       val q = graphview.layout.get_node(edge._2)
   112       val ds =
   103       val ds = {
   113       {
       
   114         val a = p.y min q.y
   104         val a = p.y min q.y
   115         val b = p.y max q.y
   105         val b = p.y max q.y
   116         graphview.layout.dummies_iterator(edge).filter(d => a < d.y && d.y < b).toList
   106         graphview.layout.dummies_iterator(edge).filter(d => a < d.y && d.y < b).toList
   117       }
   107       }
   118 
   108 
   152         if (graphview.show_arrow_heads) Arrow_Head.paint(gfx, path, Shapes.shape(q))
   142         if (graphview.show_arrow_heads) Arrow_Head.paint(gfx, path, Shapes.shape(q))
   153       }
   143       }
   154     }
   144     }
   155   }
   145   }
   156 
   146 
   157   object Arrow_Head
   147   object Arrow_Head {
   158   {
       
   159     type Point = (Double, Double)
   148     type Point = (Double, Double)
   160 
   149 
   161     private def position(path: GeneralPath, shape: Shape): Option[AffineTransform] =
   150     private def position(path: GeneralPath, shape: Shape): Option[AffineTransform] = {
   162     {
   151       def intersecting_line(path: GeneralPath, shape: Shape): Option[(Point, Point)] = {
   163       def intersecting_line(path: GeneralPath, shape: Shape): Option[(Point, Point)] =
       
   164       {
       
   165         val i = path.getPathIterator(null, 1.0)
   152         val i = path.getPathIterator(null, 1.0)
   166         val seg = Array[Double](0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
   153         val seg = Array[Double](0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
   167         var p1 = (0.0, 0.0)
   154         var p1 = (0.0, 0.0)
   168         var p2 = (0.0, 0.0)
   155         var p2 = (0.0, 0.0)
   169         while (!i.isDone) {
   156         while (!i.isDone) {
   180           i.next()
   167           i.next()
   181         }
   168         }
   182         None
   169         None
   183       }
   170       }
   184 
   171 
   185       def binary_search(line: (Point, Point), shape: Shape): Option[AffineTransform] =
   172       def binary_search(line: (Point, Point), shape: Shape): Option[AffineTransform] = {
   186       {
       
   187         val ((fx, fy), (tx, ty)) = line
   173         val ((fx, fy), (tx, ty)) = line
   188         if (shape.contains(fx, fy) == shape.contains(tx, ty))
   174         if (shape.contains(fx, fy) == shape.contains(tx, ty))
   189           None
   175           None
   190         else {
   176         else {
   191           val (dx, dy) = (fx - tx, fy - ty)
   177           val (dx, dy) = (fx - tx, fy - ty)
   208         case None => None
   194         case None => None
   209         case Some(line) => binary_search(line, shape)
   195         case Some(line) => binary_search(line, shape)
   210       }
   196       }
   211     }
   197     }
   212 
   198 
   213     def paint(gfx: Graphics2D, path: GeneralPath, shape: Shape): Unit =
   199     def paint(gfx: Graphics2D, path: GeneralPath, shape: Shape): Unit = {
   214     {
       
   215       position(path, shape) match {
   200       position(path, shape) match {
   216         case None =>
   201         case None =>
   217         case Some(at) =>
   202         case Some(at) =>
   218           val arrow = new GeneralPath(Path2D.WIND_EVEN_ODD, 3)
   203           val arrow = new GeneralPath(Path2D.WIND_EVEN_ODD, 3)
   219           arrow.moveTo(0, 0)
   204           arrow.moveTo(0, 0)