summaryrefslogtreecommitdiffstats
path: root/lib/kformula/formulacursor.h
diff options
context:
space:
mode:
Diffstat (limited to 'lib/kformula/formulacursor.h')
-rw-r--r--lib/kformula/formulacursor.h465
1 files changed, 465 insertions, 0 deletions
diff --git a/lib/kformula/formulacursor.h b/lib/kformula/formulacursor.h
new file mode 100644
index 000000000..72cfb1781
--- /dev/null
+++ b/lib/kformula/formulacursor.h
@@ -0,0 +1,465 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001 Andrea Rizzi <rizzi@kde.org>
+ Ulrich Kuettler <ulrich.kuettler@mailbox.tu-dresden.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ 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 FORMULACURSOR_H
+#define FORMULACURSOR_H
+
+#include <qstring.h>
+
+#include "basicelement.h"
+#include "kformuladefs.h"
+
+KFORMULA_NAMESPACE_BEGIN
+
+class FormulaElement;
+class IndexElement;
+class MatrixElement;
+class NameSequence;
+class RootElement;
+class SymbolElement;
+class TextElement;
+
+
+/**
+ * The selection. This might be a position selection or
+ * an area. Each view will need one FormulaCursor.
+ *
+ * The @ref Container always uses the cursor to operate on
+ * the element tree.
+ *
+ * Note that it is up to the elements to actually move the cursor.
+ * (The cursor has no chance to know how.)
+ */
+class FormulaCursor {
+
+ // Yes, we do have a friend.
+ friend class SequenceElement;
+
+public:
+
+ /**
+ * Creates a cursor and puts is at the beginning
+ * of the formula.
+ *
+ * @param element the formula the cursor point to. This must not be 0.
+ */
+ FormulaCursor(FormulaElement* element);
+
+ FormulaCursor& operator= (const FormulaCursor&);
+
+ // where the cursor and the mark are
+ uint getPos() const { return cursorPos; }
+ int getMark() const { return markPos; }
+
+ /**
+ * Tells whether the cursor has changed since last cleaning.
+ */
+ bool hasChanged() const { return hasChangedFlag; }
+
+ /**
+ * Resets the cursor's change flag. The widget calls this
+ * if it has drawn the cursor.
+ */
+ void clearChangedFlag() { hasChangedFlag = false; }
+
+ /**
+ * Returns wether we are in selection mode.
+ */
+ bool isSelectionMode() const { return selectionFlag; }
+
+ /**
+ * Returns wether there actually is a selection.
+ */
+ bool isSelection() const { return selectionFlag && (getPos() != getMark()); }
+
+ /**
+ * Sets the selection mode.
+ */
+ void setSelection(bool selection) { selectionFlag = selection; hasChangedFlag = true; }
+
+ /**
+ * Calculates the size of the cursor. Needs to be called before
+ * the cursor can be drawn.
+ */
+ void calcCursorSize( const ContextStyle& context, bool smallCursor );
+
+ /**
+ * Draws the cursor at its current position.
+ * The cursor will always be drawn in xor mode.
+ */
+ void draw( QPainter&, const ContextStyle& context, StyleAttributes& style,
+ bool smallCursor, bool activeCursor );
+
+
+ // simple cursor movement.
+
+ void moveLeft(int flag = NormalMovement);
+ void moveRight(int flag = NormalMovement);
+ void moveUp(int flag = NormalMovement);
+ void moveDown(int flag = NormalMovement);
+
+ void moveHome(int flag = NormalMovement);
+ void moveEnd(int flag = NormalMovement);
+
+ /** @returns whether the cursor is at the first position. */
+ bool isHome() const;
+
+ /** @returns whether the cursor is at the last position. */
+ bool isEnd() const;
+
+ // how to travel
+
+ bool getLinearMovement() const { return linearMovement; }
+
+ /**
+ * Sets the cursor in linear mode. This means you can visit every
+ * element just by moving left and right.
+ */
+ void setLinearMovement(bool linear) { linearMovement = linear; }
+
+ /**
+ * Moves the cursor inside the element. Selection is turned off.
+ */
+ void goInsideElement(BasicElement* element);
+
+ // mouse selection
+
+ void mousePress( const LuPixelPoint&, int flags );
+ void mouseMove( const LuPixelPoint&, int flags );
+ void mouseRelease( const LuPixelPoint&, int flags );
+
+ /**
+ * Inserts the child at the current position.
+ * Ignores the selection.
+ */
+ void insert(BasicElement*, Direction = beforeCursor);
+
+ /**
+ * Inserts the listed children at the current position.
+ * Ignores the selection.
+ * The list will be emptied.
+ */
+ void insert(QPtrList<BasicElement>&,
+ Direction = beforeCursor);
+
+ /**
+ * Removes the current selected children and returns them.
+ * The cursor needs to be normal (that is be inside a SequenceElement)
+ * for this to have any effect.
+ */
+ void remove(QPtrList<BasicElement>&,
+ Direction = beforeCursor);
+
+
+ /**
+ * Replaces the current selection with the supplied element.
+ * The replaced elements become the new element's main child's content.
+ */
+ void replaceSelectionWith(BasicElement*,
+ Direction = beforeCursor);
+
+ /**
+ * Replaces the element the cursor points to with its main child's
+ * content.
+ */
+ BasicElement* replaceByMainChildContent(Direction = beforeCursor);
+
+ /**
+ * Trys to find the element we are the main child of and replace
+ * it with our content.
+ *
+ * This is simply another form of replaceByMainChildContent. You
+ * use this one if the cursor is normalized and inside the main child.
+ */
+ BasicElement* removeEnclosingElement(Direction = beforeCursor);
+
+ /**
+ * Returns wether the element the cursor points to should be replaced.
+ * Elements are senseless as soon as they only contain a main child.
+ */
+ bool elementIsSenseless();
+
+
+ // The range that is selected. Makes no sense if there is
+ // no selection.
+
+ int getSelectionStart() const { return QMIN(getPos(), getMark()); }
+ int getSelectionEnd() const { return QMAX(getPos(), getMark()); }
+
+
+ /**
+ * Sets the cursor to a new position.
+ * This gets called from the element that wants
+ * to own the cursor. It is a mistake to call this if you aren't
+ * an element.
+ *
+ * If you provide a mark >= 0 the selection gets turned on.
+ * If there is a selection and you don't provide a mark the
+ * current mark won't change.
+ */
+ void setTo(BasicElement* element, uint cursor, int mark=-1);
+
+ void setPos(uint pos);
+ void setMark(int mark);
+
+
+ /**
+ * The element we are in. In most cases this is a SequenceElement.
+ * There is no way to place a cursor outside a SequenceElement by
+ * normal movement.
+ * But in special cases (e.g. if you remove an index from an
+ * IndexElement) the cursor can be placed to odd places. This is
+ * the reason why you have to normalize the cursor after each
+ * removal.
+ */
+ BasicElement* getElement() { return current; }
+ const BasicElement* getElement() const { return current; }
+
+
+ /**
+ * Moves the cursor to a normal position. That is somewhere
+ * inside a SequenceElement.
+ * You need to call this after each removal because the cursor
+ * might point to some non existing place.
+ */
+ void normalize(Direction direction = beforeCursor);
+
+
+ /**
+ * Returns the sequence the cursor is in if we are normal. If not returns 0.
+ */
+ SequenceElement* normal();
+ const SequenceElement* normal() const;
+
+ /**
+ * Returns the IndexElement the cursor is on or 0
+ * if there is non.
+ */
+ IndexElement* getActiveIndexElement();
+
+ /**
+ * Returns the RootElement the cursor is on or 0
+ * if there is non.
+ */
+ RootElement* getActiveRootElement();
+
+ /**
+ * Returns the SymbolElement the cursor is on or 0
+ * if there is non.
+ */
+ SymbolElement* getActiveSymbolElement();
+
+ /**
+ * @returns the NameSequence the cursor is on or 0
+ * if there is non.
+ */
+ NameSequence* getActiveNameSequence();
+
+ /**
+ * @returns the TextElement the cursor is on or 0.
+ */
+ TextElement* getActiveTextElement();
+
+ /**
+ * @returns the MatrixElement the cursor is on or 0.
+ */
+ MatrixElement* getActiveMatrixElement();
+
+ /**
+ * Selects the element the cursor points to (stands after)
+ * if there is such an element and if there is no selection.
+ */
+ void selectActiveElement();
+
+ /**
+ * Stores the currently selected elements inside a dom.
+ */
+ void copy( QDomDocument& doc );
+
+ /**
+ * Inserts the elements that could be read from the dom into
+ * the list. Returns true on success.
+ */
+ bool buildElementsFromDom( QDomElement root, QPtrList<BasicElement>& list );
+
+ /**
+ * Inserts the elements that could be read from the MathML dom into
+ * the list. Returns true on success.
+ */
+ bool buildElementsFromMathMLDom( QDomElement root, QPtrList<BasicElement>& list );
+
+ // undo/redo support
+
+ /**
+ * A black box that is supposed to contain everything
+ * which is needed to describe a cursor. Only the cursor
+ * itself is allowed to read it.
+ */
+ class CursorData {
+ friend class FormulaCursor;
+ BasicElement* current;
+ uint cursorPos;
+ int markPos;
+ bool selectionFlag;
+ bool linearMovement;
+ bool readOnly;
+
+ CursorData(BasicElement* c,
+ uint pos, int mark, bool selection, bool linear, bool ro)
+ : current(c), cursorPos(pos), markPos(mark),
+ selectionFlag(selection), linearMovement(linear),
+ readOnly(ro) {}
+ };
+
+ /**
+ * Creates a new CursorData object that describes the cursor.
+ * It's up to the caller to delete this object.
+ */
+ CursorData* getCursorData();
+
+ /**
+ * Sets the cursor to where the CursorData points to. No checking is done
+ * so you better make sure the point exists.
+ */
+ void setCursorData(CursorData* data);
+
+ /**
+ * The element is going to leave the formula with and all its children.
+ */
+ void elementWillVanish(BasicElement* element);
+
+ /**
+ * A new formula has been loaded. Our current element has to change.
+ */
+ void formulaLoaded(FormulaElement* rootElement);
+
+ /**
+ * @returns the point inside the formula widget where the cursor is.
+ */
+ const LuPixelPoint& getCursorPoint() const { return cursorPoint; }
+
+ /**
+ * @returns the area the cursor is currently on.
+ */
+ const LuPixelRect& getCursorSize() const { return cursorSize; }
+ void addCursorSize( const LuPixelRect& rect ) { cursorSize |= rect; }
+
+ /**
+ * @returns whether we are allowed to alter the document.
+ */
+ bool isReadOnly() const;
+
+ /**
+ * Puts the widget in read only mode.
+ */
+ void setReadOnly(bool ro) { readOnly = ro; }
+
+private:
+
+ /**
+ * Returns the child the cursor points to. Depending on the
+ * direction this might be the child before or after the
+ * cursor.
+ *
+ * Might be 0 is there is no such child.
+ */
+ BasicElement* getActiveChild(Direction direction);
+
+ /**
+ * Returns the child that is currently selected.
+ *
+ * Might be 0 is there is no such child. e.g. if there are more
+ * than one element selected.
+ */
+ BasicElement* getSelectedChild();
+
+ /**
+ * Tells whether we currently point to the given elements
+ * main child and to the place behind its last child.
+ */
+ bool pointsAfterMainChild(BasicElement*);
+
+ /**
+ * Sets the selection according to the shift key.
+ */
+ void handleSelectState(int flag);
+
+
+ /**
+ * The element the cursor is inside right now.
+ */
+ BasicElement* current;
+
+ /**
+ * The position the cursor in on inside the element.
+ * Might be anything from 0 to current->children->size().
+ *
+ * This is where new elements are put in.
+ */
+ uint cursorPos;
+
+ /**
+ * The position of the mark. If we are in selection mode this
+ * is the other side of the selected area.
+ * Note that the mark always belongs to the same SequenceElement
+ * as the cursor.
+ */
+ int markPos;
+
+ /**
+ * Tells whether there is a selection area.
+ * (This is not equal to (markPos != -1).)
+ */
+ bool selectionFlag;
+
+ /**
+ * Tells whether we want to travel through all elements by
+ * left and right movement.
+ */
+ bool linearMovement;
+
+ /**
+ * The point in the middle of the cursor. Gets updated
+ * each time the cursor is drawn.
+ */
+ LuPixelPoint cursorPoint;
+
+ /**
+ * The area that is covered by the cursor. Gets updated
+ * each time the cursor is drawn.
+ */
+ LuPixelRect cursorSize;
+
+ /**
+ * Tells whether the cursor has been changed. This is set
+ * by any of the setSomething methods. It's used by the
+ * widget the cursor belongs to.
+ */
+ bool hasChangedFlag;
+
+ /**
+ * Whether we are only allowed to read.
+ */
+ bool readOnly;
+};
+
+KFORMULA_NAMESPACE_END
+
+#endif // FORMULACURSOR_H