mirror of
https://github.com/atom/atom.git
synced 2026-04-28 03:01:47 -04:00
Move the overlay calculation into the presenter.
This commit is contained in:
@@ -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'
|
||||
|
||||
@@ -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 =>
|
||||
|
||||
Reference in New Issue
Block a user