You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
466 lines
13 KiB
466 lines
13 KiB
/* 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
|