Pass view measurements to model via presenter

Someday, we won’t need to pass measurements to the model anymore.
This commit is contained in:
Nathan Sobo
2015-02-04 14:48:17 -07:00
parent 9bdb961b3f
commit b94576dc09
3 changed files with 63 additions and 36 deletions

View File

@@ -137,7 +137,7 @@ describe "TextEditorPresenter", ->
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 = buildPresenter(contentFrameWidth: 50, baseCharacterWidth: 10)
presenter = buildPresenter(contentFrameWidth: 470, 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()
@@ -180,6 +180,11 @@ describe "TextEditorPresenter", ->
expectStateUpdate presenter, -> editor.getBuffer().insert([6, 0], new Array(100).join('x'))
expect(presenter.state.horizontalScrollbar.scrollLeft).toBe scrollLeftBefore
it "never goes negative", ->
presenter = buildPresenter(scrollLeft: 10, verticalScrollbarWidth: 10, contentFrameWidth: 500)
expectStateUpdate presenter, -> presenter.setScrollLeft(-300)
expect(presenter.state.horizontalScrollbar.scrollLeft).toBe 0
describe ".verticalScrollbar", ->
describe ".visible", ->
it "is true if the scrollHeight exceeds the computed client height", ->
@@ -278,6 +283,11 @@ describe "TextEditorPresenter", ->
expectStateUpdate presenter, -> editor.getBuffer().insert([9, Infinity], '\n\n\n')
expect(presenter.state.verticalScrollbar.scrollTop).toBe scrollTopBefore
it "never goes negative", ->
presenter = buildPresenter(scrollTop: 10, height: 50, horizontalScrollbarHeight: 10)
expectStateUpdate presenter, -> presenter.setScrollTop(-100)
expect(presenter.state.verticalScrollbar.scrollTop).toBe 0
describe ".content", ->
describe ".scrollingVertically", ->
it "is true for ::stoppedScrollingDelay milliseconds following a changes to ::scrollTop", ->
@@ -354,7 +364,7 @@ describe "TextEditorPresenter", ->
expect(presenter.state.content.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 = buildPresenter(contentFrameWidth: 50, baseCharacterWidth: 10)
presenter = buildPresenter(contentFrameWidth: 470, baseCharacterWidth: 10)
expect(presenter.state.content.scrollWidth).toBe 10 * editor.getMaxScreenLineLength() + 1
expectStateUpdate presenter, -> editor.setSoftWrapped(true)
expect(presenter.state.content.scrollWidth).toBe 10 * editor.getMaxScreenLineLength()
@@ -397,6 +407,12 @@ describe "TextEditorPresenter", ->
expectStateUpdate presenter, -> editor.getBuffer().insert([9, Infinity], '\n\n\n')
expect(presenter.state.content.scrollTop).toBe scrollTopBefore
it "never goes negative", ->
presenter = buildPresenter(scrollTop: 10, height: 50, horizontalScrollbarHeight: 10)
expectStateUpdate presenter, -> presenter.setScrollTop(-100)
expect(presenter.state.content.scrollTop).toBe 0
describe ".scrollLeft", ->
it "tracks the value of ::scrollLeft", ->
presenter = buildPresenter(scrollLeft: 10, lineHeight: 10, baseCharacterWidth: 10, verticalScrollbarWidth: 10, contentFrameWidth: 500)
expect(presenter.state.content.scrollLeft).toBe 10
@@ -422,6 +438,11 @@ describe "TextEditorPresenter", ->
expectStateUpdate presenter, -> editor.getBuffer().insert([6, 0], new Array(100).join('x'))
expect(presenter.state.content.scrollLeft).toBe scrollLeftBefore
it "never goes negative", ->
presenter = buildPresenter(scrollLeft: 10, verticalScrollbarWidth: 10, contentFrameWidth: 500)
expectStateUpdate presenter, -> presenter.setScrollLeft(-300)
expect(presenter.state.content.scrollLeft).toBe 0
describe ".indentGuidesVisible", ->
it "is initialized based on the editor.showIndentGuide config setting", ->
presenter = buildPresenter()
@@ -1477,6 +1498,11 @@ describe "TextEditorPresenter", ->
expectStateUpdate presenter, -> editor.getBuffer().insert([9, Infinity], '\n\n\n')
expect(presenter.state.gutter.scrollTop).toBe scrollTopBefore
it "never goes negative", ->
presenter = buildPresenter(scrollTop: 10, height: 50, horizontalScrollbarHeight: 10)
expectStateUpdate presenter, -> presenter.setScrollTop(-100)
expect(presenter.state.gutter.scrollTop).toBe 0
describe ".backgroundColor", ->
it "is assigned to ::gutterBackgroundColor if present, and to ::backgroundColor otherwise", ->
presenter = buildPresenter(backgroundColor: "rgba(255, 0, 0, 0)", gutterBackgroundColor: "rgba(0, 255, 0, 0)")

View File

@@ -230,8 +230,6 @@ TextEditorComponent = React.createClass
@subscribe editor.observeGrammar(@onGrammarChanged)
@subscribe editor.observeCursors(@onCursorAdded)
@subscribe editor.observeSelections(@onSelectionAdded)
@subscribe editor.$scrollTop.changes, @onScrollTopChanged
@subscribe editor.$scrollLeft.changes, @onScrollLeftChanged
@subscribe editor.$verticalScrollbarWidth.changes, @requestUpdate
@subscribe editor.$horizontalScrollbarHeight.changes, @requestUpdate
@subscribe editor.$height.changes, @requestUpdate
@@ -356,7 +354,6 @@ TextEditorComponent = React.createClass
pendingScrollTop = @pendingScrollTop
@pendingScrollTop = null
@presenter.setScrollTop(pendingScrollTop)
@props.editor.setScrollTop(pendingScrollTop)
onHorizontalScroll: (scrollLeft) ->
{editor} = @props
@@ -367,7 +364,6 @@ TextEditorComponent = React.createClass
@pendingScrollLeft = scrollLeft
unless animationFramePending
@requestAnimationFrame =>
@props.editor.setScrollLeft(@pendingScrollLeft)
@presenter.setScrollLeft(@pendingScrollLeft)
@pendingScrollLeft = null
@@ -389,13 +385,13 @@ TextEditorComponent = React.createClass
if Math.abs(wheelDeltaX) > Math.abs(wheelDeltaY)
# Scrolling horizontally
previousScrollLeft = editor.getScrollLeft()
editor.setScrollLeft(previousScrollLeft - Math.round(wheelDeltaX * @scrollSensitivity))
@presenter.setScrollLeft(previousScrollLeft - Math.round(wheelDeltaX * @scrollSensitivity))
event.preventDefault() unless previousScrollLeft is editor.getScrollLeft()
else
# Scrolling vertically
@presenter.setMouseWheelScreenRow(@screenRowForNode(event.target))
previousScrollTop = editor.getScrollTop()
editor.setScrollTop(previousScrollTop - Math.round(wheelDeltaY * @scrollSensitivity))
previousScrollTop = @presenter.scrollTop
@presenter.setScrollTop(previousScrollTop - Math.round(wheelDeltaY * @scrollSensitivity))
event.preventDefault() unless previousScrollTop is editor.getScrollTop()
onScrollViewScroll: ->
@@ -550,24 +546,6 @@ TextEditorComponent = React.createClass
@selectionChanged = true
@requestUpdate()
onScrollTopChanged: ->
@presenter.setScrollTop(@props.editor.getScrollTop())
@requestUpdate()
@onStoppedScrollingAfterDelay ?= debounce(@onStoppedScrolling, 200)
@onStoppedScrollingAfterDelay()
onScrollLeftChanged: ->
@presenter.setScrollLeft(@props.editor.getScrollLeft())
@requestUpdate()
onStoppedScrolling: ->
return unless @isMounted()
@mouseWheelScreenRow = null
@requestUpdate()
onStoppedScrollingAfterDelay: null # created lazily
onCursorAdded: (cursor) ->
@subscribe cursor.onDidChangePosition @onCursorMoved
@@ -675,18 +653,15 @@ TextEditorComponent = React.createClass
height = hostElement.offsetHeight
if height > 0
@presenter.setHeight(height)
editor.setHeight(height)
else
@presenter.setAutoHeight(true)
@presenter.setHeight(null)
editor.setHeight(null)
clientWidth = scrollViewNode.clientWidth
paddingLeft = parseInt(getComputedStyle(scrollViewNode).paddingLeft)
clientWidth -= paddingLeft
if clientWidth > 0
@presenter.setContentFrameWidth(clientWidth)
editor.setWidth(clientWidth)
sampleFontStyling: ->
oldFontSize = @fontSize
@@ -737,9 +712,7 @@ TextEditorComponent = React.createClass
width = (cornerNode.offsetWidth - cornerNode.clientWidth) or 15
height = (cornerNode.offsetHeight - cornerNode.clientHeight) or 15
editor.setVerticalScrollbarWidth(width)
@presenter.setVerticalScrollbarWidth(width)
editor.setHorizontalScrollbarHeight(height)
@presenter.setHorizontalScrollbarHeight(height)
cornerNode.style.display = originalDisplayValue

View File

@@ -18,6 +18,7 @@ class TextEditorPresenter
@disposables = new CompositeDisposable
@emitter = new Emitter
@charWidthsByScope = {}
@transferMeasurementsToModel()
@observeModel()
@observeConfig()
@buildState()
@@ -29,6 +30,16 @@ class TextEditorPresenter
onDidUpdateState: (callback) ->
@emitter.on 'did-update-state', callback
transferMeasurementsToModel: ->
@model.setHeight(@height) if @height?
@model.setWidth(@contentFrameWidth) if @contentFrameWidth?
@model.setLineHeightInPixels(@lineHeight) if @lineHeight?
@model.setDefaultCharWidth(@baseCharacterWidth) if @baseCharacterWidth?
@model.setScrollTop(@scrollTop) if @scrollTop?
@model.setScrollLeft(@scrollLeft) if @scrollLeft?
@model.setVerticalScrollbarWidth(@verticalScrollbarWidth) if @verticalScrollbarWidth?
@model.setHorizontalScrollbarHeight(@horizontalScrollbarHeight) if @horizontalScrollbarHeight?
observeModel: ->
@disposables.add @model.onDidChange =>
@updateHeightState()
@@ -49,6 +60,8 @@ class TextEditorPresenter
@updateLineNumbersState()
@disposables.add @model.onDidAddDecoration(@didAddDecoration.bind(this))
@disposables.add @model.onDidAddCursor(@didAddCursor.bind(this))
@disposables.add @model.onDidChangeScrollTop(@setScrollTop.bind(this))
@disposables.add @model.onDidChangeScrollLeft(@setScrollLeft.bind(this))
@observeDecoration(decoration) for decoration in @model.getDecorations()
@observeCursor(cursor) for cursor in @model.getCursors()
@@ -346,16 +359,22 @@ class TextEditorPresenter
@contentFrameWidth - @computeVerticalScrollbarWidth()
computeScrollTop: ->
@scrollTop = @constrainScrollTop(@scrollTop)
constrainScrollTop: (scrollTop) ->
if @hasRequiredMeasurements()
@scrollTop = Math.min(@scrollTop, @computeScrollHeight() - @computeClientHeight())
Math.max(0, Math.min(scrollTop, @computeScrollHeight() - @computeClientHeight()))
else
@scrollTop
Math.max(0, scrollTop) if scrollTop?
computeScrollLeft: ->
@scrollLeft = @constrainScrollLeft(@scrollLeft)
constrainScrollLeft: (scrollLeft) ->
if @hasRequiredMeasurements()
@scrollLeft = Math.min(@scrollLeft, @computeScrollWidth() - @computeClientWidth())
Math.max(0, Math.min(scrollLeft, @computeScrollWidth() - @computeClientWidth()))
else
@scrollLeft
Math.max(0, scrollLeft) if scrollLeft?
computeHorizontalScrollbarHeight: ->
contentWidth = @computeContentWidth()
@@ -423,8 +442,10 @@ class TextEditorPresenter
@horizontalScrollbarHeight?
setScrollTop: (scrollTop) ->
scrollTop = @constrainScrollTop(scrollTop)
unless @scrollTop is scrollTop
@scrollTop = scrollTop
@model.setScrollTop(scrollTop)
@didStartScrolling()
@updateVerticalScrollState()
@updateDecorations()
@@ -450,19 +471,23 @@ class TextEditorPresenter
@emitter.emit 'did-update-state'
setScrollLeft: (scrollLeft) ->
scrollLeft = @constrainScrollLeft(scrollLeft)
unless @scrollLeft is scrollLeft
@scrollLeft = scrollLeft
@model.setScrollLeft(scrollLeft)
@updateHorizontalScrollState()
setHorizontalScrollbarHeight: (horizontalScrollbarHeight) ->
unless @horizontalScrollbarHeight is horizontalScrollbarHeight
@horizontalScrollbarHeight = horizontalScrollbarHeight
@model.setHorizontalScrollbarHeight(horizontalScrollbarHeight)
@updateScrollbarsState()
@updateVerticalScrollState()
setVerticalScrollbarWidth: (verticalScrollbarWidth) ->
unless @verticalScrollbarWidth is verticalScrollbarWidth
@verticalScrollbarWidth = verticalScrollbarWidth
@model.setVerticalScrollbarWidth(verticalScrollbarWidth)
@updateScrollbarsState()
@updateHorizontalScrollState()
@@ -474,6 +499,7 @@ class TextEditorPresenter
setHeight: (height) ->
unless @height is height
@height = height
@model.setHeight(height)
@updateVerticalScrollState()
@updateScrollbarsState()
@updateDecorations()
@@ -487,6 +513,7 @@ class TextEditorPresenter
setContentFrameWidth: (contentFrameWidth) ->
unless @contentFrameWidth is contentFrameWidth
@contentFrameWidth = contentFrameWidth
@model.setWidth(contentFrameWidth)
@updateVerticalScrollState()
@updateHorizontalScrollState()
@updateScrollbarsState()
@@ -523,6 +550,7 @@ class TextEditorPresenter
setBaseCharacterWidth: (baseCharacterWidth) ->
unless @baseCharacterWidth is baseCharacterWidth
@baseCharacterWidth = baseCharacterWidth
@model.setDefaultCharWidth(baseCharacterWidth)
@characterWidthsChanged()
getScopedCharWidth: (scopeNames, char) ->