1 19 20 package org.openide.src.nodes; 21 22 import java.awt.Component ; 23 import java.beans.*; 24 import java.io.IOException ; 25 import java.lang.reflect.Modifier ; 26 import java.lang.reflect.InvocationTargetException ; 27 import java.util.*; 28 import java.awt.datatransfer.Transferable ; 29 import org.openide.DialogDisplayer; 30 31 import org.openide.ErrorManager; 32 import org.openide.src.*; 33 import org.openide.nodes.*; 34 import org.openide.util.NbBundle; 35 import org.openide.util.datatransfer.*; 36 import org.openide.NotifyDescriptor; 37 38 39 44 public class ClassElementNode extends MemberElementNode { 45 46 47 private static final String [] ICON_AFFECTING_PROPERTIES = new String [] { 48 PROP_CLASS_OR_INTERFACE 49 }; 50 51 56 public ClassElementNode(ClassElement element, Children children, boolean writeable) { 57 super(element, children, writeable); 58 setElementFormat0(((ClassElement)element).isInterface() ? 59 sourceOptions.getInterfaceElementFormat() : 60 sourceOptions.getClassElementFormat()); 61 } 62 63 public org.openide.util.HelpCtx getHelpCtx () { 64 if (((ClassElement)element).isClassOrInterface()) 65 return new org.openide.util.HelpCtx ("org.openide.src.nodes.ClassNode"); else 67 return new org.openide.util.HelpCtx ("org.openide.src.nodes.InterfaceNode"); } 69 70 73 protected String resolveIconBase() { 74 return ((ClassElement)element).isInterface() ? INTERFACE : CLASS; 75 } 76 77 81 protected String [] getIconAffectingProperties() { 82 return ICON_AFFECTING_PROPERTIES; 83 } 84 85 88 protected ElementFormat getHintElementFormat() { 89 return ((ClassElement)element).isInterface() ? 90 sourceOptions.getInterfaceElementLongFormat() : 91 sourceOptions.getClassElementLongFormat(); 92 } 93 94 95 protected Sheet createSheet () { 96 Sheet sheet = Sheet.createDefault(); 97 Sheet.Set ps = sheet.get(Sheet.PROPERTIES); 98 ps.put(createModifiersProperty(writeable)); 99 ps.put(createNameProperty(writeable)); 100 if (((ClassElement)element).isClass()) 101 ps.put(createSuperclassProperty(writeable)); 102 ps.put(createInterfacesProperty(writeable)); 103 return sheet; 104 } 105 106 110 public void destroy() throws IOException { 111 SourceEditSupport.invokeAtomicAsUser(element, new SourceEditSupport.ExceptionalRunnable() { 112 public void run() throws SourceException { 113 ClassElement el = (ClassElement) element; 114 if (el.getDeclaringClass() != null) { 115 el.getDeclaringClass().removeClass(el); 116 } 117 else { 118 el.getSource().removeClass(el); 119 } 120 } 121 }); 122 super.destroy(); 123 } 124 125 public Component getCustomizer() { 126 return new ClassCustomizer((ClassElement)element); 127 } 128 129 public boolean hasCustomizer() { 130 return isWriteable(); 131 } 132 133 144 protected void createPasteTypes (final Transferable t, java.util.List s) { 145 if (isWriteable()) { 146 if (t.isDataFlavorSupported(ExTransferable.multiFlavor)) { 148 createMultiPasteTypes(t, s, NodeTransfer.COPY); 149 createMultiPasteTypes(t, s, NodeTransfer.MOVE); 150 return; 151 } 152 for (int i = 0; i <= 1; i++) { 153 final boolean delete = (i == 1); 154 final Element addingElement = (Element) NodeTransfer.cookie(t, 155 delete ? NodeTransfer.MOVE : NodeTransfer.COPY, Element.class); 156 157 if (addingElement != null && isValidElement(addingElement)) { 158 s.add(new PasteType() { 159 public Transferable paste() throws IOException { 160 pasteElement(addingElement, delete); 161 return delete ? ExTransferable.EMPTY : null; 162 } 163 }); 164 } 165 } 166 } 167 super.createPasteTypes(t, s); 168 } 169 170 171 private static boolean isValidElement(Element el) { 172 Element.Impl2 impl = (Element.Impl2) el.getCookie(Element.Impl2.class); 174 return impl == null || impl.isValid(); 175 } 176 177 private void createMultiPasteTypes(Transferable t, List s, int action) { 178 MultiTransferObject mto; 179 180 try { 181 mto = (MultiTransferObject) t.getTransferData (ExTransferable.multiFlavor); 182 } catch (java.awt.datatransfer.UnsupportedFlavorException ex) { 183 return; 184 } catch (IOException ex) { 185 return; 186 } 187 188 int count = mto.getCount(); 189 Collection candidates = new LinkedList(); 190 191 for (int i = 0; i < count; i++) { 192 Node n = NodeTransfer.node(mto.getTransferableAt(i), action); 193 if (n == null) 194 break; 195 Element el = (Element)n.getCookie(Element.class); 196 if (el == null || !isValidElement(el) || 199 !(el instanceof MemberElement || el instanceof InitializerElement)) 200 break; 201 addNodeCandidate(candidates, el); 205 } 206 if (candidates.isEmpty()) 207 return; 208 s.add(new SourceEditSupport.ClassMultiPasteType( 209 this, candidates, (action & NodeTransfer.MOVE) > 0)); 210 } 211 212 private void addNodeCandidate(Collection candidates, Element el) { 213 ClassElement enc2 = findEnclosingClass(el); 214 SourceElement enc2Src = enc2.getSource(); 215 String fn2 = enc2.getName().getFullName(); 216 217 for (Iterator it = candidates.iterator(); it.hasNext(); ) { 218 Element can = (Element)it.next(); 219 ClassElement enc1 = findEnclosingClass(can); 220 221 if (enc1.getSource() != enc2Src) { 222 continue; 223 } 224 if (enc1 == enc2) { 226 if (can == enc1) { 227 return; 229 } else if (el == enc2) { 230 it.remove(); 234 continue; 236 } else { 237 break; 240 } 241 } 242 String fn1 = enc1.getName().getFullName(); 243 if (fn2.startsWith(fn1)) { 244 if (enc1 == can) { 245 return; 247 } else 248 continue; 249 } else if (fn1.startsWith(fn2)) { 250 if (enc2 == el) { 251 it.remove(); 252 continue; 253 } else 254 break; 255 } 256 } 257 candidates.add(el); 258 } 259 260 private ClassElement findEnclosingClass(Element el) { 261 if (el instanceof ClassElement) 262 return (ClassElement)el; 263 else if (el instanceof MemberElement) 264 return ((MemberElement)el).getDeclaringClass(); 265 else if (el instanceof InitializerElement) 266 return ((InitializerElement)el).getDeclaringClass(); 267 else 268 return null; 269 } 270 271 PropertyChangeListener createElementListener() { 272 return new ClassElementListener(); 273 } 274 275 280 void pasteElement(final Element addingElement, final boolean delete) throws IOException { 281 final boolean[] cancelled = {false}; 282 283 ClassElement declClazz, myDecl; 286 287 if (addingElement instanceof ClassElement) { 288 declClazz = (ClassElement)addingElement; 289 for (myDecl = (ClassElement)element; myDecl != null; myDecl = myDecl.getDeclaringClass()) { 290 if (declClazz == myDecl) { 291 throw (IOException )ErrorManager.getDefault().annotate( 292 new IOException ("Recursion detected"), bundle.getString("ERR_RecursePaste") 294 ); 295 } 296 } 297 } 298 SourceEditSupport.invokeAtomicAsUser(element, new SourceEditSupport.ExceptionalRunnable() { 299 public void run() throws SourceException { 300 ClassElement clazz = (ClassElement) element; 301 if (addingElement instanceof InitializerElement) { 302 InitializerElement e = (InitializerElement)addingElement; 303 clazz.addInitializer(e); 304 } 305 if (addingElement instanceof FieldElement) { 306 clazz.addField((FieldElement)addingElement); 307 } 308 else if (addingElement instanceof MethodElement) { 309 MethodElement me = (MethodElement) addingElement; 310 if (((ClassElement) element).isInterface()) { 311 if (delete 312 && (me.getBody() != null) 313 && (!me.getBody().trim().equals("")) && (!isPastingConfirmed(me))) { 315 cancelled[0] = true; 316 return; 317 } 318 me = (MethodElement) me.clone(); 319 me.setBody(null); 320 } else if (me.getBody() == null) { 321 me = (MethodElement) me.clone(); 322 me.setBody(""); } 324 clazz.addMethod(me); 325 } 326 else if (addingElement instanceof ConstructorElement) { 327 clazz.addConstructor((ConstructorElement)addingElement); 328 } 329 else if (addingElement instanceof ClassElement) { 330 ClassElement pclass = (ClassElement)addingElement; 331 ClassElement myClass; 332 333 clazz.addClass(pclass); 334 myClass = clazz.getClass(Identifier.create(pclass.getName().getName())); 335 if (pclass.getDeclaringClass() == null && myClass != null) { 336 myClass.setModifiers(myClass.getModifiers() | Modifier.STATIC); 339 } 340 } 341 } 342 }); 343 if (delete && (!cancelled[0])) { 344 final ClassElement origClazz; 345 SourceElement src = null; 346 347 if (addingElement instanceof InitializerElement) { 348 origClazz = ((InitializerElement)addingElement).getDeclaringClass(); 349 } else if (addingElement instanceof MemberElement) { 350 origClazz = ((MemberElement)addingElement).getDeclaringClass(); 351 if (addingElement instanceof ClassElement) { 352 ClassElement me = (ClassElement)addingElement; 353 src = me.getSource(); 354 } 355 } else { 356 origClazz = null; 357 } 358 359 if (src == null && origClazz != null) { 360 src = origClazz.getSource(); 361 } 362 363 final SourceElement classSource = src; 364 SourceEditSupport.ExceptionalRunnable r = new SourceEditSupport.ExceptionalRunnable() { 365 public void run() throws SourceException { 366 if (addingElement instanceof InitializerElement) { 367 InitializerElement e = (InitializerElement)addingElement; 368 if (origClazz != null) 369 origClazz.removeInitializer(e); 370 } else if (addingElement instanceof MemberElement) { 371 if (origClazz != null) { 372 if (addingElement instanceof FieldElement) { 373 origClazz.removeField((FieldElement)addingElement); 374 } else if (addingElement instanceof MethodElement) { 375 origClazz.removeMethod((MethodElement)addingElement); 376 } else if (addingElement instanceof ConstructorElement) { 377 origClazz.removeConstructor((ConstructorElement)addingElement); 378 } else if (addingElement instanceof ClassElement) { 379 origClazz.removeClass((ClassElement)addingElement); 380 } 381 } else if ((addingElement instanceof ClassElement) && 382 classSource != null) { 383 classSource.removeClass((ClassElement)addingElement); 384 } 385 } 386 } 387 }; 388 389 if (src == null) { 390 try { 391 r.run(); 392 } catch (SourceException e) { 393 throw new IOException (e.getMessage()); 394 } 395 } else { 396 SourceEditSupport.invokeAtomicAsUser(addingElement, r); 397 } 398 } 399 } 400 401 408 private boolean isPastingConfirmed(MethodElement me) { 409 String title = NbBundle.getMessage(ClassElementNode.class, 410 "TIT_PastingMethod"); String text = NbBundle.getMessage(ClassElementNode.class, 412 "CONFIRM_DeleteMethodBody", me.getName()); 414 NotifyDescriptor desc = new NotifyDescriptor.Confirmation( 415 text, title, NotifyDescriptor.YES_NO_OPTION); 416 return NotifyDescriptor.YES_OPTION.equals 417 (DialogDisplayer.getDefault().notify(desc)); 418 419 } 420 421 422 426 protected Node.Property createSuperclassProperty(boolean canW) { 427 return new ElementProp(PROP_SUPERCLASS, String .class, canW) { 428 429 public Object getValue () { 430 Identifier id = ((ClassElement)element).getSuperclass(); 431 return id == null ? "" : id.getFullName(); } 433 434 435 public void setValue(final Object val) throws IllegalArgumentException , 436 IllegalAccessException , InvocationTargetException { 437 super.setValue(val); 438 if (!(val instanceof String )) 439 throw new IllegalArgumentException (); 440 final String str = ((String )val).trim(); 441 if (str != null && !"".equals(str)) { 442 Type t = Type.parse(str); 443 if (!t.isClass()) 444 throw new IllegalArgumentException (); 445 } 446 447 runAtomic(element, new SourceEditSupport.ExceptionalRunnable() { 448 public void run() throws SourceException { 449 Identifier superclass = str.equals("") ? null: Identifier.create(str); ((ClassElement)element).setSuperclass(superclass); 451 } 452 }); 453 } 454 }; 455 } 456 457 462 protected Node.Property createInterfacesProperty(boolean canW) { 463 ElementProp prop = new ElementProp(PROP_INTERFACES, Identifier[].class, canW) { 464 465 public Object getValue () { 466 return ((ClassElement)element).getInterfaces(); 467 } 468 469 470 public void setValue(final Object val) throws IllegalArgumentException , 471 IllegalAccessException , InvocationTargetException { 472 super.setValue(val); 473 if (!(val instanceof Identifier[])) 474 throw new IllegalArgumentException (); 475 476 runAtomic(element, new SourceEditSupport.ExceptionalRunnable() { 477 public void run() throws SourceException { 478 ((ClassElement)element).setInterfaces((Identifier[])val); 479 } 480 }); 481 } 482 }; 483 484 if (((ClassElement)element).isInterface()) { 485 prop.setDisplayName(bundle.getString("PROP_superInterfaces")); 486 prop.setShortDescription(bundle.getString("HINT_superInterfaces")); 487 } 488 prop.setValue("changeImmediate" ,Boolean.FALSE); return prop; 490 } 491 492 public NewType[] getNewTypes() { 493 if (writeable) { 494 return SourceEditSupport.createNewTypes((ClassElement)element); 495 } else { 496 return super.getNewTypes(); 497 } 498 } 499 500 public Transferable clipboardCopy() { 501 Transferable t = NodeTransfer.transferable(this, NodeTransfer.CLIPBOARD_COPY); 502 ExTransferable xt = ExTransferable.create(t); 503 xt.put(NodeTransfer.createPaste(new SourceEditSupport.PackagePaste( 504 (ClassElement)this.element, false 505 ))); 506 return xt; 507 } 508 509 public Transferable clipboardCut() { 510 Transferable t = NodeTransfer.transferable(this, NodeTransfer.CLIPBOARD_CUT); 511 ExTransferable xt = ExTransferable.create(t); 512 xt.put(NodeTransfer.createPaste(new SourceEditSupport.PackagePaste( 513 (ClassElement)this.element, true 514 ))); 515 return xt; 516 } 517 518 private class ClassElementListener extends ElementListener { 519 public void propertyChange(PropertyChangeEvent evt) { 520 if (evt.getPropertyName().equals(ElementProperties.PROP_CLASS_OR_INTERFACE)) { 521 setElementFormat(((ClassElement)element).isClass() ? 522 sourceOptions.getClassElementFormat() : 523 sourceOptions.getInterfaceElementFormat()); 524 } 525 super.propertyChange(evt); 526 } 527 } 528 } 529 | Popular Tags |