1 19 20 package org.netbeans.editor; 21 22 import java.awt.Color ; 23 import java.awt.Dimension ; 24 import java.awt.Font ; 25 import java.awt.FontMetrics ; 26 import java.awt.Graphics ; 27 import java.awt.Rectangle ; 28 import java.awt.Shape ; 29 import java.awt.event.MouseAdapter ; 30 import java.awt.event.MouseEvent ; 31 import java.awt.event.MouseMotionListener ; 32 import java.util.ArrayList ; 33 import java.util.Collections ; 34 import java.util.HashMap ; 35 import java.util.List ; 36 import java.util.Map ; 37 import javax.swing.JComponent ; 38 import javax.swing.SwingUtilities ; 39 import javax.swing.event.DocumentEvent ; 40 import javax.swing.event.DocumentListener ; 41 import javax.swing.text.AbstractDocument ; 42 import javax.swing.text.BadLocationException ; 43 import javax.swing.text.Document ; 44 import javax.swing.text.JTextComponent ; 45 import javax.swing.text.Position ; 46 import javax.swing.text.View ; 47 import org.netbeans.api.editor.fold.Fold; 48 import org.netbeans.api.editor.fold.FoldHierarchy; 49 import org.netbeans.api.editor.fold.FoldHierarchyEvent; 50 import org.netbeans.api.editor.fold.FoldHierarchyListener; 51 import org.netbeans.api.editor.fold.FoldUtilities; 52 import org.netbeans.editor.Coloring; 53 54 60 public class CodeFoldingSideBar extends JComponent implements SettingsChangeListener{ 61 62 protected JTextComponent component; 63 64 protected Font font; 65 protected Color foreColor; 66 protected Color backColor; 67 private boolean enabled; 68 69 protected List visibleMarks = new ArrayList (); 70 71 72 public static final int PAINT_NOOP = 0; 73 public static final int PAINT_MARK = 1; 74 public static final int PAINT_LINE = 2; 75 public static final int PAINT_END_MARK = 3; 76 public static final int SINGLE_PAINT_MARK = 4; 77 78 79 80 public CodeFoldingSideBar() { 81 setOpaque(true); 82 } 83 84 public CodeFoldingSideBar(JTextComponent component){ 85 super(); 86 this.component = component; 87 88 Settings.addSettingsChangeListener(this); 89 settingsChange(null); 91 FoldingMouseListener listener = new FoldingMouseListener(); 92 addMouseListener(listener); 93 addMouseMotionListener(listener); 94 FoldHierarchy foldHierarchy = FoldHierarchy.get(component); 95 foldHierarchy.addFoldHierarchyListener(new SideBarFoldHierarchyListener()); 96 Document doc = getDocument(); 97 doc.addDocumentListener( new DocumentListener () { 98 public void insertUpdate(DocumentEvent evt) { 99 if (!(evt instanceof BaseDocumentEvent)) return; 100 101 BaseDocumentEvent bevt = (BaseDocumentEvent)evt; 102 if (bevt.getLFCount() > 0) { repaint(); 104 } 105 } 106 107 public void removeUpdate(DocumentEvent evt) { 108 if (!(evt instanceof BaseDocumentEvent)) return; 109 110 BaseDocumentEvent bevt = (BaseDocumentEvent)evt; 111 if (bevt.getLFCount() > 0) { repaint(); 113 } 114 } 115 116 public void changedUpdate(DocumentEvent evt) { 117 } 118 119 }); 120 setOpaque(true); 121 } 122 123 129 private boolean enableSideBarComponent(boolean enable){ 130 if (enable == enabled) { 131 return false; 132 } 133 enabled = enable; 134 updatePreferredSize(); 135 return true; 136 } 137 138 private void updatePreferredSize() { 139 if (enabled) { 140 setPreferredSize(new Dimension (getColoringFont().getSize(), component.getHeight())); 141 setMaximumSize(new Dimension (Integer.MAX_VALUE, Integer.MAX_VALUE)); 142 }else{ 143 setPreferredSize(new Dimension (0,0)); 144 setMaximumSize(new Dimension (0,0)); 145 } 146 revalidate(); 147 } 148 149 private Font getDefaultColoringFont(){ 150 Coloring defaultColoring = getEditorUI().getDefaultColoring(); 152 if (defaultColoring!=null){ 153 if (defaultColoring.getFont() != null){ 154 return defaultColoring.getFont(); 155 } 156 } 157 return SettingsDefaults.defaultFont; 158 } 159 160 protected Font getColoringFont(){ 161 if (font != null) return font; 162 Coloring foldColoring = getEditorUI().getColoring(SettingsNames.CODE_FOLDING_BAR_COLORING); 163 if (foldColoring != null){ 164 if (foldColoring.getFont()!=null){ 165 font = foldColoring.getFont(); 166 return font; 167 } 168 } 169 font = getDefaultColoringFont(); 170 return font; 171 } 172 173 public void update(Graphics g) { 175 } 176 177 178 protected Color getForeColor(){ 179 if (foreColor != null) return foreColor; 180 Coloring foldColoring = getEditorUI().getColoring(SettingsNames.CODE_FOLDING_BAR_COLORING); 181 if (foldColoring != null && foldColoring.getForeColor()!=null){ 182 foreColor = foldColoring.getForeColor(); 183 return foreColor; 184 } 185 foreColor = getDefaultForeColor(); 186 return foreColor; 187 } 188 189 private Color getDefaultForeColor(){ 190 Coloring defaultColoring = getEditorUI().getDefaultColoring(); 192 if (defaultColoring!=null && defaultColoring.getForeColor()!=null){ 193 return defaultColoring.getForeColor(); 194 } 195 return SettingsDefaults.defaultForeColor; 196 } 197 198 private Color getDefaultBackColor(){ 199 Coloring defaultColoring = getEditorUI().getDefaultColoring(); 201 if (defaultColoring!=null){ 202 return defaultColoring.getBackColor(); 203 } 204 return SettingsDefaults.defaultBackColor; 205 } 206 207 protected Color getBackColor(){ 208 if (backColor != null) return backColor; 209 Coloring foldColoring = getEditorUI().getColoring(SettingsNames.CODE_FOLDING_BAR_COLORING); 210 if (foldColoring != null && foldColoring.getBackColor()!=null){ 211 backColor = foldColoring.getBackColor(); 212 return backColor; 213 } 214 backColor = getDefaultBackColor(); 215 return backColor; 216 } 217 218 public void settingsChange(SettingsChangeEvent evt) { 219 EditorUI editorUI = getEditorUI(); 220 if (editorUI == null) { 221 return; 222 } 223 224 Document doc = component.getDocument(); 226 Class kitClass = (doc instanceof BaseDocument) 227 ? Utilities.getKitClass(component) 228 : BaseKit.class; 229 230 Font origFont = font; 231 232 Coloring foldingColoring = editorUI.getColoring(SettingsNames.CODE_FOLDING_BAR_COLORING); 233 234 if (foldingColoring != null) { 235 font = foldingColoring.getFont(); 236 foreColor = foldingColoring.getForeColor(); 237 backColor = foldingColoring.getBackColor(); 238 } 239 240 if (font == null) { 241 font = getDefaultColoringFont(); 242 } 243 if (foreColor == null) { 244 this.foreColor = getDefaultForeColor(); 245 } 246 if (backColor == null) { 247 backColor = getDefaultBackColor(); 248 } 249 250 Boolean newEnabled = (Boolean )Settings.getValue(kitClass, SettingsNames.CODE_FOLDING_ENABLE); 251 boolean change = enableSideBarComponent((newEnabled != null) ? newEnabled.booleanValue() : false); 252 253 if (!change) { if (font != null && font.equals(origFont)) { 255 repaint(); 256 } else { 257 updatePreferredSize(); 258 revalidate(); 259 } 260 } 261 } 262 263 protected void collectPaintInfos(Fold fold, Map map, int level, int startIndex, int endIndex){ 264 View rootView = Utilities.getDocumentView(component); 265 if (rootView == null) return; 266 for (int i=0; i<fold.getFoldCount(); i++){ 267 int startViewIndex = rootView.getViewIndex(fold.getFold(i).getStartOffset(), Position.Bias.Forward); 268 int endViewIndex = rootView.getViewIndex(fold.getFold(i).getEndOffset(), Position.Bias.Forward); 269 if (endViewIndex>=startIndex && startViewIndex<=endIndex) 270 collectPaintInfos((Fold)fold.getFold(i), map, level+1, startIndex, endIndex); 271 } 272 int foldStartOffset = fold.getStartOffset(); 273 int foldEndOffset = fold.getEndOffset(); 274 int docLength = rootView.getDocument().getLength(); 275 276 if (foldEndOffset > docLength) return; 277 278 int startViewIndex = rootView.getViewIndex(foldStartOffset, Position.Bias.Forward); 279 int endViewIndex = rootView.getViewIndex(foldEndOffset, Position.Bias.Forward); 280 281 try{ 282 View view; 283 BaseTextUI textUI = (BaseTextUI)component.getUI(); 284 Shape viewShape; 285 Rectangle viewRect; 286 int markY = -1; 287 int y=-1; 288 289 if (startIndex <= startViewIndex){ 291 view = rootView.getView(startViewIndex); 292 viewShape = textUI.modelToView(component, view.getStartOffset()); 293 if (viewShape != null) { 294 viewRect = viewShape.getBounds(); 295 y = viewRect.y + viewRect.height; 296 boolean isSingleLineFold = startViewIndex == endViewIndex; 297 if (fold.isCollapsed() || isSingleLineFold){ 298 map.put(new Integer (viewRect.y), 299 new CodeFoldingSideBar.PaintInfo((isSingleLineFold?SINGLE_PAINT_MARK:PAINT_MARK), level, viewRect.y, viewRect.height, fold.isCollapsed())); 300 return; 301 } 302 303 markY = viewRect.y; 304 map.put(new Integer (viewRect.y), new CodeFoldingSideBar.PaintInfo(PAINT_MARK, level, viewRect.y, viewRect.height, fold.isCollapsed())); 305 } 306 } 307 308 if (level == 0){ 310 int loopStart = (startViewIndex<startIndex)? startIndex : startViewIndex+1; 311 int loopEnd = (endViewIndex>endIndex)? endIndex : endViewIndex; 312 viewRect = null; 313 for (int i=loopStart; i<=loopEnd; i++){ 314 view = rootView.getView(i); 315 if (view instanceof DrawEngineLineView && y > -1){ 317 int h = (int)((DrawEngineLineView)view).getLayoutMajorAxisPreferredSpan(); 318 viewRect = new Rectangle (0, y, 0, h); 319 if (i<loopEnd && loopEnd>loopStart) y += h; 320 }else{ 321 viewShape = textUI.modelToView(component, view.getStartOffset()); 322 if (viewShape != null){ 323 viewRect = viewShape.getBounds(); 324 if (i<loopEnd && loopEnd>loopStart) { 325 y = viewRect.y + viewRect.height; 326 } 327 } 328 } 329 if (viewRect != null && !map.containsKey(new Integer (viewRect.y))){ 330 map.put(new Integer (viewRect.y), new CodeFoldingSideBar.PaintInfo(PAINT_LINE, level, viewRect.y, viewRect.height)); 331 } 332 } 333 } 334 335 if (endViewIndex<=endIndex){ 337 view = rootView.getView(endViewIndex); 338 viewRect = null; 340 if (view instanceof DrawEngineLineView && y > -1 && level == 0){ 341 int h = (int)((DrawEngineLineView)view).getLayoutMajorAxisPreferredSpan(); 342 viewRect = new Rectangle (0, y, 0, h); 343 y += h; 344 }else{ 345 viewShape = textUI.modelToView(component, view.getStartOffset()); 346 if (viewShape !=null){ 347 viewRect = viewShape.getBounds(); 348 y = viewRect.y + viewRect.height; 349 } 350 } 351 if (viewRect !=null && markY!=viewRect.y){ 352 PaintInfo pi = (PaintInfo)map.get(new Integer (viewRect.y)); 353 if (pi==null || (pi.getPaintOperation() != PAINT_MARK && pi.getPaintOperation() != SINGLE_PAINT_MARK) || level>=pi.getInnerLevel()){ 354 map.put(new Integer (viewRect.y), new CodeFoldingSideBar.PaintInfo(PAINT_END_MARK, level, viewRect.y, viewRect.height)); 355 } 356 } 357 } 358 }catch(BadLocationException ble){ 359 ble.printStackTrace(); 360 } 361 362 } 363 364 protected List getPaintInfo(int startPos, int endPos){ 365 List ret = new ArrayList (); 366 367 List foldList = getFoldList(startPos, endPos); 368 if (foldList.size() == 0) { 369 return ret; 370 } 371 372 BaseTextUI textUI = (BaseTextUI)component.getUI(); 373 javax.swing.text.Element rootElem = textUI.getRootView(component).getElement(); 374 View rootView = Utilities.getDocumentView(component); 375 if (rootView == null) return ret; 376 377 Document doc = component.getDocument(); 378 if (!(doc instanceof BaseDocument)) return ret; 379 380 BaseDocument bDoc = (BaseDocument) doc; 381 382 Map map = new HashMap (); 383 384 bDoc.readLock(); 385 386 try { 387 FoldHierarchy hierarchy = FoldHierarchy.get(component); 388 hierarchy.lock(); 389 try { 390 391 int startViewIndex = rootView.getViewIndex(startPos,Position.Bias.Forward); 392 int endViewIndex = rootView.getViewIndex(endPos,Position.Bias.Forward); 393 394 for (int i=0; i<foldList.size(); i++){ 395 Fold fold = (Fold)foldList.get(i); 396 collectPaintInfos(fold, map, 0, startViewIndex, endViewIndex); 397 } 398 399 } finally { 400 hierarchy.unlock(); 401 } 402 403 } finally { 404 bDoc.readUnlock(); 405 } 406 407 return new ArrayList (map.values()); 408 } 409 410 protected EditorUI getEditorUI(){ 411 return Utilities.getEditorUI(component); 412 } 413 414 protected Document getDocument(){ 415 return component.getDocument(); 416 } 417 418 419 private Fold getLastLineFold(FoldHierarchy hierarchy, int rowStart, int rowEnd){ 420 Fold fold = FoldUtilities.findNearestFold(hierarchy, rowStart); 421 while (fold != null && fold.getStartOffset()<rowEnd){ 422 Fold nextFold = FoldUtilities.findNearestFold(hierarchy, (fold.isCollapsed()) ? fold.getEndOffset() : fold.getStartOffset()+1); 423 if (nextFold == fold) return fold; 424 if (nextFold!=null && nextFold.getStartOffset() < rowEnd){ 425 fold = nextFold; 426 }else{ 427 return fold; 428 } 429 } 430 return fold; 431 } 432 433 protected void performAction(Mark mark){ 434 BaseTextUI textUI = (BaseTextUI)component.getUI(); 435 javax.swing.text.Element rootElem = textUI.getRootView(component).getElement(); 436 437 View rootView = Utilities.getDocumentView(component); 438 if (rootView == null) return; 439 try{ 440 int startViewIndex = rootView.getViewIndex(textUI.getPosFromY(mark.y+mark.size/2), 441 Position.Bias.Forward); 442 View view = rootView.getView(startViewIndex); 443 444 FoldHierarchy foldHierarchy = FoldHierarchy.get(component); 446 AbstractDocument adoc = (AbstractDocument )foldHierarchy.getComponent().getDocument(); 447 adoc.readLock(); 448 try { 449 foldHierarchy.lock(); 450 try { 451 452 int viewStartOffset = view.getStartOffset(); 453 int rowStart = javax.swing.text.Utilities.getRowStart(component, viewStartOffset); 454 int rowEnd = javax.swing.text.Utilities.getRowEnd(component, viewStartOffset); 455 Fold clickedFold = getLastLineFold(foldHierarchy, rowStart, rowEnd); if (clickedFold != null && clickedFold.getStartOffset() < view.getEndOffset()) { 457 foldHierarchy.toggle(clickedFold); 458 } 459 } finally { 460 foldHierarchy.unlock(); 461 } 462 } finally { 463 adoc.readUnlock(); 464 } 465 }catch(BadLocationException ble){ 467 ble.printStackTrace(); 468 } 469 } 470 471 protected int getMarkSize(Graphics g){ 472 if (g != null){ 473 FontMetrics fm = g.getFontMetrics(getColoringFont()); 474 if (fm != null){ 475 int ret = fm.getAscent() - fm.getDescent(); 476 return ret - ret%2; 477 } 478 } 479 return -1; 480 } 481 482 protected void paintComponent(Graphics g) { 483 484 if (!enabled) return; 485 Rectangle clip = getVisibleRect(); visibleMarks.clear(); 487 g.setColor(getBackColor()); 488 g.fillRect(clip.x, clip.y, clip.width, clip.height); 489 g.setColor(getForeColor()); 490 491 javax.swing.plaf.TextUI ui = component.getUI(); 492 if (!(ui instanceof BaseTextUI)) return; 493 BaseTextUI textUI = (BaseTextUI)ui; 494 495 try{ 496 int startPos = textUI.getPosFromY(clip.y); 497 int endPos = textUI.viewToModel(component, Short.MAX_VALUE/2, clip.y+clip.height); 498 499 List ps = getPaintInfo(startPos, endPos); 500 Font defFont = getColoringFont(); 501 502 for (int i = 0; i <ps.size(); i++){ 503 504 PaintInfo paintInfo = (PaintInfo)ps.get(i); 505 506 if (paintInfo.getPaintOperation() == PAINT_NOOP && paintInfo.getInnerLevel() == 0) continue; 508 boolean isFolded = paintInfo.isCollapsed(); 509 int y = paintInfo.getPaintY(); 510 int height = paintInfo.getPaintHeight(); 511 int markSize = getMarkSize(g); 512 int halfMarkSize = markSize/2; 513 int markX = (defFont.getSize()-markSize)/2; int markY = y + g.getFontMetrics(defFont).getDescent(); int plusGap = (int)Math.round(markSize/3.8); int lineX = markX + halfMarkSize; 518 int paintOperation = paintInfo.getPaintOperation(); 519 if (paintOperation == PAINT_MARK || paintOperation == SINGLE_PAINT_MARK){ 520 g.drawRect(markX, markY, markSize, markSize); 521 g.drawLine(plusGap+markX, markY+halfMarkSize, markSize+markX-plusGap, markY+halfMarkSize); 522 if (isFolded){ 523 g.drawLine(lineX, markY+plusGap, lineX, markY+markSize-plusGap); 524 }else{ 525 if (paintOperation != SINGLE_PAINT_MARK) g.drawLine(lineX, markY + markSize, lineX, y + height); 526 } 527 if (paintInfo.getInnerLevel() > 0){ g.drawLine(lineX, y, lineX, markY); 529 g.drawLine(lineX, markY + markSize, lineX, y + height); 530 } 531 visibleMarks.add(new Mark(markX, markY, markSize, isFolded)); 532 } else if (paintOperation == PAINT_LINE){ 533 g.drawLine(lineX, y, lineX, y + height ); 534 } else if (paintOperation == PAINT_END_MARK){ 535 g.drawLine(lineX, y, lineX, y + height/2); 536 g.drawLine(lineX, y + height/2, lineX + halfMarkSize, y + height/2); 537 if (paintInfo.getInnerLevel() > 0){ g.drawLine(lineX, y + height/2, lineX, y + height); 539 } 540 } 541 542 } 543 }catch(BadLocationException ble){ 544 ble.printStackTrace(); 545 } 546 } 547 548 private List getFoldList(int start, int end) { 549 FoldHierarchy hierarchy = FoldHierarchy.get(component); 550 551 hierarchy.lock(); 552 try { 553 List ret = new ArrayList (); 554 Fold rootFold = hierarchy.getRootFold(); 555 int index = FoldUtilities.findFoldEndIndex(rootFold, start); 556 int foldCount = rootFold.getFoldCount(); 557 while (index < foldCount) { 558 Fold f = rootFold.getFold(index); 559 if (f.getStartOffset() <= end) { 560 ret.add(f); 561 } else { 562 break; } 564 index++; 565 } 566 return ret; 567 } finally { 568 hierarchy.unlock(); 569 } 570 } 571 572 573 public class PaintInfo{ 574 575 int paintOperation; 576 int innerLevel; 577 int paintY; 578 int paintHeight; 579 boolean isCollapsed; 580 581 public PaintInfo(int paintOperation, int innerLevel, int paintY, int paintHeight, boolean isCollapsed){ 582 this.paintOperation = paintOperation; 583 this.innerLevel = innerLevel; 584 this.paintY = paintY; 585 this.paintHeight = paintHeight; 586 this.isCollapsed = isCollapsed; 587 } 588 589 public PaintInfo(int paintOperation, int innerLevel, int paintY, int paintHeight){ 590 this(paintOperation, innerLevel, paintY, paintHeight, false); 591 } 592 593 public int getPaintOperation(){ 594 return paintOperation; 595 } 596 597 public int getInnerLevel(){ 598 return innerLevel; 599 } 600 601 public int getPaintY(){ 602 return paintY; 603 } 604 605 public int getPaintHeight(){ 606 return paintHeight; 607 } 608 609 public boolean isCollapsed(){ 610 return isCollapsed; 611 } 612 613 public void setPaintOperation(int paintOperation){ 614 this.paintOperation = paintOperation; 615 } 616 617 public void setInnerLevel(int innerLevel){ 618 this.innerLevel = innerLevel; 619 } 620 621 public String toString(){ 622 StringBuffer sb = new StringBuffer (""); 623 if (paintOperation == PAINT_NOOP){ 624 sb.append("PAINT_NOOP\n"); }else if (paintOperation == PAINT_MARK){ 626 sb.append("PAINT_MARK\n"); }else if (paintOperation == PAINT_LINE){ 628 sb.append("PAINT_LINE\n"); }else if (paintOperation == PAINT_END_MARK) { 630 sb.append("PAINT_END_MARK\n"); } 632 sb.append("level:"+innerLevel); sb.append("\ncollapsedFold:"+isCollapsed); return sb.toString(); 635 } 636 } 637 638 639 public class Mark{ 640 public int x; 641 public int y; 642 public int size; 643 public boolean isFolded; 644 645 public Mark(int x, int y, int size, boolean isFolded){ 646 this.x = x; 647 this.y = y; 648 this.size = size; 649 this.isFolded = isFolded; 650 } 651 } 652 653 654 class FoldingMouseListener extends MouseAdapter implements MouseMotionListener { 655 656 public FoldingMouseListener(){ 657 super(); 658 } 659 660 private Mark getClickedMark(MouseEvent e){ 661 if (e == null || !SwingUtilities.isLeftMouseButton(e)) return null; 662 int x = e.getX(); 663 int y = e.getY(); 664 for (int i=0; i<visibleMarks.size(); i++){ 665 Mark mark = (Mark)visibleMarks.get(i); 666 if (x >= mark.x && x <= (mark.x + mark.size) && y >= mark.y && y <= (mark.y + mark.size)){ 667 return mark; 668 } 669 } 670 return null; 671 } 672 673 private MouseEvent createNewMouseEvent(MouseEvent oldEvent){ 674 int x = oldEvent.getX() - CodeFoldingSideBar.this.getWidth(); 675 return new MouseEvent (component, 676 oldEvent.getID(), 677 oldEvent.getWhen(), 678 oldEvent.getModifiers(), 679 x, 680 oldEvent.getY(), 681 oldEvent.getClickCount(), 682 oldEvent.isPopupTrigger(), 683 oldEvent.getButton()); 684 } 685 686 687 public void mousePressed (MouseEvent e) { 688 Mark mark = getClickedMark(e); 689 if (mark!=null){ 690 performAction(mark); 691 } else { 692 component.dispatchEvent(createNewMouseEvent(e)); 693 } 694 } 695 696 public void mouseReleased(MouseEvent e){ 697 Mark mark = getClickedMark(e); 698 if (mark==null){ 699 component.dispatchEvent(createNewMouseEvent(e)); 700 } 701 } 702 703 public void mouseEntered(MouseEvent e) { 704 Mark mark = getClickedMark(e); 705 if (mark==null){ 706 component.dispatchEvent(createNewMouseEvent(e)); 707 } 708 } 709 710 public void mouseExited(MouseEvent e) { 711 Mark mark = getClickedMark(e); 712 if (mark==null){ 713 component.dispatchEvent(createNewMouseEvent(e)); 714 } 715 } 716 717 public void mouseMoved(MouseEvent e) { 718 Mark mark = getClickedMark(e); 719 if (mark==null){ 720 component.dispatchEvent(createNewMouseEvent(e)); 721 } 722 } 723 724 public void mouseDragged(MouseEvent e) { 725 Mark mark = getClickedMark(e); 726 if (mark==null){ 727 component.dispatchEvent(createNewMouseEvent(e)); 728 } 729 } 730 } 731 732 class SideBarFoldHierarchyListener implements FoldHierarchyListener{ 733 734 public SideBarFoldHierarchyListener(){ 735 } 736 737 public void foldHierarchyChanged(FoldHierarchyEvent evt) { 738 repaint(); 739 } 740 } 741 742 } 743 | Popular Tags |