diff --git a/src/app/anchor.coffee b/src/app/anchor.coffee index 689216e6e..676d3e97f 100644 --- a/src/app/anchor.coffee +++ b/src/app/anchor.coffee @@ -1,4 +1,6 @@ Point = require 'point' +EventEmitter = require 'event-emitter' +_ = require 'underscore' module.exports = class Anchor @@ -21,7 +23,7 @@ class Anchor newColumn = position.column newRow += position.row - oldRange.end.row - @setBufferPosition [newRow, newColumn] + @setBufferPosition([newRow, newColumn], bufferChange: true) getBufferPosition: -> @bufferPosition @@ -36,6 +38,7 @@ class Anchor @screenPosition setScreenPosition: (position, options={}) -> + previousScreenPosition = @screenPosition @screenPosition = Point.fromObject(position) clip = options.clip ? true assignBufferPosition = options.assignBufferPosition ? true @@ -46,7 +49,11 @@ class Anchor Object.freeze @screenPosition Object.freeze @bufferPosition - refreshScreenPosition: (options) -> - screenPosition = @editSession.screenPositionForBufferPosition(@bufferPosition, options) - @setScreenPosition(screenPosition, clip: false, assignBufferPosition: false) + unless @screenPosition.isEqual(previousScreenPosition) + @trigger 'change-screen-position', @screenPosition, bufferChange: options.bufferChange + refreshScreenPosition: (options={}) -> + screenPosition = @editSession.screenPositionForBufferPosition(@bufferPosition, options) + @setScreenPosition(screenPosition, bufferChange: options.bufferChange, clip: false, assignBufferPosition: false) + +_.extend(Anchor.prototype, EventEmitter) diff --git a/src/app/cursor.coffee b/src/app/cursor.coffee index 7db99eb49..9596280fe 100644 --- a/src/app/cursor.coffee +++ b/src/app/cursor.coffee @@ -12,28 +12,28 @@ class Cursor wordRegex: /(\w+)|([^\w\s]+)/g constructor: ({@editSession, screenPosition, bufferPosition}) -> - @anchor = new Anchor(@editSession) + @anchor = @editSession.addAnchor() + @anchor.on 'change-screen-position', (args...) => @trigger 'change-screen-position', args... @setScreenPosition(screenPosition) if screenPosition @setBufferPosition(bufferPosition) if bufferPosition destroy: -> + @editSession.removeAnchor(@anchor) @editSession.removeCursor(this) @trigger 'destroy' setScreenPosition: (screenPosition, options) -> - @anchor.setScreenPosition(screenPosition, options) @goalColumn = null @clearSelection() - @trigger 'change-screen-position', @getScreenPosition(), bufferChange: false + @anchor.setScreenPosition(screenPosition, options) getScreenPosition: -> @anchor.getScreenPosition() setBufferPosition: (bufferPosition, options) -> - @anchor.setBufferPosition(bufferPosition, options) @goalColumn = null @clearSelection() - @trigger 'change-screen-position', @getScreenPosition(), bufferChange: false + @anchor.setBufferPosition(bufferPosition, options) getBufferPosition: -> @anchor.getBufferPosition() @@ -53,11 +53,6 @@ class Cursor refreshScreenPosition: -> @anchor.refreshScreenPosition() - @trigger 'change-screen-position', @getScreenPosition(), bufferChange: false - - handleBufferChange: (e) -> - @anchor.handleBufferChange(e) - @trigger 'change-screen-position', @getScreenPosition(), bufferChange: true moveUp: -> { row, column } = @getScreenPosition() diff --git a/src/app/edit-session.coffee b/src/app/edit-session.coffee index d505e515f..db90fa96c 100644 --- a/src/app/edit-session.coffee +++ b/src/app/edit-session.coffee @@ -1,5 +1,6 @@ Point = require 'point' Buffer = require 'buffer' +Anchor = require 'anchor' DisplayBuffer = require 'display-buffer' Cursor = require 'cursor' Selection = require 'selection' @@ -20,6 +21,7 @@ class EditSession scrollTop: 0 scrollLeft: 0 displayBuffer: null + anchors: null cursors: null selections: null autoIndent: true @@ -31,17 +33,19 @@ class EditSession @softTabs ?= true @displayBuffer = new DisplayBuffer(@buffer, { @tabText }) @tokenizedBuffer = @displayBuffer.tokenizedBuffer + @anchors = [] @cursors = [] @selections = [] @addCursorAtScreenPosition([0, 0]) @buffer.on "change.edit-session-#{@id}", (e) => - for selection in @getSelections() - selection.handleBufferChange(e) + anchor.handleBufferChange(e) for anchor in @getAnchors() + @mergeCursors() @displayBuffer.on "change.edit-session-#{@id}", (e) => @trigger 'screen-lines-change', e - @moveCursors (cursor) -> cursor.refreshScreenPosition() unless e.bufferChanged + unless e.bufferChanged + anchor.refreshScreenPosition() for anchor in @getAnchors() destroy: -> @buffer.off ".edit-session-#{@id}" @@ -227,6 +231,17 @@ class EditSession fn(selection) for selection in selections @buffer.endUndoBatch(@getSelectedBufferRanges()) + getAnchors: -> + new Array(@anchors...) + + addAnchor: -> + anchor = new Anchor(this) + @anchors.push(anchor) + anchor + + removeAnchor: (anchor) -> + _.remove(@anchors, anchor) + getCursors: -> new Array(@cursors...) getCursor: (index=0) -> diff --git a/src/app/point.coffee b/src/app/point.coffee index ab7991dea..27d68188e 100644 --- a/src/app/point.coffee +++ b/src/app/point.coffee @@ -56,6 +56,7 @@ class Point 0 isEqual: (other) -> + return false unless other other = Point.fromObject(other) @row == other.row and @column == other.column diff --git a/src/app/selection.coffee b/src/app/selection.coffee index 0cacf5a08..2569a3a27 100644 --- a/src/app/selection.coffee +++ b/src/app/selection.coffee @@ -68,7 +68,9 @@ class Selection @editSession.buffer.getTextInRange(@getBufferRange()) clear: -> - @modifyScreenRange => @anchor = null + @modifyScreenRange => + @editSession.removeAnchor(@anchor) + @anchor = null selectWord: -> @setBufferRange(@cursor.getCurrentWordBufferRange()) @@ -209,11 +211,6 @@ class Selection autoOutdent: -> @editSession.autoOutdentBufferRow(@cursor.getBufferRow()) - handleBufferChange: (e) -> - @modifyScreenRange => - @anchor?.handleBufferChange(e) - @cursor.handleBufferChange(e) - modifySelection: (fn) -> @retainSelection = true @view?.retainSelection = true @@ -229,7 +226,7 @@ class Selection @trigger 'change-screen-range', newScreenRange unless oldScreenRange.isEqual(newScreenRange) placeAnchor: -> - @anchor = new Anchor(@editSession) + @anchor = @editSession.addAnchor() @anchor.setScreenPosition(@cursor.getScreenPosition()) intersectsBufferRange: (bufferRange) ->