mirror of
https://github.com/atom/atom.git
synced 2026-01-23 05:48:10 -05:00
Filter decorations in the components.
This reduces the number of intermediate objects we need to create. The downside is a bit more code complexity in the components.
This commit is contained in:
@@ -2,6 +2,12 @@ _ = require 'underscore-plus'
|
||||
|
||||
module.exports =
|
||||
class Decoration
|
||||
@isType: (decoration, decorationType) ->
|
||||
if _.isArray(decoration.type)
|
||||
decorationType in decoration.type
|
||||
else
|
||||
decorationType is decoration.type
|
||||
|
||||
constructor: (@marker, properties) ->
|
||||
_.extend(this, properties)
|
||||
|
||||
@@ -12,10 +18,7 @@ class Decoration
|
||||
@marker?.isValid()
|
||||
|
||||
isType: (decorationType) ->
|
||||
if _.isArray(@type)
|
||||
decorationType in @type
|
||||
else
|
||||
decorationType is @type
|
||||
Decoration.isType(this, decorationType)
|
||||
|
||||
toObject: ->
|
||||
copy = {}
|
||||
|
||||
@@ -51,11 +51,9 @@ EditorComponent = React.createClass
|
||||
[renderedStartRow, renderedEndRow] = renderedRowRange
|
||||
cursorScreenRanges = @getCursorScreenRanges(renderedRowRange)
|
||||
|
||||
decorationsByMarkerId = editor.decorationsForScreenRowRange(renderedStartRow, renderedEndRow)
|
||||
highlightDecorations = @decorationsByMarkerIdForType(decorationsByMarkerId, 'highlight')
|
||||
|
||||
decorationsByScreenRow = @indexDecorationsByScreenRow(decorationsByMarkerId)
|
||||
gutterDecorations = @decorationsByScreenRowForType(decorationsByScreenRow, 'gutter')
|
||||
decorations = editor.decorationsForScreenRowRange(renderedStartRow, renderedEndRow)
|
||||
decorationsByMarkerId = @filterDecorationsByMarkerId(decorations)
|
||||
decorationsByScreenRow = @filterDecorationsByScreenRow(decorations)
|
||||
|
||||
scrollHeight = editor.getScrollHeight()
|
||||
scrollWidth = editor.getScrollWidth()
|
||||
@@ -79,7 +77,7 @@ EditorComponent = React.createClass
|
||||
|
||||
div className: className, style: {fontSize, lineHeight, fontFamily}, tabIndex: -1,
|
||||
GutterComponent {
|
||||
ref: 'gutter', decorations: gutterDecorations,
|
||||
ref: 'gutter', decorations: decorationsByScreenRow,
|
||||
editor, renderedRowRange, maxLineNumberDigits,
|
||||
scrollTop, scrollHeight, lineHeightInPixels, @pendingChanges, mouseWheelScreenRow
|
||||
}
|
||||
@@ -99,7 +97,7 @@ EditorComponent = React.createClass
|
||||
}
|
||||
LinesComponent {
|
||||
ref: 'lines',
|
||||
editor, lineHeightInPixels, defaultCharWidth, highlightDecorations,
|
||||
editor, lineHeightInPixels, defaultCharWidth, decorationsByScreenRow, decorationsByMarkerId,
|
||||
showIndentGuide, renderedRowRange, @pendingChanges, scrollTop, scrollLeft,
|
||||
@scrollingVertically, scrollHeight, scrollWidth, mouseWheelScreenRow, invisibles,
|
||||
visible, scrollViewHeight
|
||||
@@ -223,22 +221,22 @@ EditorComponent = React.createClass
|
||||
cursorScreenRanges[cursor.id] = screenRange
|
||||
cursorScreenRanges
|
||||
|
||||
indexDecorationsByScreenRow: (decorationsByMarkerId) ->
|
||||
filterDecorationsByScreenRow: (decorationsByMarkerId) ->
|
||||
decorationsByScreenRow = {}
|
||||
for id, decorations of decorationsByMarkerId
|
||||
for decoration in decorations
|
||||
continue unless decoration.isValid()
|
||||
range = decoration.getScreenRange()
|
||||
for screenRow in [range.start.row..range.end.row]
|
||||
decorationsByScreenRow[screenRow] ?= []
|
||||
decorationsByScreenRow[screenRow].push(decoration)
|
||||
if decoration.isValid() and decoration.isType('gutter') or decoration.isType('line')
|
||||
range = decoration.getScreenRange()
|
||||
for screenRow in [range.start.row..range.end.row]
|
||||
decorationsByScreenRow[screenRow] ?= []
|
||||
decorationsByScreenRow[screenRow].push decoration.toObject()
|
||||
decorationsByScreenRow
|
||||
|
||||
decorationsByMarkerIdForType: (decorationsByMarkerId, decorationType) ->
|
||||
filterDecorationsByMarkerId: (decorationsByMarkerId) ->
|
||||
filteredDecorations = {}
|
||||
for id, decorations of decorationsByMarkerId
|
||||
for decoration in decorations
|
||||
if decoration.isType(decorationType) and decoration.isValid()
|
||||
if decoration.isValid() and decoration.isType('highlight')
|
||||
# Using decoration.toObject() for comparability sake. This effectively
|
||||
# caches the current state of the decoration object (importantly, the range).
|
||||
# We need to cache the range because the Decoration's marker's range changes.
|
||||
@@ -246,24 +244,6 @@ EditorComponent = React.createClass
|
||||
filteredDecorations[id].push decoration.toObject()
|
||||
filteredDecorations
|
||||
|
||||
decorationsByScreenRowForType: (decorationsByScreenRow, decorationType) ->
|
||||
{editor} = @props
|
||||
filteredDecorations = {}
|
||||
|
||||
for screenRow, decorations of decorationsByScreenRow
|
||||
for decoration in decorations
|
||||
if decoration.isType(decorationType)
|
||||
filteredDecorations[screenRow] ?= []
|
||||
filteredDecorations[screenRow].push decoration.toObject()
|
||||
|
||||
[startScreenRow, endScreenRow] = @getRenderedRowRange()
|
||||
for screenRow in [startScreenRow...endScreenRow]
|
||||
if editor.isFoldableAtScreenRow(screenRow)
|
||||
filteredDecorations[screenRow] ?= []
|
||||
filteredDecorations[screenRow].push {class: 'foldable'}
|
||||
|
||||
filteredDecorations
|
||||
|
||||
observeEditor: ->
|
||||
{editor} = @props
|
||||
@subscribe editor, 'batched-updates-started', @onBatchedUpdatesStarted
|
||||
|
||||
@@ -2,6 +2,7 @@ _ = require 'underscore-plus'
|
||||
React = require 'react-atom-fork'
|
||||
{div} = require 'reactionary-atom-fork'
|
||||
{isEqual, isEqualForProperties, multiplyString, toArray} = require 'underscore-plus'
|
||||
Decoration = require './decoration'
|
||||
SubscriberMixin = require './subscriber-mixin'
|
||||
|
||||
WrapperDiv = document.createElement('div')
|
||||
@@ -127,8 +128,8 @@ GutterComponent = React.createClass
|
||||
node.removeChild(lineNumberNode)
|
||||
|
||||
buildLineNumberHTML: (bufferRow, softWrapped, maxLineNumberDigits, screenRow, decorations) ->
|
||||
{editor, lineHeightInPixels} = @props
|
||||
if screenRow?
|
||||
{lineHeightInPixels} = @props
|
||||
style = "position: absolute; top: #{screenRow * lineHeightInPixels}px;"
|
||||
else
|
||||
style = "visibility: hidden;"
|
||||
@@ -137,7 +138,10 @@ GutterComponent = React.createClass
|
||||
classes = ''
|
||||
if decorations?
|
||||
for decoration in decorations
|
||||
classes += decoration.class + ' ' if not softWrapped or softWrapped and decoration.softWrap
|
||||
if Decoration.isType(decoration, 'gutter')
|
||||
classes += decoration.class + ' ' if not softWrapped or softWrapped and decoration.softWrap
|
||||
|
||||
classes += "foldable " if bufferRow >= 0 and editor.isFoldableAtBufferRow(bufferRow)
|
||||
classes += "line-number line-number-#{bufferRow}"
|
||||
|
||||
"<div class=\"#{classes}\" style=\"#{style}\" data-buffer-row=\"#{bufferRow}\" data-screen-row=\"#{screenRow}\">#{innerHTML}</div>"
|
||||
@@ -153,16 +157,22 @@ GutterComponent = React.createClass
|
||||
padding + lineNumber + iconHTML
|
||||
|
||||
updateLineNumberNode: (lineNumberId, bufferRow, screenRow, softWrapped, decorations) ->
|
||||
{editor} = @props
|
||||
node = @lineNumberNodesById[lineNumberId]
|
||||
previousDecorations = @previousDecorations[screenRow]
|
||||
|
||||
if editor.isFoldableAtBufferRow(bufferRow)
|
||||
node.classList.add('foldable')
|
||||
else
|
||||
node.classList.remove('foldable')
|
||||
|
||||
if previousDecorations?
|
||||
for decoration in previousDecorations
|
||||
node.classList.remove(decoration.class) if not contains(decorations, decoration)
|
||||
node.classList.remove(decoration.class) if Decoration.isType(decoration, 'gutter') and not contains(decorations, decoration)
|
||||
|
||||
if decorations?
|
||||
for decoration in decorations
|
||||
if not contains(previousDecorations, decoration) and (not softWrapped or softWrapped and decoration.softWrap)
|
||||
if Decoration.isType(decoration, 'gutter') and not contains(previousDecorations, decoration) and (not softWrapped or softWrapped and decoration.softWrap)
|
||||
node.classList.add(decoration.class)
|
||||
|
||||
unless @screenRowsByLineNumberId[lineNumberId] is screenRow
|
||||
|
||||
@@ -11,14 +11,14 @@ HighlightsComponent = React.createClass
|
||||
div className: 'highlights', @renderHighlights()
|
||||
|
||||
renderHighlights: ->
|
||||
{editor, highlightDecorations, lineHeightInPixels} = @props
|
||||
{editor, decorationsByMarkerId, lineHeightInPixels} = @props
|
||||
|
||||
highlightComponents = []
|
||||
for markerId, decorations of highlightDecorations
|
||||
for markerId, decorations of decorationsByMarkerId
|
||||
if decorations?
|
||||
for decoration in decorations
|
||||
highlightComponents.push(HighlightComponent({key: "#{markerId}-#{decoration.class}", decoration, editor, lineHeightInPixels}))
|
||||
highlightComponents
|
||||
|
||||
shouldComponentUpdate: (newProps) ->
|
||||
not isEqualForProperties(newProps, @props, 'highlightDecorations', 'lineHeightInPixels', 'defaultCharWidth')
|
||||
not isEqualForProperties(newProps, @props, 'decorationsByMarkerId', 'lineHeightInPixels', 'defaultCharWidth')
|
||||
|
||||
@@ -15,14 +15,14 @@ LinesComponent = React.createClass
|
||||
|
||||
render: ->
|
||||
if @isMounted()
|
||||
{editor, highlightDecorations, scrollTop, scrollLeft, scrollHeight, scrollWidth, lineHeightInPixels, defaultCharWidth, scrollViewHeight} = @props
|
||||
{editor, decorationsByMarkerId, scrollTop, scrollLeft, scrollHeight, scrollWidth, lineHeightInPixels, defaultCharWidth, scrollViewHeight} = @props
|
||||
style =
|
||||
height: Math.max(scrollHeight, scrollViewHeight)
|
||||
width: scrollWidth
|
||||
WebkitTransform: "translate3d(#{-scrollLeft}px, #{-scrollTop}px, 0px)"
|
||||
|
||||
div {className: 'lines editor-colors', style},
|
||||
HighlightsComponent({editor, highlightDecorations, lineHeightInPixels, defaultCharWidth}) if @isMounted()
|
||||
HighlightsComponent({editor, decorationsByMarkerId, lineHeightInPixels, defaultCharWidth}) if @isMounted()
|
||||
|
||||
componentWillMount: ->
|
||||
@measuredLines = new WeakSet
|
||||
@@ -32,7 +32,7 @@ LinesComponent = React.createClass
|
||||
|
||||
shouldComponentUpdate: (newProps) ->
|
||||
return true unless isEqualForProperties(newProps, @props,
|
||||
'renderedRowRange', 'highlightDecorations', 'lineHeightInPixels', 'defaultCharWidth',
|
||||
'renderedRowRange', 'decorationsByMarkerId', 'lineHeightInPixels', 'defaultCharWidth',
|
||||
'scrollTop', 'scrollLeft', 'showIndentGuide', 'scrollingVertically', 'invisibles', 'visible',
|
||||
'scrollViewHeight', 'mouseWheelScreenRow'
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user