00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
#include <qmemarray.h>
00022
#include <qpainter.h>
00023
#include <qptrlist.h>
00024
00025
#include <kdebug.h>
00026
#include <klocale.h>
00027
00028
#include "MatrixDialog.h"
00029
#include "elementvisitor.h"
00030
#include "formulaelement.h"
00031
#include "formulacursor.h"
00032
#include "kformulacontainer.h"
00033
#include "kformulacommand.h"
00034
#include "matrixelement.h"
00035
#include "sequenceelement.h"
00036
#include "spaceelement.h"
00037
00038
00039 KFORMULA_NAMESPACE_BEGIN
00040
00041
00042
class MatrixSequenceElement :
public SequenceElement {
00043
typedef SequenceElement inherited;
00044
public:
00045
00046 MatrixSequenceElement(
BasicElement* parent = 0 ) :
SequenceElement( parent ) {}
00047
virtual MatrixSequenceElement* clone() {
00048
return new MatrixSequenceElement( *
this );
00049 }
00050
00059
virtual KCommand* buildCommand(
Container*, Request* );
00060 };
00061
00062
00063
class KFCRemoveRow :
public Command {
00064
public:
00065 KFCRemoveRow(
const QString& name,
Container* document,
MatrixElement* m, uint r, uint c );
00066 ~KFCRemoveRow();
00067
00068
virtual void execute();
00069
virtual void unexecute();
00070
00071
protected:
00072
MatrixElement* matrix;
00073 uint rowPos;
00074 uint colPos;
00075
00076
QPtrList<MatrixSequenceElement>* row;
00077 };
00078
00079
00080
class KFCInsertRow :
public KFCRemoveRow {
00081
public:
00082 KFCInsertRow(
const QString& name,
Container* document,
MatrixElement* m, uint r, uint c );
00083
00084
virtual void execute() { KFCRemoveRow::unexecute(); }
00085
virtual void unexecute() { KFCRemoveRow::execute(); }
00086 };
00087
00088
00089
class KFCRemoveColumn :
public Command {
00090
public:
00091 KFCRemoveColumn(
const QString& name,
Container* document,
MatrixElement* m, uint r, uint c );
00092 ~KFCRemoveColumn();
00093
00094
virtual void execute();
00095
virtual void unexecute();
00096
00097
protected:
00098
MatrixElement* matrix;
00099 uint rowPos;
00100 uint colPos;
00101
00102
QPtrList<MatrixSequenceElement>* column;
00103 };
00104
00105
00106
class KFCInsertColumn :
public KFCRemoveColumn {
00107
public:
00108 KFCInsertColumn(
const QString& name,
Container* document,
MatrixElement* m, uint r, uint c );
00109
00110
virtual void execute() { KFCRemoveColumn::unexecute(); }
00111
virtual void unexecute() { KFCRemoveColumn::execute(); }
00112 };
00113
00114
00115 KCommand* MatrixSequenceElement::buildCommand(
Container* container, Request* request )
00116 {
00117
FormulaCursor* cursor = container->
activeCursor();
00118
if ( cursor->
isReadOnly() ) {
00119
return 0;
00120 }
00121
00122
switch ( *request ) {
00123
case req_appendColumn:
00124
case req_appendRow:
00125
case req_insertColumn:
00126
case req_removeColumn:
00127
case req_insertRow:
00128
case req_removeRow: {
00129
MatrixElement* matrix = static_cast<MatrixElement*>( getParent() );
00130
FormulaCursor* cursor = container->
activeCursor();
00131
for ( uint row = 0; row < matrix->
getRows(); row++ ) {
00132
for ( uint col = 0; col < matrix->
getColumns(); col++ ) {
00133
if ( matrix->
getElement( row, col ) == cursor->
getElement() ) {
00134
switch ( *request ) {
00135
case req_appendColumn:
00136
return new KFCInsertColumn( i18n(
"Append Column" ), container, matrix, row, matrix->
getColumns() );
00137
case req_appendRow:
00138
return new KFCInsertRow( i18n(
"Append Row" ), container, matrix, matrix->
getRows(), col );
00139
case req_insertColumn:
00140
return new KFCInsertColumn( i18n(
"Insert Column" ), container, matrix, row, col );
00141
case req_removeColumn:
00142
if ( matrix->
getColumns() > 1 ) {
00143
return new KFCRemoveColumn( i18n(
"Remove Column" ), container, matrix, row, col );
00144 }
00145
break;
00146
case req_insertRow:
00147
return new KFCInsertRow( i18n(
"Insert Row" ), container, matrix, row, col );
00148
case req_removeRow:
00149
if ( matrix->
getRows() > 1 ) {
00150
return new KFCRemoveRow( i18n(
"Remove Row" ), container, matrix, row, col );
00151 }
00152
break;
00153
default:
00154
break;
00155 }
00156 }
00157 }
00158 }
00159 kdWarning( DEBUGID ) <<
"MatrixSequenceElement::buildCommand: Sequence not found." << endl;
00160
break;
00161 }
00162
default:
00163
break;
00164 }
00165
return inherited::buildCommand( container, request );
00166 }
00167
00168
00169 KFCRemoveRow::KFCRemoveRow(
const QString& name,
Container* document,
MatrixElement* m, uint r, uint c )
00170 : Command( name, document ), matrix( m ), rowPos( r ), colPos( c ), row( 0 )
00171 {
00172 }
00173
00174 KFCRemoveRow::~KFCRemoveRow()
00175 {
00176
delete row;
00177 }
00178
00179
void KFCRemoveRow::execute()
00180 {
00181
FormulaCursor* cursor = getExecuteCursor();
00182 row = matrix->
content.at( rowPos );
00183
FormulaElement* formula = matrix->
formula();
00184
for ( uint i = matrix->
getColumns(); i > 0; i-- ) {
00185 formula->
elementRemoval( row->at( i-1 ) );
00186 }
00187 matrix->
content.take( rowPos );
00188 formula->
changed();
00189
if ( rowPos < matrix->
getRows() ) {
00190 matrix->
getElement( rowPos, colPos )->goInside( cursor );
00191 }
00192
else {
00193 matrix->
getElement( rowPos-1, colPos )->goInside( cursor );
00194 }
00195 testDirty();
00196 }
00197
00198
void KFCRemoveRow::unexecute()
00199 {
00200 matrix->
content.insert( rowPos, row );
00201 row = 0;
00202
FormulaCursor* cursor = getExecuteCursor();
00203 matrix->
getElement( rowPos, colPos )->goInside( cursor );
00204 matrix->
formula()->
changed();
00205 testDirty();
00206 }
00207
00208
00209 KFCInsertRow::KFCInsertRow(
const QString& name,
Container* document,
MatrixElement* m, uint r, uint c )
00210 : KFCRemoveRow( name, document, m, r, c )
00211 {
00212 row =
new QPtrList< MatrixSequenceElement >;
00213 row->setAutoDelete(
true );
00214
for ( uint i = 0; i < matrix->
getColumns(); i++ ) {
00215 row->append(
new MatrixSequenceElement( matrix ) );
00216 }
00217 }
00218
00219
00220 KFCRemoveColumn::KFCRemoveColumn(
const QString& name,
Container* document,
MatrixElement* m, uint r, uint c )
00221 : Command( name, document ), matrix( m ), rowPos( r ), colPos( c )
00222 {
00223 column =
new QPtrList< MatrixSequenceElement >;
00224 column->setAutoDelete(
true );
00225 }
00226
00227 KFCRemoveColumn::~KFCRemoveColumn()
00228 {
00229
delete column;
00230 }
00231
00232
void KFCRemoveColumn::execute()
00233 {
00234
FormulaCursor* cursor = getExecuteCursor();
00235
FormulaElement* formula = matrix->
formula();
00236
for ( uint i = 0; i < matrix->
getRows(); i++ ) {
00237 column->append( matrix->
getElement( i, colPos ) );
00238 formula->
elementRemoval( column->at( i ) );
00239 matrix->
content.at( i )->take( colPos );
00240 }
00241 formula->
changed();
00242
if ( colPos < matrix->
getColumns() ) {
00243 matrix->
getElement( rowPos, colPos )->goInside( cursor );
00244 }
00245
else {
00246 matrix->
getElement( rowPos, colPos-1 )->goInside( cursor );
00247 }
00248 testDirty();
00249 }
00250
00251
void KFCRemoveColumn::unexecute()
00252 {
00253
for ( uint i = 0; i < matrix->
getRows(); i++ ) {
00254 matrix->
content.at( i )->insert( colPos, column->take( 0 ) );
00255 }
00256
FormulaCursor* cursor = getExecuteCursor();
00257 matrix->
getElement( rowPos, colPos )->goInside( cursor );
00258 matrix->
formula()->
changed();
00259 testDirty();
00260 }
00261
00262
00263 KFCInsertColumn::KFCInsertColumn(
const QString& name,
Container* document,
MatrixElement* m, uint r, uint c )
00264 : KFCRemoveColumn( name, document, m, r, c )
00265 {
00266
for ( uint i = 0; i < matrix->
getRows(); i++ ) {
00267 column->append(
new MatrixSequenceElement( matrix ) );
00268 }
00269 }
00270
00271
00272 MatrixElement::MatrixElement(uint rows, uint columns,
BasicElement* parent)
00273 :
BasicElement(parent)
00274 {
00275
for (uint r = 0; r < rows; r++) {
00276 QPtrList< MatrixSequenceElement >* list =
new QPtrList< MatrixSequenceElement >;
00277 list->setAutoDelete(
true);
00278
for (uint c = 0; c < columns; c++) {
00279 list->append(
new MatrixSequenceElement(
this));
00280 }
00281 content.append(list);
00282 }
00283 content.setAutoDelete(
true);
00284 }
00285
00286 MatrixElement::~MatrixElement()
00287 {
00288 }
00289
00290
00291 MatrixElement::MatrixElement(
const MatrixElement& other )
00292 :
BasicElement( other )
00293 {
00294 uint rows = other.
getRows();
00295 uint columns = other.
getColumns();
00296
00297
QPtrListIterator< QPtrList< MatrixSequenceElement > > rowIter( other.
content );
00298
for (uint r = 0; r < rows; r++) {
00299 ++rowIter;
00300
QPtrListIterator< MatrixSequenceElement > colIter( *rowIter.current() );
00301
00302 QPtrList< MatrixSequenceElement >* list =
new QPtrList< MatrixSequenceElement >;
00303 list->setAutoDelete(
true);
00304
for (uint c = 0; c < columns; c++) {
00305 ++colIter;
00306 MatrixSequenceElement *mse =
00307
00308
new MatrixSequenceElement( *colIter.current() );
00309 list->append( mse );
00310 mse->setParent(
this );
00311 }
00312 content.append(list);
00313 }
00314 content.setAutoDelete(
true);
00315 }
00316
00317
00318 bool MatrixElement::accept(
ElementVisitor* visitor )
00319 {
00320
return visitor->
visit(
this );
00321 }
00322
00323
00324 void MatrixElement::entered(
SequenceElement* )
00325 {
00326
formula()->
tell( i18n(
"Matrix element" ) );
00327 }
00328
00329
00330 BasicElement*
MatrixElement::goToPos(
FormulaCursor* cursor,
bool& handled,
00331
const LuPixelPoint& point,
const LuPixelPoint& parentOrigin )
00332 {
00333
BasicElement* e = BasicElement::goToPos(cursor, handled, point, parentOrigin);
00334
if (e != 0) {
00335
LuPixelPoint myPos(parentOrigin.x() + getX(),
00336 parentOrigin.y() + getY());
00337
00338 uint rows = getRows();
00339 uint columns = getColumns();
00340
00341
for (uint r = 0; r < rows; r++) {
00342
for (uint c = 0; c < columns; c++) {
00343
BasicElement* element = getElement(r, c);
00344 e = element->
goToPos(cursor, handled, point, myPos);
00345
if (e != 0) {
00346
return e;
00347 }
00348 }
00349 }
00350
00351
00352 luPixel dx = point.x() - myPos.x();
00353 luPixel dy = point.y() - myPos.y();
00354
00355 uint row = rows;
00356
for (uint r = 0; r < rows; r++) {
00357
BasicElement* element = getElement(r, 0);
00358
if (element->
getY() > dy) {
00359 row = r;
00360
break;
00361 }
00362 }
00363
if (row == 0) {
00364
BasicElement* element = getParent();
00365 element->
moveLeft(cursor,
this);
00366 handled =
true;
00367
return element;
00368 }
00369 row--;
00370
00371 uint column = columns;
00372
for (uint c = 0; c < columns; c++) {
00373
BasicElement* element = getElement(row, c);
00374
if (element->
getX() > dx) {
00375 column = c;
00376
break;
00377 }
00378 }
00379
if (column == 0) {
00380
BasicElement* element = getParent();
00381 element->
moveLeft(cursor,
this);
00382 handled =
true;
00383
return element;
00384 }
00385 column--;
00386
00387
00388 row = rows;
00389
for (uint r = 0; r < rows; r++) {
00390
BasicElement* element = getElement(r, column);
00391
if (element->
getY() > dy) {
00392 row = r;
00393
break;
00394 }
00395 }
00396
if (row == 0) {
00397
BasicElement* element = getParent();
00398 element->
moveLeft(cursor,
this);
00399 handled =
true;
00400
return element;
00401 }
00402 row--;
00403
00404
BasicElement* element = getElement(row, column);
00405 element->
moveLeft(cursor,
this);
00406 handled =
true;
00407
return element;
00408 }
00409
return 0;
00410 }
00411
00412
00413
00414
00415
00416
00417
00418
00419
00424 void MatrixElement::calcSizes(
const ContextStyle& style, ContextStyle::TextStyle tstyle, ContextStyle::IndexStyle istyle)
00425 {
00426
QMemArray<luPixel> toMidlines(getRows());
00427
QMemArray<luPixel> fromMidlines(getRows());
00428
QMemArray<luPixel> widths(getColumns());
00429
00430 toMidlines.fill(0);
00431 fromMidlines.fill(0);
00432 widths.fill(0);
00433
00434 uint rows = getRows();
00435 uint columns = getColumns();
00436
00437 ContextStyle::TextStyle i_tstyle = style.convertTextStyleFraction(tstyle);
00438 ContextStyle::IndexStyle i_istyle = style.convertIndexStyleUpper(istyle);
00439
00440
for (uint r = 0; r < rows; r++) {
00441 QPtrList< MatrixSequenceElement >* list = content.at(r);
00442
for (uint c = 0; c < columns; c++) {
00443
SequenceElement* element = list->at(c);
00444 element->
calcSizes( style, i_tstyle, i_istyle );
00445 toMidlines[r] = QMAX(toMidlines[r], element->
axis( style, i_tstyle ));
00446 fromMidlines[r] = QMAX(fromMidlines[r],
00447 element->
getHeight()-element->
axis( style, i_tstyle ));
00448 widths[c] = QMAX(widths[c], element->
getWidth());
00449 }
00450 }
00451
00452 luPixel distX = style.ptToPixelX( style.getThinSpace( tstyle ) );
00453 luPixel distY = style.ptToPixelY( style.getThinSpace( tstyle ) );
00454
00455 luPixel yPos = 0;
00456
for (uint r = 0; r < rows; r++) {
00457 QPtrList< MatrixSequenceElement >* list = content.at(r);
00458 luPixel xPos = 0;
00459 yPos += toMidlines[r];
00460
for (uint c = 0; c < columns; c++) {
00461
SequenceElement* element = list->at(c);
00462
switch (style.getMatrixAlignment()) {
00463
case ContextStyle::left:
00464 element->
setX(xPos);
00465
break;
00466
case ContextStyle::center:
00467 element->
setX(xPos + (widths[c] - element->
getWidth())/2);
00468
break;
00469
case ContextStyle::right:
00470 element->
setX(xPos + widths[c] - element->
getWidth());
00471
break;
00472 }
00473 element->
setY(yPos - element->
axis( style, i_tstyle ));
00474 xPos += widths[c] + distX;
00475 }
00476 yPos += fromMidlines[r] + distY;
00477 }
00478
00479 luPixel width = distX * (columns - 1);
00480 luPixel height = distY * (rows - 1);
00481
00482
for (uint r = 0; r < rows; r++) height += toMidlines[r] + fromMidlines[r];
00483
for (uint c = 0; c < columns; c++) width += widths[c];
00484
00485 setWidth(width);
00486 setHeight(height);
00487
if ((rows == 2) && (columns == 1)) {
00488 setBaseline(
getMainChild()->getHeight() + distY / 2 + style.axisHeight( tstyle ) );
00489 }
00490
else {
00491 setBaseline( height/2 + style.axisHeight( tstyle ) );
00492 }
00493 }
00494
00500 void MatrixElement::draw(
QPainter& painter,
const LuPixelRect& rect,
00501
const ContextStyle& style,
00502 ContextStyle::TextStyle tstyle,
00503 ContextStyle::IndexStyle istyle,
00504
const LuPixelPoint& parentOrigin )
00505 {
00506
LuPixelPoint myPos( parentOrigin.x()+getX(), parentOrigin.y()+getY() );
00507
00508
00509
00510 uint rows = getRows();
00511 uint columns = getColumns();
00512
00513
for (uint r = 0; r < rows; r++) {
00514
for (uint c = 0; c < columns; c++) {
00515 getElement(r, c)->draw(painter, rect, style,
00516 style.convertTextStyleFraction(tstyle),
00517 style.convertIndexStyleUpper(istyle),
00518 myPos);
00519 }
00520 }
00521
00522
00523
00524
00525 }
00526
00527
00528 void MatrixElement::dispatchFontCommand(
FontCommand* cmd )
00529 {
00530 uint rows = getRows();
00531 uint columns = getColumns();
00532
00533
for (uint r = 0; r < rows; r++) {
00534
for (uint c = 0; c < columns; c++) {
00535 getElement(r, c)->dispatchFontCommand( cmd );
00536 }
00537 }
00538 }
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00554 void MatrixElement::moveLeft(
FormulaCursor* cursor,
BasicElement* from)
00555 {
00556
if (cursor->
isSelectionMode()) {
00557 getParent()->moveLeft(cursor,
this);
00558 }
00559
else {
00560
if (from == getParent()) {
00561 getElement(getRows()-1, getColumns()-1)->moveLeft(cursor,
this);
00562 }
00563
else {
00564
bool linear = cursor->
getLinearMovement();
00565 uint row = 0;
00566 uint column = 0;
00567
if (searchElement(from, row, column)) {
00568
if (column > 0) {
00569 getElement(row, column-1)->moveLeft(cursor,
this);
00570 }
00571
else if (linear && (row > 0)) {
00572 getElement(row-1, getColumns()-1)->moveLeft(cursor,
this);
00573 }
00574
else {
00575 getParent()->moveLeft(cursor,
this);
00576 }
00577 }
00578
else {
00579 getParent()->moveLeft(cursor,
this);
00580 }
00581 }
00582 }
00583 }
00584
00590 void MatrixElement::moveRight(
FormulaCursor* cursor,
BasicElement* from)
00591 {
00592
if (cursor->
isSelectionMode()) {
00593 getParent()->moveRight(cursor,
this);
00594 }
00595
else {
00596
if (from == getParent()) {
00597 getElement(0, 0)->moveRight(cursor,
this);
00598 }
00599
else {
00600
bool linear = cursor->
getLinearMovement();
00601 uint row = 0;
00602 uint column = 0;
00603
if (searchElement(from, row, column)) {
00604
if (column < getColumns()-1) {
00605 getElement(row, column+1)->moveRight(cursor,
this);
00606 }
00607
else if (linear && (row < getRows()-1)) {
00608 getElement(row+1, 0)->moveRight(cursor,
this);
00609 }
00610
else {
00611 getParent()->moveRight(cursor,
this);
00612 }
00613 }
00614
else {
00615 getParent()->moveRight(cursor,
this);
00616 }
00617 }
00618 }
00619 }
00620
00626 void MatrixElement::moveUp(
FormulaCursor* cursor,
BasicElement* from)
00627 {
00628
if (cursor->
isSelectionMode()) {
00629 getParent()->moveUp(cursor,
this);
00630 }
00631
else {
00632
if (from == getParent()) {
00633 getElement(0, 0)->moveRight(cursor,
this);
00634 }
00635
else {
00636 uint row = 0;
00637 uint column = 0;
00638
if (searchElement(from, row, column)) {
00639
if (row > 0) {
00640 getElement(row-1, column)->moveRight(cursor,
this);
00641 }
00642
else {
00643 getParent()->moveUp(cursor,
this);
00644 }
00645 }
00646
else {
00647 getParent()->moveUp(cursor,
this);
00648 }
00649 }
00650 }
00651 }
00652
00658 void MatrixElement::moveDown(
FormulaCursor* cursor,
BasicElement* from)
00659 {
00660
if (cursor->
isSelectionMode()) {
00661 getParent()->moveDown(cursor,
this);
00662 }
00663
else {
00664
if (from == getParent()) {
00665 getElement(0, 0)->moveRight(cursor,
this);
00666 }
00667
else {
00668 uint row = 0;
00669 uint column = 0;
00670
if (searchElement(from, row, column)) {
00671
if (row < getRows()-1) {
00672 getElement(row+1, column)->moveRight(cursor,
this);
00673 }
00674
else {
00675 getParent()->moveDown(cursor,
this);
00676 }
00677 }
00678
else {
00679 getParent()->moveDown(cursor,
this);
00680 }
00681 }
00682 }
00683 }
00684
00689 void MatrixElement::goInside(
FormulaCursor* cursor)
00690 {
00691 getElement(0, 0)->goInside(cursor);
00692 }
00693
00694
00695
00696 SequenceElement*
MatrixElement::getMainChild()
00697 {
00698
return content.at(0)->at(0);
00699 }
00700
00701 void MatrixElement::selectChild(
FormulaCursor* cursor,
BasicElement* child)
00702 {
00703 uint rows = getRows();
00704 uint columns = getColumns();
00705
for (uint r = 0; r < rows; r++) {
00706
for (uint c = 0; c < columns; c++) {
00707
if (child == getElement(r, c)) {
00708 cursor->
setTo(
this, r*columns+c);
00709 }
00710 }
00711 }
00712 }
00713
00714
bool MatrixElement::searchElement(
BasicElement* element, uint& row, uint& column)
00715 {
00716 uint rows = getRows();
00717 uint columns = getColumns();
00718
for (uint r = 0; r < rows; r++) {
00719
for (uint c = 0; c < columns; c++) {
00720
if (element == getElement(r, c)) {
00721 row = r;
00722 column = c;
00723
return true;
00724 }
00725 }
00726 }
00727
return false;
00728 }
00729
00730
00734 void MatrixElement::writeDom(
QDomElement element)
00735 {
00736 BasicElement::writeDom(element);
00737
00738 uint rows = getRows();
00739 uint cols = getColumns();
00740
00741 element.setAttribute(
"ROWS", rows);
00742 element.setAttribute(
"COLUMNS", cols);
00743
00744
QDomDocument doc = element.ownerDocument();
00745
00746
for (uint r = 0; r < rows; r++) {
00747
for (uint c = 0; c < cols; c++) {
00748
QDomElement tmp = getElement(r,c)->getElementDom(doc);
00749 element.appendChild(tmp);
00750 }
00751 element.appendChild(doc.createComment(
"end of row"));
00752 }
00753 }
00754
00759 bool MatrixElement::readAttributesFromDom(
QDomElement element)
00760 {
00761
if (!BasicElement::readAttributesFromDom(element)) {
00762
return false;
00763 }
00764 uint rows = 0;
00765
QString rowStr = element.attribute(
"ROWS");
00766
if(!rowStr.isNull()) {
00767 rows = rowStr.toInt();
00768 }
00769
if (rows == 0) {
00770 kdWarning( DEBUGID ) <<
"Rows <= 0 in MatrixElement." << endl;
00771
return false;
00772 }
00773
00774
QString columnStr = element.attribute(
"COLUMNS");
00775 uint cols = 0;
00776
if(!columnStr.isNull()) {
00777 cols = columnStr.toInt();
00778 }
00779
if (cols == 0) {
00780 kdWarning( DEBUGID ) <<
"Columns <= 0 in MatrixElement." << endl;
00781
return false;
00782 }
00783
00784 content.clear();
00785
for (uint r = 0; r < rows; r++) {
00786 QPtrList< MatrixSequenceElement >* list =
new QPtrList< MatrixSequenceElement >;
00787 list->setAutoDelete(
true);
00788 content.append(list);
00789
for (uint c = 0; c < cols; c++) {
00790 MatrixSequenceElement* element =
new MatrixSequenceElement(
this);
00791 list->append(element);
00792 }
00793 }
00794
return true;
00795 }
00796
00802 bool MatrixElement::readContentFromDom(
QDomNode& node)
00803 {
00804
if (!BasicElement::readContentFromDom(node)) {
00805
return false;
00806 }
00807
00808 uint rows = getRows();
00809 uint cols = getColumns();
00810
00811 uint r = 0;
00812 uint c = 0;
00813
while ( !node.isNull() && r < rows ) {
00814
if ( node.isElement() ) {
00815
SequenceElement* element = getElement( r, c );
00816
QDomElement e = node.toElement();
00817
if ( !element->
buildFromDom( e ) ) {
00818
return false;
00819 }
00820 c++;
00821
if ( c == cols ) {
00822 c = 0;
00823 r++;
00824 }
00825 }
00826 node = node.nextSibling();
00827 }
00828
return true;
00829 }
00830
00831 QString MatrixElement::toLatex()
00832 {
00833
00834
00835
QString matrix;
00836 uint cols=getColumns();
00837 uint rows=getRows();
00838
00839 matrix=
"\\begin{array}{ ";
00840
for(uint i=0;i<cols;i++)
00841 matrix+=
"c ";
00842
00843 matrix+=
"}";
00844
00845
for (uint r = 0; r < rows; r++) {
00846
for (uint c = 0; c < cols; c++) {
00847 matrix+=getElement(r, c)->toLatex();
00848
if( c < cols-1) matrix+=
" & ";
00849 }
00850
if(r < rows-1 ) matrix+=
" \\\\ ";
00851 }
00852
00853 matrix+=
"\\end{array}";
00854
00855
return matrix;
00856 }
00857
00858
QString MatrixElement::formulaString()
00859 {
00860
QString matrix =
"[";
00861 uint cols=getColumns();
00862 uint rows=getRows();
00863
for (uint r = 0; r < rows; r++) {
00864 matrix +=
"[";
00865
for (uint c = 0; c < cols; c++) {
00866 matrix+=getElement(r, c)->formulaString();
00867
if ( c < cols-1 ) matrix+=
", ";
00868 }
00869 matrix +=
"]";
00870
if ( r < rows-1 ) matrix +=
", ";
00871 }
00872 matrix +=
"]";
00873
return matrix;
00874 }
00875
00876
00877
SequenceElement* MatrixElement::elementAt(uint row, uint column)
00878 {
00879
return getElement( row, column );
00880 }
00881
00882
00883 void MatrixElement::writeMathML(
QDomDocument doc,
QDomNode parent )
00884 {
00885
QDomElement de = doc.createElement(
"mtable" );
00886
QDomElement row;
00887
QDomElement cell;
00888
00889 uint rows = getRows();
00890 uint cols = getColumns();
00891
00892
for ( uint r = 0; r < rows; r++ )
00893 {
00894 row = doc.createElement(
"mtr" );
00895 de.appendChild( row );
00896
for ( uint c = 0; c < cols; c++ )
00897 {
00898 cell = doc.createElement(
"mtd" );
00899 row.appendChild( cell );
00900 getElement(r,c)->writeMathML( doc, cell );
00901 }
00902 }
00903
00904 parent.appendChild( de );
00905 }
00906
00907
00909
00910
00915
class MultilineSequenceElement :
public SequenceElement {
00916
typedef SequenceElement inherited;
00917
public:
00918
00919 MultilineSequenceElement(
BasicElement* parent = 0 );
00920
00921
virtual MultilineSequenceElement* clone() {
00922
return new MultilineSequenceElement( *
this );
00923 }
00924
00925
virtual BasicElement* goToPos(
FormulaCursor*,
bool& handled,
00926
const LuPixelPoint& point,
const LuPixelPoint& parentOrigin );
00927
00932
virtual void calcSizes(
const ContextStyle& context,
00933 ContextStyle::TextStyle tstyle,
00934 ContextStyle::IndexStyle istyle );
00935
00936
virtual void registerTab(
BasicElement* tab );
00937
00946
virtual KCommand* buildCommand(
Container*, Request* );
00947
00948
virtual KCommand* input(
Container* container,
QKeyEvent* event );
00949
00950
virtual KCommand* input(
Container* container,
QChar ch );
00951
00952 uint tabCount()
const {
return tabs.count(); }
00953
00954
BasicElement* tab( uint i ) {
return tabs.at( i ); }
00955
00957
void moveTabTo( uint i, luPixel pos );
00958
00960
int tabBefore( uint pos );
00961
00963
int tabPos( uint i );
00964
00965
virtual void writeMathML(
QDomDocument doc,
QDomNode parent );
00966
00967
private:
00968
00969
QPtrList<BasicElement> tabs;
00970 };
00971
00972
00973
00974
class KFCNewLine :
public Command {
00975
public:
00976 KFCNewLine(
const QString& name,
Container* document,
00977 MultilineSequenceElement* line, uint pos );
00978
00979
virtual ~KFCNewLine();
00980
00981
virtual void execute();
00982
virtual void unexecute();
00983
00984
private:
00985 MultilineSequenceElement* m_line;
00986 MultilineSequenceElement* m_newline;
00987 uint m_pos;
00988 };
00989
00990
00991 KFCNewLine::KFCNewLine(
const QString& name,
Container* document,
00992 MultilineSequenceElement* line, uint pos )
00993 : Command( name, document ),
00994 m_line( line ), m_pos( pos )
00995 {
00996 m_newline =
new MultilineSequenceElement( m_line->getParent() );
00997 }
00998
00999
01000 KFCNewLine::~KFCNewLine()
01001 {
01002
delete m_newline;
01003 }
01004
01005
01006
void KFCNewLine::execute()
01007 {
01008
FormulaCursor* cursor = getExecuteCursor();
01009
MultilineElement* parent = static_cast<MultilineElement*>( m_line->getParent() );
01010
int linePos = parent->
content.find( m_line );
01011 parent->
content.insert( linePos+1, m_newline );
01012
01013
01014
if ( m_line->countChildren() > static_cast<int>( m_pos ) ) {
01015
01016
01017 m_line->selectAllChildren( cursor );
01018 cursor->
setMark( m_pos );
01019
QPtrList<BasicElement> elementList;
01020 m_line->remove( cursor, elementList, beforeCursor );
01021
01022
01023 m_newline->goInside( cursor );
01024 m_newline->insert( cursor, elementList, beforeCursor );
01025 cursor->
setPos( cursor->
getMark() );
01026 }
01027
else {
01028 m_newline->goInside( cursor );
01029 }
01030
01031
01032 m_newline = 0;
01033
01034
01035
FormulaElement*
formula = m_line->
formula();
01036 formula->
changed();
01037 testDirty();
01038 }
01039
01040
01041
void KFCNewLine::unexecute()
01042 {
01043
FormulaCursor* cursor = getExecuteCursor();
01044
MultilineElement* parent = static_cast<MultilineElement*>( m_line->getParent() );
01045
int linePos = parent->
content.find( m_line );
01046
01047
01048 m_newline = parent->
content.at( linePos+1 );
01049
01050
01051
FormulaElement*
formula = m_line->
formula();
01052 formula->
elementRemoval( m_newline );
01053
01054
01055
if ( m_newline->countChildren() > 0 ) {
01056
01057
01058 m_newline->selectAllChildren( cursor );
01059
QPtrList<BasicElement> elementList;
01060 m_newline->remove( cursor, elementList, beforeCursor );
01061
01062
01063 m_line->moveEnd( cursor );
01064 m_line->insert( cursor, elementList, beforeCursor );
01065 cursor->
setPos( cursor->
getMark() );
01066 }
01067
else {
01068 m_line->moveEnd( cursor );
01069 }
01070 parent->
content.take( linePos+1 );
01071
01072
01073 formula->
changed();
01074 testDirty();
01075 }
01076
01077
01078 MultilineSequenceElement::MultilineSequenceElement(
BasicElement* parent )
01079 :
SequenceElement( parent )
01080 {
01081 tabs.setAutoDelete(
false );
01082 }
01083
01084
01085
BasicElement* MultilineSequenceElement::goToPos(
FormulaCursor* cursor,
bool& handled,
01086
const LuPixelPoint& point,
const LuPixelPoint& parentOrigin )
01087 {
01088
01089
01090
BasicElement* e = inherited::goToPos(cursor, handled, point, parentOrigin);
01091
01092
if (e == 0) {
01093
01094
if ( ( point.x() > getX()+getWidth() ) &&
01095 ( point.y() >= getY() ) &&
01096 ( point.y() < getY()+getHeight() ) ) {
01097 cursor->
setTo(
this, countChildren());
01098 handled =
true;
01099
return this;
01100 }
01101 }
01102
return e;
01103 }
01104
01105
01106
void MultilineSequenceElement::calcSizes(
const ContextStyle& context,
01107 ContextStyle::TextStyle tstyle,
01108 ContextStyle::IndexStyle istyle )
01109 {
01110 tabs.clear();
01111 inherited::calcSizes( context, tstyle, istyle );
01112 }
01113
01114
01115
void MultilineSequenceElement::registerTab(
BasicElement* tab )
01116 {
01117 tabs.append( tab );
01118 }
01119
01120
01121 KCommand* MultilineSequenceElement::buildCommand(
Container* container, Request* request )
01122 {
01123
FormulaCursor* cursor = container->
activeCursor();
01124
if ( cursor->
isReadOnly() ) {
01125
return 0;
01126 }
01127
01128
switch ( *request ) {
01129
case req_remove: {
01130
01131
01132
break;
01133 }
01134
case req_addNewline: {
01135
FormulaCursor* cursor = container->
activeCursor();
01136
return new KFCNewLine( i18n(
"Add Newline" ), container,
this, cursor->
getPos() );
01137 }
01138
case req_addTabMark: {
01139
KFCReplace* command =
new KFCReplace( i18n(
"Add Tabmark"), container );
01140
SpaceElement* element =
new SpaceElement( THIN,
true );
01141 command->
addElement( element );
01142
return command;
01143 }
01144
default:
01145
break;
01146 }
01147
return inherited::buildCommand( container, request );
01148 }
01149
01150
01151 KCommand* MultilineSequenceElement::input(
Container* container,
QKeyEvent* event )
01152 {
01153
int action = event->key();
01154
01155
01156
01157
switch ( action ) {
01158
case Qt::Key_Enter:
01159
case Qt::Key_Return: {
01160 Request newline( req_addNewline );
01161
return buildCommand( container, &newline );
01162 }
01163
case Qt::Key_Tab: {
01164 Request r( req_addTabMark );
01165
return buildCommand( container, &r );
01166 }
01167 }
01168
return inherited::input( container, event );
01169 }
01170
01171
01172 KCommand* MultilineSequenceElement::input(
Container* container,
QChar ch )
01173 {
01174
int latin1 = ch.latin1();
01175
switch (latin1) {
01176
case '&': {
01177 Request r( req_addTabMark );
01178
return buildCommand( container, &r );
01179 }
01180 }
01181
return inherited::input( container, ch );
01182 }
01183
01184
01185
void MultilineSequenceElement::moveTabTo( uint i, luPixel pos )
01186 {
01187
BasicElement* marker = tab( i );
01188 luPixel diff = pos - marker->
getX();
01189 marker->
setWidth( marker->
getWidth() + diff );
01190
01191
for (
int p = childPos( marker )+1; p < countChildren(); ++p ) {
01192
BasicElement* child =
getChild( p );
01193 child->
setX( child->
getX() + diff );
01194 }
01195
01196 setWidth( getWidth()+diff );
01197 }
01198
01199
01200
int MultilineSequenceElement::tabBefore( uint pos )
01201 {
01202
if ( tabs.isEmpty() ) {
01203
return -1;
01204 }
01205 uint tabNum = 0;
01206
for ( uint i=0; i<pos; ++i ) {
01207
BasicElement* child =
getChild( i );
01208
if ( tabs.at( tabNum ) == child ) {
01209
if ( tabNum+1 == tabs.count() ) {
01210
return tabNum;
01211 }
01212 ++tabNum;
01213 }
01214 }
01215
return static_cast<int>( tabNum )-1;
01216 }
01217
01218
01219
int MultilineSequenceElement::tabPos( uint i )
01220 {
01221
if ( i < tabs.count() ) {
01222
return childPos( tabs.at( i ) );
01223 }
01224
return -1;
01225 }
01226
01227
01228
void MultilineSequenceElement::writeMathML(
QDomDocument doc,
01229
QDomNode parent )
01230 {
01231
01232
01233
QDomElement tmp = doc.createElement(
"TMP" );
01234
01235 inherited::writeMathML( doc, tmp );
01236
01237
01238
01239
01240
01241
01242
QDomElement mtd = doc.createElement(
"mtd" );
01243
01244
01245
QDomNode n = tmp.firstChild().firstChild();
01246
while ( !n.isNull() ) {
01247
01248
if ( n.isElement() && n.toElement().tagName() ==
"TAB" ) {
01249 parent.appendChild( mtd );
01250 mtd = doc.createElement(
"mtd" );
01251 }
01252
else {
01253 mtd.appendChild( n.cloneNode() );
01254 }
01255 n = n.nextSibling();
01256 }
01257
01258 parent.appendChild( mtd );
01259 }
01260
01261
01262 MultilineElement::MultilineElement(
BasicElement* parent )
01263 :
BasicElement( parent )
01264 {
01265 content.setAutoDelete(
true );
01266 content.append(
new MultilineSequenceElement(
this ) );
01267 }
01268
01269 MultilineElement::~MultilineElement()
01270 {
01271 }
01272
01273
MultilineElement::MultilineElement(
const MultilineElement& other )
01274 :
BasicElement( other )
01275 {
01276 content.setAutoDelete(
true );
01277 uint count = other.
content.count();
01278
for (uint i = 0; i < count; i++) {
01279 MultilineSequenceElement* line = content.at(i)->clone();
01280 line->setParent(
this );
01281 content.append( line );
01282 }
01283 }
01284
01285
01286 bool MultilineElement::accept(
ElementVisitor* visitor )
01287 {
01288
return visitor->
visit(
this );
01289 }
01290
01291
01292 void MultilineElement::entered(
SequenceElement* )
01293 {
01294
formula()->
tell( i18n(
"Multi line element" ) );
01295 }
01296
01297
01301 BasicElement*
MultilineElement::goToPos(
FormulaCursor* cursor,
bool& handled,
01302
const LuPixelPoint& point,
const LuPixelPoint& parentOrigin )
01303 {
01304
BasicElement* e = inherited::goToPos(cursor, handled, point, parentOrigin);
01305
if ( e != 0 ) {
01306
LuPixelPoint myPos(parentOrigin.x() + getX(),
01307 parentOrigin.y() + getY());
01308
01309 uint count = content.count();
01310
for ( uint i = 0; i < count; ++i ) {
01311 MultilineSequenceElement* line = content.at(i);
01312 e = line->goToPos(cursor, handled, point, myPos);
01313
if (e != 0) {
01314
return e;
01315 }
01316 }
01317
return this;
01318 }
01319
return 0;
01320 }
01321
01322 void MultilineElement::goInside(
FormulaCursor* cursor )
01323 {
01324 content.at( 0 )->goInside( cursor );
01325 }
01326
01327 void MultilineElement::moveLeft(
FormulaCursor* cursor,
BasicElement* from )
01328 {
01329
01330
01331
if (cursor->
isSelectionMode()) {
01332 getParent()->moveLeft(cursor,
this);
01333 }
01334
else {
01335
01336
01337
if (from == getParent()) {
01338 content.at( content.count()-1 )->moveLeft(cursor,
this);
01339 }
01340
else {
01341
01342
01343
int pos = content.find( static_cast<MultilineSequenceElement*>( from ) );
01344
if ( pos > -1 ) {
01345
if ( pos > 0 ) {
01346 content.at( pos-1 )->moveLeft( cursor,
this );
01347 }
01348
else {
01349 getParent()->moveLeft(cursor,
this);
01350 }
01351 }
01352
else {
01353 kdDebug( DEBUGID ) << k_funcinfo << endl;
01354 kdDebug( DEBUGID ) <<
"Serious confusion. Must never happen." << endl;
01355 }
01356 }
01357 }
01358 }
01359
01360 void MultilineElement::moveRight(
FormulaCursor* cursor,
BasicElement* from )
01361 {
01362
if (cursor->
isSelectionMode()) {
01363 getParent()->moveRight(cursor,
this);
01364 }
01365
else {
01366
if (from == getParent()) {
01367 content.at( 0 )->moveRight(cursor,
this);
01368 }
01369
else {
01370
int pos = content.find( static_cast<MultilineSequenceElement*>( from ) );
01371
if ( pos > -1 ) {
01372 uint upos = pos;
01373
if ( upos < content.count() ) {
01374
if ( upos < content.count()-1 ) {
01375 content.at( upos+1 )->moveRight( cursor,
this );
01376 }
01377
else {
01378 getParent()->moveRight(cursor,
this);
01379 }
01380
return;
01381 }
01382 }
01383 kdDebug( DEBUGID ) << k_funcinfo << endl;
01384 kdDebug( DEBUGID ) <<
"Serious confusion. Must never happen." << endl;
01385 }
01386 }
01387 }
01388
01389 void MultilineElement::moveUp(
FormulaCursor* cursor,
BasicElement* from )
01390 {
01391
01392
01393
if (cursor->
isSelectionMode()) {
01394 getParent()->moveLeft(cursor,
this);
01395 }
01396
else {
01397
01398
01399
if (from == getParent()) {
01400 content.at( content.count()-1 )->moveLeft(cursor,
this);
01401 }
01402
else {
01403
01404
01405
int pos = content.find( static_cast<MultilineSequenceElement*>( from ) );
01406
if ( pos > -1 ) {
01407
if ( pos > 0 ) {
01408
01409
01410
01411
int cursorPos = cursor->
getPos();
01412 MultilineSequenceElement* current = content.at( pos );
01413 MultilineSequenceElement* newLine = content.at( pos-1 );
01414
int tabNum = current->tabBefore( cursorPos );
01415
if ( tabNum > -1 ) {
01416
int oldTabPos = current->tabPos( tabNum );
01417
int newTabPos = newLine->tabPos( tabNum );
01418
if ( newTabPos > -1 ) {
01419 cursorPos += newTabPos-oldTabPos;
01420
int nextNewTabPos = newLine->tabPos( tabNum+1 );
01421
if ( nextNewTabPos > -1 ) {
01422 cursorPos = QMIN( cursorPos, nextNewTabPos );
01423 }
01424 }
01425
else {
01426 cursorPos = newLine->countChildren();
01427 }
01428 }
01429
else {
01430
int nextNewTabPos = newLine->tabPos( 0 );
01431
if ( nextNewTabPos > -1 ) {
01432 cursorPos = QMIN( cursorPos, nextNewTabPos );
01433 }
01434 }
01435 cursor->
setTo( newLine,
01436 QMIN( cursorPos,
01437 newLine->countChildren() ) );
01438 }
01439
else {
01440 getParent()->moveLeft(cursor,
this);
01441 }
01442 }
01443
else {
01444 kdDebug( DEBUGID ) << k_funcinfo << endl;
01445 kdDebug( DEBUGID ) <<
"Serious confusion. Must never happen." << endl;
01446 }
01447 }
01448 }
01449 }
01450
01451 void MultilineElement::moveDown(
FormulaCursor* cursor,
BasicElement* from )
01452 {
01453
if (cursor->
isSelectionMode()) {
01454 getParent()->moveRight(cursor,
this);
01455 }
01456
else {
01457
if (from == getParent()) {
01458 content.at( 0 )->moveRight(cursor,
this);
01459 }
01460
else {
01461
int pos = content.find( static_cast<MultilineSequenceElement*>( from ) );
01462
if ( pos > -1 ) {
01463 uint upos = pos;
01464
if ( upos < content.count() ) {
01465
if ( upos < content.count()-1 ) {
01466
01467
01468
01469
int cursorPos = cursor->
getPos();
01470 MultilineSequenceElement* current = content.at( upos );
01471 MultilineSequenceElement* newLine = content.at( upos+1 );
01472
int tabNum = current->tabBefore( cursorPos );
01473
if ( tabNum > -1 ) {
01474
int oldTabPos = current->tabPos( tabNum );
01475
int newTabPos = newLine->tabPos( tabNum );
01476
if ( newTabPos > -1 ) {
01477 cursorPos += newTabPos-oldTabPos;
01478
int nextNewTabPos = newLine->tabPos( tabNum+1 );
01479
if ( nextNewTabPos > -1 ) {
01480 cursorPos = QMIN( cursorPos, nextNewTabPos );
01481 }
01482 }
01483
else {
01484 cursorPos = newLine->countChildren();
01485 }
01486 }
01487
else {
01488
int nextNewTabPos = newLine->tabPos( 0 );
01489
if ( nextNewTabPos > -1 ) {
01490 cursorPos = QMIN( cursorPos, nextNewTabPos );
01491 }
01492 }
01493 cursor->
setTo( newLine,
01494 QMIN( cursorPos,
01495 newLine->countChildren() ) );
01496 }
01497
else {
01498 getParent()->moveRight(cursor,
this);
01499 }
01500
return;
01501 }
01502 }
01503 kdDebug( DEBUGID ) << k_funcinfo << endl;
01504 kdDebug( DEBUGID ) <<
"Serious confusion. Must never happen." << endl;
01505 }
01506 }
01507 }
01508
01509
01510 void MultilineElement::calcSizes(
const ContextStyle& context,
01511 ContextStyle::TextStyle tstyle,
01512 ContextStyle::IndexStyle istyle )
01513 {
01514 luPt mySize = context.
getAdjustedSize( tstyle );
01515
QFont font = context.
getDefaultFont();
01516 font.setPointSizeFloat( context.
layoutUnitPtToPt( mySize ) );
01517
QFontMetrics fm( font );
01518 luPixel leading = context.
ptToLayoutUnitPt( fm.leading() );
01519 luPixel distY = context.
ptToPixelY( context.
getThinSpace( tstyle ) );
01520
01521 uint count = content.count();
01522 luPixel height = -leading;
01523 luPixel width = 0;
01524 uint tabCount = 0;
01525
for ( uint i = 0; i < count; ++i ) {
01526 MultilineSequenceElement* line = content.at(i);
01527 line->calcSizes( context, tstyle, istyle );
01528 tabCount = QMAX( tabCount, line->tabCount() );
01529
01530 height += leading;
01531 line->setX( 0 );
01532 line->setY( height );
01533 height += line->getHeight() + distY;
01534 width = QMAX( line->getWidth(), width );
01535 }
01536
01537
01538
for ( uint t = 0; t < tabCount; ++t ) {
01539 luPixel pos = 0;
01540
for ( uint i = 0; i < count; ++i ) {
01541 MultilineSequenceElement* line = content.at(i);
01542
if ( t < line->tabCount() ) {
01543 pos = QMAX( pos, line->tab( t )->getX() );
01544 }
01545
else {
01546 pos = QMAX( pos, line->getWidth() );
01547 }
01548 }
01549
for ( uint i = 0; i < count; ++i ) {
01550 MultilineSequenceElement* line = content.at(i);
01551
if ( t < line->tabCount() ) {
01552 line->moveTabTo( t, pos );
01553 width = QMAX( width, line->getWidth() );
01554 }
01555 }
01556 }
01557
01558 setHeight( height );
01559 setWidth( width );
01560
if ( count == 1 ) {
01561 setBaseline( content.at( 0 )->getBaseline() );
01562 }
01563
else {
01564
01565 setBaseline( height/2 + context.
axisHeight( tstyle ) );
01566 }
01567 }
01568
01569 void MultilineElement::draw(
QPainter& painter,
const LuPixelRect& r,
01570
const ContextStyle& context,
01571 ContextStyle::TextStyle tstyle,
01572 ContextStyle::IndexStyle istyle,
01573
const LuPixelPoint& parentOrigin )
01574 {
01575
LuPixelPoint myPos( parentOrigin.x() + getX(), parentOrigin.y() + getY() );
01576 uint count = content.count();
01577
01578
if ( context.
edit() ) {
01579 uint tabCount = 0;
01580 painter.setPen( context.
getHelpColor() );
01581
for ( uint i = 0; i < count; ++i ) {
01582 MultilineSequenceElement* line = content.at(i);
01583
if ( tabCount < line->tabCount() ) {
01584
for ( uint t = tabCount; t < line->tabCount(); ++t ) {
01585
BasicElement* marker = line->tab( t );
01586 painter.drawLine( context.
layoutUnitToPixelX( myPos.x()+marker->
getX() ),
01587 context.
layoutUnitToPixelY( myPos.y() ),
01588 context.
layoutUnitToPixelX( myPos.x()+marker->
getX() ),
01589 context.
layoutUnitToPixelY( myPos.y()+getHeight() ) );
01590 }
01591 tabCount = line->tabCount();
01592 }
01593 }
01594 }
01595
01596
for ( uint i = 0; i < count; ++i ) {
01597 MultilineSequenceElement* line = content.at(i);
01598 line->draw( painter, r, context, tstyle, istyle, myPos );
01599 }
01600 }
01601
01602
01603 void MultilineElement::dispatchFontCommand(
FontCommand* cmd )
01604 {
01605 uint count = content.count();
01606
for ( uint i = 0; i < count; ++i ) {
01607 MultilineSequenceElement* line = content.at(i);
01608 line->dispatchFontCommand( cmd );
01609 }
01610 }
01611
01612 void MultilineElement::insert(
FormulaCursor* cursor,
01613
QPtrList<BasicElement>& newChildren,
01614 Direction direction )
01615 {
01616 MultilineSequenceElement* e = static_cast<MultilineSequenceElement*>(newChildren.take(0));
01617 e->setParent(
this);
01618 content.insert( cursor->
getPos(), e );
01619
01620
if (direction == beforeCursor) {
01621 e->moveLeft(cursor,
this);
01622 }
01623
else {
01624 e->moveRight(cursor,
this);
01625 }
01626 cursor->
setSelection(
false);
01627
formula()->
changed();
01628 }
01629
01630 void MultilineElement::remove(
FormulaCursor* cursor,
01631
QPtrList<BasicElement>& removedChildren,
01632 Direction direction )
01633 {
01634
if ( content.count() == 1 ) {
01635 getParent()->selectChild(cursor,
this);
01636 getParent()->remove(cursor, removedChildren, direction);
01637 }
01638
else {
01639 MultilineSequenceElement* e = content.take( cursor->
getPos() );
01640 removedChildren.append( e );
01641
formula()->
elementRemoval( e );
01642
01643
formula()->
changed();
01644 }
01645 }
01646
01647 void MultilineElement::normalize(
FormulaCursor* cursor, Direction direction )
01648 {
01649
int pos = cursor->
getPos();
01650
if ( ( cursor->
getElement() ==
this ) &&
01651 ( pos > -1 ) && ( static_cast<unsigned>( pos ) <= content.count() ) ) {
01652
switch ( direction ) {
01653
case beforeCursor:
01654
if ( pos > 0 ) {
01655 content.at( pos-1 )->moveLeft( cursor,
this );
01656
break;
01657 }
01658
01659
case afterCursor:
01660
if ( static_cast<unsigned>( pos ) < content.count() ) {
01661 content.at( pos )->moveRight( cursor,
this );
01662 }
01663
else {
01664 content.at( pos-1 )->moveLeft( cursor,
this );
01665 }
01666
break;
01667 }
01668 }
01669
else {
01670 inherited::normalize( cursor, direction );
01671 }
01672 }
01673
01674 SequenceElement*
MultilineElement::getMainChild()
01675 {
01676
return content.at( 0 );
01677 }
01678
01679 void MultilineElement::selectChild(
FormulaCursor* cursor,
BasicElement* child)
01680 {
01681
int pos = content.find( dynamic_cast<MultilineSequenceElement*>( child ) );
01682
if ( pos > -1 ) {
01683 cursor->
setTo(
this, pos );
01684
01685 }
01686 }
01687
01688
01692 void MultilineElement::writeDom(
QDomElement element)
01693 {
01694 BasicElement::writeDom(element);
01695
01696 uint lineCount = content.count();
01697 element.setAttribute(
"LINES", lineCount );
01698
01699
QDomDocument doc = element.ownerDocument();
01700
for ( uint i = 0; i < lineCount; ++i ) {
01701
QDomElement tmp = content.at( i )->getElementDom(doc);
01702 element.appendChild(tmp);
01703 }
01704 }
01705
01706 void MultilineElement::writeMathML(
QDomDocument doc,
QDomNode parent )
01707 {
01708
QDomElement de = doc.createElement(
"mtable" );
01709
QDomElement row;
QDomElement cell;
01710
01711
for ( uint i = 0; i < content.count(); ++i ) {
01712 row = doc.createElement(
"mtr" );
01713 de.appendChild( row );
01714
01715
01716
01717
01718 content.at( i )->writeMathML( doc, row );
01719 }
01720
01721 parent.appendChild( de );
01722 }
01723
01728 bool MultilineElement::readAttributesFromDom(
QDomElement element)
01729 {
01730
if (!BasicElement::readAttributesFromDom(element)) {
01731
return false;
01732 }
01733 uint lineCount = 0;
01734
QString lineCountStr = element.attribute(
"LINES");
01735
if(!lineCountStr.isNull()) {
01736 lineCount = lineCountStr.toInt();
01737 }
01738
if (lineCount == 0) {
01739 kdWarning( DEBUGID ) <<
"lineCount <= 0 in MultilineElement." << endl;
01740
return false;
01741 }
01742
01743 content.clear();
01744
for ( uint i = 0; i < lineCount; ++i ) {
01745 MultilineSequenceElement* element =
new MultilineSequenceElement(
this);
01746 content.append(element);
01747 }
01748
return true;
01749 }
01750
01756 bool MultilineElement::readContentFromDom(
QDomNode& node)
01757 {
01758
if (!BasicElement::readContentFromDom(node)) {
01759
return false;
01760 }
01761
01762 uint lineCount = content.count();
01763 uint i = 0;
01764
while ( !node.isNull() && i < lineCount ) {
01765
if ( node.isElement() ) {
01766
SequenceElement* element = content.at( i );
01767
QDomElement e = node.toElement();
01768
if ( !element->
buildFromDom( e ) ) {
01769
return false;
01770 }
01771 ++i;
01772 }
01773 node = node.nextSibling();
01774 }
01775
return true;
01776 }
01777
01778 QString MultilineElement::toLatex()
01779 {
01780 uint lineCount = content.count();
01781
QString muliline =
"\\begin{split} ";
01782
for ( uint i = 0; i < lineCount; ++i ) {
01783 muliline += content.at( i )->toLatex();
01784 muliline +=
" \\\\ ";
01785 }
01786 muliline +=
"\\end{split}";
01787
return muliline;
01788 }
01789
01790
01791
QString MultilineElement::formulaString()
01792 {
01793 uint lineCount = content.count();
01794
QString muliline =
"";
01795
for ( uint i = 0; i < lineCount; ++i ) {
01796 muliline += content.at( i )->formulaString();
01797 muliline +=
"\n";
01798 }
01799
01800
return muliline;
01801 }
01802
01803
01804 KFORMULA_NAMESPACE_END