00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
#include <qptrlist.h>
00022
#include <qpainter.h>
00023
#include <qpen.h>
00024
#include <qpointarray.h>
00025
00026
#include <kdebug.h>
00027
#include <klocale.h>
00028
00029
#include "bracketelement.h"
00030
#include "elementvisitor.h"
00031
#include "fontstyle.h"
00032
#include "formulacursor.h"
00033
#include "formulaelement.h"
00034
#include "sequenceelement.h"
00035
00036 KFORMULA_NAMESPACE_BEGIN
00037
00038 SingleContentElement::SingleContentElement(
BasicElement* parent )
00039 :
BasicElement( parent )
00040 {
00041 content =
new SequenceElement(
this );
00042 }
00043
00044
00045 SingleContentElement::SingleContentElement(
const SingleContentElement& other )
00046 :
BasicElement( other )
00047 {
00048 content =
new SequenceElement( other.
content );
00049 content->setParent(
this );
00050 }
00051
00052
00053 SingleContentElement::~SingleContentElement()
00054 {
00055
delete content;
00056 }
00057
00058
00059 QChar SingleContentElement::getCharacter()
const
00060
{
00061
00062
00063
00064
if ( content->
isTextOnly() ) {
00065
return '\\';
00066 }
00067
return content->
getCharacter();
00068 }
00069
00070 BasicElement*
SingleContentElement::goToPos(
FormulaCursor* cursor,
bool& handled,
00071
const LuPixelPoint& point,
const LuPixelPoint& parentOrigin )
00072 {
00073
BasicElement* e = BasicElement::goToPos(cursor, handled, point, parentOrigin);
00074
if (e != 0) {
00075
LuPixelPoint myPos(parentOrigin.x() + getX(),
00076 parentOrigin.y() + getY());
00077
00078 e = content->
goToPos(cursor, handled, point, myPos);
00079
if (e != 0) {
00080
return e;
00081 }
00082
return this;
00083 }
00084
return 0;
00085 }
00086
00087 void SingleContentElement::dispatchFontCommand(
FontCommand* cmd )
00088 {
00089 content->
dispatchFontCommand( cmd );
00090 }
00091
00092 void SingleContentElement::moveLeft(
FormulaCursor* cursor,
BasicElement* from)
00093 {
00094
if (cursor->
isSelectionMode()) {
00095 getParent()->
moveLeft(cursor,
this);
00096 }
00097
else {
00098
00099
if (from == getParent()) {
00100 content->
moveLeft(cursor,
this);
00101 }
00102
else {
00103 getParent()->moveLeft(cursor,
this);
00104 }
00105 }
00106 }
00107
00108 void SingleContentElement::moveRight(
FormulaCursor* cursor,
BasicElement* from)
00109 {
00110
if (cursor->
isSelectionMode()) {
00111 getParent()->
moveRight(cursor,
this);
00112 }
00113
else {
00114
00115
if (from == getParent()) {
00116 content->
moveRight(cursor,
this);
00117 }
00118
else {
00119 getParent()->moveRight(cursor,
this);
00120 }
00121 }
00122 }
00123
00124 void SingleContentElement::moveUp(
FormulaCursor* cursor,
BasicElement* )
00125 {
00126 getParent()->
moveUp(cursor,
this);
00127 }
00128
00129 void SingleContentElement::moveDown(
FormulaCursor* cursor,
BasicElement* )
00130 {
00131 getParent()->
moveDown(cursor,
this);
00132 }
00133
00134 void SingleContentElement::remove(
FormulaCursor* cursor,
00135
QPtrList<BasicElement>& removedChildren,
00136 Direction direction )
00137 {
00138
switch (cursor->
getPos()) {
00139
case contentPos:
00140
BasicElement* parent = getParent();
00141 parent->
selectChild(cursor,
this);
00142 parent->
remove(cursor, removedChildren, direction);
00143 }
00144 }
00145
00146 void SingleContentElement::normalize(
FormulaCursor* cursor, Direction direction )
00147 {
00148
if (direction == beforeCursor) {
00149 content->
moveLeft(cursor,
this);
00150 }
00151
else {
00152 content->
moveRight(cursor,
this);
00153 }
00154 }
00155
00156 SequenceElement*
SingleContentElement::getMainChild()
00157 {
00158
return content;
00159 }
00160
00161 void SingleContentElement::selectChild(
FormulaCursor* cursor,
BasicElement* child)
00162 {
00163
if (child == content) {
00164 cursor->
setTo(
this, contentPos);
00165 }
00166 }
00167
00168 void SingleContentElement::writeDom(
QDomElement element)
00169 {
00170 BasicElement::writeDom(element);
00171
00172
QDomDocument doc = element.ownerDocument();
00173
00174
QDomElement con = doc.createElement(
"CONTENT");
00175 con.appendChild(content->
getElementDom(doc));
00176 element.appendChild(con);
00177 }
00178
00179 bool SingleContentElement::readContentFromDom(
QDomNode& node)
00180 {
00181
if (!BasicElement::readContentFromDom(node)) {
00182
return false;
00183 }
00184
00185
if ( !buildChild( content, node,
"CONTENT" ) ) {
00186 kdWarning( DEBUGID ) <<
"Empty content in " <<
getTagName() << endl;
00187
return false;
00188 }
00189 node = node.nextSibling();
00190
00191
return true;
00192 }
00193
00194 void SingleContentElement::writeMathML(
QDomDocument doc,
QDomNode parent )
00195 {
00196 content->
writeMathML( doc, parent );
00197 }
00198
00199
00200
00201 BracketElement::BracketElement(SymbolType l, SymbolType r,
BasicElement* parent)
00202 :
SingleContentElement(parent),
00203 left( 0 ), right( 0 ),
00204 leftType( l ), rightType( r )
00205 {
00206 }
00207
00208
00209 BracketElement::~BracketElement()
00210 {
00211
delete left;
00212
delete right;
00213 }
00214
00215
00216 BracketElement::BracketElement(
const BracketElement& other )
00217 :
SingleContentElement( other ),
00218 left( 0 ), right( 0 ),
00219 leftType( other.leftType ), rightType( other.rightType )
00220 {
00221 }
00222
00223
00224 bool BracketElement::accept(
ElementVisitor* visitor )
00225 {
00226
return visitor->
visit(
this );
00227 }
00228
00229
00230 void BracketElement::entered(
SequenceElement* )
00231 {
00232
formula()->
tell( i18n(
"Delimited list" ) );
00233 }
00234
00235
00236 BasicElement*
BracketElement::goToPos(
FormulaCursor* cursor,
bool& handled,
00237
const LuPixelPoint& point,
const LuPixelPoint& parentOrigin )
00238 {
00239
BasicElement* e = BasicElement::goToPos(cursor, handled, point, parentOrigin);
00240
if (e != 0) {
00241
LuPixelPoint myPos(parentOrigin.x() + getX(),
00242 parentOrigin.y() + getY());
00243 e = getContent()->
goToPos(cursor, handled, point, myPos);
00244
if (e != 0) {
00245
return e;
00246 }
00247
00248
00249 luPixel dx = point.x() - myPos.x();
00250 luPixel dy = point.y() - myPos.y();
00251
00252
if ((dx > getContent()->getX()+getContent()->getWidth()) ||
00253 (dy > getContent()->getY()+getContent()->getHeight())) {
00254 getContent()->moveEnd(cursor);
00255 handled =
true;
00256
return getContent();
00257 }
00258
return this;
00259 }
00260
return 0;
00261 }
00262
00263
00268 void BracketElement::calcSizes(
const ContextStyle& style, ContextStyle::TextStyle tstyle, ContextStyle::IndexStyle istyle)
00269 {
00270
SequenceElement* content = getContent();
00271 content->
calcSizes(style, tstyle, istyle);
00272
00273
00274
delete left;
00275
delete right;
00276 left = style.fontStyle().createArtwork( leftType );
00277 right = style.fontStyle().createArtwork( rightType );
00278
00279
00280
if (content->
isTextOnly()) {
00281 left->calcSizes(style, tstyle);
00282 right->calcSizes(style, tstyle);
00283
00284 setBaseline(QMAX(content->
getBaseline(),
00285 QMAX(left->getBaseline(), right->getBaseline())));
00286
00287 content->
setY(getBaseline() - content->
getBaseline());
00288 left ->setY(getBaseline() - left ->getBaseline());
00289 right ->setY(getBaseline() - right ->getBaseline());
00290
00291
00292 setHeight(QMAX(content->
getY() + content->
getHeight(),
00293 QMAX(left ->getY() + left ->getHeight(),
00294 right->getY() + right->getHeight())));
00295 }
00296
else {
00297
00298 luPixel contentHeight = 2 * QMAX( content->
axis( style, tstyle ),
00299 content->
getHeight() - content->
axis( style, tstyle ) );
00300 left->calcSizes( style, tstyle, contentHeight );
00301 right->calcSizes( style, tstyle, contentHeight );
00302
00303
00304 setHeight(QMAX(contentHeight,
00305 QMAX(left->getHeight(), right->getHeight())));
00306
00307
00308 content->
setY(getHeight() / 2 - content->
axis( style, tstyle ));
00309 setBaseline(content->
getBaseline() + content->
getY());
00310
00311
if ( left->isNormalChar() ) {
00312 left->setY(getBaseline() - left->getBaseline());
00313 }
00314
else {
00315 left->setY((getHeight() - left->getHeight())/2);
00316 }
00317
if ( right->isNormalChar() ) {
00318 right->setY(getBaseline() - right->getBaseline());
00319 }
00320
else {
00321 right->setY((getHeight() - right->getHeight())/2);
00322 }
00323
00324
00325
00326
00327
00328
00329
00330
00331 }
00332
00333
00334 setWidth(left->getWidth() + content->
getWidth() + right->getWidth());
00335 content->
setX(left->getWidth());
00336 right ->setX(left->getWidth()+content->
getWidth());
00337 }
00338
00339
00345 void BracketElement::draw(
QPainter& painter,
const LuPixelRect& r,
00346
const ContextStyle& style,
00347 ContextStyle::TextStyle tstyle,
00348 ContextStyle::IndexStyle istyle,
00349
const LuPixelPoint& parentOrigin )
00350 {
00351
LuPixelPoint myPos( parentOrigin.x()+getX(), parentOrigin.y()+getY() );
00352
00353
00354
00355
SequenceElement* content = getContent();
00356 content->
draw(painter, r, style, tstyle, istyle, myPos);
00357
00358
if (content->
isTextOnly()) {
00359 left->draw(painter, r, style, tstyle, myPos);
00360 right->draw(painter, r, style, tstyle, myPos);
00361 }
00362
else {
00363 luPixel contentHeight = 2 * QMAX(content->
axis( style, tstyle ),
00364 content->
getHeight() - content->
axis( style, tstyle ));
00365 left->draw(painter, r, style, tstyle, contentHeight, myPos);
00366 right->draw(painter, r, style, tstyle, contentHeight, myPos);
00367 }
00368
00369
00370
#if 0
00371
painter.setBrush( Qt::NoBrush );
00372 painter.setPen( Qt::red );
00373 painter.drawRect( style.layoutUnitToPixelX( myPos.x()+left->getX() ),
00374 style.layoutUnitToPixelY( myPos.y()+left->getY() ),
00375 style.layoutUnitToPixelX( left->getWidth() ),
00376 style.layoutUnitToPixelY( left->getHeight() ) );
00377 painter.drawRect( style.layoutUnitToPixelX( myPos.x()+right->getX() ),
00378 style.layoutUnitToPixelY( myPos.y()+right->getY() ),
00379 style.layoutUnitToPixelX( right->getWidth() ),
00380 style.layoutUnitToPixelY( right->getHeight() ) );
00381
#endif
00382
}
00383
00384
00388 void BracketElement::writeDom(
QDomElement element)
00389 {
00390 SingleContentElement::writeDom(element);
00391 element.setAttribute(
"LEFT", leftType);
00392 element.setAttribute(
"RIGHT", rightType);
00393 }
00394
00399 bool BracketElement::readAttributesFromDom(
QDomElement element)
00400 {
00401
if (!BasicElement::readAttributesFromDom(element)) {
00402
return false;
00403 }
00404
QString leftStr = element.attribute(
"LEFT");
00405
if(!leftStr.isNull()) {
00406 leftType = static_cast<SymbolType>(leftStr.toInt());
00407 }
00408
QString rightStr = element.attribute(
"RIGHT");
00409
if(!rightStr.isNull()) {
00410 rightType = static_cast<SymbolType>(rightStr.toInt());
00411 }
00412
return true;
00413 }
00414
00415 QString BracketElement::toLatex()
00416 {
00417
QString ls,rs,cs;
00418 cs=getContent()->
toLatex();
00419 ls=
"\\left"+latexString(leftType);
00420 rs=
"\\right"+latexString(rightType);
00421
00422
return ls+cs+rs;
00423 }
00424
00425
QString BracketElement::latexString(
char type)
00426 {
00427
switch (type) {
00428
case ']':
00429
return "]";
00430
case '[':
00431
return "[";
00432
case '{':
00433
return "\\{";
00434
case '}':
00435
return "\\}";
00436
case '(':
00437
return "(";
00438
case ')':
00439
return ")";
00440
case '|':
00441
return "|";
00442
case '<':
00443
return "\\langle";
00444
case '>':
00445
return "\\rangle";
00446
case '/':
00447
return "/";
00448
case '\\':
00449
return "\\backslash";
00450 }
00451
return ".";
00452 }
00453
00454
QString BracketElement::formulaString()
00455 {
00456
return "(" + getContent()->
formulaString() +
")";
00457 }
00458
00459 void BracketElement::writeMathML(
QDomDocument doc,
QDomNode parent )
00460 {
00461
QDomElement de = doc.createElement(
"mfenced" );
00462
if ( left->getType() != LeftRoundBracket ||
00463 right->getType() != RightRoundBracket )
00464 {
00465 de.setAttribute(
"open",
QString(
QChar( leftType ) ) );
00466 de.setAttribute(
"close",
QString(
QChar( rightType ) ) );
00467 }
00468 SingleContentElement::writeMathML( doc, de );
00469 parent.appendChild( de );
00470 }
00471
00472
00473 OverlineElement::OverlineElement(
BasicElement* parent )
00474 :
SingleContentElement( parent )
00475 {
00476 }
00477
00478 OverlineElement::~OverlineElement()
00479 {
00480 }
00481
00482 OverlineElement::OverlineElement(
const OverlineElement& other )
00483 :
SingleContentElement( other )
00484 {
00485 }
00486
00487
00488 bool OverlineElement::accept(
ElementVisitor* visitor )
00489 {
00490
return visitor->
visit(
this );
00491 }
00492
00493
00494 void OverlineElement::entered(
SequenceElement* )
00495 {
00496
formula()->
tell( i18n(
"Overline" ) );
00497 }
00498
00499
00500 void OverlineElement::calcSizes(
const ContextStyle& style, ContextStyle::TextStyle tstyle, ContextStyle::IndexStyle istyle)
00501 {
00502
SequenceElement* content = getContent();
00503 content->
calcSizes(style, tstyle,
00504 style.convertIndexStyleLower(istyle));
00505
00506
00507 luPixel distY = style.ptToPixelY( style.getThinSpace( tstyle ) );
00508
00509
00510 setWidth( content->
getWidth() );
00511 setHeight( content->
getHeight() + distY );
00512
00513 content->
setX( 0 );
00514 content->
setY( distY );
00515 setBaseline(content->
getBaseline() + content->
getY());
00516 }
00517
00518 void OverlineElement::draw(
QPainter& painter,
const LuPixelRect& r,
00519
const ContextStyle& style,
00520 ContextStyle::TextStyle tstyle,
00521 ContextStyle::IndexStyle istyle,
00522
const LuPixelPoint& parentOrigin )
00523 {
00524
LuPixelPoint myPos( parentOrigin.x()+getX(), parentOrigin.y()+getY() );
00525
00526
00527
00528
SequenceElement* content = getContent();
00529 content->
draw( painter, r, style, tstyle,
00530 style.convertIndexStyleLower( istyle ), myPos );
00531
00532 luPixel x = myPos.x();
00533 luPixel y = myPos.y();
00534
00535 luPixel distY = style.ptToPixelY( style.getThinSpace( tstyle ) );
00536
00537
00538 painter.setPen(
QPen( style.getDefaultColor(),
00539 style.layoutUnitToPixelY( style.getLineWidth() ) ) );
00540
00541 painter.drawLine( style.layoutUnitToPixelX( x ),
00542 style.layoutUnitToPixelY( y+distY/3 ),
00543 style.layoutUnitToPixelX( x+content->
getWidth() ),
00544 style.layoutUnitToPixelY( y+distY/3 ) );
00545 }
00546
00547
00548 QString OverlineElement::toLatex()
00549 {
00550
return "\\overline{" + getContent()->
toLatex() +
"}";
00551 }
00552
00553
QString OverlineElement::formulaString()
00554 {
00555
return getContent()->
formulaString();
00556 }
00557
00558 void OverlineElement::writeMathML(
QDomDocument doc,
QDomNode parent )
00559 {
00560
QDomElement de = doc.createElement(
"mover" );
00561 SingleContentElement::writeMathML( doc, de );
00562
QDomElement op = doc.createElement(
"mo" );
00563
00564 op.appendChild( doc.createEntityReference(
"OverBar" ) );
00565 de.appendChild( op );
00566 parent.appendChild( de );
00567 }
00568
00569
00570 UnderlineElement::UnderlineElement(
BasicElement* parent )
00571 :
SingleContentElement( parent )
00572 {
00573 }
00574
00575 UnderlineElement::~UnderlineElement()
00576 {
00577 }
00578
00579
00580 UnderlineElement::UnderlineElement(
const UnderlineElement& other )
00581 :
SingleContentElement( other )
00582 {
00583 }
00584
00585
00586 bool UnderlineElement::accept(
ElementVisitor* visitor )
00587 {
00588
return visitor->
visit(
this );
00589 }
00590
00591
00592 void UnderlineElement::entered(
SequenceElement* )
00593 {
00594
formula()->
tell( i18n(
"Underline" ) );
00595 }
00596
00597
00598 void UnderlineElement::calcSizes(
const ContextStyle& style,
00599 ContextStyle::TextStyle tstyle,
00600 ContextStyle::IndexStyle istyle)
00601 {
00602
SequenceElement* content = getContent();
00603 content->
calcSizes(style, tstyle,
00604 style.convertIndexStyleLower(istyle));
00605
00606
00607 luPixel distY = style.ptToPixelY( style.getThinSpace( tstyle ) );
00608
00609
00610 setWidth( content->
getWidth() );
00611 setHeight( content->
getHeight() + distY );
00612
00613 content->
setX( 0 );
00614 content->
setY( 0 );
00615 setBaseline(content->
getBaseline() + content->
getY());
00616 }
00617
00618 void UnderlineElement::draw(
QPainter& painter,
const LuPixelRect& r,
00619
const ContextStyle& style,
00620 ContextStyle::TextStyle tstyle,
00621 ContextStyle::IndexStyle istyle,
00622
const LuPixelPoint& parentOrigin )
00623 {
00624
LuPixelPoint myPos( parentOrigin.x()+getX(), parentOrigin.y()+getY() );
00625
00626
00627
00628
SequenceElement* content = getContent();
00629 content->
draw( painter, r, style, tstyle,
00630 style.convertIndexStyleLower( istyle ), myPos );
00631
00632 luPixel x = myPos.x();
00633 luPixel y = myPos.y();
00634
00635
00636
00637
00638 painter.setPen(
QPen( style.getDefaultColor(),
00639 style.layoutUnitToPixelY( style.getLineWidth() ) ) );
00640
00641 painter.drawLine( style.layoutUnitToPixelX( x ),
00642 style.layoutUnitToPixelY( y+getHeight()-style.getLineWidth() ),
00643 style.layoutUnitToPixelX( x+content->
getWidth() ),
00644 style.layoutUnitToPixelY( y+getHeight()-style.getLineWidth() ) );
00645 }
00646
00647
00648 QString UnderlineElement::toLatex()
00649 {
00650
return "\\underline{" + getContent()->
toLatex() +
"}";
00651 }
00652
00653
QString UnderlineElement::formulaString()
00654 {
00655
return getContent()->
formulaString();
00656 }
00657
00658 void UnderlineElement::writeMathML(
QDomDocument doc,
QDomNode parent )
00659 {
00660
QDomElement de = doc.createElement(
"munder" );
00661 SingleContentElement::writeMathML( doc, de );
00662
QDomElement op = doc.createElement(
"mo" );
00663
00664 op.appendChild( doc.createEntityReference(
"UnderBar" ) );
00665 de.appendChild( op );
00666 parent.appendChild( de );
00667 }
00668
00669 KFORMULA_NAMESPACE_END