lib Library API Documentation

indexelement.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 00023 #include <kdebug.h> 00024 #include <klocale.h> 00025 00026 #include "elementvisitor.h" 00027 #include "indexelement.h" 00028 #include "formulacursor.h" 00029 #include "formulaelement.h" 00030 #include "kformulacommand.h" 00031 #include "sequenceelement.h" 00032 00033 00034 KFORMULA_NAMESPACE_BEGIN 00035 00036 00037 class IndexSequenceElement : public SequenceElement { 00038 typedef SequenceElement inherited; 00039 public: 00040 00041 IndexSequenceElement( BasicElement* parent = 0 ) : SequenceElement( parent ) {} 00042 virtual IndexSequenceElement* clone() { 00043 return new IndexSequenceElement( *this ); 00044 } 00045 00054 virtual KCommand* buildCommand( Container*, Request* ); 00055 }; 00056 00057 00058 KCommand* IndexSequenceElement::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 IndexElement* element = static_cast<IndexElement*>( getParent() ); 00073 IndexRequest* ir = static_cast<IndexRequest*>( request ); 00074 ElementIndexPtr index = element->getIndex( ir->index() ); 00075 if ( !index->hasIndex() ) { 00076 KFCAddGenericIndex* command = new KFCAddGenericIndex( container, index ); 00077 return command; 00078 } 00079 else { 00080 index->moveToIndex( cursor, afterCursor ); 00081 cursor->setSelection( false ); 00082 formula()->cursorHasMoved( cursor ); 00083 return 0; 00084 } 00085 } 00086 default: 00087 break; 00088 } 00089 return inherited::buildCommand( container, request ); 00090 } 00091 00092 00093 IndexElement::IndexElement(BasicElement* parent) 00094 : BasicElement(parent) 00095 { 00096 content = new IndexSequenceElement( this ); 00097 00098 upperLeft = 0; 00099 upperMiddle = 0; 00100 upperRight = 0; 00101 lowerLeft = 0; 00102 lowerMiddle = 0; 00103 lowerRight = 0; 00104 } 00105 00106 IndexElement::~IndexElement() 00107 { 00108 delete content; 00109 delete upperLeft; 00110 delete upperMiddle; 00111 delete upperRight; 00112 delete lowerLeft; 00113 delete lowerMiddle; 00114 delete lowerRight; 00115 } 00116 00117 00118 IndexElement::IndexElement( const IndexElement& other ) 00119 : BasicElement( other ) 00120 { 00121 content = new IndexSequenceElement( *dynamic_cast<IndexSequenceElement*>( other.content ) ); 00122 00123 if ( other.upperLeft ) { 00124 upperLeft = new SequenceElement( *( other.upperLeft ) ); 00125 upperLeft->setParent( this ); 00126 } 00127 else { 00128 upperLeft = 0; 00129 } 00130 if ( other.upperMiddle ) { 00131 upperMiddle = new SequenceElement( *( other.upperMiddle ) ); 00132 upperMiddle->setParent( this ); 00133 } 00134 else { 00135 upperMiddle = 0; 00136 } 00137 if ( other.upperRight ) { 00138 upperRight = new SequenceElement( *( other.upperRight ) ); 00139 upperRight->setParent( this ); 00140 } 00141 else { 00142 upperRight = 0; 00143 } 00144 00145 if ( other.lowerLeft ) { 00146 lowerLeft = new SequenceElement( *( other.lowerLeft ) ); 00147 lowerLeft->setParent( this ); 00148 } 00149 else { 00150 lowerLeft = 0; 00151 } 00152 if ( other.lowerMiddle ) { 00153 lowerMiddle = new SequenceElement( *( other.lowerMiddle ) ); 00154 lowerMiddle->setParent( this ); 00155 } 00156 else { 00157 lowerMiddle = 0; 00158 } 00159 if ( other.lowerRight ) { 00160 lowerRight = new SequenceElement( *( other.lowerRight ) ); 00161 lowerRight->setParent( this ); 00162 } 00163 else { 00164 lowerRight = 0; 00165 } 00166 } 00167 00168 00169 bool IndexElement::accept( ElementVisitor* visitor ) 00170 { 00171 return visitor->visit( this ); 00172 } 00173 00174 00175 QChar IndexElement::getCharacter() const 00176 { 00177 if ( !content->isTextOnly() ) { 00178 return QChar::null; 00179 } 00180 00181 if ( hasUpperRight() && !upperRight->isTextOnly() ) { 00182 return QChar::null; 00183 } 00184 if ( hasUpperMiddle() && !upperMiddle->isTextOnly() ) { 00185 return QChar::null; 00186 } 00187 if ( hasUpperLeft() && !upperLeft->isTextOnly() ) { 00188 return QChar::null; 00189 } 00190 if ( hasLowerRight() && !lowerRight->isTextOnly() ) { 00191 return QChar::null; 00192 } 00193 if ( hasLowerMiddle() && !lowerMiddle->isTextOnly() ) { 00194 return QChar::null; 00195 } 00196 if ( hasLowerLeft() && !lowerLeft->isTextOnly() ) { 00197 return QChar::null; 00198 } 00199 00200 return ' '; 00201 } 00202 00203 void IndexElement::entered( SequenceElement* child ) 00204 { 00205 if ( child == content ) { 00206 formula()->tell( i18n( "Indexed list" ) ); 00207 } 00208 else { 00209 formula()->tell( i18n( "Index" ) ); 00210 } 00211 } 00212 00213 00217 BasicElement* IndexElement::goToPos( FormulaCursor* cursor, bool& handled, 00218 const LuPixelPoint& point, const LuPixelPoint& parentOrigin ) 00219 { 00220 BasicElement* e = BasicElement::goToPos(cursor, handled, point, parentOrigin); 00221 if (e != 0) { 00222 LuPixelPoint myPos(parentOrigin.x()+getX(), parentOrigin.y()+getY()); 00223 e = content->goToPos(cursor, handled, point, myPos); 00224 if (e != 0) return e; 00225 00226 if (hasUpperRight()) { 00227 e = upperRight->goToPos(cursor, handled, point, myPos); 00228 if (e != 0) return e; 00229 } 00230 if (hasUpperMiddle()) { 00231 e = upperMiddle->goToPos(cursor, handled, point, myPos); 00232 if (e != 0) return e; 00233 } 00234 if (hasUpperLeft()) { 00235 e = upperLeft->goToPos(cursor, handled, point, myPos); 00236 if (e != 0) return e; 00237 } 00238 if (hasLowerRight()) { 00239 e = lowerRight->goToPos(cursor, handled, point, myPos); 00240 if (e != 0) return e; 00241 } 00242 if (hasLowerMiddle()) { 00243 e = lowerMiddle->goToPos(cursor, handled, point, myPos); 00244 if (e != 0) return e; 00245 } 00246 if (hasLowerLeft()) { 00247 e = lowerLeft->goToPos(cursor, handled, point, myPos); 00248 if (e != 0) return e; 00249 } 00250 00251 luPixel dx = point.x() - myPos.x(); 00252 luPixel dy = point.y() - myPos.y(); 00253 00254 // the positions after the left indexes 00255 if (dx < content->getX()+content->getWidth()) { 00256 if (dy < content->getY()) { 00257 if (hasUpperMiddle() && (dx > upperMiddle->getX())) { 00258 upperMiddle->moveLeft(cursor, this); 00259 handled = true; 00260 return upperMiddle; 00261 } 00262 if (hasUpperLeft() && (dx > upperLeft->getX())) { 00263 upperLeft->moveLeft(cursor, this); 00264 handled = true; 00265 return upperLeft; 00266 } 00267 } 00268 else if (dy > content->getY()+content->getHeight()) { 00269 if (hasLowerMiddle() && (dx > lowerMiddle->getX())) { 00270 lowerMiddle->moveLeft(cursor, this); 00271 handled = true; 00272 return lowerMiddle; 00273 } 00274 if (hasLowerLeft() && (dx > lowerLeft->getX())) { 00275 lowerLeft->moveLeft(cursor, this); 00276 handled = true; 00277 return lowerLeft; 00278 } 00279 } 00280 } 00281 // the positions after the left indexes 00282 else { 00283 if (dy < content->getY()) { 00284 if (hasUpperRight()) { 00285 upperRight->moveLeft(cursor, this); 00286 handled = true; 00287 return upperRight; 00288 } 00289 } 00290 else if (dy > content->getY()+content->getHeight()) { 00291 if (hasLowerRight()) { 00292 lowerRight->moveLeft(cursor, this); 00293 handled = true; 00294 return lowerRight; 00295 } 00296 } 00297 else { 00298 content->moveLeft(cursor, this); 00299 handled = true; 00300 return content; 00301 } 00302 } 00303 00304 return this; 00305 } 00306 return 0; 00307 } 00308 00309 00310 // drawing 00311 // 00312 // Drawing depends on a context which knows the required properties like 00313 // fonts, spaces and such. 00314 // It is essential to calculate elements size with the same context 00315 // before you draw. 00316 00317 00318 void IndexElement::setMiddleX(int xOffset, int middleWidth) 00319 { 00320 content->setX(xOffset + (middleWidth - content->getWidth()) / 2); 00321 if (hasUpperMiddle()) { 00322 upperMiddle->setX(xOffset + (middleWidth - upperMiddle->getWidth()) / 2); 00323 } 00324 if (hasLowerMiddle()) { 00325 lowerMiddle->setX(xOffset + (middleWidth - lowerMiddle->getWidth()) / 2); 00326 } 00327 } 00328 00329 00334 void IndexElement::calcSizes(const ContextStyle& style, ContextStyle::TextStyle tstyle, ContextStyle::IndexStyle istyle) 00335 { 00336 luPixel distY = style.ptToPixelY( style.getThinSpace( tstyle ) ); 00337 00338 ContextStyle::TextStyle i_tstyle = style.convertTextStyleIndex(tstyle); 00339 ContextStyle::IndexStyle u_istyle = style.convertIndexStyleUpper( istyle ); 00340 ContextStyle::IndexStyle l_istyle = style.convertIndexStyleLower( istyle ); 00341 00342 // get the indexes size 00343 luPixel ulWidth = 0, ulHeight = 0, ulMidline = 0; 00344 if (hasUpperLeft()) { 00345 upperLeft->calcSizes( style, i_tstyle, u_istyle ); 00346 ulWidth = upperLeft->getWidth(); 00347 ulHeight = upperLeft->getHeight(); 00348 ulMidline = upperLeft->axis( style, i_tstyle ); 00349 } 00350 00351 luPixel umWidth = 0, umHeight = 0, umMidline = 0; 00352 if (hasUpperMiddle()) { 00353 upperMiddle->calcSizes( style, i_tstyle, u_istyle ); 00354 umWidth = upperMiddle->getWidth(); 00355 umHeight = upperMiddle->getHeight() + distY; 00356 umMidline = upperMiddle->axis( style, i_tstyle ); 00357 } 00358 00359 luPixel urWidth = 0, urHeight = 0, urMidline = 0; 00360 if (hasUpperRight()) { 00361 upperRight->calcSizes( style, i_tstyle, u_istyle ); 00362 urWidth = upperRight->getWidth(); 00363 urHeight = upperRight->getHeight(); 00364 urMidline = upperRight->axis( style, i_tstyle ); 00365 } 00366 00367 luPixel llWidth = 0, llHeight = 0, llMidline = 0; 00368 if (hasLowerLeft()) { 00369 lowerLeft->calcSizes( style, i_tstyle, l_istyle ); 00370 llWidth = lowerLeft->getWidth(); 00371 llHeight = lowerLeft->getHeight(); 00372 llMidline = lowerLeft->axis( style, i_tstyle ); 00373 } 00374 00375 luPixel lmWidth = 0, lmHeight = 0, lmMidline = 0; 00376 if (hasLowerMiddle()) { 00377 lowerMiddle->calcSizes( style, i_tstyle, l_istyle ); 00378 lmWidth = lowerMiddle->getWidth(); 00379 lmHeight = lowerMiddle->getHeight() + distY; 00380 lmMidline = lowerMiddle->axis( style, i_tstyle ); 00381 } 00382 00383 luPixel lrWidth = 0, lrHeight = 0, lrMidline = 0; 00384 if (hasLowerRight()) { 00385 lowerRight->calcSizes( style, i_tstyle, l_istyle ); 00386 lrWidth = lowerRight->getWidth(); 00387 lrHeight = lowerRight->getHeight(); 00388 lrMidline = lowerRight->axis( style, i_tstyle ); 00389 } 00390 00391 // get the contents size 00392 content->calcSizes(style, tstyle, istyle); 00393 luPixel width = QMAX(content->getWidth(), QMAX(umWidth, lmWidth)); 00394 luPixel toMidline = content->axis( style, tstyle ); 00395 luPixel fromMidline = content->getHeight() - toMidline; 00396 00397 // calculate the x offsets 00398 if (ulWidth > llWidth) { 00399 upperLeft->setX(0); 00400 if (hasLowerLeft()) { 00401 lowerLeft->setX(ulWidth - llWidth); 00402 } 00403 setMiddleX(ulWidth, width); 00404 width += ulWidth; 00405 } 00406 else { 00407 if (hasUpperLeft()) { 00408 upperLeft->setX(llWidth - ulWidth); 00409 } 00410 if (hasLowerLeft()) { 00411 lowerLeft->setX(0); 00412 } 00413 setMiddleX(llWidth, width); 00414 width += llWidth; 00415 } 00416 00417 if (hasUpperRight()) { 00418 upperRight->setX(width); 00419 } 00420 if (hasLowerRight()) { 00421 lowerRight->setX(width); 00422 } 00423 width += QMAX(urWidth, lrWidth); 00424 00425 // calculate the y offsets 00426 luPixel ulOffset = 0; 00427 luPixel urOffset = 0; 00428 luPixel llOffset = 0; 00429 luPixel lrOffset = 0; 00430 if (content->isTextOnly()) { 00431 luPt mySize = style.getAdjustedSize( tstyle ); 00432 QFont font = style.getDefaultFont(); 00433 font.setPointSizeFloat( style.layoutUnitPtToPt( mySize ) ); 00434 00435 QFontMetrics fm(font); 00436 LuPixelRect bound = fm.boundingRect('x'); 00437 00438 luPixel exBaseline = style.ptToLayoutUnitPt( -bound.top() ); 00439 00440 // the upper half 00441 ulOffset = ulHeight + exBaseline - content->getBaseline(); 00442 urOffset = urHeight + exBaseline - content->getBaseline(); 00443 00444 // the lower half 00445 llOffset = lrOffset = content->getBaseline(); 00446 } 00447 else { 00448 00449 // the upper half 00450 ulOffset = QMAX(ulMidline, ulHeight-toMidline); 00451 urOffset = QMAX(urMidline, urHeight-toMidline); 00452 00453 // the lower half 00454 llOffset = QMAX(content->getHeight()-llMidline, toMidline); 00455 lrOffset = QMAX(content->getHeight()-lrMidline, toMidline); 00456 } 00457 luPixel height = QMAX(umHeight, QMAX(ulOffset, urOffset)); 00458 00459 // the upper half 00460 content->setY(height); 00461 toMidline += height; 00462 if (hasUpperLeft()) { 00463 upperLeft->setY(height-ulOffset); 00464 } 00465 if (hasUpperMiddle()) { 00466 upperMiddle->setY(height-umHeight); 00467 } 00468 if (hasUpperRight()) { 00469 upperRight->setY(height-urOffset); 00470 } 00471 00472 // the lower half 00473 if (hasLowerLeft()) { 00474 lowerLeft->setY(height+llOffset); 00475 } 00476 if (hasLowerMiddle()) { 00477 lowerMiddle->setY(height+content->getHeight()+distY); 00478 } 00479 if (hasLowerRight()) { 00480 lowerRight->setY(height+lrOffset); 00481 } 00482 00483 fromMidline += QMAX(QMAX(llHeight+llOffset, lrHeight+lrOffset) - content->getHeight(), lmHeight); 00484 00485 // set the result 00486 setWidth(width); 00487 setHeight(toMidline+fromMidline); 00488 if (content->isTextOnly()) { 00489 setBaseline(content->getY() + content->getBaseline()); 00490 //setMidline(content->getY() + content->getMidline()); 00491 } 00492 else { 00493 //setMidline(toMidline); 00494 setBaseline(content->getBaseline() + content->getY()); 00495 } 00496 } 00497 00503 void IndexElement::draw( QPainter& painter, const LuPixelRect& r, 00504 const ContextStyle& style, 00505 ContextStyle::TextStyle tstyle, 00506 ContextStyle::IndexStyle istyle, 00507 const LuPixelPoint& parentOrigin ) 00508 { 00509 LuPixelPoint myPos( parentOrigin.x()+getX(), parentOrigin.y()+getY() ); 00510 //if ( !LuPixelRect( myPos.x(), myPos.y(), getWidth(), getHeight() ).intersects( r ) ) 00511 // return; 00512 00513 ContextStyle::TextStyle i_tstyle = style.convertTextStyleIndex(tstyle); 00514 ContextStyle::IndexStyle u_istyle = style.convertIndexStyleUpper( istyle ); 00515 ContextStyle::IndexStyle l_istyle = style.convertIndexStyleLower( istyle ); 00516 00517 content->draw(painter, r, style, tstyle, istyle, myPos); 00518 if (hasUpperLeft()) { 00519 upperLeft->draw(painter, r, style, i_tstyle, u_istyle, myPos); 00520 } 00521 if (hasUpperMiddle()) { 00522 upperMiddle->draw(painter, r, style, i_tstyle, u_istyle, myPos); 00523 } 00524 if (hasUpperRight()) { 00525 upperRight->draw(painter, r, style, i_tstyle, u_istyle, myPos); 00526 } 00527 if (hasLowerLeft()) { 00528 lowerLeft->draw(painter, r, style, i_tstyle, l_istyle, myPos); 00529 } 00530 if (hasLowerMiddle()) { 00531 lowerMiddle->draw(painter, r, style, i_tstyle, l_istyle, myPos); 00532 } 00533 if (hasLowerRight()) { 00534 lowerRight->draw(painter, r, style, i_tstyle, l_istyle, myPos); 00535 } 00536 00537 // Debug 00538 //painter.setBrush(Qt::NoBrush); 00539 //painter.setPen(Qt::red); 00540 //painter.drawRect(myPos.x(), myPos.y(), getWidth(), getHeight()); 00541 //painter.drawLine(myPos.x(), myPos.y()+getMidline(), 00542 // myPos.x()+getWidth(), myPos.y()+getMidline()); 00543 } 00544 00545 00546 void IndexElement::dispatchFontCommand( FontCommand* cmd ) 00547 { 00548 content->dispatchFontCommand( cmd ); 00549 if (hasUpperLeft()) { 00550 upperLeft->dispatchFontCommand( cmd ); 00551 } 00552 if (hasUpperMiddle()) { 00553 upperMiddle->dispatchFontCommand( cmd ); 00554 } 00555 if (hasUpperRight()) { 00556 upperRight->dispatchFontCommand( cmd ); 00557 } 00558 if (hasLowerLeft()) { 00559 lowerLeft->dispatchFontCommand( cmd ); 00560 } 00561 if (hasLowerMiddle()) { 00562 lowerMiddle->dispatchFontCommand( cmd ); 00563 } 00564 if (hasLowerRight()) { 00565 lowerRight->dispatchFontCommand( cmd ); 00566 } 00567 } 00568 00569 00570 // navigation 00571 // 00572 // The elements are responsible to handle cursor movement themselves. 00573 // To do this they need to know the direction the cursor moves and 00574 // the element it comes from. 00575 // 00576 // The cursor might be in normal or in selection mode. 00577 00578 int IndexElement::getFromPos(BasicElement* from) 00579 { 00580 if (from == lowerRight) { 00581 return lowerRightPos; 00582 } 00583 else if (from == upperRight) { 00584 return upperRightPos; 00585 } 00586 else if (from == lowerMiddle) { 00587 return lowerMiddlePos; 00588 } 00589 else if (from == content) { 00590 return contentPos; 00591 } 00592 else if (from == upperMiddle) { 00593 return upperMiddlePos; 00594 } 00595 else if (from == lowerLeft) { 00596 return lowerLeftPos; 00597 } 00598 else if (from == upperLeft) { 00599 return upperLeftPos; 00600 } 00601 return parentPos; 00602 } 00603 00609 void IndexElement::moveLeft(FormulaCursor* cursor, BasicElement* from) 00610 { 00611 if (cursor->isSelectionMode()) { 00612 getParent()->moveLeft(cursor, this); 00613 } 00614 else { 00615 bool linear = cursor->getLinearMovement(); 00616 int fromPos = getFromPos(from); 00617 if (!linear) { 00618 if ((fromPos == lowerRightPos) && hasLowerMiddle()) { 00619 lowerMiddle->moveLeft(cursor, this); 00620 return; 00621 } 00622 else if ((fromPos == upperRightPos) && hasUpperMiddle()) { 00623 upperMiddle->moveLeft(cursor, this); 00624 return; 00625 } 00626 else if ((fromPos == lowerMiddlePos) && hasLowerLeft()) { 00627 lowerLeft->moveLeft(cursor, this); 00628 return; 00629 } 00630 else if ((fromPos == upperMiddlePos) && hasUpperLeft()) { 00631 upperLeft->moveLeft(cursor, this); 00632 return; 00633 } 00634 } 00635 switch (fromPos) { 00636 case parentPos: 00637 if (hasLowerRight() && linear) { 00638 lowerRight->moveLeft(cursor, this); 00639 break; 00640 } 00641 case lowerRightPos: 00642 if (hasUpperRight() && linear) { 00643 upperRight->moveLeft(cursor, this); 00644 break; 00645 } 00646 case upperRightPos: 00647 if (hasLowerMiddle() && linear) { 00648 lowerMiddle->moveLeft(cursor, this); 00649 break; 00650 } 00651 case lowerMiddlePos: 00652 content->moveLeft(cursor, this); 00653 break; 00654 case contentPos: 00655 if (hasUpperMiddle() && linear) { 00656 upperMiddle->moveLeft(cursor, this); 00657 break; 00658 } 00659 case upperMiddlePos: 00660 if (hasLowerLeft() && linear) { 00661 lowerLeft->moveLeft(cursor, this); 00662 break; 00663 } 00664 case lowerLeftPos: 00665 if (hasUpperLeft() && linear) { 00666 upperLeft->moveLeft(cursor, this); 00667 break; 00668 } 00669 case upperLeftPos: 00670 getParent()->moveLeft(cursor, this); 00671 } 00672 } 00673 } 00674 00680 void IndexElement::moveRight(FormulaCursor* cursor, BasicElement* from) 00681 { 00682 if (cursor->isSelectionMode()) { 00683 getParent()->moveRight(cursor, this); 00684 } 00685 else { 00686 bool linear = cursor->getLinearMovement(); 00687 int fromPos = getFromPos(from); 00688 if (!linear) { 00689 if ((fromPos == lowerLeftPos) && hasLowerMiddle()) { 00690 lowerMiddle->moveRight(cursor, this); 00691 return; 00692 } 00693 else if ((fromPos == upperLeftPos) && hasUpperMiddle()) { 00694 upperMiddle->moveRight(cursor, this); 00695 return; 00696 } 00697 else if ((fromPos == lowerMiddlePos) && hasLowerRight()) { 00698 lowerRight->moveRight(cursor, this); 00699 return; 00700 } 00701 else if ((fromPos == upperMiddlePos) && hasUpperRight()) { 00702 upperRight->moveRight(cursor, this); 00703 return; 00704 } 00705 } 00706 switch (fromPos) { 00707 case parentPos: 00708 if (hasUpperLeft() && linear) { 00709 upperLeft->moveRight(cursor, this); 00710 break; 00711 } 00712 case upperLeftPos: 00713 if (hasLowerLeft() && linear) { 00714 lowerLeft->moveRight(cursor, this); 00715 break; 00716 } 00717 case lowerLeftPos: 00718 if (hasUpperMiddle() && linear) { 00719 upperMiddle->moveRight(cursor, this); 00720 break; 00721 } 00722 case upperMiddlePos: 00723 content->moveRight(cursor, this); 00724 break; 00725 case contentPos: 00726 if (hasLowerMiddle() && linear) { 00727 lowerMiddle->moveRight(cursor, this); 00728 break; 00729 } 00730 case lowerMiddlePos: 00731 if (hasUpperRight() && linear) { 00732 upperRight->moveRight(cursor, this); 00733 break; 00734 } 00735 case upperRightPos: 00736 if (hasLowerRight() && linear) { 00737 lowerRight->moveRight(cursor, this); 00738 break; 00739 } 00740 case lowerRightPos: 00741 getParent()->moveRight(cursor, this); 00742 } 00743 } 00744 } 00745 00751 void IndexElement::moveUp(FormulaCursor* cursor, BasicElement* from) 00752 { 00753 if (cursor->isSelectionMode()) { 00754 getParent()->moveUp(cursor, this); 00755 } 00756 else { 00757 if (from == content) { 00758 if ((cursor->getPos() == 0) && (cursor->getElement() == from)) { 00759 if (hasUpperLeft()) { 00760 upperLeft->moveLeft(cursor, this); 00761 return; 00762 } 00763 else if (hasUpperMiddle()) { 00764 upperMiddle->moveRight(cursor, this); 00765 return; 00766 } 00767 } 00768 if (hasUpperRight()) { 00769 upperRight->moveRight(cursor, this); 00770 } 00771 else if (hasUpperMiddle()) { 00772 upperMiddle->moveLeft(cursor, this); 00773 } 00774 else if (hasUpperLeft()) { 00775 upperLeft->moveLeft(cursor, this); 00776 } 00777 else { 00778 getParent()->moveUp(cursor, this); 00779 } 00780 } 00781 else if ((from == upperLeft) || (from == upperMiddle) || (from == upperRight)) { 00782 getParent()->moveUp(cursor, this); 00783 } 00784 else if ((from == getParent()) || (from == lowerLeft) || (from == lowerMiddle)) { 00785 content->moveRight(cursor, this); 00786 } 00787 else if (from == lowerRight) { 00788 content->moveLeft(cursor, this); 00789 } 00790 } 00791 } 00792 00798 void IndexElement::moveDown(FormulaCursor* cursor, BasicElement* from) 00799 { 00800 if (cursor->isSelectionMode()) { 00801 getParent()->moveDown(cursor, this); 00802 } 00803 else { 00804 if (from == content) { 00805 if ((cursor->getPos() == 0) && (cursor->getElement() == from)) { 00806 if (hasLowerLeft()) { 00807 lowerLeft->moveLeft(cursor, this); 00808 return; 00809 } 00810 else if (hasLowerMiddle()) { 00811 lowerMiddle->moveRight(cursor, this); 00812 return; 00813 } 00814 } 00815 if (hasLowerRight()) { 00816 lowerRight->moveRight(cursor, this); 00817 } 00818 else if (hasLowerMiddle()) { 00819 lowerMiddle->moveLeft(cursor, this); 00820 } 00821 else if (hasLowerLeft()) { 00822 lowerLeft->moveLeft(cursor, this); 00823 } 00824 else { 00825 getParent()->moveDown(cursor, this); 00826 } 00827 } 00828 else if ((from == lowerLeft) || (from == lowerMiddle) || (from == lowerRight)) { 00829 getParent()->moveDown(cursor, this); 00830 } 00831 else if ((from == getParent()) || (from == upperLeft) || (from == upperMiddle)) { 00832 content->moveRight(cursor, this); 00833 } 00834 if (from == upperRight) { 00835 content->moveLeft(cursor, this); 00836 } 00837 } 00838 } 00839 00840 00841 // children 00842 00843 00844 // main child 00845 // 00846 // If an element has children one has to become the main one. 00847 00848 // void IndexElement::setMainChild(SequenceElement* child) 00849 // { 00850 // formula()->elementRemoval(content); 00851 // content = child; 00852 // content->setParent(this); 00853 // formula()->changed(); 00854 // } 00855 00856 00867 void IndexElement::insert(FormulaCursor* cursor, 00868 QPtrList<BasicElement>& newChildren, 00869 Direction direction) 00870 { 00871 SequenceElement* index = static_cast<SequenceElement*>(newChildren.take(0)); 00872 index->setParent(this); 00873 00874 switch (cursor->getPos()) { 00875 case upperLeftPos: 00876 upperLeft = index; 00877 break; 00878 case lowerLeftPos: 00879 lowerLeft = index; 00880 break; 00881 case upperMiddlePos: 00882 upperMiddle = index; 00883 break; 00884 case lowerMiddlePos: 00885 lowerMiddle = index; 00886 break; 00887 case upperRightPos: 00888 upperRight = index; 00889 break; 00890 case lowerRightPos: 00891 lowerRight = index; 00892 break; 00893 default: 00894 // this is an error! 00895 return; 00896 } 00897 00898 if (direction == beforeCursor) { 00899 index->moveLeft(cursor, this); 00900 } 00901 else { 00902 index->moveRight(cursor, this); 00903 } 00904 cursor->setSelection(false); 00905 formula()->changed(); 00906 } 00907 00908 00920 void IndexElement::remove(FormulaCursor* cursor, 00921 QPtrList<BasicElement>& removedChildren, 00922 Direction direction) 00923 { 00924 int pos = cursor->getPos(); 00925 switch (pos) { 00926 case upperLeftPos: 00927 removedChildren.append(upperLeft); 00928 formula()->elementRemoval(upperLeft); 00929 upperLeft = 0; 00930 setToUpperLeft(cursor); 00931 break; 00932 case lowerLeftPos: 00933 removedChildren.append(lowerLeft); 00934 formula()->elementRemoval(lowerLeft); 00935 lowerLeft = 0; 00936 setToLowerLeft(cursor); 00937 break; 00938 case contentPos: { 00939 BasicElement* parent = getParent(); 00940 parent->selectChild(cursor, this); 00941 parent->remove(cursor, removedChildren, direction); 00942 break; 00943 } 00944 case upperMiddlePos: 00945 removedChildren.append(upperMiddle); 00946 formula()->elementRemoval(upperMiddle); 00947 upperMiddle = 0; 00948 setToUpperMiddle(cursor); 00949 break; 00950 case lowerMiddlePos: 00951 removedChildren.append(lowerMiddle); 00952 formula()->elementRemoval(lowerMiddle); 00953 lowerMiddle = 0; 00954 setToLowerMiddle(cursor); 00955 break; 00956 case upperRightPos: 00957 removedChildren.append(upperRight); 00958 formula()->elementRemoval(upperRight); 00959 upperRight = 0; 00960 setToUpperRight(cursor); 00961 break; 00962 case lowerRightPos: 00963 removedChildren.append(lowerRight); 00964 formula()->elementRemoval(lowerRight); 00965 lowerRight = 0; 00966 setToLowerRight(cursor); 00967 break; 00968 } 00969 formula()->changed(); 00970 } 00971 00976 void IndexElement::normalize(FormulaCursor* cursor, Direction direction) 00977 { 00978 if (direction == beforeCursor) { 00979 content->moveLeft(cursor, this); 00980 } 00981 else { 00982 content->moveRight(cursor, this); 00983 } 00984 } 00985 00991 bool IndexElement::isSenseless() 00992 { 00993 return !hasUpperLeft() && !hasUpperRight() && !hasUpperMiddle() && 00994 !hasLowerLeft() && !hasLowerRight() && !hasLowerMiddle(); 00995 } 00996 00997 01001 BasicElement* IndexElement::getChild(FormulaCursor* cursor, Direction) 01002 { 01003 int pos = cursor->getPos(); 01004 /* 01005 It makes no sense to care for the direction. 01006 if (direction == beforeCursor) { 01007 pos -= 1; 01008 } 01009 */ 01010 switch (pos) { 01011 case contentPos: 01012 return content; 01013 case upperLeftPos: 01014 return upperLeft; 01015 case lowerLeftPos: 01016 return lowerLeft; 01017 case upperMiddlePos: 01018 return upperMiddle; 01019 case lowerMiddlePos: 01020 return lowerMiddle; 01021 case upperRightPos: 01022 return upperRight; 01023 case lowerRightPos: 01024 return lowerRight; 01025 } 01026 return 0; 01027 } 01028 01029 01034 void IndexElement::selectChild(FormulaCursor* cursor, BasicElement* child) 01035 { 01036 if (child == content) { 01037 setToContent(cursor); 01038 } 01039 else if (child == upperLeft) { 01040 setToUpperLeft(cursor); 01041 } 01042 else if (child == lowerLeft) { 01043 setToLowerLeft(cursor); 01044 } 01045 else if (child == upperMiddle) { 01046 setToUpperMiddle(cursor); 01047 } 01048 else if (child == lowerMiddle) { 01049 setToLowerMiddle(cursor); 01050 } 01051 else if (child == upperRight) { 01052 setToUpperRight(cursor); 01053 } 01054 else if (child == lowerRight) { 01055 setToLowerRight(cursor); 01056 } 01057 } 01058 01059 01066 void IndexElement::setToContent(FormulaCursor* cursor) 01067 { 01068 cursor->setTo(this, contentPos); 01069 } 01070 01071 // point the cursor to a gap where an index is to be inserted. 01072 // this makes no sense if there is such an index already. 01073 01074 void IndexElement::setToUpperLeft(FormulaCursor* cursor) 01075 { 01076 cursor->setTo(this, upperLeftPos); 01077 } 01078 01079 void IndexElement::setToUpperMiddle(FormulaCursor* cursor) 01080 { 01081 cursor->setTo(this, upperMiddlePos); 01082 } 01083 01084 void IndexElement::setToUpperRight(FormulaCursor* cursor) 01085 { 01086 cursor->setTo(this, upperRightPos); 01087 } 01088 01089 void IndexElement::setToLowerLeft(FormulaCursor* cursor) 01090 { 01091 cursor->setTo(this, lowerLeftPos); 01092 } 01093 01094 void IndexElement::setToLowerMiddle(FormulaCursor* cursor) 01095 { 01096 cursor->setTo(this, lowerMiddlePos); 01097 } 01098 01099 void IndexElement::setToLowerRight(FormulaCursor* cursor) 01100 { 01101 cursor->setTo(this, lowerRightPos); 01102 } 01103 01104 01105 // move inside an index that exists already. 01106 01107 void IndexElement::moveToUpperLeft(FormulaCursor* cursor, Direction direction) 01108 { 01109 if (hasUpperLeft()) { 01110 if (direction == beforeCursor) { 01111 upperLeft->moveLeft(cursor, this); 01112 } 01113 else { 01114 upperLeft->moveRight(cursor, this); 01115 } 01116 } 01117 } 01118 01119 void IndexElement::moveToUpperMiddle(FormulaCursor* cursor, Direction direction) 01120 { 01121 if (hasUpperMiddle()) { 01122 if (direction == beforeCursor) { 01123 upperMiddle->moveLeft(cursor, this); 01124 } 01125 else { 01126 upperMiddle->moveRight(cursor, this); 01127 } 01128 } 01129 } 01130 01131 void IndexElement::moveToUpperRight(FormulaCursor* cursor, Direction direction) 01132 { 01133 if (hasUpperRight()) { 01134 if (direction == beforeCursor) { 01135 upperRight->moveLeft(cursor, this); 01136 } 01137 else { 01138 upperRight->moveRight(cursor, this); 01139 } 01140 } 01141 } 01142 01143 void IndexElement::moveToLowerLeft(FormulaCursor* cursor, Direction direction) 01144 { 01145 if (hasLowerLeft()) { 01146 if (direction == beforeCursor) { 01147 lowerLeft->moveLeft(cursor, this); 01148 } 01149 else { 01150 lowerLeft->moveRight(cursor, this); 01151 } 01152 } 01153 } 01154 01155 void IndexElement::moveToLowerMiddle(FormulaCursor* cursor, Direction direction) 01156 { 01157 if (hasLowerMiddle()) { 01158 if (direction == beforeCursor) { 01159 lowerMiddle->moveLeft(cursor, this); 01160 } 01161 else { 01162 lowerMiddle->moveRight(cursor, this); 01163 } 01164 } 01165 } 01166 01167 void IndexElement::moveToLowerRight(FormulaCursor* cursor, Direction direction) 01168 { 01169 if (hasLowerRight()) { 01170 if (direction == beforeCursor) { 01171 lowerRight->moveLeft(cursor, this); 01172 } 01173 else { 01174 lowerRight->moveRight(cursor, this); 01175 } 01176 } 01177 } 01178 01179 01183 void IndexElement::writeDom(QDomElement element) 01184 { 01185 BasicElement::writeDom(element); 01186 01187 QDomDocument doc = element.ownerDocument(); 01188 01189 QDomElement cont = doc.createElement("CONTENT"); 01190 cont.appendChild(content->getElementDom(doc)); 01191 element.appendChild(cont); 01192 01193 if (hasUpperLeft()) { 01194 QDomElement ind = doc.createElement("UPPERLEFT"); 01195 ind.appendChild(upperLeft->getElementDom(doc)); 01196 element.appendChild(ind); 01197 } 01198 if (hasUpperMiddle()) { 01199 QDomElement ind = doc.createElement("UPPERMIDDLE"); 01200 ind.appendChild(upperMiddle->getElementDom(doc)); 01201 element.appendChild(ind); 01202 } 01203 if (hasUpperRight()) { 01204 QDomElement ind = doc.createElement("UPPERRIGHT"); 01205 ind.appendChild(upperRight->getElementDom(doc)); 01206 element.appendChild(ind); 01207 } 01208 if (hasLowerLeft()) { 01209 QDomElement ind = doc.createElement("LOWERLEFT"); 01210 ind.appendChild(lowerLeft->getElementDom(doc)); 01211 element.appendChild(ind); 01212 } 01213 if (hasLowerMiddle()) { 01214 QDomElement ind = doc.createElement("LOWERMIDDLE"); 01215 ind.appendChild(lowerMiddle->getElementDom(doc)); 01216 element.appendChild(ind); 01217 } 01218 if (hasLowerRight()) { 01219 QDomElement ind = doc.createElement("LOWERRIGHT"); 01220 ind.appendChild(lowerRight->getElementDom(doc)); 01221 element.appendChild(ind); 01222 } 01223 } 01224 01229 bool IndexElement::readAttributesFromDom(QDomElement element) 01230 { 01231 if (!BasicElement::readAttributesFromDom(element)) { 01232 return false; 01233 } 01234 return true; 01235 } 01236 01242 bool IndexElement::readContentFromDom(QDomNode& node) 01243 { 01244 if (!BasicElement::readContentFromDom(node)) { 01245 return false; 01246 } 01247 01248 if ( !buildChild( content, node, "CONTENT" ) ) { 01249 kdWarning( DEBUGID ) << "Empty content in IndexElement." << endl; 01250 return false; 01251 } 01252 node = node.nextSibling(); 01253 01254 bool upperLeftRead = false; 01255 bool upperMiddleRead = false; 01256 bool upperRightRead = false; 01257 bool lowerLeftRead = false; 01258 bool lowerMiddleRead = false; 01259 bool lowerRightRead = false; 01260 01261 while (!node.isNull() && 01262 !(upperLeftRead && upperMiddleRead && upperRightRead && 01263 lowerLeftRead && lowerMiddleRead && lowerRightRead)) { 01264 01265 if (!upperLeftRead && (node.nodeName().upper() == "UPPERLEFT")) { 01266 upperLeftRead = buildChild( upperLeft=new SequenceElement( this ), node, "UPPERLEFT" ); 01267 if ( !upperLeftRead ) return false; 01268 } 01269 01270 if (!upperMiddleRead && (node.nodeName().upper() == "UPPERMIDDLE")) { 01271 upperMiddleRead = buildChild( upperMiddle=new SequenceElement( this ), node, "UPPERMIDDLE" ); 01272 if ( !upperMiddleRead ) return false; 01273 } 01274 01275 if (!upperRightRead && (node.nodeName().upper() == "UPPERRIGHT")) { 01276 upperRightRead = buildChild( upperRight=new SequenceElement( this ), node, "UPPERRIGHT" ); 01277 if ( !upperRightRead ) return false; 01278 } 01279 01280 if (!lowerLeftRead && (node.nodeName().upper() == "LOWERLEFT")) { 01281 lowerLeftRead = buildChild( lowerLeft=new SequenceElement( this ), node, "LOWERLEFT" ); 01282 if ( !lowerLeftRead ) return false; 01283 } 01284 01285 if (!lowerMiddleRead && (node.nodeName().upper() == "LOWERMIDDLE")) { 01286 lowerMiddleRead = buildChild( lowerMiddle=new SequenceElement( this ), node, "LOWERMIDDLE" ); 01287 if ( !lowerMiddleRead ) return false; 01288 } 01289 01290 if (!lowerRightRead && (node.nodeName().upper() == "LOWERRIGHT")) { 01291 lowerRightRead = buildChild( lowerRight=new SequenceElement( this ), node, "LOWERRIGHT" ); 01292 if ( !lowerRightRead ) return false; 01293 } 01294 01295 node = node.nextSibling(); 01296 } 01297 return upperLeftRead || upperMiddleRead || upperRightRead || 01298 lowerLeftRead || lowerMiddleRead || lowerRightRead; 01299 } 01300 01301 ElementIndexPtr IndexElement::getIndex( int position ) 01302 { 01303 switch (position) { 01304 case upperRightPos: 01305 return getUpperRight(); 01306 case lowerRightPos: 01307 return getLowerRight(); 01308 case lowerMiddlePos: 01309 return getLowerMiddle(); 01310 case upperMiddlePos: 01311 return getUpperMiddle(); 01312 case lowerLeftPos: 01313 return getLowerLeft(); 01314 case upperLeftPos: 01315 return getUpperLeft(); 01316 } 01317 return getUpperRight(); 01318 } 01319 01320 01321 01322 QString IndexElement::toLatex() 01323 { 01324 QString index; 01325 01326 if ( hasUpperMiddle() ) { 01327 index += "\\overset" + upperMiddle->toLatex() + "{"; 01328 } 01329 01330 if ( hasLowerMiddle() ) { 01331 index += "\\underset" + lowerMiddle->toLatex() + "{"; 01332 } 01333 01334 if ( hasUpperLeft() || hasUpperRight() ) { 01335 index += "{}"; 01336 if ( hasUpperLeft() ) 01337 index += "^" + upperLeft->toLatex(); 01338 if ( hasLowerLeft() ) 01339 index += "_" + lowerLeft->toLatex(); 01340 } 01341 01342 index += content->toLatex(); 01343 01344 if ( hasUpperRight() ) 01345 index += "^" + upperRight->toLatex(); 01346 if ( hasLowerRight() ) 01347 index += "_" + lowerRight->toLatex(); 01348 01349 if ( hasLowerMiddle() ) { 01350 index += "}"; 01351 } 01352 01353 if ( hasUpperMiddle() ) { 01354 index += "}"; 01355 } 01356 01357 return index; 01358 } 01359 01360 QString IndexElement::formulaString() 01361 { 01362 QString index = "(" + content->formulaString() + ")"; 01363 if ( hasLowerRight() ) { 01364 index += "_(" + lowerRight->formulaString() + ")"; 01365 } 01366 if ( hasUpperRight() ) { 01367 index += "**(" + upperRight->formulaString() + ")"; 01368 } 01369 return index; 01370 } 01371 01372 void IndexElement::writeMathML( QDomDocument doc, QDomNode parent ) 01373 { 01374 QDomElement de; 01375 QDomElement uo; 01376 bool uoscripts = true; 01377 01378 if ( hasUpperMiddle() && hasLowerMiddle() ) 01379 { 01380 uo = doc.createElement( "munderover" ); 01381 content->writeMathML( doc, uo ); // base 01382 lowerMiddle->writeMathML( doc, uo ); 01383 upperMiddle->writeMathML( doc, uo ); 01384 } 01385 else if ( hasUpperMiddle() ) 01386 { 01387 uo = doc.createElement( "mover" ); 01388 content->writeMathML( doc, uo ); // base 01389 upperMiddle->writeMathML( doc, uo ); 01390 } 01391 else if ( hasLowerMiddle() ) 01392 { 01393 uo = doc.createElement( "munder" ); 01394 content->writeMathML( doc, uo ); // base 01395 lowerMiddle->writeMathML( doc, uo ); 01396 } 01397 else // no over- or underscripts 01398 uoscripts = false; 01399 01400 01401 if ( hasLowerLeft() || hasUpperLeft() ) 01402 { 01403 de = doc.createElement( "mmultiscripts" ); 01404 if ( !uoscripts ) // base 01405 content->writeMathML( doc, de ); 01406 else 01407 de.appendChild( uo ); 01408 01409 if ( hasLowerRight() ) 01410 lowerRight->writeMathML( doc, de ); 01411 else 01412 de.appendChild( doc.createElement( "none" ) ); 01413 01414 if ( hasUpperRight() ) 01415 upperRight->writeMathML( doc, de ); 01416 else 01417 de.appendChild( doc.createElement( "none" ) ); 01418 01419 de.appendChild( doc.createElement( "mprescripts" ) ); 01420 01421 if ( hasLowerLeft() ) 01422 lowerLeft->writeMathML( doc, de ); 01423 else 01424 de.appendChild( doc.createElement( "none" ) ); 01425 01426 if ( hasUpperLeft() ) 01427 upperLeft->writeMathML( doc, de ); 01428 else 01429 de.appendChild( doc.createElement( "none" ) ); 01430 } 01431 else if ( hasLowerRight() || hasUpperRight() ) 01432 { 01433 if ( !hasUpperRight() ) 01434 { 01435 de = doc.createElement( "msub" ); 01436 if ( !uoscripts ) // base 01437 content->writeMathML( doc, de ); 01438 else 01439 de.appendChild( uo ); 01440 lowerRight->writeMathML( doc, de ); 01441 } 01442 else if ( !hasLowerRight() ) 01443 { 01444 de = doc.createElement( "msup" ); 01445 if ( !uoscripts ) // base 01446 content->writeMathML( doc, de ); 01447 else 01448 de.appendChild( uo ); 01449 upperRight->writeMathML( doc, de ); 01450 } 01451 else // both 01452 { 01453 de = doc.createElement( "msubsup" ); 01454 if ( !uoscripts ) // base 01455 content->writeMathML( doc, de ); 01456 else 01457 de.appendChild( uo ); 01458 lowerRight->writeMathML( doc, de ); 01459 upperRight->writeMathML( doc, de ); 01460 } 01461 } 01462 else // no mmultiscripts, msubsup, msub or msup 01463 de = uo; 01464 01465 01466 parent.appendChild( de ); 01467 01468 } 01469 01470 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:22 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003