diff --git a/spec/text-editor-component-spec.coffee b/spec/text-editor-component-spec.coffee index d4a64c300..f576685c3 100644 --- a/spec/text-editor-component-spec.coffee +++ b/spec/text-editor-component-spec.coffee @@ -706,13 +706,13 @@ describe "TextEditorComponent", -> cursorNodes = componentNode.querySelectorAll('.cursor') expect(cursorNodes.length).toBe 2 - expect(cursorNodes[0].style['-webkit-transform']).toBe "translate(#{11 * charWidth}px, #{8 * lineHeightInPixels}px)" - expect(cursorNodes[1].style['-webkit-transform']).toBe "translate(#{10 * charWidth}px, #{4 * lineHeightInPixels}px)" + expect(cursorNodes[0].style['-webkit-transform']).toBe "translate(#{10 * charWidth}px, #{4 * lineHeightInPixels}px)" + expect(cursorNodes[1].style['-webkit-transform']).toBe "translate(#{11 * charWidth}px, #{8 * lineHeightInPixels}px)" wrapperView.on 'cursor:moved', cursorMovedListener = jasmine.createSpy('cursorMovedListener') cursor3.setScreenPosition([4, 11], autoscroll: false) nextAnimationFrame() - expect(cursorNodes[1].style['-webkit-transform']).toBe "translate(#{11 * charWidth}px, #{4 * lineHeightInPixels}px)" + expect(cursorNodes[0].style['-webkit-transform']).toBe "translate(#{11 * charWidth}px, #{4 * lineHeightInPixels}px)" expect(cursorMovedListener).toHaveBeenCalled() cursor3.destroy() diff --git a/src/cursor-component.coffee b/src/cursor-component.coffee deleted file mode 100644 index ec7e04c1c..000000000 --- a/src/cursor-component.coffee +++ /dev/null @@ -1,14 +0,0 @@ -React = require 'react-atom-fork' -{div} = require 'reactionary-atom-fork' -{isEqualForProperties} = require 'underscore-plus' - -module.exports = -CursorComponent = React.createClass - displayName: 'CursorComponent' - - render: -> - {pixelRect} = @props - {top, left, height, width} = pixelRect - WebkitTransform = "translate(#{left}px, #{top}px)" - - div className: 'cursor', style: {height, width, WebkitTransform} diff --git a/src/cursors-component.coffee b/src/cursors-component.coffee index 646618e9b..bf704a1a5 100644 --- a/src/cursors-component.coffee +++ b/src/cursors-component.coffee @@ -2,18 +2,67 @@ React = require 'react-atom-fork' {div} = require 'reactionary-atom-fork' {debounce, toArray, isEqualForProperties, isEqual} = require 'underscore-plus' SubscriberMixin = require './subscriber-mixin' -CursorComponent = require './cursor-component' module.exports = CursorsComponent = React.createClass displayName: 'CursorsComponent' + oldState: null + cursorNodesById: null render: -> - {presenter} = @props + div className: 'cursors' - className = 'cursors' - className += ' blink-off' if presenter.state.content.blinkCursorsOff + componentWillMount: -> + @cursorNodesById = {} - div {className}, - for key, pixelRect of presenter.state.content.cursors - CursorComponent({key, pixelRect}) + componentDidMount: -> + @updateSync() + + componentDidUpdate: -> + @updateSync() + + updateSync: -> + node = @getDOMNode() + newState = @props.presenter.state.content + @oldState ?= {cursors: {}} + + # update blink class + if newState.blinkCursorsOff isnt @oldState.blinkCursorsOff + if newState.blinkCursorsOff + node.classList.add 'blink-off' + else + node.classList.remove 'blink-off' + @oldState.blinkCursorsOff = newState.blinkCursorsOff + + # remove cursors + for id of @oldState.cursors + unless newState.cursors[id]? + @cursorNodesById[id].remove() + delete @cursorNodesById[id] + delete @oldState.cursors[id] + + # add or update cursors + for id, cursorState of newState.cursors + unless @oldState.cursors[id]? + cursorNode = document.createElement('div') + cursorNode.classList.add('cursor') + @cursorNodesById[id] = cursorNode + node.appendChild(cursorNode) + @updateCursorNode(id, cursorState) + + updateCursorNode: (id, newCursorState) -> + cursorNode = @cursorNodesById[id] + oldCursorState = (@oldState.cursors[id] ?= {}) + + if newCursorState.top isnt oldCursorState.top or newCursorState.left isnt oldCursorState.left + cursorNode.style['-webkit-transform'] = "translate(#{newCursorState.left}px, #{newCursorState.top}px)" + oldCursorState.top = newCursorState.top + oldCursorState.left = newCursorState.left + + if newCursorState.height isnt oldCursorState.height + cursorNode.style.height = newCursorState.height + 'px' + oldCursorState.height = newCursorState.height + + if newCursorState.width isnt oldCursorState.width + cursorNode.style.width = newCursorState.width + 'px' + oldCursorState.width = newCursorState.width