1   /*
2    *  Copyright (c) 1998-2005, The University of Sheffield.
3    *
4    *  This file is part of GATE (see http://gate.ac.uk/), and is free
5    *  software, licenced under the GNU Library General Public License,
6    *  Version 2, June 1991 (in the distribution as file licence.html,
7    *  and also available at http://gate.ac.uk/gate/licence.html).
8    *
9    *  Valentin Tablan 15/11/2001
10   *
11   *  $Id: OptionsDialog.java,v 1.16 2005/01/11 13:51:34 ian Exp $
12   *
13   */
14  package gate.gui;
15  
16  import java.awt.*;
17  import java.awt.event.ActionEvent;
18  import java.awt.event.ActionListener;
19  import java.beans.PropertyChangeEvent;
20  import java.beans.PropertyChangeListener;
21  import java.util.*;
22  import java.util.List;
23  
24  import javax.swing.*;
25  import javax.swing.plaf.FontUIResource;
26  
27  import gate.Gate;
28  import gate.GateConstants;
29  import gate.swing.JFontChooser;
30  import gate.util.OptionsMap;
31  
32  /**
33   * The options dialog for Gate.
34   */
35  public class OptionsDialog extends JDialog {
36    public OptionsDialog(Frame owner){
37      super(owner, "GATE Options", true);
38      MainFrame.getGuiRoots().add(this);
39    }
40  
41    protected void initLocalData(){
42      lookAndFeelClassName = Gate.getUserConfig().
43                             getString(GateConstants.LOOK_AND_FEEL);
44  
45      textComponentsFont = Gate.getUserConfig().
46                           getFont(GateConstants.TEXT_COMPONENTS_FONT);
47  
48      menusFont = Gate.getUserConfig().
49                  getFont(GateConstants.MENUS_FONT);
50  
51      componentsFont = Gate.getUserConfig().
52                       getFont(GateConstants.OTHER_COMPONENTS_FONT);
53      dirtyGUI = false;
54    }
55  
56  
57    protected void initGuiComponents(){
58      getContentPane().removeAll();
59      mainTabbedPane = new JTabbedPane(JTabbedPane.TOP);
60      getContentPane().setLayout(new BoxLayout(getContentPane(),
61                                               BoxLayout.Y_AXIS));
62      getContentPane().add(mainTabbedPane);
63  
64      Box appearanceBox = Box.createVerticalBox();
65      //the LNF combo
66      List supportedLNFs = new ArrayList();
67      LNFData currentLNF = null;
68      UIManager.LookAndFeelInfo[] lnfs = UIManager.getInstalledLookAndFeels();
69      for(int i = 0; i < lnfs.length; i++){
70        UIManager.LookAndFeelInfo lnf = lnfs[i];
71        try{
72          Class lnfClass = Class.forName(lnf.getClassName());
73          if(((LookAndFeel)(lnfClass.newInstance())).isSupportedLookAndFeel()){
74            if(lnf.getName().equals(UIManager.getLookAndFeel().getName())){
75              supportedLNFs.add(currentLNF =
76                                new LNFData(lnf.getClassName(), lnf.getName()));
77            }else{
78              supportedLNFs.add(new LNFData(lnf.getClassName(), lnf.getName()));
79            }
80          }
81        }catch(ClassNotFoundException cnfe){
82        }catch(IllegalAccessException iae){
83        }catch(InstantiationException ie){
84        }
85      }
86      lnfCombo = new JComboBox(supportedLNFs.toArray());
87      lnfCombo.setSelectedItem(currentLNF);
88  
89      Box horBox = Box.createHorizontalBox();
90      horBox.add(Box.createHorizontalStrut(5));
91      horBox.add(new JLabel("Look and feel:"));
92      horBox.add(Box.createHorizontalStrut(5));
93      horBox.add(lnfCombo);
94      horBox.add(Box.createHorizontalStrut(5));
95      appearanceBox.add(Box.createVerticalStrut(10));
96      appearanceBox.add(horBox);
97      appearanceBox.add(Box.createVerticalStrut(10));
98  
99      JPanel panel = new JPanel();
100     panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
101     panel.setBorder(BorderFactory.createTitledBorder(" Font options "));
102 
103     fontBG = new ButtonGroup();
104     textBtn = new JRadioButton("Text components font");
105     textBtn.setActionCommand("text");
106     fontBG.add(textBtn);
107     menuBtn = new JRadioButton("Menu components font");
108     menuBtn.setActionCommand("menu");
109     fontBG.add(menuBtn);
110     otherCompsBtn = new JRadioButton("Other components font");
111     otherCompsBtn.setActionCommand("other");
112     fontBG.add(otherCompsBtn);
113     Box verBox = Box.createVerticalBox();
114     verBox.add(Box.createVerticalStrut(5));
115     verBox.add(textBtn);
116     verBox.add(Box.createVerticalStrut(5));
117     verBox.add(menuBtn);
118     verBox.add(Box.createVerticalStrut(5));
119     verBox.add(otherCompsBtn);
120     verBox.add(Box.createVerticalStrut(5));
121     verBox.add(Box.createVerticalGlue());
122     panel.add(verBox);
123 
124     fontChooser = new JFontChooser();
125     panel.add(fontChooser);
126 
127     appearanceBox.add(panel);
128 
129     mainTabbedPane.add("Appearance", appearanceBox);
130 
131     Box advancedBox = Box.createVerticalBox();
132     saveOptionsChk = new JCheckBox(
133         "Save options on exit",
134         Gate.getUserConfig().getBoolean(GateConstants.SAVE_OPTIONS_ON_EXIT).
135         booleanValue());
136 
137     saveSessionChk = new JCheckBox(
138         "Save session on exit",
139         Gate.getUserConfig().getBoolean(GateConstants.SAVE_SESSION_ON_EXIT).
140         booleanValue());
141 
142     includeFeaturesOnPreserveFormatChk = new JCheckBox(
143       "Include annotation features for \"Save preserving format\"",
144       Gate.getUserConfig().
145       getBoolean(GateConstants.SAVE_FEATURES_WHEN_PRESERVING_FORMAT).
146       booleanValue());
147 
148     addSpaceOnMarkupUnpackChk = new JCheckBox(
149       "Add space on markup unpack if needed",
150       true);
151 
152     if ( (Gate.getUserConfig().
153        get(GateConstants.DOCUMENT_ADD_SPACE_ON_UNPACK_FEATURE_NAME) != null)
154       &&
155       !Gate.getUserConfig().
156         getBoolean(GateConstants.DOCUMENT_ADD_SPACE_ON_UNPACK_FEATURE_NAME).
157           booleanValue()
158       )
159       addSpaceOnMarkupUnpackChk.setSelected(false);
160 
161     ButtonGroup bGroup = new ButtonGroup();
162     doceditInsertAppendChk = new JCheckBox("Append (default)");
163     bGroup.add(doceditInsertAppendChk);
164     doceditInsertPrependChk = new JCheckBox("Prepend");
165     bGroup.add(doceditInsertPrependChk);
166     doceditInsertPrependChk.setSelected(Gate.getUserConfig().
167         getBoolean(GateConstants.DOCEDIT_INSERT_PREPEND).booleanValue());
168     doceditInsertAppendChk.setSelected(Gate.getUserConfig().
169         getBoolean(GateConstants.DOCEDIT_INSERT_APPEND).booleanValue());
170     //if none set then set the default one
171     if(!(doceditInsertAppendChk.isSelected()||
172          doceditInsertPrependChk.isSelected()))
173       doceditInsertAppendChk.setSelected(true);
174 
175     JPanel vBox = new JPanel();
176     vBox.setLayout(new BoxLayout(vBox, BoxLayout.Y_AXIS));
177     vBox.add(includeFeaturesOnPreserveFormatChk);
178     vBox.add(Box.createVerticalStrut(10));
179     vBox.add(addSpaceOnMarkupUnpackChk);
180     vBox.add(Box.createVerticalStrut(10));
181     vBox.setBorder(BorderFactory.createTitledBorder(
182         BorderFactory.createEtchedBorder() , " Advanced features "));
183     advancedBox.add(vBox);
184     advancedBox.add(Box.createVerticalStrut(10));
185 
186 
187     vBox = new JPanel();
188     vBox.setLayout(new BoxLayout(vBox, BoxLayout.Y_AXIS));
189     vBox.add(Box.createVerticalStrut(10));
190     vBox.add(saveOptionsChk);
191     vBox.add(Box.createVerticalStrut(10));
192     vBox.add(saveSessionChk);
193     vBox.add(Box.createVerticalStrut(10));
194     vBox.setBorder(BorderFactory.createTitledBorder(
195         BorderFactory.createEtchedBorder() , " Session persistence "));
196     advancedBox.add(vBox);
197 
198     vBox = new JPanel();
199     vBox.setLayout(new BoxLayout(vBox, BoxLayout.Y_AXIS));
200     vBox.add(Box.createVerticalStrut(10));
201     vBox.add(doceditInsertAppendChk);
202     vBox.add(Box.createVerticalStrut(10));
203     vBox.add(doceditInsertPrependChk);
204     vBox.add(Box.createVerticalStrut(10));
205     vBox.setBorder(BorderFactory.createTitledBorder(
206         BorderFactory.createEtchedBorder() ,
207         " Document editor insert behaviour "));
208     advancedBox.add(vBox);
209 
210     mainTabbedPane.add("Advanced", advancedBox);
211 
212     Box buttonsBox = Box.createHorizontalBox();
213     buttonsBox.add(Box.createHorizontalGlue());
214     buttonsBox.add(okButton = new JButton(new OKAction()));
215     buttonsBox.add(Box.createHorizontalStrut(10));
216     buttonsBox.add(cancelButton = new JButton("Cancel"));
217     buttonsBox.add(Box.createHorizontalGlue());
218 
219     getContentPane().add(Box.createVerticalStrut(10));
220     getContentPane().add(buttonsBox);
221     getContentPane().add(Box.createVerticalStrut(10));
222   }
223 
224   protected void initListeners(){
225     lnfCombo.addActionListener(new ActionListener() {
226       public void actionPerformed(ActionEvent e) {
227         if(!lookAndFeelClassName.equals(
228            ((LNFData)lnfCombo.getSelectedItem()).className)
229           ){
230           dirtyGUI = true;
231           lookAndFeelClassName = ((LNFData)lnfCombo.getSelectedItem()).
232                                  className;
233         }
234       }
235     });
236 
237     fontChooser.addPropertyChangeListener(new PropertyChangeListener() {
238       public void propertyChange(PropertyChangeEvent e) {
239         if(e.getPropertyName().equals("fontValue")){
240           String selectedFont = fontBG.getSelection().getActionCommand();
241           if(selectedFont.equals("text")){
242             textComponentsFont = (Font)e.getNewValue();
243             dirtyGUI = true;
244           }else if(selectedFont.equals("menu")){
245             menusFont = (Font)e.getNewValue();
246             dirtyGUI = true;
247           }else if(selectedFont.equals("other")){
248             componentsFont = (Font)e.getNewValue();
249             dirtyGUI = true;
250           }
251         }
252       }
253     });
254 
255     textBtn.addActionListener(new ActionListener() {
256       public void actionPerformed(ActionEvent e) {
257         if(textBtn.isSelected()) selectedFontChanged();
258         selectedFontBtn = "text";
259         fontChooser.setFontValue(textComponentsFont);
260       }
261     });
262 
263     menuBtn.addActionListener(new ActionListener() {
264       public void actionPerformed(ActionEvent e) {
265         if(menuBtn.isSelected()) selectedFontChanged();
266         selectedFontBtn = "menu";
267         fontChooser.setFontValue(menusFont);
268       }
269     });
270 
271     otherCompsBtn.addActionListener(new ActionListener() {
272       public void actionPerformed(ActionEvent e) {
273         if(otherCompsBtn.isSelected()) selectedFontChanged();
274         selectedFontBtn = "other";
275         fontChooser.setFontValue(componentsFont);
276       }
277     });
278 
279     cancelButton.setAction(new AbstractAction("Cancel"){
280       public void actionPerformed(ActionEvent evt){
281         setVisible(false);
282       }
283     });
284     textBtn.setSelected(true);
285   }
286 
287   public void dispose(){
288     MainFrame.getGuiRoots().remove(this);
289     super.dispose();
290   }
291 
292   protected void selectedFontChanged(){
293     if(selectedFontBtn != null){
294       //save the old font
295       if(selectedFontBtn.equals("text")){
296         textComponentsFont = fontChooser.getFontValue();
297       }else if(selectedFontBtn.equals("menu")){
298         menusFont = fontChooser.getFontValue();
299       }else if(selectedFontBtn.equals("other")){
300         componentsFont = fontChooser.getFontValue();
301       }
302     }
303   }
304 
305   public void show(){
306     initLocalData();
307     initGuiComponents();
308     textBtn.setSelected(true);
309     fontChooser.setFontValue(textComponentsFont);
310     initListeners();
311     pack();
312     setLocationRelativeTo(getOwner());
313     super.show();
314   }
315 
316   public static void main(String args[]){
317     try{
318       UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
319     }catch(Exception e){
320       e.printStackTrace();
321     }
322     final JFrame frame = new JFrame("Foo frame");
323     frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
324     JButton btn = new JButton("Show dialog");
325     btn.addActionListener(new ActionListener() {
326       public void actionPerformed(ActionEvent e) {
327         OptionsDialog dialog = new OptionsDialog(frame);
328         dialog.pack();
329         dialog.show();
330       }
331     });
332     frame.getContentPane().add(btn);
333     frame.pack();
334     frame.setVisible(true);
335     System.out.println("Font: " + UIManager.getFont("Button.font"));
336   }// main
337 
338 
339   protected static void setUIDefaults(Object[] keys, Object value) {
340     for(int i = 0; i < keys.length; i++){
341       UIManager.put(keys[i], value);
342     }
343   }// setUIDefaults(Object[] keys, Object value)
344 
345   /**
346    * Updates the Swing defaults table with the provided font to be used for the
347    * text components
348    */
349   public static void setTextComponentsFont(Font font){
350     setUIDefaults(textComponentsKeys, new FontUIResource(font));
351     Gate.getUserConfig().put(GateConstants.TEXT_COMPONENTS_FONT, font);
352   }
353 
354   /**
355    * Updates the Swing defaults table with the provided font to be used for the
356    * menu components
357    */
358   public static void setMenuComponentsFont(Font font){
359     setUIDefaults(menuKeys, new FontUIResource(font));
360     Gate.getUserConfig().put(GateConstants.MENUS_FONT, font);
361   }
362 
363   /**
364    * Updates the Swing defaults table with the provided font to be used for
365    * various compoents that neither text or menu components
366    */
367   public static void setComponentsFont(Font font){
368     setUIDefaults(componentsKeys, new FontUIResource(font));
369     Gate.getUserConfig().put(GateConstants.OTHER_COMPONENTS_FONT, font);
370   }
371 
372   class OKAction extends AbstractAction{
373     OKAction(){
374       super("OK");
375     }
376 
377     public void actionPerformed(ActionEvent evt) {
378       OptionsMap userConfig = Gate.getUserConfig();
379       if(dirtyGUI){
380         setMenuComponentsFont(menusFont);
381         setComponentsFont(componentsFont);
382         setTextComponentsFont(textComponentsFont);
383         userConfig.put(GateConstants.LOOK_AND_FEEL, lookAndFeelClassName);
384         try{
385           UIManager.setLookAndFeel(lookAndFeelClassName);
386           Iterator rootsIter = MainFrame.getGuiRoots().iterator();
387           while(rootsIter.hasNext()){
388             SwingUtilities.updateComponentTreeUI((Component)rootsIter.next());
389           }
390         }catch(Exception e){}
391       }
392 
393       userConfig.put(GateConstants.SAVE_OPTIONS_ON_EXIT,
394                      new Boolean(saveOptionsChk.isSelected()));
395       userConfig.put(GateConstants.SAVE_SESSION_ON_EXIT,
396                      new Boolean(saveSessionChk.isSelected()));
397       userConfig.put(GateConstants.SAVE_FEATURES_WHEN_PRESERVING_FORMAT,
398                      new Boolean(includeFeaturesOnPreserveFormatChk.
399                                  isSelected()));
400       userConfig.put(GateConstants.DOCUMENT_ADD_SPACE_ON_UNPACK_FEATURE_NAME,
401                      new Boolean(addSpaceOnMarkupUnpackChk.
402                                  isSelected()));
403       userConfig.put(GateConstants.DOCEDIT_INSERT_APPEND,
404                      new Boolean(doceditInsertAppendChk.isSelected()));
405       userConfig.put(GateConstants.DOCEDIT_INSERT_PREPEND,
406                      new Boolean(doceditInsertPrependChk.isSelected()));
407       setVisible(false);
408     }// void actionPerformed(ActionEvent evt)
409   }
410 
411   protected static class LNFData{
412     public LNFData(String className, String name){
413       this.className = className;
414       this.name = name;
415     }
416 
417     public String toString(){
418       return name;
419     }
420 
421     String className;
422     String name;
423   }
424 
425 
426   public static String[] menuKeys = new String[]{"CheckBoxMenuItem.acceleratorFont",
427                                           "CheckBoxMenuItem.font",
428                                           "Menu.acceleratorFont",
429                                           "Menu.font",
430                                           "MenuBar.font",
431                                           "MenuItem.acceleratorFont",
432                                           "MenuItem.font",
433                                           "RadioButtonMenuItem.acceleratorFont",
434                                           "RadioButtonMenuItem.font"};
435 
436   public static String[] componentsKeys =
437                              new String[]{"Button.font",
438                                           "CheckBox.font",
439                                           "ColorChooser.font",
440                                           "ComboBox.font",
441                                           "InternalFrame.titleFont",
442                                           "Label.font",
443                                           "List.font",
444                                           "OptionPane.font",
445                                           "Panel.font",
446                                           "PasswordField.font",
447                                           "PopupMenu.font",
448                                           "ProgressBar.font",
449                                           "RadioButton.font",
450                                           "ScrollPane.font",
451                                           "TabbedPane.font",
452                                           "Table.font",
453                                           "TableHeader.font",
454                                           "TextField.font",
455                                           "TitledBorder.font",
456                                           "ToggleButton.font",
457                                           "ToolBar.font",
458                                           "ToolTip.font",
459                                           "Tree.font",
460                                           "Viewport.font"};
461 
462   public static String[] textComponentsKeys =
463                              new String[]{"EditorPane.font",
464                                           "TextArea.font",
465                                           "TextPane.font"};
466 
467   /**
468    * The main tabbed pane
469    */
470   JTabbedPane mainTabbedPane;
471 
472   /**
473    * The OK button. The action for this button is an {@link OKAction}
474    */
475   JButton okButton;
476 
477   /**
478    * The Cancel button: hides the dialog without doing anything
479    */
480   JButton cancelButton;
481 
482   /**
483    * Radio button used to set the font for text components
484    */
485   JRadioButton textBtn;
486 
487   /**
488    * which text is currently being edited; values are: "text", "menu", "other"
489    */
490   String selectedFontBtn = null;
491 
492   /**
493    * Radio button used to set the font for menu components
494    */
495   JRadioButton menuBtn;
496 
497   /**
498    * Radio button used to set the font for other components
499    */
500   JRadioButton otherCompsBtn;
501 
502   /**
503    * Button group for the font setting radio buttons
504    */
505   ButtonGroup fontBG;
506 
507   /**
508    * The font chooser used for selecting fonts
509    */
510   JFontChooser fontChooser;
511 
512   /**
513    * The "Save Options on close" checkbox
514    */
515   JCheckBox saveOptionsChk;
516 
517   /**
518    * The "Save Session on close" checkbox
519    */
520   JCheckBox saveSessionChk;
521 
522   /**
523    * The "Include Annotation Features in Save Preserving Format" checkbox
524    */
525   JCheckBox includeFeaturesOnPreserveFormatChk;
526 
527   /**
528    * The "Add extra space markup unpack if needed" checkbox
529    */
530   JCheckBox addSpaceOnMarkupUnpackChk;
531 
532   /** The Docedit append checkbox */
533   JCheckBox doceditInsertAppendChk;
534 
535   /** The Docedit prepend checkbox */
536   JCheckBox doceditInsertPrependChk;
537 
538   /**
539    * The name of the look and feel class
540    */
541   String lookAndFeelClassName;
542 
543   /**
544    * The font to be used for the menus; cached value for the one in the user
545    * config map.
546    */
547   Font menusFont;
548 
549   /**
550    * The font to be used for text components; cached value for the one in the
551    * user config map.
552    */
553   Font textComponentsFont;
554 
555   /**
556    * The font to be used for GUI components; cached value for the one in the
557    * user config map.
558    */
559   Font componentsFont;
560 
561   /**
562    * This flag becomes true when an GUI related option has been changed
563    */
564   boolean dirtyGUI;
565 
566   /**
567    * The combobox for the look and feel selection
568    */
569   JComboBox lnfCombo;
570 }