KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > gsf > 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.gsf;
21
22 import java.awt.event.ActionEvent JavaDoc;
23 import java.io.IOException JavaDoc;
24 import java.util.ArrayList JavaDoc;
25 import java.util.List JavaDoc;
26 import java.util.MissingResourceException JavaDoc;
27 import javax.swing.Action JavaDoc;
28 import javax.swing.event.CaretEvent JavaDoc;
29 import javax.swing.event.CaretListener JavaDoc;
30 import javax.swing.text.Caret JavaDoc;
31 import javax.swing.text.JTextComponent JavaDoc;
32 import org.netbeans.api.gsf.CancellableTask;
33 import org.netbeans.api.gsf.OffsetRange;
34 import org.netbeans.api.retouche.source.CompilationController;
35 import org.netbeans.api.retouche.source.Phase;
36 import org.netbeans.api.retouche.source.Source;
37 import org.netbeans.editor.BaseAction;
38 import org.openide.ErrorManager;
39 import org.openide.util.NbBundle;
40
41 /**
42  * Code selection according to syntax tree.
43  *
44  * TODO: javadoc selection
45  *
46  * @author Miloslav Metelka, Jan Pokorsky
47  */

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

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