00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
#include <qpainter.h>
00022
#include <qpen.h>
00023
00024
#include <kdebug.h>
00025
#include <klocale.h>
00026
00027
#include "elementvisitor.h"
00028
#include "formulacursor.h"
00029
#include "formulaelement.h"
00030
#include "kformulacommand.h"
00031
#include "rootelement.h"
00032
#include "sequenceelement.h"
00033
00034 KFORMULA_NAMESPACE_BEGIN
00035
00036
00037
class RootSequenceElement :
public SequenceElement {
00038
typedef SequenceElement inherited;
00039
public:
00040
00041 RootSequenceElement(
BasicElement* parent = 0 ) :
SequenceElement( parent ) {}
00042
virtual RootSequenceElement* clone() {
00043
return new RootSequenceElement( *
this );
00044 }
00045
00054
virtual KCommand* buildCommand(
Container*, Request* );
00055 };
00056
00057
00058 KCommand* RootSequenceElement::buildCommand(
Container* container, Request* request )
00059 {
00060
FormulaCursor* cursor = container->
activeCursor();
00061
if ( cursor->
isReadOnly() ) {
00062
return 0;
00063 }
00064
00065
switch ( *request ) {
00066
case req_addIndex: {
00067
FormulaCursor* cursor = container->
activeCursor();
00068
if ( cursor->
isSelection() ||
00069 ( cursor->
getPos() > 0 && cursor->
getPos() < countChildren() ) ) {
00070
break;
00071 }
00072 IndexRequest* ir = static_cast<IndexRequest*>( request );
00073
if ( ir->index() == upperLeftPos ) {
00074
RootElement* element = static_cast<RootElement*>( getParent() );
00075 ElementIndexPtr index = element->
getIndex();
00076
if ( !index->hasIndex() ) {
00077
KFCAddGenericIndex* command =
new KFCAddGenericIndex( container, index );
00078
return command;
00079 }
00080
else {
00081 index->moveToIndex( cursor, afterCursor );
00082 cursor->
setSelection(
false );
00083 formula()->cursorHasMoved( cursor );
00084
return 0;
00085 }
00086 }
00087 }
00088
default:
00089
break;
00090 }
00091
return inherited::buildCommand( container, request );
00092 }
00093
00094
00095 RootElement::RootElement(
BasicElement* parent)
00096 :
BasicElement(parent)
00097 {
00098 content =
new RootSequenceElement(
this );
00099 index = 0;
00100 }
00101
00102 RootElement::~RootElement()
00103 {
00104
delete index;
00105
delete content;
00106 }
00107
00108
00109 RootElement::RootElement(
const RootElement& other )
00110 :
BasicElement( other )
00111 {
00112 content =
new RootSequenceElement( *dynamic_cast<RootSequenceElement*>( other.
content ) );
00113
if ( other.
index ) {
00114 index =
new SequenceElement( *( other.
index ) );
00115 index->setParent(
this );
00116 }
00117
else {
00118 index = 0;
00119 }
00120 }
00121
00122
00123 bool RootElement::accept(
ElementVisitor* visitor )
00124 {
00125
return visitor->
visit(
this );
00126 }
00127
00128
00129 void RootElement::entered(
SequenceElement* child )
00130 {
00131
if ( child == content ) {
00132
formula()->
tell( i18n(
"Main list of root" ) );
00133 }
00134
else {
00135
formula()->
tell( i18n(
"Index" ) );
00136 }
00137 }
00138
00139
00140 BasicElement*
RootElement::goToPos(
FormulaCursor* cursor,
bool& handled,
00141
const LuPixelPoint& point,
const LuPixelPoint& parentOrigin)
00142 {
00143
BasicElement* e = BasicElement::goToPos(cursor, handled, point, parentOrigin);
00144
if (e != 0) {
00145
LuPixelPoint myPos(parentOrigin.x() + getX(),
00146 parentOrigin.y() + getY());
00147
00148 e = content->
goToPos(cursor, handled, point, myPos);
00149
if (e != 0) {
00150
return e;
00151 }
00152
if (hasIndex()) {
00153 e = index->
goToPos(cursor, handled, point, myPos);
00154
if (e != 0) {
00155
return e;
00156 }
00157 }
00158
00159
00160 luPixel dy = point.y() - myPos.y();
00161
00162
00163
if (hasIndex()) {
00164
if (dy < index->
getHeight()) {
00165 index->
moveLeft(cursor,
this);
00166 handled =
true;
00167
return index;
00168 }
00169 }
00170
00171
return this;
00172 }
00173
return 0;
00174 }
00175
00176
00181 void RootElement::calcSizes(
const ContextStyle& style, ContextStyle::TextStyle tstyle, ContextStyle::IndexStyle istyle)
00182 {
00183 content->
calcSizes(style, tstyle,
00184 style.convertIndexStyleLower(istyle));
00185
00186 luPixel indexWidth = 0;
00187 luPixel indexHeight = 0;
00188
if (hasIndex()) {
00189 index->
calcSizes(style,
00190 style.convertTextStyleIndex(tstyle),
00191 style.convertIndexStyleUpper(istyle));
00192 indexWidth = index->
getWidth();
00193 indexHeight = index->
getHeight();
00194 }
00195
00196 luPixel distX = style.ptToPixelX( style.getThinSpace( tstyle ) );
00197 luPixel distY = style.ptToPixelY( style.getThinSpace( tstyle ) );
00198 luPixel unit = (content->
getHeight() + distY)/ 3;
00199
00200
if (hasIndex()) {
00201
if (indexWidth > unit) {
00202 index->
setX(0);
00203 rootOffset.setX( indexWidth - unit );
00204 }
00205
else {
00206 index->
setX( ( unit - indexWidth )/2 );
00207 rootOffset.setX(0);
00208 }
00209
if (indexHeight > unit) {
00210 index->
setY(0);
00211 rootOffset.setY( indexHeight - unit );
00212 }
00213
else {
00214 index->
setY( unit - indexHeight );
00215 rootOffset.setY(0);
00216 }
00217 }
00218
else {
00219 rootOffset.setX(0);
00220 rootOffset.setY(0);
00221 }
00222
00223 setWidth( content->
getWidth() + unit+unit/3+ rootOffset.x() + distX/2 );
00224 setHeight( content->
getHeight() + distY*2 + rootOffset.y() );
00225
00226 content->
setX( rootOffset.x() + unit+unit/3 );
00227 content->
setY( rootOffset.y() + distY );
00228 setBaseline(content->
getBaseline() + content->
getY());
00229 }
00230
00236 void RootElement::draw(
QPainter& painter,
const LuPixelRect& r,
00237
const ContextStyle& style,
00238 ContextStyle::TextStyle tstyle,
00239 ContextStyle::IndexStyle istyle,
00240
const LuPixelPoint& parentOrigin )
00241 {
00242
LuPixelPoint myPos( parentOrigin.x()+getX(), parentOrigin.y()+getY() );
00243
00244
00245
00246 content->
draw(painter, r, style, tstyle,
00247 style.convertIndexStyleLower(istyle), myPos);
00248
if (hasIndex()) {
00249 index->
draw(painter, r, style,
00250 style.convertTextStyleIndex(tstyle),
00251 style.convertIndexStyleUpper(istyle), myPos);
00252 }
00253
00254 luPixel x = myPos.x() + rootOffset.x();
00255 luPixel y = myPos.y() + rootOffset.y();
00256
00257 luPixel distY = style.ptToPixelY( style.getThinSpace( tstyle ) );
00258 luPixel unit = (content->
getHeight() + distY)/ 3;
00259
00260 painter.setPen(
QPen( style.getDefaultColor(),
00261 style.layoutUnitToPixelX( 2*style.getLineWidth() ) ) );
00262 painter.drawLine( style.layoutUnitToPixelX( x+unit/3 ),
00263 style.layoutUnitToPixelY( y+unit+distY/3 ),
00264 style.layoutUnitToPixelX( x+unit/2+unit/3 ),
00265 style.layoutUnitToPixelY( myPos.y()+getHeight() ) );
00266
00267 painter.setPen(
QPen( style.getDefaultColor(),
00268 style.layoutUnitToPixelY( style.getLineWidth() ) ) );
00269
00270 painter.drawLine( style.layoutUnitToPixelX( x+unit+unit/3 ),
00271 style.layoutUnitToPixelY( y+distY/3 ),
00272 style.layoutUnitToPixelX( x+unit/2+unit/3 ),
00273 style.layoutUnitToPixelY( myPos.y()+getHeight() ) );
00274 painter.drawLine( style.layoutUnitToPixelX( x+unit+unit/3 ),
00275 style.layoutUnitToPixelY( y+distY/3 ),
00276 style.layoutUnitToPixelX( x+unit+unit/3+content->
getWidth() ),
00277 style.layoutUnitToPixelY( y+distY/3 ) );
00278 painter.drawLine( style.layoutUnitToPixelX( x+unit/3 ),
00279 style.layoutUnitToPixelY( y+unit+distY/2 ),
00280 style.layoutUnitToPixelX( x ),
00281 style.layoutUnitToPixelY( y+unit+unit/2 ) );
00282 }
00283
00284
00285 void RootElement::dispatchFontCommand(
FontCommand* cmd )
00286 {
00287 content->
dispatchFontCommand( cmd );
00288
if (hasIndex()) {
00289 index->
dispatchFontCommand( cmd );
00290 }
00291 }
00292
00298 void RootElement::moveLeft(
FormulaCursor* cursor,
BasicElement* from)
00299 {
00300
if (cursor->
isSelectionMode()) {
00301 getParent()->
moveLeft(cursor,
this);
00302 }
00303
else {
00304
bool linear = cursor->
getLinearMovement();
00305
if (from == getParent()) {
00306 content->
moveLeft(cursor,
this);
00307 }
00308
else if (from == content) {
00309
if (linear && hasIndex()) {
00310 index->
moveLeft(cursor,
this);
00311 }
00312
else {
00313 getParent()->moveLeft(cursor,
this);
00314 }
00315 }
00316
else {
00317 getParent()->moveLeft(cursor,
this);
00318 }
00319 }
00320 }
00321
00327 void RootElement::moveRight(
FormulaCursor* cursor,
BasicElement* from)
00328 {
00329
if (cursor->
isSelectionMode()) {
00330 getParent()->
moveRight(cursor,
this);
00331 }
00332
else {
00333
bool linear = cursor->
getLinearMovement();
00334
if (from == getParent()) {
00335
if (linear && hasIndex()) {
00336 index->
moveRight(cursor,
this);
00337 }
00338
else {
00339 content->
moveRight(cursor,
this);
00340 }
00341 }
00342
else if (from == index) {
00343 content->
moveRight(cursor,
this);
00344 }
00345
else {
00346 getParent()->moveRight(cursor,
this);
00347 }
00348 }
00349 }
00350
00356 void RootElement::moveUp(
FormulaCursor* cursor,
BasicElement* from)
00357 {
00358
if (cursor->
isSelectionMode()) {
00359 getParent()->
moveUp(cursor,
this);
00360 }
00361
else {
00362
if (from == getParent()) {
00363 content->
moveRight(cursor,
this);
00364 }
00365
else if (from == content) {
00366
if (hasIndex()) {
00367 index->
moveRight(cursor,
this);
00368 }
00369
else {
00370 getParent()->moveUp(cursor,
this);
00371 }
00372 }
00373
else {
00374 getParent()->moveUp(cursor,
this);
00375 }
00376 }
00377 }
00378
00384 void RootElement::moveDown(
FormulaCursor* cursor,
BasicElement* from)
00385 {
00386
if (cursor->
isSelectionMode()) {
00387 getParent()->
moveDown(cursor,
this);
00388 }
00389
else {
00390
if (from == getParent()) {
00391
if (hasIndex()) {
00392 index->
moveRight(cursor,
this);
00393 }
00394
else {
00395 content->
moveRight(cursor,
this);
00396 }
00397 }
00398
else if (from == index) {
00399 content->
moveRight(cursor,
this);
00400 }
00401
else {
00402 getParent()->moveDown(cursor,
this);
00403 }
00404 }
00405 }
00406
00410 void RootElement::insert(
FormulaCursor* cursor,
00411
QPtrList<BasicElement>& newChildren,
00412 Direction direction)
00413 {
00414
if (cursor->
getPos() == upperLeftPos) {
00415 index = static_cast<SequenceElement*>(newChildren.take(0));
00416 index->
setParent(
this);
00417
00418
if (direction == beforeCursor) {
00419 index->
moveLeft(cursor,
this);
00420 }
00421
else {
00422 index->
moveRight(cursor,
this);
00423 }
00424 cursor->
setSelection(
false);
00425
formula()->
changed();
00426 }
00427 }
00428
00435 void RootElement::remove(
FormulaCursor* cursor,
00436
QPtrList<BasicElement>& removedChildren,
00437 Direction direction)
00438 {
00439
switch (cursor->
getPos()) {
00440
case contentPos:
00441 getParent()->
selectChild(cursor,
this);
00442 getParent()->
remove(cursor, removedChildren, direction);
00443
break;
00444
case upperLeftPos:
00445 removedChildren.append(index);
00446
formula()->
elementRemoval(index);
00447 index = 0;
00448 cursor->
setTo(
this, upperLeftPos);
00449
formula()->
changed();
00450
break;
00451 }
00452 }
00453
00454
00459 void RootElement::normalize(
FormulaCursor* cursor, Direction direction)
00460 {
00461
if (direction == beforeCursor) {
00462 content->
moveLeft(cursor,
this);
00463 }
00464
else {
00465 content->
moveRight(cursor,
this);
00466 }
00467 }
00468
00469
00470
00471
00472
00473
00474 SequenceElement*
RootElement::getMainChild()
00475 {
00476
return content;
00477 }
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00492 void RootElement::selectChild(
FormulaCursor* cursor,
BasicElement* child)
00493 {
00494
if (child == content) {
00495 cursor->
setTo(
this, contentPos);
00496 }
00497
else if (child == index) {
00498 cursor->
setTo(
this, upperLeftPos);
00499 }
00500 }
00501
00502
00503 void RootElement::moveToIndex(
FormulaCursor* cursor, Direction direction)
00504 {
00505
if (hasIndex()) {
00506
if (direction == beforeCursor) {
00507 index->
moveLeft(cursor,
this);
00508 }
00509
else {
00510 index->
moveRight(cursor,
this);
00511 }
00512 }
00513 }
00514
00515
void RootElement::setToIndex(
FormulaCursor* cursor)
00516 {
00517 cursor->
setTo(
this, upperLeftPos);
00518 }
00519
00520
00524 void RootElement::writeDom(
QDomElement element)
00525 {
00526 BasicElement::writeDom(element);
00527
00528
QDomDocument doc = element.ownerDocument();
00529
00530
QDomElement con = doc.createElement(
"CONTENT");
00531 con.appendChild(content->
getElementDom(doc));
00532 element.appendChild(con);
00533
00534
if(hasIndex()) {
00535
QDomElement ind = doc.createElement(
"ROOTINDEX");
00536 ind.appendChild(index->
getElementDom(doc));
00537 element.appendChild(ind);
00538 }
00539 }
00540
00545 bool RootElement::readAttributesFromDom(
QDomElement element)
00546 {
00547
return BasicElement::readAttributesFromDom(element);
00548 }
00549
00555 bool RootElement::readContentFromDom(
QDomNode& node)
00556 {
00557
if (!BasicElement::readContentFromDom(node)) {
00558
return false;
00559 }
00560
00561
if ( !buildChild( content, node,
"CONTENT" ) ) {
00562 kdWarning( DEBUGID ) <<
"Empty content in RootElement." << endl;
00563
return false;
00564 }
00565 node = node.nextSibling();
00566
00567
if ( node.nodeName().upper() ==
"ROOTINDEX" ) {
00568
if ( !buildChild( index=
new SequenceElement(
this ), node,
"ROOTINDEX" ) ) {
00569
return false;
00570 }
00571 }
00572
00573
else if ( node.nodeName().upper() ==
"INDEX" ) {
00574
if ( !buildChild( index=
new SequenceElement(
this ), node,
"INDEX" ) ) {
00575
return false;
00576 }
00577 }
00578 node = node.nextSibling();
00579
00580
return true;
00581 }
00582
00583 QString RootElement::toLatex()
00584 {
00585
QString root;
00586 root=
"\\sqrt";
00587
if(hasIndex()) {
00588 root+=
"[";
00589 root+=index->
toLatex();
00590 root+=
"]";
00591 }
00592 root+=
"{";
00593 root+=content->
toLatex();
00594 root+=
"}";
00595
00596
return root;
00597 }
00598
00599
QString RootElement::formulaString()
00600 {
00601
if ( hasIndex() ) {
00602
return "(" + content->
formulaString() +
")**(1.0/(" + index->
formulaString() +
"))";
00603 }
00604
return "sqrt(" + content->
formulaString() +
")";
00605 }
00606
00607 void RootElement::writeMathML(
QDomDocument doc,
QDomNode parent )
00608 {
00609
QDomElement de;
00610
00611
if( hasIndex() )
00612 de = doc.createElement(
"mroot" );
00613
else
00614 de = doc.createElement(
"msqrt" );
00615
00616 content->
writeMathML( doc, de );
00617
00618
if( hasIndex() )
00619 {
00620 index->
writeMathML( doc, de );
00621 }
00622
00623 parent.appendChild( de );
00624 }
00625
00626 KFORMULA_NAMESPACE_END