KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > editor > java > SelectCodeElementAction


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-2007 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.editor.java;
21
22 import com.sun.source.tree.Tree;
23 import com.sun.source.util.SourcePositions;
24 import com.sun.source.util.TreePath;
25 import java.awt.event.ActionEvent JavaDoc;
26 import java.io.IOException JavaDoc;
27 import java.util.ArrayList JavaDoc;
28 import java.util.List JavaDoc;
29 import java.util.MissingResourceException JavaDoc;
30 import javax.swing.Action JavaDoc;
31 import javax.swing.event.CaretEvent JavaDoc;
32 import javax.swing.event.CaretListener JavaDoc;
33 import javax.swing.text.Caret JavaDoc;
34 import javax.swing.text.JTextComponent JavaDoc;
35 import org.netbeans.api.java.source.CancellableTask;
36 import org.netbeans.api.java.source.CompilationController;
37 import org.netbeans.api.java.source.JavaSource;
38 import org.netbeans.api.java.source.JavaSource.Phase;
39 import org.netbeans.editor.BaseAction;
40 import org.openide.ErrorManager;
41 import org.openide.util.NbBundle;
42
43 /**
44  * Code selection according to syntax tree.
45  *
46  * TODO: javadoc selection
47  *
48  * @author Miloslav Metelka, Jan Pokorsky
49  */

50 final class SelectCodeElementAction extends BaseAction {
51
52     private boolean selectNext;
53
54     /**
55      * Construct new action that selects next/previous code elements
56      * according to the language model.
57      * <br>
58      *
59      * @param name name of the action (should be one of
60      * <br>
61      * <code>JavaKit.selectNextElementAction</code>
62      * <code>JavaKit.selectPreviousElementAction</code>
63      * @param selectNext <code>true</code> if the next element should be selected.
64      * <code>False</code> if the previous element should be selected.
65      */

66     public SelectCodeElementAction(String JavaDoc name, boolean selectNext) {
67         super(name);
68         this.selectNext = selectNext;
69         String JavaDoc desc = getShortDescription();
70         if (desc != null) {
71             putValue(SHORT_DESCRIPTION, desc);
72         }
73     }
74         
75     public String JavaDoc getShortDescription(){
76         String JavaDoc name = (String JavaDoc)getValue(Action.NAME);
77         if (name == null) return null;
78         String JavaDoc shortDesc;
79         try {
80             shortDesc = NbBundle.getBundle(JavaKit.class).getString(name); // NOI18N
81
}catch (MissingResourceException JavaDoc mre){
82             shortDesc = name;
83         }
84         return shortDesc;
85     }
86     
87     public void actionPerformed(ActionEvent JavaDoc evt, JTextComponent JavaDoc target) {
88         if (target != null) {
89             int selectionStartOffset = target.getSelectionStart();
90             int selectionEndOffset = target.getSelectionEnd();
91             if (selectionEndOffset > selectionStartOffset || selectNext) {
92                 SelectionHandler handler = (SelectionHandler)target.getClientProperty(SelectionHandler.class);
93                 if (handler == null) {
94                     handler = new SelectionHandler(target);
95                     target.addCaretListener(handler);
96                     // No need to remove the listener above as the handler
97
// is stored is the client-property of the component itself
98
target.putClientProperty(SelectionHandler.class, handler);
99                 }
100                 
101                 if (selectNext) { // select next element
102
handler.selectNext();
103                 } else { // select previous
104
handler.selectPrevious();
105                 }
106             }
107         }
108     }
109
110     private static final class SelectionHandler implements CaretListener JavaDoc, CancellableTask<CompilationController>, Runnable JavaDoc {
111         
112         private JTextComponent JavaDoc target;
113         private SelectionInfo[] selectionInfos;
114         private int selIndex = -1;
115         private boolean ignoreNextCaretUpdate;
116
117         SelectionHandler(JTextComponent JavaDoc target) {
118             this.target = target;
119         }
120
121         public void selectNext() {
122             if (selectionInfos == null) {
123                 JavaSource js = JavaSource.forDocument(target.getDocument());
124                 try {
125                     js.runUserActionTask(this, true);
126                 } catch (IOException JavaDoc ex) {
127                     ErrorManager.getDefault().notify(ex);
128                 }
129             }
130             
131             run();
132         }
133
134         public synchronized void selectPrevious() {
135             if (selIndex > 0) {
136                 select(selectionInfos[--selIndex]);
137             }
138         }
139
140         private void select(SelectionInfo selectionInfo) {
141             Caret JavaDoc caret = target.getCaret();
142             markIgnoreNextCaretUpdate();
143             caret.setDot(selectionInfo.getStartOffset());
144             markIgnoreNextCaretUpdate();
145             caret.moveDot(selectionInfo.getEndOffset());
146         }
147         
148         private void markIgnoreNextCaretUpdate() {
149             ignoreNextCaretUpdate = true;
150         }
151         
152         public void caretUpdate(CaretEvent JavaDoc e) {
153             if (!ignoreNextCaretUpdate) {
154                 synchronized (this) {
155                     selectionInfos = null;
156                     selIndex = -1;
157                 }
158             }
159             ignoreNextCaretUpdate = false;
160         }
161
162         public void cancel() {
163         }
164
165         public void run(CompilationController cc) {
166             try {
167                 cc.toPhase(Phase.RESOLVED);
168                 selectionInfos = initSelectionPath(target, cc);
169             } catch (IOException JavaDoc ex) {
170                 ErrorManager.getDefault().notify(ex);
171             }
172         }
173         
174         private SelectionInfo[] initSelectionPath(JTextComponent JavaDoc target, CompilationController ci) {
175             List JavaDoc<SelectionInfo> positions = new ArrayList JavaDoc<SelectionInfo>();
176             SourcePositions sp = ci.getTrees().getSourcePositions();
177             TreePath tp = ci.getTreeUtilities().pathFor(target.getCaretPosition());
178             for (Tree tree: tp) {
179                 int startPos = (int)sp.getStartPosition(tp.getCompilationUnit(), tree);
180                 int endPos = (int)sp.getEndPosition(tp.getCompilationUnit(), tree);
181                 positions.add(new SelectionInfo(startPos, endPos));
182             }
183             return positions.toArray(new SelectionInfo[positions.size()]);
184         }
185
186         public void run() {
187             if (selIndex < selectionInfos.length - 1) {
188                 select(selectionInfos[++selIndex]);
189             }
190         }
191
192     }
193     
194     private static final class SelectionInfo {
195         
196         private int startOffset;
197         private int endOffset;
198         
199         SelectionInfo(int startOffset, int endOffset) {
200             this.startOffset = startOffset;
201             this.endOffset = endOffset;
202         }
203         
204         public int getStartOffset() {
205             return startOffset;
206         }
207         
208         public int getEndOffset() {
209             return endOffset;
210         }
211         
212     }
213 }
214
Popular Tags