11package org .codingteam .icfpc2021 .visualizer
22
3- import org .codingteam .icfpc2021 .{Json , Problem }
3+ import org .codingteam .icfpc2021 .{Json , Problem , Point , Rect }
44
55import java .awt ._
66import java .awt .event .{ActionEvent , MouseEvent , MouseListener , _ }
77import java .nio .file .{Files , Path }
88import javax .swing ._
9+ import scala .collection .mutable .BitSet
910
1011class Visualizer (val problem : Problem ) extends JFrame (" Codingteam ICPFC-2021" ) {
1112
1213 private val translator = new Translator (problem)
14+ private var solution = problem.figure.vertices
15+
1316 private var selection : Option [(java.awt.Point , java.awt.Point )] = None
17+ private var selectedFigureVertices = new BitSet
18+
1419 private lazy val mainPanel = {
1520 val p = new JPanel ()
1621 p.setLayout(new BorderLayout ())
@@ -31,20 +36,28 @@ class Visualizer(val problem: Problem) extends JFrame("Codingteam ICPFC-2021") {
3136 val (x, y) = translator.toScreen(vert)
3237 g.drawString(String .valueOf(i), x, y)
3338 }
34- selection foreach { r =>
35- val (x1, x2) = (r._1.x.min(r._2.x), r._1.x.max(r._2.x))
36- val (y1, y2) = (r._1.y.min(r._2.y), r._1.y.max(r._2.y))
39+
40+ selection foreach { sel =>
41+ val (x1, x2) = (sel._1.x.min(sel._2.x), sel._1.x.max(sel._2.x))
42+ val (y1, y2) = (sel._1.y.min(sel._2.y), sel._1.y.max(sel._2.y))
3743 g2.drawRect(x1, y1, x2 - x1, y2 - y1)
3844 }
45+
46+ g2.setColor(Color .RED )
47+ for (i <- selectedFigureVertices) {
48+ val (x, y) = translator.toScreen(solution(i))
49+ g.fillOval(x - 4 , y - 4 , 8 , 8 )
50+ }
51+
3952 g2.setColor(Color .RED )
4053 for (edge <- problem.figure.edges) {
41- val (x1, y1) = translator.toScreen(problem.figure.vertices (edge.vertex1))
42- val (x2, y2) = translator.toScreen(problem.figure.vertices (edge.vertex2))
54+ val (x1, y1) = translator.toScreen(solution (edge.vertex1))
55+ val (x2, y2) = translator.toScreen(solution (edge.vertex2))
4356 g.drawLine(x1, y1, x2, y2)
4457 }
4558
4659 g2.setColor(Color .BLACK )
47- for ((vert, i) <- problem.figure.vertices .zipWithIndex) {
60+ for ((vert, i) <- solution .zipWithIndex) {
4861 val (x, y) = translator.toScreen(vert)
4962 g.drawString(String .valueOf(i), x, y)
5063 }
@@ -76,6 +89,18 @@ class Visualizer(val problem: Problem) extends JFrame("Codingteam ICPFC-2021") {
7689 override def mouseDragged (e : MouseEvent ): Unit = {
7790 selection foreach { sel =>
7891 sel._2.setLocation(e.getX, e.getY)
92+
93+ val (x1, x2) = (sel._1.x.min(sel._2.x), sel._1.x.max(sel._2.x))
94+ val (y1, y2) = (sel._1.y.min(sel._2.y), sel._1.y.max(sel._2.y))
95+ val rect = Rect (translator.toModel(x1, y1), translator.toModel(x2, y2))
96+
97+ selectedFigureVertices.clear()
98+ for ((vert, i) <- solution.zipWithIndex) {
99+ if (rect.contains(vert)) {
100+ selectedFigureVertices.add(i)
101+ }
102+ }
103+
79104 p.repaint()
80105 }
81106 }
@@ -85,13 +110,22 @@ class Visualizer(val problem: Problem) extends JFrame("Codingteam ICPFC-2021") {
85110 p
86111
87112 }
113+
88114 private lazy val buttonsPanel = {
89115 val tb = new JToolBar ()
90- tb.add(testAction)
116+ tb.add(visualizer.makeAction(" Test Action" , () => println(" Test action called" )))
117+ tb.add(visualizer.makeAction(" ←" , () => moveSelected(Point (- 1 , 0 ))))
118+ tb.add(visualizer.makeAction(" →" , () => moveSelected(Point (+ 1 , 0 ))))
119+ tb.add(visualizer.makeAction(" ↑" , () => moveSelected(Point (0 , - 1 ))))
120+ tb.add(visualizer.makeAction(" ↓" , () => moveSelected(Point (0 , + 1 ))))
91121 tb
92122 }
93- private lazy val testAction = new AbstractAction (" Test action" ) {
94- override def actionPerformed (e : ActionEvent ): Unit = println(" Test action called" )
123+
124+ private def moveSelected (delta : Point ): Unit = {
125+ solution = solution.zipWithIndex.map { case (p, idx) =>
126+ if (selectedFigureVertices.contains(idx)) p + delta else p
127+ }
128+ problemPanel.repaint()
95129 }
96130
97131 private def init (): Unit = {
@@ -104,6 +138,13 @@ class Visualizer(val problem: Problem) extends JFrame("Codingteam ICPFC-2021") {
104138 init()
105139}
106140
141+ package object visualizer {
142+ // TODO: move this helper function somewhere to an appropriate place
143+ def makeAction (name : String , callback : () => Unit ): AbstractAction = new AbstractAction (name) {
144+ override def actionPerformed (e : ActionEvent ): Unit = callback()
145+ }
146+ }
147+
107148object Visualizer {
108149 def show (problemFile : Path ): Visualizer = {
109150 val content = Files .readString(problemFile)
0 commit comments