From f0920bf63b7816ef4fb66cd3c5dc0d7f76f29faf Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 19 Jan 2015 10:48:44 -0700 Subject: [PATCH] Start on TextEditorPresenter with lines state --- spec/text-editor-presenter-spec.coffee | 80 ++++++++++++++++++++++++++ src/text-editor-presenter.coffee | 20 +++++++ 2 files changed, 100 insertions(+) create mode 100644 spec/text-editor-presenter-spec.coffee create mode 100644 src/text-editor-presenter.coffee diff --git a/spec/text-editor-presenter-spec.coffee b/spec/text-editor-presenter-spec.coffee new file mode 100644 index 000000000..021548033 --- /dev/null +++ b/spec/text-editor-presenter-spec.coffee @@ -0,0 +1,80 @@ +TextBuffer = require 'text-buffer' +TextEditor = require '../src/text-editor' +TextEditorPresenter = require '../src/text-editor-presenter' + +describe "TextEditorPresenter", -> + [buffer, editor] = [] + + beforeEach -> + buffer = new TextBuffer(filePath: require.resolve('./fixtures/sample.js')) + editor = new TextEditor({buffer}) + waitsForPromise -> buffer.load() + + afterEach -> + editor.destroy() + buffer.destroy() + + expectValues = (actual, expected) -> + for key, value of expected + expect(actual[key]).toBe value + + describe "lines", -> + describe "on initialization", -> + it "contains the lines that are visible on screen, plus the overdraw margin", -> + presenter = new TextEditorPresenter(model: editor, clientHeight: 25, scrollTop: 0, lineHeight: 10, lineOverdrawMargin: 1) + + line0 = editor.tokenizedLineForScreenRow(0) + expectValues presenter.state.lines[line0.id], { + screenRow: 0 + tokens: line0.tokens + top: 10 * 0 + } + + line1 = editor.tokenizedLineForScreenRow(1) + expectValues presenter.state.lines[line1.id], { + screenRow: 1 + tokens: line1.tokens + top: 10 * 1 + } + + line2 = editor.tokenizedLineForScreenRow(2) + expectValues presenter.state.lines[line2.id], { + screenRow: 2 + tokens: line2.tokens + top: 10 * 2 + } + + # this row is rendered due to the overdraw margin + line3 = editor.tokenizedLineForScreenRow(3) + expectValues presenter.state.lines[line3.id], { + screenRow: 3 + tokens: line3.tokens + top: 10 * 3 + } + + it "contains the lines that are visible on screen, minus the overdraw margin", -> + presenter = new TextEditorPresenter(model: editor, clientHeight: 25, scrollTop: 115, lineHeight: 10, lineOverdrawMargin: 1) + + # this row is rendered due to the overdraw margin + line10 = editor.tokenizedLineForScreenRow(10) + expectValues presenter.state.lines[line10.id], { + screenRow: 10 + tokens: line10.tokens + top: 10 * 10 + } + + line11 = editor.tokenizedLineForScreenRow(11) + expectValues presenter.state.lines[line11.id], { + screenRow: 11 + tokens: line11.tokens + top: 10 * 11 + } + + line12 = editor.tokenizedLineForScreenRow(12) + expectValues presenter.state.lines[line12.id], { + screenRow: 12 + tokens: line12.tokens + top: 10 * 12 + } + + # rows beyond the end of the content are not rendered diff --git a/src/text-editor-presenter.coffee b/src/text-editor-presenter.coffee new file mode 100644 index 000000000..3dcb6c657 --- /dev/null +++ b/src/text-editor-presenter.coffee @@ -0,0 +1,20 @@ +module.exports = +class TextEditorPresenter + constructor: ({@model, @clientHeight, @scrollTop, @lineHeight, @lineOverdrawMargin}) -> + @state = {} + @buildLinesState() + + buildLinesState: -> + @state.lines = {} + startRow = Math.floor(@scrollTop / @lineHeight) - @lineOverdrawMargin + startRow = Math.max(0, startRow) + endRow = startRow + Math.ceil(@clientHeight / @lineHeight) + @lineOverdrawMargin + endRow = Math.min(@model.getScreenLineCount(), endRow) + + for line, i in @model.tokenizedLinesForScreenRows(startRow, endRow) + row = startRow + i + @state.lines[line.id] = { + screenRow: row + tokens: line.tokens + top: row * @lineHeight + }