2014-04-14 20:11:11 +04:00
|
|
|
React = require 'react'
|
|
|
|
{div} = require 'reactionary'
|
2014-04-20 21:44:48 +04:00
|
|
|
{isEqual, isEqualForProperties, multiplyString} = require 'underscore-plus'
|
2014-04-15 23:56:58 +04:00
|
|
|
SubscriberMixin = require './subscriber-mixin'
|
2014-04-14 20:11:11 +04:00
|
|
|
|
|
|
|
module.exports =
|
|
|
|
GutterComponent = React.createClass
|
2014-04-15 20:39:47 +04:00
|
|
|
displayName: 'GutterComponent'
|
2014-04-15 23:56:58 +04:00
|
|
|
mixins: [SubscriberMixin]
|
2014-04-15 20:39:47 +04:00
|
|
|
|
2014-04-25 05:07:17 +04:00
|
|
|
lastMeasuredWidth: null
|
|
|
|
|
2014-04-14 20:11:11 +04:00
|
|
|
render: ->
|
2014-05-11 00:26:23 +04:00
|
|
|
if @isMounted()
|
|
|
|
{editor, renderedRowRange, lineOverdraw, scrollTop, lineHeight, showIndentGuide} = @props
|
|
|
|
[startRow, endRow] = renderedRowRange
|
|
|
|
scrollOffset = -scrollTop % lineHeight
|
|
|
|
maxLineNumberDigits = editor.getLineCount().toString().length
|
|
|
|
|
|
|
|
wrapCount = 0
|
|
|
|
lineNumbers =
|
|
|
|
for bufferRow, index in editor.bufferRowsForScreenRows(startRow, endRow - 1)
|
|
|
|
if bufferRow is lastBufferRow
|
|
|
|
lineNumber = '•'
|
|
|
|
key = "#{bufferRow + 1}-#{++wrapCount}"
|
|
|
|
else
|
|
|
|
lastBufferRow = bufferRow
|
|
|
|
wrapCount = 0
|
|
|
|
lineNumber = "#{bufferRow + 1}"
|
|
|
|
key = lineNumber
|
|
|
|
|
|
|
|
LineNumberComponent({key, lineNumber, maxLineNumberDigits, index, lineHeight, scrollOffset})
|
2014-04-15 04:07:55 +04:00
|
|
|
|
2014-05-11 00:26:23 +04:00
|
|
|
div className: 'gutter',
|
|
|
|
div className: 'line-numbers',
|
|
|
|
lineNumbers
|
2014-04-14 20:11:11 +04:00
|
|
|
|
2014-04-15 23:56:58 +04:00
|
|
|
# Only update the gutter if the visible row range has changed or if a
|
|
|
|
# non-zero-delta change to the screen lines has occurred within the current
|
|
|
|
# visible row range.
|
|
|
|
shouldComponentUpdate: (newProps) ->
|
2014-04-25 05:07:17 +04:00
|
|
|
return true unless isEqualForProperties(newProps, @props, 'renderedRowRange', 'scrollTop', 'lineHeight', 'fontSize')
|
2014-04-15 23:56:58 +04:00
|
|
|
|
2014-04-23 21:41:29 +04:00
|
|
|
{renderedRowRange, pendingChanges} = newProps
|
2014-04-16 22:19:18 +04:00
|
|
|
for change in pendingChanges when change.screenDelta > 0 or change.bufferDelta > 0
|
2014-04-20 21:44:48 +04:00
|
|
|
return true unless change.end <= renderedRowRange.start or renderedRowRange.end <= change.start
|
2014-04-15 23:56:58 +04:00
|
|
|
|
|
|
|
false
|
|
|
|
|
2014-04-25 05:07:17 +04:00
|
|
|
componentDidUpdate: (oldProps) ->
|
|
|
|
unless @lastMeasuredWidth? and isEqualForProperties(oldProps, @props, 'maxLineNumberDigits', 'fontSize', 'fontFamily')
|
|
|
|
width = @getDOMNode().offsetWidth
|
|
|
|
if width isnt @lastMeasuredWidth
|
|
|
|
@lastMeasuredWidth = width
|
|
|
|
@props.onWidthChanged(width)
|
|
|
|
|
2014-04-14 20:11:11 +04:00
|
|
|
LineNumberComponent = React.createClass
|
2014-04-16 03:17:30 +04:00
|
|
|
displayName: 'LineNumberComponent'
|
|
|
|
|
2014-04-14 20:11:11 +04:00
|
|
|
render: ->
|
2014-05-11 00:26:23 +04:00
|
|
|
{index, lineHeight, scrollOffset} = @props
|
2014-04-14 20:11:11 +04:00
|
|
|
div
|
2014-05-11 00:26:23 +04:00
|
|
|
className: "line-number"
|
|
|
|
style: {WebkitTransform: "translate3d(0px, #{index * lineHeight + scrollOffset}px, 0px)"}
|
2014-04-14 20:11:11 +04:00
|
|
|
dangerouslySetInnerHTML: {__html: @buildInnerHTML()}
|
|
|
|
|
|
|
|
buildInnerHTML: ->
|
2014-04-25 05:07:17 +04:00
|
|
|
{lineNumber, maxLineNumberDigits} = @props
|
|
|
|
if lineNumber.length < maxLineNumberDigits
|
|
|
|
padding = multiplyString(' ', maxLineNumberDigits - lineNumber.length)
|
2014-04-14 20:11:11 +04:00
|
|
|
padding + lineNumber + @iconDivHTML
|
|
|
|
else
|
|
|
|
lineNumber + @iconDivHTML
|
|
|
|
|
|
|
|
iconDivHTML: '<div class="icon-right"></div>'
|
2014-04-15 04:07:43 +04:00
|
|
|
|
2014-04-20 21:44:48 +04:00
|
|
|
shouldComponentUpdate: (newProps) ->
|
2014-05-11 00:26:23 +04:00
|
|
|
not isEqualForProperties(newProps, @props, 'index', 'lineHeight', 'scrollOffset')
|