diff --git a/spec/fake-lines-yardstick.coffee b/spec/fake-lines-yardstick.coffee index 1872b8c65..781318f8c 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 = targetRow * @model.getLineHeightInPixels() + top = @topPixelPositionForRow(targetRow) left = 0 column = 0 @@ -60,17 +60,37 @@ class FakeLinesYardstick {top, left} - pixelRectForScreenRange: (screenRange) -> - lineHeight = @model.getLineHeightInPixels() + rowForTopPixelPosition: (position, floor = true) -> + top = 0 + for tileStartRow in [0..@model.getScreenLineCount()] by @presenter.getTileSize() + tileEndRow = Math.min(tileStartRow + @presenter.getTileSize(), @model.getScreenLineCount()) + for row in [tileStartRow...tileEndRow] by 1 + nextTop = top + @presenter.getScreenRowHeight(row) + if floor + return row if nextTop > position + else + return row if top >= position + top = nextTop + @model.getScreenLineCount() + topPixelPositionForRow: (targetRow) -> + top = 0 + for tileStartRow in [0..@model.getScreenLineCount()] by @presenter.getTileSize() + tileEndRow = Math.min(tileStartRow + @presenter.getTileSize(), @model.getScreenLineCount()) + for row in [tileStartRow...tileEndRow] by 1 + return top if row is targetRow + top += @presenter.getScreenRowHeight(row) + top + + pixelRectForScreenRange: (screenRange) -> if screenRange.end.row > screenRange.start.row top = @pixelPositionForScreenPosition(screenRange.start).top left = 0 - height = (screenRange.end.row - screenRange.start.row + 1) * lineHeight + height = @topPixelPositionForRow(screenRange.end.row + 1) - top width = @presenter.getScrollWidth() else {top, left} = @pixelPositionForScreenPosition(screenRange.start, false) - height = lineHeight + height = @topPixelPositionForRow(screenRange.end.row + 1) - top width = @pixelPositionForScreenPosition(screenRange.end, false).left - left {top, left, width, height} diff --git a/src/lines-yardstick.coffee b/src/lines-yardstick.coffee index 54ba6cf57..2febf8add 100644 --- a/src/lines-yardstick.coffee +++ b/src/lines-yardstick.coffee @@ -22,11 +22,9 @@ class LinesYardstick targetTop = pixelPosition.top targetLeft = pixelPosition.left defaultCharWidth = @model.getDefaultCharWidth() - row = Math.floor(targetTop / @model.getLineHeightInPixels()) - targetLeft = 0 if row < 0 + row = @rowForTopPixelPosition(targetTop) + targetLeft = 0 if targetTop < 0 targetLeft = Infinity if row > @model.getLastScreenRow() - row = Math.min(row, @model.getLastScreenRow()) - row = Math.max(0, row) @prepareScreenRowsForMeasurement([row]) unless measureVisibleLinesOnly @@ -92,7 +90,7 @@ class LinesYardstick @prepareScreenRowsForMeasurement([targetRow]) unless measureVisibleLinesOnly - top = targetRow * @model.getLineHeightInPixels() + top = @topPixelPositionForRow(targetRow) left = @leftPixelPositionForScreenPosition(targetRow, targetColumn) @clearScreenRowsForMeasurement() unless measureVisibleLinesOnly @@ -174,17 +172,37 @@ class LinesYardstick left + width - offset - pixelRectForScreenRange: (screenRange, measureVisibleLinesOnly) -> - lineHeight = @model.getLineHeightInPixels() + rowForTopPixelPosition: (position, floor = true) -> + top = 0 + for tileStartRow in [0..@model.getScreenLineCount()] by @presenter.getTileSize() + tileEndRow = Math.min(tileStartRow + @presenter.getTileSize(), @model.getScreenLineCount()) + for row in [tileStartRow...tileEndRow] by 1 + nextTop = top + @presenter.getScreenRowHeight(row) + if floor + return row if nextTop > position + else + return row if top >= position + top = nextTop + @model.getScreenLineCount() + topPixelPositionForRow: (targetRow) -> + top = 0 + for tileStartRow in [0..@model.getScreenLineCount()] by @presenter.getTileSize() + tileEndRow = Math.min(tileStartRow + @presenter.getTileSize(), @model.getScreenLineCount()) + for row in [tileStartRow...tileEndRow] by 1 + return top if row is targetRow + top += @presenter.getScreenRowHeight(row) + top + + pixelRectForScreenRange: (screenRange, measureVisibleLinesOnly) -> if screenRange.end.row > screenRange.start.row top = @pixelPositionForScreenPosition(screenRange.start, true, measureVisibleLinesOnly).top left = 0 - height = (screenRange.end.row - screenRange.start.row + 1) * lineHeight + height = @topPixelPositionForRow(screenRange.end.row + 1) - top width = @presenter.getScrollWidth() else {top, left} = @pixelPositionForScreenPosition(screenRange.start, false, measureVisibleLinesOnly) - height = lineHeight + height = @topPixelPositionForRow(screenRange.end.row + 1) - top width = @pixelPositionForScreenPosition(screenRange.end, false, measureVisibleLinesOnly).left - left {top, left, width, height} diff --git a/src/text-editor-presenter.coffee b/src/text-editor-presenter.coffee index 4fd612ec5..041a117e1 100644 --- a/src/text-editor-presenter.coffee +++ b/src/text-editor-presenter.coffee @@ -374,6 +374,9 @@ class TextEditorPresenter getEndTileRow: -> @constrainRow(@tileForRow(@endRow)) + getTileSize: -> + @tileSize + isValidScreenRow: (screenRow) -> screenRow >= 0 and screenRow < @model.getScreenLineCount() @@ -424,8 +427,8 @@ class TextEditorPresenter continue if rowsWithinTile.length is 0 - top = @positionForRow(tileStartRow) - height = @positionForRow(tileStartRow + @tileSize) - top + top = @linesYardstick.topPixelPositionForRow(tileStartRow) + height = @linesYardstick.topPixelPositionForRow(tileStartRow + @tileSize) - top tile = @state.content.tiles[tileStartRow] ?= {} tile.top = top - @scrollTop @@ -697,38 +700,15 @@ class TextEditorPresenter getScreenRowHeight: (screenRow) -> @heightsByScreenRow[screenRow] or @lineHeight - setScreenRowHeight: (screenRow, height) -> - @heightsByScreenRow[screenRow] = height - - rowForPosition: (position, floor = true) -> - top = 0 - for tileRow in [0..@model.getScreenLineCount()] by @tileSize - for row in [tileRow...Math.min(tileRow + @tileSize, @model.getScreenLineCount())] by 1 - nextTop = top + @getScreenRowHeight(row) - if floor - return row if nextTop > position - else - return row if top >= position - top = nextTop - @model.getScreenLineCount() - - positionForRow: (targetRow) -> - top = 0 - for tileRow in [0..@model.getScreenLineCount()] by @tileSize - for row in [tileRow...Math.min(tileRow + @tileSize, @model.getScreenLineCount())] by 1 - return top if row is targetRow - top += @getScreenRowHeight(row) - top - updateStartRow: -> return unless @scrollTop? and @lineHeight? - @startRow = Math.max(0, @rowForPosition(@scrollTop)) + @startRow = Math.max(0, @linesYardstick.rowForTopPixelPosition(@scrollTop)) updateEndRow: -> return unless @scrollTop? and @lineHeight? and @height? - @endRow = @rowForPosition(@scrollTop + @height + @lineHeight, false) + @endRow = @linesYardstick.rowForTopPixelPosition(@scrollTop + @height + @lineHeight, false) updateRowsPerPage: -> rowsPerPage = Math.floor(@getClientHeight() / @lineHeight)