mirror of
https://github.com/atom/atom.git
synced 2026-01-24 06:18:03 -05:00
Constrain scrollTop based on clientHeight and scrollHeight
This commit is contained in:
@@ -223,11 +223,30 @@ describe "TextEditorPresenter", ->
|
||||
|
||||
describe ".scrollTop", ->
|
||||
it "tracks the value of ::scrollTop", ->
|
||||
presenter = new TextEditorPresenter(model: editor, scrollTop: 10, lineHeight: 10)
|
||||
presenter = new TextEditorPresenter(model: editor, scrollTop: 10, lineHeight: 10, height: 20)
|
||||
expect(presenter.state.verticalScrollbar.scrollTop).toBe 10
|
||||
expectStateUpdate presenter, -> presenter.setScrollTop(50)
|
||||
expect(presenter.state.verticalScrollbar.scrollTop).toBe 50
|
||||
|
||||
it "never exceeds the computed scroll height minus the computed client height", ->
|
||||
presenter = new TextEditorPresenter(model: editor, scrollTop: 10, lineHeight: 10, height: 50, horizontalScrollbarHeight: 10)
|
||||
expectStateUpdate presenter, -> presenter.setScrollTop(100)
|
||||
expect(presenter.state.verticalScrollbar.scrollTop).toBe presenter.computeScrollHeight() - presenter.computeClientHeight()
|
||||
|
||||
expectStateUpdate presenter, -> presenter.setHeight(60)
|
||||
expect(presenter.state.verticalScrollbar.scrollTop).toBe presenter.computeScrollHeight() - presenter.computeClientHeight()
|
||||
|
||||
expectStateUpdate presenter, -> presenter.setHorizontalScrollbarHeight(15)
|
||||
expect(presenter.state.verticalScrollbar.scrollTop).toBe presenter.computeScrollHeight() - presenter.computeClientHeight()
|
||||
|
||||
expectStateUpdate presenter, -> editor.getBuffer().delete([[8, 0], [12, 0]])
|
||||
expect(presenter.state.verticalScrollbar.scrollTop).toBe presenter.computeScrollHeight() - presenter.computeClientHeight()
|
||||
|
||||
# Scroll top only gets smaller when needed as dimensions change, never bigger
|
||||
scrollTopBefore = presenter.state.verticalScrollbar.scrollTop
|
||||
expectStateUpdate presenter, -> editor.getBuffer().insert([9, Infinity], '\n\n\n')
|
||||
expect(presenter.state.verticalScrollbar.scrollTop).toBe scrollTopBefore
|
||||
|
||||
describe ".content", ->
|
||||
describe ".scrollingVertically", ->
|
||||
it "is true for ::stoppedScrollingDelay milliseconds following a changes to ::scrollTop", ->
|
||||
@@ -323,11 +342,30 @@ describe "TextEditorPresenter", ->
|
||||
|
||||
describe ".scrollTop", ->
|
||||
it "tracks the value of ::scrollTop", ->
|
||||
presenter = new TextEditorPresenter(model: editor, scrollTop: 10, lineHeight: 10)
|
||||
presenter = new TextEditorPresenter(model: editor, scrollTop: 10, lineHeight: 10, height: 20)
|
||||
expect(presenter.state.content.scrollTop).toBe 10
|
||||
expectStateUpdate presenter, -> presenter.setScrollTop(50)
|
||||
expect(presenter.state.content.scrollTop).toBe 50
|
||||
|
||||
it "never exceeds the computed scroll height minus the computed client height", ->
|
||||
presenter = new TextEditorPresenter(model: editor, scrollTop: 10, lineHeight: 10, height: 50, horizontalScrollbarHeight: 10)
|
||||
expectStateUpdate presenter, -> presenter.setScrollTop(100)
|
||||
expect(presenter.state.content.scrollTop).toBe presenter.computeScrollHeight() - presenter.computeClientHeight()
|
||||
|
||||
expectStateUpdate presenter, -> presenter.setHeight(60)
|
||||
expect(presenter.state.content.scrollTop).toBe presenter.computeScrollHeight() - presenter.computeClientHeight()
|
||||
|
||||
expectStateUpdate presenter, -> presenter.setHorizontalScrollbarHeight(15)
|
||||
expect(presenter.state.content.scrollTop).toBe presenter.computeScrollHeight() - presenter.computeClientHeight()
|
||||
|
||||
expectStateUpdate presenter, -> editor.getBuffer().delete([[8, 0], [12, 0]])
|
||||
expect(presenter.state.content.scrollTop).toBe presenter.computeScrollHeight() - presenter.computeClientHeight()
|
||||
|
||||
# Scroll top only gets smaller when needed as dimensions change, never bigger
|
||||
scrollTopBefore = presenter.state.verticalScrollbar.scrollTop
|
||||
expectStateUpdate presenter, -> editor.getBuffer().insert([9, Infinity], '\n\n\n')
|
||||
expect(presenter.state.content.scrollTop).toBe scrollTopBefore
|
||||
|
||||
describe ".scrollLeft", ->
|
||||
it "tracks the value of ::scrollLeft", ->
|
||||
presenter = new TextEditorPresenter(model: editor, scrollLeft: 10, lineHeight: 10, lineOverdrawMargin: 1)
|
||||
@@ -1366,11 +1404,30 @@ describe "TextEditorPresenter", ->
|
||||
|
||||
describe ".scrollTop", ->
|
||||
it "tracks the value of ::scrollTop", ->
|
||||
presenter = new TextEditorPresenter(model: editor, scrollTop: 10, lineHeight: 10)
|
||||
presenter = new TextEditorPresenter(model: editor, scrollTop: 10, lineHeight: 10, height: 20)
|
||||
expect(presenter.state.gutter.scrollTop).toBe 10
|
||||
expectStateUpdate presenter, -> presenter.setScrollTop(50)
|
||||
expect(presenter.state.gutter.scrollTop).toBe 50
|
||||
|
||||
it "never exceeds the computed scroll height minus the computed client height", ->
|
||||
presenter = new TextEditorPresenter(model: editor, scrollTop: 10, lineHeight: 10, height: 50, horizontalScrollbarHeight: 10)
|
||||
expectStateUpdate presenter, -> presenter.setScrollTop(100)
|
||||
expect(presenter.state.gutter.scrollTop).toBe presenter.computeScrollHeight() - presenter.computeClientHeight()
|
||||
|
||||
expectStateUpdate presenter, -> presenter.setHeight(60)
|
||||
expect(presenter.state.gutter.scrollTop).toBe presenter.computeScrollHeight() - presenter.computeClientHeight()
|
||||
|
||||
expectStateUpdate presenter, -> presenter.setHorizontalScrollbarHeight(15)
|
||||
expect(presenter.state.gutter.scrollTop).toBe presenter.computeScrollHeight() - presenter.computeClientHeight()
|
||||
|
||||
expectStateUpdate presenter, -> editor.getBuffer().delete([[8, 0], [12, 0]])
|
||||
expect(presenter.state.gutter.scrollTop).toBe presenter.computeScrollHeight() - presenter.computeClientHeight()
|
||||
|
||||
# Scroll top only gets smaller when needed as dimensions change, never bigger
|
||||
scrollTopBefore = presenter.state.verticalScrollbar.scrollTop
|
||||
expectStateUpdate presenter, -> editor.getBuffer().insert([9, Infinity], '\n\n\n')
|
||||
expect(presenter.state.gutter.scrollTop).toBe scrollTopBefore
|
||||
|
||||
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)")
|
||||
|
||||
@@ -96,7 +96,7 @@ class TextEditorPresenter
|
||||
@state.gutter.scrollHeight = scrollHeight
|
||||
@state.verticalScrollbar.scrollHeight = scrollHeight
|
||||
|
||||
scrollTop = @scrollTop
|
||||
scrollTop = @computeScrollTop()
|
||||
@state.content.scrollTop = scrollTop
|
||||
@state.gutter.scrollTop = scrollTop
|
||||
@state.verticalScrollbar.scrollTop = scrollTop
|
||||
@@ -114,26 +114,16 @@ class TextEditorPresenter
|
||||
@emitter.emit 'did-update-state'
|
||||
|
||||
updateScrollbarsState: ->
|
||||
contentWidth = @computeContentWidth()
|
||||
contentHeight = @computeContentHeight()
|
||||
clientWidthWithoutVerticalScrollbar = @contentFrameWidth
|
||||
clientWidthWithVerticalScrollbar = clientWidthWithoutVerticalScrollbar - @verticalScrollbarWidth
|
||||
clientHeightWithoutHorizontalScrollbar = @getHeight()
|
||||
clientHeightWithHorizontalScrollbar = clientHeightWithoutHorizontalScrollbar - @horizontalScrollbarHeight
|
||||
horizontalScrollbarVisible =
|
||||
contentWidth > clientWidthWithoutVerticalScrollbar or
|
||||
contentWidth > clientWidthWithVerticalScrollbar and contentHeight > clientHeightWithoutHorizontalScrollbar
|
||||
verticalScrollbarVisible =
|
||||
contentHeight > clientHeightWithoutHorizontalScrollbar or
|
||||
contentHeight > clientHeightWithHorizontalScrollbar and contentWidth > clientWidthWithoutVerticalScrollbar
|
||||
horizontalScrollbarHeight = @computeHorizontalScrollbarHeight()
|
||||
verticalScrollbarWidth = @computeVerticalScrollbarWidth()
|
||||
|
||||
@state.horizontalScrollbar.visible = horizontalScrollbarVisible
|
||||
@state.horizontalScrollbar.visible = horizontalScrollbarHeight > 0
|
||||
@state.horizontalScrollbar.height = @horizontalScrollbarHeight
|
||||
@state.horizontalScrollbar.right = if verticalScrollbarVisible then @verticalScrollbarWidth else 0
|
||||
@state.horizontalScrollbar.right = verticalScrollbarWidth
|
||||
|
||||
@state.verticalScrollbar.visible = verticalScrollbarVisible
|
||||
@state.verticalScrollbar.visible = verticalScrollbarWidth > 0
|
||||
@state.verticalScrollbar.width = @verticalScrollbarWidth
|
||||
@state.verticalScrollbar.bottom = if horizontalScrollbarVisible then @horizontalScrollbarHeight else 0
|
||||
@state.verticalScrollbar.bottom = horizontalScrollbarHeight
|
||||
|
||||
@emitter.emit 'did-update-state'
|
||||
|
||||
@@ -324,11 +314,11 @@ class TextEditorPresenter
|
||||
regions
|
||||
|
||||
computeStartRow: ->
|
||||
startRow = Math.floor(@scrollTop / @lineHeight) - @lineOverdrawMargin
|
||||
startRow = Math.floor(@computeScrollTop() / @lineHeight) - @lineOverdrawMargin
|
||||
Math.max(0, startRow)
|
||||
|
||||
computeEndRow: ->
|
||||
startRow = Math.floor(@scrollTop / @lineHeight)
|
||||
startRow = Math.floor(@computeScrollTop() / @lineHeight)
|
||||
visibleLinesCount = Math.ceil(@getHeight() / @lineHeight) + 1
|
||||
endRow = startRow + visibleLinesCount + @lineOverdrawMargin
|
||||
Math.min(@model.getScreenLineCount(), endRow)
|
||||
@@ -347,6 +337,49 @@ class TextEditorPresenter
|
||||
computeContentHeight: ->
|
||||
@lineHeight * @model.getScreenLineCount()
|
||||
|
||||
computeClientHeight: ->
|
||||
@getHeight() - @computeHorizontalScrollbarHeight()
|
||||
|
||||
computeClientWidth: ->
|
||||
@contentFrameWidth - @computeVerticalScrollbarWidth()
|
||||
|
||||
computeScrollTop: ->
|
||||
@scrollTop = Math.min(@scrollTop, @computeScrollHeight() - @computeClientHeight())
|
||||
|
||||
computeHorizontalScrollbarHeight: ->
|
||||
contentWidth = @computeContentWidth()
|
||||
contentHeight = @computeContentHeight()
|
||||
clientWidthWithoutVerticalScrollbar = @contentFrameWidth
|
||||
clientWidthWithVerticalScrollbar = clientWidthWithoutVerticalScrollbar - @verticalScrollbarWidth
|
||||
clientHeightWithoutHorizontalScrollbar = @getHeight()
|
||||
clientHeightWithHorizontalScrollbar = clientHeightWithoutHorizontalScrollbar - @horizontalScrollbarHeight
|
||||
|
||||
horizontalScrollbarVisible =
|
||||
contentWidth > clientWidthWithoutVerticalScrollbar or
|
||||
contentWidth > clientWidthWithVerticalScrollbar and contentHeight > clientHeightWithoutHorizontalScrollbar
|
||||
|
||||
if horizontalScrollbarVisible
|
||||
@horizontalScrollbarHeight
|
||||
else
|
||||
0
|
||||
|
||||
computeVerticalScrollbarWidth: ->
|
||||
contentWidth = @computeContentWidth()
|
||||
contentHeight = @computeContentHeight()
|
||||
clientWidthWithoutVerticalScrollbar = @contentFrameWidth
|
||||
clientWidthWithVerticalScrollbar = clientWidthWithoutVerticalScrollbar - @verticalScrollbarWidth
|
||||
clientHeightWithoutHorizontalScrollbar = @getHeight()
|
||||
clientHeightWithHorizontalScrollbar = clientHeightWithoutHorizontalScrollbar - @horizontalScrollbarHeight
|
||||
|
||||
verticalScrollbarVisible =
|
||||
contentHeight > clientHeightWithoutHorizontalScrollbar or
|
||||
contentHeight > clientHeightWithHorizontalScrollbar and contentWidth > clientWidthWithoutVerticalScrollbar
|
||||
|
||||
if verticalScrollbarVisible
|
||||
@verticalScrollbarWidth
|
||||
else
|
||||
0
|
||||
|
||||
lineDecorationClassesForRow: (row) ->
|
||||
return null if @model.isMini()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user