1 19 20 package org.netbeans.core.actions; 21 22 import java.awt.Component ; 23 import java.awt.Dialog ; 24 import java.awt.Dimension ; 25 import java.awt.Font ; 26 import java.awt.GridBagConstraints ; 27 import java.awt.Toolkit ; 28 import java.awt.event.ActionEvent ; 29 import java.awt.event.ActionListener ; 30 import java.awt.event.MouseEvent ; 31 import java.awt.event.MouseListener ; 32 import java.beans.PropertyChangeEvent ; 33 import java.beans.PropertyChangeListener ; 34 import java.io.ObjectStreamException ; 35 import java.lang.ref.Reference ; 36 import java.lang.ref.WeakReference ; 37 import java.util.ArrayList ; 38 import java.util.Collection ; 39 import java.util.Iterator ; 40 import java.util.List ; 41 import javax.swing.JButton ; 42 import javax.swing.JComponent ; 43 import javax.swing.JSplitPane ; 44 import javax.swing.KeyStroke ; 45 import javax.swing.SwingUtilities ; 46 import javax.swing.UIManager ; 47 import javax.swing.border.Border ; 48 import javax.swing.table.JTableHeader ; 49 import org.netbeans.core.NbMainExplorer; 50 import org.netbeans.core.NbPlaces; 51 import org.netbeans.core.NbTopManager; 52 import org.netbeans.core.projects.SettingChildren; 53 import org.netbeans.core.startup.layers.SessionManager; 54 import org.openide.DialogDescriptor; 55 import org.openide.DialogDisplayer; 56 import org.openide.awt.Mnemonics; 57 import org.openide.awt.StatusDisplayer; 58 import org.openide.cookies.InstanceCookie; 59 import org.openide.explorer.ExplorerManager; 60 import org.netbeans.beaninfo.ExplorerPanel; 61 import org.openide.explorer.propertysheet.PropertySheetView; 62 import org.openide.explorer.view.NodeTableModel; 63 import org.openide.explorer.view.TreeTableView; 64 import org.openide.explorer.view.TreeView; 65 import org.openide.loaders.DataObject; 66 import org.openide.loaders.DataShadow; 67 import org.openide.nodes.FilterNode; 68 import org.openide.nodes.Node; 69 import org.openide.nodes.PropertySupport; 70 import org.openide.util.HelpCtx; 71 import org.openide.util.Mutex; 72 import org.openide.util.NbBundle; 73 import org.openide.util.RequestProcessor; 74 import org.openide.util.WeakListeners; 75 import org.openide.util.actions.CallableSystemAction; 76 import org.openide.windows.TopComponent; 77 78 83 public class OptionsAction extends CallableSystemAction { 84 85 public OptionsAction() { 86 putValue("noIconInMenu", Boolean.TRUE); } 88 89 private static final String HELP_ID = "org.netbeans.core.actions.OptionsAction"; 91 92 private Reference <Dialog > dialogWRef = new WeakReference <Dialog >(null); 93 94 95 public void performAction () { 96 final OptionsPanel optionPanel = OptionsPanel.singleton (); 97 98 Mutex.EVENT.readAccess(new Runnable () { 99 public void run() { 100 Dialog dialog = dialogWRef.get(); 101 102 if(dialog == null || !dialog.isShowing()) { 103 JButton closeButton = new JButton (); 104 Mnemonics.setLocalizedText(closeButton, NbBundle.getMessage(OptionsAction.class, "CTL_close_button")); 105 closeButton.getAccessibleContext().setAccessibleDescription(NbBundle.getMessage(OptionsAction.class, "ACSD_close_button")); 106 String title = (String ) OptionsAction.this.getValue 107 ("optionsDialogTitle"); 108 DialogDescriptor dd = new DialogDescriptor( 109 InitPanel.getDefault(optionPanel), 110 title == null ? optionPanel.getName() : title, 111 false, 112 new Object [] {closeButton}, 113 closeButton, 114 DialogDescriptor.DEFAULT_ALIGN, 115 getHelpCtx (), 116 null); 117 118 String name = (String ) OptionsAction.this.getValue 120 ("additionalActionName"); 121 if (name != null) { 122 ActionListener actionListener = (ActionListener ) 123 OptionsAction.this.getValue ("additionalActionListener"); 124 JButton additionalButton = new JButton (); 125 Mnemonics.setLocalizedText (additionalButton, name); 126 additionalButton.addActionListener (new ActionListener () { 127 public void actionPerformed (ActionEvent e) { 128 Dialog dialog = dialogWRef.get (); 129 dialog.setVisible (false); 130 } 131 }); 132 additionalButton.addActionListener (actionListener); 133 dd.setAdditionalOptions (new Object [] {additionalButton}); 134 } 135 137 optionPanel.setDialogDescriptor(dd); 139 140 dialog = DialogDisplayer.getDefault().createDialog(dd); 141 dialog.setVisible(true); 142 dialogWRef = new WeakReference <Dialog >(dialog); 143 } else { 144 dialog.toFront(); 145 } 146 } 147 }); } 149 150 protected boolean asynchronous() { 151 return false; 152 } 153 154 public HelpCtx getHelpCtx() { 155 return new HelpCtx (HELP_ID); 156 } 157 158 public String getName() { 159 return NbBundle.getBundle(OptionsAction.class).getString("Options"); 160 } 161 162 163 public static final class OptionsPanel extends NbMainExplorer.ExplorerTab 164 implements PropertyChangeListener { 165 166 public static final String MODE_NAME = "options"; 167 168 private static OptionsPanel singleton; 169 170 private static String TEMPLATES_DISPLAY_NAME = NbBundle.getBundle(OptionsAction.class).getString("CTL_Templates_name"); 172 173 private Collection <Node> toExpand; 174 private transient boolean expanded; 175 176 private transient Node rootNode; 177 178 private transient Reference <DialogDescriptor> descriptorRef = new WeakReference <DialogDescriptor>(null); 180 181 182 private OptionsPanel () { 183 validateRootContext (); 184 putClientProperty("NamingType", "BothOnlyCompName"); putClientProperty("TabPolicy", "HideWhenAlone"); 189 getExplorerManager().addPropertyChangeListener(this); 190 } 191 192 194 public int getPersistenceType() { 195 return TopComponent.PERSISTENCE_ALWAYS; 196 } 197 198 protected String preferredID () { 199 return "options"; } 201 202 public void propertyChange(PropertyChangeEvent evt) { 204 if(ExplorerManager.PROP_SELECTED_NODES.equals(evt.getPropertyName())) { 205 DialogDescriptor dd = descriptorRef.get(); 206 if(dd != null) { 207 dd.setHelpCtx(getHelpCtx()); 208 } 209 } 210 } 211 public void setDialogDescriptor(DialogDescriptor dd) { 213 descriptorRef = new WeakReference <DialogDescriptor>(dd); 214 } 215 216 public HelpCtx getHelpCtx () { 217 HelpCtx defaultHelp = new HelpCtx (HELP_ID); 218 HelpCtx help = org.openide.explorer.ExplorerUtils.getHelpCtx ( 219 getExplorerManager ().getSelectedNodes (), 220 defaultHelp 221 ); 222 if (!defaultHelp.equals (help)) { 225 Node node = getExplorerManager ().getSelectedNodes ()[0]; 227 HelpCtx readHelpId = getHelpId (node); 228 if (readHelpId != null) return readHelpId; 229 230 while (node != null && !TEMPLATES_DISPLAY_NAME.equals (node.getDisplayName ())) { 232 readHelpId = getHelpId (node); 233 if (readHelpId != null) return readHelpId; 234 node = node.getParentNode (); 235 } 236 if (node != null && TEMPLATES_DISPLAY_NAME.equals (node.getDisplayName ())) { 237 return new HelpCtx ("org.netbeans.core.actions.OptionsAction$TemplatesSubnode"); } 239 } 240 return help; 241 } 242 243 private HelpCtx getHelpId (Node node) { 244 DataObject dataObj = (DataObject)node.getCookie (DataObject.class); 246 if (dataObj != null) { 247 Object o = dataObj.getPrimaryFile ().getAttribute ("helpID"); if (o != null) { 249 return new HelpCtx (o.toString ()); 250 } 251 } 252 return null; 253 } 254 255 256 static OptionsPanel singleton () { 257 if (singleton == null) { 258 singleton = new OptionsPanel(); 259 } 260 return singleton; 261 } 262 263 private transient JSplitPane split=null; 264 protected TreeView initGui () { 265 TTW retVal = new TTW () ; 266 267 268 split = new JSplitPane (JSplitPane.HORIZONTAL_SPLIT); 269 PropertySheetView propertyView = new PropertySheetView(); 270 271 split.setLeftComponent(retVal); 272 split.setRightComponent(propertyView); 273 split.setBorder((Border )UIManager.get("Nb.ScrollPane.border")); 276 setLayout (new java.awt.GridBagLayout ()); 277 278 GridBagConstraints gridBagConstraints = new GridBagConstraints (); 279 gridBagConstraints.fill = GridBagConstraints.BOTH; 280 gridBagConstraints.weightx = 1.0; 281 gridBagConstraints.weighty = 1.0; 282 gridBagConstraints.gridwidth = 2; 283 add (split, gridBagConstraints); 284 285 return retVal; 286 } 287 288 290 public Dimension getPreferredSize() { 291 Dimension result = super.getPreferredSize(); 294 Font treeFont = UIManager.getFont("Tree.font"); int fontsize = treeFont != null ? treeFont.getSize() : 11; 296 if (fontsize > 11) { 297 int factor = fontsize - 11; 298 result.height += 15 * factor; 299 result.width += 50 * factor; 300 Dimension screen = Toolkit.getDefaultToolkit().getScreenSize(); 301 if (result.height > screen.height) { 302 result.height = screen.height -30; 303 } 304 if (result.width > screen.width) { 305 result.width = screen.width -30; 306 } 307 } else { 308 result.width += 20; 309 result.height +=20; 310 } 311 312 return result; 313 } 314 315 318 protected void updateTitle () { 319 } 321 322 boolean isPrepared () { 323 return toExpand != null; 324 } 325 326 public void prepareNodes() { 327 if (toExpand == null) { 328 List <Node> arr = new ArrayList <Node> (101); 329 expandNodes(getRootContext (), 2, arr); 330 toExpand = arr; 331 } 332 } 333 334 335 protected void componentShowing () { 336 super.componentShowing (); 337 if (!expanded) { 338 ((TTW)view).expandTheseNodes (toExpand, getExplorerManager ().getRootContext ()); 339 expanded = true; 340 } 341 split.setDividerLocation(getPreferredSize().width / 2); 343 } 344 345 346 protected void validateRootContext () { 347 Node n = initRC (); 348 setRootContext (n); 349 } 350 351 352 public Object readResolve () 353 throws ObjectStreamException { 354 if (singleton == null) { 355 singleton = this; 356 } 357 singleton.scheduleValidation(); 358 rootNode = getRootContext (); 360 return singleton; 361 } 362 363 private synchronized Node initRC () { 364 if (rootNode == null) { 365 rootNode = new OptionsFilterNode (); 366 } 367 return rootNode; 368 } 369 370 372 private static void expandNodes (Node n, final int depth, final Collection <Node> list) { 373 if (depth == 0) { 374 return; 375 } 376 377 DataObject obj = (DataObject)n.getCookie(DataObject.class); 378 if (obj instanceof DataShadow) { 379 obj = ((DataShadow)obj).getOriginal(); 380 } 381 382 if (obj != null) { 383 if (!obj.getPrimaryFile().getPath().startsWith ("UI/Services")) { return; 385 } 386 387 InstanceCookie ic = (InstanceCookie)obj.getCookie (InstanceCookie.class); 388 if (ic != null) { 389 390 if (ic instanceof InstanceCookie.Of) { 391 if (((InstanceCookie.Of)ic).instanceOf (Node.class)) { 392 return; 393 } 394 } 395 } 396 } 397 398 if (!list.contains (n)) { 400 list.add (n); 401 } 402 403 Node[] arr = n.getChildren().getNodes(true); 404 for (int i = 0; i < arr.length; i++) { 405 final Node p = arr[i]; 406 expandNodes(p, depth - 1, list); 407 } 408 } 409 410 414 417 private static class NTM extends NodeTableModel { 418 public NTM () { 419 super (); 420 } 421 422 protected Node.Property getPropertyFor(Node node, Node.Property prop) { 423 Object value = node.getValue (prop.getName()); 424 if (value instanceof Node.Property) { 425 return (Node.Property)value; 426 } 427 428 return null; 429 } 430 } 431 432 private static class TTW extends TreeTableView implements MouseListener , PropertyChangeListener , java.awt.event.ActionListener { 433 434 private final Node.Property indicator = new IndicatorProperty(); 435 436 private final Node.Property session = new SettingChildren.FileStateProperty (SettingChildren.PROP_LAYER_SESSION); 437 438 private final Node.Property modules = new SettingChildren.FileStateProperty (SettingChildren.PROP_LAYER_MODULES); 439 440 441 private Node.Property active_set [] = null; 442 PropertyChangeListener weakL = null; 443 444 public TTW () { 445 super (new NTM ()); 446 447 refreshColumns (true); 448 addMouseListener (this); 449 weakL = WeakListeners.propertyChange(this, SessionManager.getDefault ()); 450 SessionManager.getDefault ().addPropertyChangeListener (weakL); 451 452 registerKeyboardAction( 453 this, 454 KeyStroke.getKeyStroke('+'), 455 JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT 456 ); 457 458 getAccessibleContext().setAccessibleName(NbBundle.getBundle(OptionsAction.class).getString("ACSN_optionsTree")); 459 getAccessibleContext().setAccessibleDescription(NbBundle.getBundle(OptionsAction.class).getString("ACSD_optionsTree")); 460 } 461 public void mouseExited (MouseEvent evt) { 462 } 463 public void mouseReleased (MouseEvent evt) { 464 } 465 public void mousePressed (MouseEvent evt) { 466 } 467 public void mouseClicked (MouseEvent evt) { 468 Component c = evt.getComponent (); 469 if (c instanceof JTableHeader ) { 470 JTableHeader h = (JTableHeader )c; 471 472 if (1 == h.columnAtPoint (evt.getPoint ())) { 474 refreshColumns (true); 475 } 476 } 477 } 478 public void mouseEntered (MouseEvent evt) { 479 } 480 public void propertyChange(PropertyChangeEvent evt) { 481 if (SessionManager.PROP_OPEN.equals (evt.getPropertyName ())) { 482 refreshColumns (false); 483 } 484 } 485 private void refreshColumns (boolean changeSets) { 486 Node.Property new_set [] = active_set; 487 int length = active_set == null ? 0 : active_set.length; 488 489 if ((changeSets && length == 1) || (!changeSets && length > 1)) { 490 new_set = new Node.Property[] {indicator, session, modules}; 492 493 indicator.setDisplayName ( 494 NbBundle.getMessage(OptionsAction.class, "LBL_IndicatorProperty_Name_Expanded")); indicator.setShortDescription ( 496 NbBundle.getMessage(OptionsAction.class, "LBL_IndicatorProperty_Description_Expanded")); } 498 else { 499 if (changeSets) { 500 new_set = new Node.Property[] {indicator}; 501 indicator.setDisplayName ( 502 NbBundle.getMessage(OptionsAction.class, "LBL_IndicatorProperty_Name")); indicator.setShortDescription ( 504 NbBundle.getMessage(OptionsAction.class, "LBL_IndicatorProperty_Description")); } 506 } 507 508 if (active_set != new_set) { 509 final Node.Property set [] = new_set; 511 if (SwingUtilities.isEventDispatchThread()) { 512 setNewSet(set); 513 } else { 514 SwingUtilities.invokeLater (new Runnable () { 515 public void run () { 516 setNewSet(set); 517 } 518 }); 519 } 520 active_set = new_set; 522 } 523 } 524 525 private void setNewSet (Node.Property[] set) { 526 setProperties (set); 528 setTreePreferredWidth(set.length == 1 ? 480 : 300); 530 setTableColumnPreferredWidth (0, 20); 531 for (int i = 1; i < set.length; i++) { 532 setTableColumnPreferredWidth (i, 60); 533 } 534 } 535 536 public void actionPerformed(ActionEvent e) { 537 refreshColumns(true); 538 } 539 540 public void expandTheseNodes (Collection <Node> paths, Node root) { 541 Iterator <Node> it = paths.iterator(); 542 543 Node first = null; 544 while (it.hasNext()) { 545 Node n = it.next(); 546 if (first == null) { 547 first = n; 548 } 549 550 this.expandNode(n); 551 } 552 553 if (first != null) { 554 collapseNode (first); 555 expandNode (first); 556 } 557 558 tree.scrollRowToVisible(0); 560 } 561 562 563 private static final class IndicatorProperty extends PropertySupport.ReadOnly<String > { 564 565 public IndicatorProperty() { 566 super("indicator", String .class, "", ""); } 568 569 public String getValue() { 570 return ""; } 572 573 } 574 575 } 576 577 578 private static class OptionsFilterNode extends FilterNode { 579 public OptionsFilterNode () { 580 super ( 581 NbPlaces.getDefault().session(), 582 new SettingChildren (NbPlaces.getDefault().session()) 583 ); 584 } 585 public HelpCtx getHelpCtx () { 586 return new HelpCtx (OptionsFilterNode.class); 587 } 588 589 public Node.Handle getHandle () { 590 return new H (); 591 } 592 593 private static class H implements Node.Handle { 594 H() {} 595 596 private static final long serialVersionUID = -5158460093499159177L; 597 598 public Node getNode () throws java.io.IOException { 599 return new OptionsFilterNode (); 600 } 601 } 602 } 603 604 } } 606 | Popular Tags |