1 | /* |
2 | SPDX-FileCopyrightText: 2010 Christoph Cullmann <cullmann@kde.org> |
3 | |
4 | Based on code of the SmartCursor/Range by: |
5 | SPDX-FileCopyrightText: 2003-2005 Hamish Rodda <rodda@kde.org> |
6 | |
7 | SPDX-License-Identifier: LGPL-2.0-or-later |
8 | */ |
9 | |
10 | #ifndef KATE_TEXTRANGE_H |
11 | #define |
12 | |
13 | #include <ktexteditor/movingrange.h> |
14 | |
15 | #include "katetextcursor.h" |
16 | |
17 | namespace KTextEditor |
18 | { |
19 | class MovingRangeFeedback; |
20 | class View; |
21 | } |
22 | |
23 | namespace Kate |
24 | { |
25 | class TextBuffer; |
26 | |
27 | /** |
28 | * Class representing a 'clever' text range. |
29 | * It will automagically move if the text inside the buffer it belongs to is modified. |
30 | * By intention no subclass of KTextEditor::Range, must be converted manually. |
31 | * A TextRange is allowed to be empty. If you call setInvalidateIfEmpty(true), |
32 | * a TextRange will become automatically invalid as soon as start() == end() |
33 | * position holds. |
34 | */ |
35 | class final : public KTextEditor::MovingRange |
36 | { |
37 | // this is a friend, block changes might invalidate ranges... |
38 | friend class TextBlock; |
39 | |
40 | public: |
41 | /** |
42 | * Construct a text range. |
43 | * A TextRange is not allowed to be empty, as soon as start == end position, it will become |
44 | * automatically invalid! |
45 | * @param buffer parent text buffer |
46 | * @param range The initial text range assumed by the new range. |
47 | * @param insertBehavior Define whether the range should expand when text is inserted adjacent to the range. |
48 | * @param emptyBehavior Define whether the range should invalidate itself on becoming empty. |
49 | */ |
50 | (TextBuffer &buffer, KTextEditor::Range range, InsertBehaviors insertBehavior, EmptyBehavior emptyBehavior = AllowEmpty); |
51 | |
52 | /** |
53 | * No copy constructor, don't allow this to be copied. |
54 | */ |
55 | (const TextRange &) = delete; |
56 | |
57 | /** |
58 | * Destruct the text block |
59 | */ |
60 | () override; |
61 | |
62 | /** |
63 | * No assignment operator, no copying around. |
64 | */ |
65 | TextRange &(const TextRange &) = delete; |
66 | |
67 | /** |
68 | * Set insert behaviors. |
69 | * @param insertBehaviors new insert behaviors |
70 | */ |
71 | void (InsertBehaviors insertBehaviors) override; |
72 | |
73 | /** |
74 | * Get current insert behaviors. |
75 | * @return current insert behaviors |
76 | */ |
77 | InsertBehaviors () const override; |
78 | |
79 | /** |
80 | * Set if this range will invalidate itself if it becomes empty. |
81 | * @param emptyBehavior behavior on becoming empty |
82 | */ |
83 | void (EmptyBehavior emptyBehavior) override; |
84 | |
85 | /** |
86 | * Will this range invalidate itself if it becomes empty? |
87 | * @return behavior on becoming empty |
88 | */ |
89 | EmptyBehavior () const override |
90 | { |
91 | return m_invalidateIfEmpty ? InvalidateIfEmpty : AllowEmpty; |
92 | } |
93 | |
94 | /** |
95 | * Gets the document to which this range is bound. |
96 | * \return a pointer to the document |
97 | */ |
98 | KTextEditor::Document *() const override; |
99 | |
100 | /** |
101 | * Set the range of this range. |
102 | * A TextRange is not allowed to be empty, as soon as start == end position, it will become |
103 | * automatically invalid! |
104 | * @param range new range for this clever range |
105 | */ |
106 | void (KTextEditor::Range range) override; |
107 | |
108 | /** |
109 | * \overload |
110 | * Set the range of this range |
111 | * A TextRange is not allowed to be empty, as soon as start == end position, it will become |
112 | * automatically invalid! |
113 | * @param start new start for this clever range |
114 | * @param end new end for this clever range |
115 | */ |
116 | void (KTextEditor::Cursor start, KTextEditor::Cursor end) |
117 | { |
118 | KTextEditor::MovingRange::setRange(start, end); |
119 | } |
120 | |
121 | /** |
122 | * Set the range of this range and the connected attribute. |
123 | * Avoids internal overhead of separate setting that. |
124 | * |
125 | * A TextRange is not allowed to be empty, as soon as start == end position, it will become |
126 | * automatically invalid! |
127 | * |
128 | * @param range new range for this clever range |
129 | * @param attribute Attribute to assign to this range. If null, simply removes the previous Attribute. |
130 | * |
131 | * @since 6.0 |
132 | */ |
133 | void (KTextEditor::Range range, KTextEditor::Attribute::Ptr attribute) override; |
134 | |
135 | /** |
136 | * Set the range of this range and the connected attribute and Z-depth. |
137 | * Avoids internal overhead of separate setting that. |
138 | * |
139 | * A TextRange is not allowed to be empty, as soon as start == end position, it will become |
140 | * automatically invalid! |
141 | * |
142 | * @param range new range for this clever range |
143 | * @param attribute Attribute to assign to this range. If null, simply removes the previous Attribute. |
144 | * @param zDepth new Z-depth of this range |
145 | * |
146 | * @since 6.0 |
147 | */ |
148 | void (KTextEditor::Range range, KTextEditor::Attribute::Ptr attribute, qreal zDepth) override; |
149 | |
150 | /** |
151 | * Retrieve start cursor of this range, read-only. |
152 | * @return start cursor |
153 | */ |
154 | const KTextEditor::MovingCursor &() const override |
155 | { |
156 | return m_start; |
157 | } |
158 | |
159 | /** |
160 | * Non-virtual version of start(), which is faster. |
161 | * @return start cursor |
162 | */ |
163 | const TextCursor &() const |
164 | { |
165 | return m_start; |
166 | } |
167 | |
168 | /** |
169 | * Retrieve end cursor of this range, read-only. |
170 | * @return end cursor |
171 | */ |
172 | const KTextEditor::MovingCursor &() const override |
173 | { |
174 | return m_end; |
175 | } |
176 | |
177 | /** |
178 | * Nonvirtual version of end(), which is faster. |
179 | * @return end cursor |
180 | */ |
181 | const TextCursor &() const |
182 | { |
183 | return m_end; |
184 | } |
185 | |
186 | /** |
187 | * Hides parent's impl of toLineRange() and uses non-virtual functions internally. |
188 | */ |
189 | KTextEditor::LineRange () const |
190 | { |
191 | return {startInternal().lineInternal(), endInternal().lineInternal()}; |
192 | } |
193 | |
194 | /** |
195 | * Convert this clever range into a dumb one. |
196 | * @return normal range |
197 | */ |
198 | const KTextEditor::Range () const |
199 | { |
200 | auto startCursor = KTextEditor::Cursor(startInternal().lineInternal(), startInternal().columnInternal()); |
201 | auto endCursor = KTextEditor::Cursor(endInternal().lineInternal(), endInternal().columnInternal()); |
202 | return KTextEditor::Range(startCursor, endCursor); |
203 | } |
204 | |
205 | /** |
206 | * Convert this clever range into a dumb one. Equal to toRange, allowing to use implicit conversion. |
207 | * @return normal range |
208 | */ |
209 | () const |
210 | { |
211 | return toRange(); |
212 | } |
213 | |
214 | /** |
215 | * Gets the active view for this range. Might be already invalid, internally only used for pointer comparisons. |
216 | * |
217 | * \return a pointer to the active view |
218 | */ |
219 | KTextEditor::View *() const override |
220 | { |
221 | return m_view; |
222 | } |
223 | |
224 | /** |
225 | * Sets the currently active view for this range. |
226 | * This will trigger update of the relevant view parts, if the view changed. |
227 | * Set view before the attribute, that will avoid not needed redraws. |
228 | * |
229 | * \param view View to assign to this range. If null, simply |
230 | * removes the previous view. |
231 | */ |
232 | void (KTextEditor::View *view) override; |
233 | |
234 | /** |
235 | * Gets the active Attribute for this range. |
236 | * |
237 | * \return a pointer to the active attribute |
238 | */ |
239 | const KTextEditor::Attribute::Ptr &() const override |
240 | { |
241 | return m_attribute; |
242 | } |
243 | |
244 | /** |
245 | * \return whether a nonzero attribute is set. This is faster than checking attribute(), |
246 | * because the reference-counting is omitted. |
247 | */ |
248 | bool () const |
249 | { |
250 | return m_attribute.constData(); |
251 | } |
252 | |
253 | /** |
254 | * Sets the currently active attribute for this range. |
255 | * This will trigger update of the relevant view parts. |
256 | * |
257 | * \param attribute Attribute to assign to this range. If null, simply |
258 | * removes the previous Attribute. |
259 | */ |
260 | void (KTextEditor::Attribute::Ptr attribute) override; |
261 | |
262 | /** |
263 | * Gets the active MovingRangeFeedback for this range. |
264 | * |
265 | * \return a pointer to the active MovingRangeFeedback |
266 | */ |
267 | KTextEditor::MovingRangeFeedback *() const override |
268 | { |
269 | return m_feedback; |
270 | } |
271 | |
272 | /** |
273 | * Sets the currently active MovingRangeFeedback for this range. |
274 | * This will trigger evaluation if feedback must be send again (for example if mouse is already inside range). |
275 | * |
276 | * \param feedback MovingRangeFeedback to assign to this range. If null, simply |
277 | * removes the previous MovingRangeFeedback. |
278 | */ |
279 | void (KTextEditor::MovingRangeFeedback *feedback) override; |
280 | |
281 | /** |
282 | * Is this range's attribute only visible in views, not for example prints? |
283 | * Default is false. |
284 | * @return range visible only for views |
285 | */ |
286 | bool () const override |
287 | { |
288 | return m_attributeOnlyForViews; |
289 | } |
290 | |
291 | /** |
292 | * Set if this range's attribute is only visible in views, not for example prints. |
293 | * @param onlyForViews attribute only valid for views |
294 | */ |
295 | void (bool onlyForViews) override; |
296 | |
297 | /** |
298 | * Gets the current Z-depth of this range. |
299 | * Ranges with smaller Z-depth than others will win during rendering. |
300 | * Default is 0.0. |
301 | * |
302 | * \return current Z-depth of this range |
303 | */ |
304 | qreal () const override |
305 | { |
306 | return m_zDepth; |
307 | } |
308 | |
309 | /** |
310 | * Set the current Z-depth of this range. |
311 | * Ranges with smaller Z-depth than others will win during rendering. |
312 | * This will trigger update of the relevant view parts, if the depth changed. |
313 | * Set depth before the attribute, that will avoid not needed redraws. |
314 | * Default is 0.0. |
315 | * |
316 | * \param zDepth new Z-depth of this range |
317 | */ |
318 | void (qreal zDepth) override; |
319 | |
320 | private: |
321 | /** |
322 | * Check if range is valid, used by constructor and setRange. |
323 | * If at least one cursor is invalid, both will set to invalid. |
324 | * Same if range itself is invalid (start >= end). |
325 | * |
326 | * IMPORTANT: Notifications might need to deletion of this range! |
327 | * |
328 | * @param oldLineRange line range of this range before changing of cursors, needed to add/remove range from m_ranges in blocks, required! |
329 | * @param notifyAboutChange should feedback be emitted or not? |
330 | */ |
331 | void (KTextEditor::LineRange oldLineRange, bool notifyAboutChange = true); |
332 | |
333 | /** |
334 | * Add/Remove range from the lookup m_ranges hash of each block |
335 | * @param oldLineRange old line range before changing of cursors, needed to add/remove range from m_ranges in blocks |
336 | * @param lineRange line range to start looking for the range to remove |
337 | */ |
338 | void (KTextEditor::LineRange oldLineRange, KTextEditor::LineRange lineRange); |
339 | |
340 | /** |
341 | * Mark this range for later validity checking. |
342 | */ |
343 | void () |
344 | { |
345 | m_isCheckValidityRequired = true; |
346 | } |
347 | |
348 | /** |
349 | * Does this range need validity checking? |
350 | * @return is checking required? |
351 | */ |
352 | bool () const |
353 | { |
354 | return m_isCheckValidityRequired; |
355 | } |
356 | |
357 | private: |
358 | /** |
359 | * parent text buffer |
360 | * is a reference, and no pointer, as this must always exist and can't change |
361 | */ |
362 | TextBuffer &; |
363 | |
364 | /** |
365 | * Start cursor for this range, is a clever cursor |
366 | */ |
367 | TextCursor ; |
368 | |
369 | /** |
370 | * End cursor for this range, is a clever cursor |
371 | */ |
372 | TextCursor ; |
373 | |
374 | /** |
375 | * The view for which the attribute is valid, 0 means any view |
376 | */ |
377 | KTextEditor::View *; |
378 | |
379 | /** |
380 | * This range's current attribute. |
381 | */ |
382 | KTextEditor::Attribute::Ptr ; |
383 | |
384 | /** |
385 | * pointer to the active MovingRangeFeedback |
386 | */ |
387 | KTextEditor::MovingRangeFeedback *; |
388 | |
389 | /** |
390 | * Z-depth of this range for rendering |
391 | */ |
392 | qreal ; |
393 | |
394 | /** |
395 | * Is this range's attribute only visible in views, not for example prints? |
396 | */ |
397 | bool ; |
398 | |
399 | /** |
400 | * Will this range invalidate itself if it becomes empty? |
401 | */ |
402 | bool ; |
403 | |
404 | /** |
405 | * Should this range be validated? |
406 | * Used by KateTextBlock to avoid multiple updates without costly hashing. |
407 | * Reset by checkValidity(). |
408 | */ |
409 | bool = false; |
410 | }; |
411 | |
412 | } |
413 | |
414 | #endif |
415 | |