bracketelement.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 <tqptrlist.h>
22#include <tqpainter.h>
23#include <tqpen.h>
24#include <tqpointarray.h>
25
26#include <kdebug.h>
27#include <tdelocale.h>
28
29#include "bracketelement.h"
30#include "elementvisitor.h"
31#include "fontstyle.h"
32#include "formulacursor.h"
33#include "formulaelement.h"
34#include "sequenceelement.h"
35
36KFORMULA_NAMESPACE_BEGIN
37
38SingleContentElement::SingleContentElement(BasicElement* parent )
39 : BasicElement( parent )
40{
41 content = new SequenceElement( this );
42}
43
44
45SingleContentElement::SingleContentElement( const SingleContentElement& other )
46 : BasicElement( other )
47{
48 content = new SequenceElement( other.content );
49 content->setParent( this );
50}
51
52
53SingleContentElement::~SingleContentElement()
54{
55 delete content;
56}
57
58
60{
61 // This is meant to make the SingleContentElement text only.
62 // This "fixes" the parenthesis problem (parenthesis too large).
63 // I'm not sure if we really want this. There should be better ways.
64 if ( content->isTextOnly() ) {
65 return '\\';
66 }
67 return content->getCharacter();
68}
69
71 const LuPixelPoint& point, const LuPixelPoint& parentOrigin )
72{
73 BasicElement* e = BasicElement::goToPos(cursor, handled, point, parentOrigin);
74 if (e != 0) {
75 LuPixelPoint myPos(parentOrigin.x() + getX(),
76 parentOrigin.y() + getY());
77
78 e = content->goToPos(cursor, handled, point, myPos);
79 if (e != 0) {
80 return e;
81 }
82 return this;
83 }
84 return 0;
85}
86
91
93{
94 if (cursor->isSelectionMode()) {
95 getParent()->moveLeft(cursor, this);
96 }
97 else {
98 //bool linear = cursor->getLinearMovement();
99 if (from == getParent()) {
100 content->moveLeft(cursor, this);
101 }
102 else {
103 getParent()->moveLeft(cursor, this);
104 }
105 }
106}
107
109{
110 if (cursor->isSelectionMode()) {
111 getParent()->moveRight(cursor, this);
112 }
113 else {
114 //bool linear = cursor->getLinearMovement();
115 if (from == getParent()) {
116 content->moveRight(cursor, this);
117 }
118 else {
119 getParent()->moveRight(cursor, this);
120 }
121 }
122}
123
125{
126 getParent()->moveUp(cursor, this);
127}
128
130{
131 getParent()->moveDown(cursor, this);
132}
133
135 TQPtrList<BasicElement>& removedChildren,
136 Direction direction )
137{
138 switch (cursor->getPos()) {
139 case contentPos:
140 BasicElement* parent = getParent();
141 parent->selectChild(cursor, this);
142 parent->remove(cursor, removedChildren, direction);
143 }
144}
145
146void SingleContentElement::normalize( FormulaCursor* cursor, Direction direction )
147{
148 if (direction == beforeCursor) {
149 content->moveLeft(cursor, this);
150 }
151 else {
152 content->moveRight(cursor, this);
153 }
154}
155
160
162{
163 if (child == content) {
164 cursor->setTo(this, contentPos);
165 }
166}
167
168void SingleContentElement::writeDom(TQDomElement element)
169{
170 BasicElement::writeDom(element);
171
172 TQDomDocument doc = element.ownerDocument();
173
174 TQDomElement con = doc.createElement("CONTENT");
175 con.appendChild(content->getElementDom(doc));
176 element.appendChild(con);
177}
178
180{
182 return false;
183 }
184
185 if ( !buildChild( content, node, "CONTENT" ) ) {
186 kdWarning( DEBUGID ) << "Empty content in " << getTagName() << endl;
187 return false;
188 }
189 node = node.nextSibling();
190
191 return true;
192}
193
195{
196 if ( BasicElement::readContentFromMathMLDom( node ) == -1 ) {
197 return -1;
198 }
199
200 int nodeCounter = content->buildMathMLChild( node );
201 if ( nodeCounter == -1 ) {
202 kdWarning( DEBUGID) << "Empty content in SingleContentElement\n";
203 return -1;
204 }
205
206 return nodeCounter;
207}
208
209void SingleContentElement::writeMathMLContent( TQDomDocument& doc, TQDomElement& element, bool oasisFormat ) const
210{
211 content->writeMathML( doc, element, oasisFormat );
212}
213
214
215
216BracketElement::BracketElement(SymbolType l, SymbolType r, BasicElement* parent)
217 : SingleContentElement(parent),
218 left( 0 ), right( 0 ),
219 leftType( l ), rightType( r ),
220 m_operator( false ), m_customLeft( false ), m_customRight( false )
221{
222}
223
224
225BracketElement::~BracketElement()
226{
227 delete left;
228 delete right;
229}
230
231
232BracketElement::BracketElement( const BracketElement& other )
233 : SingleContentElement( other ),
234 left( 0 ), right( 0 ),
235 leftType( other.leftType ), rightType( other.rightType ),
236 m_operator( other.m_operator ),
237 m_customLeft( other.m_customLeft ), m_customRight( other.m_customRight )
238{
239}
240
241
243{
244 return visitor->visit( this );
245}
246
247
249{
250 formula()->tell( i18n( "Delimited list" ) );
251}
252
253
255 const LuPixelPoint& point, const LuPixelPoint& parentOrigin )
256{
257 BasicElement* e = BasicElement::goToPos(cursor, handled, point, parentOrigin);
258 if (e != 0) {
259 LuPixelPoint myPos(parentOrigin.x() + getX(),
260 parentOrigin.y() + getY());
261 e = getContent()->goToPos(cursor, handled, point, myPos);
262 if (e != 0) {
263 return e;
264 }
265
266 // We are in one of those gaps.
267 luPixel dx = point.x() - myPos.x();
268 luPixel dy = point.y() - myPos.y();
269
270 if ((dx > getContent()->getX()+getContent()->getWidth()) ||
271 (dy > getContent()->getY()+getContent()->getHeight())) {
272 getContent()->moveEnd(cursor);
273 handled = true;
274 return getContent();
275 }
276 return this;
277 }
278 return 0;
279}
280
281
288 ContextStyle::IndexStyle istyle,
289 StyleAttributes& style )
290{
291 SequenceElement* content = getContent();
292 content->calcSizes( context, tstyle, istyle, style );
293
294 //if ( left == 0 ) {
295 delete left;
296 delete right;
297 left = context.fontStyle().createArtwork( leftType );
298 right = context.fontStyle().createArtwork( rightType );
299 //}
300
301 double factor = style.sizeFactor();
302 if (content->isTextOnly()) {
303 left->calcSizes(context, tstyle, factor);
304 right->calcSizes(context, tstyle, factor);
305
306 setBaseline(TQMAX(content->getBaseline(),
307 TQMAX(left->getBaseline(), right->getBaseline())));
308
309 content->setY(getBaseline() - content->getBaseline());
310 left ->setY(getBaseline() - left ->getBaseline());
311 right ->setY(getBaseline() - right ->getBaseline());
312
313 //setMidline(content->getY() + content->getMidline());
314 setHeight(TQMAX(content->getY() + content->getHeight(),
315 TQMAX(left ->getY() + left ->getHeight(),
316 right->getY() + right->getHeight())));
317 }
318 else {
319 //kdDebug( DEBUGID ) << "BracketElement::calcSizes " << content->axis( context, tstyle ) << " " << content->getHeight() << endl;
320 luPixel contentHeight = 2 * TQMAX( content->axis( context, tstyle, factor ),
321 content->getHeight() - content->axis( context, tstyle, factor ) );
322 left->calcSizes( context, tstyle, factor, contentHeight );
323 right->calcSizes( context, tstyle, factor, contentHeight );
324
325 // height
326 setHeight(TQMAX(contentHeight,
327 TQMAX(left->getHeight(), right->getHeight())));
328 //setMidline(getHeight() / 2);
329
330 content->setY(getHeight() / 2 - content->axis( context, tstyle, factor ));
331 setBaseline(content->getBaseline() + content->getY());
332
333 if ( left->isNormalChar() ) {
334 left->setY(getBaseline() - left->getBaseline());
335 }
336 else {
337 left->setY((getHeight() - left->getHeight())/2);
338 }
339 if ( right->isNormalChar() ) {
340 right->setY(getBaseline() - right->getBaseline());
341 }
342 else {
343 right->setY((getHeight() - right->getHeight())/2);
344 }
345
346// kdDebug() << "BracketElement::calcSizes" << endl
347// << "getHeight(): " << getHeight() << endl
348// << "left->getHeight(): " << left->getHeight() << endl
349// << "right->getHeight(): " << right->getHeight() << endl
350// << "left->getY(): " << left->getY() << endl
351// << "right->getY(): " << right->getY() << endl
352// << endl;
353 }
354
355 // width
356 setWidth(left->getWidth() + content->getWidth() + right->getWidth());
357 content->setX(left->getWidth());
358 right ->setX(left->getWidth()+content->getWidth());
359}
360
361
367void BracketElement::draw( TQPainter& painter, const LuPixelRect& r,
368 const ContextStyle& context,
370 ContextStyle::IndexStyle istyle,
371 StyleAttributes& style,
372 const LuPixelPoint& parentOrigin )
373{
374 LuPixelPoint myPos( parentOrigin.x()+getX(), parentOrigin.y()+getY() );
375 //if ( !LuPixelRect( myPos.x(), myPos.y(), getWidth(), getHeight() ).intersects( r ) )
376 // return;
377
378 SequenceElement* content = getContent();
379 content->draw(painter, r, context, tstyle, istyle, style, myPos);
380
381 if (content->isTextOnly()) {
382 left->draw(painter, r, context, tstyle, style, myPos);
383 right->draw(painter, r, context, tstyle, style, myPos);
384 }
385 else {
386 double factor = style.sizeFactor();
387 luPixel contentHeight = 2 * TQMAX(content->axis( context, tstyle, factor ),
388 content->getHeight() - content->axis( context, tstyle, factor ));
389 left->draw(painter, r, context, tstyle, style, contentHeight, myPos);
390 right->draw(painter, r, context, tstyle, style, contentHeight, myPos);
391 }
392
393 // Debug
394#if 0
395 painter.setBrush( TQt::NoBrush );
396 painter.setPen( TQt::red );
397 painter.drawRect( context.layoutUnitToPixelX( myPos.x()+left->getX() ),
398 context.layoutUnitToPixelY( myPos.y()+left->getY() ),
399 context.layoutUnitToPixelX( left->getWidth() ),
400 context.layoutUnitToPixelY( left->getHeight() ) );
401 painter.drawRect( context.layoutUnitToPixelX( myPos.x()+right->getX() ),
402 context.layoutUnitToPixelY( myPos.y()+right->getY() ),
403 context.layoutUnitToPixelX( right->getWidth() ),
404 context.layoutUnitToPixelY( right->getHeight() ) );
405#endif
406}
407
408
412void BracketElement::writeDom(TQDomElement element)
413{
415 element.setAttribute("LEFT", leftType);
416 element.setAttribute("RIGHT", rightType);
417}
418
424{
426 return false;
427 }
428 TQString leftStr = element.attribute("LEFT");
429 if(!leftStr.isNull()) {
430 leftType = static_cast<SymbolType>(leftStr.toInt());
431 }
432 TQString rightStr = element.attribute("RIGHT");
433 if(!rightStr.isNull()) {
434 rightType = static_cast<SymbolType>(rightStr.toInt());
435 }
436 return true;
437}
438
443bool BracketElement::readAttributesFromMathMLDom(const TQDomElement& element)
444{
446 return false;
447 }
448
449 if ( element.tagName().lower() == "mo" ) {
450 m_operator = true;
451 // TODO: parse attributes in section 3.2.5.2
452 }
453 else { // mfenced, see attributes in section 3.3.8.2
454 leftType = LeftRoundBracket;
455 rightType = RightRoundBracket;
456 TQString openStr = element.attribute( "open" ).stripWhiteSpace();
457 if ( !openStr.isNull() ) {
458 m_customLeft = true;
459 if ( openStr == "[" )
460 leftType = LeftSquareBracket;
461 else if ( openStr == "]" )
462 leftType = RightSquareBracket;
463 else if ( openStr == "{" )
464 leftType = LeftCurlyBracket;
465 else if ( openStr == "}" )
466 leftType = RightCurlyBracket;
467 else if ( openStr == "<" )
468 leftType = LeftCornerBracket;
469 else if ( openStr == ">" )
470 leftType = RightCornerBracket;
471 else if ( openStr == "(" )
472 leftType = LeftRoundBracket;
473 else if ( openStr == ")" )
474 leftType = RightRoundBracket;
475 else if ( openStr == "/" )
476 leftType = SlashBracket;
477 else if ( openStr == "\\" )
478 leftType = BackSlashBracket;
479 else // TODO: Check for entity references
480 leftType = LeftRoundBracket;
481 }
482 TQString closeStr = element.attribute( "close" ).stripWhiteSpace();
483 if ( !closeStr.isNull() ) {
484 m_customRight = true;
485 if ( closeStr == "[" )
486 rightType = LeftSquareBracket;
487 else if ( closeStr == "]" )
488 rightType = RightSquareBracket;
489 else if ( closeStr == "{" )
490 rightType = LeftCurlyBracket;
491 else if ( closeStr == "}" )
492 rightType = RightCurlyBracket;
493 else if ( closeStr == "<" )
494 rightType = LeftCornerBracket;
495 else if ( closeStr == ">" )
496 rightType = RightCornerBracket;
497 else if ( closeStr == "(" )
498 rightType = LeftRoundBracket;
499 else if ( closeStr == ")" )
500 rightType = RightRoundBracket;
501 else if ( closeStr == "/" )
502 rightType = SlashBracket;
503 else if ( closeStr == "\\" )
504 rightType = BackSlashBracket;
505 else // TODO: Check for entity references
506 rightType = LeftRoundBracket;
507 }
508 m_separators = element.attribute( "separators" ).simplifyWhiteSpace();
509 }
510 return true;
511}
512
519{
520 bool empty = false;
521 int nodeCounter = 0;
522 if ( m_operator ) {
523 node = node.parentNode();
524 TQDomNode open = node;
525 TQDomNode parent = node.parentNode();
526 if ( ! operatorType( node, true ) )
527 return -1;
528 int nodeNum = searchOperator( node );
529 if ( nodeNum == -1 ) // Closing bracket not found
530 return -1;
531 if ( nodeNum == 0 ) { // Empty content
532 empty = true;
533 }
534 else if ( nodeNum == 1 ) {
535 do {
536 node = node.nextSibling();
537 nodeCounter++;
538 } while ( ! node.isElement() );
539 }
540 else { // More than two elements inside, infer a mrow
541 nodeCounter += nodeNum;
542 kdWarning() << "NodeNum: " << nodeNum << endl;
543 TQDomDocument doc = node.ownerDocument();
544 TQDomElement de = doc.createElement( "mrow" );
545 int i = 0;
546 do {
547 TQDomNode n = node.nextSibling();
548 de.appendChild( node.toElement() );
549 node = n;
550 } while ( ++i < nodeNum );
551 parent.insertAfter( de, open );
552 node = de;
553 kdWarning() << doc.toString() << endl;
554 }
555 }
556 else {
557 // if it's a mfence tag, we need to convert to equivalent expanded form.
558 // See section 3.3.8
559 while ( ! node.isNull() && ! node.isElement() )
560 node = node.nextSibling();
561 TQDomNode next = node.nextSibling();
562 while ( ! next.isNull() && ! next.isElement() )
563 next = next.nextSibling();
564 if ( ! next.isNull()) {
565 TQDomDocument doc = node.ownerDocument();
566 TQDomNode parent = node.parentNode();
567 TQString ns = parent.prefix();
568 TQDomElement de = doc.createElementNS( ns, "mrow" );
569 uint pos = 0;
570 while ( ! node.isNull() ) {
571 TQDomNode no = node.nextSibling();
572 while ( ! no.isNull() && ! no.isElement() )
573 no = no.nextSibling();
574 de.appendChild( node.toElement() );
575 if ( ! no.isNull() && ( m_separators.isNull() || ! m_separators.isEmpty() ) ) {
576 TQDomElement sep = doc.createElementNS( ns, "mo" );
577 de.appendChild( sep );
578 if ( m_separators.isNull() ) {
579 sep.appendChild( doc.createTextNode( "," ) );
580 }
581 else {
582 if ( m_separators.at( pos ).isSpace() ) {
583 pos++;
584 }
585 sep.appendChild( doc.createTextNode( TQString ( m_separators.at( pos ) ) ) );
586 }
587 if ( pos < m_separators.length() - 1 ) {
588 pos++;
589 }
590 }
591 node = no;
592 }
593 parent.appendChild( de );
594 node = parent.firstChild();
595 while ( ! node.isElement() )
596 node = node.nextSibling();
597 }
598 }
599 if ( ! empty ) {
600 int contentNumber = inherited::readContentFromMathMLDom( node );
601 if ( contentNumber == -1 )
602 return -1;
603 nodeCounter += contentNumber;
604 for (int i = 0; i < contentNumber; i++ ) {
605 if ( node.isNull() ) {
606 return -1;
607 }
608 node = node.nextSibling();
609 }
610 }
611 if ( m_operator ) {
612 int operatorNumber = operatorType( node, false );
613 if ( operatorNumber == -1 ) {
614 return -1;
615 }
616 nodeCounter += operatorNumber;
617 }
618 kdDebug( DEBUGID ) << "Number of bracket nodes: " << nodeCounter << endl;
619 return nodeCounter;
620}
621
623{
624 TQString ls,rs,cs;
625 cs=getContent()->toLatex();
626 ls="\\left"+latexString(leftType) + " ";
627 rs=" \\right"+latexString(rightType);
628
629 return ls+cs+rs;
630}
631
632TQString BracketElement::latexString(char type)
633{
634 switch (type) {
635 case ']':
636 return "]";
637 case '[':
638 return "[";
639 case '{':
640 return "\\{";
641 case '}':
642 return "\\}";
643 case '(':
644 return "(";
645 case ')':
646 return ")";
647 case '|':
648 return "|";
649 case '<':
650 return "\\langle";
651 case '>':
652 return "\\rangle";
653 case '/':
654 return "/";
655 case '\\':
656 return "\\backslash";
657 }
658 return ".";
659}
660
661TQString BracketElement::formulaString()
662{
663 return "(" + getContent()->formulaString() + ")";
664}
665
666int BracketElement::operatorType( TQDomNode& node, bool open )
667{
668 int counter = 1;
669 SymbolType* type = open ? &leftType : &rightType;
670 while ( ! node.isNull() && ! node.isElement() ) {
671 node = node.nextSibling();
672 counter++;
673 }
674 if ( node.isElement() ) {
675 TQDomElement e = node.toElement();
676 TQDomNode child = e.firstChild();
677 if ( child.isEntityReference() ) {
678 kdWarning() << "Entity Reference\n";
679 TQString name = node.nodeName();
680 // TODO: To fully support these, SymbolType has to be extended,
681 // and better Unicode support is a must
682 // CloseCurlyDoubleQuote 0x201D
683 // CloseCurlyQoute 0x2019
684 // LeftCeiling 0x2308
685 // LeftDoubleBracket 0x301A
686 // LeftFloor 0x230A
687 // OpenCurlyDoubleQuote 0x201C
688 // OpenCurlyQuote 0x2018
689 // RightCeiling 0x2309
690 // RightDoubleBracket 0x301B
691 // RightFloor 0x230B
692 if ( name == "LeftAngleBracket" ) {
693 *type = LeftCornerBracket;
694 }
695 else if ( name == "RightAngleBracket" ) {
696 *type = RightCornerBracket;
697 }
698 else {
699 if ( open ) {
700 *type = LeftRoundBracket;
701 }
702 else
703 *type = RightRoundBracket;
704 }
705 }
706 else {
707 TQString s = e.text();
708 if ( s.isNull() )
709 return -1;
710 *type = static_cast<SymbolType>( TQString::number( s.at( 0 ).latin1() ).toInt() );
711 }
712 }
713 else {
714 return -1;
715 }
716 return counter;
717}
718
719int BracketElement::searchOperator( const TQDomNode& node )
720{
721 TQDomNode n = node;
722 for ( int i = -2; ! n.isNull(); n = n.nextSibling() ) {
723 if ( n.isElement() ) {
724 i++;
725 TQDomElement e = n.toElement();
726 if ( e.tagName().lower() == "mo" ) {
727 // Try to guess looking at attributes
728 TQString form = e.attribute( "form" );
729 TQString f;
730 if ( ! form.isNull() ) {
731 f = form.stripWhiteSpace().lower();
732 }
733 TQString fence = e.attribute( "fence" );
734 if ( ! fence.isNull() ) {
735 if ( fence.stripWhiteSpace().lower() == "false" ) {
736 continue;
737 }
738 if ( ! f.isNull() ) {
739 if ( f == "postfix" ) {
740 return i;
741 }
742 else {
743 continue;
744 }
745 }
746 }
747
748 // Guess looking at contents
749 TQDomNode child = e.firstChild();
750 TQString name;
751 if ( child.isText() )
752 name = child.toText().data().stripWhiteSpace();
753 else if ( child.isEntityReference() )
754 name = child.nodeName();
755 else
756 continue;
757 if ( name == ")"
758 || name == "]"
759 || name == "}"
760 || name == "CloseCurlyDoubleQuote"
761 || name == "CloseCurlyQuote"
762 || name == "RightAngleBracket"
763 || name == "RightCeiling"
764 || name == "RightDoubleBracket"
765 || name == "RightFloor" ) {
766 if ( f.isNull() || f == "postfix" )
767 return i;
768 }
769 if ( name == "("
770 || name == "["
771 || name == "{"
772 || name == "LeftAngleBracket"
773 || name == "LeftCeiling"
774 || name == "LeftDoubleBracket"
775 || name == "LeftFloor"
776 || name == "OpenCurlyQuote" ) {
777 if ( ! f.isNull() && f == "postfix" )
778 return i;
779 }
780 }
781 }
782 }
783 return -1;
784}
785
786
787void BracketElement::writeMathMLAttributes( TQDomElement& element ) const
788{
789 if ( left->getType() != LeftRoundBracket ||
790 right->getType() != RightRoundBracket )
791 {
792 element.setAttribute( "open", TQString( TQChar( leftType ) ) );
793 element.setAttribute( "close", TQString( TQChar( rightType ) ) );
794 }
795 if ( ! m_separators.isNull() ) {
796 element.setAttribute( "separators", m_separators );
797 }
798}
799
800OverlineElement::OverlineElement( BasicElement* parent )
801 : SingleContentElement( parent )
802{
803}
804
805OverlineElement::~OverlineElement()
806{
807}
808
809OverlineElement::OverlineElement( const OverlineElement& other )
810 : SingleContentElement( other )
811{
812}
813
814
816{
817 return visitor->visit( this );
818}
819
820
822{
823 formula()->tell( i18n( "Overline" ) );
824}
825
826
829 ContextStyle::IndexStyle istyle,
830 StyleAttributes& style )
831{
832 SequenceElement* content = getContent();
833 content->calcSizes(context, tstyle,
834 context.convertIndexStyleLower(istyle), style );
835
836 //luPixel distX = context.ptToPixelX( context.getThinSpace( tstyle, style.sizeFactor() ) );
837 luPixel distY = context.ptToPixelY( context.getThinSpace( tstyle, style.sizeFactor() ) );
838 //luPixel unit = (content->getHeight() + distY)/ 3;
839
840 setWidth( content->getWidth() );
841 setHeight( content->getHeight() + distY );
842
843 content->setX( 0 );
844 content->setY( distY );
845 setBaseline(content->getBaseline() + content->getY());
846}
847
848void OverlineElement::draw( TQPainter& painter, const LuPixelRect& r,
849 const ContextStyle& context,
851 ContextStyle::IndexStyle istyle,
852 StyleAttributes& style,
853 const LuPixelPoint& parentOrigin )
854{
855 LuPixelPoint myPos( parentOrigin.x()+getX(), parentOrigin.y()+getY() );
856 //if ( !LuPixelRect( myPos.x(), myPos.y(), getWidth(), getHeight() ).intersects( r ) )
857 // return;
858
859 SequenceElement* content = getContent();
860 content->draw( painter, r, context, tstyle,
861 context.convertIndexStyleLower( istyle ), style, myPos );
862
863 luPixel x = myPos.x();
864 luPixel y = myPos.y();
865 //int distX = context.getDistanceX(tstyle);
866 double factor = style.sizeFactor();
867 luPixel distY = context.ptToPixelY( context.getThinSpace( tstyle, factor ) );
868 //luPixel unit = (content->getHeight() + distY)/ 3;
869
870 painter.setPen( TQPen( context.getDefaultColor(),
871 context.layoutUnitToPixelY( context.getLineWidth( factor ) ) ) );
872
873 painter.drawLine( context.layoutUnitToPixelX( x ),
874 context.layoutUnitToPixelY( y+distY/3 ),
875 context.layoutUnitToPixelX( x+content->getWidth() ),
876 context.layoutUnitToPixelY( y+distY/3 ) );
877}
878
879
881{
882 return "\\overline{" + getContent()->toLatex() + "}";
883}
884
885TQString OverlineElement::formulaString()
886{
887 return getContent()->formulaString();
888}
889
890void OverlineElement::writeMathML( TQDomDocument& doc, TQDomNode& parent, bool oasisFormat ) const
891{
892 TQDomElement de = doc.createElement( oasisFormat ? "math:mover" : "mover" );
893 SingleContentElement::writeMathML( doc, de, oasisFormat );
894 TQDomElement op = doc.createElement( oasisFormat ? "math:mo" : "mo" );
895 // is this the right entity? Mozilla renders it correctly.
896 op.appendChild( doc.createEntityReference( "OverBar" ) );
897 de.appendChild( op );
898 parent.appendChild( de );
899}
900
901
902UnderlineElement::UnderlineElement( BasicElement* parent )
903 : SingleContentElement( parent )
904{
905}
906
907UnderlineElement::~UnderlineElement()
908{
909}
910
911
912UnderlineElement::UnderlineElement( const UnderlineElement& other )
913 : SingleContentElement( other )
914{
915}
916
917
919{
920 return visitor->visit( this );
921}
922
923
925{
926 formula()->tell( i18n( "Underline" ) );
927}
928
929
932 ContextStyle::IndexStyle istyle,
933 StyleAttributes& style )
934{
935 SequenceElement* content = getContent();
936 double factor = style.sizeFactor();
937 content->calcSizes(context, tstyle,
938 context.convertIndexStyleLower(istyle), style );
939
940 //luPixel distX = context.ptToPixelX( context.getThinSpace( tstyle ) );
941 luPixel distY = context.ptToPixelY( context.getThinSpace( tstyle, factor ) );
942 //luPixel unit = (content->getHeight() + distY)/ 3;
943
944 setWidth( content->getWidth() );
945 setHeight( content->getHeight() + distY );
946
947 content->setX( 0 );
948 content->setY( 0 );
949 setBaseline(content->getBaseline() + content->getY());
950}
951
952void UnderlineElement::draw( TQPainter& painter, const LuPixelRect& r,
953 const ContextStyle& context,
955 ContextStyle::IndexStyle istyle,
956 StyleAttributes& style,
957 const LuPixelPoint& parentOrigin )
958{
959 LuPixelPoint myPos( parentOrigin.x()+getX(), parentOrigin.y()+getY() );
960 //if ( !LuPixelRect( myPos.x(), myPos.y(), getWidth(), getHeight() ).intersects( r ) )
961 // return;
962
963 SequenceElement* content = getContent();
964 content->draw( painter, r, context, tstyle,
965 context.convertIndexStyleLower( istyle ), style, myPos );
966
967 luPixel x = myPos.x();
968 luPixel y = myPos.y();
969 //int distX = context.getDistanceX(tstyle);
970 //luPixel distY = context.ptToPixelY( context.getThinSpace( tstyle ) );
971 //luPixel unit = (content->getHeight() + distY)/ 3;
972
973 double factor = style.sizeFactor();
974 painter.setPen( TQPen( context.getDefaultColor(),
975 context.layoutUnitToPixelY( context.getLineWidth( factor ) ) ) );
976
977 painter.drawLine( context.layoutUnitToPixelX( x ),
978 context.layoutUnitToPixelY( y+getHeight()-context.getLineWidth( factor ) ),
979 context.layoutUnitToPixelX( x+content->getWidth() ),
980 context.layoutUnitToPixelY( y+getHeight()-context.getLineWidth( factor ) ) );
981}
982
983
985{
986 return "\\underline{" + getContent()->toLatex() + "}";
987}
988
989TQString UnderlineElement::formulaString()
990{
991 return getContent()->formulaString();
992}
993
994void UnderlineElement::writeMathML( TQDomDocument& doc, TQDomNode& parent, bool oasisFormat ) const
995{
996 TQDomElement de = doc.createElement( oasisFormat ? "math:munder" : "munder" );
997 SingleContentElement::writeMathML( doc, de, oasisFormat );
998 TQDomElement op = doc.createElement( oasisFormat ? "math:mo" : "mo" );
999 // is this the right entity? Mozilla renders it correctly.
1000 op.appendChild( doc.createEntityReference( "UnderBar" ) );
1001 de.appendChild( op );
1002 parent.appendChild( de );
1003}
1004
1005KFORMULA_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 TQString getTagName() const
Returns the tag name of this element type.
virtual void selectChild(FormulaCursor *, BasicElement *)
Sets the cursor to select the child.
virtual TQChar getCharacter() const
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.
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.
A left and/or right bracket around one child.
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 writeDom(TQDomElement element)
Appends our attributes to the dom element.
virtual TQString toLatex()
virtual void entered(SequenceElement *child)
The cursor has entered one of our child sequences.
virtual bool accept(ElementVisitor *visitor)
Visit this element.
virtual bool readAttributesFromMathMLDom(const TQDomElement &element)
Reads our attributes from the MathML element.
virtual bool readAttributesFromDom(TQDomElement element)
Reads our attributes from the element.
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 calcSizes(const ContextStyle &context, ContextStyle::TextStyle tstyle, ContextStyle::IndexStyle istyle, StyleAttributes &style)
Calculates our width and height and our children's parentPosition.
virtual int readContentFromMathMLDom(TQDomNode &node)
Reads our content from the MathML node.
Contains all the style information for the formela.
TextStyle
Textstyles like in TeX.
IndexStyle convertIndexStyleLower(IndexStyle) const
Index-style-conversions a la TeX.
luPixel getLineWidth(double factor) const
All simple lines like the one that makes up a fraction.
Base for all font commands that act on the current selection.
The selection.
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.
void tell(const TQString &msg)
Tell the user something has happened.
int layoutUnitToPixelX(int lupix) const
The "layout unit pixel" -> "[zoomed] view pixel" conversions.
A line above the content.
virtual TQString toLatex()
virtual void entered(SequenceElement *child)
The cursor has entered one of our child sequences.
virtual void writeMathML(TQDomDocument &doc, TQDomNode &parent, bool oasisFormat=false) const
Same as above, just MathML.
virtual bool accept(ElementVisitor *visitor)
Visit this element.
virtual void calcSizes(const ContextStyle &context, ContextStyle::TextStyle tstyle, ContextStyle::IndexStyle istyle, StyleAttributes &style)
Calculates our width and height and our children's parentPosition.
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.
The element that contains a number of children.
virtual TQString toLatex()
virtual bool isTextOnly() const
virtual void moveEnd(FormulaCursor *cursor)
Moves the cursor to the last position in this sequence.
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.
The base of (all) elements that contain just one content 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 moveUp(FormulaCursor *cursor, BasicElement *from)
Enters this element while moving up 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 TQChar getCharacter() const
virtual void normalize(FormulaCursor *, Direction)
Moves the cursor to a normal place where new elements might be inserted.
virtual void moveRight(FormulaCursor *cursor, BasicElement *from)
Enters this element while moving to the right starting inside the element ‘from’.
virtual void moveDown(FormulaCursor *cursor, BasicElement *from)
Enters this element while moving down starting inside the element ‘from’.
virtual SequenceElement * getMainChild()
Removes the child.
virtual void selectChild(FormulaCursor *cursor, BasicElement *child)
Sets the cursor to select the child.
virtual void moveLeft(FormulaCursor *cursor, BasicElement *from)
Enters this element while moving to the left starting inside the element ‘from’.
virtual void dispatchFontCommand(FontCommand *cmd)
Dispatch this FontCommand to all our TextElement children.
virtual int readContentFromMathMLDom(TQDomNode &node)
Reads our content from the MathML node.
virtual void remove(FormulaCursor *, TQPtrList< BasicElement > &, Direction)
Removes all selected children and returns them.
A line below the content.
virtual bool accept(ElementVisitor *visitor)
Visit this element.
virtual void writeMathML(TQDomDocument &doc, TQDomNode &parent, bool oasisFormat=false) const
Same as above, just MathML.
virtual TQString toLatex()
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 entered(SequenceElement *child)
The cursor has entered one of our child sequences.
virtual void calcSizes(const ContextStyle &context, ContextStyle::TextStyle tstyle, ContextStyle::IndexStyle istyle, StyleAttributes &style)
Calculates our width and height and our children's parentPosition.
TDEAction * open(const TQObject *recvr, const char *slot, TDEActionCollection *parent, const char *name=0)
const char * name(StdAction id)