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.6 2002/03/04 18:03:17 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     JPanel vBox = new JPanel();
150     vBox.setLayout(new BoxLayout(vBox, BoxLayout.Y_AXIS));
151     vBox.add(includeFeaturesOnPreserveFormatChk);
152     vBox.add(Box.createVerticalStrut(10));
153     vBox.setBorder(BorderFactory.createTitledBorder(
154         BorderFactory.createEtchedBorder() , " Advanced features "));
155     advancedBox.add(vBox);
156     advancedBox.add(Box.createVerticalStrut(10));
157 
158 
159     vBox = new JPanel();
160     vBox.setLayout(new BoxLayout(vBox, BoxLayout.Y_AXIS));
161     vBox.add(Box.createVerticalStrut(10));
162     vBox.add(saveOptionsChk);
163     vBox.add(Box.createVerticalStrut(10));
164     vBox.add(saveSessionChk);
165     vBox.add(Box.createVerticalStrut(10));
166     vBox.setBorder(BorderFactory.createTitledBorder(
167         BorderFactory.createEtchedBorder() , " Session persistence "));
168     advancedBox.add(vBox);
169 
170 
171 
172     mainTabbedPane.add("Advanced", advancedBox);
173 
174     Box buttonsBox = Box.createHorizontalBox();
175     buttonsBox.add(Box.createHorizontalGlue());
176     buttonsBox.add(okButton = new JButton(new OKAction()));
177     buttonsBox.add(Box.createHorizontalStrut(10));
178     buttonsBox.add(cancelButton = new JButton("Cancel"));
179     buttonsBox.add(Box.createHorizontalGlue());
180 
181     getContentPane().add(Box.createVerticalStrut(10));
182     getContentPane().add(buttonsBox);
183     getContentPane().add(Box.createVerticalStrut(10));
184   }
185 
186   protected void initListeners(){
187     lnfCombo.addActionListener(new ActionListener() {
188       public void actionPerformed(ActionEvent e) {
189         if(!lookAndFeelClassName.equals(
190            ((LNFData)lnfCombo.getSelectedItem()).className)
191           ){
192           dirtyGUI = true;
193           lookAndFeelClassName = ((LNFData)lnfCombo.getSelectedItem()).
194                                  className;
195         }
196       }
197     });
198 
199     fontChooser.addPropertyChangeListener(new PropertyChangeListener() {
200       public void propertyChange(PropertyChangeEvent e) {
201         if(e.getPropertyName().equals("fontValue")){
202           String selectedFont = fontBG.getSelection().getActionCommand();
203           if(selectedFont.equals("text")){
204             textComponentsFont = (Font)e.getNewValue();
205             dirtyGUI = true;
206           }else if(selectedFont.equals("menu")){
207             menusFont = (Font)e.getNewValue();
208             dirtyGUI = true;
209           }else if(selectedFont.equals("other")){
210             componentsFont = (Font)e.getNewValue();
211             dirtyGUI = true;
212           }
213         }
214       }
215     });
216 
217     textBtn.addActionListener(new ActionListener() {
218       public void actionPerformed(ActionEvent e) {
219         if(textBtn.isSelected()) selectedFontChanged();
220         selectedFontBtn = "text";
221         fontChooser.setFontValue(textComponentsFont);
222       }
223     });
224 
225     menuBtn.addActionListener(new ActionListener() {
226       public void actionPerformed(ActionEvent e) {
227         if(menuBtn.isSelected()) selectedFontChanged();
228         selectedFontBtn = "menu";
229         fontChooser.setFontValue(menusFont);
230       }
231     });
232 
233     otherCompsBtn.addActionListener(new ActionListener() {
234       public void actionPerformed(ActionEvent e) {
235         if(otherCompsBtn.isSelected()) selectedFontChanged();
236         selectedFontBtn = "other";
237         fontChooser.setFontValue(componentsFont);
238       }
239     });
240 
241     cancelButton.setAction(new AbstractAction("Cancel"){
242       public void actionPerformed(ActionEvent evt){
243         hide();
244       }
245     });
246     textBtn.setSelected(true);
247   }
248 
249   public void dispose(){
250     MainFrame.getGuiRoots().remove(this);
251     super.dispose();
252   }
253 
254   protected void selectedFontChanged(){
255     if(selectedFontBtn != null){
256       //save the old font
257       if(selectedFontBtn.equals("text")){
258         textComponentsFont = fontChooser.getFontValue();
259       }else if(selectedFontBtn.equals("menu")){
260         menusFont = fontChooser.getFontValue();
261       }else if(selectedFontBtn.equals("other")){
262         componentsFont = fontChooser.getFontValue();
263       }
264     }
265   }
266 
267   public void show(){
268     initLocalData();
269     initGuiComponents();
270     textBtn.setSelected(true);
271     fontChooser.setFontValue(textComponentsFont);
272     initListeners();
273     pack();
274     setLocationRelativeTo(getOwner());
275     super.show();
276   }
277 
278   public static void main(String args[]){
279     try{
280       UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
281     }catch(Exception e){
282       e.printStackTrace();
283     }
284     final JFrame frame = new JFrame("Foo frame");
285     frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
286     JButton btn = new JButton("Show dialog");
287     btn.addActionListener(new ActionListener() {
288       public void actionPerformed(ActionEvent e) {
289         OptionsDialog dialog = new OptionsDialog(frame);
290         dialog.pack();
291         dialog.show();
292       }
293     });
294     frame.getContentPane().add(btn);
295     frame.pack();
296     frame.setVisible(true);
297     System.out.println("Font: " + UIManager.getFont("Button.font"));
298   }// main
299 
300 
301   protected static void setUIDefaults(Object[] keys, Object value) {
302     for(int i = 0; i < keys.length; i++){
303       UIManager.put(keys[i], value);
304     }
305   }// setUIDefaults(Object[] keys, Object value)
306 
307   /**
308    * Updates the Swing defaults table with the provided font to be used for the
309    * text components
310    */
311   public static void setTextComponentsFont(Font font){
312     setUIDefaults(textComponentsKeys, new FontUIResource(font));
313     Gate.getUserConfig().put(GateConstants.TEXT_COMPONENTS_FONT, font);
314   }
315 
316   /**
317    * Updates the Swing defaults table with the provided font to be used for the
318    * menu components
319    */
320   public static void setMenuComponentsFont(Font font){
321     setUIDefaults(menuKeys, new FontUIResource(font));
322     Gate.getUserConfig().put(GateConstants.MENUS_FONT, font);
323   }
324 
325   /**
326    * Updates the Swing defaults table with the provided font to be used for
327    * various compoents that neither text or menu components
328    */
329   public static void setComponentsFont(Font font){
330     setUIDefaults(componentsKeys, new FontUIResource(font));
331     Gate.getUserConfig().put(GateConstants.OTHER_COMPONENTS_FONT, font);
332   }
333 
334   class OKAction extends AbstractAction{
335     OKAction(){
336       super("OK");
337     }
338 
339     public void actionPerformed(ActionEvent evt) {
340       OptionsMap userConfig = Gate.getUserConfig();
341       if(dirtyGUI){
342         setMenuComponentsFont(menusFont);
343         setComponentsFont(componentsFont);
344         setTextComponentsFont(textComponentsFont);
345         userConfig.put(GateConstants.LOOK_AND_FEEL, lookAndFeelClassName);
346         try{
347           UIManager.setLookAndFeel(lookAndFeelClassName);
348           Iterator rootsIter = MainFrame.getGuiRoots().iterator();
349           while(rootsIter.hasNext()){
350             SwingUtilities.updateComponentTreeUI((Component)rootsIter.next());
351           }
352         }catch(Exception e){}
353       }
354 
355       userConfig.put(GateConstants.SAVE_OPTIONS_ON_EXIT,
356                      new Boolean(saveOptionsChk.isSelected()));
357       userConfig.put(GateConstants.SAVE_SESSION_ON_EXIT,
358                      new Boolean(saveSessionChk.isSelected()));
359       userConfig.put(GateConstants.SAVE_FEATURES_WHEN_PRESERVING_FORMAT,
360                      new Boolean(includeFeaturesOnPreserveFormatChk.
361                                  isSelected()));
362       hide();
363     }// void actionPerformed(ActionEvent evt)
364   }
365 
366   protected static class LNFData{
367     public LNFData(String className, String name){
368       this.className = className;
369       this.name = name;
370     }
371 
372     public String toString(){
373       return name;
374     }
375 
376     String className;
377     String name;
378   }
379 
380 
381   public static String[] menuKeys = new String[]{"CheckBoxMenuItem.acceleratorFont",
382                                           "CheckBoxMenuItem.font",
383                                           "Menu.acceleratorFont",
384                                           "Menu.font",
385                                           "MenuBar.font",
386                                           "MenuItem.acceleratorFont",
387                                           "MenuItem.font",
388                                           "RadioButtonMenuItem.acceleratorFont",
389                                           "RadioButtonMenuItem.font"};
390 
391   public static String[] componentsKeys =
392                              new String[]{"Button.font",
393                                           "CheckBox.font",
394                                           "ColorChooser.font",
395                                           "ComboBox.font",
396                                           "InternalFrame.titleFont",
397                                           "Label.font",
398                                           "List.font",
399                                           "OptionPane.font",
400                                           "Panel.font",
401                                           "PasswordField.font",
402                                           "PopupMenu.font",
403                                           "ProgressBar.font",
404                                           "RadioButton.font",
405                                           "ScrollPane.font",
406                                           "TabbedPane.font",
407                                           "Table.font",
408                                           "TableHeader.font",
409                                           "TitledBorder.font",
410                                           "ToggleButton.font",
411                                           "ToolBar.font",
412                                           "ToolTip.font",
413                                           "Tree.font",
414                                           "Viewport.font"};
415 
416   public static String[] textComponentsKeys =
417                              new String[]{"EditorPane.font",
418                                           "TextArea.font",
419                                           "TextField.font",
420                                           "TextPane.font"};
421 
422   /**
423    * The main tabbed pane
424    */
425   JTabbedPane mainTabbedPane;
426 
427   /**
428    * The OK button. The action for this button is an {@link OKAction}
429    */
430   JButton okButton;
431 
432   /**
433    * The Cancel button: hides the dialog without doing anything
434    */
435   JButton cancelButton;
436 
437   /**
438    * Radio button used to set the font for text components
439    */
440   JRadioButton textBtn;
441 
442   /**
443    * which text is currently being edited; values are: "text", "menu", "other"
444    */
445   String selectedFontBtn = null;
446 
447   /**
448    * Radio button used to set the font for menu components
449    */
450   JRadioButton menuBtn;
451 
452   /**
453    * Radio button used to set the font for other components
454    */
455   JRadioButton otherCompsBtn;
456 
457   /**
458    * Button group for the font setting radio buttons
459    */
460   ButtonGroup fontBG;
461 
462   /**
463    * The font chooser used for selecting fonts
464    */
465   JFontChooser fontChooser;
466 
467   /**
468    * The "Save Options on close" checkbox
469    */
470   JCheckBox saveOptionsChk;
471 
472   /**
473    * The "Save Session on close" checkbox
474    */
475   JCheckBox saveSessionChk;
476 
477   /**
478    * The "Include Annotation Features in Save Preserving Format" checkbox
479    */
480   JCheckBox includeFeaturesOnPreserveFormatChk;
481 
482   /**
483    * The name of the look and feel class
484    */
485   String lookAndFeelClassName;
486 
487   /**
488    * The font to be used for the menus; cached value for the one in the user
489    * config map.
490    */
491   Font menusFont;
492 
493   /**
494    * The font to be used for text components; cached value for the one in the
495    * user config map.
496    */
497   Font textComponentsFont;
498 
499   /**
500    * The font to be used for GUI components; cached value for the one in the
501    * user config map.
502    */
503   Font componentsFont;
504 
505   /**
506    * This flag becomes true when an GUI related option has been changed
507    */
508   boolean dirtyGUI;
509 
510   /**
511    * The combobox for the look and feel selection
512    */
513   JComboBox lnfCombo;
514 }