sequenceelement.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 <stdlib.h>
22#include <math.h>
23
24#include <tqpainter.h>
25#include <tqpaintdevice.h>
26#include <tqvaluestack.h>
27
28#include <kcommand.h>
29#include <kdebug.h>
30#include <tdelocale.h>
31
32//#include <boost/spirit.hpp>
33
34#include "MatrixDialog.h"
35#include "bracketelement.h"
36#include "creationstrategy.h"
37#include "elementtype.h"
38#include "elementvisitor.h"
39#include "formulacursor.h"
40#include "formulaelement.h"
41#include "fractionelement.h"
42#include "indexelement.h"
43#include "kformulacommand.h"
44#include "kformulacontainer.h"
45#include "kformuladocument.h"
46#include "matrixelement.h"
47#include "rootelement.h"
48#include "sequenceelement.h"
49#include "sequenceparser.h"
50#include "spaceelement.h"
51#include "symbolelement.h"
52#include "symboltable.h"
53#include "textelement.h"
54#include "numberelement.h"
55#include "identifierelement.h"
56#include "operatorelement.h"
57
58#include <assert.h>
59
60KFORMULA_NAMESPACE_BEGIN
61//using namespace std;
62
63ElementCreationStrategy* SequenceElement::creationStrategy = 0;
64
65void SequenceElement::setCreationStrategy( ElementCreationStrategy* strategy )
66{
67 creationStrategy = strategy;
68}
69
70void SequenceElement::setStyle( StyleElement *st )
71{
72 style = st;
73}
74
75SequenceElement::SequenceElement(BasicElement* parent)
76 : BasicElement(parent), parseTree(0), textSequence(true),singlePipe(true), style(0)
77{
78 assert( creationStrategy != 0 );
79 children.setAutoDelete(true);
80}
81
82
83SequenceElement::~SequenceElement()
84{
85 delete parseTree;
86}
87
88SequenceElement::SequenceElement( const SequenceElement& other )
89 : BasicElement( other )
90{
91 children.setAutoDelete(true);
92 uint count = other.children.count();
93 for (uint i = 0; i < count; i++) {
94 BasicElement* child = children.at(i)->clone();
95 child->setParent( this );
96 children.append( child );
97 }
98}
99
100
102{
103 return visitor->visit( this );
104}
105
106
108{
109 return getParent()->readOnly( this );
110}
111
112
117 const LuPixelPoint& point, const LuPixelPoint& parentOrigin )
118{
119 BasicElement* e = BasicElement::goToPos(cursor, handled, point, parentOrigin);
120 if (e != 0) {
121 LuPixelPoint myPos(parentOrigin.x() + getX(),
122 parentOrigin.y() + getY());
123
124 uint count = children.count();
125 for (uint i = 0; i < count; i++) {
126 BasicElement* child = children.at(i);
127 e = child->goToPos(cursor, handled, point, myPos);
128 if (e != 0) {
129 if (!handled) {
130 handled = true;
131 if ((point.x() - myPos.x()) < (e->getX() + e->getWidth()*2/3)) {
132 cursor->setTo(this, children.find(e));
133 }
134 else {
135 cursor->setTo(this, children.find(e)+1);
136 }
137 }
138 return e;
139 }
140 }
141
142 luPixel dx = point.x() - myPos.x();
143 //int dy = point.y() - myPos.y();
144
145 for (uint i = 0; i < count; i++) {
146 BasicElement* child = children.at(i);
147 if (dx < child->getX()) {
148 cursor->setTo( this, i );
149 handled = true;
150 return children.at( i );
151 }
152 }
153
154 cursor->setTo(this, countChildren());
155 handled = true;
156 return this;
157 }
158 return 0;
159}
160
161
163{
164 uint count = children.count();
165 for (uint i = 0; i < count; i++) {
166 BasicElement* child = children.at(i);
167 if (!child->isInvisible()) {
168 return false;
169 }
170 }
171 return true;
172}
173
174
181 ContextStyle::IndexStyle istyle,
182 StyleAttributes& style )
183{
184 double factor = style.sizeFactor();
185 if (!isEmpty()) {
186 luPixel width = 0;
187 luPixel toBaseline = 0;
188 luPixel fromBaseline = 0;
189
190 width += context.ptToPixelX( getSpaceBefore( context, tstyle, factor ) );
191
192 // Let's do all normal elements that have a base line.
193 TQPtrListIterator<BasicElement> it( children );
194 for ( ; it.current(); ++it ) {
195 BasicElement* child = it.current();
196
197 if ( !child->isInvisible() ) {
198 child->calcSizes( context, tstyle, istyle, style );
199 child->setX( width );
200 width += child->getWidth();
201
202 luPixel childBaseline = child->getBaseline();
203 if ( childBaseline > -1 ) {
204 toBaseline = TQMAX( toBaseline, childBaseline );
205 fromBaseline = TQMAX( fromBaseline,
206 child->getHeight() - childBaseline );
207 }
208 else {
209 luPixel bl = child->getHeight()/2 + context.axisHeight( tstyle, factor );
210 toBaseline = TQMAX( toBaseline, bl );
211 fromBaseline = TQMAX( fromBaseline, child->getHeight() - bl );
212 }
213 }
214 else {
215 child->setX( width );
216 }
217 }
218
219 width += context.ptToPixelX( getSpaceAfter( context, tstyle, factor ) );
220
221 setWidth(width);
222 setHeight(toBaseline+fromBaseline);
223 setBaseline(toBaseline);
224
226 }
227 else {
228 luPixel w = context.getEmptyRectWidth( factor );
229 luPixel h = context.getEmptyRectHeight( factor );
230 setWidth( w );
231 setHeight( h );
232 setBaseline( h );
233 //setMidline( h*.5 );
234 }
235}
236
237
239{
240 TQPtrListIterator<BasicElement> it( children );
241 for ( ; it.current(); ++it ) {
242 BasicElement* child = it.current();
243 child->setY(getBaseline() - child->getBaseline());
244 }
245}
246
247
253void SequenceElement::draw( TQPainter& painter, const LuPixelRect& r,
254 const ContextStyle& context,
256 ContextStyle::IndexStyle istyle,
257 StyleAttributes& style,
258 const LuPixelPoint& parentOrigin )
259{
260 LuPixelPoint myPos( parentOrigin.x() + getX(), parentOrigin.y() + getY() );
261 // There might be zero sized elements that still want to be drawn at least
262 // in edit mode. (EmptyElement)
263 //if ( !LuPixelRect( myPos.x(), myPos.y(), getWidth(), getHeight() ).intersects( r ) )
264 // return;
265
266 if (!isEmpty()) {
267 TQPtrListIterator<BasicElement> it( children );
268 for (int i = 0 ; it.current(); i++) {
269 BasicElement* child = it.current();
270 if (!child->isInvisible()) {
271 child->draw(painter, r, context, tstyle, istyle, style, myPos);
272
273 // Each starting element draws the whole token
274 // This only concerns TextElements.
275 /*
276 ElementType* token = child->getElementType();
277 if ( token != 0 ) {
278 it += token->end() - token->start();
279 }
280 else {
281 ++it;
282 }
283 */
284 }
285// else {
286 ++it;
287// }
288 }
289 }
290 else {
291 drawEmptyRect( painter, context, style.sizeFactor(), myPos );
292 }
293 // Debug
294 //painter.setPen(TQt::green);
295 //painter.drawRect(parentOrigin.x() + getX(), parentOrigin.y() + getY(),
296 // getWidth(), getHeight());
297// painter.drawLine( context.layoutUnitToPixelX( parentOrigin.x() + getX() ),
298// context.layoutUnitToPixelY( parentOrigin.y() + getY() + axis( context, tstyle ) ),
299// context.layoutUnitToPixelX( parentOrigin.x() + getX() + getWidth() ),
300// context.layoutUnitToPixelY( parentOrigin.y() + getY() + axis( context, tstyle ) ) );
301// painter.setPen(TQt::red);
302// painter.drawLine( context.layoutUnitToPixelX( parentOrigin.x() + getX() ),
303// context.layoutUnitToPixelY( parentOrigin.y() + getY() + getBaseline() ),
304// context.layoutUnitToPixelX( parentOrigin.x() + getX() + getWidth() ),
305// context.layoutUnitToPixelY( parentOrigin.y() + getY() + getBaseline() ) );
306}
307
308
310{
311 TQPtrListIterator<BasicElement> it( children );
312 for ( ; it.current(); ++it ) {
313 BasicElement* child = it.current();
314 child->dispatchFontCommand( cmd );
315 }
316}
317
318
319void SequenceElement::drawEmptyRect( TQPainter& painter, const ContextStyle& context,
320 double factor, const LuPixelPoint& upperLeft )
321{
322 if ( context.edit() ) {
323 painter.setBrush(TQt::NoBrush);
324 painter.setPen( TQPen( context.getEmptyColor(),
325 context.layoutUnitToPixelX( context.getLineWidth( factor ) ) ) );
326 painter.drawRect( context.layoutUnitToPixelX( upperLeft.x() ),
327 context.layoutUnitToPixelY( upperLeft.y() ),
328 context.layoutUnitToPixelX( getWidth() ),
329 context.layoutUnitToPixelY( getHeight() ) );
330 }
331}
332
333void SequenceElement::calcCursorSize( const ContextStyle& context,
334 FormulaCursor* cursor, bool smallCursor )
335{
336 LuPixelPoint point = widgetPos();
337 uint pos = cursor->getPos();
338
339 luPixel posX = getChildPosition( context, pos );
340 luPixel height = getHeight();
341
342 luPixel unitX = context.ptToLayoutUnitPixX( 1 );
343 luPixel unitY = context.ptToLayoutUnitPixY( 1 );
344
345 // Here are those evil constants that describe the cursor size.
346
347 if ( cursor->isSelection() ) {
348 uint mark = cursor->getMark();
349 luPixel markX = getChildPosition( context, mark );
350 luPixel x = TQMIN(posX, markX);
351 luPixel width = abs(posX - markX);
352
353 if ( smallCursor ) {
354 cursor->cursorSize.setRect( point.x()+x, point.y(), width, height );
355 }
356 else {
357 cursor->cursorSize.setRect( point.x()+x, point.y() - 2*unitY,
358 width + unitX, height + 4*unitY );
359 }
360 }
361 else {
362 if ( smallCursor ) {
363 cursor->cursorSize.setRect( point.x()+posX, point.y(),
364 unitX, height );
365 }
366 else {
367 cursor->cursorSize.setRect( point.x(), point.y() - 2*unitY,
368 getWidth() + unitX, height + 4*unitY );
369 }
370 }
371
372 cursor->cursorPoint.setX( point.x()+posX );
373 cursor->cursorPoint.setY( point.y()+getHeight()/2 );
374}
375
376
380void SequenceElement::drawCursor( TQPainter& painter, const ContextStyle& context,
381 StyleAttributes& style, FormulaCursor* cursor,
382 bool smallCursor, bool activeCursor )
383{
384 painter.setRasterOp( TQt::XorROP );
385 if ( cursor->isSelection() ) {
386 const LuPixelRect& r = cursor->cursorSize;
387 painter.fillRect( context.layoutUnitToPixelX( r.x() ),
388 context.layoutUnitToPixelY( r.y() ),
389 context.layoutUnitToPixelX( r.width() ),
390 context.layoutUnitToPixelY( r.height() ),
391 TQt::white );
392 }
393 painter.setPen( TQPen( TQt::white,
394 context.layoutUnitToPixelX( context.getLineWidth( style.sizeFactor() )/2 ) ) );
395 const LuPixelPoint& point = cursor->getCursorPoint();
396 const LuPixelRect& size = cursor->getCursorSize();
397 if ( activeCursor )
398 {
399 int offset = 0;
400 if ( cursor->isSelection() && cursor->getPos() > cursor->getMark() )
401 offset = -1;
402 painter.drawLine( context.layoutUnitToPixelX( point.x() ) + offset,
403 context.layoutUnitToPixelY( size.top() ),
404 context.layoutUnitToPixelX( point.x() ) + offset,
405 context.layoutUnitToPixelY( size.bottom() )-1 );
406 painter.drawLine( context.layoutUnitToPixelX( point.x() ) + offset + 1,
407 context.layoutUnitToPixelY( size.top() ),
408 context.layoutUnitToPixelX( point.x() ) + offset + 1,
409 context.layoutUnitToPixelY( size.bottom() )-1 );
410 }
411 if ( !smallCursor && !cursor->isSelection() )
412 painter.drawLine( context.layoutUnitToPixelX( size.left() ),
413 context.layoutUnitToPixelY( size.bottom() )-1,
414 context.layoutUnitToPixelX( size.right() )-1,
415 context.layoutUnitToPixelY( size.bottom() )-1 );
416 // This might be wrong but probably isn't.
417 painter.setRasterOp( TQt::CopyROP );
418}
419
420
421luPixel SequenceElement::getChildPosition( const ContextStyle& context, uint child )
422{
423 if (child < children.count()) {
424 return children.at(child)->getX();
425 }
426 else {
427 if (children.count() > 0) {
428 return children.at(child-1)->getX() + children.at(child-1)->getWidth();
429 }
430 else {
431 return context.ptToLayoutUnitPixX( 2 );
432 }
433 }
434}
435
436
437// navigation
438//
439// The elements are responsible to handle cursor movement themselves.
440// To do this they need to know the direction the cursor moves and
441// the element it comes from.
442//
443// The cursor might be in normal or in selection mode.
444
451{
452 // Our parent asks us for a cursor position. Found.
453 if (from == getParent()) {
454 cursor->setTo(this, children.count());
455 if ( cursor->isSelectionMode() ) {
456 cursor->setMark( children.count() );
457 }
458 from->entered( this );
459 }
460
461 // We already owned the cursor. Ask next child then.
462 else if (from == this) {
463 if (cursor->getPos() > 0) {
464 cursor->setTo(this, cursor->getPos()-1);
465
466 // invisible elements are not visible so we move on.
467 if (children.at(cursor->getPos())->isInvisible()) {
468 moveLeft(cursor, this);
469 }
470 }
471 else {
472 // Needed because FormulaElement derives this.
473 if (getParent() != 0) {
474 getParent()->moveLeft(cursor, this);
475 }
476 else {
477 formula()->moveOutLeft( cursor );
478 }
479 }
480 }
481
482 // The cursor came from one of our children or
483 // something is wrong.
484 else {
485 int fromPos = children.find(from);
486 if ( fromPos > 0 ) {
487 children.at( fromPos - 1)->moveLeft( cursor, this );
488 }
489
490 // invisible elements are not visible so we move on.
491 if (from->isInvisible()) {
492 moveLeft(cursor, this);
493 }
494 formula()->tell( "" );
495 }
496}
497
504{
505 // Our parent asks us for a cursor position. Found.
506 if (from == getParent()) {
507 cursor->setTo(this, 0);
508 from->entered( this );
509 }
510
511 // We already owned the cursor. Ask next child then.
512 else if (from == this) {
513 uint pos = cursor->getPos();
514 if (pos < children.count()) {
515 cursor->setTo(this, pos+1);
516
517 // invisible elements are not visible so we move on.
518 if (children.at(pos)->isInvisible()) {
519 moveRight(cursor, this);
520 }
521 }
522 else {
523 // Needed because FormulaElement derives this.
524 if (getParent() != 0) {
525 getParent()->moveRight(cursor, this);
526 }
527 else {
528 formula()->moveOutRight( cursor );
529 }
530 }
531 }
532
533 // The cursor came from one of our children or
534 // something is wrong.
535 else {
536 int fromPos = children.find(from);
537 if ( fromPos < children.count() - 1 ) {
538 children.at( fromPos + 1 )->moveDown( cursor, this );
539 }
540 else {
541 cursor->setTo(this, fromPos+1);
542 }
543 if (cursor->isSelectionMode()) {
544 cursor->setMark(fromPos);
545 }
546
547 // invisible elements are not visible so we move on.
548 if (from->isInvisible()) {
549 moveRight(cursor, this);
550 }
551 formula()->tell( "" );
552 }
553}
554
555
557{
558 uint pos = cursor->getPos();
559 if (pos > 0) {
560 ElementType* type = children.at(pos-1)->getElementType();
561 if (type != 0) {
562 cursor->setTo(this, type->start());
563 }
564 }
565 else {
566 moveLeft(cursor, this);
567 }
568}
569
570
572{
573 uint pos = cursor->getPos();
574 if (pos < children.count()) {
575 ElementType* type = children.at(pos)->getElementType();
576 if (type != 0) {
577 cursor->setTo(this, type->end());
578 }
579 }
580 else {
581 moveRight(cursor, this);
582 }
583}
584
585
592{
593 if (from == getParent()) {
594 moveRight(cursor, this);
595 }
596 else if ( from == this ) {
597 if ( getParent() != 0 ) {
598 uint pos = cursor->getPos();
599 if ( pos < (children.count() - 1) / 2 ) {
600 getParent()->moveLeft( cursor, this );
601 }
602 else {
603 getParent()->moveRight( cursor, this );
604 }
605 }
606 else {
607 formula()->moveOutAbove( cursor );
608 }
609 }
610 else {
611 if (getParent() != 0) {
612 getParent()->moveUp(cursor, this);
613 }
614 else {
615 formula()->moveOutAbove( cursor );
616 }
617 }
618}
619
626{
627 if (from == getParent()) {
628 cursor->setTo(this, 0);
629 from->entered( this );
630 }
631 else if (from == this) {
632 uint pos = cursor->getPos();
633 if (pos < children.count()) {
634 children.at(pos)->moveDown(cursor, this);
635 }
636 }
637 else {
638 if (getParent() != 0) {
639 getParent()->moveDown(cursor, this);
640 }
641 else {
642 cursor->setTo( this, children.count() );
643 from->entered( this );
644// formula()->moveOutBelow( cursor );
645 }
646 }
647}
648
654{
655 if (cursor->isSelectionMode()) {
656 BasicElement* element = cursor->getElement();
657 if (element != this) {
658 while (element->getParent() != this) {
659 element = element->getParent();
660 }
661 cursor->setMark(children.find(element)+1);
662 }
663 }
664 cursor->setTo(this, 0);
665}
666
672{
673 if (cursor->isSelectionMode()) {
674 BasicElement* element = cursor->getElement();
675 if (element != this) {
676 while (element->getParent() != this) {
677 element = element->getParent();
678 if (element == 0) {
679 cursor->setMark(children.count());
680 break;
681 }
682 }
683 if (element != 0) {
684 cursor->setMark(children.find(element));
685 }
686 }
687 }
688 cursor->setTo(this, children.count());
689}
690
696{
697 cursor->setSelection(false);
698 cursor->setTo(this, 0);
699}
700
706{
707 cursor->setSelection(false);
708 cursor->setTo(this, children.count());
709}
710
711
712// children
713
724bool SequenceElement::insert( uint index, BasicElement *child )
725{
726 return children.insert( index, child );
727}
728
736// void SequenceElement::removeChild(FormulaCursor* cursor, BasicElement* child)
737// {
738// int pos = children.find(child);
739// formula()->elementRemoval(child, pos);
740// cursor->setTo(this, pos);
741// children.remove(pos);
742// /*
743// if len(self.children) == 0:
744// if self.parent != None:
745// self.parent.removeChild(cursor, self)
746// return
747// */
748// formula()->changed();
749// }
750
751
760 TQPtrList<BasicElement>& newChildren,
761 Direction direction)
762{
763 int pos = cursor->getPos();
764 uint count = newChildren.count();
765 for (uint i = 0; i < count; i++) {
766 BasicElement* child = newChildren.take(0);
767 child->setParent(this);
768 children.insert(pos+i, child);
769 }
770 if (direction == beforeCursor) {
771 cursor->setTo(this, pos+count, pos);
772 }
773 else {
774 cursor->setTo(this, pos, pos+count);
775 }
776
777 formula()->changed();
778 parse();
779}
780
781
789 TQPtrList<BasicElement>& removedChildren,
790 Direction direction)
791{
792 if (cursor->isSelection()) {
793 int from = cursor->getSelectionStart();
794 int to = cursor->getSelectionEnd();
795 for (int i = from; i < to; i++) {
796 removeChild(removedChildren, from);
797 }
798 cursor->setTo(this, from);
799 cursor->setSelection(false);
800 }
801 else {
802 if (direction == beforeCursor) {
803 int pos = cursor->getPos() - 1;
804 if (pos >= 0) {
805 while (pos >= 0) {
806 BasicElement* child = children.at(pos);
807 formula()->elementRemoval(child);
808 children.take(pos);
809 removedChildren.prepend(child);
810 if (!child->isInvisible()) {
811 break;
812 }
813 pos--;
814 }
815 cursor->setTo(this, pos);
816 formula()->changed();
817 }
818 }
819 else {
820 uint pos = cursor->getPos();
821 if (pos < children.count()) {
822 while (pos < children.count()) {
823 BasicElement* child = children.at(pos);
824 formula()->elementRemoval(child);
825 children.take(pos);
826 removedChildren.append(child);
827 if (!child->isInvisible()) {
828 break;
829 }
830 }
831 // It is necessary to set the cursor to its old
832 // position because it got a notification and
833 // moved to the beginning of this sequence.
834 cursor->setTo(this, pos);
835 formula()->changed();
836 }
837 }
838 }
839 parse();
840}
841
842
846void SequenceElement::removeChild(TQPtrList<BasicElement>& removedChildren, int pos)
847{
848 BasicElement* child = children.at(pos);
849 formula()->elementRemoval(child);
850 children.take(pos);
851 removedChildren.append(child);
852 //cerr << *removedChildren.at(0) << endl;
853 formula()->changed();
854}
855
856
862{
863 cursor->setSelection(false);
864}
865
866
872{
873 if ( direction == beforeCursor ) {
874 if ( cursor->getPos() > 0 ) {
875 return children.at( cursor->getPos() - 1 );
876 }
877 }
878 else {
879 if ( cursor->getPos() < tqRound( children.count() ) ) {
880 return children.at( cursor->getPos() );
881 }
882 }
883 return 0;
884}
885
886
892{
893 int pos = children.find(child);
894 if (pos > -1) {
895 cursor->setTo(this, pos+1, pos);
896 }
897}
898
900{
901 int childPos = children.find(child);
902 if (childPos > -1) {
903 int pos = cursor->getPos();
904 if (pos > childPos) {
905 pos--;
906 }
907 int mark = cursor->getMark();
908 if (mark > childPos) {
909 mark--;
910 }
911 cursor->setTo(this, pos, mark);
912 }
913}
914
915
920{
921 cursor->setTo(this, children.count(), 0);
922}
923
924bool SequenceElement::onlyTextSelected( FormulaCursor* cursor )
925{
926 if ( cursor->isSelection() ) {
927 uint from = TQMIN( cursor->getPos(), cursor->getMark() );
928 uint to = TQMAX( cursor->getPos(), cursor->getMark() );
929 for ( uint i = from; i < to; i++ ) {
930 BasicElement* element = getChild( i );
931 if ( element->getCharacter() == TQChar::null ) {
932 return false;
933 }
934 }
935 }
936 return true;
937}
938
939
940KCommand* SequenceElement::buildCommand( Container* container, Request* request )
941{
942 FormulaCursor* cursor = container->activeCursor();
943 if ( cursor->isReadOnly() ) {
944 formula()->tell( i18n( "write protection" ) );
945 return 0;
946 }
947
948 switch ( *request ) {
949 case req_addText: {
950 KFCReplaceToken* command = new KFCReplaceToken( i18n("Add Text"), container );
951 TextRequest* tr = static_cast<TextRequest*>( request );
952 IdentifierElement* id = creationStrategy->createIdentifierElement();
953 command->addToken( id );
954 for ( uint i = 0; i < tr->text().length(); i++ ) {
955 TextElement* text = creationStrategy->createTextElement( tr->text()[i] );
956 command->addContent( id, text );
957 }
958 return command;
959 }
960 case req_addTextChar: {
961 KFCReplaceToken* command = new KFCReplaceToken( i18n("Add Text"), container );
962 TextCharRequest* tr = static_cast<TextCharRequest*>( request );
963 IdentifierElement* id = creationStrategy->createIdentifierElement();
964 TextElement* text = creationStrategy->createTextElement( tr->ch() );
965 command->addToken( id );
966 command->addContent( id, text );
967 return command;
968 }
969
970 case req_addOperator: {
971 KFCReplaceToken* command = new KFCReplaceToken( i18n("Add Operator"), container );
972 OperatorRequest* opr = static_cast<OperatorRequest*>( request );
973 OperatorElement* op = creationStrategy->createOperatorElement();
974 TextElement* text = creationStrategy->createTextElement( opr->ch() );
975 command->addToken( op );
976 command->addContent( op, text );
977 return command;
978 }
979
980 case req_addNumber: {
981 KFCReplaceToken* command = new KFCReplaceToken( i18n("Add Number"), container );
982 NumberRequest* nr = static_cast<NumberRequest*>( request );
983 NumberElement* num = creationStrategy->createNumberElement();
984 num->setParent( this );
985 TextElement* text = creationStrategy->createTextElement( nr->ch() );
986 text->setParent( num );
987 command->addToken( num );
988 command->addContent( num, text );
989 return command;
990 }
991
992 case req_addEmptyBox: {
993 EmptyElement* element = creationStrategy->createEmptyElement();
994 if ( element != 0 ) {
995 KFCReplace* command = new KFCReplace( i18n("Add Empty Box"), container );
996 command->addElement( element );
997 return command;
998 }
999 break;
1000 }
1001 case req_addNameSequence:
1002 if ( onlyTextSelected( container->activeCursor() ) ) {
1003 NameSequence* nameSequence = creationStrategy->createNameSequence();
1004 if ( nameSequence != 0 ) {
1005 KFCAddReplacing* command = new KFCAddReplacing( i18n( "Add Name" ), container );
1006 command->setElement( nameSequence );
1007 return command;
1008 }
1009 }
1010 break;
1011 case req_addBracket: {
1012 BracketRequest* br = static_cast<BracketRequest*>( request );
1013 BracketElement* bracketElement =
1014 creationStrategy->createBracketElement( br->left(), br->right() );
1015 if ( bracketElement != 0 ) {
1016 KFCAddReplacing* command = new KFCAddReplacing(i18n("Add Bracket"), container);
1017 command->setElement( bracketElement );
1018 return command;
1019 }
1020 break;
1021 }
1022 case req_addOverline: {
1023 OverlineElement* overline = creationStrategy->createOverlineElement();
1024 if ( overline != 0 ) {
1025 KFCAddReplacing* command = new KFCAddReplacing(i18n("Add Overline"), container);
1026 command->setElement( overline );
1027 return command;
1028 }
1029 break;
1030 }
1031 case req_addUnderline: {
1032 UnderlineElement* underline = creationStrategy->createUnderlineElement();
1033 if ( underline != 0 ) {
1034 KFCAddReplacing* command = new KFCAddReplacing(i18n("Add Underline"), container);
1035 command->setElement( underline );
1036 return command;
1037 }
1038 break;
1039 }
1040 case req_addMultiline: {
1041 MultilineElement* multiline = creationStrategy->createMultilineElement();
1042 if ( multiline != 0 ) {
1043 KFCAddReplacing* command = new KFCAddReplacing(i18n("Add Multiline"), container);
1044 command->setElement( multiline );
1045 return command;
1046 }
1047 break;
1048 }
1049 case req_addSpace: {
1050 SpaceRequest* sr = static_cast<SpaceRequest*>( request );
1051 SpaceElement* element = creationStrategy->createSpaceElement( sr->space() );
1052 if ( element != 0 ) {
1053 KFCReplace* command = new KFCReplace( i18n("Add Space"), container );
1054 command->addElement( element );
1055 return command;
1056 }
1057 break;
1058 }
1059 case req_addFraction: {
1060 FractionElement* fraction = creationStrategy->createFractionElement();
1061 if ( fraction != 0 ) {
1062 KFCAddReplacing* command = new KFCAddReplacing(i18n("Add Fraction"), container);
1063 command->setElement( fraction );
1064 return command;
1065 }
1066 break;
1067 }
1068 case req_addRoot: {
1069 RootElement* root = creationStrategy->createRootElement();
1070 if ( root != 0 ) {
1071 KFCAddReplacing* command = new KFCAddReplacing(i18n("Add Root"), container);
1072 command->setElement( root );
1073 return command;
1074 }
1075 break;
1076 }
1077 case req_addSymbol: {
1078 SymbolRequest* sr = static_cast<SymbolRequest*>( request );
1079 SymbolElement* symbol = creationStrategy->createSymbolElement( sr->type() );
1080 if ( symbol != 0 ) {
1081 KFCAddReplacing* command = new KFCAddReplacing( i18n( "Add Symbol" ), container );
1082 command->setElement( symbol );
1083 return command;
1084 }
1085 break;
1086 }
1087 case req_addOneByTwoMatrix: {
1088 FractionElement* element = creationStrategy->createFractionElement();
1089 if ( element != 0 ) {
1090 KFCAddReplacing* command = new KFCAddReplacing( i18n("Add 1x2 Matrix"), container );
1091 element->showLine(false);
1092 command->setElement(element);
1093 return command;
1094 }
1095 }
1096 case req_addMatrix: {
1097 MatrixRequest* mr = static_cast<MatrixRequest*>( request );
1098 uint rows = mr->rows(), cols = mr->columns();
1099 if ( ( rows == 0 ) || ( cols == 0 ) ) {
1100 MatrixDialog* dialog = new MatrixDialog( 0 );
1101 if ( dialog->exec() ) {
1102 rows = dialog->h;
1103 cols = dialog->w;
1104 }
1105 delete dialog;
1106 }
1107
1108 if ( ( rows != 0 ) && ( cols != 0 ) ) {
1109 KFCAddReplacing* command = new KFCAddReplacing( i18n( "Add Matrix" ), container );
1110 command->setElement( creationStrategy->createMatrixElement( rows, cols ) );
1111 return command;
1112 }
1113 else
1114 return 0L;
1115 }
1116 case req_addIndex: {
1117 if ( cursor->getPos() > 0 && !cursor->isSelection() ) {
1118 IndexElement* element =
1119 dynamic_cast<IndexElement*>( children.at( cursor->getPos()-1 ) );
1120 if ( element != 0 ) {
1121 element->goInside( cursor );
1122 return element->buildCommand( container, request );
1123 }
1124 }
1125 IndexElement* element = creationStrategy->createIndexElement();
1126 if ( element != 0 ) {
1127 if ( !cursor->isSelection() ) {
1128 cursor->moveLeft( SelectMovement | WordMovement );
1129 }
1130 IndexRequest* ir = static_cast<IndexRequest*>( request );
1131 KFCAddIndex* command = new KFCAddIndex( container, element,
1132 element->getIndex( ir->index() ) );
1133 return command;
1134 }
1135 break;
1136 }
1137 case req_removeEnclosing: {
1138 if ( !cursor->isSelection() ) {
1139 DirectedRemove* dr = static_cast<DirectedRemove*>( request );
1140 KFCRemoveEnclosing* command = new KFCRemoveEnclosing( container, dr->direction() );
1141 return command;
1142 }
1143 }
1144 case req_remove: {
1145 SequenceElement* sequence = cursor->normal();
1146 if ( sequence &&
1147 ( sequence == sequence->formula() ) &&
1148 ( sequence->countChildren() == 0 ) ) {
1149 sequence->formula()->removeFormula( cursor );
1150 return 0;
1151 }
1152 else {
1153 DirectedRemove* dr = static_cast<DirectedRemove*>( request );
1154
1155 // empty removes are not legal!
1156 if ( !cursor->isSelection() ) {
1157 if ( countChildren() > 0 ) {
1158 if ( ( cursor->getPos() == 0 ) && ( dr->direction() == beforeCursor ) ) {
1159 return 0;
1160 }
1161 if ( ( cursor->getPos() == countChildren() ) && ( dr->direction() == afterCursor ) ) {
1162 return 0;
1163 }
1164 }
1165 else if ( getParent() == 0 ) {
1166 return 0;
1167 }
1168 }
1169
1170 KFCRemove* command = new KFCRemove( container, dr->direction() );
1171 return command;
1172 }
1173 }
1174 case req_compactExpression: {
1175 cursor->moveEnd();
1176 cursor->moveRight();
1177 formula()->cursorHasMoved( cursor );
1178 break;
1179 }
1180 case req_makeGreek: {
1181 TextElement* element = cursor->getActiveTextElement();
1182 if ((element != 0) && !element->isSymbol()) {
1183 cursor->selectActiveElement();
1184 const SymbolTable& table = container->document()->getSymbolTable();
1185 if (table.greekLetters().find(element->getCharacter()) != -1) {
1186 KFCReplace* command = new KFCReplace( i18n( "Change Char to Symbol" ), container );
1187 TextElement* symbol = creationStrategy->createTextElement( table.unicodeFromSymbolFont( element->getCharacter() ), true );
1188 command->addElement( symbol );
1189 return command;
1190 }
1191 cursor->setSelection( false );
1192 }
1193 break;
1194 }
1195 case req_paste:
1196 case req_copy:
1197 case req_cut:
1198 break;
1199 case req_formatBold:
1200 case req_formatItalic: {
1201 if ( cursor->isSelection() ) {
1202 CharStyleRequest* csr = static_cast<CharStyleRequest*>( request );
1203 CharStyle cs = normalChar;
1204 if ( csr->bold() ) cs = static_cast<CharStyle>( cs | boldChar );
1205 if ( csr->italic() ) cs = static_cast<CharStyle>( cs | italicChar );
1206 CharStyleCommand* cmd = new CharStyleCommand( cs, i18n( "Change Char Style" ), container );
1207 int end = cursor->getSelectionEnd();
1208 for ( int i = cursor->getSelectionStart(); i<end; ++i ) {
1209 cmd->addElement( children.at( i ) );
1210 }
1211 return cmd;
1212 }
1213 break;
1214 }
1215 case req_formatFamily: {
1216 if ( cursor->isSelection() ) {
1217 CharFamilyRequest* cfr = static_cast<CharFamilyRequest*>( request );
1218 CharFamily cf = cfr->charFamily();
1219 CharFamilyCommand* cmd = new CharFamilyCommand( cf, i18n( "Change Char Family" ), container );
1220 int end = cursor->getSelectionEnd();
1221 for ( int i = cursor->getSelectionStart(); i<end; ++i ) {
1222 cmd->addElement( children.at( i ) );
1223 }
1224 return cmd;
1225 }
1226 break;
1227 }
1228 default:
1229 break;
1230 }
1231 return 0;
1232}
1233
1234
1235KCommand* SequenceElement::input( Container* container, TQKeyEvent* event )
1236{
1237 TQChar ch = event->text().at( 0 );
1238 if ( ch.isPrint() ) {
1239 return input( container, ch );
1240 }
1241 else {
1242 int action = event->key();
1243 int state = event->state();
1244 MoveFlag flag = movementFlag(state);
1245
1246 switch ( action ) {
1247 case TQt::Key_BackSpace: {
1248 DirectedRemove r( req_remove, beforeCursor );
1249 return buildCommand( container, &r );
1250 }
1251 case TQt::Key_Delete: {
1252 DirectedRemove r( req_remove, afterCursor );
1253 return buildCommand( container, &r );
1254 }
1255 case TQt::Key_Left: {
1256 FormulaCursor* cursor = container->activeCursor();
1257 cursor->moveLeft( flag );
1258 formula()->cursorHasMoved( cursor );
1259 break;
1260 }
1261 case TQt::Key_Right: {
1262 FormulaCursor* cursor = container->activeCursor();
1263 cursor->moveRight( flag );
1264 formula()->cursorHasMoved( cursor );
1265 break;
1266 }
1267 case TQt::Key_Up: {
1268 FormulaCursor* cursor = container->activeCursor();
1269 cursor->moveUp( flag );
1270 formula()->cursorHasMoved( cursor );
1271 break;
1272 }
1273 case TQt::Key_Down: {
1274 FormulaCursor* cursor = container->activeCursor();
1275 cursor->moveDown( flag );
1276 formula()->cursorHasMoved( cursor );
1277 break;
1278 }
1279 case TQt::Key_Home: {
1280 FormulaCursor* cursor = container->activeCursor();
1281 cursor->moveHome( flag );
1282 formula()->cursorHasMoved( cursor );
1283 break;
1284 }
1285 case TQt::Key_End: {
1286 FormulaCursor* cursor = container->activeCursor();
1287 cursor->moveEnd( flag );
1288 formula()->cursorHasMoved( cursor );
1289 break;
1290 }
1291 default:
1292 if ( state & TQt::ControlButton ) {
1293 switch ( event->key() ) {
1294 case TQt::Key_AsciiCircum: {
1295 IndexRequest r( upperLeftPos );
1296 return buildCommand( container, &r );
1297 }
1298 case TQt::Key_Underscore: {
1299 IndexRequest r( lowerLeftPos );
1300 return buildCommand( container, &r );
1301 }
1302 default:
1303 break;
1304 }
1305 }
1306 }
1307 }
1308 return 0;
1309}
1310
1311
1313{
1314 int unicode = ch.unicode();
1315 switch (unicode) {
1316 case '(': {
1317 BracketRequest r( container->document()->leftBracketChar(),
1318 container->document()->rightBracketChar() );
1319 singlePipe = true;
1320 return buildCommand( container, &r );
1321 }
1322 case '[': {
1323 BracketRequest r( LeftSquareBracket, RightSquareBracket );
1324 singlePipe = true;
1325 return buildCommand( container, &r );
1326 }
1327 case '{': {
1328 BracketRequest r( LeftCurlyBracket, RightCurlyBracket );
1329 singlePipe = true;
1330 return buildCommand( container, &r );
1331 }
1332 case '|': {
1333 if (!singlePipe) { // We have had 2 '|' in a row so we want brackets
1334
1335 DirectedRemove rDelete( req_remove, beforeCursor ); //Delete the previous '|' we dont need it any more
1336 KCommand* command = buildCommand( container, &rDelete );
1337 command->execute();
1338
1339 BracketRequest rBracket( LeftLineBracket , RightLineBracket);
1340 singlePipe = true; //the next '|' will be a single pipe again
1341 return buildCommand( container, &rBracket );
1342 }
1343 else { // We really do only want 1 '|'
1344 TextCharRequest r(ch);
1345
1346 //in case another '|' character is entered right after this one, '| |' brackets are made; see above
1347 singlePipe = false;
1348
1349 return buildCommand( container, &r );
1350 }
1351 }
1352 case '^': {
1353 IndexRequest r( upperRightPos );
1354 singlePipe = true;
1355 return buildCommand( container, &r );
1356 }
1357 case '_': {
1358 IndexRequest r( lowerRightPos );
1359 singlePipe = true;
1360 return buildCommand( container, &r );
1361 }
1362 /*
1363 case ' ': {
1364 Request r( req_compactExpression );
1365 singlePipe = true;
1366 return buildCommand( container, &r );
1367 }*/
1368 case '}': {
1369 Request r( req_addEmptyBox );
1370 singlePipe = true;
1371 return buildCommand( container, &r );
1372 }
1373 case ']':
1374 case ')':
1375 singlePipe = true;
1376 break;
1377 case '\\': {
1378 Request r( req_addNameSequence );
1379 singlePipe = true;
1380 return buildCommand( container, &r );
1381 }
1382 default: {
1383 singlePipe = true;
1384 if ( ch.isPunct() || ch.isSymbol() ) {
1385 OperatorRequest r( ch );
1386 return buildCommand( container, &r );
1387 }
1388 if ( ch.isNumber() ) {
1389 NumberRequest r( ch );
1390 return buildCommand( container, &r );
1391 }
1392 TextCharRequest r( ch );
1393 return buildCommand( container, &r );
1394 }
1395 }
1396 return 0;
1397}
1398
1402void SequenceElement::getChildrenDom( TQDomDocument& doc, TQDomElement elem,
1403 uint from, uint to)
1404{
1405 for (uint i = from; i < to; i++) {
1406 TQDomElement tmpEleDom=children.at(i)->getElementDom(doc);
1407 elem.appendChild(tmpEleDom);
1408 }
1409}
1410
1414void SequenceElement::getChildrenMathMLDom( TQDomDocument& doc, TQDomNode& parent,
1415 uint from, uint to)
1416{
1417 for ( uint i = from; i < to; i++ ) {
1418 children.at( i )->writeMathML( doc, parent, false );
1419 }
1420}
1421
1422
1428bool SequenceElement::buildChildrenFromDom(TQPtrList<BasicElement>& list, TQDomNode n)
1429{
1430 while (!n.isNull()) {
1431 if (n.isElement()) {
1432 TQDomElement e = n.toElement();
1433 BasicElement* child = 0;
1434 TQString tag = e.tagName().upper();
1435
1436 child = createElement(tag, e);
1437 if (child != 0) {
1438 child->setParent(this);
1439 if (child->buildFromDom(e)) {
1440 list.append(child);
1441 }
1442 else {
1443 delete child;
1444 return false;
1445 }
1446 }
1447 else {
1448 return false;
1449 }
1450 }
1451 n = n.nextSibling();
1452 }
1453 parse();
1454 return true;
1455}
1456
1457
1458BasicElement* SequenceElement::createElement( TQString type, const TQDomElement& element )
1459{
1460 return creationStrategy->createElement( type, element );
1461}
1462
1466void SequenceElement::writeDom(TQDomElement element)
1467{
1468 BasicElement::writeDom(element);
1469
1470 uint count = children.count();
1471 TQDomDocument doc = element.ownerDocument();
1472 getChildrenDom(doc, element, 0, count);
1473}
1474
1480{
1482 return false;
1483 }
1484 return true;
1485}
1486
1493{
1495 return false;
1496 }
1497
1498 return buildChildrenFromDom(children, node);
1499}
1500
1501
1503{
1504 delete parseTree;
1505
1506 textSequence = true;
1507 for (BasicElement* element = children.first();
1508 element != 0;
1509 element = children.next()) {
1510
1511 // Those types are gone. Make sure they won't
1512 // be used.
1513 element->setElementType(0);
1514
1515 if (element->getCharacter().isNull()) {
1516 textSequence = false;
1517 }
1518 }
1519
1520 const SymbolTable& symbols = formula()->getSymbolTable();
1521 SequenceParser parser(symbols);
1522 parseTree = parser.parse(children);
1523
1524 // With the IndexElement dynamically changing its text/non-text
1525 // behaviour we need to reparse your parent, too. Hacky!
1526 BasicElement* p = getParent();
1527 if ( p != 0 ) {
1528 SequenceElement* seq = dynamic_cast<SequenceElement*>( p->getParent() );
1529 if ( seq != 0 ) {
1530 seq->parse();
1531 }
1532 }
1533 // debug
1534 //parseTree->output();
1535}
1536
1537
1539{
1540 return ( child->getElementType() != 0 ) && isChildNumber( child->getElementType()->start(), child );
1541}
1542
1543
1545{
1546 TQString content;
1547 uint count = children.count();
1548 for ( uint i = 0; i < count; i++ ) {
1549 BasicElement* child = children.at( i );
1550// if ( isFirstOfToken( child ) ) {
1551// content += "";
1552// }
1553 content += child->toLatex();
1554 }
1555 return content;
1556}
1557
1558
1559TQString SequenceElement::formulaString()
1560{
1561 TQString content;
1562 uint count = children.count();
1563 for ( uint i = 0; i < count; i++ ) {
1564 BasicElement* child = children.at( i );
1565 //if ( isFirstOfToken( child ) ) {
1566 // content += " ";
1567 //}
1568 content += child->formulaString();
1569 }
1570 return content;
1571}
1572
1573
1574void SequenceElement::writeMathMLContent( TQDomDocument& doc, TQDomElement& element, bool oasisFormat ) const
1575{
1576 for ( TQPtrListIterator<BasicElement> it( children ); it.current(); ++it ) {
1577 it.current()->writeMathML( doc, element, oasisFormat );
1578 }
1579}
1580
1581
1582const BasicElement* SequenceElement::getChild( uint i ) const
1583{
1584 TQPtrListIterator<BasicElement> it( children );
1585 it += i;
1586 return it.current();
1587}
1588
1589
1590int SequenceElement::childPos( const BasicElement* child ) const
1591{
1592 TQPtrListIterator<BasicElement> it( children );
1593 uint count = it.count();
1594 for ( uint i=0; i<count; ++i, ++it ) {
1595 if ( it.current() == child ) {
1596 return i;
1597 }
1598 }
1599 return -1;
1600}
1601
1602
1603NameSequence::NameSequence( BasicElement* parent )
1604 : SequenceElement( parent )
1605{
1606}
1607
1608
1610{
1611 return visitor->visit( this );
1612}
1613
1614
1615void NameSequence::calcCursorSize( const ContextStyle& context,
1616 FormulaCursor* cursor, bool smallCursor )
1617{
1618 inherited::calcCursorSize( context, cursor, smallCursor );
1619 LuPixelPoint point = widgetPos();
1620 luPixel unitX = context.ptToLayoutUnitPixX( 1 );
1621 luPixel unitY = context.ptToLayoutUnitPixY( 1 );
1622 cursor->addCursorSize( LuPixelRect( point.x()-unitX, point.y()-unitY,
1623 getWidth()+2*unitX, getHeight()+2*unitY ) );
1624}
1625
1626void NameSequence::drawCursor( TQPainter& painter, const ContextStyle& context,
1627 StyleAttributes& style, FormulaCursor* cursor,
1628 bool smallCursor, bool activeCursor )
1629{
1630 LuPixelPoint point = widgetPos();
1631 painter.setPen( TQPen( context.getEmptyColor(),
1632 context.layoutUnitToPixelX( context.getLineWidth( style.sizeFactor() )/2 ) ) );
1633 luPixel unitX = context.ptToLayoutUnitPixX( 1 );
1634 luPixel unitY = context.ptToLayoutUnitPixY( 1 );
1635 painter.drawRect( context.layoutUnitToPixelX( point.x()-unitX ),
1636 context.layoutUnitToPixelY( point.y()-unitY ),
1637 context.layoutUnitToPixelX( getWidth()+2*unitX ),
1638 context.layoutUnitToPixelY( getHeight()+2*unitY ) );
1639
1640 inherited::drawCursor( painter, context, style, cursor, smallCursor, activeCursor );
1641}
1642
1644{
1645 uint pos = cursor->getPos();
1646 if ( pos > 0 ) {
1647 cursor->setTo( this, 0 );
1648 }
1649 else {
1650 moveLeft( cursor, this );
1651 }
1652}
1653
1655{
1656 int pos = cursor->getPos();
1657 if ( pos < countChildren() ) {
1658 cursor->setTo( this, countChildren() );
1659 }
1660 else {
1661 moveRight( cursor, this );
1662 }
1663}
1664
1665
1666KCommand* NameSequence::compactExpressionCmd( Container* container )
1667{
1668 BasicElement* element = replaceElement( container->document()->getSymbolTable() );
1669 if ( element != 0 ) {
1670 getParent()->selectChild( container->activeCursor(), this );
1671
1672 KFCReplace* command = new KFCReplace( i18n( "Add Element" ), container );
1673 command->addElement( element );
1674 return command;
1675 }
1676 return 0;
1677}
1678
1679KCommand* NameSequence::buildCommand( Container* container, Request* request )
1680{
1681 switch ( *request ) {
1682 case req_compactExpression:
1683 return compactExpressionCmd( container );
1684 case req_addSpace:
1685 case req_addIndex:
1686 case req_addMatrix:
1687 case req_addOneByTwoMatrix:
1688 case req_addSymbol:
1689 case req_addRoot:
1690 case req_addFraction:
1691 case req_addBracket:
1692 case req_addNameSequence:
1693 return 0;
1694 default:
1695 break;
1696 }
1697 return inherited::buildCommand( container, request );
1698}
1699
1700
1701KCommand* NameSequence::input( Container* container, TQChar ch )
1702{
1703 int unicode = ch.unicode();
1704 switch (unicode) {
1705 case '(':
1706 case '[':
1707 case '|':
1708 case '^':
1709 case '_':
1710 case '}':
1711 case ']':
1712 case ')':
1713 case '\\': {
1714// KCommand* compact = compactExpressionCmd( container );
1715// KCommand* cmd = static_cast<SequenceElement*>( getParent() )->input( container, ch );
1716// if ( compact != 0 ) {
1717// KMacroCommand* macro = new KMacroCommand( cmd->name() );
1718// macro->addCommand( compact );
1719// macro->addCommand( cmd );
1720// return macro;
1721// }
1722// else {
1723// return cmd;
1724// }
1725 break;
1726 }
1727 case '{':
1728 case ' ': {
1729 Request r( req_compactExpression );
1730 return buildCommand( container, &r );
1731 }
1732 default: {
1733 TextCharRequest r( ch );
1734 return buildCommand( container, &r );
1735 }
1736 }
1737 return 0;
1738}
1739
1745
1747{
1748 TQString name = buildName();
1749 TQChar ch = table.unicode( name );
1750 if ( !ch.isNull() ) {
1751 return new TextElement( ch, true );
1752 }
1753 else {
1754 ch = table.unicode( i18n( name.latin1() ) );
1755 if ( !ch.isNull() ) {
1756 return new TextElement( ch, true );
1757 }
1758 }
1759
1760 if ( name == "!" ) return new SpaceElement( NEGTHIN );
1761 if ( name == "," ) return new SpaceElement( THIN );
1762 if ( name == ">" ) return new SpaceElement( MEDIUM );
1763 if ( name == ";" ) return new SpaceElement( THICK );
1764 if ( name == "quad" ) return new SpaceElement( QUAD );
1765
1766 if ( name == "frac" ) return new FractionElement();
1767 if ( name == "atop" ) {
1768 FractionElement* frac = new FractionElement();
1769 frac->showLine( false );
1770 return frac;
1771 }
1772 if ( name == "sqrt" ) return new RootElement();
1773
1774 return 0;
1775}
1776
1778{
1779 if ( type == "TEXT" ) return new TextElement();
1780 return 0;
1781}
1782
1783// void NameSequence::parse()
1784// {
1785// // A name sequence is known as name and so are its children.
1786// // Caution: this is fake!
1787// for ( int i = 0; i < countChildren(); i++ ) {
1788// getChild( i )->setElementType( getElementType() );
1789// }
1790// }
1791
1792TQString NameSequence::buildName()
1793{
1794 TQString name;
1795 for ( uint i = 0; i < countChildren(); i++ ) {
1796 name += getChild( i )->getCharacter();
1797 }
1798 return name;
1799}
1800
1802{
1803 SequenceElement* sequence = cursor->normal();
1804 if ( sequence == 0 ) {
1805 return false;
1806 }
1807 return sequence->onlyTextSelected( cursor );
1808}
1809
1810int SequenceElement::buildChildrenFromMathMLDom(TQPtrList<BasicElement>& list, TQDomNode n)
1811{
1812 while (!n.isNull()) {
1813 int nodeNumber = 1;
1814 if (n.isElement()) {
1815 TQDomElement e = n.toElement();
1816 BasicElement* child = 0;
1817 TQString tag = e.tagName().lower();
1818
1819 kdDebug( DEBUGID ) << "Sequence Tag: " << tag << endl;
1820 if ( tag == "semantics" ) { // Special case, just pick the first child
1821 TQDomNode node = e.firstChild();
1822 while( ! node.isElement() ) {
1823 node = node.nextSibling();
1824 if ( node.isNull() ) {
1825 return -1;
1826 }
1827 }
1828 e = node.toElement();
1829 tag = e.tagName().lower();
1830 }
1831 child = creationStrategy->createElement(tag, e);
1832 if (child != 0) {
1833 child->setParent(this);
1834 if (style != 0) {
1835 child->setStyle(style);
1836 }
1837 nodeNumber = child->buildFromMathMLDom( e );
1838 if ( nodeNumber != -1 ) {
1839 list.append(child);
1840 }
1841 else {
1842 delete child;
1843 return -1;
1844 }
1845 }
1846 else {
1847 kdWarning() << "Unsupported MathML element: " << tag << endl;
1848 }
1849 }
1850 for (int i = 0; i < nodeNumber; i++ ) {
1851 if ( n.isNull() ) {
1852 return -1;
1853 }
1854 n = n.nextSibling();
1855 }
1856 }
1857 // Operator elements inside a sequence have to be parsed to get proper form
1858 // value. Form value is needed to access operator dictionary and has to be
1859 // obtained after sequence parsing since its value depends on position
1860 // inside the sequence.
1861
1862 // If the sequence contains more than one element, if the first or last
1863 // element are operators, they have to be marked differently
1864 if ( list.count() > 1 ) {
1865 if ( list.getFirst()->getElementName() == "mo" ) {
1866 static_cast<OperatorElement*>( list.getFirst() )->setForm( PrefixForm );
1867 }
1868 if ( list.getLast()->getElementName() == "mo" ) {
1869 static_cast<OperatorElement*>( list.getLast() )->setForm( PostfixForm );
1870 }
1871 for ( uint i = 1; i < list.count() - 1; i++ ) {
1872 if ( list.at( i )->getElementName() == "mo" ) {
1873 static_cast<OperatorElement*>( list.at( i ) )->setForm( InfixForm );
1874 }
1875 }
1876 }
1877 else if ( list.count() == 1 ) {
1878 if ( list.getFirst()->getElementName() == "mo" ) {
1879 static_cast<OperatorElement*>( list.getFirst() )->setForm( InfixForm );
1880 }
1881 }
1882 parse();
1883 return 1;
1884}
1885
1889{
1890 if ( BasicElement::readContentFromMathMLDom(node) == -1 ) {
1891 return -1;
1892 }
1893
1894 return buildChildrenFromMathMLDom(children, node);
1895}
1896
1897int SequenceElement::buildMathMLChild( TQDomNode node )
1898{
1899 int nodeCounter = 1;
1900 while ( ! node.isElement() ) {
1901 node = node.nextSibling();
1902 nodeCounter++;
1903 if ( node.isNull() ) {
1904 return -1;
1905 }
1906 }
1907 TQDomElement e = node.toElement();
1908 BasicElement* child = 0;
1909 TQString tag = e.tagName().lower();
1910
1911 child = creationStrategy->createElement(tag, e);
1912 if (child != 0) {
1913 child->setParent(this);
1914 if (style != 0) {
1915 child->setStyle(style);
1916 }
1917 if (child->buildFromMathMLDom(e) != -1) {
1918 children.append(child);
1919 }
1920 else {
1921 delete child;
1922 return -1;
1923 }
1924 }
1925 else {
1926 return -1;
1927 }
1928 parse();
1929 return nodeCounter;
1930}
1931
1932
1933
1934KFORMULA_NAMESPACE_END
Basis of every formula element.
LuPixelPoint widgetPos()
Returns our position inside the widget.
virtual FormulaElement * formula()
Provide fast access to the rootElement for each child.
virtual void draw(TQPainter &painter, const LuPixelRect &r, const ContextStyle &context, ContextStyle::TextStyle tstyle, ContextStyle::IndexStyle istyle, StyleAttributes &style, const LuPixelPoint &parentOrigin)=0
Draws the whole element including its children.
virtual bool readContentFromDom(TQDomNode &node)
Reads our content from the node.
virtual bool isInvisible() const
virtual void entered(SequenceElement *)
The cursor has entered one of our child sequences.
virtual int readContentFromMathMLDom(TQDomNode &node)
Reads our content from the MathML node.
virtual void moveUp(FormulaCursor *, BasicElement *)
Enters this element while moving up starting inside the element ‘from’.
int buildFromMathMLDom(TQDomElement element)
Set this element attribute, build children and call their builFromMathMLDom.
virtual bool readOnly(const BasicElement *child) const
virtual TQString toLatex()
virtual void selectChild(FormulaCursor *, BasicElement *)
Sets the cursor to select the child.
virtual void goInside(FormulaCursor *cursor)
Sets the cursor inside this element to its start position.
bool buildFromDom(TQDomElement element)
Set this element attribute, build children and call their buildFromDom.
virtual void calcSizes(const ContextStyle &context, ContextStyle::TextStyle tstyle, ContextStyle::IndexStyle istyle, StyleAttributes &style)=0
Calculates our width and height and our children's parentPosition.
ElementType * getElementType() const
virtual TQChar getCharacter() const
virtual void setElementType(ElementType *t)
Sets a new type.
virtual bool readAttributesFromDom(TQDomElement element)
Reads our attributes from the element.
virtual BasicElement * goToPos(FormulaCursor *, bool &handled, const LuPixelPoint &point, const LuPixelPoint &parentOrigin)
Sets the cursor and returns the element the point is in.
virtual void dispatchFontCommand(FontCommand *)
Dispatch this FontCommand to all our TextElement children.
virtual KCommand * buildCommand(Container *, Request *)
This is called by the container to get a command depending on the current cursor position (this is ho...
virtual void writeDom(TQDomElement element)
Appends our attributes to the dom element.
virtual void moveRight(FormulaCursor *cursor, BasicElement *from)
Enters this element while moving to the right starting inside the element ‘from’.
virtual void moveLeft(FormulaCursor *cursor, BasicElement *from)
Enters this element while moving to the left starting inside the element ‘from’.
virtual void moveDown(FormulaCursor *, BasicElement *)
Enters this element while moving down starting inside the element ‘from’.
A left and/or right bracket around one child.
Changes the char family of a number of elements an their children.
Changes the char style of a number of elements an their children.
The document.
virtual Document * document() const
FormulaCursor * activeCursor()
Contains all the style information for the formela.
TextStyle
Textstyles like in TeX.
luPixel getLineWidth(double factor) const
All simple lines like the one that makes up a fraction.
const SymbolTable & getSymbolTable() const
An object of this type needs to be known by the SequenceElement.
virtual TextElement * createTextElement(const TQChar &ch, bool symbol=false)=0
there must always be a TextElement, so this can never return 0
virtual MatrixElement * createMatrixElement(uint rows, uint columns)=0
when this gets called the user has seen the matrix dialog and expects a matrix!
Basis of all types.
Definition elementtype.h:52
uint start() const
Definition elementtype.h:71
An element that represents an empty box.
Base for all font commands that act on the current selection.
void addElement(BasicElement *element)
Collects all parent elements those children are to be changend.
The selection.
bool isSelection() const
Returns wether there actually is a selection.
const LuPixelPoint & getCursorPoint() const
SequenceElement * normal()
Returns the sequence the cursor is in if we are normal.
void selectActiveElement()
Selects the element the cursor points to (stands after) if there is such an element and if there is n...
void setSelection(bool selection)
Sets the selection mode.
bool isSelectionMode() const
Returns wether we are in selection mode.
const LuPixelRect & getCursorSize() const
void setTo(BasicElement *element, uint cursor, int mark=-1)
Sets the cursor to a new position.
BasicElement * getElement()
The element we are in.
TextElement * getActiveTextElement()
bool isReadOnly() const
void elementRemoval(BasicElement *child)
Gets called just before the child is removed from the element tree.
void tell(const TQString &msg)
Tell the user something has happened.
void cursorHasMoved(FormulaCursor *)
Gets called when a request has the side effect of moving the cursor.
virtual void changed()
Gets called whenever something changes and we need to recalc.
const SymbolTable & getSymbolTable() const
void removeFormula(FormulaCursor *)
Gets called when the formula wants to vanish.
void showLine(bool line)
Moves the cursor away from the given child.
The element with up to four indexes in the four corners.
ElementIndexPtr getIndex(int position)
Returns the index at the position.
virtual void execute()=0
Add an IndexElement.
The command that takes the main child out of the selected element and replaces the element with it.
void addContent(BasicElement *element, BasicElement *content)
Collect content for each token.
void addToken(BasicElement *element)
Collect all tokens that are to be added.
void addElement(BasicElement *element)
Collects all elements that are to be added.
Command to remove the parent element.
Command that is used to remove the currently selected element.
Removes the current selection and adds any new tokens afterwards.
Removes the current selection and adds any new elements afterwards.
int ptToPixelX(double pt) const
Basic pt to pixel and pixel to pt conversions, valid at any zoom level, as well as at the Layout Unit...
int ptToLayoutUnitPixX(double x_pt) const
The "document pt" -> "Layout Unit pixels" conversions, for convenience.
int layoutUnitToPixelX(int lupix) const
The "layout unit pixel" -> "[zoomed] view pixel" conversions.
Dialog for entering matrix sizes.
Any number of lines.
The sequence thats a name.
BasicElement * replaceElement(const SymbolTable &table)
virtual void drawCursor(TQPainter &painter, const ContextStyle &context, StyleAttributes &style, FormulaCursor *cursor, bool smallCursor, bool activeCursor)
If the cursor is inside a sequence it needs to be drawn.
static bool isValidSelection(FormulaCursor *cursor)
Tests whether the selected elements can be inserted in a name sequence.
virtual void moveWordRight(FormulaCursor *cursor)
Moves to the end of this word or if we are there already to the end of the next.
virtual KCommand * buildCommand(Container *, Request *)
This is called by the container to get a command depending on the current cursor position (this is ho...
virtual BasicElement * createElement(TQString type)
Creates a new element with the given type.
virtual void moveWordLeft(FormulaCursor *cursor)
Moves to the beginning of this word or if we are there already to the beginning of the previous.
virtual void setElementType(ElementType *t)
Sets a new type.
virtual KCommand * input(Container *container, TQChar ch)
Parses the input.
virtual bool accept(ElementVisitor *visitor)
Visit this element.
A line above the content.
A nice graphical root.
Definition rootelement.h:35
The element that contains a number of children.
virtual void goInsideLast(FormulaCursor *cursor)
Sets the cursor inside this element to its last position.
virtual KCommand * input(Container *container, TQChar ch)
Parses the input.
uint countChildren() const
virtual TQString toLatex()
void selectAllChildren(FormulaCursor *cursor)
Selects all children.
void getChildrenMathMLDom(TQDomDocument &doc, TQDomNode &elem, uint from, uint to)
Stores the given childrens MathML dom in the element.
virtual void moveEnd(FormulaCursor *cursor)
Moves the cursor to the last position in this sequence.
virtual KCommand * buildCommand(Container *, Request *)
This is called by the container to get a command depending on the current cursor position (this is ho...
virtual void moveWordLeft(FormulaCursor *cursor)
Moves to the beginning of this word or if we are there already to the beginning of the previous.
virtual void remove(FormulaCursor *, TQPtrList< BasicElement > &, Direction)
Removes all selected children and returns them.
virtual bool readAttributesFromDom(TQDomElement element)
Reads our attributes from the element.
void getChildrenDom(TQDomDocument &doc, TQDomElement elem, uint from, uint to)
Stores the given childrens dom in the element.
virtual BasicElement * getChild(FormulaCursor *, Direction=beforeCursor)
Returns the child at the cursor.
virtual bool isFirstOfToken(BasicElement *child)
virtual void moveDown(FormulaCursor *cursor, BasicElement *from)
Enters this element while moving down starting inside the element ‘from’.
virtual void drawCursor(TQPainter &painter, const ContextStyle &context, StyleAttributes &style, FormulaCursor *cursor, bool smallCursor, bool activeCursor)
If the cursor is inside a sequence it needs to be drawn.
virtual void parse()
Parses the sequence and generates a new syntax tree.
virtual void moveRight(FormulaCursor *cursor, BasicElement *from)
Enters this element while moving to the right starting inside the element ‘from’.
virtual void moveWordRight(FormulaCursor *cursor)
Moves to the end of this word or if we are there already to the end of the next.
luPixel getChildPosition(const ContextStyle &context, uint child)
virtual void goInside(FormulaCursor *cursor)
Sets the cursor inside this element to its start position.
virtual void dispatchFontCommand(FontCommand *cmd)
Dispatch this FontCommand to all our TextElement children.
virtual luPt getSpaceBefore(const ContextStyle &, ContextStyle::TextStyle, double)
Space around sequence.
virtual void childWillVanish(FormulaCursor *cursor, BasicElement *child)
Moves the cursor away from the given child.
virtual void calcSizes(const ContextStyle &cstyle, ContextStyle::TextStyle tstyle, ContextStyle::IndexStyle istyle, StyleAttributes &style)
Calculates our width and height and our children's parentPosition.
virtual void writeDom(TQDomElement element)
Appends our attributes to the dom element.
virtual bool accept(ElementVisitor *visitor)
Visit this element.
virtual void selectChild(FormulaCursor *cursor, BasicElement *child)
Sets the cursor to select the child.
bool isChildNumber(uint pos, BasicElement *child)
virtual bool readContentFromDom(TQDomNode &node)
Reads our content from the node.
virtual void setChildrenPositions()
Sets the childrens' positions after their size has been calculated.
virtual bool readOnly(const FormulaCursor *) const
bool buildChildrenFromDom(TQPtrList< BasicElement > &list, TQDomNode n)
Builds elements from the given node and its siblings and puts them into the list.
virtual void moveUp(FormulaCursor *cursor, BasicElement *from)
Enters this element while moving up starting inside the element ‘from’.
virtual void moveLeft(FormulaCursor *cursor, BasicElement *from)
Enters this element while moving to the left starting inside the element ‘from’.
virtual BasicElement * goToPos(FormulaCursor *, bool &handled, const LuPixelPoint &point, const LuPixelPoint &parentOrigin)
Sets the cursor and returns the element the point is in.
virtual void insert(FormulaCursor *, TQPtrList< BasicElement > &, Direction)
Inserts all new children at the cursor position.
virtual int readContentFromMathMLDom(TQDomNode &node)
Reads our content from the MathML node.
virtual BasicElement * createElement(TQString type, const TQDomElement &element)
Creates a new element with the given type.
virtual void normalize(FormulaCursor *, Direction)
Moves the cursor to a normal place where new elements might be inserted.
virtual void draw(TQPainter &painter, const LuPixelRect &r, const ContextStyle &context, ContextStyle::TextStyle tstyle, ContextStyle::IndexStyle istyle, StyleAttributes &style, const LuPixelPoint &parentOrigin)
Draws the whole element including its children.
virtual void moveHome(FormulaCursor *cursor)
Moves the cursor to the first position in this sequence.
The parser that gets the element list and returns a syntax tree.
ElementType * parse(TQPtrList< BasicElement > &elements)
A element that represents a space.
A symbol is simply a piece of art.
The symbol table.
Definition symboltable.h:77
TQChar unicodeFromSymbolFont(TQChar pos) const
TQString greekLetters() const
TQChar unicode(TQString name) const
An element that represents one char.
Definition textelement.h:37
virtual TQChar getCharacter() const
Definition textelement.h:65
bool isSymbol() const
Moves the cursor away from the given child.
A line below the content.
const char * name(StdAction id)