1 19 20 package org.openide.nodes; 21 22 import java.awt.Image ; 23 import java.awt.datatransfer.Transferable ; 24 import java.beans.FeatureDescriptor ; 25 import java.beans.PropertyChangeEvent ; 26 import java.beans.PropertyChangeListener ; 27 import java.beans.PropertyEditor ; 28 import java.io.IOException ; 29 import java.io.PrintWriter ; 30 import java.io.StringWriter ; 31 import java.lang.ref.Reference ; 32 import java.lang.ref.SoftReference ; 33 import java.lang.ref.WeakReference ; 34 import java.lang.reflect.InvocationTargetException ; 35 import java.util.HashSet ; 36 import java.util.Map ; 37 import java.util.Set ; 38 import java.util.WeakHashMap ; 39 import java.util.logging.Level ; 40 import java.util.logging.Logger ; 41 import javax.swing.Action ; 42 import javax.swing.JPopupMenu ; 43 import javax.swing.event.EventListenerList ; 44 import org.openide.util.HelpCtx; 45 import org.openide.util.Lookup; 46 import org.openide.util.LookupEvent; 47 import org.openide.util.LookupListener; 48 import org.openide.util.NbBundle; 49 import org.openide.util.actions.SystemAction; 50 import org.openide.util.datatransfer.NewType; 51 import org.openide.util.datatransfer.PasteType; 52 53 84 public abstract class Node extends FeatureDescriptor implements Lookup.Provider, HelpCtx.Provider { 85 86 public static final Node EMPTY = new AbstractNode(Children.LEAF); 87 88 91 92 93 public static final String PROP_DISPLAY_NAME = "displayName"; 95 98 public static final String PROP_NAME = "name"; 100 101 public static final String PROP_SHORT_DESCRIPTION = "shortDescription"; 103 104 public static final String PROP_ICON = "icon"; 106 107 public static final String PROP_OPENED_ICON = "openedIcon"; 109 110 public static final String PROP_PARENT_NODE = "parentNode"; 112 113 public static final String PROP_PROPERTY_SETS = "propertySets"; 115 116 public static final String PROP_COOKIE = "cookie"; 118 121 public static final String PROP_LEAF = "leaf"; 123 125 private static final Logger err = Logger.getLogger("org.openide.nodes.Node"); 127 128 private static Map <EventListenerList ,Reference <Lookup>> lookups = new WeakHashMap <EventListenerList ,Reference <Lookup>>(37); 129 130 131 private static final Set <String > warnedBadProperties = new HashSet <String >(100); 132 133 134 private static final Lookup.Template<Node.Cookie> TEMPL_COOKIE = new Lookup.Template<Node.Cookie>(Node.Cookie.class); 135 136 137 private static final Object INIT_LOCK = new Object (); 138 139 143 private Object parent; 144 145 148 Children hierarchy; 149 150 152 private transient EventListenerList listeners; 153 154 159 protected Node(Children h) throws IllegalStateException { 160 this(h, null); 161 } 162 163 200 protected Node(Children h, Lookup lookup) throws IllegalStateException { 201 this.hierarchy = h; 202 203 lookup = replaceProvidedLookup(lookup); 205 206 if (lookup != null) { 207 this.listeners = new LookupEventList(lookup); 208 } else { 209 this.listeners = new EventListenerList (); 210 } 211 212 h.attachTo(this); 214 } 215 216 219 Lookup replaceProvidedLookup(Lookup l) { 220 return l; 221 } 222 223 227 final Lookup internalLookup(boolean init) { 228 if (listeners instanceof LookupEventList) { 229 return ((LookupEventList) listeners).init(init); 230 } else { 231 return null; 232 } 233 } 234 235 248 protected Object clone() throws CloneNotSupportedException { 249 Node n = (Node) super.clone(); 250 Children hier2; 251 252 if (hierarchy instanceof Cloneable ) { 253 hier2 = (Children) hierarchy.cloneHierarchy(); 254 } else { 255 hier2 = Children.LEAF; 256 } 257 258 n.hierarchy = hier2; 260 hier2.attachTo(n); 261 262 n.parent = null; 264 265 if (listeners instanceof LookupEventList) { 267 n.listeners = new LookupEventList(internalLookup(false)); 268 } else { 269 n.listeners = new EventListenerList (); 270 } 271 272 return n; 273 } 274 275 283 public abstract Node cloneNode(); 284 285 288 private Children getParentChildren() { 289 return (this.parent instanceof ChildrenArray) ? ((ChildrenArray) this.parent).getChildren() 290 : (Children) this.parent; 291 } 292 293 300 final synchronized void assignTo(Children parent, int index) { 301 Children ch = getParentChildren(); 302 303 if ((ch != null) && (ch != parent)) { 304 throw new IllegalStateException ( 305 "Cannot initialize " + index + "th child of node " + parent.getNode() + 306 "; it already belongs to node " + ch.getNode() 307 ); } 309 310 if (!(this.parent instanceof ChildrenArray)) { 311 this.parent = parent; 312 } 313 } 314 315 318 final synchronized void reassignTo(Children currentParent, ChildrenArray itsArray) { 319 if ((this.parent != currentParent) && (this.parent != itsArray)) { 320 throw new IllegalStateException ( 321 "Unauthorized call to change parent: " + this.parent + " and should be: " + currentParent 322 ); 323 } 324 325 this.parent = itsArray; 326 } 327 328 331 final synchronized void deassignFrom(Children parent) { 332 Children p = getParentChildren(); 333 334 if (parent != p) { 335 throw new IllegalArgumentException ("Deassign from wrong parent. Old: " + p + " Caller: " + parent); } 337 338 this.parent = null; 339 } 340 341 346 public void setName(String s) { 347 String name = super.getName(); 348 349 if ((name == null) || !name.equals(s)) { 350 super.setName(s); 351 fireNameChange(name, s); 352 } 353 } 354 355 358 public void setDisplayName(String s) { 359 String displayName = super.getDisplayName(); 360 361 if ((displayName == null) || !displayName.equals(s)) { 362 super.setDisplayName(s); 363 fireDisplayNameChange(displayName, s); 364 } 365 } 366 367 371 public void setShortDescription(String s) { 372 String descr = super.getShortDescription(); 373 374 if ((descr == null) || !descr.equals(s)) { 375 super.setShortDescription(s); 376 fireShortDescriptionChange(descr, s); 377 } 378 } 379 380 384 public abstract Image getIcon(int type); 385 386 392 public abstract Image getOpenedIcon(int type); 393 394 397 public abstract HelpCtx getHelpCtx(); 398 399 402 public final Children getChildren() { 403 updateChildren(); 404 405 return hierarchy; 406 } 407 408 411 void updateChildren() { 412 } 413 414 421 protected final void setChildren(final Children ch) { 422 Children.MUTEX.postWriteRequest(new Runnable () { public void run() { 423 Node[] oldNodes = null; 424 425 if (hierarchy.isInitialized()) { 426 oldNodes = hierarchy.getNodes(); 427 } 428 hierarchy.detachFrom(); 429 430 boolean wasLeaf = hierarchy == Children.LEAF; 431 432 hierarchy = ch; 433 hierarchy.attachTo(Node.this); 434 435 if (wasLeaf != (hierarchy == Children.LEAF)) { 436 fireOwnPropertyChange(PROP_LEAF, wasLeaf, hierarchy == Children.LEAF); 437 } 438 439 if ((oldNodes != null) && !wasLeaf) { 440 fireSubNodesChange(false, oldNodes, oldNodes); 441 Node[] arr = hierarchy.getNodes(); 442 if (arr.length > 0) { 443 fireSubNodesChange(true, arr, null); 444 } 445 } 446 }}); 447 } 448 449 452 public final boolean isLeaf() { 453 updateChildren(); 454 455 return hierarchy == Children.LEAF; 456 } 457 458 461 public final Node getParentNode() { 462 Children ch = getParentChildren(); 464 465 return (ch == null) ? null : ch.getNode(); 466 } 467 468 474 public abstract boolean canRename(); 475 476 479 public abstract boolean canDestroy(); 480 481 483 494 public void destroy() throws IOException { 495 Children.MUTEX.postWriteRequest( 496 new Runnable () { 497 public void run() { 498 Children p = getParentChildren(); 499 500 if (p != null) { 501 p.remove(new Node[] { Node.this }); 503 } 504 505 fireNodeDestroyed(); 507 } 508 } 509 ); 510 } 511 512 518 public abstract PropertySet[] getPropertySets(); 519 520 526 public abstract Transferable clipboardCopy() throws IOException ; 527 528 534 public abstract Transferable clipboardCut() throws IOException ; 535 536 543 public abstract Transferable drag() throws IOException ; 544 545 548 public abstract boolean canCopy(); 549 550 553 public abstract boolean canCut(); 554 555 560 public abstract PasteType[] getPasteTypes(Transferable t); 561 562 572 public abstract PasteType getDropType(Transferable t, int action, int index); 573 574 578 public abstract NewType[] getNewTypes(); 579 580 594 public Action [] getActions(boolean context) { 595 return context ? getContextActions() : getActions(); 596 } 597 598 607 @Deprecated 608 public SystemAction[] getActions() { 609 return NodeOp.getDefaultActions(); 610 } 611 612 625 @Deprecated 626 public SystemAction[] getContextActions() { 627 return getActions(); 628 } 629 630 634 @Deprecated 635 public SystemAction getDefaultAction() { 636 return null; 637 } 638 639 649 public Action getPreferredAction() { 650 return getDefaultAction(); 651 } 652 653 658 public final JPopupMenu getContextMenu() { 659 return NodeOp.findContextMenuImpl(new Node[] { this }, null); 660 } 661 662 667 public abstract boolean hasCustomizer(); 668 669 672 public abstract java.awt.Component getCustomizer(); 673 674 686 public <T extends Node.Cookie> T getCookie(Class <T> type) { 687 Lookup l = internalLookup(true); 688 689 if (l != null) { 690 Object obj = l.lookup(type); 691 if (Node.Cookie.class.isInstance(obj)) { 692 return type.cast(obj); 693 } 694 CookieSet.enhancedQueryMode(l, type); 695 } 696 697 return null; 698 } 699 700 708 public final Lookup getLookup() { 709 synchronized (listeners) { 710 Lookup l = internalLookup(true); 711 712 if (l != null) { 713 return l; 714 } 715 716 l = findDelegatingLookup(); 717 718 if (l != null) { 719 return l; 720 } 721 722 NodeLookup nl = new NodeLookup(this); 724 registerDelegatingLookup(nl); 725 726 return nl; 727 } 728 } 729 730 752 public String getHtmlDisplayName() { 753 return null; 754 } 755 756 758 final void registerDelegatingLookup(NodeLookup l) { 759 synchronized (lookups) { 761 lookups.put(listeners, new WeakReference <Lookup>(l)); 762 } 763 } 764 765 769 final Lookup findDelegatingLookup() { 770 Reference <Lookup> ref = lookups.get(listeners); 771 772 return (ref == null) ? null : ref.get(); 773 } 774 775 781 public abstract Node.Handle getHandle(); 782 783 789 public final void addNodeListener(NodeListener l) { 790 listeners.add(NodeListener.class, l); 791 listenerAdded(); 792 } 793 794 795 void listenerAdded() { 796 } 797 798 801 public final void removeNodeListener(NodeListener l) { 802 listeners.remove(NodeListener.class, l); 803 } 804 805 808 public final void addPropertyChangeListener(PropertyChangeListener l) { 809 int count = -1; 810 811 if (err.isLoggable(Level.FINE)) { 812 count = getPropertyChangeListenersCount(); 813 } 814 815 listeners.add(PropertyChangeListener .class, l); 816 817 if (err.isLoggable(Level.FINE)) { 818 err.log( 819 Level.FINE, 820 "ADD - " + getName() + " [" + count + "]->[" + getPropertyChangeListenersCount() + "] " + l 821 ); 822 } 823 824 notifyPropertyChangeListenerAdded(l); 825 } 826 827 830 void notifyPropertyChangeListenerAdded(PropertyChangeListener l) { 831 } 832 833 835 int getPropertyChangeListenersCount() { 836 return listeners.getListenerCount(PropertyChangeListener .class); 837 } 838 839 844 protected final boolean hasPropertyChangeListener() { 845 return getPropertyChangeListenersCount() > 0; 846 } 847 848 851 public final void removePropertyChangeListener(PropertyChangeListener l) { 852 int count = -1; 853 854 if (err.isLoggable(Level.FINE)) { 855 count = getPropertyChangeListenersCount(); 856 } 857 858 listeners.remove(PropertyChangeListener .class, l); 859 860 if (err.isLoggable(Level.FINE)) { 861 err.log( 862 Level.FINE, 863 "RMV - " + getName() + " [" + count + "]->[" + getPropertyChangeListenersCount() + "] " + l 864 ); 865 } 866 867 notifyPropertyChangeListenerRemoved(l); 868 } 869 870 873 void notifyPropertyChangeListenerRemoved(PropertyChangeListener l) { 874 } 875 876 883 protected final void firePropertyChange(String name, Object o, Object n) { 884 if (err.isLoggable(Level.WARNING) && (name != null) && propertySetsAreKnown()) { 886 Node.PropertySet[] pss = getPropertySets(); 887 boolean exists = false; 888 889 for (int i = 0; i < pss.length; i++) { 890 Node.Property[] ps = pss[i].getProperties(); 891 892 for (int j = 0; j < ps.length; j++) { 893 if (ps[j].getName().equals(name)) { 894 exists = true; 895 896 break; 897 } 898 } 899 } 900 901 if (!exists) { 902 synchronized (warnedBadProperties) { 903 String clazz = getClass().getName(); 904 905 if (warnedBadProperties.add(clazz + "." + name)) { 906 StringWriter w = new StringWriter (); 907 IllegalStateException ise = new IllegalStateException ("Warning - the node \"" + 908 getDisplayName() + 909 "\" [" + 910 clazz + 911 "] is trying to fire the property " + 912 name + 913 " which is not included in its property sets. This is illegal. See IZ #31413 for details." 914 ); ise.printStackTrace(new PrintWriter (w)); 916 Logger.getLogger(Node.class.getName()).warning(w.toString()); 917 } 918 } 919 } 920 } 921 922 if ((o != null) && (n != null) && ((o == n) || o.equals(n))) { 924 return; 925 } 926 927 PropertyChangeEvent ev = null; 928 929 Object [] listeners = this.listeners.getListenerList(); 930 931 for (int i = listeners.length - 2; i >= 0; i -= 2) { 934 if (listeners[i] == PropertyChangeListener .class) { 935 if (ev == null) { 937 ev = new PropertyChangeEvent (this, name, o, n); 938 } 939 940 ((PropertyChangeListener ) listeners[i + 1]).propertyChange(ev); 941 } 942 } 943 } 944 945 952 boolean propertySetsAreKnown() { 953 return false; 954 } 955 956 960 protected final void fireNameChange(String o, String n) { 961 fireOwnPropertyChange(PROP_NAME, o, n); 962 } 963 964 968 protected final void fireDisplayNameChange(String o, String n) { 969 fireOwnPropertyChange(PROP_DISPLAY_NAME, o, n); 970 } 971 972 976 protected final void fireShortDescriptionChange(String o, String n) { 977 fireOwnPropertyChange(PROP_SHORT_DESCRIPTION, o, n); 978 } 979 980 982 protected final void fireIconChange() { 983 fireOwnPropertyChange(PROP_ICON, null, null); 984 } 985 986 988 protected final void fireOpenedIconChange() { 989 fireOwnPropertyChange(PROP_OPENED_ICON, null, null); 990 } 991 992 1003 final void fireSubNodesChange(boolean addAction, Node[] delta, Node[] from) { 1004 NodeMemberEvent ev = null; 1005 1006 Object [] listeners = this.listeners.getListenerList(); 1007 1008 for (int i = listeners.length - 2; i >= 0; i -= 2) { 1011 if (listeners[i] == NodeListener.class) { 1012 if (ev == null) { 1014 ev = new NodeMemberEvent(this, addAction, delta, from); 1015 } 1016 1017 if (addAction) { 1018 ((NodeListener) listeners[i + 1]).childrenAdded(ev); 1019 } else { 1020 ((NodeListener) listeners[i + 1]).childrenRemoved(ev); 1021 } 1022 } 1023 } 1024 } 1025 1026 1030 final void fireReorderChange(int[] indices) { 1031 NodeReorderEvent ev = null; 1032 1033 Object [] listeners = this.listeners.getListenerList(); 1034 1035 for (int i = listeners.length - 2; i >= 0; i -= 2) { 1038 if (listeners[i] == NodeListener.class) { 1039 if (ev == null) { 1041 ev = new NodeReorderEvent(this, indices); 1042 } 1043 1044 ((NodeListener) listeners[i + 1]).childrenReordered(ev); 1045 } 1046 } 1047 } 1048 1049 1051 protected final void fireNodeDestroyed() { 1052 NodeEvent ev = null; 1053 1054 Object [] listeners = this.listeners.getListenerList(); 1055 1056 for (int i = listeners.length - 2; i >= 0; i -= 2) { 1059 if (listeners[i] == NodeListener.class) { 1060 if (ev == null) { 1062 ev = new NodeEvent(this); 1063 } 1064 1065 ((NodeListener) listeners[i + 1]).nodeDestroyed(ev); 1066 } 1067 } 1068 } 1069 1070 1074 final void fireParentNodeChange(Node o, Node n) { 1075 fireOwnPropertyChange(PROP_PARENT_NODE, o, n); 1076 } 1077 1078 1082 protected final void firePropertySetsChange(PropertySet[] o, PropertySet[] n) { 1083 fireOwnPropertyChange(PROP_PROPERTY_SETS, o, n); 1084 } 1085 1086 1089 protected final void fireCookieChange() { 1090 Lookup l = findDelegatingLookup(); 1091 1092 if (l instanceof NodeLookup) { 1093 ((NodeLookup) l).updateLookupAsCookiesAreChanged(null); 1094 } 1095 1096 fireOwnPropertyChange(PROP_COOKIE, null, null); 1097 } 1098 1099 1104 final void fireOwnPropertyChange(String name, Object o, Object n) { 1105 if ((o != null) && (n != null) && ((o == n) || o.equals(n))) { 1107 return; 1108 } 1109 1110 PropertyChangeEvent ev = null; 1111 1112 Object [] listeners = this.listeners.getListenerList(); 1113 1114 for (int i = listeners.length - 2; i >= 0; i -= 2) { 1117 if (listeners[i] == NodeListener.class) { 1118 if (ev == null) { 1120 ev = new PropertyChangeEvent (this, name, o, n); 1121 } 1122 1123 ((NodeListener) listeners[i + 1]).propertyChange(ev); 1124 } 1125 } 1126 } 1127 1128 1135 public boolean equals(Object obj) { 1136 if (obj instanceof FilterNode) { 1137 return ((FilterNode) obj).equals(this); 1138 } 1139 1140 return this == obj; 1141 } 1142 1143 1147 static String getString(final String resName) { 1148 return NbBundle.getBundle(Node.class).getString(resName); 1149 } 1150 1151 public String toString() { 1152 return super.toString() + "[Name=" + getName() + ", displayName=" + getDisplayName() + "]"; } 1154 1155 1159 public static interface Cookie { 1160 } 1161 1162 1170 public static interface Handle extends java.io.Serializable { 1171 1172 @Deprecated 1173 long serialVersionUID = -4518262478987434353L; 1174 1175 1180 public Node getNode() throws java.io.IOException ; 1181 } 1182 1183 1190 public static abstract class PropertySet extends FeatureDescriptor { 1191 1192 public PropertySet() { 1193 } 1194 1195 1200 public PropertySet(String name, String displayName, String shortDescription) { 1201 super.setName(name); 1202 super.setDisplayName(displayName); 1203 super.setShortDescription(shortDescription); 1204 } 1205 1206 1211 public abstract Property<?>[] getProperties(); 1212 1213 1216 public boolean equals(Object propertySet) { 1217 if (!(propertySet instanceof PropertySet)) { 1218 return false; 1219 } 1220 1221 return ((PropertySet) propertySet).getName().equals(getName()); 1222 } 1223 1224 1228 public int hashCode() { 1229 return getName().hashCode(); 1230 } 1231 1232 1248 public String getHtmlDisplayName() { 1249 return null; 1250 } 1251 } 1252 1253 1263 public static abstract class Property<T> extends FeatureDescriptor { 1264 1271 private static final Set <String > warnedNames = new HashSet <String >(); 1272 1273 1274 private Class <T> type; 1275 1276 private Reference <PropertyEditor > edRef = null; 1279 1280 1283 public Property(Class <T> valueType) { 1284 this.type = valueType; 1285 super.setName(""); } 1287 1288 1294 public Class <T> getValueType() { 1295 return type; 1296 } 1297 1298 1301 public abstract boolean canRead(); 1302 1303 1308 public abstract T getValue() throws IllegalAccessException , InvocationTargetException ; 1309 1310 1313 public abstract boolean canWrite(); 1314 1315 1321 public abstract void setValue(T val) 1322 throws IllegalAccessException , IllegalArgumentException , InvocationTargetException ; 1323 1324 1327 public boolean supportsDefaultValue() { 1328 return false; 1329 } 1330 1331 1339 public void restoreDefaultValue() throws IllegalAccessException , InvocationTargetException { 1340 } 1341 1342 1354 public boolean isDefaultValue() { 1355 String name = getClass().getName(); 1356 1357 if (supportsDefaultValue() && warnedNames.add(name)) { 1359 Logger.getLogger(Node.Property.class.getName()).log( 1360 Level.WARNING, 1361 "Class " + name + " must override isDefaultValue() since it " + 1362 "overrides supportsDefaultValue() to be true" 1363 ); 1364 } 1365 1366 return true; 1367 } 1368 1369 1372 public PropertyEditor getPropertyEditor() { 1373 if (type == null) { 1374 return null; 1375 } 1376 1377 PropertyEditor result = null; 1378 1379 if (edRef != null) { 1380 result = edRef.get(); 1381 } 1382 1383 if (result == null) { 1384 result = java.beans.PropertyEditorManager.findEditor(type); 1385 edRef = new SoftReference <PropertyEditor >(result); 1386 } 1387 1388 return result; 1389 } 1390 1391 1395 @Override 1396 public boolean equals(Object property) { 1397 if (!(property instanceof Property)) { 1400 return false; 1401 } 1402 1403 Class <?> propValueType = ((Property) property).getValueType(); 1404 Class <?> valueType = getValueType(); 1405 1406 if (((propValueType == null) && (valueType != null)) || ((propValueType != null) && (valueType == null))) { 1407 return false; 1408 } 1409 1410 return ((Property) property).getName().equals(getName()) && 1411 (((propValueType == null) && (valueType == null)) || propValueType.equals(valueType)); 1412 } 1413 1414 1418 @Override 1419 public int hashCode() { 1420 Class <?> valueType = getValueType(); 1421 1422 return getName().hashCode() * ((valueType == null) ? 1 : valueType.hashCode()); 1423 } 1424 1425 1440 public String getHtmlDisplayName() { 1441 return null; 1442 } 1443 } 1444 1445 1449 public static abstract class IndexedProperty<T,E> extends Node.Property<T> { 1450 1451 private Class <E> elementType; 1452 1453 1456 public IndexedProperty(Class <T> valueType, Class <E> elementType) { 1457 super(valueType); 1458 this.elementType = elementType; 1459 } 1460 1461 1464 public abstract boolean canIndexedRead(); 1465 1466 1469 public Class <E> getElementType() { 1470 return elementType; 1471 } 1472 1473 1481 public abstract E getIndexedValue(int index) 1482 throws IllegalAccessException , IllegalArgumentException , InvocationTargetException ; 1483 1484 1487 public abstract boolean canIndexedWrite(); 1488 1489 1497 public abstract void setIndexedValue(int indx, E val) 1498 throws IllegalAccessException , IllegalArgumentException , InvocationTargetException ; 1499 1500 1503 public PropertyEditor getIndexedPropertyEditor() { 1504 return java.beans.PropertyEditorManager.findEditor(elementType); 1505 } 1506 1507 1511 @Override 1512 public boolean equals(Object property) { 1513 try { 1514 if (!super.equals(property)) { 1515 return false; 1516 } 1517 1518 Class <?> propElementType = ((IndexedProperty) property).getElementType(); 1519 Class <?> elementType = getElementType(); 1520 1521 if ( 1522 ((propElementType == null) && (elementType != null)) || 1523 ((propElementType != null) && (elementType == null)) 1524 ) { 1525 return false; 1526 } 1527 1528 return (((propElementType == null) && (elementType == null)) || propElementType.equals(elementType)); 1529 } catch (ClassCastException e) { 1530 return false; 1531 } 1532 } 1533 1534 1538 @Override 1539 public int hashCode() { 1540 Class <?> ementType = getElementType(); 1541 1542 return super.hashCode() * ((elementType == null) ? 1 : elementType.hashCode()); 1543 } 1544 } 1545 1546 1549 private final class LookupEventList extends EventListenerList implements LookupListener { 1550 public final Lookup lookup; 1551 private Lookup.Result<Node.Cookie> result; 1552 1553 public LookupEventList(Lookup l) { 1554 this.lookup = l; 1555 } 1556 1557 public Lookup init(boolean init) { 1558 boolean doInit = false; 1559 1560 synchronized (INIT_LOCK) { 1561 if (init && (result == null)) { 1562 result = lookup.lookup(TEMPL_COOKIE); 1563 assert result != null : "Null lookup result from " + lookup + " in " + Node.this; 1564 result.addLookupListener(this); 1565 doInit = true; 1566 } 1567 } 1568 1569 if (doInit) { 1570 result.allItems(); 1571 } 1572 1573 return lookup; 1574 } 1575 1576 public void resultChanged(LookupEvent ev) { 1577 if (Node.this instanceof FilterNode) { 1578 FilterNode f = (FilterNode) Node.this; 1579 1580 if (f.getOriginal() == NodeLookup.NO_COOKIE_CHANGE.get()) { 1582 return; 1585 } 1586 } 1587 1588 fireCookieChange(); 1589 } 1590 } 1591} 1592 | Popular Tags |