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 )
00464 {
00465
QDomElement de = doc.createElement(
"mfrac" );
00466
if ( !withLine )
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