diff --git a/src/highlights-component.coffee b/src/highlights-component.coffee index 5a5747d4c..eb64b9bc4 100644 --- a/src/highlights-component.coffee +++ b/src/highlights-component.coffee @@ -21,7 +21,7 @@ class HighlightsComponent @domNode updateSync: (state) -> - newState = state.content.highlights + newState = state.highlights @oldState ?= {} # remove highlights diff --git a/src/lines-component.coffee b/src/lines-component.coffee index 23f1c0015..bac1c9616 100644 --- a/src/lines-component.coffee +++ b/src/lines-component.coffee @@ -1,7 +1,6 @@ {$$} = require 'space-pen' CursorsComponent = require './cursors-component' -HighlightsComponent = require './highlights-component' TileComponent = require './tile-component' DummyLineNode = $$(-> @div className: 'line', style: 'position: absolute; visibility: hidden;', => @span 'x')[0] @@ -24,9 +23,6 @@ class LinesComponent @cursorsComponent = new CursorsComponent(@presenter) @domNode.appendChild(@cursorsComponent.getDomNode()) - @highlightsComponent = new HighlightsComponent(@presenter) - @domNode.appendChild(@highlightsComponent.getDomNode()) - if @useShadowDOM insertionPoint = document.createElement('content') insertionPoint.setAttribute('select', '.overlayer') @@ -63,7 +59,6 @@ class LinesComponent @oldState.scrollWidth = @newState.scrollWidth @cursorsComponent.updateSync(state) - @highlightsComponent.updateSync(state) @oldState.indentGuidesVisible = @newState.indentGuidesVisible @oldState.scrollWidth = @newState.scrollWidth diff --git a/src/text-editor-presenter.coffee b/src/text-editor-presenter.coffee index 03cfd5a21..5d447edaa 100644 --- a/src/text-editor-presenter.coffee +++ b/src/text-editor-presenter.coffee @@ -335,6 +335,7 @@ class TextEditorPresenter tile.left = -@scrollLeft tile.height = @tileSize * @lineHeight tile.display = "block" + tile.highlights ?= {} @updateLinesState(tile, startRow, endRow) @@ -1041,7 +1042,7 @@ class TextEditorPresenter hasPixelPositionRequirements: -> @lineHeight? and @baseCharacterWidth? - pixelPositionForScreenPosition: (screenPosition, clip=true) -> + pixelPositionForScreenPosition: (screenPosition, clip=true, foo) -> screenPosition = Point.fromObject(screenPosition) screenPosition = @model.clipScreenPosition(screenPosition) if clip @@ -1050,6 +1051,7 @@ class TextEditorPresenter baseCharacterWidth = @baseCharacterWidth top = targetRow * @lineHeight + top -= foo * @lineHeight if foo? left = 0 column = 0 @@ -1074,8 +1076,8 @@ class TextEditorPresenter left += characterWidths[char] ? baseCharacterWidth unless char is '\0' column += charLength - top -= @scrollTop - left -= @scrollLeft + top -= @scrollTop unless foo? + left -= @scrollLeft unless foo? {top, left} hasPixelRectRequirements: -> @@ -1175,9 +1177,10 @@ class TextEditorPresenter else if decoration.isType('highlight') visibleHighlights[decoration.id] = @updateHighlightState(decoration) - for id of @state.content.highlights - unless visibleHighlights[id] - delete @state.content.highlights[id] + for tileId, tileState of @state.content.tiles + for id, highlight of tileState.highlights + unless visibleHighlights[id] + delete tileState.highlights[id] return @@ -1236,7 +1239,12 @@ class TextEditorPresenter range = marker.getScreenRange() if decoration.isDestroyed() or not marker.isValid() or range.isEmpty() or not range.intersectsRowRange(@startRow, @endRow - 1) - delete @state.content.highlights[decoration.id] + tileStartRow = @tileForRow(range.start.row) + tileEndRow = @tileForRow(range.end.row) + + for tile in [tileStartRow..tileEndRow] by @tileSize + delete @state.content.tiles[tile]?.highlights[decoration.id] + @emitDidUpdateState() return @@ -1248,32 +1256,54 @@ class TextEditorPresenter range.end.column = 0 if range.isEmpty() - delete @state.content.highlights[decoration.id] + tileState = @state.content.tiles[@tileForRow(range.start.row)] + delete tileState.highlights[decoration.id] @emitDidUpdateState() return - highlightState = @state.content.highlights[decoration.id] ?= { - flashCount: 0 - flashDuration: null - flashClass: null - } + flash = decoration.consumeNextFlash() - if flash = decoration.consumeNextFlash() - highlightState.flashCount++ - highlightState.flashClass = flash.class - highlightState.flashDuration = flash.duration + startRow = range.start.row + while startRow <= range.end.row + tileStartRow = @tileForRow(startRow) + tileEndRow = tileStartRow + @tileSize + tileState = @state.content.tiles[tileStartRow] ?= {highlights: {}} + endRow = Math.min(tileEndRow, range.end.row) + + tileRange = new Range(new Point(startRow, 0), new Point(endRow, Infinity)) + + if startRow is range.start.row + tileRange.start.column = range.start.column + + if endRow is range.end.row + tileRange.end.column = range.end.column + + highlightState = tileState.highlights[decoration.id] ?= { + flashCount: 0 + flashDuration: null + flashClass: null + tileRow: tileStartRow + } + + if flash? + highlightState.flashCount++ + highlightState.flashClass = flash.class + highlightState.flashDuration = flash.duration + + highlightState.class = properties.class + highlightState.deprecatedRegionClass = properties.deprecatedRegionClass + highlightState.regions = @buildHighlightRegions(tileStartRow, tileRange) + + startRow = tileEndRow - highlightState.class = properties.class - highlightState.deprecatedRegionClass = properties.deprecatedRegionClass - highlightState.regions = @buildHighlightRegions(range) @emitDidUpdateState() true - buildHighlightRegions: (screenRange) -> + buildHighlightRegions: (tileStartRow, screenRange) -> lineHeightInPixels = @lineHeight - startPixelPosition = @pixelPositionForScreenPosition(screenRange.start, true) - endPixelPosition = @pixelPositionForScreenPosition(screenRange.end, true) + startPixelPosition = @pixelPositionForScreenPosition(screenRange.start, true, tileStartRow) + endPixelPosition = @pixelPositionForScreenPosition(screenRange.end, true, tileStartRow) spannedRows = screenRange.end.row - screenRange.start.row + 1 if spannedRows is 1 diff --git a/src/tile-component.coffee b/src/tile-component.coffee index 5659b73a9..1aeeea952 100644 --- a/src/tile-component.coffee +++ b/src/tile-component.coffee @@ -1,5 +1,6 @@ _ = require 'underscore-plus' +HighlightsComponent = require './highlights-component' TokenIterator = require './token-iterator' AcceptFilter = {acceptNode: -> NodeFilter.FILTER_ACCEPT} WrapperDiv = document.createElement('div') @@ -26,6 +27,9 @@ class TileComponent @domNode.style.position = "absolute" @domNode.style.display = "block" + @highlightsComponent = new HighlightsComponent(@presenter) + @domNode.appendChild(@highlightsComponent.getDomNode()) + getDomNode: -> @domNode @@ -62,6 +66,8 @@ class TileComponent @domNode.style.width = @newState.scrollWidth + 'px' @oldState.scrollWidth = @newState.scrollWidth + @highlightsComponent.updateSync(@newTileState) + @oldState.indentGuidesVisible = @newState.indentGuidesVisible @oldState.scrollWidth = @newState.scrollWidth