File indexing completed on 2024-04-28 07:46:28

0001 /*
0002     SPDX-FileCopyrightText: 2005 Hamish Rodda <rodda@kde.org>
0003     SPDX-FileCopyrightText: 2008-2018 Dominik Haumann <dhaumann@kde.org>
0004 
0005     SPDX-License-Identifier: LGPL-2.0-or-later
0006 */
0007 
0008 #ifndef KATELAYOUTCACHE_H
0009 #define KATELAYOUTCACHE_H
0010 
0011 #include <QPair>
0012 
0013 #include <ktexteditor/range.h>
0014 
0015 #include "katetextlayout.h"
0016 
0017 class KateRenderer;
0018 
0019 class KateLineLayoutMap
0020 {
0021 public:
0022     void clear();
0023 
0024     void insert(int realLine, std::unique_ptr<KateLineLayout> lineLayoutPtr);
0025 
0026     void relayoutLines(int startRealLine, int endRealLine);
0027 
0028     void slotEditDone(int fromLine, int toLine, int shiftAmount, std::vector<KateTextLayout> &textLayouts);
0029 
0030     KateLineLayout *find(int i);
0031 
0032     typedef std::pair<int, std::unique_ptr<KateLineLayout>> LineLayoutPair;
0033 
0034 private:
0035     typedef std::vector<LineLayoutPair> LineLayoutMap;
0036     LineLayoutMap m_lineLayouts;
0037 };
0038 
0039 /**
0040  * This class handles Kate's caching of layouting information (in KateLineLayout
0041  * and KateTextLayout).  This information is used primarily by both the view and
0042  * the renderer.
0043  *
0044  * We outsource the hardcore layouting logic to the renderer, but other than
0045  * that, this class handles all manipulation of the layout objects.
0046  *
0047  * This is separate from the renderer 1) for clarity 2) so you can have separate
0048  * caches for separate views of the same document, even for view and printer
0049  * (if the renderer is made to support rendering onto different targets).
0050  *
0051  * @author Hamish Rodda \<rodda@kde.org\>
0052  */
0053 
0054 class KateLayoutCache : public QObject
0055 {
0056 public:
0057     explicit KateLayoutCache(KateRenderer *renderer, QObject *parent);
0058 
0059     void clear();
0060 
0061     int viewWidth() const;
0062     void setViewWidth(int width);
0063 
0064     bool wrap() const;
0065     void setWrap(bool wrap);
0066 
0067     bool acceptDirtyLayouts() const;
0068     void setAcceptDirtyLayouts(bool accept);
0069 
0070     // BEGIN generic methods to get/set layouts
0071     /**
0072      * Returns the KateLineLayout for the specified line.
0073      *
0074      * If one does not exist, it will be created and laid out.
0075      * Layouts which are not directly part of the view will be kept until the
0076      * cache is full or until they are invalidated by other means (eg. the text
0077      * changes).
0078      *
0079      * This function shall never return null
0080      *
0081      * \param realLine real line number of the layout to retrieve.
0082      * \param virtualLine virtual line number. only needed if you think it may have changed
0083      *                    (ie. basically internal to KateLayoutCache)
0084      */
0085     KateLineLayout *line(int realLine, int virtualLine = -1);
0086 
0087     /// Returns the layout describing the text line which is occupied by \p realCursor.
0088     KateTextLayout textLayout(const KTextEditor::Cursor realCursor);
0089 
0090     /// Returns the layout of the specified realLine + viewLine.
0091     /// if viewLine is -1, return the last.
0092     KateTextLayout textLayout(uint realLine, int viewLine);
0093     // END
0094 
0095     // BEGIN methods to do with the caching of lines visible within a view
0096     /// Returns the layout of the corresponding line in the view
0097     KateTextLayout &viewLine(int viewLine);
0098 
0099     /**
0100      * Find the view line of the cursor, relative to the display (0 = top line of view, 1 = second line, etc.)
0101      *
0102      * If @p limitToVisible is true, the function can return -2 for lines below the view. The idea is to get extra
0103      * information about where the line lies when its out of the view so the clients doesn't have to make second
0104      * call of this function with limitToVisible = false and potentionaly rerendering the whole document.
0105      *
0106      * \param virtualCursor cursor position
0107      * \param limitToVisible if true, limit the search to only visible lines
0108      *
0109      * @return line number relative to the display. If @p limitToVisible is true,
0110      * then valid values are only positive, negative values are invalid cursors for -1 and -2 for cursor is
0111      * below the view.
0112      */
0113     int displayViewLine(const KTextEditor::Cursor virtualCursor, bool limitToVisible = false);
0114 
0115     int viewCacheLineCount() const;
0116     KTextEditor::Cursor viewCacheStart() const;
0117     KTextEditor::Cursor viewCacheEnd() const;
0118     void updateViewCache(const KTextEditor::Cursor startPos, int newViewLineCount = -1, int viewLinesScrolled = 0);
0119 
0120     void relayoutLines(int startRealLine, int endRealLine);
0121 
0122     // find the index of the last view line for a specific line
0123     int lastViewLine(int realLine);
0124     // find the view line of cursor c (0 = same line, 1 = down one, etc.)
0125     int viewLine(const KTextEditor::Cursor realCursor);
0126     int viewLineCount(int realLine);
0127 
0128     void viewCacheDebugOutput() const;
0129     // END
0130 
0131 private:
0132     void wrapLine(KTextEditor::Document *, const KTextEditor::Cursor position);
0133     void unwrapLine(KTextEditor::Document *, int line);
0134     void insertText(KTextEditor::Document *, const KTextEditor::Cursor position, const QString &text);
0135     void removeText(KTextEditor::Document *, KTextEditor::Range range, const QString &);
0136 
0137 private:
0138     KateRenderer *m_renderer;
0139 
0140     /**
0141      * The master cache of all line layouts.
0142      *
0143      * Layouts which are not within the current view cache and whose
0144      * refcount == 1 are only known to the cache and can be safely deleted.
0145      */
0146     KateLineLayoutMap m_lineLayouts;
0147 
0148     // Convenience vector for quick direct access to the specific text layout
0149     KTextEditor::Cursor m_startPos = KTextEditor::Cursor::invalid();
0150 
0151     std::vector<KateTextLayout> m_textLayouts;
0152 
0153     int m_viewWidth = 0;
0154     bool m_wrap = false;
0155     bool m_acceptDirtyLayouts = false;
0156 };
0157 
0158 #endif