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 2006 Martin Pfeiffer <hubipete@gmx.net>
5 Copyright (C) 2007 Alfredo Beaumont Sainz <alfredo.beaumont@gmail.com>
6 2009 Jeremias Epperlein <jeeree@web.de>
7 Copyright (C) 2010 Inge Wallin <inge@lysator.liu.se>
8
9 This library is free software; you can redistribute it and/or
10 modify it under the terms of the GNU Library General Public
11 License as published by the Free Software Foundation; either
12 version 2 of the License, or (at your option) any later version.
13
14 This library is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Library General Public License for more details.
18
19 You should have received a copy of the GNU Library General Public License
20 along with this library; see the file COPYING.LIB. If not, write to
21 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 Boston, MA 02110-1301, USA.
23 */
24
25 #include "RootElement.h"
26
27 #include "AttributeManager.h"
28 #include "FormulaCursor.h"
29 #include "RowElement.h"
30 #include "FormulaDebug.h"
31
32 #include <KoXmlReader.h>
33
34 #include <QPainter>
35 #include <QPen>
36
RootElement(BasicElement * parent)37 RootElement::RootElement( BasicElement* parent ) : FixedElement( parent )
38 {
39 m_radicand = new RowElement( this );
40 m_exponent = new RowElement( this );
41 }
42
~RootElement()43 RootElement::~RootElement()
44 {
45 delete m_radicand;
46 delete m_exponent;
47 }
48
paint(QPainter & painter,AttributeManager * am)49 void RootElement::paint( QPainter& painter, AttributeManager* am )
50 {
51 Q_UNUSED( am )
52 QPen pen;
53 pen.setWidth( m_lineThickness );
54 painter.setPen( pen );
55 painter.drawPath( m_rootSymbol );
56 }
57
layout(const AttributeManager * am)58 void RootElement::layout( const AttributeManager* am )
59 {
60 // Calculate values to layout the root symbol
61 qreal thinSpace = am->layoutSpacing( this );
62 qreal symbolHeight = m_radicand->baseLine();
63 if( m_radicand->height() > symbolHeight*1.3 ) symbolHeight = m_radicand->height();
64 symbolHeight += thinSpace;
65 qreal tickWidth = symbolHeight / 3.0; // The width of the root symbol's tick part
66
67 m_lineThickness = am->lineThickness(this);
68
69 // The root symbol an xOffset and yOffset due to the exponent.
70 qreal xOffset = m_exponent->width() - tickWidth/2;
71 xOffset = xOffset < 0 ? 0 : xOffset; // no negative offset for the root symbol
72 qreal yOffset = m_exponent->height() - 2.0*symbolHeight/5.0;
73 yOffset = yOffset < 0 ? 0 : yOffset;
74
75 // Set the roots dimensions
76 setBaseLine( yOffset + thinSpace + m_radicand->baseLine() );
77 setHeight( yOffset + thinSpace + m_radicand->height() );
78 setWidth( xOffset + tickWidth + m_radicand->width() + thinSpace );
79
80 // Place the children in the correct place
81 m_radicand->setOrigin( QPointF( xOffset+tickWidth+thinSpace, yOffset+thinSpace ) );
82 m_exponent->setOrigin( QPointF( 0.0, 0.0 ) );
83
84 // Draw the actual root symbol to a path as buffer
85 m_rootSymbol = QPainterPath();
86 m_rootSymbol.moveTo( xOffset+m_lineThickness, yOffset + 2.0 * symbolHeight / 3.0 );
87 m_rootSymbol.lineTo( m_rootSymbol.currentPosition().x()+tickWidth*0.5, yOffset + symbolHeight - m_lineThickness/2 );
88 m_rootSymbol.lineTo( m_rootSymbol.currentPosition().x()+tickWidth*0.5, yOffset + m_lineThickness/2 );
89 m_rootSymbol.lineTo( width()-m_lineThickness/2, yOffset + m_lineThickness/2);
90 }
91
childElements() const92 const QList<BasicElement*> RootElement::childElements() const
93 {
94 QList<BasicElement*> tmp;
95 tmp << m_exponent << m_radicand;
96 return tmp;
97 }
98
99
100 // QList< BasicElement* > RootElement::elementsBetween(int pos1, int pos2) const
101 // {
102 // QList<BasicElement*> tmp;
103 // if (pos1==0 && pos2 >0) {
104 // tmp.append(m_exponent);
105 // }
106 // if (pos1<3 && pos2==3) {
107 // tmp.append(m_radicand);
108 // }
109 // return tmp;
110 // }
111
112 // int RootElement::positionOfChild(BasicElement* child) const
113 // {
114 // if (child==m_exponent) {
115 // return 0;
116 // } else if (child==m_radicand) {
117 // return 2;
118 // }
119 // return -1;
120 // }
121
setCursorTo(FormulaCursor & cursor,QPointF point)122 bool RootElement::setCursorTo(FormulaCursor& cursor, QPointF point)
123 {
124 if (cursor.isSelecting()) {
125 return false;
126 }
127 if (m_exponent->boundingRect().contains(point)) {
128 return m_exponent->setCursorTo(cursor, point-m_exponent->origin());
129 } else {
130 return m_radicand->setCursorTo(cursor, point-m_radicand->origin());
131 }
132 }
133
moveCursor(FormulaCursor & newcursor,FormulaCursor & oldcursor)134 bool RootElement::moveCursor(FormulaCursor& newcursor, FormulaCursor& oldcursor)
135 {
136 if (newcursor.isSelecting()) {
137 return false;
138 } else {
139 return moveHorSituation(newcursor,oldcursor,0,1);
140 }
141 }
142
143
endPosition() const144 int RootElement::endPosition() const
145 {
146 return 3;
147 }
148
149
replaceChild(BasicElement * oldelement,BasicElement * newelement)150 bool RootElement::replaceChild ( BasicElement* oldelement, BasicElement* newelement )
151 {
152 if (newelement->elementType()==Row) {
153 RowElement* newrow = static_cast<RowElement*>(newelement);
154 if (oldelement == m_exponent) {
155 m_exponent = newrow;
156 return true;
157 } else if (oldelement == m_radicand) {
158 m_radicand = newrow;
159 return true;
160 }
161 }
162 return false;
163 }
164
elementType() const165 ElementType RootElement::elementType() const
166 {
167 return Root;
168 }
169
readMathMLContent(const KoXmlElement & element)170 bool RootElement::readMathMLContent( const KoXmlElement& element )
171 {
172 KoXmlElement tmp;
173 int counter = 0;
174 forEachElement(tmp, element) {
175 if (counter==0) {
176 loadElement(tmp, &m_radicand);
177 } else if (counter==1) {
178 loadElement(tmp, &m_exponent);
179 } else {
180 debugFormula << "Too many arguments to mroot";
181 }
182 counter++;
183 }
184 if (counter < 2) {
185 debugFormula << "Not enough arguments to mroot";
186 }
187
188 return true;
189 }
190
writeMathMLContent(KoXmlWriter * writer,const QString & ns) const191 void RootElement::writeMathMLContent( KoXmlWriter* writer, const QString& ns ) const
192 {
193 Q_ASSERT( m_radicand );
194 Q_ASSERT( m_exponent );
195 m_radicand->writeMathML( writer, ns );
196 m_exponent->writeMathML( writer, ns );
197 }
198
199