3b5f5de5a7e4223797785e0eb92265626a7563a9
[divverent/nexuiz.git] / misc / tools / NexuizDemoRecorder / main / src / main / java / com / nexuiz / demorecorder / ui / swinggui / SwingGUI.java
1 package com.nexuiz.demorecorder.ui.swinggui;\r
2 \r
3 import java.awt.Container;\r
4 import java.awt.Dimension;\r
5 import java.awt.Point;\r
6 import java.awt.event.ActionEvent;\r
7 import java.awt.event.ActionListener;\r
8 import java.awt.event.MouseEvent;\r
9 import java.awt.event.MouseListener;\r
10 import java.awt.event.WindowEvent;\r
11 import java.awt.event.WindowListener;\r
12 import java.io.File;\r
13 import java.io.FileInputStream;\r
14 import java.io.FileOutputStream;\r
15 import java.io.IOException;\r
16 import java.io.InputStream;\r
17 import java.io.ObjectInputStream;\r
18 import java.io.ObjectOutputStream;\r
19 import java.net.URL;\r
20 import java.util.ArrayList;\r
21 import java.util.List;\r
22 \r
23 import javax.help.HelpBroker;\r
24 import javax.help.HelpSet;\r
25 import javax.swing.BorderFactory;\r
26 import javax.swing.Icon;\r
27 import javax.swing.ImageIcon;\r
28 import javax.swing.JButton;\r
29 import javax.swing.JFileChooser;\r
30 import javax.swing.JFrame;\r
31 import javax.swing.JMenu;\r
32 import javax.swing.JMenuBar;\r
33 import javax.swing.JMenuItem;\r
34 import javax.swing.JOptionPane;\r
35 import javax.swing.JPanel;\r
36 import javax.swing.JPopupMenu;\r
37 import javax.swing.JScrollPane;\r
38 import javax.swing.JTable;\r
39 import javax.swing.UIManager;\r
40 import javax.swing.border.TitledBorder;\r
41 \r
42 import net.miginfocom.swing.MigLayout;\r
43 \r
44 import org.jdesktop.swingx.JXTable;\r
45 \r
46 import com.nexuiz.demorecorder.application.DemoRecorderApplication;\r
47 import com.nexuiz.demorecorder.application.DemoRecorderUtils;\r
48 import com.nexuiz.demorecorder.application.NDRPreferences;\r
49 import com.nexuiz.demorecorder.application.DemoRecorderApplication.Preferences;\r
50 import com.nexuiz.demorecorder.application.jobs.RecordJob;\r
51 import com.nexuiz.demorecorder.application.jobs.RecordJob.State;\r
52 import com.nexuiz.demorecorder.application.plugins.EncoderPlugin;\r
53 import com.nexuiz.demorecorder.ui.DemoRecorderUI;\r
54 import com.nexuiz.demorecorder.ui.swinggui.tablemodels.RecordJobTemplatesTableModel;\r
55 import com.nexuiz.demorecorder.ui.swinggui.tablemodels.RecordJobsTableModel;\r
56 import com.nexuiz.demorecorder.ui.swinggui.utils.ShowErrorDialogExceptionHandler;\r
57 import com.nexuiz.demorecorder.ui.swinggui.utils.XProperties;\r
58 import com.nexuiz.demorecorder.ui.swinggui.utils.XProperties.XTableState;\r
59 \r
60 public class SwingGUI extends JFrame implements WindowListener, DemoRecorderUI {\r
61         \r
62         private static final long serialVersionUID = -7287303462488231068L;\r
63         public static final String JOB_TABLE_PREFERENCES_FILENAME = "jobsTable.pref";\r
64         public static final String TEMPLATE_TABLE_PREFERENCES_FILENAME = "templatesTable.pref";\r
65         public static final String TEMPLATE_TABLE_CONTENT_FILENAME = "templates.dat";\r
66 \r
67         private DemoRecorderApplication appLayer;\r
68         private PreferencesDialog preferencesDialog;\r
69         \r
70         private JXTable jobsTable = null;\r
71         private JPopupMenu jobsTablePopupMenu;\r
72         private ActionListener jobButtonActionListener = new JobButtonActionListener();\r
73         private MouseListener jobsTableMouseListener = new JobsTableMouseListener();\r
74         \r
75         private JXTable templatesTable = null;\r
76         private JPopupMenu templatesTablePopupMenu;\r
77         private ActionListener templateButtonActionListener = new TemplateButtonActionListener();\r
78         private MouseListener templatesTableMouseListener = new TemplatesTableMouseListener();\r
79         \r
80         private ActionListener recordButtonActionListener = new RecordButtonActionListener();\r
81         \r
82         private static final String LABEL_JOB_CREATE = "Create";\r
83         private static final String LABEL_JOB_CREATE_FROM_TEMPL = "Create from template";\r
84         private static final String LABEL_JOB_DELETE = "Delete";\r
85         private static final String LABEL_JOB_CLEAR = "Clear";\r
86         private static final String LABEL_JOB_EDIT = "Edit job";\r
87         private static final String LABEL_JOB_DUPLICATE = "Duplicate job";\r
88         private static final String LABEL_JOB_START = "Start job";\r
89         private static final String LABEL_JOB_SHOWERROR = "Show error message";\r
90         private static final String LABEL_JOB_RESET_STATE_WAITING = "Reset job status to 'waiting'";\r
91         private static final String LABEL_JOB_RESET_STATE_DONE = "Reset job status to 'done'";\r
92         \r
93         private static final String LABEL_TEMPL_CREATE = "Create";\r
94         private static final String LABEL_TEMPL_CREATE_FROM_JOB = "Create from job";\r
95         private static final String LABEL_TEMPL_DELETE = "Delete";\r
96         private static final String LABEL_TEMPL_CLEAR = "Clear";\r
97         private static final String LABEL_TEMPL_EDIT = "Edit template";\r
98         private static final String LABEL_TEMPL_DUPLICATE = "Duplicate template";\r
99         \r
100         private ActionListener menuButtonActionListener = new MenuButtonActionListener();\r
101         private JMenuItem fileLoadQueue = new JMenuItem("Load job queue", getIcon("fileopen.png"));\r
102         private JMenuItem fileSaveQueue = new JMenuItem("Save job queue", getIcon("filesave.png"));\r
103         private JMenuItem filePreferences = new JMenuItem("Preferences", getIcon("advanced.png"));\r
104         private JMenuItem fileExit = new JMenuItem("Exit", getIcon("exit.png"));\r
105         private JMenuItem helpHelp = new JMenuItem("Show help", getIcon("help.png"));\r
106         private JMenuItem helpAbout = new JMenuItem("About", getIcon("info.png"));\r
107         private JFileChooser jobQueueSaveAsFC = new JFileChooser();\r
108         \r
109         private JButton jobs_create = new JButton(LABEL_JOB_CREATE, getIcon("edit_add.png"));\r
110         private JButton jobs_createFromTempl = new JButton(LABEL_JOB_CREATE_FROM_TEMPL, getIcon("view_right_p.png"));\r
111         private JButton jobs_delete = new JButton(LABEL_JOB_DELETE, getIcon("editdelete.png"));\r
112         private JButton jobs_clear = new JButton(LABEL_JOB_CLEAR, getIcon("editclear.png"));\r
113         private JMenuItem jobs_contextmenu_edit = new JMenuItem(LABEL_JOB_EDIT, getIcon("edit.png"));\r
114         private JMenuItem jobs_contextmenu_duplicate = new JMenuItem(LABEL_JOB_DUPLICATE, getIcon("editcopy.png"));\r
115         private JMenuItem jobs_contextmenu_delete = new JMenuItem(LABEL_JOB_DELETE, getIcon("editdelete.png"));\r
116         private JMenuItem jobs_contextmenu_start = new JMenuItem(LABEL_JOB_START, getIcon("player_play.png"));\r
117         private JMenuItem jobs_contextmenu_showerror = new JMenuItem(LABEL_JOB_SHOWERROR, getIcon("status_unknown.png"));\r
118         private JMenuItem jobs_contextmenu_resetstate_waiting = new JMenuItem(LABEL_JOB_RESET_STATE_WAITING, getIcon("quick_restart.png"));\r
119         private JMenuItem jobs_contextmenu_resetstate_done = new JMenuItem(LABEL_JOB_RESET_STATE_DONE, getIcon("quick_restart_blue.png"));\r
120         private List<JMenuItem> jobs_contextmenu_runPluginMenuItems = new ArrayList<JMenuItem>();\r
121         \r
122         private JButton templ_create = new JButton(LABEL_TEMPL_CREATE, getIcon("edit_add.png"));\r
123         private JButton templ_createFromJob = new JButton(LABEL_TEMPL_CREATE_FROM_JOB, getIcon("view_right_p.png"));\r
124         private JButton templ_delete = new JButton(LABEL_TEMPL_DELETE, getIcon("editdelete.png"));\r
125         private JButton templ_clear = new JButton(LABEL_TEMPL_CLEAR, getIcon("editclear.png"));\r
126         private JMenuItem templ_contextmenu_edit = new JMenuItem(LABEL_TEMPL_EDIT, getIcon("edit.png"));\r
127         private JMenuItem templ_contextmenu_duplicate = new JMenuItem(LABEL_TEMPL_DUPLICATE, getIcon("editcopy.png"));\r
128         private JMenuItem templ_contextmenu_delete = new JMenuItem(LABEL_TEMPL_DELETE, getIcon("editdelete.png"));\r
129         \r
130         private static final String PROCESSING_START = "Start processing";\r
131         private static final String PROCESSING_STOP_NOW = "Stop processing";\r
132         private static final String PROCESSING_STOP_LATER = "Processing will stop after current job finished";\r
133         private JButton processing_start = new JButton(PROCESSING_START, getIcon("player_play.png"));\r
134         private JButton processing_stop = new JButton(PROCESSING_STOP_NOW, getIcon("player_pause.png"));\r
135         \r
136         private StatusBar statusBar = new StatusBar();\r
137         \r
138         private static HelpBroker mainHelpBroker = null;\r
139         private static final String mainHelpSetName = "help/DemoRecorderHelp.hs";\r
140 \r
141         public SwingGUI(DemoRecorderApplication appLayer) {\r
142                 super("Nexuiz Demo Recorder v0.2");\r
143                 addWindowListener(this);\r
144 \r
145                 this.appLayer = appLayer;\r
146 \r
147                 this.setupLayout();\r
148                 this.setupHelp();\r
149                 this.preferencesDialog = new PreferencesDialog(this, appLayer);\r
150 \r
151                 setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);\r
152                 // Display the window.\r
153                 pack();\r
154                 setVisible(true);\r
155                 //now that we have the GUI we can set the parent window for the error dialog\r
156                 ShowErrorDialogExceptionHandler.setParentWindow(this);\r
157         }\r
158 \r
159         private void setupHelp() {\r
160                 if (mainHelpBroker == null){\r
161                         HelpSet mainHelpSet = null;\r
162 \r
163                         try {\r
164                                 URL hsURL = HelpSet.findHelpSet(null, mainHelpSetName);\r
165                                 mainHelpSet = new HelpSet(null, hsURL);\r
166                         } catch (Exception e) {\r
167                                 DemoRecorderUtils.showNonCriticalErrorDialog("Could not properly create the help", e, true);\r
168                         }\r
169 \r
170                         if (mainHelpSet != null)\r
171                                 mainHelpBroker = mainHelpSet.createHelpBroker();\r
172                         }\r
173         }\r
174 \r
175         private void setupLayout() {\r
176                 setLayout(new MigLayout("wrap 1,insets 10", "[400:700:,grow,fill]",\r
177                                 "[grow,fill][grow,fill][][]"));\r
178                 Container contentPane = getContentPane();\r
179                 setJMenuBar(this.buildMenu());\r
180 \r
181                 this.setupTemplatePanel();\r
182                 this.setupJobPanel();\r
183                 this.setupRecordPanel();\r
184 \r
185                 contentPane.add(statusBar, "south,height 23::");\r
186         }\r
187 \r
188         private void setupTemplatePanel() {\r
189                 JPanel templatePanel = new JPanel(new MigLayout("", "[500:500:,grow,fill][170!,fill,grow]", "[grow,fill]"));\r
190                 TitledBorder templatePanelTitle = BorderFactory.createTitledBorder("Templates");\r
191                 templatePanel.setBorder(templatePanelTitle);\r
192                 getContentPane().add(templatePanel);\r
193                 \r
194                 this.setupTemplatesTable();\r
195                 this.loadTableStates(this.templatesTable);\r
196                 JScrollPane templateScrollPane = new JScrollPane(templatesTable);\r
197                 templatePanel.add(templateScrollPane);\r
198                 \r
199                 this.templ_create.addActionListener(this.templateButtonActionListener);\r
200                 this.templ_createFromJob.addActionListener(this.templateButtonActionListener);\r
201                 this.templ_delete.addActionListener(this.templateButtonActionListener);\r
202                 this.templ_clear.addActionListener(this.templateButtonActionListener);\r
203                 \r
204                 this.templ_contextmenu_edit.addActionListener(this.templateButtonActionListener);\r
205                 this.templ_contextmenu_duplicate.addActionListener(this.templateButtonActionListener);\r
206                 this.templ_contextmenu_delete.addActionListener(this.templateButtonActionListener);\r
207                 \r
208                 this.configureTableButtons();\r
209                 \r
210                 JPanel templateControlButtonPanel = new JPanel(new MigLayout("wrap 1", "fill,grow"));\r
211                 templateControlButtonPanel.add(this.templ_create);\r
212                 templateControlButtonPanel.add(this.templ_createFromJob);\r
213                 templateControlButtonPanel.add(this.templ_delete);\r
214                 templateControlButtonPanel.add(this.templ_clear);\r
215                 templatePanel.add(templateControlButtonPanel);\r
216         }\r
217 \r
218         private void setupJobPanel() {\r
219                 JPanel jobPanel = new JPanel(new MigLayout("", "[500:500:,grow,fill][170!,fill,grow]", "[grow,fill]"));\r
220                 TitledBorder jobPanelTitle = BorderFactory.createTitledBorder("Jobs");\r
221                 jobPanel.setBorder(jobPanelTitle);\r
222                 getContentPane().add(jobPanel);\r
223 \r
224                 this.setupJobsTable();\r
225                 this.loadTableStates(this.jobsTable);\r
226                 \r
227                 JScrollPane jobScrollPane = new JScrollPane(jobsTable);\r
228                 jobPanel.add(jobScrollPane);\r
229                 \r
230                 this.jobs_create.addActionListener(this.jobButtonActionListener);\r
231                 this.jobs_createFromTempl.addActionListener(this.jobButtonActionListener);\r
232                 this.jobs_delete.addActionListener(this.jobButtonActionListener);\r
233                 this.jobs_clear.addActionListener(this.jobButtonActionListener);\r
234                 \r
235                 this.jobs_contextmenu_edit.addActionListener(this.jobButtonActionListener);\r
236                 this.jobs_contextmenu_duplicate.addActionListener(this.jobButtonActionListener);\r
237                 this.jobs_contextmenu_delete.addActionListener(this.jobButtonActionListener);\r
238                 this.jobs_contextmenu_start.addActionListener(this.jobButtonActionListener);\r
239                 this.jobs_contextmenu_showerror.addActionListener(this.jobButtonActionListener);\r
240                 this.jobs_contextmenu_resetstate_waiting.addActionListener(this.jobButtonActionListener);\r
241                 this.jobs_contextmenu_resetstate_done.addActionListener(this.jobButtonActionListener);\r
242                 \r
243                 //initialize button states\r
244                 configureTableButtons();\r
245                 \r
246                 JPanel jobControlButtonPanel = new JPanel(new MigLayout("wrap 1", "fill,grow"));\r
247                 jobControlButtonPanel.add(this.jobs_create);\r
248                 jobControlButtonPanel.add(this.jobs_createFromTempl);\r
249                 jobControlButtonPanel.add(this.jobs_delete);\r
250                 jobControlButtonPanel.add(this.jobs_clear);\r
251                 jobPanel.add(jobControlButtonPanel);\r
252         }\r
253         \r
254         private void setupJobsTable() {\r
255                 RecordJobsTableModel tableModel = new RecordJobsTableModel(this.appLayer);\r
256                 jobsTable = new JXTable(tableModel);\r
257                 jobsTable.setColumnControlVisible(true);\r
258                 jobsTable.setPreferredScrollableViewportSize(new Dimension(400, 100));\r
259                 jobsTable.addMouseListener(this.jobsTableMouseListener);\r
260         }\r
261         \r
262         private void setupTemplatesTable() {\r
263                 RecordJobTemplatesTableModel tableModel = new RecordJobTemplatesTableModel();\r
264                 templatesTable = new JXTable(tableModel);\r
265                 templatesTable.setColumnControlVisible(true);\r
266                 templatesTable.setPreferredScrollableViewportSize(new Dimension(400, 100));\r
267                 templatesTable.addMouseListener(this.templatesTableMouseListener);\r
268         }\r
269 \r
270         private void setupRecordPanel() {\r
271                 JPanel recButtonPanel = new JPanel(new MigLayout());\r
272                 recButtonPanel.add(processing_start);\r
273                 recButtonPanel.add(processing_stop);\r
274                 processing_stop.setEnabled(false);\r
275                 processing_start.addActionListener(recordButtonActionListener);\r
276                 processing_stop.addActionListener(recordButtonActionListener);\r
277                 getContentPane().add(recButtonPanel);\r
278         }\r
279 \r
280         public static void setSystemLAF() {\r
281                 try {\r
282                         // Set System L&F\r
283                         UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());\r
284                 } catch (Exception e) {\r
285                 }\r
286         }\r
287         \r
288         public void RecordJobPropertiesChange(RecordJob job) {\r
289                 RecordJobsTableModel jobsTableModel = (RecordJobsTableModel) this.jobsTable.getModel();\r
290                 List<RecordJob> recordJobs = jobsTableModel.getRecordJobs();\r
291                 int jobIndex = recordJobs.indexOf(job);\r
292                 if (jobIndex == -1) {\r
293                         //new job\r
294                         recordJobs.add(job);\r
295                         //add job at the end of the table:\r
296                         int position = jobsTableModel.getRowCount() - 1;\r
297                         jobsTableModel.fireTableRowsInserted(position, position);\r
298                 } else {\r
299                         //job already existed\r
300                         jobIndex = this.jobsTable.convertRowIndexToView(jobIndex); //convert due to possible view sorting\r
301                         jobsTableModel.fireTableRowsUpdated(jobIndex, jobIndex);\r
302                 }\r
303         }\r
304 \r
305         public void recordingFinished() {\r
306                 JOptionPane.showMessageDialog(SwingGUI.this, "Finished recording all jobs", "Recording done", JOptionPane.INFORMATION_MESSAGE);\r
307                 statusBar.showState(false);\r
308                 processing_start.setEnabled(true);\r
309                 processing_stop.setEnabled(false);\r
310                 processing_stop.setText(PROCESSING_STOP_NOW);\r
311         }\r
312 \r
313         private JMenuBar buildMenu() {\r
314                 JMenuBar menuBar = new JMenuBar();\r
315 \r
316                 JMenu fileMenu = new JMenu("File");\r
317                 fileMenu.add(fileLoadQueue);\r
318                 fileMenu.add(fileSaveQueue);\r
319                 fileMenu.add(filePreferences);\r
320                 fileMenu.add(fileExit);\r
321                 menuBar.add(fileMenu);\r
322                 \r
323                 fileLoadQueue.addActionListener(menuButtonActionListener);\r
324                 fileSaveQueue.addActionListener(menuButtonActionListener);\r
325                 filePreferences.addActionListener(menuButtonActionListener);\r
326                 fileExit.addActionListener(menuButtonActionListener);\r
327 \r
328                 JMenu helpMenu = new JMenu("Help");\r
329                 helpMenu.add(helpHelp);\r
330                 helpMenu.add(helpAbout);\r
331                 menuBar.add(helpMenu);\r
332                 \r
333                 helpHelp.addActionListener(menuButtonActionListener);\r
334                 helpAbout.addActionListener(menuButtonActionListener);\r
335                 \r
336                 this.setupEncoderPluginButtons();\r
337                 \r
338                 this.jobsTablePopupMenu = new JPopupMenu();\r
339                 this.jobsTablePopupMenu.add(jobs_contextmenu_edit);\r
340                 this.jobsTablePopupMenu.add(jobs_contextmenu_duplicate);\r
341                 this.jobsTablePopupMenu.add(jobs_contextmenu_delete);\r
342                 this.jobsTablePopupMenu.add(jobs_contextmenu_start);\r
343                 //add JMenus for plugins\r
344                 for (JMenuItem menuItem : jobs_contextmenu_runPluginMenuItems) {\r
345                         this.jobsTablePopupMenu.add(menuItem);\r
346                 }\r
347                 this.jobsTablePopupMenu.add(jobs_contextmenu_showerror);\r
348                 this.jobsTablePopupMenu.add(jobs_contextmenu_resetstate_waiting);\r
349                 this.jobsTablePopupMenu.add(jobs_contextmenu_resetstate_done);\r
350                 \r
351                 \r
352                 \r
353                 \r
354                 this.templatesTablePopupMenu = new JPopupMenu();\r
355                 this.templatesTablePopupMenu.add(templ_contextmenu_edit);\r
356                 this.templatesTablePopupMenu.add(templ_contextmenu_duplicate);\r
357                 this.templatesTablePopupMenu.add(templ_contextmenu_delete);\r
358 \r
359                 return menuBar;\r
360         }\r
361         \r
362         private void setupEncoderPluginButtons() {\r
363                 for (EncoderPlugin plugin : appLayer.getEncoderPlugins()) {\r
364                         JMenuItem pluginMenuItem = new JMenuItem("Just run " + plugin.getName() + " plugin", getIcon("package.png"));\r
365                         pluginMenuItem.addActionListener(jobButtonActionListener);\r
366                         this.jobs_contextmenu_runPluginMenuItems.add(pluginMenuItem);\r
367                 }\r
368         }\r
369 \r
370         private void saveTableStates(JXTable table) {\r
371                 String fileName;\r
372                 if (table == jobsTable) {\r
373                         fileName = JOB_TABLE_PREFERENCES_FILENAME;\r
374                 } else {\r
375                         fileName = TEMPLATE_TABLE_PREFERENCES_FILENAME;\r
376                 }\r
377                 String exceptionMessage = "An error occurred while trying to save the table state file " + fileName;\r
378                 \r
379                 XProperties.XTableProperty t = new XProperties.XTableProperty();\r
380                 XTableState tableState;\r
381                 try {\r
382                         tableState = (XTableState) t.getSessionState(table);\r
383                 } catch (Exception e) { //most likely ClassCastException\r
384                         DemoRecorderUtils.showNonCriticalErrorDialog(exceptionMessage, e, true);\r
385                         return;\r
386                 }\r
387                 \r
388                 File tableStateFile = DemoRecorderUtils.computeLocalFile(DemoRecorderApplication.PREFERENCES_DIRNAME, fileName);\r
389                 DemoRecorderUtils.attemptFileCreation(tableStateFile);\r
390                 \r
391                 try {\r
392                         FileOutputStream fout = new FileOutputStream(tableStateFile);\r
393                         ObjectOutputStream oos = new ObjectOutputStream(fout);\r
394                         oos.writeObject(tableState);\r
395                         oos.close();\r
396                 } catch (Exception e) {\r
397                         DemoRecorderUtils.showNonCriticalErrorDialog(exceptionMessage, e, true);\r
398                 }\r
399         }\r
400         \r
401         private void loadTableStates(JXTable table) {\r
402                 String fileName;\r
403                 if (table == jobsTable) {\r
404                         fileName = JOB_TABLE_PREFERENCES_FILENAME;\r
405                 } else {\r
406                         fileName = TEMPLATE_TABLE_PREFERENCES_FILENAME;\r
407                 }\r
408                 \r
409                 XProperties.XTableProperty t = new XProperties.XTableProperty();\r
410                 \r
411                 File tableStateFile = DemoRecorderUtils.computeLocalFile(DemoRecorderApplication.PREFERENCES_DIRNAME, fileName);\r
412                 \r
413                 XTableState tableState;\r
414                 \r
415                 try {\r
416                         FileInputStream fin = new FileInputStream(tableStateFile);\r
417                         ObjectInputStream ois = new ObjectInputStream(fin);\r
418                         tableState = (XTableState) ois.readObject();\r
419                         t.setSessionState(table, tableState);\r
420                 } catch (Exception e) {\r
421                          //manually hide columns\r
422                         if (table == jobsTable) {\r
423                                 //re-create table to be sure\r
424                                 this.setupJobsTable();\r
425                                 //manually hide some columns\r
426                                 jobsTable.getColumnExt(RecordJobsTableModel.EXECUTE_AFTER_CAP).setVisible(false);\r
427                                 jobsTable.getColumnExt(RecordJobsTableModel.EXECUTE_BEFORE_CAP).setVisible(false);\r
428                                 jobsTable.getColumnExt(RecordJobsTableModel.VIDEO_DESTINATION_PATH).setVisible(false);\r
429                                 jobsTable.getColumnExt(RecordJobsTableModel.DPVIDEO_PATH).setVisible(false);\r
430                                 jobsTable.getColumnExt(RecordJobsTableModel.RELATIVE_DEMO_PATH).setVisible(false);\r
431                                 jobsTable.getColumnExt(RecordJobsTableModel.ENGINE_PARAMETERS).setVisible(false);\r
432                                 jobsTable.getColumnExt(RecordJobsTableModel.ENGINE_PATH).setVisible(false);\r
433                         } else {\r
434                                 //re-create table to be sure\r
435                                 this.setupTemplatesTable();\r
436                                 //manually hide some columns\r
437                                 templatesTable.getColumnExt(RecordJobTemplatesTableModel.EXECUTE_AFTER_CAP).setVisible(false);\r
438                                 templatesTable.getColumnExt(RecordJobTemplatesTableModel.EXECUTE_BEFORE_CAP).setVisible(false);\r
439                                 templatesTable.getColumnExt(RecordJobTemplatesTableModel.VIDEO_DESTINATION_PATH).setVisible(false);\r
440                                 templatesTable.getColumnExt(RecordJobTemplatesTableModel.DPVIDEO_PATH).setVisible(false);\r
441                                 templatesTable.getColumnExt(RecordJobTemplatesTableModel.RELATIVE_DEMO_PATH).setVisible(false);\r
442                                 templatesTable.getColumnExt(RecordJobTemplatesTableModel.DEMO_FILE_PATH).setVisible(false);\r
443                                 templatesTable.getColumnExt(RecordJobTemplatesTableModel.ENGINE_PARAMETERS).setVisible(false);\r
444                                 templatesTable.getColumnExt(RecordJobTemplatesTableModel.ENGINE_PATH).setVisible(false);\r
445                                 templatesTable.getColumnExt(RecordJobTemplatesTableModel.JOB_NAME).setVisible(false);\r
446                         }\r
447                 }\r
448         }\r
449         \r
450         private class MenuButtonActionListener implements ActionListener {\r
451 \r
452                 public void actionPerformed(ActionEvent e) {\r
453                         if (e.getSource() == fileLoadQueue) {\r
454                                 int result = jobQueueSaveAsFC.showOpenDialog(SwingGUI.this);\r
455                                 if (result == JFileChooser.APPROVE_OPTION) {\r
456                                         File selectedFile = jobQueueSaveAsFC.getSelectedFile();\r
457                                         if (selectedFile.isFile()) {\r
458                                                 RecordJobsTableModel tableModel = (RecordJobsTableModel) jobsTable.getModel();\r
459                                                 tableModel.loadNewJobQueue(selectedFile);\r
460                                                 configureTableButtons();\r
461                                         }\r
462                                 }\r
463                                 \r
464                         } else if (e.getSource() == fileSaveQueue) {\r
465                                 int result = jobQueueSaveAsFC.showSaveDialog(SwingGUI.this);\r
466                                 if (result == JFileChooser.APPROVE_OPTION) {\r
467                                         File selectedFile = jobQueueSaveAsFC.getSelectedFile();\r
468                                         if (!DemoRecorderUtils.getFileExtension(selectedFile).equals("queue")) {\r
469                                                 //if file is not a .queue file, make it one\r
470                                                 selectedFile = new File(selectedFile.getAbsoluteFile() + ".queue");\r
471                                         }\r
472                                         if (selectedFile.exists()) {\r
473                                                 int confirm = JOptionPane.showConfirmDialog(SwingGUI.this, "File already exists. Are you sure you want to overwrite it?", "Confirm overwrite", JOptionPane.YES_NO_OPTION);\r
474                                                 if (confirm == JOptionPane.NO_OPTION) {\r
475                                                         return;\r
476                                                 }\r
477                                         }\r
478                                         appLayer.saveJobQueue(selectedFile);\r
479                                 }\r
480                         } else if (e.getSource() == filePreferences) {\r
481                                 preferencesDialog.showDialog();\r
482                         } else if (e.getSource() == fileExit) {\r
483                                 shutDown();\r
484                         } else if (e.getSource() == helpHelp) {\r
485                                 if (mainHelpBroker != null) {\r
486                                         mainHelpBroker.setDisplayed(true);\r
487                                 }\r
488                         } else if (e.getSource() == helpAbout) {\r
489                                 showAboutBox();\r
490                         }\r
491                 }\r
492                 \r
493         }\r
494 \r
495         /**\r
496          * Listens to the clicks on buttons that are in the job panel (next to the jobs table)\r
497          * or its context menu.\r
498          */\r
499         private class JobButtonActionListener implements ActionListener {\r
500 \r
501                 public void actionPerformed(ActionEvent e) {\r
502                         List<RecordJob> selectedJobs = getSelectedRecordJobs(jobsTable);\r
503                         List<RecordJob> selectedTemplates = getSelectedRecordJobs(templatesTable);\r
504                         if (e.getSource() == jobs_create) {\r
505                                 JobDialog jobDialog = new JobDialog(SwingGUI.this, appLayer);\r
506                                 jobDialog.showDialog();\r
507                                 configureTableButtons();\r
508                         }\r
509                         else if (e.getSource() == jobs_createFromTempl) {\r
510                                 if (selectedTemplates.size() != 1) {\r
511                                         return;\r
512                                 }\r
513                                 RecordJobTemplate template = (RecordJobTemplate) selectedTemplates.get(0);\r
514 //                              JobDialog jobDialog = new JobDialog(SwingGUI.this, template, appLayer);\r
515                                 JobDialog jobDialog = new JobDialog(SwingGUI.this, template, appLayer, JobDialog.CREATE_JOB_FROM_TEMPLATE);\r
516                                 jobDialog.showDialog();\r
517                                 configureTableButtons();\r
518                         }\r
519                         else if (e.getSource() == jobs_delete || e.getSource() == jobs_contextmenu_delete) {\r
520                                 int result = JOptionPane.showConfirmDialog(SwingGUI.this, "Are you sure you want to delete the selected job(s)?", "Confirm delete", JOptionPane.YES_NO_OPTION);\r
521                                 if (result == JOptionPane.YES_OPTION) {\r
522                                         deleteSelectedJobs(false);\r
523                                         configureTableButtons();\r
524                                 }\r
525                         }\r
526                         else if (e.getSource() == jobs_clear) {\r
527                                 int result = JOptionPane.showConfirmDialog(SwingGUI.this, "Are you sure you want to clear the job list?", "Confirm clear", JOptionPane.YES_NO_OPTION);\r
528                                 if (result == JOptionPane.YES_OPTION) {\r
529                                         deleteSelectedJobs(true);\r
530                                         configureTableButtons();\r
531                                 }\r
532                         } else if (e.getSource() == jobs_contextmenu_edit) {\r
533                                 if (selectedJobs.size() == 1) {\r
534                                         RecordJob selectedJob = selectedJobs.get(0);\r
535                                         JobDialog jobDialog = new JobDialog(SwingGUI.this, selectedJob, appLayer);\r
536                                         jobDialog.showDialog();\r
537                                         configureTableButtons();\r
538                                 }\r
539                         } else if (e.getSource() == jobs_contextmenu_showerror) {\r
540                                 if (selectedJobs.size() == 1) {\r
541                                         RecordJob selectedJob = selectedJobs.get(0);\r
542                                         DemoRecorderUtils.showNonCriticalErrorDialog(selectedJob.getLastException());\r
543                                 }\r
544                         } else if (e.getSource() == jobs_contextmenu_resetstate_waiting) {\r
545                                 for (RecordJob job : selectedJobs) {\r
546                                         job.setState(RecordJob.State.WAITING);\r
547                                 }\r
548                         } else if (e.getSource() == jobs_contextmenu_resetstate_done) {\r
549                                 for (RecordJob job : selectedJobs) {\r
550                                         if (job.getState() == State.ERROR_PLUGIN) {\r
551                                                 job.setState(RecordJob.State.DONE);\r
552                                         }\r
553                                 }\r
554                         } else if (e.getSource() == jobs_contextmenu_start) {\r
555                                 appLayer.recordSelectedJobs(selectedJobs);\r
556                                 if (appLayer.getState() == DemoRecorderApplication.STATE_WORKING) {\r
557                                         processing_start.setEnabled(false);\r
558                                         processing_stop.setEnabled(true);\r
559                                         statusBar.showState(true);\r
560                                 }\r
561                         } else if (e.getSource() == jobs_contextmenu_duplicate) {\r
562                                 if (selectedJobs.size() > 0) {\r
563                                         this.duplicateRecordJobs(selectedJobs);\r
564                                         //select all new duplicates in the table automatically\r
565                                         jobsTable.setRowSelectionInterval(jobsTable.getRowCount() - selectedJobs.size(), jobsTable.getRowCount() - 1);\r
566                                         configureTableButtons();\r
567                                 }\r
568                         } else if (jobs_contextmenu_runPluginMenuItems.contains(e.getSource())) {\r
569                                 int index = jobs_contextmenu_runPluginMenuItems.indexOf(e.getSource());\r
570                                 EncoderPlugin selectedPlugin = appLayer.getEncoderPlugins().get(index);\r
571                                 \r
572                                 appLayer.executePluginForSelectedJobs(selectedPlugin, selectedJobs);\r
573                                 if (appLayer.getState() == DemoRecorderApplication.STATE_WORKING) {\r
574                                         processing_start.setEnabled(false);\r
575                                         processing_stop.setEnabled(true);\r
576                                         statusBar.showState(true);\r
577                                 }\r
578                         }\r
579                 }\r
580                 \r
581                 private void duplicateRecordJobs(List<RecordJob> jobs) {\r
582                         String nameSuffix = appLayer.getPreferences().getProperty(NDRPreferences.MAIN_APPLICATION, Preferences.JOB_NAME_APPEND_DUPLICATE);\r
583                         for (RecordJob job : jobs) {\r
584                                 RecordJob newJob = appLayer.createRecordJob(\r
585                                         job.getJobName() + nameSuffix,\r
586                                         job.getEnginePath(),\r
587                                         job.getEngineParameters(),\r
588                                         job.getDemoFile(),\r
589                                         job.getRelativeDemoPath(),\r
590                                         job.getDpVideoPath(),\r
591                                         job.getVideoDestination(),\r
592                                         job.getExecuteBeforeCap(),\r
593                                         job.getExecuteAfterCap(),\r
594                                         job.getStartSecond(),\r
595                                         job.getEndSecond()\r
596                                 );\r
597                                 newJob.setEncoderPluginSettings(job.getEncoderPluginSettings());\r
598                         }\r
599                 }\r
600                 \r
601         }\r
602         \r
603         private class TemplateButtonActionListener implements ActionListener {\r
604                 public void actionPerformed(ActionEvent e) {\r
605                         if (e.getSource() == templ_create) {\r
606                                 RecordJobTemplatesTableModel tableModel = (RecordJobTemplatesTableModel) templatesTable.getModel();\r
607                                 JobDialog jobDialog = new JobDialog(SwingGUI.this, tableModel, templatesTable, appLayer);\r
608                                 jobDialog.showDialog();\r
609                                 configureTableButtons();\r
610                         }\r
611                         else if (e.getSource() == templ_createFromJob) {\r
612                                 this.createTemplateFromJob();\r
613                                 configureTableButtons();\r
614                         }\r
615                         else if (e.getSource() == templ_delete || e.getSource() == templ_contextmenu_delete) {\r
616                                 int result = JOptionPane.showConfirmDialog(SwingGUI.this, "Are you sure you want to delete the selected template(s)?", "Confirm delete", JOptionPane.YES_NO_OPTION);\r
617                                 if (result == JOptionPane.YES_OPTION) {\r
618                                         deleteSelectedTemplates(false);\r
619                                 }\r
620                                 configureTableButtons();\r
621                         }\r
622                         else if (e.getSource() == templ_clear) {\r
623                                 int result = JOptionPane.showConfirmDialog(SwingGUI.this, "Are you sure you want to clear the template list?", "Confirm clear", JOptionPane.YES_NO_OPTION);\r
624                                 if (result == JOptionPane.YES_OPTION) {\r
625                                         deleteSelectedTemplates(true);\r
626                                 }\r
627                                 configureTableButtons();\r
628                         }\r
629                         else if (e.getSource() == templ_contextmenu_edit) {\r
630                                 List<RecordJob> selectedTemplates = getSelectedRecordJobs(templatesTable);\r
631                                 if (selectedTemplates.size() == 1) {\r
632                                         RecordJobTemplate selectedTemplate = (RecordJobTemplate) selectedTemplates.get(0);\r
633                                         JobDialog jobDialog = new JobDialog(SwingGUI.this, selectedTemplate, appLayer, JobDialog.EDIT_TEMPLATE);\r
634                                         jobDialog.showDialog();\r
635                                         configureTableButtons();\r
636                                 }\r
637                         }\r
638                         else if (e.getSource() == templ_contextmenu_duplicate) {\r
639                                 List<RecordJob> selectedTemplates = getSelectedRecordJobs(templatesTable);\r
640                                 if (selectedTemplates.size() > 0) {\r
641                                         this.duplicateTemplates(selectedTemplates);\r
642                                         //select all new duplicates in the table automatically\r
643                                         templatesTable.setRowSelectionInterval(templatesTable.getRowCount() - selectedTemplates.size(), templatesTable.getRowCount() - 1);\r
644                                         configureTableButtons();\r
645                                 }\r
646                         }\r
647                 }\r
648                 \r
649                 private void createTemplateFromJob() {\r
650                         List<RecordJob> selectedJobs = getSelectedRecordJobs(jobsTable);\r
651                         if (selectedJobs.size() == 1) {\r
652                                 RecordJob job = selectedJobs.get(0);\r
653                                 RecordJobTemplate templ = new RecordJobTemplate(\r
654                                         "Generated from job",\r
655                                         "Generated from job",\r
656                                         job.getJobName(),\r
657                                         job.getEnginePath(),\r
658                                         job.getEngineParameters(),\r
659                                         job.getDemoFile().getParentFile(),\r
660                                         job.getRelativeDemoPath(),\r
661                                         job.getDpVideoPath(),\r
662                                         job.getVideoDestination().getParentFile(),\r
663                                         job.getExecuteBeforeCap(),\r
664                                         job.getExecuteAfterCap()\r
665                                 );\r
666                                 templ.setEncoderPluginSettings(job.getEncoderPluginSettings());\r
667                                 \r
668                                 RecordJobTemplatesTableModel tableModel = (RecordJobTemplatesTableModel) templatesTable.getModel();\r
669                                 tableModel.addRecordJobTemplate(templ);\r
670                         }\r
671                 }\r
672                 \r
673                 private void duplicateTemplates(List<RecordJob> selectedTemplates) {\r
674                         for (RecordJob job : selectedTemplates) {\r
675                                 RecordJobTemplate template = (RecordJobTemplate) job;\r
676                                 RecordJobTemplate templ = new RecordJobTemplate(\r
677                                         template.getName(),\r
678                                         template.getSummary(),\r
679                                         template.getJobName(),\r
680                                         template.getEnginePath(),\r
681                                         template.getEngineParameters(),\r
682                                         template.getDemoFile(),\r
683                                         template.getRelativeDemoPath(),\r
684                                         template.getDpVideoPath(),\r
685                                         template.getVideoDestination(),\r
686                                         template.getExecuteBeforeCap(),\r
687                                         template.getExecuteAfterCap()\r
688                                 );\r
689                                 templ.setEncoderPluginSettings(template.getEncoderPluginSettings());\r
690                                 \r
691                                 RecordJobTemplatesTableModel tableModel = (RecordJobTemplatesTableModel) templatesTable.getModel();\r
692                                 tableModel.addRecordJobTemplate(templ);\r
693                         }\r
694                 }\r
695         }\r
696         \r
697         private class RecordButtonActionListener implements ActionListener {\r
698 \r
699                 public void actionPerformed(ActionEvent e) {\r
700                         if (e.getSource() == processing_start) {\r
701                                 appLayer.startRecording();\r
702                                 if (appLayer.getState() == DemoRecorderApplication.STATE_WORKING) {\r
703                                         processing_start.setEnabled(false);\r
704                                         processing_stop.setEnabled(true);\r
705                                         statusBar.showState(true);\r
706                                 }\r
707                         } else if (e.getSource() == processing_stop) {\r
708                                 if (appLayer.getState() == DemoRecorderApplication.STATE_WORKING) {\r
709                                         appLayer.stopRecording();\r
710                                         processing_stop.setEnabled(false);\r
711                                         processing_stop.setText(PROCESSING_STOP_LATER);\r
712                                 }\r
713                         }\r
714                 }\r
715         }\r
716         \r
717         private void deleteSelectedJobs(boolean deleteAllJobs) {\r
718                 RecordJobsTableModel tableModel = (RecordJobsTableModel) jobsTable.getModel();\r
719                 if (deleteAllJobs) {\r
720                         int rowCount = jobsTable.getRowCount();\r
721                         for (int i = rowCount - 1; i >= 0; i--) {\r
722                                 int modelRowIndex = jobsTable.convertRowIndexToModel(i);\r
723                                 tableModel.deleteRecordJob(modelRowIndex, i);\r
724                         }\r
725                 } else {\r
726                         int[] selectedRows = jobsTable.getSelectedRows();\r
727                         for (int i = selectedRows.length - 1; i >= 0; i--) {\r
728                                 int modelRowIndex = jobsTable.convertRowIndexToModel(selectedRows[i]);\r
729                                 tableModel.deleteRecordJob(modelRowIndex, selectedRows[i]);\r
730                         }\r
731                 }\r
732         }\r
733         \r
734         private void deleteSelectedTemplates(boolean deleteAllTemplates) {\r
735                 RecordJobTemplatesTableModel tableModel = (RecordJobTemplatesTableModel) templatesTable.getModel();\r
736                 if (deleteAllTemplates) {\r
737                         int rowCount = templatesTable.getRowCount();\r
738                         for (int i = rowCount - 1; i >= 0; i--) {\r
739                                 int modelRowIndex = templatesTable.convertRowIndexToModel(i);\r
740                                 tableModel.deleteRecordJobTemplate(modelRowIndex, i);\r
741                         }\r
742                 } else {\r
743                         int[] selectedRows = templatesTable.getSelectedRows();\r
744                         for (int i = selectedRows.length - 1; i >= 0; i--) {\r
745                                 int modelRowIndex = templatesTable.convertRowIndexToModel(selectedRows[i]);\r
746                                 tableModel.deleteRecordJobTemplate(modelRowIndex, selectedRows[i]);\r
747                         }\r
748                 }\r
749                 //update the button state of buttons dealing with jobs\r
750                 this.configureTableButtons();\r
751         }\r
752         \r
753         /**\r
754          * Iterates through all RecordJob objects (or just the selected ones) and returns true\r
755          * if at least one of them has one or more has the given state(s).\r
756          * @param state\r
757          * @param justSelectedJobs\r
758          * @return\r
759          */\r
760         private boolean checkJobStates(RecordJob.State[] state, boolean justSelectedJobs) {\r
761                 boolean foundState = false;\r
762                 List<RecordJob> jobsToLookAt = null;\r
763                 if (!justSelectedJobs) {\r
764                         jobsToLookAt = this.appLayer.getRecordJobs();\r
765                 } else {\r
766                         jobsToLookAt = getSelectedRecordJobs(jobsTable);\r
767                 }\r
768                 \r
769                 for (RecordJob currentJob : jobsToLookAt) {\r
770                         for (int i = 0; i < state.length; i++) {\r
771                                 if (currentJob.getState() == state[i]) {\r
772                                         foundState = true;\r
773                                         break;\r
774                                 }\r
775                         }\r
776                 }\r
777                 return foundState;\r
778         }\r
779         \r
780         /**\r
781          * Returns the list of selected RecordJobs or RecordJobTemplates.\r
782          * @param table jobsTable or templatesTable\r
783          * @return list of selected RecordJobs or RecordJobTemplates\r
784          */\r
785         private List<RecordJob> getSelectedRecordJobs(JXTable table) {\r
786                 List<RecordJob> list = new ArrayList<RecordJob>();\r
787                 if (table.getSelectedRowCount() > 0) {\r
788                         int[] selectedRows = table.getSelectedRows();\r
789                         for (int i = 0; i < selectedRows.length; i++) {\r
790                                 int modelRowIndex = table.convertRowIndexToModel(selectedRows[i]);\r
791                                 if (table == jobsTable) {\r
792                                         RecordJobsTableModel tableModel = (RecordJobsTableModel) table.getModel();\r
793                                         RecordJob job = tableModel.getRecordJob(modelRowIndex);\r
794                                         if (job != null) {\r
795                                                 list.add(job);\r
796                                         }\r
797                                 } else {\r
798                                         RecordJobTemplatesTableModel tableModel = (RecordJobTemplatesTableModel) table.getModel();\r
799                                         RecordJobTemplate template = tableModel.getRecordJobTemplate(modelRowIndex);\r
800                                         if (template != null) {\r
801                                                 list.add(template);\r
802                                         }\r
803                                 }\r
804                         }\r
805                 }\r
806                 \r
807                 return list;\r
808         }\r
809         \r
810         private void configureTableButtons() {\r
811                 if (jobsTable != null) {\r
812                         if (jobsTable.getRowCount() == 0) {\r
813                                 jobs_clear.setEnabled(false);\r
814                                 jobs_delete.setEnabled(false);\r
815                         } else {\r
816                                 jobs_clear.setEnabled(true);\r
817                                 jobs_delete.setEnabled(true);\r
818                                 if (jobsTable.getSelectedRowCount() == 0) {\r
819                                         jobs_delete.setEnabled(false);\r
820                                 } else {\r
821                                         //go through all elements and check for attributes PROCESSING\r
822                                         RecordJob.State[] lookForState = {RecordJob.State.PROCESSING};\r
823                                         boolean foundState = checkJobStates(lookForState, false);\r
824                                         if (foundState) {\r
825                                                 //we have to disable the clear and delete button\r
826                                                 jobs_delete.setEnabled(false);\r
827                                         }\r
828                                 }\r
829                         }\r
830                         if (templatesTable.getSelectedRowCount() == 1) {\r
831                                 jobs_createFromTempl.setEnabled(true);\r
832                         } else {\r
833                                 jobs_createFromTempl.setEnabled(false);\r
834                         }\r
835                 }\r
836                 \r
837                 if (templatesTable != null) {\r
838                         templ_createFromJob.setEnabled(false);\r
839                         templ_delete.setEnabled(false);\r
840                         templ_clear.setEnabled(false);\r
841                         \r
842                         if (jobsTable != null && jobsTable.getSelectedRowCount() == 1) {\r
843                                 templ_createFromJob.setEnabled(true);\r
844                         }\r
845                         \r
846                         if (templatesTable.getSelectedRowCount() > 0) {\r
847                                 templ_delete.setEnabled(true);\r
848                         }\r
849                         \r
850                         if (templatesTable.getRowCount() > 0) {\r
851                                 templ_clear.setEnabled(true);\r
852                         }\r
853                 }\r
854         }\r
855         \r
856         private class JobsTableMouseListener implements MouseListener {\r
857 \r
858                 public void mouseClicked(MouseEvent e) {\r
859                         if (e != null && e.getClickCount() == 2) {\r
860                                 List<RecordJob> selectedJobs = getSelectedRecordJobs(jobsTable);\r
861                                 if (selectedJobs.size() == 1) {\r
862                                         RecordJob selectedJob = selectedJobs.get(0);\r
863                                         if (selectedJob.getState() != RecordJob.State.PROCESSING) {\r
864                                                 JobDialog jobDialog = new JobDialog(SwingGUI.this, selectedJob, appLayer);\r
865                                                 jobDialog.showDialog();\r
866                                         }\r
867                                 }\r
868                         } else {\r
869                                 configureTableButtons();\r
870                         }\r
871                 }\r
872 \r
873                 public void mouseEntered(MouseEvent e) {}\r
874 \r
875                 public void mouseExited(MouseEvent e) {}\r
876 \r
877                 public void mousePressed(MouseEvent e) {\r
878                         this.showPopupMenu(e);\r
879                 }\r
880 \r
881                 public void mouseReleased(MouseEvent e) {\r
882                         this.showPopupMenu(e);\r
883                 }\r
884                 \r
885                 private void showPopupMenu(MouseEvent e) {\r
886                         if (e.isPopupTrigger()) {\r
887                                 JTable table = (JTable)(e.getSource());\r
888                                 Point p = e.getPoint();\r
889                                 int row = table.rowAtPoint(p);\r
890                                 int[] selectedRows = table.getSelectedRows();\r
891                                 //figure out whether we have to reselect the current row under the pointer,\r
892                                 //which is only the case if the already selected rows don't include the one under\r
893                                 //the pointer yet\r
894                                 boolean reSelect = true;\r
895                                 for (int i = 0; i < selectedRows.length; i++) {\r
896                                         if (row == selectedRows[i]) {\r
897                                                 reSelect = false;\r
898                                                 break;\r
899                                         }\r
900                                 }\r
901                                 \r
902                                 if (row != -1 && reSelect) {\r
903                                         table.setRowSelectionInterval(row, row);\r
904                                 }\r
905                                 \r
906                                 this.configurePopupMenu();\r
907                                 configureTableButtons();\r
908                                 jobsTablePopupMenu.show(e.getComponent(), e.getX(), e.getY());\r
909                         }\r
910                 }\r
911                 \r
912                 private void configurePopupMenu() {\r
913                         //Disable all buttons first\r
914                         jobs_contextmenu_edit.setEnabled(false);\r
915                         jobs_contextmenu_duplicate.setEnabled(false);\r
916                         jobs_contextmenu_delete.setEnabled(false);\r
917                         jobs_contextmenu_resetstate_waiting.setEnabled(false);\r
918                         jobs_contextmenu_resetstate_done.setEnabled(false);\r
919                         jobs_contextmenu_showerror.setEnabled(false);\r
920                         jobs_contextmenu_start.setEnabled(false);\r
921                         for (JMenuItem pluginItem : jobs_contextmenu_runPluginMenuItems) {\r
922                                 pluginItem.setEnabled(false);\r
923                         }\r
924                         \r
925                         //edit, duplicate, and show error buttons\r
926                         if (jobsTable.getSelectedRowCount() == 1) {\r
927                                 jobs_contextmenu_edit.setEnabled(true);\r
928                                 \r
929                                 //Show error button\r
930                                 List<RecordJob> selectedJobs = getSelectedRecordJobs(jobsTable);\r
931                                 RecordJob selectedJob = selectedJobs.get(0);\r
932                                 if (selectedJob.getState() == RecordJob.State.ERROR || selectedJob.getState() == RecordJob.State.ERROR_PLUGIN) {\r
933                                         jobs_contextmenu_showerror.setEnabled(true);\r
934                                 }\r
935                         }\r
936                         \r
937                         if (jobsTable.getSelectedRowCount() > 0) {\r
938                                 jobs_contextmenu_duplicate.setEnabled(true);\r
939                                 //Delete button\r
940                                 RecordJob.State[] states = {RecordJob.State.PROCESSING};\r
941                                 if (!checkJobStates(states, false)) {\r
942                                         //none of the jobs is processing\r
943                                         jobs_contextmenu_delete.setEnabled(true);\r
944                                         jobs_contextmenu_resetstate_waiting.setEnabled(true);\r
945                                 } else {\r
946                                         jobs_contextmenu_edit.setEnabled(false);\r
947                                         jobs_contextmenu_duplicate.setEnabled(false);\r
948                                 }\r
949                                 \r
950                                 //Start button\r
951                                 RecordJob.State[] states2 = {RecordJob.State.ERROR, RecordJob.State.DONE, RecordJob.State.PROCESSING, RecordJob.State.ERROR_PLUGIN};\r
952                                 if (!checkJobStates(states2, true)) {\r
953                                         //only enable start if none of the selected jobs as any of the States above\r
954                                         //as the only job State that is not listed is "waiting", we only enable the button if all jobs are waiting\r
955                                         jobs_contextmenu_start.setEnabled(true);\r
956                                 }\r
957                                 \r
958                                 //reset to 'done' button\r
959                                 RecordJob.State[] states3 = {RecordJob.State.ERROR, RecordJob.State.WAITING, RecordJob.State.PROCESSING};\r
960                                 if (!checkJobStates(states3, true)) {\r
961                                         //only enable the "reset to done" button when processes have the state DONE or ERROR_PLUGIN\r
962                                         jobs_contextmenu_resetstate_done.setEnabled(true);\r
963                                 }\r
964                                 \r
965                                 //plugin buttons, enable only when state of the job is DONE\r
966                                 RecordJob.State[] states4 = {RecordJob.State.ERROR, RecordJob.State.WAITING, RecordJob.State.PROCESSING, RecordJob.State.ERROR_PLUGIN};\r
967                                 if (!checkJobStates(states4, true)) {\r
968                                         int counter = 0;\r
969                                         for (JMenuItem pluginItem : jobs_contextmenu_runPluginMenuItems) {\r
970                                                 if (appLayer.getEncoderPlugins().get(counter).isEnabled()) {\r
971                                                         pluginItem.setEnabled(true);\r
972                                                 }\r
973                                                 counter++;\r
974                                         }\r
975                                 }\r
976                         }\r
977                 }\r
978                 \r
979         }\r
980         \r
981         private class TemplatesTableMouseListener implements MouseListener {\r
982 \r
983                 public void mouseClicked(MouseEvent e) {\r
984                         if (e != null && e.getClickCount() == 2) {\r
985                                 List<RecordJob> selectedJobs = getSelectedRecordJobs(templatesTable);\r
986                                 if (selectedJobs.size() == 1) {\r
987                                         RecordJobTemplate selectedJob = (RecordJobTemplate) selectedJobs.get(0);\r
988                                         JobDialog jobDialog = new JobDialog(SwingGUI.this, selectedJob, appLayer, JobDialog.EDIT_TEMPLATE);\r
989                                         jobDialog.showDialog();\r
990                                         configureTableButtons();\r
991                                 }\r
992                         } else {\r
993                                 configureTableButtons();\r
994                         }\r
995                 }\r
996 \r
997                 public void mouseEntered(MouseEvent e) {}\r
998 \r
999                 public void mouseExited(MouseEvent e) {}\r
1000 \r
1001                 public void mousePressed(MouseEvent e) {\r
1002                         this.showPopupMenu(e);\r
1003                 }\r
1004 \r
1005                 public void mouseReleased(MouseEvent e) {\r
1006                         this.showPopupMenu(e);\r
1007                 }\r
1008                 \r
1009                 private void showPopupMenu(MouseEvent e) {\r
1010                         if (e.isPopupTrigger()) {\r
1011                                 JTable table = (JTable)(e.getSource());\r
1012                                 Point p = e.getPoint();\r
1013                                 int row = table.rowAtPoint(p);\r
1014                                 int[] selectedRows = table.getSelectedRows();\r
1015                                 //figure out whether we have to reselect the current row under the pointer,\r
1016                                 //which is only the case if the already selected rows don't include the one under\r
1017                                 //the pointer yet\r
1018                                 boolean reSelect = true;\r
1019                                 for (int i = 0; i < selectedRows.length; i++) {\r
1020                                         if (row == selectedRows[i]) {\r
1021                                                 reSelect = false;\r
1022                                                 break;\r
1023                                         }\r
1024                                 }\r
1025                                 \r
1026                                 if (row != -1 && reSelect) {\r
1027                                         table.setRowSelectionInterval(row, row);\r
1028                                 }\r
1029                                 \r
1030                                 this.configurePopupMenu();\r
1031                                 configureTableButtons();\r
1032                                 templatesTablePopupMenu.show(e.getComponent(), e.getX(), e.getY());\r
1033                         }\r
1034                 }\r
1035                 \r
1036                 private void configurePopupMenu() {\r
1037                         //Various buttons\r
1038                         templ_contextmenu_edit.setEnabled(false);\r
1039                         templ_contextmenu_duplicate.setEnabled(false);\r
1040                         templ_contextmenu_delete.setEnabled(false);\r
1041                         \r
1042                         //Edit button\r
1043                         if (templatesTable.getSelectedRowCount() == 1) {\r
1044                                 templ_contextmenu_edit.setEnabled(true);\r
1045                         }\r
1046                         \r
1047                         //Delete and duplicate button\r
1048                         if (templatesTable.getSelectedRowCount() > 0) {\r
1049                                 templ_contextmenu_delete.setEnabled(true);\r
1050                                 templ_contextmenu_duplicate.setEnabled(true);\r
1051                         }\r
1052                 }\r
1053         }\r
1054                 \r
1055         private void showAboutBox() {\r
1056         try {\r
1057             InputStream inStream = ClassLoader.getSystemResourceAsStream("about.html");\r
1058             StringBuffer out = new StringBuffer();\r
1059             byte[] b = new byte[4096];\r
1060             for (int n; (n = inStream.read(b)) != -1;) {\r
1061                 out.append(new String(b, 0, n));\r
1062             }\r
1063             String htmlString = out.toString();\r
1064             htmlString = htmlString.replaceAll("[\\r\\n]", "");\r
1065             JOptionPane.showMessageDialog(this, htmlString, "About", JOptionPane.PLAIN_MESSAGE);\r
1066         } catch (IOException ex) {\r
1067             ex.printStackTrace();\r
1068         }\r
1069     }\r
1070 \r
1071         public void windowActivated(WindowEvent e) {}\r
1072         public void windowClosed(WindowEvent e) {}\r
1073         public void windowDeactivated(WindowEvent e) {}\r
1074         public void windowDeiconified(WindowEvent e) {}\r
1075         public void windowIconified(WindowEvent e) {}\r
1076         public void windowOpened(WindowEvent e) {}\r
1077 \r
1078         public void windowClosing(WindowEvent e) {\r
1079                 this.shutDown();\r
1080         }\r
1081 \r
1082         private void shutDown() {\r
1083                 if (this.appLayer.getState() == DemoRecorderApplication.STATE_WORKING) {\r
1084                         int result = JOptionPane.showConfirmDialog(this, "There are still jobs being recorded. Are you sure you want to exit?", "Confirm close", JOptionPane.YES_NO_OPTION);\r
1085                         if (result == JOptionPane.NO_OPTION) {\r
1086                                 return;\r
1087                         }\r
1088                 }\r
1089                 saveTableStates(jobsTable);\r
1090                 saveTableStates(templatesTable);\r
1091                 saveTemplateTableContent();\r
1092                 this.appLayer.shutDown();\r
1093                 this.dispose();\r
1094                 System.exit(0);\r
1095         }\r
1096         \r
1097         private void saveTemplateTableContent() {\r
1098                 File path = DemoRecorderUtils.computeLocalFile(DemoRecorderApplication.PREFERENCES_DIRNAME, TEMPLATE_TABLE_CONTENT_FILENAME);\r
1099                 RecordJobTemplatesTableModel tableModel = (RecordJobTemplatesTableModel) templatesTable.getModel();\r
1100                 tableModel.saveTemplateListToFile(path);\r
1101         }\r
1102         \r
1103         private Icon getIcon(String iconString) {\r
1104                 URL url = ClassLoader.getSystemResource("icons/" + iconString);\r
1105                 Icon i = new ImageIcon(url);\r
1106                 return i;\r
1107         }\r
1108 \r
1109 }\r