KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > languages > studio > ASTBrowserTopComponent


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.languages.studio;
21
22 import org.netbeans.api.languages.ASTItem;
23 import org.netbeans.api.languages.ASTItem;
24 import org.netbeans.api.languages.ASTNode;
25 import org.netbeans.api.languages.ASTPath;
26 import org.netbeans.api.languages.ParseException;
27 import org.netbeans.api.languages.ParserManager;
28 import org.netbeans.api.languages.ASTToken;
29 import org.netbeans.modules.editor.NbEditorDocument;
30 import org.openide.ErrorManager;
31 import org.openide.cookies.EditorCookie;
32 import org.openide.nodes.Node;
33 import org.openide.util.NbBundle;
34 import org.openide.windows.TopComponent;
35 import org.openide.windows.WindowManager;
36 import java.awt.BorderLayout JavaDoc;
37 import java.awt.Color JavaDoc;
38 import java.awt.Component JavaDoc;
39 import javax.swing.tree.TreePath JavaDoc;
40 import javax.swing.event.CaretEvent JavaDoc;
41 import javax.swing.event.CaretListener JavaDoc;
42 import javax.swing.event.TreeSelectionEvent JavaDoc;
43 import javax.swing.event.TreeSelectionListener JavaDoc;
44 import javax.swing.text.Document JavaDoc;
45 import javax.swing.tree.DefaultTreeCellRenderer JavaDoc;
46 import javax.swing.tree.DefaultTreeModel JavaDoc;
47 import javax.swing.tree.TreeNode JavaDoc;
48 import java.awt.event.FocusEvent JavaDoc;
49 import java.awt.event.FocusListener JavaDoc;
50 import java.beans.PropertyChangeEvent JavaDoc;
51 import java.beans.PropertyChangeListener JavaDoc;
52 import java.io.Serializable JavaDoc;
53 import java.lang.ref.WeakReference JavaDoc;
54 import java.util.ArrayList JavaDoc;
55 import java.util.Enumeration JavaDoc;
56 import java.util.HashMap JavaDoc;
57 import java.util.Iterator JavaDoc;
58 import java.util.List JavaDoc;
59 import java.util.Map JavaDoc;
60 import javax.swing.JEditorPane JavaDoc;
61 import javax.swing.JScrollPane JavaDoc;
62 import javax.swing.JTree JavaDoc;
63 import javax.swing.SwingUtilities JavaDoc;
64
65
66 /**
67  * Top component which displays something.
68  */

69 final class ASTBrowserTopComponent extends TopComponent {
70     
71     private static final long serialVersionUID = 1L;
72     private static ASTBrowserTopComponent instance;
73     private static final String JavaDoc PREFERRED_ID = "ASTBrowserTopComponent";
74     
75     private JTree JavaDoc tree;
76     private Listener JavaDoc listener;
77     private HighlighterSupport highlighting = new HighlighterSupport (Color.yellow);
78
79     
80     private ASTBrowserTopComponent () {
81         initComponents ();
82         setLayout (new BorderLayout JavaDoc ());
83         tree = new JTree JavaDoc ();
84         tree.setCellRenderer (new Renderer JavaDoc ());
85         tree.addTreeSelectionListener (new TreeSelectionListener JavaDoc () {
86             public void valueChanged (TreeSelectionEvent JavaDoc e) {
87                 mark ();
88             }
89         });
90         tree.addFocusListener (new FocusListener JavaDoc () {
91             public void focusGained (FocusEvent JavaDoc e) {
92                 mark ();
93             }
94             public void focusLost (FocusEvent JavaDoc e) {
95                 mark ();
96             }
97         });
98         tree.setShowsRootHandles (true);
99         tree.setModel (new DefaultTreeModel JavaDoc (new TNode (null, null)));
100         add (new JScrollPane JavaDoc (tree), BorderLayout.CENTER);
101         setName (NbBundle.getMessage (ASTBrowserTopComponent.class, "CTL_ASTBrowserTopComponent"));
102         setToolTipText (NbBundle.getMessage (ASTBrowserTopComponent.class, "HINT_ASTBrowserTopComponent"));
103 // setIcon(Utilities.loadImage(ICON_PATH, true));
104
}
105     
106     /** This method is called from within the constructor to
107      * initialize the form.
108      * WARNING: Do NOT modify this code. The content of this method is
109      * always regenerated by the Form Editor.
110      */

111     // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
112
private void initComponents() {
113
114         org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(this);
115         this.setLayout(layout);
116         layout.setHorizontalGroup(
117             layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
118             .add(0, 400, Short.MAX_VALUE)
119         );
120         layout.setVerticalGroup(
121             layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
122             .add(0, 300, Short.MAX_VALUE)
123         );
124     }// </editor-fold>//GEN-END:initComponents
125

126     
127     // Variables declaration - do not modify//GEN-BEGIN:variables
128
// End of variables declaration//GEN-END:variables
129

130     /**
131      * Gets default instance. Do not use directly: reserved for *.settings files only,
132      * i.e. deserialization routines; otherwise you could get a non-deserialized instance.
133      * To obtain the singleton instance, use {@link findInstance}.
134      */

135     public static synchronized ASTBrowserTopComponent getDefault () {
136         if (instance == null) {
137             instance = new ASTBrowserTopComponent ();
138         }
139         return instance;
140     }
141     
142     /**
143      * Obtain the ASTBrowserTopComponent instance. Never call {@link #getDefault} directly!
144      */

145     public static synchronized ASTBrowserTopComponent findInstance () {
146         TopComponent win = WindowManager.getDefault ().findTopComponent (PREFERRED_ID);
147         if (win == null) {
148             ErrorManager.getDefault ().log (ErrorManager.WARNING, "Cannot find ASTBrowser component. It will not be located properly in the window system.");
149             return getDefault ();
150         }
151         if (win instanceof ASTBrowserTopComponent) {
152             return (ASTBrowserTopComponent)win;
153         }
154         ErrorManager.getDefault ().log (ErrorManager.WARNING, "There seem to be multiple components with the '" + PREFERRED_ID + "' ID. That is a potential source of errors and unexpected behavior.");
155         return getDefault ();
156     }
157     
158     public int getPersistenceType () {
159         return TopComponent.PERSISTENCE_ALWAYS;
160     }
161     
162     public void componentShowing () {
163         // TODO add custom code on component opening
164
refresh ();
165         if (listener == null)
166             listener = new Listener JavaDoc (this);
167     }
168     
169     public void componentHidden () {
170         // TODO add custom code on component closing
171
if (listener != null) {
172             listener.remove ();
173             listener = null;
174         }
175     }
176     
177     /** replaces this in object stream */
178     public Object JavaDoc writeReplace () {
179         return new ResolvableHelper ();
180     }
181     
182     protected String JavaDoc preferredID () {
183         return PREFERRED_ID;
184     }
185     
186     private void mark () {
187         if (tree.isFocusOwner ()) {
188             Node[] ns = TopComponent.getRegistry ().getActivatedNodes ();
189             if (ns.length == 1) {
190                 EditorCookie editorCookie = (EditorCookie) ns [0].getLookup ().
191                     lookup (EditorCookie.class);
192                 if (editorCookie != null) {
193                     TNode tn = (TNode) tree.getLastSelectedPathComponent ();
194                     if (tn != null) {
195                         ASTItem item = tn.getASTItem ();
196                         if (item == null) return;
197                         highlighting.highlight (
198                             editorCookie.getDocument (),
199                             item
200                         );
201                         return;
202                     }
203                 }
204             }
205         }
206         highlighting.removeHighlight ();
207     }
208     
209     private CaretListener JavaDoc caretListener;
210     private JEditorPane JavaDoc lastPane;
211     private ASTNode rootNode;
212     
213     
214     private void refresh () {
215         SwingUtilities.invokeLater(new Runnable JavaDoc() {
216             public void run() {
217                 ASTNode nr = getCurrentRootNode ();
218                 if (nr == rootNode) return;
219                 rootNode = nr;
220                 DefaultTreeModel JavaDoc model = new DefaultTreeModel JavaDoc (new TNode (null, rootNode));
221                 tree.setModel (model);
222             }
223         });
224     }
225     
226     private ASTNode getCurrentRootNode () {
227         Node[] ns = TopComponent.getRegistry ().getActivatedNodes ();
228         if (ns.length != 1) return null;
229         EditorCookie editorCookie = (EditorCookie) ns [0].getLookup ().
230             lookup (EditorCookie.class);
231         if (editorCookie == null) return null;
232         if (editorCookie.getOpenedPanes () == null) return null;
233         if (editorCookie.getOpenedPanes ().length < 1) return null;
234         JEditorPane JavaDoc pane = editorCookie.getOpenedPanes () [0];
235         if (caretListener == null)
236             caretListener = new CListener ();
237         if (lastPane != null && lastPane != pane) {
238             lastPane.removeCaretListener (caretListener);
239             lastPane = null;
240         }
241         if (lastPane == null) {
242             pane.addCaretListener (caretListener);
243             lastPane = pane;
244         }
245         Document doc = editorCookie.getDocument ();
246         if (doc == null || !(doc instanceof NbEditorDocument)) return null;
247         String JavaDoc mimeType = (String JavaDoc) doc.getProperty ("mimeType");
248         try {
249             return ParserManager.get ((NbEditorDocument) doc).getAST ();
250         } catch (ParseException ex) {
251             return ex.getASTNode ();
252         }
253     }
254
255     
256     // innerclasses ............................................................
257

258     static class TNode implements TreeNode JavaDoc {
259         
260         private TNode parent;
261         private ASTItem astItem;
262         private List JavaDoc children;
263         private Map JavaDoc map;
264         
265         TNode (TNode parent, ASTItem astItem) {
266             this.parent = parent;
267             this.astItem = astItem;
268         }
269         
270         private void initChildren () {
271             if (children != null) return;
272             children = new ArrayList JavaDoc ();
273             map = new HashMap JavaDoc ();
274             if (astItem == null) return;
275             List JavaDoc<ASTItem> chList = astItem.getChildren ();
276             
277             if (chList != null) {
278                 Iterator JavaDoc<ASTItem> it = chList.iterator ();
279                 while (it.hasNext ()) {
280                     ASTItem item = it.next ();
281                     TreeNode JavaDoc tn = new TNode (this, item);
282                     children.add (tn);
283                     map.put (item, tn);
284                 }
285             }
286         }
287         
288         String JavaDoc getName () {
289             if (astItem == null)
290                 return "No syntax definition.";
291             if (astItem instanceof ASTNode)
292                 return ((ASTNode) astItem).getNT ();
293             return astItem.toString ();
294         }
295         
296         ASTItem getASTItem () {
297             return astItem;
298         }
299         
300         TreeNode JavaDoc getTreeNode (Object JavaDoc o) {
301             initChildren ();
302             return (TreeNode JavaDoc) map.get (o);
303         }
304         
305         public TreeNode JavaDoc getChildAt (int childIndex) {
306             initChildren ();
307             return (TreeNode JavaDoc) children.get (childIndex);
308         }
309
310         public int getChildCount () {
311             initChildren ();
312             return children.size ();
313         }
314
315         public TreeNode JavaDoc getParent () {
316             return parent;
317         }
318
319         public int getIndex (TreeNode JavaDoc node) {
320             initChildren ();
321             return children.indexOf (node);
322         }
323
324         public boolean getAllowsChildren () {
325             return true;
326         }
327
328         public boolean isLeaf () {
329             if (astItem == null)
330                 return false;
331             return astItem.getChildren ().isEmpty ();
332         }
333
334         public Enumeration JavaDoc children () {
335             return new Enumeration JavaDoc () {
336                 private Iterator JavaDoc it = children.iterator ();
337                 public boolean hasMoreElements () {
338                     return it.hasNext ();
339                 }
340
341                 public Object JavaDoc nextElement () {
342                     return it.next ();
343                 }
344             };
345         }
346     }
347     
348     class CListener implements CaretListener JavaDoc {
349         public void caretUpdate (CaretEvent JavaDoc e) {
350             if (rootNode == null) return;
351             ASTPath path = rootNode.findPath (e.getDot ());
352             if (path == null) return;
353             TreeNode JavaDoc tNode = (TreeNode JavaDoc) tree.getModel ().getRoot ();
354             List JavaDoc treePath = new ArrayList JavaDoc ();
355             Iterator JavaDoc it = path.listIterator ();
356             if (!it.hasNext ()) return;
357             it.next ();
358             treePath.add (tNode);
359             while (tNode instanceof TNode && it.hasNext ()) {
360                 tNode = ((TNode) tNode).getTreeNode (it.next ());
361                 if (tNode == null) throw new NullPointerException JavaDoc ();
362                 treePath.add (tNode);
363             }
364             TreePath JavaDoc treePath2 = new TreePath JavaDoc (treePath.toArray ());
365             DefaultTreeModel JavaDoc model = new DefaultTreeModel JavaDoc ((TreeNode JavaDoc) tree.getModel ().getRoot ());
366             tree.setModel (model);
367             tree.setSelectionPath (treePath2);
368             tree.scrollPathToVisible (treePath2);
369         }
370     }
371
372     private static class Renderer extends DefaultTreeCellRenderer JavaDoc {
373         
374         public Component getTreeCellRendererComponent (
375             JTree JavaDoc tree,
376             Object JavaDoc value,
377             boolean sel,
378             boolean expanded,
379             boolean leaf,
380             int row,
381             boolean hasFocus
382         ) {
383             return super.getTreeCellRendererComponent (
384                 tree,
385                 ((TNode) value).getName (),
386                 sel, expanded, leaf, row, hasFocus
387             );
388         }
389     }
390     
391     final static class ResolvableHelper implements Serializable JavaDoc {
392         private static final long serialVersionUID = 1L;
393         public Object JavaDoc readResolve () {
394             return ASTBrowserTopComponent.getDefault ();
395         }
396     }
397     
398     private static class Listener implements PropertyChangeListener JavaDoc {
399         
400         private WeakReference JavaDoc component;
401         
402         
403         Listener (ASTBrowserTopComponent c) {
404             component = new WeakReference JavaDoc (c);
405             TopComponent.getRegistry ().addPropertyChangeListener (this);
406         }
407
408         ASTBrowserTopComponent getComponent () {
409             ASTBrowserTopComponent c = (ASTBrowserTopComponent) component.get ();
410             if (c != null) return c;
411             remove ();
412             return null;
413         }
414         
415         void remove () {
416             TopComponent.getRegistry ().removePropertyChangeListener (this);
417         }
418         
419         public void propertyChange (PropertyChangeEvent JavaDoc evt) {
420             ASTBrowserTopComponent c = getComponent ();
421             if (c == null) return;
422             c.refresh ();
423         }
424     }
425 }
426
Popular Tags