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& context,
00182 ContextStyle::TextStyle tstyle,
00183 ContextStyle::IndexStyle istyle,
00184 StyleAttributes& style )
00185 {
00186 content->calcSizes( context, tstyle,
00187 context.convertIndexStyleLower(istyle), style );
00188
00189 luPixel indexWidth = 0;
00190 luPixel indexHeight = 0;
00191 if (hasIndex()) {
00192 index->calcSizes( context,
00193 context.convertTextStyleIndex(tstyle),
00194 context.convertIndexStyleUpper(istyle),
00195 style );
00196 indexWidth = index->getWidth();
00197 indexHeight = index->getHeight();
00198 }
00199
00200 double factor = style.sizeFactor();
00201 luPixel distX = context.ptToPixelX( context.getThinSpace( tstyle, factor ) );
00202 luPixel distY = context.ptToPixelY( context.getThinSpace( tstyle, factor ) );
00203 luPixel unit = (content->getHeight() + distY)/ 3;
00204
00205 if (hasIndex()) {
00206 if (indexWidth > unit) {
00207 index->setX(0);
00208 rootOffset.setX( indexWidth - unit );
00209 }
00210 else {
00211 index->setX( ( unit - indexWidth )/2 );
00212 rootOffset.setX(0);
00213 }
00214 if (indexHeight > unit) {
00215 index->setY(0);
00216 rootOffset.setY( indexHeight - unit );
00217 }
00218 else {
00219 index->setY( unit - indexHeight );
00220 rootOffset.setY(0);
00221 }
00222 }
00223 else {
00224 rootOffset.setX(0);
00225 rootOffset.setY(0);
00226 }
00227
00228 setWidth( content->getWidth() + unit+unit/3+ rootOffset.x() + distX/2 );
00229 setHeight( content->getHeight() + distY*2 + rootOffset.y() );
00230
00231 content->setX( rootOffset.x() + unit+unit/3 );
00232 content->setY( rootOffset.y() + distY );
00233 setBaseline(content->getBaseline() + content->getY());
00234 }
00235
00241 void RootElement::draw( QPainter& painter, const LuPixelRect& r,
00242 const ContextStyle& context,
00243 ContextStyle::TextStyle tstyle,
00244 ContextStyle::IndexStyle istyle,
00245 StyleAttributes& style,
00246 const LuPixelPoint& parentOrigin )
00247 {
00248 LuPixelPoint myPos( parentOrigin.x()+getX(), parentOrigin.y()+getY() );
00249
00250
00251
00252 content->draw( painter, r, context, tstyle,
00253 context.convertIndexStyleLower(istyle), style, myPos);
00254 if (hasIndex()) {
00255 index->draw(painter, r, context,
00256 context.convertTextStyleIndex(tstyle),
00257 context.convertIndexStyleUpper(istyle), style, myPos);
00258 }
00259
00260 luPixel x = myPos.x() + rootOffset.x();
00261 luPixel y = myPos.y() + rootOffset.y();
00262
00263 double factor = style.sizeFactor();
00264 luPixel distY = context.ptToPixelY( context.getThinSpace( tstyle, factor ) );
00265 luPixel unit = (content->getHeight() + distY)/ 3;
00266
00267 painter.setPen( QPen( style.color(),
00268 context.layoutUnitToPixelX( 2*context.getLineWidth( factor ) ) ) );
00269 painter.drawLine( context.layoutUnitToPixelX( x+unit/3 ),
00270 context.layoutUnitToPixelY( y+unit+distY/3 ),
00271 context.layoutUnitToPixelX( x+unit/2+unit/3 ),
00272 context.layoutUnitToPixelY( myPos.y()+getHeight() ) );
00273
00274 painter.setPen( QPen( style.color(),
00275 context.layoutUnitToPixelY( context.getLineWidth( factor ) ) ) );
00276
00277 painter.drawLine( context.layoutUnitToPixelX( x+unit+unit/3 ),
00278 context.layoutUnitToPixelY( y+distY/3 ),
00279 context.layoutUnitToPixelX( x+unit/2+unit/3 ),
00280 context.layoutUnitToPixelY( myPos.y()+getHeight() ) );
00281 painter.drawLine( context.layoutUnitToPixelX( x+unit+unit/3 ),
00282 context.layoutUnitToPixelY( y+distY/3 ),
00283 context.layoutUnitToPixelX( x+unit+unit/3+content->getWidth() ),
00284 context.layoutUnitToPixelY( y+distY/3 ) );
00285 painter.drawLine( context.layoutUnitToPixelX( x+unit/3 ),
00286 context.layoutUnitToPixelY( y+unit+distY/2 ),
00287 context.layoutUnitToPixelX( x ),
00288 context.layoutUnitToPixelY( y+unit+unit/2 ) );
00289 }
00290
00291
00292 void RootElement::dispatchFontCommand( FontCommand* cmd )
00293 {
00294 content->dispatchFontCommand( cmd );
00295 if (hasIndex()) {
00296 index->dispatchFontCommand( cmd );
00297 }
00298 }
00299
00305 void RootElement::moveLeft(FormulaCursor* cursor, BasicElement* from)
00306 {
00307 if (cursor->isSelectionMode()) {
00308 getParent()->moveLeft(cursor, this);
00309 }
00310 else {
00311 bool linear = cursor->getLinearMovement();
00312 if (from == getParent()) {
00313 content->moveLeft(cursor, this);
00314 }
00315 else if (from == content) {
00316 if (linear && hasIndex()) {
00317 index->moveLeft(cursor, this);
00318 }
00319 else {
00320 getParent()->moveLeft(cursor, this);
00321 }
00322 }
00323 else {
00324 getParent()->moveLeft(cursor, this);
00325 }
00326 }
00327 }
00328
00334 void RootElement::moveRight(FormulaCursor* cursor, BasicElement* from)
00335 {
00336 if (cursor->isSelectionMode()) {
00337 getParent()->moveRight(cursor, this);
00338 }
00339 else {
00340 bool linear = cursor->getLinearMovement();
00341 if (from == getParent()) {
00342 if (linear && hasIndex()) {
00343 index->moveRight(cursor, this);
00344 }
00345 else {
00346 content->moveRight(cursor, this);
00347 }
00348 }
00349 else if (from == index) {
00350 content->moveRight(cursor, this);
00351 }
00352 else {
00353 getParent()->moveRight(cursor, this);
00354 }
00355 }
00356 }
00357
00363 void RootElement::moveUp(FormulaCursor* cursor, BasicElement* from)
00364 {
00365 if (cursor->isSelectionMode()) {
00366 getParent()->moveUp(cursor, this);
00367 }
00368 else {
00369 if (from == getParent()) {
00370 content->moveRight(cursor, this);
00371 }
00372 else if (from == content) {
00373 if (hasIndex()) {
00374 index->moveRight(cursor, this);
00375 }
00376 else {
00377 getParent()->moveUp(cursor, this);
00378 }
00379 }
00380 else {
00381 getParent()->moveUp(cursor, this);
00382 }
00383 }
00384 }
00385
00391 void RootElement::moveDown(FormulaCursor* cursor, BasicElement* from)
00392 {
00393 if (cursor->isSelectionMode()) {
00394 getParent()->moveDown(cursor, this);
00395 }
00396 else {
00397 if (from == getParent()) {
00398 if (hasIndex()) {
00399 index->moveRight(cursor, this);
00400 }
00401 else {
00402 content->moveRight(cursor, this);
00403 }
00404 }
00405 else if (from == index) {
00406 content->moveRight(cursor, this);
00407 }
00408 else {
00409 getParent()->moveDown(cursor, this);
00410 }
00411 }
00412 }
00413
00417 void RootElement::insert(FormulaCursor* cursor,
00418 QPtrList<BasicElement>& newChildren,
00419 Direction direction)
00420 {
00421 if (cursor->getPos() == upperLeftPos) {
00422 index = static_cast<SequenceElement*>(newChildren.take(0));
00423 index->setParent(this);
00424
00425 if (direction == beforeCursor) {
00426 index->moveLeft(cursor, this);
00427 }
00428 else {
00429 index->moveRight(cursor, this);
00430 }
00431 cursor->setSelection(false);
00432 formula()->changed();
00433 }
00434 }
00435
00442 void RootElement::remove(FormulaCursor* cursor,
00443 QPtrList<BasicElement>& removedChildren,
00444 Direction direction)
00445 {
00446 switch (cursor->getPos()) {
00447 case contentPos:
00448 getParent()->selectChild(cursor, this);
00449 getParent()->remove(cursor, removedChildren, direction);
00450 break;
00451 case upperLeftPos:
00452 removedChildren.append(index);
00453 formula()->elementRemoval(index);
00454 index = 0;
00455 cursor->setTo(this, upperLeftPos);
00456 formula()->changed();
00457 break;
00458 }
00459 }
00460
00461
00466 void RootElement::normalize(FormulaCursor* cursor, Direction direction)
00467 {
00468 if (direction == beforeCursor) {
00469 content->moveLeft(cursor, this);
00470 }
00471 else {
00472 content->moveRight(cursor, this);
00473 }
00474 }
00475
00476
00477
00478
00479
00480
00481 SequenceElement* RootElement::getMainChild()
00482 {
00483 return content;
00484 }
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00499 void RootElement::selectChild(FormulaCursor* cursor, BasicElement* child)
00500 {
00501 if (child == content) {
00502 cursor->setTo(this, contentPos);
00503 }
00504 else if (child == index) {
00505 cursor->setTo(this, upperLeftPos);
00506 }
00507 }
00508
00509
00510 void RootElement::moveToIndex(FormulaCursor* cursor, Direction direction)
00511 {
00512 if (hasIndex()) {
00513 if (direction == beforeCursor) {
00514 index->moveLeft(cursor, this);
00515 }
00516 else {
00517 index->moveRight(cursor, this);
00518 }
00519 }
00520 }
00521
00522 void RootElement::setToIndex(FormulaCursor* cursor)
00523 {
00524 cursor->setTo(this, upperLeftPos);
00525 }
00526
00527
00531 void RootElement::writeDom(QDomElement element)
00532 {
00533 BasicElement::writeDom(element);
00534
00535 QDomDocument doc = element.ownerDocument();
00536
00537 QDomElement con = doc.createElement("CONTENT");
00538 con.appendChild(content->getElementDom(doc));
00539 element.appendChild(con);
00540
00541 if(hasIndex()) {
00542 QDomElement ind = doc.createElement("ROOTINDEX");
00543 ind.appendChild(index->getElementDom(doc));
00544 element.appendChild(ind);
00545 }
00546 }
00547
00552 bool RootElement::readAttributesFromDom(QDomElement element)
00553 {
00554 return BasicElement::readAttributesFromDom(element);
00555 }
00556
00562 bool RootElement::readContentFromDom(QDomNode& node)
00563 {
00564 if (!BasicElement::readContentFromDom(node)) {
00565 return false;
00566 }
00567
00568 if ( !buildChild( content, node, "CONTENT" ) ) {
00569 kdWarning( DEBUGID ) << "Empty content in RootElement." << endl;
00570 return false;
00571 }
00572 node = node.nextSibling();
00573
00574 if ( node.nodeName().upper() == "ROOTINDEX" ) {
00575 if ( !buildChild( index=new SequenceElement( this ), node, "ROOTINDEX" ) ) {
00576 return false;
00577 }
00578 }
00579
00580 else if ( node.nodeName().upper() == "INDEX" ) {
00581 if ( !buildChild( index=new SequenceElement( this ), node, "INDEX" ) ) {
00582 return false;
00583 }
00584 }
00585 node = node.nextSibling();
00586
00587 return true;
00588 }
00589
00595 bool RootElement::readAttributesFromMathMLDom(const QDomElement& element)
00596 {
00597 if ( element.tagName().lower() == "mroot" )
00598 square = false;
00599 else
00600 square = true;
00601 return true;
00602 }
00603
00604
00610 int RootElement::readContentFromMathMLDom(QDomNode& node)
00611 {
00612 if ( BasicElement::readContentFromMathMLDom( node ) == -1 ) {
00613 return -1;
00614 }
00615
00616 if ( square ) {
00617
00618 if ( content->readContentFromMathMLDom( node ) == -1 ) {
00619 kdWarning( DEBUGID ) << "Empty content in RootElement." << endl;
00620 return -1;
00621 }
00622 }
00623 else {
00624
00625 int contentNumber = content->buildMathMLChild( node );
00626 if ( contentNumber == -1 ) {
00627 kdWarning( DEBUGID ) << "Empty content in RootElement." << endl;
00628 return -1;
00629 }
00630 for (int i = 0; i < contentNumber; i++ ) {
00631 if ( node.isNull() ) {
00632 return -1;
00633 }
00634 node = node.nextSibling();
00635 }
00636
00637 index = new SequenceElement( this );
00638 if ( index->buildMathMLChild( node ) == -1 ) {
00639 kdWarning( DEBUGID ) << "Empty index in RootElement." << endl;
00640 return -1;
00641 }
00642 }
00643
00644 return 1;
00645 }
00646
00647 QString RootElement::toLatex()
00648 {
00649 QString root;
00650 root="\\sqrt";
00651 if(hasIndex()) {
00652 root+="[";
00653 root+=index->toLatex();
00654 root+="]";
00655 }
00656 root+="{";
00657 root+=content->toLatex();
00658 root+="}";
00659
00660 return root;
00661 }
00662
00663 QString RootElement::formulaString()
00664 {
00665 if ( hasIndex() ) {
00666 return "(" + content->formulaString() + ")**(1.0/(" + index->formulaString() + "))";
00667 }
00668 return "sqrt(" + content->formulaString() + ")";
00669 }
00670
00671 void RootElement::writeMathMLContent( QDomDocument& doc, QDomElement& element, bool oasisFormat ) const
00672 {
00673 content->writeMathML( doc, element, oasisFormat );
00674 if( hasIndex() )
00675 {
00676 index->writeMathML( doc, element, oasisFormat );
00677 }
00678 }
00679
00680 KFORMULA_NAMESPACE_END