This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

View | Details | Raw Unified | Return to bug 145920
Collapse All | Expand All

(-)a/editor.lib/src/org/netbeans/editor/CodeFoldingSideBar.java (-44 / +40 lines)
Lines 83-88 Link Here
83
import org.netbeans.api.editor.settings.FontColorNames;
83
import org.netbeans.api.editor.settings.FontColorNames;
84
import org.netbeans.api.editor.settings.FontColorSettings;
84
import org.netbeans.api.editor.settings.FontColorSettings;
85
import org.netbeans.api.editor.settings.SimpleValueNames;
85
import org.netbeans.api.editor.settings.SimpleValueNames;
86
import org.netbeans.editor.view.spi.CodeFoldingPainter;
86
import org.netbeans.modules.editor.lib.EditorPreferencesDefaults;
87
import org.netbeans.modules.editor.lib.EditorPreferencesDefaults;
87
import org.netbeans.modules.editor.lib.SettingsConversions;
88
import org.netbeans.modules.editor.lib.SettingsConversions;
88
import org.openide.util.Lookup;
89
import org.openide.util.Lookup;
Lines 132-137 Link Here
132
    private boolean enabled = false;
133
    private boolean enabled = false;
133
    
134
    
134
    protected List visibleMarks = new ArrayList();
135
    protected List visibleMarks = new ArrayList();
136
    protected CodeFoldingPainter painter;
135
    
137
    
136
    /** Paint operations */
138
    /** Paint operations */
137
    public static final int PAINT_NOOP             = 0;
139
    public static final int PAINT_NOOP             = 0;
Lines 169-174 Link Here
169
    public CodeFoldingSideBar(JTextComponent component){
171
    public CodeFoldingSideBar(JTextComponent component){
170
        super();
172
        super();
171
        this.component = component;
173
        this.component = component;
174
        
175
        painter = MimeLookup.getLookup(org.netbeans.lib.editor.util.swing.DocumentUtilities.getMimeType(component)).lookup(CodeFoldingPainter.class);
176
        if(painter==null){
177
            painter = new CodeFoldingPainter.DefaultPainter();
178
        }
172
179
173
        FoldingMouseListener listener = new FoldingMouseListener();
180
        FoldingMouseListener listener = new FoldingMouseListener();
174
        addMouseListener(listener);
181
        addMouseListener(listener);
Lines 301-309 Link Here
301
                    viewRect = viewShape.getBounds();
308
                    viewRect = viewShape.getBounds();
302
                    y = viewRect.y + viewRect.height;
309
                    y = viewRect.y + viewRect.height;
303
                    boolean isSingleLineFold = startViewIndex == endViewIndex;
310
                    boolean isSingleLineFold = startViewIndex == endViewIndex;
311
                    //emi: the check bellow seems to be redundant, fold.isCollaped determines isSingleLineFold to be true
304
                    if (fold.isCollapsed() || isSingleLineFold){
312
                    if (fold.isCollapsed() || isSingleLineFold){
313
                        boolean foldedSinglePaint = fold.isCollapsed();
314
                        if(foldedSinglePaint){
315
                            //see if the parents ends on the same line and mark it as SINGLE_PAINT_MARK 
316
                            int off = fold.getEndOffset();
317
                            int rowEnd = javax.swing.text.Utilities.getRowEnd(component, off);
318
                            Fold parent = fold.getParent();
319
                            while(parent!=null && !FoldUtilities.isRootFold(parent)){
320
                                if(rowEnd!=javax.swing.text.Utilities.getRowEnd(component, parent.getEndOffset())){
321
                                    foldedSinglePaint = false;
322
                                    break;
323
                                }
324
                                parent = parent.getParent();
325
                            }
326
                        }
327
                        boolean singleMarkKind = fold.isCollapsed() ? foldedSinglePaint : isSingleLineFold;
305
                        map.put(new Integer(viewRect.y), 
328
                        map.put(new Integer(viewRect.y), 
306
                            new CodeFoldingSideBar.PaintInfo((isSingleLineFold?SINGLE_PAINT_MARK:PAINT_MARK), level, viewRect.y, viewRect.height, fold.isCollapsed()));
329
                            new CodeFoldingSideBar.PaintInfo((singleMarkKind?SINGLE_PAINT_MARK:PAINT_MARK), level, viewRect.y, viewRect.height, fold.isCollapsed()));
307
                        return;
330
                        return;
308
                    }
331
                    }
309
332
Lines 422-428 Link Here
422
    }
445
    }
423
446
424
    
447
    
425
    private Fold getLastLineFold(FoldHierarchy hierarchy, int rowStart, int rowEnd){
448
    private Fold getLastLineFold(FoldHierarchy hierarchy, int rowStart, int rowEnd, Position.Bias bias){
449
        if(Position.Bias.Backward.equals(bias)){
450
            return FoldUtilities.findOffsetFold(hierarchy, rowStart);
451
        }
452
        //normal forward bias
426
        Fold fold = FoldUtilities.findNearestFold(hierarchy, rowStart);
453
        Fold fold = FoldUtilities.findNearestFold(hierarchy, rowStart);
427
        while (fold != null && fold.getStartOffset()<rowEnd){
454
        while (fold != null && fold.getStartOffset()<rowEnd){
428
            Fold nextFold = FoldUtilities.findNearestFold(hierarchy, (fold.isCollapsed()) ? fold.getEndOffset() : fold.getStartOffset()+1);
455
            Fold nextFold = FoldUtilities.findNearestFold(hierarchy, (fold.isCollapsed()) ? fold.getEndOffset() : fold.getStartOffset()+1);
Lines 444-450 Link Here
444
        if (rootView == null) return;
471
        if (rootView == null) return;
445
        try{
472
        try{
446
            int startViewIndex = rootView.getViewIndex(textUI.getPosFromY(mark.y+mark.size/2),
473
            int startViewIndex = rootView.getViewIndex(textUI.getPosFromY(mark.y+mark.size/2),
447
                Position.Bias.Forward);            
474
                /*mark.bias*/Position.Bias.Forward);            
448
            View view = rootView.getView(startViewIndex);
475
            View view = rootView.getView(startViewIndex);
449
            
476
            
450
            // Find corresponding fold
477
            // Find corresponding fold
Lines 458-464 Link Here
458
                    int viewStartOffset = view.getStartOffset();
485
                    int viewStartOffset = view.getStartOffset();
459
                    int rowStart = javax.swing.text.Utilities.getRowStart(component, viewStartOffset);
486
                    int rowStart = javax.swing.text.Utilities.getRowStart(component, viewStartOffset);
460
                    int rowEnd = javax.swing.text.Utilities.getRowEnd(component, viewStartOffset);
487
                    int rowEnd = javax.swing.text.Utilities.getRowEnd(component, viewStartOffset);
461
                    Fold clickedFold = getLastLineFold(foldHierarchy, rowStart, rowEnd);//FoldUtilities.findNearestFold(foldHierarchy, viewStartOffset);
488
                    Fold clickedFold = getLastLineFold(foldHierarchy, rowStart, rowEnd, mark.bias);//FoldUtilities.findNearestFold(foldHierarchy, viewStartOffset);
462
                    if (clickedFold != null && clickedFold.getStartOffset() < view.getEndOffset()) {
489
                    if (clickedFold != null && clickedFold.getStartOffset() < view.getEndOffset()) {
463
                        foldHierarchy.toggle(clickedFold); 
490
                        foldHierarchy.toggle(clickedFold); 
464
                    }
491
                    }
Lines 468-474 Link Here
468
            } finally {
495
            } finally {
469
                adoc.readUnlock();
496
                adoc.readUnlock();
470
            }
497
            }
471
            //System.out.println((mark.isFolded ? "Unfold" : "Fold") + " action performed on:"+view); //[TEMP]
472
        } catch (BadLocationException ble) {
498
        } catch (BadLocationException ble) {
473
            LOG.log(Level.WARNING, null, ble);
499
            LOG.log(Level.WARNING, null, ble);
474
        }
500
        }
Lines 510-552 Link Here
510
            for (int i = 0; i <ps.size(); i++){
536
            for (int i = 0; i <ps.size(); i++){
511
537
512
                PaintInfo paintInfo = (PaintInfo)ps.get(i);
538
                PaintInfo paintInfo = (PaintInfo)ps.get(i);
513
                
539
               
514
                if (paintInfo.getPaintOperation() == PAINT_NOOP && paintInfo.getInnerLevel() == 0) continue; //No painting for this view
540
                painter.paint(g, paintInfo,getMarkSize(g),defFont, visibleMarks);
515
                
516
                boolean isFolded = paintInfo.isCollapsed();
517
                int y = paintInfo.getPaintY();
518
                int height = paintInfo.getPaintHeight();
519
                int markSize = getMarkSize(g);
520
                int halfMarkSize = markSize/2;
521
                int markX = (defFont.getSize()-markSize)/2; // x position of mark rectangle
522
                int markY = y + g.getFontMetrics(defFont).getDescent(); // y position of mark rectangle
523
                int plusGap = (int)Math.round(markSize/3.8); // distance between mark rectangle vertical side and start/end of minus sign
524
                int lineX = markX + halfMarkSize; // x position of the centre of mark
525
                
526
                int paintOperation = paintInfo.getPaintOperation();
527
                if (paintOperation == PAINT_MARK || paintOperation == SINGLE_PAINT_MARK){
528
                    g.drawRect(markX, markY, markSize, markSize);
529
                    g.drawLine(plusGap+markX, markY+halfMarkSize, markSize+markX-plusGap, markY+halfMarkSize);
530
                    if (isFolded){
531
                        g.drawLine(lineX, markY+plusGap, lineX, markY+markSize-plusGap);
532
                    }else{
533
                        if (paintOperation != SINGLE_PAINT_MARK) g.drawLine(lineX, markY + markSize, lineX, y + height);
534
                    }
535
                    if (paintInfo.getInnerLevel() > 0){ //[PENDING]
536
                        g.drawLine(lineX, y, lineX, markY);
537
                        g.drawLine(lineX, markY + markSize, lineX, y + height);
538
                    }
539
                    visibleMarks.add(new Mark(markX, markY, markSize, isFolded));
540
                } else if (paintOperation == PAINT_LINE){
541
                    g.drawLine(lineX, y, lineX, y + height );
542
                } else if (paintOperation == PAINT_END_MARK){
543
                    g.drawLine(lineX, y, lineX, y + height/2);
544
                    g.drawLine(lineX, y + height/2, lineX + halfMarkSize, y + height/2);
545
                    if (paintInfo.getInnerLevel() > 0){//[PENDING]
546
                        g.drawLine(lineX, y + height/2, lineX, y + height);
547
                    }
548
                }
549
                
550
            }
541
            }
551
        } catch (BadLocationException ble) {
542
        } catch (BadLocationException ble) {
552
            LOG.log(Level.WARNING, null, ble);
543
            LOG.log(Level.WARNING, null, ble);
Lines 644-660 Link Here
644
    }
635
    }
645
    
636
    
646
    /** Keeps info of visible folding mark */
637
    /** Keeps info of visible folding mark */
647
    public class Mark{
638
    public static class Mark{
648
        public int x;
639
        public int x;
649
        public int y;
640
        public int y;
650
        public int size;
641
        public int size;
651
        public boolean isFolded;
642
        public boolean isFolded;
643
        public Position.Bias bias;
652
        
644
        
653
        public Mark(int x, int y, int size, boolean isFolded){
645
        public Mark(int x, int y, int size, boolean isFolded, Position.Bias bias){
654
            this.x = x;
646
            this.x = x;
655
            this.y = y;
647
            this.y = y;
656
            this.size = size;
648
            this.size = size;
657
            this.isFolded = isFolded;
649
            this.isFolded = isFolded;
650
            this.bias = bias;
651
        }
652
        public Mark(int x, int y, int size, boolean isFolded){
653
            this(x, y, size, isFolded, Position.Bias.Forward);
658
        }
654
        }
659
    }
655
    }
660
    
656
    
(-)e4cac6efdbe1 (+53 lines)
Added Link Here
1
package org.netbeans.editor.view.spi;
2
3
import java.awt.Font;
4
import java.awt.Graphics;
5
import java.util.List;
6
import org.netbeans.editor.CodeFoldingSideBar;
7
import org.netbeans.editor.CodeFoldingSideBar.PaintInfo;
8
9
public abstract class CodeFoldingPainter {
10
    public abstract void paint(Graphics g, PaintInfo info,int markSize, Font defFont, List visibleMarks);
11
    
12
    public static class DefaultPainter extends CodeFoldingPainter {
13
14
        @Override
15
        public void paint(Graphics g, PaintInfo paintInfo, int markSize, Font defFont, List visibleMarks) {
16
                if (paintInfo.getPaintOperation() == CodeFoldingSideBar.PAINT_NOOP && paintInfo.getInnerLevel() == 0) return; //No painting for this view
17
                
18
                boolean isFolded = paintInfo.isCollapsed();
19
                int y = paintInfo.getPaintY();
20
                int height = paintInfo.getPaintHeight();
21
                int halfMarkSize = markSize/2;
22
                int markX = (defFont.getSize()-markSize)/2; // x position of mark rectangle
23
                int markY = y + g.getFontMetrics(defFont).getDescent(); // y position of mark rectangle
24
                int plusGap = (int)Math.round(markSize/3.8); // distance between mark rectangle vertical side and start/end of minus sign
25
                int lineX = markX + halfMarkSize; // x position of the centre of mark
26
                
27
                int paintOperation = paintInfo.getPaintOperation();
28
                if (paintOperation == CodeFoldingSideBar.PAINT_MARK || paintOperation == CodeFoldingSideBar.SINGLE_PAINT_MARK){
29
                    g.drawRect(markX, markY, markSize, markSize);
30
                    g.drawLine(plusGap+markX, markY+halfMarkSize, markSize+markX-plusGap, markY+halfMarkSize);
31
                    if (isFolded){
32
                        g.drawLine(lineX, markY+plusGap, lineX, markY+markSize-plusGap);
33
                    }else{
34
                        if (paintOperation != CodeFoldingSideBar.SINGLE_PAINT_MARK) g.drawLine(lineX, markY + markSize, lineX, y + height);
35
                    }
36
                    if (paintInfo.getInnerLevel() > 0){ //[PENDING]
37
                        g.drawLine(lineX, y, lineX, markY);
38
                        if (paintOperation != CodeFoldingSideBar.SINGLE_PAINT_MARK) g.drawLine(lineX, markY + markSize, lineX, y + height);
39
                    }
40
                    visibleMarks.add(new CodeFoldingSideBar.Mark(markX, markY, markSize, isFolded));
41
                } else if (paintOperation == CodeFoldingSideBar.PAINT_LINE){
42
                    g.drawLine(lineX, y, lineX, y + height );
43
                } else if (paintOperation == CodeFoldingSideBar.PAINT_END_MARK){
44
                    g.drawLine(lineX, y, lineX, y + height/2);
45
                    g.drawLine(lineX, y + height/2, lineX + halfMarkSize, y + height/2);
46
                    if (paintInfo.getInnerLevel() > 0){//[PENDING]
47
                        g.drawLine(lineX, y + height/2, lineX, y + height);
48
                    }
49
                }
50
        }
51
        
52
    }
53
}

Return to bug 145920