lib Library API Documentation

rootelement.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 #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 //int dx = point.x() - myPos.x(); 00160 luPixel dy = point.y() - myPos.y(); 00161 00162 // the position after the index 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 //if ( !LuPixelRect( myPos.x(), myPos.y(), getWidth(), getHeight() ).intersects( r ) ) 00244 // return; 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 //int distX = style.getDistanceX(tstyle); 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 // main child 00471 // 00472 // If an element has children one has to become the main one. 00473 00474 SequenceElement* RootElement::getMainChild() 00475 { 00476 return content; 00477 } 00478 00479 // void RootElement::setMainChild(SequenceElement* child) 00480 // { 00481 // formula()->elementRemoval(content); 00482 // content = child; 00483 // content->setParent(this); 00484 // formula()->changed(); 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 // backward compatibility 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 ) 00608 { 00609 QDomElement de; 00610 00611 if( hasIndex() ) 00612 de = doc.createElement( "mroot" ); 00613 else 00614 de = doc.createElement( "msqrt" ); 00615 00616 content->writeMathML( doc, de ); 00617 00618 if( hasIndex() ) 00619 { 00620 index->writeMathML( doc, de ); 00621 } 00622 00623 parent.appendChild( de ); 00624 } 00625 00626 KFORMULA_NAMESPACE_END
KDE Logo
This file is part of the documentation for lib Library Version 1.3.3.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Sep 24 18:22:28 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003