1 19 20 package org.netbeans.beaninfo.editors; 21 22 import java.awt.event.KeyEvent ; 23 import java.io.IOException ; 24 import java.lang.ref.*; 25 import java.util.Arrays ; 26 import java.util.StringTokenizer ; 27 import java.beans.*; 28 import java.io.File ; 29 30 import javax.swing.event.DocumentListener ; 31 import javax.swing.event.ChangeListener ; 32 import javax.swing.event.ChangeEvent ; 33 import javax.swing.KeyStroke ; 34 import javax.swing.SwingUtilities ; 35 import org.openide.explorer.propertysheet.PropertyEnv; 36 import org.openide.loaders.*; 37 import org.openide.nodes.*; 38 import org.openide.explorer.ExplorerManager; 39 import org.openide.filesystems.*; 40 import org.openide.util.Exceptions; 41 import org.openide.util.HelpCtx; 42 import org.openide.util.NbCollections; 43 import org.openide.windows.TopComponent; 44 49 class DataFolderPanel extends TopComponent implements 50 DocumentListener , DataFilter, 51 PropertyChangeListener, VetoableChangeListener { 52 53 54 static java.awt.Dimension PREF_DIM = new java.awt.Dimension (450, 250); 55 56 57 58 private ChangeListener listener; 59 60 61 Reference<FileSystem> system = new WeakReference<FileSystem> (null); 62 63 64 private Node rootNode; 65 66 67 private DataFolder df; 68 69 70 private DataFolderEditor editor; 71 72 private static final String PATH_TOKEN_DELIMITER = "/" + java.io.File.separatorChar; 74 private String last_suggestion = ""; 75 76 public DataFolderPanel(DataFolderEditor ed) { 77 this(); 78 editor = ed; 79 80 editor.env.setState(PropertyEnv.STATE_NEEDS_VALIDATION); 81 editor.env.addPropertyChangeListener(this); 82 } 83 84 85 public DataFolderPanel() { 86 initComponents (); 87 88 setName (getString("LAB_TargetLocationPanelName")); 89 90 setBorder (new javax.swing.border.EmptyBorder (new java.awt.Insets (12, 12, 0, 11))); 91 97 98 rootNode = createPackagesNode (); 99 100 beanTreeView.setRootVisible (false); 101 102 packagesPanel.getExplorerManager ().setRootContext (rootNode); 103 packagesPanel.getExplorerManager ().addPropertyChangeListener (this); 104 packagesPanel.getExplorerManager ().addVetoableChangeListener (this); 105 106 packageName.getDocument().addDocumentListener(this); 108 packageName.unregisterKeyboardAction(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0)); 109 110 beanTreeView.getAccessibleContext().setAccessibleDescription(getString("ACSD_DataFolderTree")); 111 packageName.getAccessibleContext().setAccessibleDescription(getString("ACSD_package")); 112 directoryName.getAccessibleContext().setAccessibleDescription(getString("ACSD_directory")); 113 createButton.getAccessibleContext().setAccessibleDescription(getString("ACSD_Create")); 114 getAccessibleContext().setAccessibleDescription(getString("ACSD_DataFolderPanel")); 115 } 116 117 118 public java.awt.Dimension getPreferredSize() { 119 return PREF_DIM; 120 } 121 122 124 public void requestFocus () { 125 } 130 131 133 private Node createPackagesNode () { 134 Node topNode = RepositoryNodeFactory.getDefault().repository(this); 135 Node [] nodes = topNode.getChildren ().getNodes (true); 136 assert nodes != null && nodes.length == 1 : "Only one subnode " + topNode + " found, but was " + Arrays.asList (nodes); 137 return nodes [0]; 138 } 139 140 145 private void initComponents() { 147 java.awt.GridBagConstraints gridBagConstraints; 148 149 packagesPanel = new org.netbeans.beaninfo.ExplorerPanel(); 150 beanTreeView = new org.openide.explorer.view.BeanTreeView(); 151 descriptionLabel = new javax.swing.JLabel (); 152 packageLabel = new javax.swing.JLabel (); 153 packageName = new javax.swing.JTextField (); 154 dirLabel = new javax.swing.JLabel (); 155 directoryName = new javax.swing.JTextField (); 156 createButton = new javax.swing.JButton (); 157 158 setLayout(new java.awt.BorderLayout ()); 159 160 packagesPanel.setLayout(new java.awt.GridBagLayout ()); 161 162 beanTreeView.setDefaultActionAllowed(false); 163 beanTreeView.setPopupAllowed(false); 164 gridBagConstraints = new java.awt.GridBagConstraints (); 165 gridBagConstraints.gridx = 0; 166 gridBagConstraints.gridy = 1; 167 gridBagConstraints.gridwidth = 3; 168 gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; 169 gridBagConstraints.weightx = 1.0; 170 gridBagConstraints.weighty = 1.0; 171 gridBagConstraints.insets = new java.awt.Insets (0, 0, 5, 0); 172 packagesPanel.add(beanTreeView, gridBagConstraints); 173 174 descriptionLabel.setLabelFor(beanTreeView); 175 org.openide.awt.Mnemonics.setLocalizedText(descriptionLabel, org.openide.util.NbBundle.getBundle(DataFolderPanel.class).getString("LAB_TargetLocationDescription")); gridBagConstraints = new java.awt.GridBagConstraints (); 177 gridBagConstraints.gridx = 0; 178 gridBagConstraints.gridy = 0; 179 gridBagConstraints.gridwidth = 3; 180 gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; 181 gridBagConstraints.insets = new java.awt.Insets (0, 0, 2, 0); 182 packagesPanel.add(descriptionLabel, gridBagConstraints); 183 184 packageLabel.setLabelFor(packageName); 185 org.openide.awt.Mnemonics.setLocalizedText(packageLabel, org.openide.util.NbBundle.getBundle(DataFolderPanel.class).getString("LAB_package")); gridBagConstraints = new java.awt.GridBagConstraints (); 187 gridBagConstraints.gridx = 0; 188 gridBagConstraints.gridy = 2; 189 gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; 190 gridBagConstraints.insets = new java.awt.Insets (0, 0, 5, 12); 191 packagesPanel.add(packageLabel, gridBagConstraints); 192 gridBagConstraints = new java.awt.GridBagConstraints (); 193 gridBagConstraints.gridx = 1; 194 gridBagConstraints.gridy = 2; 195 gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; 196 gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; 197 gridBagConstraints.weightx = 1.0; 198 gridBagConstraints.insets = new java.awt.Insets (0, 0, 5, 5); 199 packagesPanel.add(packageName, gridBagConstraints); 200 201 org.openide.awt.Mnemonics.setLocalizedText(dirLabel, org.openide.util.NbBundle.getBundle(DataFolderPanel.class).getString("LAB_directory")); gridBagConstraints = new java.awt.GridBagConstraints (); 203 gridBagConstraints.gridx = 0; 204 gridBagConstraints.gridy = 3; 205 gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; 206 gridBagConstraints.insets = new java.awt.Insets (0, 0, 0, 12); 207 packagesPanel.add(dirLabel, gridBagConstraints); 208 209 directoryName.setEnabled(false); 210 gridBagConstraints = new java.awt.GridBagConstraints (); 211 gridBagConstraints.gridx = 1; 212 gridBagConstraints.gridy = 3; 213 gridBagConstraints.gridwidth = 2; 214 gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; 215 packagesPanel.add(directoryName, gridBagConstraints); 216 217 org.openide.awt.Mnemonics.setLocalizedText(createButton, org.openide.util.NbBundle.getBundle(DataFolderPanel.class).getString("CTL_Create")); createButton.setEnabled(false); 219 createButton.addActionListener(new java.awt.event.ActionListener () { 220 public void actionPerformed(java.awt.event.ActionEvent evt) { 221 createButtonActionPerformed(evt); 222 } 223 }); 224 gridBagConstraints = new java.awt.GridBagConstraints (); 225 gridBagConstraints.gridx = 2; 226 gridBagConstraints.gridy = 2; 227 gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; 228 gridBagConstraints.insets = new java.awt.Insets (0, 0, 5, 0); 229 packagesPanel.add(createButton, gridBagConstraints); 230 231 add(packagesPanel, java.awt.BorderLayout.CENTER); 232 } 234 private void createButtonActionPerformed(java.awt.event.ActionEvent evt) { try { 236 final DataFolder newDf = (DataFolder)getPropertyValue(); 238 setTargetFolder(newDf); 240 updateDirectory (); 241 updatePropertyEditor(); 242 enableCreateButton(); 243 } catch (IllegalStateException ex) { 244 throw new RuntimeException (ex.getMessage()); 245 } 246 } 248 249 private org.openide.explorer.view.BeanTreeView beanTreeView; 251 private javax.swing.JButton createButton; 252 private javax.swing.JLabel descriptionLabel; 253 private javax.swing.JLabel dirLabel; 254 private javax.swing.JTextField directoryName; 255 private javax.swing.JLabel packageLabel; 256 private javax.swing.JTextField packageName; 257 private org.netbeans.beaninfo.ExplorerPanel packagesPanel; 258 260 264 269 public boolean acceptDataObject(DataObject obj) { 270 return obj instanceof DataFolder; 271 } 272 273 275 public void vetoableChange(PropertyChangeEvent ev) 276 throws PropertyVetoException { 277 if (ExplorerManager.PROP_SELECTED_NODES.equals (ev.getPropertyName ())) { 278 Node[] arr = (Node[])ev.getNewValue(); 279 280 if (arr.length > 1) { 281 throw new PropertyVetoException ("Only single selection allowed", ev); } 283 } 284 } 285 286 288 public void propertyChange (PropertyChangeEvent ev) { 289 if (ExplorerManager.PROP_SELECTED_NODES.equals (ev.getPropertyName ())) { 290 Node[] arr = packagesPanel.getExplorerManager ().getSelectedNodes (); 291 if (!isVisible()) { 292 return; 294 } 295 if (arr.length == 1) { 296 if (!isValid ()) { 297 setTargetFolder (null); 298 implSetDataFolder (null); 299 return ; 300 } 301 DataFolder df = (DataFolder)arr[0].getCookie (DataFolder.class); 302 if (df != null) { 303 setTargetFolder (df); 304 updatePropertyEditor(); 305 enableCreateButton(); 306 return; 307 } 308 } 309 setTargetFolder (null); 310 implSetDataFolder (null); 311 } 312 313 314 if (PropertyEnv.PROP_STATE.equals(ev.getPropertyName()) && ev.getNewValue() == PropertyEnv.STATE_VALID) { 315 editor.setValue(getPropertyValue()); 316 } 317 318 } 319 320 322 private void fireStateChanged () { 323 if (listener != null) { 324 listener.stateChanged (new ChangeEvent (this)); 325 } 326 } 327 328 332 public void changedUpdate(final javax.swing.event.DocumentEvent p1) { 333 if (p1.getDocument () == packageName.getDocument ()) { 334 SwingUtilities.invokeLater (new Runnable () { 335 public void run () { 336 String text = packageName.getText (); 337 if (text != null) { 338 if (isValid()) { 339 setTargetFolder (text, false); 340 updatePropertyEditor(); 341 } 342 updateDirectory (); 343 } 344 enableCreateButton(); 345 } 346 }); 347 return; 348 } 349 } 350 351 public void removeUpdate(final javax.swing.event.DocumentEvent p1) { 352 if (p1.getDocument () == packageName.getDocument ()) { 355 SwingUtilities.invokeLater(new Runnable () { 356 public void run () { 357 if (packageName.getText ().length () == 0) { 358 FileSystem fs = system.get (); 359 if (fs != null) { 360 DataFolder df = DataFolder.findFolder (fs.getRoot ()); 361 setTargetFolder (df); 362 packageName.selectAll (); 363 } 364 } 365 String text = packageName.getText (); 366 if (text != null) { 367 if (isValid()) { 368 setTargetFolder (text, true); 369 updatePropertyEditor(); 370 } 371 updateDirectory (); 372 } 373 enableCreateButton(); 374 } 375 }); 376 } 377 } 378 379 public void insertUpdate(final javax.swing.event.DocumentEvent p1) { 380 changedUpdate (p1); 381 } 382 383 384 387 public org.openide.util.HelpCtx getHelp () { 388 return new HelpCtx (DataFolderPanel.class); 389 } 390 391 395 public boolean isValid () { 396 String text = packageName.getText (); 397 if (text.length () == 0) { 398 Node[] arr = packagesPanel.getExplorerManager ().getSelectedNodes (); 399 if (arr.length == 1 && arr[0] == rootNode) { 400 return false; 401 } 402 } 403 404 return true; 405 } 406 407 411 public void addChangeListener (ChangeListener l) { 412 if (listener != null) throw new IllegalStateException (); 413 414 listener = l; 415 } 416 417 420 public void removeChangeListener (ChangeListener l) { 421 listener = null; 422 } 423 424 433 private static String computeSuggestion ( 434 Node node, 435 String pref, 436 Node[] first 437 ) { 438 Node[] arr = node.getChildren ().getNodes (); 439 440 String match = null; 441 442 for (int i = 0; i < arr.length; i++) { 443 String name = arr[i].getName (); 444 if (name.startsWith (pref)) { 445 if (match == null) { 447 match = name; 449 if (first != null) { 450 first[0] = arr[i]; 451 } 452 } else { 453 int indx = pref.length (); 455 int end = Math.min (name.length (), match.length ()); 456 while (indx < end && match.charAt (indx) == name.charAt (indx)) { 457 indx++; 458 } 459 match = match.substring (0, indx); 460 } 461 } 462 } 463 464 if (match == null ) { return null; 466 } else { 467 return match.substring (pref.length ()); 468 } 469 } 470 471 472 476 boolean setTargetFolder (final DataFolder f) { 477 boolean exact; 478 Node n = null; 479 String name; 480 481 df = f; 482 483 if (f != null) { 484 FileObject fo = f.getPrimaryFile (); 485 name = fo.getPath(); 486 487 StringTokenizer st = new StringTokenizer (name, PATH_TOKEN_DELIMITER); 488 try { 489 FileSystem fs = fo.getFileSystem (); 490 491 if (fo.isRoot ()) { 492 name = packageName.getText().trim(); 494 boolean withSubfolder = name.indexOf (File.separatorChar) != -1; 496 if (fo.getFileObject (name) != null || withSubfolder) { 497 name = ""; } 499 } 500 501 system = new WeakReference<FileSystem> (fs); 502 503 n = NodeOp.findPath(rootNode, NbCollections.checkedEnumerationByFilter(st, String .class, true)); 504 505 exact = true; 506 507 } catch (FileStateInvalidException ex) { 508 n = rootNode; 510 name = ""; exact = false; 512 } catch (NodeNotFoundException ex) { 513 n = ex.getClosestNode(); 514 DataFolder df = (DataFolder)n.getCookie (DataFolder.class); 515 if (df != null) { 516 name = df.getPrimaryFile ().getPath (); 517 } else { 518 name = ""; } 520 exact = false; 521 } 522 523 524 } else { 525 n = rootNode; 527 name = null; 528 exact = true; 529 } 530 531 ExplorerManager em = packagesPanel.getExplorerManager (); 533 em.removePropertyChangeListener (this); 534 packageName.getDocument ().removeDocumentListener (this); 535 536 try { 537 em.setSelectedNodes (new Node[] { n }); 538 } catch (PropertyVetoException ex) { 539 throw new InternalError (); 540 } 541 542 packageName.setText (name); 543 updateDirectory (); 544 545 packageName.getDocument ().addDocumentListener (this); 546 em.addPropertyChangeListener (this); 547 548 fireStateChanged (); 549 550 return exact; 551 } 552 553 559 private DataFolder getTargetFolder(boolean create) throws IOException { 560 if (create && isValid()) { 561 FileSystem fs = system.get (); 562 if (fs != null) { 563 DataFolder folder = DataFolder.findFolder (fs.getRoot ()); 564 String currentName = packageName.getText().replace('\\', '/'); 565 if (currentName.length () > 0) { 566 folder = DataFolder.create (folder, currentName); 567 } 568 df = folder; 569 return folder; 570 } 571 } 572 return df; 573 } 574 575 579 private boolean setTargetFolder (final String f, boolean afterDelete) { 580 Node n = null; 581 NodeNotFoundException closest = null; 582 583 java.util.Collection <Node> selected = new java.util.HashSet <Node> (); 586 Node[] nodes = packagesPanel.getExplorerManager().getSelectedNodes(); 587 for ( int i = 0; i < nodes.length; i++ ) { 588 Node n1 = nodes[i]; 589 if ( n1.getParentNode() == null ) { 590 continue; 591 } 592 while ( n1.getParentNode().getParentNode() != null ) 593 n1 = n1.getParentNode(); 594 selected.add( n1 ); 595 } 596 597 StringTokenizer st = new StringTokenizer (f, PATH_TOKEN_DELIMITER); 598 599 try { 600 n = NodeOp.findPath(rootNode, NbCollections.checkedEnumerationByFilter(st, String .class, true)); 601 } catch (NodeNotFoundException ex) { 602 if (!st.hasMoreElements ()) { 603 607 final String sugg = computeSuggestion ( 609 ex.getClosestNode (), 610 ex.getMissingChildName(), 611 null 612 ); 613 614 if ( sugg != null ) { 615 closest = ex; 618 } 619 } 620 } 621 622 if (n != null) { 623 closest = null; 625 } else { 626 627 if (closest == null) { 628 return false; 630 } 631 632 n = closest.getClosestNode (); 634 635 637 } 638 639 ExplorerManager em = packagesPanel.getExplorerManager (); 641 em.removePropertyChangeListener (this); 642 643 if (closest != null) { 645 Node[] first = new Node[1]; 646 String sugg = computeSuggestion ( 647 closest.getClosestNode (), 648 closest.getMissingChildName(), 649 first 650 ); 651 652 if ( afterDelete && sugg != null && sugg.equals( last_suggestion ) ) 653 sugg = null; 654 655 last_suggestion = sugg; 656 if (sugg != null) { 657 packageName.getDocument ().removeDocumentListener ( 658 DataFolderPanel.this 659 ); 660 661 packageName.setText (f + sugg); 662 updateDirectory (); 663 664 javax.swing.text.Caret c = packageName.getCaret (); 665 c.setDot (f.length () + sugg.length ()); 666 c.moveDot (f.length ()); 667 668 packageName.getDocument ().addDocumentListener ( 669 DataFolderPanel.this 670 ); 671 } 672 673 if (first[0] != null) { 674 n = first[0]; 676 } 677 } 678 679 680 try { 682 em.setSelectedNodes(new Node[] { n }); 683 } catch (PropertyVetoException ex) { 685 throw new InternalError (); 686 } 687 688 df = (DataFolder)n.getCookie (DataFolder.class); 690 if (df != null) { 691 try { 692 FileSystem fs = df.getPrimaryFile ().getFileSystem (); 693 system = new WeakReference<FileSystem> (fs); 694 } catch (FileStateInvalidException ex) { 695 } 696 } 697 698 699 em.addPropertyChangeListener (this); 700 701 fireStateChanged (); 702 703 return closest == null; 704 } 705 706 708 void updateDirectory () { 709 FileSystem fs = system.get (); 710 if (fs == null) { 711 directoryName.setText(""); return; 714 } 715 String name = packageName.getText (); 716 FileObject folder = fs.findResource(name); 717 if (folder != null) { 718 File f = FileUtil.toFile(folder); 719 if (f != null) { 720 directoryName.setText(f.getAbsolutePath()); 722 } else { 723 directoryName.setText(""); } 726 } else { 727 FileObject fo = fs.getRoot(); 728 assert fo != null : fs; 729 File f = FileUtil.toFile(fo); 730 if (f != null) { 731 File f2 = new File (f, name.replace('/', File.separatorChar)); directoryName.setText(f2.getAbsolutePath()); 737 } else { 738 directoryName.setText(""); } 742 } 743 } 744 745 private void implSetDataFolder (DataFolder df) { 747 if (editor != null) { 748 if (!isValid ()) { 749 editor.setDataFolder (null); 750 } else { 751 FileSystem fs = null; 752 if (system != null) { 753 fs = system.get(); 754 } 755 if (df == null && fs!= null) { 756 FileObject fo = fs.getRoot(); 757 if (fo != null) { 759 df = DataFolder.findFolder (fo); 760 } 761 } 762 if (df != null) { 763 String name = df.getPrimaryFile ().getPath (); 764 if (name.equals(packageName.getText())) { 765 editor.setDataFolder (df); 766 } else { 767 editor.setDataFolder (null); 768 } 769 } else { 770 editor.setDataFolder(null); 771 } 772 } 773 } 774 } 775 776 777 void updatePropertyEditor() { 778 try { 779 DataFolder newF = getTargetFolder(false); 780 implSetDataFolder (newF); 783 } catch (IOException ex) { 784 Exceptions.printStackTrace(ex); 785 } 786 } 787 788 789 void enableCreateButton() { 790 String name = null; 791 if (df != null) { 792 name = df.getPrimaryFile ().getPath (); 793 } else { 794 name = ""; } 796 if (name.equals(packageName.getText())) { 797 createButton.setEnabled(false); 799 } else { 800 createButton.setEnabled(isValid()); 801 } 802 } 803 804 805 810 private Object getPropertyValue() throws IllegalStateException { 811 if (isValid()) { 812 try { 813 df = getTargetFolder(true); 814 return df; 815 } catch (IOException x) { 816 Exceptions.printStackTrace(x); 817 throw new IllegalStateException (); 818 } 819 } else { 820 throw new IllegalStateException (); 821 } 822 } 823 public static class ShadowDirNode extends AbstractNode { 824 public ShadowDirNode(Children children) { 825 super(children); 826 } 827 } 828 829 public static class ShadowLeafNode extends AbstractNode { 830 public ShadowLeafNode() { 831 super(Children.LEAF); 832 } 833 } 834 835 private static String getString (String s) { 836 return org.openide.util.NbBundle.getBundle (DataFolderPanel.class).getString (s); 837 } 838 } 839 | Popular Tags |