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