00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
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
00155
00156
00157 numerator->draw(painter, r, style,
00158 style.convertTextStyleFraction( tstyle ),
00159 style.convertIndexStyleUpper( istyle ), myPos);
00160 if (denominator) {
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
00355
00356
00357
00358 SequenceElement* FractionElement::getMainChild()
00359 {
00360 return numerator;
00361 }
00362
00363
00364
00365
00366
00367
00368
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, bool oasisFormat )
00464 {
00465 QDomElement de = doc.createElement( oasisFormat ? "math:mfrac": "mfrac" );
00466 if ( !withLine )
00467 de.setAttribute( "linethickness", 0 );
00468 numerator->writeMathML( doc, de, oasisFormat );
00469 denominator->writeMathML( doc, de, oasisFormat );
00470 parent.appendChild( de );
00471 }
00472
00473 KFORMULA_NAMESPACE_END