1 19 20 package org.openide.windows; 21 22 import java.awt.BorderLayout ; 23 import java.awt.Component ; 24 import java.awt.DefaultKeyboardFocusManager ; 25 import java.awt.KeyboardFocusManager ; 26 import java.awt.event.ActionEvent ; 27 import java.beans.FeatureDescriptor ; 28 import java.util.*; 29 import javax.swing.AbstractAction ; 30 import javax.swing.ActionMap ; 31 import javax.swing.JTextField ; 32 33 import junit.framework.*; 34 35 import org.netbeans.junit.*; 36 import org.openide.cookies.*; 37 import org.openide.nodes.*; 38 import org.openide.util.*; 39 import org.openide.util.lookup.AbstractLookup; 40 import org.openide.util.lookup.InstanceContent; 41 42 46 public class TopComponentGetLookupTest extends NbTestCase { 47 48 49 protected TopComponent top; 50 protected TopComponent get; 51 52 protected Lookup lookup; 53 54 public TopComponentGetLookupTest(String testName) { 55 super(testName); 56 } 57 58 public static Test suite() { 59 return new NbTestSuite(TopComponentGetLookupTest.class); 60 } 61 62 64 protected void setUp () { 65 top = new TopComponent (); 66 get = top; 67 lookup = top.getLookup (); 68 } 69 70 protected boolean runInEQ () { 71 return true; 72 } 73 74 75 76 78 private void doTestNodes(Node[] arr, Class c, int cnt) { 79 if (arr != null) { 80 top.setActivatedNodes(arr); 81 } 82 83 assertNotNull ("At least one node is registered", lookup.lookup (c)); 84 Lookup.Result res = lookup.lookup (new Lookup.Template (c)); 85 Collection coll = res.allItems(); 86 assertEquals ("Two registered: " + coll, cnt, coll.size ()); 87 } 88 89 public void testNodes () { 90 doTestNodes(new Node[] {new N("1"), new N("2")}, N.class, 2); 91 doTestNodes(new Node[] {new N("1"), new N("2")}, FeatureDescriptor .class, 2); 92 } 93 94 private void doTestNodesWithChangesInLookup (Class c) { 95 InstanceContent ic = new InstanceContent(); 96 97 Node[] arr = new Node[] { 98 new AbstractNode(Children.LEAF, new AbstractLookup(ic)), 99 new AbstractNode(Children.LEAF, Lookup.EMPTY), 100 }; 101 arr[0].setName("cookie-container-node"); 102 arr[1].setName("node-as-cookie"); 103 doTestNodes (arr, c, 2); 105 106 ic.add (arr[1]); 107 108 111 Collection all = lookup.lookup(new Lookup.Template(c)).allInstances(); 112 assertEquals("Two nodes are in TC lookup", 2, all.size()); 113 assertEquals("They are the ones we expect", new HashSet(Arrays.asList(arr)), new HashSet(all)); 114 assertTrue("Lookup simple query gives one or the other", new HashSet(Arrays.asList(arr)).contains(lookup.lookup(c))); 115 assertEquals("Have two lookup items", 2, lookup.lookup(new Lookup.Template(c)).allItems().size()); 116 117 doTestNodes (null, c, 2); 118 } 119 120 public void testNodesWhenTheyAreNotInTheirLookup () { 121 doTestNodesWithChangesInLookup(AbstractNode.class); 122 } 123 124 public void testNodesSuperclassesWhenTheyAreNotInTheirLookup () { 125 doTestNodesWithChangesInLookup(FeatureDescriptor .class); 126 } 127 128 public void testFilterNodeProblems () { 129 class CookieN extends AbstractNode implements Node.Cookie { 130 public CookieN () { 131 super (Children.LEAF); 132 getCookieSet ().add (this); 133 } 134 135 } 136 137 CookieN n = new CookieN (); 138 FilterNode fn = new FilterNode (n); 139 top.setActivatedNodes (new Node[] { fn }); 140 assertTrue ("CookieN is in FilterNode lookup", n == fn.getLookup ().lookup (CookieN.class)); 141 assertTrue ("CookieN is in TopComponent", n == lookup.lookup (CookieN.class)); 142 assertEquals ("Just one node", 1, lookup.lookup (new Lookup.Template (Node.class)).allItems ().size ()); 143 assertTrue ("Plain cookie found", n == lookup.lookup (Node.Cookie.class)); 144 } 145 146 147 149 public void testCookies () { 150 N[] arr = { new N ("1"), new N ("2"), new N ("3") }; 151 152 top.setActivatedNodes (arr); 153 assertEquals ("Three nodes there", 3, top.getActivatedNodes ().length); 154 155 L l = new L (); 156 Lookup.Result res = lookup.lookup(new Lookup.Template(OpenCookie.class)); 157 res.addLookupListener (l); 158 159 assertEquals ("Empty now", res.allItems().size (), 0); 160 161 arr[0].state (0x01); 163 assertEquals ("One item", res.allItems ().size (), 1); 164 l.check ("One change", 1); 165 166 arr[2].state (0x02); 168 assertEquals ("Still one item", res.allItems ().size (), 1); 169 l.check ("No change", 0); 170 171 arr[2].state (0x03); 173 assertEquals ("Both items", res.allItems ().size (), 2); 174 l.check ("One change again", 1); 175 176 arr[0].state (0x00); 177 178 assertEquals ("One still there", res.allItems ().size (), 1); 179 assertEquals("The second object", lookup.lookup(OpenCookie.class), arr[2].getCookie(OpenCookie.class)); 180 181 top.setActivatedNodes(new Node[0]); 182 assertNull("No cookie now", lookup.lookup(OpenCookie.class)); 183 } 184 185 public void testNodesAreInTheLookupAndNothingIsFiredBeforeFirstQuery () { 186 AbstractNode n1 = new AbstractNode(Children.LEAF, Lookup.EMPTY); 187 top.setActivatedNodes(new Node[] { n1 }); 188 assertEquals ("One node there", 1, top.getActivatedNodes ().length); 189 assertEquals ("Is the right now", n1, top.getActivatedNodes ()[0]); 190 191 Lookup.Result res = lookup.lookup(new Lookup.Template(Node.class)); 192 L l = new L (); 193 res.addLookupListener(l); 194 195 l.check ("Nothing fired before first query", 0); 196 res.allInstances (); 197 l.check ("Nothing is fired on first query", 0); 198 lookup.lookup(new Lookup.Template(Node.class)).allInstances(); 199 l.check ("And additional query does not change anything either", 0); 200 } 201 202 public void testNodesAreThereEvenIfTheyAreNotContainedInTheirOwnLookup () { 203 Lookup.Result res = lookup.lookup(new Lookup.Template(Node.class)); 204 205 AbstractNode n1 = new AbstractNode(Children.LEAF, Lookup.EMPTY); 206 207 InstanceContent content = new InstanceContent (); 208 AbstractNode n2 = new AbstractNode(Children.LEAF, new AbstractLookup(content)); 209 210 assertNull ("Not present in its lookup", n1.getLookup ().lookup (n1.getClass ())); 211 assertNull ("Not present in its lookup", n2.getLookup ().lookup (n2.getClass ())); 212 213 top.setActivatedNodes (new AbstractNode[] { n1 }); 214 assertEquals ("But node is in the lookup", n1, lookup.lookup (n1.getClass ())); 215 216 assertEquals ("One item there", 1, res.allInstances ().size ()); 217 218 L listener = new L (); 219 res.addLookupListener(listener); 220 221 top.setActivatedNodes (new AbstractNode[] { n2 }); 222 assertEquals ("One node there", 1, top.getActivatedNodes ().length); 223 assertEquals ("n2", n2, top.getActivatedNodes ()[0]); 224 225 listener.check ("Node changed", 1); 229 230 Collection addedByTCLookup = res.allInstances(); 231 assertEquals ("One item still", 1, addedByTCLookup.size ()); 232 233 content.add (n2); 234 assertEquals ("After the n2.getLookup starts to return itself, there is no change", 235 addedByTCLookup, res.allInstances ()); 236 237 listener.check ("And nothing is fired", 0); 239 240 content.remove (n2); 241 assertEquals ("After the n2.getLookup stops to return itself, there is no change", 242 addedByTCLookup, res.allInstances ()); 243 listener.check ("And nothing is fired", 0); 245 246 content.add (n1); 247 listener.check ("And nothing is fired", 0); 249 Collection one = res.allInstances(); 251 assertEquals("Really just the activated node", 1, one.size()); 252 Iterator it = one.iterator(); 253 assertEquals("It is the one added by the TC lookup", n2, it.next()); 254 } 255 256 public void testNoChangeWhenSomethingIsChangedOnNotActivatedNode () { 257 doTestNoChangeWhenSomethingIsChangedOnNotActivatedNode (0); 258 } 259 260 public void testNoChangeWhenSomethingIsChangedOnNotActivatedNode2 () { 261 doTestNoChangeWhenSomethingIsChangedOnNotActivatedNode (50); 262 } 263 264 private void doTestNoChangeWhenSomethingIsChangedOnNotActivatedNode (int initialSize) { 265 Object obj = new OpenCookie() { public void open() {} }; 266 267 Lookup.Result res = lookup.lookup(new Lookup.Template(OpenCookie.class)); 268 Lookup.Result nodeRes = lookup.lookup (new Lookup.Template(Node.class)); 269 270 InstanceContent ic = new InstanceContent (); 271 CountingLookup cnt = new CountingLookup (ic); 272 AbstractNode ac = new AbstractNode(Children.LEAF, cnt); 273 for (int i = 0; i < initialSize; i++) { 274 ic.add (new Integer (i)); 275 } 276 277 top.setActivatedNodes(new org.openide.nodes.Node[] { ac }); 278 assertEquals ("One node there", 1, top.getActivatedNodes ().length); 279 assertEquals ("It is the ac one", ac, top.getActivatedNodes ()[0]); 280 ic.add (obj); 281 282 L listener = new L (); 283 284 res.allItems(); 285 nodeRes.allItems (); 286 res.addLookupListener (listener); 287 288 Collection allListeners = cnt.listeners; 289 290 assertEquals ("Has the cookie", 1, res.allItems ().size ()); 291 listener.check ("No changes yet", 0); 292 293 ic.remove (obj); 294 295 assertEquals ("Does not have the cookie", 0, res.allItems ().size ()); 296 listener.check ("One change", 1); 297 298 top.setActivatedNodes (new N[0]); 299 assertEquals("The nodes are empty", 0, top.getActivatedNodes ().length); 300 listener.check ("No change", 0); 301 302 cnt.queries = 0; 303 ic.add (obj); 304 ic.add (ac); 305 listener.check ("Removing the object or node from not active node does not send any event", 0); 306 307 nodeRes.allItems (); 308 listener.check ("Queriing for node does generate an event", 0); 309 assertEquals ("No Queries to the not active node made", 0, cnt.queries); 310 assertEquals ("No listeneners on cookies", allListeners, cnt.listeners); 311 } 312 313 public void testBug32470FilterNodeAndANodeImplementingACookie () { 314 class NY extends AbstractNode implements SaveCookie { 315 public NY () { 316 super(Children.LEAF); 317 getCookieSet ().add (this); 318 } 319 320 public void save () { 321 } 322 } 323 324 Node ny = new NY (); 325 Node node = new FilterNode (new FilterNode (ny, null, ny.getLookup ())); 326 top.setActivatedNodes (new Node[] { node }); 327 328 Lookup.Template nodeTemplate = new Lookup.Template(Node.class); 329 Lookup.Template saveTemplate = new Lookup.Template(SaveCookie.class); 330 java.util.Collection res; 331 332 res = lookup.lookup (nodeTemplate).allInstances (); 333 334 assertEquals("just one returned", res.size(), 1); 335 assertEquals("node is node", node, res.iterator().next()); 336 341 res = lookup.lookup (saveTemplate).allInstances (); 342 343 assertEquals("just one returned", res.size(), 1); 344 assertEquals("node is node", ny, res.iterator().next()); 345 350 res = lookup.lookup (nodeTemplate).allInstances (); 351 352 assertEquals("just one returned", res.size(), 1); 353 assertEquals("node is node", node, res.iterator().next()); 354 } 359 360 public void testActionMapIsTakenFromComponentAndAlsoFromFocusedOne () { 361 JTextField panel = new JTextField (); 362 363 class Def extends DefaultKeyboardFocusManager { 364 private Component c; 365 366 public Def(Component c) { 367 this.c = c; 368 } 369 public Component getFocusOwner() { 370 return c; 371 } 372 } 373 KeyboardFocusManager prev = KeyboardFocusManager.getCurrentKeyboardFocusManager(); 374 375 try { 376 KeyboardFocusManager.setCurrentKeyboardFocusManager(new Def (panel)); 377 378 379 380 top.add(BorderLayout.CENTER, panel); 381 382 class Act extends AbstractAction { 383 public void actionPerformed(ActionEvent ev) { 384 } 385 } 386 Act act1 = new Act (); 387 Act act2 = new Act (); 388 Act act3 = new Act (); 389 390 top.getActionMap ().put ("globalRegistration", act1); 391 top.getActionMap ().put ("doubleRegistration", act2); 392 393 panel.getActionMap ().put ("doubleRegistration", act3); 394 panel.getActionMap ().put ("focusedRegistration", act3); 395 396 397 ActionMap map = (ActionMap )top.getLookup ().lookup (ActionMap .class); 398 399 assertEquals ("actions registered directly on TC are found", act1, map.get ("globalRegistration")); 400 assertEquals ("even if they are provided by focused component", act2, map.get ("doubleRegistration")); 401 402 assertEquals ("Should be focused now", 403 panel, 404 KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner() 405 ); 406 assertEquals ("actions are delegated to focus owner, if not present", act3, map.get ("focusedRegistration")); 407 408 JTextField f = new JTextField (); 409 f.getActionMap ().put ("focusedRegistration", act3); 410 KeyboardFocusManager.setCurrentKeyboardFocusManager(new Def (f)); 411 assertEquals ("f should be focused now", 412 f, 413 KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner() 414 ); 415 assertEquals ("but as it is not in the right component, nothing is found", null, map.get ("focusedRegistration")); 416 } finally { 417 KeyboardFocusManager.setCurrentKeyboardFocusManager (prev); 418 } 419 } 420 421 422 public void testChangingNodesDoesNotChangeActionMap () { 423 N node = new N ("testChangingNodesDoesNotChangeActionMap"); 424 node.state (0x00); 425 top.setActivatedNodes(new Node[] { node }); 426 427 Lookup.Result res = lookup.lookup (new Lookup.Template (ActionMap .class)); 428 assertEquals ("One item there", 1, res.allInstances ().size ()); 429 ActionMap map = (ActionMap )res.allInstances().toArray()[0]; 430 431 L l = new L (); 432 res.addLookupListener (l); 433 434 node.state (0x01); 435 436 assertEquals ("Map is still the same", map, res.allInstances().toArray()[0]); 437 438 l.check ("No change in lookup", 0); 439 440 top.setActivatedNodes (new Node[] { Node.EMPTY }); 441 assertEquals ("Map remains the same", map, res.allInstances().toArray()[0]); 442 443 l.check ("There is no change", 0); 444 445 } 446 447 public void testMapKeys45323 () { 448 assertNotNull (top.getActionMap ().keys ()); 449 } 450 451 452 458 public void testForeignNodesInLookupIgnoredForNodeQuery() throws Exception { 459 class CloseCookieNode extends AbstractNode implements CloseCookie { 460 CloseCookieNode() { 461 super(Children.LEAF); 462 setName("n1"); 463 } 464 public boolean close() {return true;} 465 } 466 Node n1 = new CloseCookieNode(); 467 Node n2 = new AbstractNode(Children.LEAF) { 468 { 469 setName("n2"); 470 class ViewCookieNode extends AbstractNode implements ViewCookie { 471 ViewCookieNode() { 472 super(Children.LEAF); 473 setName("n3"); 474 } 475 public void view() {} 476 } 477 getCookieSet().add(new ViewCookieNode()); 478 getCookieSet().add(new OpenCookie() { 479 public void open() {} 480 }); 481 } 482 }; 483 Node[] sel = new Node[] {n1, n2}; 484 assertEquals("First node in selection has CloseCookie", 485 1, 486 n1.getLookup().lookup(new Lookup.Template(CloseCookie.class)).allInstances().size()); 487 assertEquals("Second node in selection has OpenCookie", 488 1, 489 n2.getLookup().lookup(new Lookup.Template(OpenCookie.class)).allInstances().size()); 490 assertEquals("Second node in selection has ViewCookie (actually a Node)", 491 1, 492 n2.getLookup().lookup(new Lookup.Template(ViewCookie.class)).allInstances().size()); 493 ViewCookie v = (ViewCookie)n2.getCookie(ViewCookie.class); 494 assertNotNull(v); 495 assertTrue(v instanceof Node); 496 497 HashSet queryJustOnce = new HashSet(n2.getLookup().lookup(new Lookup.Template(Node.class)).allInstances()); 498 assertEquals("Second node in selection has two nodes in its own lookup", 499 new HashSet(Arrays.asList(new Object [] {n2, v})), queryJustOnce 500 ); 501 assertEquals(2, queryJustOnce.size()); 502 top.setActivatedNodes(sel); 503 assertEquals("CloseCookie propagated from one member of node selection to TC lookup", 504 1, 505 lookup.lookup(new Lookup.Template(CloseCookie.class)).allInstances().size()); 506 assertEquals("OpenCookie propagated from one member of node selection to TC lookup", 507 1, 508 lookup.lookup(new Lookup.Template(OpenCookie.class)).allInstances().size()); 509 assertEquals("ViewCookie propagated from one member of node selection to TC lookup", 510 1, 511 lookup.lookup(new Lookup.Template(ViewCookie.class)).allInstances().size()); 512 assertEquals("But TC lookup query on Node gives only selection, not cookie node", 513 new HashSet(Arrays.asList(sel)), 514 new HashSet(lookup.lookup(new Lookup.Template(Node.class)).allInstances())); 515 assertEquals(2, lookup.lookup(new Lookup.Template(Node.class)).allInstances().size()); 516 assertEquals("TC lookup query on FeatureDescriptor gives all three however", 517 3, 518 lookup.lookup(new Lookup.Template(FeatureDescriptor .class)).allInstances().size()); 519 top.setActivatedNodes(new Node[] {n1}); 520 assertEquals("After setting node selection to one node, TC lookup has only that node", 521 Collections.singleton(n1), 522 new HashSet(lookup.lookup(new Lookup.Template(Node.class)).allInstances())); 523 assertEquals(1, lookup.lookup(new Lookup.Template(Node.class)).allInstances().size()); 524 assertEquals("And the OpenCookie is gone", 525 0, 526 lookup.lookup(new Lookup.Template(OpenCookie.class)).allInstances().size()); 527 assertEquals("And the ViewCookie is gone", 528 0, 529 lookup.lookup(new Lookup.Template(ViewCookie.class)).allInstances().size()); 530 assertEquals("But the CloseCookie remains", 531 1, 532 lookup.lookup(new Lookup.Template(CloseCookie.class)).allInstances().size()); 533 } 534 535 public void testAssociateLookupCanBecalledJustOnce () throws Exception { 536 class TC extends TopComponent { 537 public TC () { 538 } 539 540 public TC (Lookup l) { 541 super (l); 542 } 543 544 public void asso (Lookup l) { 545 associateLookup (l); 546 } 547 } 548 549 TC tc = new TC (); 550 assertNotNull ("There is default lookup", tc.getLookup ()); 551 try { 552 tc.asso (Lookup.EMPTY); 553 fail ("Should throw an exception"); 554 } catch (IllegalStateException ex) { 555 } 557 558 tc = new TC (Lookup.EMPTY); 559 assertEquals ("Should return the provided lookup", Lookup.EMPTY, tc.getLookup ()); 560 561 try { 562 tc.asso (Lookup.EMPTY); 563 fail ("Should throw an exception - second association not possible"); 564 } catch (IllegalStateException ex) { 565 } 567 568 tc = new TC (); 569 tc.asso (Lookup.EMPTY); 570 assertEquals ("First association was successful", Lookup.EMPTY, tc.getLookup ()); 571 572 try { 573 tc.asso (new TC ().getLookup ()); 574 fail ("Should throw an exception - second association not possible"); 575 } catch (IllegalStateException ex) { 576 } 578 } 579 580 582 private static final class L extends Object 583 implements LookupListener { 584 private int cnt; 585 586 589 public void resultChanged(LookupEvent ev) { 590 cnt++; 591 } 592 593 595 public void checkAtLeast (String text, int num) { 596 if (cnt < num) { 597 fail (text + " expected at least " + num + " but was " + cnt); 598 } 599 cnt = 0; 600 } 601 602 604 public void check (String text, int num) { 605 assertEquals (text, num, cnt); 606 cnt = 0; 607 } 608 } 609 610 611 613 protected static final class N extends AbstractNode { 614 private Node.Cookie[] cookies = { 615 new OpenCookie() { public void open() {} }, 616 new EditCookie() { public void edit() {} }, 617 new SaveCookie() { public void save() {} }, 618 new CloseCookie() { public boolean close() { return true; } }, 619 }; 620 621 private int s; 622 623 public N (String name) { 624 super(Children.LEAF); 625 setName (name); 626 } 627 628 public void state (int s) { 629 this.s = s; 630 fireCookieChange (); 631 } 632 633 public Node.Cookie getCookie(Class c) { 634 int mask = 0x01; 635 636 for (int i = 0; i < cookies.length; i++) { 637 if ((s & mask) != 0 && c.isInstance(cookies[i])) { 638 return cookies[i]; 639 } 640 mask = mask << 1; 641 642 } 643 return null; 644 } 645 } 646 647 private static final class CountingLookup extends Lookup { 648 private Lookup delegate; 649 public List listeners = new ArrayList(); 650 public int queries; 651 652 public CountingLookup(InstanceContent ic) { 653 delegate = new AbstractLookup (ic); 654 655 } 656 657 public Object lookup(Class clazz) { 658 return delegate.lookup (clazz); 659 } 660 661 public Lookup.Result lookup(Lookup.Template template) { 662 if ( 663 !Node.Cookie.class.isAssignableFrom(template.getType()) && 664 !Node.class.isAssignableFrom(template.getType()) 665 ) { 666 return delegate.lookup (template); 667 } 668 669 670 final Lookup.Result d = delegate.lookup (template); 671 672 class Wrap extends Lookup.Result { 673 public void addLookupListener(LookupListener l) { 674 listeners.add (l); 675 d.addLookupListener (l); 676 } 677 678 public void removeLookupListener(LookupListener l) { 679 listeners.remove (l); 680 d.removeLookupListener (l); 681 } 682 public Collection allInstances() { 683 queries++; 684 return d.allInstances (); 685 } 686 public Collection allItems() { 687 queries++; 688 return d.allItems (); 689 } 690 public Set allClasses() { 691 queries++; 692 return d.allClasses (); 693 } 694 } 695 696 return new Wrap (); 697 } 698 699 } 700 } 701 | Popular Tags |