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.5.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Mar 11 11:47:39 2005 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003