File indexing completed on 2024-09-15 03:40:11
0001 /* 0002 SPDX-FileCopyrightText: 2010 Christoph Cullmann <cullmann@kde.org> 0003 0004 Based on code of the SmartCursor/Range by: 0005 SPDX-FileCopyrightText: 2003-2005 Hamish Rodda <rodda@kde.org> 0006 0007 SPDX-License-Identifier: LGPL-2.0-or-later 0008 */ 0009 0010 #ifndef KATE_TEXTRANGE_H 0011 #define KATE_TEXTRANGE_H 0012 0013 #include <ktexteditor/movingrange.h> 0014 0015 #include "katetextcursor.h" 0016 0017 namespace KTextEditor 0018 { 0019 class MovingRangeFeedback; 0020 class View; 0021 } 0022 0023 namespace Kate 0024 { 0025 class TextBuffer; 0026 0027 /** 0028 * Class representing a 'clever' text range. 0029 * It will automagically move if the text inside the buffer it belongs to is modified. 0030 * By intention no subclass of KTextEditor::Range, must be converted manually. 0031 * A TextRange is allowed to be empty. If you call setInvalidateIfEmpty(true), 0032 * a TextRange will become automatically invalid as soon as start() == end() 0033 * position holds. 0034 */ 0035 class TextRange final : public KTextEditor::MovingRange 0036 { 0037 // this is a friend, block changes might invalidate ranges... 0038 friend class TextBlock; 0039 0040 public: 0041 /** 0042 * Construct a text range. 0043 * A TextRange is not allowed to be empty, as soon as start == end position, it will become 0044 * automatically invalid! 0045 * @param buffer parent text buffer 0046 * @param range The initial text range assumed by the new range. 0047 * @param insertBehavior Define whether the range should expand when text is inserted adjacent to the range. 0048 * @param emptyBehavior Define whether the range should invalidate itself on becoming empty. 0049 */ 0050 TextRange(TextBuffer &buffer, KTextEditor::Range range, InsertBehaviors insertBehavior, EmptyBehavior emptyBehavior = AllowEmpty); 0051 0052 /** 0053 * No copy constructor, don't allow this to be copied. 0054 */ 0055 TextRange(const TextRange &) = delete; 0056 0057 /** 0058 * Destruct the text block 0059 */ 0060 ~TextRange() override; 0061 0062 /** 0063 * No assignment operator, no copying around. 0064 */ 0065 TextRange &operator=(const TextRange &) = delete; 0066 0067 /** 0068 * Set insert behaviors. 0069 * @param insertBehaviors new insert behaviors 0070 */ 0071 void setInsertBehaviors(InsertBehaviors insertBehaviors) override; 0072 0073 /** 0074 * Get current insert behaviors. 0075 * @return current insert behaviors 0076 */ 0077 InsertBehaviors insertBehaviors() const override; 0078 0079 /** 0080 * Set if this range will invalidate itself if it becomes empty. 0081 * @param emptyBehavior behavior on becoming empty 0082 */ 0083 void setEmptyBehavior(EmptyBehavior emptyBehavior) override; 0084 0085 /** 0086 * Will this range invalidate itself if it becomes empty? 0087 * @return behavior on becoming empty 0088 */ 0089 EmptyBehavior emptyBehavior() const override 0090 { 0091 return m_invalidateIfEmpty ? InvalidateIfEmpty : AllowEmpty; 0092 } 0093 0094 /** 0095 * Gets the document to which this range is bound. 0096 * \return a pointer to the document 0097 */ 0098 KTextEditor::Document *document() const override; 0099 0100 /** 0101 * Set the range of this range. 0102 * A TextRange is not allowed to be empty, as soon as start == end position, it will become 0103 * automatically invalid! 0104 * @param range new range for this clever range 0105 */ 0106 void setRange(KTextEditor::Range range) override; 0107 0108 /** 0109 * \overload 0110 * Set the range of this range 0111 * A TextRange is not allowed to be empty, as soon as start == end position, it will become 0112 * automatically invalid! 0113 * @param start new start for this clever range 0114 * @param end new end for this clever range 0115 */ 0116 void setRange(KTextEditor::Cursor start, KTextEditor::Cursor end) 0117 { 0118 KTextEditor::MovingRange::setRange(start, end); 0119 } 0120 0121 /** 0122 * Retrieve start cursor of this range, read-only. 0123 * @return start cursor 0124 */ 0125 const KTextEditor::MovingCursor &start() const override 0126 { 0127 return m_start; 0128 } 0129 0130 /** 0131 * Non-virtual version of start(), which is faster. 0132 * @return start cursor 0133 */ 0134 const TextCursor &startInternal() const 0135 { 0136 return m_start; 0137 } 0138 0139 /** 0140 * Retrieve end cursor of this range, read-only. 0141 * @return end cursor 0142 */ 0143 const KTextEditor::MovingCursor &end() const override 0144 { 0145 return m_end; 0146 } 0147 0148 /** 0149 * Nonvirtual version of end(), which is faster. 0150 * @return end cursor 0151 */ 0152 const TextCursor &endInternal() const 0153 { 0154 return m_end; 0155 } 0156 0157 /** 0158 * Hides parent's impl of toLineRange() and uses non-virtual functions internally. 0159 */ 0160 KTextEditor::LineRange toLineRange() const 0161 { 0162 return {startInternal().lineInternal(), endInternal().lineInternal()}; 0163 } 0164 0165 /** 0166 * Convert this clever range into a dumb one. 0167 * @return normal range 0168 */ 0169 const KTextEditor::Range toRange() const 0170 { 0171 auto startCursor = KTextEditor::Cursor(startInternal().lineInternal(), startInternal().columnInternal()); 0172 auto endCursor = KTextEditor::Cursor(endInternal().lineInternal(), endInternal().columnInternal()); 0173 return KTextEditor::Range(startCursor, endCursor); 0174 } 0175 0176 /** 0177 * Convert this clever range into a dumb one. Equal to toRange, allowing to use implicit conversion. 0178 * @return normal range 0179 */ 0180 operator KTextEditor::Range() const 0181 { 0182 return toRange(); 0183 } 0184 0185 /** 0186 * Gets the active view for this range. Might be already invalid, internally only used for pointer comparisons. 0187 * 0188 * \return a pointer to the active view 0189 */ 0190 KTextEditor::View *view() const override 0191 { 0192 return m_view; 0193 } 0194 0195 /** 0196 * Sets the currently active view for this range. 0197 * This will trigger update of the relevant view parts, if the view changed. 0198 * Set view before the attribute, that will avoid not needed redraws. 0199 * 0200 * \param view View to assign to this range. If null, simply 0201 * removes the previous view. 0202 */ 0203 void setView(KTextEditor::View *view) override; 0204 0205 /** 0206 * Gets the active Attribute for this range. 0207 * 0208 * \return a pointer to the active attribute 0209 */ 0210 const KTextEditor::Attribute::Ptr &attribute() const override 0211 { 0212 return m_attribute; 0213 } 0214 0215 /** 0216 * \return whether a nonzero attribute is set. This is faster than checking attribute(), 0217 * because the reference-counting is omitted. 0218 */ 0219 bool hasAttribute() const 0220 { 0221 return m_attribute.constData(); 0222 } 0223 0224 /** 0225 * Sets the currently active attribute for this range. 0226 * This will trigger update of the relevant view parts. 0227 * 0228 * \param attribute Attribute to assign to this range. If null, simply 0229 * removes the previous Attribute. 0230 */ 0231 void setAttribute(KTextEditor::Attribute::Ptr attribute) override; 0232 0233 /** 0234 * Gets the active MovingRangeFeedback for this range. 0235 * 0236 * \return a pointer to the active MovingRangeFeedback 0237 */ 0238 KTextEditor::MovingRangeFeedback *feedback() const override 0239 { 0240 return m_feedback; 0241 } 0242 0243 /** 0244 * Sets the currently active MovingRangeFeedback for this range. 0245 * This will trigger evaluation if feedback must be send again (for example if mouse is already inside range). 0246 * 0247 * \param feedback MovingRangeFeedback to assign to this range. If null, simply 0248 * removes the previous MovingRangeFeedback. 0249 */ 0250 void setFeedback(KTextEditor::MovingRangeFeedback *feedback) override; 0251 0252 /** 0253 * Is this range's attribute only visible in views, not for example prints? 0254 * Default is false. 0255 * @return range visible only for views 0256 */ 0257 bool attributeOnlyForViews() const override 0258 { 0259 return m_attributeOnlyForViews; 0260 } 0261 0262 /** 0263 * Set if this range's attribute is only visible in views, not for example prints. 0264 * @param onlyForViews attribute only valid for views 0265 */ 0266 void setAttributeOnlyForViews(bool onlyForViews) override; 0267 0268 /** 0269 * Gets the current Z-depth of this range. 0270 * Ranges with smaller Z-depth than others will win during rendering. 0271 * Default is 0.0. 0272 * 0273 * \return current Z-depth of this range 0274 */ 0275 qreal zDepth() const override 0276 { 0277 return m_zDepth; 0278 } 0279 0280 /** 0281 * Set the current Z-depth of this range. 0282 * Ranges with smaller Z-depth than others will win during rendering. 0283 * This will trigger update of the relevant view parts, if the depth changed. 0284 * Set depth before the attribute, that will avoid not needed redraws. 0285 * Default is 0.0. 0286 * 0287 * \param zDepth new Z-depth of this range 0288 */ 0289 void setZDepth(qreal zDepth) override; 0290 0291 private: 0292 /** 0293 * Check if range is valid, used by constructor and setRange. 0294 * If at least one cursor is invalid, both will set to invalid. 0295 * Same if range itself is invalid (start >= end). 0296 * 0297 * IMPORTANT: Notifications might need to deletion of this range! 0298 * 0299 * @param oldLineRange line range of this range before changing of cursors, needed to add/remove range from m_ranges in blocks, required! 0300 * @param notifyAboutChange should feedback be emitted or not? 0301 */ 0302 void checkValidity(KTextEditor::LineRange oldLineRange, bool notifyAboutChange = true); 0303 0304 /** 0305 * Add/Remove range from the lookup m_ranges hash of each block 0306 * @param oldLineRange old line range before changing of cursors, needed to add/remove range from m_ranges in blocks 0307 * @param lineRange line range to start looking for the range to remove 0308 */ 0309 void fixLookup(KTextEditor::LineRange oldLineRange, KTextEditor::LineRange lineRange); 0310 0311 /** 0312 * Mark this range for later validity checking. 0313 */ 0314 void setValidityCheckRequired() 0315 { 0316 m_isCheckValidityRequired = true; 0317 } 0318 0319 /** 0320 * Does this range need validity checking? 0321 * @return is checking required? 0322 */ 0323 bool isValidityCheckRequired() const 0324 { 0325 return m_isCheckValidityRequired; 0326 } 0327 0328 private: 0329 /** 0330 * parent text buffer 0331 * is a reference, and no pointer, as this must always exist and can't change 0332 */ 0333 TextBuffer &m_buffer; 0334 0335 /** 0336 * Start cursor for this range, is a clever cursor 0337 */ 0338 TextCursor m_start; 0339 0340 /** 0341 * End cursor for this range, is a clever cursor 0342 */ 0343 TextCursor m_end; 0344 0345 /** 0346 * The view for which the attribute is valid, 0 means any view 0347 */ 0348 KTextEditor::View *m_view; 0349 0350 /** 0351 * This range's current attribute. 0352 */ 0353 KTextEditor::Attribute::Ptr m_attribute; 0354 0355 /** 0356 * pointer to the active MovingRangeFeedback 0357 */ 0358 KTextEditor::MovingRangeFeedback *m_feedback; 0359 0360 /** 0361 * Z-depth of this range for rendering 0362 */ 0363 qreal m_zDepth; 0364 0365 /** 0366 * Is this range's attribute only visible in views, not for example prints? 0367 */ 0368 bool m_attributeOnlyForViews; 0369 0370 /** 0371 * Will this range invalidate itself if it becomes empty? 0372 */ 0373 bool m_invalidateIfEmpty; 0374 0375 /** 0376 * Should this range be validated? 0377 * Used by KateTextBlock to avoid multiple updates without costly hashing. 0378 * Reset by checkValidity(). 0379 */ 0380 bool m_isCheckValidityRequired = false; 0381 }; 0382 0383 } 0384 0385 #endif