lib Library API Documentation

rootelement.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 <qpainter.h>
00022 #include <qpen.h>
00023 
00024 #include <kdebug.h>
00025 #include <klocale.h>
00026 
00027 #include "elementvisitor.h"
00028 #include "formulacursor.h"
00029 #include "formulaelement.h"
00030 #include "kformulacommand.h"
00031 #include "rootelement.h"
00032 #include "sequenceelement.h"
00033 
00034 KFORMULA_NAMESPACE_BEGIN
00035 
00036 
00037 class RootSequenceElement : public SequenceElement {
00038     typedef SequenceElement inherited;
00039 public:
00040 
00041     RootSequenceElement( BasicElement* parent = 0 ) : SequenceElement( parent ) {}
00042     virtual RootSequenceElement* clone() {
00043         return new RootSequenceElement( *this );
00044     }
00045 
00054     virtual KCommand* buildCommand( Container*, Request* );
00055 };
00056 
00057 
00058 KCommand* RootSequenceElement::buildCommand( Container* container, Request* request )
00059 {
00060     FormulaCursor* cursor = container->activeCursor();
00061     if ( cursor->isReadOnly() ) {
00062         return 0;
00063     }
00064 
00065     switch ( *request ) {
00066     case req_addIndex: {
00067         FormulaCursor* cursor = container->activeCursor();
00068         if ( cursor->isSelection() ||
00069              ( cursor->getPos() > 0 && cursor->getPos() < countChildren() ) ) {
00070             break;
00071         }
00072         IndexRequest* ir = static_cast<IndexRequest*>( request );
00073         if ( ir->index() == upperLeftPos ) {
00074             RootElement* element = static_cast<RootElement*>( getParent() );
00075             ElementIndexPtr index = element->getIndex();
00076             if ( !index->hasIndex() ) {
00077                 KFCAddGenericIndex* command = new KFCAddGenericIndex( container, index );
00078                 return command;
00079             }
00080             else {
00081                 index->moveToIndex( cursor, afterCursor );
00082                 cursor->setSelection( false );
00083                 formula()->cursorHasMoved( cursor );
00084                 return 0;
00085             }
00086         }
00087     }
00088     default:
00089         break;
00090     }
00091     return inherited::buildCommand( container, request );
00092 }
00093 
00094 
00095 RootElement::RootElement(BasicElement* parent)
00096     : BasicElement(parent)
00097 {
00098     content = new RootSequenceElement( this );
00099     index = 0;
00100 }
00101 
00102 RootElement::~RootElement()
00103 {
00104     delete index;
00105     delete content;
00106 }
00107 
00108 
00109 RootElement::RootElement( const RootElement& other )
00110     : BasicElement( other )
00111 {
00112     content = new RootSequenceElement( *dynamic_cast<RootSequenceElement*>( other.content ) );
00113     if ( other.index ) {
00114         index = new SequenceElement( *( other.index ) );
00115         index->setParent( this );
00116     }
00117     else {
00118         index = 0;
00119     }
00120 }
00121 
00122 
00123 bool RootElement::accept( ElementVisitor* visitor )
00124 {
00125     return visitor->visit( this );
00126 }
00127 
00128 
00129 void RootElement::entered( SequenceElement* child )
00130 {
00131     if ( child == content ) {
00132         formula()->tell( i18n( "Main list of root" ) );
00133     }
00134     else {
00135         formula()->tell( i18n( "Index" ) );
00136     }
00137 }
00138 
00139 
00140 BasicElement* RootElement::goToPos( FormulaCursor* cursor, bool& handled,
00141                                     const LuPixelPoint& point, const LuPixelPoint& parentOrigin)
00142 {
00143     BasicElement* e = BasicElement::goToPos(cursor, handled, point, parentOrigin);
00144     if (e != 0) {
00145         LuPixelPoint myPos(parentOrigin.x() + getX(),
00146                            parentOrigin.y() + getY());
00147 
00148         e = content->goToPos(cursor, handled, point, myPos);
00149         if (e != 0) {
00150             return e;
00151         }
00152         if (hasIndex()) {
00153             e = index->goToPos(cursor, handled, point, myPos);
00154             if (e != 0) {
00155                 return e;
00156             }
00157         }
00158 
00159         //int dx = point.x() - myPos.x();
00160         luPixel dy = point.y() - myPos.y();
00161 
00162         // the position after the index
00163         if (hasIndex()) {
00164             if (dy < index->getHeight()) {
00165                 index->moveLeft(cursor, this);
00166                 handled = true;
00167                 return index;
00168             }
00169         }
00170 
00171         return this;
00172     }
00173     return 0;
00174 }
00175 
00176 
00181 void RootElement::calcSizes(const ContextStyle& style, ContextStyle::TextStyle tstyle, ContextStyle::IndexStyle istyle)
00182 {
00183     content->calcSizes(style, tstyle,
00184                style.convertIndexStyleLower(istyle));
00185 
00186     luPixel indexWidth = 0;
00187     luPixel indexHeight = 0;
00188     if (hasIndex()) {
00189     index->calcSizes(style,
00190              style.convertTextStyleIndex(tstyle),
00191              style.convertIndexStyleUpper(istyle));
00192         indexWidth = index->getWidth();
00193         indexHeight = index->getHeight();
00194     }
00195 
00196     luPixel distX = style.ptToPixelX( style.getThinSpace( tstyle ) );
00197     luPixel distY = style.ptToPixelY( style.getThinSpace( tstyle ) );
00198     luPixel unit = (content->getHeight() + distY)/ 3;
00199 
00200     if (hasIndex()) {
00201         if (indexWidth > unit) {
00202             index->setX(0);
00203             rootOffset.setX( indexWidth - unit );
00204         }
00205         else {
00206             index->setX( ( unit - indexWidth )/2 );
00207             rootOffset.setX(0);
00208         }
00209         if (indexHeight > unit) {
00210             index->setY(0);
00211             rootOffset.setY( indexHeight - unit );
00212         }
00213         else {
00214             index->setY( unit - indexHeight );
00215             rootOffset.setY(0);
00216         }
00217     }
00218     else {
00219         rootOffset.setX(0);
00220         rootOffset.setY(0);
00221     }
00222 
00223     setWidth( content->getWidth() + unit+unit/3+ rootOffset.x() + distX/2 );
00224     setHeight( content->getHeight() + distY*2 + rootOffset.y() );
00225 
00226     content->setX( rootOffset.x() + unit+unit/3 );
00227     content->setY( rootOffset.y() + distY );
00228     setBaseline(content->getBaseline() + content->getY());
00229 }
00230 
00236 void RootElement::draw( QPainter& painter, const LuPixelRect& r,
00237                         const ContextStyle& style,
00238                         ContextStyle::TextStyle tstyle,
00239                         ContextStyle::IndexStyle istyle,
00240                         const LuPixelPoint& parentOrigin )
00241 {
00242     LuPixelPoint myPos( parentOrigin.x()+getX(), parentOrigin.y()+getY() );
00243     //if ( !LuPixelRect( myPos.x(), myPos.y(), getWidth(), getHeight() ).intersects( r ) )
00244     //    return;
00245 
00246     content->draw(painter, r, style, tstyle,
00247           style.convertIndexStyleLower(istyle), myPos);
00248     if (hasIndex()) {
00249         index->draw(painter, r, style,
00250             style.convertTextStyleIndex(tstyle),
00251             style.convertIndexStyleUpper(istyle), myPos);
00252     }
00253 
00254     luPixel x = myPos.x() + rootOffset.x();
00255     luPixel y = myPos.y() + rootOffset.y();
00256     //int distX = style.getDistanceX(tstyle);
00257     luPixel distY = style.ptToPixelY( style.getThinSpace( tstyle ) );
00258     luPixel unit = (content->getHeight() + distY)/ 3;
00259 
00260     painter.setPen( QPen( style.getDefaultColor(),
00261                           style.layoutUnitToPixelX( 2*style.getLineWidth() ) ) );
00262     painter.drawLine( style.layoutUnitToPixelX( x+unit/3 ),
00263                       style.layoutUnitToPixelY( y+unit+distY/3 ),
00264                       style.layoutUnitToPixelX( x+unit/2+unit/3 ),
00265                       style.layoutUnitToPixelY( myPos.y()+getHeight() ) );
00266 
00267     painter.setPen( QPen( style.getDefaultColor(),
00268                           style.layoutUnitToPixelY( style.getLineWidth() ) ) );
00269 
00270     painter.drawLine( style.layoutUnitToPixelX( x+unit+unit/3 ),
00271                       style.layoutUnitToPixelY( y+distY/3 ),
00272                       style.layoutUnitToPixelX( x+unit/2+unit/3 ),
00273                       style.layoutUnitToPixelY( myPos.y()+getHeight() ) );
00274     painter.drawLine( style.layoutUnitToPixelX( x+unit+unit/3 ),
00275                       style.layoutUnitToPixelY( y+distY/3 ),
00276                       style.layoutUnitToPixelX( x+unit+unit/3+content->getWidth() ),
00277                       style.layoutUnitToPixelY( y+distY/3 ) );
00278     painter.drawLine( style.layoutUnitToPixelX( x+unit/3 ),
00279                       style.layoutUnitToPixelY( y+unit+distY/2 ),
00280                       style.layoutUnitToPixelX( x ),
00281                       style.layoutUnitToPixelY( y+unit+unit/2 ) );
00282 }
00283 
00284 
00285 void RootElement::dispatchFontCommand( FontCommand* cmd )
00286 {
00287     content->dispatchFontCommand( cmd );
00288     if (hasIndex()) {
00289         index->dispatchFontCommand( cmd );
00290     }
00291 }
00292 
00298 void RootElement::moveLeft(FormulaCursor* cursor, BasicElement* from)
00299 {
00300     if (cursor->isSelectionMode()) {
00301         getParent()->moveLeft(cursor, this);
00302     }
00303     else {
00304         bool linear = cursor->getLinearMovement();
00305         if (from == getParent()) {
00306             content->moveLeft(cursor, this);
00307         }
00308         else if (from == content) {
00309             if (linear && hasIndex()) {
00310                 index->moveLeft(cursor, this);
00311             }
00312             else {
00313                 getParent()->moveLeft(cursor, this);
00314             }
00315         }
00316         else {
00317             getParent()->moveLeft(cursor, this);
00318         }
00319     }
00320 }
00321 
00327 void RootElement::moveRight(FormulaCursor* cursor, BasicElement* from)
00328 {
00329     if (cursor->isSelectionMode()) {
00330         getParent()->moveRight(cursor, this);
00331     }
00332     else {
00333         bool linear = cursor->getLinearMovement();
00334         if (from == getParent()) {
00335             if (linear && hasIndex()) {
00336                 index->moveRight(cursor, this);
00337             }
00338             else {
00339                 content->moveRight(cursor, this);
00340             }
00341         }
00342         else if (from == index) {
00343             content->moveRight(cursor, this);
00344         }
00345         else {
00346             getParent()->moveRight(cursor, this);
00347         }
00348     }
00349 }
00350 
00356 void RootElement::moveUp(FormulaCursor* cursor, BasicElement* from)
00357 {
00358     if (cursor->isSelectionMode()) {
00359         getParent()->moveUp(cursor, this);
00360     }
00361     else {
00362         if (from == getParent()) {
00363             content->moveRight(cursor, this);
00364         }
00365         else if (from == content) {
00366             if (hasIndex()) {
00367                 index->moveRight(cursor, this);
00368             }
00369             else {
00370                 getParent()->moveUp(cursor, this);
00371             }
00372         }
00373         else {
00374             getParent()->moveUp(cursor, this);
00375         }
00376     }
00377 }
00378 
00384 void RootElement::moveDown(FormulaCursor* cursor, BasicElement* from)
00385 {
00386     if (cursor->isSelectionMode()) {
00387         getParent()->moveDown(cursor, this);
00388     }
00389     else {
00390         if (from == getParent()) {
00391             if (hasIndex()) {
00392                 index->moveRight(cursor, this);
00393             }
00394             else {
00395                 content->moveRight(cursor, this);
00396             }
00397         }
00398         else if (from == index) {
00399             content->moveRight(cursor, this);
00400         }
00401         else {
00402             getParent()->moveDown(cursor, this);
00403         }
00404     }
00405 }
00406 
00410 void RootElement::insert(FormulaCursor* cursor,
00411                          QPtrList<BasicElement>& newChildren,
00412                          Direction direction)
00413 {
00414     if (cursor->getPos() == upperLeftPos) {
00415         index = static_cast<SequenceElement*>(newChildren.take(0));
00416         index->setParent(this);
00417 
00418         if (direction == beforeCursor) {
00419             index->moveLeft(cursor, this);
00420         }
00421         else {
00422             index->moveRight(cursor, this);
00423         }
00424         cursor->setSelection(false);
00425         formula()->changed();
00426     }
00427 }
00428 
00435 void RootElement::remove(FormulaCursor* cursor,
00436                          QPtrList<BasicElement>& removedChildren,
00437                          Direction direction)
00438 {
00439     switch (cursor->getPos()) {
00440     case contentPos:
00441         getParent()->selectChild(cursor, this);
00442         getParent()->remove(cursor, removedChildren, direction);
00443         break;
00444     case upperLeftPos:
00445         removedChildren.append(index);
00446         formula()->elementRemoval(index);
00447         index = 0;
00448         cursor->setTo(this, upperLeftPos);
00449         formula()->changed();
00450         break;
00451     }
00452 }
00453 
00454 
00459 void RootElement::normalize(FormulaCursor* cursor, Direction direction)
00460 {
00461     if (direction == beforeCursor) {
00462         content->moveLeft(cursor, this);
00463     }
00464     else {
00465         content->moveRight(cursor, this);
00466     }
00467 }
00468 
00469 
00470 // main child
00471 //
00472 // If an element has children one has to become the main one.
00473 
00474 SequenceElement* RootElement::getMainChild()
00475 {
00476     return content;
00477 }
00478 
00479 // void RootElement::setMainChild(SequenceElement* child)
00480 // {
00481 //     formula()->elementRemoval(content);
00482 //     content = child;
00483 //     content->setParent(this);
00484 //     formula()->changed();
00485 // }
00486 
00487 
00492 void RootElement::selectChild(FormulaCursor* cursor, BasicElement* child)
00493 {
00494     if (child == content) {
00495         cursor->setTo(this, contentPos);
00496     }
00497     else if (child == index) {
00498         cursor->setTo(this, upperLeftPos);
00499     }
00500 }
00501 
00502 
00503 void RootElement::moveToIndex(FormulaCursor* cursor, Direction direction)
00504 {
00505     if (hasIndex()) {
00506         if (direction == beforeCursor) {
00507             index->moveLeft(cursor, this);
00508         }
00509         else {
00510             index->moveRight(cursor, this);
00511         }
00512     }
00513 }
00514 
00515 void RootElement::setToIndex(FormulaCursor* cursor)
00516 {
00517     cursor->setTo(this, upperLeftPos);
00518 }
00519 
00520 
00524 void RootElement::writeDom(QDomElement element)
00525 {
00526     BasicElement::writeDom(element);
00527 
00528     QDomDocument doc = element.ownerDocument();
00529 
00530     QDomElement con = doc.createElement("CONTENT");
00531     con.appendChild(content->getElementDom(doc));
00532     element.appendChild(con);
00533 
00534     if(hasIndex()) {
00535         QDomElement ind = doc.createElement("ROOTINDEX");
00536         ind.appendChild(index->getElementDom(doc));
00537         element.appendChild(ind);
00538     }
00539 }
00540 
00545 bool RootElement::readAttributesFromDom(QDomElement element)
00546 {
00547     return BasicElement::readAttributesFromDom(element);
00548 }
00549 
00555 bool RootElement::readContentFromDom(QDomNode& node)
00556 {
00557     if (!BasicElement::readContentFromDom(node)) {
00558         return false;
00559     }
00560 
00561     if ( !buildChild( content, node, "CONTENT" ) ) {
00562         kdWarning( DEBUGID ) << "Empty content in RootElement." << endl;
00563         return false;
00564     }
00565     node = node.nextSibling();
00566 
00567     if ( node.nodeName().upper() == "ROOTINDEX" ) {
00568         if ( !buildChild( index=new SequenceElement( this ), node, "ROOTINDEX" ) ) {
00569             return false;
00570         }
00571     }
00572     // backward compatibility
00573     else if ( node.nodeName().upper() == "INDEX" ) {
00574         if ( !buildChild( index=new SequenceElement( this ), node, "INDEX" ) ) {
00575             return false;
00576         }
00577     }
00578     node = node.nextSibling();
00579 
00580     return true;
00581 }
00582 
00583 QString RootElement::toLatex()
00584 {
00585     QString root;
00586     root="\\sqrt";
00587     if(hasIndex()) {
00588         root+="[";
00589     root+=index->toLatex();
00590     root+="]";
00591     }
00592     root+="{";
00593     root+=content->toLatex();
00594     root+="}";
00595 
00596     return root;
00597 }
00598 
00599 QString RootElement::formulaString()
00600 {
00601     if ( hasIndex() ) {
00602         return "(" + content->formulaString() + ")**(1.0/(" + index->formulaString() + "))";
00603     }
00604     return "sqrt(" + content->formulaString() + ")";
00605 }
00606 
00607 void RootElement::writeMathML( QDomDocument& doc, QDomNode parent, bool oasisFormat )
00608 {
00609     QDomElement de;
00610 
00611     if( hasIndex() )
00612         de = doc.createElement( oasisFormat ? "math:mroot" : "mroot" );
00613     else
00614         de = doc.createElement( oasisFormat ? "math:msqrt" : "msqrt" );
00615 
00616     content->writeMathML( doc, de, oasisFormat );
00617 
00618     if( hasIndex() )
00619     {
00620         index->writeMathML( doc, de, oasisFormat );
00621     }
00622 
00623     parent.appendChild( de );
00624 }
00625 
00626 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