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