kformulacommand.cpp
1/* This file is part of the KDE project
2 Copyright (C) 2001 Andrea Rizzi <rizzi@kde.org>
3 Ulrich Kuettler <ulrich.kuettler@mailbox.tu-dresden.de>
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to
17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19*/
20
21#include <tdelocale.h> //This is for undo descriptions
22
23#include <tqvaluelist.h>
24
25#include "formulacursor.h"
26#include "formulaelement.h"
27#include "indexelement.h"
28#include "kformulacommand.h"
29#include "matrixelement.h"
30#include "sequenceelement.h"
31#include "textelement.h"
32#include "tokenelement.h"
33
34
35KFORMULA_NAMESPACE_BEGIN
36
37int PlainCommand::evilDestructionCount = 0;
38
39PlainCommand::PlainCommand( const TQString& name )
40 : KNamedCommand(name)
41{
42 evilDestructionCount++;
43}
44
45PlainCommand::~PlainCommand()
46{
47 evilDestructionCount--;
48}
49
50Command::Command(const TQString &name, Container* document)
51 : PlainCommand(name), cursordata(0), undocursor(0), doc(document)
52{
53}
54
55Command::~Command()
56{
57 delete undocursor;
58 delete cursordata;
59}
60
61FormulaCursor* Command::getExecuteCursor()
62{
63 FormulaCursor* cursor = getActiveCursor();
64 if (cursordata == 0) {
65 setExecuteCursor(getActiveCursor());
66 }
67 else {
68 cursor->setCursorData(cursordata);
69 }
70 return cursor;
71}
72
73void Command::setExecuteCursor(FormulaCursor* cursor)
74{
75 // assert(cursordata == 0);
76 cursordata = cursor->getCursorData();
77}
78
79FormulaCursor* Command::getUnexecuteCursor()
80{
81 FormulaCursor* cursor = getActiveCursor();
82 cursor->setCursorData(undocursor);
83 destroyUndoCursor();
84 return cursor;
85}
86
87void Command::setUnexecuteCursor(FormulaCursor* cursor)
88{
89 // assert(undocursor == 0);
90 undocursor = cursor->getCursorData();
91}
92
93
94// ****** Generic Add command
95
96KFCAdd::KFCAdd(const TQString &name, Container *document)
97 : Command(name, document)
98{
99 addList.setAutoDelete( true );
100}
101
102
103void KFCAdd::execute()
104{
105 FormulaCursor* cursor = getExecuteCursor();
106 cursor->insert(addList, beforeCursor);
107 setUnexecuteCursor(cursor);
108 cursor->setSelection(false);
109 testDirty();
110}
111
112
113void KFCAdd::unexecute()
114{
115 FormulaCursor* cursor = getUnexecuteCursor();
116 cursor->remove(addList, beforeCursor);
117 //cursor->setSelection(false);
118 cursor->normalize();
119 testDirty();
120}
121
122
123// ****** Remove selection command
124
126 Direction direction)
127 : Command(i18n("Remove Selected Text"), document),
128 dir(direction)
129{
130 removedList.setAutoDelete( true );
131}
132
133void KFCRemoveSelection::execute()
134{
135 FormulaCursor* cursor = getExecuteCursor();
136 cursor->remove(removedList, dir);
137 setUnexecuteCursor(cursor);
138 testDirty();
139}
140
141void KFCRemoveSelection::unexecute()
142{
143 FormulaCursor* cursor = getUnexecuteCursor();
144 cursor->insert(removedList);
145 cursor->setSelection(false);
146 testDirty();
147}
148
149
150
151KFCReplace::KFCReplace(const TQString &name, Container* document)
152 : KFCAdd(name, document), removeSelection(0)
153{
154}
155
156KFCReplace::~KFCReplace()
157{
158 delete removeSelection;
159}
160
161void KFCReplace::execute()
162{
163 if (getActiveCursor()->isSelection() && (removeSelection == 0)) {
164 removeSelection = new KFCRemoveSelection(getDocument());
165 }
166 if (removeSelection != 0) {
167 removeSelection->execute();
168 }
169 KFCAdd::execute();
170}
171
172void KFCReplace::unexecute()
173{
174 KFCAdd::unexecute();
175 if (removeSelection != 0) {
176 removeSelection->unexecute();
177 }
178}
179
180
181// ****** Token Add command
182
183KFCAddToken::KFCAddToken(const TQString &name, Container *document)
184 : Command(name, document)
185{
186}
187
188KFCAddToken::~KFCAddToken()
189{
190 TQPtrDictIterator< TQPtrList< BasicElement > > it( contentList );
191 TQPtrList< BasicElement >* list;
192 while ( ( list = it.current() ) != 0 ) {
193 delete list;
194 ++it;
195 }
196}
197
198void KFCAddToken::execute()
199{
200 kdDebug( DEBUGID ) << k_funcinfo << endl;
201 FormulaCursor* cursor = getExecuteCursor();
202 TQPtrList<BasicElement> tokenListTmp = tokenList;
203 cursor->insert( tokenList, beforeCursor );
204 tokenList = tokenListTmp;
205 TQPtrListIterator< BasicElement > it( tokenList );
206 BasicElement* element;
207 BasicElement* current = cursor->getElement();
208 while ( (element = it.current()) != 0 ) {
209 element->goInside( cursor );
210 cursor->insert( *contentList.find( element ), beforeCursor );
211 ++it;
212 }
213 setUnexecuteCursor( cursor );
214 cursor->setSelection(false);
215 testDirty();
216}
217
218
219void KFCAddToken::unexecute()
220{
221 kdDebug( DEBUGID ) << k_funcinfo << endl;
222 FormulaCursor* cursor = getUnexecuteCursor();
223 SequenceElement* parent = static_cast<SequenceElement*>(cursor->getElement()->getParent());
224
225 for ( int i = 0; i < tokenList.count(); i++ ) {
226 SequenceElement* current = static_cast<SequenceElement*>(cursor->getElement());
227 TQPtrList< BasicElement > list;
228 for ( uint i = 0; i < current->countChildren(); ++i ) {
229 cursor->remove( list, beforeCursor );
230 }
231 if ( parent ) {
232 int pos = parent->childPos( current );
233 cursor->setTo( parent, pos + 1);
234 cursor->remove( list, beforeCursor );
235 if ( pos > 0 ) {
236 BasicElement* element = parent->getChild( pos - 1 );
237 if (element)
238 element->moveEnd( cursor );
239 }
240 }
241 }
242 testDirty();
243}
244
249{
250 tokenList.append( element );
251 contentList.insert( element, new TQPtrList< BasicElement > );
252 contentList.find( element )->setAutoDelete( true );
253}
254
255KFCReplaceToken::KFCReplaceToken(const TQString &name, Container* document)
256 : KFCAddToken(name, document), removeSelection(0)
257{
258}
259
260KFCReplaceToken::~KFCReplaceToken()
261{
262 delete removeSelection;
263}
264
265void KFCReplaceToken::execute()
266{
267 kdDebug( DEBUGID ) << k_funcinfo << endl;
268 if (getActiveCursor()->isSelection() && (removeSelection == 0)) {
269 removeSelection = new KFCRemoveSelection(getDocument());
270 }
271 if (removeSelection != 0) {
272 removeSelection->execute();
273 }
274 KFCAddToken::execute();
275}
276
277void KFCReplaceToken::unexecute()
278{
279 kdDebug( DEBUGID ) << k_funcinfo << endl;
280 KFCAddToken::unexecute();
281 if (removeSelection != 0) {
282 removeSelection->unexecute();
283 }
284}
285
286
287KFCSplitToken::KFCSplitToken(const TQString &name, Container* document)
288 : KFCAddToken(name, document), removeSelection(0)
289{
290 splitList.setAutoDelete( true );
291}
292
293KFCSplitToken::~KFCSplitToken()
294{
295 delete splitCursor;
296 delete removeSelection;
297}
298
299void KFCSplitToken::execute()
300{
301 FormulaCursor* cursor = getExecuteCursor();
302 if (getActiveCursor()->isSelection() && (removeSelection == 0)) {
303 removeSelection = new KFCRemoveSelection(getDocument());
304 }
305 if (removeSelection != 0) {
306 removeSelection->execute();
307 }
308 splitCursor = cursor->getCursorData();
309 SequenceElement* parent = static_cast<SequenceElement*>( cursor->getElement() );
310 if ( parent ) {
311 cursor->setMark( parent->countChildren() );
312 cursor->setSelection( true );
313 }
314 cursor->remove( splitList, afterCursor );
315 TokenElement *token = new TokenElement();// TODO
316 addToken( token );
317 TQPtrListIterator< BasicElement > it ( splitList );
318 BasicElement* element;
319 while ( ( element = it.current() ) != 0 ) {
320 addContent( token, element );
321 ++it;
322 }
323 KFCAddToken::execute();
324 cursor = getExecuteCursor();
325 if ( parent ) {
326 BasicElement* child = parent->getChild( cursor->getPos() );
327 if ( child ) {
328 child->moveEnd( cursor );
329 }
330 }
331}
332
333void KFCSplitToken::unexecute()
334{
335 kdDebug( DEBUGID ) << k_funcinfo << endl;
336 KFCAddToken::unexecute();
337 FormulaCursor *cursor = getUnexecuteCursor();
338 cursor->setCursorData( splitCursor );
339 cursor->insert( splitList, afterCursor );
340 if (removeSelection != 0) {
341 removeSelection->unexecute();
342 }
343 testDirty();
344}
345
346
348 Direction direction)
349 : Command(i18n("Remove Selected Text"), document),
350 element(0), simpleRemoveCursor(0), dir(direction)
351{
352 removedList.setAutoDelete( true );
353}
354
355KFCRemove::~KFCRemove()
356{
357 delete simpleRemoveCursor;
358 delete element;
359}
360
361void KFCRemove::execute()
362{
363 FormulaCursor* cursor = getExecuteCursor();
364 cursor->remove(removedList, dir);
365 if (cursor->elementIsSenseless()) {
366 simpleRemoveCursor = cursor->getCursorData();
367 element = cursor->replaceByMainChildContent();
368 }
369 setUnexecuteCursor(cursor);
370 cursor->normalize( dir );
371 testDirty();
372}
373
374void KFCRemove::unexecute()
375{
376 FormulaCursor* cursor = getUnexecuteCursor();
377 if (element != 0) {
378 cursor->replaceSelectionWith(element);
379 element = 0;
380
381 cursor->setCursorData(simpleRemoveCursor);
382 delete simpleRemoveCursor;
383 simpleRemoveCursor = 0;
384 }
385 cursor->insert(removedList, dir);
386 cursor->setSelection(false);
387 testDirty();
388}
389
390
391KFCRemoveEnclosing::KFCRemoveEnclosing(Container* document,
392 Direction dir)
393 : Command(i18n("Remove Enclosing Element"), document),
394 element(0), direction(dir)
395{
396}
397
398KFCRemoveEnclosing::~KFCRemoveEnclosing()
399{
400 delete element;
401}
402
403void KFCRemoveEnclosing::execute()
404{
405 FormulaCursor* cursor = getExecuteCursor();
406 element = cursor->removeEnclosingElement(direction);
407 setUnexecuteCursor(cursor);
408 //cursor->normalize();
409 cursor->setSelection(false);
410 testDirty();
411}
412
413void KFCRemoveEnclosing::unexecute()
414{
415 FormulaCursor* cursor = getUnexecuteCursor();
416 if ( element ) {
417 cursor->replaceSelectionWith(element);
418 }
419 cursor->normalize();
420 cursor->setSelection(false);
421 element = 0;
422 testDirty();
423}
424
425
426// ****** Add root, bracket etc command
427
428KFCAddReplacing::KFCAddReplacing(const TQString &name, Container* document)
429 : Command(name, document), element(0)
430{
431}
432
433KFCAddReplacing::~KFCAddReplacing()
434{
435 delete element;
436}
437
438
439void KFCAddReplacing::execute()
440{
441 FormulaCursor* cursor = getExecuteCursor();
442 cursor->replaceSelectionWith(element);
443 setUnexecuteCursor(cursor);
444 cursor->goInsideElement(element);
445 element = 0;
446 testDirty();
447}
448
449
450void KFCAddReplacing::unexecute()
451{
452 FormulaCursor* cursor = getUnexecuteCursor();
453 element = cursor->replaceByMainChildContent();
454 cursor->normalize();
455 testDirty();
456}
457
458
459// ****** Add index command
460
461KFCAddGenericIndex::KFCAddGenericIndex(Container* document, ElementIndexPtr &_index)
462 : KFCAdd(i18n("Add Index"), document), index(std::move(_index))
463{
464 addElement(new SequenceElement());
465}
466
467void KFCAddGenericIndex::execute()
468{
469 index->setToIndex(getActiveCursor());
470 KFCAdd::execute();
471}
472
473
474KFCAddIndex::KFCAddIndex(Container* document,
475 IndexElement* element, ElementIndexPtr index)
476 : KFCAddReplacing(i18n("Add Index"), document),
477 addIndex(document, index)
478{
479 setElement(element);
480}
481
482KFCAddIndex::~KFCAddIndex()
483{
484}
485
486void KFCAddIndex::execute()
487{
488 KFCAddReplacing::execute();
489 addIndex.execute();
490}
491
492void KFCAddIndex::unexecute()
493{
494 addIndex.unexecute();
495 KFCAddReplacing::unexecute();
496}
497
498
499KFCChangeBaseSize::KFCChangeBaseSize( const TQString& name, Container* document,
500 FormulaElement* formula, int size )
501 : PlainCommand( name ), m_document( document ), m_formula( formula ), m_size( size )
502{
503 m_oldSize = formula->getBaseSize();
504}
505
506void KFCChangeBaseSize::execute()
507{
508 m_formula->setBaseSize( m_size );
509 m_document->recalc();
510}
511
512void KFCChangeBaseSize::unexecute()
513{
514 m_formula->setBaseSize( m_oldSize );
515 m_document->recalc();
516}
517
518
519FontCommand::FontCommand( const TQString& name, Container* document )
520 : Command( name, document )
521{
522 list.setAutoDelete( false );
523 elementList.setAutoDelete( false );
524}
525
526
527void FontCommand::collectChildren()
528{
529 list.clear();
530 uint count = elementList.count();
531 for ( uint i=0; i<count; ++i ) {
532 elementList.at( i )->dispatchFontCommand( this );
533 }
534}
535
536
537void FontCommand::parseSequences( const TQMap<SequenceElement*, int>& parents )
538{
539 TQValueList<SequenceElement*> sequences = parents.keys();
540 for ( TQValueList<SequenceElement*>::iterator i = sequences.begin();
541 i != sequences.end();
542 ++i ) {
543 ( *i )->parse();
544 }
545}
546
547
548CharStyleCommand::CharStyleCommand( CharStyle cs, const TQString& name, Container* document )
549 : FontCommand( name, document ), charStyle( cs )
550{
551}
552
553void CharStyleCommand::execute()
554{
555 collectChildren();
556 TQMap<SequenceElement*, int> parentCollector;
557
558 styleList.clear();
559 uint count = childrenList().count();
560 styleList.reserve( count );
561 for ( uint i=0; i<count; ++i ) {
562 TextElement* child = childrenList().at( i );
563 styleList[i] = child->getCharStyle();
564 child->setCharStyle( charStyle );
565 parentCollector[static_cast<SequenceElement*>( child->getParent() )] = 1;
566 }
567 parseSequences( parentCollector );
568 testDirty();
569}
570
571void CharStyleCommand::unexecute()
572{
573 TQMap<SequenceElement*, int> parentCollector;
574 uint count = childrenList().count();
575 //styleList.reserve( count );
576 for ( uint i=0; i<count; ++i ) {
577 TextElement* child = childrenList().at( i );
578 child->setCharStyle( styleList[i] );
579 parentCollector[static_cast<SequenceElement*>( child->getParent() )] = 1;
580 }
581 parseSequences( parentCollector );
582 testDirty();
583}
584
585
586CharFamilyCommand::CharFamilyCommand( CharFamily cf, const TQString& name, Container* document )
587 : FontCommand( name, document ), charFamily( cf )
588{
589}
590
591void CharFamilyCommand::execute()
592{
593 collectChildren();
594
595 TQMap<SequenceElement*, int> parentCollector;
596
597 familyList.clear();
598 uint count = childrenList().count();
599 familyList.reserve( count );
600 for ( uint i=0; i<count; ++i ) {
601 TextElement* child = childrenList().at( i );
602 familyList[i] = child->getCharFamily();
603 child->setCharFamily( charFamily );
604 parentCollector[static_cast<SequenceElement*>( child->getParent() )] = 1;
605 }
606 parseSequences( parentCollector );
607 testDirty();
608}
609
610void CharFamilyCommand::unexecute()
611{
612 TQMap<SequenceElement*, int> parentCollector;
613 uint count = childrenList().count();
614 //familyList.reserve( count );
615 for ( uint i=0; i<count; ++i ) {
616 TextElement* child = childrenList().at( i );
617 child->setCharFamily( familyList[i] );
618 parentCollector[static_cast<SequenceElement*>( child->getParent() )] = 1;
619 }
620 parseSequences( parentCollector );
621 testDirty();
622}
623
624
625KFORMULA_NAMESPACE_END
Basis of every formula element.
virtual void goInside(FormulaCursor *cursor)
Sets the cursor inside this element to its start position.
virtual void moveEnd(FormulaCursor *)
Moves the cursor to the last position in this sequence.
The document.
Base for all font commands that act on the current selection.
The selection.
void normalize(Direction direction=beforeCursor)
Moves the cursor to a normal position.
void insert(BasicElement *, Direction=beforeCursor)
Inserts the child at the current position.
void replaceSelectionWith(BasicElement *, Direction=beforeCursor)
Replaces the current selection with the supplied element.
void setCursorData(CursorData *data)
Sets the cursor to where the CursorData points to.
void setSelection(bool selection)
Sets the selection mode.
CursorData * getCursorData()
Creates a new CursorData object that describes the cursor.
BasicElement * replaceByMainChildContent(Direction=beforeCursor)
Replaces the element the cursor points to with its main child's content.
BasicElement * removeEnclosingElement(Direction=beforeCursor)
Trys to find the element we are the main child of and replace it with our content.
void goInsideElement(BasicElement *element)
Moves the cursor inside the element.
void setTo(BasicElement *element, uint cursor, int mark=-1)
Sets the cursor to a new position.
bool elementIsSenseless()
Returns wether the element the cursor points to should be replaced.
BasicElement * getElement()
The element we are in.
void remove(TQPtrList< BasicElement > &, Direction=beforeCursor)
Removes the current selected children and returns them.
The main element.
The element with up to four indexes in the four corners.
The command that takes the main child out of the selected element and replaces the element with it.
Command to add a token element, with content.
void addContent(BasicElement *element, BasicElement *content)
Collect content for each token.
void addToken(BasicElement *element)
Collect all tokens that are to be added.
Base for all commands that want to add a simple element.
Command that is used to remove the current selection if we want to replace it with another element.
KFCRemoveSelection(Container *document, Direction dir=beforeCursor)
generic add command, default implementation do nothing
KFCRemove(Container *document, Direction dir)
generic add command, default implementation do nothing
Base for all kformula commands.
PlainCommand(const TQString &name)
Sets up the command.
The element that contains a number of children.
uint countChildren() const
virtual BasicElement * getChild(FormulaCursor *, Direction=beforeCursor)
Returns the child at the cursor.
An element that represents one char.
Definition textelement.h:37
const char * name(StdAction id)