1 19 20 package org.openide.awt; 21 22 import java.awt.Component ; 23 import java.awt.EventQueue ; 24 import java.awt.event.KeyEvent ; 25 import java.io.Externalizable ; 26 import java.io.IOException ; 27 import java.io.ObjectInput ; 28 import java.io.ObjectOutput ; 29 import java.util.ArrayList ; 30 import java.util.Arrays ; 31 import java.util.Iterator ; 32 import java.util.LinkedList ; 33 import javax.swing.Action ; 34 import javax.swing.BorderFactory ; 35 import javax.swing.ImageIcon ; 36 import javax.swing.JButton ; 37 import javax.swing.JMenu ; 38 import javax.swing.JMenuBar ; 39 import javax.swing.JMenuItem ; 40 import javax.swing.JSeparator ; 41 import javax.swing.KeyStroke ; 42 import javax.swing.UIManager ; 43 import javax.swing.event.ChangeEvent ; 44 import javax.swing.event.ChangeListener ; 45 import org.openide.cookies.InstanceCookie; 46 import org.openide.filesystems.FileObject; 47 import org.openide.filesystems.Repository; 48 import org.openide.loaders.DataFolder; 49 import org.openide.loaders.DataObject; 50 import org.openide.loaders.FolderInstance; 51 import org.openide.loaders.InstanceSupport; 52 import org.openide.nodes.Node; 53 import org.openide.nodes.NodeEvent; 54 import org.openide.nodes.NodeListener; 55 import org.openide.nodes.NodeMemberEvent; 56 import org.openide.nodes.NodeReorderEvent; 57 import org.openide.util.Exceptions; 58 import org.openide.util.NbBundle; 59 import org.openide.util.Task; 60 import org.openide.util.Utilities; 61 import org.openide.util.actions.Presenter; 62 63 88 public class MenuBar extends JMenuBar implements Externalizable { 89 90 91 private MenuBarFolder menuBarFolder; 92 93 97 98 static final long serialVersionUID =-4721949937356581268L; 99 100 103 public MenuBar() { 104 super(); 105 } 106 107 111 public MenuBar(DataFolder folder) { 112 this(); 113 boolean GTK = "GTK".equals(UIManager.getLookAndFeel().getID()); 114 if (!GTK) { setBorder (BorderFactory.createEmptyBorder()); 117 } 118 DataFolder theFolder = folder; 119 if (theFolder == null) { 120 FileObject fo = Repository.getDefault().getDefaultFileSystem().findResource("Menu"); 121 if (fo == null) throw new IllegalStateException ("No Menu/"); theFolder = DataFolder.findFolder(fo); 123 } 124 startLoading(theFolder); 125 126 if(folder != null) { 127 getAccessibleContext().setAccessibleDescription(folder.getName()); 128 } 129 } 130 131 public void addImpl (Component c, Object constraint, int idx) { 132 if (Utilities.isMac() && 136 Boolean.getBoolean ("apple.laf.useScreenMenuBar")) { if (!(c instanceof JMenu )) { 138 return; 139 } 140 } 141 super.addImpl (c, constraint, idx); 142 } 143 144 148 protected boolean processKeyBinding(KeyStroke ks, 149 KeyEvent e, 150 int condition, 151 boolean pressed) { 152 if (Utilities.isMac()) { 153 int mods = e.getModifiers(); 154 boolean isCtrl = (mods & KeyEvent.CTRL_MASK) != 0; 155 boolean isAlt = (mods & KeyEvent.ALT_MASK) != 0; 156 if (isAlt) { 157 return false; 158 } 159 if (isAlt && !isCtrl) { 160 mods = mods & ~ KeyEvent.ALT_MASK; 161 mods = mods & ~ KeyEvent.ALT_DOWN_MASK; 162 mods |= KeyEvent.CTRL_MASK; 163 mods |= KeyEvent.CTRL_DOWN_MASK; 164 } else if (!isAlt && isCtrl) { 165 mods = mods & ~ KeyEvent.CTRL_MASK; 166 mods = mods & ~ KeyEvent.CTRL_DOWN_MASK; 167 mods |= KeyEvent.ALT_MASK; 168 mods |= KeyEvent.ALT_DOWN_MASK; 169 } else if (!isAlt && !isCtrl) { 170 return super.processKeyBinding (ks, e, condition, pressed); 171 } 172 173 KeyEvent newEvent = new MarkedKeyEvent ((Component ) e.getSource(), e.getID(), 174 e.getWhen(), mods, e.getKeyCode(), e.getKeyChar(), 175 e.getKeyLocation()); 176 177 KeyStroke newStroke = e.getID() == KeyEvent.KEY_TYPED ? 178 KeyStroke.getKeyStroke (ks.getKeyChar(), mods) : 179 KeyStroke.getKeyStroke (ks.getKeyCode(), mods, 180 !ks.isOnKeyRelease()); 181 182 boolean result = super.processKeyBinding (newStroke, newEvent, 183 condition, pressed); 184 185 if (newEvent.isConsumed()) { 186 e.consume(); 187 } 188 return result; 189 } else { 190 return super.processKeyBinding (ks, e, condition, pressed); 191 } 192 } 193 194 195 public void waitFinished () { 196 menuBarFolder.instanceFinished(); 197 } 198 199 203 public void writeExternal(ObjectOutput out) throws IOException { 204 out.writeObject(menuBarFolder.getFolder()); 205 } 206 207 213 public void readExternal(ObjectInput in) throws IOException , ClassNotFoundException { 214 startLoading((DataFolder)in.readObject()); 215 } 216 217 218 void startLoading (final DataFolder folder) { 219 menuBarFolder = new MenuBarFolder(folder); 220 } 221 222 227 static void allInstances (InstanceCookie[] arr, java.util.List <Object > list) { 228 Exception ex = null; 229 230 for (int i = 0; i < arr.length; i++) { 231 232 Exception newEx = null; 233 try { 234 Object o = arr[i].instanceCreate(); 235 list.add (o); 236 } catch (ClassNotFoundException e) { 237 newEx = e; 238 } catch (IOException e) { 239 newEx = e; 240 } 241 242 if (newEx != null) { 243 Throwable t = newEx; 244 while (true) { 245 if (t.getCause() == null) { 246 t.initCause(ex); 247 break; 248 } 249 t = t.getCause(); 250 } 251 ex = newEx; 252 } 253 } 254 255 if (ex != null) { 257 Exceptions.printStackTrace(ex); 258 } 259 } 260 261 264 private final class MenuBarFolder extends FolderInstance { 265 266 private ArrayList <Component > managed = new ArrayList <Component >(); 267 268 271 public MenuBarFolder (final DataFolder folder) { 272 super(folder); 273 recreate (); 274 } 275 276 278 private void cleanUp() { 279 for (Iterator <Component > it = managed.iterator(); it.hasNext(); ) { 280 MenuBar.this.remove(it.next()); 281 } 282 managed.clear(); 283 } 284 285 286 private void addComponent (Component c) { 287 MenuBar.this.add(c, managed.size()); 288 managed.add(c); 289 } 290 291 294 public String instanceName () { 295 return MenuBar.class.getName(); 296 } 297 298 301 public Class instanceClass () { 302 return MenuBar.class; 303 } 304 305 310 protected InstanceCookie acceptCookie(InstanceCookie cookie) 311 throws IOException , ClassNotFoundException { 312 Class cls = cookie.instanceClass(); 313 boolean is = 314 Component .class.isAssignableFrom(cls) || 315 Presenter.Toolbar.class.isAssignableFrom(cls) || 316 Action .class.isAssignableFrom(cls); 317 return is ? cookie : null; 318 } 319 320 326 protected InstanceCookie acceptFolder (DataFolder df) { 327 return new LazyMenu(df, false).slave; 328 } 329 330 335 protected Object createInstance(InstanceCookie[] cookies) 336 throws IOException , ClassNotFoundException { 337 final LinkedList <Object > ll = new LinkedList <Object >(); 338 allInstances(cookies, ll); 339 340 final MenuBar mb = MenuBar.this; 341 342 if (ll.equals(Arrays.asList(mb.getComponents()))) { 343 return mb; 344 } 345 346 cleanUp(); for (Object o: ll) { 349 Component component = convertToComponent(o); 350 if (component != null) { 351 addComponent(component); 352 } 353 } 354 mb.validate(); 355 mb.repaint(); 356 return mb; 357 } 358 359 private Component convertToComponent(final Object obj) { 360 Component retVal = null; 361 if (obj instanceof Component ) { 362 retVal = (Component )obj; 363 } else { 364 if (obj instanceof Presenter.Toolbar) { 365 retVal = ((Presenter.Toolbar)obj).getToolbarPresenter(); 366 } else if (obj instanceof Action ) { 367 Action a = (Action ) obj; 368 JButton button = new JButton (); 369 Actions.connect(button, a); 370 retVal = button; 371 } 372 } 373 if (retVal instanceof JButton ) { ((JButton )retVal).setBorderPainted(false); 375 ((JButton )retVal).setMargin(new java.awt.Insets (0, 2, 0, 2)); 376 } 377 return retVal; 378 } 379 380 381 DataFolder getFolder () { 382 return folder; 383 } 384 385 386 protected Task postCreationTask (Runnable run) { 387 return new AWTTask (run); 388 } 389 390 } 391 392 396 private static final class MarkedKeyEvent extends KeyEvent { 397 public MarkedKeyEvent (Component c, int id, 398 long when, int mods, int code, char kchar, 399 int loc) { 400 super(c, id, when, mods, code, kchar, loc); 401 } 402 } 403 404 405 private static class LazyMenu extends JMenu implements NodeListener, Runnable , ChangeListener { 406 DataFolder master; 407 boolean icon; 408 MenuFolder slave; 409 DynaMenuModel dynaModel; 410 411 412 public LazyMenu(final DataFolder df, boolean icon) { 413 this.master = df; 414 this.icon = icon; 415 this.dynaModel = new DynaMenuModel(); 416 this.slave = new MenuFolder(); 417 418 Node n = master.getNodeDelegate (); 420 n.addNodeListener (org.openide.nodes.NodeOp.weakNodeListener (this, n)); 421 updateProps(); 422 getModel().addChangeListener(this); 423 424 } 425 426 protected boolean processKeyBinding(KeyStroke ks, 427 KeyEvent e, 428 int condition, 429 boolean pressed) { 430 if (Utilities.isMac()) { 431 int mods = e.getModifiers(); 432 boolean isCtrl = (mods & KeyEvent.CTRL_MASK) != 0; 433 boolean isAlt = (mods & KeyEvent.ALT_MASK) != 0; 434 if (isAlt && (e instanceof MarkedKeyEvent)) { 435 mods = mods & ~ KeyEvent.CTRL_MASK; 436 mods = mods & ~ KeyEvent.CTRL_DOWN_MASK; 437 mods |= KeyEvent.ALT_MASK; 438 mods |= KeyEvent.ALT_DOWN_MASK; 439 440 KeyEvent newEvent = new MarkedKeyEvent ( 441 (Component ) e.getSource(), e.getID(), 442 e.getWhen(), mods, e.getKeyCode(), e.getKeyChar(), 443 e.getKeyLocation()); 444 445 KeyStroke newStroke = e.getID() == KeyEvent.KEY_TYPED ? 446 KeyStroke.getKeyStroke (ks.getKeyChar(), mods) : 447 KeyStroke.getKeyStroke (ks.getKeyCode(), mods, 448 !ks.isOnKeyRelease()); 449 450 boolean result = super.processKeyBinding (newStroke, 451 newEvent, condition, pressed); 452 453 if (newEvent.isConsumed()) { 454 e.consume(); 455 } 456 return result; 457 } else if (!isAlt) { 458 return super.processKeyBinding (ks, e, condition, pressed); 459 } else { 460 return false; 461 } 462 } else { 463 return super.processKeyBinding (ks, e, condition, pressed); 464 } 465 } 466 467 private void updateProps() { 468 if (master.isValid()) { 469 Node n = master.getNodeDelegate (); 471 Mnemonics.setLocalizedText(this, n.getDisplayName()); 472 if (icon) setIcon (new ImageIcon ( 473 n.getIcon (java.beans.BeanInfo.ICON_COLOR_16x16))); 474 } else { 475 setText(master.getName()); 476 setIcon(null); 477 } 478 } 479 480 482 public void run() { 483 updateProps(); 484 } 485 486 487 public void propertyChange (java.beans.PropertyChangeEvent ev) { 488 if ( 489 Node.PROP_DISPLAY_NAME.equals (ev.getPropertyName ()) || 490 Node.PROP_NAME.equals (ev.getPropertyName ()) || 491 Node.PROP_ICON.equals (ev.getPropertyName ()) 492 ) { 493 if (EventQueue.isDispatchThread ()) { 495 updateProps(); } else { 497 EventQueue.invokeLater (this); 498 } 499 } 500 } 501 502 public void childrenAdded (NodeMemberEvent ev) {} 504 public void childrenRemoved (NodeMemberEvent ev) {} 505 public void childrenReordered(NodeReorderEvent ev) {} 506 public void nodeDestroyed (NodeEvent ev) {} 507 508 private boolean selected = false; 509 public void stateChanged(ChangeEvent event) { 510 if (selected) { 511 selected = false; 512 } else { 513 selected = true; 514 doInitialize(); 515 dynaModel.checkSubmenu(this); 516 517 } 518 } 519 520 521 523 539 private void doInitialize() { 540 slave.waitFinishedSuper(); 541 } 542 543 546 private class MenuFolder extends FolderInstance { 547 548 552 public MenuFolder () { 553 super(master); 554 } 555 556 557 560 public String instanceName () { 561 return LazyMenu.class.getName(); 562 } 563 564 567 public Class instanceClass () { 568 return JMenu .class; 569 } 570 571 572 public Object instanceCreate() throws IOException , ClassNotFoundException { 573 return LazyMenu.this; 574 } 575 576 public void waitFinished() { 577 } 579 580 void waitFinishedSuper() { 581 super.waitFinished(); 582 } 583 584 585 588 protected InstanceCookie acceptDataObject (DataObject dob) { 589 InstanceCookie ic = super.acceptDataObject(dob); 590 if (ic == null) { 591 JMenuItem item = ExecBridge.createMenuItem(dob); 592 return item != null ? new InstanceSupport.Instance(item) : null; 593 } else { 594 return ic; 595 } 596 } 597 598 603 protected InstanceCookie acceptCookie(InstanceCookie cookie) 604 throws IOException , ClassNotFoundException { 605 Class c = cookie.instanceClass(); 609 boolean is = 610 Presenter.Menu.class.isAssignableFrom (c) || 611 JMenuItem .class.isAssignableFrom (c) || 612 JSeparator .class.isAssignableFrom (c) || 613 Action .class.isAssignableFrom (c); 614 return is ? cookie : null; 615 } 616 617 623 protected InstanceCookie acceptFolder(DataFolder df) { 624 boolean hasIcon = df.getPrimaryFile().getAttribute("SystemFileSystem.icon") != null; 625 return new LazyMenu(df, hasIcon).slave; 626 } 627 628 632 protected Object createInstance(InstanceCookie[] cookies) 633 throws IOException , ClassNotFoundException { 634 LazyMenu m = LazyMenu.this; 635 636 LinkedList <Object > cInstances = new LinkedList <Object >(); 638 allInstances (cookies, cInstances); 639 640 m.removeAll(); 641 642 if(cInstances.isEmpty()) { 647 JMenuItem item = new JMenuItem ( 648 NbBundle.getMessage(DataObject.class, "CTL_EmptyMenu")); 649 650 item.setEnabled(false); 651 m.add(item); 652 } 653 654 m.dynaModel.loadSubmenu(cInstances, m); 655 656 return m; 657 } 658 659 674 675 677 protected Task postCreationTask (Runnable run) { 678 return new AWTTask (run); 679 } 680 } 681 } 682 683 } 684 | Popular Tags |