diff options
Diffstat (limited to 'kate/part/katesupercursor.h')
-rw-r--r-- | kate/part/katesupercursor.h | 463 |
1 files changed, 463 insertions, 0 deletions
diff --git a/kate/part/katesupercursor.h b/kate/part/katesupercursor.h new file mode 100644 index 000000000..e6b16baa8 --- /dev/null +++ b/kate/part/katesupercursor.h @@ -0,0 +1,463 @@ +/* This file is part of the KDE libraries + Copyright (C) 2003 Hamish Rodda <rodda@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KATESUPERCURSOR_H +#define KATESUPERCURSOR_H + +#include "katecursor.h" + +class KateDocument; +class KateView; + +/** + * Possible additional features: + * - Notification when a cursor enters or exits a view + * - suggest something :) + * + * Unresolved issues: + * - testing, testing, testing + * - ie. everything which hasn't already been tested, you can see that which has inside the #ifdefs + * - api niceness + */ + +/** + * A cursor which updates and gives off various interesting signals. + * + * This aims to be a working version of what KateCursor was originally intended to be. + * + * @author Hamish Rodda + **/ +class KateSuperCursor : public QObject, public KateDocCursor, public Kate::Cursor +{ + Q_OBJECT + +public: + /** + * bool privateC says: if private, than don't show to apps using the cursorinterface in the list, + * all internally only used SuperCursors should be private or people could modify them from the + * outside breaking kate's internals + */ + KateSuperCursor(KateDocument* doc, bool privateC, const KateTextCursor& cursor, QObject* parent = 0L, const char* name = 0L); + KateSuperCursor(KateDocument* doc, bool privateC, int lineNum = 0, int col = 0, QObject* parent = 0L, const char* name = 0L); + + ~KateSuperCursor (); + + public: + // KTextEditor::Cursor interface + void position(uint *line, uint *col) const; + bool setPosition(uint line, uint col); + bool insertText(const QString& text); + bool removeText(uint numberOfCharacters); + QChar currentChar() const; + + /** + * @returns true if the cursor is situated at the start of the line, false if it isn't. + */ + bool atStartOfLine() const; + + /** + * @returns true if the cursor is situated at the end of the line, false if it isn't. + */ + bool atEndOfLine() const; + + /** + * Returns how this cursor behaves when text is inserted at the cursor. + * Defaults to not moving on insert. + */ + bool moveOnInsert() const; + + /** + * Change the behavior of the cursor when text is inserted at the cursor. + * + * If @p moveOnInsert is true, the cursor will end up at the end of the insert. + */ + void setMoveOnInsert(bool moveOnInsert); + + /** + * Debug: output the position. + */ + operator QString(); + + // Reimplementations; + virtual void setLine(int lineNum); + virtual void setCol(int colNum); + virtual void setPos(const KateTextCursor& pos); + virtual void setPos(int lineNum, int colNum); + + signals: + /** + * The cursor's position was directly changed by the program. + */ + void positionDirectlyChanged(); + + /** + * The cursor's position was changed. + */ + void positionChanged(); + + /** + * Athough an edit took place, the cursor's position was unchanged. + */ + void positionUnChanged(); + + /** + * The cursor's surrounding characters were both deleted simultaneously. + * The cursor is automatically placed at the start of the deleted region. + */ + void positionDeleted(); + + /** + * A character was inserted immediately before the cursor. + * + * Whether the char was inserted before or after this cursor depends on + * moveOnInsert(): + * @li true -> the char was inserted before + * @li false -> the char was inserted after + */ + void charInsertedAt(); + + /** + * The character immediately before the cursor was deleted. + */ + void charDeletedBefore(); + + /** + * The character immediately after the cursor was deleted. + */ + void charDeletedAfter(); + + //BEGIN METHODES TO CALL FROM KATE DOCUMENT TO KEEP CURSOR UP TO DATE + public: + void editTextInserted ( uint line, uint col, uint len); + void editTextRemoved ( uint line, uint col, uint len); + + void editLineWrapped ( uint line, uint col, bool newLine = true ); + void editLineUnWrapped ( uint line, uint col, bool removeLine = true, uint length = 0 ); + + void editLineInserted ( uint line ); + void editLineRemoved ( uint line ); + //END + + private: + KateDocument *m_doc; + bool m_moveOnInsert : 1; + bool m_lineRemoved : 1; + bool m_privateCursor : 1; +}; + +/** + * Represents a range of text, from the start() to the end(). + * + * Also tracks its position and emits useful signals. + */ +class KateSuperRange : public QObject, public KateRange +{ + friend class KateSuperRangeList; + + Q_OBJECT + +public: + /// Determine how the range reacts to characters inserted immediately outside the range. + enum InsertBehaviour { + /// Don't expand to encapsulate new characters in either direction. This is the default. + DoNotExpand = 0, + /// Expand to encapsulate new characters to the left of the range. + ExpandLeft = 0x1, + /// Expand to encapsulate new characters to the right of the range. + ExpandRight = 0x2 + }; + + /** + * Constructor. Takes posession of @p start and @p end. + */ + KateSuperRange(KateSuperCursor* start, KateSuperCursor* end, QObject* parent = 0L, const char* name = 0L); + KateSuperRange(KateDocument* doc, const KateRange& range, QObject* parent = 0L, const char* name = 0L); + KateSuperRange(KateDocument* doc, const KateTextCursor& start, const KateTextCursor& end, QObject* parent = 0L, const char* name = 0L); + + virtual ~KateSuperRange(); + + // fulfill KateRange requirements + virtual KateTextCursor& start(); + virtual KateTextCursor& end(); + virtual const KateTextCursor& start() const; + virtual const KateTextCursor& end() const; + + void allowZeroLength(bool yes=true){m_allowZeroLength=yes;} + /** + * Returns the super start cursor. + */ + KateSuperCursor& superStart(); + const KateSuperCursor& superStart() const; + + /** + * Returns the super end cursor. + */ + KateSuperCursor& superEnd(); + const KateSuperCursor& superEnd() const; + + /** + * Returns how this range reacts to characters inserted immediately outside the range. + */ + int behaviour() const; + + /** + * Determine how the range should react to characters inserted immediately outside the range. + * + * TODO does this need a custom function to enable determining of the behavior based on the + * text that is inserted / deleted? + * + * @sa InsertBehaviour + */ + void setBehaviour(int behaviour); + + /** + * Start and end must be valid and start <= end. + */ + virtual bool isValid() const; + + /** + * This is for use where the ranges are used in a heirachy, + * ie. their parents are KateSuperRanges which completely + * encapsulate them. + * + * @todo constrain children when their position changes deliberately; + * eliminate() children when they are equivalent to their parents + * + * @returns true if the range contains the cursor and no children + * also contain it; false otherwise. + */ + bool owns(const KateTextCursor& cursor) const; + + /** + * Returns true if the range includes @p cursor 's character. + * Returns false if @p cursor == end(). + */ + bool includes(const KateTextCursor& cursor) const; + + /** + * Returns true if the range includes @p line + */ + bool includes(uint lineNum) const; + + /** + * Returns true if the range totally encompasses @p line + */ + bool includesWholeLine(uint lineNum) const; + + /** + * Returns whether @p cursor is the site of a boundary of this range. + */ + bool boundaryAt(const KateTextCursor& cursor) const; + + /** + * Returns whether there is a boundary of this range on @p line. + */ + bool boundaryOn(uint lineNum) const; + +signals: + /** + * More interesting signals that aren't worth implementing here: + * firstCharDeleted: start()::charDeleted() + * lastCharDeleted: end()::previousCharDeleted() + */ + + /** + * The range's position changed. + */ + void positionChanged(); + + /** + * The range's position was unchanged. + */ + void positionUnChanged(); + + /** + * The contents of the range changed. + */ + void contentsChanged(); + + /** + * Either cursor's surrounding characters were both deleted. + */ + void boundaryDeleted(); + + /** + * The range now contains no characters (ie. the start and end cursors are the same). + * + * To eliminate this range under different conditions, connect the other signal directly + * to this signal. + */ + void eliminated(); + + /** + * Indicates the region needs re-drawing. + */ + void tagRange(KateSuperRange* range); + +public slots: + void slotTagRange(); + +private slots: + void slotEvaluateChanged(); + void slotEvaluateUnChanged(); + +private: + void init(); + void evaluateEliminated(); + void evaluatePositionChanged(); + + KateSuperCursor* m_start; + KateSuperCursor* m_end; + bool m_evaluate; + bool m_startChanged; + bool m_endChanged; + bool m_deleteCursors; + bool m_allowZeroLength; +}; + +class KateSuperCursorList : public QPtrList<KateSuperCursor> +{ +protected: + virtual int compareItems(QPtrCollection::Item item1, QPtrCollection::Item item2); +}; + +class KateSuperRangeList : public QObject, public QPtrList<KateSuperRange> +{ + Q_OBJECT + +public: + /** + * @sa autoManage() + */ + KateSuperRangeList(bool autoManage = true, QObject* parent = 0L, const char* name = 0L); + + /** + * Semi-copy constructor. + * + * Does not copy auto-manage value, as that would make it too easy to perform + * double-deletions. + * + * Also, does not connect signals and slots to save time, as this is mainly + * used by the document itself while drawing (call connectAll() to re-constitute) + */ + KateSuperRangeList(const QPtrList<KateSuperRange>& rangeList, QObject* parent = 0L, const char* name = 0L); + + virtual ~KateSuperRangeList() {} + /** + * Append another list. + * If this object was created by the semi-copy constructor, it may not connect items + * (unless connectAll() has already been called), call connectAll(). + */ + void appendList(const QPtrList<KateSuperRange>& rangeList); + + /** + * Connect items that are not connected. This only needs to be called once, + * and only if this was created with the semi-copy constructor. + */ + void connectAll(); + + /** + * Override to emit rangeEliminated() signals. + */ + virtual void clear(); + + /** + * Automanage is a combination of autodeleting of the objects and + * removing of any eliminated() ranges. + */ + bool autoManage() const; + + /** + * @sa autoManage() + */ + void setAutoManage(bool autoManage); + + /** + * This is just a straight-forward list so that there is no confusion about whether + * this list should be auto-managed (ie. it shouldn't, to avoid double deletions). + */ + QPtrList<KateSuperRange> rangesIncluding(const KateTextCursor& cursor); + QPtrList<KateSuperRange> rangesIncluding(uint line); + + /** + * @retval true if one of the ranges in the list includes @p cursor + * @retval false otherwise + */ + bool rangesInclude(const KateTextCursor& cursor); + + /** + * Construct a list of boundaries, and return the first, or 0L if there are none. + * If @p start is defined, the first boundary returned will be at or after @p start. + * + * @returns the first boundary location + */ + KateSuperCursor* firstBoundary(const KateTextCursor* start = 0L); + + /** + * @returns the next boundary, or 0L if there are no more. + */ + KateSuperCursor* nextBoundary(); + + /** + * @returns the current boundary + */ + KateSuperCursor* currentBoundary(); + +signals: + /** + * The range now contains no characters (ie. the start and end cursors are the same). + * If autoManage() is true, the range will be deleted after the signal has processed. + */ + void rangeEliminated(KateSuperRange* range); + + /** + * There are no ranges left. + */ + void listEmpty(); + + /** + * Connected to all ranges if connect()ed. + */ + void tagRange(KateSuperRange* range); + +protected: + /** + * internal reimplementation + */ + virtual int compareItems(QPtrCollection::Item item1, QPtrCollection::Item item2); + + /** + * internal reimplementation + */ + virtual QPtrCollection::Item newItem(QPtrCollection::Item d); + +private slots: + void slotEliminated(); + void slotDeleted(QObject* range); + +private: + bool m_autoManage; + bool m_connect; + + KateSuperCursorList m_columnBoundaries; + bool m_trackingBoundaries; +}; + +#endif + +// kate: space-indent on; indent-width 2; replace-tabs on; |