From 7f1b094ed2232f2e19340d812bf0bbde6c1c1c7d Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 21 Jun 2012 17:29:12 -0600 Subject: [PATCH 1/2] Make Cursor and Selection create anchors via EditSession.prototype.addAnchor --- src/app/cursor.coffee | 3 ++- src/app/edit-session.coffee | 11 +++++++++++ src/app/selection.coffee | 6 ++++-- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/app/cursor.coffee b/src/app/cursor.coffee index c151efc21..044b9ab0d 100644 --- a/src/app/cursor.coffee +++ b/src/app/cursor.coffee @@ -12,11 +12,12 @@ class Cursor wordRegex: /(\w+)|([^\w\s]+)/g constructor: ({@editSession, screenPosition, bufferPosition}) -> - @anchor = new Anchor(@editSession) + @anchor = @editSession.addAnchor() @setScreenPosition(screenPosition) if screenPosition @setBufferPosition(bufferPosition) if bufferPosition destroy: -> + @editSession.removeAnchor(@anchor) @editSession.removeCursor(this) @trigger 'destroy' diff --git a/src/app/edit-session.coffee b/src/app/edit-session.coffee index c38227b80..8de5d7f6f 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,6 +33,7 @@ class EditSession @softTabs ?= true @displayBuffer = new DisplayBuffer(@buffer, { @tabText }) @tokenizedBuffer = @displayBuffer.tokenizedBuffer + @anchors = [] @cursors = [] @selections = [] @addCursorAtScreenPosition([0, 0]) @@ -227,6 +230,14 @@ class EditSession fn(selection) for selection in selections @buffer.endUndoBatch(@getSelectedBufferRanges()) + 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/selection.coffee b/src/app/selection.coffee index 0cacf5a08..db0a09b3b 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()) @@ -229,7 +231,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) -> From 8fa5723be93ef86c52f0dfb021632ba9fc1a1e76 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 21 Jun 2012 17:57:23 -0600 Subject: [PATCH 2/2] When buffer or display-buffer change, update the position of all anchors on EditSession. Cursors and selections no longer need to handle buffer/display-buffer changes directly. They register anchors with the EditSession, and subscribe to changes in their position instead. This opens up the anchor facility for use by extensions that want to track the screen position of a point in the buffer as the buffer and display buffer change. --- src/app/anchor.coffee | 15 +++++++++++---- src/app/cursor.coffee | 12 +++--------- src/app/edit-session.coffee | 10 +++++++--- src/app/point.coffee | 1 + src/app/selection.coffee | 5 ----- 5 files changed, 22 insertions(+), 21 deletions(-) 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 044b9ab0d..ff868b9a0 100644 --- a/src/app/cursor.coffee +++ b/src/app/cursor.coffee @@ -13,6 +13,7 @@ class Cursor constructor: ({@editSession, screenPosition, bufferPosition}) -> @anchor = @editSession.addAnchor() + @anchor.on 'change-screen-position', (args...) => @trigger 'change-screen-position', args... @setScreenPosition(screenPosition) if screenPosition @setBufferPosition(bufferPosition) if bufferPosition @@ -22,19 +23,17 @@ class Cursor @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() @@ -54,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 8de5d7f6f..e673daf1a 100644 --- a/src/app/edit-session.coffee +++ b/src/app/edit-session.coffee @@ -39,12 +39,13 @@ class EditSession @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}" @@ -230,6 +231,9 @@ class EditSession fn(selection) for selection in selections @buffer.endUndoBatch(@getSelectedBufferRanges()) + getAnchors: -> + new Array(@anchors...) + addAnchor: -> anchor = new Anchor(this) @anchors.push(anchor) 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 db0a09b3b..2569a3a27 100644 --- a/src/app/selection.coffee +++ b/src/app/selection.coffee @@ -211,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