PageRenderTime 30ms CodeModel.GetById 1ms RepoModel.GetById 0ms app.codeStats 0ms

/jEdit/tags/jedit-4-2-pre14/org/gjt/sp/jedit/gui/OptionsDialog.java

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