lib

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
129void RootElement::entered( SequenceElement* child )
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
140BasicElement* RootElement::goToPos( FormulaCursor* cursor, bool& handled,
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
305void RootElement::moveLeft(FormulaCursor* cursor, BasicElement* from)
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
334void RootElement::moveRight(FormulaCursor* cursor, BasicElement* from)
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
363void RootElement::moveUp(FormulaCursor* cursor, BasicElement* from)
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
391void RootElement::moveDown(FormulaCursor* cursor, BasicElement* from)
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
499void RootElement::selectChild(FormulaCursor* cursor, BasicElement* child)
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.
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 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.
The document.
FormulaCursor * activeCursor()
Contains all the style information for the formela.
TextStyle
Textstyles like in TeX.
luPixel getLineWidth(double factor) const
All simple lines like the one that makes up a fraction.
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.
void cursorHasMoved(FormulaCursor *)
Gets called when a request has the side effect of moving the cursor.
virtual void changed()
Gets called whenever something changes and we need to recalc.
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 insert(FormulaCursor *, TQPtrList< BasicElement > &, Direction)
Enters this element while moving to the left starting inside the element `from'.
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 SequenceElement * getMainChild()
Removes the child.
virtual bool accept(ElementVisitor *visitor)
Visit this element.
virtual TQString toLatex()
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)
Draws the whole element including its 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 calcSizes(const ContextStyle &cstyle, ContextStyle::TextStyle tstyle, ContextStyle::IndexStyle istyle, StyleAttributes &style)
Calculates our width and height and our children's parentPosition.
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.
uint countChildren() 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...