Give each scrollbar its own state object and track visibility

This commit is contained in:
Nathan Sobo 2015-01-28 18:44:10 -07:00
parent 42ab02d7d2
commit 14776e3f0a
2 changed files with 92 additions and 14 deletions

View File

@ -77,20 +77,73 @@ describe "TextEditorPresenter", ->
expectStateUpdate presenter, -> advanceClock(100)
expect(presenter.state.scrollingVertically).toBe false
describe ".scrollbars", ->
describe ".horizontalHeight", ->
describe ".horizontalScrollbar", ->
describe ".visible", ->
it "is true if the scrollWidth exceeds the computed client width", ->
presenter = new TextEditorPresenter
model: editor
height: editor.getLineCount() * 10
contentFrameWidth: editor.getMaxScreenLineLength() * 10 + 1
baseCharacterWidth: 10
lineHeight: 10
horizontalScrollbarHeight: 10
verticalScrollbarWidth: 10
{state} = presenter
expect(state.horizontalScrollbar.visible).toBe false
# ::contentFrameWidth itself is smaller than scrollWidth
presenter.setContentFrameWidth(editor.getMaxScreenLineLength() * 10)
expect(state.horizontalScrollbar.visible).toBe true
# restore...
presenter.setContentFrameWidth(editor.getMaxScreenLineLength() * 10 + 1)
expect(state.horizontalScrollbar.visible).toBe false
# visible vertical scrollbar makes the clientWidth smaller than the scrollWidth
presenter.setHeight((editor.getLineCount() * 10) - 1)
expect(state.horizontalScrollbar.visible).toBe true
describe ".height", ->
it "tracks the value of ::horizontalScrollbarHeight", ->
presenter = new TextEditorPresenter(model: editor, horizontalScrollbarHeight: 10)
expect(presenter.state.scrollbars.horizontalHeight).toBe 10
expect(presenter.state.horizontalScrollbar.height).toBe 10
expectStateUpdate presenter, -> presenter.setHorizontalScrollbarHeight(20)
expect(presenter.state.scrollbars.horizontalHeight).toBe 20
expect(presenter.state.horizontalScrollbar.height).toBe 20
describe ".verticalWidth", ->
describe ".verticalScrollbar", ->
describe ".visible", ->
it "is true if the scrollHeight exceeds the computed client height", ->
presenter = new TextEditorPresenter
model: editor
height: editor.getLineCount() * 10
contentFrameWidth: editor.getMaxScreenLineLength() * 10 + 1
baseCharacterWidth: 10
lineHeight: 10
horizontalScrollbarHeight: 10
verticalScrollbarWidth: 10
{state} = presenter
expect(state.verticalScrollbar.visible).toBe false
# ::height itself is smaller than scrollWidth
presenter.setHeight(editor.getLineCount() * 10 - 1)
expect(state.verticalScrollbar.visible).toBe true
# restore...
presenter.setHeight(editor.getLineCount() * 10)
expect(state.verticalScrollbar.visible).toBe false
# visible horizontal scrollbar makes the clientHeight smaller than the scrollHeight
presenter.setContentFrameWidth(editor.getMaxScreenLineLength() * 10)
expect(state.verticalScrollbar.visible).toBe true
describe ".width", ->
it "is assigned based on ::verticalScrollbarWidth", ->
presenter = new TextEditorPresenter(model: editor, verticalScrollbarWidth: 10)
expect(presenter.state.scrollbars.verticalWidth).toBe 10
expect(presenter.state.verticalScrollbar.width).toBe 10
expectStateUpdate presenter, -> presenter.setVerticalScrollbarWidth(20)
expect(presenter.state.scrollbars.verticalWidth).toBe 20
expect(presenter.state.verticalScrollbar.width).toBe 20
describe ".content", ->
describe ".scrollWidth", ->

View File

@ -52,7 +52,8 @@ class TextEditorPresenter
buildState: ->
@state =
scrollingVertically: false
scrollbars: {}
horizontalScrollbar: {}
verticalScrollbar: {}
content:
blinkCursorsOff: false
lines: {}
@ -78,8 +79,24 @@ class TextEditorPresenter
@state.scrollTop = @getScrollTop()
updateScrollbarsState: ->
@state.scrollbars.horizontalHeight = @getHorizontalScrollbarHeight()
@state.scrollbars.verticalWidth = @getVerticalScrollbarWidth()
@state.horizontalScrollbar.height = @getHorizontalScrollbarHeight()
@state.verticalScrollbar.width = @getVerticalScrollbarWidth()
contentWidth = @computeContentWidth()
contentHeight = @computeContentHeight()
clientWidthWithoutVerticalScrollbar = @getContentFrameWidth()
clientWidthWithVerticalScrollbar = clientWidthWithoutVerticalScrollbar - @getVerticalScrollbarWidth()
clientHeightWithoutHorizontalScrollbar = @getHeight()
clientHeightWithHorizontalScrollbar = clientHeightWithoutHorizontalScrollbar - @getHorizontalScrollbarHeight()
@state.horizontalScrollbar.visible =
contentWidth > clientWidthWithoutVerticalScrollbar or
contentWidth > clientWidthWithVerticalScrollbar and contentHeight > clientHeightWithoutHorizontalScrollbar
@state.verticalScrollbar.visible =
contentHeight > clientHeightWithoutHorizontalScrollbar or
contentHeight > clientHeightWithHorizontalScrollbar and contentWidth > clientWidthWithoutVerticalScrollbar
@emitter.emit 'did-update-state'
updateContentState: ->
@ -309,12 +326,18 @@ class TextEditorPresenter
Math.min(@model.getScreenLineCount(), endRow)
computeScrollWidth: ->
contentWidth = @pixelPositionForScreenPosition([@model.getLongestScreenRow(), Infinity]).left
contentWidth += 1 unless @model.isSoftWrapped() # account for cursor width
Math.max(contentWidth, @getContentFrameWidth())
Math.max(@computeContentWidth(), @getContentFrameWidth())
computeScrollHeight: ->
Math.max(@getLineHeight() * @model.getScreenLineCount(), @getHeight())
Math.max(@computeContentHeight(), @getHeight())
computeContentWidth: ->
contentWidth = @pixelPositionForScreenPosition([@model.getLongestScreenRow(), Infinity]).left
contentWidth += 1 unless @model.isSoftWrapped() # account for cursor width
contentWidth
computeContentHeight: ->
@getLineHeight() * @model.getScreenLineCount()
lineDecorationClassesForRow: (row) ->
return null if @model.isMini()
@ -411,6 +434,7 @@ class TextEditorPresenter
setHeight: (@height) ->
@updateVerticalScrollState()
@updateScrollbarsState()
@updateLinesState()
@updateCursorsState()
@updateHighlightsState()
@ -420,6 +444,7 @@ class TextEditorPresenter
@height ? @model.getScreenLineCount() * @getLineHeight()
setContentFrameWidth: (@contentFrameWidth) ->
@updateScrollbarsState()
@updateContentState()
@updateLinesState()