Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/gjt/sp/jedit/gui/OptionsDialog.java


1   /*
2    * OptionsDialog.java - Tree options dialog
3    * :tabSize=8:indentSize=8:noTabs=false:
4    * :folding=explicit:collapseFolds=1:
5    *
6    * Copyright (C) 1998, 2003 Slava Pestov
7    * Portions copyright (C) 1999 mike dillon
8    *
9    * This program is free software; you can redistribute it and/or
10   * modify it under the terms of the GNU General Public License
11   * as published by the Free Software Foundation; either version 2
12   * of the License, or any later version.
13   *
14   * This program is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   * GNU General Public License for more details.
18   *
19   * You should have received a copy of the GNU General Public License
20   * along with this program; if not, write to the Free Software
21   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22   */
23  
24  package org.gjt.sp.jedit.gui;
25  
26  //{{{ Imports
27  import javax.swing.*;
28  import javax.swing.border.*;
29  import javax.swing.event.*;
30  import javax.swing.tree.*;
31  import java.awt.*;
32  import java.awt.event.*;
33  import java.util.*;
34  import org.gjt.sp.jedit.*;
35  import org.gjt.sp.util.Log;
36  //}}}
37  
38  /**
39   * An abstract tabbed options dialog box.
40   * @author Slava Pestov
41   * @version $Id: OptionsDialog.java,v 1.36 2003/10/10 23:46:24 spestov Exp $
42   */
43  public abstract class OptionsDialog extends EnhancedDialog
44    implements ActionListener, TreeSelectionListener
45  {
46    //{{{ OptionsDialog constructor
47    public OptionsDialog(Frame frame, String name, String pane)
48    {
49      super(frame, jEdit.getProperty(name + ".title"), true);
50      init(name,pane);
51    } //}}}
52  
53    //{{{ OptionsDialog constructor
54    public OptionsDialog(Dialog dialog, String name, String pane)
55    {
56      super(dialog, jEdit.getProperty(name + ".title"), true);
57      init(name,pane);
58    } //}}}
59  
60    //{{{ addOptionGroup() method
61    public void addOptionGroup(OptionGroup group)
62    {
63      getDefaultGroup().addOptionGroup(group);
64    } //}}}
65  
66    //{{{ addOptionPane() method
67    public void addOptionPane(OptionPane pane)
68    {
69      getDefaultGroup().addOptionPane(pane);
70    } //}}}
71  
72    //{{{ ok() method
73    public void ok()
74    {
75      if(currentPane != null)
76        jEdit.setProperty(name + ".last",currentPane.getName());
77      ok(true);
78    } //}}}
79  
80    //{{{ cancel() method
81    public void cancel()
82    {
83      if(currentPane != null)
84        jEdit.setProperty(name + ".last",currentPane.getName());
85      dispose();
86    } //}}}
87  
88    //{{{ ok() method
89    public void ok(boolean dispose)
90    {
91      OptionTreeModel m = (OptionTreeModel) paneTree
92        .getModel();
93      save(m.getRoot());
94  
95      /* This will fire the PROPERTIES_CHANGED event */
96      jEdit.propertiesChanged();
97  
98      // Save settings to disk
99      jEdit.saveSettings();
100 
101     // get rid of this dialog if necessary
102     if(dispose)
103       dispose();
104   } //}}}
105 
106   //{{{ dispose() method
107   public void dispose()
108   {
109     GUIUtilities.saveGeometry(this,name);
110     jEdit.setIntegerProperty(name + ".splitter",splitter.getDividerLocation());
111     super.dispose();
112   } //}}}
113 
114   //{{{ actionPerformed() method
115   public void actionPerformed(ActionEvent evt)
116   {
117     Object source = evt.getSource();
118 
119     if(source == ok)
120     {
121       ok();
122     }
123     else if(source == cancel)
124     {
125       cancel();
126     }
127     else if(source == apply)
128     {
129       ok(false);
130     }
131   } //}}}
132 
133   //{{{ valueChanged() method
134   public void valueChanged(TreeSelectionEvent evt)
135   {
136     TreePath path = evt.getPath();
137 
138     if(path == null)
139       return;
140 
141     Object lastPathComponent = path.getLastPathComponent();
142     if(!(lastPathComponent instanceof String
143       || lastPathComponent instanceof OptionPane))
144     {
145       return;
146     }
147 
148     Object[] nodes = path.getPath();
149 
150     StringBuffer buf = new StringBuffer();
151 
152     OptionPane optionPane = null;
153 
154     int lastIdx = nodes.length - 1;
155 
156     for (int i = paneTree.isRootVisible() ? 0 : 1;
157       i <= lastIdx; i++)
158     {
159       String label;
160       Object node = nodes[i];
161       if (node instanceof OptionPane)
162       {
163         optionPane = (OptionPane)node;
164         label = jEdit.getProperty("options."
165           + optionPane.getName()
166           + ".label");
167       }
168       else if (node instanceof OptionGroup)
169       {
170         label = ((OptionGroup)node).getLabel();
171       }
172       else if (node instanceof String)
173       {
174         label = jEdit.getProperty("options."
175           + node + ".label");
176         optionPane = (OptionPane)deferredOptionPanes
177           .get((String)node);
178         if(optionPane == null)
179         {
180           String propName = "options." + node + ".code";
181           String code = jEdit.getProperty(propName);
182           if(code != null)
183           {
184             optionPane = (OptionPane)
185               BeanShell.eval(
186               jEdit.getActiveView(),
187               BeanShell.getNameSpace(),
188               code
189             );
190 
191             if(optionPane != null)
192             {
193               deferredOptionPanes.put(
194                 node,optionPane);
195             }
196             else
197               continue;
198           }
199           else
200           {
201             Log.log(Log.ERROR,this,propName
202               + " not defined");
203             continue;
204           }
205         }
206       }
207       else
208       {
209         continue;
210       }
211 
212       buf.append(label);
213 
214       if (i != lastIdx)
215         buf.append(": ");
216     }
217 
218     if(optionPane == null)
219       return;
220 
221     setTitle(jEdit.getProperty("options.title-template",
222       new Object[] { jEdit.getProperty(this.name + ".title"),
223       buf.toString() }));
224 
225     try
226     {
227       optionPane.init();
228     }
229     catch(Throwable t)
230     {
231       Log.log(Log.ERROR,this,"Error initializing options:");
232       Log.log(Log.ERROR,this,t);
233     }
234 
235     if(currentPane != null)
236       stage.remove(currentPane.getComponent());
237     currentPane = optionPane;
238     stage.add(BorderLayout.CENTER,currentPane.getComponent());
239     stage.revalidate();
240     stage.repaint();
241 
242     if(!isShowing())
243       addNotify();
244 
245     updateSize();
246 
247     currentPane = optionPane;
248   } //}}}
249 
250   //{{{ Protected members
251   protected abstract OptionTreeModel createOptionTreeModel();
252   protected abstract OptionGroup getDefaultGroup();
253   //}}}
254 
255   //{{{ Private members
256 
257   //{{{ Instance variables
258   private String name;
259   private JSplitPane splitter;
260   private JTree paneTree;
261   private JPanel stage;
262   private JButton ok;
263   private JButton cancel;
264   private JButton apply;
265   private OptionPane currentPane;
266   private Map deferredOptionPanes;
267   //}}}
268 
269   //{{{ init() method
270   private void init(String name, String pane)
271   {
272     this.name = name;
273 
274     deferredOptionPanes = new HashMap();
275 
276     JPanel content = new JPanel(new BorderLayout(12,12));
277     content.setBorder(new EmptyBorder(12,12,12,12));
278     setContentPane(content);
279 
280     stage = new JPanel(new BorderLayout());
281 
282     paneTree = new JTree(createOptionTreeModel());
283     paneTree.setVisibleRowCount(1);
284     paneTree.setCellRenderer(new PaneNameRenderer());
285 
286     // looks bad with the OS X L&F, apparently...
287     if(!OperatingSystem.isMacOSLF())
288       paneTree.putClientProperty("JTree.lineStyle", "Angled");
289 
290     paneTree.setShowsRootHandles(true);
291     paneTree.setRootVisible(false);
292 
293     JScrollPane scroller = new JScrollPane(paneTree,
294       JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
295       JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
296     splitter = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
297       scroller,stage);
298     content.add(splitter, BorderLayout.CENTER);
299 
300     Box buttons = new Box(BoxLayout.X_AXIS);
301     buttons.add(Box.createGlue());
302 
303     ok = new JButton(jEdit.getProperty("common.ok"));
304     ok.addActionListener(this);
305     buttons.add(ok);
306     buttons.add(Box.createHorizontalStrut(6));
307     getRootPane().setDefaultButton(ok);
308     cancel = new JButton(jEdit.getProperty("common.cancel"));
309     cancel.addActionListener(this);
310     buttons.add(cancel);
311     buttons.add(Box.createHorizontalStrut(6));
312     apply = new JButton(jEdit.getProperty("common.apply"));
313     apply.addActionListener(this);
314     buttons.add(apply);
315 
316     buttons.add(Box.createGlue());
317 
318     content.add(buttons, BorderLayout.SOUTH);
319 
320     // register the Options dialog as a TreeSelectionListener.
321     // this is done before the initial selection to ensure that the
322     // first selected OptionPane is displayed on startup.
323     paneTree.getSelectionModel().addTreeSelectionListener(this);
324 
325     OptionGroup rootNode = (OptionGroup)paneTree.getModel().getRoot();
326     for(int i = 0; i < rootNode.getMemberCount(); i++)
327     {
328       paneTree.expandPath(new TreePath(
329       new Object[] { rootNode, rootNode.getMember(i) }));
330     }
331 
332     // returns false if no such pane exists; calling with null
333     // param selects first option pane found
334     if(!selectPane(rootNode,pane))
335       selectPane(rootNode,null);
336 
337     splitter.setDividerLocation(paneTree.getPreferredSize().width
338       + scroller.getVerticalScrollBar().getPreferredSize()
339       .width);
340 
341     GUIUtilities.loadGeometry(this,name);
342     int dividerLocation = jEdit.getIntegerProperty(name + ".splitter",-1);
343     if(dividerLocation != -1)
344       splitter.setDividerLocation(dividerLocation);
345 
346     // in case saved geometry is too small
347     updateSize();
348 
349     show();
350   } //}}}
351 
352   //{{{ selectPane() method
353   private boolean selectPane(OptionGroup node, String name)
354   {
355     return selectPane(node,name,new ArrayList());
356   } //}}}
357 
358   //{{{ selectPane() method
359   private boolean selectPane(OptionGroup node, String name, ArrayList path)
360   {
361     path.add(node);
362 
363     Enumeration enum = node.getMembers();
364     while(enum.hasMoreElements())
365     {
366       Object obj = enum.nextElement();
367       if(obj instanceof OptionGroup)
368       {
369         OptionGroup grp = (OptionGroup)obj;
370         if(grp.getName().equals(name))
371         {
372           path.add(grp);
373           path.add(grp.getMember(0));
374           TreePath treePath = new TreePath(
375             path.toArray());
376           paneTree.scrollPathToVisible(treePath);
377           paneTree.setSelectionPath(treePath);
378           return true;
379         }
380         else if(selectPane((OptionGroup)obj,name,path))
381           return true;
382       }
383       else if(obj instanceof OptionPane)
384       {
385         OptionPane pane = (OptionPane)obj;
386         if(pane.getName().equals(name)
387           || name == null)
388         {
389           path.add(pane);
390           TreePath treePath = new TreePath(
391             path.toArray());
392           paneTree.scrollPathToVisible(treePath);
393           paneTree.setSelectionPath(treePath);
394           return true;
395         }
396       }
397       else if(obj instanceof String)
398       {
399         String pane = (String)obj;
400         if(pane.equals(name)
401           || name == null)
402         {
403           path.add(pane);
404           TreePath treePath = new TreePath(
405             path.toArray());
406           paneTree.scrollPathToVisible(treePath);
407           paneTree.setSelectionPath(treePath);
408           return true;
409         }
410       }
411     }
412 
413     path.remove(node);
414 
415     return false;
416   } //}}}
417 
418   //{{{ save() method
419   private void save(Object obj)
420   {
421     if(obj instanceof OptionGroup)
422     {
423       OptionGroup grp = (OptionGroup)obj;
424       Enumeration members = grp.getMembers();
425       while(members.hasMoreElements())
426       {
427         save(members.nextElement());
428       }
429     }
430     else if(obj instanceof OptionPane)
431     {
432       try
433       {
434         ((OptionPane)obj).save();
435       }
436       catch(Throwable t)
437       {
438         Log.log(Log.ERROR,this,"Error saving options:");
439         Log.log(Log.ERROR,this,t);
440       }
441     }
442     else if(obj instanceof String)
443     {
444       save(deferredOptionPanes.get(obj));
445     }
446   } //}}}
447 
448   //{{{ updateSize() method
449   private void updateSize()
450   {
451     Dimension currentSize = getSize();
452     Dimension requestedSize = getPreferredSize();
453     Dimension newSize = new Dimension(
454       Math.max(currentSize.width,requestedSize.width),
455       Math.max(currentSize.height,requestedSize.height)
456     );
457     if(newSize.width < 300)
458       newSize.width = 300;
459     if(newSize.height < 200)
460       newSize.height = 200;
461     setSize(newSize);
462     validate();
463   } //}}}
464 
465   //}}}
466 
467   //{{{ PaneNameRenderer class
468   class PaneNameRenderer extends DefaultTreeCellRenderer
469   {
470     public PaneNameRenderer()
471     {
472       paneFont = UIManager.getFont("Tree.font");
473       if(paneFont == null)
474         paneFont = jEdit.getFontProperty("metal.secondary.font");
475       groupFont = paneFont.deriveFont(Font.BOLD);
476     }
477 
478     public Component getTreeCellRendererComponent(JTree tree,
479       Object value, boolean selected, boolean expanded,
480       boolean leaf, int row, boolean hasFocus)
481     {
482       super.getTreeCellRendererComponent(tree,value,
483         selected,expanded,leaf,row,hasFocus);
484 
485       String name = null;
486 
487       if (value instanceof OptionGroup)
488       {
489         setText(((OptionGroup)value).getLabel());
490         this.setFont(groupFont);
491       }
492       else if (value instanceof OptionPane)
493       {
494         name = ((OptionPane)value).getName();
495         this.setFont(paneFont);
496       }
497       else if (value instanceof String)
498       {
499         name = ((String)value);
500         this.setFont(paneFont);
501       }
502 
503       if (name != null)
504       {
505         String label = jEdit.getProperty("options." +
506           name + ".label");
507 
508         if (label == null)
509         {
510           setText("NO LABEL PROPERTY: " + name);
511         }
512         else
513         {
514           setText(label);
515         }
516       }
517 
518       setIcon(null);
519 
520       return this;
521     }
522 
523     private Font paneFont;
524     private Font groupFont;
525   } //}}}
526 
527   //{{{ OptionTreeModel class
528   public class OptionTreeModel implements TreeModel
529   {
530     public void addTreeModelListener(TreeModelListener l)
531     {
532       listenerList.add(TreeModelListener.class, l);
533     }
534 
535     public void removeTreeModelListener(TreeModelListener l)
536     {
537       listenerList.remove(TreeModelListener.class, l);
538     }
539 
540     public Object getChild(Object parent, int index)
541     {
542       if (parent instanceof OptionGroup)
543       {
544         return ((OptionGroup)parent).getMember(index);
545       }
546       else
547       {
548         return null;
549       }
550     }
551 
552     public int getChildCount(Object parent)
553     {
554       if (parent instanceof OptionGroup)
555       {
556         return ((OptionGroup)parent).getMemberCount();
557       }
558       else
559       {
560         return 0;
561       }
562     }
563 
564     public int getIndexOfChild(Object parent, Object child)
565     {
566       if (parent instanceof OptionGroup)
567       {
568         return ((OptionGroup)parent)
569           .getMemberIndex(child);
570       }
571       else
572       {
573         return -1;
574       }
575     }
576 
577     public Object getRoot()
578     {
579       return root;
580     }
581 
582     public boolean isLeaf(Object node)
583     {
584       return !(node instanceof OptionGroup);
585     }
586 
587     public void valueForPathChanged(TreePath path, Object newValue)
588     {
589       // this model may not be changed by the TableCellEditor
590     }
591 
592     protected void fireNodesChanged(Object source, Object[] path,
593       int[] childIndices, Object[] children)
594     {
595       Object[] listeners = listenerList.getListenerList();
596 
597       TreeModelEvent modelEvent = null;
598       for (int i = listeners.length - 2; i >= 0; i -= 2)
599       {
600         if (listeners[i] != TreeModelListener.class)
601           continue;
602 
603         if (modelEvent == null)
604         {
605           modelEvent = new TreeModelEvent(source,
606             path, childIndices, children);
607         }
608 
609         ((TreeModelListener)listeners[i + 1])
610           .treeNodesChanged(modelEvent);
611       }
612     }
613 
614     protected void fireNodesInserted(Object source, Object[] path,
615       int[] childIndices, Object[] children)
616     {
617       Object[] listeners = listenerList.getListenerList();
618 
619       TreeModelEvent modelEvent = null;
620       for (int i = listeners.length - 2; i >= 0; i -= 2)
621       {
622         if (listeners[i] != TreeModelListener.class)
623           continue;
624 
625         if (modelEvent == null)
626         {
627           modelEvent = new TreeModelEvent(source,
628             path, childIndices, children);
629         }
630 
631         ((TreeModelListener)listeners[i + 1])
632           .treeNodesInserted(modelEvent);
633       }
634     }
635 
636     protected void fireNodesRemoved(Object source, Object[] path,
637       int[] childIndices, Object[] children)
638     {
639       Object[] listeners = listenerList.getListenerList();
640 
641       TreeModelEvent modelEvent = null;
642       for (int i = listeners.length - 2; i >= 0; i -= 2)
643       {
644         if (listeners[i] != TreeModelListener.class)
645           continue;
646 
647         if (modelEvent == null)
648         {
649           modelEvent = new TreeModelEvent(source,
650             path, childIndices, children);
651         }
652 
653         ((TreeModelListener)listeners[i + 1])
654           .treeNodesRemoved(modelEvent);
655       }
656     }
657 
658     protected void fireTreeStructureChanged(Object source,
659       Object[] path, int[] childIndices, Object[] children)
660     {
661       Object[] listeners = listenerList.getListenerList();
662 
663       TreeModelEvent modelEvent = null;
664       for (int i = listeners.length - 2; i >= 0; i -= 2)
665       {
666         if (listeners[i] != TreeModelListener.class)
667           continue;
668 
669         if (modelEvent == null)
670         {
671           modelEvent = new TreeModelEvent(source,
672             path, childIndices, children);
673         }
674 
675         ((TreeModelListener)listeners[i + 1])
676           .treeStructureChanged(modelEvent);
677       }
678     }
679 
680     private OptionGroup root = new OptionGroup(null);
681     private EventListenerList listenerList = new EventListenerList();
682   } //}}}
683 }