Hide and show scrollbars before measuring them after stylesheet changes

We measure the scrollbar-corner node when there's a stylesheet change,
but Chromium won't apply the new style if it was already visible before
the change. This commit hides and shows it before measuring so we get
accurate values.
This commit is contained in:
Nathan Sobo
2014-05-02 13:28:29 -07:00
parent bdd605e85b
commit 1c1ace90db
2 changed files with 26 additions and 11 deletions

View File

@@ -604,6 +604,10 @@ describe "EditorComponent", ->
expect(horizontalScrollbarNode.style.display).toBe ''
it "makes the dummy scrollbar divs only as tall/wide as the actual scrollbars", ->
node.style.height = 4 * lineHeightInPixels + 'px'
node.style.width = 10 * charWidth + 'px'
component.measureHeightAndWidth()
atom.themes.applyStylesheet "test", """
::-webkit-scrollbar {
width: 8px;
@@ -611,12 +615,11 @@ describe "EditorComponent", ->
}
"""
node.style.height = 4 * lineHeightInPixels + 'px'
node.style.width = 10 * charWidth + 'px'
component.measureHeightAndWidth()
scrollbarCornerNode = node.querySelector('.scrollbar-corner')
expect(verticalScrollbarNode.offsetWidth).toBe 8
expect(horizontalScrollbarNode.offsetHeight).toBe 8
expect(scrollbarCornerNode.offsetWidth).toBe 8
expect(scrollbarCornerNode.offsetHeight).toBe 8
it "assigns the bottom/right of the scrollbars to the width of the opposite scrollbar if it is visible", ->
scrollbarCornerNode = node.querySelector('.scrollbar-corner')

View File

@@ -22,6 +22,7 @@ EditorComponent = React.createClass
preservedRowRange: null
scrollingVertically: false
gutterWidth: 0
refreshingScrollbars: false
measuringScrollbars: true
render: ->
@@ -65,7 +66,7 @@ EditorComponent = React.createClass
onScroll: @onVerticalScroll
scrollTop: scrollTop
scrollHeight: scrollHeight
visible: not @measuringScrollbars and verticallyScrollable
visible: verticallyScrollable and not @refreshingScrollbars and not @measuringScrollbars
scrollableInOppositeDirection: horizontallyScrollable
verticalScrollbarWidth: verticalScrollbarWidth
horizontalScrollbarHeight: horizontalScrollbarHeight
@@ -77,7 +78,7 @@ EditorComponent = React.createClass
onScroll: @onHorizontalScroll
scrollLeft: scrollLeft
scrollWidth: scrollWidth + @gutterWidth
visible: not @measuringScrollbars and horizontallyScrollable
visible: horizontallyScrollable and not @refreshingScrollbars and not @measuringScrollbars
scrollableInOppositeDirection: verticallyScrollable
verticalScrollbarWidth: verticalScrollbarWidth
horizontalScrollbarHeight: horizontalScrollbarHeight
@@ -85,7 +86,7 @@ EditorComponent = React.createClass
# Also used to measure the height/width of scrollbars after the initial render
ScrollbarCornerComponent
ref: 'scrollbarCorner'
visible: @measuringScrollbars or horizontallyScrollable and verticallyScrollable
visible: not @refreshingScrollbars and (@measuringScrollbars or horizontallyScrollable and verticallyScrollable)
measuringScrollbars: @measuringScrollbars
height: horizontalScrollbarHeight
width: verticalScrollbarWidth
@@ -127,6 +128,7 @@ EditorComponent = React.createClass
componentDidUpdate: ->
@pendingChanges.length = 0
@cursorsMoved = false
@refreshingScrollbars = false
@measureScrollbars() if @measuringScrollbars
@props.parentView.trigger 'editor:display-updated'
@@ -323,13 +325,23 @@ EditorComponent = React.createClass
event.preventDefault()
onStylesheetsChanged: ->
# Request that scrollbars be re-measured. This hides both scrollbars and
# measures the scrollbar corner.
# Believe it or not, proper handling of changes to scrollbar styles requires
# three DOM updates.
# Scrollbar style changes won't apply to scrollbars that are already
# visible, so first we need to hide scrollbars so we can redisplay them and
# force Chromium to apply updates.
@refreshingScrollbars = true
@requestUpdate()
# Next, we display only the scrollbar corner so we can measure the new
# scrollbar dimensions. The ::measuringScrollbars property will be set back
# to false after the scrollbars are measured.
@measuringScrollbars = true
@requestUpdate()
# Update again now that the scrollbars have been measured. This makes them
# visible again if necessary, and ensures they are the correct width/height.
# Finally, we restore the scrollbars based on the newly-measured dimensions
# if the editor's content and dimensions require them to be visible.
@requestUpdate()
clearPreservedRowRange: ->