mirror of
https://github.com/atom/atom.git
synced 2026-01-23 13:58:08 -05:00
Make each section of presenter state self-contained
This means we have some duplicated values in different parts of the tree, but it’s cleaner in the view since each component only consumes a single object. Seems like the presenter should convey the correct data to the correct locations and minimize the logic in the view. A few duplicated integers is a reasonable trade-off.
This commit is contained in:
@@ -33,50 +33,6 @@ describe "TextEditorPresenter", ->
|
||||
# These `describe` and `it` blocks mirror the structure of the ::state object.
|
||||
# Please maintain this structure when adding specs for new state fields.
|
||||
describe "::state", ->
|
||||
describe ".scrollHeight", ->
|
||||
it "is initialized based on the lineHeight, the number of lines, and the height", ->
|
||||
presenter = new TextEditorPresenter(model: editor, scrollTop: 0, lineHeight: 10)
|
||||
expect(presenter.state.scrollHeight).toBe editor.getScreenLineCount() * 10
|
||||
|
||||
presenter = new TextEditorPresenter(model: editor, scrollTop: 0, lineHeight: 10, height: 500)
|
||||
expect(presenter.state.scrollHeight).toBe 500
|
||||
|
||||
it "updates when the ::lineHeight changes", ->
|
||||
presenter = new TextEditorPresenter(model: editor, scrollTop: 0, lineHeight: 10)
|
||||
expectStateUpdate presenter, -> presenter.setLineHeight(20)
|
||||
expect(presenter.state.scrollHeight).toBe editor.getScreenLineCount() * 20
|
||||
|
||||
it "updates when the line count changes", ->
|
||||
presenter = new TextEditorPresenter(model: editor, scrollTop: 0, lineHeight: 10)
|
||||
expectStateUpdate presenter, -> editor.getBuffer().append("\n\n\n")
|
||||
expect(presenter.state.scrollHeight).toBe editor.getScreenLineCount() * 10
|
||||
|
||||
it "updates when ::height changes", ->
|
||||
presenter = new TextEditorPresenter(model: editor, scrollTop: 0, lineHeight: 10)
|
||||
expectStateUpdate presenter, -> presenter.setHeight(500)
|
||||
expect(presenter.state.scrollHeight).toBe 500
|
||||
|
||||
describe ".scrollTop", ->
|
||||
it "tracks the value of ::scrollTop", ->
|
||||
presenter = new TextEditorPresenter(model: editor, scrollTop: 10, lineHeight: 10)
|
||||
expect(presenter.state.scrollTop).toBe 10
|
||||
expectStateUpdate presenter, -> presenter.setScrollTop(50)
|
||||
expect(presenter.state.scrollTop).toBe 50
|
||||
|
||||
describe ".scrollingVertically", ->
|
||||
it "is true for ::stoppedScrollingDelay milliseconds following a changes to ::scrollTop", ->
|
||||
presenter = new TextEditorPresenter(model: editor, scrollTop: 10, stoppedScrollingDelay: 200)
|
||||
expect(presenter.state.scrollingVertically).toBe false
|
||||
expectStateUpdate presenter, -> presenter.setScrollTop(0)
|
||||
expect(presenter.state.scrollingVertically).toBe true
|
||||
advanceClock(100)
|
||||
expect(presenter.state.scrollingVertically).toBe true
|
||||
presenter.setScrollTop(10)
|
||||
advanceClock(100)
|
||||
expect(presenter.state.scrollingVertically).toBe true
|
||||
expectStateUpdate presenter, -> advanceClock(100)
|
||||
expect(presenter.state.scrollingVertically).toBe false
|
||||
|
||||
describe ".horizontalScrollbar", ->
|
||||
describe ".visible", ->
|
||||
it "is true if the scrollWidth exceeds the computed client width", ->
|
||||
@@ -127,6 +83,58 @@ describe "TextEditorPresenter", ->
|
||||
presenter.setHeight((editor.getLineCount() * 10) - 1)
|
||||
expect(state.horizontalScrollbar.right).toBe 10
|
||||
|
||||
describe ".scrollWidth", ->
|
||||
it "is initialized as the max of the ::contentFrameWidth and the width of the longest line", ->
|
||||
maxLineLength = editor.getMaxScreenLineLength()
|
||||
|
||||
presenter = new TextEditorPresenter(model: editor, contentFrameWidth: 50, baseCharacterWidth: 10)
|
||||
expect(presenter.state.horizontalScrollbar.scrollWidth).toBe 10 * maxLineLength + 1
|
||||
|
||||
presenter = new TextEditorPresenter(model: editor, contentFrameWidth: 10 * maxLineLength + 20, baseCharacterWidth: 10)
|
||||
expect(presenter.state.horizontalScrollbar.scrollWidth).toBe 10 * maxLineLength + 20
|
||||
|
||||
it "updates when the ::contentFrameWidth changes", ->
|
||||
maxLineLength = editor.getMaxScreenLineLength()
|
||||
presenter = new TextEditorPresenter(model: editor, contentFrameWidth: 50, baseCharacterWidth: 10)
|
||||
|
||||
expect(presenter.state.horizontalScrollbar.scrollWidth).toBe 10 * maxLineLength + 1
|
||||
expectStateUpdate presenter, -> presenter.setContentFrameWidth(10 * maxLineLength + 20)
|
||||
expect(presenter.state.horizontalScrollbar.scrollWidth).toBe 10 * maxLineLength + 20
|
||||
|
||||
it "updates when the ::baseCharacterWidth changes", ->
|
||||
maxLineLength = editor.getMaxScreenLineLength()
|
||||
presenter = new TextEditorPresenter(model: editor, contentFrameWidth: 50, baseCharacterWidth: 10)
|
||||
|
||||
expect(presenter.state.horizontalScrollbar.scrollWidth).toBe 10 * maxLineLength + 1
|
||||
expectStateUpdate presenter, -> presenter.setBaseCharacterWidth(15)
|
||||
expect(presenter.state.horizontalScrollbar.scrollWidth).toBe 15 * maxLineLength + 1
|
||||
|
||||
it "updates when the scoped character widths change", ->
|
||||
waitsForPromise -> atom.packages.activatePackage('language-javascript')
|
||||
|
||||
runs ->
|
||||
maxLineLength = editor.getMaxScreenLineLength()
|
||||
presenter = new TextEditorPresenter(model: editor, contentFrameWidth: 50, baseCharacterWidth: 10)
|
||||
|
||||
expect(presenter.state.horizontalScrollbar.scrollWidth).toBe 10 * maxLineLength + 1
|
||||
expectStateUpdate presenter, -> presenter.setScopedCharWidth(['source.js', 'support.function.js'], 'p', 20)
|
||||
expect(presenter.state.horizontalScrollbar.scrollWidth).toBe (10 * (maxLineLength - 2)) + (20 * 2) + 1 # 2 of the characters are 20px wide now instead of 10px wide
|
||||
|
||||
it "updates when ::softWrapped changes on the editor", ->
|
||||
presenter = new TextEditorPresenter(model: editor, contentFrameWidth: 50, baseCharacterWidth: 10)
|
||||
expect(presenter.state.horizontalScrollbar.scrollWidth).toBe 10 * editor.getMaxScreenLineLength() + 1
|
||||
expectStateUpdate presenter, -> editor.setSoftWrapped(true)
|
||||
expect(presenter.state.horizontalScrollbar.scrollWidth).toBe 10 * editor.getMaxScreenLineLength()
|
||||
expectStateUpdate presenter, -> editor.setSoftWrapped(false)
|
||||
expect(presenter.state.horizontalScrollbar.scrollWidth).toBe 10 * editor.getMaxScreenLineLength() + 1
|
||||
|
||||
describe ".scrollLeft", ->
|
||||
it "tracks the value of ::scrollLeft", ->
|
||||
presenter = new TextEditorPresenter(model: editor, scrollLeft: 10, lineHeight: 10, lineOverdrawMargin: 1)
|
||||
expect(presenter.state.horizontalScrollbar.scrollLeft).toBe 10
|
||||
expectStateUpdate presenter, -> presenter.setScrollLeft(50)
|
||||
expect(presenter.state.horizontalScrollbar.scrollLeft).toBe 50
|
||||
|
||||
describe ".verticalScrollbar", ->
|
||||
describe ".visible", ->
|
||||
it "is true if the scrollHeight exceeds the computed client height", ->
|
||||
@@ -177,7 +185,74 @@ describe "TextEditorPresenter", ->
|
||||
presenter.setContentFrameWidth(editor.getMaxScreenLineLength() * 10)
|
||||
expect(state.verticalScrollbar.bottom).toBe 10
|
||||
|
||||
describe ".scrollHeight", ->
|
||||
it "is initialized based on the lineHeight, the number of lines, and the height", ->
|
||||
presenter = new TextEditorPresenter(model: editor, scrollTop: 0, lineHeight: 10)
|
||||
expect(presenter.state.verticalScrollbar.scrollHeight).toBe editor.getScreenLineCount() * 10
|
||||
|
||||
presenter = new TextEditorPresenter(model: editor, scrollTop: 0, lineHeight: 10, height: 500)
|
||||
expect(presenter.state.verticalScrollbar.scrollHeight).toBe 500
|
||||
|
||||
it "updates when the ::lineHeight changes", ->
|
||||
presenter = new TextEditorPresenter(model: editor, scrollTop: 0, lineHeight: 10)
|
||||
expectStateUpdate presenter, -> presenter.setLineHeight(20)
|
||||
expect(presenter.state.verticalScrollbar.scrollHeight).toBe editor.getScreenLineCount() * 20
|
||||
|
||||
it "updates when the line count changes", ->
|
||||
presenter = new TextEditorPresenter(model: editor, scrollTop: 0, lineHeight: 10)
|
||||
expectStateUpdate presenter, -> editor.getBuffer().append("\n\n\n")
|
||||
expect(presenter.state.verticalScrollbar.scrollHeight).toBe editor.getScreenLineCount() * 10
|
||||
|
||||
it "updates when ::height changes", ->
|
||||
presenter = new TextEditorPresenter(model: editor, scrollTop: 0, lineHeight: 10)
|
||||
expectStateUpdate presenter, -> presenter.setHeight(500)
|
||||
expect(presenter.state.verticalScrollbar.scrollHeight).toBe 500
|
||||
|
||||
describe ".scrollTop", ->
|
||||
it "tracks the value of ::scrollTop", ->
|
||||
presenter = new TextEditorPresenter(model: editor, scrollTop: 10, lineHeight: 10)
|
||||
expect(presenter.state.verticalScrollbar.scrollTop).toBe 10
|
||||
expectStateUpdate presenter, -> presenter.setScrollTop(50)
|
||||
expect(presenter.state.verticalScrollbar.scrollTop).toBe 50
|
||||
|
||||
describe ".content", ->
|
||||
describe ".scrollingVertically", ->
|
||||
it "is true for ::stoppedScrollingDelay milliseconds following a changes to ::scrollTop", ->
|
||||
presenter = new TextEditorPresenter(model: editor, scrollTop: 10, stoppedScrollingDelay: 200)
|
||||
expect(presenter.state.content.scrollingVertically).toBe false
|
||||
expectStateUpdate presenter, -> presenter.setScrollTop(0)
|
||||
expect(presenter.state.content.scrollingVertically).toBe true
|
||||
advanceClock(100)
|
||||
expect(presenter.state.content.scrollingVertically).toBe true
|
||||
presenter.setScrollTop(10)
|
||||
advanceClock(100)
|
||||
expect(presenter.state.content.scrollingVertically).toBe true
|
||||
expectStateUpdate presenter, -> advanceClock(100)
|
||||
expect(presenter.state.content.scrollingVertically).toBe false
|
||||
|
||||
describe ".scrollHeight", ->
|
||||
it "is initialized based on the lineHeight, the number of lines, and the height", ->
|
||||
presenter = new TextEditorPresenter(model: editor, scrollTop: 0, lineHeight: 10)
|
||||
expect(presenter.state.content.scrollHeight).toBe editor.getScreenLineCount() * 10
|
||||
|
||||
presenter = new TextEditorPresenter(model: editor, scrollTop: 0, lineHeight: 10, height: 500)
|
||||
expect(presenter.state.content.scrollHeight).toBe 500
|
||||
|
||||
it "updates when the ::lineHeight changes", ->
|
||||
presenter = new TextEditorPresenter(model: editor, scrollTop: 0, lineHeight: 10)
|
||||
expectStateUpdate presenter, -> presenter.setLineHeight(20)
|
||||
expect(presenter.state.content.scrollHeight).toBe editor.getScreenLineCount() * 20
|
||||
|
||||
it "updates when the line count changes", ->
|
||||
presenter = new TextEditorPresenter(model: editor, scrollTop: 0, lineHeight: 10)
|
||||
expectStateUpdate presenter, -> editor.getBuffer().append("\n\n\n")
|
||||
expect(presenter.state.content.scrollHeight).toBe editor.getScreenLineCount() * 10
|
||||
|
||||
it "updates when ::height changes", ->
|
||||
presenter = new TextEditorPresenter(model: editor, scrollTop: 0, lineHeight: 10)
|
||||
expectStateUpdate presenter, -> presenter.setHeight(500)
|
||||
expect(presenter.state.content.scrollHeight).toBe 500
|
||||
|
||||
describe ".scrollWidth", ->
|
||||
it "is initialized as the max of the ::contentFrameWidth and the width of the longest line", ->
|
||||
maxLineLength = editor.getMaxScreenLineLength()
|
||||
@@ -223,6 +298,13 @@ describe "TextEditorPresenter", ->
|
||||
expectStateUpdate presenter, -> editor.setSoftWrapped(false)
|
||||
expect(presenter.state.content.scrollWidth).toBe 10 * editor.getMaxScreenLineLength() + 1
|
||||
|
||||
describe ".scrollTop", ->
|
||||
it "tracks the value of ::scrollTop", ->
|
||||
presenter = new TextEditorPresenter(model: editor, scrollTop: 10, lineHeight: 10)
|
||||
expect(presenter.state.content.scrollTop).toBe 10
|
||||
expectStateUpdate presenter, -> presenter.setScrollTop(50)
|
||||
expect(presenter.state.content.scrollTop).toBe 50
|
||||
|
||||
describe ".scrollLeft", ->
|
||||
it "tracks the value of ::scrollLeft", ->
|
||||
presenter = new TextEditorPresenter(model: editor, scrollLeft: 10, lineHeight: 10, lineOverdrawMargin: 1)
|
||||
@@ -1236,6 +1318,36 @@ describe "TextEditorPresenter", ->
|
||||
expect(presenter.state.content.overlays).not.toEqual({})
|
||||
|
||||
describe ".gutter", ->
|
||||
describe ".scrollHeight", ->
|
||||
it "is initialized based on the lineHeight, the number of lines, and the height", ->
|
||||
presenter = new TextEditorPresenter(model: editor, scrollTop: 0, lineHeight: 10)
|
||||
expect(presenter.state.gutter.scrollHeight).toBe editor.getScreenLineCount() * 10
|
||||
|
||||
presenter = new TextEditorPresenter(model: editor, scrollTop: 0, lineHeight: 10, height: 500)
|
||||
expect(presenter.state.gutter.scrollHeight).toBe 500
|
||||
|
||||
it "updates when the ::lineHeight changes", ->
|
||||
presenter = new TextEditorPresenter(model: editor, scrollTop: 0, lineHeight: 10)
|
||||
expectStateUpdate presenter, -> presenter.setLineHeight(20)
|
||||
expect(presenter.state.gutter.scrollHeight).toBe editor.getScreenLineCount() * 20
|
||||
|
||||
it "updates when the line count changes", ->
|
||||
presenter = new TextEditorPresenter(model: editor, scrollTop: 0, lineHeight: 10)
|
||||
expectStateUpdate presenter, -> editor.getBuffer().append("\n\n\n")
|
||||
expect(presenter.state.gutter.scrollHeight).toBe editor.getScreenLineCount() * 10
|
||||
|
||||
it "updates when ::height changes", ->
|
||||
presenter = new TextEditorPresenter(model: editor, scrollTop: 0, lineHeight: 10)
|
||||
expectStateUpdate presenter, -> presenter.setHeight(500)
|
||||
expect(presenter.state.gutter.scrollHeight).toBe 500
|
||||
|
||||
describe ".scrollTop", ->
|
||||
it "tracks the value of ::scrollTop", ->
|
||||
presenter = new TextEditorPresenter(model: editor, scrollTop: 10, lineHeight: 10)
|
||||
expect(presenter.state.gutter.scrollTop).toBe 10
|
||||
expectStateUpdate presenter, -> presenter.setScrollTop(50)
|
||||
expect(presenter.state.gutter.scrollTop).toBe 50
|
||||
|
||||
describe ".backgroundColor", ->
|
||||
it "is assigned to ::gutterBackgroundColor if present, and to ::backgroundColor otherwise", ->
|
||||
presenter = new TextEditorPresenter(model: editor, backgroundColor: "rgba(255, 0, 0, 0)", gutterBackgroundColor: "rgba(0, 255, 0, 0)")
|
||||
|
||||
@@ -19,16 +19,20 @@ GutterComponent = React.createClass
|
||||
|
||||
render: ->
|
||||
{presenter} = @props
|
||||
@newState = presenter.state.gutter
|
||||
@oldState ?= {lineNumbers: {}}
|
||||
|
||||
{scrollHeight, backgroundColor} = @newState
|
||||
|
||||
div className: 'gutter',
|
||||
div className: 'line-numbers', ref: 'lineNumbers', style:
|
||||
height: presenter.state.scrollHeight
|
||||
height: scrollHeight
|
||||
WebkitTransform: @getTransform() if presenter.hasRequiredMeasurements()
|
||||
backgroundColor: presenter.state.gutter.backgroundColor
|
||||
backgroundColor: backgroundColor
|
||||
|
||||
getTransform: ->
|
||||
{presenter, useHardwareAcceleration} = @props
|
||||
{scrollTop} = presenter.state
|
||||
{useHardwareAcceleration} = @props
|
||||
{scrollTop} = @newState
|
||||
|
||||
if useHardwareAcceleration
|
||||
"translate3d(0px, #{-scrollTop}px, 0px)"
|
||||
@@ -39,7 +43,7 @@ GutterComponent = React.createClass
|
||||
@lineNumberNodesById = {}
|
||||
|
||||
componentDidMount: ->
|
||||
{@maxLineNumberDigits} = @props.presenter.state.gutter
|
||||
{@maxLineNumberDigits} = @newState
|
||||
@appendDummyLineNumber()
|
||||
@updateLineNumbers()
|
||||
|
||||
@@ -48,7 +52,7 @@ GutterComponent = React.createClass
|
||||
node.addEventListener 'mousedown', @onMouseDown
|
||||
|
||||
componentDidUpdate: (oldProps) ->
|
||||
{maxLineNumberDigits} = @props.presenter.state.gutter
|
||||
{maxLineNumberDigits} = @newState
|
||||
unless maxLineNumberDigits is @maxLineNumberDigits
|
||||
@maxLineNumberDigits = maxLineNumberDigits
|
||||
@updateDummyLineNumber()
|
||||
@@ -69,13 +73,10 @@ GutterComponent = React.createClass
|
||||
@dummyLineNumberNode.innerHTML = @buildLineNumberInnerHTML(0, false)
|
||||
|
||||
updateLineNumbers: ->
|
||||
{presenter} = @props
|
||||
@oldState ?= {lineNumbers: {}}
|
||||
newState = presenter.state.gutter
|
||||
newLineNumberIds = null
|
||||
newLineNumbersHTML = null
|
||||
|
||||
for id, lineNumberState of newState.lineNumbers
|
||||
for id, lineNumberState of @newState.lineNumbers
|
||||
if @oldState.lineNumbers.hasOwnProperty(id)
|
||||
@updateLineNumberNode(id, lineNumberState)
|
||||
else
|
||||
@@ -96,7 +97,7 @@ GutterComponent = React.createClass
|
||||
node.appendChild(lineNumberNode)
|
||||
|
||||
for id, lineNumberState of @oldState.lineNumbers
|
||||
unless newState.lineNumbers.hasOwnProperty(id)
|
||||
unless @newState.lineNumbers.hasOwnProperty(id)
|
||||
@lineNumberNodesById[id].remove()
|
||||
delete @lineNumberNodesById[id]
|
||||
delete @oldState.lineNumbers[id]
|
||||
@@ -113,7 +114,7 @@ GutterComponent = React.createClass
|
||||
"<div class=\"#{className}\" style=\"#{style}\" data-buffer-row=\"#{bufferRow}\" data-screen-row=\"#{screenRow}\">#{innerHTML}</div>"
|
||||
|
||||
buildLineNumberInnerHTML: (bufferRow, softWrapped) ->
|
||||
{maxLineNumberDigits} = @props.presenter.state.gutter
|
||||
{maxLineNumberDigits} = @newState
|
||||
|
||||
if softWrapped
|
||||
lineNumber = "•"
|
||||
|
||||
@@ -18,11 +18,10 @@ LinesComponent = React.createClass
|
||||
|
||||
render: ->
|
||||
{editor, presenter} = @props
|
||||
@oldState ?= {content: {lines: {}}}
|
||||
@newState = presenter.state
|
||||
@oldState ?= {lines: {}}
|
||||
@newState = presenter.state.content
|
||||
|
||||
{scrollHeight} = @newState
|
||||
{scrollWidth, backgroundColor, placeholderText} = @newState.content
|
||||
{scrollHeight, scrollWidth, backgroundColor, placeholderText} = @newState
|
||||
|
||||
style =
|
||||
height: scrollHeight
|
||||
@@ -36,8 +35,7 @@ LinesComponent = React.createClass
|
||||
HighlightsComponent {presenter}
|
||||
|
||||
getTransform: ->
|
||||
{scrollTop} = @newState
|
||||
{scrollLeft} = @newState.content
|
||||
{scrollTop, scrollLeft} = @newState
|
||||
{useHardwareAcceleration} = @props
|
||||
|
||||
if useHardwareAcceleration
|
||||
@@ -68,41 +66,41 @@ LinesComponent = React.createClass
|
||||
componentDidUpdate: ->
|
||||
{visible, presenter} = @props
|
||||
|
||||
@removeLineNodes() unless @oldState?.content.indentGuidesVisible is @newState?.content.indentGuidesVisible
|
||||
@removeLineNodes() unless @oldState?.indentGuidesVisible is @newState?.indentGuidesVisible
|
||||
@updateLineNodes()
|
||||
@measureCharactersInNewLines() if visible and not presenter.state.scrollingVertically
|
||||
|
||||
@overlayManager?.render(@props)
|
||||
|
||||
@oldState.content.indentGuidesVisible = @newState.content.indentGuidesVisible
|
||||
@oldState.content.scrollWidth = @newState.content.scrollWidth
|
||||
@oldState.indentGuidesVisible = @newState.indentGuidesVisible
|
||||
@oldState.scrollWidth = @newState.scrollWidth
|
||||
|
||||
clearScreenRowCaches: ->
|
||||
@screenRowsByLineId = {}
|
||||
@lineIdsByScreenRow = {}
|
||||
|
||||
removeLineNodes: ->
|
||||
@removeLineNode(id) for id of @oldState.content.lines
|
||||
@removeLineNode(id) for id of @oldState.lines
|
||||
|
||||
removeLineNode: (id) ->
|
||||
@lineNodesByLineId[id].remove()
|
||||
delete @lineNodesByLineId[id]
|
||||
delete @lineIdsByScreenRow[@screenRowsByLineId[id]]
|
||||
delete @screenRowsByLineId[id]
|
||||
delete @oldState.content.lines[id]
|
||||
delete @oldState.lines[id]
|
||||
|
||||
updateLineNodes: ->
|
||||
{presenter} = @props
|
||||
|
||||
for id of @oldState.content.lines
|
||||
unless @newState.content.lines.hasOwnProperty(id)
|
||||
for id of @oldState.lines
|
||||
unless @newState.lines.hasOwnProperty(id)
|
||||
@removeLineNode(id)
|
||||
|
||||
newLineIds = null
|
||||
newLinesHTML = null
|
||||
|
||||
for id, lineState of @newState.content.lines
|
||||
if @oldState.content.lines.hasOwnProperty(id)
|
||||
for id, lineState of @newState.lines
|
||||
if @oldState.lines.hasOwnProperty(id)
|
||||
@updateLineNode(id)
|
||||
else
|
||||
newLineIds ?= []
|
||||
@@ -111,7 +109,7 @@ LinesComponent = React.createClass
|
||||
newLinesHTML += @buildLineHTML(id)
|
||||
@screenRowsByLineId[id] = lineState.screenRow
|
||||
@lineIdsByScreenRow[lineState.screenRow] = id
|
||||
@oldState.content.lines[id] = _.clone(lineState)
|
||||
@oldState.lines[id] = _.clone(lineState)
|
||||
|
||||
return unless newLineIds?
|
||||
|
||||
@@ -125,8 +123,8 @@ LinesComponent = React.createClass
|
||||
|
||||
buildLineHTML: (id) ->
|
||||
{presenter} = @props
|
||||
{scrollWidth} = @newState.content
|
||||
{screenRow, tokens, text, top, lineEnding, fold, isSoftWrapped, indentLevel, decorationClasses} = @newState.content.lines[id]
|
||||
{scrollWidth} = @newState
|
||||
{screenRow, tokens, text, top, lineEnding, fold, isSoftWrapped, indentLevel, decorationClasses} = @newState.lines[id]
|
||||
|
||||
classes = ''
|
||||
if decorationClasses?
|
||||
@@ -146,8 +144,8 @@ LinesComponent = React.createClass
|
||||
lineHTML
|
||||
|
||||
buildEmptyLineInnerHTML: (id) ->
|
||||
{indentGuidesVisible} = @newState.content
|
||||
{indentLevel, tabLength, endOfLineInvisibles} = @newState.content.lines[id]
|
||||
{indentGuidesVisible} = @newState
|
||||
{indentLevel, tabLength, endOfLineInvisibles} = @newState.lines[id]
|
||||
|
||||
if indentGuidesVisible and indentLevel > 0
|
||||
invisibleIndex = 0
|
||||
@@ -170,8 +168,8 @@ LinesComponent = React.createClass
|
||||
|
||||
buildLineInnerHTML: (id) ->
|
||||
{editor} = @props
|
||||
{indentGuidesVisible} = @newState.content
|
||||
{tokens, text} = @newState.content.lines[id]
|
||||
{indentGuidesVisible} = @newState
|
||||
{tokens, text} = @newState.lines[id]
|
||||
innerHTML = ""
|
||||
|
||||
scopeStack = []
|
||||
@@ -187,7 +185,7 @@ LinesComponent = React.createClass
|
||||
innerHTML
|
||||
|
||||
buildEndOfLineHTML: (id) ->
|
||||
{endOfLineInvisibles} = @newState.content.lines[id]
|
||||
{endOfLineInvisibles} = @newState.lines[id]
|
||||
|
||||
html = ''
|
||||
if endOfLineInvisibles?
|
||||
@@ -221,13 +219,13 @@ LinesComponent = React.createClass
|
||||
"<span class=\"#{scope.replace(/\.+/g, ' ')}\">"
|
||||
|
||||
updateLineNode: (id) ->
|
||||
{scrollWidth} = @newState.content
|
||||
{screenRow, top} = @newState.content.lines[id]
|
||||
{scrollWidth} = @newState
|
||||
{screenRow, top} = @newState.lines[id]
|
||||
|
||||
lineNode = @lineNodesByLineId[id]
|
||||
|
||||
newDecorationClasses = @newState.content.lines[id].decorationClasses
|
||||
oldDecorationClasses = @oldState.content.lines[id].decorationClasses
|
||||
newDecorationClasses = @newState.lines[id].decorationClasses
|
||||
oldDecorationClasses = @oldState.lines[id].decorationClasses
|
||||
|
||||
if oldDecorationClasses?
|
||||
for decorationClass in oldDecorationClasses
|
||||
@@ -272,7 +270,7 @@ LinesComponent = React.createClass
|
||||
node = @getDOMNode()
|
||||
|
||||
editor.batchCharacterMeasurement =>
|
||||
for id, lineState of @oldState.content.lines
|
||||
for id, lineState of @oldState.lines
|
||||
unless @measuredLines.has(id)
|
||||
lineNode = @lineNodesByLineId[id]
|
||||
@measureCharactersInLine(lineState, lineNode)
|
||||
|
||||
@@ -27,8 +27,7 @@ class OverlayManager
|
||||
itemHeight = item.offsetHeight
|
||||
|
||||
|
||||
{scrollTop} = presenter.state
|
||||
{scrollLeft} = presenter.state.content
|
||||
{scrollTop, scrollLeft} = presenter.state.content
|
||||
|
||||
left = pixelPosition.left
|
||||
if left + itemWidth - scrollLeft > presenter.getContentFrameWidth() and left - itemWidth >= scrollLeft
|
||||
|
||||
@@ -11,29 +11,29 @@ ScrollbarComponent = React.createClass
|
||||
|
||||
switch orientation
|
||||
when 'vertical'
|
||||
state = presenter.state.verticalScrollbar
|
||||
@newState = presenter.state.verticalScrollbar
|
||||
when 'horizontal'
|
||||
state = presenter.state.horizontalScrollbar
|
||||
@newState = presenter.state.horizontalScrollbar
|
||||
|
||||
style = {}
|
||||
|
||||
style.display = 'none' unless state.visible
|
||||
style.display = 'none' unless @newState.visible
|
||||
style.transform = 'translateZ(0)' if useHardwareAcceleration # See atom/atom#3559
|
||||
switch orientation
|
||||
when 'vertical'
|
||||
style.width = state.width
|
||||
style.bottom = state.bottom
|
||||
style.width = @newState.width
|
||||
style.bottom = @newState.bottom
|
||||
when 'horizontal'
|
||||
style.left = 0
|
||||
style.right = state.right
|
||||
style.height = state.height
|
||||
style.right = @newState.right
|
||||
style.height = @newState.height
|
||||
|
||||
div {className, style},
|
||||
switch orientation
|
||||
when 'vertical'
|
||||
div className: 'scrollbar-content', style: {height: presenter.state.scrollHeight}
|
||||
div className: 'scrollbar-content', style: {height: @newState.scrollHeight}
|
||||
when 'horizontal'
|
||||
div className: 'scrollbar-content', style: {width: presenter.state.content.scrollWidth}
|
||||
div className: 'scrollbar-content', style: {width: @newState.scrollWidth}
|
||||
|
||||
componentDidMount: ->
|
||||
{orientation} = @props
|
||||
@@ -47,14 +47,14 @@ ScrollbarComponent = React.createClass
|
||||
@getDOMNode().removeEventListener 'scroll', @onScroll
|
||||
|
||||
componentDidUpdate: ->
|
||||
{orientation, presenter} = @props
|
||||
{orientation} = @props
|
||||
node = @getDOMNode()
|
||||
|
||||
switch orientation
|
||||
when 'vertical'
|
||||
node.scrollTop = presenter.state.scrollTop
|
||||
node.scrollTop = @newState.scrollTop
|
||||
when 'horizontal'
|
||||
node.scrollLeft = presenter.state.content.scrollLeft
|
||||
node.scrollLeft = @newState.scrollLeft
|
||||
|
||||
onScroll: ->
|
||||
{orientation, onScroll} = @props
|
||||
|
||||
@@ -34,7 +34,6 @@ TextEditorComponent = React.createClass
|
||||
scrollSensitivity: 0.4
|
||||
heightAndWidthMeasurementRequested: false
|
||||
inputEnabled: true
|
||||
scopedCharacterWidthsChangeCount: null
|
||||
domPollingInterval: 100
|
||||
domPollingIntervalId: null
|
||||
domPollingPaused: false
|
||||
@@ -56,7 +55,7 @@ TextEditorComponent = React.createClass
|
||||
hiddenInputStyle = @getHiddenInputPosition()
|
||||
hiddenInputStyle.WebkitTransform = 'translateZ(0)' if @useHardwareAcceleration
|
||||
|
||||
style.height = @presenter.state.scrollHeight if @autoHeight
|
||||
style.height = @presenter.state.content.scrollHeight if @autoHeight
|
||||
|
||||
if useShadowDOM
|
||||
className = 'editor-contents--private'
|
||||
@@ -233,7 +232,6 @@ TextEditorComponent = React.createClass
|
||||
@subscribe editor.observeGrammar(@onGrammarChanged)
|
||||
@subscribe editor.observeCursors(@onCursorAdded)
|
||||
@subscribe editor.observeSelections(@onSelectionAdded)
|
||||
@subscribe editor.onDidChangeCharacterWidths(@onCharacterWidthsChanged)
|
||||
@subscribe editor.$scrollTop.changes, @onScrollTopChanged
|
||||
@subscribe editor.$scrollLeft.changes, @onScrollLeftChanged
|
||||
@subscribe editor.$verticalScrollbarWidth.changes, @requestUpdate
|
||||
@@ -579,9 +577,6 @@ TextEditorComponent = React.createClass
|
||||
@cursorMoved = true
|
||||
@requestUpdate()
|
||||
|
||||
onCharacterWidthsChanged: (@scopedCharacterWidthsChangeCount) ->
|
||||
@requestUpdate()
|
||||
|
||||
handleDragUntilMouseUp: (event, dragHandler) ->
|
||||
{editor} = @props
|
||||
dragging = false
|
||||
|
||||
@@ -51,10 +51,10 @@ class TextEditorPresenter
|
||||
|
||||
buildState: ->
|
||||
@state =
|
||||
scrollingVertically: false
|
||||
horizontalScrollbar: {}
|
||||
verticalScrollbar: {}
|
||||
content:
|
||||
scrollingVertically: false
|
||||
blinkCursorsOff: false
|
||||
lines: {}
|
||||
highlights: {}
|
||||
@@ -65,6 +65,7 @@ class TextEditorPresenter
|
||||
|
||||
updateState: ->
|
||||
@updateVerticalScrollState()
|
||||
@updateHorizontalScrollState()
|
||||
@updateScrollbarsState()
|
||||
@updateContentState()
|
||||
@updateLinesState()
|
||||
@@ -75,8 +76,28 @@ class TextEditorPresenter
|
||||
@updateLineNumbersState()
|
||||
|
||||
updateVerticalScrollState: ->
|
||||
@state.scrollHeight = @computeScrollHeight()
|
||||
@state.scrollTop = @getScrollTop()
|
||||
scrollHeight = @computeScrollHeight()
|
||||
@state.content.scrollHeight = scrollHeight
|
||||
@state.gutter.scrollHeight = scrollHeight
|
||||
@state.verticalScrollbar.scrollHeight = scrollHeight
|
||||
|
||||
scrollTop = @getScrollTop()
|
||||
@state.content.scrollTop = scrollTop
|
||||
@state.gutter.scrollTop = scrollTop
|
||||
@state.verticalScrollbar.scrollTop = scrollTop
|
||||
|
||||
@emitter.emit 'did-update-state'
|
||||
|
||||
updateHorizontalScrollState: ->
|
||||
scrollWidth = @computeScrollWidth()
|
||||
@state.content.scrollWidth = scrollWidth
|
||||
@state.horizontalScrollbar.scrollWidth = scrollWidth
|
||||
|
||||
scrollLeft = @getScrollLeft()
|
||||
@state.content.scrollLeft = @getScrollLeft()
|
||||
@state.horizontalScrollbar.scrollLeft = @getScrollLeft()
|
||||
|
||||
@emitter.emit 'did-update-state'
|
||||
|
||||
updateScrollbarsState: ->
|
||||
contentWidth = @computeContentWidth()
|
||||
@@ -406,11 +427,11 @@ class TextEditorPresenter
|
||||
clearTimeout(@stoppedScrollingTimeoutId)
|
||||
@stoppedScrollingTimeoutId = null
|
||||
@stoppedScrollingTimeoutId = setTimeout(@didStopScrolling.bind(this), @stoppedScrollingDelay)
|
||||
@state.scrollingVertically = true
|
||||
@state.content.scrollingVertically = true
|
||||
@emitter.emit 'did-update-state'
|
||||
|
||||
didStopScrolling: ->
|
||||
@state.scrollingVertically = false
|
||||
@state.content.scrollingVertically = false
|
||||
if @getMouseWheelScreenRow()?
|
||||
@mouseWheelScreenRow = null
|
||||
@updateLinesState()
|
||||
@@ -421,7 +442,7 @@ class TextEditorPresenter
|
||||
getScrollTop: -> @scrollTop
|
||||
|
||||
setScrollLeft: (@scrollLeft) ->
|
||||
@updateContentState()
|
||||
@updateHorizontalScrollState()
|
||||
|
||||
getScrollLeft: -> @scrollLeft
|
||||
|
||||
@@ -447,6 +468,7 @@ class TextEditorPresenter
|
||||
@height ? @model.getScreenLineCount() * @getLineHeight()
|
||||
|
||||
setContentFrameWidth: (@contentFrameWidth) ->
|
||||
@updateHorizontalScrollState()
|
||||
@updateScrollbarsState()
|
||||
@updateContentState()
|
||||
@updateLinesState()
|
||||
@@ -511,6 +533,7 @@ class TextEditorPresenter
|
||||
@characterWidthsChanged() unless @batchingCharacterMeasurement
|
||||
|
||||
characterWidthsChanged: ->
|
||||
@updateHorizontalScrollState()
|
||||
@updateContentState()
|
||||
@updateLinesState()
|
||||
@updateCursorsState()
|
||||
|
||||
Reference in New Issue
Block a user