src/Tools/Graphview/graph_panel.scala
changeset 75393 87ebf5a50283
parent 73367 77ef8bef0593
child 75809 1dd5d4f4b69e
equal deleted inserted replaced
75388:b3ca4a6ed74b 75393:87ebf5a50283
    18 
    18 
    19 import scala.swing.{BorderPanel, Button, CheckBox, Action, FileChooser, Panel, ScrollPane}
    19 import scala.swing.{BorderPanel, Button, CheckBox, Action, FileChooser, Panel, ScrollPane}
    20 import scala.swing.event.{Event, Key, MousePressed, MouseDragged, MouseClicked, MouseEvent}
    20 import scala.swing.event.{Event, Key, MousePressed, MouseDragged, MouseClicked, MouseEvent}
    21 
    21 
    22 
    22 
    23 class Graph_Panel(val graphview: Graphview) extends BorderPanel
    23 class Graph_Panel(val graphview: Graphview) extends BorderPanel {
    24 {
       
    25   graph_panel =>
    24   graph_panel =>
    26 
    25 
    27 
    26 
    28 
    27 
    29   /** graph **/
    28   /** graph **/
    30 
    29 
    31   /* painter */
    30   /* painter */
    32 
    31 
    33   private val painter = new Panel
    32   private val painter = new Panel {
    34   {
    33     override def paint(gfx: Graphics2D): Unit = {
    35     override def paint(gfx: Graphics2D): Unit =
       
    36     {
       
    37       super.paintComponent(gfx)
    34       super.paintComponent(gfx)
    38 
    35 
    39       gfx.setColor(graphview.background_color)
    36       gfx.setColor(graphview.background_color)
    40       gfx.fillRect(0, 0, peer.getWidth, peer.getHeight)
    37       gfx.fillRect(0, 0, peer.getWidth, peer.getHeight)
    41 
    38 
    42       gfx.transform(Transform())
    39       gfx.transform(Transform())
    43       graphview.paint(gfx)
    40       graphview.paint(gfx)
    44     }
    41     }
    45   }
    42   }
    46 
    43 
    47   def set_preferred_size(): Unit =
    44   def set_preferred_size(): Unit = {
    48   {
       
    49     val box = graphview.bounding_box()
    45     val box = graphview.bounding_box()
    50     val s = Transform.scale_discrete
    46     val s = Transform.scale_discrete
    51     painter.preferredSize = new Dimension((box.width * s).ceil.toInt, (box.height * s).ceil.toInt)
    47     painter.preferredSize = new Dimension((box.width * s).ceil.toInt, (box.height * s).ceil.toInt)
    52     painter.revalidate()
    48     painter.revalidate()
    53   }
    49   }
    54 
    50 
    55   def refresh(): Unit =
    51   def refresh(): Unit = {
    56   {
       
    57     if (painter != null) {
    52     if (painter != null) {
    58       set_preferred_size()
    53       set_preferred_size()
    59       painter.repaint()
    54       painter.repaint()
    60     }
    55     }
    61   }
    56   }
    62 
    57 
    63   def scroll_to_node(node: Graph_Display.Node): Unit =
    58   def scroll_to_node(node: Graph_Display.Node): Unit = {
    64   {
       
    65     val gap = graphview.metrics.gap
    59     val gap = graphview.metrics.gap
    66     val info = graphview.layout.get_node(node)
    60     val info = graphview.layout.get_node(node)
    67 
    61 
    68     val t = Transform()
    62     val t = Transform()
    69     val p =
    63     val p =
    99     verticalScrollBarPolicy = ScrollPane.BarPolicy.Always
    93     verticalScrollBarPolicy = ScrollPane.BarPolicy.Always
   100 
    94 
   101     listenTo(mouse.moves)
    95     listenTo(mouse.moves)
   102     listenTo(mouse.clicks)
    96     listenTo(mouse.clicks)
   103     reactions +=
    97     reactions +=
   104     {
    98       {
   105       case MousePressed(_, p, _, _, _) =>
    99         case MousePressed(_, p, _, _, _) =>
   106         Mouse_Interaction.pressed(p)
   100           Mouse_Interaction.pressed(p)
   107         painter.repaint()
   101           painter.repaint()
   108       case MouseDragged(_, to, _) =>
   102         case MouseDragged(_, to, _) =>
   109         Mouse_Interaction.dragged(to)
   103           Mouse_Interaction.dragged(to)
   110         painter.repaint()
   104           painter.repaint()
   111       case e @ MouseClicked(_, p, m, n, _) =>
   105         case e @ MouseClicked(_, p, m, n, _) =>
   112         Mouse_Interaction.clicked(p, m, n, SwingUtilities.isRightMouseButton(e.peer))
   106           Mouse_Interaction.clicked(p, m, n, SwingUtilities.isRightMouseButton(e.peer))
   113         painter.repaint()
   107           painter.repaint()
   114     }
   108       }
   115 
   109 
   116     contents = painter
   110     contents = painter
   117   }
   111   }
   118   graph_pane.peer.getVerticalScrollBar.setUnitIncrement(10)
   112   graph_pane.peer.getVerticalScrollBar.setUnitIncrement(10)
   119 
   113 
   120 
   114 
   121   /* transform */
   115   /* transform */
   122 
   116 
   123   def rescale(s: Double): Unit =
   117   def rescale(s: Double): Unit = {
   124   {
       
   125     Transform.scale = s
   118     Transform.scale = s
   126     if (zoom != null) zoom.set_item((Transform.scale_discrete * 100).floor.toInt)
   119     if (zoom != null) zoom.set_item((Transform.scale_discrete * 100).floor.toInt)
   127     refresh()
   120     refresh()
   128   }
   121   }
   129 
   122 
   130   def fit_to_window(): Unit =
   123   def fit_to_window(): Unit = {
   131   {
       
   132     Transform.fit_to_window()
   124     Transform.fit_to_window()
   133     refresh()
   125     refresh()
   134   }
   126   }
   135 
   127 
   136   private object Transform
   128   private object Transform {
   137   {
       
   138     private var _scale: Double = 1.0
   129     private var _scale: Double = 1.0
   139     def scale: Double = _scale
   130     def scale: Double = _scale
   140     def scale_=(s: Double): Unit =
   131     def scale_=(s: Double): Unit = {
   141     {
       
   142       _scale = (s min 10.0) max 0.1
   132       _scale = (s min 10.0) max 0.1
   143     }
   133     }
   144 
   134 
   145     def scale_discrete: Double =
   135     def scale_discrete: Double = {
   146     {
       
   147       val font_height = GUI.line_metrics(graphview.metrics.font).getHeight.toInt
   136       val font_height = GUI.line_metrics(graphview.metrics.font).getHeight.toInt
   148       (scale * font_height).floor / font_height
   137       (scale * font_height).floor / font_height
   149     }
   138     }
   150 
   139 
   151     def apply(): AffineTransform =
   140     def apply(): AffineTransform = {
   152     {
       
   153       val box = graphview.bounding_box()
   141       val box = graphview.bounding_box()
   154       val t = AffineTransform.getScaleInstance(scale_discrete, scale_discrete)
   142       val t = AffineTransform.getScaleInstance(scale_discrete, scale_discrete)
   155       t.translate(- box.x, - box.y)
   143       t.translate(- box.x, - box.y)
   156       t
   144       t
   157     }
   145     }
   158 
   146 
   159     def fit_to_window(): Unit =
   147     def fit_to_window(): Unit = {
   160     {
       
   161       if (graphview.visible_graph.is_empty)
   148       if (graphview.visible_graph.is_empty)
   162         rescale(1.0)
   149         rescale(1.0)
   163       else {
   150       else {
   164         val box = graphview.bounding_box()
   151         val box = graphview.bounding_box()
   165         rescale((size.width / box.width) min (size.height / box.height))
   152         rescale((size.width / box.width) min (size.height / box.height))
   166       }
   153       }
   167     }
   154     }
   168 
   155 
   169     def pane_to_graph_coordinates(at: Point2D): Point2D =
   156     def pane_to_graph_coordinates(at: Point2D): Point2D = {
   170     {
       
   171       val s = Transform.scale_discrete
   157       val s = Transform.scale_discrete
   172       val p = Transform().inverseTransform(graph_pane.peer.getViewport.getViewPosition, null)
   158       val p = Transform().inverseTransform(graph_pane.peer.getViewport.getViewPosition, null)
   173 
   159 
   174       p.setLocation(p.getX + at.getX / s, p.getY + at.getY / s)
   160       p.setLocation(p.getX + at.getX / s, p.getY + at.getY / s)
   175       p
   161       p
   180   /* interaction */
   166   /* interaction */
   181 
   167 
   182   graphview.model.Colors.events += { case _ => painter.repaint() }
   168   graphview.model.Colors.events += { case _ => painter.repaint() }
   183   graphview.model.Mutators.events += { case _ => painter.repaint() }
   169   graphview.model.Mutators.events += { case _ => painter.repaint() }
   184 
   170 
   185   private object Mouse_Interaction
   171   private object Mouse_Interaction {
   186   {
       
   187     private var draginfo: (Point, List[Graph_Display.Node], List[Layout.Dummy]) =
   172     private var draginfo: (Point, List[Graph_Display.Node], List[Layout.Dummy]) =
   188       (new Point(0, 0), Nil, Nil)
   173       (new Point(0, 0), Nil, Nil)
   189 
   174 
   190     def pressed(at: Point): Unit =
   175     def pressed(at: Point): Unit = {
   191     {
       
   192       val c = Transform.pane_to_graph_coordinates(at)
   176       val c = Transform.pane_to_graph_coordinates(at)
   193       val l =
   177       val l =
   194         graphview.find_node(c) match {
   178         graphview.find_node(c) match {
   195           case Some(node) =>
   179           case Some(node) =>
   196             if (graphview.Selection.contains(node)) graphview.Selection.get()
   180             if (graphview.Selection.contains(node)) graphview.Selection.get()
   203           case _ => Nil
   187           case _ => Nil
   204         }
   188         }
   205       draginfo = (at, l, d)
   189       draginfo = (at, l, d)
   206     }
   190     }
   207 
   191 
   208     def dragged(to: Point): Unit =
   192     def dragged(to: Point): Unit = {
   209     {
       
   210       val (from, p, d) = draginfo
   193       val (from, p, d) = draginfo
   211 
   194 
   212       val s = Transform.scale_discrete
   195       val s = Transform.scale_discrete
   213       val dx = to.x - from.x
   196       val dx = to.x - from.x
   214       val dy = to.y - from.y
   197       val dy = to.y - from.y
   227       }
   210       }
   228 
   211 
   229       draginfo = (to, p, d)
   212       draginfo = (to, p, d)
   230     }
   213     }
   231 
   214 
   232     def clicked(at: Point, m: Key.Modifiers, clicks: Int, right_click: Boolean): Unit =
   215     def clicked(at: Point, m: Key.Modifiers, clicks: Int, right_click: Boolean): Unit = {
   233     {
       
   234       val c = Transform.pane_to_graph_coordinates(at)
   216       val c = Transform.pane_to_graph_coordinates(at)
   235 
   217 
   236       if (clicks < 2) {
   218       if (clicks < 2) {
   237         if (right_click) {
   219         if (right_click) {
   238           // FIXME
   220           // FIXME