1/* This file is part of the Kate project.
2 *
3 * Copyright (C) 2010 Christoph Cullmann <cullmann@kde.org>
4 *
5 * Based on code of the SmartCursor/Range by:
6 * Copyright (C) 2003-2005 Hamish Rodda <rodda@kde.org>
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
17 *
18 * You should have received a copy of the GNU Library General Public License
19 * along with this library; see the file COPYING.LIB. If not, write to
20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
22 */
23
24#ifndef KATE_TEXTRANGE_H
25#define KATE_TEXTRANGE_H
26
27#include <ktexteditor/view.h>
28#include <ktexteditor/movingrange.h>
29#include <ktexteditor/movingrangefeedback.h>
30
31#include "katepartprivate_export.h"
32#include "katetextcursor.h"
33
34namespace Kate {
35
36class TextBuffer;
37
38/**
39 * Class representing a 'clever' text range.
40 * It will automagically move if the text inside the buffer it belongs to is modified.
41 * By intention no subclass of KTextEditor::Range, must be converted manually.
42 * A TextRange is allowed to be empty. If you call setInvalidateIfEmpty(true),
43 * a TextRange will become automatically invalid as soon as start() == end()
44 * position holds.
45 */
46class KATEPART_TESTS_EXPORT TextRange : public KTextEditor::MovingRange {
47 // this is a friend, block changes might invalidate ranges...
48 friend class TextBlock;
49
50 public:
51 /**
52 * Construct a text range.
53 * A TextRange is not allowed to be empty, as soon as start == end position, it will become
54 * automatically invalid!
55 * @param buffer parent text buffer
56 * @param range The initial text range assumed by the new range.
57 * @param insertBehavior Define whether the range should expand when text is inserted adjacent to the range.
58 * @param emptyBehavior Define whether the range should invalidate itself on becoming empty.
59 */
60 TextRange (TextBuffer &buffer, const KTextEditor::Range &range, InsertBehaviors insertBehavior, EmptyBehavior emptyBehavior = AllowEmpty);
61
62 /**
63 * Destruct the text block
64 */
65 ~TextRange ();
66
67 /**
68 * Set insert behaviors.
69 * @param insertBehaviors new insert behaviors
70 */
71 void setInsertBehaviors (InsertBehaviors insertBehaviors);
72
73 /**
74 * Get current insert behaviors.
75 * @return current insert behaviors
76 */
77 InsertBehaviors insertBehaviors () const;
78
79 /**
80 * Set if this range will invalidate itself if it becomes empty.
81 * @param emptyBehavior behavior on becoming empty
82 */
83 void setEmptyBehavior (EmptyBehavior emptyBehavior);
84
85 /**
86 * Will this range invalidate itself if it becomes empty?
87 * @return behavior on becoming empty
88 */
89 EmptyBehavior emptyBehavior () const { return m_invalidateIfEmpty ? InvalidateIfEmpty : AllowEmpty; }
90
91 /**
92 * Gets the document to which this range is bound.
93 * \return a pointer to the document
94 */
95 KTextEditor::Document *document () const;
96
97 /**
98 * Set the range of this range.
99 * A TextRange is not allowed to be empty, as soon as start == end position, it will become
100 * automatically invalid!
101 * @param range new range for this clever range
102 */
103 void setRange (const KTextEditor::Range &range);
104
105 /**
106 * \overload
107 * Set the range of this range
108 * A TextRange is not allowed to be empty, as soon as start == end position, it will become
109 * automatically invalid!
110 * @param start new start for this clever range
111 * @param end new end for this clever range
112 */
113 void setRange (const KTextEditor::Cursor &start, const KTextEditor::Cursor &end) { KTextEditor::MovingRange::setRange (start, end); }
114
115 /**
116 * Retrieve start cursor of this range, read-only.
117 * @return start cursor
118 */
119 const KTextEditor::MovingCursor &start () const { return m_start; }
120
121 /**
122 * Non-virtual version of start(), which is faster.
123 * @return start cursor
124 */
125 const TextCursor &startInternal() const { return m_start; }
126
127 /**
128 * Retrieve end cursor of this range, read-only.
129 * @return end cursor
130 */
131 const KTextEditor::MovingCursor &end () const { return m_end; }
132
133 /**
134 * Nonvirtual version of end(), which is faster.
135 * @return end cursor
136 */
137 const TextCursor &endInternal () const { return m_end; }
138
139 /**
140 * Convert this clever range into a dumb one.
141 * @return normal range
142 */
143 const KTextEditor::Range toRange () const { return KTextEditor::Range (start().toCursor(), end().toCursor()); }
144
145 /**
146 * Convert this clever range into a dumb one. Equal to toRange, allowing to use implicit conversion.
147 * @return normal range
148 */
149 operator const KTextEditor::Range () const { return KTextEditor::Range (start().toCursor(), end().toCursor()); }
150
151 /**
152 * Gets the active view for this range. Might be already invalid, internally only used for pointer comparisons.
153 *
154 * \return a pointer to the active view
155 */
156 KTextEditor::View *view () const { return m_view; }
157
158 /**
159 * Sets the currently active view for this range.
160 * This will trigger update of the relevant view parts, if the view changed.
161 * Set view before the attribute, that will avoid not needed redraws.
162 *
163 * \param attribute View to assign to this range. If null, simply
164 * removes the previous view.
165 */
166 void setView (KTextEditor::View *view);
167
168 /**
169 * Gets the active Attribute for this range.
170 *
171 * \return a pointer to the active attribute
172 */
173 KTextEditor::Attribute::Ptr attribute () const { return m_attribute; }
174
175 /**
176 * \return whether a nonzero attribute is set. This is faster than checking attribute(),
177 * because the reference-counting is omitted.
178 */
179 bool hasAttribute() const { return !m_attribute.isNull(); }
180
181 /**
182 * Sets the currently active attribute for this range.
183 * This will trigger update of the relevant view parts.
184 *
185 * \param attribute Attribute to assign to this range. If null, simply
186 * removes the previous Attribute.
187 */
188 void setAttribute (KTextEditor::Attribute::Ptr attribute);
189
190 /**
191 * Gets the active MovingRangeFeedback for this range.
192 *
193 * \return a pointer to the active MovingRangeFeedback
194 */
195 KTextEditor::MovingRangeFeedback *feedback () const { return m_feedback; }
196
197 /**
198 * Sets the currently active MovingRangeFeedback for this range.
199 * This will trigger evaluation if feedback must be send again (for example if mouse is already inside range).
200 *
201 * \param attribute MovingRangeFeedback to assign to this range. If null, simply
202 * removes the previous MovingRangeFeedback.
203 */
204 void setFeedback (KTextEditor::MovingRangeFeedback *feedback);
205
206 /**
207 * Is this range's attribute only visible in views, not for example prints?
208 * Default is false.
209 * @return range visible only for views
210 */
211 bool attributeOnlyForViews () const { return m_attributeOnlyForViews; }
212
213 /**
214 * Set if this range's attribute is only visible in views, not for example prints.
215 * @param onlyForViews attribute only valid for views
216 */
217 void setAttributeOnlyForViews (bool onlyForViews);
218
219 /**
220 * Gets the current Z-depth of this range.
221 * Ranges with smaller Z-depth than others will win during rendering.
222 * Default is 0.0.
223 *
224 * \return current Z-depth of this range
225 */
226 qreal zDepth () const { return m_zDepth; }
227
228 /**
229 * Set the current Z-depth of this range.
230 * Ranges with smaller Z-depth than others will win during rendering.
231 * This will trigger update of the relevant view parts, if the depth changed.
232 * Set depth before the attribute, that will avoid not needed redraws.
233 * Default is 0.0.
234 *
235 * \param zDepth new Z-depth of this range
236 */
237 void setZDepth (qreal zDepth);
238
239 private:
240 /**
241 * no copy constructor, don't allow this to be copied.
242 */
243 TextRange (const TextRange &);
244
245 /**
246 * no assignment operator, no copying around.
247 */
248 TextRange &operator= (const TextRange &);
249
250 /**
251 * Check if range is valid, used by constructor and setRange.
252 * If at least one cursor is invalid, both will set to invalid.
253 * Same if range itself is invalid (start >= end).
254 * @param oldStartLine old start line of this range before changing of cursors, needed to add/remove range from m_ranges in blocks
255 * @param oldEndLine old end line of this range
256 * @param notifyAboutChange should feedback be emitted or not?
257 */
258 void checkValidity (int oldStartLine = -1, int oldEndLine = -1, bool notifyAboutChange = true);
259
260 /**
261 * Add/Remove range from the lookup m_ranges hash of each block
262 * @param oldStartLine old start line of this range before changing of cursors, needed to add/remove range from m_ranges in blocks
263 * @param oldEndLine old end line of this range
264 * @param startLine start line to start looking for the range to remove
265 * @param endLine end line of this range
266 */
267 void fixLookup (int oldStartLine, int oldEndLine, int startLine, int endLine);
268
269 private:
270 /**
271 * parent text buffer
272 * is a reference, and no pointer, as this must always exist and can't change
273 */
274 TextBuffer &m_buffer;
275
276 /**
277 * Start cursor for this range, is a clever cursor
278 */
279 TextCursor m_start;
280
281 /**
282 * End cursor for this range, is a clever cursor
283 */
284 TextCursor m_end;
285
286 /**
287 * The view for which the attribute is valid, 0 means any view
288 */
289 KTextEditor::View *m_view;
290
291 /**
292 * This range's current attribute.
293 */
294 KTextEditor::Attribute::Ptr m_attribute;
295
296 /**
297 * pointer to the active MovingRangeFeedback
298 */
299 KTextEditor::MovingRangeFeedback *m_feedback;
300
301 /**
302 * Z-depth of this range for rendering
303 */
304 qreal m_zDepth;
305
306 /**
307 * Is this range's attribute only visible in views, not for example prints?
308 */
309 bool m_attributeOnlyForViews;
310
311 /**
312 * Will this range invalidate itself if it becomes empty?
313 */
314 bool m_invalidateIfEmpty;
315};
316
317}
318
319#endif
320