diff options
Diffstat (limited to 'lib/kformula/bracketelement.cpp')
-rw-r--r-- | lib/kformula/bracketelement.cpp | 1005 |
1 files changed, 1005 insertions, 0 deletions
diff --git a/lib/kformula/bracketelement.cpp b/lib/kformula/bracketelement.cpp new file mode 100644 index 00000000..45aa5469 --- /dev/null +++ b/lib/kformula/bracketelement.cpp @@ -0,0 +1,1005 @@ +/* This file is part of the KDE project + Copyright (C) 2001 Andrea Rizzi <rizzi@kde.org> + Ulrich Kuettler <ulrich.kuettler@mailbox.tu-dresden.de> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include <tqptrlist.h> +#include <tqpainter.h> +#include <tqpen.h> +#include <tqpointarray.h> + +#include <kdebug.h> +#include <tdelocale.h> + +#include "bracketelement.h" +#include "elementvisitor.h" +#include "fontstyle.h" +#include "formulacursor.h" +#include "formulaelement.h" +#include "sequenceelement.h" + +KFORMULA_NAMESPACE_BEGIN + +SingleContentElement::SingleContentElement(BasicElement* parent ) + : BasicElement( parent ) +{ + content = new SequenceElement( this ); +} + + +SingleContentElement::SingleContentElement( const SingleContentElement& other ) + : BasicElement( other ) +{ + content = new SequenceElement( other.content ); + content->setParent( this ); +} + + +SingleContentElement::~SingleContentElement() +{ + delete content; +} + + +TQChar SingleContentElement::getCharacter() const +{ + // This is meant to make the SingleContentElement text only. + // This "fixes" the parenthesis problem (parenthesis too large). + // I'm not sure if we really want this. There should be better ways. + if ( content->isTextOnly() ) { + return '\\'; + } + return content->getCharacter(); +} + +BasicElement* SingleContentElement::goToPos( FormulaCursor* cursor, bool& handled, + const LuPixelPoint& point, const LuPixelPoint& parentOrigin ) +{ + BasicElement* e = BasicElement::goToPos(cursor, handled, point, parentOrigin); + if (e != 0) { + LuPixelPoint myPos(parentOrigin.x() + getX(), + parentOrigin.y() + getY()); + + e = content->goToPos(cursor, handled, point, myPos); + if (e != 0) { + return e; + } + return this; + } + return 0; +} + +void SingleContentElement::dispatchFontCommand( FontCommand* cmd ) +{ + content->dispatchFontCommand( cmd ); +} + +void SingleContentElement::moveLeft(FormulaCursor* cursor, BasicElement* from) +{ + if (cursor->isSelectionMode()) { + getParent()->moveLeft(cursor, this); + } + else { + //bool linear = cursor->getLinearMovement(); + if (from == getParent()) { + content->moveLeft(cursor, this); + } + else { + getParent()->moveLeft(cursor, this); + } + } +} + +void SingleContentElement::moveRight(FormulaCursor* cursor, BasicElement* from) +{ + if (cursor->isSelectionMode()) { + getParent()->moveRight(cursor, this); + } + else { + //bool linear = cursor->getLinearMovement(); + if (from == getParent()) { + content->moveRight(cursor, this); + } + else { + getParent()->moveRight(cursor, this); + } + } +} + +void SingleContentElement::moveUp(FormulaCursor* cursor, BasicElement* /*from*/) +{ + getParent()->moveUp(cursor, this); +} + +void SingleContentElement::moveDown(FormulaCursor* cursor, BasicElement* /*from*/) +{ + getParent()->moveDown(cursor, this); +} + +void SingleContentElement::remove( FormulaCursor* cursor, + TQPtrList<BasicElement>& removedChildren, + Direction direction ) +{ + switch (cursor->getPos()) { + case contentPos: + BasicElement* parent = getParent(); + parent->selectChild(cursor, this); + parent->remove(cursor, removedChildren, direction); + } +} + +void SingleContentElement::normalize( FormulaCursor* cursor, Direction direction ) +{ + if (direction == beforeCursor) { + content->moveLeft(cursor, this); + } + else { + content->moveRight(cursor, this); + } +} + +SequenceElement* SingleContentElement::getMainChild() +{ + return content; +} + +void SingleContentElement::selectChild(FormulaCursor* cursor, BasicElement* child) +{ + if (child == content) { + cursor->setTo(this, contentPos); + } +} + +void SingleContentElement::writeDom(TQDomElement element) +{ + BasicElement::writeDom(element); + + TQDomDocument doc = element.ownerDocument(); + + TQDomElement con = doc.createElement("CONTENT"); + con.appendChild(content->getElementDom(doc)); + element.appendChild(con); +} + +bool SingleContentElement::readContentFromDom(TQDomNode& node) +{ + if (!BasicElement::readContentFromDom(node)) { + return false; + } + + if ( !buildChild( content, node, "CONTENT" ) ) { + kdWarning( DEBUGID ) << "Empty content in " << getTagName() << endl; + return false; + } + node = node.nextSibling(); + + return true; +} + +int SingleContentElement::readContentFromMathMLDom( TQDomNode& node ) +{ + if ( BasicElement::readContentFromMathMLDom( node ) == -1 ) { + return -1; + } + + int nodeCounter = content->buildMathMLChild( node ); + if ( nodeCounter == -1 ) { + kdWarning( DEBUGID) << "Empty content in SingleContentElement\n"; + return -1; + } + + return nodeCounter; +} + +void SingleContentElement::writeMathMLContent( TQDomDocument& doc, TQDomElement& element, bool oasisFormat ) const +{ + content->writeMathML( doc, element, oasisFormat ); +} + + + +BracketElement::BracketElement(SymbolType l, SymbolType r, BasicElement* parent) + : SingleContentElement(parent), + left( 0 ), right( 0 ), + leftType( l ), rightType( r ), + m_operator( false ), m_customLeft( false ), m_customRight( false ) +{ +} + + +BracketElement::~BracketElement() +{ + delete left; + delete right; +} + + +BracketElement::BracketElement( const BracketElement& other ) + : SingleContentElement( other ), + left( 0 ), right( 0 ), + leftType( other.leftType ), rightType( other.rightType ), + m_operator( other.m_operator ), + m_customLeft( other.m_customLeft ), m_customRight( other.m_customRight ) +{ +} + + +bool BracketElement::accept( ElementVisitor* visitor ) +{ + return visitor->visit( this ); +} + + +void BracketElement::entered( SequenceElement* /*child*/ ) +{ + formula()->tell( i18n( "Delimited list" ) ); +} + + +BasicElement* BracketElement::goToPos( FormulaCursor* cursor, bool& handled, + const LuPixelPoint& point, const LuPixelPoint& parentOrigin ) +{ + BasicElement* e = BasicElement::goToPos(cursor, handled, point, parentOrigin); + if (e != 0) { + LuPixelPoint myPos(parentOrigin.x() + getX(), + parentOrigin.y() + getY()); + e = getContent()->goToPos(cursor, handled, point, myPos); + if (e != 0) { + return e; + } + + // We are in one of those gaps. + luPixel dx = point.x() - myPos.x(); + luPixel dy = point.y() - myPos.y(); + + if ((dx > getContent()->getX()+getContent()->getWidth()) || + (dy > getContent()->getY()+getContent()->getHeight())) { + getContent()->moveEnd(cursor); + handled = true; + return getContent(); + } + return this; + } + return 0; +} + + +/** + * Calculates our width and height and + * our children's parentPosition. + */ +void BracketElement::calcSizes( const ContextStyle& context, + ContextStyle::TextStyle tstyle, + ContextStyle::IndexStyle istyle, + StyleAttributes& style ) +{ + SequenceElement* content = getContent(); + content->calcSizes( context, tstyle, istyle, style ); + + //if ( left == 0 ) { + delete left; + delete right; + left = context.fontStyle().createArtwork( leftType ); + right = context.fontStyle().createArtwork( rightType ); + //} + + double factor = style.sizeFactor(); + if (content->isTextOnly()) { + left->calcSizes(context, tstyle, factor); + right->calcSizes(context, tstyle, factor); + + setBaseline(TQMAX(content->getBaseline(), + TQMAX(left->getBaseline(), right->getBaseline()))); + + content->setY(getBaseline() - content->getBaseline()); + left ->setY(getBaseline() - left ->getBaseline()); + right ->setY(getBaseline() - right ->getBaseline()); + + //setMidline(content->getY() + content->getMidline()); + setHeight(TQMAX(content->getY() + content->getHeight(), + TQMAX(left ->getY() + left ->getHeight(), + right->getY() + right->getHeight()))); + } + else { + //kdDebug( DEBUGID ) << "BracketElement::calcSizes " << content->axis( context, tstyle ) << " " << content->getHeight() << endl; + luPixel contentHeight = 2 * TQMAX( content->axis( context, tstyle, factor ), + content->getHeight() - content->axis( context, tstyle, factor ) ); + left->calcSizes( context, tstyle, factor, contentHeight ); + right->calcSizes( context, tstyle, factor, contentHeight ); + + // height + setHeight(TQMAX(contentHeight, + TQMAX(left->getHeight(), right->getHeight()))); + //setMidline(getHeight() / 2); + + content->setY(getHeight() / 2 - content->axis( context, tstyle, factor )); + setBaseline(content->getBaseline() + content->getY()); + + if ( left->isNormalChar() ) { + left->setY(getBaseline() - left->getBaseline()); + } + else { + left->setY((getHeight() - left->getHeight())/2); + } + if ( right->isNormalChar() ) { + right->setY(getBaseline() - right->getBaseline()); + } + else { + right->setY((getHeight() - right->getHeight())/2); + } + +// kdDebug() << "BracketElement::calcSizes" << endl +// << "getHeight(): " << getHeight() << endl +// << "left->getHeight(): " << left->getHeight() << endl +// << "right->getHeight(): " << right->getHeight() << endl +// << "left->getY(): " << left->getY() << endl +// << "right->getY(): " << right->getY() << endl +// << endl; + } + + // width + setWidth(left->getWidth() + content->getWidth() + right->getWidth()); + content->setX(left->getWidth()); + right ->setX(left->getWidth()+content->getWidth()); +} + + +/** + * Draws the whole element including its children. + * The `parentOrigin' is the point this element's parent starts. + * We can use our parentPosition to get our own origin then. + */ +void BracketElement::draw( TQPainter& painter, const LuPixelRect& r, + const ContextStyle& context, + ContextStyle::TextStyle tstyle, + ContextStyle::IndexStyle istyle, + StyleAttributes& style, + const LuPixelPoint& parentOrigin ) +{ + LuPixelPoint myPos( parentOrigin.x()+getX(), parentOrigin.y()+getY() ); + //if ( !LuPixelRect( myPos.x(), myPos.y(), getWidth(), getHeight() ).intersects( r ) ) + // return; + + SequenceElement* content = getContent(); + content->draw(painter, r, context, tstyle, istyle, style, myPos); + + if (content->isTextOnly()) { + left->draw(painter, r, context, tstyle, style, myPos); + right->draw(painter, r, context, tstyle, style, myPos); + } + else { + double factor = style.sizeFactor(); + luPixel contentHeight = 2 * TQMAX(content->axis( context, tstyle, factor ), + content->getHeight() - content->axis( context, tstyle, factor )); + left->draw(painter, r, context, tstyle, style, contentHeight, myPos); + right->draw(painter, r, context, tstyle, style, contentHeight, myPos); + } + + // Debug +#if 0 + painter.setBrush( TQt::NoBrush ); + painter.setPen( TQt::red ); + painter.drawRect( context.layoutUnitToPixelX( myPos.x()+left->getX() ), + context.layoutUnitToPixelY( myPos.y()+left->getY() ), + context.layoutUnitToPixelX( left->getWidth() ), + context.layoutUnitToPixelY( left->getHeight() ) ); + painter.drawRect( context.layoutUnitToPixelX( myPos.x()+right->getX() ), + context.layoutUnitToPixelY( myPos.y()+right->getY() ), + context.layoutUnitToPixelX( right->getWidth() ), + context.layoutUnitToPixelY( right->getHeight() ) ); +#endif +} + + +/** + * Appends our attributes to the dom element. + */ +void BracketElement::writeDom(TQDomElement element) +{ + SingleContentElement::writeDom(element); + element.setAttribute("LEFT", leftType); + element.setAttribute("RIGHT", rightType); +} + +/** + * Reads our attributes from the element. + * Returns false if it failed. + */ +bool BracketElement::readAttributesFromDom(TQDomElement element) +{ + if (!BasicElement::readAttributesFromDom(element)) { + return false; + } + TQString leftStr = element.attribute("LEFT"); + if(!leftStr.isNull()) { + leftType = static_cast<SymbolType>(leftStr.toInt()); + } + TQString rightStr = element.attribute("RIGHT"); + if(!rightStr.isNull()) { + rightType = static_cast<SymbolType>(rightStr.toInt()); + } + return true; +} + +/** + * Reads our attributes from the MathML element. + * Returns false if it failed. + */ +bool BracketElement::readAttributesFromMathMLDom(const TQDomElement& element) +{ + if ( !BasicElement::readAttributesFromMathMLDom( element ) ) { + return false; + } + + if ( element.tagName().lower() == "mo" ) { + m_operator = true; + // TODO: parse attributes in section 3.2.5.2 + } + else { // mfenced, see attributes in section 3.3.8.2 + leftType = LeftRoundBracket; + rightType = RightRoundBracket; + TQString openStr = element.attribute( "open" ).stripWhiteSpace(); + if ( !openStr.isNull() ) { + m_customLeft = true; + if ( openStr == "[" ) + leftType = LeftSquareBracket; + else if ( openStr == "]" ) + leftType = RightSquareBracket; + else if ( openStr == "{" ) + leftType = LeftCurlyBracket; + else if ( openStr == "}" ) + leftType = RightCurlyBracket; + else if ( openStr == "<" ) + leftType = LeftCornerBracket; + else if ( openStr == ">" ) + leftType = RightCornerBracket; + else if ( openStr == "(" ) + leftType = LeftRoundBracket; + else if ( openStr == ")" ) + leftType = RightRoundBracket; + else if ( openStr == "/" ) + leftType = SlashBracket; + else if ( openStr == "\\" ) + leftType = BackSlashBracket; + else // TODO: Check for entity references + leftType = LeftRoundBracket; + } + TQString closeStr = element.attribute( "close" ).stripWhiteSpace(); + if ( !closeStr.isNull() ) { + m_customRight = true; + if ( closeStr == "[" ) + rightType = LeftSquareBracket; + else if ( closeStr == "]" ) + rightType = RightSquareBracket; + else if ( closeStr == "{" ) + rightType = LeftCurlyBracket; + else if ( closeStr == "}" ) + rightType = RightCurlyBracket; + else if ( closeStr == "<" ) + rightType = LeftCornerBracket; + else if ( closeStr == ">" ) + rightType = RightCornerBracket; + else if ( closeStr == "(" ) + rightType = LeftRoundBracket; + else if ( closeStr == ")" ) + rightType = RightRoundBracket; + else if ( closeStr == "/" ) + rightType = SlashBracket; + else if ( closeStr == "\\" ) + rightType = BackSlashBracket; + else // TODO: Check for entity references + rightType = LeftRoundBracket; + } + m_separators = element.attribute( "separators" ).simplifyWhiteSpace(); + } + return true; +} + +/** + * Reads our content from the MathML node. Sets the node to the next node + * that needs to be read. + * Returns false if it failed. + */ +int BracketElement::readContentFromMathMLDom(TQDomNode& node) +{ + bool empty = false; + int nodeCounter = 0; + if ( m_operator ) { + node = node.parentNode(); + TQDomNode open = node; + TQDomNode parent = node.parentNode(); + if ( ! operatorType( node, true ) ) + return -1; + int nodeNum = searchOperator( node ); + if ( nodeNum == -1 ) // Closing bracket not found + return -1; + if ( nodeNum == 0 ) { // Empty content + empty = true; + } + else if ( nodeNum == 1 ) { + do { + node = node.nextSibling(); + nodeCounter++; + } while ( ! node.isElement() ); + } + else { // More than two elements inside, infer a mrow + nodeCounter += nodeNum; + kdWarning() << "NodeNum: " << nodeNum << endl; + TQDomDocument doc = node.ownerDocument(); + TQDomElement de = doc.createElement( "mrow" ); + int i = 0; + do { + TQDomNode n = node.nextSibling(); + de.appendChild( node.toElement() ); + node = n; + } while ( ++i < nodeNum ); + parent.insertAfter( de, open ); + node = de; + kdWarning() << doc.toString() << endl; + } + } + else { + // if it's a mfence tag, we need to convert to equivalent expanded form. + // See section 3.3.8 + while ( ! node.isNull() && ! node.isElement() ) + node = node.nextSibling(); + TQDomNode next = node.nextSibling(); + while ( ! next.isNull() && ! next.isElement() ) + next = next.nextSibling(); + if ( ! next.isNull()) { + TQDomDocument doc = node.ownerDocument(); + TQDomNode parent = node.parentNode(); + TQString ns = parent.prefix(); + TQDomElement de = doc.createElementNS( ns, "mrow" ); + uint pos = 0; + while ( ! node.isNull() ) { + TQDomNode no = node.nextSibling(); + while ( ! no.isNull() && ! no.isElement() ) + no = no.nextSibling(); + de.appendChild( node.toElement() ); + if ( ! no.isNull() && ( m_separators.isNull() || ! m_separators.isEmpty() ) ) { + TQDomElement sep = doc.createElementNS( ns, "mo" ); + de.appendChild( sep ); + if ( m_separators.isNull() ) { + sep.appendChild( doc.createTextNode( "," ) ); + } + else { + if ( m_separators.at( pos ).isSpace() ) { + pos++; + } + sep.appendChild( doc.createTextNode( TQString ( m_separators.at( pos ) ) ) ); + } + if ( pos < m_separators.length() - 1 ) { + pos++; + } + } + node = no; + } + parent.appendChild( de ); + node = parent.firstChild(); + while ( ! node.isElement() ) + node = node.nextSibling(); + } + } + if ( ! empty ) { + int contentNumber = inherited::readContentFromMathMLDom( node ); + if ( contentNumber == -1 ) + return -1; + nodeCounter += contentNumber; + for (int i = 0; i < contentNumber; i++ ) { + if ( node.isNull() ) { + return -1; + } + node = node.nextSibling(); + } + } + if ( m_operator ) { + int operatorNumber = operatorType( node, false ); + if ( operatorNumber == -1 ) { + return -1; + } + nodeCounter += operatorNumber; + } + kdDebug( DEBUGID ) << "Number of bracket nodes: " << nodeCounter << endl; + return nodeCounter; +} + +TQString BracketElement::toLatex() +{ + TQString ls,rs,cs; + cs=getContent()->toLatex(); + ls="\\left"+latexString(leftType) + " "; + rs=" \\right"+latexString(rightType); + + return ls+cs+rs; +} + +TQString BracketElement::latexString(char type) +{ + switch (type) { + case ']': + return "]"; + case '[': + return "["; + case '{': + return "\\{"; + case '}': + return "\\}"; + case '(': + return "("; + case ')': + return ")"; + case '|': + return "|"; + case '<': + return "\\langle"; + case '>': + return "\\rangle"; + case '/': + return "/"; + case '\\': + return "\\backslash"; + } + return "."; +} + +TQString BracketElement::formulaString() +{ + return "(" + getContent()->formulaString() + ")"; +} + +int BracketElement::operatorType( TQDomNode& node, bool open ) +{ + int counter = 1; + SymbolType* type = open ? &leftType : &rightType; + while ( ! node.isNull() && ! node.isElement() ) { + node = node.nextSibling(); + counter++; + } + if ( node.isElement() ) { + TQDomElement e = node.toElement(); + TQDomNode child = e.firstChild(); + if ( child.isEntityReference() ) { + kdWarning() << "Entity Reference\n"; + TQString name = node.nodeName(); + // TODO: To fully support these, SymbolType has to be extended, + // and better Unicode support is a must + // CloseCurlyDoubleQuote 0x201D + // CloseCurlyQoute 0x2019 + // LeftCeiling 0x2308 + // LeftDoubleBracket 0x301A + // LeftFloor 0x230A + // OpenCurlyDoubleQuote 0x201C + // OpenCurlyQuote 0x2018 + // RightCeiling 0x2309 + // RightDoubleBracket 0x301B + // RightFloor 0x230B + if ( name == "LeftAngleBracket" ) { + *type = LeftCornerBracket; + } + else if ( name == "RightAngleBracket" ) { + *type = RightCornerBracket; + } + else { + if ( open ) { + *type = LeftRoundBracket; + } + else + *type = RightRoundBracket; + } + } + else { + TQString s = e.text(); + if ( s.isNull() ) + return -1; + *type = static_cast<SymbolType>( TQString::number( s.at( 0 ).latin1() ).toInt() ); + } + } + else { + return -1; + } + return counter; +} + +int BracketElement::searchOperator( const TQDomNode& node ) +{ + TQDomNode n = node; + for ( int i = -2; ! n.isNull(); n = n.nextSibling() ) { + if ( n.isElement() ) { + i++; + TQDomElement e = n.toElement(); + if ( e.tagName().lower() == "mo" ) { + // Try to guess looking at attributes + TQString form = e.attribute( "form" ); + TQString f; + if ( ! form.isNull() ) { + f = form.stripWhiteSpace().lower(); + } + TQString fence = e.attribute( "fence" ); + if ( ! fence.isNull() ) { + if ( fence.stripWhiteSpace().lower() == "false" ) { + continue; + } + if ( ! f.isNull() ) { + if ( f == "postfix" ) { + return i; + } + else { + continue; + } + } + } + + // Guess looking at contents + TQDomNode child = e.firstChild(); + TQString name; + if ( child.isText() ) + name = child.toText().data().stripWhiteSpace(); + else if ( child.isEntityReference() ) + name = child.nodeName(); + else + continue; + if ( name == ")" + || name == "]" + || name == "}" + || name == "CloseCurlyDoubleQuote" + || name == "CloseCurlyQuote" + || name == "RightAngleBracket" + || name == "RightCeiling" + || name == "RightDoubleBracket" + || name == "RightFloor" ) { + if ( f.isNull() || f == "postfix" ) + return i; + } + if ( name == "(" + || name == "[" + || name == "{" + || name == "LeftAngleBracket" + || name == "LeftCeiling" + || name == "LeftDoubleBracket" + || name == "LeftFloor" + || name == "OpenCurlyQuote" ) { + if ( ! f.isNull() && f == "postfix" ) + return i; + } + } + } + } + return -1; +} + + +void BracketElement::writeMathMLAttributes( TQDomElement& element ) const +{ + if ( left->getType() != LeftRoundBracket || + right->getType() != RightRoundBracket ) + { + element.setAttribute( "open", TQString( TQChar( leftType ) ) ); + element.setAttribute( "close", TQString( TQChar( rightType ) ) ); + } + if ( ! m_separators.isNull() ) { + element.setAttribute( "separators", m_separators ); + } +} + +OverlineElement::OverlineElement( BasicElement* parent ) + : SingleContentElement( parent ) +{ +} + +OverlineElement::~OverlineElement() +{ +} + +OverlineElement::OverlineElement( const OverlineElement& other ) + : SingleContentElement( other ) +{ +} + + +bool OverlineElement::accept( ElementVisitor* visitor ) +{ + return visitor->visit( this ); +} + + +void OverlineElement::entered( SequenceElement* /*child*/ ) +{ + formula()->tell( i18n( "Overline" ) ); +} + + +void OverlineElement::calcSizes( const ContextStyle& context, + ContextStyle::TextStyle tstyle, + ContextStyle::IndexStyle istyle, + StyleAttributes& style ) +{ + SequenceElement* content = getContent(); + content->calcSizes(context, tstyle, + context.convertIndexStyleLower(istyle), style ); + + //luPixel distX = context.ptToPixelX( context.getThinSpace( tstyle, style.sizeFactor() ) ); + luPixel distY = context.ptToPixelY( context.getThinSpace( tstyle, style.sizeFactor() ) ); + //luPixel unit = (content->getHeight() + distY)/ 3; + + setWidth( content->getWidth() ); + setHeight( content->getHeight() + distY ); + + content->setX( 0 ); + content->setY( distY ); + setBaseline(content->getBaseline() + content->getY()); +} + +void OverlineElement::draw( TQPainter& painter, const LuPixelRect& r, + const ContextStyle& context, + ContextStyle::TextStyle tstyle, + ContextStyle::IndexStyle istyle, + StyleAttributes& style, + const LuPixelPoint& parentOrigin ) +{ + LuPixelPoint myPos( parentOrigin.x()+getX(), parentOrigin.y()+getY() ); + //if ( !LuPixelRect( myPos.x(), myPos.y(), getWidth(), getHeight() ).intersects( r ) ) + // return; + + SequenceElement* content = getContent(); + content->draw( painter, r, context, tstyle, + context.convertIndexStyleLower( istyle ), style, myPos ); + + luPixel x = myPos.x(); + luPixel y = myPos.y(); + //int distX = context.getDistanceX(tstyle); + double factor = style.sizeFactor(); + luPixel distY = context.ptToPixelY( context.getThinSpace( tstyle, factor ) ); + //luPixel unit = (content->getHeight() + distY)/ 3; + + painter.setPen( TQPen( context.getDefaultColor(), + context.layoutUnitToPixelY( context.getLineWidth( factor ) ) ) ); + + painter.drawLine( context.layoutUnitToPixelX( x ), + context.layoutUnitToPixelY( y+distY/3 ), + context.layoutUnitToPixelX( x+content->getWidth() ), + context.layoutUnitToPixelY( y+distY/3 ) ); +} + + +TQString OverlineElement::toLatex() +{ + return "\\overline{" + getContent()->toLatex() + "}"; +} + +TQString OverlineElement::formulaString() +{ + return getContent()->formulaString(); +} + +void OverlineElement::writeMathML( TQDomDocument& doc, TQDomNode& parent, bool oasisFormat ) const +{ + TQDomElement de = doc.createElement( oasisFormat ? "math:mover" : "mover" ); + SingleContentElement::writeMathML( doc, de, oasisFormat ); + TQDomElement op = doc.createElement( oasisFormat ? "math:mo" : "mo" ); + // is this the right entity? Mozilla renders it correctly. + op.appendChild( doc.createEntityReference( "OverBar" ) ); + de.appendChild( op ); + parent.appendChild( de ); +} + + +UnderlineElement::UnderlineElement( BasicElement* parent ) + : SingleContentElement( parent ) +{ +} + +UnderlineElement::~UnderlineElement() +{ +} + + +UnderlineElement::UnderlineElement( const UnderlineElement& other ) + : SingleContentElement( other ) +{ +} + + +bool UnderlineElement::accept( ElementVisitor* visitor ) +{ + return visitor->visit( this ); +} + + +void UnderlineElement::entered( SequenceElement* /*child*/ ) +{ + formula()->tell( i18n( "Underline" ) ); +} + + +void UnderlineElement::calcSizes( const ContextStyle& context, + ContextStyle::TextStyle tstyle, + ContextStyle::IndexStyle istyle, + StyleAttributes& style ) +{ + SequenceElement* content = getContent(); + double factor = style.sizeFactor(); + content->calcSizes(context, tstyle, + context.convertIndexStyleLower(istyle), style ); + + //luPixel distX = context.ptToPixelX( context.getThinSpace( tstyle ) ); + luPixel distY = context.ptToPixelY( context.getThinSpace( tstyle, factor ) ); + //luPixel unit = (content->getHeight() + distY)/ 3; + + setWidth( content->getWidth() ); + setHeight( content->getHeight() + distY ); + + content->setX( 0 ); + content->setY( 0 ); + setBaseline(content->getBaseline() + content->getY()); +} + +void UnderlineElement::draw( TQPainter& painter, const LuPixelRect& r, + const ContextStyle& context, + ContextStyle::TextStyle tstyle, + ContextStyle::IndexStyle istyle, + StyleAttributes& style, + const LuPixelPoint& parentOrigin ) +{ + LuPixelPoint myPos( parentOrigin.x()+getX(), parentOrigin.y()+getY() ); + //if ( !LuPixelRect( myPos.x(), myPos.y(), getWidth(), getHeight() ).intersects( r ) ) + // return; + + SequenceElement* content = getContent(); + content->draw( painter, r, context, tstyle, + context.convertIndexStyleLower( istyle ), style, myPos ); + + luPixel x = myPos.x(); + luPixel y = myPos.y(); + //int distX = context.getDistanceX(tstyle); + //luPixel distY = context.ptToPixelY( context.getThinSpace( tstyle ) ); + //luPixel unit = (content->getHeight() + distY)/ 3; + + double factor = style.sizeFactor(); + painter.setPen( TQPen( context.getDefaultColor(), + context.layoutUnitToPixelY( context.getLineWidth( factor ) ) ) ); + + painter.drawLine( context.layoutUnitToPixelX( x ), + context.layoutUnitToPixelY( y+getHeight()-context.getLineWidth( factor ) ), + context.layoutUnitToPixelX( x+content->getWidth() ), + context.layoutUnitToPixelY( y+getHeight()-context.getLineWidth( factor ) ) ); +} + + +TQString UnderlineElement::toLatex() +{ + return "\\underline{" + getContent()->toLatex() + "}"; +} + +TQString UnderlineElement::formulaString() +{ + return getContent()->formulaString(); +} + +void UnderlineElement::writeMathML( TQDomDocument& doc, TQDomNode& parent, bool oasisFormat ) const +{ + TQDomElement de = doc.createElement( oasisFormat ? "math:munder" : "munder" ); + SingleContentElement::writeMathML( doc, de, oasisFormat ); + TQDomElement op = doc.createElement( oasisFormat ? "math:mo" : "mo" ); + // is this the right entity? Mozilla renders it correctly. + op.appendChild( doc.createEntityReference( "UnderBar" ) ); + de.appendChild( op ); + parent.appendChild( de ); +} + +KFORMULA_NAMESPACE_END |