rootelement.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#include <tqpen.h>
23
24#include <kdebug.h>
25#include <tdelocale.h>
26
27#include "elementvisitor.h"
28#include "formulacursor.h"
29#include "formulaelement.h"
30#include "kformulacommand.h"
31#include "rootelement.h"
32#include "sequenceelement.h"
33
34KFORMULA_NAMESPACE_BEGIN
35
36
37class RootSequenceElement : public SequenceElement {
38 typedef SequenceElement inherited;
39public:
40
41 RootSequenceElement( BasicElement* parent = 0 ) : SequenceElement( parent ) {}
42 virtual RootSequenceElement* clone() {
43 return new RootSequenceElement( *this );
44 }
45
54 virtual KCommand* buildCommand( Container*, Request* );
55};
56
57
58KCommand* RootSequenceElement::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 IndexRequest* ir = static_cast<IndexRequest*>( request );
73 if ( ir->index() == upperLeftPos ) {
74 RootElement* element = static_cast<RootElement*>( getParent() );
75 ElementIndexPtr index = element->getIndex();
76 if ( !index->hasIndex() ) {
77 KFCAddGenericIndex* command = new KFCAddGenericIndex( container, index );
78 return command;
79 }
80 else {
81 index->moveToIndex( cursor, afterCursor );
82 cursor->setSelection( false );
83 formula()->cursorHasMoved( cursor );
84 return 0;
85 }
86 }
87 }
88 default:
89 break;
90 }
91 return inherited::buildCommand( container, request );
92}
93
94
95RootElement::RootElement(BasicElement* parent)
96 : BasicElement(parent)
97{
98 content = new RootSequenceElement( this );
99 index = 0;
100}
101
102RootElement::~RootElement()
103{
104 delete index;
105 delete content;
106}
107
108
109RootElement::RootElement( const RootElement& other )
110 : BasicElement( other )
111{
112 content = new RootSequenceElement( *dynamic_cast<RootSequenceElement*>( other.content ) );
113 if ( other.index ) {
114 index = new SequenceElement( *( other.index ) );
115 index->setParent( this );
116 }
117 else {
118 index = 0;
119 }
120}
121
122
124{
125 return visitor->visit( this );
126}
127
128
130{
131 if ( child == content ) {
132 formula()->tell( i18n( "Main list of root" ) );
133 }
134 else {
135 formula()->tell( i18n( "Index" ) );
136 }
137}
138
139
141 const LuPixelPoint& point, const LuPixelPoint& parentOrigin)
142{
143 BasicElement* e = BasicElement::goToPos(cursor, handled, point, parentOrigin);
144 if (e != 0) {
145 LuPixelPoint myPos(parentOrigin.x() + getX(),
146 parentOrigin.y() + getY());
147
148 e = content->goToPos(cursor, handled, point, myPos);
149 if (e != 0) {
150 return e;
151 }
152 if (hasIndex()) {
153 e = index->goToPos(cursor, handled, point, myPos);
154 if (e != 0) {
155 return e;
156 }
157 }
158
159 //int dx = point.x() - myPos.x();
160 luPixel dy = point.y() - myPos.y();
161
162 // the position after the index
163 if (hasIndex()) {
164 if (dy < index->getHeight()) {
165 index->moveLeft(cursor, this);
166 handled = true;
167 return index;
168 }
169 }
170
171 return this;
172 }
173 return 0;
174}
175
176
183 ContextStyle::IndexStyle istyle,
184 StyleAttributes& style )
185{
186 content->calcSizes( context, tstyle,
187 context.convertIndexStyleLower(istyle), style );
188
189 luPixel indexWidth = 0;
190 luPixel indexHeight = 0;
191 if (hasIndex()) {
192 index->calcSizes( context,
193 context.convertTextStyleIndex(tstyle),
194 context.convertIndexStyleUpper(istyle),
195 style );
196 indexWidth = index->getWidth();
197 indexHeight = index->getHeight();
198 }
199
200 double factor = style.sizeFactor();
201 luPixel distX = context.ptToPixelX( context.getThinSpace( tstyle, factor ) );
202 luPixel distY = context.ptToPixelY( context.getThinSpace( tstyle, factor ) );
203 luPixel unit = (content->getHeight() + distY)/ 3;
204
205 if (hasIndex()) {
206 if (indexWidth > unit) {
207 index->setX(0);
208 rootOffset.setX( indexWidth - unit );
209 }
210 else {
211 index->setX( ( unit - indexWidth )/2 );
212 rootOffset.setX(0);
213 }
214 if (indexHeight > unit) {
215 index->setY(0);
216 rootOffset.setY( indexHeight - unit );
217 }
218 else {
219 index->setY( unit - indexHeight );
220 rootOffset.setY(0);
221 }
222 }
223 else {
224 rootOffset.setX(0);
225 rootOffset.setY(0);
226 }
227
228 setWidth( content->getWidth() + unit+unit/3+ rootOffset.x() + distX/2 );
229 setHeight( content->getHeight() + distY*2 + rootOffset.y() );
230
231 content->setX( rootOffset.x() + unit+unit/3 );
232 content->setY( rootOffset.y() + distY );
233 setBaseline(content->getBaseline() + content->getY());
234}
235
241void RootElement::draw( TQPainter& painter, const LuPixelRect& r,
242 const ContextStyle& context,
244 ContextStyle::IndexStyle istyle,
245 StyleAttributes& style,
246 const LuPixelPoint& parentOrigin )
247{
248 LuPixelPoint myPos( parentOrigin.x()+getX(), parentOrigin.y()+getY() );
249 //if ( !LuPixelRect( myPos.x(), myPos.y(), getWidth(), getHeight() ).intersects( r ) )
250 // return;
251
252 content->draw( painter, r, context, tstyle,
253 context.convertIndexStyleLower(istyle), style, myPos);
254 if (hasIndex()) {
255 index->draw(painter, r, context,
256 context.convertTextStyleIndex(tstyle),
257 context.convertIndexStyleUpper(istyle), style, myPos);
258 }
259
260 luPixel x = myPos.x() + rootOffset.x();
261 luPixel y = myPos.y() + rootOffset.y();
262 //int distX = context.getDistanceX(tstyle);
263 double factor = style.sizeFactor();
264 luPixel distY = context.ptToPixelY( context.getThinSpace( tstyle, factor ) );
265 luPixel unit = (content->getHeight() + distY)/ 3;
266
267 painter.setPen( TQPen( style.color(),
268 context.layoutUnitToPixelX( 2*context.getLineWidth( factor ) ) ) );
269 painter.drawLine( context.layoutUnitToPixelX( x+unit/3 ),
270 context.layoutUnitToPixelY( y+unit+distY/3 ),
271 context.layoutUnitToPixelX( x+unit/2+unit/3 ),
272 context.layoutUnitToPixelY( myPos.y()+getHeight() ) );
273
274 painter.setPen( TQPen( style.color(),
275 context.layoutUnitToPixelY( context.getLineWidth( factor ) ) ) );
276
277 painter.drawLine( context.layoutUnitToPixelX( x+unit+unit/3 ),
278 context.layoutUnitToPixelY( y+distY/3 ),
279 context.layoutUnitToPixelX( x+unit/2+unit/3 ),
280 context.layoutUnitToPixelY( myPos.y()+getHeight() ) );
281 painter.drawLine( context.layoutUnitToPixelX( x+unit+unit/3 ),
282 context.layoutUnitToPixelY( y+distY/3 ),
283 context.layoutUnitToPixelX( x+unit+unit/3+content->getWidth() ),
284 context.layoutUnitToPixelY( y+distY/3 ) );
285 painter.drawLine( context.layoutUnitToPixelX( x+unit/3 ),
286 context.layoutUnitToPixelY( y+unit+distY/2 ),
287 context.layoutUnitToPixelX( x ),
288 context.layoutUnitToPixelY( y+unit+unit/2 ) );
289}
290
291
293{
294 content->dispatchFontCommand( cmd );
295 if (hasIndex()) {
296 index->dispatchFontCommand( cmd );
297 }
298}
299
306{
307 if (cursor->isSelectionMode()) {
308 getParent()->moveLeft(cursor, this);
309 }
310 else {
311 bool linear = cursor->getLinearMovement();
312 if (from == getParent()) {
313 content->moveLeft(cursor, this);
314 }
315 else if (from == content) {
316 if (linear && hasIndex()) {
317 index->moveLeft(cursor, this);
318 }
319 else {
320 getParent()->moveLeft(cursor, this);
321 }
322 }
323 else {
324 getParent()->moveLeft(cursor, this);
325 }
326 }
327}
328
335{
336 if (cursor->isSelectionMode()) {
337 getParent()->moveRight(cursor, this);
338 }
339 else {
340 bool linear = cursor->getLinearMovement();
341 if (from == getParent()) {
342 if (linear && hasIndex()) {
343 index->moveRight(cursor, this);
344 }
345 else {
346 content->moveRight(cursor, this);
347 }
348 }
349 else if (from == index) {
350 content->moveRight(cursor, this);
351 }
352 else {
353 getParent()->moveRight(cursor, this);
354 }
355 }
356}
357
364{
365 if (cursor->isSelectionMode()) {
366 getParent()->moveUp(cursor, this);
367 }
368 else {
369 if (from == getParent()) {
370 content->moveRight(cursor, this);
371 }
372 else if (from == content) {
373 if (hasIndex()) {
374 index->moveRight(cursor, this);
375 }
376 else {
377 getParent()->moveUp(cursor, this);
378 }
379 }
380 else {
381 getParent()->moveUp(cursor, this);
382 }
383 }
384}
385
392{
393 if (cursor->isSelectionMode()) {
394 getParent()->moveDown(cursor, this);
395 }
396 else {
397 if (from == getParent()) {
398 if (hasIndex()) {
399 index->moveRight(cursor, this);
400 }
401 else {
402 content->moveRight(cursor, this);
403 }
404 }
405 else if (from == index) {
406 content->moveRight(cursor, this);
407 }
408 else {
409 getParent()->moveDown(cursor, this);
410 }
411 }
412}
413
418 TQPtrList<BasicElement>& newChildren,
419 Direction direction)
420{
421 if (cursor->getPos() == upperLeftPos) {
422 index = static_cast<SequenceElement*>(newChildren.take(0));
423 index->setParent(this);
424
425 if (direction == beforeCursor) {
426 index->moveLeft(cursor, this);
427 }
428 else {
429 index->moveRight(cursor, this);
430 }
431 cursor->setSelection(false);
432 formula()->changed();
433 }
434}
435
443 TQPtrList<BasicElement>& removedChildren,
444 Direction direction)
445{
446 switch (cursor->getPos()) {
447 case contentPos:
448 getParent()->selectChild(cursor, this);
449 getParent()->remove(cursor, removedChildren, direction);
450 break;
451 case upperLeftPos:
452 removedChildren.append(index);
453 formula()->elementRemoval(index);
454 index = 0;
455 cursor->setTo(this, upperLeftPos);
456 formula()->changed();
457 break;
458 }
459}
460
461
466void RootElement::normalize(FormulaCursor* cursor, Direction direction)
467{
468 if (direction == beforeCursor) {
469 content->moveLeft(cursor, this);
470 }
471 else {
472 content->moveRight(cursor, this);
473 }
474}
475
476
477// main child
478//
479// If an element has children one has to become the main one.
480
482{
483 return content;
484}
485
486// void RootElement::setMainChild(SequenceElement* child)
487// {
488// formula()->elementRemoval(content);
489// content = child;
490// content->setParent(this);
491// formula()->changed();
492// }
493
494
500{
501 if (child == content) {
502 cursor->setTo(this, contentPos);
503 }
504 else if (child == index) {
505 cursor->setTo(this, upperLeftPos);
506 }
507}
508
509
510void RootElement::moveToIndex(FormulaCursor* cursor, Direction direction)
511{
512 if (hasIndex()) {
513 if (direction == beforeCursor) {
514 index->moveLeft(cursor, this);
515 }
516 else {
517 index->moveRight(cursor, this);
518 }
519 }
520}
521
522void RootElement::setToIndex(FormulaCursor* cursor)
523{
524 cursor->setTo(this, upperLeftPos);
525}
526
527
531void RootElement::writeDom(TQDomElement element)
532{
533 BasicElement::writeDom(element);
534
535 TQDomDocument doc = element.ownerDocument();
536
537 TQDomElement con = doc.createElement("CONTENT");
538 con.appendChild(content->getElementDom(doc));
539 element.appendChild(con);
540
541 if(hasIndex()) {
542 TQDomElement ind = doc.createElement("ROOTINDEX");
543 ind.appendChild(index->getElementDom(doc));
544 element.appendChild(ind);
545 }
546}
547
552bool RootElement::readAttributesFromDom(TQDomElement element)
553{
555}
556
563{
565 return false;
566 }
567
568 if ( !buildChild( content, node, "CONTENT" ) ) {
569 kdWarning( DEBUGID ) << "Empty content in RootElement." << endl;
570 return false;
571 }
572 node = node.nextSibling();
573
574 if ( node.nodeName().upper() == "ROOTINDEX" ) {
575 if ( !buildChild( index=new SequenceElement( this ), node, "ROOTINDEX" ) ) {
576 return false;
577 }
578 }
579 // backward compatibility
580 else if ( node.nodeName().upper() == "INDEX" ) {
581 if ( !buildChild( index=new SequenceElement( this ), node, "INDEX" ) ) {
582 return false;
583 }
584 }
585 node = node.nextSibling();
586
587 return true;
588}
589
595bool RootElement::readAttributesFromMathMLDom(const TQDomElement& element)
596{
597 if ( element.tagName().lower() == "mroot" )
598 square = false;
599 else
600 square = true;
601 return true;
602}
603
604
611{
612 if ( BasicElement::readContentFromMathMLDom( node ) == -1 ) {
613 return -1;
614 }
615
616 if ( square ) {
617 // Any number of arguments are allowed
618 if ( content->readContentFromMathMLDom( node ) == -1 ) {
619 kdWarning( DEBUGID ) << "Empty content in RootElement." << endl;
620 return -1;
621 }
622 }
623 else {
624 // Exactly two arguments are required
625 int contentNumber = content->buildMathMLChild( node );
626 if ( contentNumber == -1 ) {
627 kdWarning( DEBUGID ) << "Empty content in RootElement." << endl;
628 return -1;
629 }
630 for (int i = 0; i < contentNumber; i++ ) {
631 if ( node.isNull() ) {
632 return -1;
633 }
634 node = node.nextSibling();
635 }
636
637 index = new SequenceElement( this );
638 if ( index->buildMathMLChild( node ) == -1 ) {
639 kdWarning( DEBUGID ) << "Empty index in RootElement." << endl;
640 return -1;
641 }
642 }
643
644 return 1;
645}
646
648{
649 TQString root;
650 root="\\sqrt";
651 if(hasIndex()) {
652 root+="[";
653 root+=index->toLatex();
654 root+="]";
655 }
656 root+="{";
657 root+=content->toLatex();
658 root+="}";
659
660 return root;
661}
662
663TQString RootElement::formulaString()
664{
665 if ( hasIndex() ) {
666 return "(" + content->formulaString() + ")**(1.0/(" + index->formulaString() + "))";
667 }
668 return "sqrt(" + content->formulaString() + ")";
669}
670
671void RootElement::writeMathMLContent( TQDomDocument& doc, TQDomElement& element, bool oasisFormat ) const
672{
673 content->writeMathML( doc, element, oasisFormat );
674 if( hasIndex() )
675 {
676 index->writeMathML( doc, element, oasisFormat );
677 }
678}
679
680KFORMULA_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 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.
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.
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.
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.
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.
int ptToPixelX(double pt) const
Basic pt to pixel and pixel to pt conversions, valid at any zoom level, as well as at the Layout Unit...
int layoutUnitToPixelX(int lupix) const
The "layout unit pixel" -> "[zoomed] view pixel" conversions.
A nice graphical root.
Definition rootelement.h:35
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 moveRight(FormulaCursor *cursor, BasicElement *from)
Enters this element while moving to the right starting inside the element ‘from’.
virtual void insert(FormulaCursor *, TQPtrList< BasicElement > &, Direction)
Reinserts the index if it has been removed.
void moveToIndex(FormulaCursor *, Direction)
Moves the cursor away from the given child.
virtual bool readAttributesFromMathMLDom(const TQDomElement &element)
Reads our attributes from the MathML element.
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 bool accept(ElementVisitor *visitor)
Visit this element.
virtual TQString toLatex()
virtual void moveUp(FormulaCursor *cursor, BasicElement *from)
Enters this element while moving up starting inside the element ‘from’.
virtual bool readAttributesFromDom(TQDomElement element)
Reads our attributes from the element.
virtual int readContentFromMathMLDom(TQDomNode &node)
Reads our content from the MathML node.
virtual bool readContentFromDom(TQDomNode &node)
Reads our content from the node.
virtual void entered(SequenceElement *child)
The cursor has entered one of our child sequences.
virtual void dispatchFontCommand(FontCommand *cmd)
Dispatch this FontCommand to all our TextElement children.
virtual void normalize(FormulaCursor *, Direction)
Moves the cursor to a normal place where new elements might be inserted.
virtual void writeDom(TQDomElement element)
Appends our attributes to the dom element.
virtual void moveLeft(FormulaCursor *cursor, BasicElement *from)
Enters this element while moving to the left starting inside the element ‘from’.
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 draw(TQPainter &painter, const LuPixelRect &r, const ContextStyle &cstyle, ContextStyle::TextStyle tstyle, ContextStyle::IndexStyle istyle, StyleAttributes &style, const LuPixelPoint &parentOrigin)
Draws the whole element including its children.
virtual void selectChild(FormulaCursor *cursor, BasicElement *child)
Sets the cursor to select the child.
virtual void remove(FormulaCursor *, TQPtrList< BasicElement > &, Direction)
Removes all selected children and returns them.
The element that contains a number of children.
virtual TQString toLatex()
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 int readContentFromMathMLDom(TQDomNode &node)
Reads our content from the MathML node.
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.