lib

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., 51 Franklin Street, Fifth Floor,
00018  * Boston, MA 02110-1301, 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, 
00083                           bool smallCursor, bool activeCursor )
00084 {
00085     //if (readOnly && !isSelection())
00086     //return;
00087 
00088     // We only draw the cursor if its normalized.
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     //mouseSelectionFlag = false;
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         // If there is no child to remove in the sequence
00326         // remove the sequence instead.
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     // we suppres deletion here to get an error if something
00352     // was left in the list.
00353     //list.setAutoDelete(true);
00354 
00355     //remove(list, direction);
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         BasicElement* parent = element->getParent();
00367         if (direction == beforeCursor) {
00368             parent->moveRight(this, element);
00369         }
00370         else {
00371             parent->moveLeft(this, element);
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 //     if ((element == 0) && !isSelection()) {
00576 //         element = dynamic_cast<MatrixElement*>(getElement()->getParent());
00577 //         if (!pointsAfterMainChild(element)) {
00578 //             return 0;
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             // This is meant to catch all cursors that did not
00597             // cause the deletion.
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     //current = rootElement;
00614     //setPos(0);
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         //kdDebug() << k_funcinfo << "readOnly=" << ro << endl;
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             // This must never happen.
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 // Keep in sync with 'setCursorData'
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
KDE Home | KDE Accessibility Home | Description of Access Keys