lib Library API Documentation

fractionelement.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 
00023 #include <kdebug.h>
00024 #include <klocale.h>
00025 
00026 #include "elementvisitor.h"
00027 #include "formulaelement.h"
00028 #include "formulacursor.h"
00029 #include "fractionelement.h"
00030 #include "sequenceelement.h"
00031 
00032 KFORMULA_NAMESPACE_BEGIN
00033 using namespace std;
00034 
00035 FractionElement::FractionElement(BasicElement* parent)
00036         : BasicElement(parent), withLine(true)
00037 {
00038     numerator = new SequenceElement(this);
00039     denominator = new SequenceElement(this);
00040 }
00041 
00042 FractionElement::~FractionElement()
00043 {
00044     delete denominator;
00045     delete numerator;
00046 }
00047 
00048 FractionElement::FractionElement( const FractionElement& other )
00049     : BasicElement( other ), withLine( other.withLine )
00050 {
00051     numerator = new SequenceElement( *( other.numerator ) );
00052     denominator = new SequenceElement( *( other.denominator ) );
00053     numerator->setParent( this );
00054     denominator->setParent( this );
00055 }
00056 
00057 
00058 bool FractionElement::accept( ElementVisitor* visitor )
00059 {
00060     return visitor->visit( this );
00061 }
00062 
00063 void FractionElement::entered( SequenceElement* child )
00064 {
00065     if ( child == numerator ) {
00066         formula()->tell( i18n( "Numerator" ) );
00067     }
00068     else {
00069         formula()->tell( i18n( "Denominator" ) );
00070     }
00071 }
00072 
00073 
00074 BasicElement* FractionElement::goToPos( FormulaCursor* cursor, bool& handled,
00075                                         const LuPixelPoint& point, const LuPixelPoint& parentOrigin )
00076 {
00077     BasicElement* e = BasicElement::goToPos(cursor, handled, point, parentOrigin);
00078     if (e != 0) {
00079         LuPixelPoint myPos(parentOrigin.x() + getX(),
00080                            parentOrigin.y() + getY());
00081         e = numerator->goToPos(cursor, handled, point, myPos);
00082         if (e != 0) {
00083             return e;
00084         }
00085         e = denominator->goToPos(cursor, handled, point, myPos);
00086         if (e != 0) {
00087             return e;
00088         }
00089 
00090         luPixel dx = point.x() - myPos.x();
00091         luPixel dy = point.y() - myPos.y();
00092 
00093         // the positions after the numerator / denominator
00094         if ((dx > numerator->getX()) &&
00095             (dy < numerator->getHeight())) {
00096             numerator->moveLeft(cursor, this);
00097             handled = true;
00098             return numerator;
00099         }
00100         else if ((dx > denominator->getX()) &&
00101                  (dy > denominator->getY())) {
00102             denominator->moveLeft(cursor, this);
00103             handled = true;
00104             return denominator;
00105         }
00106 
00107         return this;
00108     }
00109     return 0;
00110 }
00111 
00112 
00117 void FractionElement::calcSizes(const ContextStyle& style, ContextStyle::TextStyle tstyle, ContextStyle::IndexStyle istyle)
00118 {
00119     ContextStyle::TextStyle i_tstyle = style.convertTextStyleFraction( tstyle );
00120     ContextStyle::IndexStyle u_istyle = style.convertIndexStyleUpper( istyle );
00121     ContextStyle::IndexStyle l_istyle = style.convertIndexStyleLower( istyle );
00122 
00123     numerator->calcSizes( style, i_tstyle, u_istyle );
00124     denominator->calcSizes( style, i_tstyle, l_istyle );
00125 
00126     luPixel distY = style.ptToPixelY( style.getThinSpace( tstyle ) );
00127 
00128     setWidth( QMAX( numerator->getWidth(), denominator->getWidth() ) );
00129     setHeight( numerator->getHeight() + denominator->getHeight() +
00130                2*distY + style.getLineWidth() );
00131     setBaseline( qRound( numerator->getHeight() + distY + .5*style.getLineWidth() +
00132                  style.axisHeight( tstyle ) ) );
00133 
00134     numerator->setX( ( getWidth() - numerator->getWidth() ) / 2 );
00135     denominator->setX( ( getWidth() - denominator->getWidth() ) / 2 );
00136 
00137     numerator->setY( 0 );
00138     denominator->setY( getHeight() - denominator->getHeight() );
00139 }
00140 
00141 
00147 void FractionElement::draw( QPainter& painter, const LuPixelRect& r,
00148                             const ContextStyle& style,
00149                             ContextStyle::TextStyle tstyle,
00150                             ContextStyle::IndexStyle istyle,
00151                             const LuPixelPoint& parentOrigin )
00152 {
00153     LuPixelPoint myPos( parentOrigin.x()+getX(), parentOrigin.y()+getY() );
00154     //if ( !LuPixelRect( myPos.x(), myPos.y(), getWidth(), getHeight() ).intersects( r ) )
00155     //    return;
00156 
00157     numerator->draw(painter, r, style,
00158             style.convertTextStyleFraction( tstyle ),
00159             style.convertIndexStyleUpper( istyle ), myPos);
00160     if (denominator) { // Can be temporarily 0 see FractionElement::remove
00161         denominator->draw(painter, r, style,
00162               style.convertTextStyleFraction( tstyle ),
00163               style.convertIndexStyleLower( istyle ), myPos);
00164     }
00165 
00166     if ( withLine ) {
00167         painter.setPen( QPen( style.getDefaultColor(),
00168                               style.layoutUnitToPixelY( style.getLineWidth() ) ) );
00169         painter.drawLine( style.layoutUnitToPixelX( myPos.x() ),
00170                           style.layoutUnitToPixelY( myPos.y() + axis( style, tstyle ) ),
00171                           style.layoutUnitToPixelX( myPos.x() + getWidth() ),
00172                           style.layoutUnitToPixelY( myPos.y() + axis( style, tstyle ) ) );
00173     }
00174 }
00175 
00176 
00177 void FractionElement::dispatchFontCommand( FontCommand* cmd )
00178 {
00179     numerator->dispatchFontCommand( cmd );
00180     denominator->dispatchFontCommand( cmd );
00181 }
00182 
00188 void FractionElement::moveLeft(FormulaCursor* cursor, BasicElement* from)
00189 {
00190     if (cursor->isSelectionMode()) {
00191         getParent()->moveLeft(cursor, this);
00192     }
00193     else {
00194         bool linear = cursor->getLinearMovement();
00195         if (from == getParent()) {
00196             if (linear) {
00197                 denominator->moveLeft(cursor, this);
00198             }
00199             else {
00200                 numerator->moveLeft(cursor, this);
00201             }
00202         }
00203         else if (from == denominator) {
00204             numerator->moveLeft(cursor, this);
00205         }
00206         else {
00207             getParent()->moveLeft(cursor, this);
00208         }
00209     }
00210 }
00211 
00212 
00218 void FractionElement::moveRight(FormulaCursor* cursor, BasicElement* from)
00219 {
00220     if (cursor->isSelectionMode()) {
00221         getParent()->moveRight(cursor, this);
00222     }
00223     else {
00224         bool linear = cursor->getLinearMovement();
00225         if (from == getParent()) {
00226             numerator->moveRight(cursor, this);
00227         }
00228         else if (from == numerator) {
00229             if (linear) {
00230                 denominator->moveRight(cursor, this);
00231             }
00232             else {
00233                 getParent()->moveRight(cursor, this);
00234             }
00235         }
00236         else {
00237             getParent()->moveRight(cursor, this);
00238         }
00239     }
00240 }
00241 
00242 
00248 void FractionElement::moveUp(FormulaCursor* cursor, BasicElement* from)
00249 {
00250     if (cursor->isSelectionMode()) {
00251         getParent()->moveUp(cursor, this);
00252     }
00253     else {
00254         if (from == getParent()) {
00255             denominator->moveRight(cursor, this);
00256         }
00257         else if (from == denominator) {
00258             numerator->moveRight(cursor, this);
00259         }
00260         else {
00261             getParent()->moveUp(cursor, this);
00262         }
00263     }
00264 }
00265 
00266 
00272 void FractionElement::moveDown(FormulaCursor* cursor, BasicElement* from)
00273 {
00274     if (cursor->isSelectionMode()) {
00275         getParent()->moveDown(cursor, this);
00276     }
00277     else {
00278         if (from == getParent()) {
00279             numerator->moveRight(cursor, this);
00280         }
00281         else if (from == numerator) {
00282             denominator->moveRight(cursor, this);
00283         }
00284         else {
00285             getParent()->moveDown(cursor, this);
00286         }
00287     }
00288 }
00289 
00290 
00294 void FractionElement::insert(FormulaCursor* cursor,
00295                              QPtrList<BasicElement>& newChildren,
00296                              Direction direction)
00297 {
00298     if (cursor->getPos() == denominatorPos) {
00299         denominator = static_cast<SequenceElement*>(newChildren.take(0));
00300         denominator->setParent(this);
00301 
00302         if (direction == beforeCursor) {
00303             denominator->moveLeft(cursor, this);
00304         }
00305         else {
00306             denominator->moveRight(cursor, this);
00307         }
00308         cursor->setSelection(false);
00309         formula()->changed();
00310     }
00311 }
00312 
00313 
00323 void FractionElement::remove(FormulaCursor* cursor,
00324                              QPtrList<BasicElement>& removedChildren,
00325                              Direction direction)
00326 {
00327     switch (cursor->getPos()) {
00328     case numeratorPos:
00329         getParent()->selectChild(cursor, this);
00330         getParent()->remove(cursor, removedChildren, direction);
00331         break;
00332     case denominatorPos:
00333         removedChildren.append(denominator);
00334         formula()->elementRemoval(denominator);
00335         denominator = 0;
00336         cursor->setTo(this, denominatorPos);
00337         formula()->changed();
00338         break;
00339     }
00340 }
00341 
00342 
00348 bool FractionElement::isSenseless()
00349 {
00350     return denominator == 0;
00351 }
00352 
00353 
00354 // main child
00355 //
00356 // If an element has children one has to become the main one.
00357 
00358 SequenceElement* FractionElement::getMainChild()
00359 {
00360     return numerator;
00361 }
00362 
00363 // void FractionElement::setMainChild(SequenceElement* child)
00364 // {
00365 //     formula()->elementRemoval(numerator);
00366 //     numerator = child;
00367 //     numerator->setParent(this);
00368 //     formula()->changed();
00369 // }
00370 
00371 
00376 void FractionElement::selectChild(FormulaCursor* cursor, BasicElement* child)
00377 {
00378     if (child == numerator) {
00379         cursor->setTo(this, numeratorPos);
00380     }
00381     else if (child == denominator) {
00382         cursor->setTo(this, denominatorPos);
00383     }
00384 }
00385 
00386 
00390 void FractionElement::writeDom(QDomElement element)
00391 {
00392     BasicElement::writeDom(element);
00393 
00394     QDomDocument doc = element.ownerDocument();
00395     if (!withLine) element.setAttribute("NOLINE", 1);
00396 
00397     QDomElement num = doc.createElement("NUMERATOR");
00398     num.appendChild(numerator->getElementDom(doc));
00399     element.appendChild(num);
00400 
00401     QDomElement den = doc.createElement("DENOMINATOR");
00402     den.appendChild(denominator->getElementDom(doc));
00403     element.appendChild(den);
00404 }
00405 
00410 bool FractionElement::readAttributesFromDom(QDomElement element)
00411 {
00412     if (!BasicElement::readAttributesFromDom(element)) {
00413         return false;
00414     }
00415     QString lineStr = element.attribute("NOLINE");
00416     if(!lineStr.isNull()) {
00417         withLine = lineStr.toInt() == 0;
00418     }
00419     return true;
00420 }
00421 
00427 bool FractionElement::readContentFromDom(QDomNode& node)
00428 {
00429     if (!BasicElement::readContentFromDom(node)) {
00430         return false;
00431     }
00432 
00433     if ( !buildChild( numerator, node, "NUMERATOR" ) ) {
00434         kdWarning( DEBUGID ) << "Empty numerator in FractionElement." << endl;
00435         return false;
00436     }
00437     node = node.nextSibling();
00438 
00439     if ( !buildChild( denominator, node, "DENOMINATOR" ) ) {
00440         kdWarning( DEBUGID ) << "Empty denominator in FractionElement." << endl;
00441         return false;
00442     }
00443     node = node.nextSibling();
00444 
00445     return true;
00446 }
00447 
00448 QString FractionElement::toLatex()
00449 {
00450     if ( withLine ) {
00451         return "\\frac" + numerator->toLatex() + denominator->toLatex();
00452     }
00453     else {
00454         return "{" + numerator->toLatex() + "\\atop " + denominator->toLatex() + "}";
00455     }
00456 }
00457 
00458 QString FractionElement::formulaString()
00459 {
00460     return "(" + numerator->formulaString() + ")/(" + denominator->formulaString() + ")";
00461 }
00462 
00463 void FractionElement::writeMathML( QDomDocument doc, QDomNode parent )
00464 {
00465     QDomElement de = doc.createElement( "mfrac" );
00466     if ( !withLine ) // why is this no function?
00467         de.setAttribute( "linethickness", 0 );
00468     numerator->writeMathML( doc, de );
00469     denominator->writeMathML( doc, de );
00470     parent.appendChild( de );
00471 }
00472 
00473 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:39 2005 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003