Start on cursor rendering

This commit is contained in:
Nathan Sobo
2014-04-01 15:06:38 -06:00
parent 61d9ff4ba4
commit 70e5880b1d
3 changed files with 75 additions and 18 deletions

View File

@@ -2,7 +2,7 @@
EditorComponent = require '../src/editor-component'
describe "EditorComponent", ->
[editor, component, node, lineHeight] = []
[editor, component, node, lineHeight, charWidth] = []
beforeEach ->
editor = atom.project.openSync('sample.js')
@@ -10,10 +10,9 @@ describe "EditorComponent", ->
component = React.renderComponent(EditorComponent({editor}), container)
node = component.getDOMNode()
fontSize = 20
lineHeight = 1.3 * fontSize
node.style.lineHeight = 1.3
node.style.fontSize = fontSize + 'px'
node.style.fontSize = '20px'
{lineHeight, charWidth} = component.measureLineDimensions()
it "renders only the currently-visible lines", ->
node.style.height = 4.5 * lineHeight + 'px'
@@ -28,7 +27,7 @@ describe "EditorComponent", ->
spyOn(window, 'requestAnimationFrame').andCallFake (fn) -> fn()
component.onVerticalScroll()
expect(node.querySelector('.lines').style['-webkit-transform']).toBe "translateY(#{-2.5 * lineHeight}px)"
expect(node.querySelector('.scrollable-content').style['-webkit-transform']).toBe "translateY(#{-2.5 * lineHeight}px)"
lines = node.querySelectorAll('.line')
expect(lines.length).toBe 5
@@ -38,3 +37,15 @@ describe "EditorComponent", ->
spacers = node.querySelectorAll('.spacer')
expect(spacers[0].offsetHeight).toBe 2 * lineHeight
expect(spacers[1].offsetHeight).toBe (editor.getScreenLineCount() - 7) * lineHeight
it "renders the currently visible selections", ->
editor.setCursorScreenPosition([0, 5])
node.style.height = 4.5 * lineHeight + 'px'
component.updateAllDimensions()
cursorNodes = node.querySelectorAll('.cursor')
expect(cursorNodes[0].offsetHeight).toBe lineHeight
expect(cursorNodes[0].offsetWidth).toBe charWidth
expect(cursorNodes[0].offsetTop).toBe 0
expect(cursorNodes[0].offsetLeft).toBe 5 * charWidth

View File

@@ -10,22 +10,37 @@ module.exports =
React.createClass
pendingScrollTop: null
statics: {DummyLineNode}
render: ->
div className: 'editor',
div className: 'scroll-view', ref: 'scrollView',
div className: 'overlayer',
InputComponent ref: 'hiddenInput', className: 'hidden-input', onInput: @onInput
@renderVisibleLines()
InputComponent ref: 'hiddenInput', className: 'hidden-input', onInput: @onInput
@renderScrollableContent()
div className: 'vertical-scrollbar', ref: 'verticalScrollbar', onScroll: @onVerticalScroll,
div outlet: 'verticalScrollbarContent', style: {height: @getScrollHeight()}
renderScrollableContent: ->
height = @props.editor.getScreenLineCount() * @state.lineHeight
WebkitTransform = "translateY(#{-@state.scrollTop}px)"
div className: 'scrollable-content', style: {height, WebkitTransform},
@renderOverlayer()
@renderVisibleLines()
renderOverlayer: ->
{lineHeight, charWidth} = @state
div className: 'overlayer',
for selection in @props.editor.getSelections()
SelectionComponent({selection, lineHeight, charWidth})
renderVisibleLines: ->
[startRow, endRow] = @getVisibleRowRange()
precedingHeight = startRow * @state.lineHeight
lineCount = @props.editor.getScreenLineCount()
followingHeight = (lineCount - endRow) * @state.lineHeight
followingHeight = (@props.editor.getScreenLineCount() - endRow) * @state.lineHeight
div className: 'lines', ref: 'lines', style: {WebkitTransform: "translateY(#{-@state.scrollTop}px)"}, [
div className: 'lines', ref: 'lines', [
div className: 'spacer', key: 'top-spacer', style: {height: precedingHeight}
(for tokenizedLine in @props.editor.linesForScreenRows(startRow, endRow - 1)
LineComponent({tokenizedLine, key: tokenizedLine.id}))...
@@ -62,8 +77,6 @@ React.createClass
event.preventDefault()
onInput: (char, replaceLastChar) ->
console.log char, replaceLastChar
@props.editor.insertText(char)
onScreenLinesChanged: ({start, end}) ->
@@ -82,21 +95,21 @@ React.createClass
@props.editor.getLineCount() * @state.lineHeight
updateAllDimensions: ->
lineHeight = @measureLineHeight()
{height, width} = @measureScrollViewDimensions()
@setState({lineHeight, height, width})
{lineHeight, charWidth} = @measureLineDimensions()
@setState({height, width, lineHeight, charWidth})
measureScrollViewDimensions: ->
scrollViewNode = @refs.scrollView.getDOMNode()
{height: scrollViewNode.clientHeight, width: scrollViewNode.clientWidth}
measureLineHeight: ->
measureLineDimensions: ->
linesNode = @refs.lines.getDOMNode()
linesNode.appendChild(DummyLineNode)
lineHeight = DummyLineNode.getBoundingClientRect().height
charWidth = DummyLineNode.firstChild.getBoundingClientRect().width
linesNode.removeChild(DummyLineNode)
lineHeight
{lineHeight, charWidth}
LineComponent = React.createClass
render: ->
@@ -151,3 +164,26 @@ InputComponent = React.createClass
focus: ->
@getDOMNode().focus()
SelectionComponent = React.createClass
render: ->
console.log "render selection component"
{selection, lineHeight, charWidth} = @props
{cursor} = selection
div className: 'selection',
CursorComponent({cursor, lineHeight, charWidth})
CursorComponent = React.createClass
render: ->
{cursor, lineHeight, charWidth} = @props
{row, column} = cursor.getScreenPosition()
console.log "char width", charWidth
div className: 'cursor', style: {
height: lineHeight,
width: charWidth
top: row * lineHeight
left: column * charWidth
}

View File

@@ -200,3 +200,13 @@
color: @text-color-subtle;
}
}
.react-wrapper > .editor {
.scrollable-content {
position: relative;
}
.cursor {
visibility: visible;
}
}