1 19 20 package org.netbeans.modules.form; 21 22 import java.awt.event.*; 23 import java.beans.*; 24 import java.awt.datatransfer.*; 25 import javax.swing.text.DefaultEditorKit ; 26 27 import org.openide.*; 28 import org.openide.actions.PasteAction; 29 import org.openide.nodes.*; 30 import org.openide.explorer.*; 31 import org.openide.awt.UndoRedo; 32 import org.openide.explorer.view.BeanTreeView; 33 import org.openide.windows.*; 34 import org.openide.util.*; 35 import org.openide.util.actions.SystemAction; 36 import org.openide.util.actions.ActionPerformer; 37 import org.openide.util.datatransfer.*; 38 39 import org.netbeans.modules.form.actions.TestAction; 40 import org.netbeans.modules.form.palette.PaletteUtils; 41 42 47 48 public class ComponentInspector extends TopComponent 49 implements ExplorerManager.Provider 50 { 51 private ExplorerManager explorerManager; 52 53 private TestAction testAction = (TestAction) 54 SystemAction.findObject(TestAction.class, true); 55 56 private PasteAction pasteAction = (PasteAction) 57 SystemAction.findObject(PasteAction.class, true); 58 59 private CopyCutActionPerformer copyActionPerformer = new CopyCutActionPerformer(true); 60 private CopyCutActionPerformer cutActionPerformer = new CopyCutActionPerformer(false); 61 private DeleteActionPerformer deleteActionPerformer = new DeleteActionPerformer(); 62 63 private ClipboardListener clipboardListener; 64 65 66 private FormEditor focusedForm; 67 68 private EmptyInspectorNode emptyInspectorNode; 69 70 private BeanTreeView treeView; 71 72 73 private static final String EMPTY_INSPECTOR_ICON_BASE = 74 "org/netbeans/modules/form/resources/emptyInspector"; 76 77 private static final String iconURL = 78 "org/netbeans/modules/form/resources/inspector.png"; 80 private static ComponentInspector instance; 81 82 85 87 public static synchronized ComponentInspector getDefault() { 88 if (instance == null) 89 instance = new ComponentInspector(); 90 return instance; 91 } 92 93 94 public static synchronized ComponentInspector getInstance() { 95 if (instance == null) { 96 TopComponent tc = WindowManager.getDefault().findTopComponent("ComponentInspector"); if (instance == null) { 98 ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, new IllegalStateException ( 99 "Can not find ComponentInspector component for its ID. Returned " + tc)); instance = new ComponentInspector(); 101 } 102 } 103 return instance; 104 } 105 106 108 public int getPersistenceType() { 109 return TopComponent.PERSISTENCE_ALWAYS; 110 } 111 112 private ComponentInspector() { 113 explorerManager = new ExplorerManager(); 114 115 associateLookup( 116 ExplorerUtils.createLookup(explorerManager, setupActionMap(getActionMap())) 117 ); 118 119 emptyInspectorNode = new EmptyInspectorNode(); 120 explorerManager.setRootContext(emptyInspectorNode); 121 122 explorerManager.addPropertyChangeListener(new NodeSelectionListener()); 123 124 setLayout(new java.awt.BorderLayout ()); 125 createComponents(); 126 127 setIcon(Utilities.loadImage(iconURL)); 128 setName(FormUtils.getBundleString("CTL_InspectorTitle")); setToolTipText(FormUtils.getBundleString("HINT_ComponentInspector")); } 131 132 javax.swing.ActionMap setupActionMap(javax.swing.ActionMap map) { 133 map.put(DefaultEditorKit.copyAction, copyActionPerformer); 134 map.put(DefaultEditorKit.cutAction, cutActionPerformer); 135 map.put("delete", deleteActionPerformer); 138 return map; 139 } 140 141 private void createComponents() { 142 treeView = new BeanTreeView(); 143 treeView.setDragSource(true); 144 treeView.setDropTarget(true); 145 treeView.getAccessibleContext().setAccessibleName( 146 FormUtils.getBundleString("ACS_ComponentTree")); treeView.getAccessibleContext().setAccessibleDescription( 148 FormUtils.getBundleString("ACSD_ComponentTree")); add(java.awt.BorderLayout.CENTER, treeView); 150 } 151 152 155 public ExplorerManager getExplorerManager() { 157 return explorerManager; 158 } 159 160 public UndoRedo getUndoRedo() { 161 UndoRedo ur = focusedForm != null ? 162 focusedForm.getFormUndoRedoManager() : null; 163 return ur != null ? ur : super.getUndoRedo(); 164 } 165 166 public HelpCtx getHelpCtx() { 167 return new HelpCtx("gui.component-inspector"); } 169 170 171 public Object writeReplace() { 172 return new ResolvableHelper(); 173 } 174 175 protected void componentActivated() { 176 attachActions(); 177 } 178 179 protected void componentDeactivated() { 180 detachActions(); 181 } 182 183 186 synchronized void attachActions() { 187 ExplorerUtils.activateActions(explorerManager, true); 188 updatePasteAction(); 189 190 Clipboard c = getClipboard(); 191 if (c instanceof ExClipboard) { 192 ExClipboard clip = (ExClipboard) c; 193 if (clipboardListener == null) 194 clipboardListener = new ClipboardChangesListener(); 195 clip.addClipboardListener(clipboardListener); 196 } 197 } 198 199 synchronized void detachActions() { 200 ExplorerUtils.activateActions(explorerManager, false); 201 202 Clipboard c = getClipboard(); 203 if (c instanceof ExClipboard) { 204 ExClipboard clip = (ExClipboard) c; 205 clip.removeClipboardListener(clipboardListener); 206 } 207 } 208 209 212 public void focusForm(final FormEditor form) { 213 if (focusedForm != form) 214 focusFormInAwtThread(form, 0); 215 } 216 217 221 public void focusForm(final FormEditor form, boolean visible) { 222 if (focusedForm != form) 223 focusFormInAwtThread(form, visible ? 1 : -1); 224 } 225 226 private void focusFormInAwtThread(final FormEditor form, 227 final int visibility) { 228 if (java.awt.EventQueue.isDispatchThread()) { 229 focusFormImpl(form, visibility); 230 } 231 else { 232 java.awt.EventQueue.invokeLater(new Runnable () { 233 public void run() { 234 focusFormImpl(form, visibility); 235 } 236 }); 237 } 238 } 239 240 private void focusFormImpl(FormEditor form, int visibility) { 241 focusedForm = form; 242 243 if ((form == null) || (form.getFormDesigner() == null)) { 244 testAction.setFormDesigner(null); 245 PaletteUtils.setContext(null); 246 247 removeAll(); 249 createComponents(); 250 revalidate(); 251 252 getExplorerManager().setRootContext(emptyInspectorNode); 253 } 254 else { 255 Node[] selectedNodes = form.getFormDesigner().getSelectedComponentNodes(); 256 257 testAction.setFormDesigner(form.getFormDesigner()); 258 PaletteUtils.setContext(form.getFormDataObject().getPrimaryFile()); 259 260 Node formNode = form.getFormRootNode(); 261 if (formNode == null) { System.err.println("Warning: FormEditorSupport.getFormRootNode() returns null"); getExplorerManager().setRootContext(emptyInspectorNode); 264 } 265 else 266 getExplorerManager().setRootContext(formNode); 267 268 try { 269 getExplorerManager().setSelectedNodes(selectedNodes); 270 } catch (PropertyVetoException ex) { 271 ex.printStackTrace(); } 273 274 } 275 276 if (visibility > 0) 277 open(); 278 else if (visibility < 0) 279 close(); 280 } 281 282 public FormEditor getFocusedForm() { 283 return focusedForm; 284 } 285 286 288 void setSelectedNodes(Node[] nodes, FormEditor form) 289 throws PropertyVetoException 290 { 291 if (form == focusedForm) 292 getExplorerManager().setSelectedNodes(nodes); 293 } 294 295 Node[] getSelectedNodes() { 296 return getExplorerManager().getSelectedNodes(); 297 } 298 299 302 private void updatePasteAction() { 304 if(java.awt.EventQueue.isDispatchThread()) { 305 updatePasteActionInAwtThread(); 306 } else { 307 java.awt.EventQueue.invokeLater(new Runnable () { 308 public void run() { 309 updatePasteActionInAwtThread(); 310 } 311 }); 312 } 313 } 314 315 private void updatePasteActionInAwtThread() { 316 Node[] selected = getExplorerManager().getSelectedNodes(); 317 if (selected != null && selected.length == 1) { 318 Clipboard clipboard = getClipboard(); 320 Transferable trans = clipboard.getContents(this); if (trans != null) { 322 Node node = selected[0]; 323 PasteType[] pasteTypes = node.getPasteTypes(trans); 324 if (pasteTypes.length != 0) { 325 pasteAction.setPasteTypes(pasteTypes); 327 return; 328 } 329 330 boolean multiFlavor = false; 331 try { 332 multiFlavor = trans.isDataFlavorSupported( 333 ExTransferable.multiFlavor); 334 } 335 catch (Exception e) {} 337 if (multiFlavor) { 338 try { 342 MultiTransferObject mto = (MultiTransferObject) 343 trans.getTransferData(ExTransferable.multiFlavor); 344 345 int n = mto.getCount(), i; 346 Transferable[] t = new Transferable[n]; 347 PasteType[] p = new PasteType[n]; 348 349 for (i=0; i < n; i++) { 350 t[i] = mto.getTransferableAt(i); 351 pasteTypes = node.getPasteTypes(t[i]); 352 if (pasteTypes.length == 0) 353 break; 354 355 p[i] = pasteTypes[0]; } 357 358 if (i == n) { pasteAction.setPasteTypes( 360 new PasteType[] { new MultiPasteType(t, p) }); 361 return; 362 } 363 } 364 catch (Exception ex) { 365 org.openide.ErrorManager.getDefault().notify(org.openide.ErrorManager.INFORMATIONAL, ex); 366 } 367 } 368 } 369 } 370 371 pasteAction.setPasteTypes(null); 372 } 373 374 private Clipboard getClipboard() { 375 Clipboard c = (java.awt.datatransfer.Clipboard ) 376 Lookup.getDefault().lookup(java.awt.datatransfer.Clipboard .class); 377 if (c == null) 378 c = java.awt.Toolkit.getDefaultToolkit().getSystemClipboard(); 379 return c; 380 } 381 382 protected String preferredID() { 383 return getClass().getName(); 384 } 385 386 public boolean requestFocusInWindow() { 387 super.requestFocusInWindow(); 388 return treeView.requestFocusInWindow(); 389 } 390 391 394 private class NodeSelectionListener implements PropertyChangeListener, 396 ActionListener, Runnable 397 { 398 private javax.swing.Timer timer; 399 400 NodeSelectionListener() { 401 timer = new javax.swing.Timer (150, this); 402 timer.setCoalesce(true); 403 timer.setRepeats(false); 404 } 405 406 public void propertyChange(PropertyChangeEvent evt) { 407 if (!ExplorerManager.PROP_SELECTED_NODES.equals(evt.getPropertyName())) 408 return; 409 410 FormDesigner designer; 411 if (focusedForm == null 412 || (designer = focusedForm.getFormDesigner()) == null) 413 return; 414 415 Node[] selectedNodes = getExplorerManager().getSelectedNodes(); 416 417 if (designer.getDesignerMode() == FormDesigner.MODE_CONNECT) { 418 if (selectedNodes.length > 0) { 420 RADComponentCookie cookie = (RADComponentCookie) 421 selectedNodes[0].getCookie(RADComponentCookie.class); 422 if (cookie != null 423 && cookie.getRADComponent() == designer.getConnectionSource() 424 && selectedNodes.length > 1) 425 { 426 cookie = (RADComponentCookie) 427 selectedNodes[selectedNodes.length-1] 428 .getCookie(RADComponentCookie.class); 429 } 430 if (cookie != null) 431 designer.connectBean(cookie.getRADComponent(), true); 432 } 433 } 434 else if (evt.getSource() == ComponentInspector.this.getExplorerManager()) 435 { designer.clearSelectionImpl(); 437 for (int i=0; i < selectedNodes.length; i++) { 438 FormCookie formCookie = (FormCookie) 439 selectedNodes[i].getCookie(FormCookie.class); 440 if (formCookie != null) { 441 Node node = formCookie.getOriginalNode(); 442 if (node instanceof RADComponentNode) 443 designer.addComponentToSelectionImpl( 444 ((RADComponentNode)node).getRADComponent()); 445 } 446 } 447 designer.repaintSelection(); 448 } 449 450 for (int i=0; i < selectedNodes.length; i++) 452 ((FormNode)selectedNodes[i]).updateCookies(); 453 454 timer.restart(); 456 } 457 458 public void actionPerformed(ActionEvent evt) { java.awt.EventQueue.invokeLater(this); } 461 462 467 public void run() { 468 Node[] selectedNodes = getExplorerManager().getSelectedNodes(); 469 setActivatedNodes(selectedNodes); 470 FormDesigner designer = focusedForm != null ? 472 focusedForm.getFormDesigner() : null; 473 if (designer != null) 474 designer.setActivatedNodes(selectedNodes); 475 476 updatePasteAction(); 477 478 timer.stop(); 479 } 480 } 481 482 private class ClipboardChangesListener implements ClipboardListener { 484 public void clipboardChanged(ClipboardEvent ev) { 485 if (!ev.isConsumed()) 486 updatePasteAction(); 487 } 488 } 489 490 private class DeleteActionPerformer extends javax.swing.AbstractAction 492 implements ActionPerformer, Mutex.Action 493 { 494 private Node[] nodesToDestroy; 495 496 public void actionPerformed(ActionEvent e) { 497 performAction(null); 498 } 499 500 public void performAction(SystemAction action) { 501 Node[] selected = getExplorerManager().getSelectedNodes(); 502 503 if (selected == null || selected.length == 0) 504 return; 505 506 for (int i=0; i < selected.length; i++) 507 if (!selected[i].canDestroy()) 508 return; 509 510 try { getExplorerManager().setSelectedNodes(new Node[0]); 512 } 513 catch (PropertyVetoException e) {} 515 nodesToDestroy = selected; 516 if (java.awt.EventQueue.isDispatchThread()) 517 doDelete(); 518 else Mutex.EVENT.readAccess(this); 520 } 521 522 public Object run() { 523 doDelete(); 524 return null; 525 } 526 527 private void doDelete() { 528 if (nodesToDestroy != null) { 529 for (int i=0; i < nodesToDestroy.length; i++) { 530 try { 531 nodesToDestroy[i].destroy(); 532 } 533 catch (java.io.IOException ex) { ex.printStackTrace(); 535 } 536 } 537 nodesToDestroy = null; 538 } 539 } 540 } 541 542 private class CopyCutActionPerformer extends javax.swing.AbstractAction 544 implements ActionPerformer 545 { 546 private boolean copy; 547 548 public CopyCutActionPerformer(boolean copy) { 549 this.copy = copy; 550 } 551 552 public void actionPerformed(ActionEvent e) { 553 performAction(null); 554 } 555 556 public void performAction(SystemAction action) { 557 Transferable trans; 558 Node[] selected = getExplorerManager().getSelectedNodes(); 559 560 if (selected == null || selected.length == 0) 561 trans = null; 562 else if (selected.length == 1) 563 trans = getTransferableOwner(selected[0]); 564 else { 565 Transferable[] transArray = new Transferable[selected.length]; 566 for (int i=0; i < selected.length; i++) 567 if ((transArray[i] = getTransferableOwner(selected[i])) 568 == null) 569 return; 570 571 trans = new ExTransferable.Multi(transArray); 572 } 573 574 if (trans != null) { 575 Clipboard clipboard = getClipboard(); 576 clipboard.setContents(trans, new StringSelection("")); } 578 } 579 580 private Transferable getTransferableOwner(Node node) { 581 try { 582 return copy ? node.clipboardCopy() : node.clipboardCut(); 583 } 584 catch (java.io.IOException e) { 585 ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e); 586 return null; 587 } 588 } 589 } 590 591 private static class MultiPasteType extends PasteType 593 implements Mutex.ExceptionAction 594 { 595 private Transferable[] transIn; 596 private PasteType[] pasteTypes; 597 598 MultiPasteType(Transferable[] t, PasteType[] p) { 599 transIn = t; 600 pasteTypes = p; 601 } 602 603 public Transferable paste() throws java.io.IOException { 605 if (java.awt.EventQueue.isDispatchThread()) 606 return doPaste(); 607 else { try { 609 return (Transferable) Mutex.EVENT.readAccess(this); 610 } 611 catch (MutexException ex) { 612 Exception e = ex.getException(); 613 if (e instanceof java.io.IOException ) 614 throw (java.io.IOException ) e; 615 else { e.printStackTrace(); 617 return ExTransferable.EMPTY; 618 } 619 } 620 } 621 } 622 623 public Object run() throws Exception { 624 return doPaste(); 625 } 626 627 private Transferable doPaste() throws java.io.IOException { 628 Transferable[] transOut = new Transferable[transIn.length]; 629 for (int i=0; i < pasteTypes.length; i++) { 630 Transferable newTrans = pasteTypes[i].paste(); 631 transOut[i] = newTrans != null ? newTrans : transIn[i]; 632 } 633 return new ExTransferable.Multi(transOut); 634 } 635 } 636 637 639 private static class EmptyInspectorNode extends AbstractNode { 641 public EmptyInspectorNode() { 642 super(Children.LEAF); 643 setIconBase(EMPTY_INSPECTOR_ICON_BASE); 644 } 645 public boolean canRename() { 646 return false; 647 } 648 } 649 650 final public static class ResolvableHelper implements java.io.Serializable { 651 static final long serialVersionUID = 7424646018839457544L; 652 public Object readResolve() { 653 return ComponentInspector.getDefault(); 654 } 655 } 656 } 657 | Popular Tags |