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