1 19 package org.netbeans.modules.project.ui; 20 21 import java.awt.GridBagConstraints ; 22 import java.awt.GridBagLayout ; 23 import java.awt.Font ; 24 import java.awt.Image ; 25 import java.awt.event.ActionEvent ; 26 import java.awt.event.ActionListener ; 27 import java.awt.event.KeyEvent ; 28 import java.beans.PropertyChangeEvent ; 29 import java.beans.PropertyChangeListener ; 30 import java.beans.PropertyVetoException ; 31 import java.beans.VetoableChangeListener ; 32 import java.io.IOException ; 33 import java.io.InputStream ; 34 import java.net.URL ; 35 import java.util.StringTokenizer ; 36 import javax.swing.JComponent ; 37 import javax.swing.JPanel ; 38 import javax.swing.KeyStroke ; 39 import javax.swing.SwingUtilities ; 40 import javax.swing.ToolTipManager ; 41 import javax.swing.UIManager ; 42 import javax.swing.border.Border ; 43 import javax.swing.text.ChangedCharSetException ; 44 import javax.swing.text.Document ; 45 import javax.swing.text.html.HTMLEditorKit ; 46 import javax.swing.text.html.StyleSheet ; 47 import org.openide.ErrorManager; 48 import org.openide.awt.Mnemonics; 49 import org.openide.explorer.ExplorerManager; 50 import org.openide.explorer.view.BeanTreeView; 51 import org.openide.explorer.view.ListView; 52 import org.openide.filesystems.FileObject; 53 import org.openide.loaders.*; 54 import org.openide.nodes.AbstractNode; 55 import org.openide.nodes.Children; 56 import org.openide.nodes.FilterNode; 57 import org.openide.nodes.Node; 58 import org.openide.nodes.NodeNotFoundException; 59 import org.openide.nodes.NodeOp; 60 import org.openide.util.NbBundle; 61 import org.openide.util.RequestProcessor; 62 import org.openide.util.Utilities; 63 64 68 public class TemplatesPanelGUI extends javax.swing.JPanel implements PropertyChangeListener { 69 70 public static interface Builder { 71 72 public Children createCategoriesChildren (DataFolder folder); 73 74 public Children createTemplatesChildren (DataFolder folder); 75 76 public String getCategoriesName (); 77 78 public String getTemplatesName (); 79 80 public void fireChange (); 81 } 82 83 public static final String TEMPLATES_FOLDER = "templatesFolder"; public static final String TARGET_TEMPLATE = "targetTemplate"; private static final String ATTR_INSTANTIATING_DESC = "instantiatingWizardURL"; private static final Image PLEASE_WAIT_ICON = Utilities.loadImage ("org/netbeans/modules/project/ui/resources/wait.gif"); 88 private Builder firer; 89 90 private static final RequestProcessor RP = new RequestProcessor(); 91 92 private String presetTemplateName = null; 93 private Node pleaseWait; 94 95 96 public TemplatesPanelGUI (Builder firer) { 97 assert firer != null : "Builder can not be null"; this.firer = firer; 99 initComponents(); 100 postInitComponents (); 101 setName (NbBundle.getMessage(TemplatesPanelGUI.class, "TXT_SelectTemplate")); } 103 104 public void setTemplatesFolder (final FileObject folder) { 105 DataFolder dobj = DataFolder.findFolder (folder); 106 ((ExplorerProviderPanel)this.categoriesPanel).setRootNode(new FilterNode ( 107 dobj.getNodeDelegate(), this.firer.createCategoriesChildren(dobj))); 108 } 109 110 public void setSelectedCategoryByName (final String categoryName) { 111 if (categoryName != null) { 112 try { 113 ((org.netbeans.modules.project.ui.TemplatesPanelGUI.ExplorerProviderPanel) this.categoriesPanel).setSelectedNode(categoryName); 114 } 115 catch (NodeNotFoundException ex) { 116 ((CategoriesPanel)this.categoriesPanel).selectFirstCategory (); 118 } 119 } else { 120 ((CategoriesPanel)this.categoriesPanel).selectFirstCategory (); 122 } 123 } 124 125 public String getSelectedCategoryName () { 126 return ((ExplorerProviderPanel)this.categoriesPanel).getSelectionPath(); 127 } 128 129 public void setSelectedTemplateByName (final String templateName) { 130 presetTemplateName = templateName; 131 final TemplatesPanel tempExplorer = ((TemplatesPanel)this.projectsPanel); 132 133 SwingUtilities.invokeLater (new Runnable () { 134 public void run () { 135 if (templateName != null) { 136 try { 137 tempExplorer.setSelectedNode(templateName); 138 } 139 catch (NodeNotFoundException ex) { 140 } 142 if (tempExplorer.getSelectionPath() == null) { 143 presetTemplateName = null; 144 tempExplorer.selectFirstTemplate(); 145 } 146 } else { 147 tempExplorer.selectFirstTemplate (); 148 } 149 } 150 }); 151 152 } 153 154 public String getSelectedTemplateName () { 155 return ((TemplatesPanel)this.projectsPanel).getSelectionPath(); 156 } 157 158 public FileObject getSelectedTemplate () { 159 Node[] nodes = ((ExplorerProviderPanel) this.projectsPanel).getSelectedNodes(); 160 if (nodes != null && nodes.length == 1) { 161 DataObject dobj = nodes[0].getCookie(DataObject.class); 162 if (dobj != null) { 163 while (dobj instanceof DataShadow) { 164 dobj = ((DataShadow)dobj).getOriginal(); 165 } 166 return dobj.getPrimaryFile(); 167 } 168 } 169 return null; 170 } 171 172 public void propertyChange (PropertyChangeEvent event) { 173 if (event.getSource() == this.categoriesPanel) { 174 if (ExplorerManager.PROP_SELECTED_NODES.equals (event.getPropertyName ())) { 175 Node[] selectedNodes = (Node[]) event.getNewValue(); 176 if (selectedNodes != null && selectedNodes.length == 1) { 177 assert pleaseWait == null || !pleaseWait.equals (selectedNodes[0]) : "Cannot be fired a propertyChange with PleaseWaitNode, but was " + selectedNodes[0]; 178 try { 179 ((ExplorerProviderPanel)this.projectsPanel).setSelectedNodes(new Node[0]); 180 } catch (PropertyVetoException e) { 181 182 } 183 DataObject template = (DataObject) selectedNodes[0].getCookie(DataFolder.class); 184 if (template != null) { 185 FileObject fo = template.getPrimaryFile(); 186 ((ExplorerProviderPanel)this.projectsPanel).setRootNode( 187 new FilterNode (selectedNodes[0], this.firer.createTemplatesChildren((DataFolder)template))); 188 this.setSelectedTemplateByName (presetTemplateName); 190 } 191 } 192 } 193 } 194 else if (event.getSource() == this.projectsPanel) { 195 if (ExplorerManager.PROP_SELECTED_NODES.equals (event.getPropertyName())) { 196 Node[] selectedNodes = (Node[]) event.getNewValue (); 197 if (selectedNodes != null && selectedNodes.length == 1) { 198 DataObject template = selectedNodes[0].getCookie(DataObject.class); 199 if (template != null) { 200 FileObject fo = template.getPrimaryFile(); 201 URL descURL = getDescription (template); 202 if (descURL != null) { 203 try { 204 210 String charset = findEncodingFromURL (descURL.openStream ()); 213 ErrorManager.getDefault ().log (ErrorManager.INFORMATIONAL, "Url " + descURL + " has charset " + charset); if (charset != null) { 215 description.putClientProperty ("charset", charset); } 217 this.description.read( descURL.openStream(), descURL ); 218 } catch (ChangedCharSetException x) { 219 Document doc = description.getEditorKit ().createDefaultDocument (); 220 doc.putProperty ("IgnoreCharsetDirective", Boolean.valueOf (true)); try { 222 description.read (descURL.openStream (), doc); 223 } catch (IOException ioe) { 224 ErrorManager.getDefault ().notify (ErrorManager.INFORMATIONAL, ioe); 225 this.description.setText (NbBundle.getBundle (TemplatesPanelGUI.class).getString ("TXT_NoDescription")); } 227 } catch (IOException e) { 228 ErrorManager.getDefault ().notify (ErrorManager.INFORMATIONAL, e); 229 this.description.setText (NbBundle.getBundle (TemplatesPanelGUI.class).getString ("TXT_NoDescription")); } 231 } 232 else { 233 this.description.setText (NbBundle.getBundle (TemplatesPanelGUI.class).getString ("TXT_NoDescription")); } 235 } 236 } else { 237 this.description.setText (NbBundle.getBundle (TemplatesPanelGUI.class).getString ("TXT_NoDescription")); } 240 this.firer.fireChange (); 241 } 242 } 243 } 244 245 private void postInitComponents () { 246 Mnemonics.setLocalizedText(jLabel1, this.firer.getCategoriesName()); 247 Mnemonics.setLocalizedText(jLabel2, this.firer.getTemplatesName()); 248 this.description.setEditorKit(new HTMLEditorKit ()); 249 250 pleaseWait = new AbstractNode (Children.LEAF) { 252 public Image getIcon (int ignore) { 253 return PLEASE_WAIT_ICON; 254 } 255 }; 256 pleaseWait.setName (NbBundle.getBundle (TemplatesPanelGUI.class).getString ("LBL_TemplatesPanel_PleaseWait")); 257 Children ch = new Children.Array (); 258 ch.add (new Node[] {pleaseWait}); 259 final Node root = new AbstractNode (ch); 260 SwingUtilities.invokeLater (new Runnable () { 261 public void run () { 262 ((ExplorerProviderPanel)categoriesPanel).setRootNode (root); 263 } 264 }); 265 } 266 267 272 private void initComponents() { 274 java.awt.GridBagConstraints gridBagConstraints; 275 276 jLabel1 = new javax.swing.JLabel (); 277 jLabel2 = new javax.swing.JLabel (); 278 categoriesPanel = new CategoriesPanel (); 279 projectsPanel = new TemplatesPanel (); 280 jLabel3 = new javax.swing.JLabel (); 281 jScrollPane1 = new javax.swing.JScrollPane (); 282 description = new javax.swing.JEditorPane (); 283 284 setPreferredSize(new java.awt.Dimension (500, 230)); 285 setLayout(new java.awt.GridBagLayout ()); 286 287 jLabel1.setLabelFor(categoriesPanel); 288 org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getBundle(TemplatesPanelGUI.class).getString("CTL_Categories")); gridBagConstraints = new java.awt.GridBagConstraints (); 290 gridBagConstraints.gridx = 0; 291 gridBagConstraints.gridy = 0; 292 gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; 293 gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; 294 gridBagConstraints.weightx = 0.4; 295 gridBagConstraints.insets = new java.awt.Insets (0, 0, 0, 6); 296 add(jLabel1, gridBagConstraints); 297 298 jLabel2.setLabelFor(projectsPanel); 299 org.openide.awt.Mnemonics.setLocalizedText(jLabel2, org.openide.util.NbBundle.getBundle(TemplatesPanelGUI.class).getString("CTL_Templates")); gridBagConstraints = new java.awt.GridBagConstraints (); 301 gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER; 302 gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; 303 gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; 304 gridBagConstraints.weightx = 0.6; 305 gridBagConstraints.insets = new java.awt.Insets (0, 6, 0, 0); 306 add(jLabel2, gridBagConstraints); 307 gridBagConstraints = new java.awt.GridBagConstraints (); 308 gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; 309 gridBagConstraints.weightx = 0.4; 310 gridBagConstraints.weighty = 0.7; 311 gridBagConstraints.insets = new java.awt.Insets (2, 0, 6, 6); 312 add(categoriesPanel, gridBagConstraints); 313 gridBagConstraints = new java.awt.GridBagConstraints (); 314 gridBagConstraints.gridx = 1; 315 gridBagConstraints.gridy = 1; 316 gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER; 317 gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; 318 gridBagConstraints.weightx = 0.6; 319 gridBagConstraints.weighty = 0.7; 320 gridBagConstraints.insets = new java.awt.Insets (2, 6, 6, 0); 321 add(projectsPanel, gridBagConstraints); 322 323 jLabel3.setLabelFor(description); 324 org.openide.awt.Mnemonics.setLocalizedText(jLabel3, org.openide.util.NbBundle.getBundle(TemplatesPanelGUI.class).getString("CTL_Description")); gridBagConstraints = new java.awt.GridBagConstraints (); 326 gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER; 327 gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; 328 gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; 329 gridBagConstraints.insets = new java.awt.Insets (2, 0, 0, 0); 330 add(jLabel3, gridBagConstraints); 331 332 description.setEditable(false); 333 description.setText(org.openide.util.NbBundle.getBundle(TemplatesPanelGUI.class).getString("TXT_NoDescription")); description.setPreferredSize(new java.awt.Dimension (100, 66)); 335 jScrollPane1.setViewportView(description); 336 337 gridBagConstraints = new java.awt.GridBagConstraints (); 338 gridBagConstraints.gridx = 0; 339 gridBagConstraints.gridy = 3; 340 gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER; 341 gridBagConstraints.gridheight = java.awt.GridBagConstraints.REMAINDER; 342 gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; 343 gridBagConstraints.weightx = 1.0; 344 gridBagConstraints.weighty = 0.3; 345 gridBagConstraints.insets = new java.awt.Insets (2, 0, 0, 0); 346 add(jScrollPane1, gridBagConstraints); 347 } 349 private URL getDescription (DataObject dobj) { 350 FileObject fo = dobj.getPrimaryFile(); 352 URL desc = (URL ) fo.getAttribute(ATTR_INSTANTIATING_DESC); 353 if (desc != null) { 354 return desc; 355 } 356 desc = TemplateWizard.getDescription (dobj); 357 return desc; 358 } 359 360 private static abstract class ExplorerProviderPanel extends JPanel implements ExplorerManager.Provider, PropertyChangeListener , VetoableChangeListener { 361 362 private ExplorerManager manager; 363 364 protected ExplorerProviderPanel () { 365 this.manager = new ExplorerManager (); 366 this.manager.addPropertyChangeListener(this); 367 this.manager.addVetoableChangeListener(this); 368 this.initGUI (); 369 } 370 371 public void setRootNode (Node node) { 372 this.manager.setRootContext(node); 373 } 374 375 public Node getRootNode () { 376 return this.manager.getRootContext(); 377 } 378 379 public Node[] getSelectedNodes () { 380 return this.manager.getSelectedNodes(); 381 } 382 383 public void setSelectedNodes (Node[] nodes) throws PropertyVetoException { 384 this.manager.setSelectedNodes(nodes); 385 } 386 387 public void setSelectedNode (String path) throws NodeNotFoundException { 388 if (path == null) { 389 return; 390 } 391 StringTokenizer tk = new StringTokenizer (path,"/"); String [] names = new String [tk.countTokens()]; 393 for (int i=0;tk.hasMoreTokens();i++) { 394 names[i] = tk.nextToken(); 395 } 396 try { 397 Node node = NodeOp.findPath(this.manager.getRootContext(),names); 398 if (node != null) { 399 this.manager.setSelectedNodes(new Node[] {node}); 400 } 401 } catch (PropertyVetoException e) { 402 } 404 } 405 406 public String getSelectionPath () { 407 Node[] selectedNodes = this.manager.getSelectedNodes(); 408 if (selectedNodes == null || selectedNodes.length != 1) { 409 return null; 410 } 411 Node rootNode = this.manager.getRootContext(); 412 String [] path = NodeOp.createPath(selectedNodes[0],rootNode); 413 StringBuffer builder = new StringBuffer (); 414 for (int i=0; i< path.length; i++) { 415 builder.append('/'); builder.append(path[i]); 417 } 418 return builder.substring(1); 419 } 420 421 public ExplorerManager getExplorerManager() { 422 return this.manager; 423 } 424 425 426 public void propertyChange (final PropertyChangeEvent event) { 427 SwingUtilities.invokeLater (new Runnable () { 435 public void run () { 436 firePropertyChange(event.getPropertyName(), 437 event.getOldValue(), event.getNewValue()); 438 } 439 }); 440 } 441 442 443 public void vetoableChange(PropertyChangeEvent evt) throws PropertyVetoException { 444 if (ExplorerManager.PROP_SELECTED_NODES.equals (evt.getPropertyName())) { 445 Node[] newValue = (Node[]) evt.getNewValue(); 446 if (newValue == null || (newValue.length != 1 && newValue.length != 0)) { 447 throw new PropertyVetoException ("Invalid length",evt); } 449 } 450 } 451 452 public void requestFocus () { 453 this.createComponent().requestFocus(); 454 } 455 456 protected abstract JComponent createComponent (); 457 458 private void initGUI () { 459 this.setLayout (new GridBagLayout ()); 460 GridBagConstraints c = new GridBagConstraints (); 461 c.gridx = GridBagConstraints.RELATIVE; 462 c.gridy = GridBagConstraints.RELATIVE; 463 c.gridwidth = GridBagConstraints.REMAINDER; 464 c.gridheight = GridBagConstraints.REMAINDER; 465 c.fill = GridBagConstraints.BOTH; 466 c.anchor = GridBagConstraints.NORTHWEST; 467 c.weightx = 1.0; 468 c.weighty = 1.0; 469 JComponent component = this.createComponent (); 470 ((GridBagLayout )this.getLayout()).setConstraints(component, c); 471 this.add (component); 472 } 473 474 } 475 476 477 private static class CategoriesBeanTreeView extends BeanTreeView { 478 public CategoriesBeanTreeView () { 479 super (); 480 this.tree.setEditable(false); 481 } 482 public void selectFirstCategory () { 483 SwingUtilities.invokeLater (new Runnable () { 484 public void run () { 485 tree.setSelectionRow (0); 486 } 487 }); 488 } 489 } 490 491 private static final class CategoriesPanel extends ExplorerProviderPanel { 492 493 private CategoriesBeanTreeView btv; 494 495 protected synchronized JComponent createComponent () { 496 if (this.btv == null) { 497 this.btv = new CategoriesBeanTreeView (); 498 this.btv.setRootVisible(false); 499 this.btv.setPopupAllowed(false); 500 this.btv.setDefaultActionAllowed(false); 501 this.btv.getAccessibleContext ().setAccessibleName (NbBundle.getMessage (TemplatesPanelGUI.class, "ACSN_CategoriesPanel")); this.btv.getAccessibleContext ().setAccessibleDescription (NbBundle.getMessage (TemplatesPanelGUI.class, "ACSD_CategoriesPanel")); this.btv.setBorder((Border )UIManager.get("Nb.ScrollPane.border")); } 505 return this.btv; 506 } 507 508 public void selectFirstCategory () { 509 btv.selectFirstCategory (); 510 } 511 512 } 513 514 private static class TemplatesListView extends ListView implements ActionListener { 515 public TemplatesListView () { 516 super (); 517 list.unregisterKeyboardAction (KeyStroke.getKeyStroke (KeyEvent.VK_ENTER, 0, false)); 519 getAccessibleContext ().setAccessibleName ("OUTER LIST"); 520 getAccessibleContext ().setAccessibleDescription ("DESC OUTER LIST"); 521 setDefaultProcessor( this ); 522 ToolTipManager.sharedInstance ().unregisterComponent (list); 523 } 524 525 public void actionPerformed( ActionEvent e ) { 526 } 528 } 529 530 private static final class TemplatesPanel extends ExplorerProviderPanel { 531 532 private ListView list; 533 534 protected synchronized JComponent createComponent () { 535 if (this.list == null) { 536 this.list = new TemplatesListView (); 537 this.list.setPopupAllowed(false); 538 this.list.getAccessibleContext ().setAccessibleName (NbBundle.getMessage (TemplatesPanelGUI.class, "ACSN_TemplatesPanel")); this.list.getAccessibleContext ().setAccessibleDescription (NbBundle.getMessage (TemplatesPanelGUI.class, "ACSD_TemplatesPanel")); this.list.setBorder((Border )UIManager.get("Nb.ScrollPane.border")); } 542 543 return this.list; 544 } 545 546 public void selectFirstTemplate () { 547 try { 548 Children ch = getExplorerManager ().getRootContext ().getChildren (); 549 if (ch.getNodesCount () > 0) { 550 getExplorerManager ().setSelectedNodes (new Node[] { ch.getNodes ()[0] }); 551 } 552 } catch (PropertyVetoException pve) { 553 } 555 } 556 557 } 558 559 private javax.swing.JPanel categoriesPanel; 561 private javax.swing.JEditorPane description; 562 private javax.swing.JLabel jLabel1; 563 private javax.swing.JLabel jLabel2; 564 private javax.swing.JLabel jLabel3; 565 private javax.swing.JScrollPane jScrollPane1; 566 private javax.swing.JPanel projectsPanel; 567 569 570 void warmUp (FileObject templatesFolder) { 571 if (templatesFolder != null) { 572 DataFolder df = DataFolder.findFolder (templatesFolder); 573 if (df != null) { 574 df.getChildren(); 575 } 576 } 577 } 578 579 void doFinished (FileObject temlatesFolder, String category, String template) { 580 assert temlatesFolder != null; 581 582 this.categoriesPanel.addPropertyChangeListener(this); 583 this.projectsPanel.addPropertyChangeListener(this); 584 585 this.setTemplatesFolder (temlatesFolder); 586 this.setSelectedCategoryByName (category); 587 this.setSelectedTemplateByName (template); 588 categoriesPanel.requestFocus (); 589 if (description.getEditorKit() instanceof HTMLEditorKit ) { 590 593 598 HTMLEditorKit htmlkit = (HTMLEditorKit ) description.getEditorKit(); 599 StyleSheet css = htmlkit.getStyleSheet(); 600 if (css.getStyleSheets() != null) 601 return; 602 603 StyleSheet css2 = new StyleSheet (); 604 Font f = jLabel1.getFont(); 605 css2.addRule(new StringBuffer ("body { font-size: ").append(f.getSize()) .append("; font-family: ").append(f.getName()).append("; }").toString()); css2.addStyleSheet(css); 608 htmlkit.setStyleSheet(css2); 609 } 610 } 611 612 private static String findEncodingFromURL (InputStream stream) { 614 try { 615 byte[] arr = new byte[4096]; 616 int len = stream.read (arr, 0, arr.length); 617 String txt = new String (arr, 0, (len>=0)?len:0).toUpperCase(); 618 return findEncoding (txt); 620 } catch (Exception x) { 621 x.printStackTrace(); 622 } 623 return null; 624 } 625 626 631 private static String findEncoding (String txt) { 632 int headLen = txt.indexOf ("</HEAD>"); if (headLen == -1) headLen = txt.length (); 634 635 int content = txt.indexOf ("CONTENT-TYPE"); if (content == -1 || content > headLen) { 637 return null; 638 } 639 640 int charset = txt.indexOf ("CHARSET=", content); if (charset == -1) { 642 return null; 643 } 644 645 int charend = txt.indexOf ('"', charset); 646 int charend2 = txt.indexOf ('\'', charset); 647 if (charend == -1 && charend2 == -1) { 648 return null; 649 } 650 651 if (charend2 != -1) { 652 if (charend == -1 || charend > charend2) { 653 charend = charend2; 654 } 655 } 656 657 return txt.substring (charset + "CHARSET=".length (), charend); } 659 660 } 661 | Popular Tags |