File indexing completed on 2024-05-05 07:59:17

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