diff --git a/spec/text-editor-component-spec.coffee b/spec/text-editor-component-spec.coffee index 832ca993d..ed910df5f 100644 --- a/spec/text-editor-component-spec.coffee +++ b/spec/text-editor-component-spec.coffee @@ -572,27 +572,27 @@ describe "TextEditorComponent", -> expect(lineNumbersNode.style.backgroundColor).toBe 'rgb(255, 0, 0)' it "hides or shows the gutter based on the '::isGutterVisible' property on the model and the global 'editor.showLineNumbers' config setting", -> - expect(component.refs.gutter?).toBe true + expect(component.gutterComponent?).toBe true editor.setGutterVisible(false) nextAnimationFrame() - expect(component.refs.gutter?).toBe false + expect(componentNode.querySelector('.gutter')).toBeNull() atom.config.set("editor.showLineNumbers", false) expect(nextAnimationFrame).toBe noAnimationFrame - expect(component.refs.gutter?).toBe false + expect(componentNode.querySelector('.gutter')).toBeNull() editor.setGutterVisible(true) expect(nextAnimationFrame).toBe noAnimationFrame - expect(component.refs.gutter?).toBe false + expect(componentNode.querySelector('.gutter')).toBeNull() atom.config.set("editor.showLineNumbers", true) nextAnimationFrame() - expect(component.refs.gutter?).toBe true + expect(componentNode.querySelector('.gutter')).toBeDefined() expect(component.lineNumberNodeForScreenRow(3)?).toBe true describe "fold decorations", -> diff --git a/src/gutter-component.coffee b/src/gutter-component.coffee index 2adfcc652..3209fe806 100644 --- a/src/gutter-component.coffee +++ b/src/gutter-component.coffee @@ -1,42 +1,29 @@ _ = require 'underscore-plus' -React = require 'react-atom-fork' -{div} = require 'reactionary-atom-fork' -{isEqual, isEqualForProperties, multiplyString, toArray} = _ -Decoration = require './decoration' -SubscriberMixin = require './subscriber-mixin' WrapperDiv = document.createElement('div') module.exports = -GutterComponent = React.createClass - displayName: 'GutterComponent' - mixins: [SubscriberMixin] - +class GutterComponent dummyLineNumberNode: null - measuredWidth: null - render: -> - div className: 'gutter', - div className: 'line-numbers', ref: 'lineNumbers' - - componentWillMount: -> + constructor: ({@presenter, @onMouseDown, @editor}) -> @lineNumberNodesById = {} - componentDidMount: -> - @updateSync() + @domNode = document.createElement('div') + @domNode.classList.add('gutter') + @lineNumbersNode = document.createElement('div') + @lineNumbersNode.classList.add('line-numbers') + @domNode.appendChild(@lineNumbersNode) - node = @getDOMNode() - node.addEventListener 'click', @onClick - node.addEventListener 'mousedown', @onMouseDown + @domNode.addEventListener 'click', @onClick + @domNode.addEventListener 'mousedown', @onMouseDown - componentDidUpdate: -> @updateSync() updateSync: -> - @newState = @props.presenter.state.gutter + @newState = @presenter.state.gutter @oldState ?= {lineNumbers: {}} - @lineNumbersNode ?= @refs.lineNumbers.getDOMNode() @appendDummyLineNumber() unless @dummyLineNumberNode? if @newState.scrollHeight isnt @oldState.scrollHeight @@ -64,7 +51,7 @@ GutterComponent = React.createClass appendDummyLineNumber: -> WrapperDiv.innerHTML = @buildLineNumberHTML({bufferRow: -1}) @dummyLineNumberNode = WrapperDiv.children[0] - @refs.lineNumbers.getDOMNode().appendChild(@dummyLineNumberNode) + @lineNumbersNode.appendChild(@dummyLineNumberNode) updateDummyLineNumber: -> @dummyLineNumberNode.innerHTML = @buildLineNumberInnerHTML(0, false) @@ -85,9 +72,9 @@ GutterComponent = React.createClass if newLineNumberIds? WrapperDiv.innerHTML = newLineNumbersHTML - newLineNumberNodes = toArray(WrapperDiv.children) + newLineNumberNodes = _.toArray(WrapperDiv.children) - node = @refs.lineNumbers.getDOMNode() + node = @lineNumbersNode for id, i in newLineNumberIds lineNumberNode = newLineNumberNodes[i] @lineNumberNodesById[id] = lineNumberNode @@ -118,7 +105,7 @@ GutterComponent = React.createClass else lineNumber = (bufferRow + 1).toString() - padding = multiplyString(' ', maxLineNumberDigits - lineNumber.length) + padding = _.multiplyString(' ', maxLineNumberDigits - lineNumber.length) iconHTML = '
' padding + lineNumber + iconHTML @@ -149,21 +136,20 @@ GutterComponent = React.createClass return @lineNumberNodesById[id] null - onMouseDown: (event) -> + onMouseDown: (event) => {target} = event lineNumber = target.parentNode unless target.classList.contains('icon-right') and lineNumber.classList.contains('foldable') - @props.onMouseDown(event) + @onMouseDown(event) - onClick: (event) -> - {editor} = @props + onClick: (event) => {target} = event lineNumber = target.parentNode if target.classList.contains('icon-right') and lineNumber.classList.contains('foldable') bufferRow = parseInt(lineNumber.getAttribute('data-buffer-row')) if lineNumber.classList.contains('folded') - editor.unfoldBufferRow(bufferRow) + @editor.unfoldBufferRow(bufferRow) else - editor.foldBufferRow(bufferRow) + @editor.foldBufferRow(bufferRow) diff --git a/src/text-editor-component.coffee b/src/text-editor-component.coffee index 833491c30..2655ce5b0 100644 --- a/src/text-editor-component.coffee +++ b/src/text-editor-component.coffee @@ -40,6 +40,7 @@ TextEditorComponent = React.createClass measureLineHeightAndDefaultCharWidthWhenShown: true remeasureCharacterWidthsWhenShown: false stylingChangeAnimationFrameRequested: false + gutterComponent: null render: -> {focused, showLineNumbers} = @state @@ -62,12 +63,6 @@ TextEditorComponent = React.createClass className += ' has-selection' if hasSelection div {className, style}, - if @gutterVisible - GutterComponent { - ref: 'gutter', onMouseDown: @onGutterMouseDown, - @presenter, editor - } - div ref: 'scrollView', className: 'scroll-view', InputComponent ref: 'input' @@ -121,6 +116,8 @@ TextEditorComponent = React.createClass componentDidMount: -> {editor, stylesElement, hostElement, useShadowDOM} = @props + @mountGutterComponent() if @gutterVisible + @linesComponent = new LinesComponent({@presenter, hostElement, useShadowDOM}) scrollViewNode = @refs.scrollView.getDOMNode() horizontalScrollbarNode = @refs.horizontalScrollbar.getDOMNode() @@ -158,6 +155,13 @@ TextEditorComponent = React.createClass @cursorMoved = false @selectionChanged = false + if @gutterVisible + @mountGutterComponent() unless @gutterComponent? + @gutterComponent.updateSync() + else + @gutterComponent?.domNode?.remove() + @gutterComponent = null + @linesComponent.updateSync(@isVisible()) if @props.editor.isAlive() @@ -167,6 +171,12 @@ TextEditorComponent = React.createClass @props.hostElement.__spacePenView.trigger 'selection:changed' if selectionChanged @props.hostElement.__spacePenView.trigger 'editor:display-updated' + mountGutterComponent: -> + {editor} = @props + @gutterComponent = new GutterComponent({@presenter, editor, onMouseDown: @onGutterMouseDown}) + node = @getDOMNode() + node.insertBefore(@gutterComponent.domNode, node.firstChild) + becameVisible: -> @updatesPaused = true @measureScrollbars() if @measureScrollbarsWhenShown @@ -680,8 +690,8 @@ TextEditorComponent = React.createClass @presenter.setBackgroundColor(backgroundColor) - if @refs.gutter? - gutterBackgroundColor = getComputedStyle(@refs.gutter.getDOMNode()).backgroundColor + if @gutterComponent? + gutterBackgroundColor = getComputedStyle(@gutterComponent.domNode).backgroundColor @presenter.setGutterBackgroundColor(gutterBackgroundColor) measureLineHeightAndDefaultCharWidth: -> @@ -761,7 +771,7 @@ TextEditorComponent = React.createClass lineNodeForScreenRow: (screenRow) -> @linesComponent.lineNodeForScreenRow(screenRow) - lineNumberNodeForScreenRow: (screenRow) -> @refs.gutter.lineNumberNodeForScreenRow(screenRow) + lineNumberNodeForScreenRow: (screenRow) -> @gutterComponent.lineNumberNodeForScreenRow(screenRow) screenRowForNode: (node) -> while node?