1 11 package org.eclipse.jdt.internal.ui.text.java; 12 13 14 import org.eclipse.jface.text.BadLocationException; 15 import org.eclipse.jface.text.IDocument; 16 import org.eclipse.jface.text.IRegion; 17 import org.eclipse.jface.text.ITextDoubleClickStrategy; 18 import org.eclipse.jface.text.ITextViewer; 19 import org.eclipse.jface.text.Region; 20 21 import org.eclipse.jdt.core.JavaCore; 22 23 import org.eclipse.jdt.internal.ui.text.ISourceVersionDependent; 24 import org.eclipse.jdt.internal.ui.text.JavaPairMatcher; 25 26 29 public class JavaDoubleClickSelector implements ITextDoubleClickStrategy, ISourceVersionDependent { 30 31 46 private static final class AtJavaIdentifierDetector implements ISourceVersionDependent { 47 48 private boolean fSelectAnnotations; 49 50 private static final int UNKNOWN= -1; 51 52 53 private static final int WS= 0; 54 private static final int ID= 1; 55 private static final int IDS= 2; 56 private static final int AT= 3; 57 58 59 private static final int FORWARD= 0; 60 private static final int BACKWARD= 1; 61 62 63 private int fState; 64 68 private int fAnchorState; 69 70 private int fDirection; 71 72 private int fStart; 73 74 private int fEnd; 75 76 81 private void setAnchor(int anchor) { 82 fState= UNKNOWN; 83 fAnchorState= UNKNOWN; 84 fDirection= UNKNOWN; 85 fStart= anchor; 86 fEnd= anchor - 1; 87 } 88 89 private boolean isAt(char c) { 90 return fSelectAnnotations && c == '@'; 91 } 92 93 private boolean isIdentifierStart(char c) { 94 return Character.isJavaIdentifierStart(c); 95 } 96 97 private boolean isIdentifierPart(char c) { 98 return Character.isJavaIdentifierPart(c); 99 } 100 101 private boolean isWhitespace(char c) { 102 return fSelectAnnotations && Character.isWhitespace(c); 103 } 104 105 108 public void setSourceVersion(String version) { 109 if (JavaCore.VERSION_1_5.compareTo(version) <= 0) 110 fSelectAnnotations= true; 111 else 112 fSelectAnnotations= false; 113 } 114 115 124 private boolean backward(char c, int offset) { 125 checkDirection(BACKWARD); 126 switch (fState) { 127 case AT: 128 return false; 129 case IDS: 130 if (isAt(c)) { 131 fStart= offset; 132 fState= AT; 133 return false; 134 } 135 if (isWhitespace(c)) { 136 fState= WS; 137 return true; 138 } 139 case ID: 141 if (isIdentifierStart(c)) { 142 fStart= offset; 143 fState= IDS; 144 return true; 145 } 146 if (isIdentifierPart(c)) { 147 fStart= offset; 148 fState= ID; 149 return true; 150 } 151 return false; 152 case WS: 153 if (isWhitespace(c)) { 154 return true; 155 } 156 if (isAt(c)) { 157 fStart= offset; 158 fState= AT; 159 return false; 160 } 161 return false; 162 default: 163 return false; 164 } 165 } 166 167 175 private boolean forward(char c, int offset) { 176 checkDirection(FORWARD); 177 switch (fState) { 178 case WS: 179 case AT: 180 if (isWhitespace(c)) { 181 fState= WS; 182 return true; 183 } 184 if (isIdentifierStart(c)) { 185 fEnd= offset; 186 fState= IDS; 187 return true; 188 } 189 return false; 190 case IDS: 191 case ID: 192 if (isIdentifierStart(c)) { 193 fEnd= offset; 194 fState= IDS; 195 return true; 196 } 197 if (isIdentifierPart(c)) { 198 fEnd= offset; 199 fState= ID; 200 return true; 201 } 202 return false; 203 case UNKNOWN: 204 if (isIdentifierStart(c)) { 205 fEnd= offset; 206 fState= IDS; 207 fAnchorState= fState; 208 return true; 209 } 210 if (isIdentifierPart(c)) { 211 fEnd= offset; 212 fState= ID; 213 fAnchorState= fState; 214 return true; 215 } 216 if (isWhitespace(c)) { 217 fState= WS; 218 fAnchorState= fState; 219 return true; 220 } 221 if (isAt(c)) { 222 fStart= offset; 223 fState= AT; 224 fAnchorState= fState; 225 return true; 226 } 227 return false; 228 default: 229 return false; 230 } 231 } 232 233 238 private void checkDirection(int direction) { 239 if (fDirection == direction) 240 return; 241 242 if (direction == FORWARD) { 243 if (fStart <= fEnd) 244 fState= fAnchorState; 245 else 246 fState= UNKNOWN; 247 } else if (direction == BACKWARD) { 248 if (fEnd >= fStart) 249 fState= fAnchorState; 250 else 251 fState= UNKNOWN; 252 } 253 254 fDirection= direction; 255 } 256 257 265 public IRegion getWordSelection(IDocument document, int anchor) { 266 267 try { 268 269 final int min= 0; 270 final int max= document.getLength(); 271 setAnchor(anchor); 272 273 char c; 274 275 int offset= anchor; 276 while (offset < max) { 277 c= document.getChar(offset); 278 if (!forward(c, offset)) 279 break; 280 ++offset; 281 } 282 283 offset= anchor; while (offset >= min) { 286 c= document.getChar(offset); 287 if (!backward(c, offset)) 288 break; 289 --offset; 290 } 291 292 return new Region(fStart, fEnd - fStart + 1); 293 294 } catch (BadLocationException x) { 295 return new Region(anchor, 0); 296 } 297 } 298 299 } 300 301 protected static final char[] BRACKETS= {'{', '}', '(', ')', '[', ']', '<', '>' }; 302 protected JavaPairMatcher fPairMatcher= new JavaPairMatcher(BRACKETS); 303 protected final AtJavaIdentifierDetector fWordDetector= new AtJavaIdentifierDetector(); 304 305 306 public JavaDoubleClickSelector() { 307 super(); 308 } 309 310 313 public void doubleClicked(ITextViewer textViewer) { 314 315 int offset= textViewer.getSelectedRange().x; 316 317 if (offset < 0) 318 return; 319 320 IDocument document= textViewer.getDocument(); 321 322 IRegion region= fPairMatcher.match(document, offset); 323 if (region != null && region.getLength() >= 2) { 324 textViewer.setSelectedRange(region.getOffset() + 1, region.getLength() - 2); 325 } else { 326 region= selectWord(document, offset); 327 textViewer.setSelectedRange(region.getOffset(), region.getLength()); 328 } 329 } 330 331 protected IRegion selectWord(IDocument document, int anchor) { 332 return fWordDetector.getWordSelection(document, anchor); 333 } 334 335 338 public void setSourceVersion(String version) { 339 fPairMatcher.setSourceVersion(version); 340 fWordDetector.setSourceVersion(version); 341 } 342 } 343 | Popular Tags |