You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
koffice/lib/kformula/kformulacommand.cc

626 lines
15 KiB

/* This file is part of the KDE project
Copyright (C) 2001 Andrea Rizzi <rizzi@kde.org>
Ulrich Kuettler <ulrich.kuettler@mailbox.tu-dresden.de>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include <klocale.h> //This is for undo descriptions
#include <tqvaluelist.h>
#include "formulacursor.h"
#include "formulaelement.h"
#include "indexelement.h"
#include "kformulacommand.h"
#include "matrixelement.h"
#include "sequenceelement.h"
#include "textelement.h"
#include "tokenelement.h"
KFORMULA_NAMESPACE_BEGIN
int PlainCommand::evilDestructionCount = 0;
PlainCommand::PlainCommand( const TQString& name )
: KNamedCommand(name)
{
evilDestructionCount++;
}
PlainCommand::~PlainCommand()
{
evilDestructionCount--;
}
Command::Command(const TQString &name, Container* document)
: PlainCommand(name), cursordata(0), undocursor(0), doc(document)
{
}
Command::~Command()
{
delete undocursor;
delete cursordata;
}
FormulaCursor* Command::getExecuteCursor()
{
FormulaCursor* cursor = getActiveCursor();
if (cursordata == 0) {
setExecuteCursor(getActiveCursor());
}
else {
cursor->setCursorData(cursordata);
}
return cursor;
}
void Command::setExecuteCursor(FormulaCursor* cursor)
{
// assert(cursordata == 0);
cursordata = cursor->getCursorData();
}
FormulaCursor* Command::getUnexecuteCursor()
{
FormulaCursor* cursor = getActiveCursor();
cursor->setCursorData(undocursor);
destroyUndoCursor();
return cursor;
}
void Command::setUnexecuteCursor(FormulaCursor* cursor)
{
// assert(undocursor == 0);
undocursor = cursor->getCursorData();
}
// ****** Generic Add command
KFCAdd::KFCAdd(const TQString &name, Container *document)
: Command(name, document)
{
addList.setAutoDelete( true );
}
void KFCAdd::execute()
{
FormulaCursor* cursor = getExecuteCursor();
cursor->insert(addList, beforeCursor);
setUnexecuteCursor(cursor);
cursor->setSelection(false);
testDirty();
}
void KFCAdd::unexecute()
{
FormulaCursor* cursor = getUnexecuteCursor();
cursor->remove(addList, beforeCursor);
//cursor->setSelection(false);
cursor->normalize();
testDirty();
}
// ****** Remove selection command
KFCRemoveSelection::KFCRemoveSelection(Container *document,
Direction direction)
: Command(i18n("Remove Selected Text"), document),
dir(direction)
{
removedList.setAutoDelete( true );
}
void KFCRemoveSelection::execute()
{
FormulaCursor* cursor = getExecuteCursor();
cursor->remove(removedList, dir);
setUnexecuteCursor(cursor);
testDirty();
}
void KFCRemoveSelection::unexecute()
{
FormulaCursor* cursor = getUnexecuteCursor();
cursor->insert(removedList);
cursor->setSelection(false);
testDirty();
}
KFCReplace::KFCReplace(const TQString &name, Container* document)
: KFCAdd(name, document), removeSelection(0)
{
}
KFCReplace::~KFCReplace()
{
delete removeSelection;
}
void KFCReplace::execute()
{
if (getActiveCursor()->isSelection() && (removeSelection == 0)) {
removeSelection = new KFCRemoveSelection(getDocument());
}
if (removeSelection != 0) {
removeSelection->execute();
}
KFCAdd::execute();
}
void KFCReplace::unexecute()
{
KFCAdd::unexecute();
if (removeSelection != 0) {
removeSelection->unexecute();
}
}
// ****** Token Add command
KFCAddToken::KFCAddToken(const TQString &name, Container *document)
: Command(name, document)
{
}
KFCAddToken::~KFCAddToken()
{
TQPtrDictIterator< TQPtrList< BasicElement > > it( contentList );
TQPtrList< BasicElement >* list;
while ( ( list = it.current() ) != 0 ) {
delete list;
++it;
}
}
void KFCAddToken::execute()
{
kdDebug( DEBUGID ) << k_funcinfo << endl;
FormulaCursor* cursor = getExecuteCursor();
TQPtrList<BasicElement> tokenListTmp = tokenList;
cursor->insert( tokenList, beforeCursor );
tokenList = tokenListTmp;
TQPtrListIterator< BasicElement > it( tokenList );
BasicElement* element;
BasicElement* current = cursor->getElement();
while ( (element = it.current()) != 0 ) {
element->goInside( cursor );
cursor->insert( *contentList.find( element ), beforeCursor );
++it;
}
setUnexecuteCursor( cursor );
cursor->setSelection(false);
testDirty();
}
void KFCAddToken::unexecute()
{
kdDebug( DEBUGID ) << k_funcinfo << endl;
FormulaCursor* cursor = getUnexecuteCursor();
SequenceElement* parent = static_cast<SequenceElement*>(cursor->getElement()->getParent());
for ( int i = 0; i < tokenList.count(); i++ ) {
SequenceElement* current = static_cast<SequenceElement*>(cursor->getElement());
TQPtrList< BasicElement > list;
for ( uint i = 0; i < current->countChildren(); ++i ) {
cursor->remove( list, beforeCursor );
}
if ( parent ) {
int pos = parent->childPos( current );
cursor->setTo( parent, pos + 1);
cursor->remove( list, beforeCursor );
if ( pos > 0 ) {
BasicElement* element = parent->getChild( pos - 1 );
if (element)
element->moveEnd( cursor );
}
}
}
testDirty();
}
/**
* Collect all tokens that are to be added
*/
void KFCAddToken::addToken( BasicElement* element )
{
tokenList.append( element );
contentList.insert( element, new TQPtrList< BasicElement > );
contentList.find( element )->setAutoDelete( true );
}
KFCReplaceToken::KFCReplaceToken(const TQString &name, Container* document)
: KFCAddToken(name, document), removeSelection(0)
{
}
KFCReplaceToken::~KFCReplaceToken()
{
delete removeSelection;
}
void KFCReplaceToken::execute()
{
kdDebug( DEBUGID ) << k_funcinfo << endl;
if (getActiveCursor()->isSelection() && (removeSelection == 0)) {
removeSelection = new KFCRemoveSelection(getDocument());
}
if (removeSelection != 0) {
removeSelection->execute();
}
KFCAddToken::execute();
}
void KFCReplaceToken::unexecute()
{
kdDebug( DEBUGID ) << k_funcinfo << endl;
KFCAddToken::unexecute();
if (removeSelection != 0) {
removeSelection->unexecute();
}
}
KFCSplitToken::KFCSplitToken(const TQString &name, Container* document)
: KFCAddToken(name, document), removeSelection(0)
{
splitList.setAutoDelete( true );
}
KFCSplitToken::~KFCSplitToken()
{
delete splitCursor;
delete removeSelection;
}
void KFCSplitToken::execute()
{
FormulaCursor* cursor = getExecuteCursor();
if (getActiveCursor()->isSelection() && (removeSelection == 0)) {
removeSelection = new KFCRemoveSelection(getDocument());
}
if (removeSelection != 0) {
removeSelection->execute();
}
splitCursor = cursor->getCursorData();
SequenceElement* parent = static_cast<SequenceElement*>( cursor->getElement() );
if ( parent ) {
cursor->setMark( parent->countChildren() );
cursor->setSelection( true );
}
cursor->remove( splitList, afterCursor );
TokenElement *token = new TokenElement();// TODO
addToken( token );
TQPtrListIterator< BasicElement > it ( splitList );
BasicElement* element;
while ( ( element = it.current() ) != 0 ) {
addContent( token, element );
++it;
}
KFCAddToken::execute();
cursor = getExecuteCursor();
if ( parent ) {
BasicElement* child = parent->getChild( cursor->getPos() );
if ( child ) {
child->moveEnd( cursor );
}
}
}
void KFCSplitToken::unexecute()
{
kdDebug( DEBUGID ) << k_funcinfo << endl;
KFCAddToken::unexecute();
FormulaCursor *cursor = getUnexecuteCursor();
cursor->setCursorData( splitCursor );
cursor->insert( splitList, afterCursor );
if (removeSelection != 0) {
removeSelection->unexecute();
}
testDirty();
}
KFCRemove::KFCRemove(Container *document,
Direction direction)
: Command(i18n("Remove Selected Text"), document),
element(0), simpleRemoveCursor(0), dir(direction)
{
removedList.setAutoDelete( true );
}
KFCRemove::~KFCRemove()
{
delete simpleRemoveCursor;
delete element;
}
void KFCRemove::execute()
{
FormulaCursor* cursor = getExecuteCursor();
cursor->remove(removedList, dir);
if (cursor->elementIsSenseless()) {
simpleRemoveCursor = cursor->getCursorData();
element = cursor->replaceByMainChildContent();
}
setUnexecuteCursor(cursor);
cursor->normalize( dir );
testDirty();
}
void KFCRemove::unexecute()
{
FormulaCursor* cursor = getUnexecuteCursor();
if (element != 0) {
cursor->replaceSelectionWith(element);
element = 0;
cursor->setCursorData(simpleRemoveCursor);
delete simpleRemoveCursor;
simpleRemoveCursor = 0;
}
cursor->insert(removedList, dir);
cursor->setSelection(false);
testDirty();
}
KFCRemoveEnclosing::KFCRemoveEnclosing(Container* document,
Direction dir)
: Command(i18n("Remove Enclosing Element"), document),
element(0), direction(dir)
{
}
KFCRemoveEnclosing::~KFCRemoveEnclosing()
{
delete element;
}
void KFCRemoveEnclosing::execute()
{
FormulaCursor* cursor = getExecuteCursor();
element = cursor->removeEnclosingElement(direction);
setUnexecuteCursor(cursor);
//cursor->normalize();
cursor->setSelection(false);
testDirty();
}
void KFCRemoveEnclosing::unexecute()
{
FormulaCursor* cursor = getUnexecuteCursor();
if ( element ) {
cursor->replaceSelectionWith(element);
}
cursor->normalize();
cursor->setSelection(false);
element = 0;
testDirty();
}
// ****** Add root, bracket etc command
KFCAddReplacing::KFCAddReplacing(const TQString &name, Container* document)
: Command(name, document), element(0)
{
}
KFCAddReplacing::~KFCAddReplacing()
{
delete element;
}
void KFCAddReplacing::execute()
{
FormulaCursor* cursor = getExecuteCursor();
cursor->replaceSelectionWith(element);
setUnexecuteCursor(cursor);
cursor->goInsideElement(element);
element = 0;
testDirty();
}
void KFCAddReplacing::unexecute()
{
FormulaCursor* cursor = getUnexecuteCursor();
element = cursor->replaceByMainChildContent();
cursor->normalize();
testDirty();
}
// ****** Add index command
KFCAddGenericIndex::KFCAddGenericIndex(Container* document, ElementIndexPtr _index)
: KFCAdd(i18n("Add Index"), document), index(_index)
{
addElement(new SequenceElement());
}
void KFCAddGenericIndex::execute()
{
index->setToIndex(getActiveCursor());
KFCAdd::execute();
}
KFCAddIndex::KFCAddIndex(Container* document,
IndexElement* element, ElementIndexPtr index)
: KFCAddReplacing(i18n("Add Index"), document),
addIndex(document, index)
{
setElement(element);
}
KFCAddIndex::~KFCAddIndex()
{
}
void KFCAddIndex::execute()
{
KFCAddReplacing::execute();
addIndex.execute();
}
void KFCAddIndex::unexecute()
{
addIndex.unexecute();
KFCAddReplacing::unexecute();
}
KFCChangeBaseSize::KFCChangeBaseSize( const TQString& name, Container* document,
FormulaElement* formula, int size )
: PlainCommand( name ), m_document( document ), m_formula( formula ), m_size( size )
{
m_oldSize = formula->getBaseSize();
}
void KFCChangeBaseSize::execute()
{
m_formula->setBaseSize( m_size );
m_document->recalc();
}
void KFCChangeBaseSize::unexecute()
{
m_formula->setBaseSize( m_oldSize );
m_document->recalc();
}
FontCommand::FontCommand( const TQString& name, Container* document )
: Command( name, document )
{
list.setAutoDelete( false );
elementList.setAutoDelete( false );
}
void FontCommand::collectChildren()
{
list.clear();
uint count = elementList.count();
for ( uint i=0; i<count; ++i ) {
elementList.at( i )->dispatchFontCommand( this );
}
}
void FontCommand::parseSequences( const TQMap<SequenceElement*, int>& parents )
{
TQValueList<SequenceElement*> sequences = parents.keys();
for ( TQValueList<SequenceElement*>::iterator i = sequences.begin();
i != sequences.end();
++i ) {
( *i )->parse();
}
}
CharStyleCommand::CharStyleCommand( CharStyle cs, const TQString& name, Container* document )
: FontCommand( name, document ), charStyle( cs )
{
}
void CharStyleCommand::execute()
{
collectChildren();
TQMap<SequenceElement*, int> parentCollector;
styleList.clear();
uint count = tqchildrenList().count();
styleList.reserve( count );
for ( uint i=0; i<count; ++i ) {
TextElement* child = tqchildrenList().at( i );
styleList[i] = child->getCharStyle();
child->setCharStyle( charStyle );
parentCollector[static_cast<SequenceElement*>( child->getParent() )] = 1;
}
parseSequences( parentCollector );
testDirty();
}
void CharStyleCommand::unexecute()
{
TQMap<SequenceElement*, int> parentCollector;
uint count = tqchildrenList().count();
//styleList.reserve( count );
for ( uint i=0; i<count; ++i ) {
TextElement* child = tqchildrenList().at( i );
child->setCharStyle( styleList[i] );
parentCollector[static_cast<SequenceElement*>( child->getParent() )] = 1;
}
parseSequences( parentCollector );
testDirty();
}
CharFamilyCommand::CharFamilyCommand( CharFamily cf, const TQString& name, Container* document )
: FontCommand( name, document ), charFamily( cf )
{
}
void CharFamilyCommand::execute()
{
collectChildren();
TQMap<SequenceElement*, int> parentCollector;
familyList.clear();
uint count = tqchildrenList().count();
familyList.reserve( count );
for ( uint i=0; i<count; ++i ) {
TextElement* child = tqchildrenList().at( i );
familyList[i] = child->getCharFamily();
child->setCharFamily( charFamily );
parentCollector[static_cast<SequenceElement*>( child->getParent() )] = 1;
}
parseSequences( parentCollector );
testDirty();
}
void CharFamilyCommand::unexecute()
{
TQMap<SequenceElement*, int> parentCollector;
uint count = tqchildrenList().count();
//familyList.reserve( count );
for ( uint i=0; i<count; ++i ) {
TextElement* child = tqchildrenList().at( i );
child->setCharFamily( familyList[i] );
parentCollector[static_cast<SequenceElement*>( child->getParent() )] = 1;
}
parseSequences( parentCollector );
testDirty();
}
KFORMULA_NAMESPACE_END