1 package org.antlr.works.ate.swing; 2 3 import org.antlr.works.ate.ATEPanel; 4 import org.antlr.works.ate.ATETextPane; 5 import org.antlr.works.ate.syntax.generic.ATESyntaxEngine; 6 import org.antlr.works.ate.syntax.misc.ATEToken; 7 8 import javax.swing.text.*; 9 import java.awt.*; 10 import java.util.List ; 11 12 42 43 49 public class ATERenderingView extends PlainView { 50 51 public static final Color BACKGROUND_HIGHLIGHT_COLOR = new Color(1.0f, 1.0f, 0.5f, 0.3f); 52 public static Font DEFAULT_FONT; 53 54 protected ATEPanel textEditor; 55 protected ATETextPane textPane; 56 protected List <ATEToken> tokens; 57 58 protected DisplayOperation displayOp = new DisplayOperation(); 59 protected ModelToViewOperation modelToViewOp = new ModelToViewOperation(); 60 protected ViewToModel viewToModelOp = new ViewToModel(); 61 62 protected Graphics currentGraphics; 63 protected Color savedColor; 64 65 public ATERenderingView(Element elem, ATEPanel textEditor) { 66 super(elem); 67 this.textEditor = textEditor; 68 this.textPane = textEditor.getTextPane(); 69 } 70 71 85 protected void drawLine(int lineIndex, Graphics g, int x, int y) { 86 if(textPane.highlightCursorLine()) { 88 final Element line = getElement().getElement(lineIndex); 89 final int p0 = line.getStartOffset(); 90 final int p1 = line.getEndOffset(); 91 92 final int cursorPosition = textPane.getCaretPosition()+1; 93 if(cursorPosition > p0 && cursorPosition <= p1) { 94 saveColor(g); 95 g.setColor(BACKGROUND_HIGHLIGHT_COLOR); 96 final int fontHeight = metrics.getHeight(); 97 g.fillRect(0, y-fontHeight+metrics.getDescent(), textPane.getWidth(), fontHeight); 98 restore(g); 99 } 100 } 101 102 super.drawLine(lineIndex, g, x, y); 103 } 104 105 110 public Shape modelToView(int pos, Shape a, Position.Bias b) throws BadLocationException { 111 if(!textEditor.isSyntaxColoring()) { 112 return super.modelToView(pos, a, b); 113 } 114 115 final Element element = getElement(); 117 final int lineIndex = element.getElementIndex(pos); 119 120 final Element line = element.getElement(lineIndex); 122 final int p0 = line.getStartOffset(); 124 125 final Rectangle posRect = lineToRect(a, lineIndex); 127 128 posRect.x += renderText(modelToViewOp, currentGraphics, 0, 0, p0, pos); 131 132 posRect.width = 1; 134 posRect.height = metrics.getHeight(); 136 137 return posRect; 139 } 140 141 146 public int viewToModel(float fx, float fy, Shape a, Position.Bias[] biasReturn) { 147 if(!textEditor.isSyntaxColoring()) { 148 return super.viewToModel(fx, fy, a, biasReturn); 149 } 150 151 biasReturn[0] = Position.Bias.Forward; 153 154 final Rectangle bounds = a.getBounds(); 156 if(fy < bounds.y) { 157 return getStartOffset(); 160 } else if(fy > bounds.y + bounds.height) { 161 return getEndOffset() - 1; 164 } 165 166 Element element = getElement(); 170 171 final int lineIndex = Math.abs(((int)fy - bounds.y) / metrics.getHeight() ); 173 if(lineIndex >= element.getElementCount()) { 174 return getEndOffset() - 1; 176 } 177 178 final Element line = element.getElement(lineIndex); 180 if(fx < bounds.x) { 181 return line.getStartOffset(); 183 } else if(fx > bounds.x + bounds.width) { 184 return line.getEndOffset() - 1; 186 } 187 188 final int p0 = line.getStartOffset(); 191 final int p1 = line.getEndOffset() - 1; 192 try { 193 viewToModelOp.setParameters((int)fx, p0); 194 renderText(viewToModelOp, currentGraphics, bounds.x, (int)fy, p0, p1); 195 return viewToModelOp.modelPos; 196 } catch (BadLocationException e) { 197 return -1; 199 } 200 } 201 202 215 216 protected int drawUnselectedText(Graphics g, int x, int y, int p0, int p1) throws BadLocationException { 217 this.currentGraphics = g; 218 return renderText(displayOp, g, x, y, p0, p1); 219 } 220 221 236 protected int drawSelectedText(Graphics g, int x, int y, int p0, int p1) throws BadLocationException { 237 this.currentGraphics = g; 238 return renderText(displayOp, g, x, y, p0, p1); 239 } 240 241 246 protected int renderText(TextOperation action, Graphics g, int x, int y, int p0, int p1) throws BadLocationException { 247 if(p0 == p1) 248 return x; 249 250 if(!textEditor.isSyntaxColoring()) { 251 return super.drawUnselectedText(g, x, y, p0, p1); 252 } 253 254 final Document doc = getDocument(); 256 final ATESyntaxEngine engine = textEditor.getParserEngine(); 257 tokens = engine.getTokens(); 258 int p = p0; 259 final int start = findStartingTokenIndex(p0, 0, tokens.size(), 0); 260 for (int i = start; i < tokens.size(); i++) { 261 ATEToken t = tokens.get(i); 262 AttributeSet attribute = engine.getAttributeForToken(t); 263 if(t.start >= p0 && t.start <= p1) { 264 if(t.start > p) { 266 x = action.renderTextPortion(g, x, y, p, t.start, p1, doc, null); 267 } 268 269 x = action.renderTextPortion(g, x, y, t.start, t.end, p1, doc, attribute); 270 p = t.end; 271 } else if(t.end >= p0 && t.start < p0) { 272 x = action.renderTextPortion(g, x, y, p0, t.end, p1, doc, attribute); 273 p = t.end; 274 } else if(t.start > p1) { 275 break; 276 } 277 } 278 279 if(p < p1) { 281 x = action.renderTextPortion(g, x, y, p, p1, p1, doc, null); 282 } 283 284 return x; 285 } 286 287 295 private int findStartingTokenIndex(int p0, int low, int high, int candidate) { 296 if(Math.abs(high-low) <= 1) 297 return Math.min(candidate, low); 298 299 final int middle = low + (high-low) / 2; 300 final ATEToken t = tokens.get(middle); 301 if(p0 >= t.startLineIndex && p0 <= t.endLineIndex) { 302 return findStartingTokenIndex(p0, low, middle, middle); 303 } else { 304 if(t.startLineIndex < p0) 305 return findStartingTokenIndex(p0, middle, high, candidate); 306 else 307 return findStartingTokenIndex(p0, low, middle, candidate); 308 } 309 } 310 311 316 protected void applyAttribute(Graphics g, AttributeSet attribute) { 317 if(attribute == null) { 318 g.setColor(Color.black); 319 g.setFont(DEFAULT_FONT); 320 return; 321 } 322 323 g.setFont(getFontForAttribute(attribute)); 324 325 final Color c = StyleConstants.getForeground(attribute); 326 if(c == null) 327 g.setColor(Color.black); 328 else 329 g.setColor(c); 330 } 331 332 337 protected Font getFontForAttribute(AttributeSet attribute) { 338 Font f = DEFAULT_FONT; 339 if(StyleConstants.isBold(attribute)) 340 f = f.deriveFont(Font.BOLD); 341 if(StyleConstants.isItalic(attribute)) 342 f = f.deriveFont(Font.ITALIC); 343 return f; 344 } 345 346 350 protected void saveColor(Graphics g) { 351 savedColor = g.getColor(); 352 } 353 354 358 protected void restore(Graphics g) { 359 g.setColor(savedColor); 360 } 361 362 public interface TextOperation { 363 int renderTextPortion(Graphics g, int x, int y, int start, int end, int max, Document doc, AttributeSet attribute) throws BadLocationException; 364 } 365 366 public class DisplayOperation implements TextOperation { 367 368 public int renderTextPortion(Graphics g, int x, int y, int start, int end, int max, Document doc, AttributeSet attribute) 369 throws BadLocationException 370 { 371 if(g == null) 372 return 0; 373 374 int length = end - start; 375 if(start + length > max) 376 length = max - start; 377 378 saveColor(g); 379 applyAttribute(g, attribute); 380 Segment text = getLineBuffer(); 381 doc.getText(start, length, text); 382 383 x = Utilities.drawTabbedText(text, x, y, g, ATERenderingView.this, start); 384 restore(g); 385 return x; 386 } 387 } 388 389 public class ModelToViewOperation implements TextOperation { 390 391 public int renderTextPortion(Graphics g, int x, int y, int start, int end, int max, Document doc, AttributeSet attribute) 392 throws BadLocationException 393 { 394 if(g == null) 395 return 0; 396 397 int length = end - start; 398 if(start + length > max) 399 length = max - start; 400 401 saveColor(g); 402 applyAttribute(g, attribute); 403 Segment text = getLineBuffer(); 404 doc.getText(start, length, text); 405 406 x += Utilities.getTabbedTextWidth(text, g.getFontMetrics(), x, ATERenderingView.this, start); 407 restore(g); 408 return x; 409 } 410 } 411 412 public class ViewToModel implements TextOperation { 413 414 private int modelPos; 415 private int viewX; 416 417 public void setParameters(int viewX, int modelPos) { 418 this.viewX = viewX; 419 this.modelPos = modelPos; 420 } 421 422 public int renderTextPortion(Graphics g, int x, int y, int start, int end, int max, Document doc, AttributeSet attribute) 423 throws BadLocationException 424 { 425 if(g == null) 426 return 0; 427 428 int length = end - start; 429 if(start + length > max) 430 length = max - start; 431 432 saveColor(g); 433 applyAttribute(g, attribute); 434 Segment text = getLineBuffer(); 435 doc.getText(start, length, text); 436 437 modelPos += Utilities.getTabbedTextOffset(text, g.getFontMetrics(), x, viewX, ATERenderingView.this, start); 438 x +=Utilities.getTabbedTextWidth(text, g.getFontMetrics(), x, ATERenderingView.this, start); 439 440 restore(g); 441 return x; 442 } 443 } 444 445 } 446 | Popular Tags |