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
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
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
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
00311
00312
00313
00314
00315
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
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
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
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
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
00441 ulOffset = ulHeight + exBaseline - content->getBaseline();
00442 urOffset = urHeight + exBaseline - content->getBaseline();
00443
00444
00445 llOffset = lrOffset = content->getBaseline();
00446 }
00447 else {
00448
00449
00450 ulOffset = QMAX(ulMidline, ulHeight-toMidline);
00451 urOffset = QMAX(urMidline, urHeight-toMidline);
00452
00453
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
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
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
00486 setWidth(width);
00487 setHeight(toMidline+fromMidline);
00488 if (content->isTextOnly()) {
00489 setBaseline(content->getY() + content->getBaseline());
00490
00491 }
00492 else {
00493
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
00511
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
00538
00539
00540
00541
00542
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
00571
00572
00573
00574
00575
00576
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
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
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
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
01006
01007
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
01072
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
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
01336
01337
01338
01339
01340
01341 }
01342
01343 index += content->toLatex();
01344
01345 if ( hasUpperRight() || hasLowerRight() ) {
01346 if ( hasUpperRight() )
01347 index += "^{" + upperRight->toLatex() + "}";
01348 if ( hasLowerRight() )
01349 index += "_{" + lowerRight->toLatex() + "}";
01350 index += " ";
01351 }
01352
01353 if ( hasLowerMiddle() ) {
01354 index += "}";
01355 }
01356
01357 if ( hasUpperMiddle() ) {
01358 index += "}";
01359 }
01360
01361 return index;
01362 }
01363
01364 QString IndexElement::formulaString()
01365 {
01366 QString index = "(" + content->formulaString() + ")";
01367 if ( hasLowerRight() ) {
01368 index += "_(" + lowerRight->formulaString() + ")";
01369 }
01370 if ( hasUpperRight() ) {
01371 index += "**(" + upperRight->formulaString() + ")";
01372 }
01373 return index;
01374 }
01375
01376 void IndexElement::writeMathML( QDomDocument& doc, QDomNode& parent, bool oasisFormat )
01377 {
01378 QDomElement de;
01379 QDomElement uo;
01380 bool uoscripts = true;
01381
01382 if ( hasUpperMiddle() && hasLowerMiddle() )
01383 {
01384 uo = doc.createElement( "munderover" );
01385 content->writeMathML( doc, uo, oasisFormat );
01386 lowerMiddle->writeMathML( doc, uo, oasisFormat );
01387 upperMiddle->writeMathML( doc, uo,oasisFormat );
01388 }
01389 else if ( hasUpperMiddle() )
01390 {
01391 uo = doc.createElement( "mover" );
01392 content->writeMathML( doc, uo,oasisFormat );
01393 upperMiddle->writeMathML( doc, uo,oasisFormat );
01394 }
01395 else if ( hasLowerMiddle() )
01396 {
01397 uo = doc.createElement( "munder" );
01398 content->writeMathML( doc, uo, oasisFormat );
01399 lowerMiddle->writeMathML( doc, uo,oasisFormat );
01400 }
01401 else
01402 uoscripts = false;
01403
01404
01405 if ( hasLowerLeft() || hasUpperLeft() )
01406 {
01407 de = doc.createElement( "mmultiscripts" );
01408 if ( !uoscripts )
01409 content->writeMathML( doc, de, oasisFormat );
01410 else
01411 de.appendChild( uo );
01412
01413 if ( hasLowerRight() )
01414 lowerRight->writeMathML( doc, de, oasisFormat );
01415 else
01416 de.appendChild( doc.createElement( "none" ) );
01417
01418 if ( hasUpperRight() )
01419 upperRight->writeMathML( doc, de, oasisFormat );
01420 else
01421 de.appendChild( doc.createElement( "none" ) );
01422
01423 de.appendChild( doc.createElement( "mprescripts" ) );
01424
01425 if ( hasLowerLeft() )
01426 lowerLeft->writeMathML( doc, de, oasisFormat );
01427 else
01428 de.appendChild( doc.createElement( "none" ) );
01429
01430 if ( hasUpperLeft() )
01431 upperLeft->writeMathML( doc, de, oasisFormat );
01432 else
01433 de.appendChild( doc.createElement( "none" ) );
01434 }
01435 else if ( hasLowerRight() || hasUpperRight() )
01436 {
01437 if ( !hasUpperRight() )
01438 {
01439 de = doc.createElement( "msub" );
01440 if ( !uoscripts )
01441 content->writeMathML( doc, de, oasisFormat );
01442 else
01443 de.appendChild( uo );
01444 lowerRight->writeMathML( doc, de, oasisFormat );
01445 }
01446 else if ( !hasLowerRight() )
01447 {
01448 de = doc.createElement( "msup" );
01449 if ( !uoscripts )
01450 content->writeMathML( doc, de, oasisFormat );
01451 else
01452 de.appendChild( uo );
01453 upperRight->writeMathML( doc, de, oasisFormat );
01454 }
01455 else
01456 {
01457 de = doc.createElement( "msubsup" );
01458 if ( !uoscripts )
01459 content->writeMathML( doc, de, oasisFormat );
01460 else
01461 de.appendChild( uo );
01462 lowerRight->writeMathML( doc, de, oasisFormat );
01463 upperRight->writeMathML( doc, de,oasisFormat );
01464 }
01465 }
01466 else
01467 de = uo;
01468
01469
01470 parent.appendChild( de );
01471
01472 }
01473
01474 KFORMULA_NAMESPACE_END