KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > editor > CodeFoldingSideBar


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.editor;
21
22 import java.awt.Color JavaDoc;
23 import java.awt.Dimension JavaDoc;
24 import java.awt.Font JavaDoc;
25 import java.awt.FontMetrics JavaDoc;
26 import java.awt.Graphics JavaDoc;
27 import java.awt.Rectangle JavaDoc;
28 import java.awt.Shape JavaDoc;
29 import java.awt.event.MouseAdapter JavaDoc;
30 import java.awt.event.MouseEvent JavaDoc;
31 import java.awt.event.MouseMotionListener JavaDoc;
32 import java.util.ArrayList JavaDoc;
33 import java.util.Collections JavaDoc;
34 import java.util.HashMap JavaDoc;
35 import java.util.List JavaDoc;
36 import java.util.Map JavaDoc;
37 import javax.swing.JComponent JavaDoc;
38 import javax.swing.SwingUtilities JavaDoc;
39 import javax.swing.event.DocumentEvent JavaDoc;
40 import javax.swing.event.DocumentListener JavaDoc;
41 import javax.swing.text.AbstractDocument JavaDoc;
42 import javax.swing.text.BadLocationException JavaDoc;
43 import javax.swing.text.Document JavaDoc;
44 import javax.swing.text.JTextComponent JavaDoc;
45 import javax.swing.text.Position JavaDoc;
46 import javax.swing.text.View JavaDoc;
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 /**
55  * Code Folding Side Bar. Component responsible for drawing folding signs and responding
56  * on user fold/unfold action.
57  *
58  * @author Martin Roskanin
59  */

60 public class CodeFoldingSideBar extends JComponent JavaDoc implements SettingsChangeListener{
61     
62     protected JTextComponent JavaDoc component;
63     
64     protected Font JavaDoc font;
65     protected Color JavaDoc foreColor;
66     protected Color JavaDoc backColor;
67     private boolean enabled;
68     
69     protected List JavaDoc visibleMarks = new ArrayList JavaDoc();
70     
71     /** Paint operations */
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     /** Creates a new instance of CodeFoldingSideBar */
80     public CodeFoldingSideBar() {
81         setOpaque(true);
82     }
83     
84     public CodeFoldingSideBar(JTextComponent JavaDoc component){
85         super();
86         this.component = component;
87
88         Settings.addSettingsChangeListener(this);
89         settingsChange(null); // ensure that the settings get initialized
90

91         FoldingMouseListener listener = new FoldingMouseListener();
92         addMouseListener(listener);
93         addMouseMotionListener(listener);
94         FoldHierarchy foldHierarchy = FoldHierarchy.get(component);
95         foldHierarchy.addFoldHierarchyListener(new SideBarFoldHierarchyListener());
96         Document JavaDoc doc = getDocument();
97         doc.addDocumentListener( new DocumentListener JavaDoc() {
98                 public void insertUpdate(DocumentEvent JavaDoc evt) {
99                     if (!(evt instanceof BaseDocumentEvent)) return;
100                     
101                     BaseDocumentEvent bevt = (BaseDocumentEvent)evt;
102                     if (bevt.getLFCount() > 0) { // one or more lines inserted
103
repaint();
104                     }
105                 }
106                 
107                 public void removeUpdate(DocumentEvent JavaDoc evt) {
108                     if (!(evt instanceof BaseDocumentEvent)) return;
109                     
110                     BaseDocumentEvent bevt = (BaseDocumentEvent)evt;
111                     if (bevt.getLFCount() > 0) { // one or more lines removed
112
repaint();
113                     }
114                 }
115                 
116                 public void changedUpdate(DocumentEvent JavaDoc evt) {
117                 }
118                 
119             });
120         setOpaque(true);
121     }
122     
123     /**
124      * Enable or disable visibility of the side bar.
125      *
126      * @param enable whether the side bar should be enabled or not.
127      * @return whether visibility change occurred or not.
128      */

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 JavaDoc(getColoringFont().getSize(), component.getHeight()));
141             setMaximumSize(new Dimension JavaDoc(Integer.MAX_VALUE, Integer.MAX_VALUE));
142         }else{
143             setPreferredSize(new Dimension JavaDoc(0,0));
144             setMaximumSize(new Dimension JavaDoc(0,0));
145         }
146         revalidate();
147 }
148     
149     private Font JavaDoc getDefaultColoringFont(){
150         // font in folding coloring not available, get default (or inherited)
151
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 JavaDoc 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     // overriding due to issue #60304
174
public void update(Graphics JavaDoc g) {
175     }
176     
177     
178     protected Color JavaDoc 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 JavaDoc getDefaultForeColor(){
190         // font in folding coloring not available, get default (or inherited)
191
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 JavaDoc getDefaultBackColor(){
199         // font in folding coloring not available, get default (or inherited)
200
Coloring defaultColoring = getEditorUI().getDefaultColoring();
201         if (defaultColoring!=null){
202             return defaultColoring.getBackColor();
203         }
204         return SettingsDefaults.defaultBackColor;
205     }
206     
207     protected Color JavaDoc 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         // enable/disable the side bar
225
Document JavaDoc doc = component.getDocument();
226         Class JavaDoc kitClass = (doc instanceof BaseDocument)
227             ? Utilities.getKitClass(component)
228             : BaseKit.class;
229         
230         Font JavaDoc 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 JavaDoc newEnabled = (Boolean JavaDoc)Settings.getValue(kitClass, SettingsNames.CODE_FOLDING_ENABLE);
251         boolean change = enableSideBarComponent((newEnabled != null) ? newEnabled.booleanValue() : false);
252
253         if (!change) { // not revalidated yet
254
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 JavaDoc map, int level, int startIndex, int endIndex){
264         View JavaDoc 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 JavaDoc view;
283             BaseTextUI textUI = (BaseTextUI)component.getUI();
284             Shape JavaDoc viewShape;
285             Rectangle JavaDoc viewRect;
286             int markY = -1;
287             int y=-1;
288             
289             // PAINT_MARK
290
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 JavaDoc(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 JavaDoc(viewRect.y), new CodeFoldingSideBar.PaintInfo(PAINT_MARK, level, viewRect.y, viewRect.height, fold.isCollapsed()));
305                 }
306             }
307             
308             //PAINT_LINE
309
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                     //viewShape = textUI.modelToView(component, view.getStartOffset());
316
if (view instanceof DrawEngineLineView && y > -1){
317                         int h = (int)((DrawEngineLineView)view).getLayoutMajorAxisPreferredSpan();
318                         viewRect = new Rectangle JavaDoc(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 JavaDoc(viewRect.y))){
330                         map.put(new Integer JavaDoc(viewRect.y), new CodeFoldingSideBar.PaintInfo(PAINT_LINE, level, viewRect.y, viewRect.height));
331                     }
332                 }
333             }
334             
335             //PAINT_END_MARK
336
if (endViewIndex<=endIndex){
337                 view = rootView.getView(endViewIndex);
338                 //viewShape = textUI.modelToView(component, view.getStartOffset());
339
viewRect = null;
340                 if (view instanceof DrawEngineLineView && y > -1 && level == 0){
341                     int h = (int)((DrawEngineLineView)view).getLayoutMajorAxisPreferredSpan();
342                     viewRect = new Rectangle JavaDoc(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 JavaDoc(viewRect.y));
353                     if (pi==null || (pi.getPaintOperation() != PAINT_MARK && pi.getPaintOperation() != SINGLE_PAINT_MARK) || level>=pi.getInnerLevel()){
354                         map.put(new Integer JavaDoc(viewRect.y), new CodeFoldingSideBar.PaintInfo(PAINT_END_MARK, level, viewRect.y, viewRect.height));
355                     }
356                 }
357             }
358         }catch(BadLocationException JavaDoc ble){
359             ble.printStackTrace();
360         }
361         
362     }
363     
364     protected List JavaDoc getPaintInfo(int startPos, int endPos){
365         List JavaDoc ret = new ArrayList JavaDoc();
366         
367         List JavaDoc 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 JavaDoc rootElem = textUI.getRootView(component).getElement();
374         View JavaDoc rootView = Utilities.getDocumentView(component);
375         if (rootView == null) return ret;
376
377         Document JavaDoc doc = component.getDocument();
378         if (!(doc instanceof BaseDocument)) return ret;
379
380         BaseDocument bDoc = (BaseDocument) doc;
381         
382         Map JavaDoc map = new HashMap JavaDoc();
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 JavaDoc(map.values());
408     }
409
410     protected EditorUI getEditorUI(){
411         return Utilities.getEditorUI(component);
412     }
413     
414     protected Document JavaDoc 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 JavaDoc rootElem = textUI.getRootView(component).getElement();
436
437         View JavaDoc 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 JavaDoc view = rootView.getView(startViewIndex);
443             
444             // Find corresponding fold
445
FoldHierarchy foldHierarchy = FoldHierarchy.get(component);
446             AbstractDocument JavaDoc adoc = (AbstractDocument JavaDoc)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);//FoldUtilities.findNearestFold(foldHierarchy, viewStartOffset);
456
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             //System.out.println((mark.isFolded ? "Unfold" : "Fold") + " action performed on:"+view); //[TEMP]
466
}catch(BadLocationException JavaDoc ble){
467             ble.printStackTrace();
468         }
469     }
470     
471     protected int getMarkSize(Graphics JavaDoc g){
472         if (g != null){
473             FontMetrics JavaDoc 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 JavaDoc g) {
483         
484         if (!enabled) return;
485         Rectangle JavaDoc clip = getVisibleRect();//g.getClipBounds();
486
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 JavaDoc 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 JavaDoc ps = getPaintInfo(startPos, endPos);
500             Font JavaDoc 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; //No painting for this view
507

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; // x position of mark rectangle
514
int markY = y + g.getFontMetrics(defFont).getDescent(); // y position of mark rectangle
515
int plusGap = (int)Math.round(markSize/3.8); // distance between mark rectangle vertical side and start/end of minus sign
516
int lineX = markX + halfMarkSize; // x position of the centre of mark
517

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){ //[PENDING]
528
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){//[PENDING]
538
g.drawLine(lineX, y + height/2, lineX, y + height);
539                     }
540                 }
541                 
542             }
543         }catch(BadLocationException JavaDoc ble){
544             ble.printStackTrace();
545         }
546     }
547
548     private List JavaDoc getFoldList(int start, int end) {
549         FoldHierarchy hierarchy = FoldHierarchy.get(component);
550         
551         hierarchy.lock();
552         try {
553             List JavaDoc ret = new ArrayList JavaDoc();
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; // no more relevant folds
563
}
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 JavaDoc toString(){
622             StringBuffer JavaDoc sb = new StringBuffer JavaDoc("");
623             if (paintOperation == PAINT_NOOP){
624                 sb.append("PAINT_NOOP\n"); // NOI18N
625
}else if (paintOperation == PAINT_MARK){
626                 sb.append("PAINT_MARK\n"); // NOI18N
627
}else if (paintOperation == PAINT_LINE){
628                 sb.append("PAINT_LINE\n"); // NOI18N
629
}else if (paintOperation == PAINT_END_MARK) {
630                 sb.append("PAINT_END_MARK\n"); // NOI18N
631
}
632             sb.append("level:"+innerLevel); // NOI18N
633
sb.append("\ncollapsedFold:"+isCollapsed); // NOI18N
634
return sb.toString();
635         }
636     }
637     
638     /** Keeps info of visible folding mark */
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     /** Listening on clicking on folding marks */
654     class FoldingMouseListener extends MouseAdapter JavaDoc implements MouseMotionListener JavaDoc {
655         
656         public FoldingMouseListener(){
657             super();
658         }
659
660         private Mark getClickedMark(MouseEvent JavaDoc 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 JavaDoc createNewMouseEvent(MouseEvent JavaDoc oldEvent){
674             int x = oldEvent.getX() - CodeFoldingSideBar.this.getWidth();
675             return new MouseEvent JavaDoc(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 JavaDoc 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 JavaDoc e){
697             Mark mark = getClickedMark(e);
698             if (mark==null){
699                 component.dispatchEvent(createNewMouseEvent(e));
700             }
701         }
702         
703         public void mouseEntered(MouseEvent JavaDoc e) {
704             Mark mark = getClickedMark(e);
705             if (mark==null){
706                 component.dispatchEvent(createNewMouseEvent(e));
707             }
708         }
709         
710         public void mouseExited(MouseEvent JavaDoc e) {
711             Mark mark = getClickedMark(e);
712             if (mark==null){
713                 component.dispatchEvent(createNewMouseEvent(e));
714             }
715         }
716
717         public void mouseMoved(MouseEvent JavaDoc e) {
718             Mark mark = getClickedMark(e);
719             if (mark==null){
720                 component.dispatchEvent(createNewMouseEvent(e));
721             }
722         }
723
724         public void mouseDragged(MouseEvent JavaDoc 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