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