diff --git a/lib/mixins/canvas-drawer.coffee b/lib/mixins/canvas-drawer.coffee index 08b759f3..63746edb 100644 --- a/lib/mixins/canvas-drawer.coffee +++ b/lib/mixins/canvas-drawer.coffee @@ -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. @@ -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 @@ -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. # diff --git a/lib/mixins/decoration-management.coffee b/lib/mixins/decoration-management.coffee index be79c331..2148d060 100644 --- a/lib/mixins/decoration-management.coffee +++ b/lib/mixins/decoration-management.coffee @@ -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. diff --git a/spec/minimap-element-spec.coffee b/spec/minimap-element-spec.coffee index a4a1ec73..62fce5ee 100644 --- a/spec/minimap-element-spec.coffee +++ b/spec/minimap-element-spec.coffee @@ -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)