mirror of
https://github.com/atom/atom.git
synced 2026-04-28 03:01:47 -04:00
Render a basic gutter
This commit is contained in:
@@ -39,14 +39,39 @@ describe "EditorComponent", ->
|
||||
node.querySelector('.vertical-scrollbar').scrollTop = 2.5 * lineHeightInPixels
|
||||
component.onVerticalScroll()
|
||||
|
||||
expect(node.querySelector('.scrollable-content').style['-webkit-transform']).toBe "translateY(#{-2.5 * lineHeightInPixels}px)"
|
||||
expect(node.querySelector('.scroll-view-content').style['-webkit-transform']).toBe "translateY(#{-2.5 * lineHeightInPixels}px)"
|
||||
|
||||
lines = node.querySelectorAll('.line')
|
||||
expect(lines.length).toBe 6
|
||||
expect(lines[0].textContent).toBe editor.lineForScreenRow(2).text
|
||||
expect(lines[5].textContent).toBe editor.lineForScreenRow(7).text
|
||||
|
||||
spacers = node.querySelectorAll('.spacer')
|
||||
spacers = node.querySelectorAll('.lines .spacer')
|
||||
expect(spacers[0].offsetHeight).toBe 2 * lineHeightInPixels
|
||||
expect(spacers[1].offsetHeight).toBe (editor.getScreenLineCount() - 8) * lineHeightInPixels
|
||||
|
||||
describe "gutter rendering", ->
|
||||
it "renders the currently-visible line numbers", ->
|
||||
nbsp = String.fromCharCode(160)
|
||||
node.style.height = 4.5 * lineHeightInPixels + 'px'
|
||||
component.updateAllDimensions()
|
||||
|
||||
lines = node.querySelectorAll('.line-number')
|
||||
expect(lines.length).toBe 6
|
||||
expect(lines[0].textContent).toBe "#{nbsp}1"
|
||||
expect(lines[5].textContent).toBe "#{nbsp}6"
|
||||
|
||||
node.querySelector('.vertical-scrollbar').scrollTop = 2.5 * lineHeightInPixels
|
||||
component.onVerticalScroll()
|
||||
|
||||
expect(node.querySelector('.line-numbers').style['-webkit-transform']).toBe "translateY(#{-2.5 * lineHeightInPixels}px)"
|
||||
|
||||
lines = node.querySelectorAll('.line-number')
|
||||
expect(lines.length).toBe 6
|
||||
expect(lines[0].textContent).toBe "#{nbsp}3"
|
||||
expect(lines[5].textContent).toBe "#{nbsp}8"
|
||||
|
||||
spacers = node.querySelectorAll('.line-numbers .spacer')
|
||||
expect(spacers[0].offsetHeight).toBe 2 * lineHeightInPixels
|
||||
expect(spacers[1].offsetHeight).toBe (editor.getScreenLineCount() - 8) * lineHeightInPixels
|
||||
|
||||
@@ -148,6 +173,11 @@ describe "EditorComponent", ->
|
||||
expect(cursorNode2.classList.contains('blink-off')).toBe false
|
||||
|
||||
describe "selection rendering", ->
|
||||
scrollViewClientLeft = null
|
||||
|
||||
beforeEach ->
|
||||
scrollViewClientLeft = node.querySelector('.scroll-view').getBoundingClientRect().left
|
||||
|
||||
it "renders 1 region for 1-line selections", ->
|
||||
# 1-line selection
|
||||
editor.setSelectedScreenRange([[1, 6], [1, 10]])
|
||||
@@ -156,7 +186,7 @@ describe "EditorComponent", ->
|
||||
regionRect = regions[0].getBoundingClientRect()
|
||||
expect(regionRect.top).toBe 1 * lineHeightInPixels
|
||||
expect(regionRect.height).toBe 1 * lineHeightInPixels
|
||||
expect(regionRect.left).toBe 6 * charWidth
|
||||
expect(regionRect.left).toBe scrollViewClientLeft + 6 * charWidth
|
||||
expect(regionRect.width).toBe 4 * charWidth
|
||||
|
||||
it "renders 2 regions for 2-line selections", ->
|
||||
@@ -167,13 +197,13 @@ describe "EditorComponent", ->
|
||||
region1Rect = regions[0].getBoundingClientRect()
|
||||
expect(region1Rect.top).toBe 1 * lineHeightInPixels
|
||||
expect(region1Rect.height).toBe 1 * lineHeightInPixels
|
||||
expect(region1Rect.left).toBe 6 * charWidth
|
||||
expect(region1Rect.left).toBe scrollViewClientLeft + 6 * charWidth
|
||||
expect(region1Rect.right).toBe node.clientWidth
|
||||
|
||||
region2Rect = regions[1].getBoundingClientRect()
|
||||
expect(region2Rect.top).toBe 2 * lineHeightInPixels
|
||||
expect(region2Rect.height).toBe 1 * lineHeightInPixels
|
||||
expect(region2Rect.left).toBe 0
|
||||
expect(region2Rect.left).toBe scrollViewClientLeft + 0
|
||||
expect(region2Rect.width).toBe 10 * charWidth
|
||||
|
||||
it "renders 3 regions for selections with more than 2 lines", ->
|
||||
@@ -184,19 +214,19 @@ describe "EditorComponent", ->
|
||||
region1Rect = regions[0].getBoundingClientRect()
|
||||
expect(region1Rect.top).toBe 1 * lineHeightInPixels
|
||||
expect(region1Rect.height).toBe 1 * lineHeightInPixels
|
||||
expect(region1Rect.left).toBe 6 * charWidth
|
||||
expect(region1Rect.left).toBe scrollViewClientLeft + 6 * charWidth
|
||||
expect(region1Rect.right).toBe node.clientWidth
|
||||
|
||||
region2Rect = regions[1].getBoundingClientRect()
|
||||
expect(region2Rect.top).toBe 2 * lineHeightInPixels
|
||||
expect(region2Rect.height).toBe 3 * lineHeightInPixels
|
||||
expect(region2Rect.left).toBe 0
|
||||
expect(region2Rect.left).toBe scrollViewClientLeft + 0
|
||||
expect(region2Rect.right).toBe node.clientWidth
|
||||
|
||||
region3Rect = regions[2].getBoundingClientRect()
|
||||
expect(region3Rect.top).toBe 5 * lineHeightInPixels
|
||||
expect(region3Rect.height).toBe 1 * lineHeightInPixels
|
||||
expect(region3Rect.left).toBe 0
|
||||
expect(region3Rect.left).toBe scrollViewClientLeft + 0
|
||||
expect(region3Rect.width).toBe 10 * charWidth
|
||||
|
||||
describe "mouse interactions", ->
|
||||
@@ -290,9 +320,9 @@ describe "EditorComponent", ->
|
||||
|
||||
clientCoordinatesForScreenPosition = (screenPosition) ->
|
||||
positionOffset = editor.pixelPositionForScreenPosition(screenPosition)
|
||||
editorClientRect = node.getBoundingClientRect()
|
||||
clientX = editorClientRect.left + positionOffset.left
|
||||
clientY = editorClientRect.top + positionOffset.top - editor.getScrollTop()
|
||||
scrollViewClientRect = node.querySelector('.scroll-view').getBoundingClientRect()
|
||||
clientX = scrollViewClientRect.left + positionOffset.left
|
||||
clientY = scrollViewClientRect.top + positionOffset.top - editor.getScrollTop()
|
||||
{clientX, clientY}
|
||||
|
||||
buildMouseEvent = (type, properties...) ->
|
||||
|
||||
@@ -2,7 +2,7 @@ React = require 'react'
|
||||
ReactUpdates = require 'react/lib/ReactUpdates'
|
||||
{div, span} = require 'reactionary'
|
||||
{$$} = require 'space-pen'
|
||||
{debounce} = require 'underscore-plus'
|
||||
{debounce, multiplyString} = require 'underscore-plus'
|
||||
|
||||
InputComponent = require './input-component'
|
||||
SelectionComponent = require './selection-component'
|
||||
@@ -30,19 +30,40 @@ EditorCompont = React.createClass
|
||||
className += ' is-focused' if focused
|
||||
|
||||
div className: className, tabIndex: -1, style: {fontSize, lineHeight, fontFamily},
|
||||
div className: 'gutter',
|
||||
@renderGutterContent()
|
||||
div className: 'scroll-view', ref: 'scrollView',
|
||||
InputComponent ref: 'input', className: 'hidden-input', onInput: @onInput, onFocus: @onInputFocused, onBlur: @onInputBlurred
|
||||
@renderScrollableContent()
|
||||
@renderScrollViewContent()
|
||||
div className: 'vertical-scrollbar', ref: 'verticalScrollbar', onScroll: @onVerticalScroll,
|
||||
div outlet: 'verticalScrollbarContent', style: {height: editor.getScrollHeight()}
|
||||
|
||||
renderScrollableContent: ->
|
||||
renderGutterContent: ->
|
||||
{editor} = @props
|
||||
[startRow, endRow] = @getVisibleRowRange()
|
||||
lineHeightInPixels = editor.getLineHeight()
|
||||
precedingHeight = startRow * lineHeightInPixels
|
||||
followingHeight = (editor.getScreenLineCount() - endRow) * lineHeightInPixels
|
||||
maxDigits = editor.getLastBufferRow().toString().length
|
||||
style =
|
||||
height: editor.getScrollHeight()
|
||||
WebkitTransform: "translateY(#{-editor.getScrollTop()}px)"
|
||||
|
||||
div className: 'line-numbers', style: style, [
|
||||
div className: 'spacer', key: 'top-spacer', style: {height: precedingHeight}
|
||||
(for bufferRow in @props.editor.bufferRowsForScreenRows(startRow, endRow - 1)
|
||||
lineNumber = bufferRow + 1
|
||||
LineNumberComponent({lineNumber, maxDigits, key: lineNumber}))...
|
||||
div className: 'spacer', key: 'bottom-spacer', style: {height: followingHeight}
|
||||
]
|
||||
|
||||
renderScrollViewContent: ->
|
||||
{editor} = @props
|
||||
style =
|
||||
height: editor.getScrollHeight()
|
||||
WebkitTransform: "translateY(#{-editor.getScrollTop()}px)"
|
||||
|
||||
div {className: 'scrollable-content', style, @onMouseDown},
|
||||
div {className: 'scroll-view-content', style, @onMouseDown},
|
||||
@renderCursors()
|
||||
@renderVisibleLines()
|
||||
@renderUnderlayer()
|
||||
@@ -469,3 +490,18 @@ LineComponent = React.createClass
|
||||
"<span>#{scopeTree.getValueAsHtml({})}</span>"
|
||||
|
||||
shouldComponentUpdate: -> false
|
||||
|
||||
LineNumberComponent = React.createClass
|
||||
render: ->
|
||||
div className: 'line-number', dangerouslySetInnerHTML: {__html: @buildInnerHTML()}
|
||||
|
||||
buildInnerHTML: ->
|
||||
{lineNumber, maxDigits} = @props
|
||||
lineNumber = lineNumber.toString()
|
||||
if lineNumber.length < maxDigits
|
||||
padding = multiplyString(' ', maxDigits - lineNumber.length)
|
||||
padding + lineNumber + @iconDivHTML
|
||||
else
|
||||
lineNumber + @iconDivHTML
|
||||
|
||||
iconDivHTML: '<div class="icon-right"></div>'
|
||||
|
||||
@@ -210,7 +210,7 @@
|
||||
}
|
||||
|
||||
.react-wrapper > .editor {
|
||||
.scrollable-content {
|
||||
.scroll-view-content {
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user