OSDN Git Service

introduce plugin update framework
[stigmata/stigmata-core.git] / src / main / java / jp / sourceforge / stigmata / ui / swing / StigmataFrame.java
1 package jp.sourceforge.stigmata.ui.swing;
2
3 /*
4  * $Id$
5  */
6
7 import java.awt.BorderLayout;
8 import java.awt.Image;
9 import java.awt.event.ActionEvent;
10 import java.awt.event.ActionListener;
11 import java.awt.event.WindowAdapter;
12 import java.awt.event.WindowEvent;
13 import java.io.BufferedReader;
14 import java.io.File;
15 import java.io.FileReader;
16 import java.io.IOException;
17 import java.io.PrintWriter;
18 import java.io.StringWriter;
19 import java.util.ArrayList;
20 import java.util.HashMap;
21 import java.util.Iterator;
22 import java.util.List;
23 import java.util.Map;
24
25 import javax.swing.ButtonGroup;
26 import javax.swing.JCheckBoxMenuItem;
27 import javax.swing.JFrame;
28 import javax.swing.JLabel;
29 import javax.swing.JMenu;
30 import javax.swing.JMenuBar;
31 import javax.swing.JMenuItem;
32 import javax.swing.JOptionPane;
33 import javax.swing.JPanel;
34 import javax.swing.JScrollPane;
35 import javax.swing.JSeparator;
36 import javax.swing.JTabbedPane;
37 import javax.swing.JTextArea;
38 import javax.swing.LookAndFeel;
39 import javax.swing.SwingUtilities;
40 import javax.swing.UIManager;
41 import javax.swing.WindowConstants;
42 import javax.swing.event.ChangeEvent;
43 import javax.swing.event.ChangeListener;
44 import javax.swing.filechooser.FileFilter;
45
46 import jp.sourceforge.stigmata.BirthmarkContext;
47 import jp.sourceforge.stigmata.BirthmarkElementClassNotFoundException;
48 import jp.sourceforge.stigmata.BirthmarkEngine;
49 import jp.sourceforge.stigmata.BirthmarkEnvironment;
50 import jp.sourceforge.stigmata.BirthmarkExtractionFailedException;
51 import jp.sourceforge.stigmata.BirthmarkSet;
52 import jp.sourceforge.stigmata.ComparisonPair;
53 import jp.sourceforge.stigmata.ComparisonResultSet;
54 import jp.sourceforge.stigmata.ExtractionResultSet;
55 import jp.sourceforge.stigmata.Main;
56 import jp.sourceforge.stigmata.Stigmata;
57 import jp.sourceforge.stigmata.StigmataCommand;
58 import jp.sourceforge.stigmata.command.StigmataCommandFactory;
59 import jp.sourceforge.stigmata.event.BirthmarkEngineAdapter;
60 import jp.sourceforge.stigmata.event.BirthmarkEngineEvent;
61 import jp.sourceforge.stigmata.event.WarningMessages;
62 import jp.sourceforge.stigmata.result.CertainPairComparisonResultSet;
63 import jp.sourceforge.stigmata.ui.swing.actions.AboutAction;
64 import jp.sourceforge.stigmata.ui.swing.actions.LicenseAction;
65 import jp.sourceforge.stigmata.ui.swing.actions.OpenSettingDirAction;
66 import jp.sourceforge.stigmata.ui.swing.graph.SimilarityDistributionGraphPane;
67 import jp.sourceforge.stigmata.ui.swing.mds.MdsViewerPane;
68 import jp.sourceforge.stigmata.ui.swing.tab.EditableTabbedPane;
69 import jp.sourceforge.stigmata.utils.Utility;
70 import jp.sourceforge.talisman.i18n.Messages;
71 import jp.sourceforge.talisman.i18n.ResourceNotFoundException;
72
73 import org.apache.commons.cli.ParseException;
74
75 /**
76  *
77  * @author Haruaki TAMADA
78  * @version $Revision$
79  */
80 public class StigmataFrame extends JFrame{
81     private static final long serialVersionUID = 92345543665342134L;
82
83     private Messages messages;
84     private JTabbedPane tabPane;
85     private JMenuItem closeTabMenu;
86     private JMenuItem saveMenu;
87     private JCheckBoxMenuItem experimentalMode;
88     private Stigmata stigmata;
89     private BirthmarkEnvironment environment;
90     private ControlPane control;
91     private FileIOManager fileio;
92     private Map<String, Integer> countmap = new HashMap<String, Integer>();
93
94     public StigmataFrame(){
95         this(Stigmata.getInstance());
96     }
97
98     public StigmataFrame(Stigmata stigmata){
99         this(stigmata, BirthmarkEnvironment.getDefaultEnvironment());
100     }
101
102     public StigmataFrame(Stigmata stigmata, BirthmarkEnvironment environment){
103         this.stigmata = stigmata;
104         this.environment = environment;
105         this.fileio = new FileIOManager(this, environment);
106         try{
107             this.messages = new Messages("resources.messages");
108         } catch(ResourceNotFoundException e){
109             throw new InternalError(e.getMessage());
110         }
111         Image iconImage = GUIUtility.getImage(getMessages(), "stigmata.icon");
112         if(iconImage != null){
113             setIconImage(iconImage);
114         }
115
116         stigmata.addBirthmarkEngineListener(new BirthmarkEngineAdapter(){
117             @Override
118             public void operationDone(BirthmarkEngineEvent e){
119                 showWarnings(e.getMessage());
120             }
121         });
122
123         initLayouts();
124     }
125
126     public Messages getMessages(){
127         return messages;
128     }
129
130     public boolean isNeedToSaveSettings(){
131         return saveMenu.isEnabled();
132     }
133
134     public void setNeedToSaveSettings(boolean flag){
135         saveMenu.setEnabled(flag);
136     }
137
138     public Stigmata getStigmata(){
139         return stigmata;
140     }
141
142     public BirthmarkEnvironment getEnvironment(){
143         return environment;
144     }
145
146     public File getCurrentDirectory(){
147         return fileio.getCurrentDirectory();
148     }
149
150     public void setCurrentDirectory(File file){
151         try{
152             fileio.setCurrentDirectory(file);
153         } catch(IllegalArgumentException e){
154             JOptionPane.showMessageDialog(
155                 this,
156                 getMessages().get("notdirectory.dialog.message", file.getName()),
157                 getMessages().get("notdirectory.dialog.title"),
158                 JOptionPane.ERROR_MESSAGE
159             );
160         } catch(Exception e){
161             showExceptionMessage(e);
162         }
163     }
164
165     public File[] openFiles(FileFilter[] filters, boolean multipleSelectable, boolean directorySelectable){
166         return fileio.openFiles(filters, multipleSelectable, directorySelectable);
167     }
168
169     /**
170      * Find file to open it.
171      */
172     public File getOpenFile(String[] exts, String desc){
173         return fileio.findFile(true, exts, desc);
174     }
175
176     /**
177      * Find file for storing data to it.
178      * Extension of found file is correct as selected extension.
179      */
180     public File getSaveFile(String[] exts, String desc){
181         return fileio.findFile(false, exts, desc);
182     }
183
184     public void addBirthmarkServiceListener(BirthmarkServiceListener listener){
185         control.addBirthmarkServiceListener(listener);
186     }
187
188     public void removeBirthmarkServiceListener(BirthmarkServiceListener listener){
189         control.removeBirthmarkServiceListener(listener);
190     }
191
192     public void compareDetails(BirthmarkSet target1, BirthmarkSet target2, BirthmarkContext context){
193         PairComparisonPane detail = new PairComparisonPane(
194             this, new ComparisonPair(target1, target2, context)
195         );
196         int compareDetail = getNextCount("compare_detail");
197
198         GUIUtility.addNewTab(getMessages(), "comparedetail", tabPane, detail,
199             new Object[] { new Integer(compareDetail), },
200             new Object[] {
201                 Utility.array2String(target1.getBirthmarkTypes()),
202                 target1.getName(),
203                 target2.getName(),
204             }, true
205         );
206     }
207
208     public void compareRoundRobin(String[] targetX, String[] targetY, 
209             BirthmarkContext context){
210         try{
211             BirthmarkEngine engine = getStigmata().createEngine(context.getEnvironment());
212             ExtractionResultSet ers = engine.extract(targetX, targetY, context);
213
214             RoundRobinComparisonResultPane compare = new RoundRobinComparisonResultPane(this, ers);
215             int compareCount = getNextCount("compare");
216             GUIUtility.addNewTab(
217                 getMessages(), "compare", tabPane, compare,
218                 new Object[] { new Integer(compareCount), },
219                 new Object[] {
220                     Utility.array2String(context.getBirthmarkTypes()),
221                     Utility.array2String(targetX),
222                     Utility.array2String(targetY),
223                 }, true
224             );
225         } catch(Throwable e){
226             showExceptionMessage(e);
227         }
228     }
229
230     public void compareRoundRobinFilter(String[] targetX, String[] targetY, 
231             BirthmarkContext context){
232         try{
233             BirthmarkEngine engine = getStigmata().createEngine(context.getEnvironment());
234
235             ExtractionResultSet ers = engine.extract(targetX, targetY, context);
236             ComparisonResultSet resultset = engine.compare(ers);
237             if(context.hasFilter()){
238                 resultset = engine.filter(resultset);
239             }
240             int compareCount = getNextCount("compare");
241             GUIUtility.addNewTab(
242                 getMessages(), "compare", tabPane, new PairComparisonResultSetPane(this, resultset),
243                 new Object[] { new Integer(compareCount), },
244                 new Object[] {
245                     Utility.array2String(context.getBirthmarkTypes()),
246                     Utility.array2String(targetX),
247                     Utility.array2String(targetY),
248                 }, true
249             );
250         } catch(Throwable e){
251             showExceptionMessage(e);
252         }
253     }
254
255     public void compareGuessedPair(String[] targetX, String[] targetY, BirthmarkContext context){
256         try{
257             BirthmarkEngine engine = getStigmata().createEngine(context.getEnvironment());
258             ExtractionResultSet extraction = engine.extract(targetX, targetY, context);
259             int comparePair = getNextCount("compare_pair");
260
261             ComparisonResultSet resultset = new CertainPairComparisonResultSet(extraction);
262             GUIUtility.addNewTab(
263                 getMessages(), "comparepair", tabPane,
264                 new PairComparisonResultSetPane(this, resultset),
265                 new Object[] { new Integer(comparePair), },
266                 new Object[] {
267                     Utility.array2String(context.getBirthmarkTypes()),
268                     Utility.array2String(targetX),
269                     Utility.array2String(targetY),
270                 }, true
271             );
272             tabPane.setSelectedIndex(tabPane.getTabCount() - 1);
273         }catch(Throwable e){
274             showExceptionMessage(e);
275         }
276     }
277
278     public void compareSpecifiedPair(String[] targetX, String[] targetY, BirthmarkContext context){
279         File file = getOpenFile(
280             getMessages().getArray("comparemapping.extension"),
281             getMessages().get("comparemapping.description")
282         );
283
284         if(file != null){
285             Map<String, String> mapping = constructMapping(file);
286
287             try{
288                 BirthmarkEngine engine = getStigmata().createEngine(context.getEnvironment());
289                 context.setNameMappings(mapping);
290                 ComparisonResultSet crs = engine.compare(targetX, targetY, context);
291                 int comparePair = getNextCount("compare_pair");
292
293                 GUIUtility.addNewTab(
294                     getMessages(), "comparepair", tabPane,
295                     new PairComparisonResultSetPane(this, crs),
296                     new Object[] { new Integer(comparePair), },
297                     new Object[] {
298                         Utility.array2String(context.getBirthmarkTypes()),
299                         Utility.array2String(targetX),
300                         Utility.array2String(targetY),
301                     }, true
302                 );
303             }catch(Exception e){
304                 showExceptionMessage(e);
305             }
306         }
307     }
308
309     public void showComparisonResultSet(ComparisonResultSet resultset){
310         int comparePair = getNextCount("compare_pair");
311         GUIUtility.addNewTab(
312             getMessages(), "comparisonresultset", tabPane,
313             new PairComparisonResultSetPane(this, resultset),
314             new Object[] { new Integer(comparePair), }, null, true
315         );
316     }
317
318     public void showMdsGraph(BirthmarkSet[] set, BirthmarkContext context){
319         try{
320             MdsViewerPane panel = new MdsViewerPane(this, set, context);
321             int mappingGraphCount = getNextCount("mds_graph");
322             GUIUtility.addNewTab(
323                 getMessages(), "mappinggraph", tabPane, panel,
324                 new Object[] { new Integer(mappingGraphCount), }, null, true
325             );
326         } catch(Exception e){
327             showExceptionMessage(e);
328         }
329     }
330
331     public void showSimilarityDistributionGraph(Map<Integer, Integer> distributions){
332         SimilarityDistributionGraphPane graph = new SimilarityDistributionGraphPane(this, distributions);
333
334         int similarityGraphCount = getNextCount("similarity_graph");
335         GUIUtility.addNewTab(
336             getMessages(), "similaritygraph", tabPane, graph,
337             new Object[] { new Integer(similarityGraphCount), }, null, true
338         );
339     }
340
341     public void compareExtractionResult(ExtractionResultSet ers){
342         RoundRobinComparisonResultPane compare = new RoundRobinComparisonResultPane(this, ers);
343         int compareCount = getNextCount("compare");
344         GUIUtility.addNewTab(
345             getMessages(), "compare", tabPane, compare,
346             new Object[] { new Integer(compareCount), },
347             new Object[] {
348                 Utility.array2String(ers.getBirthmarkTypes()),
349                 Utility.array2String(new String[0]),
350                 Utility.array2String(new String[0]),
351             }, true
352         );
353     }
354
355     public void showExtractionResult(ExtractionResultSet ers){
356         int extractCount = getNextCount("extract");
357         BirthmarkExtractionResultPane viewer = new BirthmarkExtractionResultPane(this, ers);
358         GUIUtility.addNewTab(
359             getMessages(), "extract", tabPane, viewer,
360             new Object[] { new Integer(extractCount), },
361             new Object[] { Utility.array2String(ers.getBirthmarkTypes()), }, true
362         );
363     }
364
365     public void extract(String[] targetX, String[] targetY, BirthmarkContext context){
366         try{
367             BirthmarkEngine engine = getStigmata().createEngine(context.getEnvironment());
368             ExtractionResultSet ers = engine.extract(targetX, targetY, context);
369             showExtractionResult(ers);
370         }catch(Throwable e){
371             showExceptionMessage(e);
372         }
373     }
374
375     /**
376      * csv file to Map.
377      */
378     public Map<String, String> constructMapping(File file){
379         Map<String, String> mapping = new HashMap<String, String>();
380         BufferedReader in = null;
381         try{
382             in = new BufferedReader(new FileReader(file));
383             String line;
384             while((line = in.readLine()) != null){
385                 String[] tokens = line.split(", *");
386                 if(tokens.length >= 2){
387                     mapping.put(tokens[0], tokens[1]);
388                 }
389             }
390
391         }catch(Exception e){
392             showExceptionMessage(e);
393         }finally{
394             if(in != null){
395                 try{
396                     in.close();
397                 }catch(IOException e){
398                 }
399             }
400         }
401         return mapping;
402     }
403
404     private void reloadSettings(String[] args){
405         try{
406             setVisible(false);
407             dispose();
408             new Main(args);
409         } catch(ParseException e){
410         }
411     }
412
413     private void clearSettings(){
414         Utility.deleteDirectory(new File(BirthmarkEnvironment.getStigmataHome()));
415         reloadSettings(new String[] { "--reset-config", "gui", });
416     }
417
418     private void initLayouts(){
419         setTitle(getMessages().get("stigmata.frame.title"));
420         initComponents();
421
422         GUIUtility.addNewTab(getMessages(), "control", tabPane, control = new ControlPane(this), null, null, false);
423         control.inititalize();
424         tabPane.setSelectedIndex(tabPane.getTabCount() - 1);
425
426         setNeedToSaveSettings(false);
427         setSize(900, 600);
428     }
429
430     private void showWarnings(WarningMessages warnings){
431         if(warnings.getWarningCount() > 0){
432             StringBuilder sb = new StringBuilder("<html><body><dl>");
433             for(Iterator<Exception> i = warnings.exceptions(); i.hasNext(); ){
434                 Exception e = i.next();
435                 sb.append("<dt>").append(e.getClass().getName()).append("</dt>");
436                 sb.append("<dd>").append(e.getMessage()).append("</dd>");
437                 sb.append("<dd>").append(warnings.getString(e)).append("</dd>");
438             }
439             sb.append("</dl></body></html>");
440
441             JOptionPane.showMessageDialog(
442                 this, new String(sb), getMessages().get("warning.dialog.title"),
443                 JOptionPane.WARNING_MESSAGE
444             );
445         }
446     }
447
448     private void onlineUpdate(){
449         UpdatePluginsPane pane = new UpdatePluginsPane(this);
450         JOptionPane.showMessageDialog(this, pane);
451     }
452
453     private void installPlugin(){
454         File pluginFile = getOpenFile(
455             new String[] { "jar", },
456             messages.get("installplugin.fileopen.description")
457         );
458         List<String> messages = new ArrayList<String>();
459         if(pluginFile == null){
460             return;
461         }
462
463         if(Utility.isStigmataPluginJarFile(pluginFile, messages)){
464             StigmataCommand command = StigmataCommandFactory.getInstance().getCommand("install");
465             String path = pluginFile.getPath();
466             command.perform(getStigmata(), new String[] { path });
467
468             int flag = JOptionPane.showConfirmDialog(
469                 this, getMessages().get("reload.after.installplugin"),
470                 getMessages().get("reload.after.installplugin.title"),
471                 JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE
472             );
473
474             if(flag == JOptionPane.YES_OPTION){
475                 reloadSettings(new String[] { "gui", });
476             }
477             else{
478                 JOptionPane.showMessageDialog(
479                     this, getMessages().get("reload.manually"),
480                     getMessages().get("reload.manually.title"),
481                     JOptionPane.INFORMATION_MESSAGE
482                 );
483             }
484         }
485         else{
486             StringBuilder sb = new StringBuilder("<html><body>");
487             sb.append("<p>").append(getMessages().format("install.error", pluginFile.getPath())).append("</p>");
488             sb.append("<ul>");
489             for(String message: messages){
490                 sb.append("<li>").append(getMessages().get(message)).append("</li>");
491             }
492             sb.append("</ul></body></html>");
493
494             JOptionPane.showMessageDialog(
495                 this, new String(sb),
496                 getMessages().get("install.error.title"),
497                 JOptionPane.ERROR_MESSAGE
498             );
499         }
500     }
501
502     private void initComponents(){
503         setDefaultUI();
504         JMenuBar menubar = new JMenuBar();
505         menubar.add(createFileMenu());
506         menubar.add(createPluginsMenu());
507         menubar.add(createHelpMenu());
508
509         setJMenuBar(menubar);
510
511         tabPane = new EditableTabbedPane(this);
512         add(tabPane, BorderLayout.CENTER);
513
514         tabPane.addChangeListener(new ChangeListener(){
515             public void stateChanged(ChangeEvent arg0){
516                 String title = tabPane.getTitleAt(tabPane.getSelectedIndex());
517                 closeTabMenu.setEnabled(!title.equals(getMessages().get("control.tab.label")));
518             }
519         });
520         addWindowListener(new WindowAdapter(){
521             @Override
522             public void windowClosing(WindowEvent e){
523                 boolean closeFlag = true;
524                 if(isNeedToSaveSettings()){
525                     int returnValue = JOptionPane.showConfirmDialog(
526                         StigmataFrame.this,
527                         getMessages().get("needtosave.settings.message"),
528                         getMessages().get("needtosave.settings.title"),
529                         JOptionPane.YES_NO_CANCEL_OPTION,
530                         JOptionPane.WARNING_MESSAGE
531                     );
532                     closeFlag = returnValue != JOptionPane.CANCEL_OPTION;
533                     if(returnValue == JOptionPane.YES_OPTION){
534                         control.saveSettings(new File(BirthmarkEnvironment.getStigmataHome(), "stigmata.xml"));
535                     }
536                 }
537                 if(closeFlag){
538                     setVisible(false);
539                     dispose();
540                 }
541             }
542         });
543         setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
544     }
545
546     private JMenu createPluginsMenu(){
547         JMenu pluginsMenu = GUIUtility.createJMenu(getMessages(), "pluginsMenu");
548         JMenuItem installMenu = GUIUtility.createJMenuItem(getMessages(), "installplugin");
549         JMenuItem openSettingDirMenu = GUIUtility.createJMenuItem(getMessages(), "opensettingdir", new OpenSettingDirAction(this, getMessages()));
550         JMenuItem onlineUpdate = GUIUtility.createJMenuItem(getMessages(), "onlineupdate");
551
552         pluginsMenu.add(openSettingDirMenu);
553         pluginsMenu.add(installMenu);
554         pluginsMenu.add(new JSeparator());
555         pluginsMenu.add(onlineUpdate);
556
557         installMenu.addActionListener(new ActionListener(){
558             public void actionPerformed(ActionEvent evt){
559                 installPlugin();
560             }
561         });
562         onlineUpdate.addActionListener(new ActionListener(){
563             public void actionPerformed(ActionEvent e){
564                 onlineUpdate();
565             }
566         });
567
568         return pluginsMenu;
569     }
570
571     private JMenu createFileMenu(){
572         JMenu fileMenu = GUIUtility.createJMenu(getMessages(), "fileMenu");
573         JMenuItem newFrameMenu = GUIUtility.createJMenuItem(getMessages(), "newframe");
574         JMenuItem saveMenu = GUIUtility.createJMenuItem(getMessages(), "savesetting");
575         JMenuItem exportMenu = GUIUtility.createJMenuItem(getMessages(), "exportsetting");
576         JMenuItem clearMenu = GUIUtility.createJMenuItem(getMessages(), "clearsetting");
577         JMenuItem refreshMenu = GUIUtility.createJMenuItem(getMessages(), "refreshsetting");
578         JMenuItem closeTabMenu = GUIUtility.createJMenuItem(getMessages(), "closetab");
579         JMenuItem closeMenu = GUIUtility.createJMenuItem(getMessages(), "closeframe");
580         JMenuItem exitMenu = GUIUtility.createJMenuItem(getMessages(), "exit");
581         this.closeTabMenu = closeTabMenu;
582         this.saveMenu = saveMenu;
583         saveMenu.setEnabled(false);
584
585         fileMenu.add(newFrameMenu);
586         fileMenu.add(new JSeparator());
587         fileMenu.add(saveMenu);
588         fileMenu.add(exportMenu);
589         fileMenu.add(refreshMenu);
590         fileMenu.add(clearMenu);
591         fileMenu.add(new JSeparator());
592         fileMenu.add(closeTabMenu);
593         fileMenu.add(closeMenu);
594         fileMenu.add(new JSeparator());
595         fileMenu.add(exitMenu);
596
597         newFrameMenu.addActionListener(new ActionListener(){
598             public void actionPerformed(ActionEvent evt){
599                 StigmataFrame frame = new StigmataFrame(stigmata, environment);
600                 frame.setVisible(true);
601             }
602         });
603         saveMenu.addActionListener(new ActionListener(){
604             public void actionPerformed(ActionEvent e){
605                 control.saveSettings(new File(BirthmarkEnvironment.getStigmataHome(), "stigmata.xml"));
606                 setNeedToSaveSettings(false);
607             }
608         });
609
610         exportMenu.addActionListener(new ActionListener(){
611             public void actionPerformed(ActionEvent e){
612                 control.exportSettings();
613             }
614         });
615
616         closeTabMenu.addActionListener(new ActionListener(){
617             public void actionPerformed(ActionEvent evt){
618                 closeTabMenuActionPerformed();
619             }
620         });
621
622         clearMenu.addActionListener(new ActionListener(){
623             public void actionPerformed(ActionEvent evt){
624                 clearSettings();
625             }
626         });
627
628         refreshMenu.addActionListener(new ActionListener(){
629             public void actionPerformed(ActionEvent evt){
630                 reloadSettings(new String[] { "gui", });
631             }
632         });
633
634         closeMenu.addActionListener(new ActionListener(){
635             public void actionPerformed(ActionEvent evt){
636                 setVisible(false);
637                 dispose();
638             }
639         });
640
641         exitMenu.addActionListener(new ActionListener(){
642             public void actionPerformed(ActionEvent evt){
643                 System.exit(0);
644             }
645         });
646         return fileMenu;
647     }
648
649     private JMenu createHelpMenu(){
650         JMenu menu = GUIUtility.createJMenu(getMessages(), "helpmenu");
651         JMenuItem about = GUIUtility.createJMenuItem(getMessages(), "about", new AboutAction(this));
652         JMenuItem license = GUIUtility.createJMenuItem(getMessages(), "license", new LicenseAction(this));
653         JMenuItem help = GUIUtility.createJMenuItem(getMessages(), "helpmenu");
654         experimentalMode = GUIUtility.createJCheckBoxMenuItem(getMessages(), "experimentalmenu");
655
656         menu.add(about);
657         menu.add(license);
658         menu.add(help);
659         menu.add(new JSeparator());
660         menu.add(createLookAndFeelMenu());
661         menu.add(new JSeparator());
662         menu.add(experimentalMode);
663
664         experimentalMode.addActionListener(new ActionListener(){
665             public void actionPerformed(ActionEvent e){
666                 updateExperimentalModeState(((JCheckBoxMenuItem)e.getSource()).getState());
667             }
668         });
669         help.setEnabled(false);
670
671         return menu;
672     }
673
674     private JMenu createLookAndFeelMenu(){
675         JMenu laf = GUIUtility.createJMenu(getMessages(), "lookandfeel");
676         ButtonGroup bg = new ButtonGroup();
677         UIManager.LookAndFeelInfo[] info = UIManager.getInstalledLookAndFeels();
678         LookAndFeel lookfeel = UIManager.getLookAndFeel();
679
680         ActionListener listener = new ActionListener(){
681             public void actionPerformed(ActionEvent e){
682                 try{
683                     String command = e.getActionCommand();
684                     UIManager.setLookAndFeel(command);
685                     SwingUtilities.updateComponentTreeUI(StigmataFrame.this);
686                 } catch(Exception ee){
687                 }
688             }
689         };
690         for(int i = 0; i < info.length; i++){
691             JCheckBoxMenuItem item = new JCheckBoxMenuItem(info[i].getName());
692             item.setActionCommand(info[i].getClassName());
693             item.addActionListener(listener);
694             bg.add(item);
695             laf.add(item);
696
697             if(info[i].getClassName().equals(lookfeel.getClass().getName())){
698                 item.setState(true);
699             }
700         }
701
702         return laf;
703     }
704
705     public void setExperimentalMode(boolean experimentalModeFlag){
706         experimentalMode.setState(experimentalModeFlag);
707     }
708
709     private void updateExperimentalModeState(boolean status){
710         control.setExperimentalMode(status);
711     }
712
713     private void showExceptionMessage(Throwable e){
714         if(e instanceof BirthmarkElementClassNotFoundException){
715             showClassNotFoundMessage((BirthmarkElementClassNotFoundException)e);
716         }
717         else if(e instanceof OutOfMemoryError){
718             showOutOfMemoryError();
719         }
720         else{
721             JTextArea area = new JTextArea(20, 60);
722             StringWriter writer = new StringWriter();
723             PrintWriter out = new PrintWriter(writer);
724             e.printStackTrace(out);
725             if(e instanceof BirthmarkExtractionFailedException){
726                 out.println("Causes:");
727                 for(Throwable t: ((BirthmarkExtractionFailedException)e).getCauses()){
728                     t.printStackTrace(out);
729                 }
730             }
731             out.close();
732             area.setText(writer.toString());
733             JPanel panel = new JPanel(new BorderLayout());
734             panel.add(new JLabel("<html><body><p>" + getMessages().get("error.message.contactus") + "</p></body></html>"), BorderLayout.NORTH);
735             panel.add(new JScrollPane(area), BorderLayout.CENTER);
736
737             JOptionPane.showMessageDialog(
738                 this, panel, getMessages().get("error.dialog.title"),
739                 JOptionPane.WARNING_MESSAGE
740             );
741         }
742     }
743
744     private void showOutOfMemoryError(){
745         StringBuffer sb = new StringBuffer();
746         sb.append("<html><body><p>");
747         sb.append(getMessages().get("error.message.outofmemory"));
748         sb.append("</p></body></html>");
749         JOptionPane.showMessageDialog(
750             this, new String(sb), getMessages().get("error.dialog.title"),
751             JOptionPane.WARNING_MESSAGE
752         );
753     }
754
755     private void showClassNotFoundMessage(BirthmarkElementClassNotFoundException e){
756         StringBuffer sb = new StringBuffer();
757         sb.append("<html><body><p>");
758         sb.append(getMessages().get("error.message.classpath"));
759         sb.append("</p><ul>");
760         for(String name: e.getClassNames()){
761             sb.append("<li>").append(name).append("</li>");
762         }
763         sb.append("</ul></body></html>");
764         JOptionPane.showMessageDialog(
765             this, new String(sb), getMessages().get("error.dialog.title"),
766             JOptionPane.WARNING_MESSAGE
767         );
768     }
769
770     private void closeTabMenuActionPerformed(){
771         int index = tabPane.getSelectedIndex();
772         if(index == 0){
773             JOptionPane.showMessageDialog(
774                 this, getMessages().get("cannotclosecontroltab.dialog.message"),
775                 getMessages().get("cannotclosecontroltab.dialog.title"),
776                 JOptionPane.ERROR_MESSAGE
777             );
778         }
779         else{
780             tabPane.removeTabAt(index);
781         }
782     }
783
784     private int getNextCount(String label){
785         Integer i = countmap.get(label);
786         if(i == null){
787             i = new Integer(0);
788         }
789         i = i + 1;
790         countmap.put(label, i);
791         return i;
792     }
793
794     private void setDefaultUI(){
795         try{
796             UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
797         } catch(Exception e){
798         }
799     }
800 }