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