diff --git a/spec/fake-lines-yardstick.coffee b/spec/fake-lines-yardstick.coffee index 3d2ebe7d5..a8a624970 100644 --- a/spec/fake-lines-yardstick.coffee +++ b/spec/fake-lines-yardstick.coffee @@ -31,7 +31,7 @@ class FakeLinesYardstick targetColumn = screenPosition.column baseCharacterWidth = @model.getDefaultCharWidth() - top = @lineTopIndex.bottomPixelPositionForRow(targetRow) + top = @lineTopIndex.pixelPositionForRow(targetRow) left = 0 column = 0 @@ -61,14 +61,14 @@ class FakeLinesYardstick {top, left} pixelRectForScreenRange: (screenRange) -> + top = @lineTopIndex.pixelPositionForRow(screenRange.start.row) if screenRange.end.row > screenRange.start.row - top = @pixelPositionForScreenPosition(screenRange.start).top left = 0 - height = @lineTopIndex.topPixelPositionForRow(screenRange.end.row + 1) - top + height = @lineTopIndex.pixelPositionForRow(screenRange.end.row) - top + @model.getLineHeightInPixels() width = @presenter.getScrollWidth() else - {top, left} = @pixelPositionForScreenPosition(screenRange.start, false) - height = @lineTopIndex.topPixelPositionForRow(screenRange.end.row + 1) - top + {left} = @pixelPositionForScreenPosition(screenRange.start, false) + height = @lineTopIndex.pixelPositionForRow(screenRange.end.row) - top + @model.getLineHeightInPixels() width = @pixelPositionForScreenPosition(screenRange.end, false).left - left {top, left, width, height} diff --git a/spec/line-top-index-spec.js b/spec/line-top-index-spec.js deleted file mode 100644 index 62d3e1839..000000000 --- a/spec/line-top-index-spec.js +++ /dev/null @@ -1,189 +0,0 @@ -/** @babel */ - -const LineTopIndex = require('../src/linear-line-top-index') - -describe("LineTopIndex", function () { - let lineTopIndex - - beforeEach(function () { - lineTopIndex = new LineTopIndex() - lineTopIndex.setDefaultLineHeight(10) - lineTopIndex.setMaxRow(12) - }) - - describe("::topPixelPositionForRow(row)", function () { - it("performs the simple math when there are no block decorations", function () { - expect(lineTopIndex.topPixelPositionForRow(0)).toBe(0) - expect(lineTopIndex.topPixelPositionForRow(4)).toBe(40) - expect(lineTopIndex.topPixelPositionForRow(5)).toBe(50) - expect(lineTopIndex.topPixelPositionForRow(12)).toBe(120) - expect(lineTopIndex.topPixelPositionForRow(13)).toBe(120) - expect(lineTopIndex.topPixelPositionForRow(14)).toBe(120) - - lineTopIndex.splice(0, 2, 3) - - expect(lineTopIndex.topPixelPositionForRow(0)).toBe(0) - expect(lineTopIndex.topPixelPositionForRow(4)).toBe(40) - expect(lineTopIndex.topPixelPositionForRow(5)).toBe(50) - expect(lineTopIndex.topPixelPositionForRow(12)).toBe(120) - expect(lineTopIndex.topPixelPositionForRow(13)).toBe(130) - expect(lineTopIndex.topPixelPositionForRow(14)).toBe(130) - }) - - it("takes into account inserted and removed blocks", function () { - let block1 = lineTopIndex.insertBlock(0, 10) - let block2 = lineTopIndex.insertBlock(3, 20) - let block3 = lineTopIndex.insertBlock(5, 20) - - expect(lineTopIndex.topPixelPositionForRow(0)).toBe(0) - expect(lineTopIndex.topPixelPositionForRow(1)).toBe(20) - expect(lineTopIndex.topPixelPositionForRow(2)).toBe(30) - expect(lineTopIndex.topPixelPositionForRow(3)).toBe(40) - expect(lineTopIndex.topPixelPositionForRow(4)).toBe(70) - expect(lineTopIndex.topPixelPositionForRow(5)).toBe(80) - expect(lineTopIndex.topPixelPositionForRow(6)).toBe(110) - - lineTopIndex.removeBlock(block1) - lineTopIndex.removeBlock(block3) - - expect(lineTopIndex.topPixelPositionForRow(0)).toBe(0) - expect(lineTopIndex.topPixelPositionForRow(1)).toBe(10) - expect(lineTopIndex.topPixelPositionForRow(2)).toBe(20) - expect(lineTopIndex.topPixelPositionForRow(3)).toBe(30) - expect(lineTopIndex.topPixelPositionForRow(4)).toBe(60) - expect(lineTopIndex.topPixelPositionForRow(5)).toBe(70) - expect(lineTopIndex.topPixelPositionForRow(6)).toBe(80) - }) - - it("moves blocks down/up when splicing regions", function () { - let block1 = lineTopIndex.insertBlock(3, 20) - let block2 = lineTopIndex.insertBlock(5, 30) - - lineTopIndex.splice(0, 0, 4) - - expect(lineTopIndex.topPixelPositionForRow(0)).toBe(0) - expect(lineTopIndex.topPixelPositionForRow(6)).toBe(60) - expect(lineTopIndex.topPixelPositionForRow(7)).toBe(70) - expect(lineTopIndex.topPixelPositionForRow(8)).toBe(100) - expect(lineTopIndex.topPixelPositionForRow(9)).toBe(110) - expect(lineTopIndex.topPixelPositionForRow(10)).toBe(150) - expect(lineTopIndex.topPixelPositionForRow(11)).toBe(160) - - lineTopIndex.splice(0, 6, 2) - - expect(lineTopIndex.topPixelPositionForRow(0)).toBe(0) - expect(lineTopIndex.topPixelPositionForRow(3)).toBe(30) - expect(lineTopIndex.topPixelPositionForRow(4)).toBe(60) - expect(lineTopIndex.topPixelPositionForRow(5)).toBe(70) - expect(lineTopIndex.topPixelPositionForRow(6)).toBe(110) - - lineTopIndex.splice(2, 4, 0) - - expect(lineTopIndex.topPixelPositionForRow(0)).toBe(0) - expect(lineTopIndex.topPixelPositionForRow(1)).toBe(10) - expect(lineTopIndex.topPixelPositionForRow(2)).toBe(20) - expect(lineTopIndex.topPixelPositionForRow(3)).toBe(80) - expect(lineTopIndex.topPixelPositionForRow(4)).toBe(90) - expect(lineTopIndex.topPixelPositionForRow(5)).toBe(100) - expect(lineTopIndex.topPixelPositionForRow(6)).toBe(110) - expect(lineTopIndex.topPixelPositionForRow(7)).toBe(120) - expect(lineTopIndex.topPixelPositionForRow(8)).toBe(130) - expect(lineTopIndex.topPixelPositionForRow(9)).toBe(130) - }) - }) - - describe("::rowForTopPixelPosition(top)", function () { - it("performs the simple math when there are no block decorations", function () { - expect(lineTopIndex.rowForTopPixelPosition(0)).toBe(0) - expect(lineTopIndex.rowForTopPixelPosition(40)).toBe(4) - expect(lineTopIndex.rowForTopPixelPosition(44)).toBe(4) - expect(lineTopIndex.rowForTopPixelPosition(46)).toBe(4) - expect(lineTopIndex.rowForTopPixelPosition(50)).toBe(5) - expect(lineTopIndex.rowForTopPixelPosition(120)).toBe(12) - expect(lineTopIndex.rowForTopPixelPosition(130)).toBe(12) - expect(lineTopIndex.rowForTopPixelPosition(140)).toBe(12) - expect(lineTopIndex.rowForTopPixelPosition(145)).toBe(12) - - lineTopIndex.splice(0, 2, 3) - - expect(lineTopIndex.rowForTopPixelPosition(0)).toBe(0) - expect(lineTopIndex.rowForTopPixelPosition(40)).toBe(4) - expect(lineTopIndex.rowForTopPixelPosition(50)).toBe(5) - expect(lineTopIndex.rowForTopPixelPosition(120)).toBe(12) - expect(lineTopIndex.rowForTopPixelPosition(130)).toBe(13) - expect(lineTopIndex.rowForTopPixelPosition(140)).toBe(13) - }) - - it("takes into account inserted and removed blocks", function () { - let block1 = lineTopIndex.insertBlock(0, 10) - let block2 = lineTopIndex.insertBlock(3, 20) - let block3 = lineTopIndex.insertBlock(5, 20) - - expect(lineTopIndex.rowForTopPixelPosition(0)).toBe(0) - expect(lineTopIndex.rowForTopPixelPosition(6)).toBe(0) - expect(lineTopIndex.rowForTopPixelPosition(10)).toBe(0) - expect(lineTopIndex.rowForTopPixelPosition(12)).toBe(0) - expect(lineTopIndex.rowForTopPixelPosition(17)).toBe(0) - expect(lineTopIndex.rowForTopPixelPosition(20)).toBe(1) - expect(lineTopIndex.rowForTopPixelPosition(30)).toBe(2) - expect(lineTopIndex.rowForTopPixelPosition(40)).toBe(3) - expect(lineTopIndex.rowForTopPixelPosition(70)).toBe(4) - expect(lineTopIndex.rowForTopPixelPosition(80)).toBe(5) - expect(lineTopIndex.rowForTopPixelPosition(90)).toBe(5) - expect(lineTopIndex.rowForTopPixelPosition(95)).toBe(5) - expect(lineTopIndex.rowForTopPixelPosition(106)).toBe(5) - expect(lineTopIndex.rowForTopPixelPosition(110)).toBe(6) - expect(lineTopIndex.rowForTopPixelPosition(160)).toBe(11) - expect(lineTopIndex.rowForTopPixelPosition(166)).toBe(11) - expect(lineTopIndex.rowForTopPixelPosition(170)).toBe(12) - expect(lineTopIndex.rowForTopPixelPosition(240)).toBe(12) - - lineTopIndex.removeBlock(block1) - lineTopIndex.removeBlock(block3) - - expect(lineTopIndex.rowForTopPixelPosition(0)).toBe(0) - expect(lineTopIndex.rowForTopPixelPosition(10)).toBe(1) - expect(lineTopIndex.rowForTopPixelPosition(20)).toBe(2) - expect(lineTopIndex.rowForTopPixelPosition(30)).toBe(3) - expect(lineTopIndex.rowForTopPixelPosition(60)).toBe(4) - expect(lineTopIndex.rowForTopPixelPosition(70)).toBe(5) - expect(lineTopIndex.rowForTopPixelPosition(80)).toBe(6) - }) - - it("moves blocks down/up when splicing regions", function () { - let block1 = lineTopIndex.insertBlock(3, 20) - let block2 = lineTopIndex.insertBlock(5, 30) - - lineTopIndex.splice(0, 0, 4) - - expect(lineTopIndex.rowForTopPixelPosition(0)).toBe(0) - expect(lineTopIndex.rowForTopPixelPosition(60)).toBe(6) - expect(lineTopIndex.rowForTopPixelPosition(70)).toBe(7) - expect(lineTopIndex.rowForTopPixelPosition(100)).toBe(8) - expect(lineTopIndex.rowForTopPixelPosition(110)).toBe(9) - expect(lineTopIndex.rowForTopPixelPosition(150)).toBe(10) - expect(lineTopIndex.rowForTopPixelPosition(160)).toBe(11) - - lineTopIndex.splice(0, 6, 2) - - expect(lineTopIndex.rowForTopPixelPosition(0)).toBe(0) - expect(lineTopIndex.rowForTopPixelPosition(30)).toBe(3) - expect(lineTopIndex.rowForTopPixelPosition(60)).toBe(4) - expect(lineTopIndex.rowForTopPixelPosition(70)).toBe(5) - expect(lineTopIndex.rowForTopPixelPosition(110)).toBe(6) - - lineTopIndex.splice(2, 4, 0) - - expect(lineTopIndex.rowForTopPixelPosition(0)).toBe(0) - expect(lineTopIndex.rowForTopPixelPosition(10)).toBe(1) - expect(lineTopIndex.rowForTopPixelPosition(20)).toBe(2) - expect(lineTopIndex.rowForTopPixelPosition(80)).toBe(3) - expect(lineTopIndex.rowForTopPixelPosition(90)).toBe(4) - expect(lineTopIndex.rowForTopPixelPosition(100)).toBe(5) - expect(lineTopIndex.rowForTopPixelPosition(110)).toBe(6) - expect(lineTopIndex.rowForTopPixelPosition(120)).toBe(7) - expect(lineTopIndex.rowForTopPixelPosition(130)).toBe(8) - expect(lineTopIndex.rowForTopPixelPosition(130)).toBe(8) - }) - }) -}) diff --git a/spec/lines-yardstick-spec.coffee b/spec/lines-yardstick-spec.coffee index 44267699e..791385d64 100644 --- a/spec/lines-yardstick-spec.coffee +++ b/spec/lines-yardstick-spec.coffee @@ -57,9 +57,10 @@ describe "LinesYardstick", -> textNodes editor.setLineHeightInPixels(14) - lineTopIndex = new LineTopIndex() - lineTopIndex.setDefaultLineHeight(editor.getLineHeightInPixels()) - lineTopIndex.setMaxRow(editor.getScreenLineCount()) + lineTopIndex = new LineTopIndex({ + maxRow: editor.getScreenLineCount(), + defaultLineHeight: editor.getLineHeightInPixels() + }) linesYardstick = new LinesYardstick(editor, mockPresenter, mockLineNodesProvider, lineTopIndex, atom.grammars) afterEach -> diff --git a/spec/text-editor-presenter-spec.coffee b/spec/text-editor-presenter-spec.coffee index fdcb8a418..87c32475d 100644 --- a/spec/text-editor-presenter-spec.coffee +++ b/spec/text-editor-presenter-spec.coffee @@ -27,7 +27,10 @@ describe "TextEditorPresenter", -> buffer.destroy() buildPresenterWithoutMeasurements = (params={}) -> - lineTopIndex = new LineTopIndex + lineTopIndex = new LineTopIndex({ + maxRow: editor.getScreenLineCount(), + defaultLineHeight: editor.getLineHeightInPixels() + }) _.defaults params, model: editor config: atom.config @@ -526,8 +529,6 @@ describe "TextEditorPresenter", -> presenter = buildPresenter(scrollTop: 0, lineHeight: 10) expect(presenter.getState().verticalScrollbar.scrollHeight).toBe editor.getScreenLineCount() * 10 - # Setting `null` as the DOM element, as it doesn't really matter here. - # Maybe a signal that we should separate models from views? blockDecoration1 = editor.addBlockDecorationForScreenRow(0, null) blockDecoration2 = editor.addBlockDecorationForScreenRow(3, null) blockDecoration3 = editor.addBlockDecorationForScreenRow(7, null) @@ -719,8 +720,6 @@ describe "TextEditorPresenter", -> presenter = buildPresenter(scrollTop: 0, lineHeight: 10) expect(presenter.getState().verticalScrollbar.scrollHeight).toBe editor.getScreenLineCount() * 10 - # Setting `null` as the DOM element, as it doesn't really matter here. - # Maybe a signal that we should separate models from views? blockDecoration1 = editor.addBlockDecorationForScreenRow(0, null) blockDecoration2 = editor.addBlockDecorationForScreenRow(3, null) blockDecoration3 = editor.addBlockDecorationForScreenRow(7, null) @@ -3041,8 +3040,8 @@ describe "TextEditorPresenter", -> presenter.setBlockDecorationDimensions(blockDecoration3, 0, 7) decorationState = getContentForGutterWithName(presenter, 'test-gutter') - expect(decorationState[decoration1.id].top).toBe lineHeight * marker1.getScreenRange().start.row - expect(decorationState[decoration1.id].height).toBe lineHeight * marker1.getScreenRange().getRowCount() + 3 + expect(decorationState[decoration1.id].top).toBe lineHeight * marker1.getScreenRange().start.row + 3 + expect(decorationState[decoration1.id].height).toBe lineHeight * marker1.getScreenRange().getRowCount() expect(decorationState[decoration1.id].item).toBe decorationItem expect(decorationState[decoration1.id].class).toBe 'test-class' expect(decorationState[decoration2.id].top).toBe lineHeight * marker2.getScreenRange().start.row + 3 + 5 @@ -3286,8 +3285,6 @@ describe "TextEditorPresenter", -> presenter = buildPresenter(scrollTop: 0, lineHeight: 10) expect(presenter.getState().verticalScrollbar.scrollHeight).toBe editor.getScreenLineCount() * 10 - # Setting `null` as the DOM element, as it doesn't really matter here. - # Maybe a signal that we should separate models from views? blockDecoration1 = editor.addBlockDecorationForScreenRow(0, null) blockDecoration2 = editor.addBlockDecorationForScreenRow(3, null) blockDecoration3 = editor.addBlockDecorationForScreenRow(7, null) diff --git a/src/block-decorations-presenter.js b/src/block-decorations-presenter.js index bfe08dd63..7f7258226 100644 --- a/src/block-decorations-presenter.js +++ b/src/block-decorations-presenter.js @@ -31,9 +31,6 @@ class BlockDecorationsPresenter { } observeModel () { - this.lineTopIndex.setMaxRow(this.model.getScreenLineCount()) - this.lineTopIndex.setDefaultLineHeight(this.model.getLineHeightInPixels()) - this.disposables.add(this.model.onDidAddDecoration(this.observeDecoration.bind(this))) this.disposables.add(this.model.onDidChange((changeEvent) => { let oldExtent = changeEvent.end - changeEvent.start @@ -54,11 +51,10 @@ class BlockDecorationsPresenter { setDimensionsForDecoration (decoration, width, height) { let block = this.blocksByDecoration.get(decoration) if (block) { - this.lineTopIndex.resizeBlock(block, height) + this.lineTopIndex.resizeBlock(decoration.getMarker().id, height) } else { this.observeDecoration(decoration) - block = this.blocksByDecoration.get(decoration) - this.lineTopIndex.resizeBlock(block, height) + this.lineTopIndex.resizeBlock(decoration.getMarker().id, height) } this.measuredDecorations.add(decoration) @@ -124,9 +120,9 @@ class BlockDecorationsPresenter { didAddDecoration (decoration) { let screenRow = decoration.getMarker().getHeadScreenPosition().row - let block = this.lineTopIndex.insertBlock(screenRow, 0) - this.decorationsByBlock.set(block, decoration) - this.blocksByDecoration.set(decoration, block) + this.lineTopIndex.insertBlock(decoration.getMarker().id, screenRow, 0) + this.decorationsByBlock.set(decoration.getMarker().id, decoration) + this.blocksByDecoration.set(decoration, decoration.getMarker().id) this.emitter.emit('did-update-state') } @@ -136,16 +132,15 @@ class BlockDecorationsPresenter { return } - let block = this.blocksByDecoration.get(decoration) let newScreenRow = decoration.getMarker().getHeadScreenPosition().row - this.lineTopIndex.moveBlock(block, newScreenRow) + this.lineTopIndex.moveBlock(decoration.getMarker().id, newScreenRow) this.emitter.emit('did-update-state') } didDestroyDecoration (decoration) { let block = this.blocksByDecoration.get(decoration) if (block) { - this.lineTopIndex.removeBlock(block) + this.lineTopIndex.removeBlock(decoration.getMarker().id) this.blocksByDecoration.delete(decoration) this.decorationsByBlock.delete(block) } diff --git a/src/linear-line-top-index.js b/src/linear-line-top-index.js index 3fe501ec9..aad947dd8 100644 --- a/src/linear-line-top-index.js +++ b/src/linear-line-top-index.js @@ -1,27 +1,23 @@ -'use strict' +"use babel" -module.exports = -class LineTopIndex { - constructor () { - this.idCounter = 1 +export default class LineTopIndex { + constructor (params = {}) { this.blocks = [] - this.maxRow = 0 - this.defaultLineHeight = 0 + this.maxRow = params.maxRow || 0 + this.setDefaultLineHeight(params.defaultLineHeight || 0) } setDefaultLineHeight (lineHeight) { this.defaultLineHeight = lineHeight } - setMaxRow (maxRow) { - this.maxRow = maxRow + getMaxRow () { + return this.maxRow } - insertBlock (row, height) { - let id = this.idCounter++ + insertBlock (id, row, height) { this.blocks.push({id, row, height}) this.blocks.sort((a, b) => a.row - b.row) - return id } resizeBlock (id, height) { @@ -62,26 +58,21 @@ class LineTopIndex { block.row += newExtent - oldExtent } else { block.row = startRow + newExtent - // invalidate marker? } } }) - this.setMaxRow(this.maxRow + newExtent - oldExtent) + this.maxRow = this.maxRow + newExtent - oldExtent } - topPixelPositionForRow (row) { + pixelPositionForRow (row) { row = Math.min(row, this.maxRow) let linesHeight = row * this.defaultLineHeight - let blocksHeight = this.blocks.filter((block) => block.row < row).reduce((a, b) => a + b.height, 0) + let blocksHeight = this.blocks.filter((block) => block.row <= row).reduce((a, b) => a + b.height, 0) return linesHeight + blocksHeight } - bottomPixelPositionForRow (row) { - return this.topPixelPositionForRow(row + 1) - this.defaultLineHeight - } - - rowForTopPixelPosition (top, strategy) { + rowForPixelPosition (top, strategy) { const roundingStrategy = strategy || 'floor' let blocksHeight = 0 let lastRow = 0 diff --git a/src/lines-yardstick.coffee b/src/lines-yardstick.coffee index 847ebfd46..e6454989a 100644 --- a/src/lines-yardstick.coffee +++ b/src/lines-yardstick.coffee @@ -22,7 +22,7 @@ class LinesYardstick targetTop = pixelPosition.top targetLeft = pixelPosition.left defaultCharWidth = @model.getDefaultCharWidth() - row = @lineTopIndex.rowForTopPixelPosition(targetTop, 'floor') + row = @lineTopIndex.rowForPixelPosition(targetTop, 'floor') targetLeft = 0 if targetTop < 0 targetLeft = Infinity if row > @model.getLastScreenRow() row = Math.min(row, @model.getLastScreenRow()) @@ -91,7 +91,7 @@ class LinesYardstick @prepareScreenRowsForMeasurement([targetRow]) unless measureVisibleLinesOnly - top = @lineTopIndex.bottomPixelPositionForRow(targetRow) + top = @lineTopIndex.pixelPositionForRow(targetRow) left = @leftPixelPositionForScreenPosition(targetRow, targetColumn) @clearScreenRowsForMeasurement() unless measureVisibleLinesOnly @@ -174,14 +174,14 @@ class LinesYardstick left + width - offset pixelRectForScreenRange: (screenRange, measureVisibleLinesOnly) -> + top = @lineTopIndex.pixelPositionForRow(screenRange.start.row) if screenRange.end.row > screenRange.start.row - top = @pixelPositionForScreenPosition(screenRange.start, true, measureVisibleLinesOnly).top left = 0 - height = @lineTopIndex.topPixelPositionForRow(screenRange.end.row + 1) - top + height = @lineTopIndex.pixelPositionForRow(screenRange.end.row) - top + @model.getLineHeightInPixels() width = @presenter.getScrollWidth() else - {top, left} = @pixelPositionForScreenPosition(screenRange.start, false, measureVisibleLinesOnly) - height = @lineTopIndex.topPixelPositionForRow(screenRange.end.row + 1) - top + {left} = @pixelPositionForScreenPosition(screenRange.start, false, measureVisibleLinesOnly) + height = @lineTopIndex.pixelPositionForRow(screenRange.end.row) - top + @model.getLineHeightInPixels() width = @pixelPositionForScreenPosition(screenRange.end, false, measureVisibleLinesOnly).left - left {top, left, width, height} diff --git a/src/text-editor-component.coffee b/src/text-editor-component.coffee index c35139d7c..3e644a084 100644 --- a/src/text-editor-component.coffee +++ b/src/text-editor-component.coffee @@ -50,7 +50,10 @@ class TextEditorComponent @observeConfig() @setScrollSensitivity(@config.get('editor.scrollSensitivity')) - lineTopIndex = new LineTopIndex(@editor) + lineTopIndex = new LineTopIndex({ + maxRow: @editor.getScreenLineCount(), + defaultLineHeight: @editor.getLineHeightInPixels() + }) @presenter = new TextEditorPresenter model: @editor tileSize: tileSize diff --git a/src/text-editor-presenter.coffee b/src/text-editor-presenter.coffee index 5b1f01b35..ca05ea36a 100644 --- a/src/text-editor-presenter.coffee +++ b/src/text-editor-presenter.coffee @@ -442,8 +442,8 @@ class TextEditorPresenter continue if rowsWithinTile.length is 0 - top = Math.round(@lineTopIndex.topPixelPositionForRow(tileStartRow)) - bottom = Math.round(@lineTopIndex.topPixelPositionForRow(tileEndRow)) + top = Math.round(@lineTopIndex.pixelPositionForRow(tileStartRow - 1) + @lineHeight) + bottom = Math.round(@lineTopIndex.pixelPositionForRow(tileEndRow - 1) + @lineHeight) height = bottom - top tile = @state.content.tiles[tileStartRow] ?= {} @@ -659,8 +659,8 @@ class TextEditorPresenter continue unless @gutterIsVisible(gutter) for decorationId, {properties, screenRange} of @customGutterDecorationsByGutterName[gutterName] - top = @lineTopIndex.topPixelPositionForRow(screenRange.start.row) - bottom = @lineTopIndex.topPixelPositionForRow(screenRange.end.row + 1) + top = @lineTopIndex.pixelPositionForRow(screenRange.start.row) + bottom = @lineTopIndex.pixelPositionForRow(screenRange.end.row) + @lineHeight @customGutterDecorations[gutterName][decorationId] = top: top height: bottom - top @@ -724,12 +724,12 @@ class TextEditorPresenter updateStartRow: -> return unless @scrollTop? and @lineHeight? - @startRow = Math.max(0, @lineTopIndex.rowForTopPixelPosition(@scrollTop, "floor")) + @startRow = Math.max(0, @lineTopIndex.rowForPixelPosition(@scrollTop, "floor")) updateEndRow: -> return unless @scrollTop? and @lineHeight? and @height? - @endRow = @lineTopIndex.rowForTopPixelPosition(@scrollTop + @height + @lineHeight, 'ceil') + @endRow = @lineTopIndex.rowForPixelPosition(@scrollTop + @height + @lineHeight, 'ceil') updateRowsPerPage: -> rowsPerPage = Math.floor(@getClientHeight() / @lineHeight) @@ -761,7 +761,7 @@ class TextEditorPresenter updateVerticalDimensions: -> if @lineHeight? oldContentHeight = @contentHeight - @contentHeight = Math.round(@lineTopIndex.topPixelPositionForRow(Infinity)) + @contentHeight = Math.round(@lineTopIndex.pixelPositionForRow(Infinity)) if @contentHeight isnt oldContentHeight @updateHeight() @@ -1340,7 +1340,7 @@ class TextEditorPresenter screenRange.end.column = 0 repositionRegionWithinTile: (region, tileStartRow) -> - region.top += @scrollTop - @lineTopIndex.topPixelPositionForRow(tileStartRow) + region.top += @scrollTop - (@lineTopIndex.pixelPositionForRow(tileStartRow - 1) + @lineHeight) region.left += @scrollLeft buildHighlightRegions: (screenRange) -> @@ -1495,7 +1495,7 @@ class TextEditorPresenter @emitDidUpdateState() didChangeFirstVisibleScreenRow: (screenRow) -> - @updateScrollTop(@lineTopIndex.topPixelPositionForRow(screenRow)) + @updateScrollTop(@lineTopIndex.pixelPositionForRow(screenRow)) getVerticalScrollMarginInPixels: -> Math.round(@model.getVerticalScrollMargin() * @lineHeight) @@ -1516,8 +1516,8 @@ class TextEditorPresenter verticalScrollMarginInPixels = @getVerticalScrollMarginInPixels() - top = @lineTopIndex.bottomPixelPositionForRow(screenRange.start.row) - bottom = @lineTopIndex.bottomPixelPositionForRow(screenRange.end.row + 1) + top = @lineTopIndex.pixelPositionForRow(screenRange.start.row) + bottom = @lineTopIndex.pixelPositionForRow(screenRange.end.row) + @lineHeight if options?.center desiredScrollCenter = (top + bottom) / 2 @@ -1589,7 +1589,7 @@ class TextEditorPresenter restoreScrollTopIfNeeded: -> unless @scrollTop? - @updateScrollTop(@lineTopIndex.topPixelPositionForRow(@model.getFirstVisibleScreenRow())) + @updateScrollTop(@lineTopIndex.pixelPositionForRow(@model.getFirstVisibleScreenRow())) restoreScrollLeftIfNeeded: -> unless @scrollLeft?