diff -r e4cac6efdbe1 editor.lib/src/org/netbeans/editor/CodeFoldingSideBar.java --- a/editor.lib/src/org/netbeans/editor/CodeFoldingSideBar.java Wed Aug 27 07:22:03 2008 +0200 +++ b/editor.lib/src/org/netbeans/editor/CodeFoldingSideBar.java Tue Sep 02 15:43:56 2008 +0200 @@ -83,6 +83,7 @@ import org.netbeans.api.editor.settings.FontColorNames; import org.netbeans.api.editor.settings.FontColorSettings; import org.netbeans.api.editor.settings.SimpleValueNames; +import org.netbeans.editor.view.spi.CodeFoldingPainter; import org.netbeans.modules.editor.lib.EditorPreferencesDefaults; import org.netbeans.modules.editor.lib.SettingsConversions; import org.openide.util.Lookup; @@ -132,6 +133,7 @@ private boolean enabled = false; protected List visibleMarks = new ArrayList(); + protected CodeFoldingPainter painter; /** Paint operations */ public static final int PAINT_NOOP = 0; @@ -169,6 +171,11 @@ public CodeFoldingSideBar(JTextComponent component){ super(); this.component = component; + + painter = MimeLookup.getLookup(org.netbeans.lib.editor.util.swing.DocumentUtilities.getMimeType(component)).lookup(CodeFoldingPainter.class); + if(painter==null){ + painter = new CodeFoldingPainter.DefaultPainter(); + } FoldingMouseListener listener = new FoldingMouseListener(); addMouseListener(listener); @@ -301,9 +308,25 @@ viewRect = viewShape.getBounds(); y = viewRect.y + viewRect.height; boolean isSingleLineFold = startViewIndex == endViewIndex; + //emi: the check bellow seems to be redundant, fold.isCollaped determines isSingleLineFold to be true if (fold.isCollapsed() || isSingleLineFold){ + boolean foldedSinglePaint = fold.isCollapsed(); + if(foldedSinglePaint){ + //see if the parents ends on the same line and mark it as SINGLE_PAINT_MARK + int off = fold.getEndOffset(); + int rowEnd = javax.swing.text.Utilities.getRowEnd(component, off); + Fold parent = fold.getParent(); + while(parent!=null && !FoldUtilities.isRootFold(parent)){ + if(rowEnd!=javax.swing.text.Utilities.getRowEnd(component, parent.getEndOffset())){ + foldedSinglePaint = false; + break; + } + parent = parent.getParent(); + } + } + boolean singleMarkKind = fold.isCollapsed() ? foldedSinglePaint : isSingleLineFold; map.put(new Integer(viewRect.y), - new CodeFoldingSideBar.PaintInfo((isSingleLineFold?SINGLE_PAINT_MARK:PAINT_MARK), level, viewRect.y, viewRect.height, fold.isCollapsed())); + new CodeFoldingSideBar.PaintInfo((singleMarkKind?SINGLE_PAINT_MARK:PAINT_MARK), level, viewRect.y, viewRect.height, fold.isCollapsed())); return; } @@ -422,7 +445,11 @@ } - private Fold getLastLineFold(FoldHierarchy hierarchy, int rowStart, int rowEnd){ + private Fold getLastLineFold(FoldHierarchy hierarchy, int rowStart, int rowEnd, Position.Bias bias){ + if(Position.Bias.Backward.equals(bias)){ + return FoldUtilities.findOffsetFold(hierarchy, rowStart); + } + //normal forward bias Fold fold = FoldUtilities.findNearestFold(hierarchy, rowStart); while (fold != null && fold.getStartOffset() 0){ //[PENDING] - g.drawLine(lineX, y, lineX, markY); - g.drawLine(lineX, markY + markSize, lineX, y + height); - } - visibleMarks.add(new Mark(markX, markY, markSize, isFolded)); - } else if (paintOperation == PAINT_LINE){ - g.drawLine(lineX, y, lineX, y + height ); - } else if (paintOperation == PAINT_END_MARK){ - g.drawLine(lineX, y, lineX, y + height/2); - g.drawLine(lineX, y + height/2, lineX + halfMarkSize, y + height/2); - if (paintInfo.getInnerLevel() > 0){//[PENDING] - g.drawLine(lineX, y + height/2, lineX, y + height); - } - } - + + painter.paint(g, paintInfo,getMarkSize(g),defFont, visibleMarks); } } catch (BadLocationException ble) { LOG.log(Level.WARNING, null, ble); @@ -644,17 +635,22 @@ } /** Keeps info of visible folding mark */ - public class Mark{ + public static class Mark{ public int x; public int y; public int size; public boolean isFolded; + public Position.Bias bias; - public Mark(int x, int y, int size, boolean isFolded){ + public Mark(int x, int y, int size, boolean isFolded, Position.Bias bias){ this.x = x; this.y = y; this.size = size; this.isFolded = isFolded; + this.bias = bias; + } + public Mark(int x, int y, int size, boolean isFolded){ + this(x, y, size, isFolded, Position.Bias.Forward); } } diff -r e4cac6efdbe1 editor.lib/src/org/netbeans/editor/view/spi/CodeFoldingPainter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/editor.lib/src/org/netbeans/editor/view/spi/CodeFoldingPainter.java Tue Sep 02 15:43:56 2008 +0200 @@ -0,0 +1,53 @@ +package org.netbeans.editor.view.spi; + +import java.awt.Font; +import java.awt.Graphics; +import java.util.List; +import org.netbeans.editor.CodeFoldingSideBar; +import org.netbeans.editor.CodeFoldingSideBar.PaintInfo; + +public abstract class CodeFoldingPainter { + public abstract void paint(Graphics g, PaintInfo info,int markSize, Font defFont, List visibleMarks); + + public static class DefaultPainter extends CodeFoldingPainter { + + @Override + public void paint(Graphics g, PaintInfo paintInfo, int markSize, Font defFont, List visibleMarks) { + if (paintInfo.getPaintOperation() == CodeFoldingSideBar.PAINT_NOOP && paintInfo.getInnerLevel() == 0) return; //No painting for this view + + boolean isFolded = paintInfo.isCollapsed(); + int y = paintInfo.getPaintY(); + int height = paintInfo.getPaintHeight(); + int halfMarkSize = markSize/2; + int markX = (defFont.getSize()-markSize)/2; // x position of mark rectangle + int markY = y + g.getFontMetrics(defFont).getDescent(); // y position of mark rectangle + int plusGap = (int)Math.round(markSize/3.8); // distance between mark rectangle vertical side and start/end of minus sign + int lineX = markX + halfMarkSize; // x position of the centre of mark + + int paintOperation = paintInfo.getPaintOperation(); + if (paintOperation == CodeFoldingSideBar.PAINT_MARK || paintOperation == CodeFoldingSideBar.SINGLE_PAINT_MARK){ + g.drawRect(markX, markY, markSize, markSize); + g.drawLine(plusGap+markX, markY+halfMarkSize, markSize+markX-plusGap, markY+halfMarkSize); + if (isFolded){ + g.drawLine(lineX, markY+plusGap, lineX, markY+markSize-plusGap); + }else{ + if (paintOperation != CodeFoldingSideBar.SINGLE_PAINT_MARK) g.drawLine(lineX, markY + markSize, lineX, y + height); + } + if (paintInfo.getInnerLevel() > 0){ //[PENDING] + g.drawLine(lineX, y, lineX, markY); + if (paintOperation != CodeFoldingSideBar.SINGLE_PAINT_MARK) g.drawLine(lineX, markY + markSize, lineX, y + height); + } + visibleMarks.add(new CodeFoldingSideBar.Mark(markX, markY, markSize, isFolded)); + } else if (paintOperation == CodeFoldingSideBar.PAINT_LINE){ + g.drawLine(lineX, y, lineX, y + height ); + } else if (paintOperation == CodeFoldingSideBar.PAINT_END_MARK){ + g.drawLine(lineX, y, lineX, y + height/2); + g.drawLine(lineX, y + height/2, lineX + halfMarkSize, y + height/2); + if (paintInfo.getInnerLevel() > 0){//[PENDING] + g.drawLine(lineX, y + height/2, lineX, y + height); + } + } + } + + } +}