Overlay decorations render

This commit is contained in:
Ben Ogle 2014-11-10 18:11:54 -08:00
parent 89ab0becc2
commit c79db992d9
4 changed files with 68 additions and 4 deletions

View File

@ -7,6 +7,7 @@ React = require 'react-atom-fork'
Decoration = require './decoration'
CursorsComponent = require './cursors-component'
HighlightsComponent = require './highlights-component'
OverlayManager = require './overlay-manager'
DummyLineNode = $$(-> @div className: 'line', style: 'position: absolute; visibility: hidden;', => @span 'x')[0]
AcceptFilter = {acceptNode: -> NodeFilter.FILTER_ACCEPT}
@ -20,7 +21,7 @@ LinesComponent = React.createClass
{performedInitialMeasurement, cursorBlinkPeriod, cursorBlinkResumeDelay} = @props
if performedInitialMeasurement
{editor, highlightDecorations, scrollHeight, scrollWidth, placeholderText, backgroundColor} = @props
{editor, overlayDecorations, highlightDecorations, scrollHeight, scrollWidth, placeholderText, backgroundColor} = @props
{lineHeightInPixels, defaultCharWidth, scrollViewHeight, scopedCharacterWidthsChangeCount} = @props
{scrollTop, scrollLeft, cursorPixelRects, mini} = @props
style =
@ -63,10 +64,15 @@ LinesComponent = React.createClass
insertionPoint.setAttribute('select', '.overlayer')
@getDOMNode().appendChild(insertionPoint)
insertionPoint = document.createElement('content')
insertionPoint.setAttribute('select', 'atom-overlay')
@overlayManager = new OverlayManager()
@getDOMNode().appendChild(insertionPoint)
shouldComponentUpdate: (newProps) ->
return true unless isEqualForProperties(newProps, @props,
'renderedRowRange', 'lineDecorations', 'highlightDecorations', 'lineHeightInPixels', 'defaultCharWidth',
'scrollTop', 'scrollLeft', 'showIndentGuide', 'scrollingVertically', 'visible',
'overlayDecorations', 'scrollTop', 'scrollLeft', 'showIndentGuide', 'scrollingVertically', 'visible',
'scrollViewHeight', 'mouseWheelScreenRow', 'scopedCharacterWidthsChangeCount', 'lineWidth', 'useHardwareAcceleration',
'placeholderText', 'performedInitialMeasurement', 'backgroundColor', 'cursorPixelRects'
)
@ -92,6 +98,8 @@ LinesComponent = React.createClass
@updateLines(@props.lineWidth isnt prevProps.lineWidth)
@measureCharactersInNewLines() if visible and not scrollingVertically
@overlayManager?.render(@props)
clearScreenRowCaches: ->
@screenRowsByLineId = {}
@lineIdsByScreenRow = {}

View File

@ -0,0 +1,31 @@
module.exports =
class OverlayManager
constructor: ->
@overlays = {}
render: (props) ->
{hostElement, editor, overlayDecorations, lineHeightInPixels} = props
existingDecorations = null
for markerId, {startPixelPosition, endPixelPosition, decorations} of overlayDecorations
for decoration in decorations
@renderOverlay(hostElement, decoration, endPixelPosition)
existingDecorations ?= {}
existingDecorations[decoration.id] = true
for id, overlay of @overlays
unless existingDecorations? and id of existingDecorations
hostElement.removeChild(overlay)
delete @overlays[id]
return
renderOverlay: (hostElement, decoration, endPixelPosition) ->
unless overlay = @overlays[decoration.id]
overlay = @overlays[decoration.id] = document.createElement('atom-overlay')
overlay.appendChild(atom.views.getView(decoration.item))
hostElement.appendChild(overlay)
overlay.style.top = endPixelPosition.top + 'px'
overlay.style.left = endPixelPosition.left + 'px'

View File

@ -50,7 +50,7 @@ TextEditorComponent = React.createClass
render: ->
{focused, showIndentGuide, showLineNumbers, visible} = @state
{editor, mini, cursorBlinkPeriod, cursorBlinkResumeDelay} = @props
{editor, mini, cursorBlinkPeriod, cursorBlinkResumeDelay, hostElement} = @props
maxLineNumberDigits = editor.getLineCount().toString().length
hasSelection = editor.getLastSelection()? and !editor.getLastSelection().isEmpty()
style = {}
@ -66,6 +66,7 @@ TextEditorComponent = React.createClass
decorations = editor.decorationsForScreenRowRange(renderedStartRow, renderedEndRow)
highlightDecorations = @getHighlightDecorations(decorations)
overlayDecorations = @getOverlayDecorations(decorations)
lineDecorations = @getLineDecorations(decorations)
placeholderText = editor.getPlaceholderText() if editor.isEmpty()
visible = @isVisible()
@ -110,7 +111,8 @@ TextEditorComponent = React.createClass
LinesComponent {
ref: 'lines',
editor, lineHeightInPixels, defaultCharWidth, tokenizedLines, lineDecorations, highlightDecorations,
editor, lineHeightInPixels, defaultCharWidth, tokenizedLines,
lineDecorations, highlightDecorations, overlayDecorations, hostElement,
showIndentGuide, renderedRowRange, @pendingChanges, scrollTop, scrollLeft,
@scrollingVertically, scrollHeight, scrollWidth, mouseWheelScreenRow,
visible, scrollViewHeight, @scopedCharacterWidthsChangeCount, lineWidth, @useHardwareAcceleration,
@ -351,7 +353,24 @@ TextEditorComponent = React.createClass
endPixelPosition: editor.pixelPositionForScreenPosition(screenRange.end)
decorations: []
filteredDecorations[markerId].decorations.push decorationParams
filteredDecorations
getOverlayDecorations: (decorationsByMarkerId) ->
{editor} = @props
filteredDecorations = {}
for markerId, decorations of decorationsByMarkerId
marker = editor.getMarker(markerId)
screenRange = marker.getScreenRange()
if marker.isValid()
for decoration in decorations
if decoration.isType('overlay')
decorationParams = decoration.getProperties()
filteredDecorations[markerId] ?=
id: markerId
startPixelPosition: editor.pixelPositionForScreenPosition(screenRange.start)
endPixelPosition: editor.pixelPositionForScreenPosition(screenRange.end)
decorations: []
filteredDecorations[markerId].decorations.push decorationParams
filteredDecorations
observeEditor: ->

View File

@ -12,6 +12,12 @@ atom-text-editor.mini {
max-height: @component-line-height + 2; // +2 for borders
}
atom-overlay {
position: absolute;
display: block;
z-index: 4;
}
// TODO: remove this when the shadow DOM is the default
atom-text-editor .highlight {
background: none;