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 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 );
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 );
01389 upperMiddle->
writeMathML( doc, uo );
01390 }
01391
else if ( hasLowerMiddle() )
01392 {
01393 uo = doc.createElement(
"munder" );
01394 content->
writeMathML( doc, uo );
01395 lowerMiddle->
writeMathML( doc, uo );
01396 }
01397
else
01398 uoscripts =
false;
01399
01400
01401
if ( hasLowerLeft() || hasUpperLeft() )
01402 {
01403 de = doc.createElement(
"mmultiscripts" );
01404
if ( !uoscripts )
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 )
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 )
01446 content->
writeMathML( doc, de );
01447
else
01448 de.appendChild( uo );
01449 upperRight->
writeMathML( doc, de );
01450 }
01451
else
01452 {
01453 de = doc.createElement(
"msubsup" );
01454
if ( !uoscripts )
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
01463 de = uo;
01464
01465
01466 parent.appendChild( de );
01467
01468 }
01469
01470 KFORMULA_NAMESPACE_END