mirror of
https://github.com/atom/atom.git
synced 2026-01-25 14:59:03 -05:00
Cache the overlay dimensions in the presenter
This commit is contained in:
@@ -1,30 +1,86 @@
|
||||
module.exports =
|
||||
class OverlayManager
|
||||
constructor: (@presenter, @container) ->
|
||||
@overlayNodesById = {}
|
||||
@overlaysById = {}
|
||||
|
||||
render: (state) ->
|
||||
for decorationId, {pixelPosition, item} of state.content.overlays
|
||||
@renderOverlay(state, decorationId, item, pixelPosition)
|
||||
editorDimensionsHaveChanged = !@editorDimensionsAreEqual(state)
|
||||
|
||||
for id, overlayNode of @overlayNodesById
|
||||
for decorationId, overlay of state.content.overlays
|
||||
overlayHasChanged = not @overlayStateIsEqual(decorationId, overlay)
|
||||
if editorDimensionsHaveChanged or overlayHasChanged
|
||||
@renderOverlay(state, decorationId, overlay)
|
||||
@cacheOverlayState(decorationId, overlay)
|
||||
|
||||
for id, {overlayNode} of @overlaysById
|
||||
unless state.content.overlays.hasOwnProperty(id)
|
||||
delete @overlayNodesById[id]
|
||||
delete @overlaysById[id]
|
||||
overlayNode.remove()
|
||||
|
||||
return
|
||||
@cacheEditorDimensions(state)
|
||||
|
||||
renderOverlay: (state, decorationId, item, pixelPosition) ->
|
||||
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
|
||||
|
||||
measureOverlays: ->
|
||||
for decorationId, {item} of @overlaysById
|
||||
@measureOverlay(decorationId, item)
|
||||
|
||||
measureOverlay: (decorationId, item) ->
|
||||
contentMargin = parseInt(getComputedStyle(item)['margin-left']) ? 0
|
||||
@presenter.setOverlayDimensions(decorationId, item.offsetWidth, item.offsetHeight, contentMargin)
|
||||
|
||||
renderOverlay: (state, decorationId, {item, pixelPosition}) ->
|
||||
item = atom.views.getView(item)
|
||||
unless overlayNode = @overlayNodesById[decorationId]
|
||||
overlayNode = @overlayNodesById[decorationId] = document.createElement('atom-overlay')
|
||||
overlay = @overlaysById[decorationId]
|
||||
unless overlayNode = overlay?.overlayNode
|
||||
overlayNode = document.createElement('atom-overlay')
|
||||
overlayNode.appendChild(item)
|
||||
@container.appendChild(overlayNode)
|
||||
@overlaysById[decorationId] = overlay = {overlayNode, item}
|
||||
|
||||
itemWidth = item.offsetWidth
|
||||
itemHeight = item.offsetHeight
|
||||
contentMargin = parseInt(getComputedStyle(item)['margin-left']) ? 0
|
||||
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
|
||||
|
||||
@@ -158,6 +158,7 @@ class TextEditorComponent
|
||||
|
||||
readAfterUpdateSync: =>
|
||||
@linesComponent.measureCharactersInNewLines() if @isVisible() and not @newState.content.scrollingVertically
|
||||
@overlayManager?.measureOverlays()
|
||||
|
||||
mountGutterComponent: ->
|
||||
@gutterComponent = new GutterComponent({@editor, onMouseDown: @onGutterMouseDown})
|
||||
@@ -189,6 +190,8 @@ class TextEditorComponent
|
||||
else unless @updateRequested
|
||||
@updateRequested = true
|
||||
atom.views.updateDocument =>
|
||||
@editor.horribleUpdateMethod?()
|
||||
@editor.horribleUpdateMethod = null
|
||||
@updateRequested = false
|
||||
@updateSync() if @editor.isAlive()
|
||||
atom.views.readDocument(@readAfterUpdateSync)
|
||||
@@ -568,6 +571,7 @@ class TextEditorComponent
|
||||
@sampleBackgroundColors()
|
||||
@measureDimensions()
|
||||
@sampleFontStyling()
|
||||
@overlayManager?.measureOverlays()
|
||||
|
||||
checkForVisibilityChange: ->
|
||||
if @isVisible()
|
||||
@@ -617,11 +621,7 @@ class TextEditorComponent
|
||||
|
||||
measureWindowSize: ->
|
||||
return unless @mounted
|
||||
|
||||
width = window.innerWidth
|
||||
height = window.innerHeight
|
||||
|
||||
@presenter.setWindowSize(width, height)
|
||||
@presenter.setWindowSize(window.innerWidth, window.innerHeight)
|
||||
|
||||
sampleFontStyling: =>
|
||||
oldFontSize = @fontSize
|
||||
|
||||
@@ -1012,6 +1012,20 @@ 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()
|
||||
|
||||
getOverlayDimensions: (decorationId) ->
|
||||
@state.content.overlays[decorationId]
|
||||
|
||||
observeCursor: (cursor) ->
|
||||
didChangePositionDisposable = cursor.onDidChangePosition =>
|
||||
@updateHiddenInputState() if cursor.isLastCursor()
|
||||
|
||||
Reference in New Issue
Block a user