lib

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
70BasicElement* SingleContentElement::goToPos( FormulaCursor* cursor, bool& handled,
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
88{
89 content->dispatchFontCommand( cmd );
90}
91
92void SingleContentElement::moveLeft(FormulaCursor* cursor, BasicElement* from)
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
108void SingleContentElement::moveRight(FormulaCursor* cursor, BasicElement* from)
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
124void SingleContentElement::moveUp(FormulaCursor* cursor, BasicElement* /*from*/)
125{
126 getParent()->moveUp(cursor, this);
127}
128
129void SingleContentElement::moveDown(FormulaCursor* cursor, BasicElement* /*from*/)
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
157{
158 return content;
159}
160
161void SingleContentElement::selectChild(FormulaCursor* cursor, BasicElement* child)
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
248void BracketElement::entered( SequenceElement* /*child*/ )
249{
250 formula()->tell( i18n( "Delimited list" ) );
251}
252
253
254BasicElement* BracketElement::goToPos( FormulaCursor* cursor, bool& handled,
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
821void OverlineElement::entered( SequenceElement* /*child*/ )
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
924void UnderlineElement::entered( SequenceElement* /*child*/ )
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.
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 TQString getTagName() const
Returns the tag name of this element 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 writeDom(TQDomElement element)
Appends our attributes to the dom element.
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)
Draws the whole element including its children.
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 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.
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()
Draws the whole element including its children.
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.
The element that contains a number of children.
virtual bool isTextOnly() const
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 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 SequenceElement * getMainChild()
Removes the child.
virtual void selectChild(FormulaCursor *cursor, BasicElement *child)
Sets the cursor to select the child.
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)
Enters this element while moving to the left starting inside the element `from'.
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()
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)