00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <stdlib.h>
00022 #include <math.h>
00023
00024 #include <qpainter.h>
00025 #include <qpaintdevice.h>
00026 #include <qvaluestack.h>
00027
00028 #include <kcommand.h>
00029 #include <kdebug.h>
00030 #include <klocale.h>
00031
00032
00033
00034 #include "MatrixDialog.h"
00035 #include "bracketelement.h"
00036 #include "creationstrategy.h"
00037 #include "elementtype.h"
00038 #include "elementvisitor.h"
00039 #include "formulacursor.h"
00040 #include "formulaelement.h"
00041 #include "fractionelement.h"
00042 #include "indexelement.h"
00043 #include "kformulacommand.h"
00044 #include "kformulacontainer.h"
00045 #include "kformuladocument.h"
00046 #include "matrixelement.h"
00047 #include "rootelement.h"
00048 #include "sequenceelement.h"
00049 #include "sequenceparser.h"
00050 #include "spaceelement.h"
00051 #include "symbolelement.h"
00052 #include "symboltable.h"
00053 #include "textelement.h"
00054
00055 #include <assert.h>
00056
00057 KFORMULA_NAMESPACE_BEGIN
00058
00059
00060 ElementCreationStrategy* SequenceElement::creationStrategy = 0;
00061
00062 void SequenceElement::setCreationStrategy( ElementCreationStrategy* strategy )
00063 {
00064 creationStrategy = strategy;
00065 }
00066
00067
00068 SequenceElement::SequenceElement(BasicElement* parent)
00069 : BasicElement(parent), parseTree(0), textSequence(true)
00070 {
00071 assert( creationStrategy != 0 );
00072 children.setAutoDelete(true);
00073 }
00074
00075
00076 SequenceElement::~SequenceElement()
00077 {
00078 delete parseTree;
00079 }
00080
00081 SequenceElement::SequenceElement( const SequenceElement& other )
00082 : BasicElement( other )
00083 {
00084 children.setAutoDelete(true);
00085 uint count = other.children.count();
00086 for (uint i = 0; i < count; i++) {
00087 BasicElement* child = children.at(i)->clone();
00088 child->setParent( this );
00089 children.append( child );
00090 }
00091 }
00092
00093
00094 bool SequenceElement::accept( ElementVisitor* visitor )
00095 {
00096 return visitor->visit( this );
00097 }
00098
00099
00100 bool SequenceElement::readOnly( const FormulaCursor* ) const
00101 {
00102 return getParent()->readOnly( this );
00103 }
00104
00105
00109 BasicElement* SequenceElement::goToPos( FormulaCursor* cursor, bool& handled,
00110 const LuPixelPoint& point, const LuPixelPoint& parentOrigin )
00111 {
00112 BasicElement* e = BasicElement::goToPos(cursor, handled, point, parentOrigin);
00113 if (e != 0) {
00114 LuPixelPoint myPos(parentOrigin.x() + getX(),
00115 parentOrigin.y() + getY());
00116
00117 uint count = children.count();
00118 for (uint i = 0; i < count; i++) {
00119 BasicElement* child = children.at(i);
00120 e = child->goToPos(cursor, handled, point, myPos);
00121 if (e != 0) {
00122 if (!handled) {
00123 handled = true;
00124 if ((point.x() - myPos.x()) < (e->getX() + e->getWidth()*2/3)) {
00125 cursor->setTo(this, children.find(e));
00126 }
00127 else {
00128 cursor->setTo(this, children.find(e)+1);
00129 }
00130 }
00131 return e;
00132 }
00133 }
00134
00135 luPixel dx = point.x() - myPos.x();
00136
00137
00138 for (uint i = 0; i < count; i++) {
00139 BasicElement* child = children.at(i);
00140 if (dx < child->getX()) {
00141 cursor->setTo( this, i );
00142 handled = true;
00143 return children.at( i );
00144 }
00145 }
00146
00147 cursor->setTo(this, countChildren());
00148 handled = true;
00149 return this;
00150 }
00151 return 0;
00152 }
00153
00154
00155 bool SequenceElement::isEmpty()
00156 {
00157 uint count = children.count();
00158 for (uint i = 0; i < count; i++) {
00159 BasicElement* child = children.at(i);
00160 if (!child->isInvisible()) {
00161 return false;
00162 }
00163 }
00164 return true;
00165 }
00166
00167
00172 void SequenceElement::calcSizes(const ContextStyle& style,
00173 ContextStyle::TextStyle tstyle,
00174 ContextStyle::IndexStyle istyle)
00175 {
00176 if (!isEmpty()) {
00177 luPixel width = 0;
00178 luPixel toBaseline = 0;
00179 luPixel fromBaseline = 0;
00180
00181
00182 QPtrListIterator<BasicElement> it( children );
00183 for ( ; it.current(); ++it ) {
00184 BasicElement* child = it.current();
00185
00186 luPixel spaceBefore = 0;
00187 if ( isFirstOfToken( child ) ) {
00188 spaceBefore =
00189 style.ptToPixelX( child->getElementType()->getSpaceBefore( style,
00190 tstyle ) );
00191 }
00192
00193 if ( !child->isInvisible() ) {
00194 child->calcSizes( style, tstyle, istyle );
00195 child->setX( width + spaceBefore );
00196 width += child->getWidth() + spaceBefore;
00197
00198 luPixel childBaseline = child->getBaseline();
00199 if ( childBaseline > -1 ) {
00200 toBaseline = QMAX( toBaseline, childBaseline );
00201 fromBaseline = QMAX( fromBaseline,
00202 child->getHeight() - childBaseline );
00203 }
00204 else {
00205 luPixel bl = child->getHeight()/2 + style.axisHeight( tstyle );
00206 toBaseline = QMAX( toBaseline, bl );
00207 fromBaseline = QMAX( fromBaseline, child->getHeight() - bl );
00208 }
00209 }
00210 else {
00211 width += spaceBefore;
00212 child->setX( width );
00213 }
00214 }
00215
00216 setWidth(width);
00217 setHeight(toBaseline+fromBaseline);
00218 setBaseline(toBaseline);
00219
00220 setChildrenPositions();
00221 }
00222 else {
00223 luPixel w = style.getEmptyRectWidth();
00224 luPixel h = style.getEmptyRectHeight();
00225 setWidth( w );
00226 setHeight( h );
00227 setBaseline( h );
00228
00229 }
00230 }
00231
00232
00233 void SequenceElement::setChildrenPositions()
00234 {
00235 QPtrListIterator<BasicElement> it( children );
00236 for ( ; it.current(); ++it ) {
00237 BasicElement* child = it.current();
00238 child->setY(getBaseline() - child->getBaseline());
00239 }
00240 }
00241
00242
00248 void SequenceElement::draw( QPainter& painter, const LuPixelRect& r,
00249 const ContextStyle& context,
00250 ContextStyle::TextStyle tstyle,
00251 ContextStyle::IndexStyle istyle,
00252 const LuPixelPoint& parentOrigin )
00253 {
00254 LuPixelPoint myPos( parentOrigin.x() + getX(), parentOrigin.y() + getY() );
00255
00256
00257
00258
00259
00260 if (!isEmpty()) {
00261 QPtrListIterator<BasicElement> it( children );
00262 for ( ; it.current(); ) {
00263 BasicElement* child = it.current();
00264 if (!child->isInvisible()) {
00265 child->draw(painter, r, context, tstyle, istyle, myPos);
00266
00267
00268
00269 ElementType* token = child->getElementType();
00270 if ( token != 0 ) {
00271 it += token->end() - token->start();
00272 }
00273 else {
00274 ++it;
00275 }
00276 }
00277 else {
00278 ++it;
00279 }
00280 }
00281 }
00282 else {
00283 drawEmptyRect( painter, context, myPos );
00284 }
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298 }
00299
00300
00301 void SequenceElement::dispatchFontCommand( FontCommand* cmd )
00302 {
00303 QPtrListIterator<BasicElement> it( children );
00304 for ( ; it.current(); ++it ) {
00305 BasicElement* child = it.current();
00306 child->dispatchFontCommand( cmd );
00307 }
00308 }
00309
00310
00311 void SequenceElement::drawEmptyRect( QPainter& painter, const ContextStyle& context,
00312 const LuPixelPoint& upperLeft )
00313 {
00314 if ( context.edit() ) {
00315 painter.setBrush(Qt::NoBrush);
00316 painter.setPen( QPen( context.getEmptyColor(),
00317 context.layoutUnitToPixelX( context.getLineWidth() ) ) );
00318 painter.drawRect( context.layoutUnitToPixelX( upperLeft.x() ),
00319 context.layoutUnitToPixelY( upperLeft.y() ),
00320 context.layoutUnitToPixelX( getWidth() ),
00321 context.layoutUnitToPixelY( getHeight() ) );
00322 }
00323 }
00324
00325 void SequenceElement::calcCursorSize( const ContextStyle& context,
00326 FormulaCursor* cursor, bool smallCursor )
00327 {
00328 LuPixelPoint point = widgetPos();
00329 uint pos = cursor->getPos();
00330
00331 luPixel posX = getChildPosition( context, pos );
00332 luPixel height = getHeight();
00333
00334 luPixel unitX = context.ptToLayoutUnitPixX( 1 );
00335 luPixel unitY = context.ptToLayoutUnitPixY( 1 );
00336
00337
00338
00339 if ( cursor->isSelection() ) {
00340 uint mark = cursor->getMark();
00341 luPixel markX = getChildPosition( context, mark );
00342 luPixel x = QMIN(posX, markX);
00343 luPixel width = abs(posX - markX);
00344
00345 if ( smallCursor ) {
00346 cursor->cursorSize.setRect( point.x()+x, point.y(), width, height );
00347 }
00348 else {
00349 cursor->cursorSize.setRect( point.x()+x, point.y() - 2*unitY,
00350 width + unitX, height + 4*unitY );
00351 }
00352 }
00353 else {
00354 if ( smallCursor ) {
00355 cursor->cursorSize.setRect( point.x()+posX, point.y(),
00356 unitX, height );
00357 }
00358 else {
00359 cursor->cursorSize.setRect( point.x(), point.y() - 2*unitY,
00360 getWidth() + unitX, height + 4*unitY );
00361 }
00362 }
00363
00364 cursor->cursorPoint.setX( point.x()+posX );
00365 cursor->cursorPoint.setY( point.y()+getHeight()/2 );
00366 }
00367
00368
00372 void SequenceElement::drawCursor( QPainter& painter, const ContextStyle& context,
00373 FormulaCursor* cursor, bool smallCursor )
00374 {
00375 painter.setRasterOp( Qt::XorROP );
00376 if ( cursor->isSelection() ) {
00377 const LuPixelRect& r = cursor->cursorSize;
00378 painter.fillRect( context.layoutUnitToPixelX( r.x() ),
00379 context.layoutUnitToPixelY( r.y() ),
00380 context.layoutUnitToPixelX( r.width() ),
00381 context.layoutUnitToPixelY( r.height() ),
00382 Qt::white );
00383 }
00384 else {
00385 painter.setPen( QPen( Qt::white,
00386 context.layoutUnitToPixelX( context.getLineWidth()/2 ) ) );
00387 const LuPixelPoint& point = cursor->getCursorPoint();
00388 const LuPixelRect& size = cursor->getCursorSize();
00389 if ( smallCursor ) {
00390 painter.drawLine( context.layoutUnitToPixelX( point.x() ),
00391 context.layoutUnitToPixelY( size.top() ),
00392 context.layoutUnitToPixelX( point.x() ),
00393 context.layoutUnitToPixelY( size.bottom() )-1 );
00394 }
00395 else {
00396 painter.drawLine( context.layoutUnitToPixelX( point.x() ),
00397 context.layoutUnitToPixelY( size.top() ),
00398 context.layoutUnitToPixelX( point.x() ),
00399 context.layoutUnitToPixelY( size.bottom() )-1 );
00400 painter.drawLine( context.layoutUnitToPixelX( size.left() ),
00401 context.layoutUnitToPixelY( size.bottom() )-1,
00402 context.layoutUnitToPixelX( size.right() )-1,
00403 context.layoutUnitToPixelY( size.bottom() )-1 );
00404 }
00405 }
00406
00407 painter.setRasterOp( Qt::CopyROP );
00408 }
00409
00410
00411 luPixel SequenceElement::getChildPosition( const ContextStyle& context, uint child )
00412 {
00413 if (child < children.count()) {
00414 return children.at(child)->getX();
00415 }
00416 else {
00417 if (children.count() > 0) {
00418 return children.at(child-1)->getX() + children.at(child-1)->getWidth();
00419 }
00420 else {
00421 return context.ptToLayoutUnitPixX( 2 );
00422 }
00423 }
00424 }
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00440 void SequenceElement::moveLeft(FormulaCursor* cursor, BasicElement* from)
00441 {
00442
00443 if (from == getParent()) {
00444 cursor->setTo(this, children.count());
00445 from->entered( this );
00446 }
00447
00448
00449 else if (from == this) {
00450 if (cursor->getPos() > 0) {
00451 if (cursor->isSelectionMode()) {
00452 cursor->setTo(this, cursor->getPos()-1);
00453
00454
00455 if (children.at(cursor->getPos())->isInvisible()) {
00456 moveLeft(cursor, this);
00457 }
00458 }
00459 else {
00460 children.at(cursor->getPos()-1)->moveLeft(cursor, this);
00461 }
00462 }
00463 else {
00464
00465 if (getParent() != 0) {
00466 getParent()->moveLeft(cursor, this);
00467 }
00468 else {
00469 formula()->moveOutLeft( cursor );
00470 }
00471 }
00472 }
00473
00474
00475
00476 else {
00477 int fromPos = children.find(from);
00478 cursor->setTo(this, fromPos);
00479 if (cursor->isSelectionMode()) {
00480 cursor->setMark(fromPos+1);
00481 }
00482
00483
00484 if (from->isInvisible()) {
00485 moveLeft(cursor, this);
00486 }
00487 formula()->tell( "" );
00488 }
00489 }
00490
00496 void SequenceElement::moveRight(FormulaCursor* cursor, BasicElement* from)
00497 {
00498
00499 if (from == getParent()) {
00500 cursor->setTo(this, 0);
00501 from->entered( this );
00502 }
00503
00504
00505 else if (from == this) {
00506 uint pos = cursor->getPos();
00507 if (pos < children.count()) {
00508 if (cursor->isSelectionMode()) {
00509 cursor->setTo(this, pos+1);
00510
00511
00512 if (children.at(pos)->isInvisible()) {
00513 moveRight(cursor, this);
00514 }
00515 }
00516 else {
00517 children.at(pos)->moveRight(cursor, this);
00518 }
00519 }
00520 else {
00521
00522 if (getParent() != 0) {
00523 getParent()->moveRight(cursor, this);
00524 }
00525 else {
00526 formula()->moveOutRight( cursor );
00527 }
00528 }
00529 }
00530
00531
00532
00533 else {
00534 int fromPos = children.find(from);
00535 cursor->setTo(this, fromPos+1);
00536 if (cursor->isSelectionMode()) {
00537 cursor->setMark(fromPos);
00538 }
00539
00540
00541 if (from->isInvisible()) {
00542 moveRight(cursor, this);
00543 }
00544 formula()->tell( "" );
00545 }
00546 }
00547
00548
00549 void SequenceElement::moveWordLeft(FormulaCursor* cursor)
00550 {
00551 uint pos = cursor->getPos();
00552 if (pos > 0) {
00553 ElementType* type = children.at(pos-1)->getElementType();
00554 if (type != 0) {
00555 cursor->setTo(this, type->start());
00556 }
00557 }
00558 else {
00559 moveLeft(cursor, this);
00560 }
00561 }
00562
00563
00564 void SequenceElement::moveWordRight(FormulaCursor* cursor)
00565 {
00566 uint pos = cursor->getPos();
00567 if (pos < children.count()) {
00568 ElementType* type = children.at(pos)->getElementType();
00569 if (type != 0) {
00570 cursor->setTo(this, type->end());
00571 }
00572 }
00573 else {
00574 moveRight(cursor, this);
00575 }
00576 }
00577
00578
00584 void SequenceElement::moveUp(FormulaCursor* cursor, BasicElement* from)
00585 {
00586 if (from == getParent()) {
00587 moveRight(cursor, this);
00588 }
00589 else {
00590 if (getParent() != 0) {
00591 getParent()->moveUp(cursor, this);
00592 }
00593 else {
00594 formula()->moveOutAbove( cursor );
00595 }
00596 }
00597 }
00598
00604 void SequenceElement::moveDown(FormulaCursor* cursor, BasicElement* from)
00605 {
00606 if (from == getParent()) {
00607 moveRight(cursor, this);
00608 }
00609 else {
00610 if (getParent() != 0) {
00611 getParent()->moveDown(cursor, this);
00612 }
00613 else {
00614 formula()->moveOutBelow( cursor );
00615 }
00616 }
00617 }
00618
00623 void SequenceElement::moveHome(FormulaCursor* cursor)
00624 {
00625 if (cursor->isSelectionMode()) {
00626 BasicElement* element = cursor->getElement();
00627 if (element != this) {
00628 while (element->getParent() != this) {
00629 element = element->getParent();
00630 }
00631 cursor->setMark(children.find(element)+1);
00632 }
00633 }
00634 cursor->setTo(this, 0);
00635 }
00636
00641 void SequenceElement::moveEnd(FormulaCursor* cursor)
00642 {
00643 if (cursor->isSelectionMode()) {
00644 BasicElement* element = cursor->getElement();
00645 if (element != this) {
00646 while (element->getParent() != this) {
00647 element = element->getParent();
00648 if (element == 0) {
00649 cursor->setMark(children.count());
00650 break;
00651 }
00652 }
00653 if (element != 0) {
00654 cursor->setMark(children.find(element));
00655 }
00656 }
00657 }
00658 cursor->setTo(this, children.count());
00659 }
00660
00665 void SequenceElement::goInside(FormulaCursor* cursor)
00666 {
00667 cursor->setSelection(false);
00668 cursor->setTo(this, 0);
00669 }
00670
00671
00672
00673
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00704 void SequenceElement::insert(FormulaCursor* cursor,
00705 QPtrList<BasicElement>& newChildren,
00706 Direction direction)
00707 {
00708 int pos = cursor->getPos();
00709 uint count = newChildren.count();
00710 for (uint i = 0; i < count; i++) {
00711 BasicElement* child = newChildren.take(0);
00712 child->setParent(this);
00713 children.insert(pos+i, child);
00714 }
00715 if (direction == beforeCursor) {
00716 cursor->setTo(this, pos+count, pos);
00717 }
00718 else {
00719 cursor->setTo(this, pos, pos+count);
00720 }
00721
00722 formula()->changed();
00723 parse();
00724 }
00725
00726
00733 void SequenceElement::remove(FormulaCursor* cursor,
00734 QPtrList<BasicElement>& removedChildren,
00735 Direction direction)
00736 {
00737 if (cursor->isSelection()) {
00738 int from = cursor->getSelectionStart();
00739 int to = cursor->getSelectionEnd();
00740 for (int i = from; i < to; i++) {
00741 removeChild(removedChildren, from);
00742 }
00743 cursor->setTo(this, from);
00744 cursor->setSelection(false);
00745 }
00746 else {
00747 if (direction == beforeCursor) {
00748 int pos = cursor->getPos() - 1;
00749 if (pos >= 0) {
00750 while (pos >= 0) {
00751 BasicElement* child = children.at(pos);
00752 formula()->elementRemoval(child);
00753 children.take(pos);
00754 removedChildren.prepend(child);
00755 if (!child->isInvisible()) {
00756 break;
00757 }
00758 pos--;
00759 }
00760 cursor->setTo(this, pos);
00761 formula()->changed();
00762 }
00763 }
00764 else {
00765 uint pos = cursor->getPos();
00766 if (pos < children.count()) {
00767 while (pos < children.count()) {
00768 BasicElement* child = children.at(pos);
00769 formula()->elementRemoval(child);
00770 children.take(pos);
00771 removedChildren.append(child);
00772 if (!child->isInvisible()) {
00773 break;
00774 }
00775 }
00776
00777
00778
00779 cursor->setTo(this, pos);
00780 formula()->changed();
00781 }
00782 }
00783 }
00784 parse();
00785 }
00786
00787
00791 void SequenceElement::removeChild(QPtrList<BasicElement>& removedChildren, int pos)
00792 {
00793 BasicElement* child = children.at(pos);
00794 formula()->elementRemoval(child);
00795 children.take(pos);
00796 removedChildren.append(child);
00797
00798 formula()->changed();
00799 }
00800
00801
00806 void SequenceElement::normalize(FormulaCursor* cursor, Direction)
00807 {
00808 cursor->setSelection(false);
00809 }
00810
00811
00816 BasicElement* SequenceElement::getChild( FormulaCursor* cursor, Direction direction )
00817 {
00818 if ( direction == beforeCursor ) {
00819 if ( cursor->getPos() > 0 ) {
00820 return children.at( cursor->getPos() - 1 );
00821 }
00822 }
00823 else {
00824 if ( cursor->getPos() < qRound( children.count() ) ) {
00825 return children.at( cursor->getPos() );
00826 }
00827 }
00828 return 0;
00829 }
00830
00831
00836 void SequenceElement::selectChild(FormulaCursor* cursor, BasicElement* child)
00837 {
00838 int pos = children.find(child);
00839 if (pos > -1) {
00840 cursor->setTo(this, pos+1, pos);
00841 }
00842 }
00843
00844 void SequenceElement::childWillVanish(FormulaCursor* cursor, BasicElement* child)
00845 {
00846 int childPos = children.find(child);
00847 if (childPos > -1) {
00848 int pos = cursor->getPos();
00849 if (pos > childPos) {
00850 pos--;
00851 }
00852 int mark = cursor->getMark();
00853 if (mark > childPos) {
00854 mark--;
00855 }
00856 cursor->setTo(this, pos, mark);
00857 }
00858 }
00859
00860
00864 void SequenceElement::selectAllChildren(FormulaCursor* cursor)
00865 {
00866 cursor->setTo(this, children.count(), 0);
00867 }
00868
00869 bool SequenceElement::onlyTextSelected( FormulaCursor* cursor )
00870 {
00871 if ( cursor->isSelection() ) {
00872 uint from = QMIN( cursor->getPos(), cursor->getMark() );
00873 uint to = QMAX( cursor->getPos(), cursor->getMark() );
00874 for ( uint i = from; i < to; i++ ) {
00875 BasicElement* element = getChild( i );
00876 if ( element->getCharacter() == QChar::null ) {
00877 return false;
00878 }
00879 }
00880 }
00881 return true;
00882 }
00883
00884
00885 KCommand* SequenceElement::buildCommand( Container* container, Request* request )
00886 {
00887 FormulaCursor* cursor = container->activeCursor();
00888 if ( cursor->isReadOnly() ) {
00889 formula()->tell( i18n( "write protection" ) );
00890 return 0;
00891 }
00892
00893 switch ( *request ) {
00894 case req_addText: {
00895 KFCReplace* command = new KFCReplace( i18n("Add Text"), container );
00896 TextRequest* tr = static_cast<TextRequest*>( request );
00897 for ( uint i = 0; i < tr->text().length(); i++ ) {
00898 command->addElement( creationStrategy->createTextElement( tr->text()[i] ) );
00899 }
00900 return command;
00901 }
00902 case req_addTextChar: {
00903 KFCReplace* command = new KFCReplace( i18n("Add Text"), container );
00904 TextCharRequest* tr = static_cast<TextCharRequest*>( request );
00905 TextElement* element = creationStrategy->createTextElement( tr->ch(), tr->isSymbol() );
00906 command->addElement( element );
00907 return command;
00908 }
00909 case req_addEmptyBox: {
00910 EmptyElement* element = creationStrategy->createEmptyElement();
00911 if ( element != 0 ) {
00912 KFCReplace* command = new KFCReplace( i18n("Add Empty Box"), container );
00913 command->addElement( element );
00914 return command;
00915 }
00916 break;
00917 }
00918 case req_addNameSequence:
00919 if ( onlyTextSelected( container->activeCursor() ) ) {
00920 NameSequence* nameSequence = creationStrategy->createNameSequence();
00921 if ( nameSequence != 0 ) {
00922 KFCAddReplacing* command = new KFCAddReplacing( i18n( "Add Name" ), container );
00923 command->setElement( nameSequence );
00924 return command;
00925 }
00926 }
00927 break;
00928 case req_addBracket: {
00929 BracketRequest* br = static_cast<BracketRequest*>( request );
00930 BracketElement* bracketElement =
00931 creationStrategy->createBracketElement( br->left(), br->right() );
00932 if ( bracketElement != 0 ) {
00933 KFCAddReplacing* command = new KFCAddReplacing(i18n("Add Bracket"), container);
00934 command->setElement( bracketElement );
00935 return command;
00936 }
00937 break;
00938 }
00939 case req_addOverline: {
00940 OverlineElement* overline = creationStrategy->createOverlineElement();
00941 if ( overline != 0 ) {
00942 KFCAddReplacing* command = new KFCAddReplacing(i18n("Add Overline"), container);
00943 command->setElement( overline );
00944 return command;
00945 }
00946 break;
00947 }
00948 case req_addUnderline: {
00949 UnderlineElement* underline = creationStrategy->createUnderlineElement();
00950 if ( underline != 0 ) {
00951 KFCAddReplacing* command = new KFCAddReplacing(i18n("Add Underline"), container);
00952 command->setElement( underline );
00953 return command;
00954 }
00955 break;
00956 }
00957 case req_addMultiline: {
00958 MultilineElement* multiline = creationStrategy->createMultilineElement();
00959 if ( multiline != 0 ) {
00960 KFCAddReplacing* command = new KFCAddReplacing(i18n("Add Multiline"), container);
00961 command->setElement( multiline );
00962 return command;
00963 }
00964 break;
00965 }
00966 case req_addSpace: {
00967 SpaceRequest* sr = static_cast<SpaceRequest*>( request );
00968 SpaceElement* element = creationStrategy->createSpaceElement( sr->space() );
00969 if ( element != 0 ) {
00970 KFCReplace* command = new KFCReplace( i18n("Add Space"), container );
00971 command->addElement( element );
00972 return command;
00973 }
00974 break;
00975 }
00976 case req_addFraction: {
00977 FractionElement* fraction = creationStrategy->createFractionElement();
00978 if ( fraction != 0 ) {
00979 KFCAddReplacing* command = new KFCAddReplacing(i18n("Add Fraction"), container);
00980 command->setElement( fraction );
00981 return command;
00982 }
00983 break;
00984 }
00985 case req_addRoot: {
00986 RootElement* root = creationStrategy->createRootElement();
00987 if ( root != 0 ) {
00988 KFCAddReplacing* command = new KFCAddReplacing(i18n("Add Root"), container);
00989 command->setElement( root );
00990 return command;
00991 }
00992 break;
00993 }
00994 case req_addSymbol: {
00995 SymbolRequest* sr = static_cast<SymbolRequest*>( request );
00996 SymbolElement* symbol = creationStrategy->createSymbolElement( sr->type() );
00997 if ( symbol != 0 ) {
00998 KFCAddReplacing* command = new KFCAddReplacing( i18n( "Add Symbol" ), container );
00999 command->setElement( symbol );
01000 return command;
01001 }
01002 break;
01003 }
01004 case req_addOneByTwoMatrix: {
01005 FractionElement* element = creationStrategy->createFractionElement();
01006 if ( element != 0 ) {
01007 KFCAddReplacing* command = new KFCAddReplacing( i18n("Add 1x2 Matrix"), container );
01008 element->showLine(false);
01009 command->setElement(element);
01010 return command;
01011 }
01012 }
01013 case req_addMatrix: {
01014 MatrixRequest* mr = static_cast<MatrixRequest*>( request );
01015 uint rows = mr->rows(), cols = mr->columns();
01016 if ( ( rows == 0 ) || ( cols == 0 ) ) {
01017 MatrixDialog* dialog = new MatrixDialog( 0 );
01018 if ( dialog->exec() ) {
01019 rows = dialog->h;
01020 cols = dialog->w;
01021 }
01022 delete dialog;
01023 }
01024
01025 if ( ( rows != 0 ) && ( cols != 0 ) ) {
01026 KFCAddReplacing* command = new KFCAddReplacing( i18n( "Add Matrix" ), container );
01027 command->setElement( creationStrategy->createMatrixElement( rows, cols ) );
01028 return command;
01029 }
01030 else
01031 return 0L;
01032 }
01033 case req_addIndex: {
01034 if ( cursor->getPos() > 0 && !cursor->isSelection() ) {
01035 IndexElement* element =
01036 dynamic_cast<IndexElement*>( children.at( cursor->getPos()-1 ) );
01037 if ( element != 0 ) {
01038 element->getMainChild()->goInside( cursor );
01039 return element->getMainChild()->buildCommand( container, request );
01040 }
01041 }
01042 IndexElement* element = creationStrategy->createIndexElement();
01043 if ( element != 0 ) {
01044 if ( !cursor->isSelection() ) {
01045 cursor->moveLeft( SelectMovement | WordMovement );
01046 }
01047 IndexRequest* ir = static_cast<IndexRequest*>( request );
01048 KFCAddIndex* command = new KFCAddIndex( container, element,
01049 element->getIndex( ir->index() ) );
01050 return command;
01051 }
01052 break;
01053 }
01054 case req_removeEnclosing: {
01055 if ( !cursor->isSelection() ) {
01056 DirectedRemove* dr = static_cast<DirectedRemove*>( request );
01057 KFCRemoveEnclosing* command = new KFCRemoveEnclosing( container, dr->direction() );
01058 return command;
01059 }
01060 }
01061 case req_remove: {
01062 SequenceElement* sequence = cursor->normal();
01063 if ( sequence &&
01064 ( sequence == sequence->formula() ) &&
01065 ( sequence->countChildren() == 0 ) ) {
01066 sequence->formula()->removeFormula( cursor );
01067 return 0;
01068 }
01069 else {
01070 DirectedRemove* dr = static_cast<DirectedRemove*>( request );
01071
01072
01073 if ( !cursor->isSelection() ) {
01074 if ( countChildren() > 0 ) {
01075 if ( ( cursor->getPos() == 0 ) && ( dr->direction() == beforeCursor ) ) {
01076 return 0;
01077 }
01078 if ( ( cursor->getPos() == countChildren() ) && ( dr->direction() == afterCursor ) ) {
01079 return 0;
01080 }
01081 }
01082 else if ( getParent() == 0 ) {
01083 return 0;
01084 }
01085 }
01086
01087 KFCRemove* command = new KFCRemove( container, dr->direction() );
01088 return command;
01089 }
01090 }
01091 case req_compactExpression: {
01092 cursor->moveEnd();
01093 cursor->moveRight();
01094 formula()->cursorHasMoved( cursor );
01095 break;
01096 }
01097 case req_makeGreek: {
01098 TextElement* element = cursor->getActiveTextElement();
01099 if ((element != 0) && !element->isSymbol()) {
01100 cursor->selectActiveElement();
01101 const SymbolTable& table = container->document()->getSymbolTable();
01102 if (table.greekLetters().find(element->getCharacter()) != -1) {
01103 KFCReplace* command = new KFCReplace( i18n( "Change Char to Symbol" ), container );
01104 TextElement* symbol = creationStrategy->createTextElement( table.unicodeFromSymbolFont( element->getCharacter() ), true );
01105 command->addElement( symbol );
01106 return command;
01107 }
01108 cursor->setSelection( false );
01109 }
01110 break;
01111 }
01112 case req_paste:
01113 case req_copy:
01114 case req_cut:
01115 break;
01116 case req_formatBold:
01117 case req_formatItalic: {
01118 if ( cursor->isSelection() ) {
01119 CharStyleRequest* csr = static_cast<CharStyleRequest*>( request );
01120 CharStyle cs = normalChar;
01121 if ( csr->bold() ) cs = static_cast<CharStyle>( cs | boldChar );
01122 if ( csr->italic() ) cs = static_cast<CharStyle>( cs | italicChar );
01123 CharStyleCommand* cmd = new CharStyleCommand( cs, i18n( "Change Char Style" ), container );
01124 int end = cursor->getSelectionEnd();
01125 for ( int i = cursor->getSelectionStart(); i<end; ++i ) {
01126 cmd->addElement( children.at( i ) );
01127 }
01128 return cmd;
01129 }
01130 break;
01131 }
01132 case req_formatFamily: {
01133 if ( cursor->isSelection() ) {
01134 CharFamilyRequest* cfr = static_cast<CharFamilyRequest*>( request );
01135 CharFamily cf = cfr->charFamily();
01136 CharFamilyCommand* cmd = new CharFamilyCommand( cf, i18n( "Change Char Family" ), container );
01137 int end = cursor->getSelectionEnd();
01138 for ( int i = cursor->getSelectionStart(); i<end; ++i ) {
01139 cmd->addElement( children.at( i ) );
01140 }
01141 return cmd;
01142 }
01143 break;
01144 }
01145 default:
01146 break;
01147 }
01148 return 0;
01149 }
01150
01151
01152 KCommand* SequenceElement::input( Container* container, QKeyEvent* event )
01153 {
01154 QChar ch = event->text().at( 0 );
01155 if ( ch.isPrint() ) {
01156 return input( container, ch );
01157 }
01158 else {
01159 int action = event->key();
01160 int state = event->state();
01161 MoveFlag flag = movementFlag(state);
01162
01163 switch ( action ) {
01164 case Qt::Key_BackSpace: {
01165 DirectedRemove r( req_remove, beforeCursor );
01166 return buildCommand( container, &r );
01167 }
01168 case Qt::Key_Delete: {
01169 DirectedRemove r( req_remove, afterCursor );
01170 return buildCommand( container, &r );
01171 }
01172 case Qt::Key_Left: {
01173 FormulaCursor* cursor = container->activeCursor();
01174 cursor->moveLeft( flag );
01175 formula()->cursorHasMoved( cursor );
01176 break;
01177 }
01178 case Qt::Key_Right: {
01179 FormulaCursor* cursor = container->activeCursor();
01180 cursor->moveRight( flag );
01181 formula()->cursorHasMoved( cursor );
01182 break;
01183 }
01184 case Qt::Key_Up: {
01185 FormulaCursor* cursor = container->activeCursor();
01186 cursor->moveUp( flag );
01187 formula()->cursorHasMoved( cursor );
01188 break;
01189 }
01190 case Qt::Key_Down: {
01191 FormulaCursor* cursor = container->activeCursor();
01192 cursor->moveDown( flag );
01193 formula()->cursorHasMoved( cursor );
01194 break;
01195 }
01196 case Qt::Key_Home: {
01197 FormulaCursor* cursor = container->activeCursor();
01198 cursor->moveHome( flag );
01199 formula()->cursorHasMoved( cursor );
01200 break;
01201 }
01202 case Qt::Key_End: {
01203 FormulaCursor* cursor = container->activeCursor();
01204 cursor->moveEnd( flag );
01205 formula()->cursorHasMoved( cursor );
01206 break;
01207 }
01208 default:
01209 if ( state & Qt::ControlButton ) {
01210 switch ( event->key() ) {
01211 case Qt::Key_AsciiCircum: {
01212 IndexRequest r( upperLeftPos );
01213 return buildCommand( container, &r );
01214 }
01215 case Qt::Key_Underscore: {
01216 IndexRequest r( lowerLeftPos );
01217 return buildCommand( container, &r );
01218 }
01219 default:
01220 break;
01221 }
01222 }
01223 }
01224 }
01225 return 0;
01226 }
01227
01228
01229 KCommand* SequenceElement::input( Container* container, QChar ch )
01230 {
01231 int unicode = ch.unicode();
01232 switch (unicode) {
01233 case '(': {
01234 BracketRequest r( container->document()->leftBracketChar(),
01235 container->document()->rightBracketChar() );
01236 return buildCommand( container, &r );
01237 }
01238 case '[': {
01239 BracketRequest r( LeftSquareBracket, RightSquareBracket );
01240 return buildCommand( container, &r );
01241 }
01242 case '{': {
01243 BracketRequest r( LeftCurlyBracket, RightCurlyBracket );
01244 return buildCommand( container, &r );
01245 }
01246 case '|': {
01247 BracketRequest r( LeftLineBracket, RightLineBracket );
01248 return buildCommand( container, &r );
01249 }
01250 case '^': {
01251 IndexRequest r( upperRightPos );
01252 return buildCommand( container, &r );
01253 }
01254 case '_': {
01255 IndexRequest r( lowerRightPos );
01256 return buildCommand( container, &r );
01257 }
01258 case ' ': {
01259 Request r( req_compactExpression );
01260 return buildCommand( container, &r );
01261 }
01262 case '}': {
01263 Request r( req_addEmptyBox );
01264 return buildCommand( container, &r );
01265 }
01266 case ']':
01267 case ')':
01268 break;
01269 case '\\': {
01270 Request r( req_addNameSequence );
01271 return buildCommand( container, &r );
01272 }
01273 default: {
01274 TextCharRequest r( ch );
01275 return buildCommand( container, &r );
01276 }
01277 }
01278 return 0;
01279 }
01280
01284 void SequenceElement::getChildrenDom(QDomDocument doc, QDomElement elem,
01285 uint from, uint to)
01286 {
01287 for (uint i = from; i < to; i++) {
01288 QDomElement tmpEleDom=children.at(i)->getElementDom(doc);
01289 elem.appendChild(tmpEleDom);
01290 }
01291 }
01292
01293
01299 bool SequenceElement::buildChildrenFromDom(QPtrList<BasicElement>& list, QDomNode n)
01300 {
01301 while (!n.isNull()) {
01302 if (n.isElement()) {
01303 QDomElement e = n.toElement();
01304 BasicElement* child = 0;
01305 QString tag = e.tagName().upper();
01306
01307 child = createElement(tag);
01308 if (child != 0) {
01309 child->setParent(this);
01310 if (child->buildFromDom(e)) {
01311 list.append(child);
01312 }
01313 else {
01314 delete child;
01315 return false;
01316 }
01317 }
01318 else {
01319 return false;
01320 }
01321 }
01322 n = n.nextSibling();
01323 }
01324 parse();
01325 return true;
01326 }
01327
01328
01329 BasicElement* SequenceElement::createElement( QString type )
01330 {
01331 return creationStrategy->createElement( type );
01332 }
01333
01337 void SequenceElement::writeDom(QDomElement element)
01338 {
01339 BasicElement::writeDom(element);
01340
01341 uint count = children.count();
01342 QDomDocument doc = element.ownerDocument();
01343 getChildrenDom(doc, element, 0, count);
01344 }
01345
01350 bool SequenceElement::readAttributesFromDom(QDomElement element)
01351 {
01352 if (!BasicElement::readAttributesFromDom(element)) {
01353 return false;
01354 }
01355 return true;
01356 }
01357
01363 bool SequenceElement::readContentFromDom(QDomNode& node)
01364 {
01365 if (!BasicElement::readContentFromDom(node)) {
01366 return false;
01367 }
01368
01369 return buildChildrenFromDom(children, node);
01370 }
01371
01372
01373 void SequenceElement::parse()
01374 {
01375 delete parseTree;
01376
01377 textSequence = true;
01378 for (BasicElement* element = children.first();
01379 element != 0;
01380 element = children.next()) {
01381
01382
01383
01384 element->setElementType(0);
01385
01386 if (element->getCharacter().isNull()) {
01387 textSequence = false;
01388 }
01389 }
01390
01391 const SymbolTable& symbols = formula()->getSymbolTable();
01392 SequenceParser parser(symbols);
01393 parseTree = parser.parse(children);
01394
01395
01396
01397 BasicElement* p = getParent();
01398 if ( p != 0 ) {
01399 SequenceElement* seq = dynamic_cast<SequenceElement*>( p->getParent() );
01400 if ( seq != 0 ) {
01401 seq->parse();
01402 }
01403 }
01404
01405
01406 }
01407
01408
01409 bool SequenceElement::isFirstOfToken( BasicElement* child )
01410 {
01411 return ( child->getElementType() != 0 ) && isChildNumber( child->getElementType()->start(), child );
01412 }
01413
01414
01415 QString SequenceElement::toLatex()
01416 {
01417 QString content;
01418 content += "{";
01419 uint count = children.count();
01420 for ( uint i = 0; i < count; i++ ) {
01421 BasicElement* child = children.at( i );
01422 if ( isFirstOfToken( child ) ) {
01423 content += " ";
01424 }
01425 content += child->toLatex();
01426 }
01427 content += "}";
01428 return content;
01429 }
01430
01431
01432 QString SequenceElement::formulaString()
01433 {
01434 QString content;
01435 uint count = children.count();
01436 for ( uint i = 0; i < count; i++ ) {
01437 BasicElement* child = children.at( i );
01438
01439
01440
01441 content += child->formulaString();
01442 }
01443 return content;
01444 }
01445
01446
01447 void SequenceElement::writeMathML( QDomDocument doc, QDomNode parent )
01448 {
01449 QDomElement de = doc.createElement( "mrow" );
01450
01451 BasicElement* last = children.last();
01452 if ( last != 0 ) {
01453
01454 QPtrList<ElementType> tokenList;
01455 ElementType* token = last->getElementType();
01456 while ( token != 0 ) {
01457
01458 tokenList.prepend( token );
01459 token = token->getPrev();
01460 }
01461
01462 if ( tokenList.count() == 1 ) {
01463 tokenList.first()->saveMathML( this, doc, parent.toElement() );
01464 return;
01465 }
01466
01467 for ( uint i = 0; i < tokenList.count(); ++i ) {
01468 tokenList.at( i )->saveMathML( this, doc, de );
01469 }
01470 }
01471 parent.appendChild( de );
01472 }
01473
01474
01475 int SequenceElement::childPos( const BasicElement* child ) const
01476 {
01477 QPtrListIterator<BasicElement> it( children );
01478 uint count = it.count();
01479 for ( uint i=0; i<count; ++i, ++it ) {
01480 if ( it.current() == child ) {
01481 return i;
01482 }
01483 }
01484 return -1;
01485 }
01486
01487
01488 NameSequence::NameSequence( BasicElement* parent )
01489 : SequenceElement( parent )
01490 {
01491 }
01492
01493
01494 bool NameSequence::accept( ElementVisitor* visitor )
01495 {
01496 return visitor->visit( this );
01497 }
01498
01499
01500 void NameSequence::calcCursorSize( const ContextStyle& context,
01501 FormulaCursor* cursor, bool smallCursor )
01502 {
01503 inherited::calcCursorSize( context, cursor, smallCursor );
01504 LuPixelPoint point = widgetPos();
01505 luPixel unitX = context.ptToLayoutUnitPixX( 1 );
01506 luPixel unitY = context.ptToLayoutUnitPixY( 1 );
01507 cursor->addCursorSize( LuPixelRect( point.x()-unitX, point.y()-unitY,
01508 getWidth()+2*unitX, getHeight()+2*unitY ) );
01509 }
01510
01511 void NameSequence::drawCursor( QPainter& painter, const ContextStyle& context,
01512 FormulaCursor* cursor, bool smallCursor )
01513 {
01514 LuPixelPoint point = widgetPos();
01515 painter.setPen( QPen( context.getEmptyColor(),
01516 context.layoutUnitToPixelX( context.getLineWidth()/2 ) ) );
01517 luPixel unitX = context.ptToLayoutUnitPixX( 1 );
01518 luPixel unitY = context.ptToLayoutUnitPixY( 1 );
01519 painter.drawRect( context.layoutUnitToPixelX( point.x()-unitX ),
01520 context.layoutUnitToPixelY( point.y()-unitY ),
01521 context.layoutUnitToPixelX( getWidth()+2*unitX ),
01522 context.layoutUnitToPixelY( getHeight()+2*unitY ) );
01523
01524 inherited::drawCursor( painter, context, cursor, smallCursor );
01525 }
01526
01527 void NameSequence::moveWordLeft( FormulaCursor* cursor )
01528 {
01529 uint pos = cursor->getPos();
01530 if ( pos > 0 ) {
01531 cursor->setTo( this, 0 );
01532 }
01533 else {
01534 moveLeft( cursor, this );
01535 }
01536 }
01537
01538 void NameSequence::moveWordRight( FormulaCursor* cursor )
01539 {
01540 int pos = cursor->getPos();
01541 if ( pos < countChildren() ) {
01542 cursor->setTo( this, countChildren() );
01543 }
01544 else {
01545 moveRight( cursor, this );
01546 }
01547 }
01548
01549
01550 KCommand* NameSequence::compactExpressionCmd( Container* container )
01551 {
01552 BasicElement* element = replaceElement( container->document()->getSymbolTable() );
01553 if ( element != 0 ) {
01554 getParent()->selectChild( container->activeCursor(), this );
01555
01556 KFCReplace* command = new KFCReplace( i18n( "Add Element" ), container );
01557 command->addElement( element );
01558 return command;
01559 }
01560 return 0;
01561 }
01562
01563 KCommand* NameSequence::buildCommand( Container* container, Request* request )
01564 {
01565 switch ( *request ) {
01566 case req_compactExpression:
01567 return compactExpressionCmd( container );
01568 case req_addSpace:
01569 case req_addIndex:
01570 case req_addMatrix:
01571 case req_addOneByTwoMatrix:
01572 case req_addSymbol:
01573 case req_addRoot:
01574 case req_addFraction:
01575 case req_addBracket:
01576 case req_addNameSequence:
01577 return 0;
01578 default:
01579 break;
01580 }
01581 return inherited::buildCommand( container, request );
01582 }
01583
01584
01585 KCommand* NameSequence::input( Container* container, QChar ch )
01586 {
01587 int unicode = ch.unicode();
01588 switch (unicode) {
01589 case '(':
01590 case '[':
01591 case '|':
01592 case '^':
01593 case '_':
01594 case '}':
01595 case ']':
01596 case ')':
01597 case '\\': {
01598
01599
01600
01601
01602
01603
01604
01605
01606
01607
01608
01609 break;
01610 }
01611 case '{':
01612 case ' ': {
01613 Request r( req_compactExpression );
01614 return buildCommand( container, &r );
01615 }
01616 default: {
01617 TextCharRequest r( ch );
01618 return buildCommand( container, &r );
01619 }
01620 }
01621 return 0;
01622 }
01623
01624 void NameSequence::setElementType( ElementType* t )
01625 {
01626 inherited::setElementType( t );
01627 parse();
01628 }
01629
01630 BasicElement* NameSequence::replaceElement( const SymbolTable& table )
01631 {
01632 QString name = buildName();
01633 QChar ch = table.unicode( name );
01634 if ( !ch.isNull() ) {
01635 return new TextElement( ch, true );
01636 }
01637 else {
01638 ch = table.unicode( i18n( name.latin1() ) );
01639 if ( !ch.isNull() ) {
01640 return new TextElement( ch, true );
01641 }
01642 }
01643
01644 if ( name == "!" ) return new SpaceElement( NEGTHIN );
01645 if ( name == "," ) return new SpaceElement( THIN );
01646 if ( name == ">" ) return new SpaceElement( MEDIUM );
01647 if ( name == ";" ) return new SpaceElement( THICK );
01648 if ( name == "quad" ) return new SpaceElement( QUAD );
01649
01650 if ( name == "frac" ) return new FractionElement();
01651 if ( name == "atop" ) {
01652 FractionElement* frac = new FractionElement();
01653 frac->showLine( false );
01654 return frac;
01655 }
01656 if ( name == "sqrt" ) return new RootElement();
01657
01658 return 0;
01659 }
01660
01661 BasicElement* NameSequence::createElement( QString type )
01662 {
01663 if ( type == "TEXT" ) return new TextElement();
01664 return 0;
01665 }
01666
01667
01668
01669
01670
01671
01672
01673
01674
01675
01676 QString NameSequence::buildName()
01677 {
01678 QString name;
01679 for ( int i = 0; i < countChildren(); i++ ) {
01680 name += getChild( i )->getCharacter();
01681 }
01682 return name;
01683 }
01684
01685 bool NameSequence::isValidSelection( FormulaCursor* cursor )
01686 {
01687 SequenceElement* sequence = cursor->normal();
01688 if ( sequence == 0 ) {
01689 return false;
01690 }
01691 return sequence->onlyTextSelected( cursor );
01692 }
01693
01694 void NameSequence::writeMathML( QDomDocument doc, QDomNode parent )
01695 {
01696 QDomElement de = doc.createElement( "mi" );
01697 QString value;
01698 for ( int i = 0; i < countChildren(); ++i ) {
01699
01700 value += getChild( i )->getCharacter();
01701 }
01702 de.appendChild( doc.createTextNode( value ) );
01703 parent.appendChild( de );
01704 }
01705
01706 KFORMULA_NAMESPACE_END