001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041: package org.netbeans.modules.visualweb.propertyeditors;
042:
043: import java.awt.Component;
044: import java.awt.Image;
045: import java.beans.BeanInfo;
046: import java.io.File;
047: import java.io.FileFilter;
048: import java.io.IOException;
049: import java.net.MalformedURLException;
050: import java.net.URI;
051: import java.net.URISyntaxException;
052: import java.util.ArrayList;
053: import java.util.Collections;
054: import java.util.Enumeration;
055: import java.util.HashMap;
056: import java.util.ResourceBundle;
057: import java.util.Stack;
058: import java.util.WeakHashMap;
059: import javax.faces.component.UIComponent;
060: import javax.faces.component.UIViewRoot;
061: import javax.swing.ImageIcon;
062: import javax.swing.JFileChooser;
063: import javax.swing.JTree;
064: import javax.swing.tree.DefaultTreeCellRenderer;
065: import javax.swing.tree.DefaultTreeModel;
066: import javax.swing.tree.MutableTreeNode;
067: import com.sun.rave.designtime.DesignContext;
068: import com.sun.rave.designtime.DesignProject;
069: import com.sun.rave.designtime.DesignBean;
070: import com.sun.rave.designtime.DesignProperty;
071: import com.sun.rave.designtime.faces.FacesDesignProject;
072: import com.sun.rave.designtime.markup.MarkupDesignBean;
073: import javax.swing.tree.TreeNode;
074: import javax.swing.tree.TreePath;
075: import org.openide.ErrorManager;
076: import org.openide.filesystems.FileObject;
077: import org.openide.filesystems.FileUtil;
078: import org.openide.loaders.DataObject;
079: import org.openide.loaders.DataObjectNotFoundException;
080: import org.w3c.dom.Element;
081: import org.w3c.dom.NodeList;
082:
083: /**
084: * A custom property editor for URL properties. URLs may be edited by hand in a
085: * combo box, which makes current URLs found elsewhere in the project as
086: * alternative selections. A URL to a project resource or page may be constructed
087: * by choosing a target from a tree of target nodes. In this case, the editor
088: * will generate a "context relative" URL (a URL that begins with '/').
089: *
090: * @author gjmurphy
091: */
092: public class UrlPropertyPanel extends PropertyPanelBase {
093:
094: protected static ResourceBundle resourceBundle = ResourceBundle
095: .getBundle("org.netbeans.modules.visualweb.propertyeditors.Bundle");
096:
097: /**
098: * A map of projects to the most recently examined file path for that
099: * project.
100: */
101: protected static WeakHashMap directoryMap = new WeakHashMap();
102:
103: /**
104: * A default file filter used to hide project files that aren't deployed (NB
105: * backup files), and project files that cannot be targeted (JSP page fragments
106: * and files that are in the WEB-INF directory).
107: */
108: static FileFilter defaultFileFilter = new FileFilter() {
109: public boolean accept(File file) {
110: String fileName = file.getName();
111: if (fileName == null)
112: return false;
113: if (file.isDirectory() && fileName.equals("WEB-INF")) //NOI18N
114: return false;
115: if (fileName.endsWith(".jspf") || fileName.endsWith("~")) //NOI18N
116: return false;
117: return true;
118: }
119: };
120:
121: UrlPropertyEditor editor;
122: DesignContext designContext;
123: ResourceNode rootTreeNode;
124: DefaultTreeModel treeModel;
125:
126: /** Creates new form UrlPropertyPanel */
127: public UrlPropertyPanel(UrlPropertyEditor editor) {
128: super (editor);
129: this .editor = editor;
130: DesignBean designBean = editor.getDesignProperty()
131: .getDesignBean();
132: DesignProperty designProperty = editor.getDesignProperty();
133: this .designContext = designBean.getDesignContext();
134: this .rootTreeNode = generateTargetTree(designContext);
135: this .treeModel = new DefaultTreeModel(rootTreeNode);
136: initComponents();
137: // Resource trees are generally small, so by default, expand all directories
138: // at the project level
139: for (int i = 0; i < rootTreeNode.getChildCount(); i++) {
140: TreeNode n = rootTreeNode.getChildAt(i);
141: resourceTree.expandPath(new TreePath(treeModel
142: .getPathToRoot(n)));
143: }
144: // Insert into combo box URLs found in this property on all other instances
145: // of this component in context
146: DesignBean[] beans = designContext.getBeansOfType(designBean
147: .getInstance().getClass());
148: if (designProperty.getPropertyDescriptor() != null) {
149: if (beans != null && beans.length > 0) {
150: String propertyName = designProperty
151: .getPropertyDescriptor().getName();
152: for (int i = 0; i < beans.length; i++) {
153: String url = (String) beans[i].getProperty(
154: propertyName).getValue();
155: if (url != null)
156: this .urlComboBox.addItem(url);
157: }
158:
159: }
160: }
161: // If URL property already set, update display
162: if (editor.getValue() != null) {
163: String url = UrlPropertyEditor.decodeUrl(editor.getValue()
164: .toString());
165: this .urlComboBox.setSelectedItem(url);
166: // If url has no protocol, it points to a project resource, so ensure
167: // that the resource is visible in the resource tree
168: if (url.indexOf(":") < 0) {
169: TreePath path = urlToTreePath(url, this .rootTreeNode);
170: this .resourceTree.makeVisible(path);
171: this .resourceTree.setSelectionPath(path);
172: }
173: } else {
174: this .urlComboBox.setSelectedItem("");
175: }
176:
177: }
178:
179: public Object getPropertyValue() throws IllegalArgumentException {
180: return UrlPropertyEditor.encodeUrl((String) this .urlComboBox
181: .getSelectedItem());
182: }
183:
184: protected File getLastDirectory() {
185: Object key = this .editor.getDesignProperty().getDesignBean()
186: .getDesignContext().getProject();
187: return (File) UrlPropertyPanel.directoryMap.get(key);
188: }
189:
190: protected void setLastDirectory(File dir) {
191: Object key = this .editor.getDesignProperty().getDesignBean()
192: .getDesignContext().getProject();
193: UrlPropertyPanel.directoryMap.put(key, dir);
194: }
195:
196: /** This method is called from within the constructor to
197: * initialize the form.
198: * WARNING: Do NOT modify this code. The content of this method is
199: * always regenerated by the Form Editor.
200: */
201: // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
202: private void initComponents() {
203: java.awt.GridBagConstraints gridBagConstraints;
204:
205: radioButtonGroup = new javax.swing.ButtonGroup();
206: resourceScrollPane = new javax.swing.JScrollPane();
207: resourceTree = new javax.swing.JTree(treeModel);
208: addButton = new javax.swing.JButton();
209: urlPanel = new javax.swing.JPanel();
210: urlLabel = new javax.swing.JLabel();
211: urlComboBox = new javax.swing.JComboBox();
212:
213: setLayout(new java.awt.GridBagLayout());
214:
215: resourceScrollPane.setMinimumSize(new java.awt.Dimension(120,
216: 80));
217: resourceTree.setCellRenderer(new NodeRenderer());
218: resourceTree.setMinimumSize(new java.awt.Dimension(120, 80));
219: resourceTree.setRootVisible(false);
220: resourceTree.setShowsRootHandles(true);
221: resourceTree
222: .addTreeSelectionListener(new javax.swing.event.TreeSelectionListener() {
223: public void valueChanged(
224: javax.swing.event.TreeSelectionEvent evt) {
225: treeValueChanged(evt);
226: }
227: });
228:
229: resourceScrollPane.setViewportView(resourceTree);
230: resourceTree
231: .getAccessibleContext()
232: .setAccessibleName(
233: java.util.ResourceBundle
234: .getBundle(
235: "org.netbeans.modules.visualweb.propertyeditors.Bundle")
236: .getString(
237: "UrlPropertyPanel.resourceTree.AccessibleName"));
238: resourceTree
239: .getAccessibleContext()
240: .setAccessibleDescription(
241: java.util.ResourceBundle
242: .getBundle(
243: "org.netbeans.modules.visualweb.propertyeditors.Bundle")
244: .getString(
245: "UrlPropertyPanel.resourceTree.AccessibleDescription"));
246:
247: gridBagConstraints = new java.awt.GridBagConstraints();
248: gridBagConstraints.gridx = 0;
249: gridBagConstraints.gridy = 1;
250: gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
251: gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
252: gridBagConstraints.weightx = 1.0;
253: gridBagConstraints.weighty = 1.0;
254: gridBagConstraints.insets = new java.awt.Insets(11, 12, 11, 11);
255: add(resourceScrollPane, gridBagConstraints);
256:
257: addButton
258: .setMnemonic(java.util.ResourceBundle
259: .getBundle(
260: "org.netbeans.modules.visualweb.propertyeditors.Bundle")
261: .getString(
262: "UrlPropertyPanel.add.label.mnemonic")
263: .charAt(0));
264: addButton
265: .setText(java.util.ResourceBundle
266: .getBundle(
267: "org.netbeans.modules.visualweb.propertyeditors.Bundle")
268: .getString("UrlPropertyPanel.add.label"));
269: addButton
270: .addActionListener(new java.awt.event.ActionListener() {
271: public void actionPerformed(
272: java.awt.event.ActionEvent evt) {
273: addButtonActionPerformed(evt);
274: }
275: });
276:
277: gridBagConstraints = new java.awt.GridBagConstraints();
278: gridBagConstraints.gridx = 1;
279: gridBagConstraints.gridy = 1;
280: gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
281: gridBagConstraints.insets = new java.awt.Insets(11, 0, 0, 7);
282: add(addButton, gridBagConstraints);
283:
284: urlPanel.setLayout(new java.awt.GridBagLayout());
285:
286: urlLabel
287: .setText(java.util.ResourceBundle
288: .getBundle(
289: "org.netbeans.modules.visualweb.propertyeditors.Bundle")
290: .getString("UrlPropertyPanel.url.label"));
291: gridBagConstraints = new java.awt.GridBagConstraints();
292: gridBagConstraints.gridx = 0;
293: gridBagConstraints.gridy = 0;
294: gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTHWEST;
295: urlPanel.add(urlLabel, gridBagConstraints);
296:
297: urlComboBox.setEditable(true);
298: gridBagConstraints = new java.awt.GridBagConstraints();
299: gridBagConstraints.gridx = 1;
300: gridBagConstraints.gridy = 0;
301: gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
302: gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTHWEST;
303: gridBagConstraints.weightx = 1.0;
304: gridBagConstraints.insets = new java.awt.Insets(0, 6, 0, 0);
305: urlPanel.add(urlComboBox, gridBagConstraints);
306: urlComboBox.getAccessibleContext().setAccessibleName("");
307:
308: gridBagConstraints = new java.awt.GridBagConstraints();
309: gridBagConstraints.gridx = 0;
310: gridBagConstraints.gridy = 0;
311: gridBagConstraints.gridwidth = 2;
312: gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
313: gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
314: gridBagConstraints.weightx = 0.5;
315: gridBagConstraints.insets = new java.awt.Insets(7, 11, 0, 7);
316: add(urlPanel, gridBagConstraints);
317:
318: }// </editor-fold>//GEN-END:initComponents
319:
320: private void treeValueChanged(
321: javax.swing.event.TreeSelectionEvent evt) {//GEN-FIRST:event_treeValueChanged
322: TreePath path = evt.getNewLeadSelectionPath();
323: // If user has selected a node that equates to a valid URL, generate it,
324: // otherwise do nothing.
325: if (path != null) {
326: ResourceNode n = (ResourceNode) path.getPathComponent(path
327: .getPathCount() - 1);
328: if (n instanceof FileNode
329: && !((FileNode) n).getFile().isDirectory())
330: urlComboBox.setSelectedItem(n.getUrlPathString());
331: else if (n instanceof TargetNode)
332: urlComboBox.setSelectedItem(n.getUrlPathString());
333: }
334: }//GEN-LAST:event_treeValueChanged
335:
336: private void addButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addButtonActionPerformed
337: final JFileChooser fileChooser = new JFileChooser();
338: UrlFileFilter fileFilter = this .editor.getFileFilter();
339: if (fileFilter != null)
340: fileChooser.addChoosableFileFilter(fileFilter);
341: File lastDir = getLastDirectory();
342: if (lastDir != null)
343: fileChooser.setCurrentDirectory(lastDir);
344: String approveMessage = resourceBundle
345: .getString("UrlPropertyPanel.add.label"); //NOI18N
346: if (fileChooser.showDialog(this , approveMessage) == JFileChooser.APPROVE_OPTION) {
347: File file = fileChooser.getSelectedFile();
348: if (file == null || !file.exists())
349: return;
350: try {
351: DesignProject project = this .designContext.getProject();
352: project.addResource(file.toURI().toURL(), new URI(
353: "web/resources/"
354: + UrlPropertyEditor.encodeUrl(file
355: .getName())));
356: String url = "/resources/" + file.getName();
357: ResourceNode resourcesNode = getNode("/resources",
358: this .rootTreeNode);
359: if (resourcesNode == null) {
360: File rootFile = ((FileNode) this .rootTreeNode)
361: .getFile();
362: resourcesNode = new FileNode(this .rootTreeNode,
363: new File(rootFile, "/resources"));
364: this .rootTreeNode.add(resourcesNode);
365: }
366: FileNode childNode = new FileNode(resourcesNode, file);
367: this .treeModel.insertNodeInto(childNode, resourcesNode,
368: resourcesNode.getChildCount());
369: this .resourceTree.setSelectionPath(urlToTreePath(url,
370: this .rootTreeNode));
371: this .urlComboBox.setSelectedItem(url);
372: } catch (MalformedURLException e) {
373: e.printStackTrace();
374: } catch (IOException e) {
375: e.printStackTrace();
376: } catch (URISyntaxException e) {
377: e.printStackTrace();
378: }
379: }
380: setLastDirectory(fileChooser.getCurrentDirectory());
381: }//GEN-LAST:event_addButtonActionPerformed
382:
383: // Variables declaration - do not modify//GEN-BEGIN:variables
384: private javax.swing.JButton addButton;
385: private javax.swing.ButtonGroup radioButtonGroup;
386: private javax.swing.JScrollPane resourceScrollPane;
387: private javax.swing.JTree resourceTree;
388: private javax.swing.JComboBox urlComboBox;
389: private javax.swing.JLabel urlLabel;
390: private javax.swing.JPanel urlPanel;
391:
392: // End of variables declaration//GEN-END:variables
393:
394: protected TreePath urlToTreePath(String url, TreeNode treeNode) {
395: ResourceNode resourceNode = getNode(url, treeNode);
396: if (resourceNode == null) {
397: return new TreePath(new TreeNode[] { treeNode });
398: }
399: ArrayList nodeList = new ArrayList();
400: while (resourceNode != null) {
401: nodeList.add(0, resourceNode);
402: resourceNode = (ResourceNode) resourceNode.getParent();
403: }
404: return new TreePath(nodeList.toArray());
405: }
406:
407: protected ResourceNode getNode(String url, TreeNode treeNode) {
408: Stack nodeStack = new Stack();
409: nodeStack.push(treeNode);
410: ResourceNode resourceNode = null;
411: while (!nodeStack.isEmpty() && resourceNode == null) {
412: ResourceNode node = (ResourceNode) nodeStack.pop();
413: if (url.equals(node.getUrlPathString()))
414: resourceNode = node;
415: if (node.getChildCount() > 0)
416: nodeStack.addAll(Collections.list(node.children()));
417: }
418: return resourceNode;
419: }
420:
421: ResourceNode generateTargetTree(DesignContext designContext) {
422: // Generate a map of page file names to page nodes. Each page node will
423: // contain children nodes for all URL targets on the page, whether
424: // the targets are rendered by components or encoded directly in the JSP.
425: HashMap pagesMap = new HashMap(16);
426:
427: DesignContext[] contexts = designContext.getProject()
428: .getDesignContexts();
429: //DesignContext[] contexts = getDesignContexts (editor.getDesignProperty().getDesignBean());
430:
431: for (int i = 0; i < contexts.length; i++) {
432: DesignBean pageBean = contexts[i].getRootContainer();
433: if (pageBean != null
434: && pageBean.getInstance() instanceof UIViewRoot) {
435: PageNode pageNode = new PageNode(null, pageBean);
436: // To the page node, add a node for every JSF component that, when
437: // rendered, generates a URL target
438: DesignBean beans[] = contexts[i].getBeans();
439: for (int j = 0; j < beans.length; j++) {
440: Object instance = beans[j].getInstance();
441: if (UIComponent.class.isAssignableFrom(instance
442: .getClass())
443: && editor
444: .isTargetComponent((UIComponent) instance)) {
445: TargetNode target = new ComponentTargetNode(
446: pageNode, beans[j]);
447: pageNode.add(target);
448: }
449: }
450: // To the page node, add a node for every HTML target anchor found
451: // in the page's JSP document
452: if (pageBean.getChildBeanCount() > 0
453: && pageBean.getChildBeans()[0] instanceof MarkupDesignBean) {
454: Element pageElement = ((MarkupDesignBean) pageBean
455: .getChildBeans()[0]).getElement();
456: NodeList anchorList = pageElement
457: .getElementsByTagName("a");
458: for (int j = 0; j < anchorList.getLength(); j++) {
459: Element element = (Element) anchorList.item(j);
460: if (element.hasAttribute("name")) {
461: TargetNode target = new ElementTargetNode(
462: pageNode, element);
463: pageNode.add(target);
464: }
465: }
466: }
467: try {
468: File pageFileDir = new File(contexts[i]
469: .resolveResource(".").toURI());
470: File pageFile = new File(pageFileDir, pageBean
471: .getInstanceName()
472: + ".jsp");
473: pagesMap.put(pageFile, pageNode);
474: } catch (URISyntaxException e) {
475: ErrorManager.getDefault().notify(
476: ErrorManager.INFORMATIONAL, e);
477: }
478: }
479: }
480: // Create target tree, where a target is an available project resource.
481: // A stack is used to descend recursively through the project resource
482: // file hierarchy.
483: FileNode rootNode = new FileNode();
484: try {
485: DesignProject project = this .designContext.getProject();
486: File file = project.getResourceFile(new URI("web")); //NOI18N
487: FileFilter fileFilter = this .defaultFileFilter;
488: UrlFileFilter urlFileFilter = this .editor.getFileFilter();
489: if (urlFileFilter != null)
490: fileFilter = urlFileFilter.getIOFileFilter();
491: rootNode.setFile(file);
492: Stack nodeStack = new Stack();
493: nodeStack.push(rootNode);
494: while (!nodeStack.isEmpty()) {
495: FileNode node = (FileNode) nodeStack.pop();
496: file = node.getFile();
497: if (file.isDirectory()) {
498: File[] childFiles = file.listFiles(fileFilter);
499: for (int i = 0; i < childFiles.length; i++) {
500: File childFile = childFiles[i];
501: if (pagesMap.containsKey(childFile)) {
502: PageNode childNode = (PageNode) pagesMap
503: .get(childFile);
504: childNode.setParent(node);
505: childNode.setFile(childFile);
506: node.add(childNode);
507: } else {
508: FileNode childNode = new FileNode(node,
509: childFile);
510: node.add(childNode);
511: nodeStack.push(childNode);
512: }
513: }
514: }
515: }
516: } catch (URISyntaxException e) {
517: }
518: return rootNode;
519: }
520:
521: // For performance improvement. No need to get all the contexts in the project
522: private DesignContext[] getDesignContexts(DesignBean designBean) {
523: DesignProject designProject = designBean.getDesignContext()
524: .getProject();
525: DesignContext[] contexts;
526: if (designProject instanceof FacesDesignProject) {
527: contexts = ((FacesDesignProject) designProject)
528: .findDesignContexts(new String[] { "request",
529: "session", "application" });
530: } else {
531: contexts = new DesignContext[0];
532: }
533: DesignContext[] designContexts = new DesignContext[contexts.length + 1];
534: designContexts[0] = designBean.getDesignContext();
535: System.arraycopy(contexts, 0, designContexts, 1,
536: contexts.length);
537: return designContexts;
538: }
539:
540: static class ResourceNode implements MutableTreeNode {
541:
542: ArrayList children;
543: MutableTreeNode parentNode;
544:
545: ResourceNode() {
546: this .children = new ArrayList();
547: }
548:
549: ResourceNode(MutableTreeNode parentNode) {
550: this .children = new ArrayList();
551: this .parentNode = parentNode;
552: }
553:
554: public TreeNode getChildAt(int index) {
555: return (TreeNode) children.get(index);
556: }
557:
558: void add(MutableTreeNode node) {
559: children.add(node);
560: }
561:
562: public void insert(MutableTreeNode child, int index) {
563: this .children.add(index, child);
564: }
565:
566: void clear() {
567: children.clear();
568: }
569:
570: public int getIndex(TreeNode node) {
571: return children.indexOf(node);
572: }
573:
574: public boolean isLeaf() {
575: return getChildCount() == 0 ? true : false;
576: }
577:
578: public TreeNode getParent() {
579: return parentNode;
580: }
581:
582: public void setParent(MutableTreeNode node) {
583: this .parentNode = node;
584: }
585:
586: public int getChildCount() {
587: return children.size();
588: }
589:
590: public boolean getAllowsChildren() {
591: return true;
592: }
593:
594: public Enumeration children() {
595: return Collections.enumeration(children);
596: }
597:
598: char getPathSepChar() {
599: return '/';
600: }
601:
602: public String toString() {
603: return null;
604: }
605:
606: private String urlString;
607:
608: String getUrlString() {
609: return this .urlString;
610: }
611:
612: void setUrlString(String urlString) {
613: this .urlString = urlString;
614: }
615:
616: String getUrlPathString() {
617: if (getUrlString() == null)
618: return null;
619: if (getParent() == null)
620: return getPathSepChar() + getUrlString();
621: String parentPathString = ((ResourceNode) getParent())
622: .getUrlPathString();
623: if (parentPathString == null)
624: return getPathSepChar() + getUrlString();
625: return parentPathString + getPathSepChar() + getUrlString();
626: }
627:
628: public void remove(MutableTreeNode node) {
629: this .children.remove(node);
630: }
631:
632: public void remove(int index) {
633: this .children.remove(index);
634: }
635:
636: public void removeFromParent() {
637: this .parentNode = null;
638: }
639:
640: public void setUserObject(Object object) {
641: }
642:
643: }
644:
645: static class FileNode extends ResourceNode {
646:
647: String suffix;
648:
649: FileNode() {
650: super ();
651: }
652:
653: FileNode(MutableTreeNode parentNode) {
654: super (parentNode);
655: }
656:
657: FileNode(MutableTreeNode parentNode, File file) {
658: super (parentNode);
659: this .setFile(file);
660: super .setUrlString(file.getName());
661: }
662:
663: private File file;
664:
665: File getFile() {
666: return this .file;
667: }
668:
669: void setFile(File file) {
670: this .file = file;
671: String fileName = this .file.getName();
672: if (!file.isDirectory()) {
673: int i = fileName.lastIndexOf('.');
674: suffix = null;
675: if (i >= 0)
676: suffix = fileName.substring(i + 1);
677: }
678: }
679:
680: String getSuffix() {
681: return suffix;
682: }
683:
684: public String toString() {
685: return this .file.getName();
686: }
687:
688: }
689:
690: static class PageNode extends FileNode {
691:
692: DesignBean pageBean;
693:
694: PageNode(MutableTreeNode parentNode, DesignBean pageBean) {
695: super (parentNode);
696: this .pageBean = pageBean;
697: super .setUrlString(pageBean.getInstanceName() + ".jsp");
698: }
699:
700: public String toString() {
701: return this .pageBean.getInstanceName();
702: }
703:
704: String getUrlPathString() {
705: return "/faces" + super .getUrlPathString();
706: }
707:
708: }
709:
710: static abstract class TargetNode extends ResourceNode {
711:
712: TargetNode(MutableTreeNode parentNode) {
713: super (parentNode);
714: }
715:
716: char getPathSepChar() {
717: return '#';
718: }
719:
720: }
721:
722: static class ElementTargetNode extends TargetNode {
723:
724: Element element;
725:
726: ElementTargetNode(MutableTreeNode parentNode, Element element) {
727: super (parentNode);
728: this .element = element;
729: super .setUrlString(element.getAttribute("name"));
730: }
731:
732: Element getElement() {
733: return element;
734: }
735:
736: public String toString() {
737: return element.getAttribute("name");
738: }
739:
740: }
741:
742: static class ComponentTargetNode extends TargetNode {
743:
744: DesignBean componentBean;
745:
746: ComponentTargetNode(MutableTreeNode parentNode,
747: DesignBean componentBean) {
748: super (parentNode);
749: this .componentBean = componentBean;
750: super .setUrlString(((UIComponent) componentBean
751: .getInstance()).getId());
752: }
753:
754: DesignBean getComponentDesignBean() {
755: return componentBean;
756: }
757:
758: public String toString() {
759: return componentBean.getInstanceName();
760: }
761:
762: }
763:
764: static class NodeRenderer extends DefaultTreeCellRenderer {
765:
766: public Component getTreeCellRendererComponent(JTree tree,
767: Object value, boolean sel, boolean expanded,
768: boolean leaf, int row, boolean hasFocus) {
769: super .getTreeCellRendererComponent(tree, value, sel,
770: expanded, leaf, row, hasFocus);
771: if (value instanceof ComponentTargetNode) {
772: setIcon(new ImageIcon(((ComponentTargetNode) value)
773: .getComponentDesignBean().getBeanInfo()
774: .getIcon(BeanInfo.ICON_COLOR_16x16)));
775: } else if (value instanceof FileNode) {
776: try {
777: FileObject fileObject = FileUtil
778: .toFileObject(((FileNode) value).getFile());
779: Image fileImage = DataObject.find(fileObject)
780: .getNodeDelegate().getIcon(
781: BeanInfo.ICON_COLOR_16x16);
782: setIcon(new ImageIcon(fileImage));
783: } catch (DataObjectNotFoundException e) {
784: }
785: }
786: return this;
787: }
788:
789: }
790:
791: }
|