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; |
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; |
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); |
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 |
|
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); |
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 |
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 |
} |
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 |
} |
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); |
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 |
|