lib Library API Documentation

sequenceelement.cc

00001 /* This file is part of the KDE project
00002    Copyright (C) 2001 Andrea Rizzi <rizzi@kde.org>
00003                   Ulrich Kuettler <ulrich.kuettler@mailbox.tu-dresden.de>
00004 
00005    This library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License as published by the Free Software Foundation; either
00008    version 2 of the License, or (at your option) any later version.
00009 
00010    This library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Library General Public License for more details.
00014 
00015    You should have received a copy of the GNU Library General Public License
00016    along with this library; see the file COPYING.LIB.  If not, write to
00017    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00018    Boston, MA 02111-1307, USA.
00019 */
00020 
00021 #include <stdlib.h>
00022 #include <math.h>
00023 
00024 #include <qpainter.h>
00025 #include <qpaintdevice.h>
00026 #include <qvaluestack.h>
00027 
00028 #include <kcommand.h>
00029 #include <kdebug.h>
00030 #include <klocale.h>
00031 
00032 //#include <boost/spirit.hpp>
00033 
00034 #include "MatrixDialog.h"
00035 #include "bracketelement.h"
00036 #include "creationstrategy.h"
00037 #include "elementtype.h"
00038 #include "elementvisitor.h"
00039 #include "formulacursor.h"
00040 #include "formulaelement.h"
00041 #include "fractionelement.h"
00042 #include "indexelement.h"
00043 #include "kformulacommand.h"
00044 #include "kformulacontainer.h"
00045 #include "kformuladocument.h"
00046 #include "matrixelement.h"
00047 #include "rootelement.h"
00048 #include "sequenceelement.h"
00049 #include "sequenceparser.h"
00050 #include "spaceelement.h"
00051 #include "symbolelement.h"
00052 #include "symboltable.h"
00053 #include "textelement.h"
00054 
00055 #include <assert.h>
00056 
00057 KFORMULA_NAMESPACE_BEGIN
00058 //using namespace std;
00059 
00060 ElementCreationStrategy* SequenceElement::creationStrategy = 0;
00061 
00062 void SequenceElement::setCreationStrategy( ElementCreationStrategy* strategy )
00063 {
00064     creationStrategy = strategy;
00065 }
00066 
00067 
00068 SequenceElement::SequenceElement(BasicElement* parent)
00069         : BasicElement(parent), parseTree(0), textSequence(true),singlePipe(true)
00070 {
00071     assert( creationStrategy != 0 );
00072     children.setAutoDelete(true);
00073 }
00074 
00075 
00076 SequenceElement::~SequenceElement()
00077 {
00078     delete parseTree;
00079 }
00080 
00081 SequenceElement::SequenceElement( const SequenceElement& other )
00082     : BasicElement( other )
00083 {
00084     children.setAutoDelete(true);
00085     uint count = other.children.count();
00086     for (uint i = 0; i < count; i++) {
00087         BasicElement* child = children.at(i)->clone();
00088         child->setParent( this );
00089         children.append( child );
00090     }
00091 }
00092 
00093 
00094 bool SequenceElement::accept( ElementVisitor* visitor )
00095 {
00096     return visitor->visit( this );
00097 }
00098 
00099 
00100 bool SequenceElement::readOnly( const FormulaCursor* ) const
00101 {
00102     return getParent()->readOnly( this );
00103 }
00104 
00105 
00109 BasicElement* SequenceElement::goToPos( FormulaCursor* cursor, bool& handled,
00110                                         const LuPixelPoint& point, const LuPixelPoint& parentOrigin )
00111 {
00112     BasicElement* e = BasicElement::goToPos(cursor, handled, point, parentOrigin);
00113     if (e != 0) {
00114         LuPixelPoint myPos(parentOrigin.x() + getX(),
00115                            parentOrigin.y() + getY());
00116 
00117         uint count = children.count();
00118         for (uint i = 0; i < count; i++) {
00119             BasicElement* child = children.at(i);
00120             e = child->goToPos(cursor, handled, point, myPos);
00121             if (e != 0) {
00122                 if (!handled) {
00123                     handled = true;
00124                     if ((point.x() - myPos.x()) < (e->getX() + e->getWidth()*2/3)) {
00125                         cursor->setTo(this, children.find(e));
00126                     }
00127                     else {
00128                         cursor->setTo(this, children.find(e)+1);
00129                     }
00130                 }
00131                 return e;
00132             }
00133         }
00134 
00135         luPixel dx = point.x() - myPos.x();
00136         //int dy = point.y() - myPos.y();
00137 
00138         for (uint i = 0; i < count; i++) {
00139             BasicElement* child = children.at(i);
00140             if (dx < child->getX()) {
00141                 cursor->setTo( this, i );
00142                 handled = true;
00143                 return children.at( i );
00144             }
00145         }
00146 
00147         cursor->setTo(this, countChildren());
00148         handled = true;
00149         return this;
00150     }
00151     return 0;
00152 }
00153 
00154 
00155 bool SequenceElement::isEmpty()
00156 {
00157     uint count = children.count();
00158     for (uint i = 0; i < count; i++) {
00159         BasicElement* child = children.at(i);
00160         if (!child->isInvisible()) {
00161             return false;
00162         }
00163     }
00164     return true;
00165 }
00166 
00167 
00172 void SequenceElement::calcSizes(const ContextStyle& style,
00173                                 ContextStyle::TextStyle tstyle,
00174                                 ContextStyle::IndexStyle istyle)
00175 {
00176     if (!isEmpty()) {
00177         luPixel width = 0;
00178         luPixel toBaseline = 0;
00179         luPixel fromBaseline = 0;
00180 
00181         // Let's do all normal elements that have a base line.
00182         QPtrListIterator<BasicElement> it( children );
00183         for ( ; it.current(); ++it ) {
00184             BasicElement* child = it.current();
00185 
00186             luPixel spaceBefore = 0;
00187             if ( isFirstOfToken( child ) ) {
00188                 spaceBefore =
00189                     style.ptToPixelX( child->getElementType()->getSpaceBefore( style,
00190                                                                                tstyle ) );
00191             }
00192 
00193             if ( !child->isInvisible() ) {
00194                 child->calcSizes( style, tstyle, istyle );
00195                 child->setX( width + spaceBefore );
00196                 width += child->getWidth() + spaceBefore;
00197 
00198                 luPixel childBaseline = child->getBaseline();
00199                 if ( childBaseline > -1 ) {
00200                     toBaseline = QMAX( toBaseline, childBaseline );
00201                     fromBaseline = QMAX( fromBaseline,
00202                                          child->getHeight() - childBaseline );
00203                 }
00204                 else {
00205                     luPixel bl = child->getHeight()/2 + style.axisHeight( tstyle );
00206                     toBaseline = QMAX( toBaseline, bl );
00207                     fromBaseline = QMAX( fromBaseline, child->getHeight() - bl );
00208                 }
00209             }
00210             else {
00211                 width += spaceBefore;
00212                 child->setX( width );
00213             }
00214         }
00215 
00216         setWidth(width);
00217         setHeight(toBaseline+fromBaseline);
00218         setBaseline(toBaseline);
00219 
00220         setChildrenPositions();
00221     }
00222     else {
00223         luPixel w = style.getEmptyRectWidth();
00224         luPixel h = style.getEmptyRectHeight();
00225         setWidth( w );
00226         setHeight( h );
00227         setBaseline( h );
00228         //setMidline( h*.5 );
00229     }
00230 }
00231 
00232 
00233 void SequenceElement::setChildrenPositions()
00234 {
00235     QPtrListIterator<BasicElement> it( children );
00236     for ( ; it.current(); ++it ) {
00237         BasicElement* child = it.current();
00238         child->setY(getBaseline() - child->getBaseline());
00239     }
00240 }
00241 
00242 
00248 void SequenceElement::draw( QPainter& painter, const LuPixelRect& r,
00249                             const ContextStyle& context,
00250                             ContextStyle::TextStyle tstyle,
00251                             ContextStyle::IndexStyle istyle,
00252                             const LuPixelPoint& parentOrigin )
00253 {
00254     LuPixelPoint myPos( parentOrigin.x() + getX(), parentOrigin.y() + getY() );
00255     // There might be zero sized elements that still want to be drawn at least
00256     // in edit mode. (EmptyElement)
00257     //if ( !LuPixelRect( myPos.x(), myPos.y(), getWidth(), getHeight() ).intersects( r ) )
00258     //    return;
00259 
00260     if (!isEmpty()) {
00261         QPtrListIterator<BasicElement> it( children );
00262         for ( ; it.current(); ) {
00263             BasicElement* child = it.current();
00264             if (!child->isInvisible()) {
00265                 child->draw(painter, r, context, tstyle, istyle, myPos);
00266 
00267                 // Each starting element draws the whole token
00268                 // This only concerns TextElements.
00269                 ElementType* token = child->getElementType();
00270                 if ( token != 0 ) {
00271                     it += token->end() - token->start();
00272                 }
00273                 else {
00274                     ++it;
00275                 }
00276             }
00277             else {
00278                 ++it;
00279             }
00280         }
00281     }
00282     else {
00283         drawEmptyRect( painter, context, myPos );
00284     }
00285     // Debug
00286     //painter.setPen(Qt::green);
00287     //painter.drawRect(parentOrigin.x() + getX(), parentOrigin.y() + getY(),
00288     //                 getWidth(), getHeight());
00289 //     painter.drawLine( context.layoutUnitToPixelX( parentOrigin.x() + getX() ),
00290 //                       context.layoutUnitToPixelY( parentOrigin.y() + getY() + axis( context, tstyle ) ),
00291 //                       context.layoutUnitToPixelX( parentOrigin.x() + getX() + getWidth() ),
00292 //                       context.layoutUnitToPixelY( parentOrigin.y() + getY() + axis( context, tstyle ) ) );
00293 //     painter.setPen(Qt::red);
00294 //     painter.drawLine( context.layoutUnitToPixelX( parentOrigin.x() + getX() ),
00295 //                       context.layoutUnitToPixelY( parentOrigin.y() + getY() + getBaseline() ),
00296 //                       context.layoutUnitToPixelX( parentOrigin.x() + getX() + getWidth() ),
00297 //                       context.layoutUnitToPixelY( parentOrigin.y() + getY() + getBaseline() ) );
00298 }
00299 
00300 
00301 void SequenceElement::dispatchFontCommand( FontCommand* cmd )
00302 {
00303     QPtrListIterator<BasicElement> it( children );
00304     for ( ; it.current(); ++it ) {
00305         BasicElement* child = it.current();
00306         child->dispatchFontCommand( cmd );
00307     }
00308 }
00309 
00310 
00311 void SequenceElement::drawEmptyRect( QPainter& painter, const ContextStyle& context,
00312                                      const LuPixelPoint& upperLeft )
00313 {
00314     if ( context.edit() ) {
00315         painter.setBrush(Qt::NoBrush);
00316         painter.setPen( QPen( context.getEmptyColor(),
00317                               context.layoutUnitToPixelX( context.getLineWidth() ) ) );
00318         painter.drawRect( context.layoutUnitToPixelX( upperLeft.x() ),
00319                           context.layoutUnitToPixelY( upperLeft.y() ),
00320                           context.layoutUnitToPixelX( getWidth() ),
00321                           context.layoutUnitToPixelY( getHeight() ) );
00322     }
00323 }
00324 
00325 void SequenceElement::calcCursorSize( const ContextStyle& context,
00326                                       FormulaCursor* cursor, bool smallCursor )
00327 {
00328     LuPixelPoint point = widgetPos();
00329     uint pos = cursor->getPos();
00330 
00331     luPixel posX = getChildPosition( context, pos );
00332     luPixel height = getHeight();
00333 
00334     luPixel unitX = context.ptToLayoutUnitPixX( 1 );
00335     luPixel unitY = context.ptToLayoutUnitPixY( 1 );
00336 
00337     // Here are those evil constants that describe the cursor size.
00338 
00339     if ( cursor->isSelection() ) {
00340         uint mark = cursor->getMark();
00341         luPixel markX = getChildPosition( context, mark );
00342         luPixel x = QMIN(posX, markX);
00343         luPixel width = abs(posX - markX);
00344 
00345         if ( smallCursor ) {
00346             cursor->cursorSize.setRect( point.x()+x, point.y(), width, height );
00347         }
00348         else {
00349             cursor->cursorSize.setRect( point.x()+x, point.y() - 2*unitY,
00350                                         width + unitX, height + 4*unitY );
00351         }
00352     }
00353     else {
00354         if ( smallCursor ) {
00355             cursor->cursorSize.setRect( point.x()+posX, point.y(),
00356                                         unitX, height );
00357         }
00358         else {
00359             cursor->cursorSize.setRect( point.x(), point.y() - 2*unitY,
00360                                         getWidth() + unitX, height + 4*unitY );
00361         }
00362     }
00363 
00364     cursor->cursorPoint.setX( point.x()+posX );
00365     cursor->cursorPoint.setY( point.y()+getHeight()/2 );
00366 }
00367 
00368 
00372 void SequenceElement::drawCursor( QPainter& painter, const ContextStyle& context,
00373                                   FormulaCursor* cursor, bool smallCursor )
00374 {
00375     painter.setRasterOp( Qt::XorROP );
00376     if ( cursor->isSelection() ) {
00377         const LuPixelRect& r = cursor->cursorSize;
00378         painter.fillRect( context.layoutUnitToPixelX( r.x() ),
00379                           context.layoutUnitToPixelY( r.y() ),
00380                           context.layoutUnitToPixelX( r.width() ),
00381                           context.layoutUnitToPixelY( r.height() ),
00382                           Qt::white );
00383     }
00384     else {
00385         painter.setPen( QPen( Qt::white,
00386                               context.layoutUnitToPixelX( context.getLineWidth()/2 ) ) );
00387         const LuPixelPoint& point = cursor->getCursorPoint();
00388         const LuPixelRect& size = cursor->getCursorSize();
00389         if ( smallCursor ) {
00390             painter.drawLine( context.layoutUnitToPixelX( point.x() ),
00391                               context.layoutUnitToPixelY( size.top() ),
00392                               context.layoutUnitToPixelX( point.x() ),
00393                               context.layoutUnitToPixelY( size.bottom() )-1 );
00394         }
00395         else {
00396             painter.drawLine( context.layoutUnitToPixelX( point.x() ),
00397                               context.layoutUnitToPixelY( size.top() ),
00398                               context.layoutUnitToPixelX( point.x() ),
00399                               context.layoutUnitToPixelY( size.bottom() )-1 );
00400             painter.drawLine( context.layoutUnitToPixelX( size.left() ),
00401                               context.layoutUnitToPixelY( size.bottom() )-1,
00402                               context.layoutUnitToPixelX( size.right() )-1,
00403                               context.layoutUnitToPixelY( size.bottom() )-1 );
00404         }
00405     }
00406     // This might be wrong but probably isn't.
00407     painter.setRasterOp( Qt::CopyROP );
00408 }
00409 
00410 
00411 luPixel SequenceElement::getChildPosition( const ContextStyle& context, uint child )
00412 {
00413     if (child < children.count()) {
00414         return children.at(child)->getX();
00415     }
00416     else {
00417         if (children.count() > 0) {
00418             return children.at(child-1)->getX() + children.at(child-1)->getWidth();
00419         }
00420         else {
00421             return context.ptToLayoutUnitPixX( 2 );
00422         }
00423     }
00424 }
00425 
00426 
00427 // navigation
00428 //
00429 // The elements are responsible to handle cursor movement themselves.
00430 // To do this they need to know the direction the cursor moves and
00431 // the element it comes from.
00432 //
00433 // The cursor might be in normal or in selection mode.
00434 
00440 void SequenceElement::moveLeft(FormulaCursor* cursor, BasicElement* from)
00441 {
00442     // Our parent asks us for a cursor position. Found.
00443     if (from == getParent()) {
00444         cursor->setTo(this, children.count());
00445         from->entered( this );
00446     }
00447 
00448     // We already owned the cursor. Ask next child then.
00449     else if (from == this) {
00450         if (cursor->getPos() > 0) {
00451             if (cursor->isSelectionMode()) {
00452                 cursor->setTo(this, cursor->getPos()-1);
00453 
00454                 // invisible elements are not visible so we move on.
00455                 if (children.at(cursor->getPos())->isInvisible()) {
00456                     moveLeft(cursor, this);
00457                 }
00458             }
00459             else {
00460                 children.at(cursor->getPos()-1)->moveLeft(cursor, this);
00461             }
00462         }
00463         else {
00464             // Needed because FormulaElement derives this.
00465             if (getParent() != 0) {
00466                 getParent()->moveLeft(cursor, this);
00467             }
00468             else {
00469                 formula()->moveOutLeft( cursor );
00470             }
00471         }
00472     }
00473 
00474     // The cursor came from one of our children or
00475     // something is wrong.
00476     else {
00477         int fromPos = children.find(from);
00478         cursor->setTo(this, fromPos);
00479         if (cursor->isSelectionMode()) {
00480             cursor->setMark(fromPos+1);
00481         }
00482 
00483         // invisible elements are not visible so we move on.
00484         if (from->isInvisible()) {
00485             moveLeft(cursor, this);
00486         }
00487         formula()->tell( "" );
00488     }
00489 }
00490 
00496 void SequenceElement::moveRight(FormulaCursor* cursor, BasicElement* from)
00497 {
00498     // Our parent asks us for a cursor position. Found.
00499     if (from == getParent()) {
00500         cursor->setTo(this, 0);
00501         from->entered( this );
00502     }
00503 
00504     // We already owned the cursor. Ask next child then.
00505     else if (from == this) {
00506         uint pos = cursor->getPos();
00507         if (pos < children.count()) {
00508             if (cursor->isSelectionMode()) {
00509                 cursor->setTo(this, pos+1);
00510 
00511                 // invisible elements are not visible so we move on.
00512                 if (children.at(pos)->isInvisible()) {
00513                     moveRight(cursor, this);
00514                 }
00515             }
00516             else {
00517                 children.at(pos)->moveRight(cursor, this);
00518             }
00519         }
00520         else {
00521             // Needed because FormulaElement derives this.
00522             if (getParent() != 0) {
00523                 getParent()->moveRight(cursor, this);
00524             }
00525             else {
00526                 formula()->moveOutRight( cursor );
00527             }
00528         }
00529     }
00530 
00531     // The cursor came from one of our children or
00532     // something is wrong.
00533     else {
00534         int fromPos = children.find(from);
00535         cursor->setTo(this, fromPos+1);
00536         if (cursor->isSelectionMode()) {
00537             cursor->setMark(fromPos);
00538         }
00539 
00540         // invisible elements are not visible so we move on.
00541         if (from->isInvisible()) {
00542             moveRight(cursor, this);
00543         }
00544         formula()->tell( "" );
00545     }
00546 }
00547 
00548 
00549 void SequenceElement::moveWordLeft(FormulaCursor* cursor)
00550 {
00551     uint pos = cursor->getPos();
00552     if (pos > 0) {
00553         ElementType* type = children.at(pos-1)->getElementType();
00554         if (type != 0) {
00555             cursor->setTo(this, type->start());
00556         }
00557     }
00558     else {
00559         moveLeft(cursor, this);
00560     }
00561 }
00562 
00563 
00564 void SequenceElement::moveWordRight(FormulaCursor* cursor)
00565 {
00566     uint pos = cursor->getPos();
00567     if (pos < children.count()) {
00568         ElementType* type = children.at(pos)->getElementType();
00569         if (type != 0) {
00570             cursor->setTo(this, type->end());
00571         }
00572     }
00573     else {
00574         moveRight(cursor, this);
00575     }
00576 }
00577 
00578 
00584 void SequenceElement::moveUp(FormulaCursor* cursor, BasicElement* from)
00585 {
00586     if (from == getParent()) {
00587         moveRight(cursor, this);
00588     }
00589     else {
00590         if (getParent() != 0) {
00591             getParent()->moveUp(cursor, this);
00592         }
00593         else {
00594             formula()->moveOutAbove( cursor );
00595         }
00596     }
00597 }
00598 
00604 void SequenceElement::moveDown(FormulaCursor* cursor, BasicElement* from)
00605 {
00606     if (from == getParent()) {
00607         moveRight(cursor, this);
00608     }
00609     else {
00610         if (getParent() != 0) {
00611             getParent()->moveDown(cursor, this);
00612         }
00613         else {
00614             formula()->moveOutBelow( cursor );
00615         }
00616     }
00617 }
00618 
00623 void SequenceElement::moveHome(FormulaCursor* cursor)
00624 {
00625     if (cursor->isSelectionMode()) {
00626         BasicElement* element = cursor->getElement();
00627         if (element != this) {
00628             while (element->getParent() != this) {
00629                 element = element->getParent();
00630             }
00631             cursor->setMark(children.find(element)+1);
00632         }
00633     }
00634     cursor->setTo(this, 0);
00635 }
00636 
00641 void SequenceElement::moveEnd(FormulaCursor* cursor)
00642 {
00643     if (cursor->isSelectionMode()) {
00644         BasicElement* element = cursor->getElement();
00645         if (element != this) {
00646             while (element->getParent() != this) {
00647                 element = element->getParent();
00648                 if (element == 0) {
00649                     cursor->setMark(children.count());
00650                     break;
00651                 }
00652             }
00653             if (element != 0) {
00654                 cursor->setMark(children.find(element));
00655             }
00656         }
00657     }
00658     cursor->setTo(this, children.count());
00659 }
00660 
00665 void SequenceElement::goInside(FormulaCursor* cursor)
00666 {
00667     cursor->setSelection(false);
00668     cursor->setTo(this, 0);
00669 }
00670 
00671 
00672 // children
00673 
00681 // void SequenceElement::removeChild(FormulaCursor* cursor, BasicElement* child)
00682 // {
00683 //     int pos = children.find(child);
00684 //     formula()->elementRemoval(child, pos);
00685 //     cursor->setTo(this, pos);
00686 //     children.remove(pos);
00687 //     /*
00688 //         if len(self.children) == 0:
00689 //             if self.parent != None:
00690 //                 self.parent.removeChild(cursor, self)
00691 //                 return
00692 //     */
00693 //     formula()->changed();
00694 // }
00695 
00696 
00704 void SequenceElement::insert(FormulaCursor* cursor,
00705                              QPtrList<BasicElement>& newChildren,
00706                              Direction direction)
00707 {
00708     int pos = cursor->getPos();
00709     uint count = newChildren.count();
00710     for (uint i = 0; i < count; i++) {
00711         BasicElement* child = newChildren.take(0);
00712         child->setParent(this);
00713         children.insert(pos+i, child);
00714     }
00715     if (direction == beforeCursor) {
00716         cursor->setTo(this, pos+count, pos);
00717     }
00718     else {
00719         cursor->setTo(this, pos, pos+count);
00720     }
00721 
00722     formula()->changed();
00723     parse();
00724 }
00725 
00726 
00733 void SequenceElement::remove(FormulaCursor* cursor,
00734                              QPtrList<BasicElement>& removedChildren,
00735                              Direction direction)
00736 {
00737     if (cursor->isSelection()) {
00738         int from = cursor->getSelectionStart();
00739         int to = cursor->getSelectionEnd();
00740         for (int i = from; i < to; i++) {
00741             removeChild(removedChildren, from);
00742         }
00743         cursor->setTo(this, from);
00744         cursor->setSelection(false);
00745     }
00746     else {
00747         if (direction == beforeCursor) {
00748             int pos = cursor->getPos() - 1;
00749             if (pos >= 0) {
00750                 while (pos >= 0) {
00751                     BasicElement* child = children.at(pos);
00752                     formula()->elementRemoval(child);
00753                     children.take(pos);
00754                     removedChildren.prepend(child);
00755                     if (!child->isInvisible()) {
00756                         break;
00757                     }
00758                     pos--;
00759                 }
00760                 cursor->setTo(this, pos);
00761                 formula()->changed();
00762             }
00763         }
00764         else {
00765             uint pos = cursor->getPos();
00766             if (pos < children.count()) {
00767                 while (pos < children.count()) {
00768                     BasicElement* child = children.at(pos);
00769                     formula()->elementRemoval(child);
00770                     children.take(pos);
00771                     removedChildren.append(child);
00772                     if (!child->isInvisible()) {
00773                         break;
00774                     }
00775                 }
00776                 // It is necessary to set the cursor to its old
00777                 // position because it got a notification and
00778                 // moved to the beginning of this sequence.
00779                 cursor->setTo(this, pos);
00780                 formula()->changed();
00781             }
00782         }
00783     }
00784     parse();
00785 }
00786 
00787 
00791 void SequenceElement::removeChild(QPtrList<BasicElement>& removedChildren, int pos)
00792 {
00793     BasicElement* child = children.at(pos);
00794     formula()->elementRemoval(child);
00795     children.take(pos);
00796     removedChildren.append(child);
00797     //cerr << *removedChildren.at(0) << endl;
00798     formula()->changed();
00799 }
00800 
00801 
00806 void SequenceElement::normalize(FormulaCursor* cursor, Direction)
00807 {
00808     cursor->setSelection(false);
00809 }
00810 
00811 
00816 BasicElement* SequenceElement::getChild( FormulaCursor* cursor, Direction direction )
00817 {
00818     if ( direction == beforeCursor ) {
00819         if ( cursor->getPos() > 0 ) {
00820             return children.at( cursor->getPos() - 1 );
00821         }
00822     }
00823     else {
00824         if ( cursor->getPos() < qRound( children.count() ) ) {
00825             return children.at( cursor->getPos() );
00826         }
00827     }
00828     return 0;
00829 }
00830 
00831 
00836 void SequenceElement::selectChild(FormulaCursor* cursor, BasicElement* child)
00837 {
00838     int pos = children.find(child);
00839     if (pos > -1) {
00840         cursor->setTo(this, pos+1, pos);
00841     }
00842 }
00843 
00844 void SequenceElement::childWillVanish(FormulaCursor* cursor, BasicElement* child)
00845 {
00846     int childPos = children.find(child);
00847     if (childPos > -1) {
00848         int pos = cursor->getPos();
00849         if (pos > childPos) {
00850             pos--;
00851         }
00852         int mark = cursor->getMark();
00853         if (mark > childPos) {
00854             mark--;
00855         }
00856         cursor->setTo(this, pos, mark);
00857     }
00858 }
00859 
00860 
00864 void SequenceElement::selectAllChildren(FormulaCursor* cursor)
00865 {
00866     cursor->setTo(this, children.count(), 0);
00867 }
00868 
00869 bool SequenceElement::onlyTextSelected( FormulaCursor* cursor )
00870 {
00871     if ( cursor->isSelection() ) {
00872         uint from = QMIN( cursor->getPos(), cursor->getMark() );
00873         uint to = QMAX( cursor->getPos(), cursor->getMark() );
00874         for ( uint i = from; i < to; i++ ) {
00875             BasicElement* element = getChild( i );
00876             if ( element->getCharacter() == QChar::null ) {
00877                 return false;
00878             }
00879         }
00880     }
00881     return true;
00882 }
00883 
00884 
00885 KCommand* SequenceElement::buildCommand( Container* container, Request* request )
00886 {
00887     FormulaCursor* cursor = container->activeCursor();
00888     if ( cursor->isReadOnly() ) {
00889         formula()->tell( i18n( "write protection" ) );
00890         return 0;
00891     }
00892 
00893     switch ( *request ) {
00894     case req_addText: {
00895         KFCReplace* command = new KFCReplace( i18n("Add Text"), container );
00896         TextRequest* tr = static_cast<TextRequest*>( request );
00897         for ( uint i = 0; i < tr->text().length(); i++ ) {
00898             command->addElement( creationStrategy->createTextElement( tr->text()[i] ) );
00899         }
00900         return command;
00901     }
00902     case req_addTextChar: {
00903         KFCReplace* command = new KFCReplace( i18n("Add Text"), container );
00904         TextCharRequest* tr = static_cast<TextCharRequest*>( request );
00905         TextElement* element = creationStrategy->createTextElement( tr->ch(), tr->isSymbol() );
00906         command->addElement( element );
00907         return command;
00908     }
00909     case req_addEmptyBox: {
00910         EmptyElement* element = creationStrategy->createEmptyElement();
00911         if ( element != 0 ) {
00912             KFCReplace* command = new KFCReplace( i18n("Add Empty Box"), container );
00913             command->addElement( element );
00914             return command;
00915         }
00916         break;
00917     }
00918     case req_addNameSequence:
00919         if ( onlyTextSelected( container->activeCursor() ) ) {
00920             NameSequence* nameSequence = creationStrategy->createNameSequence();
00921             if ( nameSequence != 0 ) {
00922                 KFCAddReplacing* command = new KFCAddReplacing( i18n( "Add Name" ), container );
00923                 command->setElement( nameSequence );
00924                 return command;
00925             }
00926         }
00927         break;
00928     case req_addBracket: {
00929         BracketRequest* br = static_cast<BracketRequest*>( request );
00930         BracketElement* bracketElement =
00931             creationStrategy->createBracketElement( br->left(), br->right() );
00932         if ( bracketElement != 0 ) {
00933             KFCAddReplacing* command = new KFCAddReplacing(i18n("Add Bracket"), container);
00934             command->setElement( bracketElement );
00935             return command;
00936         }
00937         break;
00938     }
00939     case req_addOverline: {
00940         OverlineElement* overline = creationStrategy->createOverlineElement();
00941         if ( overline != 0 ) {
00942             KFCAddReplacing* command = new KFCAddReplacing(i18n("Add Overline"), container);
00943             command->setElement( overline );
00944             return command;
00945         }
00946         break;
00947     }
00948     case req_addUnderline: {
00949         UnderlineElement* underline = creationStrategy->createUnderlineElement();
00950         if ( underline != 0 ) {
00951             KFCAddReplacing* command = new KFCAddReplacing(i18n("Add Underline"), container);
00952             command->setElement( underline );
00953             return command;
00954         }
00955         break;
00956     }
00957     case req_addMultiline: {
00958         MultilineElement* multiline = creationStrategy->createMultilineElement();
00959         if ( multiline != 0 ) {
00960             KFCAddReplacing* command = new KFCAddReplacing(i18n("Add Multiline"), container);
00961             command->setElement( multiline );
00962             return command;
00963         }
00964         break;
00965     }
00966     case req_addSpace: {
00967         SpaceRequest* sr = static_cast<SpaceRequest*>( request );
00968         SpaceElement* element = creationStrategy->createSpaceElement( sr->space() );
00969         if ( element != 0 ) {
00970             KFCReplace* command = new KFCReplace( i18n("Add Space"), container );
00971             command->addElement( element );
00972             return command;
00973         }
00974         break;
00975     }
00976     case req_addFraction: {
00977         FractionElement* fraction = creationStrategy->createFractionElement();
00978         if ( fraction != 0 ) {
00979             KFCAddReplacing* command = new KFCAddReplacing(i18n("Add Fraction"), container);
00980             command->setElement( fraction );
00981             return command;
00982         }
00983         break;
00984     }
00985     case req_addRoot: {
00986         RootElement* root = creationStrategy->createRootElement();
00987         if ( root != 0 ) {
00988             KFCAddReplacing* command = new KFCAddReplacing(i18n("Add Root"), container);
00989             command->setElement( root );
00990             return command;
00991         }
00992         break;
00993     }
00994     case req_addSymbol: {
00995         SymbolRequest* sr = static_cast<SymbolRequest*>( request );
00996         SymbolElement* symbol = creationStrategy->createSymbolElement( sr->type() );
00997         if ( symbol != 0 ) {
00998             KFCAddReplacing* command = new KFCAddReplacing( i18n( "Add Symbol" ), container );
00999             command->setElement( symbol );
01000             return command;
01001         }
01002         break;
01003     }
01004     case req_addOneByTwoMatrix: {
01005         FractionElement* element = creationStrategy->createFractionElement();
01006         if ( element != 0 ) {
01007             KFCAddReplacing* command = new KFCAddReplacing( i18n("Add 1x2 Matrix"), container );
01008             element->showLine(false);
01009             command->setElement(element);
01010             return command;
01011         }
01012     }
01013     case req_addMatrix: {
01014         MatrixRequest* mr = static_cast<MatrixRequest*>( request );
01015         uint rows = mr->rows(), cols = mr->columns();
01016         if ( ( rows == 0 ) || ( cols == 0 ) ) {
01017             MatrixDialog* dialog = new MatrixDialog( 0 );
01018             if ( dialog->exec() ) {
01019                 rows = dialog->h;
01020                 cols = dialog->w;
01021             }
01022             delete dialog;
01023         }
01024 
01025         if ( ( rows != 0 ) && ( cols != 0 ) ) {
01026             KFCAddReplacing* command = new KFCAddReplacing( i18n( "Add Matrix" ), container );
01027             command->setElement( creationStrategy->createMatrixElement( rows, cols ) );
01028             return command;
01029         }
01030         else
01031             return 0L;
01032     }
01033     case req_addIndex: {
01034         if ( cursor->getPos() > 0 && !cursor->isSelection() ) {
01035             IndexElement* element =
01036                 dynamic_cast<IndexElement*>( children.at( cursor->getPos()-1 ) );
01037             if ( element != 0 ) {
01038                 element->getMainChild()->goInside( cursor );
01039                 return element->getMainChild()->buildCommand( container, request );
01040             }
01041         }
01042         IndexElement* element = creationStrategy->createIndexElement();
01043         if ( element != 0 ) {
01044             if ( !cursor->isSelection() ) {
01045                 cursor->moveLeft( SelectMovement | WordMovement );
01046             }
01047             IndexRequest* ir = static_cast<IndexRequest*>( request );
01048             KFCAddIndex* command = new KFCAddIndex( container, element,
01049                                                     element->getIndex( ir->index() ) );
01050             return command;
01051         }
01052         break;
01053     }
01054     case req_removeEnclosing: {
01055         if ( !cursor->isSelection() ) {
01056             DirectedRemove* dr = static_cast<DirectedRemove*>( request );
01057             KFCRemoveEnclosing* command = new KFCRemoveEnclosing( container, dr->direction() );
01058             return command;
01059         }
01060     }
01061     case req_remove: {
01062         SequenceElement* sequence = cursor->normal();
01063         if ( sequence &&
01064              ( sequence == sequence->formula() ) &&
01065              ( sequence->countChildren() == 0 ) ) {
01066             sequence->formula()->removeFormula( cursor );
01067             return 0;
01068         }
01069         else {
01070             DirectedRemove* dr = static_cast<DirectedRemove*>( request );
01071 
01072             // empty removes are not legal!
01073             if ( !cursor->isSelection() ) {
01074                 if ( countChildren() > 0 ) {
01075                     if ( ( cursor->getPos() == 0 ) && ( dr->direction() == beforeCursor ) ) {
01076                         return 0;
01077                     }
01078                     if ( ( cursor->getPos() == countChildren() ) && ( dr->direction() == afterCursor ) ) {
01079                         return 0;
01080                     }
01081                 }
01082                 else if ( getParent() == 0 ) {
01083                     return 0;
01084                 }
01085             }
01086 
01087             KFCRemove* command = new KFCRemove( container, dr->direction() );
01088             return command;
01089         }
01090     }
01091     case req_compactExpression: {
01092         cursor->moveEnd();
01093         cursor->moveRight();
01094         formula()->cursorHasMoved( cursor );
01095         break;
01096     }
01097     case req_makeGreek: {
01098         TextElement* element = cursor->getActiveTextElement();
01099         if ((element != 0) && !element->isSymbol()) {
01100             cursor->selectActiveElement();
01101             const SymbolTable& table = container->document()->getSymbolTable();
01102             if (table.greekLetters().find(element->getCharacter()) != -1) {
01103                 KFCReplace* command = new KFCReplace( i18n( "Change Char to Symbol" ), container );
01104                 TextElement* symbol = creationStrategy->createTextElement( table.unicodeFromSymbolFont( element->getCharacter() ), true );
01105                 command->addElement( symbol );
01106                 return command;
01107             }
01108             cursor->setSelection( false );
01109         }
01110         break;
01111     }
01112     case req_paste:
01113     case req_copy:
01114     case req_cut:
01115         break;
01116     case req_formatBold:
01117     case req_formatItalic: {
01118         if ( cursor->isSelection() ) {
01119             CharStyleRequest* csr = static_cast<CharStyleRequest*>( request );
01120             CharStyle cs = normalChar;
01121             if ( csr->bold() ) cs = static_cast<CharStyle>( cs | boldChar );
01122             if ( csr->italic() ) cs = static_cast<CharStyle>( cs | italicChar );
01123             CharStyleCommand* cmd = new CharStyleCommand( cs, i18n( "Change Char Style" ), container );
01124             int end = cursor->getSelectionEnd();
01125             for ( int i = cursor->getSelectionStart(); i<end; ++i ) {
01126                 cmd->addElement( children.at( i ) );
01127             }
01128             return cmd;
01129         }
01130         break;
01131     }
01132     case req_formatFamily: {
01133         if ( cursor->isSelection() ) {
01134             CharFamilyRequest* cfr = static_cast<CharFamilyRequest*>( request );
01135             CharFamily cf = cfr->charFamily();
01136             CharFamilyCommand* cmd = new CharFamilyCommand( cf, i18n( "Change Char Family" ), container );
01137             int end = cursor->getSelectionEnd();
01138             for ( int i = cursor->getSelectionStart(); i<end; ++i ) {
01139                 cmd->addElement( children.at( i ) );
01140             }
01141             return cmd;
01142         }
01143         break;
01144     }
01145     default:
01146         break;
01147     }
01148     return 0;
01149 }
01150 
01151 
01152 KCommand* SequenceElement::input( Container* container, QKeyEvent* event )
01153 {
01154     QChar ch = event->text().at( 0 );
01155     if ( ch.isPrint() ) {
01156         return input( container, ch );
01157     }
01158     else {
01159         int action = event->key();
01160         int state = event->state();
01161         MoveFlag flag = movementFlag(state);
01162 
01163     switch ( action ) {
01164         case Qt::Key_BackSpace: {
01165             DirectedRemove r( req_remove, beforeCursor );
01166             return buildCommand( container, &r );
01167         }
01168         case Qt::Key_Delete: {
01169             DirectedRemove r( req_remove, afterCursor );
01170             return buildCommand( container, &r );
01171         }
01172     case Qt::Key_Left: {
01173             FormulaCursor* cursor = container->activeCursor();
01174             cursor->moveLeft( flag );
01175             formula()->cursorHasMoved( cursor );
01176             break;
01177         }
01178         case Qt::Key_Right: {
01179             FormulaCursor* cursor = container->activeCursor();
01180             cursor->moveRight( flag );
01181             formula()->cursorHasMoved( cursor );
01182             break;
01183         }
01184         case Qt::Key_Up: {
01185             FormulaCursor* cursor = container->activeCursor();
01186             cursor->moveUp( flag );
01187             formula()->cursorHasMoved( cursor );
01188             break;
01189         }
01190         case Qt::Key_Down: {
01191             FormulaCursor* cursor = container->activeCursor();
01192             cursor->moveDown( flag );
01193             formula()->cursorHasMoved( cursor );
01194             break;
01195         }
01196         case Qt::Key_Home: {
01197             FormulaCursor* cursor = container->activeCursor();
01198             cursor->moveHome( flag );
01199             formula()->cursorHasMoved( cursor );
01200             break;
01201         }
01202         case Qt::Key_End: {
01203             FormulaCursor* cursor = container->activeCursor();
01204             cursor->moveEnd( flag );
01205             formula()->cursorHasMoved( cursor );
01206             break;
01207         }
01208         default:
01209             if ( state & Qt::ControlButton ) {
01210                 switch ( event->key() ) {
01211                 case Qt::Key_AsciiCircum: {
01212                     IndexRequest r( upperLeftPos );
01213                     return buildCommand( container, &r );
01214                 }
01215                 case Qt::Key_Underscore: {
01216                     IndexRequest r( lowerLeftPos );
01217                     return buildCommand( container, &r );
01218                 }
01219                 default:
01220                     break;
01221                 }
01222             }
01223         }
01224     }
01225     return 0;
01226 }
01227 
01228 
01229 KCommand* SequenceElement::input( Container* container, QChar ch )
01230 {
01231     int unicode = ch.unicode();
01232     switch (unicode) {
01233     case '(': {
01234         BracketRequest r( container->document()->leftBracketChar(),
01235                           container->document()->rightBracketChar() );
01236         singlePipe = true;
01237         return buildCommand( container, &r );
01238     }
01239     case '[': {
01240         BracketRequest r( LeftSquareBracket, RightSquareBracket );
01241         singlePipe = true;
01242         return buildCommand( container, &r );
01243     }
01244     case '{': {
01245         BracketRequest r( LeftCurlyBracket, RightCurlyBracket );
01246         singlePipe = true;
01247         return buildCommand( container, &r );
01248     }
01249     case '|': { 
01250         if (!singlePipe) { // We have had 2 '|' in a row so we want brackets
01251 
01252           DirectedRemove rDelete( req_remove, beforeCursor ); //Delete the previous '|' we dont need it any more
01253           KCommand* command = buildCommand( container, &rDelete );
01254           command->execute();
01255           
01256           BracketRequest rBracket( LeftLineBracket , RightLineBracket);
01257           singlePipe = true;  //the next '|' will be a single pipe again
01258           return buildCommand( container, &rBracket );    
01259         }
01260         else { // We really do only want 1 '|'
01261           TextCharRequest r(ch);
01262 
01263           //in case another '|' character is entered right after this one, '| |' brackets are made; see above
01264           singlePipe = false;
01265 
01266           return buildCommand( container, &r );   
01267         }
01268     }
01269     case '^': {
01270         IndexRequest r( upperRightPos );
01271         singlePipe = true;
01272         return buildCommand( container, &r );
01273     }
01274     case '_': {
01275         IndexRequest r( lowerRightPos );
01276         singlePipe = true;
01277         return buildCommand( container, &r );
01278     }
01279     case ' ': {
01280         Request r( req_compactExpression );
01281         singlePipe = true;
01282         return buildCommand( container, &r );
01283     }
01284     case '}': {
01285         Request r( req_addEmptyBox );
01286         singlePipe = true;
01287         return buildCommand( container, &r );
01288     }
01289     case ']':
01290     case ')':
01291         singlePipe = true; 
01292         break;
01293     case '\\': {
01294         Request r( req_addNameSequence );
01295         singlePipe = true;
01296         return buildCommand( container, &r );
01297     }
01298     default: {
01299         TextCharRequest r( ch );
01300         singlePipe = true;
01301         return buildCommand( container, &r );
01302     }
01303     }
01304     return 0;
01305 }
01306 
01310 void SequenceElement::getChildrenDom( QDomDocument& doc, QDomElement elem,
01311                                      uint from, uint to)
01312 {
01313     for (uint i = from; i < to; i++) {
01314         QDomElement tmpEleDom=children.at(i)->getElementDom(doc);
01315     elem.appendChild(tmpEleDom);
01316     }
01317 }
01318 
01319 
01325 bool SequenceElement::buildChildrenFromDom(QPtrList<BasicElement>& list, QDomNode n)
01326 {
01327     while (!n.isNull()) {
01328         if (n.isElement()) {
01329             QDomElement e = n.toElement();
01330             BasicElement* child = 0;
01331             QString tag = e.tagName().upper();
01332 
01333             child = createElement(tag);
01334             if (child != 0) {
01335                 child->setParent(this);
01336                 if (child->buildFromDom(e)) {
01337                     list.append(child);
01338                 }
01339                 else {
01340                     delete child;
01341                     return false;
01342                 }
01343             }
01344             else {
01345                 return false;
01346             }
01347         }
01348         n = n.nextSibling();
01349     }
01350     parse();
01351     return true;
01352 }
01353 
01354 
01355 BasicElement* SequenceElement::createElement( QString type )
01356 {
01357     return creationStrategy->createElement( type );
01358 }
01359 
01363 void SequenceElement::writeDom(QDomElement element)
01364 {
01365     BasicElement::writeDom(element);
01366 
01367     uint count = children.count();
01368     QDomDocument doc = element.ownerDocument();
01369     getChildrenDom(doc, element, 0, count);
01370 }
01371 
01376 bool SequenceElement::readAttributesFromDom(QDomElement element)
01377 {
01378     if (!BasicElement::readAttributesFromDom(element)) {
01379         return false;
01380     }
01381     return true;
01382 }
01383 
01389 bool SequenceElement::readContentFromDom(QDomNode& node)
01390 {
01391     if (!BasicElement::readContentFromDom(node)) {
01392         return false;
01393     }
01394 
01395     return buildChildrenFromDom(children, node);
01396 }
01397 
01398 
01399 void SequenceElement::parse()
01400 {
01401     delete parseTree;
01402 
01403     textSequence = true;
01404     for (BasicElement* element = children.first();
01405          element != 0;
01406          element = children.next()) {
01407 
01408         // Those types are gone. Make sure they won't
01409         // be used.
01410         element->setElementType(0);
01411 
01412         if (element->getCharacter().isNull()) {
01413             textSequence = false;
01414         }
01415     }
01416 
01417     const SymbolTable& symbols = formula()->getSymbolTable();
01418     SequenceParser parser(symbols);
01419     parseTree = parser.parse(children);
01420 
01421     // With the IndexElement dynamically changing its text/non-text
01422     // behaviour we need to reparse your parent, too. Hacky!
01423     BasicElement* p = getParent();
01424     if ( p != 0 ) {
01425         SequenceElement* seq = dynamic_cast<SequenceElement*>( p->getParent() );
01426         if ( seq != 0 ) {
01427             seq->parse();
01428         }
01429     }
01430     // debug
01431     //parseTree->output();
01432 }
01433 
01434 
01435 bool SequenceElement::isFirstOfToken( BasicElement* child )
01436 {
01437     return ( child->getElementType() != 0 ) && isChildNumber( child->getElementType()->start(), child );
01438 }
01439 
01440 
01441 QString SequenceElement::toLatex()
01442 {
01443     QString content;
01444     uint count = children.count();
01445     for ( uint i = 0; i < count; i++ ) {
01446         BasicElement* child = children.at( i );
01447 //         if ( isFirstOfToken( child ) ) {
01448 //             content += "";
01449 //         }
01450         content += child->toLatex();
01451     }
01452     return content;
01453 }
01454 
01455 
01456 QString SequenceElement::formulaString()
01457 {
01458     QString content;
01459     uint count = children.count();
01460     for ( uint i = 0; i < count; i++ ) {
01461         BasicElement* child = children.at( i );
01462         //if ( isFirstOfToken( child ) ) {
01463         //    content += " ";
01464         //}
01465         content += child->formulaString();
01466     }
01467     return content;
01468 }
01469 
01470 
01471 void SequenceElement::writeMathML( QDomDocument& doc, QDomNode parent, bool oasisFormat )
01472 {
01473     QDomElement de = doc.createElement( oasisFormat ? "math:mrow" : "mrow" );
01474 
01475     BasicElement* last = children.last();
01476     if ( last != 0 ) {
01477         // Create a list (right order!)
01478         QPtrList<ElementType> tokenList;
01479         ElementType* token = last->getElementType();
01480         while ( token != 0 ) {
01481             // Add to the list.
01482             tokenList.prepend( token );
01483             token = token->getPrev();
01484         }
01485 
01486         if ( tokenList.count() == 1 ) {
01487             tokenList.first()->saveMathML( this, doc, parent.toElement(), oasisFormat );
01488             return;
01489         }
01490 
01491         for ( uint i = 0; i < tokenList.count(); ++i ) {
01492             tokenList.at( i )->saveMathML( this, doc, de, oasisFormat );
01493         }
01494     }
01495     parent.appendChild( de );
01496 }
01497 
01498 
01499 int SequenceElement::childPos( const BasicElement* child ) const
01500 {
01501     QPtrListIterator<BasicElement> it( children );
01502     uint count = it.count();
01503     for ( uint i=0; i<count; ++i, ++it ) {
01504         if ( it.current() == child ) {
01505             return i;
01506         }
01507     }
01508     return -1;
01509 }
01510 
01511 
01512 NameSequence::NameSequence( BasicElement* parent )
01513     : SequenceElement( parent )
01514 {
01515 }
01516 
01517 
01518 bool NameSequence::accept( ElementVisitor* visitor )
01519 {
01520     return visitor->visit( this );
01521 }
01522 
01523 
01524 void NameSequence::calcCursorSize( const ContextStyle& context,
01525                                    FormulaCursor* cursor, bool smallCursor )
01526 {
01527     inherited::calcCursorSize( context, cursor, smallCursor );
01528     LuPixelPoint point = widgetPos();
01529     luPixel unitX = context.ptToLayoutUnitPixX( 1 );
01530     luPixel unitY = context.ptToLayoutUnitPixY( 1 );
01531     cursor->addCursorSize( LuPixelRect( point.x()-unitX, point.y()-unitY,
01532                                         getWidth()+2*unitX, getHeight()+2*unitY ) );
01533 }
01534 
01535 void NameSequence::drawCursor( QPainter& painter, const ContextStyle& context,
01536                                FormulaCursor* cursor, bool smallCursor )
01537 {
01538     LuPixelPoint point = widgetPos();
01539     painter.setPen( QPen( context.getEmptyColor(),
01540                           context.layoutUnitToPixelX( context.getLineWidth()/2 ) ) );
01541     luPixel unitX = context.ptToLayoutUnitPixX( 1 );
01542     luPixel unitY = context.ptToLayoutUnitPixY( 1 );
01543     painter.drawRect( context.layoutUnitToPixelX( point.x()-unitX ),
01544                       context.layoutUnitToPixelY( point.y()-unitY ),
01545                       context.layoutUnitToPixelX( getWidth()+2*unitX ),
01546                       context.layoutUnitToPixelY( getHeight()+2*unitY ) );
01547 
01548     inherited::drawCursor( painter, context, cursor, smallCursor );
01549 }
01550 
01551 void NameSequence::moveWordLeft( FormulaCursor* cursor )
01552 {
01553     uint pos = cursor->getPos();
01554     if ( pos > 0 ) {
01555         cursor->setTo( this, 0 );
01556     }
01557     else {
01558         moveLeft( cursor, this );
01559     }
01560 }
01561 
01562 void NameSequence::moveWordRight( FormulaCursor* cursor )
01563 {
01564     int pos = cursor->getPos();
01565     if ( pos < countChildren() ) {
01566         cursor->setTo( this, countChildren() );
01567     }
01568     else {
01569         moveRight( cursor, this );
01570     }
01571 }
01572 
01573 
01574 KCommand* NameSequence::compactExpressionCmd( Container* container )
01575 {
01576     BasicElement* element = replaceElement( container->document()->getSymbolTable() );
01577     if ( element != 0 ) {
01578         getParent()->selectChild( container->activeCursor(), this );
01579 
01580         KFCReplace* command = new KFCReplace( i18n( "Add Element" ), container );
01581         command->addElement( element );
01582         return command;
01583     }
01584     return 0;
01585 }
01586 
01587 KCommand* NameSequence::buildCommand( Container* container, Request* request )
01588 {
01589     switch ( *request ) {
01590     case req_compactExpression:
01591         return compactExpressionCmd( container );
01592     case req_addSpace:
01593     case req_addIndex:
01594     case req_addMatrix:
01595     case req_addOneByTwoMatrix:
01596     case req_addSymbol:
01597     case req_addRoot:
01598     case req_addFraction:
01599     case req_addBracket:
01600     case req_addNameSequence:
01601         return 0;
01602     default:
01603         break;
01604     }
01605     return inherited::buildCommand( container, request );
01606 }
01607 
01608 
01609 KCommand* NameSequence::input( Container* container, QChar ch )
01610 {
01611     int unicode = ch.unicode();
01612     switch (unicode) {
01613     case '(':
01614     case '[':
01615     case '|':
01616     case '^':
01617     case '_':
01618     case '}':
01619     case ']':
01620     case ')':
01621     case '\\': {
01622 //         KCommand* compact = compactExpressionCmd( container );
01623 //         KCommand* cmd = static_cast<SequenceElement*>( getParent() )->input( container, ch );
01624 //         if ( compact != 0 ) {
01625 //             KMacroCommand* macro = new KMacroCommand( cmd->name() );
01626 //             macro->addCommand( compact );
01627 //             macro->addCommand( cmd );
01628 //             return macro;
01629 //         }
01630 //         else {
01631 //             return cmd;
01632 //         }
01633         break;
01634     }
01635     case '{':
01636     case ' ': {
01637         Request r( req_compactExpression );
01638         return buildCommand( container, &r );
01639     }
01640     default: {
01641         TextCharRequest r( ch );
01642         return buildCommand( container, &r );
01643     }
01644     }
01645     return 0;
01646 }
01647 
01648 void NameSequence::setElementType( ElementType* t )
01649 {
01650     inherited::setElementType( t );
01651     parse();
01652 }
01653 
01654 BasicElement* NameSequence::replaceElement( const SymbolTable& table )
01655 {
01656     QString name = buildName();
01657     QChar ch = table.unicode( name );
01658     if ( !ch.isNull() ) {
01659         return new TextElement( ch, true );
01660     }
01661     else {
01662         ch = table.unicode( i18n( name.latin1() ) );
01663         if ( !ch.isNull() ) {
01664             return new TextElement( ch, true );
01665         }
01666     }
01667 
01668     if ( name == "!" )    return new SpaceElement( NEGTHIN );
01669     if ( name == "," )    return new SpaceElement( THIN );
01670     if ( name == ">" )    return new SpaceElement( MEDIUM );
01671     if ( name == ";" )    return new SpaceElement( THICK );
01672     if ( name == "quad" ) return new SpaceElement( QUAD );
01673 
01674     if ( name == "frac" ) return new FractionElement();
01675     if ( name == "atop" ) {
01676         FractionElement* frac = new FractionElement();
01677         frac->showLine( false );
01678         return frac;
01679     }
01680     if ( name == "sqrt" ) return new RootElement();
01681 
01682     return 0;
01683 }
01684 
01685 BasicElement* NameSequence::createElement( QString type )
01686 {
01687     if      ( type == "TEXT" )         return new TextElement();
01688     return 0;
01689 }
01690 
01691 // void NameSequence::parse()
01692 // {
01693 //     // A name sequence is known as name and so are its children.
01694 //     // Caution: this is fake!
01695 //     for ( int i = 0; i < countChildren(); i++ ) {
01696 //         getChild( i )->setElementType( getElementType() );
01697 //     }
01698 // }
01699 
01700 QString NameSequence::buildName()
01701 {
01702     QString name;
01703     for ( int i = 0; i < countChildren(); i++ ) {
01704         name += getChild( i )->getCharacter();
01705     }
01706     return name;
01707 }
01708 
01709 bool NameSequence::isValidSelection( FormulaCursor* cursor )
01710 {
01711     SequenceElement* sequence = cursor->normal();
01712     if ( sequence == 0 ) {
01713         return false;
01714     }
01715     return sequence->onlyTextSelected( cursor );
01716 }
01717 
01718 void NameSequence::writeMathML( QDomDocument& doc, QDomNode parent,bool oasisFormat )
01719 {
01720     QDomElement de = doc.createElement( oasisFormat ? "math:mi" : "mi" );
01721     QString value;
01722     for ( int i = 0; i < countChildren(); ++i ) {
01723         // these are supposed to by TextElements
01724         value += getChild( i )->getCharacter();
01725     }
01726     de.appendChild( doc.createTextNode( value ) );
01727     parent.appendChild( de );
01728 }
01729 
01730 KFORMULA_NAMESPACE_END
KDE Logo
This file is part of the documentation for lib Library Version 1.4.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Mon Feb 13 09:40:15 2006 by doxygen 1.4.2 written by Dimitri van Heesch, © 1997-2003