forked from atom/atom
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgutter-container-component.coffee
111 lines (93 loc) · 4.33 KB
/
gutter-container-component.coffee
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
_ = require 'underscore-plus'
CustomGutterComponent = require './custom-gutter-component'
LineNumberGutterComponent = require './line-number-gutter-component'
# The GutterContainerComponent manages the GutterComponents of a particular
# TextEditorComponent.
module.exports =
class GutterContainerComponent
constructor: ({@onLineNumberGutterMouseDown, @editor, @domElementPool, @views}) ->
# An array of objects of the form: {name: {String}, component: {Object}}
@gutterComponents = []
@gutterComponentsByGutterName = {}
@lineNumberGutterComponent = null
@domNode = document.createElement('div')
@domNode.classList.add('gutter-container')
@domNode.style.display = 'flex'
destroy: ->
for {component} in @gutterComponents
component.destroy?()
return
getDomNode: ->
@domNode
getLineNumberGutterComponent: ->
@lineNumberGutterComponent
updateSync: (state) ->
# The GutterContainerComponent expects the gutters to be sorted in the order
# they should appear.
newState = state.gutters
newGutterComponents = []
newGutterComponentsByGutterName = {}
for {gutter, visible, styles, content} in newState
gutterComponent = @gutterComponentsByGutterName[gutter.name]
if not gutterComponent
if gutter.name is 'line-number'
gutterComponent = new LineNumberGutterComponent({onMouseDown: @onLineNumberGutterMouseDown, @editor, gutter, @domElementPool, @views})
@lineNumberGutterComponent = gutterComponent
else
gutterComponent = new CustomGutterComponent({gutter, @views})
if visible then gutterComponent.showNode() else gutterComponent.hideNode()
# Pass the gutter only the state that it needs.
if gutter.name is 'line-number'
# For ease of use in the line number gutter component, set the shared
# 'styles' as a field under the 'content'.
gutterSubstate = _.clone(content)
gutterSubstate.styles = styles
else
# Custom gutter 'content' is keyed on gutter name, so we cannot set
# 'styles' as a subfield directly under it.
gutterSubstate = {content, styles}
gutterComponent.updateSync(gutterSubstate)
newGutterComponents.push({
name: gutter.name,
component: gutterComponent,
})
newGutterComponentsByGutterName[gutter.name] = gutterComponent
@reorderGutters(newGutterComponents, newGutterComponentsByGutterName)
@gutterComponents = newGutterComponents
@gutterComponentsByGutterName = newGutterComponentsByGutterName
###
Section: Private Methods
###
reorderGutters: (newGutterComponents, newGutterComponentsByGutterName) ->
# First, insert new gutters into the DOM.
indexInOldGutters = 0
oldGuttersLength = @gutterComponents.length
for gutterComponentDescription in newGutterComponents
gutterComponent = gutterComponentDescription.component
gutterName = gutterComponentDescription.name
if @gutterComponentsByGutterName[gutterName]
# If the gutter existed previously, we first try to move the cursor to
# the point at which it occurs in the previous gutters.
matchingGutterFound = false
while indexInOldGutters < oldGuttersLength
existingGutterComponentDescription = @gutterComponents[indexInOldGutters]
existingGutterComponent = existingGutterComponentDescription.component
indexInOldGutters++
if existingGutterComponent is gutterComponent
matchingGutterFound = true
break
if not matchingGutterFound
# If we've reached this point, the gutter previously existed, but its
# position has moved. Remove it from the DOM and re-insert it.
gutterComponent.getDomNode().remove()
@domNode.appendChild(gutterComponent.getDomNode())
else
if indexInOldGutters is oldGuttersLength
@domNode.appendChild(gutterComponent.getDomNode())
else
@domNode.insertBefore(gutterComponent.getDomNode(), @domNode.children[indexInOldGutters])
# Remove any gutters that were not present in the new gutters state.
for gutterComponentDescription in @gutterComponents
if not newGutterComponentsByGutterName[gutterComponentDescription.name]
gutterComponent = gutterComponentDescription.component
gutterComponent.getDomNode().remove()