1 19 20 package org.netbeans.modules.diff.builtin.visualizer; 21 22 import java.awt.Dimension ; 23 import java.awt.Rectangle ; 24 import java.awt.Graphics ; 25 import java.awt.Color ; 26 import java.awt.Font ; 27 import java.util.*; 28 import javax.accessibility.AccessibleContext ; 29 import javax.accessibility.AccessibleRole ; 30 import javax.swing.*; 31 import javax.swing.text.*; 32 import java.awt.FontMetrics ; 33 import java.awt.Insets ; 34 35 import org.openide.util.NbBundle; 36 37 import org.netbeans.editor.Coloring; 38 import org.netbeans.editor.EditorUI; 39 import org.netbeans.editor.FontMetricsCache; 40 import org.netbeans.editor.Settings; 41 import org.netbeans.editor.SettingsChangeEvent; 42 import org.netbeans.editor.SettingsChangeListener; 43 import org.netbeans.editor.SettingsDefaults; 44 import org.netbeans.editor.SettingsNames; 45 46 55 56 public class LinesComponent extends JComponent implements javax.accessibility.Accessible , SettingsChangeListener { 57 58 59 60 private JEditorPane editorPane; 61 62 63 private Color backgroundColor; 64 65 66 private Color foreColor; 67 68 69 private Font font; 70 71 72 private int lineHeight = 1; 73 74 private float lineHeightCorrection = 1.0f; 75 76 77 private Map coloringMap; 78 79 81 private boolean init; 82 83 85 private int numberWidth; 86 87 88 private boolean showLineNumbers = true; 89 90 91 private static final int ENLARGE_GUTTER_HEIGHT = 300; 92 93 94 private int highestLineNumber = 0; 95 96 97 private Insets lineNumberMargin; 98 99 100 private int lineNumberDigitWidth; 101 102 103 private int lineAscent; 104 105 private LinkedList<String > linesList; 106 107 108 private int activeLine = -1; 109 110 private static final long serialVersionUID = -4861542695772182147L; 111 112 public LinesComponent(JEditorPane pane) { 113 super(); 114 init = false; 115 editorPane = pane; 116 font = editorPane.getFont(); 117 foreColor = editorPane.getForeground(); 118 backgroundColor = editorPane.getBackground(); 119 setLineNumberDigitWidth(10); 120 setLineNumberMargin(new Insets (2, 2, 2, 4)); 121 Settings.addSettingsChangeListener(this); init(); 123 } 124 125 128 public AccessibleContext getAccessibleContext () { 129 if (accessibleContext == null) { 130 accessibleContext = new AccessibleJComponent() { 131 public AccessibleRole getAccessibleRole() { 132 return AccessibleRole.PANEL; 133 } 134 }; 135 } 136 return accessibleContext; 137 } 138 139 140 protected void init() { 141 createLines(); 142 getAccessibleContext().setAccessibleName(NbBundle.getMessage(LinesComponent.class, "ACSN_Lines_Component")); getAccessibleContext().setAccessibleDescription(NbBundle.getMessage(LinesComponent.class, "ACSD_Lines_Component")); } 145 146 private void createLines() { 147 linesList = new LinkedList<String >(); 148 int lineCnt; 149 StyledDocument doc = (StyledDocument)editorPane.getDocument(); 150 int lastOffset = doc.getEndPosition().getOffset(); 151 lineCnt = org.openide.text.NbDocument.findLineNumber(doc, lastOffset); 152 for (int i = 0; i < lineCnt; i++) { 153 linesList.add(Integer.toString(i + 1)); 154 } 155 } 156 157 public void addEmptyLines(int line, int count) { 158 boolean appending = line > linesList.size(); 159 for (int i = 0; i < count; i++) { 160 if (appending) { 161 linesList.add(""); 162 } else { 163 linesList.add(line, ""); 164 } 165 } 166 } 167 168 172 public void insertNumbers(int line, int startNum, int count) { 173 boolean appending = line >= linesList.size(); 174 if (appending) { 175 for (int i = 0; i < count; i++, startNum++) { 176 linesList.add(Integer.toString(startNum)); 177 } 178 } else { 179 int toAdd = Math.max(line + count - linesList.size(), 0); 180 count -= toAdd; 181 for (int i = 0; i < count; i++, startNum++, line++) { 182 linesList.set(line, Integer.toString(startNum)); 183 } 184 for (int i = 0; i < toAdd; i++, startNum++) { 185 linesList.add(Integer.toString(startNum)); 186 } 187 } 188 } 189 190 202 203 208 public void removeNumbers(int line, int count) { 209 boolean appending = line >= linesList.size(); 210 if (appending) { 211 for (int i = 0; i < count; i++) { 212 linesList.add(""); 213 } 214 } else { 215 int toAdd = Math.max(line + count - linesList.size(), 0); 216 count -= toAdd; 217 for (int i = 0; i < count; i++, line++) { 218 linesList.set(line, ""); 219 } 220 for (int i = 0; i < toAdd; i++) { 221 linesList.add(""); 222 } 223 } 224 } 225 226 230 public void shrink(int numLines) { 231 while (linesList.size() > numLines) { 232 linesList.remove(numLines); 233 } 234 } 235 236 238 private void updateState(Graphics g) { 239 Class kitClass = editorPane.getEditorKit().getClass(); 240 Object value = Settings.getValue(kitClass, SettingsNames.LINE_HEIGHT_CORRECTION); 241 if (!(value instanceof Float ) || ((Float )value).floatValue() < 0) { 243 value = SettingsDefaults.defaultLineHeightCorrection; 244 } 245 lineHeightCorrection = ((Float )value).floatValue(); 246 Map cm = getColoringMap(); 248 Object colValue = cm.get(SettingsNames.LINE_NUMBER_COLORING); 249 Coloring col = null; 251 if (colValue != null && colValue instanceof Coloring) { 252 col = (Coloring)colValue; 253 } else { 254 col = SettingsDefaults.defaultLineNumberColoring; 255 } 256 foreColor = col.getForeColor(); 257 if (foreColor == null) { 258 foreColor = ((Coloring) cm.get(SettingsNames.DEFAULT_COLORING)).getForeColor(); 259 } 260 backgroundColor = col.getBackColor(); 261 if (backgroundColor == null) { 262 backgroundColor = ((Coloring) cm.get(SettingsNames.DEFAULT_COLORING)).getBackColor(); 263 } 264 266 font = col.getFont(); 267 if (font == null) { 268 font = ((Coloring) cm.get(SettingsNames.DEFAULT_COLORING)).getFont(); 269 } 270 FontMetrics fm = g.getFontMetrics(font); 271 283 updateLineHeight(g); 284 showLineNumbers = true; 287 288 296 297 init = true; 298 299 if (highestLineNumber <= getLineCount()) { 301 highestLineNumber = getLineCount(); 302 } 303 int maxWidth = 1; 306 char[] digit = new char[1]; for (int i = 0; i <= 9; i++) { 308 digit[0] = (char)('0' + i); 309 maxWidth = Math.max(maxWidth, fm.charsWidth(digit, 0, 1)); 310 } 311 setLineNumberDigitWidth(maxWidth); 312 315 resize(); 316 } 317 318 private void updateLineHeight(Graphics g) { 319 Map cm = getColoringMap(); 321 Iterator i = cm.entrySet().iterator(); 322 int maxHeight = 1; 323 int maxAscent = 0; 324 while (i.hasNext()) { 325 Map.Entry me = (Map.Entry)i.next(); 326 String coloringName = (String )me.getKey(); 327 Coloring c = (Coloring)me.getValue(); 328 if (c != null) { 329 Font font = c.getFont(); 330 if (font != null && (c.getFontMode() & Coloring.FONT_MODE_APPLY_SIZE) != 0) { 331 FontMetrics fm = g.getFontMetrics(font); 332 if (fm != null) { 333 351 maxHeight = Math.max(maxHeight, fm.getHeight()); 352 maxAscent = Math.max(maxAscent, fm.getAscent()); 353 } 354 } 355 } 356 } 357 358 lineHeight = (int)(maxHeight * lineHeightCorrection); 360 lineAscent = (int)(maxAscent * lineHeightCorrection); 361 362 } 363 364 private Map getColoringMap() { 365 if (coloringMap == null) { 366 coloringMap = EditorUIHelper.getSharedColoringMapFor(editorPane.getEditorKit().getClass()); 367 } 368 return coloringMap; 369 } 370 371 protected void resize() { 372 Dimension dim = new Dimension (); 373 dim.width = getWidthDimension(); 375 dim.height = getHeightDimension(); 376 dim.height += ENLARGE_GUTTER_HEIGHT * lineHeight; 379 380 numberWidth = getLineNumberWidth(); 381 setPreferredSize(dim); 382 383 revalidate(); 384 } 385 386 387 protected int getLineCount() { 388 return linesList.size(); 389 } 390 391 392 protected int getDigitCount(int number) { 393 return Integer.toString(number).length(); 394 } 395 396 protected int getLineNumberWidth() { 397 int newWidth = 0; 398 Insets insets = getLineNumberMargin(); 399 if (insets != null) { 400 newWidth += insets.left + insets.right; 401 } 402 newWidth += (getDigitCount(highestLineNumber) + 1) * getLineNumberDigitWidth(); 403 return newWidth; 405 } 406 407 protected int getWidthDimension() { 408 int newWidth = 0; 409 410 if (showLineNumbers) { 411 newWidth += getLineNumberWidth(); 412 } 413 414 return newWidth; 415 } 416 417 protected int getHeightDimension() { 418 return highestLineNumber * lineHeight ; 419 } 420 421 422 public void paintComponent(Graphics g) { 423 424 super.paintComponent(g); 425 if (!init) { 426 updateState(g); 427 } 428 430 Rectangle drawHere = g.getClipBounds(); 431 432 g.setColor(backgroundColor); 434 g.fillRect(drawHere.x, drawHere.y, drawHere.width, drawHere.height); 435 436 g.setFont(font); 437 g.setColor(foreColor); 438 439 FontMetrics fm = FontMetricsCache.getFontMetrics(font, this); 440 int rightMargin = 0; 441 Insets margin = getLineNumberMargin(); 442 if (margin != null) 443 rightMargin = margin.right; 444 int line = (int)( (float)drawHere.y / (float)lineHeight ); 446 if (line > 0) 447 line--; 448 449 int y = line * lineHeight; 451 452 if (showLineNumbers) { 453 int lastLine = (int)( (float)(drawHere.y+drawHere.height) / (float)lineHeight )+1; 454 if (lastLine > highestLineNumber) { 455 int prevHighest = highestLineNumber; 456 highestLineNumber = lastLine; 457 if (getDigitCount(highestLineNumber) > getDigitCount(prevHighest)) { 458 resize(); 462 return; 463 } 464 } 465 } 466 467 468 while ( (y+(lineHeight/2)) <= (drawHere.y + drawHere.height) ) 471 { 472 if (showLineNumbers) { 474 String lineStr = null; 475 if (line < linesList.size()) { 476 lineStr = linesList.get(line); 477 } 478 if (lineStr == null) { 479 lineStr = ""; 480 } 481 String activeSymbol = "*"; 482 int lineNumberWidth = fm.stringWidth(lineStr); 483 if (line == activeLine - 1) { 484 lineStr = lineStr + activeSymbol; 485 } 486 int activeSymbolWidth = fm.stringWidth(activeSymbol); 487 lineNumberWidth = lineNumberWidth + activeSymbolWidth; 488 g.drawString(lineStr, numberWidth-lineNumberWidth-rightMargin, y + getLineAscent()); 489 } 490 491 y += lineHeight; 492 line++; 493 } 494 } 495 496 497 public void changedLine(int line) { 498 499 if (!init) 500 return; 501 502 if (line > 0) 504 line--; 505 int y = line * lineHeight; 506 507 repaint(0, y, (int)getSize().getWidth(), 3*lineHeight); 508 checkSize(); 509 } 510 511 512 public void changedAll() { 513 514 if (!init) 515 return; 516 517 524 525 repaint(); 526 checkSize(); 527 } 528 529 protected void checkSize() { 530 int count = getLineCount(); 531 if (count > highestLineNumber) { 532 highestLineNumber = count; 533 } 534 Dimension dim = getPreferredSize(); 535 if (getWidthDimension() > dim.width || 536 getHeightDimension() > dim.height) { 537 resize(); 538 } 539 } 540 541 544 public Insets getLineNumberMargin() { 545 return this.lineNumberMargin; 546 } 547 548 551 public void setLineNumberMargin(Insets lineNumberMargin) { 552 this.lineNumberMargin = lineNumberMargin; 553 } 554 555 558 public int getLineNumberDigitWidth() { 559 return this.lineNumberDigitWidth; 560 } 561 562 565 public void setLineNumberDigitWidth(int lineNumberDigitWidth) { 566 this.lineNumberDigitWidth = lineNumberDigitWidth; 567 } 568 569 572 public int getLineAscent() { 573 return this.lineAscent; 574 } 575 576 579 public void setLineAscent(int lineAscent) { 580 this.lineAscent = lineAscent; 581 } 582 583 586 public int getActiveLine() { 587 return this.activeLine; 588 } 589 590 593 public void setActiveLine(int activeLine) { 594 this.activeLine = activeLine; 595 } 596 597 public void settingsChange(SettingsChangeEvent evt) { 598 coloringMap = null; 599 init = false; 600 repaint(); 601 } 602 603 private static class EditorUIHelper extends EditorUI { 604 public EditorUIHelper () {} 605 606 609 public static Map getSharedColoringMapFor(Class kitClass) { 610 return EditorUIHelper.getSharedColoringMap(kitClass); 611 } 612 613 } 614 615 } 616 | Popular Tags |