Merge branch 'master' into as-cjk-wrap-boundary

This commit is contained in:
Antonio Scandurra
2015-12-11 13:49:53 +01:00
7 changed files with 326 additions and 363 deletions

View File

@@ -64,10 +64,10 @@
"atom-light-ui": "0.43.0",
"base16-tomorrow-dark-theme": "1.0.0",
"base16-tomorrow-light-theme": "1.0.0",
"one-dark-ui": "1.1.8",
"one-dark-ui": "1.1.9",
"one-dark-syntax": "1.1.1",
"one-light-syntax": "1.1.1",
"one-light-ui": "1.1.8",
"one-light-ui": "1.1.9",
"solarized-dark-syntax": "0.39.0",
"solarized-light-syntax": "0.23.0",
"about": "1.1.0",
@@ -123,7 +123,7 @@
"language-css": "0.36.0",
"language-gfm": "0.82.0",
"language-git": "0.11.0",
"language-go": "0.40.0",
"language-go": "0.41.0",
"language-html": "0.43.1",
"language-hyperlink": "0.16.0",
"language-java": "0.17.0",

View File

@@ -2,13 +2,9 @@
module.exports =
class FakeLinesYardstick
constructor: (@model, @presenter) ->
constructor: (@model) ->
@characterWidthsByScope = {}
prepareScreenRowsForMeasurement: ->
@presenter.getPreMeasurementState()
@screenRows = new Set(@presenter.getScreenRows())
getScopedCharacterWidth: (scopeNames, char) ->
@getScopedCharacterWidths(scopeNames)[char]
@@ -35,8 +31,6 @@ class FakeLinesYardstick
left = 0
column = 0
return {top, left: 0} unless @screenRows.has(screenPosition.row)
iterator = @model.tokenizedLineForScreenRow(targetRow).getTokenIterator()
while iterator.next()
characterWidths = @getScopedCharacterWidths(iterator.getScopes())
@@ -59,18 +53,3 @@ class FakeLinesYardstick
column += charLength
{top, left}
pixelRectForScreenRange: (screenRange) ->
lineHeight = @model.getLineHeightInPixels()
if screenRange.end.row > screenRange.start.row
top = @pixelPositionForScreenPosition(screenRange.start).top
left = 0
height = (screenRange.end.row - screenRange.start.row + 1) * lineHeight
width = @presenter.getScrollWidth()
else
{top, left} = @pixelPositionForScreenPosition(screenRange.start, false)
height = lineHeight
width = @pixelPositionForScreenPosition(screenRange.end, false).left - left
{top, left, width, height}

View File

@@ -2,7 +2,7 @@ LinesYardstick = require "../src/lines-yardstick"
{toArray} = require 'underscore-plus'
describe "LinesYardstick", ->
[editor, mockPresenter, mockLineNodesProvider, createdLineNodes, linesYardstick, buildLineNode] = []
[editor, mockLineNodesProvider, createdLineNodes, linesYardstick, buildLineNode] = []
beforeEach ->
waitsForPromise ->
@@ -31,22 +31,10 @@ describe "LinesYardstick", ->
createdLineNodes.push(lineNode)
lineNode
mockPresenter =
setScreenRowsToMeasure: (screenRows) -> screenRowsToMeasure = screenRows
clearScreenRowsToMeasure: -> setScreenRowsToMeasure = []
getPreMeasurementState: ->
state = {}
for screenRow in screenRowsToMeasure
tokenizedLine = editor.tokenizedLineForScreenRow(screenRow)
state[tokenizedLine.id] = screenRow
state
mockLineNodesProvider =
updateSync: (state) -> availableScreenRows = state
lineNodeForLineIdAndScreenRow: (lineId, screenRow) ->
return if availableScreenRows[lineId] isnt screenRow
buildLineNode(screenRow)
textNodesForLineIdAndScreenRow: (lineId, screenRow) ->
lineNode = @lineNodeForLineIdAndScreenRow(lineId, screenRow)
iterator = document.createNodeIterator(lineNode, NodeFilter.SHOW_TEXT)
@@ -56,7 +44,7 @@ describe "LinesYardstick", ->
textNodes
editor.setLineHeightInPixels(14)
linesYardstick = new LinesYardstick(editor, mockPresenter, mockLineNodesProvider, atom.grammars)
linesYardstick = new LinesYardstick(editor, mockLineNodesProvider, atom.grammars)
afterEach ->
lineNode.remove() for lineNode in createdLineNodes
@@ -153,18 +141,6 @@ describe "LinesYardstick", ->
expect(linesYardstick.pixelPositionForScreenPosition([0, 36]).left).toBe 237.5
expect(linesYardstick.pixelPositionForScreenPosition([0, 37]).left).toBe 244.09375
it "doesn't measure invisible lines if it is explicitly told so", ->
atom.styles.addStyleSheet """
* {
font-size: 12px;
font-family: monospace;
}
"""
expect(linesYardstick.pixelPositionForScreenPosition([0, 0], true, true)).toEqual({left: 0, top: 0})
expect(linesYardstick.pixelPositionForScreenPosition([0, 1], true, true)).toEqual({left: 0, top: 0})
expect(linesYardstick.pixelPositionForScreenPosition([0, 5], true, true)).toEqual({left: 0, top: 0})
describe "::screenPositionForPixelPosition(pixelPosition)", ->
it "converts pixel positions to screen positions", ->
atom.styles.addStyleSheet """
@@ -197,15 +173,3 @@ describe "LinesYardstick", ->
expect(linesYardstick.screenPositionForPixelPosition(top: Infinity, left: Infinity)).toEqual [12, 2]
expect(linesYardstick.screenPositionForPixelPosition(top: (editor.getLastScreenRow() + 1) * 14, left: 0)).toEqual [12, 2]
expect(linesYardstick.screenPositionForPixelPosition(top: editor.getLastScreenRow() * 14, left: 0)).toEqual [12, 0]
it "doesn't measure invisible lines if it is explicitly told so", ->
atom.styles.addStyleSheet """
* {
font-size: 12px;
font-family: monospace;
}
"""
expect(linesYardstick.screenPositionForPixelPosition({top: 0, left: 13}, true)).toEqual([0, 0])
expect(linesYardstick.screenPositionForPixelPosition({top: 14, left: 20}, true)).toEqual([1, 0])
expect(linesYardstick.screenPositionForPixelPosition({top: 28, left: 100}, true)).toEqual([2, 0])

File diff suppressed because it is too large Load Diff

View File

@@ -3,7 +3,7 @@ TokenIterator = require './token-iterator'
module.exports =
class LinesYardstick
constructor: (@model, @presenter, @lineNodesProvider, grammarRegistry) ->
constructor: (@model, @lineNodesProvider, grammarRegistry) ->
@tokenIterator = new TokenIterator({grammarRegistry})
@rangeForMeasurement = document.createRange()
@invalidateCache()
@@ -11,14 +11,12 @@ class LinesYardstick
invalidateCache: ->
@pixelPositionsByLineIdAndColumn = {}
prepareScreenRowsForMeasurement: (screenRows) ->
@presenter.setScreenRowsToMeasure(screenRows)
@lineNodesProvider.updateSync(@presenter.getPreMeasurementState())
measuredRowForPixelPosition: (pixelPosition) ->
targetTop = pixelPosition.top
row = Math.floor(targetTop / @model.getLineHeightInPixels())
row if 0 <= row <= @model.getLastScreenRow()
clearScreenRowsForMeasurement: ->
@presenter.clearScreenRowsToMeasure()
screenPositionForPixelPosition: (pixelPosition, measureVisibleLinesOnly) ->
screenPositionForPixelPosition: (pixelPosition) ->
targetTop = pixelPosition.top
targetLeft = pixelPosition.left
defaultCharWidth = @model.getDefaultCharWidth()
@@ -28,12 +26,10 @@ class LinesYardstick
row = Math.min(row, @model.getLastScreenRow())
row = Math.max(0, row)
@prepareScreenRowsForMeasurement([row]) unless measureVisibleLinesOnly
line = @model.tokenizedLineForScreenRow(row)
lineNode = @lineNodesProvider.lineNodeForLineIdAndScreenRow(line?.id, row)
return new Point(row, 0) unless lineNode? and line?
return Point(row, 0) unless lineNode? and line?
textNodes = @lineNodesProvider.textNodesForLineIdAndScreenRow(line.id, row)
column = 0
@@ -70,33 +66,27 @@ class LinesYardstick
left = @leftPixelPositionForCharInTextNode(lineNode, textNode, indexWithinTextNode)
charWidth = left - previousLeft
return new Point(row, previousColumn) if targetLeft <= previousLeft + (charWidth / 2)
return Point(row, previousColumn) if targetLeft <= previousLeft + (charWidth / 2)
previousLeft = left
previousColumn = column
column += charLength
@clearScreenRowsForMeasurement() unless measureVisibleLinesOnly
if targetLeft <= previousLeft + (charWidth / 2)
new Point(row, previousColumn)
Point(row, previousColumn)
else
new Point(row, column)
Point(row, column)
pixelPositionForScreenPosition: (screenPosition, clip=true, measureVisibleLinesOnly) ->
pixelPositionForScreenPosition: (screenPosition, clip=true) ->
screenPosition = Point.fromObject(screenPosition)
screenPosition = @model.clipScreenPosition(screenPosition) if clip
targetRow = screenPosition.row
targetColumn = screenPosition.column
@prepareScreenRowsForMeasurement([targetRow]) unless measureVisibleLinesOnly
top = targetRow * @model.getLineHeightInPixels()
left = @leftPixelPositionForScreenPosition(targetRow, targetColumn)
@clearScreenRowsForMeasurement() unless measureVisibleLinesOnly
{top, left}
leftPixelPositionForScreenPosition: (row, column) ->
@@ -173,18 +163,3 @@ class LinesYardstick
offset = lineNode.getBoundingClientRect().left
left + width - offset
pixelRectForScreenRange: (screenRange, measureVisibleLinesOnly) ->
lineHeight = @model.getLineHeightInPixels()
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
width = @presenter.getScrollWidth()
else
{top, left} = @pixelPositionForScreenPosition(screenRange.start, false, measureVisibleLinesOnly)
height = lineHeight
width = @pixelPositionForScreenPosition(screenRange.end, false, measureVisibleLinesOnly).left - left
{top, left, width, height}

View File

@@ -82,7 +82,7 @@ class TextEditorComponent
@linesComponent = new LinesComponent({@presenter, @hostElement, @useShadowDOM, @domElementPool, @assert, @grammars})
@scrollViewNode.appendChild(@linesComponent.getDomNode())
@linesYardstick = new LinesYardstick(@editor, @presenter, @linesComponent, @grammars)
@linesYardstick = new LinesYardstick(@editor, @linesComponent, @grammars)
@presenter.setLinesYardstick(@linesYardstick)
@horizontalScrollbarComponent = new ScrollbarComponent({orientation: 'horizontal', onScroll: @onHorizontalScroll})
@@ -127,8 +127,10 @@ class TextEditorComponent
@domNode
updateSync: ->
@updateSyncPreMeasurement()
@oldState ?= {}
@newState = @presenter.getState()
@newState = @presenter.getPostMeasurementState()
if @editor.getLastSelection()? and not @editor.getLastSelection().isEmpty()
@domNode.classList.add('has-selection')
@@ -170,6 +172,9 @@ class TextEditorComponent
@updateParentViewFocusedClassIfNeeded()
@updateParentViewMiniClass()
updateSyncPreMeasurement: ->
@linesComponent.updateSync(@presenter.getPreMeasurementState())
readAfterUpdateSync: =>
@overlayManager?.measureOverlays()
@@ -429,14 +434,42 @@ class TextEditorComponent
getVisibleRowRange: ->
@presenter.getVisibleRowRange()
pixelPositionForScreenPosition: ->
@linesYardstick.pixelPositionForScreenPosition(arguments...)
pixelPositionForScreenPosition: (screenPosition, clip) ->
unless @presenter.isRowVisible(screenPosition.row)
@presenter.setScreenRowsToMeasure([screenPosition.row])
@updateSyncPreMeasurement()
screenPositionForPixelPosition: ->
@linesYardstick.screenPositionForPixelPosition(arguments...)
pixelPosition = @linesYardstick.pixelPositionForScreenPosition(screenPosition, clip)
@presenter.clearScreenRowsToMeasure()
pixelPosition
pixelRectForScreenRange: ->
@linesYardstick.pixelRectForScreenRange(arguments...)
screenPositionForPixelPosition: (pixelPosition) ->
row = @linesYardstick.measuredRowForPixelPosition(pixelPosition)
if row? and not @presenter.isRowVisible(row)
@presenter.setScreenRowsToMeasure([row])
@updateSyncPreMeasurement()
position = @linesYardstick.screenPositionForPixelPosition(pixelPosition)
@presenter.clearScreenRowsToMeasure()
position
pixelRectForScreenRange: (screenRange) ->
rowsToMeasure = []
unless @presenter.isRowVisible(screenRange.start.row)
rowsToMeasure.push(screenRange.start.row)
unless @presenter.isRowVisible(screenRange.end.row)
rowsToMeasure.push(screenRange.end.row)
if rowsToMeasure.length > 0
@presenter.setScreenRowsToMeasure(rowsToMeasure)
@updateSyncPreMeasurement()
rect = @presenter.absolutePixelRectForScreenRange(screenRange)
if rowsToMeasure.length > 0
@presenter.clearScreenRowsToMeasure()
rect
pixelRangeForScreenRange: (screenRange, clip=true) ->
{start, end} = Range.fromObject(screenRange)

View File

@@ -121,14 +121,6 @@ class TextEditorPresenter
@updating = false
@resetTrackedUpdates()
# Public: Gets this presenter's state, updating it just in time before returning from this function.
# Returns a state {Object}, useful for rendering to screen.
getState: ->
@linesYardstick.prepareScreenRowsForMeasurement()
@getPostMeasurementState()
@state
resetTrackedUpdates: ->
@@ -1155,16 +1147,29 @@ class TextEditorPresenter
hasOverlayPositionRequirements: ->
@hasPixelRectRequirements() and @boundingClientRect? and @windowWidth and @windowHeight
absolutePixelRectForScreenRange: (screenRange) ->
lineHeight = @model.getLineHeightInPixels()
if screenRange.end.row > screenRange.start.row
top = @linesYardstick.pixelPositionForScreenPosition(screenRange.start, true).top
left = 0
height = (screenRange.end.row - screenRange.start.row + 1) * lineHeight
width = @getScrollWidth()
else
{top, left} = @linesYardstick.pixelPositionForScreenPosition(screenRange.start, false)
height = lineHeight
width = @linesYardstick.pixelPositionForScreenPosition(screenRange.end, false).left - left
{top, left, width, height}
pixelRectForScreenRange: (screenRange) ->
rect = @linesYardstick.pixelRectForScreenRange(screenRange, true)
rect = @absolutePixelRectForScreenRange(screenRange)
rect.top -= @getScrollTop()
rect.left -= @getScrollLeft()
rect.top = Math.round(rect.top)
rect.left = Math.round(rect.left)
rect.width = Math.round(rect.width)
rect.height = Math.round(rect.height)
rect
fetchDecorations: ->
@@ -1550,3 +1555,6 @@ class TextEditorPresenter
getVisibleRowRange: ->
[@startRow, @endRow]
isRowVisible: (row) ->
@startRow <= row < @endRow