lib Library API Documentation

sequenceelement.cc

00001 /* This file is part of the KDE project 00002 Copyright (C) 2001 Andrea Rizzi <rizzi@kde.org> 00003 Ulrich Kuettler <ulrich.kuettler@mailbox.tu-dresden.de> 00004 00005 This library is free software; you can redistribute it and/or 00006 modify it under the terms of the GNU Library General Public 00007 License as published by the Free Software Foundation; either 00008 version 2 of the License, or (at your option) any later version. 00009 00010 This library is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 Library General Public License for more details. 00014 00015 You should have received a copy of the GNU Library General Public License 00016 along with this library; see the file COPYING.LIB. If not, write to 00017 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 00018 Boston, MA 02111-1307, USA. 00019 */ 00020 00021 #include <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 //#include <boost/spirit.hpp> 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 //using namespace std; 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 //int dy = point.y() - myPos.y(); 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 // Let's do all normal elements that have a base line. 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 //setMidline( h*.5 ); 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 // There might be zero sized elements that still want to be drawn at least 00256 // in edit mode. (EmptyElement) 00257 //if ( !LuPixelRect( myPos.x(), myPos.y(), getWidth(), getHeight() ).intersects( r ) ) 00258 // return; 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 // Each starting element draws the whole token 00268 // This only concerns TextElements. 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 // Debug 00286 //painter.setPen(Qt::green); 00287 //painter.drawRect(parentOrigin.x() + getX(), parentOrigin.y() + getY(), 00288 // getWidth(), getHeight()); 00289 // painter.drawLine( context.layoutUnitToPixelX( parentOrigin.x() + getX() ), 00290 // context.layoutUnitToPixelY( parentOrigin.y() + getY() + axis( context, tstyle ) ), 00291 // context.layoutUnitToPixelX( parentOrigin.x() + getX() + getWidth() ), 00292 // context.layoutUnitToPixelY( parentOrigin.y() + getY() + axis( context, tstyle ) ) ); 00293 // painter.setPen(Qt::red); 00294 // painter.drawLine( context.layoutUnitToPixelX( parentOrigin.x() + getX() ), 00295 // context.layoutUnitToPixelY( parentOrigin.y() + getY() + getBaseline() ), 00296 // context.layoutUnitToPixelX( parentOrigin.x() + getX() + getWidth() ), 00297 // context.layoutUnitToPixelY( parentOrigin.y() + getY() + getBaseline() ) ); 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 // Here are those evil constants that describe the cursor size. 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 // This might be wrong but probably isn't. 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 // navigation 00428 // 00429 // The elements are responsible to handle cursor movement themselves. 00430 // To do this they need to know the direction the cursor moves and 00431 // the element it comes from. 00432 // 00433 // The cursor might be in normal or in selection mode. 00434 00440 void SequenceElement::moveLeft(FormulaCursor* cursor, BasicElement* from) 00441 { 00442 // Our parent asks us for a cursor position. Found. 00443 if (from == getParent()) { 00444 cursor->setTo(this, children.count()); 00445 from->entered( this ); 00446 } 00447 00448 // We already owned the cursor. Ask next child then. 00449 else if (from == this) { 00450 if (cursor->getPos() > 0) { 00451 if (cursor->isSelectionMode()) { 00452 cursor->setTo(this, cursor->getPos()-1); 00453 00454 // invisible elements are not visible so we move on. 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 // Needed because FormulaElement derives this. 00465 if (getParent() != 0) { 00466 getParent()->moveLeft(cursor, this); 00467 } 00468 else { 00469 formula()->moveOutLeft( cursor ); 00470 } 00471 } 00472 } 00473 00474 // The cursor came from one of our children or 00475 // something is wrong. 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 // invisible elements are not visible so we move on. 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 // Our parent asks us for a cursor position. Found. 00499 if (from == getParent()) { 00500 cursor->setTo(this, 0); 00501 from->entered( this ); 00502 } 00503 00504 // We already owned the cursor. Ask next child then. 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 // invisible elements are not visible so we move on. 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 // Needed because FormulaElement derives this. 00522 if (getParent() != 0) { 00523 getParent()->moveRight(cursor, this); 00524 } 00525 else { 00526 formula()->moveOutRight( cursor ); 00527 } 00528 } 00529 } 00530 00531 // The cursor came from one of our children or 00532 // something is wrong. 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 // invisible elements are not visible so we move on. 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 // children 00673 00681 // void SequenceElement::removeChild(FormulaCursor* cursor, BasicElement* child) 00682 // { 00683 // int pos = children.find(child); 00684 // formula()->elementRemoval(child, pos); 00685 // cursor->setTo(this, pos); 00686 // children.remove(pos); 00687 // /* 00688 // if len(self.children) == 0: 00689 // if self.parent != None: 00690 // self.parent.removeChild(cursor, self) 00691 // return 00692 // */ 00693 // formula()->changed(); 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 // It is necessary to set the cursor to its old 00777 // position because it got a notification and 00778 // moved to the beginning of this sequence. 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 //cerr << *removedChildren.at(0) << endl; 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 // empty removes are not legal! 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 // Those types are gone. Make sure they won't 01383 // be used. 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 // With the IndexElement dynamically changing its text/non-text 01396 // behaviour we need to reparse your parent, too. Hacky! 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 // debug 01405 //parseTree->output(); 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 //if ( isFirstOfToken( child ) ) { 01439 // content += " "; 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 // Create a list (right order!) 01454 QPtrList<ElementType> tokenList; 01455 ElementType* token = last->getElementType(); 01456 while ( token != 0 ) { 01457 // Add to the list. 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 // KCommand* compact = compactExpressionCmd( container ); 01599 // KCommand* cmd = static_cast<SequenceElement*>( getParent() )->input( container, ch ); 01600 // if ( compact != 0 ) { 01601 // KMacroCommand* macro = new KMacroCommand( cmd->name() ); 01602 // macro->addCommand( compact ); 01603 // macro->addCommand( cmd ); 01604 // return macro; 01605 // } 01606 // else { 01607 // return cmd; 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 // void NameSequence::parse() 01668 // { 01669 // // A name sequence is known as name and so are its children. 01670 // // Caution: this is fake! 01671 // for ( int i = 0; i < countChildren(); i++ ) { 01672 // getChild( i )->setElementType( getElementType() ); 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 // these are supposed to by TextElements 01700 value += getChild( i )->getCharacter(); 01701 } 01702 de.appendChild( doc.createTextNode( value ) ); 01703 parent.appendChild( de ); 01704 } 01705 01706 KFORMULA_NAMESPACE_END
KDE Logo
This file is part of the documentation for lib Library Version 1.3.3.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Sep 24 18:22:29 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003