Move the overlay calculation into the presenter.

This commit is contained in:
Ben Ogle
2015-04-01 13:05:52 -07:00
parent c62f06af9d
commit b0794bbb68
3 changed files with 71 additions and 91 deletions

View File

@@ -4,99 +4,38 @@ class OverlayManager
@overlaysById = {}
render: (state) ->
editorDimensionsHaveChanged = !@editorDimensionsAreEqual(state)
for decorationId, overlay of state.content.overlays
overlayHasChanged = not @overlayStateIsEqual(decorationId, overlay)
if editorDimensionsHaveChanged or overlayHasChanged
if @shouldUpdateOverlay(decorationId, overlay)
@renderOverlay(state, decorationId, overlay)
@cacheOverlayState(decorationId, overlay)
for id, {overlayNode} of @overlaysById
unless state.content.overlays.hasOwnProperty(id)
delete @overlaysById[id]
overlayNode.remove()
@cacheEditorDimensions(state)
overlayStateIsEqual: (decorationId, overlay) ->
return false unless @overlaysById[decorationId]?
@overlaysById[decorationId].itemWidth is overlay.itemWidth and
@overlaysById[decorationId].itemHeight is overlay.itemHeight and
@overlaysById[decorationId].contentMargin is overlay.contentMargin and
@overlaysById[decorationId].pixelPosition?.top is overlay.pixelPosition?.top and
@overlaysById[decorationId].pixelPosition?.left is overlay.pixelPosition?.left
cacheOverlayState: (decorationId, overlay) ->
return unless @overlaysById[decorationId]?
@overlaysById[decorationId].itemWidth = overlay.itemWidth
@overlaysById[decorationId].itemHeight = overlay.itemHeight
@overlaysById[decorationId].contentMargin = overlay.contentMargin
@overlaysById[decorationId].pixelPosition = overlay.pixelPosition
cacheEditorDimensions: (state) ->
@cachedEditorDimensions =
lineHeight: @presenter.lineHeight
contentFrameWidth: @presenter.contentFrameWidth
editorTop: @presenter.boundingClientRect?.top
editorLeft: @presenter.boundingClientRect?.left
editorWidth: @presenter.boundingClientRect?.width
windowWidth: @presenter.windowWidth
windowHeight: @presenter.windowHeight
scrollTop: state.content.scrollTop
scrollLeft: state.content.scrollLeft
editorDimensionsAreEqual: (state) ->
return false unless @cachedEditorDimensions?
@cachedEditorDimensions.lineHeight is @presenter.lineHeight and
@cachedEditorDimensions.contentFrameWidth is @presenter.contentFrameWidth and
@cachedEditorDimensions.editorTop is @presenter.boundingClientRect?.top and
@cachedEditorDimensions.editorLeft is @presenter.boundingClientRect?.left and
@cachedEditorDimensions.editorWidth is @presenter.boundingClientRect?.width and
@cachedEditorDimensions.windowWidth is @presenter.windowWidth and
@cachedEditorDimensions.windowHeight is @presenter.windowHeight and
@cachedEditorDimensions.scrollTop is state.content.scrollTop and
@cachedEditorDimensions.scrollLeft is state.content.scrollLeft
shouldUpdateOverlay: (decorationId, overlay) ->
cachedOverlay = @overlaysById[decorationId]
return true unless cachedOverlay?
cachedOverlay.pixelPosition?.top isnt overlay.pixelPosition?.top or
cachedOverlay.pixelPosition?.left isnt overlay.pixelPosition?.left
measureOverlays: ->
for decorationId, {item} of @overlaysById
@measureOverlay(decorationId, item)
for decorationId, {itemView} of @overlaysById
@measureOverlay(decorationId, itemView)
measureOverlay: (decorationId, item) ->
contentMargin = parseInt(getComputedStyle(item)['margin-left']) ? 0
@presenter.setOverlayDimensions(decorationId, item.offsetWidth, item.offsetHeight, contentMargin)
measureOverlay: (decorationId, itemView) ->
contentMargin = parseInt(getComputedStyle(itemView)['margin-left']) ? 0
@presenter.setOverlayDimensions(decorationId, itemView.offsetWidth, itemView.offsetHeight, contentMargin)
renderOverlay: (state, decorationId, {item, pixelPosition}) ->
item = atom.views.getView(item)
overlay = @overlaysById[decorationId]
unless overlayNode = overlay?.overlayNode
itemView = atom.views.getView(item)
cachedOverlay = @overlaysById[decorationId]
unless overlayNode = cachedOverlay?.overlayNode
overlayNode = document.createElement('atom-overlay')
overlayNode.appendChild(item)
overlayNode.appendChild(itemView)
@container.appendChild(overlayNode)
@overlaysById[decorationId] = overlay = {overlayNode, item}
@overlaysById[decorationId] = cachedOverlay = {overlayNode, itemView}
overlayDimensions = @presenter.getOverlayDimensions(decorationId)
unless overlayDimensions?.itemWidth?
@measureOverlay(decorationId, item)
overlayDimensions = @presenter.getOverlayDimensions(decorationId)
{itemWidth, itemHeight, contentMargin} = overlayDimensions
{scrollTop, scrollLeft} = state.content
editorBounds = @presenter.boundingClientRect
gutterWidth = editorBounds.width - @presenter.contentFrameWidth
left = pixelPosition.left - scrollLeft + gutterWidth
top = pixelPosition.top + @presenter.lineHeight - scrollTop
rightDiff = left + editorBounds.left + itemWidth + contentMargin - @presenter.windowWidth
left -= rightDiff if rightDiff > 0
leftDiff = left + editorBounds.left + contentMargin
left -= leftDiff if leftDiff < 0
if top + editorBounds.top + itemHeight > @presenter.windowHeight
top -= itemHeight + @presenter.lineHeight
overlayNode.style.top = top + 'px'
overlayNode.style.left = left + 'px'
cachedOverlay.pixelPosition = pixelPosition
overlayNode.style.top = pixelPosition.top + 'px'
overlayNode.style.left = pixelPosition.left + 'px'

View File

@@ -9,6 +9,7 @@ class TextEditorPresenter
stoppedScrollingTimeoutId: null
mouseWheelScreenRow: null
scopedCharacterWidthsChangeCount: 0
overlayDimensions: {}
constructor: (params) ->
{@model, @autoHeight, @explicitHeight, @contentFrameWidth, @scrollTop, @scrollLeft} = params
@@ -327,13 +328,39 @@ class TextEditorPresenter
else
screenPosition = decoration.getMarker().getHeadScreenPosition()
pixelPosition = @pixelPositionForScreenPosition(screenPosition)
if overlayDimensions = @overlayDimensions[decoration.id]
{itemWidth, itemHeight, contentMargin} = overlayDimensions
{scrollTop, scrollLeft} = @state.content
gutterWidth = @boundingClientRect.width - @contentFrameWidth
left = pixelPosition.left - scrollLeft + gutterWidth
top = pixelPosition.top + @lineHeight - scrollTop
rightDiff = left + @boundingClientRect.left + itemWidth + contentMargin - @windowWidth
left -= rightDiff if rightDiff > 0
leftDiff = left + @boundingClientRect.left + contentMargin
left -= leftDiff if leftDiff < 0
if top + @boundingClientRect.top + itemHeight > @windowHeight
top -= itemHeight + @lineHeight
pixelPosition.top = top
pixelPosition.left = left
@state.content.overlays[decoration.id] ?= {item}
@state.content.overlays[decoration.id].pixelPosition = @pixelPositionForScreenPosition(screenPosition)
@state.content.overlays[decoration.id].pixelPosition = pixelPosition
visibleDecorationIds[decoration.id] = true
for id of @state.content.overlays
delete @state.content.overlays[id] unless visibleDecorationIds[id]
for id of @overlayDimensions
delete @overlayDimensions[id] unless visibleDecorationIds[id]
return
updateGutterState: -> @batch "shouldUpdateGutterState", ->
@@ -566,6 +593,7 @@ class TextEditorPresenter
@updateLinesState()
@updateCursorsState()
@updateLineNumbersState()
@updateOverlaysState()
didStartScrolling: ->
if @stoppedScrollingTimeoutId?
@@ -593,6 +621,7 @@ class TextEditorPresenter
@updateHorizontalScrollState()
@updateHiddenInputState()
@updateCursorsState() unless oldScrollLeft?
@updateOverlaysState()
setHorizontalScrollbarHeight: (horizontalScrollbarHeight) ->
unless @measuredHorizontalScrollbarHeight is horizontalScrollbarHeight
@@ -1013,18 +1042,19 @@ class TextEditorPresenter
regions
setOverlayDimensions: (decorationId, itemWidth, itemHeight, contentMargin) ->
if overlayState = @state.content.overlays[decorationId]
dimensionsAreEqual = overlayState.itemWidth is itemWidth and
overlayState.itemHeight is itemHeight and
overlayState.contentMargin is contentMargin
unless dimensionsAreEqual
overlayState.itemWidth = itemWidth
overlayState.itemHeight = itemHeight
overlayState.contentMargin = contentMargin
@updateOverlaysState()
@overlayDimensions[decorationId] ?= {}
overlayState = @overlayDimensions[decorationId]
dimensionsAreEqual = overlayState.itemWidth is itemWidth and
overlayState.itemHeight is itemHeight and
overlayState.contentMargin is contentMargin
unless dimensionsAreEqual
overlayState.itemWidth = itemWidth
overlayState.itemHeight = itemHeight
overlayState.contentMargin = contentMargin
@updateOverlaysState()
getOverlayDimensions: (decorationId) ->
@state.content.overlays[decorationId]
@overlayDimensions[decorationId]
observeCursor: (cursor) ->
didChangePositionDisposable = cursor.onDidChangePosition =>