lib Library API Documentation

formulacursor.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 <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 //setTo(element, 0); 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 // We only draw the cursor if its normalized. 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 //if (readOnly && !isSelection()) 00085 //return; 00086 00087 // We only draw the cursor if its normalized. 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 //mouseSelectionFlag = false; 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 // If there is no child to remove in the sequence 00325 // remove the sequence instead. 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 // we suppres deletion here to get an error if something 00351 // was left in the list. 00352 //list.setAutoDelete(true); 00353 00354 //remove(list, direction); 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 BasicElement* parent = element->getParent(); 00366 if (direction == beforeCursor) { 00367 parent->moveRight(this, element); 00368 } 00369 else { 00370 parent->moveLeft(this, element); 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 // if ((element == 0) && !isSelection()) { 00575 // element = dynamic_cast<MatrixElement*>(getElement()->getParent()); 00576 // if (!pointsAfterMainChild(element)) { 00577 // return 0; 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 // This is meant to catch all cursors that did not 00596 // cause the deletion. 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 //current = rootElement; 00613 //setPos(0); 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 //kdDebug() << k_funcinfo << "readOnly=" << ro << endl; 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 // This must never happen. 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 // Keep in sync with 'setCursorData' 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
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 Tue Sep 28 04:03:58 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003