From bdd605e85bf64215e7d197f7caa6a46bd16d7056 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 2 May 2014 12:32:03 -0700 Subject: [PATCH] Explicitly assign dummy scrollbars to the correct width/height Previously, dummy scrollbars were always 15px wide/tall. This caused them to obscure the ability to click for the entire 15px region, even if the actual scrollbar was styled to be much thinner. Now we explicitly measure the size of scrollbars on mount and when the stylesheets change and set the height/width explicitly. --- spec/editor-component-spec.coffee | 15 ++++++++++++ src/editor-component.coffee | 33 ++++++++++++++++++++++++--- src/scrollbar-component.coffee | 2 ++ src/scrollbar-corner-component.coffee | 7 +++++- 4 files changed, 53 insertions(+), 4 deletions(-) diff --git a/spec/editor-component-spec.coffee b/spec/editor-component-spec.coffee index d9129d8af..db29d751c 100644 --- a/spec/editor-component-spec.coffee +++ b/spec/editor-component-spec.coffee @@ -603,6 +603,21 @@ describe "EditorComponent", -> expect(verticalScrollbarNode.style.display).toBe 'none' expect(horizontalScrollbarNode.style.display).toBe '' + it "makes the dummy scrollbar divs only as tall/wide as the actual scrollbars", -> + atom.themes.applyStylesheet "test", """ + ::-webkit-scrollbar { + width: 8px; + height: 8px; + } + """ + + node.style.height = 4 * lineHeightInPixels + 'px' + node.style.width = 10 * charWidth + 'px' + component.measureHeightAndWidth() + + expect(verticalScrollbarNode.offsetWidth).toBe 8 + expect(horizontalScrollbarNode.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') diff --git a/src/editor-component.coffee b/src/editor-component.coffee index 5f808fff0..062e6f213 100644 --- a/src/editor-component.coffee +++ b/src/editor-component.coffee @@ -22,6 +22,7 @@ EditorComponent = React.createClass preservedRowRange: null scrollingVertically: false gutterWidth: 0 + measuringScrollbars: true render: -> {focused, fontSize, lineHeight, fontFamily, showIndentGuide} = @state @@ -64,8 +65,9 @@ EditorComponent = React.createClass onScroll: @onVerticalScroll scrollTop: scrollTop scrollHeight: scrollHeight - visible: verticallyScrollable + visible: not @measuringScrollbars and verticallyScrollable scrollableInOppositeDirection: horizontallyScrollable + verticalScrollbarWidth: verticalScrollbarWidth horizontalScrollbarHeight: horizontalScrollbarHeight ScrollbarComponent @@ -75,12 +77,16 @@ EditorComponent = React.createClass onScroll: @onHorizontalScroll scrollLeft: scrollLeft scrollWidth: scrollWidth + @gutterWidth - visible: horizontallyScrollable + visible: not @measuringScrollbars and horizontallyScrollable scrollableInOppositeDirection: verticallyScrollable verticalScrollbarWidth: verticalScrollbarWidth + horizontalScrollbarHeight: horizontalScrollbarHeight + # Also used to measure the height/width of scrollbars after the initial render ScrollbarCornerComponent - visible: horizontallyScrollable and verticallyScrollable + ref: 'scrollbarCorner' + visible: @measuringScrollbars or horizontallyScrollable and verticallyScrollable + measuringScrollbars: @measuringScrollbars height: horizontalScrollbarHeight width: verticalScrollbarWidth @@ -106,6 +112,8 @@ EditorComponent = React.createClass @observeEditor() @listenForDOMEvents() @listenForCommands() + @measureScrollbars() + @subscribe atom.themes, 'stylesheets-changed', @onStylesheetsChanged @props.editor.setVisible(true) @requestUpdate() @@ -119,6 +127,7 @@ EditorComponent = React.createClass componentDidUpdate: -> @pendingChanges.length = 0 @cursorsMoved = false + @measureScrollbars() if @measuringScrollbars @props.parentView.trigger 'editor:display-updated' observeEditor: -> @@ -250,6 +259,14 @@ EditorComponent = React.createClass @subscribe atom.config.observe 'editor.fontSize', @setFontSize @subscribe atom.config.observe 'editor.showIndentGuide', @setShowIndentGuide + measureScrollbars: -> + @measuringScrollbars = false + + {editor} = @props + scrollbarCornerNode = @refs.scrollbarCorner.getDOMNode() + editor.setVerticalScrollbarWidth(scrollbarCornerNode.offsetWidth - scrollbarCornerNode.clientWidth) + editor.setHorizontalScrollbarHeight(scrollbarCornerNode.offsetHeight - scrollbarCornerNode.clientHeight) + setFontSize: (fontSize) -> @setState({fontSize}) @@ -305,6 +322,16 @@ EditorComponent = React.createClass event.preventDefault() + onStylesheetsChanged: -> + # Request that scrollbars be re-measured. This hides both scrollbars and + # measures the scrollbar corner. + @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. + @requestUpdate() + clearPreservedRowRange: -> @preservedRowRange = null @scrollingVertically = false diff --git a/src/scrollbar-component.coffee b/src/scrollbar-component.coffee index 4acbb5743..a4482f21d 100644 --- a/src/scrollbar-component.coffee +++ b/src/scrollbar-component.coffee @@ -12,8 +12,10 @@ ScrollbarComponent = React.createClass style.display = 'none' unless visible switch orientation when 'vertical' + style.width = verticalScrollbarWidth style.bottom = horizontalScrollbarHeight if scrollableInOppositeDirection when 'horizontal' + style.height = horizontalScrollbarHeight style.right = verticalScrollbarWidth if scrollableInOppositeDirection div {className, style, @onScroll}, diff --git a/src/scrollbar-corner-component.coffee b/src/scrollbar-corner-component.coffee index 8d1d2fdca..edcfc8389 100644 --- a/src/scrollbar-corner-component.coffee +++ b/src/scrollbar-corner-component.coffee @@ -4,7 +4,12 @@ React = require 'react' module.exports = ScrollbarComponent = React.createClass render: -> - {visible, width, height} = @props + {visible, measuringScrollbars, width, height} = @props + + if measuringScrollbars + height = 25 + width = 25 + display = 'none' unless visible div className: 'scrollbar-corner', style: {display, width, height},