Skip to content

Commit

Permalink
Add a highlight-outline decoration mode
Browse files Browse the repository at this point in the history
It works like a highlight but only render the outline
  • Loading branch information
abe33 committed Mar 2, 2015
1 parent 5d5d6a4 commit 45bf0f4
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 1 deletion.
102 changes: 101 additions & 1 deletion lib/mixins/canvas-drawer.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,12 @@ class CanvasDrawer extends Mixin
for decoration in highlightDecorations
@drawHighlightDecoration(context, decoration, y, screenRow, lineHeight, charWidth, canvasWidth)

# And the highlight box decorations are drawn.
highlightDecorations = decorations['highlight-outline']?[firstRow + row]
if highlightDecorations?.length
for decoration in highlightDecorations
@drawHighlightOutlineDecoration(context, decoration, y, screenRow, lineHeight, charWidth, canvasWidth)

context.fill()

# Internal: Draws a single token on the given context.
Expand Down Expand Up @@ -219,12 +225,18 @@ class CanvasDrawer extends Mixin

x

# Internal: Draws a line decoration on the passed-in context.
#
# context - The canvas context object.
# decoration - The `Decoration` object to render.
# y - The {Number} position on the y axis at which render the decoration.
# canvasWidth - The {Number} of the canvas width.
# lineHeight - The {Number} for the line height.
drawLineDecorations: (context, decorations, y, canvasWidth, lineHeight) ->
for decoration in decorations
context.fillStyle = @getDecorationColor(decoration)
context.fillRect(0,y,canvasWidth,lineHeight)


# Internal: Draws a highlight decoration on the passed-in context.
#
# It renders only the part of the highlight corresponding to the specified
Expand Down Expand Up @@ -254,6 +266,94 @@ class CanvasDrawer extends Mixin
else
context.fillRect(0,y*lineHeight,canvasWidth,lineHeight)

# Internal: Draws a highlight outline decoration on the passed-in context.
#
# It renders only the part of the highlight corresponding to the specified
# row.
#
# context - The canvas context object.
# decoration - The `Decoration` object to render.
# y - The {Number} position on the y axis at which render the decoration.
# screenRow - The row {Number} corresponding to the rendered row.
# lineHeight - The {Number} for the line height.
# charWidth - The {Number} for the character width.
# canvasWidth - The {Number} of the canvas width.
drawHighlightOutlineDecoration: (context, decoration, y, screenRow, lineHeight, charWidth, canvasWidth) ->
context.fillStyle = @getDecorationColor(decoration)
range = decoration.getMarker().getScreenRange()
rowSpan = range.end.row - range.start.row

if rowSpan is 0
colSpan = range.end.column - range.start.column
width = colSpan * charWidth
xStart = range.start.column * charWidth
xEnd = xStart + width
yStart = y * lineHeight
yEnd = yStart + lineHeight

context.fillRect(xStart, yStart, width, 1)
context.fillRect(xStart, yEnd, width, 1)
context.fillRect(xStart, yStart, 1, lineHeight)
context.fillRect(xEnd, yStart, 1, lineHeight)

else if rowSpan is 1
xStart = range.start.column * charWidth
xEnd = range.end.column * charWidth
if screenRow is range.start.row
width = canvasWidth - xStart
yStart = y * lineHeight
yEnd = yStart + lineHeight
xBottomStart = Math.max(xStart, xEnd)
bottomWidth = canvasWidth - xBottomStart

context.fillRect(xStart, yStart, width, 1)
context.fillRect(xBottomStart, yEnd, bottomWidth, 1)
context.fillRect(xStart, yStart, 1, lineHeight)
context.fillRect(canvasWidth - 1, yStart, 1, lineHeight)
else
width = canvasWidth - xStart
yStart = y * lineHeight
yEnd = yStart + lineHeight
bottomWidth = canvasWidth - xEnd

context.fillRect(0, yStart, xStart, 1)
context.fillRect(0, yEnd, xEnd, 1)
context.fillRect(0, yStart, 1, lineHeight)
context.fillRect(xEnd, yStart, 1, lineHeight)
else
xStart = range.start.column * charWidth
xEnd = range.end.column * charWidth

if screenRow is range.start.row
width = canvasWidth - xStart
yStart = y * lineHeight
yEnd = yStart + lineHeight

context.fillRect(xStart, yStart, width, 1)
context.fillRect(xStart, yStart, 1, lineHeight)
context.fillRect(canvasWidth - 1, yStart, 1, lineHeight)

else if screenRow is range.end.row
width = canvasWidth - xStart
yStart = y * lineHeight
yEnd = yStart + lineHeight

context.fillRect(0, yEnd, xEnd, 1)
context.fillRect(0, yStart, 1, lineHeight)
context.fillRect(xEnd, yStart, 1, lineHeight)
else
yStart = y * lineHeight
yEnd = yStart + lineHeight

context.fillRect(0, yStart, 1, lineHeight)
context.fillRect(canvasWidth - 1, yStart, 1, lineHeight)

if screenRow is range.start.row + 1
context.fillRect(0, yStart, xStart, 1)

if screenRow is range.end.row - 1
context.fillRect(xEnd, yEnd, canvasWidth - xEnd, 1)

# Internal: Copy a part of the offscreen bitmap into the onscreen one to
# reduce the amount of rendered lines during scroll.
#
Expand Down
2 changes: 2 additions & 0 deletions lib/mixins/decoration-management.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ class DecorationManagement extends Mixin
# * __highlight-over__: Same as __highlight__.
# * __highlight-under__: Renders a colored rectangle on the minimap. The
# highlight is rendered below the line's text.
# * __highlight-outline__: Renders a colored outline on the minimap. The
# highlight box is rendered above the line's text.
#
# marker - A `Marker` you want this decoration to follow.
# decorationParams - An {Object} representing the decoration eg.
Expand Down
13 changes: 13 additions & 0 deletions spec/minimap-element-spec.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,19 @@ describe 'MinimapElement', ->
expect(minimapElement.drawHighlightDecoration).toHaveBeenCalled()
expect(minimapElement.drawHighlightDecoration.calls.length).toEqual(2)

it 'renders the visible outline decorations', ->
spyOn(minimapElement, 'drawHighlightOutlineDecoration').andCallThrough()

minimap.decorateMarker(editor.markBufferRange([[1,4], [3,6]]), type: 'highlight-outline', color: '#0000ff')
minimap.decorateMarker(editor.markBufferRange([[6,0], [6,7]]), type: 'highlight-outline', color: '#0000ff')
minimap.decorateMarker(editor.markBufferRange([[100,3], [100,5]]), type: 'highlight-outline', color: '#0000ff')

editor.setScrollTop(0)
nextAnimationFrame()

expect(minimapElement.drawHighlightOutlineDecoration).toHaveBeenCalled()
expect(minimapElement.drawHighlightOutlineDecoration.calls.length).toEqual(4)

describe 'when the editor is scrolled', ->
beforeEach ->
editor.setScrollTop(2000)
Expand Down

0 comments on commit 45bf0f4

Please sign in to comment.