Merge branch 'edit-session-refactor'

This commit is contained in:
Nathan Sobo
2012-06-06 17:01:28 -06:00
3 changed files with 95 additions and 51 deletions

View File

@@ -79,21 +79,37 @@ describe "Editor", ->
expect(newEditor.scrollView.scrollLeft()).toBe 44
newEditor.remove()
describe ".remove()", ->
it "removes subscriptions from all edit session buffers", ->
otherBuffer = new Buffer(require.resolve('fixtures/sample.txt'))
expect(buffer.subscriptionCount()).toBeGreaterThan 1
editor.setBuffer(otherBuffer)
expect(otherBuffer.subscriptionCount()).toBeGreaterThan 1
editor.remove()
expect(buffer.subscriptionCount()).toBe 1
expect(otherBuffer.subscriptionCount()).toBe 1
describe ".setBuffer(buffer)", ->
otherBuffer = null
beforeEach ->
otherBuffer = new Buffer
it "sets the cursor to the beginning of the file", ->
expect(editor.getCursorScreenPosition()).toEqual(row: 0, column: 0)
it "recalls the cursor position and scroll position when the same buffer is re-assigned", ->
editor.attachToDom()
editor.height(editor.lineHeight * 5)
editor.width(editor.charWidth * 30)
editor.setCursorScreenPosition([8, 28])
advanceClock()
previousScrollTop = editor.verticalScrollbar.scrollTop()
previousScrollLeft = editor.scrollView.scrollLeft()
editor.setBuffer(new Buffer)
editor.setBuffer(otherBuffer)
expect(editor.getCursorScreenPosition()).toEqual [0, 0]
expect(editor.verticalScrollbar.scrollTop()).toBe 0
expect(editor.scrollView.scrollLeft()).toBe 0
@@ -106,7 +122,6 @@ describe "Editor", ->
it "recalls the undo history of the buffer when it is re-assigned", ->
editor.insertText('xyz')
otherBuffer = new Buffer
editor.setBuffer(otherBuffer)
editor.insertText('abc')
expect(otherBuffer.lineForRow(0)).toBe 'abc'
@@ -123,15 +138,15 @@ describe "Editor", ->
editor.redo()
expect(otherBuffer.lineForRow(0)).toBe 'abc'
it "fully unsubscribes from the previously assigned buffer", ->
otherBuffer = new Buffer
previousSubscriptionCount = otherBuffer.subscriptionCount()
it "unsubscribes from the previously assigned buffer", ->
editor.setBuffer(otherBuffer)
expect(otherBuffer.subscriptionCount()).toBeGreaterThan previousSubscriptionCount
previousSubscriptionCount = buffer.subscriptionCount()
editor.setBuffer(buffer)
expect(otherBuffer.subscriptionCount()).toBe previousSubscriptionCount
editor.setBuffer(otherBuffer)
expect(buffer.subscriptionCount()).toBe previousSubscriptionCount
it "resizes the vertical scrollbar based on the new buffer's height", ->
editor.attachToDom(heightInLines: 5)
@@ -141,6 +156,17 @@ describe "Editor", ->
editor.setBuffer(new Buffer(require.resolve('fixtures/sample.txt')))
expect(editor.verticalScrollbar.prop('scrollHeight')).toBeLessThan originalHeight
it "handles buffer manipulation correctly after switching to a new buffer", ->
editor.attachToDom()
editor.insertText("abc\n")
expect(editor.lineElementForScreenRow(0).text()).toBe 'abc'
editor.setBuffer(otherBuffer)
expect(editor.lineElementForScreenRow(0).html()).toBe ' '
editor.insertText("def\n")
expect(editor.lineElementForScreenRow(0).text()).toBe 'def'
describe ".clipScreenPosition(point)", ->
it "selects the nearest valid position to the given point", ->
expect(editor.clipScreenPosition(row: 1000, column: 0)).toEqual(row: buffer.getLastRow(), column: buffer.lineForRow(buffer.getLastRow()).length)

View File

@@ -1,11 +1,12 @@
Point = require 'point'
Buffer = require 'buffer'
Renderer = require 'renderer'
module.exports =
class EditSession
@deserialize: (state, rootView) ->
@deserialize: (state, editor, rootView) ->
buffer = Buffer.deserialize(state.buffer, rootView.project)
session = new EditSession(buffer)
session = new EditSession(editor, buffer)
session.setScrollTop(state.scrollTop)
session.setScrollLeft(state.scrollLeft)
session.setCursorScreenPosition(state.cursorScreenPosition)
@@ -14,16 +15,23 @@ class EditSession
scrollTop: 0
scrollLeft: 0
cursorScreenPosition: null
renderer: null
constructor: (@buffer) ->
constructor: (@editor, @buffer) ->
@setCursorScreenPosition([0, 0])
destroy: ->
@renderer.destroy()
serialize: ->
buffer: @buffer.serialize()
scrollTop: @getScrollTop()
scrollLeft: @getScrollLeft()
cursorScreenPosition: @getCursorScreenPosition().serialize()
getRenderer: ->
@renderer ?= new Renderer(@buffer, { softWrapColumn: @editor.calcSoftWrapColumn(), tabText: @editor.tabText })
setScrollTop: (@scrollTop) ->
getScrollTop: -> @scrollTop
@@ -36,3 +44,9 @@ class EditSession
getCursorScreenPosition: ->
@cursorScreenPosition
isEqual: (other) ->
return false unless other instanceof EditSession
@buffer == other.buffer and
@scrollTop == other.getScrollTop() and
@scrollLeft == other.getScrollLeft() and
@cursorScreenPosition.isEqual(other.getCursorScreenPosition())

View File

@@ -49,12 +49,14 @@ class Editor extends View
attached: false
lineOverdraw: 100
@deserialize: (viewState, rootView) ->
viewState = _.clone(viewState)
viewState.editSessions = viewState.editSessions.map (state) -> EditSession.deserialize(state, rootView)
new Editor(viewState)
@deserialize: (state, rootView) ->
editor = new Editor(suppressBufferCreation: true, mini: state.mini)
editor.editSessions = state.editSessions.map (state) -> EditSession.deserialize(state, editor, rootView)
editor.loadEditSession(state.activeEditSessionIndex)
editor.isFocused = state.isFocused
editor
initialize: ({editSessions, activeEditSessionIndex, buffer, isFocused, @mini} = {}) ->
initialize: ({buffer, suppressBufferCreation, @mini} = {}) ->
requireStylesheet 'editor.css'
requireStylesheet 'theme/twilight.css'
@@ -64,17 +66,13 @@ class Editor extends View
@autoIndent = true
@buildCursorAndSelection()
@handleEvents()
@editSessions = []
@editSessions = editSessions ? []
if activeEditSessionIndex?
@loadEditSession(activeEditSessionIndex)
else if buffer?
if buffer?
@setBuffer(buffer)
else
else if !suppressBufferCreation
@setBuffer(new Buffer)
@isFocused = isFocused if isFocused?
serialize: ->
@saveCurrentEditSession()
{ viewClass: "Editor", editSessions: @serializeEditSessions(), @activeEditSessionIndex, @isFocused }
@@ -319,35 +317,31 @@ class Editor extends View
@renderer.destroyFoldsContainingBufferRow(bufferRow)
setBuffer: (buffer) ->
if @buffer
@saveCurrentEditSession()
@unsubscribeFromBuffer()
@loadEditSessionForBuffer(buffer)
@buffer = buffer
@trigger 'editor-path-change'
@buffer.on "path-change.editor#{@id}", => @trigger 'editor-path-change'
@renderer = new Renderer(@buffer, { softWrapColumn: @calcSoftWrapColumn(), tabText: @tabText })
@prepareForScrolling() if @attached
@loadEditSessionForBuffer(@buffer)
@renderLines() if @attached
@buffer.on "change.editor#{@id}", (e) => @handleBufferChange(e)
setRenderer: (renderer) ->
@renderer?.off()
@renderer = renderer
@renderer.on 'change', (e) => @handleRendererChange(e)
editSessionForBuffer: (buffer) ->
@unsubscribeFromBuffer() if @buffer
@buffer = renderer.buffer
@buffer.on "path-change.editor#{@id}", => @trigger 'editor-path-change'
@buffer.on "change.editor#{@id}", (e) => @handleBufferChange(e)
@trigger 'editor-path-change'
editSessionIndexForBuffer: (buffer) ->
for editSession, index in @editSessions
return [editSession, index] if editSession.buffer == buffer
[undefined, -1]
return index if editSession.buffer == buffer
null
loadEditSessionForBuffer: (buffer) ->
[editSession, index] = @editSessionForBuffer(buffer)
if editSession
@activeEditSessionIndex = index
else
@editSessions.push(new EditSession(buffer))
@activeEditSessionIndex = @editSessions.length - 1
@loadEditSession()
index = @editSessionIndexForBuffer(buffer)
unless index?
index = @editSessions.length
@editSessions.push(new EditSession(this, buffer))
@loadEditSession(index)
loadNextEditSession: ->
nextIndex = (@activeEditSessionIndex + 1) % @editSessions.length
@@ -361,9 +355,14 @@ class Editor extends View
loadEditSession: (index=@activeEditSessionIndex) ->
editSession = @editSessions[index]
throw new Error("Edit session not found") unless editSession
@setBuffer(editSession.buffer) unless @buffer == editSession.buffer
@saveCurrentEditSession() if @activeEditSessionIndex?
@activeEditSessionIndex = index
@setScrollPositionFromActiveEditSession() if @attached
@setRenderer(editSession.getRenderer())
if @attached
@prepareForScrolling()
@setScrollPositionFromActiveEditSession()
@renderLines()
@setCursorScreenPosition(editSession.cursorScreenPosition ? [0, 0])
getActiveEditSession: ->
@@ -749,7 +748,10 @@ class Editor extends View
return super if keepData
@trigger 'before-remove'
@destroyEditSessions()
@unsubscribeFromBuffer()
$(window).off ".editor#{@id}"
rootView = @rootView()
rootView?.off ".editor#{@id}"
@@ -758,7 +760,9 @@ class Editor extends View
unsubscribeFromBuffer: ->
@buffer.off ".editor#{@id}"
@renderer.destroy()
destroyEditSessions: ->
session.destroy() for session in @editSessions
stateForScreenRow: (row) ->
@renderer.lineForRow(row).state