OSDN Git Service

da988aa325d22743d3b1a9c99a330e8be07b4e33
[stigmata/stigmata.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             @Override
516             public void stateChanged(ChangeEvent arg0){
517                 String title = tabPane.getTitleAt(tabPane.getSelectedIndex());
518                 closeTabMenu.setEnabled(!title.equals(getMessages().get("control.tab.label")));
519             }
520         });
521         addWindowListener(new WindowAdapter(){
522             @Override
523             public void windowClosing(WindowEvent e){
524                 boolean closeFlag = true;
525                 if(isNeedToSaveSettings()){
526                     int returnValue = JOptionPane.showConfirmDialog(
527                         StigmataFrame.this,
528                         getMessages().get("needtosave.settings.message"),
529                         getMessages().get("needtosave.settings.title"),
530                         JOptionPane.YES_NO_CANCEL_OPTION,
531                         JOptionPane.WARNING_MESSAGE
532                     );
533                     closeFlag = returnValue != JOptionPane.CANCEL_OPTION;
534                     if(returnValue == JOptionPane.YES_OPTION){
535                         control.saveSettings(new File(BirthmarkEnvironment.getStigmataHome(), "stigmata.xml"));
536                     }
537                 }
538                 if(closeFlag){
539                     setVisible(false);
540                     dispose();
541                 }
542             }
543         });
544         setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
545     }
546
547     private JMenu createPluginsMenu(){
548         JMenu pluginsMenu = GUIUtility.createJMenu(getMessages(), "pluginsMenu");
549         JMenuItem installMenu = GUIUtility.createJMenuItem(getMessages(), "installplugin");
550         JMenuItem openSettingDirMenu = GUIUtility.createJMenuItem(getMessages(), "opensettingdir", new OpenSettingDirAction(this, getMessages()));
551         JMenuItem onlineUpdate = GUIUtility.createJMenuItem(getMessages(), "onlineupdate");
552
553         pluginsMenu.add(openSettingDirMenu);
554         pluginsMenu.add(installMenu);
555         pluginsMenu.add(new JSeparator());
556         pluginsMenu.add(onlineUpdate);
557
558         installMenu.addActionListener(new ActionListener(){
559             @Override
560             public void actionPerformed(ActionEvent evt){
561                 installPlugin();
562             }
563         });
564         onlineUpdate.addActionListener(new ActionListener(){
565             @Override
566             public void actionPerformed(ActionEvent e){
567                 onlineUpdate();
568             }
569         });
570
571         return pluginsMenu;
572     }
573
574     private JMenu createFileMenu(){
575         JMenu fileMenu = GUIUtility.createJMenu(getMessages(), "fileMenu");
576         JMenuItem newFrameMenu = GUIUtility.createJMenuItem(getMessages(), "newframe");
577         JMenuItem saveMenu = GUIUtility.createJMenuItem(getMessages(), "savesetting");
578         JMenuItem exportMenu = GUIUtility.createJMenuItem(getMessages(), "exportsetting");
579         JMenuItem clearMenu = GUIUtility.createJMenuItem(getMessages(), "clearsetting");
580         JMenuItem refreshMenu = GUIUtility.createJMenuItem(getMessages(), "refreshsetting");
581         JMenuItem closeTabMenu = GUIUtility.createJMenuItem(getMessages(), "closetab");
582         JMenuItem closeMenu = GUIUtility.createJMenuItem(getMessages(), "closeframe");
583         JMenuItem exitMenu = GUIUtility.createJMenuItem(getMessages(), "exit");
584         this.closeTabMenu = closeTabMenu;
585         this.saveMenu = saveMenu;
586         saveMenu.setEnabled(false);
587
588         fileMenu.add(newFrameMenu);
589         fileMenu.add(new JSeparator());
590         fileMenu.add(saveMenu);
591         fileMenu.add(exportMenu);
592         fileMenu.add(refreshMenu);
593         fileMenu.add(clearMenu);
594         fileMenu.add(new JSeparator());
595         fileMenu.add(closeTabMenu);
596         fileMenu.add(closeMenu);
597         fileMenu.add(new JSeparator());
598         fileMenu.add(exitMenu);
599
600         newFrameMenu.addActionListener(new ActionListener(){
601             @Override
602             public void actionPerformed(ActionEvent evt){
603                 StigmataFrame frame = new StigmataFrame(stigmata, environment);
604                 frame.setVisible(true);
605             }
606         });
607         saveMenu.addActionListener(new ActionListener(){
608             @Override
609             public void actionPerformed(ActionEvent e){
610                 control.saveSettings(new File(BirthmarkEnvironment.getStigmataHome(), "stigmata.xml"));
611                 setNeedToSaveSettings(false);
612             }
613         });
614
615         exportMenu.addActionListener(new ActionListener(){
616             @Override
617             public void actionPerformed(ActionEvent e){
618                 control.exportSettings();
619             }
620         });
621
622         closeTabMenu.addActionListener(new ActionListener(){
623             @Override
624             public void actionPerformed(ActionEvent evt){
625                 closeTabMenuActionPerformed();
626             }
627         });
628
629         clearMenu.addActionListener(new ActionListener(){
630             @Override
631             public void actionPerformed(ActionEvent evt){
632                 clearSettings();
633             }
634         });
635
636         refreshMenu.addActionListener(new ActionListener(){
637             @Override
638             public void actionPerformed(ActionEvent evt){
639                 reloadSettings(new String[] { "gui", });
640             }
641         });
642
643         closeMenu.addActionListener(new ActionListener(){
644             @Override
645             public void actionPerformed(ActionEvent evt){
646                 setVisible(false);
647                 dispose();
648             }
649         });
650
651         exitMenu.addActionListener(new ActionListener(){
652             @Override
653             public void actionPerformed(ActionEvent evt){
654                 System.exit(0);
655             }
656         });
657         return fileMenu;
658     }
659
660     private JMenu createHelpMenu(){
661         JMenu menu = GUIUtility.createJMenu(getMessages(), "helpmenu");
662         JMenuItem about = GUIUtility.createJMenuItem(getMessages(), "about", new AboutAction(this));
663         JMenuItem license = GUIUtility.createJMenuItem(getMessages(), "license", new LicenseAction(this));
664         JMenuItem help = GUIUtility.createJMenuItem(getMessages(), "helpmenu");
665         experimentalMode = GUIUtility.createJCheckBoxMenuItem(getMessages(), "experimentalmenu");
666
667         menu.add(about);
668         menu.add(license);
669         menu.add(help);
670         menu.add(new JSeparator());
671         menu.add(createLookAndFeelMenu());
672         menu.add(new JSeparator());
673         menu.add(experimentalMode);
674
675         experimentalMode.addActionListener(new ActionListener(){
676             @Override
677             public void actionPerformed(ActionEvent e){
678                 updateExperimentalModeState(((JCheckBoxMenuItem)e.getSource()).getState());
679             }
680         });
681         help.setEnabled(false);
682
683         return menu;
684     }
685
686     private JMenu createLookAndFeelMenu(){
687         JMenu laf = GUIUtility.createJMenu(getMessages(), "lookandfeel");
688         ButtonGroup bg = new ButtonGroup();
689         UIManager.LookAndFeelInfo[] info = UIManager.getInstalledLookAndFeels();
690         LookAndFeel lookfeel = UIManager.getLookAndFeel();
691
692         ActionListener listener = new ActionListener(){
693             @Override
694             public void actionPerformed(ActionEvent e){
695                 try{
696                     String command = e.getActionCommand();
697                     UIManager.setLookAndFeel(command);
698                     SwingUtilities.updateComponentTreeUI(StigmataFrame.this);
699                 } catch(Exception ee){
700                 }
701             }
702         };
703         for(int i = 0; i < info.length; i++){
704             JCheckBoxMenuItem item = new JCheckBoxMenuItem(info[i].getName());
705             item.setActionCommand(info[i].getClassName());
706             item.addActionListener(listener);
707             bg.add(item);
708             laf.add(item);
709
710             if(info[i].getClassName().equals(lookfeel.getClass().getName())){
711                 item.setState(true);
712             }
713         }
714
715         return laf;
716     }
717
718     public void setExperimentalMode(boolean experimentalModeFlag){
719         experimentalMode.setState(experimentalModeFlag);
720     }
721
722     private void updateExperimentalModeState(boolean status){
723         control.setExperimentalMode(status);
724     }
725
726     private void showExceptionMessage(Throwable e){
727         if(e instanceof BirthmarkElementClassNotFoundException){
728             showClassNotFoundMessage((BirthmarkElementClassNotFoundException)e);
729         }
730         else if(e instanceof OutOfMemoryError){
731             showOutOfMemoryError();
732         }
733         else{
734             JTextArea area = new JTextArea(20, 60);
735             StringWriter writer = new StringWriter();
736             PrintWriter out = new PrintWriter(writer);
737             e.printStackTrace(out);
738             if(e instanceof BirthmarkExtractionFailedException){
739                 out.println("Causes:");
740                 for(Throwable t: ((BirthmarkExtractionFailedException)e).getCauses()){
741                     t.printStackTrace(out);
742                 }
743             }
744             out.close();
745             area.setText(writer.toString());
746             JPanel panel = new JPanel(new BorderLayout());
747             panel.add(new JLabel("<html><body><p>" + getMessages().get("error.message.contactus") + "</p></body></html>"), BorderLayout.NORTH);
748             panel.add(new JScrollPane(area), BorderLayout.CENTER);
749
750             JOptionPane.showMessageDialog(
751                 this, panel, getMessages().get("error.dialog.title"),
752                 JOptionPane.WARNING_MESSAGE
753             );
754         }
755     }
756
757     private void showOutOfMemoryError(){
758         StringBuffer sb = new StringBuffer();
759         sb.append("<html><body><p>");
760         sb.append(getMessages().get("error.message.outofmemory"));
761         sb.append("</p></body></html>");
762         JOptionPane.showMessageDialog(
763             this, new String(sb), getMessages().get("error.dialog.title"),
764             JOptionPane.WARNING_MESSAGE
765         );
766     }
767
768     private void showClassNotFoundMessage(BirthmarkElementClassNotFoundException e){
769         StringBuffer sb = new StringBuffer();
770         sb.append("<html><body><p>");
771         sb.append(getMessages().get("error.message.classpath"));
772         sb.append("</p><ul>");
773         for(String name: e.getClassNames()){
774             sb.append("<li>").append(name).append("</li>");
775         }
776         sb.append("</ul></body></html>");
777         JOptionPane.showMessageDialog(
778             this, new String(sb), getMessages().get("error.dialog.title"),
779             JOptionPane.WARNING_MESSAGE
780         );
781     }
782
783     private void closeTabMenuActionPerformed(){
784         int index = tabPane.getSelectedIndex();
785         if(index == 0){
786             JOptionPane.showMessageDialog(
787                 this, getMessages().get("cannotclosecontroltab.dialog.message"),
788                 getMessages().get("cannotclosecontroltab.dialog.title"),
789                 JOptionPane.ERROR_MESSAGE
790             );
791         }
792         else{
793             tabPane.removeTabAt(index);
794         }
795     }
796
797     private int getNextCount(String label){
798         Integer i = countmap.get(label);
799         if(i == null){
800             i = new Integer(0);
801         }
802         i = i + 1;
803         countmap.put(label, i);
804         return i;
805     }
806
807     private void setDefaultUI(){
808         try{
809             UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
810         } catch(Exception e){
811         }
812     }
813 }