@@ -27,6 +27,9 @@ import java.awt.event.ActionListener
2727import java.awt.event.FocusEvent
2828import java.awt.event.FocusListener
2929import java.text.DecimalFormat
30+ import javax.swing.Box
31+ import javax.swing.DefaultComboBoxModel
32+ import javax.swing.JComboBox
3033import javax.swing.JComponent
3134import javax.swing.JLabel
3235import javax.swing.JPanel
@@ -59,6 +62,9 @@ class RunnerPanel implements FocusListener, ActionListener {
5962 ToolbarButton refreshButton
6063 ToolbarButton rerunButton
6164 ToolbarButton rerunWorksheetButton
65+ DefaultComboBoxModel<ComboBoxItem<String ,String > > runComboBoxModel
66+ ToolbarButton clearButton
67+ JComboBox<ComboBoxItem<String ,String > > runComboBox
6268 JLabel statusLabel
6369 JLabel testCounterValueLabel
6470 JLabel errorCounterValueLabel
@@ -107,17 +113,39 @@ class RunnerPanel implements FocusListener, ActionListener {
107113 testWarningsTextArea. text = null
108114 testServerOutputTextArea. text = null
109115 }
116+
117+ private def refreshRunsComboBox () {
118+ if (runs. size > 0 ) {
119+ runComboBox. removeActionListener(this )
120+ runComboBoxModel. removeAllElements
121+ for (var i = runs. size - 1 ; i >= 0 ; i-- ) {
122+ val entry = runs. entrySet. get(i)
123+ val item = new ComboBoxItem<String , String > (entry. key, entry. value. name)
124+ runComboBoxModel. addElement(item)
125+ }
126+ runComboBox. selectedIndex = 0
127+ runComboBox. addActionListener(this )
128+ }
129+ }
110130
111131 def setModel (Run run ) {
112132 runs. put(run. reporterId, run)
113- currentRun = run
114- testOverviewTableModel. model = run. tests
115- resetDerived
133+ refreshRunsComboBox
134+ setCurrentRun(run)
116135 }
117136
118- def update (String reporterId ) {
119- val run = runs. get(reporterId)
120- val row = run. totalNumberOfCompletedTests - 1
137+ private def setCurrentRun (Run run ) {
138+ if (run !== currentRun) {
139+ currentRun = run
140+ testOverviewTableModel. model = run. tests
141+ resetDerived
142+ runComboBox. selectedItem = run. name
143+ }
144+ }
145+
146+ def synchronized update (String reporterId ) {
147+ setCurrentRun(runs. get(reporterId))
148+ val row = currentRun. totalNumberOfCompletedTests - 1
121149 val header = testOverviewTableModel. testIdColumnName
122150 val idColumn = testOverviewTable. columnModel. getColumn(3 )
123151 if (idColumn. headerValue != header) {
@@ -133,19 +161,19 @@ class RunnerPanel implements FocusListener, ActionListener {
133161 testOverviewTable. scrollRectToVisible = positionOfCurrentTest
134162 }
135163 }
136- statusLabel. text = run . status
137- testCounterValueLabel. text = ' ' ' «run .totalNumberOfCompletedTests»/«run .totalNumberOfTests»' ' '
138- errorCounterValueLabel. text = ' ' ' «run .counter.error»' ' '
139- failureCounterValueLabel. text = ' ' ' «run .counter.failure»' ' '
140- disabledCounterValueLabel. text = ' ' ' «run .counter.disabled»' ' '
141- warningsCounterValueLabel. text = ' ' ' «run .counter.warning»' ' '
142- infoCounterValueLabel. text = ' ' ' «run .infoCount»' ' '
143- if (run . totalNumberOfTests == 0 ) {
164+ statusLabel. text = currentRun . status
165+ testCounterValueLabel. text = ' ' ' «currentRun .totalNumberOfCompletedTests»/«currentRun .totalNumberOfTests»' ' '
166+ errorCounterValueLabel. text = ' ' ' «currentRun .counter.error»' ' '
167+ failureCounterValueLabel. text = ' ' ' «currentRun .counter.failure»' ' '
168+ disabledCounterValueLabel. text = ' ' ' «currentRun .counter.disabled»' ' '
169+ warningsCounterValueLabel. text = ' ' ' «currentRun .counter.warning»' ' '
170+ infoCounterValueLabel. text = ' ' ' «currentRun .infoCount»' ' '
171+ if (currentRun . totalNumberOfTests == 0 ) {
144172 progressBar. value = 100
145173 } else {
146- progressBar. value = Math . round(100 * run . totalNumberOfCompletedTests / run . totalNumberOfTests)
174+ progressBar. value = Math . round(100 * currentRun . totalNumberOfCompletedTests / currentRun . totalNumberOfTests)
147175 }
148- if (run . counter. error > 0 || run . counter. failure > 0 ) {
176+ if (currentRun . counter. error > 0 || currentRun . counter. failure > 0 ) {
149177 progressBar. foreground = RED
150178 } else {
151179 progressBar. foreground = GREEN
@@ -199,6 +227,20 @@ class RunnerPanel implements FocusListener, ActionListener {
199227 } else if (e. source == rerunWorksheetButton) {
200228 val worksheet = new UtplsqlWorksheetRunner (currentRun. pathList, currentRun. connectionName)
201229 worksheet. runTestAsync
230+ } else if (e. source == runComboBox) {
231+ if (currentRun !== null ) {
232+ val comboBoxItem = runComboBox. selectedItem as ComboBoxItem<String , String >
233+ if (currentRun. reporterId != comboBoxItem. key) {
234+ update(comboBoxItem. key)
235+ testDetailTabbedPane. selectedIndex = 0
236+ }
237+ }
238+ } else if (e. source == clearButton) {
239+ val run = currentRun
240+ runs. clear
241+ currentRun = null
242+ setModel(run)
243+ update(run. reporterId)
202244 }
203245 }
204246
@@ -352,8 +394,18 @@ class RunnerPanel implements FocusListener, ActionListener {
352394 rerunWorksheetButton. toolTipText = " Rerun all tests in a new worksheet"
353395 rerunWorksheetButton. addActionListener(this )
354396 toolbar. add(rerunWorksheetButton)
355-
356-
397+ toolbar. add(Box . createHorizontalGlue())
398+ runComboBoxModel = new DefaultComboBoxModel<ComboBoxItem<String , String > > ;
399+ runComboBox = new JComboBox<ComboBoxItem<String , String > > (runComboBoxModel);
400+ runComboBox. editable = false
401+ val comboBoxDim = new Dimension (500 , 50 )
402+ runComboBox. maximumSize = comboBoxDim
403+ runComboBox. addActionListener(this )
404+ toolbar. add(runComboBox)
405+ clearButton = new ToolbarButton (UtplsqlResources . getIcon(" CLEAR_ICON" ))
406+ clearButton. toolTipText = " Clear history"
407+ clearButton. addActionListener(this )
408+ toolbar. add(clearButton)
357409 c. gridx = 0
358410 c. gridy = 0
359411 c. gridwidth = 1
0 commit comments