QueuePanel.scala 3.84 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package de.tu_darmstadt.cs.esa.tapasco.itapasco.common
import  de.tu_darmstadt.cs.esa.tapasco.task._
import  de.tu_darmstadt.cs.esa.tapasco.util._
import  scala.swing.{BorderPanel, Button, Label, ScrollPane, Swing, Table}
import  scala.swing.BorderPanel.Position._
import  scala.swing.event._
import  java.time.format.DateTimeFormatter, java.time.format.FormatStyle
import  QueuePanel.Events._

/**
 * A BorderPanel which shows a list of [[task.Task]] instances in a queue.
 * @param m MVC model.
 * @param label Description of the queue.
 * @param tasks Function to query current state of the list (will be called repeatedly).
 * @param onClear If not None, will present a button with label 'Clear', which triggers
                  this action when clicked.
 **/
class QueuePanel(
    label: String,
    tasks: () => Seq[Task],
    onClear: Option[() => Unit] = None) extends BorderPanel {
  // scalastyle:off magic.number
  private[this] val _dateFormat = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT)

  private def taskToArray(t: Task): Array[Any] = Array(
    t.description,
    t.queued map (_dateFormat.format(_)) getOrElse "",
    t.started map (_dateFormat.format(_)) getOrElse "",
29
30
    t.completed map (_dateFormat.format(_)) getOrElse "",
    t.result
31
32
33
34
35
36
37
  )

  private def tasksToTable(tasks: Seq[Task]): Array[Array[Any]] =
    (tasks map (taskToArray(_))).toArray

  private def mkTable(tasks: Seq[Task]): Table = new Table(
    tasksToTable(tasks),
38
    Seq("Task", "Queued at", "Started at", "Completed at", "Successful")
39
40
41
42
43
44
45
46
47
48
49
  ) {
    selection.elementMode = scala.swing.Table.ElementMode.Row
    val m = model
    model = new javax.swing.table.AbstractTableModel {
      def getColumnCount(): Int = m.getColumnCount()
      def getRowCount(): Int = m.getRowCount()
      def getValueAt(row: Int, col: Int): Object = m.getValueAt(row, col)
      override def isCellEditable(row: Int, col: Int): Boolean = false
      override def getColumnName(col: Int): String = m.getColumnName(col)
    }

50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
    // highlight unsuccessful rows
    import javax.swing.table._, javax.swing._
    private final val cr = new DefaultTableCellRenderer {
      override def getTableCellRendererComponent(table: JTable, value: Any, isSelected: Boolean, hasFocus: Boolean,
                                                 row: Int, col: Int): JComponent = {
        val r = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col)
        if (tasks(row).completed.nonEmpty) {
          if (!tasks(row).result) {
            setBackground(DefaultColors.toSeq(3))
          } else {
            setBackground(DefaultColors.toSeq(2))
          }
        }
        this
      }
    }
    peer.setDefaultRenderer(classOf[Object], cr)

68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
    // auto-resize columns
    val cols = 0 until peer.getColumnCount() map { i => (i, peer.getColumnModel().getColumn(i)) }
    cols foreach { case (cidx, col) => col.setPreferredWidth(if (cidx == 0) 800 else 150) }
  }

  def update(): Unit = {
    val tbl = mkTable(tasks())
    listenTo(tbl.selection)
    layout(new ScrollPane(tbl) {
      preferredSize = new java.awt.Dimension(0, tbl.rowHeight * 5)
    }) = Center
  }

  object Selection extends Publisher { type Event = QueuePanel.Event }

  reactions += {
    case TableRowsSelected(t, rng, false) => Selection.publish(TaskSelected(tasks().lift(rng.min)))
  }

  layout(new BorderPanel {
    layout(new Label(label) { border = Swing.EmptyBorder(8, 0, 4, 0) }) = West
    onClear map { clear =>
      val b = new Button("Clear") { preferredSize = new java.awt.Dimension(80, 16) }
      layout(b) = East
      listenTo(b)
      reactions += {
        case ButtonClicked(bt) => if (bt.equals(b)) clear() else {}
      }
    }
  }) = North

  update()
  // scalastyle:on magic.number
}

object QueuePanel {
  sealed trait Event
  final object Events {
    final case class TaskSelected(ot: Option[Task]) extends Event
  }
}