@@ -70,7 +70,7 @@ class StyledRangeContainer {
70
70
}
71
71
}
72
72
73
- var _storage : [ ProviderID : RangeStore < StyleElement > ] = [ : ]
73
+ var _storage : [ ProviderID : ( store : RangeStore < StyleElement > , priority : Int ) ] = [ : ]
74
74
weak var delegate : StyledRangeContainerDelegate ?
75
75
76
76
/// Initialize the container with a list of provider identifiers. Each provider is given an id, they should be
@@ -80,17 +80,21 @@ class StyledRangeContainer {
80
80
/// - providers: An array of identifiers given to providers.
81
81
init ( documentLength: Int , providers: [ ProviderID ] ) {
82
82
for provider in providers {
83
- _storage [ provider] = RangeStore < StyleElement > ( documentLength: documentLength)
83
+ _storage [ provider] = ( store : RangeStore < StyleElement > ( documentLength: documentLength) , priority : provider )
84
84
}
85
85
}
86
86
87
- func addProvider( _ id: ProviderID , documentLength: Int ) {
87
+ func addProvider( _ id: ProviderID , priority : Int , documentLength: Int ) {
88
88
assert ( !_storage. keys. contains ( id) , " Provider already exists " )
89
- _storage [ id] = RangeStore < StyleElement > ( documentLength: documentLength)
89
+ _storage [ id] = ( store: RangeStore < StyleElement > ( documentLength: documentLength) , priority: priority)
90
+ }
91
+
92
+ func setPriority( providerId: ProviderID , priority: Int ) {
93
+ _storage [ providerId] ? . priority = priority
90
94
}
91
95
92
96
func removeProvider( _ id: ProviderID ) {
93
- guard let provider = _storage [ id] else { return }
97
+ guard let provider = _storage [ id] ? . store else { return }
94
98
applyHighlightResult (
95
99
provider: id,
96
100
highlights: [ ] ,
@@ -99,64 +103,9 @@ class StyledRangeContainer {
99
103
_storage. removeValue ( forKey: id)
100
104
}
101
105
102
- /// Coalesces all styled runs into a single continuous array of styled runs.
103
- ///
104
- /// When there is an overlapping, conflicting style (eg: provider 2 gives `.comment` to the range `0..<2`, and
105
- /// provider 1 gives `.string` to `1..<2`), the provider with a lower identifier will be prioritized. In the example
106
- /// case, the final value would be `0..<1=.comment` and `1..<2=.string`.
107
- ///
108
- /// - Parameter range: The range to query.
109
- /// - Returns: An array of continuous styled runs.
110
- func runsIn( range: NSRange ) -> [ RangeStoreRun < StyleElement > ] {
111
- func combineLowerPriority( _ lhs: inout RangeStoreRun < StyleElement > , _ rhs: RangeStoreRun < StyleElement > ) {
112
- lhs. value = lhs. value? . combineLowerPriority ( rhs. value) ?? rhs. value
113
- }
114
-
115
- func combineHigherPriority( _ lhs: inout RangeStoreRun < StyleElement > , _ rhs: RangeStoreRun < StyleElement > ) {
116
- lhs. value = lhs. value? . combineHigherPriority ( rhs. value) ?? rhs. value
117
- }
118
-
119
- // Ordered by priority, lower = higher priority.
120
- var allRuns = _storage. sorted ( by: { $0. key < $1. key } ) . map { $0. value. runs ( in: range. intRange) }
121
- var runs : [ RangeStoreRun < StyleElement > ] = [ ]
122
-
123
- var minValue = allRuns. compactMap { $0. last } . enumerated ( ) . min ( by: { $0. 1 . length < $1. 1 . length } )
124
-
125
- while let value = minValue {
126
- // Get minimum length off the end of each array
127
- let minRunIdx = value. offset
128
- var minRun = value. element
129
-
130
- for idx in ( 0 ..< allRuns. count) . reversed ( ) where idx != minRunIdx {
131
- guard let last = allRuns [ idx] . last else { continue }
132
- if idx < minRunIdx {
133
- combineHigherPriority ( & minRun, last)
134
- } else {
135
- combineLowerPriority ( & minRun, last)
136
- }
137
-
138
- if last. length == minRun. length {
139
- allRuns [ idx] . removeLast ( )
140
- } else {
141
- // safe due to guard a few lines above.
142
- allRuns [ idx] [ allRuns [ idx] . count - 1 ] . subtractLength ( minRun)
143
- }
144
- }
145
-
146
- if !allRuns[ minRunIdx] . isEmpty {
147
- allRuns [ minRunIdx] . removeLast ( )
148
- }
149
-
150
- runs. append ( minRun)
151
- minValue = allRuns. compactMap { $0. last } . enumerated ( ) . min ( by: { $0. 1 . length < $1. 1 . length } )
152
- }
153
-
154
- return runs. reversed ( )
155
- }
156
-
157
106
func storageUpdated( editedRange: NSRange , changeInLength delta: Int ) {
158
107
for key in _storage. keys {
159
- _storage [ key] ? . storageUpdated ( editedRange: editedRange, changeInLength: delta)
108
+ _storage [ key] ? . store . storageUpdated ( editedRange: editedRange, changeInLength: delta)
160
109
}
161
110
}
162
111
}
@@ -171,7 +120,7 @@ extension StyledRangeContainer: HighlightProviderStateDelegate {
171
120
/// - rangeToHighlight: The range to apply the highlights to.
172
121
func applyHighlightResult( provider: ProviderID , highlights: [ HighlightRange ] , rangeToHighlight: NSRange ) {
173
122
assert ( rangeToHighlight != . notFound, " NSNotFound is an invalid highlight range " )
174
- guard var storage = _storage [ provider] else {
123
+ guard var storage = _storage [ provider] ? . store else {
175
124
assertionFailure ( " No storage found for the given provider: \( provider) " )
176
125
return
177
126
}
@@ -193,12 +142,12 @@ extension StyledRangeContainer: HighlightProviderStateDelegate {
193
142
lastIndex = highlight. range. max
194
143
}
195
144
196
- if lastIndex != rangeToHighlight. upperBound {
145
+ if lastIndex < rangeToHighlight. upperBound {
197
146
runs. append ( . empty( length: rangeToHighlight. upperBound - lastIndex) )
198
147
}
199
148
200
149
storage. set ( runs: runs, for: rangeToHighlight. intRange)
201
- _storage [ provider] = storage
150
+ _storage [ provider] ? . store = storage
202
151
delegate? . styleContainerDidUpdate ( in: rangeToHighlight)
203
152
}
204
153
}
0 commit comments