| 1 31 32 package org.antlr.works.ate; 33 34 import org.antlr.works.ate.swing.ATEEditorKit; 35 import org.antlr.works.ate.swing.ATERenderingView; 36 import org.antlr.xjlib.appkit.undo.XJUndo; 37 38 import javax.swing.*; 39 import javax.swing.text.*; 40 import javax.swing.undo.AbstractUndoableEdit ; 41 import java.awt.*; 42 import java.awt.event.KeyEvent ; 43 import java.awt.event.MouseEvent ; 44 45 public class ATETextPane extends JTextPane 46 { 47 public static final String ATTRIBUTE_CHARACTER_FOLDING_PROXY = "char_folding_proxy"; 48 public static final String ATTRIBUTE_PARAGRAPH_FOLDING_PROXY = "para_folding_proxy"; 49 50 protected ATEPanel textEditor; 51 52 private boolean writable = true; 53 54 protected boolean wrap = false; 55 protected boolean highlightCursorLine = false; 56 private int destinationCursorPosition = -1; 57 58 public ATETextPane(ATEPanel textEditor, StyledEditorKit editorKit) { 59 super(new DefaultStyledDocument()); 60 setCaret(new ATECaret()); 61 setEditorKit(editorKit==null?new ATEEditorKit(textEditor):editorKit); 62 this.textEditor = textEditor; 63 } 64 65 public void setWritable(boolean flag) { 66 this.writable = flag; 67 } 68 69 public boolean isWritable() { 70 return writable; 71 } 72 73 public void setWordWrap(boolean flag) { 74 this.wrap = flag; 75 } 76 77 public boolean getWordWrap() { 78 return wrap; 79 } 80 81 public void setHighlightCursorLine(boolean flag) { 82 this.highlightCursorLine = flag; 83 } 84 85 public boolean highlightCursorLine() { 86 return highlightCursorLine; 87 } 88 89 93 public void setFont(Font f) { 94 super.setFont(f); 95 ATERenderingView.DEFAULT_FONT = f; 96 } 97 98 public void setTabSize(int size) { 99 getDocument().putProperty(PlainDocument.tabSizeAttribute, size); 100 } 101 102 public boolean getScrollableTracksViewportWidth() { 103 if(!wrap) { 104 Component parent = getParent(); 105 return parent == null || getUI().getPreferredSize(this).width < parent.getSize().width; 106 } else 107 return super.getScrollableTracksViewportWidth(); 108 } 109 110 public void setBounds(int x, int y, int width, int height) { 111 if(!wrap) { 112 Dimension size = this.getPreferredSize(); 113 super.setBounds(x, y, 114 Math.max(size.width, width), Math.max(size.height, height)); 115 } else { 116 super.setBounds(x, y, width, height); 117 } 118 } 119 120 @Override  121 public void paintComponent(Graphics g) { 122 super.paintComponent(g); 123 paintDestinationCursor(g); 124 textEditor.textPaneDidPaint(g); 125 } 126 127 private void paintDestinationCursor(Graphics g) { 128 if(destinationCursorPosition < 0) return; 129 130 try { 131 Rectangle r = modelToView(destinationCursorPosition); 132 g.setColor(Color.black); 133 g.drawRect(r.x, r.y, r.width, r.height); 134 } catch (BadLocationException e) { 135 e.printStackTrace(); 137 } 138 } 139 140 145 public void printPaint(Graphics g) { 146 boolean flag = highlightCursorLine(); 147 setHighlightCursorLine(false); 148 boolean caretVisible = getCaret().isVisible(); 149 getCaret().setVisible(false); 150 paint(g); 151 getCaret().setVisible(caretVisible); 152 setHighlightCursorLine(flag); 153 } 154 155 @Override  156 protected void processKeyEvent(KeyEvent keyEvent) { 157 if(writable) { 159 if(keyEvent.getKeyCode() == KeyEvent.VK_TAB && keyEvent.getID() == KeyEvent.KEY_PRESSED) { 160 int start = getSelectionStart(); 161 int stop = getSelectionEnd(); 162 if(start != stop) { 163 try { 165 indentText(start, stop, keyEvent.isShiftDown()?-1:1); 166 keyEvent.consume(); 167 } catch (BadLocationException e) { 168 e.printStackTrace(); 169 } 170 } else { 171 super.processKeyEvent(keyEvent); 172 } 173 } else { 174 super.processKeyEvent(keyEvent); 175 } 176 } else { 177 if(keyEvent.isActionKey()) { 178 super.processKeyEvent(keyEvent); 179 } else if((keyEvent.getModifiers() & KeyEvent.META_MASK) > 0) { 180 super.processKeyEvent(keyEvent); 181 } else if((keyEvent.getModifiers() & KeyEvent.CTRL_MASK) > 0) { 182 super.processKeyEvent(keyEvent); 183 } else { 184 Toolkit.getDefaultToolkit().beep(); 185 } 186 } 187 } 188 189 protected void indentText(int start, int stop, int direction) throws BadLocationException { 190 Element paragraph = getDocument().getDefaultRootElement(); 191 final int contentCount = paragraph.getElementCount(); 192 final String oldText = getText(); 193 194 StringBuffer sb = new StringBuffer (oldText); 195 196 int modified = 0; 197 for (int i=contentCount-1; i>=0; i--) { 198 Element e = paragraph.getElement(i); 199 int rangeStart = e.getStartOffset(); 200 int rangeEnd = e.getEndOffset(); 201 if(start >= rangeStart && start <= rangeEnd || 202 rangeStart >= start && rangeStart <= stop) 203 { 204 if(direction == -1) { 205 if(sb.charAt(rangeStart) == '\t') { 206 sb.delete(rangeStart, rangeStart+1); 207 modified++; 208 } 209 } else { 210 sb.insert(rangeStart, "\t"); 211 modified++; 212 } 213 } 214 } 215 216 if(modified == 0) return; 217 218 textEditor.disableUndo(); 219 XJUndo undo = textEditor.getTextPaneUndo(); 220 undo.addEditEvent(new UndoableRefactoringEdit(oldText, sb.toString())); 221 setText(sb.toString()); 222 textEditor.enableUndo(); 223 224 getCaret().setDot(start+direction); 225 if(modified > 1) { 226 getCaret().moveDot(stop+2*direction); 227 } else { 228 getCaret().moveDot(stop+direction); 229 } 230 } 231 232 protected class UndoableRefactoringEdit extends AbstractUndoableEdit { 233 234 public String oldContent; 235 public String newContent; 236 237 public UndoableRefactoringEdit(String oldContent, String newContent) { 238 this.oldContent = oldContent; 239 this.newContent = newContent; 240 } 241 242 public void redo() { 243 super.redo(); 244 refactorReplaceEditorText(newContent); 245 } 246 247 public void undo() { 248 super.undo(); 249 refactorReplaceEditorText(oldContent); 250 } 251 252 private void refactorReplaceEditorText(String text) { 253 int old = getCaretPosition(); 254 textEditor.disableUndo(); 255 setText(text); 256 textEditor.enableUndo(); 257 setCaretPosition(Math.min(old, text.length())); 258 } 259 } 260 261 protected class ATECaret extends DefaultCaret { 262 263 public boolean selectingWord = false; 264 public boolean selectingLine = false; 265 public boolean draggingWord = false; 266 public boolean draggingLine = false; 267 public boolean startedDragging = false; public int mouseDraggingOffset; 269 public int selectionMovingLineBegin; 270 public int selectionMovingLineEnd; 271 public int selectionAnchorLineBegin; 272 public int selectionAnchorLineEnd; 273 public int selectionStart; 274 public int selectionEnd; 275 public int dragDropCursorPosition = 0; 276 277 public ATECaret() { 278 setBlinkRate(500); 279 } 280 281 public void paint(Graphics g) { 282 if(!isVisible()) 283 return; 284 try { 285 Rectangle r = ATETextPane.this.modelToView(getDot()); 286 g.setColor(ATETextPane.this.getCaretColor()); 287 g.drawLine(r.x, r.y, r.x, r.y + r.height - 1); 288 g.drawLine(r.x+1, r.y, r.x+1, r.y + r.height - 1); 289 } 290 catch (BadLocationException e) { 291 } 293 } 294 295 protected synchronized void damage(Rectangle r) { 296 if(r == null) 297 return; 298 299 x = r.x; 300 y = r.y; 301 width = 2; 302 height = r.height; 303 repaint(); 304 } 305 306 public void mouseClicked(MouseEvent e) { 307 if(e.getClickCount()<2 || !SwingUtilities.isLeftMouseButton(e)){ 310 super.mouseClicked(e); 311 } 312 } 313 314 public void mousePressed(MouseEvent e) { 315 if(!isWritable() || e.getButton() != MouseEvent.BUTTON1) { 316 super.mousePressed(e); 317 return; 318 } 319 320 draggingWord =false; 321 draggingLine =false; 322 selectingWord=false; 323 selectingLine=false; 324 startedDragging=false; 325 326 if(e.getClickCount()%2 == 0) { 327 selectWord(); 328 selectingWord = true; 329 selectionStart = getSelectionStart(); 330 selectionEnd = getSelectionEnd(); 331 setDragEnabled(false); 332 e.consume(); 333 return; 334 } 335 if(e.getClickCount()%3 == 0) { 336 selectLine(); 337 selectingLine = true; 338 selectionStart = getSelectionStart(); 339 selectionEnd = getSelectionEnd(); 340 selectionMovingLineBegin=selectionStart; 341 selectionAnchorLineBegin=selectionStart; 342 selectionMovingLineEnd=selectionEnd; 343 selectionAnchorLineEnd=selectionEnd; 344 setDragEnabled(false); 345 e.consume(); 346 return; 347 } 348 349 selectionStart = getSelectionStart(); 350 selectionEnd = getSelectionEnd(); 351 int mouseCharIndex = viewToModel(e.getPoint()); 352 if(selectionStart!=selectionEnd&&e.getClickCount()==1&& 353 mouseCharIndex>=selectionStart&&mouseCharIndex<=selectionEnd){ 354 String s = getText(); 355 if ((selectionStart==0||s.charAt(selectionStart-1)=='\n')&&s.charAt(selectionEnd-1)=='\n'){ 356 draggingLine=true; 357 } else { 358 draggingWord=true; 359 } 360 mouseDraggingOffset=mouseCharIndex-selectionStart; 361 } 362 if (!draggingWord&&!draggingLine) 365 super.mousePressed(e); 366 } 367 368 public void mouseReleased(MouseEvent e) { 369 if(!isWritable() || e.getButton() != MouseEvent.BUTTON1) { 370 super.mouseReleased(e); 371 return; 372 } 373 374 if (draggingWord||draggingLine){ 375 endDestinationCursor(); 377 super.mousePressed(e); 378 } 379 if (startedDragging){ 380 super.mousePressed(e); 381 } 382 if (draggingWord){ 383 moveSelectionWord(e); 384 }else if (draggingLine){ 385 moveSelectionLine(e); 386 } 387 super.mouseReleased(e); 389 } 390 391 public void mouseDragged(MouseEvent e) { 392 if(!isWritable() || e.getButton() != MouseEvent.BUTTON1) { 393 super.mouseDragged(e); 394 return; 395 } 396 397 if (draggingWord ||draggingLine){ 399 dragDropCursorPosition = viewToModel(e.getPoint()); 400 if (!startedDragging){ 401 startedDragging=true; 402 beginDestinationCursor(); 403 } 404 } 405 if(selectingWord) { 406 extendSelectionWord(e); 407 ATETextPane.this.repaint(); 408 } else if (selectingLine){ 409 extendSelectionLine(e); 410 } else if (draggingWord){ 411 setDestinationCursorPosition(viewToModel(e.getPoint())); 412 } else if (draggingLine){ 413 int mouseCharIndex = viewToModel(e.getPoint()); 414 int lineBegin = findBeginningLineBoundary(mouseCharIndex); 415 setDestinationCursorPosition(lineBegin); 416 } else{ 417 super.mouseDragged(e); 418 } 419 ATETextPane.this.repaint(); 421 } 422 423 431 private void setDestinationCursorPosition(int pos) { 432 destinationCursorPosition = pos; 433 if(destinationCursorPosition != -1) { 434 try { 435 ATETextPane.this.scrollRectToVisible(modelToView(pos)); 437 } catch (BadLocationException e) { 438 } 440 } 441 ATETextPane.this.repaint(); 442 } 443 444 private void beginDestinationCursor() { 445 setDragEnabled(false); 447 setVisible(false); 448 } 449 450 private void endDestinationCursor() { 451 setDragEnabled(true); 452 setVisible(true); 453 setDestinationCursorPosition(-1); 454 } 455 456 private void moveSelectionLine(MouseEvent e) { 457 int mouseCharIndex = viewToModel(e.getPoint()); 458 StyledDocument doc = getStyledDocument(); 459 textEditor.getTextPaneUndo().beginUndoGroup("moveSelectionLine"); 460 try{ 461 if(mouseCharIndex > selectionEnd) { 462 int moveTo = findBeginningLineBoundary(mouseCharIndex); 463 int offset = moveTo-selectionEnd; 464 String s = doc.getText(selectionEnd, offset); 465 doc.remove(selectionEnd,offset); 466 doc.insertString(selectionStart,s,null); 467 selectionEnd = selectionEnd+offset; 468 selectionStart = selectionStart+offset; 469 } 470 else if(mouseCharIndex < selectionStart) { 471 int moveFrom = Math.max(0,findBeginningLineBoundary(mouseCharIndex)); 472 int offset = selectionStart - moveFrom; 473 String s = doc.getText(moveFrom, offset); 474 doc.insertString(selectionEnd,s,null); 475 doc.remove(moveFrom,offset); 476 selectionEnd = selectionEnd-offset; 477 selectionStart = selectionStart-offset; 478 } 479 }catch(BadLocationException ex){System.out.println(ex);} 480 textEditor.getTextPaneUndo().endUndoGroup(); 481 } 482 483 private void moveSelectionWord(MouseEvent e) { 484 int mouseCharIndex = viewToModel(e.getPoint()); 485 StyledDocument doc = getStyledDocument(); 486 textEditor.getTextPaneUndo().beginUndoGroup("moveSelectionWord"); 487 try{ 488 if(mouseCharIndex > selectionEnd) { 489 int offset = mouseCharIndex-selectionEnd; 490 String s = doc.getText(selectionEnd, offset); 491 doc.remove(selectionEnd,offset); 492 doc.insertString(selectionStart,s,null); 493 selectionEnd = selectionEnd+offset; 494 selectionStart = selectionStart+offset; 495 } 496 else if(mouseCharIndex < selectionStart) { 497 mouseCharIndex = Math.max(0,mouseCharIndex); 498 int offset = selectionStart - mouseCharIndex; 499 String s = doc.getText(mouseCharIndex, offset); 500 doc.insertString(selectionEnd,s,null); 501 doc.remove(mouseCharIndex,offset); 502 selectionEnd = selectionEnd-offset; 503 selectionStart = selectionStart-offset; 504 } 505 }catch(BadLocationException ex){System.out.println(ex);} 506 textEditor.getTextPaneUndo().endUndoGroup(); 507 } 508 509 public void extendSelectionWord(MouseEvent e) { 510 int mouseCharIndex = viewToModel(e.getPoint()); 511 512 if(mouseCharIndex > selectionEnd) { 513 int npos = findNextWordBoundary(mouseCharIndex); 514 if(npos > selectionEnd) 515 select(selectionStart, npos); 516 } else if(mouseCharIndex < selectionStart) { 517 int npos = findPrevWordBoundary(mouseCharIndex); 518 if(npos < selectionStart) 519 select(Math.max(0, npos), selectionEnd); 520 } else 521 select(selectionStart, selectionEnd); 522 } 523 524 public void extendSelectionLine(MouseEvent e) { 525 int mouseCharIndex = viewToModel(e.getPoint()); 526 if(mouseCharIndex > selectionMovingLineEnd) { 527 int npos = findEndLineBoundary(mouseCharIndex); 528 if(npos > selectionMovingLineEnd){ 529 selectionMovingLineEnd = npos; 530 selectionMovingLineBegin = findBeginningLineBoundary(mouseCharIndex); 531 selectionStart = Math.min(selectionMovingLineBegin,selectionAnchorLineBegin); 532 selectionEnd = Math.max(selectionMovingLineEnd,selectionAnchorLineEnd); 533 select(selectionStart, selectionEnd); 534 } 535 } else if(mouseCharIndex < selectionMovingLineBegin) { 536 int npos = Math.max(0,findBeginningLineBoundary(mouseCharIndex)); 537 if(npos < selectionMovingLineBegin){ 538 selectionMovingLineBegin = npos; 539 selectionMovingLineEnd = findEndLineBoundary(mouseCharIndex); 540 selectionEnd = Math.max(selectionMovingLineEnd,selectionAnchorLineEnd); 541 selectionStart = Math.min(selectionMovingLineBegin,selectionAnchorLineBegin); 542 select(selectionStart, selectionEnd); 543 } 544 } else{ select(selectionStart, selectionEnd); 546 } 547 } 548 549 public void selectWord() { 550 int p = getCaretPosition(); 551 552 setCaretPosition(findPrevWordBoundary(p)); 553 moveCaretPosition(findNextWordBoundary(p)); 554 } 555 public void selectLine() { 556 int p = getCaretPosition(); 557 558 setCaretPosition(findBeginningLineBoundary(p)); 559 moveCaretPosition(findEndLineBoundary(p)); 560 } 561 562 private int findBeginningLineBoundary(int pos) { 563 int index = pos-1; 564 String s = getText(); 565 while(index >= 0 && s.charAt(index)!='\n') { 566 index--; 567 } 568 return index +1; 569 } 570 571 private int findEndLineBoundary(int pos) { 572 int index = pos; 573 String s = getText(); 574 while(index < s.length() && s.charAt(index)!='\n') { 575 index++; 576 } 577 return index+1; 578 } 579 580 public int findPrevWordBoundary(int pos) { 581 int index = pos-1; 582 String s = getText(); 583 while(index >= 0 && isWordChar(s.charAt(index))) { 584 index--; 585 } 586 return index +1; 587 } 588 589 public int findNextWordBoundary(int pos) { 590 int index = pos; 591 String s = getText(); 592 while(index < s.length() && isWordChar(s.charAt(index))) { 593 index++; 594 } 595 return index; 596 } 597 598 public boolean isWordChar(char c) { 599 return Character.isLetterOrDigit(c) || c == '_'; 600 } 601 } 602 603 } 604 | Popular Tags |