00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <qpainter.h>
00022
00023 #include <kdebug.h>
00024 #include <assert.h>
00025
00026 #include "formulacursor.h"
00027 #include "formulaelement.h"
00028 #include "indexelement.h"
00029 #include "matrixelement.h"
00030 #include "rootelement.h"
00031 #include "sequenceelement.h"
00032 #include "symbolelement.h"
00033 #include "textelement.h"
00034
00035 KFORMULA_NAMESPACE_BEGIN
00036
00037 FormulaCursor::FormulaCursor(FormulaElement* element)
00038 : selectionFlag(false), linearMovement(false),
00039 hasChangedFlag(true), readOnly(false)
00040 {
00041
00042 element->goInside( this );
00043 }
00044
00045 void FormulaCursor::setTo(BasicElement* element, int cursor, int mark)
00046 {
00047 hasChangedFlag = true;
00048 current = element;
00049 cursorPos = cursor;
00050 if ((mark == -1) && selectionFlag) {
00051 return;
00052 }
00053 if (mark != -1) {
00054 setSelection(true);
00055 }
00056 markPos = mark;
00057 }
00058
00059
00060 void FormulaCursor::setPos(int pos)
00061 {
00062 hasChangedFlag = true;
00063 cursorPos = pos;
00064 }
00065
00066 void FormulaCursor::setMark(int mark)
00067 {
00068 hasChangedFlag = true;
00069 markPos = mark;
00070 }
00071
00072 void FormulaCursor::calcCursorSize( const ContextStyle& context, bool smallCursor )
00073 {
00074
00075 SequenceElement* sequence = dynamic_cast<SequenceElement*>(current);
00076
00077 if (sequence != 0) {
00078 sequence->calcCursorSize( context, this, smallCursor );
00079 }
00080 }
00081
00082 void FormulaCursor::draw( QPainter& painter, const ContextStyle& context, bool smallCursor )
00083 {
00084
00085
00086
00087
00088 SequenceElement* sequence = dynamic_cast<SequenceElement*>(current);
00089
00090 if (sequence != 0) {
00091 sequence->drawCursor( painter, context, this, smallCursor );
00092 }
00093 }
00094
00095
00096 void FormulaCursor::handleSelectState(int flag)
00097 {
00098 if (flag & SelectMovement) {
00099 if (!isSelection()) {
00100 setMark(getPos());
00101 setSelection(true);
00102 }
00103 }
00104 else {
00105 setSelection(false);
00106 }
00107 }
00108
00109 void FormulaCursor::moveLeft(int flag)
00110 {
00111 BasicElement* element = getElement();
00112 handleSelectState(flag);
00113 if (flag & WordMovement) {
00114 SequenceElement* sequence = dynamic_cast<SequenceElement*>(current);
00115 if (sequence != 0) {
00116 sequence->moveWordLeft(this);
00117 }
00118 else {
00119 element->moveHome(this);
00120 }
00121 }
00122 else {
00123 element->moveLeft(this, element);
00124 }
00125 }
00126
00127 void FormulaCursor::moveRight(int flag)
00128 {
00129 BasicElement* element = getElement();
00130 handleSelectState(flag);
00131 if (flag & WordMovement) {
00132 SequenceElement* sequence = dynamic_cast<SequenceElement*>(current);
00133 if (sequence != 0) {
00134 sequence->moveWordRight(this);
00135 }
00136 else {
00137 element->moveEnd(this);
00138 }
00139 }
00140 else {
00141 element->moveRight(this, element);
00142 }
00143 }
00144
00145 void FormulaCursor::moveUp(int flag)
00146 {
00147 BasicElement* element = getElement();
00148 handleSelectState(flag);
00149 element->moveUp(this, element);
00150 }
00151
00152 void FormulaCursor::moveDown(int flag)
00153 {
00154 BasicElement* element = getElement();
00155 handleSelectState(flag);
00156 element->moveDown(this, element);
00157 }
00158
00159 void FormulaCursor::moveHome(int flag)
00160 {
00161 BasicElement* element = getElement();
00162 handleSelectState(flag);
00163 if (flag & WordMovement) {
00164 element->formula()->moveHome(this);
00165 }
00166 else {
00167 element->moveHome(this);
00168 }
00169 }
00170
00171 void FormulaCursor::moveEnd(int flag)
00172 {
00173 BasicElement* element = getElement();
00174 handleSelectState(flag);
00175 if (flag & WordMovement) {
00176 element->formula()->moveEnd(this);
00177 }
00178 else {
00179 element->moveEnd(this);
00180 }
00181 }
00182
00183 bool FormulaCursor::isHome() const
00184 {
00185 return ( getElement() == getElement()->formula() ) && ( getPos() == 0 );
00186 }
00187
00188 bool FormulaCursor::isEnd() const
00189 {
00190 return ( getElement() == getElement()->formula() ) &&
00191 ( getPos() == normal()->countChildren() );
00192 }
00193
00194 void FormulaCursor::mousePress( const LuPixelPoint& pos, int flag )
00195 {
00196 FormulaElement* formula = getElement()->formula();
00197 formula->goToPos( this, pos );
00198 if (flag & SelectMovement) {
00199 setSelection(true);
00200 if (getMark() == -1) {
00201 setMark(getPos());
00202 }
00203 }
00204 else {
00205 setSelection(false);
00206 setMark(getPos());
00207 }
00208 }
00209
00210 void FormulaCursor::mouseMove( const LuPixelPoint& point, int )
00211 {
00212 setSelection(true);
00213 BasicElement* element = getElement();
00214 int mark = getMark();
00215
00216 FormulaElement* formula = getElement()->formula();
00217 formula->goToPos( this, point );
00218 BasicElement* newElement = getElement();
00219 int pos = getPos();
00220
00221 BasicElement* posChild = 0;
00222 BasicElement* markChild = 0;
00223 while (element != newElement) {
00224 posChild = newElement;
00225 newElement = newElement->getParent();
00226 if (newElement == 0) {
00227 posChild = 0;
00228 newElement = getElement();
00229 markChild = element;
00230 element = element->getParent();
00231 }
00232 }
00233
00234 if (dynamic_cast<SequenceElement*>(element) == 0) {
00235 element = element->getParent();
00236 element->selectChild(this, newElement);
00237 }
00238 else {
00239 if (posChild != 0) {
00240 element->selectChild(this, posChild);
00241 pos = getPos();
00242 }
00243 if (markChild != 0) {
00244 element->selectChild(this, markChild);
00245 mark = getMark();
00246 }
00247 if (pos == mark) {
00248 if ((posChild == 0) && (markChild != 0)) {
00249 mark++;
00250 }
00251 else if ((posChild != 0) && (markChild == 0)) {
00252 mark--;
00253 }
00254 }
00255 else if (pos < mark) {
00256 if (posChild != 0) {
00257 pos--;
00258 }
00259 }
00260 setTo(element, pos, mark);
00261 }
00262 }
00263
00264 void FormulaCursor::mouseRelease( const LuPixelPoint&, int )
00265 {
00266
00267 }
00268
00269
00273 void FormulaCursor::goInsideElement(BasicElement* element)
00274 {
00275 element->goInside(this);
00276 }
00277
00278
00285 void FormulaCursor::normalize(Direction direction)
00286 {
00287 BasicElement* element = getElement();
00288 element->normalize(this, direction);
00289 }
00290
00291
00296 void FormulaCursor::insert(BasicElement* child, Direction direction)
00297 {
00298 QPtrList<BasicElement> list;
00299 list.append(child);
00300 insert(list, direction);
00301 }
00302
00303 void FormulaCursor::insert(QPtrList<BasicElement>& children,
00304 Direction direction)
00305 {
00306 assert( !isReadOnly() );
00307 BasicElement* element = getElement();
00308 element->insert(this, children, direction);
00309 }
00310
00311
00317 void FormulaCursor::remove(QPtrList<BasicElement>& children,
00318 Direction direction)
00319 {
00320 assert( !isReadOnly() );
00321 SequenceElement* sequence = normal();
00322 if (sequence != 0) {
00323
00324
00325
00326 if (sequence->countChildren() == 0) {
00327 BasicElement* parent = sequence->getParent();
00328 if (parent != 0) {
00329 parent->selectChild(this, sequence);
00330 parent->remove(this, children, direction);
00331 return;
00332 }
00333 }
00334 else {
00335 sequence->remove(this, children, direction);
00336 }
00337 }
00338 }
00339
00340
00345 void FormulaCursor::replaceSelectionWith(BasicElement* element,
00346 Direction direction)
00347 {
00348 assert( !isReadOnly() );
00349 QPtrList<BasicElement> list;
00350
00351
00352
00353
00354
00355 if (isSelection()) {
00356 getElement()->remove(this, list, direction);
00357 }
00358
00359 insert(element, direction);
00360 SequenceElement* mainChild = element->getMainChild();
00361 if (mainChild != 0) {
00362 mainChild->goInside(this);
00363 insert(list);
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373 element->selectChild(this, mainChild);
00374 }
00375 }
00376
00377
00382 BasicElement* FormulaCursor::replaceByMainChildContent(Direction direction)
00383 {
00384 assert( !isReadOnly() );
00385 QPtrList<BasicElement> childrenList;
00386 QPtrList<BasicElement> list;
00387 BasicElement* element = getElement();
00388 SequenceElement* mainChild = element->getMainChild();
00389 if ((mainChild != 0) && (mainChild->countChildren() > 0)) {
00390 mainChild->selectAllChildren(this);
00391 remove(childrenList);
00392 }
00393 element->getParent()->moveRight(this, element);
00394 setSelection(false);
00395 remove(list);
00396 insert(childrenList, direction);
00397 if (list.count() > 0) {
00398 return list.take(0);
00399 }
00400 return 0;
00401 }
00402
00403
00411 BasicElement* FormulaCursor::removeEnclosingElement(Direction direction)
00412 {
00413 assert( !isReadOnly() );
00414 BasicElement* parent = getElement()->getParent();
00415 if (parent != 0) {
00416 if (getElement() == parent->getMainChild()) {
00417 parent->selectChild(this, getElement());
00418 return replaceByMainChildContent(direction);
00419 }
00420 }
00421 return 0;
00422 }
00423
00424
00429 bool FormulaCursor::elementIsSenseless()
00430 {
00431 BasicElement* element = getElement();
00432 return element->isSenseless();
00433 }
00434
00435
00443 BasicElement* FormulaCursor::getActiveChild(Direction direction)
00444 {
00445 return getElement()->getChild(this, direction);
00446 }
00447
00448 BasicElement* FormulaCursor::getSelectedChild()
00449 {
00450 if (isSelection()) {
00451 if ((getSelectionEnd() - getSelectionStart()) > 1) {
00452 return 0;
00453 }
00454 return getActiveChild((getPos() > getMark()) ?
00455 beforeCursor :
00456 afterCursor);
00457 }
00458 else {
00459 return getActiveChild(beforeCursor);
00460 }
00461 }
00462
00463
00464 void FormulaCursor::selectActiveElement()
00465 {
00466 if ( !isSelection() && getPos() > 0 ) {
00467 setSelection( true );
00468 setMark( getPos() - 1 );
00469 }
00470 }
00471
00472
00477 bool FormulaCursor::pointsAfterMainChild(BasicElement* element)
00478 {
00479 if (element != 0) {
00480 SequenceElement* mainChild = element->getMainChild();
00481 return (getElement() == mainChild) &&
00482 ((mainChild->countChildren() == getPos()) || (0 == getPos()));
00483 }
00484 return false;
00485 }
00486
00487
00492 IndexElement* FormulaCursor::getActiveIndexElement()
00493 {
00494 IndexElement* element = dynamic_cast<IndexElement*>(getSelectedChild());
00495
00496 if ((element == 0) && !isSelection()) {
00497 element = dynamic_cast<IndexElement*>(getElement()->getParent());
00498 if (!pointsAfterMainChild(element)) {
00499 return 0;
00500 }
00501 }
00502 return element;
00503 }
00504
00505
00510 RootElement* FormulaCursor::getActiveRootElement()
00511 {
00512 RootElement* element = dynamic_cast<RootElement*>(getSelectedChild());
00513
00514 if ((element == 0) && !isSelection()) {
00515 element = dynamic_cast<RootElement*>(getElement()->getParent());
00516 if (!pointsAfterMainChild(element)) {
00517 return 0;
00518 }
00519 }
00520 return element;
00521 }
00522
00523
00528 SymbolElement* FormulaCursor::getActiveSymbolElement()
00529 {
00530 SymbolElement* element = dynamic_cast<SymbolElement*>(getSelectedChild());
00531
00532 if ((element == 0) && !isSelection()) {
00533 element = dynamic_cast<SymbolElement*>(getElement()->getParent());
00534 if (!pointsAfterMainChild(element)) {
00535 return 0;
00536 }
00537 }
00538 return element;
00539 }
00540
00545 NameSequence* FormulaCursor::getActiveNameSequence()
00546 {
00547 NameSequence* element = dynamic_cast<NameSequence*>( getSelectedChild() );
00548
00549 if ( ( element == 0 ) && !isSelection() ) {
00550 element = dynamic_cast<NameSequence*>( getElement() );
00551 if ( !pointsAfterMainChild( element ) ) {
00552 return 0;
00553 }
00554 }
00555 return element;
00556 }
00557
00561 TextElement* FormulaCursor::getActiveTextElement()
00562 {
00563 return dynamic_cast<TextElement*>(getSelectedChild());
00564 }
00565
00566
00567 MatrixElement* FormulaCursor::getActiveMatrixElement()
00568 {
00569 MatrixElement* element = dynamic_cast<MatrixElement*>(getSelectedChild());
00570
00571 if ( ( element != 0 ) && !isSelection() ) {
00572 normal()->selectChild( this, element );
00573 }
00574
00575
00576
00577
00578
00579
00580 return element;
00581 }
00582
00586 void FormulaCursor::elementWillVanish(BasicElement* element)
00587 {
00588 BasicElement* child = getElement();
00589 if (child == element->getParent()) {
00590 child->childWillVanish(this, element);
00591 return;
00592 }
00593 while (child != 0) {
00594 if (child == element) {
00595
00596
00597 child->getParent()->moveLeft(this, child);
00598 setSelection(false);
00599 hasChangedFlag = true;
00600 return;
00601 }
00602 child = child->getParent();
00603 }
00604 }
00605
00606
00610 void FormulaCursor::formulaLoaded(FormulaElement* rootElement)
00611 {
00612
00613
00614 rootElement->goInside( this );
00615 setMark(-1);
00616 setSelection(false);
00617 }
00618
00619
00620 bool FormulaCursor::isReadOnly() const
00621 {
00622 if ( readOnly ) {
00623 return true;
00624 }
00625 const SequenceElement* sequence = normal();
00626 if ( sequence != 0 ) {
00627 bool ro = sequence->readOnly( this );
00628
00629 return ro;
00630 }
00631 return false;
00632 }
00633
00634
00638 void FormulaCursor::copy( QDomDocument doc )
00639 {
00640 if (isSelection()) {
00641 SequenceElement* sequence = normal();
00642 if (sequence != 0) {
00643 QDomElement root = doc.documentElement();
00644 QDomElement de = sequence->formula()->emptyFormulaElement( doc );
00645 root.appendChild( de );
00646
00647 sequence->getChildrenDom(doc, de, getSelectionStart(), getSelectionEnd());
00648 }
00649 else {
00650
00651 qFatal("A not normalized cursor is selecting.");
00652 }
00653 }
00654 }
00655
00660 bool FormulaCursor::buildElementsFromDom( QDomElement root, QPtrList<BasicElement>& list )
00661 {
00662 assert( !isReadOnly() );
00663 SequenceElement* sequence = normal();
00664 if (sequence != 0) {
00665 QDomElement e = root.firstChild().toElement();
00666 if (sequence->buildChildrenFromDom(list, e.firstChild())) {
00667 return true;
00668 }
00669 }
00670 return false;
00671 }
00672
00673
00678 FormulaCursor::CursorData* FormulaCursor::getCursorData()
00679 {
00680 return new CursorData(current, cursorPos, markPos,
00681 selectionFlag, linearMovement, readOnly);
00682 }
00683
00684
00685
00686 FormulaCursor& FormulaCursor::operator= (const FormulaCursor& other)
00687 {
00688 current = other.current;
00689 cursorPos = other.cursorPos;
00690 markPos = other.markPos;
00691 selectionFlag = other.selectionFlag;
00692 linearMovement = other.linearMovement;
00693 readOnly = other.readOnly;
00694 hasChangedFlag = true;
00695 return *this;
00696 }
00697
00698
00703 void FormulaCursor::setCursorData(FormulaCursor::CursorData* data)
00704 {
00705 current = data->current;
00706 cursorPos = data->cursorPos;
00707 markPos = data->markPos;
00708 selectionFlag = data->selectionFlag;
00709 linearMovement = data->linearMovement;
00710 readOnly = data->readOnly;
00711 hasChangedFlag = true;
00712 }
00713
00714
00718 SequenceElement* FormulaCursor::normal()
00719 {
00720 return dynamic_cast<SequenceElement*>(current);
00721 }
00722
00723 const SequenceElement* FormulaCursor::normal() const
00724 {
00725 return dynamic_cast<SequenceElement*>(current);
00726 }
00727
00728 KFORMULA_NAMESPACE_END