1 23 24 package org.gjt.sp.jedit.gui; 25 26 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 java.util.List ; 35 36 37 import org.gjt.sp.jedit.*; 38 import org.gjt.sp.util.Log; 39 41 46 public abstract class OptionsDialog extends EnhancedDialog 47 implements ActionListener, TreeSelectionListener 48 { 49 private String name; 51 private JSplitPane splitter; 52 protected JTree paneTree; 53 private JScrollPane stage; 54 private JButton ok; 55 private JButton cancel; 56 private JButton apply; 57 protected OptionPane currentPane; 58 private Map<Object , OptionPane> deferredOptionPanes; 59 61 68 protected OptionsDialog(Frame frame, String name, String pane) 69 { 70 super(frame, jEdit.getProperty(name + ".title"), true); 71 init(name,pane); 72 } 74 protected OptionsDialog(Dialog dialog, String name, String pane) 76 { 77 super(dialog, jEdit.getProperty(name + ".title"), true); 78 init(name,pane); 79 } 81 public void addOptionGroup(OptionGroup group) 83 { 84 getDefaultGroup().addOptionGroup(group); 85 } 87 public void addOptionPane(OptionPane pane) 89 { 90 getDefaultGroup().addOptionPane(pane); 91 } 93 public void ok() 95 { 96 if(currentPane != null) 97 jEdit.setProperty(name + ".last",currentPane.getName()); 98 ok(true); 99 } 101 public void cancel() 103 { 104 if(currentPane != null) 105 jEdit.setProperty(name + ".last",currentPane.getName()); 106 dispose(); 107 } 109 public void ok(boolean dispose) 111 { 112 OptionTreeModel m = (OptionTreeModel) paneTree 113 .getModel(); 114 save(m.getRoot()); 115 116 117 jEdit.propertiesChanged(); 118 119 jEdit.saveSettings(); 121 122 if(dispose) 124 dispose(); 125 } 127 public void dispose() 129 { 130 GUIUtilities.saveGeometry(this,name); 131 jEdit.setIntegerProperty(name + ".splitter",splitter.getDividerLocation()); 132 super.dispose(); 133 } 135 public void actionPerformed(ActionEvent evt) 137 { 138 Object source = evt.getSource(); 139 140 if(source == ok) 141 { 142 ok(); 143 } 144 else if(source == cancel) 145 { 146 cancel(); 147 } 148 else if(source == apply) 149 { 150 ok(false); 151 } 152 } 154 public void valueChanged(TreeSelectionEvent evt) 156 { 157 TreePath path = evt.getPath(); 158 159 if(path == null) 160 return; 161 162 Object lastPathComponent = path.getLastPathComponent(); 163 if(!(lastPathComponent instanceof String 164 || lastPathComponent instanceof OptionPane)) 165 { 166 return; 167 } 168 169 Object [] nodes = path.getPath(); 170 171 StringBuilder buf = new StringBuilder (); 172 173 OptionPane optionPane = null; 174 175 int lastIdx = nodes.length - 1; 176 177 for (int i = paneTree.isRootVisible() ? 0 : 1; 178 i <= lastIdx; i++) 179 { 180 String label; 181 Object node = nodes[i]; 182 if (node instanceof OptionPane) 183 { 184 optionPane = (OptionPane)node; 185 label = jEdit.getProperty("options." 186 + optionPane.getName() 187 + ".label"); 188 } 189 else if (node instanceof OptionGroup) 190 { 191 label = ((OptionGroup)node).getLabel(); 192 } 193 else if (node instanceof String ) 194 { 195 label = jEdit.getProperty("options." 196 + node + ".label"); 197 optionPane = deferredOptionPanes.get(node); 198 if(optionPane == null) 199 { 200 String propName = "options." + node + ".code"; 201 String code = jEdit.getProperty(propName); 202 if(code != null) 203 { 204 optionPane = (OptionPane) 205 BeanShell.eval( 206 jEdit.getActiveView(), 207 BeanShell.getNameSpace(), 208 code 209 ); 210 211 if(optionPane != null) 212 { 213 deferredOptionPanes.put( 214 node,optionPane); 215 } 216 else 217 continue; 218 } 219 else 220 { 221 Log.log(Log.ERROR,this,propName 222 + " not defined"); 223 continue; 224 } 225 } 226 } 227 else 228 { 229 continue; 230 } 231 232 buf.append(label); 233 234 if (i != lastIdx) 235 buf.append(": "); 236 } 237 238 if(optionPane == null) 239 return; 240 241 setTitle(jEdit.getProperty("options.title-template", 242 new Object [] { jEdit.getProperty(name + ".title"), 243 buf.toString() })); 244 245 try 246 { 247 optionPane.init(); 248 } 249 catch(Throwable t) 250 { 251 Log.log(Log.ERROR,this,"Error initializing options:"); 252 Log.log(Log.ERROR,this,t); 253 } 254 255 currentPane = optionPane; 256 stage.setViewportView(currentPane.getComponent()); 257 stage.revalidate(); 258 stage.repaint(); 259 260 if(!isShowing()) 261 addNotify(); 262 263 updateSize(); 264 265 currentPane = optionPane; 266 } 268 274 protected abstract OptionTreeModel createOptionTreeModel(); 275 277 protected abstract OptionGroup getDefaultGroup(); 278 280 292 protected void init(String name, String pane) 293 { 294 this.name = name; 295 296 deferredOptionPanes = new HashMap<Object , OptionPane>(); 297 298 JPanel content = new JPanel(new BorderLayout(12,12)); 299 content.setBorder(new EmptyBorder(12,12,12,12)); 300 setContentPane(content); 301 stage = new JScrollPane(); 302 303 paneTree = new JTree(createOptionTreeModel()); 304 paneTree.setVisibleRowCount(1); 305 paneTree.setCellRenderer(new PaneNameRenderer()); 306 307 if(!OperatingSystem.isMacOSLF()) 309 paneTree.putClientProperty("JTree.lineStyle", "Angled"); 310 311 paneTree.setShowsRootHandles(true); 312 paneTree.setRootVisible(false); 313 314 JScrollPane scroller = new JScrollPane(paneTree, 315 ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, 316 ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED); 317 scroller.setMinimumSize(new Dimension(100, 0)); 318 splitter = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, 319 jEdit.getBooleanProperty("appearance.continuousLayout"), 320 scroller, 321 stage); 322 content.add(splitter, BorderLayout.CENTER); 323 324 Box buttons = new Box(BoxLayout.X_AXIS); 325 buttons.add(Box.createGlue()); 326 327 ok = new JButton(jEdit.getProperty("common.ok")); 328 ok.addActionListener(this); 329 buttons.add(ok); 330 buttons.add(Box.createHorizontalStrut(6)); 331 getRootPane().setDefaultButton(ok); 332 cancel = new JButton(jEdit.getProperty("common.cancel")); 333 cancel.addActionListener(this); 334 buttons.add(cancel); 335 buttons.add(Box.createHorizontalStrut(6)); 336 apply = new JButton(jEdit.getProperty("common.apply")); 337 apply.addActionListener(this); 338 buttons.add(apply); 339 340 buttons.add(Box.createGlue()); 341 342 content.add(buttons, BorderLayout.SOUTH); 343 344 paneTree.getSelectionModel().addTreeSelectionListener(this); 348 349 OptionGroup rootNode = (OptionGroup)paneTree.getModel().getRoot(); 350 for(int i = 0; i < rootNode.getMemberCount(); i++) 351 { 352 paneTree.expandPath(new TreePath( 353 new Object [] { rootNode, rootNode.getMember(i) })); 354 } 355 356 if(!selectPane(rootNode, pane)) 359 selectPane(rootNode,null); 360 361 splitter.setDividerLocation(paneTree.getPreferredSize().width 362 + scroller.getVerticalScrollBar().getPreferredSize() 363 .width); 364 365 GUIUtilities.loadGeometry(this,name); 366 int dividerLocation = jEdit.getIntegerProperty(name + ".splitter",-1); 367 if(dividerLocation != -1) 368 splitter.setDividerLocation(dividerLocation); 369 370 updateSize(); 372 373 setVisible(true); 374 } 376 378 private boolean selectPane(OptionGroup node, String name) 380 { 381 return selectPane(node,name,new ArrayList()); 382 } 384 private boolean selectPane(OptionGroup node, String name, List path) 386 { 387 path.add(node); 388 389 Enumeration e = node.getMembers(); 390 while(e.hasMoreElements()) 391 { 392 Object obj = e.nextElement(); 393 if(obj instanceof OptionGroup) 394 { 395 OptionGroup grp = (OptionGroup)obj; 396 if(grp.getName().equals(name)) 397 { 398 path.add(grp); 399 path.add(grp.getMember(0)); 400 TreePath treePath = new TreePath( 401 path.toArray()); 402 paneTree.scrollPathToVisible(treePath); 403 paneTree.setSelectionPath(treePath); 404 return true; 405 } 406 else if(selectPane((OptionGroup)obj,name,path)) 407 return true; 408 } 409 else if(obj instanceof OptionPane) 410 { 411 OptionPane pane = (OptionPane)obj; 412 if(pane.getName().equals(name) 413 || name == null) 414 { 415 path.add(pane); 416 TreePath treePath = new TreePath( 417 path.toArray()); 418 paneTree.scrollPathToVisible(treePath); 419 paneTree.setSelectionPath(treePath); 420 return true; 421 } 422 } 423 else if(obj instanceof String ) 424 { 425 String pane = (String )obj; 426 if(pane.equals(name) 427 || name == null) 428 { 429 path.add(pane); 430 TreePath treePath = new TreePath( 431 path.toArray()); 432 paneTree.scrollPathToVisible(treePath); 433 paneTree.setSelectionPath(treePath); 434 return true; 435 } 436 } 437 } 438 439 path.remove(node); 440 441 return false; 442 } 444 private void save(Object obj) 446 { 447 if(obj instanceof OptionGroup) 448 { 449 OptionGroup grp = (OptionGroup)obj; 450 Enumeration members = grp.getMembers(); 451 while(members.hasMoreElements()) 452 { 453 save(members.nextElement()); 454 } 455 } 456 else if(obj instanceof OptionPane) 457 { 458 try 459 { 460 ((OptionPane)obj).save(); 461 } 462 catch(Throwable t) 463 { 464 Log.log(Log.ERROR,this,"Error saving options:"); 465 Log.log(Log.ERROR,this,t); 466 } 467 } 468 else if(obj instanceof String ) 469 { 470 save(deferredOptionPanes.get(obj)); 471 } 472 } 474 private void updateSize() 476 { 477 Dimension currentSize = getSize(); 478 Dimension requestedSize = getPreferredSize(); 479 Dimension newSize = new Dimension( 480 Math.max(currentSize.width,requestedSize.width), 481 Math.max(currentSize.height,requestedSize.height) 482 ); 483 if(newSize.width < 300) 484 newSize.width = 300; 485 if(newSize.height < 200) 486 newSize.height = 200; 487 setSize(newSize); 488 validate(); 489 } 491 493 public static class PaneNameRenderer extends DefaultTreeCellRenderer 495 { 496 public PaneNameRenderer() 497 { 498 paneFont = UIManager.getFont("Tree.font"); 499 if(paneFont == null) 500 paneFont = jEdit.getFontProperty("metal.secondary.font"); 501 groupFont = paneFont.deriveFont(Font.BOLD); 502 } 503 504 public Component getTreeCellRendererComponent(JTree tree, 505 Object value, boolean selected, boolean expanded, 506 boolean leaf, int row, boolean hasFocus) 507 { 508 super.getTreeCellRendererComponent(tree,value, 509 selected,expanded,leaf,row,hasFocus); 510 511 String name = null; 512 513 if (value instanceof OptionGroup) 514 { 515 setText(((OptionGroup)value).getLabel()); 516 setFont(groupFont); 517 } 518 else if (value instanceof OptionPane) 519 { 520 name = ((OptionPane)value).getName(); 521 setFont(paneFont); 522 } 523 else if (value instanceof String ) 524 { 525 name = (String ) value; 526 setFont(paneFont); 527 } 528 529 if (name != null) 530 { 531 String label = jEdit.getProperty("options." + 532 name + ".label"); 533 534 if (label == null) 535 { 536 setText("NO LABEL PROPERTY: " + name); 537 } 538 else 539 { 540 setText(label); 541 } 542 } 543 544 setIcon(null); 545 546 return this; 547 } 548 549 private Font paneFont; 550 private final Font groupFont; 551 } 553 public class OptionTreeModel implements TreeModel 555 { 556 public void addTreeModelListener(TreeModelListener l) 557 { 558 listenerList.add(TreeModelListener.class, l); 559 } 560 561 public void removeTreeModelListener(TreeModelListener l) 562 { 563 listenerList.remove(TreeModelListener.class, l); 564 } 565 566 public Object getChild(Object parent, int index) 567 { 568 if (parent instanceof OptionGroup) 569 { 570 return ((OptionGroup)parent).getMember(index); 571 } 572 else 573 { 574 return null; 575 } 576 } 577 578 public int getChildCount(Object parent) 579 { 580 if (parent instanceof OptionGroup) 581 { 582 return ((OptionGroup)parent).getMemberCount(); 583 } 584 else 585 { 586 return 0; 587 } 588 } 589 590 public int getIndexOfChild(Object parent, Object child) 591 { 592 if (parent instanceof OptionGroup) 593 { 594 return ((OptionGroup)parent) 595 .getMemberIndex(child); 596 } 597 else 598 { 599 return -1; 600 } 601 } 602 603 public Object getRoot() 604 { 605 return root; 606 } 607 608 public boolean isLeaf(Object node) 609 { 610 return !(node instanceof OptionGroup); 611 } 612 613 public void valueForPathChanged(TreePath path, Object newValue) 614 { 615 } 617 618 protected void fireNodesChanged(Object source, Object [] path, 619 int[] childIndices, Object [] children) 620 { 621 Object [] listeners = listenerList.getListenerList(); 622 623 TreeModelEvent modelEvent = null; 624 for (int i = listeners.length - 2; i >= 0; i -= 2) 625 { 626 if (listeners[i] != TreeModelListener.class) 627 continue; 628 629 if (modelEvent == null) 630 { 631 modelEvent = new TreeModelEvent(source, 632 path, childIndices, children); 633 } 634 635 ((TreeModelListener)listeners[i + 1]) 636 .treeNodesChanged(modelEvent); 637 } 638 } 639 640 protected void fireNodesInserted(Object source, Object [] path, 641 int[] childIndices, Object [] children) 642 { 643 Object [] listeners = listenerList.getListenerList(); 644 645 TreeModelEvent modelEvent = null; 646 for (int i = listeners.length - 2; i >= 0; i -= 2) 647 { 648 if (listeners[i] != TreeModelListener.class) 649 continue; 650 651 if (modelEvent == null) 652 { 653 modelEvent = new TreeModelEvent(source, 654 path, childIndices, children); 655 } 656 657 ((TreeModelListener)listeners[i + 1]) 658 .treeNodesInserted(modelEvent); 659 } 660 } 661 662 protected void fireNodesRemoved(Object source, Object [] path, 663 int[] childIndices, Object [] children) 664 { 665 Object [] listeners = listenerList.getListenerList(); 666 667 TreeModelEvent modelEvent = null; 668 for (int i = listeners.length - 2; i >= 0; i -= 2) 669 { 670 if (listeners[i] != TreeModelListener.class) 671 continue; 672 673 if (modelEvent == null) 674 { 675 modelEvent = new TreeModelEvent(source, 676 path, childIndices, children); 677 } 678 679 ((TreeModelListener)listeners[i + 1]) 680 .treeNodesRemoved(modelEvent); 681 } 682 } 683 684 protected void fireTreeStructureChanged(Object source, 685 Object [] path, int[] childIndices, Object [] children) 686 { 687 Object [] listeners = listenerList.getListenerList(); 688 689 TreeModelEvent modelEvent = null; 690 for (int i = listeners.length - 2; i >= 0; i -= 2) 691 { 692 if (listeners[i] != TreeModelListener.class) 693 continue; 694 695 if (modelEvent == null) 696 { 697 modelEvent = new TreeModelEvent(source, 698 path, childIndices, children); 699 } 700 701 ((TreeModelListener)listeners[i + 1]) 702 .treeStructureChanged(modelEvent); 703 } 704 } 705 706 private final OptionGroup root = new OptionGroup(null); 707 private final EventListenerList listenerList = new EventListenerList(); 708 } } 710 | Popular Tags |