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)
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         return buildCommand( container, &r );
01237     }
01238     case '[': {
01239         BracketRequest r( LeftSquareBracket, RightSquareBracket );
01240         return buildCommand( container, &r );
01241     }
01242     case '{': {
01243         BracketRequest r( LeftCurlyBracket, RightCurlyBracket );
01244         return buildCommand( container, &r );
01245     }
01246     case '|': {
01247         BracketRequest r( LeftLineBracket, RightLineBracket );
01248         return buildCommand( container, &r );
01249     }
01250     case '^': {
01251         IndexRequest r( upperRightPos );
01252         return buildCommand( container, &r );
01253     }
01254     case '_': {
01255         IndexRequest r( lowerRightPos );
01256         return buildCommand( container, &r );
01257     }
01258     case ' ': {
01259         Request r( req_compactExpression );
01260         return buildCommand( container, &r );
01261     }
01262     case '}': {
01263         Request r( req_addEmptyBox );
01264         return buildCommand( container, &r );
01265     }
01266     case ']':
01267     case ')':
01268         break;
01269     case '\\': {
01270         Request r( req_addNameSequence );
01271         return buildCommand( container, &r );
01272     }
01273     default: {
01274         TextCharRequest r( ch );
01275         return buildCommand( container, &r );
01276     }
01277     }
01278     return 0;
01279 }
01280 
01284 void SequenceElement::getChildrenDom(QDomDocument doc, QDomElement elem,
01285                                      uint from, uint to)
01286 {
01287     for (uint i = from; i < to; i++) {
01288         QDomElement tmpEleDom=children.at(i)->getElementDom(doc);
01289     elem.appendChild(tmpEleDom);
01290     }
01291 }
01292 
01293 
01299 bool SequenceElement::buildChildrenFromDom(QPtrList<BasicElement>& list, QDomNode n)
01300 {
01301     while (!n.isNull()) {
01302         if (n.isElement()) {
01303             QDomElement e = n.toElement();
01304             BasicElement* child = 0;
01305             QString tag = e.tagName().upper();
01306 
01307             child = createElement(tag);
01308             if (child != 0) {
01309                 child->setParent(this);
01310                 if (child->buildFromDom(e)) {
01311                     list.append(child);
01312                 }
01313                 else {
01314                     delete child;
01315                     return false;
01316                 }
01317             }
01318             else {
01319                 return false;
01320             }
01321         }
01322         n = n.nextSibling();
01323     }
01324     parse();
01325     return true;
01326 }
01327 
01328 
01329 BasicElement* SequenceElement::createElement( QString type )
01330 {
01331     return creationStrategy->createElement( type );
01332 }
01333 
01337 void SequenceElement::writeDom(QDomElement element)
01338 {
01339     BasicElement::writeDom(element);
01340 
01341     uint count = children.count();
01342     QDomDocument doc = element.ownerDocument();
01343     getChildrenDom(doc, element, 0, count);
01344 }
01345 
01350 bool SequenceElement::readAttributesFromDom(QDomElement element)
01351 {
01352     if (!BasicElement::readAttributesFromDom(element)) {
01353         return false;
01354     }
01355     return true;
01356 }
01357 
01363 bool SequenceElement::readContentFromDom(QDomNode& node)
01364 {
01365     if (!BasicElement::readContentFromDom(node)) {
01366         return false;
01367     }
01368 
01369     return buildChildrenFromDom(children, node);
01370 }
01371 
01372 
01373 void SequenceElement::parse()
01374 {
01375     delete parseTree;
01376 
01377     textSequence = true;
01378     for (BasicElement* element = children.first();
01379          element != 0;
01380          element = children.next()) {
01381 
01382         // Those types are gone. Make sure they won't
01383         // be used.
01384         element->setElementType(0);
01385 
01386         if (element->getCharacter().isNull()) {
01387             textSequence = false;
01388         }
01389     }
01390 
01391     const SymbolTable& symbols = formula()->getSymbolTable();
01392     SequenceParser parser(symbols);
01393     parseTree = parser.parse(children);
01394 
01395     // With the IndexElement dynamically changing its text/non-text
01396     // behaviour we need to reparse your parent, too. Hacky!
01397     BasicElement* p = getParent();
01398     if ( p != 0 ) {
01399         SequenceElement* seq = dynamic_cast<SequenceElement*>( p->getParent() );
01400         if ( seq != 0 ) {
01401             seq->parse();
01402         }
01403     }
01404     // debug
01405     //parseTree->output();
01406 }
01407 
01408 
01409 bool SequenceElement::isFirstOfToken( BasicElement* child )
01410 {
01411     return ( child->getElementType() != 0 ) && isChildNumber( child->getElementType()->start(), child );
01412 }
01413 
01414 
01415 QString SequenceElement::toLatex()
01416 {
01417     QString content;
01418     content += "{";
01419     uint count = children.count();
01420     for ( uint i = 0; i < count; i++ ) {
01421         BasicElement* child = children.at( i );
01422         if ( isFirstOfToken( child ) ) {
01423             content += " ";
01424         }
01425         content += child->toLatex();
01426     }
01427     content += "}";
01428     return content;
01429 }
01430 
01431 
01432 QString SequenceElement::formulaString()
01433 {
01434     QString content;
01435     uint count = children.count();
01436     for ( uint i = 0; i < count; i++ ) {
01437         BasicElement* child = children.at( i );
01438         //if ( isFirstOfToken( child ) ) {
01439         //    content += " ";
01440         //}
01441         content += child->formulaString();
01442     }
01443     return content;
01444 }
01445 
01446 
01447 void SequenceElement::writeMathML( QDomDocument doc, QDomNode parent )
01448 {
01449     QDomElement de = doc.createElement( "mrow" );
01450 
01451     BasicElement* last = children.last();
01452     if ( last != 0 ) {
01453         // Create a list (right order!)
01454         QPtrList<ElementType> tokenList;
01455         ElementType* token = last->getElementType();
01456         while ( token != 0 ) {
01457             // Add to the list.
01458             tokenList.prepend( token );
01459             token = token->getPrev();
01460         }
01461 
01462         if ( tokenList.count() == 1 ) {
01463             tokenList.first()->saveMathML( this, doc, parent.toElement() );
01464             return;
01465         }
01466 
01467         for ( uint i = 0; i < tokenList.count(); ++i ) {
01468             tokenList.at( i )->saveMathML( this, doc, de );
01469         }
01470     }
01471     parent.appendChild( de );
01472 }
01473 
01474 
01475 int SequenceElement::childPos( const BasicElement* child ) const
01476 {
01477     QPtrListIterator<BasicElement> it( children );
01478     uint count = it.count();
01479     for ( uint i=0; i<count; ++i, ++it ) {
01480         if ( it.current() == child ) {
01481             return i;
01482         }
01483     }
01484     return -1;
01485 }
01486 
01487 
01488 NameSequence::NameSequence( BasicElement* parent )
01489     : SequenceElement( parent )
01490 {
01491 }
01492 
01493 
01494 bool NameSequence::accept( ElementVisitor* visitor )
01495 {
01496     return visitor->visit( this );
01497 }
01498 
01499 
01500 void NameSequence::calcCursorSize( const ContextStyle& context,
01501                                    FormulaCursor* cursor, bool smallCursor )
01502 {
01503     inherited::calcCursorSize( context, cursor, smallCursor );
01504     LuPixelPoint point = widgetPos();
01505     luPixel unitX = context.ptToLayoutUnitPixX( 1 );
01506     luPixel unitY = context.ptToLayoutUnitPixY( 1 );
01507     cursor->addCursorSize( LuPixelRect( point.x()-unitX, point.y()-unitY,
01508                                         getWidth()+2*unitX, getHeight()+2*unitY ) );
01509 }
01510 
01511 void NameSequence::drawCursor( QPainter& painter, const ContextStyle& context,
01512                                FormulaCursor* cursor, bool smallCursor )
01513 {
01514     LuPixelPoint point = widgetPos();
01515     painter.setPen( QPen( context.getEmptyColor(),
01516                           context.layoutUnitToPixelX( context.getLineWidth()/2 ) ) );
01517     luPixel unitX = context.ptToLayoutUnitPixX( 1 );
01518     luPixel unitY = context.ptToLayoutUnitPixY( 1 );
01519     painter.drawRect( context.layoutUnitToPixelX( point.x()-unitX ),
01520                       context.layoutUnitToPixelY( point.y()-unitY ),
01521                       context.layoutUnitToPixelX( getWidth()+2*unitX ),
01522                       context.layoutUnitToPixelY( getHeight()+2*unitY ) );
01523 
01524     inherited::drawCursor( painter, context, cursor, smallCursor );
01525 }
01526 
01527 void NameSequence::moveWordLeft( FormulaCursor* cursor )
01528 {
01529     uint pos = cursor->getPos();
01530     if ( pos > 0 ) {
01531         cursor->setTo( this, 0 );
01532     }
01533     else {
01534         moveLeft( cursor, this );
01535     }
01536 }
01537 
01538 void NameSequence::moveWordRight( FormulaCursor* cursor )
01539 {
01540     int pos = cursor->getPos();
01541     if ( pos < countChildren() ) {
01542         cursor->setTo( this, countChildren() );
01543     }
01544     else {
01545         moveRight( cursor, this );
01546     }
01547 }
01548 
01549 
01550 KCommand* NameSequence::compactExpressionCmd( Container* container )
01551 {
01552     BasicElement* element = replaceElement( container->document()->getSymbolTable() );
01553     if ( element != 0 ) {
01554         getParent()->selectChild( container->activeCursor(), this );
01555 
01556         KFCReplace* command = new KFCReplace( i18n( "Add Element" ), container );
01557         command->addElement( element );
01558         return command;
01559     }
01560     return 0;
01561 }
01562 
01563 KCommand* NameSequence::buildCommand( Container* container, Request* request )
01564 {
01565     switch ( *request ) {
01566     case req_compactExpression:
01567         return compactExpressionCmd( container );
01568     case req_addSpace:
01569     case req_addIndex:
01570     case req_addMatrix:
01571     case req_addOneByTwoMatrix:
01572     case req_addSymbol:
01573     case req_addRoot:
01574     case req_addFraction:
01575     case req_addBracket:
01576     case req_addNameSequence:
01577         return 0;
01578     default:
01579         break;
01580     }
01581     return inherited::buildCommand( container, request );
01582 }
01583 
01584 
01585 KCommand* NameSequence::input( Container* container, QChar ch )
01586 {
01587     int unicode = ch.unicode();
01588     switch (unicode) {
01589     case '(':
01590     case '[':
01591     case '|':
01592     case '^':
01593     case '_':
01594     case '}':
01595     case ']':
01596     case ')':
01597     case '\\': {
01598 //         KCommand* compact = compactExpressionCmd( container );
01599 //         KCommand* cmd = static_cast<SequenceElement*>( getParent() )->input( container, ch );
01600 //         if ( compact != 0 ) {
01601 //             KMacroCommand* macro = new KMacroCommand( cmd->name() );
01602 //             macro->addCommand( compact );
01603 //             macro->addCommand( cmd );
01604 //             return macro;
01605 //         }
01606 //         else {
01607 //             return cmd;
01608 //         }
01609         break;
01610     }
01611     case '{':
01612     case ' ': {
01613         Request r( req_compactExpression );
01614         return buildCommand( container, &r );
01615     }
01616     default: {
01617         TextCharRequest r( ch );
01618         return buildCommand( container, &r );
01619     }
01620     }
01621     return 0;
01622 }
01623 
01624 void NameSequence::setElementType( ElementType* t )
01625 {
01626     inherited::setElementType( t );
01627     parse();
01628 }
01629 
01630 BasicElement* NameSequence::replaceElement( const SymbolTable& table )
01631 {
01632     QString name = buildName();
01633     QChar ch = table.unicode( name );
01634     if ( !ch.isNull() ) {
01635         return new TextElement( ch, true );
01636     }
01637     else {
01638         ch = table.unicode( i18n( name.latin1() ) );
01639         if ( !ch.isNull() ) {
01640             return new TextElement( ch, true );
01641         }
01642     }
01643 
01644     if ( name == "!" )    return new SpaceElement( NEGTHIN );
01645     if ( name == "," )    return new SpaceElement( THIN );
01646     if ( name == ">" )    return new SpaceElement( MEDIUM );
01647     if ( name == ";" )    return new SpaceElement( THICK );
01648     if ( name == "quad" ) return new SpaceElement( QUAD );
01649 
01650     if ( name == "frac" ) return new FractionElement();
01651     if ( name == "atop" ) {
01652         FractionElement* frac = new FractionElement();
01653         frac->showLine( false );
01654         return frac;
01655     }
01656     if ( name == "sqrt" ) return new RootElement();
01657 
01658     return 0;
01659 }
01660 
01661 BasicElement* NameSequence::createElement( QString type )
01662 {
01663     if      ( type == "TEXT" )         return new TextElement();
01664     return 0;
01665 }
01666 
01667 // void NameSequence::parse()
01668 // {
01669 //     // A name sequence is known as name and so are its children.
01670 //     // Caution: this is fake!
01671 //     for ( int i = 0; i < countChildren(); i++ ) {
01672 //         getChild( i )->setElementType( getElementType() );
01673 //     }
01674 // }
01675 
01676 QString NameSequence::buildName()
01677 {
01678     QString name;
01679     for ( int i = 0; i < countChildren(); i++ ) {
01680         name += getChild( i )->getCharacter();
01681     }
01682     return name;
01683 }
01684 
01685 bool NameSequence::isValidSelection( FormulaCursor* cursor )
01686 {
01687     SequenceElement* sequence = cursor->normal();
01688     if ( sequence == 0 ) {
01689         return false;
01690     }
01691     return sequence->onlyTextSelected( cursor );
01692 }
01693 
01694 void NameSequence::writeMathML( QDomDocument doc, QDomNode parent )
01695 {
01696     QDomElement de = doc.createElement( "mi" );
01697     QString value;
01698     for ( int i = 0; i < countChildren(); ++i ) {
01699         // these are supposed to by TextElements
01700         value += getChild( i )->getCharacter();
01701     }
01702     de.appendChild( doc.createTextNode( value ) );
01703     parent.appendChild( de );
01704 }
01705 
01706 KFORMULA_NAMESPACE_END
KDE Logo
This file is part of the documentation for lib Library Version 1.3.5.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Mar 11 11:47:46 2005 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003