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 #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
00160 luPixel dy = point.y() - myPos.y();
00161
00162
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
00244
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
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
00471
00472
00473
00474 SequenceElement* RootElement::getMainChild()
00475 {
00476 return content;
00477 }
00478
00479
00480
00481
00482
00483
00484
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
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