indexelement.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 <tqpainter.h>
22
23#include <kdebug.h>
24#include <tdelocale.h>
25
26#include "elementvisitor.h"
27#include "indexelement.h"
28#include "formulacursor.h"
29#include "formulaelement.h"
30#include "kformulacommand.h"
31#include "sequenceelement.h"
32
33
34KFORMULA_NAMESPACE_BEGIN
35
36
37class IndexSequenceElement : public SequenceElement {
38 typedef SequenceElement inherited;
39public:
40
41 IndexSequenceElement( BasicElement* parent = 0 ) : SequenceElement( parent ) {}
42 virtual IndexSequenceElement* clone() {
43 return new IndexSequenceElement( *this );
44 }
45
54 virtual KCommand* buildCommand( Container*, Request* );
55};
56
57
58KCommand* IndexSequenceElement::buildCommand( Container* container, Request* request )
59{
60 FormulaCursor* cursor = container->activeCursor();
61 if ( cursor->isReadOnly() ) {
62 return 0;
63 }
64
65 switch ( *request ) {
66 case req_addIndex: {
67 FormulaCursor* cursor = container->activeCursor();
68 if ( cursor->isSelection() ||
69 ( cursor->getPos() > 0 && cursor->getPos() < countChildren() ) ) {
70 break;
71 }
72 IndexElement* element = static_cast<IndexElement*>( getParent() );
73 IndexRequest* ir = static_cast<IndexRequest*>( request );
74 ElementIndexPtr index = element->getIndex( ir->index() );
75 if ( !index->hasIndex() ) {
76 KFCAddGenericIndex* command = new KFCAddGenericIndex( container, index );
77 return command;
78 }
79 else {
80 index->moveToIndex( cursor, afterCursor );
81 cursor->setSelection( false );
82 formula()->cursorHasMoved( cursor );
83 return 0;
84 }
85 }
86 default:
87 break;
88 }
89 return inherited::buildCommand( container, request );
90}
91
92
93IndexElement::IndexElement(BasicElement* parent)
94 : BasicElement(parent),
95 m_subScriptShiftType( NoSize ),
96 m_superScriptShiftType( NoSize ),
97 m_customAccentUnder( false ),
98 m_customAccent ( false )
99{
100 content = new IndexSequenceElement( this );
101
102 upperLeft = 0;
103 upperMiddle = 0;
104 upperRight = 0;
105 lowerLeft = 0;
106 lowerMiddle = 0;
107 lowerRight = 0;
108}
109
110IndexElement::~IndexElement()
111{
112 delete content;
113 delete upperLeft;
114 delete upperMiddle;
115 delete upperRight;
116 delete lowerLeft;
117 delete lowerMiddle;
118 delete lowerRight;
119}
120
121
122IndexElement::IndexElement( const IndexElement& other )
123 : BasicElement( other ),
124 m_subScriptShiftType( other.m_subScriptShiftType ),
125 m_subScriptShift( other.m_subScriptShift ),
126 m_superScriptShiftType( other.m_superScriptShiftType ),
127 m_superScriptShift( other.m_superScriptShift ),
128 m_customAccentUnder( other.m_customAccentUnder ),
129 m_accentUnder( other.m_accentUnder ),
130 m_customAccent ( other.m_customAccent ),
131 m_accent( other.m_accent )
132{
133 content = new IndexSequenceElement( *dynamic_cast<IndexSequenceElement*>( other.content ) );
134
135 if ( other.upperLeft ) {
136 upperLeft = new SequenceElement( *( other.upperLeft ) );
137 upperLeft->setParent( this );
138 }
139 else {
140 upperLeft = 0;
141 }
142 if ( other.upperMiddle ) {
143 upperMiddle = new SequenceElement( *( other.upperMiddle ) );
144 upperMiddle->setParent( this );
145 }
146 else {
147 upperMiddle = 0;
148 }
149 if ( other.upperRight ) {
150 upperRight = new SequenceElement( *( other.upperRight ) );
151 upperRight->setParent( this );
152 }
153 else {
154 upperRight = 0;
155 }
156
157 if ( other.lowerLeft ) {
158 lowerLeft = new SequenceElement( *( other.lowerLeft ) );
159 lowerLeft->setParent( this );
160 }
161 else {
162 lowerLeft = 0;
163 }
164 if ( other.lowerMiddle ) {
165 lowerMiddle = new SequenceElement( *( other.lowerMiddle ) );
166 lowerMiddle->setParent( this );
167 }
168 else {
169 lowerMiddle = 0;
170 }
171 if ( other.lowerRight ) {
172 lowerRight = new SequenceElement( *( other.lowerRight ) );
173 lowerRight->setParent( this );
174 }
175 else {
176 lowerRight = 0;
177 }
178}
179
180
182{
183 return visitor->visit( this );
184}
185
186
188{
189 if ( !content->isTextOnly() ) {
190 return TQChar::null;
191 }
192
193 if ( hasUpperRight() && !upperRight->isTextOnly() ) {
194 return TQChar::null;
195 }
196 if ( hasUpperMiddle() && !upperMiddle->isTextOnly() ) {
197 return TQChar::null;
198 }
199 if ( hasUpperLeft() && !upperLeft->isTextOnly() ) {
200 return TQChar::null;
201 }
202 if ( hasLowerRight() && !lowerRight->isTextOnly() ) {
203 return TQChar::null;
204 }
205 if ( hasLowerMiddle() && !lowerMiddle->isTextOnly() ) {
206 return TQChar::null;
207 }
208 if ( hasLowerLeft() && !lowerLeft->isTextOnly() ) {
209 return TQChar::null;
210 }
211
212 return ' ';
213}
214
216{
217 if ( child == content ) {
218 formula()->tell( i18n( "Indexed list" ) );
219 }
220 else {
221 formula()->tell( i18n( "Index" ) );
222 }
223}
224
225
230 const LuPixelPoint& point, const LuPixelPoint& parentOrigin )
231{
232 BasicElement* e = BasicElement::goToPos(cursor, handled, point, parentOrigin);
233 if (e != 0) {
234 LuPixelPoint myPos(parentOrigin.x()+getX(), parentOrigin.y()+getY());
235 e = content->goToPos(cursor, handled, point, myPos);
236 if (e != 0) return e;
237
238 if (hasUpperRight()) {
239 e = upperRight->goToPos(cursor, handled, point, myPos);
240 if (e != 0) return e;
241 }
242 if (hasUpperMiddle()) {
243 e = upperMiddle->goToPos(cursor, handled, point, myPos);
244 if (e != 0) return e;
245 }
246 if (hasUpperLeft()) {
247 e = upperLeft->goToPos(cursor, handled, point, myPos);
248 if (e != 0) return e;
249 }
250 if (hasLowerRight()) {
251 e = lowerRight->goToPos(cursor, handled, point, myPos);
252 if (e != 0) return e;
253 }
254 if (hasLowerMiddle()) {
255 e = lowerMiddle->goToPos(cursor, handled, point, myPos);
256 if (e != 0) return e;
257 }
258 if (hasLowerLeft()) {
259 e = lowerLeft->goToPos(cursor, handled, point, myPos);
260 if (e != 0) return e;
261 }
262
263 luPixel dx = point.x() - myPos.x();
264 luPixel dy = point.y() - myPos.y();
265
266 // the positions after the left indexes
267 if (dx < content->getX()+content->getWidth()) {
268 if (dy < content->getY()) {
269 if (hasUpperMiddle() && (dx > upperMiddle->getX())) {
270 upperMiddle->moveLeft(cursor, this);
271 handled = true;
272 return upperMiddle;
273 }
274 if (hasUpperLeft() && (dx > upperLeft->getX())) {
275 upperLeft->moveLeft(cursor, this);
276 handled = true;
277 return upperLeft;
278 }
279 }
280 else if (dy > content->getY()+content->getHeight()) {
281 if (hasLowerMiddle() && (dx > lowerMiddle->getX())) {
282 lowerMiddle->moveLeft(cursor, this);
283 handled = true;
284 return lowerMiddle;
285 }
286 if (hasLowerLeft() && (dx > lowerLeft->getX())) {
287 lowerLeft->moveLeft(cursor, this);
288 handled = true;
289 return lowerLeft;
290 }
291 }
292 }
293 // the positions after the left indexes
294 else {
295 if (dy < content->getY()) {
296 if (hasUpperRight()) {
297 upperRight->moveLeft(cursor, this);
298 handled = true;
299 return upperRight;
300 }
301 }
302 else if (dy > content->getY()+content->getHeight()) {
303 if (hasLowerRight()) {
304 lowerRight->moveLeft(cursor, this);
305 handled = true;
306 return lowerRight;
307 }
308 }
309 else {
310 content->moveLeft(cursor, this);
311 handled = true;
312 return content;
313 }
314 }
315
316 return this;
317 }
318 return 0;
319}
320
321
322// drawing
323//
324// Drawing depends on a context which knows the required properties like
325// fonts, spaces and such.
326// It is essential to calculate elements size with the same context
327// before you draw.
328
329
330void IndexElement::setMiddleX(int xOffset, int middleWidth)
331{
332 content->setX(xOffset + (middleWidth - content->getWidth()) / 2);
333 if (hasUpperMiddle()) {
334 upperMiddle->setX(xOffset + (middleWidth - upperMiddle->getWidth()) / 2);
335 }
336 if (hasLowerMiddle()) {
337 lowerMiddle->setX(xOffset + (middleWidth - lowerMiddle->getWidth()) / 2);
338 }
339}
340
341
348 ContextStyle::IndexStyle istyle,
349 StyleAttributes& style )
350{
351 double factor = style.sizeFactor();
352 luPixel distY = context.ptToPixelY( context.getThinSpace( tstyle, factor ) );
353
354 ContextStyle::TextStyle i_tstyle = context.convertTextStyleIndex(tstyle);
355 ContextStyle::IndexStyle u_istyle = context.convertIndexStyleUpper( istyle );
356 ContextStyle::IndexStyle l_istyle = context.convertIndexStyleLower( istyle );
357
358 // get the indexes size
359 luPixel ulWidth = 0, ulHeight = 0, ulMidline = 0;
360 if (hasUpperLeft()) {
361 upperLeft->calcSizes( context, i_tstyle, u_istyle, style );
362 ulWidth = upperLeft->getWidth();
363 ulHeight = upperLeft->getHeight();
364 ulMidline = upperLeft->axis( context, i_tstyle, factor );
365 }
366
367 luPixel umWidth = 0, umHeight = 0, umMidline = 0;
368 if (hasUpperMiddle()) {
369 upperMiddle->calcSizes( context, i_tstyle, u_istyle, style );
370 umWidth = upperMiddle->getWidth();
371 umHeight = upperMiddle->getHeight() + distY;
372 umMidline = upperMiddle->axis( context, i_tstyle, factor );
373 }
374
375 luPixel urWidth = 0, urHeight = 0, urMidline = 0;
376 if (hasUpperRight()) {
377 upperRight->calcSizes( context, i_tstyle, u_istyle, style );
378 urWidth = upperRight->getWidth();
379 urHeight = upperRight->getHeight();
380 urMidline = upperRight->axis( context, i_tstyle, factor );
381 }
382
383 luPixel llWidth = 0, llHeight = 0, llMidline = 0;
384 if (hasLowerLeft()) {
385 lowerLeft->calcSizes( context, i_tstyle, l_istyle, style );
386 llWidth = lowerLeft->getWidth();
387 llHeight = lowerLeft->getHeight();
388 llMidline = lowerLeft->axis( context, i_tstyle, factor );
389 }
390
391 luPixel lmWidth = 0, lmHeight = 0, lmMidline = 0;
392 if (hasLowerMiddle()) {
393 lowerMiddle->calcSizes( context, i_tstyle, l_istyle, style );
394 lmWidth = lowerMiddle->getWidth();
395 lmHeight = lowerMiddle->getHeight() + distY;
396 lmMidline = lowerMiddle->axis( context, i_tstyle, factor );
397 }
398
399 luPixel lrWidth = 0, lrHeight = 0, lrMidline = 0;
400 if (hasLowerRight()) {
401 lowerRight->calcSizes( context, i_tstyle, l_istyle, style );
402 lrWidth = lowerRight->getWidth();
403 lrHeight = lowerRight->getHeight();
404 lrMidline = lowerRight->axis( context, i_tstyle, factor );
405 }
406
407 // get the contents size
408 content->calcSizes( context, tstyle, istyle, style );
409 luPixel width = TQMAX(content->getWidth(), TQMAX(umWidth, lmWidth));
410 luPixel toMidline = content->axis( context, tstyle, factor );
411 luPixel fromMidline = content->getHeight() - toMidline;
412
413 // calculate the x offsets
414 if (ulWidth > llWidth) {
415 upperLeft->setX(0);
416 if (hasLowerLeft()) {
417 lowerLeft->setX(ulWidth - llWidth);
418 }
419 setMiddleX(ulWidth, width);
420 width += ulWidth;
421 }
422 else {
423 if (hasUpperLeft()) {
424 upperLeft->setX(llWidth - ulWidth);
425 }
426 if (hasLowerLeft()) {
427 lowerLeft->setX(0);
428 }
429 setMiddleX(llWidth, width);
430 width += llWidth;
431 }
432
433 if (hasUpperRight()) {
434 upperRight->setX(width);
435 }
436 if (hasLowerRight()) {
437 lowerRight->setX(width);
438 }
439 width += TQMAX(urWidth, lrWidth);
440
441 // calculate the y offsets
442 luPixel ulOffset = 0;
443 luPixel urOffset = 0;
444 luPixel llOffset = 0;
445 luPixel lrOffset = 0;
446 if (content->isTextOnly()) {
447 luPt mySize = context.getAdjustedSize( tstyle, factor );
448 TQFont font = context.getDefaultFont();
449 font.setPointSizeFloat( context.layoutUnitPtToPt( mySize ) );
450
451 TQFontMetrics fm(font);
452 LuPixelRect bound = fm.boundingRect('x');
453
454 luPixel exBaseline = context.ptToLayoutUnitPt( -bound.top() );
455
456 // the upper half
457 ulOffset = ulHeight + exBaseline - content->getBaseline();
458 urOffset = urHeight + exBaseline - content->getBaseline();
459
460 // the lower half
461 llOffset = lrOffset = content->getBaseline();
462 }
463 else {
464
465 // the upper half
466 ulOffset = TQMAX(ulMidline, ulHeight-toMidline);
467 urOffset = TQMAX(urMidline, urHeight-toMidline);
468
469 // the lower half
470 llOffset = TQMAX(content->getHeight()-llMidline, toMidline);
471 lrOffset = TQMAX(content->getHeight()-lrMidline, toMidline);
472 }
473
474 // Add more offset if defined in attributes
475 switch ( m_superScriptShiftType ) {
476 case AbsoluteSize:
477 urOffset += context.ptToLayoutUnitPt( m_superScriptShift );
478 break;
479 case RelativeSize:
480 urOffset += urOffset * m_superScriptShift;
481 break;
482 case PixelSize:
483 urOffset += context.pixelToLayoutUnitY( m_superScriptShift );
484 break;
485 default:
486 break;
487 }
488
489 switch ( m_subScriptShiftType ) {
490 case AbsoluteSize:
491 lrOffset += context.ptToLayoutUnitPt( m_subScriptShift );
492 break;
493 case RelativeSize:
494 lrOffset += lrOffset * m_subScriptShift;
495 break;
496 case PixelSize:
497 lrOffset += context.pixelToLayoutUnitY( m_subScriptShift );
498 break;
499 default:
500 break;
501 }
502
503 luPixel height = TQMAX(umHeight, TQMAX(ulOffset, urOffset));
504
505 // the upper half
506 content->setY(height);
507 toMidline += height;
508 if (hasUpperLeft()) {
509 upperLeft->setY(height-ulOffset);
510 }
511 if (hasUpperMiddle()) {
512 upperMiddle->setY(height-umHeight);
513 }
514 if (hasUpperRight()) {
515 upperRight->setY( height - urOffset );
516 }
517
518 // the lower half
519 if (hasLowerLeft()) {
520 lowerLeft->setY(height+llOffset);
521 }
522 if (hasLowerMiddle()) {
523 lowerMiddle->setY(height+content->getHeight()+distY);
524 }
525 if (hasLowerRight()) {
526 lowerRight->setY( height + lrOffset );
527 }
528
529 fromMidline += TQMAX(TQMAX(llHeight+llOffset, lrHeight+lrOffset) - content->getHeight(), lmHeight);
530
531 // set the result
532 setWidth(width);
533 setHeight(toMidline+fromMidline);
534 if (content->isTextOnly()) {
535 setBaseline(content->getY() + content->getBaseline());
536 //setMidline(content->getY() + content->getMidline());
537 }
538 else {
539 //setMidline(toMidline);
540 setBaseline(content->getBaseline() + content->getY());
541 }
542}
543
549void IndexElement::draw( TQPainter& painter, const LuPixelRect& r,
550 const ContextStyle& context,
552 ContextStyle::IndexStyle istyle,
553 StyleAttributes& style,
554 const LuPixelPoint& parentOrigin )
555{
556 LuPixelPoint myPos( parentOrigin.x()+getX(), parentOrigin.y()+getY() );
557 //if ( !LuPixelRect( myPos.x(), myPos.y(), getWidth(), getHeight() ).intersects( r ) )
558 // return;
559
560 ContextStyle::TextStyle i_tstyle = context.convertTextStyleIndex(tstyle);
561 ContextStyle::IndexStyle u_istyle = context.convertIndexStyleUpper( istyle );
562 ContextStyle::IndexStyle l_istyle = context.convertIndexStyleLower( istyle );
563
564 content->draw(painter, r, context, tstyle, istyle, style, myPos);
565 if (hasUpperLeft()) {
566 upperLeft->draw(painter, r, context, i_tstyle, u_istyle, style, myPos);
567 }
568 if (hasUpperMiddle()) {
569 upperMiddle->draw(painter, r, context, i_tstyle, u_istyle, style, myPos);
570 }
571 if (hasUpperRight()) {
572 upperRight->draw(painter, r, context, i_tstyle, u_istyle, style, myPos);
573 }
574 if (hasLowerLeft()) {
575 lowerLeft->draw(painter, r, context, i_tstyle, l_istyle, style, myPos);
576 }
577 if (hasLowerMiddle()) {
578 lowerMiddle->draw(painter, r, context, i_tstyle, l_istyle, style, myPos);
579 }
580 if (hasLowerRight()) {
581 lowerRight->draw(painter, r, context, i_tstyle, l_istyle, style, myPos);
582 }
583
584 // Debug
585 //painter.setBrush(TQt::NoBrush);
586 //painter.setPen(TQt::red);
587 //painter.drawRect(myPos.x(), myPos.y(), getWidth(), getHeight());
588 //painter.drawLine(myPos.x(), myPos.y()+getMidline(),
589 // myPos.x()+getWidth(), myPos.y()+getMidline());
590}
591
592
594{
595 content->dispatchFontCommand( cmd );
596 if (hasUpperLeft()) {
597 upperLeft->dispatchFontCommand( cmd );
598 }
599 if (hasUpperMiddle()) {
600 upperMiddle->dispatchFontCommand( cmd );
601 }
602 if (hasUpperRight()) {
603 upperRight->dispatchFontCommand( cmd );
604 }
605 if (hasLowerLeft()) {
606 lowerLeft->dispatchFontCommand( cmd );
607 }
608 if (hasLowerMiddle()) {
609 lowerMiddle->dispatchFontCommand( cmd );
610 }
611 if (hasLowerRight()) {
612 lowerRight->dispatchFontCommand( cmd );
613 }
614}
615
616
617// navigation
618//
619// The elements are responsible to handle cursor movement themselves.
620// To do this they need to know the direction the cursor moves and
621// the element it comes from.
622//
623// The cursor might be in normal or in selection mode.
624
625int IndexElement::getFromPos(BasicElement* from)
626{
627 if (from == lowerRight) {
628 return lowerRightPos;
629 }
630 else if (from == upperRight) {
631 return upperRightPos;
632 }
633 else if (from == lowerMiddle) {
634 return lowerMiddlePos;
635 }
636 else if (from == content) {
637 return contentPos;
638 }
639 else if (from == upperMiddle) {
640 return upperMiddlePos;
641 }
642 else if (from == lowerLeft) {
643 return lowerLeftPos;
644 }
645 else if (from == upperLeft) {
646 return upperLeftPos;
647 }
648 return parentPos;
649}
650
657{
658 if (cursor->isSelectionMode()) {
659 getParent()->moveLeft(cursor, this);
660 }
661 else {
662 bool linear = cursor->getLinearMovement();
663 int fromPos = getFromPos(from);
664 if (!linear) {
665 if ((fromPos == lowerRightPos) && hasLowerMiddle()) {
666 lowerMiddle->moveLeft(cursor, this);
667 return;
668 }
669 else if ((fromPos == upperRightPos) && hasUpperMiddle()) {
670 upperMiddle->moveLeft(cursor, this);
671 return;
672 }
673 else if ((fromPos == lowerMiddlePos) && hasLowerLeft()) {
674 lowerLeft->moveLeft(cursor, this);
675 return;
676 }
677 else if ((fromPos == upperMiddlePos) && hasUpperLeft()) {
678 upperLeft->moveLeft(cursor, this);
679 return;
680 }
681 }
682 switch (fromPos) {
683 case parentPos:
684 if (hasLowerRight() && linear) {
685 lowerRight->moveLeft(cursor, this);
686 break;
687 }
688 case lowerRightPos:
689 if (hasUpperRight() && linear) {
690 upperRight->moveLeft(cursor, this);
691 break;
692 }
693 case upperRightPos:
694 if (hasLowerMiddle() && linear) {
695 lowerMiddle->moveLeft(cursor, this);
696 break;
697 }
698 case lowerMiddlePos:
699 content->moveLeft(cursor, this);
700 break;
701 case contentPos:
702 if (hasUpperMiddle() && linear) {
703 upperMiddle->moveLeft(cursor, this);
704 break;
705 }
706 case upperMiddlePos:
707 if (hasLowerLeft() && linear) {
708 lowerLeft->moveLeft(cursor, this);
709 break;
710 }
711 case lowerLeftPos:
712 if (hasUpperLeft() && linear) {
713 upperLeft->moveLeft(cursor, this);
714 break;
715 }
716 case upperLeftPos:
717 getParent()->moveLeft(cursor, this);
718 }
719 }
720}
721
728{
729 if (cursor->isSelectionMode()) {
730 getParent()->moveRight(cursor, this);
731 }
732 else {
733 bool linear = cursor->getLinearMovement();
734 int fromPos = getFromPos(from);
735 if (!linear) {
736 if ((fromPos == lowerLeftPos) && hasLowerMiddle()) {
737 lowerMiddle->moveRight(cursor, this);
738 return;
739 }
740 else if ((fromPos == upperLeftPos) && hasUpperMiddle()) {
741 upperMiddle->moveRight(cursor, this);
742 return;
743 }
744 else if ((fromPos == lowerMiddlePos) && hasLowerRight()) {
745 lowerRight->moveRight(cursor, this);
746 return;
747 }
748 else if ((fromPos == upperMiddlePos) && hasUpperRight()) {
749 upperRight->moveRight(cursor, this);
750 return;
751 }
752 }
753 switch (fromPos) {
754 case parentPos:
755 if (hasUpperLeft() && linear) {
756 upperLeft->moveRight(cursor, this);
757 break;
758 }
759 case upperLeftPos:
760 if (hasLowerLeft() && linear) {
761 lowerLeft->moveRight(cursor, this);
762 break;
763 }
764 case lowerLeftPos:
765 if (hasUpperMiddle() && linear) {
766 upperMiddle->moveRight(cursor, this);
767 break;
768 }
769 case upperMiddlePos:
770 content->moveRight(cursor, this);
771 break;
772 case contentPos:
773 if (hasLowerMiddle() && linear) {
774 lowerMiddle->moveRight(cursor, this);
775 break;
776 }
777 case lowerMiddlePos:
778 if (hasUpperRight() && linear) {
779 upperRight->moveRight(cursor, this);
780 break;
781 }
782 case upperRightPos:
783 if (hasLowerRight() && linear) {
784 lowerRight->moveRight(cursor, this);
785 break;
786 }
787 case lowerRightPos:
788 getParent()->moveRight(cursor, this);
789 }
790 }
791}
792
799{
800 if (cursor->isSelectionMode()) {
801 getParent()->moveUp(cursor, this);
802 }
803 else {
804 if (from == content) {
805 if ((cursor->getPos() == 0) && (cursor->getElement() == from)) {
806 if (hasUpperLeft()) {
807 upperLeft->moveLeft(cursor, this);
808 return;
809 }
810 else if (hasUpperMiddle()) {
811 upperMiddle->moveRight(cursor, this);
812 return;
813 }
814 }
815 if (hasUpperRight()) {
816 upperRight->moveRight(cursor, this);
817 }
818 else if (hasUpperMiddle()) {
819 upperMiddle->moveLeft(cursor, this);
820 }
821 else if (hasUpperLeft()) {
822 upperLeft->moveLeft(cursor, this);
823 }
824 else {
825 getParent()->moveUp(cursor, this);
826 }
827 }
828 else if ((from == upperLeft) || (from == upperMiddle) || (from == upperRight)) {
829 getParent()->moveUp(cursor, this);
830 }
831 else if ((from == getParent()) || (from == lowerLeft) || (from == lowerMiddle)) {
832 content->moveRight(cursor, this);
833 }
834 else if (from == lowerRight) {
835 content->moveLeft(cursor, this);
836 }
837 }
838}
839
846{
847 if (cursor->isSelectionMode()) {
848 getParent()->moveDown(cursor, this);
849 }
850 else {
851 if (from == content) {
852 if ((cursor->getPos() == 0) && (cursor->getElement() == from)) {
853 if (hasLowerLeft()) {
854 lowerLeft->moveLeft(cursor, this);
855 return;
856 }
857 else if (hasLowerMiddle()) {
858 lowerMiddle->moveRight(cursor, this);
859 return;
860 }
861 }
862 if (hasLowerRight()) {
863 lowerRight->moveRight(cursor, this);
864 }
865 else if (hasLowerMiddle()) {
866 lowerMiddle->moveLeft(cursor, this);
867 }
868 else if (hasLowerLeft()) {
869 lowerLeft->moveLeft(cursor, this);
870 }
871 else {
872 getParent()->moveDown(cursor, this);
873 }
874 }
875 else if ((from == lowerLeft) || (from == lowerMiddle) || (from == lowerRight)) {
876 getParent()->moveDown(cursor, this);
877 }
878 else if ((from == getParent()) || (from == upperLeft) || (from == upperMiddle)) {
879 content->moveRight(cursor, this);
880 }
881 if (from == upperRight) {
882 content->moveLeft(cursor, this);
883 }
884 }
885}
886
887
888// children
889
890
891// main child
892//
893// If an element has children one has to become the main one.
894
895// void IndexElement::setMainChild(SequenceElement* child)
896// {
897// formula()->elementRemoval(content);
898// content = child;
899// content->setParent(this);
900// formula()->changed();
901// }
902
903
915 TQPtrList<BasicElement>& newChildren,
916 Direction direction)
917{
918 SequenceElement* index = static_cast<SequenceElement*>(newChildren.take(0));
919 index->setParent(this);
920
921 switch (cursor->getPos()) {
922 case upperLeftPos:
923 upperLeft = index;
924 break;
925 case lowerLeftPos:
926 lowerLeft = index;
927 break;
928 case upperMiddlePos:
929 upperMiddle = index;
930 break;
931 case lowerMiddlePos:
932 lowerMiddle = index;
933 break;
934 case upperRightPos:
935 upperRight = index;
936 break;
937 case lowerRightPos:
938 lowerRight = index;
939 break;
940 default:
941 // this is an error!
942 return;
943 }
944
945 if (direction == beforeCursor) {
946 index->moveLeft(cursor, this);
947 }
948 else {
949 index->moveRight(cursor, this);
950 }
951 cursor->setSelection(false);
952 formula()->changed();
953}
954
955
968 TQPtrList<BasicElement>& removedChildren,
969 Direction direction)
970{
971 int pos = cursor->getPos();
972 switch (pos) {
973 case upperLeftPos:
974 removedChildren.append(upperLeft);
975 formula()->elementRemoval(upperLeft);
976 upperLeft = 0;
977 setToUpperLeft(cursor);
978 break;
979 case lowerLeftPos:
980 removedChildren.append(lowerLeft);
981 formula()->elementRemoval(lowerLeft);
982 lowerLeft = 0;
983 setToLowerLeft(cursor);
984 break;
985 case contentPos: {
986 BasicElement* parent = getParent();
987 parent->selectChild(cursor, this);
988 parent->remove(cursor, removedChildren, direction);
989 break;
990 }
991 case upperMiddlePos:
992 removedChildren.append(upperMiddle);
993 formula()->elementRemoval(upperMiddle);
994 upperMiddle = 0;
995 setToUpperMiddle(cursor);
996 break;
997 case lowerMiddlePos:
998 removedChildren.append(lowerMiddle);
999 formula()->elementRemoval(lowerMiddle);
1000 lowerMiddle = 0;
1001 setToLowerMiddle(cursor);
1002 break;
1003 case upperRightPos:
1004 removedChildren.append(upperRight);
1005 formula()->elementRemoval(upperRight);
1006 upperRight = 0;
1007 setToUpperRight(cursor);
1008 break;
1009 case lowerRightPos:
1010 removedChildren.append(lowerRight);
1011 formula()->elementRemoval(lowerRight);
1012 lowerRight = 0;
1013 setToLowerRight(cursor);
1014 break;
1015 }
1016 formula()->changed();
1017}
1018
1023void IndexElement::normalize(FormulaCursor* cursor, Direction direction)
1024{
1025 if (direction == beforeCursor) {
1026 content->moveLeft(cursor, this);
1027 }
1028 else {
1029 content->moveRight(cursor, this);
1030 }
1031}
1032
1039{
1040 return !hasUpperLeft() && !hasUpperRight() && !hasUpperMiddle() &&
1041 !hasLowerLeft() && !hasLowerRight() && !hasLowerMiddle();
1042}
1043
1044
1049{
1050 int pos = cursor->getPos();
1051 /*
1052 It makes no sense to care for the direction.
1053 if (direction == beforeCursor) {
1054 pos -= 1;
1055 }
1056 */
1057 switch (pos) {
1058 case contentPos:
1059 return content;
1060 case upperLeftPos:
1061 return upperLeft;
1062 case lowerLeftPos:
1063 return lowerLeft;
1064 case upperMiddlePos:
1065 return upperMiddle;
1066 case lowerMiddlePos:
1067 return lowerMiddle;
1068 case upperRightPos:
1069 return upperRight;
1070 case lowerRightPos:
1071 return lowerRight;
1072 }
1073 return 0;
1074}
1075
1076
1082{
1083 if (child == content) {
1084 setToContent(cursor);
1085 }
1086 else if (child == upperLeft) {
1087 setToUpperLeft(cursor);
1088 }
1089 else if (child == lowerLeft) {
1090 setToLowerLeft(cursor);
1091 }
1092 else if (child == upperMiddle) {
1093 setToUpperMiddle(cursor);
1094 }
1095 else if (child == lowerMiddle) {
1096 setToLowerMiddle(cursor);
1097 }
1098 else if (child == upperRight) {
1099 setToUpperRight(cursor);
1100 }
1101 else if (child == lowerRight) {
1102 setToLowerRight(cursor);
1103 }
1104}
1105
1106
1113void IndexElement::setToContent(FormulaCursor* cursor)
1114{
1115 cursor->setTo(this, contentPos);
1116}
1117
1118// point the cursor to a gap where an index is to be inserted.
1119// this makes no sense if there is such an index already.
1120
1121void IndexElement::setToUpperLeft(FormulaCursor* cursor)
1122{
1123 cursor->setTo(this, upperLeftPos);
1124}
1125
1126void IndexElement::setToUpperMiddle(FormulaCursor* cursor)
1127{
1128 cursor->setTo(this, upperMiddlePos);
1129}
1130
1131void IndexElement::setToUpperRight(FormulaCursor* cursor)
1132{
1133 cursor->setTo(this, upperRightPos);
1134}
1135
1136void IndexElement::setToLowerLeft(FormulaCursor* cursor)
1137{
1138 cursor->setTo(this, lowerLeftPos);
1139}
1140
1141void IndexElement::setToLowerMiddle(FormulaCursor* cursor)
1142{
1143 cursor->setTo(this, lowerMiddlePos);
1144}
1145
1146void IndexElement::setToLowerRight(FormulaCursor* cursor)
1147{
1148 cursor->setTo(this, lowerRightPos);
1149}
1150
1151
1152// move inside an index that exists already.
1153
1154void IndexElement::moveToUpperLeft(FormulaCursor* cursor, Direction direction)
1155{
1156 if (hasUpperLeft()) {
1157 if (direction == beforeCursor) {
1158 upperLeft->moveLeft(cursor, this);
1159 }
1160 else {
1161 upperLeft->moveRight(cursor, this);
1162 }
1163 }
1164}
1165
1166void IndexElement::moveToUpperMiddle(FormulaCursor* cursor, Direction direction)
1167{
1168 if (hasUpperMiddle()) {
1169 if (direction == beforeCursor) {
1170 upperMiddle->moveLeft(cursor, this);
1171 }
1172 else {
1173 upperMiddle->moveRight(cursor, this);
1174 }
1175 }
1176}
1177
1178void IndexElement::moveToUpperRight(FormulaCursor* cursor, Direction direction)
1179{
1180 if (hasUpperRight()) {
1181 if (direction == beforeCursor) {
1182 upperRight->moveLeft(cursor, this);
1183 }
1184 else {
1185 upperRight->moveRight(cursor, this);
1186 }
1187 }
1188}
1189
1190void IndexElement::moveToLowerLeft(FormulaCursor* cursor, Direction direction)
1191{
1192 if (hasLowerLeft()) {
1193 if (direction == beforeCursor) {
1194 lowerLeft->moveLeft(cursor, this);
1195 }
1196 else {
1197 lowerLeft->moveRight(cursor, this);
1198 }
1199 }
1200}
1201
1202void IndexElement::moveToLowerMiddle(FormulaCursor* cursor, Direction direction)
1203{
1204 if (hasLowerMiddle()) {
1205 if (direction == beforeCursor) {
1206 lowerMiddle->moveLeft(cursor, this);
1207 }
1208 else {
1209 lowerMiddle->moveRight(cursor, this);
1210 }
1211 }
1212}
1213
1214void IndexElement::moveToLowerRight(FormulaCursor* cursor, Direction direction)
1215{
1216 if (hasLowerRight()) {
1217 if (direction == beforeCursor) {
1218 lowerRight->moveLeft(cursor, this);
1219 }
1220 else {
1221 lowerRight->moveRight(cursor, this);
1222 }
1223 }
1224}
1225
1226
1230void IndexElement::writeDom(TQDomElement element)
1231{
1232 BasicElement::writeDom(element);
1233
1234 TQDomDocument doc = element.ownerDocument();
1235
1236 TQDomElement cont = doc.createElement("CONTENT");
1237 cont.appendChild(content->getElementDom(doc));
1238 element.appendChild(cont);
1239
1240 if (hasUpperLeft()) {
1241 TQDomElement ind = doc.createElement("UPPERLEFT");
1242 ind.appendChild(upperLeft->getElementDom(doc));
1243 element.appendChild(ind);
1244 }
1245 if (hasUpperMiddle()) {
1246 TQDomElement ind = doc.createElement("UPPERMIDDLE");
1247 ind.appendChild(upperMiddle->getElementDom(doc));
1248 element.appendChild(ind);
1249 }
1250 if (hasUpperRight()) {
1251 TQDomElement ind = doc.createElement("UPPERRIGHT");
1252 ind.appendChild(upperRight->getElementDom(doc));
1253 element.appendChild(ind);
1254 }
1255 if (hasLowerLeft()) {
1256 TQDomElement ind = doc.createElement("LOWERLEFT");
1257 ind.appendChild(lowerLeft->getElementDom(doc));
1258 element.appendChild(ind);
1259 }
1260 if (hasLowerMiddle()) {
1261 TQDomElement ind = doc.createElement("LOWERMIDDLE");
1262 ind.appendChild(lowerMiddle->getElementDom(doc));
1263 element.appendChild(ind);
1264 }
1265 if (hasLowerRight()) {
1266 TQDomElement ind = doc.createElement("LOWERRIGHT");
1267 ind.appendChild(lowerRight->getElementDom(doc));
1268 element.appendChild(ind);
1269 }
1270}
1271
1276bool IndexElement::readAttributesFromDom(TQDomElement element)
1277{
1279 return false;
1280 }
1281 return true;
1282}
1283
1290{
1292 return false;
1293 }
1294
1295 if ( !buildChild( content, node, "CONTENT" ) ) {
1296 kdWarning( DEBUGID ) << "Empty content in IndexElement." << endl;
1297 return false;
1298 }
1299 node = node.nextSibling();
1300
1301 bool upperLeftRead = false;
1302 bool upperMiddleRead = false;
1303 bool upperRightRead = false;
1304 bool lowerLeftRead = false;
1305 bool lowerMiddleRead = false;
1306 bool lowerRightRead = false;
1307
1308 while (!node.isNull() &&
1309 !(upperLeftRead && upperMiddleRead && upperRightRead &&
1310 lowerLeftRead && lowerMiddleRead && lowerRightRead)) {
1311
1312 if (!upperLeftRead && (node.nodeName().upper() == "UPPERLEFT")) {
1313 upperLeftRead = buildChild( upperLeft=new SequenceElement( this ), node, "UPPERLEFT" );
1314 if ( !upperLeftRead ) return false;
1315 }
1316
1317 if (!upperMiddleRead && (node.nodeName().upper() == "UPPERMIDDLE")) {
1318 upperMiddleRead = buildChild( upperMiddle=new SequenceElement( this ), node, "UPPERMIDDLE" );
1319 if ( !upperMiddleRead ) return false;
1320 }
1321
1322 if (!upperRightRead && (node.nodeName().upper() == "UPPERRIGHT")) {
1323 upperRightRead = buildChild( upperRight=new SequenceElement( this ), node, "UPPERRIGHT" );
1324 if ( !upperRightRead ) return false;
1325 }
1326
1327 if (!lowerLeftRead && (node.nodeName().upper() == "LOWERLEFT")) {
1328 lowerLeftRead = buildChild( lowerLeft=new SequenceElement( this ), node, "LOWERLEFT" );
1329 if ( !lowerLeftRead ) return false;
1330 }
1331
1332 if (!lowerMiddleRead && (node.nodeName().upper() == "LOWERMIDDLE")) {
1333 lowerMiddleRead = buildChild( lowerMiddle=new SequenceElement( this ), node, "LOWERMIDDLE" );
1334 if ( !lowerMiddleRead ) return false;
1335 }
1336
1337 if (!lowerRightRead && (node.nodeName().upper() == "LOWERRIGHT")) {
1338 lowerRightRead = buildChild( lowerRight=new SequenceElement( this ), node, "LOWERRIGHT" );
1339 if ( !lowerRightRead ) return false;
1340 }
1341
1342 node = node.nextSibling();
1343 }
1344 return upperLeftRead || upperMiddleRead || upperRightRead ||
1345 lowerLeftRead || lowerMiddleRead || lowerRightRead;
1346}
1347
1348bool IndexElement::readAttributesFromMathMLDom( const TQDomElement& element )
1349{
1351 return false;
1352 }
1353
1354 TQString tag = element.tagName().stripWhiteSpace().lower();
1355 if ( tag == "msub" || tag == "msubsup" ) {
1356 TQString subscriptshiftStr = element.attribute( "subscriptshift" ).stripWhiteSpace().lower();
1357 if ( ! subscriptshiftStr.isNull() ) {
1358 m_subScriptShift = getSize( subscriptshiftStr, &m_subScriptShiftType );
1359 }
1360 }
1361 if ( tag == "msup" || tag == "msubsup" ) {
1362 TQString superscriptshiftStr = element.attribute( "superscriptshift" ).stripWhiteSpace().lower();
1363 if ( ! superscriptshiftStr.isNull() ) {
1364 m_superScriptShift = getSize( superscriptshiftStr, &m_superScriptShiftType );
1365 }
1366 }
1367
1368 if ( tag == "munder" || tag == "munderover" ) {
1369 TQString accentunderStr = element.attribute( "accentunder" ).stripWhiteSpace().lower();
1370 if ( ! accentunderStr.isNull() ) {
1371 if ( accentunderStr == "true" ) {
1372 m_customAccentUnder = true;
1373 m_accentUnder = true;
1374 }
1375 else if ( accentunderStr == "false" ) {
1376 m_customAccentUnder = true;
1377 m_accentUnder = false;
1378 }
1379 else {
1380 kdWarning( DEBUGID ) << "Invalid value for attribute `accentunder': "
1381 << accentunderStr << endl;
1382 }
1383 }
1384 }
1385 if ( tag == "mover" || tag == "munderover" ) {
1386 TQString accentStr = element.attribute( "accent" ).stripWhiteSpace().lower();
1387 if ( ! accentStr.isNull() ) {
1388 if ( accentStr == "true" ) {
1389 m_customAccent = true;
1390 m_accent = true;
1391 }
1392 else if ( accentStr == "false" ) {
1393 m_customAccent = true;
1394 m_accent = false;
1395 }
1396 else {
1397 kdWarning( DEBUGID ) << "Invalid value for attribute `accent': "
1398 << accentStr << endl;
1399 }
1400 }
1401 }
1402 return true;
1403}
1404
1412{
1413 if ( BasicElement::readContentFromMathMLDom( node ) == -1 ) {
1414 return -1;
1415 }
1416
1417 int contentNumber = content->buildMathMLChild( node );
1418 if ( contentNumber == -1 ) {
1419 kdWarning( DEBUGID ) << "Empty base in Script" << endl;
1420 return -1;
1421 }
1422 for (int i = 0; i < contentNumber; i++ ) {
1423 if ( node.isNull() ) {
1424 return -1;
1425 }
1426 node = node.nextSibling();
1427 }
1428
1429 TQString indexType = node.parentNode().toElement().tagName().lower();
1430 if ( indexType == "msub" ) {
1431 lowerRight = new SequenceElement( this );
1432 int lowerRightNumber = lowerRight->buildMathMLChild( node );
1433 if ( lowerRightNumber == -1 ) {
1434 kdWarning( DEBUGID ) << "Empty subscript in Script" << endl;
1435 return -1;
1436 }
1437 for (int i = 0; i < lowerRightNumber; i++ ) {
1438 if ( node.isNull() ) {
1439 return -1;
1440 }
1441 node = node.nextSibling();
1442 }
1443
1444 return 1;
1445 }
1446
1447 if ( indexType == "msup" ) {
1448 upperRight = new SequenceElement( this );
1449 int upperRightNumber = upperRight->buildMathMLChild( node );
1450 if ( upperRightNumber == -1 ) {
1451 kdWarning( DEBUGID ) << "Empty superscript in Script" << endl;
1452 return -1;
1453 }
1454 for (int i = 0; i < upperRightNumber; i++ ) {
1455 if ( node.isNull() ) {
1456 return -1;
1457 }
1458 node = node.nextSibling();
1459 }
1460
1461 return 1;
1462 }
1463
1464 if ( indexType == "msubsup" ) {
1465 lowerRight = new SequenceElement( this );
1466 int lowerRightNumber = lowerRight->buildMathMLChild( node );
1467 if ( lowerRightNumber == -1 ) {
1468 kdWarning( DEBUGID ) << "Empty subscript in Script" << endl;
1469 return -1;
1470 }
1471 for (int i = 0; i < lowerRightNumber; i++ ) {
1472 if ( node.isNull() ) {
1473 return -1;
1474 }
1475 node = node.nextSibling();
1476 }
1477
1478 upperRight = new SequenceElement( this );
1479 int upperRightNumber = upperRight->buildMathMLChild( node );
1480 if ( upperRightNumber == -1 ) {
1481 kdWarning( DEBUGID ) << "Empty superscript in Script" << endl;
1482 return -1;
1483 }
1484 for (int i = 0; i < upperRightNumber; i++ ) {
1485 if ( node.isNull() ) {
1486 return -1;
1487 }
1488 node = node.nextSibling();
1489 }
1490
1491 return 1;
1492 }
1493 if ( indexType == "munder" ) {
1494 lowerMiddle = new SequenceElement( this );
1495 int lowerMiddleNumber = lowerMiddle->buildMathMLChild( node );
1496 if ( lowerMiddleNumber == -1 ) {
1497 kdWarning( DEBUGID ) << "Empty underscript in Script" << endl;
1498 return -1;
1499 }
1500 for (int i = 0; i < lowerMiddleNumber; i++ ) {
1501 if ( node.isNull() ) {
1502 return -1;
1503 }
1504 node = node.nextSibling();
1505 }
1506
1507 return 1;
1508 }
1509
1510 if ( indexType == "mover" ) {
1511 upperMiddle = new SequenceElement( this );
1512 int upperMiddleNumber = upperMiddle->buildMathMLChild( node );
1513 if ( upperMiddleNumber == -1 ) {
1514 kdWarning( DEBUGID ) << "Empty overscript in Script" << endl;
1515 return -1;
1516 }
1517 for (int i = 0; i < upperMiddleNumber; i++ ) {
1518 if ( node.isNull() ) {
1519 return -1;
1520 }
1521 node = node.nextSibling();
1522 }
1523
1524 return 1;
1525 }
1526
1527 if ( indexType == "munderover" ) {
1528 lowerMiddle = new SequenceElement( this );
1529 int lowerMiddleNumber = lowerMiddle->buildMathMLChild( node );
1530 if ( lowerMiddleNumber == -1 ) {
1531 kdWarning( DEBUGID ) << "Empty underscript in Script" << endl;
1532 return -1;
1533 }
1534 for (int i = 0; i < lowerMiddleNumber; i++ ) {
1535 if ( node.isNull() ) {
1536 return -1;
1537 }
1538 node = node.nextSibling();
1539 }
1540
1541
1542 upperMiddle = new SequenceElement( this );
1543 int upperMiddleNumber = upperMiddle->buildMathMLChild( node );
1544 if ( upperMiddleNumber == -1 ) {
1545 kdWarning( DEBUGID ) << "Empty overscript in Script" << endl;
1546 return -1;
1547 }
1548 for (int i = 0; i < upperMiddleNumber; i++ ) {
1549 if ( node.isNull() ) {
1550 return -1;
1551 }
1552 node = node.nextSibling();
1553 }
1554
1555 return 1;
1556 }
1557 // TODO: mmultiscripts, section 3.4.7
1558 return 1;
1559}
1560
1561
1562ElementIndexPtr IndexElement::getIndex( int position )
1563{
1564 switch (position) {
1565 case upperRightPos:
1566 return getUpperRight();
1567 case lowerRightPos:
1568 return getLowerRight();
1569 case lowerMiddlePos:
1570 return getLowerMiddle();
1571 case upperMiddlePos:
1572 return getUpperMiddle();
1573 case lowerLeftPos:
1574 return getLowerLeft();
1575 case upperLeftPos:
1576 return getUpperLeft();
1577 }
1578 return getUpperRight();
1579}
1580
1581
1582
1584{
1585 TQString index;
1586
1587 if ( hasUpperMiddle() ) {
1588 index += "\\overset{" + upperMiddle->toLatex() + "}{";
1589 }
1590
1591 if ( hasLowerMiddle() ) {
1592 index += "\\underset{" + lowerMiddle->toLatex() + "}{";
1593 }
1594
1595 if ( hasUpperLeft() || hasUpperRight() ) { //Not sure that this is possible in Latex!
1596 /*index += "{}";
1597 if ( hasUpperLeft() )
1598 index += "^" + upperLeft->toLatex();
1599 if ( hasLowerLeft() )
1600 index += "_" + lowerLeft->toLatex();
1601 */
1602 }
1603
1604 index += content->toLatex();
1605
1606 if ( hasUpperRight() || hasLowerRight() ) {
1607 if ( hasUpperRight() )
1608 index += "^{" + upperRight->toLatex() + "}";
1609 if ( hasLowerRight() )
1610 index += "_{" + lowerRight->toLatex() + "}";
1611 index += " ";
1612 }
1613
1614 if ( hasLowerMiddle() ) {
1615 index += "}";
1616 }
1617
1618 if ( hasUpperMiddle() ) {
1619 index += "}";
1620 }
1621
1622 return index;
1623}
1624
1625TQString IndexElement::formulaString()
1626{
1627 TQString index = "(" + content->formulaString() + ")";
1628 if ( hasLowerRight() ) {
1629 index += "_(" + lowerRight->formulaString() + ")";
1630 }
1631 if ( hasUpperRight() ) {
1632 index += "**(" + upperRight->formulaString() + ")";
1633 }
1634 return index;
1635}
1636
1637TQString IndexElement::getElementName() const
1638{
1639 if ( hasUpperMiddle() && hasLowerMiddle() )
1640 return "munderover";
1641 if ( hasUpperMiddle() )
1642 return "mover";
1643 if ( hasLowerMiddle() )
1644 return "munder";
1645 if ( hasLowerLeft() || hasUpperLeft() )
1646 return "mmultiscripts";
1647 if ( hasLowerRight() || hasUpperRight() ) {
1648 if ( ! hasUpperRight() )
1649 return "msub";
1650 if ( ! hasLowerRight() )
1651 return "msup";
1652 }
1653 return "msubsup";
1654}
1655
1656void IndexElement::writeMathMLAttributes( TQDomElement& element ) const
1657{
1658 TQString tag = getElementName();
1659 if ( tag == "msub" || tag == "msubsup" ) {
1660 switch ( m_subScriptShiftType ) {
1661 case AbsoluteSize:
1662 element.setAttribute( "subscriptshift", TQString( "%1pt" ).arg( m_subScriptShift ) );
1663 break;
1664 case RelativeSize:
1665 element.setAttribute( "subscriptshift", TQString( "%1%" ).arg( m_subScriptShift * 100.0 ) );
1666 break;
1667 case PixelSize:
1668 element.setAttribute( "subscriptshift", TQString( "%1px" ).arg( m_subScriptShift ) );
1669 break;
1670 default:
1671 break;
1672 }
1673 }
1674 if ( tag == "msup" || tag == "msubsup" ) {
1675 switch ( m_superScriptShiftType ) {
1676 case AbsoluteSize:
1677 element.setAttribute( "superscriptshift", TQString( "%1pt" ).arg( m_superScriptShift ) );
1678 break;
1679 case RelativeSize:
1680 element.setAttribute( "superscriptshift", TQString( "%1%" ).arg( m_superScriptShift * 100.0 ) );
1681 break;
1682 case PixelSize:
1683 element.setAttribute( "superscriptshift", TQString( "%1px" ).arg( m_superScriptShift ) );
1684 break;
1685 default:
1686 break;
1687 }
1688 }
1689 if ( tag == "munder" || tag == "munderover" ) {
1690 if ( m_customAccentUnder ) {
1691 element.setAttribute( "accentunder", m_accentUnder ? "true" : "false" );
1692 }
1693 }
1694 if ( tag == "mover" || tag == "munderover" ) {
1695 if ( m_customAccent ) {
1696 element.setAttribute( "accent", m_accent ? "true" : "false" );
1697 }
1698 }
1699}
1700
1701
1702void IndexElement::writeMathMLContent( TQDomDocument& doc,
1703 TQDomElement& element,
1704 bool oasisFormat ) const
1705{
1706 TQDomElement de;
1707
1708 content->writeMathML( doc, element, oasisFormat ); // base
1709 if ( hasUpperMiddle() && hasLowerMiddle() )
1710 {
1711 lowerMiddle->writeMathML( doc, element, oasisFormat );
1712 upperMiddle->writeMathML( doc, element,oasisFormat );
1713 }
1714 else if ( hasUpperMiddle() )
1715 {
1716 upperMiddle->writeMathML( doc, element,oasisFormat );
1717 }
1718 else if ( hasLowerMiddle() )
1719 {
1720 lowerMiddle->writeMathML( doc, element,oasisFormat );
1721 }
1722
1723 if ( hasLowerLeft() || hasUpperLeft() )
1724 {
1725 if ( hasLowerRight() )
1726 lowerRight->writeMathML( doc, element, oasisFormat );
1727 else
1728 element.appendChild( doc.createElement( "none" ) );
1729
1730 if ( hasUpperRight() )
1731 upperRight->writeMathML( doc, element, oasisFormat );
1732 else
1733 element.appendChild( doc.createElement( "none" ) );
1734
1735 element.appendChild( doc.createElement( "mprescripts" ) );
1736
1737 if ( hasLowerLeft() )
1738 lowerLeft->writeMathML( doc, element, oasisFormat );
1739 else
1740 element.appendChild( doc.createElement( "none" ) );
1741
1742 if ( hasUpperLeft() )
1743 upperLeft->writeMathML( doc, element, oasisFormat );
1744 else
1745 element.appendChild( doc.createElement( "none" ) );
1746 }
1747 else if ( hasLowerRight() || hasUpperRight() )
1748 {
1749 if ( !hasUpperRight() ) {
1750 lowerRight->writeMathML( doc, element, oasisFormat );
1751 }
1752 else if ( !hasLowerRight() ) {
1753 upperRight->writeMathML( doc, element, oasisFormat );
1754 }
1755 else // both
1756 {
1757 lowerRight->writeMathML( doc, element, oasisFormat );
1758 upperRight->writeMathML( doc, element,oasisFormat );
1759 }
1760 }
1761}
1762
1763KFORMULA_NAMESPACE_END
Basis of every formula element.
virtual FormulaElement * formula()
Provide fast access to the rootElement for each child.
virtual void remove(FormulaCursor *, TQPtrList< BasicElement > &, Direction)
Removes all selected children and returns them.
bool buildChild(SequenceElement *child, TQDomNode node, TQString name)
Returns if the SequenceElement could be constructed from the nodes first child.
virtual bool readAttributesFromMathMLDom(const TQDomElement &element)
Reads our attributes from the MathML element.
virtual bool readContentFromDom(TQDomNode &node)
Reads our content from the node.
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’.
virtual void selectChild(FormulaCursor *, BasicElement *)
Sets the cursor to select the child.
TQDomElement getElementDom(TQDomDocument &doc)
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.
double getSize(const TQString &str, SizeType *st)
Utility function that sets the size type and returns the size value from a MathML attribute string wi...
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’.
virtual void writeMathML(TQDomDocument &doc, TQDomNode &parent, bool oasisFormat=false) const
Same as above, just MathML.
The document.
FormulaCursor * activeCursor()
Contains all the style information for the formela.
TextStyle convertTextStyleIndex(TextStyle tstyle) const
Font-conversions a la TeX.
luPt getAdjustedSize(TextStyle tstyle, double factor) const
Calculates the font size corresponding to the given TextStyle.
TextStyle
Textstyles like in TeX.
IndexStyle convertIndexStyleLower(IndexStyle) const
Index-style-conversions a la TeX.
IndexStyle convertIndexStyleUpper(IndexStyle istyle) const
Index-style-conversions a la TeX.
Base for all font commands that act on the current selection.
The selection.
bool isSelection() const
Returns wether there actually is a selection.
void setSelection(bool selection)
Sets the selection mode.
bool isSelectionMode() const
Returns wether we are in selection mode.
void setTo(BasicElement *element, uint cursor, int mark=-1)
Sets the cursor to a new position.
BasicElement * getElement()
The element we are in.
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.
virtual void changed()
Gets called whenever something changes and we need to recalc.
The element with up to four indexes in the four corners.
virtual void moveDown(FormulaCursor *cursor, BasicElement *from)
Enters this element while moving down starting inside the element ‘from’.
virtual bool isSenseless()
Moves the cursor away from the given child.
virtual int readContentFromMathMLDom(TQDomNode &node)
Reads our content from the MathML node.
virtual void normalize(FormulaCursor *, Direction)
Moves the cursor to a normal place where new elements might be inserted.
virtual bool accept(ElementVisitor *visitor)
Visit this element.
virtual TQString toLatex()
virtual void insert(FormulaCursor *, TQPtrList< BasicElement > &, Direction)
Inserts all new children at the cursor position.
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 remove(FormulaCursor *, TQPtrList< BasicElement > &, Direction)
Removes all selected children and returns them.
virtual void selectChild(FormulaCursor *cursor, BasicElement *child)
Sets the cursor to select the child.
ElementIndexPtr getIndex(int position)
Returns the index at the position.
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 bool readAttributesFromMathMLDom(const TQDomElement &element)
Reads our attributes from the MathML element.
virtual bool readContentFromDom(TQDomNode &node)
Reads our content from the node.
virtual void writeDom(TQDomElement element)
Appends our attributes to the dom element.
virtual void dispatchFontCommand(FontCommand *cmd)
Dispatch this FontCommand to all our TextElement children.
virtual void moveLeft(FormulaCursor *cursor, BasicElement *from)
Enters this element while moving to the left starting inside the element ‘from’.
virtual void entered(SequenceElement *child)
The cursor has entered one of our child sequences.
virtual void moveRight(FormulaCursor *cursor, BasicElement *from)
Enters this element while moving to the right 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 moveUp(FormulaCursor *cursor, BasicElement *from)
Enters this element while moving up starting inside the element ‘from’.
virtual BasicElement * getChild(FormulaCursor *, Direction=beforeCursor)
Returns the child at the cursor.
virtual bool readAttributesFromDom(TQDomElement element)
Reads our attributes from the element.
virtual TQChar getCharacter() const
static double ptToLayoutUnitPt(double pt)
Not zoom dependent.
The element that contains a number of children.
virtual TQString toLatex()
virtual bool isTextOnly() const
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 moveRight(FormulaCursor *cursor, BasicElement *from)
Enters this element while moving to the right starting inside the element ‘from’.
virtual void dispatchFontCommand(FontCommand *cmd)
Dispatch this FontCommand to all our TextElement children.
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 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 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.