diff --git a/lib/kformula2/Makefile.am b/lib/kformula2/Makefile.am index 9ecdf4f483..458b48bc99 100644 --- a/lib/kformula2/Makefile.am +++ b/lib/kformula2/Makefile.am @@ -1,27 +1,27 @@ INCLUDES= $(all_includes) SUBDIRS = ####### # you can add here more. This one gets installed lib_LTLIBRARIES = libkformula2.la KFORMULA2VERSION= 0.0.1 KFORMULA2PATCH= 0 libkformula2_la_SOURCES = basicelement.cc contextstyle.cc formulacursor.cc \ formulaelement.cc indexelement.cc kformulacontainer.cc kformulawidget.cc \ sequenceelement.cc textelement.cc bracketelement.cc operatorelement.cc \ matrixelement.cc fractionelement.cc rootelement.cc symbolelement.cc \ artwork.cc complexelement.cc -include_HEADERS = +include_HEADERS = libkformula2_la_LDFLAGS = -version-info 3:0 -no-undefined libkformula2_la_LIBADD = $(LIB_KDEUI) $(all_libraries) $(KDE_RPATH) libkformula2_la_METASOURCES = AUTO check_PROGRAMS = kformulatest kformulatest_SOURCES = main.cc kformulatest_LDADD = libkformula2.la diff --git a/lib/kformula2/UNDO b/lib/kformula2/UNDO index 3503c14c00..6935086298 100644 --- a/lib/kformula2/UNDO +++ b/lib/kformula2/UNDO @@ -1,26 +1,45 @@ -UNDO/REDO needs +New UNDO/REDO idea: +Each time an editing method is called it will put a new entry on the undo or redo stack. +the new addText declaration is + +addText(FormulaCursor *,QString,isDo=true) + +addText(cursor,"x") +will add to undo stack +while +addText(cursor,"x",false) +will add to redo stack + +Each time a undo or redo is called it is removed from the stack. + + + + + + +---OLD IDEA:------------------- add element (except matrix) and nothing is selected ************************* Info to store: cursorData before and after insert, text added Undo: Delete previous element of tmpCursor created with saved data of after insert cursor. Redo: tmpCursor created with saved data of before insert cursor. addXXX(tmpCursor[,textadded],NOUNDO); where XXX is the type of element addMatrix******************************************************************* the delete action is perfromed on "before insert" cursor instead of "after insert" cursor and in right direction For selected text: This depends on some behaviour we not yet decide. diff --git a/lib/kformula2/basicelement.cc b/lib/kformula2/basicelement.cc index e05bb73715..b173393ba6 100644 --- a/lib/kformula2/basicelement.cc +++ b/lib/kformula2/basicelement.cc @@ -1,91 +1,103 @@ /* This file is part of the KDE project Copyright (C) 2001 Andrea Rizzi Ulrich Kuettler 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "contextstyle.h" #include "basicelement.h" #include "formulacursor.h" #include "sequenceelement.h" int BasicElement::evilDestructionCount = 0; BasicElement::BasicElement(BasicElement* p) : parent(p) { relativeSize = 0; evilDestructionCount++; } BasicElement::~BasicElement() { evilDestructionCount--; } ostream& BasicElement::output(ostream& stream) { return stream << "BasicElement: " << position.x() << ", " << position.y() << ", " << size.width() << ", " << size.height(); } /** * Returns the element the point is in. */ BasicElement* BasicElement::isInside(const QPoint& point, const QPoint& parentOrigin) { int x = point.x() - (parentOrigin.x() + getX()); if ((x >= 0) && (x < getWidth())) { int y = point.y() - (parentOrigin.y() + getY()); if ((y >= 0) && (y < getHeight())) { return this; } } return 0; } /** * Returns our position inside the widget. */ QPoint BasicElement::widgetPos() { int x = 0; int y = 0; for (BasicElement* element = this; element != 0; element = element->parent) { x += element->getX(); y += element->getY(); } return QPoint(x, y); } /** * Sets the cursor inside this element to its start position. * For most elements that is the main child. */ void BasicElement::goInside(FormulaCursor* cursor) { BasicElement* mainChild = getMainChild(); if (mainChild != 0) { mainChild->goInside(cursor); } } + +QDomElement BasicElement::getElementDom(QDomDocument *doc) +{ + QDomElement de=doc->createElement("BASIC"); + cerr << "Element" << endl; +// de.setTagName("BASIC"); + if(relativeSize!=0) { + de.setAttribute("SIZE",relativeSize); + } + return de; +} + diff --git a/lib/kformula2/basicelement.h b/lib/kformula2/basicelement.h index 0ce705b2f3..ad45d67864 100644 --- a/lib/kformula2/basicelement.h +++ b/lib/kformula2/basicelement.h @@ -1,305 +1,316 @@ /* This file is part of the KDE project Copyright (C) 2001 Andrea Rizzi Ulrich Kuettler 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. 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __BASICELEMENT_H #define __BASICELEMENT_H #include // Qt Include #include #include #include +#include // KDE Include // Formula include #include "contextstyle.h" class ComplexElement; class FormulaCursor; class FormulaElement; class SequenceElement; /** * Basis of every formula element. * * Each element might contain children. Each child needs * its own unique number. It is not guaranteed, however, * that the number stays the same all the time. * (The SequenceElement's children are simply counted.) */ class BasicElement { public: BasicElement(BasicElement* parent = 0); virtual ~BasicElement(); /** * Provide fast access to the rootElement for each child. */ virtual FormulaElement* formula() { return parent->formula(); } /** * Returns this if we are a complex element that knows how to * handle indexes. */ virtual ComplexElement* getComplexElement() { return 0; } /** * Returns the element the point is in. */ virtual BasicElement* isInside(const QPoint& point, const QPoint& parentOrigin); /** * Returns our position inside the widget. */ QPoint widgetPos(); // 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. /** * Calculates our width and height and * our children's parentPosition. */ virtual void calcSizes(ContextStyle& context, int parentSize) = 0; /** * Draws the whole element including its children. * The `parentOrigin' is the point this element's parent starts. * We can use our parentPosition to get our own origin then. */ virtual void draw(QPainter& painter, ContextStyle& context, int parentSize, const QPoint& parentOrigin) = 0; // 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) = 0; /** * 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) = 0; /** * 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*, BasicElement*) {} /** * 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*, BasicElement* ) {} /** * Moves the cursor to the first position in this sequence. * (That is before the first child.) */ virtual void moveHome(FormulaCursor*) {} /** * Moves the cursor to the last position in this sequence. * (That is behind the last child.) */ virtual void moveEnd(FormulaCursor*) {} /** * Sets the cursor inside this element to its start position. * For most elements that is the main child. */ virtual void goInside(FormulaCursor* cursor); // children /** * Removes the child. If this was the main child this element might * request its own removal. * The cursor is the one that caused the removal. It has to be moved * to the place any user expects the cursor after that particular * element has been removed. */ //virtual void removeChild(FormulaCursor* cursor, BasicElement* child) {} // main child // // If an element has children one has to become the main one. virtual SequenceElement* getMainChild() { return 0; } virtual void setMainChild(SequenceElement*) {} // editing // // Insert and remove children. /** * Wether we want to insert to the left of the cursor * or right of it. * The same for deletion. */ enum Direction { beforeCursor, afterCursor }; /** * Inserts all new children at the cursor position. Places the * cursor according to the direction. * * The list will be emptied but stays the property of the caller. */ virtual void insert(FormulaCursor*, QList&, Direction) {} /** * Removes all selected children and returns them. Places the * cursor to where the children have been. */ virtual void remove(FormulaCursor*, QList&, Direction) {} /** * Moves the cursor to a normal place where new elements * might be inserted. */ virtual void normalize(FormulaCursor*, Direction) {} /** * Returns wether the element has no more useful * children (except its main child) and should therefore * be replaced by its main child's content. */ virtual bool isSenseless() { return false; } /** * Returns the child at the cursor. */ virtual BasicElement* getChild(FormulaCursor*, Direction = beforeCursor) { return 0; } /** * Sets the cursor to select the child. The mark is placed before, * the position behind it. */ virtual void selectChild(FormulaCursor*, BasicElement*) {} // basic support BasicElement* getParent() { return parent; } void setParent(BasicElement* p) { parent = p; } int getX() const { return position.x(); } int getY() const { return position.y(); } void setX(int x) { position.setX(x); } void setY(int y) { position.setY(y); } //QSize getSize() { return size; } int getWidth() const { return size.width(); } int getHeight() const { return size.height(); } int getRelativeSize() const { return relativeSize; } void setRelativeSize(int size) { relativeSize = size; } /** * Our position inside our parent. */ //QPoint getParentPosition() { return position; } int getMidline() const { return midline; } + //Save/load support + /** + * @return a QDomElement that contain as DomChildren the + * children, and as attribute the attribute of this + * element. + */ + + virtual QDomElement getElementDom(QDomDocument *doc); + + // debug virtual ostream& output(ostream&); static int getEvilDestructionCount() { return evilDestructionCount; } protected: void setWidth(int width) { size.setWidth(width); } void setHeight(int height) { size.setHeight(height); } void setMidline(int mline) { midline = mline; } private: /** * Our parent. * The parent might not be null except for the FormulaElement * that is the top of the element tree. */ BasicElement* parent; /** * This elements size. */ QSize size; /** * Our position relative to our parent. */ QPoint position; /** * The position of our middle line from * the upper border. */ int midline; /** * Our size relative to those of our parent. */ int relativeSize; // debug static int evilDestructionCount; // copying not allowed. BasicElement(BasicElement&) {} BasicElement& operator= (BasicElement&) { return *this; } }; #endif // __BASICELEMENT_H diff --git a/lib/kformula2/bracketelement.cc b/lib/kformula2/bracketelement.cc index c21c0ffaf0..543d27b312 100644 --- a/lib/kformula2/bracketelement.cc +++ b/lib/kformula2/bracketelement.cc @@ -1,390 +1,410 @@ /* This file is part of the KDE project Copyright (C) 2001 Andrea Rizzi Ulrich Kuettler 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include "bracketelement.h" #include "formulacursor.h" #include "formulaelement.h" #include "sequenceelement.h" BracketElement::BracketElement(char l, char r, BasicElement* parent) : BasicElement(parent) { content = new SequenceElement(this); right = createBracket(r); left = createBracket(l); } BracketElement::~BracketElement() { delete left; delete right; delete content; } /** * Calculates our width and height and * our children's parentPosition. */ void BracketElement::calcSizes(ContextStyle& style, int parentSize) { int mySize = parentSize + getRelativeSize(); content->calcSizes(style, parentSize); int contentHeight = 2 * QMAX(content->getMidline(), content->getHeight() - content->getMidline()); left->calcSizes(style, mySize, contentHeight, false); right->calcSizes(style, mySize, contentHeight, true); // width setWidth(left->getWidth() + content->getWidth() + right->getWidth()); content->setX(left->getWidth()); right ->setX(left->getWidth()+content->getWidth()); // height setHeight(QMAX(content->getHeight(), QMAX(left->getHeight(), right->getHeight()))); setMidline(getHeight() / 2); left ->setY((getHeight() - left ->getHeight())/2); right ->setY((getHeight() - right ->getHeight())/2); content->setY(getMidline() - content->getMidline()); } /** * Draws the whole element including its children. * The `parentOrigin' is the point this element's parent starts. * We can use our parentPosition to get our own origin then. */ void BracketElement::draw(QPainter& painter, ContextStyle& style, int parentSize, const QPoint& parentOrigin) { QPoint myPos(parentOrigin.x()+getX(), parentOrigin.y()+getY()); int mySize = parentSize + getRelativeSize(); left->draw(painter, style, mySize, myPos, false); content->draw(painter, style, mySize, myPos); right->draw(painter, style, mySize, myPos, true); } /** * 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. */ void BracketElement::moveLeft(FormulaCursor* cursor, BasicElement* from) { if (cursor->isSelectionMode()) { getParent()->moveLeft(cursor, this); } else { if (from == getParent()) { content->moveLeft(cursor, this); } else { getParent()->moveLeft(cursor, this); } } } /** * 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. */ void BracketElement::moveRight(FormulaCursor* cursor, BasicElement* from) { if (cursor->isSelectionMode()) { getParent()->moveRight(cursor, this); } else { if (from == getParent()) { content->moveRight(cursor, this); } else { getParent()->moveRight(cursor, this); } } } /** * Enters this element while moving up starting inside * the element `from'. Searches for a cursor position inside * this element or above it. */ void BracketElement::moveUp(FormulaCursor* cursor, BasicElement*) { getParent()->moveUp(cursor, this); } /** * Enters this element while moving down starting inside * the element `from'. Searches for a cursor position inside * this element or below it. */ void BracketElement::moveDown(FormulaCursor* cursor, BasicElement*) { getParent()->moveDown(cursor, this); } /** * Removes all selected children and returns them. Places the * cursor to where the children have been. * * Here we remove ourselve if we are requested to remove our content. */ void BracketElement::remove(FormulaCursor* cursor, QList& removedChildren, Direction direction) { if (cursor->getPos() == contentPos) { BasicElement* parent = getParent(); parent->selectChild(cursor, this); parent->remove(cursor, removedChildren, direction); } } // main child // // If an element has children one has to become the main one. SequenceElement* BracketElement::getMainChild() { return content; } void BracketElement::setMainChild(SequenceElement* child) { formula()->elementRemoval(content); content = child; content->setParent(this); formula()->changed(); } /** * Sets the cursor to select the child. The mark is placed before, * the position behind it. */ void BracketElement::selectChild(FormulaCursor* cursor, BasicElement* child) { if (child == content) { cursor->setTo(this, contentPos); } } /** * Creates a new bracket object that matches the char. */ BracketElement::Bracket* BracketElement::createBracket(char bracket) { switch (bracket) { case '[': case ']': return new SquareBracket; case '{': case '}': return new CurlyBracket; case '|': return new LineBracket; case '<': case '>': return new CornerBracket; case '(': case ')': return new RoundBracket; default: return new EmptyBracket; } } // '(' and ')' void BracketElement::RoundBracket::calcSizes(ContextStyle& style, int parentSize, int contentHeight, bool right) { int height = contentHeight > 21 ? contentHeight+2 : 24; size.setWidth(8); size.setHeight(height); } void BracketElement::RoundBracket::draw(QPainter& painter, ContextStyle& style, int parentSize, const QPoint& origin, bool right) { int x = origin.x() + point.x(); int y = origin.y() + point.y(); int thickness = size.width()/4+1; //painter.setBrush(style.getDefaultColor()); painter.setPen(QPen(style.getDefaultColor(), 2)); if (right) { painter.drawArc(x-thickness, y, size.width(), size.height(), 270*16, 180*16); } else { painter.drawArc(x+thickness, y, size.width(), size.height(), 90*16, 180*16); } } // '[' and ']' void BracketElement::SquareBracket::calcSizes(ContextStyle& style, int parentSize, int contentHeight, bool right) { int height = contentHeight > 21 ? contentHeight+2 : 24; size.setWidth(8); size.setHeight(height); } void BracketElement::SquareBracket::draw(QPainter& painter, ContextStyle& style, int parentSize, const QPoint& origin, bool right) { int x = origin.x() + point.x() + 1; int y = origin.y() + point.y(); int width = getWidth()-2; int thickness = width/4+1; int unit = width - thickness; painter.setBrush(style.getDefaultColor()); painter.setPen(Qt::NoPen); QPointArray points(10); if (right) { points.setPoint(1, x, y); points.setPoint(2, x + width, y); points.setPoint(3, x + width, y + getHeight()); points.setPoint(4, x, y + getHeight()); points.setPoint(5, x, y + getHeight() - thickness); points.setPoint(6, x + unit, y + getHeight() - thickness); points.setPoint(7, x + unit, y + thickness); points.setPoint(8, x, y + thickness); } else { points.setPoint(1, x, y); points.setPoint(2, x + width, y); points.setPoint(3, x + width, y + thickness); points.setPoint(4, x + thickness, y + thickness); points.setPoint(5, x + thickness, y + getHeight() - thickness); points.setPoint(6, x + width, y + getHeight() - thickness); points.setPoint(7, x + width, y+getHeight()); points.setPoint(8, x, y+getHeight()); } painter.drawPolygon(points, false, 1, 8); } // '{' and '}' void BracketElement::CurlyBracket::calcSizes(ContextStyle& style, int parentSize, int contentHeight, bool right) { size.setWidth(contentHeight/4); size.setHeight(contentHeight); } void BracketElement::CurlyBracket::draw(QPainter& painter, ContextStyle& style, int parentSize, const QPoint& origin, bool right) { // todo } // '|' void BracketElement::LineBracket::calcSizes(ContextStyle& style, int parentSize, int contentHeight, bool right) { int height = contentHeight > 21 ? contentHeight+2 : 24; size.setWidth(8); size.setHeight(height); } void BracketElement::LineBracket::draw(QPainter& painter, ContextStyle& style, int parentSize, const QPoint& origin, bool right) { int x = origin.x() + point.x() + 1; int y = origin.y() + point.y(); int width = getWidth()-2; int thickness = width/4+1; int unit = width - thickness; painter.setBrush(style.getDefaultColor()); painter.setPen(Qt::NoPen); QPointArray points(5); points.setPoint(1, x+unit/2, y); points.setPoint(2, x+unit/2+thickness, y); points.setPoint(3, x+unit/2+thickness, y+getHeight()); points.setPoint(4, x+unit/2, y+getHeight()); painter.drawPolygon(points, false, 1, 4); } // '<' and '>' void BracketElement::CornerBracket::calcSizes(ContextStyle& style, int parentSize, int contentHeight, bool right) { int height = contentHeight > 21 ? contentHeight+2 : 24; size.setWidth(8); size.setHeight(height); } void BracketElement::CornerBracket::draw(QPainter& painter, ContextStyle& style, int parentSize, const QPoint& origin, bool right) { int x = origin.x() + point.x() + 1; int y = origin.y() + point.y(); int width = getWidth()-2; int thickness = width/4+1; int unit = width - thickness; painter.setBrush(style.getDefaultColor()); painter.setPen(Qt::NoPen); QPointArray points(5); if (right) { points.setPoint(1, x+unit, y); points.setPoint(2, x, y + getHeight()/2); points.setPoint(3, x+unit, y+getHeight()); //points.setPoint(4, x, y+getHeight()); } else { points.setPoint(1, x, y); points.setPoint(2, x+unit, y + getHeight()/2); points.setPoint(3, x, y+getHeight()); //points.setPoint(4, x, y+getHeight()); } painter.drawPolyline(points, 1, /*4*/3); } + +QDomElement BracketElement::getElementDom(QDomDocument *doc) +{ + QDomElement de=doc->createElement("BRACKET"); + int sz=getRelativeSize(); + if(sz!=0) { + de.setAttribute("SIZE",sz); + } + QDomElement con=doc->createElement("CONTENT"); + con.appendChild(content->getElementDom(doc)); + de.appendChild(con); + +#warning TODO bracket type attribute + + de.setAttribute("LEFT","("); + de.setAttribute("RIGHT",")"); + return de; +} + + diff --git a/lib/kformula2/bracketelement.h b/lib/kformula2/bracketelement.h index 7effc29b5c..96b0adc775 100644 --- a/lib/kformula2/bracketelement.h +++ b/lib/kformula2/bracketelement.h @@ -1,194 +1,198 @@ /* This file is part of the KDE project Copyright (C) 2001 Andrea Rizzi Ulrich Kuettler 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __BRACKETELEMENT_H #define __BRACKETELEMENT_H #include #include #include "basicelement.h" class SequenceElement; /** * A left and/or right bracket around one child. */ class BracketElement : public BasicElement { public: enum { contentPos }; BracketElement(char left, char right, BasicElement* parent = 0); ~BracketElement(); /** * Calculates our width and height and * our children's parentPosition. */ virtual void calcSizes(ContextStyle& style, int parentSize); /** * Draws the whole element including its children. * The `parentOrigin' is the point this element's parent starts. * We can use our parentPosition to get our own origin then. */ virtual void draw(QPainter& painter, ContextStyle& style, int parentSize, const QPoint& parentOrigin); /** * 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); /** * 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); /** * Removes all selected children and returns them. Places the * cursor to where the children have been. * * Here we remove ourselve if we are requested to remove our content. */ virtual void remove(FormulaCursor*, QList&, Direction); // main child // // If an element has children one has to become the main one. virtual SequenceElement* getMainChild(); virtual void setMainChild(SequenceElement*); /** * Sets the cursor to select the child. The mark is placed before, * the position behind it. */ virtual void selectChild(FormulaCursor* cursor, BasicElement* child); + + + virtual QDomElement getElementDom(QDomDocument *doc); + private: class Bracket { public: virtual void calcSizes(ContextStyle& style, int parentSize, int contentHeight, bool right) = 0; virtual void draw(QPainter& painter, ContextStyle& style, int parentSize, const QPoint& origin, bool right) = 0; int getWidth() const { return size.width(); } int getHeight() const { return size.height(); } void setX(int x) { point.setX(x); } void setY(int y) { point.setY(y); } protected: QSize size; QPoint point; }; // '(' and ')' class RoundBracket : public Bracket { virtual void calcSizes(ContextStyle& style, int parentSize, int contentHeight, bool right); virtual void draw(QPainter& painter, ContextStyle& style, int parentSize, const QPoint& origin, bool right); }; // '[' and ']' class SquareBracket : public Bracket { virtual void calcSizes(ContextStyle& style, int parentSize, int contentHeight, bool right); virtual void draw(QPainter& painter, ContextStyle& style, int parentSize, const QPoint& origin, bool right); }; // '{' and '}' class CurlyBracket : public Bracket { virtual void calcSizes(ContextStyle& style, int parentSize, int contentHeight, bool right); virtual void draw(QPainter& painter, ContextStyle& style, int parentSize, const QPoint& origin, bool right); }; // '|' class LineBracket : public Bracket { virtual void calcSizes(ContextStyle& style, int parentSize, int contentHeight, bool right); virtual void draw(QPainter& painter, ContextStyle& style, int parentSize, const QPoint& origin, bool right); }; // '<' and '>' class CornerBracket : public Bracket { virtual void calcSizes(ContextStyle& style, int parentSize, int contentHeight, bool right); virtual void draw(QPainter& painter, ContextStyle& style, int parentSize, const QPoint& origin, bool right); }; // everything else class EmptyBracket : public Bracket { virtual void calcSizes(ContextStyle&, int, int, bool) {} virtual void draw(QPainter&, ContextStyle&, int, const QPoint&, bool) {} }; /** * Creates a new bracket object that matches the char. */ Bracket* createBracket(char bracket); /** * The brackets we are showing. */ Bracket* left; Bracket* right; /** * Our main child. */ SequenceElement* content; }; #endif // __BRACKETELEMENT_H diff --git a/lib/kformula2/formulaelement.cc b/lib/kformula2/formulaelement.cc index e3399dcd90..ee7af9868f 100644 --- a/lib/kformula2/formulaelement.cc +++ b/lib/kformula2/formulaelement.cc @@ -1,59 +1,62 @@ /* This file is part of the KDE project Copyright (C) 2001 Andrea Rizzi Ulrich Kuettler 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include "contextstyle.h" #include "formulaelement.h" #include "kformulacontainer.h" FormulaElement::FormulaElement(KFormulaContainer* container) : document(container) { size = 20; } void FormulaElement::elementRemoval(BasicElement* child) { document->elementRemoval(child); } void FormulaElement::changed() { document->changed(); } /** * Calculates the formulas sizes and positions. */ void FormulaElement::calcSizes(ContextStyle& context) { SequenceElement::calcSizes(context, size); } /** * Draws the whole thing. */ void FormulaElement::draw(QPainter& painter, ContextStyle& context) { SequenceElement::draw(painter, context, size, QPoint()); } + + + diff --git a/lib/kformula2/formulaelement.h b/lib/kformula2/formulaelement.h index 4d6e1548c0..fcb6a3cc9f 100644 --- a/lib/kformula2/formulaelement.h +++ b/lib/kformula2/formulaelement.h @@ -1,82 +1,87 @@ /* This file is part of the KDE project Copyright (C) 2001 Andrea Rizzi Ulrich Kuettler 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __FORMULAELEMENT_H #define __FORMULAELEMENT_H // Formula include #include "sequenceelement.h" class BasicElement; class ContextStyle; class KFormulaContainer; /** * The main element. * A formula consists of a FormulaElement and its children. * The only element that has no parent. */ class FormulaElement : public SequenceElement { public: FormulaElement(KFormulaContainer* container); /** * Provide fast access to the rootElement for each child. */ virtual FormulaElement* formula() { return this; } /** * Gets called just before the child is removed from * the element tree. */ void elementRemoval(BasicElement* child); /** * Gets called whenever something changes and we need to * recalc. */ void changed(); /** * Calculates the formulas sizes and positions. */ void calcSizes(ContextStyle& context); /** * Draws the whole thing. */ void draw(QPainter& painter, ContextStyle& context); + + + //Save&Load + // virtual QDomElement getElementDom(); + private: /** * The document that owns this formula. */ KFormulaContainer* document; /** * The root element has to know its size. */ int size; }; #endif // __FORMULAELEMENT_H diff --git a/lib/kformula2/fractionelement.cc b/lib/kformula2/fractionelement.cc index 372524754e..f4924349c3 100644 --- a/lib/kformula2/fractionelement.cc +++ b/lib/kformula2/fractionelement.cc @@ -1,275 +1,295 @@ /* This file is part of the KDE project Copyright (C) 2001 Andrea Rizzi Ulrich Kuettler 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. 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include "formulaelement.h" #include "formulacursor.h" #include "fractionelement.h" #include "sequenceelement.h" FractionElement::FractionElement(BasicElement* parent) : BasicElement(parent) { numerator = new SequenceElement(this); denominator = new SequenceElement(this); } FractionElement::~FractionElement() { delete denominator; delete numerator; } /** * Calculates our width and height and * our children's parentPosition. */ void FractionElement::calcSizes(ContextStyle& style, int parentSize) { int mySize = parentSize + getRelativeSize(); numerator->calcSizes(style, mySize); denominator->calcSizes(style, mySize); int dist = style.getDistance(); setWidth(QMAX(numerator->getWidth(), denominator->getWidth())); setHeight(numerator->getHeight() + dist + denominator->getHeight()); setMidline(numerator->getHeight() + dist / 2); numerator->setX((getWidth() - numerator->getWidth()) / 2); denominator->setX((getWidth() - denominator->getWidth()) / 2); numerator->setY(0); denominator->setY(getHeight() - denominator->getHeight()); } /** * Draws the whole element including its children. * The `parentOrigin' is the point this element's parent starts. * We can use our parentPosition to get our own origin then. */ void FractionElement::draw(QPainter& painter, ContextStyle& style, int parentSize, const QPoint& parentOrigin) { QPoint myPos(parentOrigin.x()+getX(), parentOrigin.y()+getY()); int mySize = parentSize + getRelativeSize(); numerator->draw(painter, style, mySize, myPos); denominator->draw(painter, style, mySize, myPos); painter.setPen(Qt::black); painter.drawLine(myPos.x(), myPos.y() + getMidline(), myPos.x() + getWidth(), myPos.y() + getMidline()); } /** * 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. */ void FractionElement::moveLeft(FormulaCursor* cursor, BasicElement* from) { if (cursor->isSelectionMode()) { getParent()->moveLeft(cursor, this); } else { if (from == getParent()) { denominator->moveLeft(cursor, this); } else if (from == denominator) { numerator->moveLeft(cursor, this); } else { getParent()->moveLeft(cursor, this); } } } /** * 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. */ void FractionElement::moveRight(FormulaCursor* cursor, BasicElement* from) { if (cursor->isSelectionMode()) { getParent()->moveRight(cursor, this); } else { if (from == getParent()) { numerator->moveRight(cursor, this); } else if (from == numerator) { denominator->moveRight(cursor, this); } else { getParent()->moveRight(cursor, this); } } } /** * Enters this element while moving up starting inside * the element `from'. Searches for a cursor position inside * this element or above it. */ void FractionElement::moveUp(FormulaCursor* cursor, BasicElement* from) { if (cursor->isSelectionMode()) { getParent()->moveUp(cursor, this); } else { if (from == getParent()) { denominator->moveRight(cursor, this); } else if (from == denominator) { numerator->moveRight(cursor, this); } else { getParent()->moveUp(cursor, this); } } } /** * Enters this element while moving down starting inside * the element `from'. Searches for a cursor position inside * this element or below it. */ void FractionElement::moveDown(FormulaCursor* cursor, BasicElement* from) { if (cursor->isSelectionMode()) { getParent()->moveDown(cursor, this); } else { if (from == getParent()) { numerator->moveRight(cursor, this); } else if (from == numerator) { denominator->moveRight(cursor, this); } else { getParent()->moveDown(cursor, this); } } } /** * Reinserts the denominator if it has been removed. */ void FractionElement::insert(FormulaCursor* cursor, QList& newChildren, Direction direction) { if (cursor->getPos() == denominatorPos) { denominator = static_cast(newChildren.take(0)); denominator->setParent(this); if (direction == beforeCursor) { denominator->moveLeft(cursor, this); } else { denominator->moveRight(cursor, this); } cursor->setSelection(false); formula()->changed(); } } /** * Removes all selected children and returns them. Places the * cursor to where the children have been. * * We remove ourselve if we are requested to remove our numerator. * * It is possible to remove the denominator. But after this we * are senseless and the caller is required to replace us. */ void FractionElement::remove(FormulaCursor* cursor, QList& removedChildren, Direction direction) { switch (cursor->getPos()) { case numeratorPos: getParent()->selectChild(cursor, this); getParent()->remove(cursor, removedChildren, direction); break; case denominatorPos: removedChildren.append(denominator); formula()->elementRemoval(denominator); denominator = 0; cursor->setTo(this, denominatorPos); formula()->changed(); break; } } /** * Returns wether the element has no more useful * children (except its main child) and should therefore * be replaced by its main child's content. */ bool FractionElement::isSenseless() { return denominator == 0; } // main child // // If an element has children one has to become the main one. SequenceElement* FractionElement::getMainChild() { return numerator; } void FractionElement::setMainChild(SequenceElement* child) { formula()->elementRemoval(numerator); numerator = child; numerator->setParent(this); formula()->changed(); } /** * Sets the cursor to select the child. The mark is placed before, * the position behind it. */ void FractionElement::selectChild(FormulaCursor* cursor, BasicElement* child) { if (child == numerator) { cursor->setTo(this, numeratorPos); } else if (child == denominator) { cursor->setTo(this, denominatorPos); } } + +QDomElement FractionElement::getElementDom(QDomDocument *doc) +{ + QDomElement de=doc->createElement("FRACTION"); + int sz=getRelativeSize(); + if(sz!=0) { + de.setAttribute("SIZE",sz); + } + + QDomElement den=doc->createElement("NUMERATOR"); + den.appendChild(numerator->getElementDom(doc)); + + QDomElement num=doc->createElement("DENOMINATOR"); + num.appendChild(denominator->getElementDom(doc)); + + de.appendChild(den); + de.appendChild(num); + + return de; +} diff --git a/lib/kformula2/fractionelement.h b/lib/kformula2/fractionelement.h index 31eba0b432..ca6953f050 100644 --- a/lib/kformula2/fractionelement.h +++ b/lib/kformula2/fractionelement.h @@ -1,126 +1,134 @@ /* This file is part of the KDE project Copyright (C) 2001 Andrea Rizzi Ulrich Kuettler 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. 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __FRACTIONELEMENT_H #define __FRACTIONELEMENT_H #include "basicelement.h" class SequenceElement; /** * A fraction. */ class FractionElement : public BasicElement { public: enum { numeratorPos, denominatorPos }; FractionElement(BasicElement* parent = 0); ~FractionElement(); /** * Calculates our width and height and * our children's parentPosition. */ virtual void calcSizes(ContextStyle& style, int parentSize); /** * Draws the whole element including its children. * The `parentOrigin' is the point this element's parent starts. * We can use our parentPosition to get our own origin then. */ virtual void draw(QPainter& painter, ContextStyle& style, int parentSize, const QPoint& parentOrigin); /** * 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); /** * 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); /** * Reinserts the denominator if it has been removed. */ virtual void insert(FormulaCursor*, QList&, Direction); /** * Removes all selected children and returns them. Places the * cursor to where the children have been. * * We remove ourselve if we are requested to remove our numerator. * * It is possible to remove the denominator. But after this we * are senseless and the caller is required to replace us. */ virtual void remove(FormulaCursor*, QList&, Direction); // main child // // If an element has children one has to become the main one. virtual SequenceElement* getMainChild(); virtual void setMainChild(SequenceElement*); /** * Returns wether the element has no more useful * children (except its main child) and should therefore * be replaced by its main child's content. */ virtual bool isSenseless(); /** * Sets the cursor to select the child. The mark is placed before, * the position behind it. */ virtual void selectChild(FormulaCursor* cursor, BasicElement* child); + + //Save/load support + /** + * @return a QDomElement that contain as DomChildren the + * children, and as attribute the attribute of this + * element. + */ + virtual QDomElement getElementDom(QDomDocument *doc); private: SequenceElement* numerator; SequenceElement* denominator; }; #endif // __FRACTIONELEMENT_H diff --git a/lib/kformula2/indexelement.cc b/lib/kformula2/indexelement.cc index d81170d8bb..da23f74cae 100644 --- a/lib/kformula2/indexelement.cc +++ b/lib/kformula2/indexelement.cc @@ -1,755 +1,797 @@ /* This file is part of the KDE project Copyright (C) 2001 Andrea Rizzi Ulrich Kuettler 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "indexelement.h" #include "formulacursor.h" #include "formulaelement.h" #include "sequenceelement.h" IndexElement::IndexElement(BasicElement* parent) : ComplexElement(parent) { content = new SequenceElement(this); upperLeft = 0; upperRight = 0; lowerLeft = 0; lowerRight = 0; } IndexElement::~IndexElement() { delete content; delete upperLeft; delete upperRight; delete lowerLeft; delete lowerRight; } ostream& IndexElement::output(ostream& stream) { stream << "IndexElement {\n"; BasicElement::output(stream) << endl; stream << "content: "; content->output(stream) << endl; if (hasUpperLeft()) { stream << "upperLeft: "; upperLeft->output(stream) << endl; } if (hasLowerLeft()) { stream << "lowerLeft: "; lowerLeft->output(stream) << endl; } if (hasUpperRight()) { stream << "upperRight: "; upperRight->output(stream) << endl; } if (hasLowerRight()) { stream << "lowerRight: "; lowerRight->output(stream) << endl; } stream << '}'; return stream; } /** * Returns the element the point is in. */ BasicElement* IndexElement::isInside(const QPoint& point, const QPoint& parentOrigin) { BasicElement* e = BasicElement::isInside(point, parentOrigin); if (e != 0) { QPoint myPos(parentOrigin.x()+getX(), parentOrigin.y()+getY()); e = content->isInside(point, myPos); if (e != 0) return e; if (hasUpperRight()) { e = upperRight->isInside(point, myPos); if (e != 0) return e; } if (hasUpperLeft()) { e = upperLeft->isInside(point, myPos); if (e != 0) return e; } if (hasLowerRight()) { e = lowerRight->isInside(point, myPos); if (e != 0) return e; } if (hasLowerLeft()) { e = lowerLeft->isInside(point, myPos); if (e != 0) return e; } return this; } return 0; } // 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. /** * Calculates our width and height and * our children's parentPosition. */ void IndexElement::calcSizes(ContextStyle& contextStyle, int parentSize) { int mySize = parentSize + getRelativeSize(); // get the indexes size int ulWidth = 0, ulHeight = 0, ulMidline = 0; if (hasUpperLeft()) { upperLeft->calcSizes(contextStyle, mySize); ulWidth = upperLeft->getWidth(); ulHeight = upperLeft->getHeight(); ulMidline = upperLeft->getMidline(); } int urWidth = 0, urHeight = 0, urMidline = 0; if (hasUpperRight()) { upperRight->calcSizes(contextStyle, mySize); urWidth = upperRight->getWidth(); urHeight = upperRight->getHeight(); urMidline = upperRight->getMidline(); } int llWidth = 0, llHeight = 0, llMidline = 0; if (hasLowerLeft()) { lowerLeft->calcSizes(contextStyle, mySize); llWidth = lowerLeft->getWidth(); llHeight = lowerLeft->getHeight(); llMidline = lowerLeft->getMidline(); } int lrWidth = 0, lrHeight = 0, lrMidline = 0; if (hasLowerRight()) { lowerRight->calcSizes(contextStyle, mySize); lrWidth = lowerRight->getWidth(); lrHeight = lowerRight->getHeight(); lrMidline = lowerRight->getMidline(); } // get the contents size content->calcSizes(contextStyle, mySize); int width = content->getWidth(); int toMidline = content->getMidline(); int fromMidline = content->getHeight() - toMidline; // calculate the x offsets if (ulWidth > llWidth) { upperLeft->setX(0); if (hasLowerLeft()) { lowerLeft->setX(ulWidth - llWidth); } content->setX(ulWidth); width += ulWidth; } else { if (hasUpperLeft()) { upperLeft->setX(llWidth - ulWidth); } if (hasLowerLeft()) { lowerLeft->setX(0); } content->setX(llWidth); width += llWidth; } if (hasUpperRight()) { upperRight->setX(width); } if (hasLowerRight()) { lowerRight->setX(width); } width += QMAX(urWidth, lrWidth); // calculate the y offsets if (ulHeight > urHeight) { upperLeft->setY(0); if (hasUpperRight()) { upperRight->setY(ulHeight - urHeight); } content->setY(QMAX(ulHeight - toMidline/2, 0)); toMidline += content->getY(); } else { if (hasUpperLeft()) { upperLeft->setY(urHeight - ulHeight); } if (hasUpperRight()) { upperRight->setY(0); } content->setY(QMAX(urHeight - toMidline/2, 0)); toMidline += content->getY(); } if (hasLowerLeft()) { lowerLeft->setY(toMidline + fromMidline/2); } if (hasLowerRight()) { lowerRight->setY(toMidline + fromMidline/2); } fromMidline += QMAX(QMAX(llHeight, lrHeight) - fromMidline/2, 0); // set the result setWidth(width); setHeight(toMidline+fromMidline); setMidline(toMidline); } /** * Draws the whole element including its children. * The `parentOrigin' is the point this element's parent starts. * We can use our parentPosition to get our own origin then. */ void IndexElement::draw(QPainter& painter, ContextStyle& contextStyle, int parentSize, const QPoint& parentOrigin) { QPoint myPos(parentOrigin.x()+getX(), parentOrigin.y()+getY()); int mySize = parentSize + getRelativeSize(); content->draw(painter, contextStyle, mySize, myPos); if (hasUpperLeft()) { upperLeft->draw(painter, contextStyle, mySize, myPos); } if (hasUpperRight()) { upperRight->draw(painter, contextStyle, mySize, myPos); } if (hasLowerLeft()) { lowerLeft->draw(painter, contextStyle, mySize, myPos); } if (hasLowerRight()) { lowerRight->draw(painter, contextStyle, mySize, myPos); } // Debug //painter.setPen(Qt.red) //painter.drawRect(x, y, self.width(), self.height()) } // 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. */ void IndexElement::moveLeft(FormulaCursor* cursor, BasicElement* from) { if (cursor->isSelectionMode()) { getParent()->moveLeft(cursor, this); } else { if (from == getParent()) { if (hasLowerRight()) { lowerRight->moveLeft(cursor, this); } else if (hasUpperRight()) { upperRight->moveLeft(cursor, this); } else { content->moveLeft(cursor, this); } } else if (from == lowerRight) { if (hasUpperRight()) { upperRight->moveLeft(cursor, this); } else { content->moveLeft(cursor, this); } } else if (from == upperRight) { content->moveLeft(cursor, this); } else if (from == content) { if (hasLowerLeft()) { lowerLeft->moveLeft(cursor, this); } else if (hasUpperLeft()) { upperLeft->moveLeft(cursor, this); } else { getParent()->moveLeft(cursor, this); } } else if (from == lowerLeft) { if (hasUpperLeft()) { upperLeft->moveLeft(cursor, this); } else { getParent()->moveLeft(cursor, this); } } else if (from == upperLeft) { getParent()->moveLeft(cursor, this); } } } /** * 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. */ void IndexElement::moveRight(FormulaCursor* cursor, BasicElement* from) { if (cursor->isSelectionMode()) { getParent()->moveRight(cursor, this); } else { if (from == getParent()) { if (hasUpperLeft()) { upperLeft->moveRight(cursor, this); } else if (hasLowerLeft()) { lowerLeft->moveRight(cursor, this); } else { content->moveRight(cursor, this); } } else if (from == getParent()) { if (hasLowerLeft()) { lowerLeft->moveRight(cursor, this); } else { content->moveRight(cursor, this); } } else if (from == lowerLeft) { content->moveRight(cursor, this); } else if (from == content) { if (hasUpperRight()) { upperRight->moveRight(cursor, this); } else if (hasLowerRight()) { lowerRight->moveRight(cursor, this); } else { getParent()->moveRight(cursor, this); } } else if (from == upperRight) { if (hasLowerRight()) { lowerRight->moveRight(cursor, this); } else { getParent()->moveRight(cursor, this); } } else if (from == lowerRight) { getParent()->moveRight(cursor, this); } } } /** * Enters this element while moving up starting inside * the element `from'. Searches for a cursor position inside * this element or above it. */ void IndexElement::moveUp(FormulaCursor* cursor, BasicElement* from) { if (cursor->isSelectionMode()) { getParent()->moveUp(cursor, this); } else { if (from == content) { if (hasUpperRight()) { upperRight->moveRight(cursor, this); } else if (hasUpperLeft()) { upperLeft->moveLeft(cursor, this); } else { getParent()->moveUp(cursor, this); } } else if ((from == upperLeft) || (from == upperRight)) { getParent()->moveUp(cursor, this); } else if ((from == getParent()) || (from == lowerLeft)) { content->moveRight(cursor, this); } else if (from == lowerRight) { content->moveLeft(cursor, this); } } } /** * Enters this element while moving down starting inside * the element `from'. Searches for a cursor position inside * this element or below it. */ void IndexElement::moveDown(FormulaCursor* cursor, BasicElement* from) { if (cursor->isSelectionMode()) { getParent()->moveDown(cursor, this); } else { if (from == content) { if (hasLowerRight()) { lowerRight->moveRight(cursor, this); } else if (hasLowerLeft()) { lowerLeft->moveLeft(cursor, this); } else { getParent()->moveDown(cursor, this); } } else if ((from == lowerLeft) || (from == lowerRight)) { getParent()->moveDown(cursor, this); } else if ((from == getParent()) || (from == upperLeft)) { content->moveRight(cursor, this); } if (from == upperRight) { content->moveLeft(cursor, this); } } } // children // main child // // If an element has children one has to become the main one. void IndexElement::setMainChild(SequenceElement* child) { formula()->elementRemoval(content); content = child; content->setParent(this); formula()->changed(); } /** * Inserts all new children at the cursor position. Places the * cursor according to the direction. * * You only can insert one index at a time. So the list must contain * exactly on SequenceElement. And the index you want to insert * must not exist already. * * The list will be emptied but stays the property of the caller. */ void IndexElement::insert(FormulaCursor* cursor, QList& newChildren, Direction direction) { SequenceElement* index = static_cast(newChildren.take(0)); index->setParent(this); switch (cursor->getPos()) { case upperLeftPos: upperLeft = index; break; case lowerLeftPos: lowerLeft = index; break; case upperRightPos: upperRight = index; break; case lowerRightPos: lowerRight = index; break; default: // this is an error! return; } if (direction == beforeCursor) { index->moveLeft(cursor, this); } else { index->moveRight(cursor, this); } cursor->setSelection(false); formula()->changed(); } /** * Removes all selected children and returns them. Places the * cursor to where the children have been. * * The cursor has to be inside one of our indexes which is supposed * to be empty. The index will be removed and the cursor will * be placed to the removed index so it can be inserted again. * This methode is called by SequenceElement::remove only. * * The ownership of the list is passed to the caller. */ void IndexElement::remove(FormulaCursor* cursor, QList& removedChildren, Direction direction) { int pos = cursor->getPos(); switch (pos) { case upperLeftPos: removedChildren.append(upperLeft); formula()->elementRemoval(upperLeft); upperLeft = 0; setToUpperLeft(cursor); break; case lowerLeftPos: removedChildren.append(lowerLeft); formula()->elementRemoval(lowerLeft); lowerLeft = 0; setToLowerLeft(cursor); break; case contentPos: { BasicElement* parent = getParent(); parent->selectChild(cursor, this); parent->remove(cursor, removedChildren, direction); break; } case upperRightPos: removedChildren.append(upperRight); formula()->elementRemoval(upperRight); upperRight = 0; setToUpperRight(cursor); break; case lowerRightPos: removedChildren.append(lowerRight); formula()->elementRemoval(lowerRight); lowerRight = 0; setToLowerRight(cursor); break; } formula()->changed(); } /** * Moves the cursor to a normal place where new elements * might be inserted. */ void IndexElement::normalize(FormulaCursor* cursor, BasicElement::Direction direction) { if (direction == BasicElement::beforeCursor) { content->moveLeft(cursor, this); } else { content->moveRight(cursor, this); } } /** * Returns wether the element has no more useful * children (except its main child) and should therefore * be replaced by its main child's content. */ bool IndexElement::isSenseless() { return !hasUpperLeft() && !hasUpperRight() && !hasLowerLeft() && !hasLowerRight(); } /** * Returns the child at the cursor. */ BasicElement* IndexElement::getChild(FormulaCursor* cursor, Direction) { int pos = cursor->getPos(); /* It makes no sense to care for the direction. if (direction == beforeCursor) { pos -= 1; } */ switch (pos) { case contentPos: return content; case upperLeftPos: return upperLeft; case lowerLeftPos: return lowerLeft; case upperRightPos: return upperRight; case lowerRightPos: return lowerRight; } return 0; } /** * Sets the cursor to select the child. The mark is placed before, * the position behind it. */ void IndexElement::selectChild(FormulaCursor* cursor, BasicElement* child) { if (child == content) { setToContent(cursor); } else if (child == upperLeft) { setToUpperLeft(cursor); } else if (child == lowerLeft) { setToLowerLeft(cursor); } else if (child == upperRight) { setToUpperRight(cursor); } else if (child == lowerRight) { setToLowerRight(cursor); } } // SequenceElement* IndexElement::requireUpperLeft() // { // if (!hasUpperLeft()) { // upperLeft = new SequenceElement(this); // } // return upperLeft; // } // SequenceElement* IndexElement::requireUpperRight() // { // if (!hasUpperRight()) { // upperRight = new SequenceElement(this); // } // return upperRight; // } // SequenceElement* IndexElement::requireLowerLeft() // { // if (!hasLowerLeft()) { // lowerLeft = new SequenceElement(this); // } // return lowerLeft; // } // SequenceElement* IndexElement::requireLowerRight() // { // if (!hasLowerRight()) { // lowerRight = new SequenceElement(this); // } // return lowerRight; // } /** * Sets the cursor to point to the place where the content is. * There always is a content so this is not a useful place. * No insertion or removal will succeed as long as the cursor is * there. */ void IndexElement::setToContent(FormulaCursor* cursor) { cursor->setTo(this, contentPos); } // point the cursor to a gap where an index is to be inserted. // this makes no sense if there is such an index already. void IndexElement::setToUpperLeft(FormulaCursor* cursor) { cursor->setTo(this, upperLeftPos); } void IndexElement::setToUpperRight(FormulaCursor* cursor) { cursor->setTo(this, upperRightPos); } void IndexElement::setToLowerLeft(FormulaCursor* cursor) { cursor->setTo(this, lowerLeftPos); } void IndexElement::setToLowerRight(FormulaCursor* cursor) { cursor->setTo(this, lowerRightPos); } // move inside an index that exists already. void IndexElement::moveToUpperLeft(FormulaCursor* cursor, Direction direction) { if (hasUpperLeft()) { if (direction == beforeCursor) { upperLeft->moveLeft(cursor, this); } else { upperLeft->moveRight(cursor, this); } } } void IndexElement::moveToUpperRight(FormulaCursor* cursor, Direction direction) { if (hasUpperRight()) { if (direction == beforeCursor) { upperRight->moveLeft(cursor, this); } else { upperRight->moveRight(cursor, this); } } } void IndexElement::moveToLowerLeft(FormulaCursor* cursor, Direction direction) { if (hasLowerLeft()) { if (direction == beforeCursor) { lowerLeft->moveLeft(cursor, this); } else { lowerLeft->moveRight(cursor, this); } } } void IndexElement::moveToLowerRight(FormulaCursor* cursor, Direction direction) { if (hasLowerRight()) { if (direction == beforeCursor) { lowerRight->moveLeft(cursor, this); } else { lowerRight->moveRight(cursor, this); } } } +QDomElement IndexElement::getElementDom(QDomDocument *doc) +{ + QDomElement de=doc->createElement("INDEX"); + int sz=getRelativeSize(); + if(sz!=0) { + de.setAttribute("SIZE",sz); + } + + + QDomElement cont=doc->createElement("CONTENT"); + cont.appendChild(content->getElementDom(doc)); + de.appendChild(cont); + + + if (hasUpperLeft()) { + QDomElement ind=doc->createElement("UPPERLEFT"); + ind.appendChild(upperLeft->getElementDom(doc)); + de.appendChild(ind); + } + + if (hasUpperRight()) { + QDomElement ind=doc->createElement("UPPERRIGHT"); + ind.appendChild(upperRight->getElementDom(doc)); + de.appendChild(ind); + } + if (hasLowerLeft()) { + QDomElement ind=doc->createElement("LOWERLEFT"); + ind.appendChild(lowerLeft->getElementDom(doc)); + de.appendChild(ind); + } + if (hasLowerRight()) { + QDomElement ind=doc->createElement("LOWERRIGHT"); + ind.appendChild(lowerRight->getElementDom(doc)); + de.appendChild(ind); + } + + + return de; +} + + + diff --git a/lib/kformula2/indexelement.h b/lib/kformula2/indexelement.h index 38acc278da..e45c37de1a 100644 --- a/lib/kformula2/indexelement.h +++ b/lib/kformula2/indexelement.h @@ -1,251 +1,253 @@ /* This file is part of the KDE project Copyright (C) 2001 Andrea Rizzi Ulrich Kuettler 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __INDEXELEMENT_H #define __INDEXELEMENT_H // Formula include #include "complexelement.h" class SequenceElement; /** * The element with up to four indexes in the four corners. */ class IndexElement : public ComplexElement { public: // each index has its own number. enum { upperLeftPos, lowerLeftPos, contentPos, upperRightPos, lowerRightPos }; IndexElement(BasicElement* parent = 0); ~IndexElement(); /** * Returns the element the point is in. */ virtual BasicElement* isInside(const QPoint& point, const QPoint& parentOrigin); // 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. /** * Calculates our width and height and * our children's parentPosition. */ virtual void calcSizes(ContextStyle& context, int parentSize); /** * Draws the whole element including its children. * The `parentOrigin' is the point this element's parent starts. * We can use our parentPosition to get our own origin then. */ virtual void draw(QPainter& painter, ContextStyle& context, int parentSize, const QPoint& parentOrigin); // 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); /** * 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); // children /** * Removes the child. If this was the main child this element might * request its own removal. * The cursor is the one that caused the removal. It has to be moved * to the place any user expects the cursor after that particular * element has been removed. */ //virtual void removeChild(FormulaCursor* cursor, BasicElement* child); // main child // // If an element has children one has to become the main one. virtual SequenceElement* getMainChild() { return content; } virtual void setMainChild(SequenceElement*); /** * Inserts all new children at the cursor position. Places the * cursor according to the direction. * * You only can insert one index at a time. So the list must contain * exactly on SequenceElement. And the index you want to insert * must not exist already. * * The list will be emptied but stays the property of the caller. */ virtual void insert(FormulaCursor*, QList&, Direction); /** * Removes all selected children and returns them. Places the * cursor to where the children have been. * * The cursor has to be inside one of our indexes which is supposed * to be empty. The index will be removed and the cursor will * be placed to the removed index so it can be inserted again. * This methode is called by SequenceElement::remove only. * * The ownership of the list is passed to the caller. */ virtual void remove(FormulaCursor*, QList&, 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. */ 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); /** * Returns wether the element has no more useful * children (except its main child) and should therefore * be replaced by its main child's content. */ virtual bool isSenseless(); bool hasUpperLeft() const { return upperLeft != 0; } bool hasUpperRight() const { return upperRight != 0; } bool hasLowerLeft() const { return lowerLeft != 0; } bool hasLowerRight() const { return lowerRight != 0; } // Return the index. If there is non, create it first. // SequenceElement* requireUpperLeft(); // SequenceElement* requireUpperRight(); // SequenceElement* requireLowerLeft(); // SequenceElement* requireLowerRight(); // If we want to create an index we need a cursor that points there. void setToUpperLeft(FormulaCursor* cursor); void setToUpperRight(FormulaCursor* cursor); void setToLowerLeft(FormulaCursor* cursor); void setToLowerRight(FormulaCursor* cursor); // If the index is there we need a way to move into it. void moveToUpperLeft(FormulaCursor* cursor, Direction direction); void moveToUpperRight(FormulaCursor* cursor, Direction direction); void moveToLowerLeft(FormulaCursor* cursor, Direction direction); void moveToLowerRight(FormulaCursor* cursor, Direction direction); // ComplexElement // Moves the cursor inside the index. The index has to exist. virtual void moveToUpperIndex(FormulaCursor* cursor, Direction direction) { moveToUpperRight(cursor, direction); } virtual void moveToLowerIndex(FormulaCursor* cursor, Direction direction) { moveToLowerRight(cursor, direction); } // Sets the cursor to point to the place where the index normaly // is. These functions are only used if there is no such index and // we want to insert them. virtual void setToUpperIndex(FormulaCursor* cursor) { setToUpperRight(cursor); } virtual void setToLowerIndex(FormulaCursor* cursor) { setToLowerRight(cursor); } // Tells whether we own those indexes virtual bool hasUpperIndex() const { return hasUpperRight(); } virtual bool hasLowerIndex() const { return hasLowerRight(); } - + + virtual QDomElement getElementDom(QDomDocument *doc); + // debug virtual ostream& output(ostream&); private: /** * Sets the cursor to point to the place where the content is. * There always is a content so this is not a useful place. * No insertion or removal will succeed as long as the cursor is * there. */ void setToContent(FormulaCursor* cursor); /** * Our main child. This is guaranteed not to be null. */ SequenceElement* content; /** * The four indexes. Each one might be null. * If the last one is removed the whole IndexElement * should be replaced by its main child. */ SequenceElement* upperLeft; SequenceElement* upperRight; SequenceElement* lowerLeft; SequenceElement* lowerRight; }; #endif // __INDEXELEMENT_H diff --git a/lib/kformula2/kformulacontainer.cc b/lib/kformula2/kformulacontainer.cc index dd85d19a80..1d3cc3009e 100644 --- a/lib/kformula2/kformulacontainer.cc +++ b/lib/kformula2/kformulacontainer.cc @@ -1,236 +1,259 @@ /* This file is part of the KDE project Copyright (C) 2001 Andrea Rizzi Ulrich Kuettler 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - +#include +#include +#include #include #include #include #include "bracketelement.h" #include "complexelement.h" #include "contextstyle.h" #include "formulacursor.h" #include "formulaelement.h" #include "fractionelement.h" #include "indexelement.h" #include "kformulacontainer.h" #include "matrixelement.h" #include "operatorelement.h" #include "rootelement.h" #include "sequenceelement.h" #include "symbolelement.h" #include "textelement.h" KFormulaContainer::KFormulaContainer() : rootElement(this) { dirty = true; testDirty(); } KFormulaContainer::~KFormulaContainer() { } FormulaCursor* KFormulaContainer::createCursor() { FormulaCursor* cursor = new FormulaCursor(&rootElement); connect(this, SIGNAL(elementWillVanish(BasicElement*)), cursor, SLOT(elementWillVanish(BasicElement*))); return cursor; } void KFormulaContainer::destroyCursor(FormulaCursor* cursor) { delete cursor; } /** * Gets called just before the child is removed from * the element tree. */ void KFormulaContainer::elementRemoval(BasicElement* child) { emit elementWillVanish(child); } /** * Gets called whenever something changes and we need to * recalc. */ void KFormulaContainer::changed() { dirty = true; } /** * Draws the whole thing. */ void KFormulaContainer::draw(QPainter& painter) { rootElement.draw(painter, context); } void KFormulaContainer::addText(FormulaCursor* cursor, QChar ch) { if (cursor->isSelection()) { removeSelection(cursor, BasicElement::beforeCursor); } QList list; list.setAutoDelete(true); list.append(new TextElement(ch)); cursor->insert(list); cursor->setSelection(false); } void KFormulaContainer::addOperator(FormulaCursor* cursor, QChar ch) { QList list; list.setAutoDelete(true); list.append(new OperatorElement(ch)); cursor->insert(list); cursor->setSelection(false); } void KFormulaContainer::addBracket(FormulaCursor* cursor, char left, char right) { BracketElement* bracket = new BracketElement(left, right); if (cursor->isSelection()) { cursor->replaceSelectionWith(bracket); } else { cursor->insert(bracket); //cursor->setSelection(false); } cursor->goInsideElement(bracket); } void KFormulaContainer::addFraction(FormulaCursor* cursor) { FractionElement* fraction = new FractionElement; if (cursor->isSelection()) { cursor->replaceSelectionWith(fraction); } else { cursor->insert(fraction); //cursor->setSelection(false); } cursor->goInsideElement(fraction); } void KFormulaContainer::addRoot(FormulaCursor* cursor) { RootElement* root = new RootElement(); if (cursor->isSelection()) { cursor->replaceSelectionWith(root); } else { cursor->insert(root); //cursor->setSelection(false); } cursor->goInsideElement(root); } void KFormulaContainer::addSymbol(FormulaCursor* cursor, Artwork::SymbolType type) { SymbolElement* symbol = new SymbolElement(type); if (cursor->isSelection()) { cursor->replaceSelectionWith(symbol); } else { cursor->insert(symbol); //cursor->setSelection(false); } cursor->goInsideElement(symbol); } void KFormulaContainer::addMatrix(FormulaCursor* cursor, int rows, int columns) { MatrixElement* matrix = new MatrixElement(rows, columns); cursor->insert(matrix); cursor->goInsideElement(matrix); } void KFormulaContainer::addLowerRightIndex(FormulaCursor* cursor) { ComplexElement* element = cursor->getActiveIndexedElement(); if ((element == 0) || !element->mightHaveLowerIndex()) { element = new IndexElement; cursor->replaceSelectionWith(element, BasicElement::beforeCursor); } if (!element->hasLowerIndex()) { SequenceElement* index = new SequenceElement; element->setToLowerIndex(cursor); cursor->insert(index); //cursor->goInsideElement(index); } else { element->moveToLowerIndex(cursor, BasicElement::afterCursor); } } void KFormulaContainer::addUpperRightIndex(FormulaCursor* cursor) { ComplexElement* element = cursor->getActiveIndexedElement(); if ((element == 0) || !element->mightHaveUpperIndex()) { element = new IndexElement; cursor->replaceSelectionWith(element, BasicElement::beforeCursor); } if (!element->hasUpperIndex()) { SequenceElement* index = new SequenceElement; element->setToUpperIndex(cursor); cursor->insert(index); //cursor->goInsideElement(index); } else { element->moveToUpperIndex(cursor, BasicElement::afterCursor); } } void KFormulaContainer::removeSelection(FormulaCursor* cursor, BasicElement::Direction direction) { QList list; list.setAutoDelete(true); cursor->remove(list, direction); if (cursor->elementIsSenseless()) { BasicElement* element = cursor->replaceByMainChildContent(); delete element; } //cursor->normalize(direction); cursor->normalize(); } void KFormulaContainer::testDirty() { if (dirty) { dirty = false; rootElement.calcSizes(context); emit formulaChanged(); } } + +QDomDocument KFormulaContainer::domData() +{ + QDomDocument doc("KFORMULA"); + doc.appendChild(rootElement.getElementDom(&doc)); + return doc; +} + +void KFormulaContainer::save(QString file) +{ + + QFile f(file); + if(!f.open(IO_ReadWrite)) + cerr << "Error" << endl; + QCString data=domData().toCString(); + fprintf(stderr,"%s\n",(const char *)data); + + QTextStream str(&f); + domData().save(str,4); + f.close(); +} diff --git a/lib/kformula2/kformulacontainer.h b/lib/kformula2/kformulacontainer.h index 817cdef832..bca3e0bcad 100644 --- a/lib/kformula2/kformulacontainer.h +++ b/lib/kformula2/kformulacontainer.h @@ -1,130 +1,145 @@ /* This file is part of the KDE project Copyright (C) 2001 Andrea Rizzi Ulrich Kuettler 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __KFORMULACONTAINER_H #define __KFORMULACONTAINER_H #include #include "artwork.h" #include "basicelement.h" #include "contextstyle.h" #include "formulaelement.h" class BasicElement; class FormulaCursor; class QKeyEvent; class QPainter; class KFormulaContainer : public QObject { Q_OBJECT public: KFormulaContainer(); ~KFormulaContainer(); /** * Returns a new cursor. It points to the beginning of the * formula. */ FormulaCursor* createCursor(); /** * Destroys the cursor. It must not be used afterwards. */ void destroyCursor(FormulaCursor*); /** * Gets called just before the child is removed from * the element tree. */ void elementRemoval(BasicElement* child); /** * Gets called whenever something changes and we need to * recalc. */ void changed(); /** * Draws the whole thing. */ void draw(QPainter& painter); + /** + * This function return all the data contained in + * the formula. + * @return the content of the formula as a + * QDomDocument. + */ + QDomDocument domData(); + + /** + * Save function. + * Save the formula into the specified file. + * It overwrite the file if exists. + */ + void save(QString file); + signals: /** * The formula has changed and needs to be redrawn. */ void formulaChanged(); /** * The element is going to leave the formula with and all its children. */ void elementWillVanish(BasicElement* element); public slots: // There a lot of thing we can do with the formula. void addText(FormulaCursor* cursor, QChar ch); void addOperator(FormulaCursor* cursor, QChar ch); void addBracket(FormulaCursor* cursor, char left, char right); void addFraction(FormulaCursor* cursor); void addRoot(FormulaCursor* cursor); void addSymbol(FormulaCursor* cursor, Artwork::SymbolType type); void addMatrix(FormulaCursor* cursor, int rows, int columns); void addLowerRightIndex(FormulaCursor* cursor); void addUpperRightIndex(FormulaCursor* cursor); void removeSelection(FormulaCursor* cursor, BasicElement::Direction); /** * Emits a formulaChanged signal if we are dirty. */ void testDirty(); private: /** * The element tree's root. */ FormulaElement rootElement; /** * The style that should be used to draw the formula. */ ContextStyle context; /** * If true we need to recalc the formula. */ bool dirty; // debug friend class TestFormulaCursor; }; #endif // __KFORMULACONTAINER_H diff --git a/lib/kformula2/kformulawidget.cc b/lib/kformula2/kformulawidget.cc index 25e892e3fd..fcb986b930 100644 --- a/lib/kformula2/kformulawidget.cc +++ b/lib/kformula2/kformulawidget.cc @@ -1,161 +1,164 @@ /* This file is part of the KDE project Copyright (C) 2001 Andrea Rizzi Ulrich Kuettler 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include "formulacursor.h" #include "kformulacontainer.h" #include "kformulawidget.h" KFormulaWidget::KFormulaWidget(KFormulaContainer* doc, QWidget* parent, const char* name, WFlags f) : QWidget(parent, name, f), document(doc) { cursor = document->createCursor(); connect(document, SIGNAL(formulaChanged()), this, SLOT(formulaChanged())); } KFormulaWidget::~KFormulaWidget() { document->destroyCursor(cursor); } void KFormulaWidget::paintEvent(QPaintEvent*) { QPainter painter; painter.begin(this); document->draw(painter); cursor->draw(painter); painter.end(); } void KFormulaWidget::keyPressEvent(QKeyEvent* event) { QPainter painter; painter.begin(this); cursor->draw(painter); QChar ch = event->text().at(0); if (ch.isPrint()) { int latin1 = ch.latin1(); switch (latin1) { case '(': document->addBracket(cursor, '(', ')'); break; case '[': document->addBracket(cursor, '[', ']'); break; case '{': break; case '|': document->addBracket(cursor, '|', '|'); break; case '/': document->addFraction(cursor); break; case '#': // here we need a dialog! document->addMatrix(cursor, 4, 5); break; case '\\': document->addRoot(cursor); break; case '+': case '-': case '*': case '=': case '<': case '>': document->addOperator(cursor, ch); break; case '^': document->addUpperRightIndex(cursor); break; case '_': document->addLowerRightIndex(cursor); break; case ' ': break; default: document->addText(cursor, ch); } } else { int action = event->key(); int state = event->state(); int flag=0; if(state & Qt::ControlButton) flag+=FormulaCursor::WordMovement; if(state & Qt::ShiftButton) flag+=FormulaCursor::SelectMovement; switch (action) { case Qt::Key_Left: cursor->moveLeft(flag); break; case Qt::Key_Right: cursor->moveRight(flag); break; case Qt::Key_Up: cursor->moveUp(flag); break; case Qt::Key_Down: cursor->moveDown(flag); break; case Qt::Key_BackSpace: document->removeSelection(cursor, BasicElement::beforeCursor); break; case Qt::Key_Delete: document->removeSelection(cursor, BasicElement::afterCursor); break; case Qt::Key_Home: cursor->moveHome(flag); break; case Qt::Key_End: cursor->moveEnd(flag); break; case Qt::Key_F1: document->addSymbol(cursor, Artwork::product); break; case Qt::Key_F2: document->addSymbol(cursor, Artwork::sum); break; case Qt::Key_F3: document->addSymbol(cursor, Artwork::integral); break; - } + case Qt::Key_F4: + document->save("test"); + break; + } } //Is this necessary here ? document->testDirty(); cursor->draw(painter); painter.end(); } void KFormulaWidget::formulaChanged() { update(); } diff --git a/lib/kformula2/rootelement.cc b/lib/kformula2/rootelement.cc index 19156ae003..ee25241894 100644 --- a/lib/kformula2/rootelement.cc +++ b/lib/kformula2/rootelement.cc @@ -1,352 +1,375 @@ /* This file is part of the KDE project Copyright (C) 2001 Andrea Rizzi Ulrich Kuettler 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. 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include "formulacursor.h" #include "formulaelement.h" #include "rootelement.h" #include "sequenceelement.h" RootElement::RootElement(BasicElement* parent) : ComplexElement(parent) { content = new SequenceElement(this); //index = 0; index = new SequenceElement(this); } RootElement::~RootElement() { delete index; delete content; } /** * Calculates our width and height and * our children's parentPosition. */ void RootElement::calcSizes(ContextStyle& style, int parentSize) { int mySize = parentSize + getRelativeSize(); content->calcSizes(style, mySize); int indexWidth = 0; int indexHeight = 0; if (hasIndex()) { index->calcSizes(style, mySize); indexWidth = index->getWidth(); indexHeight = index->getHeight(); } int dist = style.getDistance(); int unit = (content->getHeight() + dist)/ 3; if (hasIndex()) { if (indexWidth > unit) { index->setX(0); rootOffset.setX(indexWidth - unit); } else { index->setX((unit - indexWidth)/2); rootOffset.setX(0); } if (indexHeight > unit) { index->setY(0); rootOffset.setY(indexHeight - unit); } else { index->setY(unit - indexHeight); rootOffset.setY(0); } } else { rootOffset.setX(0); rootOffset.setY(0); } setWidth(content->getWidth() + unit+unit/3+ rootOffset.x()); setHeight(content->getHeight() + dist + rootOffset.y()); setMidline(getHeight() - content->getHeight() + content->getMidline()); content->setX(rootOffset.x() + unit+unit/3); content->setY(rootOffset.y() + dist); } /** * Draws the whole element including its children. * The `parentOrigin' is the point this element's parent starts. * We can use our parentPosition to get our own origin then. */ void RootElement::draw(QPainter& painter, ContextStyle& style, int parentSize, const QPoint& parentOrigin) { QPoint myPos(parentOrigin.x()+getX(), parentOrigin.y()+getY()); int mySize = parentSize + getRelativeSize(); content->draw(painter, style, mySize, myPos); if (hasIndex()) { index->draw(painter, style, mySize, myPos); } int x = myPos.x() + rootOffset.x(); int y = myPos.y() + rootOffset.y(); int dist = style.getDistance(); int unit = (content->getHeight() + dist)/ 3; painter.setPen(QPen(style.getDefaultColor(), 2)); painter.drawLine(x+unit/3, y+unit+dist/2, x+unit/2+unit/3, y+content->getHeight()+dist/2); painter.setPen(QPen(style.getDefaultColor(), 1)); painter.drawLine(x+unit+unit/3, y+dist/2, x+unit/2+unit/3, y+content->getHeight()+dist/2); painter.drawLine(x+unit+unit/3, y+dist/2, x+unit+unit/3+content->getWidth(), y+dist/2); painter.drawLine(x+unit/3, y+unit+dist/2, x, y+unit+unit/2); } /** * 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. */ void RootElement::moveLeft(FormulaCursor* cursor, BasicElement* from) { if (cursor->isSelectionMode()) { getParent()->moveLeft(cursor, this); } else { if (from == getParent()) { content->moveLeft(cursor, this); } else if (from == content) { if (hasIndex()) { index->moveLeft(cursor, this); } else { getParent()->moveLeft(cursor, this); } } else { getParent()->moveLeft(cursor, this); } } } /** * 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. */ void RootElement::moveRight(FormulaCursor* cursor, BasicElement* from) { if (cursor->isSelectionMode()) { getParent()->moveRight(cursor, this); } else { if (from == getParent()) { if (hasIndex()) { index->moveRight(cursor, this); } else { content->moveRight(cursor, this); } } else if (from == index) { content->moveRight(cursor, this); } else { getParent()->moveRight(cursor, this); } } } /** * Enters this element while moving up starting inside * the element `from'. Searches for a cursor position inside * this element or above it. */ void RootElement::moveUp(FormulaCursor* cursor, BasicElement* from) { if (cursor->isSelectionMode()) { getParent()->moveUp(cursor, this); } else { if (from == getParent()) { content->moveRight(cursor, this); } else if (from == content) { if (hasIndex()) { index->moveRight(cursor, this); } else { getParent()->moveUp(cursor, this); } } else { getParent()->moveUp(cursor, this); } } } /** * Enters this element while moving down starting inside * the element `from'. Searches for a cursor position inside * this element or below it. */ void RootElement::moveDown(FormulaCursor* cursor, BasicElement* from) { if (cursor->isSelectionMode()) { getParent()->moveDown(cursor, this); } else { if (from == getParent()) { if (hasIndex()) { index->moveRight(cursor, this); } else { content->moveRight(cursor, this); } } else if (from == index) { content->moveRight(cursor, this); } else { getParent()->moveDown(cursor, this); } } } /** * Reinserts the index if it has been removed. */ void RootElement::insert(FormulaCursor* cursor, QList& newChildren, Direction direction) { if (cursor->getPos() == indexPos) { index = static_cast(newChildren.take(0)); index->setParent(this); if (direction == beforeCursor) { index->moveLeft(cursor, this); } else { index->moveRight(cursor, this); } cursor->setSelection(false); formula()->changed(); } } /** * Removes all selected children and returns them. Places the * cursor to where the children have been. * * We remove ourselve if we are requested to remove our content. */ void RootElement::remove(FormulaCursor* cursor, QList& removedChildren, Direction direction) { switch (cursor->getPos()) { case contentPos: getParent()->selectChild(cursor, this); getParent()->remove(cursor, removedChildren, direction); break; case indexPos: removedChildren.append(index); formula()->elementRemoval(index); index = 0; cursor->setTo(this, indexPos); formula()->changed(); break; } } /** * Moves the cursor to a normal place where new elements * might be inserted. */ void RootElement::normalize(FormulaCursor* cursor, Direction direction) { if (direction == BasicElement::beforeCursor) { content->moveLeft(cursor, this); } else { content->moveRight(cursor, this); } } // main child // // If an element has children one has to become the main one. SequenceElement* RootElement::getMainChild() { return content; } void RootElement::setMainChild(SequenceElement* child) { formula()->elementRemoval(content); content = child; content->setParent(this); formula()->changed(); } /** * Sets the cursor to select the child. The mark is placed before, * the position behind it. */ void RootElement::selectChild(FormulaCursor* cursor, BasicElement* child) { if (child == content) { cursor->setTo(this, contentPos); } else if (child == index) { cursor->setTo(this, indexPos); } } void RootElement::moveToUpperIndex(FormulaCursor* cursor, Direction direction) { if (hasIndex()) { if (direction == beforeCursor) { index->moveLeft(cursor, this); } else { index->moveRight(cursor, this); } } } void RootElement::setToUpperIndex(FormulaCursor* cursor) { cursor->setTo(this, indexPos); } + +QDomElement RootElement::getElementDom(QDomDocument *doc) +{ + QDomElement de=doc->createElement("ROOT"); + int sz=getRelativeSize(); + if(sz!=0) { + de.setAttribute("SIZE",sz); + } + QDomElement con=doc->createElement("CONTENT"); + con.appendChild(content->getElementDom(doc)); + de.appendChild(con); + + if(hasIndex()) { + QDomElement ind=doc->createElement("INDEX"); + ind.appendChild(index->getElementDom(doc)); + de.appendChild(ind); + } + + + return de; +} + + diff --git a/lib/kformula2/rootelement.h b/lib/kformula2/rootelement.h index 404f86ce64..7ddda78df4 100644 --- a/lib/kformula2/rootelement.h +++ b/lib/kformula2/rootelement.h @@ -1,160 +1,163 @@ /* This file is part of the KDE project Copyright (C) 2001 Andrea Rizzi Ulrich Kuettler 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. 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __ROOTELEMENT_H #define __ROOTELEMENT_H #include #include "complexelement.h" class SequenceElement; /** * A nice graphical root. */ class RootElement : public ComplexElement { public: enum { contentPos, indexPos }; RootElement(BasicElement* parent = 0); ~RootElement(); /** * Calculates our width and height and * our children's parentPosition. */ virtual void calcSizes(ContextStyle& style, int parentSize); /** * Draws the whole element including its children. * The `parentOrigin' is the point this element's parent starts. * We can use our parentPosition to get our own origin then. */ virtual void draw(QPainter& painter, ContextStyle& style, int parentSize, const QPoint& parentOrigin); /** * 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); /** * 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); /** * Reinserts the index if it has been removed. */ virtual void insert(FormulaCursor*, QList&, Direction); /** * Removes all selected children and returns them. Places the * cursor to where the children have been. * * We remove ourselve if we are requested to remove our numerator. * * It is possible to remove the denominator. But after this we * are senseless and the caller is required to replace us. */ virtual void remove(FormulaCursor*, QList&, Direction); /** * Moves the cursor to a normal place where new elements * might be inserted. */ virtual void normalize(FormulaCursor*, Direction); // main child // // If an element has children one has to become the main one. virtual SequenceElement* getMainChild(); virtual void setMainChild(SequenceElement*); /** * Sets the cursor to select the child. The mark is placed before, * the position behind it. */ virtual void selectChild(FormulaCursor* cursor, BasicElement* child); bool hasIndex() const { return index != 0; } // ComplexElement // Moves the cursor inside the index. The index has to exist. virtual void moveToUpperIndex(FormulaCursor*, Direction); virtual void moveToLowerIndex(FormulaCursor*, Direction) {} // Sets the cursor to point to the place where the index normaly // is. These functions are only used if there is no such index and // we want to insert them. virtual void setToUpperIndex(FormulaCursor*); virtual void setToLowerIndex(FormulaCursor*) {} // Tells whether we own those indexes virtual bool hasUpperIndex() const { return hasIndex(); } virtual bool hasLowerIndex() const { return false; } // Tells whether we are allowed to own them. // A root will never have a lower index! virtual bool mightHaveLowerIndex() const { return false; } + + virtual QDomElement getElementDom(QDomDocument *doc); + private: /** * The one below the graph. */ SequenceElement* content; /** * An optional index. */ SequenceElement* index; /** * The point the artwork relates to. */ QPoint rootOffset; }; #endif // __ROOTELEMENT_H diff --git a/lib/kformula2/sequenceelement.cc b/lib/kformula2/sequenceelement.cc index 1813cf7a91..7ffdf03cb1 100644 --- a/lib/kformula2/sequenceelement.cc +++ b/lib/kformula2/sequenceelement.cc @@ -1,533 +1,553 @@ /* This file is part of the KDE project Copyright (C) 2001 Andrea Rizzi Ulrich Kuettler 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include "formulacursor.h" #include "formulaelement.h" #include "sequenceelement.h" SequenceElement::SequenceElement(BasicElement* parent) : BasicElement(parent) { children.setAutoDelete(true); } SequenceElement::~SequenceElement() { } ostream& SequenceElement::output(ostream& stream) { stream << "SequenceElement {\n"; BasicElement::output(stream) << endl; uint count = children.count(); for (uint i = 0; i < count; i++) { children.at(i)->output(stream); stream << '\n'; } stream << '}'; return stream; } /** * Returns the element the point is in. */ BasicElement* SequenceElement::isInside(const QPoint& point, const QPoint& parentOrigin) { BasicElement* e = BasicElement::isInside(point, parentOrigin); if (e != 0) { QPoint myPos(parentOrigin.x() + getX(), parentOrigin.y() + getY()); uint count = children.count(); for (uint i = 0; i < count; i++) { BasicElement* child = children.at(i); e = child->isInside(point, myPos); if (e != 0) return e; } return this; } return 0; } /** * Calculates our width and height and * our children's parentPosition. */ void SequenceElement::calcSizes(ContextStyle& context, int parentSize) { if (children.count() > 0) { int width = 0; int toMidline = 0; int fromMidline = 0; uint count = children.count(); for (uint i = 0; i < count; i++) { BasicElement* child = children.at(i); child->calcSizes(context, parentSize+getRelativeSize()); child->setX(width); width += child->getWidth(); toMidline = QMAX(toMidline, child->getMidline()); fromMidline = QMAX(fromMidline, child->getHeight()-child->getMidline()); } setWidth(width); setHeight(toMidline+fromMidline); setMidline(toMidline); for (uint i = 0; i < count; i++) { BasicElement* child = children.at(i); child->setY(getMidline() - child->getMidline()); } } else { setWidth(10); setHeight(10); setMidline(5); } } /** * Draws the whole element including its children. * The `parentOrigin' is the point this element's parent starts. * We can use our parentPosition to get our own origin then. */ void SequenceElement::draw(QPainter& painter, ContextStyle& context, int parentSize, const QPoint& parentOrigin) { QPoint myPos(parentOrigin.x() + getX(), parentOrigin.y() + getY()); if (children.count() > 0) { int mySize = parentSize+getRelativeSize(); uint count = children.count(); for (uint i = 0; i < count; i++) { BasicElement* child = children.at(i); child->draw(painter, context, mySize, myPos); // Debug //painter.setPen(Qt::green); //painter.drawRect(parentOrigin.x() + getX(), parentOrigin.y() + getY(), // getWidth(), getHeight()); } } else { painter.setBrush(Qt::NoBrush); painter.setPen(Qt::blue); painter.drawRect(myPos.x(), myPos.y(), getWidth(), getHeight()); } } /** * If the cursor is inside a sequence it needs to be drawn. */ void SequenceElement::drawCursor(FormulaCursor* cursor, QPainter& painter) { QPoint point = widgetPos(); int height = getHeight(); int posX; uint pos = cursor->getPos(); if (pos < children.count()) { posX = children.at(pos)->getX(); } else { if (children.count() > 0) { posX = getWidth(); } else { posX = 2; } } if (cursor->isSelection()) { int markX; uint mark = cursor->getMark(); if (mark < children.count()) { markX = children.at(mark)->getX(); } else { markX = getWidth(); } int x = QMIN(posX, markX); int width = abs(posX - markX); painter.setRasterOp(Qt::XorROP); painter.fillRect(point.x()+x, point.y(), width, height, Qt::white); painter.setRasterOp(Qt::CopyROP); } else { painter.setRasterOp(Qt::XorROP); painter.setPen(Qt::white); painter.drawLine(point.x()+posX, point.y()-2, point.x()+posX, point.y()+height+2); painter.drawLine(point.x(), point.y()+height+3, point.x()+getWidth(), point.y()+height+3); painter.setRasterOp(Qt::CopyROP); } } // 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. */ void SequenceElement::moveLeft(FormulaCursor* cursor, BasicElement* from) { // Our parent asks us for a cursor position. Found. if (from == getParent()) { cursor->setTo(this, children.count()); } // We already owned the cursor. Ask next child then. else if (from == this) { if (cursor->getPos() > 0) { if (cursor->isSelectionMode()) { cursor->setTo(this, cursor->getPos()-1); } else { children.at(cursor->getPos()-1)->moveLeft(cursor, this); } } else { // Needed because FormulaElement derives this. if (getParent() != 0) { getParent()->moveLeft(cursor, this); } } } // The cursor came from one of our children or // something is wrong. else { int fromPos = children.find(from); cursor->setTo(this, fromPos); if (cursor->isSelectionMode()) { if (!cursor->isMouseMark()) { cursor->setMark(fromPos+1); } } } } /** * 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. */ void SequenceElement::moveRight(FormulaCursor* cursor, BasicElement* from) { // Our parent asks us for a cursor position. Found. if (from == getParent()) { cursor->setTo(this, 0); } // We already owned the cursor. Ask next child then. else if (from == this) { uint pos = cursor->getPos(); if (pos < children.count()) { if (cursor->isSelectionMode()) { cursor->setTo(this, pos+1); } else { children.at(pos)->moveRight(cursor, this); } } else { // Needed because FormulaElement derives this. if (getParent() != 0) { getParent()->moveRight(cursor, this); } } } // The cursor came from one of our children or // something is wrong. else { int fromPos = children.find(from); cursor->setTo(this, fromPos+1); if (cursor->isSelectionMode()) { if (!cursor->isMouseMark()) { cursor->setMark(fromPos); } } } } /** * Enters this element while moving up starting inside * the element `from'. Searches for a cursor position inside * this element or above it. */ void SequenceElement::moveUp(FormulaCursor* cursor, BasicElement* from) { if (from == getParent()) { moveRight(cursor, this); } else { if (getParent() != 0) { getParent()->moveUp(cursor, this); } } } /** * Enters this element while moving down starting inside * the element `from'. Searches for a cursor position inside * this element or below it. */ void SequenceElement::moveDown(FormulaCursor* cursor, BasicElement* from) { if (from == getParent()) { moveRight(cursor, this); } else { if (getParent() != 0) { getParent()->moveDown(cursor, this); } } } /** * Moves the cursor to the first position in this sequence. * (That is before the first child.) */ void SequenceElement::moveHome(FormulaCursor* cursor) { if (cursor->isSelectionMode()) { BasicElement* element = cursor->getElement(); if (element != this) { while (element->getParent() != this) { element = element->getParent(); } cursor->setMark(children.find(element)+1); } } cursor->setTo(this, 0); } /** * Moves the cursor to the last position in this sequence. * (That is behind the last child.) */ void SequenceElement::moveEnd(FormulaCursor* cursor) { if (cursor->isSelectionMode()) { BasicElement* element = cursor->getElement(); if (element != this) { while (element->getParent() != this) { element = element->getParent(); } cursor->setMark(children.find(element)); } } cursor->setTo(this, children.count()); } /** * Sets the cursor inside this element to its start position. * For most elements that is the main child. */ void SequenceElement::goInside(FormulaCursor* cursor) { cursor->setSelection(false); cursor->setTo(this, 0); } // children /** * Removes the child. If this was the main child this element might * request its own removal. * The cursor is the one that caused the removal. It has to be moved * to the place any user expects the cursor after that particular * element has been removed. */ // void SequenceElement::removeChild(FormulaCursor* cursor, BasicElement* child) // { // int pos = children.find(child); // formula()->elementRemoval(child, pos); // cursor->setTo(this, pos); // children.remove(pos); // /* // if len(self.children) == 0: // if self.parent != None: // self.parent.removeChild(cursor, self) // return // */ // formula()->changed(); // } /** * Inserts all new children 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. */ void SequenceElement::insert(FormulaCursor* cursor, QList& newChildren, Direction direction) { int pos = cursor->getPos(); uint count = newChildren.count(); for (uint i = 0; i < count; i++) { BasicElement* child = newChildren.take(0); child->setParent(this); children.insert(pos+i, child); } if (direction == beforeCursor) { cursor->setTo(this, pos+count, pos); } else { cursor->setTo(this, pos, pos+count); } formula()->changed(); } /** * Removes all selected children and returns them. Places the * cursor to where the children have been. * * The ownership of the list is passed to the caller. */ void SequenceElement::remove(FormulaCursor* cursor, QList& removedChildren, Direction direction) { if (cursor->isSelection()) { int from = cursor->getSelectionStart(); int to = cursor->getSelectionEnd(); for (int i = from; i < to; i++) { removeChild(removedChildren, from); } cursor->setTo(this, from); cursor->setSelection(false); } else { if (direction == beforeCursor) { int pos = cursor->getPos() - 1; if (pos >= 0) { removeChild(removedChildren, pos); cursor->setTo(this, pos); } } else { uint pos = cursor->getPos(); if (pos < children.count()) { removeChild(removedChildren, pos); // It is necessary to set the cursor to its old // position because it got a notification and // moved to the beginning of this sequence. cursor->setTo(this, pos); } } } } /** * Removes the children at pos and appends it to the list. */ void SequenceElement::removeChild(QList& removedChildren, int pos) { BasicElement* child = children.at(pos); formula()->elementRemoval(child); children.take(pos); removedChildren.append(child); //cerr << *removedChildren.at(0) << endl; formula()->changed(); } /** * Moves the cursor to a normal place where new elements * might be inserted. */ void SequenceElement::normalize(FormulaCursor* cursor, Direction) { cursor->setSelection(false); } /** * Returns the child at the cursor. * Does not care about the selection. */ BasicElement* SequenceElement::getChild(FormulaCursor* cursor, Direction direction) { if (direction == beforeCursor) { int pos = cursor->getPos()-1; if (pos >= 0) { return children.at(pos); } } else { uint pos = cursor->getPos(); if (pos < children.count()) { return children.at(pos); } } return 0; } /** * Sets the cursor to select the child. The mark is placed before, * the position behind it. */ void SequenceElement::selectChild(FormulaCursor* cursor, BasicElement* child) { int pos = children.find(child); if (pos > -1) { cursor->setTo(this, pos+1, pos); } } /** * Selects all children. The cursor is put behind, the mark before them. */ void SequenceElement::selectAllChildren(FormulaCursor* cursor) { cursor->setTo(this, children.count(), 0); } + +QDomElement SequenceElement::getElementDom(QDomDocument *doc) +{ + QDomElement de=doc->createElement("SEQUENCE"); + int sz=getRelativeSize(); + if(sz!=0) { + de.setAttribute("SIZE",sz); + } + + uint count = children.count(); + for (uint i = 0; i < count; i++) { + QDomElement tmpEleDom=children.at(i)->getElementDom(doc); + de.appendChild(tmpEleDom); + } + return de; +} + + + + diff --git a/lib/kformula2/sequenceelement.h b/lib/kformula2/sequenceelement.h index 8eca9154ab..8e89431bf6 100644 --- a/lib/kformula2/sequenceelement.h +++ b/lib/kformula2/sequenceelement.h @@ -1,202 +1,206 @@ /* This file is part of the KDE project Copyright (C) 2001 Andrea Rizzi Ulrich Kuettler 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __SEQUENCEELEMENT_H #define __SEQUENCEELEMENT_H // Qt Include #include // Formula include #include "basicelement.h" /** * The element that contains a number of children. * The children are aligned in one line. */ class SequenceElement : public BasicElement { public: SequenceElement(BasicElement* parent = 0); ~SequenceElement(); /** * Returns the element the point is in. */ virtual BasicElement* isInside(const QPoint& point, const QPoint& parentOrigin); // 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. /** * Calculates our width and height and * our children's parentPosition. */ virtual void calcSizes(ContextStyle& context, int parentSize); /** * Draws the whole element including its children. * The `parentOrigin' is the point this element's parent starts. * We can use our parentPosition to get our own origin then. */ virtual void draw(QPainter& painter, ContextStyle& context, int parentSize, const QPoint& parentOrigin); /** * If the cursor is inside a sequence it needs to be drawn. */ void drawCursor(FormulaCursor* cursor, QPainter& painter); // 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); /** * 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); // children /** * Removes the child. If this was the main child this element might * request its own removal. * The cursor is the one that caused the removal. It has to be moved * to the place any user expects the cursor after that particular * element has been removed. */ //virtual void removeChild(FormulaCursor* cursor, BasicElement* child); /** * Inserts all new children 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*, QList&, Direction); /** * Removes all selected children and returns them. Places the * cursor to where the children have been. */ virtual void remove(FormulaCursor*, QList&, 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); /** * Returns the number of children we have. */ int countChildren() const { return children.count(); } /** * Selects all children. The cursor is put behind, the mark before them. */ void selectAllChildren(FormulaCursor* cursor); //BasicElement* getChildAt(int pos); + //Save&load + virtual QDomElement getElementDom(QDomDocument *doc); + + // debug virtual ostream& output(ostream&); private: /** * Removes the children at pos and appends it to the list. */ void removeChild(QList& removedChildren, int pos); /** * Our children. Be sure to notify the rootElement before * you remove any. */ QList children; }; #endif // __SEQUENCEELEMENT_H diff --git a/lib/kformula2/textelement.cc b/lib/kformula2/textelement.cc index d0775f5b78..7bfab845d3 100644 --- a/lib/kformula2/textelement.cc +++ b/lib/kformula2/textelement.cc @@ -1,108 +1,126 @@ /* This file is part of the KDE project Copyright (C) 2001 Andrea Rizzi Ulrich Kuettler 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // Debug #include #include #include #include "basicelement.h" #include "textelement.h" #include "contextstyle.h" TextElement::TextElement(QChar ch, BasicElement* parent) : BasicElement(parent), character(ch) { } ostream& TextElement::output(ostream& stream) { stream << "TextElement: " << character << ", "; BasicElement::output(stream); return stream; } /** * Calculates our width and height and * our children's parentPosition. */ void TextElement::calcSizes(ContextStyle& context, int parentSize) { int mySize = parentSize + getRelativeSize(); //QFontMetrics fm = context.fontMetrics(); QFont font = context.getDefaultFont(); font.setPointSize(mySize); QFontMetrics fm(font); setWidth(fm.width(character)); setHeight(fm.height()); setMidline(getHeight() / 2); baseline = fm.ascent(); } /** * Draws the whole element including its children. * The `parentOrigin' is the point this element's parent starts. * We can use our parentPosition to get our own origin then. */ void TextElement::draw(QPainter& painter, ContextStyle& context, int parentSize, const QPoint& parentOrigin) { int mySize = parentSize + getRelativeSize(); //context.setupPainter(painter); //cerr << "TextElement::draw: " << parentOrigin.x()+getX() << " " << parentOrigin.y()+getY()+baseline << " " << character << "\n"; QFont font = context.getDefaultFont(); font.setPointSize(mySize); painter.setFont(font); painter.setPen(context.getDefaultColor()); painter.drawText(parentOrigin.x()+getX(), parentOrigin.y()+getY()+baseline, character); } // 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. */ void TextElement::moveLeft(FormulaCursor* cursor, BasicElement*) { getParent()->moveLeft(cursor, this); } /** * 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. */ void TextElement::moveRight(FormulaCursor* cursor, BasicElement*) { getParent()->moveRight(cursor, this); } + + +QDomElement TextElement::getElementDom(QDomDocument *doc) +{ + + QDomElement de=doc->createElement("TEXT"); + int sz=getRelativeSize(); + if(sz!=0) { + de.setAttribute("SIZE",sz); + } + //May be this is wrong + de.setAttribute("CHAR",QString(character)); + cerr << "TAG: " << (const char *)de.tagName().latin1() << endl; + cerr << "end of text" << endl; + return de; +} + + diff --git a/lib/kformula2/textelement.h b/lib/kformula2/textelement.h index 00aed3bd66..54dda754b5 100644 --- a/lib/kformula2/textelement.h +++ b/lib/kformula2/textelement.h @@ -1,99 +1,102 @@ /* This file is part of the KDE project Copyright (C) 2001 Andrea Rizzi Ulrich Kuettler 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __TEXTELEMENT_H #define __TEXTELEMENT_H #include #include "basicelement.h" /** * A element that represents one char. */ class TextElement : public BasicElement { public: TextElement(QChar ch, BasicElement* parent = 0); // 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. /** * Calculates our width and height and * our children's parentPosition. */ virtual void calcSizes(ContextStyle& context, int parentSize); /** * Draws the whole element including its children. * The `parentOrigin' is the point this element's parent starts. * We can use our parentPosition to get our own origin then. */ virtual void draw(QPainter& painter, ContextStyle& context, int parentSize, const QPoint& parentOrigin); // 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); + //Save&load + virtual QDomElement getElementDom(QDomDocument *doc); + // debug virtual ostream& output(ostream&); private: /** * Our content. */ QChar character; /** * The position of our baseline. */ int baseline; }; #endif // __TEXTELEMENT_H