lib

symbolelement.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., 51 Franklin Street, Fifth Floor,
00018  * Boston, MA 02110-1301, USA.
00019 */
00020 
00021 #include <qpainter.h>
00022 
00023 #include <kdebug.h>
00024 
00025 #include "elementvisitor.h"
00026 #include "formulacursor.h"
00027 #include "formulaelement.h"
00028 #include "kformulacommand.h"
00029 #include "sequenceelement.h"
00030 #include "symbolelement.h"
00031 
00032 KFORMULA_NAMESPACE_BEGIN
00033 
00034 
00035 class SymbolSequenceElement : public SequenceElement {
00036     typedef SequenceElement inherited;
00037 public:
00038 
00039     SymbolSequenceElement( BasicElement* parent = 0 ) : SequenceElement( parent ) {}
00040 
00049     virtual KCommand* buildCommand( Container*, Request* );
00050 };
00051 
00052 
00053 KCommand* SymbolSequenceElement::buildCommand( Container* container, Request* request )
00054 {
00055     FormulaCursor* cursor = container->activeCursor();
00056     if ( cursor->isReadOnly() ) {
00057         return 0;
00058     }
00059 
00060     switch ( *request ) {
00061     case req_addIndex: {
00062         FormulaCursor* cursor = container->activeCursor();
00063         if ( cursor->isSelection() ||
00064              ( cursor->getPos() > 0 && cursor->getPos() < countChildren() ) ) {
00065             break;
00066         }
00067         IndexRequest* ir = static_cast<IndexRequest*>( request );
00068         if ( ( ir->index() == upperMiddlePos ) || ( ir->index() == lowerMiddlePos ) ) {
00069             SymbolElement* element = static_cast<SymbolElement*>( getParent() );
00070             ElementIndexPtr index = element->getIndex( ir->index() );
00071             if ( !index->hasIndex() ) {
00072                 KFCAddGenericIndex* command = new KFCAddGenericIndex( container, index );
00073                 return command;
00074             }
00075             else {
00076                 index->moveToIndex( cursor, afterCursor );
00077                 cursor->setSelection( false );
00078                 formula()->cursorHasMoved( cursor );
00079                 return 0;
00080             }
00081         }
00082     }
00083     default:
00084         break;
00085     }
00086     return inherited::buildCommand( container, request );
00087 }
00088 
00089 
00090 SymbolElement::SymbolElement(SymbolType type, BasicElement* parent)
00091     : BasicElement(parent), symbol( 0 ), symbolType( type )
00092 {
00093     content = new SymbolSequenceElement( this );
00094     upper = 0;
00095     lower = 0;
00096 }
00097 
00098 SymbolElement::~SymbolElement()
00099 {
00100     delete lower;
00101     delete upper;
00102     delete content;
00103     delete symbol;
00104 }
00105 
00106 
00107 SymbolElement::SymbolElement( const SymbolElement& other )
00108     : BasicElement( other ), symbol( 0 ), symbolType( other.symbolType )
00109 {
00110     content = new SymbolSequenceElement( *dynamic_cast<SymbolSequenceElement*>( other.content ) );
00111     content->setParent( this );
00112 
00113     if ( other.upper ) {
00114         upper = new SequenceElement( *( other.upper ) );
00115         upper->setParent( this );
00116     }
00117     else {
00118         upper = 0;
00119     }
00120     if ( other.lower ) {
00121         lower = new SequenceElement( *( other.lower ) );
00122         lower->setParent( this );
00123     }
00124     else {
00125         lower = 0;
00126     }
00127 }
00128 
00129 
00130 bool SymbolElement::accept( ElementVisitor* visitor )
00131 {
00132     return visitor->visit( this );
00133 }
00134 
00135 
00136 BasicElement* SymbolElement::goToPos( FormulaCursor* cursor, bool& handled,
00137                                       const LuPixelPoint& point, const LuPixelPoint& parentOrigin )
00138 {
00139     BasicElement* e = BasicElement::goToPos(cursor, handled, point, parentOrigin);
00140     if (e != 0) {
00141         LuPixelPoint myPos(parentOrigin.x() + getX(),
00142                            parentOrigin.y() + getY());
00143 
00144         e = content->goToPos(cursor, handled, point, myPos);
00145         if (e != 0) {
00146             return e;
00147         }
00148         if (hasLower()) {
00149             e = lower->goToPos(cursor, handled, point, myPos);
00150             if (e != 0) {
00151                 return e;
00152             }
00153         }
00154         if (hasUpper()) {
00155             e = upper->goToPos(cursor, handled, point, myPos);
00156             if (e != 0) {
00157                 return e;
00158             }
00159         }
00160 
00161         // the positions after the indexes.
00162         luPixel dx = point.x() - myPos.x();
00163         luPixel dy = point.y() - myPos.y();
00164         if (dy < symbol->getY()) {
00165             if (hasUpper() && (dx > upper->getX())) {
00166                 upper->moveLeft(cursor, this);
00167                 handled = true;
00168                 return upper;
00169             }
00170         }
00171         else if (dy > symbol->getY()+symbol->getHeight()) {
00172             if (hasLower() && (dx > lower->getX())) {
00173                 lower->moveLeft(cursor, this);
00174                 handled = true;
00175                 return lower;
00176             }
00177         }
00178 
00179         // Have the cursor jump behind the integral.
00180         if ( ( dx < symbol->getX()+symbol->getWidth() ) &&
00181              ( dx > symbol->getX()+symbol->getWidth()/2 ) ) {
00182             content->moveRight( cursor, this );
00183             handled = true;
00184             return content;
00185         }
00186 
00187         return this;
00188     }
00189     return 0;
00190 }
00191 
00192 
00197 void SymbolElement::calcSizes( const ContextStyle& context,
00198                                ContextStyle::TextStyle tstyle,
00199                                ContextStyle::IndexStyle istyle,
00200                                StyleAttributes& style )
00201 {
00202     double factor = style.sizeFactor();
00203     luPt mySize = context.getAdjustedSize( tstyle, factor );
00204     luPixel distX = context.ptToPixelX( context.getThinSpace( tstyle, factor ) );
00205     luPixel distY = context.ptToPixelY( context.getThinSpace( tstyle, factor ) );
00206 
00207     //if ( symbol == 0 ) {
00208     delete symbol;
00209     symbol = context.fontStyle().createArtwork( symbolType );
00210     //}
00211 
00212     symbol->calcSizes(context, tstyle, factor, mySize);
00213     content->calcSizes( context, tstyle, istyle, style );
00214 
00215     //symbol->scale(((double)parentSize)/symbol->getHeight()*2);
00216 
00217     luPixel upperWidth = 0;
00218     luPixel upperHeight = 0;
00219     if (hasUpper()) {
00220         upper->calcSizes( context, context.convertTextStyleIndex( tstyle ),
00221                           context.convertIndexStyleUpper( istyle ), style );
00222         upperWidth = upper->getWidth();
00223         upperHeight = upper->getHeight() + distY;
00224     }
00225 
00226     luPixel lowerWidth = 0;
00227     luPixel lowerHeight = 0;
00228     if (hasLower()) {
00229         lower->calcSizes( context, context.convertTextStyleIndex( tstyle ),
00230                           context.convertIndexStyleLower( istyle ), style );
00231         lowerWidth = lower->getWidth();
00232         lowerHeight = lower->getHeight() + distY;
00233     }
00234 
00235     // widths
00236     luPixel xOffset = QMAX(symbol->getWidth(), QMAX(upperWidth, lowerWidth));
00237     if (context.getCenterSymbol()) {
00238         symbol->setX((xOffset - symbol->getWidth()) / 2);
00239     }
00240     else {
00241         symbol->setX(xOffset - symbol->getWidth());
00242     }
00243     // ???
00244     content->setX(xOffset +
00245                   static_cast<luPixel>( symbol->slant()*symbol->getHeight()/2 ) +
00246                   distX/2);
00247 
00248     setWidth(QMAX(content->getX() + content->getWidth(),
00249                   QMAX(upperWidth, lowerWidth)));
00250 
00251     // heights
00252     //int toMidline = QMAX(content->getHeight() / 2,
00253     luPixel toMidline = QMAX(content->axis( context, tstyle, factor ),
00254                              upperHeight + symbol->getHeight()/2);
00255     //int fromMidline = QMAX(content->getHeight() / 2,
00256     luPixel fromMidline = QMAX(content->getHeight() - content->axis( context, tstyle, factor ),
00257                                lowerHeight + symbol->getHeight()/2);
00258     setHeight(toMidline + fromMidline);
00259     //setMidline(toMidline);
00260 
00261     symbol->setY(toMidline - symbol->getHeight()/2);
00262     //content->setY(toMidline - content->getHeight()/2);
00263     content->setY(toMidline - content->axis( context, tstyle, factor ));
00264 
00265     if (hasUpper()) {
00266         luPixel slant =
00267             static_cast<luPixel>( symbol->slant()*( symbol->getHeight()+distY ) );
00268         if (context.getCenterSymbol()) {
00269             upper->setX((xOffset - upperWidth) / 2 + slant );
00270         }
00271         else {
00272             if (upperWidth < symbol->getWidth()) {
00273                 upper->setX(symbol->getX() +
00274                             (symbol->getWidth() - upperWidth) / 2 + slant );
00275             }
00276             else {
00277                 upper->setX(xOffset - upperWidth);
00278             }
00279         }
00280         upper->setY(toMidline - upperHeight - symbol->getHeight()/2);
00281     }
00282     if (hasLower()) {
00283         luPixel slant = static_cast<luPixel>( -symbol->slant()*distY );
00284         if (context.getCenterSymbol()) {
00285             lower->setX((xOffset - lowerWidth) / 2 + slant);
00286         }
00287         else {
00288             if (lowerWidth < symbol->getWidth()) {
00289                 lower->setX(symbol->getX() +
00290                             (symbol->getWidth() - lowerWidth) / 2 + slant );
00291             }
00292             else {
00293                 lower->setX(xOffset - lowerWidth);
00294             }
00295         }
00296         lower->setY(toMidline + symbol->getHeight()/2 + distY);
00297     }
00298     setBaseline(content->getBaseline() + content->getY());
00299 }
00300 
00306 void SymbolElement::draw( QPainter& painter, const LuPixelRect& r,
00307                           const ContextStyle& context,
00308                           ContextStyle::TextStyle tstyle,
00309                           ContextStyle::IndexStyle istyle,
00310                           StyleAttributes& style,
00311                           const LuPixelPoint& parentOrigin )
00312 {
00313     LuPixelPoint myPos( parentOrigin.x()+getX(), parentOrigin.y()+getY() );
00314     //if ( !LuPixelRect( myPos.x(), myPos.y(), getWidth(), getHeight() ).intersects( r ) )
00315     //    return;
00316 
00317     luPt mySize = context.getAdjustedSize( tstyle, style.sizeFactor() );
00318     symbol->draw( painter, r, context, tstyle, style, mySize, myPos );
00319     content->draw( painter, r, context, tstyle, istyle, style, myPos );
00320     if ( hasUpper() ) {
00321         upper->draw( painter, r, context, context.convertTextStyleIndex( tstyle ),
00322                      context.convertIndexStyleUpper( istyle ), style, myPos );
00323     }
00324     if ( hasLower() ) {
00325         lower->draw( painter, r, context, context.convertTextStyleIndex( tstyle ),
00326                      context.convertIndexStyleLower( istyle ), style, myPos );
00327     }
00328 
00329     // Debug
00330 #if 0
00331     painter.setBrush(Qt::NoBrush);
00332     painter.setPen(Qt::red);
00333 //     painter.drawRect( context.layoutUnitToPixelX( myPos.x() ),
00334 //                       context.layoutUnitToPixelY( myPos.y() ),
00335 //                       context.layoutUnitToPixelX( getWidth() ),
00336 //                       context.layoutUnitToPixelY( getHeight() ) );
00337     painter.drawRect( context.layoutUnitToPixelX( myPos.x()+symbol->getX() ),
00338                       context.layoutUnitToPixelY( myPos.y()+symbol->getY() ),
00339                       context.layoutUnitToPixelX( symbol->getWidth() ),
00340                       context.layoutUnitToPixelY( symbol->getHeight() ) );
00341     painter.setPen(Qt::green);
00342     painter.drawLine( context.layoutUnitToPixelX( myPos.x() ),
00343                       context.layoutUnitToPixelY( myPos.y()+axis(context, tstyle) ),
00344                       context.layoutUnitToPixelX( myPos.x()+getWidth() ),
00345                       context.layoutUnitToPixelY( myPos.y()+axis(context, tstyle) ) );
00346 #endif
00347 }
00348 
00349 
00350 void SymbolElement::dispatchFontCommand( FontCommand* cmd )
00351 {
00352     content->dispatchFontCommand( cmd );
00353     if ( hasUpper() ) {
00354         upper->dispatchFontCommand( cmd );
00355     }
00356     if ( hasLower() ) {
00357         lower->dispatchFontCommand( cmd );
00358     }
00359 }
00360 
00361 // navigation
00362 //
00363 // The elements are responsible to handle cursor movement themselves.
00364 // To do this they need to know the direction the cursor moves and
00365 // the element it comes from.
00366 //
00367 // The cursor might be in normal or in selection mode.
00368 
00374 void SymbolElement::moveLeft(FormulaCursor* cursor, BasicElement* from)
00375 {
00376     if (cursor->isSelectionMode()) {
00377         getParent()->moveLeft(cursor, this);
00378     }
00379     else {
00380         bool linear = cursor->getLinearMovement();
00381         if (from == getParent()) {
00382             content->moveLeft(cursor, this);
00383         }
00384         else if (from == content) {
00385             if (linear && hasLower()) {
00386                 lower->moveLeft(cursor, this);
00387             }
00388             else if (linear && hasUpper()) {
00389                 upper->moveLeft(cursor, this);
00390             }
00391             else {
00392                 getParent()->moveLeft(cursor, this);
00393             }
00394         }
00395         else if (from == lower) {
00396             if (linear && hasUpper()) {
00397                 upper->moveLeft(cursor, this);
00398             }
00399             else {
00400                 getParent()->moveLeft(cursor, this);
00401             }
00402         }
00403         else if (from == upper) {
00404             getParent()->moveLeft(cursor, this);
00405         }
00406     }
00407 }
00408 
00414 void SymbolElement::moveRight(FormulaCursor* cursor, BasicElement* from)
00415 {
00416     if (cursor->isSelectionMode()) {
00417         getParent()->moveRight(cursor, this);
00418     }
00419     else {
00420         bool linear = cursor->getLinearMovement();
00421         if (from == getParent()) {
00422             if (linear && hasUpper()) {
00423                 upper->moveRight(cursor, this);
00424             }
00425             else if (linear && hasLower()) {
00426                 lower->moveRight(cursor, this);
00427             }
00428             else {
00429                 content->moveRight(cursor, this);
00430             }
00431         }
00432         else if (from == upper) {
00433             if (linear && hasLower()) {
00434                 lower->moveRight(cursor, this);
00435             }
00436             else {
00437                 content->moveRight(cursor, this);
00438             }
00439         }
00440         else if (from == lower) {
00441             content->moveRight(cursor, this);
00442         }
00443         else if (from == content) {
00444             getParent()->moveRight(cursor, this);
00445         }
00446     }
00447 }
00448 
00454 void SymbolElement::moveUp(FormulaCursor* cursor, BasicElement* from)
00455 {
00456     if (cursor->isSelectionMode()) {
00457         getParent()->moveUp(cursor, this);
00458     }
00459     else {
00460         if (from == content) {
00461             if (hasUpper()) {
00462                 upper->moveLeft(cursor, this);
00463             }
00464             else {
00465                 getParent()->moveUp(cursor, this);
00466             }
00467         }
00468         else if (from == upper) {
00469             getParent()->moveUp(cursor, this);
00470         }
00471         else if ((from == getParent()) || (from == lower)) {
00472             content->moveRight(cursor, this);
00473         }
00474     }
00475 }
00476 
00482 void SymbolElement::moveDown(FormulaCursor* cursor, BasicElement* from)
00483 {
00484     if (cursor->isSelectionMode()) {
00485         getParent()->moveDown(cursor, this);
00486     }
00487     else {
00488         if (from == content) {
00489             if (hasLower()) {
00490                 lower->moveLeft(cursor, this);
00491             }
00492             else {
00493                 getParent()->moveDown(cursor, this);
00494             }
00495         }
00496         else if (from == lower) {
00497             getParent()->moveDown(cursor, this);
00498         }
00499         else if ((from == getParent()) || (from == upper)) {
00500             content->moveRight(cursor, this);
00501         }
00502     }
00503 }
00504 
00505 // children
00506 
00507 // main child
00508 //
00509 // If an element has children one has to become the main one.
00510 
00511 // void SymbolElement::setMainChild(SequenceElement* child)
00512 // {
00513 //     formula()->elementRemoval(content);
00514 //     content = child;
00515 //     content->setParent(this);
00516 //     formula()->changed();
00517 // }
00518 
00519 
00530 void SymbolElement::insert(FormulaCursor* cursor,
00531                            QPtrList<BasicElement>& newChildren,
00532                            Direction direction)
00533 {
00534     SequenceElement* index = static_cast<SequenceElement*>(newChildren.take(0));
00535     index->setParent(this);
00536 
00537     switch (cursor->getPos()) {
00538     case upperMiddlePos:
00539         upper = index;
00540         break;
00541     case lowerMiddlePos:
00542         lower = index;
00543         break;
00544     default:
00545         // this is an error!
00546         return;
00547     }
00548 
00549     if (direction == beforeCursor) {
00550         index->moveLeft(cursor, this);
00551     }
00552     else {
00553         index->moveRight(cursor, this);
00554     }
00555     cursor->setSelection(false);
00556     formula()->changed();
00557 }
00558 
00570 void SymbolElement::remove(FormulaCursor* cursor,
00571                            QPtrList<BasicElement>& removedChildren,
00572                            Direction direction)
00573 {
00574     int pos = cursor->getPos();
00575     switch (pos) {
00576     case upperMiddlePos:
00577         removedChildren.append(upper);
00578         formula()->elementRemoval(upper);
00579         upper = 0;
00580         setToUpper(cursor);
00581         break;
00582     case lowerMiddlePos:
00583         removedChildren.append(lower);
00584         formula()->elementRemoval(lower);
00585         lower = 0;
00586         setToLower(cursor);
00587         break;
00588     case contentPos: {
00589         BasicElement* parent = getParent();
00590         parent->selectChild(cursor, this);
00591         parent->remove(cursor, removedChildren, direction);
00592         break;
00593     }
00594     }
00595     formula()->changed();
00596 }
00597 
00602 void SymbolElement::normalize(FormulaCursor* cursor, Direction direction)
00603 {
00604     if (direction == beforeCursor) {
00605         content->moveLeft(cursor, this);
00606     }
00607     else {
00608         content->moveRight(cursor, this);
00609     }
00610 }
00611 
00615 BasicElement* SymbolElement::getChild(FormulaCursor* cursor, Direction)
00616 {
00617     int pos = cursor->getPos();
00618     switch (pos) {
00619     case contentPos:
00620         return content;
00621     case upperMiddlePos:
00622         return upper;
00623     case lowerMiddlePos:
00624         return lower;
00625     }
00626     return 0;
00627 }
00628 
00633 void SymbolElement::selectChild(FormulaCursor* cursor, BasicElement* child)
00634 {
00635     if (child == content) {
00636         setToContent(cursor);
00637     }
00638     else if (child == upper) {
00639         setToUpper(cursor);
00640     }
00641     else if (child == lower) {
00642         setToLower(cursor);
00643     }
00644 }
00645 
00646 void SymbolElement::setToUpper(FormulaCursor* cursor)
00647 {
00648     cursor->setTo(this, upperMiddlePos);
00649 }
00650 
00651 void SymbolElement::setToLower(FormulaCursor* cursor)
00652 {
00653     cursor->setTo(this, lowerMiddlePos);
00654 }
00655 
00662 void SymbolElement::setToContent(FormulaCursor* cursor)
00663 {
00664     cursor->setTo(this, contentPos);
00665 }
00666 
00667 
00668 void SymbolElement::moveToUpper(FormulaCursor* cursor, Direction direction)
00669 {
00670     if (hasUpper()) {
00671         if (direction == beforeCursor) {
00672             upper->moveLeft(cursor, this);
00673         }
00674         else {
00675             upper->moveRight(cursor, this);
00676         }
00677     }
00678 }
00679 
00680 void SymbolElement::moveToLower(FormulaCursor* cursor, Direction direction)
00681 {
00682     if (hasLower()) {
00683         if (direction == beforeCursor) {
00684             lower->moveLeft(cursor, this);
00685         }
00686         else {
00687             lower->moveRight(cursor, this);
00688         }
00689     }
00690 }
00691 
00692 
00693 ElementIndexPtr SymbolElement::getIndex( int position )
00694 {
00695     switch ( position ) {
00696     case lowerMiddlePos:
00697         return getLowerIndex();
00698     case upperMiddlePos:
00699         return getUpperIndex();
00700     }
00701     return getUpperIndex();
00702 }
00703 
00704 
00708 void SymbolElement::writeDom(QDomElement element)
00709 {
00710     BasicElement::writeDom(element);
00711 
00712     element.setAttribute("TYPE", symbolType);
00713 
00714     QDomDocument doc = element.ownerDocument();
00715 
00716     QDomElement con = doc.createElement("CONTENT");
00717     con.appendChild(content->getElementDom(doc));
00718     element.appendChild(con);
00719 
00720     if(hasLower()) {
00721         QDomElement ind = doc.createElement("LOWER");
00722         ind.appendChild(lower->getElementDom(doc));
00723         element.appendChild(ind);
00724     }
00725     if(hasUpper()) {
00726         QDomElement ind = doc.createElement("UPPER");
00727         ind.appendChild(upper->getElementDom(doc));
00728         element.appendChild(ind);
00729     }
00730 }
00731 
00736 bool SymbolElement::readAttributesFromDom(QDomElement element)
00737 {
00738     if (!BasicElement::readAttributesFromDom(element)) {
00739         return false;
00740     }
00741 
00742     QString typeStr = element.attribute("TYPE");
00743     if(!typeStr.isNull()) {
00744         symbolType = static_cast<SymbolType>(typeStr.toInt());
00745     }
00746 
00747     return true;
00748 }
00749 
00755 bool SymbolElement::readContentFromDom(QDomNode& node)
00756 {
00757     if (!BasicElement::readContentFromDom(node)) {
00758         return false;
00759     }
00760 
00761     if ( !buildChild( content, node, "CONTENT" ) ) {
00762         kdWarning( DEBUGID ) << "Empty content in SymbolElement." << endl;
00763         return false;
00764     }
00765     node = node.nextSibling();
00766 
00767     bool lowerRead = false;
00768     bool upperRead = false;
00769 
00770     while (!node.isNull() && !(upperRead && lowerRead)) {
00771 
00772         if (!lowerRead && (node.nodeName().upper() == "LOWER")) {
00773             lowerRead = buildChild( lower=new SequenceElement( this ), node, "LOWER" );
00774             if ( !lowerRead ) return false;
00775         }
00776 
00777         if (!upperRead && (node.nodeName().upper() == "UPPER")) {
00778             upperRead = buildChild( upper=new SequenceElement( this ), node, "UPPER" );
00779             if ( !upperRead ) return false;
00780         }
00781 
00782         node = node.nextSibling();
00783     }
00784     return true;
00785 }
00786 
00787 QString SymbolElement::toLatex()
00788 {
00789     QString sym;
00790 
00791     switch(symbolType) {
00792 
00793     case 1001:
00794      sym="\\int";
00795     break;
00796     case 1002:
00797      sym="\\sum";
00798     break;
00799     case 1003:
00800      sym="\\prod";
00801     break;
00802 
00803     default:
00804      sym=" ";
00805 
00806     }
00807 
00808 
00809     if(hasLower()) {
00810         sym+="_{";
00811     sym+=lower->toLatex();
00812     sym+="}";
00813     }
00814 
00815     if(hasUpper()) {
00816         sym+="^{";
00817     sym+=upper->toLatex();
00818     sym+="} ";
00819     }
00820 
00821     sym += " ";
00822 
00823     sym+=content->toLatex();
00824 
00825 
00826     return sym;
00827 }
00828 
00829 QString SymbolElement::formulaString()
00830 {
00831     QString sym;
00832     switch ( symbolType ) {
00833     case 1001:
00834         sym="int(";
00835     break;
00836     case 1002:
00837         sym="sum(";
00838     break;
00839     case 1003:
00840         sym="prod(";
00841     break;
00842     default:
00843         sym="(";
00844     }
00845     sym += content->formulaString();
00846     if ( hasLower() ) {
00847         sym += ", " + lower->formulaString();
00848     }
00849     if ( hasUpper() ) {
00850         sym += ", " + upper->formulaString();
00851     }
00852     return sym + ")";
00853 }
00854 
00855 void SymbolElement::writeMathML( QDomDocument& doc, QDomNode& parent, bool oasisFormat ) const
00856 {
00857     QDomElement de = doc.createElement( oasisFormat ? "math:mrow" : "mrow" );
00858     QDomElement mo = doc.createElement( oasisFormat ? "math:mo" : "mo" );
00859 
00860     QString value;
00861 
00862     switch( symbolType )
00863     {
00864     case EmptyBracket: break;
00865     case LeftLineBracket: case RightLineBracket:
00866         mo.appendChild( doc.createTextNode( "|" ) ); break;
00867     case Integral:
00868         mo.appendChild( doc.createEntityReference( "int" ) ); break;
00869     case Sum:
00870         mo.appendChild( doc.createEntityReference( "sum" ) ); break;
00871     case Product:
00872         mo.appendChild( doc.createEntityReference( "prod" ) ); break;
00873     default:
00874         mo.appendChild( doc.createTextNode( QChar( symbolType ) ) );
00875     }
00876 
00877     QDomElement between;
00878     if ( hasUpper() && hasLower() )
00879     {
00880         between = doc.createElement( oasisFormat ? "math:msubsup" : "msubsup" );
00881         between.appendChild( mo );
00882         lower->writeMathML( doc, between, oasisFormat );
00883         upper->writeMathML( doc, between, oasisFormat );
00884     }
00885     else if ( hasUpper() )
00886     {
00887         between = doc.createElement( oasisFormat ? "math:msup" : "msup" );
00888         between.appendChild( mo );
00889         upper->writeMathML( doc, between, oasisFormat );
00890     }
00891     else if ( hasLower() )
00892     {
00893         between = doc.createElement( oasisFormat ? "math:msub" : "msub" );
00894         between.appendChild( mo );
00895         lower->writeMathML( doc, between, oasisFormat );
00896     }
00897     else
00898         between = mo;
00899 
00900     de.appendChild( between );
00901     content->writeMathML( doc, de, oasisFormat );
00902 
00903     parent.appendChild( de );
00904 }
00905 
00906 KFORMULA_NAMESPACE_END
KDE Home | KDE Accessibility Home | Description of Access Keys