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.
621 lines
19 KiB
621 lines
19 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 SEQUENCEELEMENT_H
|
|
#define SEQUENCEELEMENT_H
|
|
|
|
#include <tqptrlist.h>
|
|
#include <tqstring.h>
|
|
|
|
#include "basicelement.h"
|
|
|
|
class TQKeyEvent;
|
|
|
|
KFORMULA_NAMESPACE_BEGIN
|
|
|
|
class SymbolTable;
|
|
class ElementCreationStrategy;
|
|
|
|
/**
|
|
* The element that contains a number of tqchildren.
|
|
* The tqchildren are aligned in one line.
|
|
*/
|
|
class SequenceElement : public BasicElement {
|
|
SequenceElement& operator=( const SequenceElement& ) { return *this; }
|
|
public:
|
|
|
|
SequenceElement(BasicElement* tqparent = 0);
|
|
~SequenceElement();
|
|
|
|
SequenceElement( const SequenceElement& );
|
|
|
|
virtual SequenceElement* clone() {
|
|
return new SequenceElement( *this );
|
|
}
|
|
|
|
virtual bool accept( ElementVisitor* visitor );
|
|
|
|
/**
|
|
* @returns whether its prohibited to change the sequence with this cursor.
|
|
*/
|
|
virtual bool readOnly( const FormulaCursor* ) const;
|
|
|
|
/**
|
|
* @returns true if the sequence contains only text.
|
|
*/
|
|
virtual bool isTextOnly() const { return textSequence; }
|
|
|
|
/**
|
|
* Sets the cursor and returns the element the point is in.
|
|
* The handled flag shows whether the cursor has been set.
|
|
* This is needed because only the innermost matching element
|
|
* is allowed to set the cursor.
|
|
*/
|
|
virtual BasicElement* goToPos( FormulaCursor*, bool& handled,
|
|
const LuPixelPoint& point,
|
|
const LuPixelPoint& tqparentOrigin );
|
|
|
|
// drawing
|
|
//
|
|
// Drawing depends on a context which knows the required properties like
|
|
// fonts, spaces and such.
|
|
// It is essential to calculate elements size with the same context
|
|
// before you draw.
|
|
|
|
/**
|
|
* Tells the sequence to have a smaller size than its parant.
|
|
*/
|
|
void setSizeReduction(const ContextStyle& context);
|
|
|
|
/**
|
|
* @returns true if there is no visible element in the sequence.
|
|
* Please note that there might be phantom elements.
|
|
*/
|
|
bool isEmpty();
|
|
|
|
/**
|
|
* Calculates our width and height and
|
|
* our tqchildren's tqparentPosition.
|
|
*/
|
|
virtual void calcSizes( const ContextStyle& cstyle,
|
|
ContextStyle::TextStyle tstyle,
|
|
ContextStyle::IndexStyle istyle,
|
|
StyleAttributes& style );
|
|
|
|
/**
|
|
* Draws the whole element including its tqchildren.
|
|
* The `tqparentOrigin' is the point this element's tqparent starts.
|
|
* We can use our tqparentPosition to get our own origin then.
|
|
*/
|
|
virtual void draw( TQPainter& painter, const LuPixelRect& r,
|
|
const ContextStyle& context,
|
|
ContextStyle::TextStyle tstyle,
|
|
ContextStyle::IndexStyle istyle,
|
|
StyleAttributes& style,
|
|
const LuPixelPoint& tqparentOrigin );
|
|
|
|
/**
|
|
* Dispatch this FontCommand to all our TextElement tqchildren.
|
|
*/
|
|
virtual void dispatchFontCommand( FontCommand* cmd );
|
|
|
|
virtual void drawEmptyRect( TQPainter& painter, const ContextStyle& context,
|
|
double factor, const LuPixelPoint& upperLeft );
|
|
|
|
virtual void calcCursorSize( const ContextStyle& context,
|
|
FormulaCursor* cursor, bool smallCursor );
|
|
|
|
/**
|
|
* If the cursor is inside a sequence it needs to be drawn.
|
|
*/
|
|
virtual void drawCursor( TQPainter& painter, const ContextStyle& context,
|
|
StyleAttributes& style, FormulaCursor* cursor,
|
|
bool smallCursor, bool activeCursor );
|
|
|
|
// navigation
|
|
//
|
|
// The elements are responsible to handle cursor movement themselves.
|
|
// To do this they need to know the direction the cursor moves and
|
|
// the element it comes from.
|
|
//
|
|
// The cursor might be in normal or in selection mode.
|
|
|
|
/**
|
|
* Enters this element while moving to the left starting inside
|
|
* the element `from'. Searches for a cursor position inside
|
|
* this element or to the left of it.
|
|
*/
|
|
virtual void moveLeft(FormulaCursor* cursor, BasicElement* from);
|
|
|
|
/**
|
|
* Enters this element while moving to the right starting inside
|
|
* the element `from'. Searches for a cursor position inside
|
|
* this element or to the right of it.
|
|
*/
|
|
virtual void moveRight(FormulaCursor* cursor, BasicElement* from);
|
|
|
|
/**
|
|
* Moves to the beginning of this word or if we are there already
|
|
* to the beginning of the previous.
|
|
*/
|
|
virtual void moveWordLeft(FormulaCursor* cursor);
|
|
|
|
/**
|
|
* Moves to the end of this word or if we are there already
|
|
* to the end of the next.
|
|
*/
|
|
virtual void moveWordRight(FormulaCursor* cursor);
|
|
|
|
/**
|
|
* Enters this element while moving up starting inside
|
|
* the element `from'. Searches for a cursor position inside
|
|
* this element or above it.
|
|
*/
|
|
virtual void moveUp(FormulaCursor* cursor, BasicElement* from);
|
|
|
|
/**
|
|
* Enters this element while moving down starting inside
|
|
* the element `from'. Searches for a cursor position inside
|
|
* this element or below it.
|
|
*/
|
|
virtual void moveDown(FormulaCursor* cursor, BasicElement* from);
|
|
|
|
/**
|
|
* Moves the cursor to the first position in this sequence.
|
|
* (That is before the first child.)
|
|
*/
|
|
virtual void moveHome(FormulaCursor* cursor);
|
|
|
|
/**
|
|
* Moves the cursor to the last position in this sequence.
|
|
* (That is behind the last child.)
|
|
*/
|
|
virtual void moveEnd(FormulaCursor* cursor);
|
|
|
|
/**
|
|
* Sets the cursor inside this element to its start position.
|
|
* For most elements that is the main child.
|
|
*/
|
|
virtual void goInside(FormulaCursor* cursor);
|
|
|
|
/**
|
|
* Sets the cursor inside this element to its last position.
|
|
* For most elements that is the main child.
|
|
*/
|
|
virtual void goInsideLast(FormulaCursor* cursor);
|
|
|
|
|
|
// tqchildren
|
|
|
|
/**
|
|
* Inserts all new tqchildren at the cursor position. Places the
|
|
* cursor according to the direction. The inserted elements will
|
|
* be selected.
|
|
*
|
|
* The list will be emptied but stays the property of the caller.
|
|
*/
|
|
virtual void insert(FormulaCursor*, TQPtrList<BasicElement>&, Direction);
|
|
|
|
/**
|
|
* Removes all selected tqchildren and returns them. Places the
|
|
* cursor to where the tqchildren have been.
|
|
*/
|
|
virtual void remove(FormulaCursor*, TQPtrList<BasicElement>&, Direction);
|
|
|
|
/**
|
|
* Moves the cursor to a normal place where new elements
|
|
* might be inserted.
|
|
*/
|
|
virtual void normalize(FormulaCursor*, Direction);
|
|
|
|
/**
|
|
* Returns the child at the cursor.
|
|
* Does not care about the selection.
|
|
*/
|
|
virtual BasicElement* getChild(FormulaCursor*, Direction = beforeCursor);
|
|
|
|
/**
|
|
* Sets the cursor to select the child. The mark is placed before,
|
|
* the position behind it.
|
|
*/
|
|
virtual void selectChild(FormulaCursor* cursor, BasicElement* child);
|
|
|
|
/**
|
|
* Moves the cursor away from the given child. The cursor is
|
|
* guaranteed to be inside this element.
|
|
*/
|
|
virtual void childWillVanish(FormulaCursor* cursor, BasicElement* child);
|
|
|
|
/**
|
|
* @returns the number of tqchildren we have.
|
|
*/
|
|
uint countChildren() const { return tqchildren.count(); }
|
|
|
|
/**
|
|
* @returns whether the child has the given number.
|
|
*/
|
|
bool isChildNumber( uint pos, BasicElement* child )
|
|
{ return tqchildren.at( pos ) == child; }
|
|
|
|
/**
|
|
* Selects all tqchildren. The cursor is put behind, the mark before them.
|
|
*/
|
|
void selectAllChildren(FormulaCursor* cursor);
|
|
|
|
bool onlyTextSelected( FormulaCursor* cursor );
|
|
|
|
|
|
/**
|
|
* This is called by the container to get a command depending on
|
|
* the current cursor position (this is how the element gets chosen)
|
|
* and the request.
|
|
*
|
|
* @returns the command that performs the requested action with
|
|
* the containers active cursor.
|
|
*/
|
|
virtual KCommand* buildCommand( Container*, Request* );
|
|
|
|
|
|
/**
|
|
* Parses the input. It's the container which does create
|
|
* new elements because it owns the undo stack. But only the
|
|
* sequence knows what chars are allowed.
|
|
*/
|
|
virtual KCommand* input( Container* container, TQChar ch );
|
|
virtual KCommand* input( Container* container, TQKeyEvent* event );
|
|
|
|
/**
|
|
* Parses the sequence and generates a new syntax tree.
|
|
* Has to be called after each modification.
|
|
*/
|
|
virtual void parse();
|
|
|
|
/**
|
|
* Stores the given tqchildrens dom in the element.
|
|
*/
|
|
void getChildrenDom( TQDomDocument& doc, TQDomElement elem, uint from, uint to);
|
|
|
|
/**
|
|
* Stores the given tqchildrens MathML dom in the element.
|
|
*/
|
|
void getChildrenMathMLDom( TQDomDocument& doc, TQDomNode& elem, uint from, uint to );
|
|
|
|
/**
|
|
* Builds elements from the given node and its siblings and
|
|
* puts them into the list.
|
|
* Returns false if an error occures.
|
|
*/
|
|
bool buildChildrenFromDom(TQPtrList<BasicElement>& list, TQDomNode n);
|
|
|
|
/**
|
|
* @returns the latex representation of the element and
|
|
* of the element's tqchildren
|
|
*/
|
|
virtual TQString toLatex();
|
|
|
|
virtual TQString formulaString();
|
|
|
|
/**
|
|
* @returns the child at position i.
|
|
*/
|
|
BasicElement* getChild(uint i) { return tqchildren.at(i); }
|
|
const BasicElement* getChild(uint i) const;
|
|
|
|
int childPos( BasicElement* child ) { return tqchildren.tqfind( child ); }
|
|
int childPos( const BasicElement* child ) const;
|
|
|
|
class ChildIterator {
|
|
public:
|
|
ChildIterator( SequenceElement* sequence, int pos=0 )
|
|
: m_sequence( sequence ), m_pos( pos ) {}
|
|
|
|
typedef BasicElement value_type;
|
|
typedef BasicElement* pointer;
|
|
typedef BasicElement& reference;
|
|
|
|
// we simply expect the compared iterators to belong
|
|
// to the same sequence.
|
|
bool operator== ( const ChildIterator& it ) const
|
|
{ return /*m_sequence==it.m_sequence &&*/ m_pos==it.m_pos; }
|
|
bool operator!= ( const ChildIterator& it ) const
|
|
{ return /*m_sequence!=it.m_sequence ||*/ m_pos!=it.m_pos; }
|
|
|
|
const BasicElement& operator* () const
|
|
{ return *m_sequence->getChild( m_pos ); }
|
|
BasicElement& operator* ()
|
|
{ return *m_sequence->getChild( m_pos ); }
|
|
|
|
BasicElement* operator->() const
|
|
{ return m_sequence->getChild( m_pos ); }
|
|
|
|
ChildIterator& operator++ ()
|
|
{ ++m_pos; return *this; }
|
|
ChildIterator operator++ ( int )
|
|
{ ChildIterator it( *this ); ++m_pos; return it; }
|
|
ChildIterator& operator-- ()
|
|
{ --m_pos; return *this; }
|
|
ChildIterator operator-- ( int )
|
|
{ ChildIterator it( *this ); --m_pos; return it; }
|
|
ChildIterator& operator+= ( int j )
|
|
{ m_pos+=j; return *this; }
|
|
ChildIterator & operator-= ( int j )
|
|
{ m_pos-=j; return *this; }
|
|
|
|
private:
|
|
SequenceElement* m_sequence;
|
|
int m_pos;
|
|
};
|
|
|
|
typedef ChildIterator iterator;
|
|
|
|
iterator begin() { return ChildIterator( this, 0 ); }
|
|
iterator end() { return ChildIterator( this, countChildren() ); }
|
|
|
|
static void setCreationStrategy( ElementCreationStrategy* strategy );
|
|
|
|
virtual void setStyle(StyleElement *style);
|
|
virtual int buildChildrenFromMathMLDom(TQPtrList<BasicElement>& list, TQDomNode n);
|
|
virtual int readContentFromMathMLDom(TQDomNode& node);
|
|
int buildMathMLChild( TQDomNode node );
|
|
|
|
protected:
|
|
|
|
//Save/load support
|
|
|
|
/**
|
|
* Returns the tag name of this element type.
|
|
*/
|
|
virtual TQString getTagName() const { return "SEQUENCE"; }
|
|
|
|
/**
|
|
* Appends our attributes to the dom element.
|
|
*/
|
|
virtual void writeDom(TQDomElement element);
|
|
|
|
virtual TQString getElementName() const { return "mrow"; }
|
|
virtual void writeMathMLContent( TQDomDocument& doc,
|
|
TQDomElement& element,
|
|
bool oasisFormat ) const;
|
|
/**
|
|
* Reads our attributes from the element.
|
|
* Returns false if it failed.
|
|
*/
|
|
virtual bool readAttributesFromDom(TQDomElement element);
|
|
|
|
/**
|
|
* Reads our content from the node. Sets the node to the next node
|
|
* that needs to be read.
|
|
* Returns false if it failed.
|
|
*/
|
|
virtual bool readContentFromDom(TQDomNode& node);
|
|
|
|
/**
|
|
* Sets the tqchildrens' positions after their size has been
|
|
* calculated.
|
|
*
|
|
* @see #calcSizes
|
|
*/
|
|
virtual void setChildrenPositions();
|
|
|
|
/**
|
|
* Creates a new element with the given type.
|
|
*
|
|
* @param type the desired type of the element
|
|
*/
|
|
virtual BasicElement* createElement(TQString type, const TQDomElement &element);
|
|
|
|
/**
|
|
* @returns the position where the child starts.
|
|
*
|
|
* @param context the context the child is in
|
|
* @param child the child's number
|
|
*/
|
|
luPixel getChildPosition( const ContextStyle& context, uint child );
|
|
|
|
/**
|
|
* @returns whether the child is the first element of its token.
|
|
*/
|
|
virtual bool isFirstOfToken( BasicElement* child );
|
|
|
|
/**
|
|
* Insert a new child in the sequence
|
|
*
|
|
* @returns true if succesful, i.e. if index is in range, otherwise returns
|
|
* false. The valid range is 0 to count(). The child is appended if index == count().
|
|
*
|
|
* @param index position in the sequence to insert the child
|
|
* @param child the child to insert in the sequence
|
|
*/
|
|
bool insert( uint index, BasicElement *child );
|
|
|
|
static ElementCreationStrategy* getCreationStrategy() { return creationStrategy; }
|
|
|
|
/**
|
|
* Space around sequence
|
|
*/
|
|
virtual luPt getSpaceBefore( const ContextStyle&, ContextStyle::TextStyle, double ) { return 0; }
|
|
virtual luPt getSpaceAfter( const ContextStyle&, ContextStyle::TextStyle, double ) { return 0; }
|
|
|
|
static ElementCreationStrategy* creationStrategy;
|
|
|
|
private:
|
|
|
|
/**
|
|
* Removes the tqchildren at pos and appends it to the list.
|
|
*/
|
|
void removeChild(TQPtrList<BasicElement>& removedChildren, int pos);
|
|
|
|
|
|
/**
|
|
* Our tqchildren. Be sure to notify the rootElement before
|
|
* you remove any.
|
|
*/
|
|
TQPtrList<BasicElement> tqchildren;
|
|
|
|
/**
|
|
* the syntax tree of the sequence
|
|
*/
|
|
ElementType* parseTree;
|
|
|
|
/**
|
|
* true if the sequence contains only text
|
|
*/
|
|
bool textSequence;
|
|
|
|
bool singlePipe; //The key '|' produces one '|' not '| |', '||' produces '| |'
|
|
|
|
StyleElement *style;
|
|
};
|
|
|
|
|
|
/**
|
|
* The sequence thats a name. Actually the purpose
|
|
* is to be able to insert any element by keyboard.
|
|
*/
|
|
class NameSequence : public SequenceElement {
|
|
typedef SequenceElement inherited;
|
|
public:
|
|
|
|
NameSequence( BasicElement* tqparent = 0 );
|
|
|
|
virtual NameSequence* clone() {
|
|
return new NameSequence( *this );
|
|
}
|
|
|
|
virtual bool accept( ElementVisitor* visitor );
|
|
|
|
/**
|
|
* @returns true if the sequence contains only text.
|
|
*/
|
|
//virtual bool isTextOnly() const { return true; }
|
|
|
|
/**
|
|
* @returns the character that represents this element. Used for
|
|
* parsing a sequence.
|
|
* This is guaranteed to be TQChar::null for all non-text elements.
|
|
*/
|
|
virtual TQChar getCharacter() const { return '\\'; }
|
|
|
|
/**
|
|
* @returns the type of this element. Used for
|
|
* parsing a sequence.
|
|
*/
|
|
virtual TokenType getTokenType() const { return NAME; }
|
|
|
|
/**
|
|
* We are our own main child. This causes interessting effects.
|
|
*/
|
|
virtual SequenceElement* getMainChild() { return this; }
|
|
|
|
virtual void calcCursorSize( const ContextStyle& context,
|
|
FormulaCursor* cursor, bool smallCursor );
|
|
|
|
/**
|
|
* If the cursor is inside a sequence it needs to be drawn.
|
|
*/
|
|
virtual void drawCursor( TQPainter& painter, const ContextStyle& context,
|
|
StyleAttributes& style, FormulaCursor* cursor,
|
|
bool smallCursor, bool activeCursor );
|
|
|
|
/**
|
|
* Moves to the beginning of this word or if we are there already
|
|
* to the beginning of the previous.
|
|
*/
|
|
virtual void moveWordLeft(FormulaCursor* cursor);
|
|
|
|
/**
|
|
* Moves to the end of this word or if we are there already
|
|
* to the end of the next.
|
|
*/
|
|
virtual void moveWordRight(FormulaCursor* cursor);
|
|
|
|
/**
|
|
* This is called by the container to get a command depending on
|
|
* the current cursor position (this is how the element gets chosen)
|
|
* and the request.
|
|
*
|
|
* @returns the command that performs the requested action with
|
|
* the containers active cursor.
|
|
*/
|
|
virtual KCommand* buildCommand( Container*, Request* );
|
|
|
|
|
|
/**
|
|
* Parses the input. It's the container which does create
|
|
* new elements because it owns the undo stack. But only the
|
|
* sequence knows what chars are allowed.
|
|
*/
|
|
virtual KCommand* input( Container* container, TQChar ch );
|
|
|
|
/**
|
|
* Sets a new type. This is done during parsing.
|
|
*/
|
|
virtual void setElementType( ElementType* t );
|
|
|
|
/**
|
|
* @returns the element this sequence is to be replaced with.
|
|
*/
|
|
BasicElement* replaceElement( const SymbolTable& table );
|
|
|
|
/**
|
|
* Tests whether the selected elements can be inserted in a
|
|
* name sequence.
|
|
*/
|
|
static bool isValidSelection( FormulaCursor* cursor );
|
|
|
|
protected:
|
|
|
|
/**
|
|
* Returns the tag name of this element type.
|
|
*/
|
|
virtual TQString getTagName() const { return "NAMESEQUENCE"; }
|
|
|
|
virtual TQString getElementName() const { return "mi"; }
|
|
/**
|
|
* Creates a new element with the given type.
|
|
*
|
|
* @param type the desired type of the element
|
|
*/
|
|
virtual BasicElement* createElement( TQString type );
|
|
|
|
/**
|
|
* Parses the sequence and generates a new syntax tree.
|
|
* Has to be called after each modification.
|
|
*/
|
|
//virtual void parse();
|
|
|
|
/**
|
|
* @returns whether the child is the first element of its token.
|
|
* This can never happen here. Our tqchildren reuse our own
|
|
* element type.
|
|
*/
|
|
virtual bool isFirstOfToken( BasicElement* ) { return false; }
|
|
|
|
private:
|
|
|
|
KCommand* compactExpressionCmd( Container* container );
|
|
|
|
TQString buildName();
|
|
};
|
|
|
|
KFORMULA_NAMESPACE_END
|
|
|
|
#endif // SEQUENCEELEMENT_H
|