Selection and Cursor use Anchor to hold their buffer and screen positions

This commit is contained in:
Corey Johnson
2012-04-03 08:53:02 -07:00
parent bf5ebc9969
commit b4cfd7fc85
6 changed files with 83 additions and 76 deletions

47
src/atom/anchor.coffee Normal file
View File

@@ -0,0 +1,47 @@
Point = require 'point'
module.exports =
class Anchor
editor: null
bufferPosition: null
screenPosition: null
constructor: (editor) ->
@editor = editor
@bufferPosition = new Point(0, 0)
@screenPosition = new Point(0, 0)
handleBufferChange: (e) ->
{ oldRange, newRange } = e
position = @getBufferPosition()
return if position.isLessThan(oldRange.end)
newRow = newRange.end.row
newColumn = newRange.end.column
if position.row == oldRange.end.row
newColumn += position.column - oldRange.end.column
else
newColumn = position.column
newRow += position.row - oldRange.end.row
@setBufferPosition [newRow, newColumn]
getBufferPosition: ->
@bufferPosition
setBufferPosition: (position) ->
screenPosition = @editor.screenPositionForBufferPosition(position)
@setScreenPosition(screenPosition, clip: false)
getScreenPosition: ->
@screenPosition
setScreenPosition: (position, options={}) ->
position = Point.fromObject(position)
clip = options.clip ? true
@screenPosition = if clip then @editor.clipScreenPosition(position) else position
@bufferPosition = @editor.bufferPositionForScreenPosition(position)
Object.freeze @screenPosition
Object.freeze @bufferPosition

View File

@@ -45,8 +45,8 @@ class CompositeCursor
setBufferPosition: (bufferPosition) ->
@moveCursors (cursor) -> cursor.setBufferPosition(bufferPosition)
refreshScreenPosition: ->
@moveCursors (cursor) -> cursor.refreshScreenPosition()
updateBufferPosition: ->
@moveCursors (cursor) -> cursor.setBufferPosition(cursor.getBufferPosition())
moveLeft: ->
@moveCursors (cursor) -> cursor.moveLeft()

View File

@@ -1,4 +1,5 @@
{View} = require 'space-pen'
Anchor = require 'anchor'
Point = require 'point'
_ = require 'underscore'
@@ -7,45 +8,38 @@ class Cursor extends View
@content: ->
@pre class: 'cursor idle', => @raw ' '
anchor: null
editor: null
screenPosition: null
bufferPosition: null
wordRegex: /(\w+)|([^\w\s]+)/g
initialize: (@editor) ->
@screenPosition = new Point(0, 0)
@anchor = new Anchor(@editor)
@one 'attach', => @updateAppearance()
handleBufferChange: (e) ->
{ newRange, oldRange } = e
position = @getBufferPosition()
return if position.isLessThan(oldRange.end)
newRow = newRange.end.row
newColumn = newRange.end.column
if position.row == oldRange.end.row
newColumn += position.column - oldRange.end.column
else
newColumn = position.column
newRow += position.row - oldRange.end.row
@setBufferPosition([newRow, newColumn])
@anchor.handleBufferChange(e)
@refreshScreenPosition()
remove: ->
@editor.compositeCursor.removeCursor(this)
@editor.compositeSelection.removeSelectionForCursor(this)
super
getBufferPosition: ->
@anchor.getBufferPosition()
setBufferPosition: (bufferPosition) ->
@anchor.setBufferPosition(bufferPosition)
@refreshScreenPosition()
getScreenPosition: ->
@anchor.getScreenPosition()
setScreenPosition: (position, options={}) ->
position = Point.fromObject(position)
clip = options.clip ? true
@screenPosition = if clip then @editor.clipScreenPosition(position) else position
@bufferPosition = @editor.bufferPositionForScreenPosition(position)
Object.freeze @screenPosition
Object.freeze @bufferPosition
@anchor.setScreenPosition(position, options)
@refreshScreenPosition(position, options)
refreshScreenPosition: ->
@goalColumn = null
@updateAppearance()
@trigger 'cursor:position-changed'
@@ -54,18 +48,6 @@ class Cursor extends View
window.clearTimeout(@idleTimeout) if @idleTimeout
@idleTimeout = window.setTimeout (=> @addClass 'idle'), 200
setBufferPosition: (bufferPosition) ->
@setScreenPosition(@editor.screenPositionForBufferPosition(bufferPosition), clip: false)
refreshScreenPosition: ->
@setBufferPosition(@bufferPosition)
getBufferPosition: ->
@bufferPosition
getScreenPosition: ->
@screenPosition
getCurrentBufferLine: ->
@editor.lineForBufferRow(@getBufferPosition().row)

View File

@@ -222,7 +222,7 @@ class Editor extends View
unless newRange.isSingleLine() and newRange.coversSameRows(oldRange)
@gutter.renderLineNumbers(@getScreenLines())
@compositeCursor.refreshScreenPosition() unless e.bufferChanged
@compositeCursor.updateBufferPosition() unless e.bufferChanged
lineElements = @buildLineElements(newRange.start.row, newRange.end.row)
@replaceLineElements(oldRange.start.row, oldRange.end.row, lineElements)

View File

@@ -1,3 +1,4 @@
Anchor = require 'anchor'
Cursor = require 'cursor'
AceOutdentAdaptor = require 'ace-outdent-adaptor'
Point = require 'point'
@@ -22,33 +23,25 @@ class Selection extends View
@clearSelection()
handleBufferChange: (e) ->
return unless @anchorScreenPosition
return unless @anchor
@anchor.handleBufferChange(e)
{ oldRange, newRange } = e
position = @anchorBufferPosition
return if position.isLessThan(oldRange.end)
newRow = newRange.end.row
newColumn = newRange.end.column
if position.row == oldRange.end.row
newColumn += position.column - oldRange.end.column
else
newColumn = position.column
newRow += position.row - oldRange.end.row
@setAnchorBufferPosition([newRow, newColumn])
placeAnchor: ->
return if @anchor
@anchor = new Anchor(@editor)
@anchor.setScreenPosition @cursor.getScreenPosition()
isEmpty: ->
@getBufferRange().isEmpty()
isReversed: ->
not @isEmpty() and @cursor.getBufferPosition().isLessThan(@anchorBufferPosition)
not @isEmpty() and @cursor.getBufferPosition().isLessThan(@anchor.getBufferPosition())
intersectsWith: (otherSelection) ->
@getScreenRange().intersectsWith(otherSelection.getScreenRange())
clearSelection: ->
@anchorScreenPosition = null
@anchor = null
@updateAppearance()
updateAppearance: ->
@@ -87,8 +80,8 @@ class Selection extends View
@regions = []
getScreenRange: ->
if @anchorScreenPosition
new Range(@anchorScreenPosition, @cursor.getScreenPosition())
if @anchor
new Range(@anchor.getScreenPosition(), @cursor.getScreenPosition())
else
new Range(@cursor.getScreenPosition(), @cursor.getScreenPosition())
@@ -168,24 +161,6 @@ class Selection extends View
fn()
@retainSelection = false
placeAnchor: ->
return if @anchorScreenPosition
@setAnchorScreenPosition(@cursor.getScreenPosition())
setAnchorScreenPosition: (screenPosition) ->
bufferPosition = Point.fromObject(screenPosition)
@anchorScreenPosition = screenPosition
@anchorBufferPosition = @editor.bufferPositionForScreenPosition(screenPosition)
setAnchorBufferPosition: (bufferPosition) ->
bufferPosition = Point.fromObject(bufferPosition)
@anchorBufferPosition = bufferPosition
@anchorScreenPosition = @editor.screenPositionForBufferPosition(bufferPosition)
selectToScreenPosition: (position) ->
@modifySelection =>
@cursor.setScreenPosition(position)
selectWord: ->
row = @cursor.getScreenPosition().row
column = @cursor.getScreenPosition().column
@@ -207,6 +182,9 @@ class Selection extends View
rowLength = @editor.buffer.lineForRow(row).length
@setBufferRange new Range([row, 0], [row, rowLength])
selectToScreenPosition: (position) ->
@modifySelection => @cursor.setScreenPosition(position)
selectRight: ->
@modifySelection => @cursor.moveRight()