You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2693 lines
84 KiB
2693 lines
84 KiB
/* 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 <tqmemarray.h>
|
|
#include <tqpainter.h>
|
|
#include <tqptrlist.h>
|
|
|
|
#include <kdebug.h>
|
|
#include <klocale.h>
|
|
|
|
#include "MatrixDialog.h"
|
|
#include "elementvisitor.h"
|
|
#include "formulaelement.h"
|
|
#include "formulacursor.h"
|
|
#include "kformulacontainer.h"
|
|
#include "kformulacommand.h"
|
|
#include "matrixelement.h"
|
|
#include "sequenceelement.h"
|
|
#include "spaceelement.h"
|
|
|
|
|
|
KFORMULA_NAMESPACE_BEGIN
|
|
|
|
|
|
class MatrixSequenceElement : public SequenceElement {
|
|
typedef SequenceElement inherited;
|
|
public:
|
|
|
|
MatrixSequenceElement( BasicElement* parent = 0 ) : SequenceElement( parent ) {}
|
|
virtual MatrixSequenceElement* clone() {
|
|
return new MatrixSequenceElement( *this );
|
|
}
|
|
|
|
/**
|
|
* This is called by the container to get a command depending on
|
|
* the current cursor position (this is how the element gets chosen)
|
|
* and the request.
|
|
*
|
|
* @returns the command that performs the requested action with
|
|
* the containers active cursor.
|
|
*/
|
|
virtual KCommand* buildCommand( Container*, Request* );
|
|
};
|
|
|
|
|
|
class KFCRemoveRow : public Command {
|
|
public:
|
|
KFCRemoveRow( const TQString& name, Container* document, MatrixElement* m, uint r, uint c );
|
|
~KFCRemoveRow();
|
|
|
|
virtual void execute();
|
|
virtual void unexecute();
|
|
|
|
protected:
|
|
MatrixElement* matrix;
|
|
uint rowPos;
|
|
uint colPos;
|
|
|
|
TQPtrList<MatrixSequenceElement>* row;
|
|
};
|
|
|
|
|
|
class KFCInsertRow : public KFCRemoveRow {
|
|
public:
|
|
KFCInsertRow( const TQString& name, Container* document, MatrixElement* m, uint r, uint c );
|
|
|
|
virtual void execute() { KFCRemoveRow::unexecute(); }
|
|
virtual void unexecute() { KFCRemoveRow::execute(); }
|
|
};
|
|
|
|
|
|
class KFCRemoveColumn : public Command {
|
|
public:
|
|
KFCRemoveColumn( const TQString& name, Container* document, MatrixElement* m, uint r, uint c );
|
|
~KFCRemoveColumn();
|
|
|
|
virtual void execute();
|
|
virtual void unexecute();
|
|
|
|
protected:
|
|
MatrixElement* matrix;
|
|
uint rowPos;
|
|
uint colPos;
|
|
|
|
TQPtrList<MatrixSequenceElement>* column;
|
|
};
|
|
|
|
|
|
class KFCInsertColumn : public KFCRemoveColumn {
|
|
public:
|
|
KFCInsertColumn( const TQString& name, Container* document, MatrixElement* m, uint r, uint c );
|
|
|
|
virtual void execute() { KFCRemoveColumn::unexecute(); }
|
|
virtual void unexecute() { KFCRemoveColumn::execute(); }
|
|
};
|
|
|
|
|
|
KCommand* MatrixSequenceElement::buildCommand( Container* container, Request* request )
|
|
{
|
|
FormulaCursor* cursor = container->activeCursor();
|
|
if ( cursor->isReadOnly() ) {
|
|
return 0;
|
|
}
|
|
|
|
switch ( *request ) {
|
|
case req_appendColumn:
|
|
case req_appendRow:
|
|
case req_insertColumn:
|
|
case req_removeColumn:
|
|
case req_insertRow:
|
|
case req_removeRow: {
|
|
MatrixElement* matrix = static_cast<MatrixElement*>( getParent() );
|
|
FormulaCursor* cursor = container->activeCursor();
|
|
for ( uint row = 0; row < matrix->getRows(); row++ ) {
|
|
for ( uint col = 0; col < matrix->getColumns(); col++ ) {
|
|
if ( matrix->getElement( row, col ) == cursor->getElement() ) {
|
|
switch ( *request ) {
|
|
case req_appendColumn:
|
|
return new KFCInsertColumn( i18n( "Append Column" ), container, matrix, row, matrix->getColumns() );
|
|
case req_appendRow:
|
|
return new KFCInsertRow( i18n( "Append Row" ), container, matrix, matrix->getRows(), col );
|
|
case req_insertColumn:
|
|
return new KFCInsertColumn( i18n( "Insert Column" ), container, matrix, row, col );
|
|
case req_removeColumn:
|
|
if ( matrix->getColumns() > 1 ) {
|
|
return new KFCRemoveColumn( i18n( "Remove Column" ), container, matrix, row, col );
|
|
}
|
|
break;
|
|
case req_insertRow:
|
|
return new KFCInsertRow( i18n( "Insert Row" ), container, matrix, row, col );
|
|
case req_removeRow:
|
|
if ( matrix->getRows() > 1 ) {
|
|
return new KFCRemoveRow( i18n( "Remove Row" ), container, matrix, row, col );
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
kdWarning( DEBUGID ) << "MatrixSequenceElement::buildCommand: Sequence not found." << endl;
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return inherited::buildCommand( container, request );
|
|
}
|
|
|
|
|
|
KFCRemoveRow::KFCRemoveRow( const TQString& name, Container* document, MatrixElement* m, uint r, uint c )
|
|
: Command( name, document ), matrix( m ), rowPos( r ), colPos( c ), row( 0 )
|
|
{
|
|
}
|
|
|
|
KFCRemoveRow::~KFCRemoveRow()
|
|
{
|
|
delete row;
|
|
}
|
|
|
|
void KFCRemoveRow::execute()
|
|
{
|
|
FormulaCursor* cursor = getExecuteCursor();
|
|
row = matrix->content.at( rowPos );
|
|
FormulaElement* formula = matrix->formula();
|
|
for ( uint i = matrix->getColumns(); i > 0; i-- ) {
|
|
formula->elementRemoval( row->at( i-1 ) );
|
|
}
|
|
matrix->content.take( rowPos );
|
|
formula->changed();
|
|
if ( rowPos < matrix->getRows() ) {
|
|
matrix->getElement( rowPos, colPos )->goInside( cursor );
|
|
}
|
|
else {
|
|
matrix->getElement( rowPos-1, colPos )->goInside( cursor );
|
|
}
|
|
testDirty();
|
|
}
|
|
|
|
void KFCRemoveRow::unexecute()
|
|
{
|
|
matrix->content.insert( rowPos, row );
|
|
row = 0;
|
|
FormulaCursor* cursor = getExecuteCursor();
|
|
matrix->getElement( rowPos, colPos )->goInside( cursor );
|
|
matrix->formula()->changed();
|
|
testDirty();
|
|
}
|
|
|
|
|
|
KFCInsertRow::KFCInsertRow( const TQString& name, Container* document, MatrixElement* m, uint r, uint c )
|
|
: KFCRemoveRow( name, document, m, r, c )
|
|
{
|
|
row = new TQPtrList< MatrixSequenceElement >;
|
|
row->setAutoDelete( true );
|
|
for ( uint i = 0; i < matrix->getColumns(); i++ ) {
|
|
row->append( new MatrixSequenceElement( matrix ) );
|
|
}
|
|
}
|
|
|
|
|
|
KFCRemoveColumn::KFCRemoveColumn( const TQString& name, Container* document, MatrixElement* m, uint r, uint c )
|
|
: Command( name, document ), matrix( m ), rowPos( r ), colPos( c )
|
|
{
|
|
column = new TQPtrList< MatrixSequenceElement >;
|
|
column->setAutoDelete( true );
|
|
}
|
|
|
|
KFCRemoveColumn::~KFCRemoveColumn()
|
|
{
|
|
delete column;
|
|
}
|
|
|
|
void KFCRemoveColumn::execute()
|
|
{
|
|
FormulaCursor* cursor = getExecuteCursor();
|
|
FormulaElement* formula = matrix->formula();
|
|
for ( uint i = 0; i < matrix->getRows(); i++ ) {
|
|
column->append( matrix->getElement( i, colPos ) );
|
|
formula->elementRemoval( column->at( i ) );
|
|
matrix->content.at( i )->take( colPos );
|
|
}
|
|
formula->changed();
|
|
if ( colPos < matrix->getColumns() ) {
|
|
matrix->getElement( rowPos, colPos )->goInside( cursor );
|
|
}
|
|
else {
|
|
matrix->getElement( rowPos, colPos-1 )->goInside( cursor );
|
|
}
|
|
testDirty();
|
|
}
|
|
|
|
void KFCRemoveColumn::unexecute()
|
|
{
|
|
for ( uint i = 0; i < matrix->getRows(); i++ ) {
|
|
matrix->content.at( i )->insert( colPos, column->take( 0 ) );
|
|
}
|
|
FormulaCursor* cursor = getExecuteCursor();
|
|
matrix->getElement( rowPos, colPos )->goInside( cursor );
|
|
matrix->formula()->changed();
|
|
testDirty();
|
|
}
|
|
|
|
|
|
KFCInsertColumn::KFCInsertColumn( const TQString& name, Container* document, MatrixElement* m, uint r, uint c )
|
|
: KFCRemoveColumn( name, document, m, r, c )
|
|
{
|
|
for ( uint i = 0; i < matrix->getRows(); i++ ) {
|
|
column->append( new MatrixSequenceElement( matrix ) );
|
|
}
|
|
}
|
|
|
|
|
|
MatrixElement::MatrixElement(uint rows, uint columns, BasicElement* parent)
|
|
: BasicElement(parent),
|
|
m_rowNumber( 0 ),
|
|
m_align( NoAlign ),
|
|
m_widthType( NoSize ),
|
|
m_frame( NoLine ),
|
|
m_frameHSpacing( NoSize ),
|
|
m_frameVSpacing( NoSize ),
|
|
m_side( NoSide ),
|
|
m_minLabelSpacingType( NoSize ),
|
|
m_customEqualRows( false ),
|
|
m_customEqualColumns( false ),
|
|
m_customDisplayStyle( false )
|
|
{
|
|
for (uint r = 0; r < rows; r++) {
|
|
TQPtrList< MatrixSequenceElement >* list = new TQPtrList< MatrixSequenceElement >;
|
|
list->setAutoDelete(true);
|
|
for (uint c = 0; c < columns; c++) {
|
|
list->append(new MatrixSequenceElement(this));
|
|
}
|
|
content.append(list);
|
|
}
|
|
content.setAutoDelete(true);
|
|
}
|
|
|
|
MatrixElement::~MatrixElement()
|
|
{
|
|
}
|
|
|
|
|
|
MatrixElement::MatrixElement( const MatrixElement& other )
|
|
: BasicElement( other )
|
|
{
|
|
uint rows = other.getRows();
|
|
uint columns = other.getColumns();
|
|
|
|
TQPtrListIterator< TQPtrList< MatrixSequenceElement > > rowIter( other.content );
|
|
for (uint r = 0; r < rows; r++) {
|
|
++rowIter;
|
|
TQPtrListIterator< MatrixSequenceElement > colIter( *rowIter.current() );
|
|
|
|
TQPtrList< MatrixSequenceElement >* list = new TQPtrList< MatrixSequenceElement >;
|
|
list->setAutoDelete(true);
|
|
for (uint c = 0; c < columns; c++) {
|
|
++colIter;
|
|
MatrixSequenceElement *mse =
|
|
//new MatrixSequenceElement( *( other.getElement( r, c ) ) );
|
|
new MatrixSequenceElement( *colIter.current() );
|
|
list->append( mse );
|
|
mse->setParent( this );
|
|
}
|
|
content.append(list);
|
|
}
|
|
content.setAutoDelete(true);
|
|
}
|
|
|
|
|
|
bool MatrixElement::accept( ElementVisitor* visitor )
|
|
{
|
|
return visitor->visit( this );
|
|
}
|
|
|
|
|
|
void MatrixElement::entered( SequenceElement* /*child*/ )
|
|
{
|
|
formula()->tell( i18n( "Matrix element" ) );
|
|
}
|
|
|
|
|
|
BasicElement* MatrixElement::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());
|
|
|
|
uint rows = getRows();
|
|
uint columns = getColumns();
|
|
|
|
for (uint r = 0; r < rows; r++) {
|
|
for (uint c = 0; c < columns; c++) {
|
|
BasicElement* element = getElement(r, c);
|
|
e = element->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();
|
|
|
|
uint row = rows;
|
|
for (uint r = 0; r < rows; r++) {
|
|
BasicElement* element = getElement(r, 0);
|
|
if (element->getY() > dy) {
|
|
row = r;
|
|
break;
|
|
}
|
|
}
|
|
if (row == 0) {
|
|
BasicElement* element = getParent();
|
|
element->moveLeft(cursor, this);
|
|
handled = true;
|
|
return element;
|
|
}
|
|
row--;
|
|
|
|
uint column = columns;
|
|
for (uint c = 0; c < columns; c++) {
|
|
BasicElement* element = getElement(row, c);
|
|
if (element->getX() > dx) {
|
|
column = c;
|
|
break;
|
|
}
|
|
}
|
|
if (column == 0) {
|
|
BasicElement* element = getParent();
|
|
element->moveLeft(cursor, this);
|
|
handled = true;
|
|
return element;
|
|
}
|
|
column--;
|
|
|
|
// Rescan the rows with the actual colums required.
|
|
row = rows;
|
|
for (uint r = 0; r < rows; r++) {
|
|
BasicElement* element = getElement(r, column);
|
|
if (element->getY() > dy) {
|
|
row = r;
|
|
break;
|
|
}
|
|
}
|
|
if (row == 0) {
|
|
BasicElement* element = getParent();
|
|
element->moveLeft(cursor, this);
|
|
handled = true;
|
|
return element;
|
|
}
|
|
row--;
|
|
|
|
BasicElement* element = getElement(row, column);
|
|
element->moveLeft(cursor, this);
|
|
handled = true;
|
|
return element;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
// drawing
|
|
//
|
|
// Drawing depends on a context which knows the required properties like
|
|
// fonts, spaces and such.
|
|
// It is essential to calculate elements size with the same context
|
|
// before you draw.
|
|
|
|
/**
|
|
* Calculates our width and height and
|
|
* our tqchildren's parentPosition.
|
|
*/
|
|
void MatrixElement::calcSizes( const ContextStyle& context,
|
|
ContextStyle::TextStyle tstyle,
|
|
ContextStyle::IndexStyle istyle,
|
|
StyleAttributes& style )
|
|
{
|
|
TQMemArray<luPixel> toMidlines(getRows());
|
|
TQMemArray<luPixel> fromMidlines(getRows());
|
|
TQMemArray<luPixel> widths(getColumns());
|
|
|
|
toMidlines.fill(0);
|
|
fromMidlines.fill(0);
|
|
widths.fill(0);
|
|
|
|
uint rows = getRows();
|
|
uint columns = getColumns();
|
|
|
|
ContextStyle::TextStyle i_tstyle = context.convertTextStyleFraction(tstyle);
|
|
ContextStyle::IndexStyle i_istyle = context.convertIndexStyleUpper(istyle);
|
|
double factor = style.sizeFactor();
|
|
|
|
for (uint r = 0; r < rows; r++) {
|
|
TQPtrList< MatrixSequenceElement >* list = content.at(r);
|
|
for (uint c = 0; c < columns; c++) {
|
|
SequenceElement* element = list->at(c);
|
|
element->calcSizes( context, i_tstyle, i_istyle, style );
|
|
toMidlines[r] = TQMAX(toMidlines[r], element->axis( context, i_tstyle, factor ));
|
|
fromMidlines[r] = TQMAX(fromMidlines[r],
|
|
element->getHeight()-element->axis( context, i_tstyle, factor ));
|
|
widths[c] = TQMAX(widths[c], element->getWidth());
|
|
}
|
|
}
|
|
|
|
luPixel distX = context.ptToPixelX( context.getThinSpace( tstyle, factor ) );
|
|
luPixel distY = context.ptToPixelY( context.getThinSpace( tstyle, factor ) );
|
|
|
|
luPixel yPos = 0;
|
|
for (uint r = 0; r < rows; r++) {
|
|
TQPtrList< MatrixSequenceElement >* list = content.at(r);
|
|
luPixel xPos = 0;
|
|
yPos += toMidlines[r];
|
|
for (uint c = 0; c < columns; c++) {
|
|
SequenceElement* element = list->at(c);
|
|
switch (context.getMatrixAlignment()) {
|
|
case ContextStyle::left:
|
|
element->setX(xPos);
|
|
break;
|
|
case ContextStyle::center:
|
|
element->setX(xPos + (widths[c] - element->getWidth())/2);
|
|
break;
|
|
case ContextStyle::right:
|
|
element->setX(xPos + widths[c] - element->getWidth());
|
|
break;
|
|
}
|
|
element->setY(yPos - element->axis( context, i_tstyle, factor ));
|
|
xPos += widths[c] + distX;
|
|
}
|
|
yPos += fromMidlines[r] + distY;
|
|
}
|
|
|
|
luPixel width = distX * (columns - 1);
|
|
luPixel height = distY * (rows - 1);
|
|
|
|
for (uint r = 0; r < rows; r++) height += toMidlines[r] + fromMidlines[r];
|
|
for (uint c = 0; c < columns; c++) width += widths[c];
|
|
|
|
setWidth(width);
|
|
setHeight(height);
|
|
if ((rows == 2) && (columns == 1)) {
|
|
setBaseline( getMainChild()->getHeight() + distY / 2 + context.axisHeight( tstyle, factor ) );
|
|
}
|
|
else {
|
|
setBaseline( height/2 + context.axisHeight( tstyle, factor ) );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Draws the whole element including its tqchildren.
|
|
* The `parentOrigin' is the point this element's parent starts.
|
|
* We can use our parentPosition to get our own origin then.
|
|
*/
|
|
void MatrixElement::draw( TQPainter& painter, const LuPixelRect& rect,
|
|
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( rect ) )
|
|
// return;
|
|
|
|
uint rows = getRows();
|
|
uint columns = getColumns();
|
|
|
|
for (uint r = 0; r < rows; r++) {
|
|
for (uint c = 0; c < columns; c++) {
|
|
getElement(r, c)->draw(painter, rect, context,
|
|
context.convertTextStyleFraction(tstyle),
|
|
context.convertIndexStyleUpper(istyle),
|
|
style,
|
|
myPos);
|
|
}
|
|
}
|
|
|
|
// Debug
|
|
//painter.setPen(TQt::red);
|
|
//painter.drawRect(myPos.x(), myPos.y(), getWidth(), getHeight());
|
|
}
|
|
|
|
|
|
void MatrixElement::dispatchFontCommand( FontCommand* cmd )
|
|
{
|
|
uint rows = getRows();
|
|
uint columns = getColumns();
|
|
|
|
for (uint r = 0; r < rows; r++) {
|
|
for (uint c = 0; c < columns; c++) {
|
|
getElement(r, c)->dispatchFontCommand( cmd );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// navigation
|
|
//
|
|
// The elements are responsible to handle cursor movement themselves.
|
|
// To do this they need to know the direction the cursor moves and
|
|
// the element it comes from.
|
|
//
|
|
// The cursor might be in normal or in selection mode.
|
|
|
|
/**
|
|
* Enters this element while moving to the left starting inside
|
|
* the element `from'. Searches for a cursor position inside
|
|
* this element or to the left of it.
|
|
*/
|
|
void MatrixElement::moveLeft(FormulaCursor* cursor, BasicElement* from)
|
|
{
|
|
if (cursor->isSelectionMode()) {
|
|
getParent()->moveLeft(cursor, this);
|
|
}
|
|
else {
|
|
if (from == getParent()) {
|
|
getElement(getRows()-1, getColumns()-1)->moveLeft(cursor, this);
|
|
}
|
|
else {
|
|
bool linear = cursor->getLinearMovement();
|
|
uint row = 0;
|
|
uint column = 0;
|
|
if (searchElement(from, row, column)) {
|
|
if (column > 0) {
|
|
getElement(row, column-1)->moveLeft(cursor, this);
|
|
}
|
|
else if (linear && (row > 0)) {
|
|
getElement(row-1, getColumns()-1)->moveLeft(cursor, this);
|
|
}
|
|
else {
|
|
getParent()->moveLeft(cursor, this);
|
|
}
|
|
}
|
|
else {
|
|
getParent()->moveLeft(cursor, this);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Enters this element while moving to the right starting inside
|
|
* the element `from'. Searches for a cursor position inside
|
|
* this element or to the right of it.
|
|
*/
|
|
void MatrixElement::moveRight(FormulaCursor* cursor, BasicElement* from)
|
|
{
|
|
if (cursor->isSelectionMode()) {
|
|
getParent()->moveRight(cursor, this);
|
|
}
|
|
else {
|
|
if (from == getParent()) {
|
|
getElement(0, 0)->moveRight(cursor, this);
|
|
}
|
|
else {
|
|
bool linear = cursor->getLinearMovement();
|
|
uint row = 0;
|
|
uint column = 0;
|
|
if (searchElement(from, row, column)) {
|
|
if (column < getColumns()-1) {
|
|
getElement(row, column+1)->moveRight(cursor, this);
|
|
}
|
|
else if (linear && (row < getRows()-1)) {
|
|
getElement(row+1, 0)->moveRight(cursor, this);
|
|
}
|
|
else {
|
|
getParent()->moveRight(cursor, this);
|
|
}
|
|
}
|
|
else {
|
|
getParent()->moveRight(cursor, this);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Enters this element while moving up starting inside
|
|
* the element `from'. Searches for a cursor position inside
|
|
* this element or above it.
|
|
*/
|
|
void MatrixElement::moveUp(FormulaCursor* cursor, BasicElement* from)
|
|
{
|
|
if (cursor->isSelectionMode()) {
|
|
getParent()->moveUp(cursor, this);
|
|
}
|
|
else {
|
|
if (from == getParent()) {
|
|
getElement(0, 0)->moveRight(cursor, this);
|
|
}
|
|
else {
|
|
uint row = 0;
|
|
uint column = 0;
|
|
if (searchElement(from, row, column)) {
|
|
if (row > 0) {
|
|
getElement(row-1, column)->moveRight(cursor, this);
|
|
}
|
|
else {
|
|
getParent()->moveUp(cursor, this);
|
|
}
|
|
}
|
|
else {
|
|
getParent()->moveUp(cursor, this);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Enters this element while moving down starting inside
|
|
* the element `from'. Searches for a cursor position inside
|
|
* this element or below it.
|
|
*/
|
|
void MatrixElement::moveDown(FormulaCursor* cursor, BasicElement* from)
|
|
{
|
|
if (cursor->isSelectionMode()) {
|
|
getParent()->moveDown(cursor, this);
|
|
}
|
|
else {
|
|
if (from == getParent()) {
|
|
getElement(0, 0)->moveRight(cursor, this);
|
|
}
|
|
else {
|
|
uint row = 0;
|
|
uint column = 0;
|
|
if (searchElement(from, row, column)) {
|
|
if (row < getRows()-1) {
|
|
getElement(row+1, column)->moveRight(cursor, this);
|
|
}
|
|
else {
|
|
getParent()->moveDown(cursor, this);
|
|
}
|
|
}
|
|
else {
|
|
getParent()->moveDown(cursor, this);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Sets the cursor inside this element to its start position.
|
|
* For most elements that is the main child.
|
|
*/
|
|
void MatrixElement::goInside(FormulaCursor* cursor)
|
|
{
|
|
getElement(0, 0)->goInside(cursor);
|
|
}
|
|
|
|
|
|
// If there is a main child we must provide the insert/remove semantics.
|
|
SequenceElement* MatrixElement::getMainChild()
|
|
{
|
|
return content.at(0)->at(0);
|
|
}
|
|
|
|
void MatrixElement::selectChild(FormulaCursor* cursor, BasicElement* child)
|
|
{
|
|
uint rows = getRows();
|
|
uint columns = getColumns();
|
|
for (uint r = 0; r < rows; r++) {
|
|
for (uint c = 0; c < columns; c++) {
|
|
if (child == getElement(r, c)) {
|
|
cursor->setTo(this, r*columns+c);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
const MatrixSequenceElement* MatrixElement::getElement( uint row, uint column ) const
|
|
{
|
|
TQPtrListIterator< TQPtrList < MatrixSequenceElement > > rows( content );
|
|
rows += row;
|
|
if ( ! rows.current() )
|
|
return 0;
|
|
|
|
TQPtrListIterator< MatrixSequenceElement > cols ( *rows.current() );
|
|
cols += column;
|
|
return cols.current();
|
|
}
|
|
|
|
|
|
bool MatrixElement::searchElement(BasicElement* element, uint& row, uint& column)
|
|
{
|
|
uint rows = getRows();
|
|
uint columns = getColumns();
|
|
for (uint r = 0; r < rows; r++) {
|
|
for (uint c = 0; c < columns; c++) {
|
|
if (element == getElement(r, c)) {
|
|
row = r;
|
|
column = c;
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
/**
|
|
* Appends our attributes to the dom element.
|
|
*/
|
|
void MatrixElement::writeDom(TQDomElement element)
|
|
{
|
|
BasicElement::writeDom(element);
|
|
|
|
uint rows = getRows();
|
|
uint cols = getColumns();
|
|
|
|
element.setAttribute("ROWS", rows);
|
|
element.setAttribute("COLUMNS", cols);
|
|
|
|
TQDomDocument doc = element.ownerDocument();
|
|
|
|
for (uint r = 0; r < rows; r++) {
|
|
for (uint c = 0; c < cols; c++) {
|
|
TQDomElement tmp = getElement(r,c)->getElementDom(doc);
|
|
element.appendChild(tmp);
|
|
}
|
|
element.appendChild(doc.createComment("end of row"));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Reads our attributes from the element.
|
|
* Returns false if it failed.
|
|
*/
|
|
bool MatrixElement::readAttributesFromDom(TQDomElement element)
|
|
{
|
|
if (!BasicElement::readAttributesFromDom(element)) {
|
|
return false;
|
|
}
|
|
uint rows = 0;
|
|
TQString rowStr = element.attribute("ROWS");
|
|
if(!rowStr.isNull()) {
|
|
rows = rowStr.toInt();
|
|
}
|
|
if (rows == 0) {
|
|
kdWarning( DEBUGID ) << "Rows <= 0 in MatrixElement." << endl;
|
|
return false;
|
|
}
|
|
|
|
TQString columnStr = element.attribute("COLUMNS");
|
|
uint cols = 0;
|
|
if(!columnStr.isNull()) {
|
|
cols = columnStr.toInt();
|
|
}
|
|
if (cols == 0) {
|
|
kdWarning( DEBUGID ) << "Columns <= 0 in MatrixElement." << endl;
|
|
return false;
|
|
}
|
|
|
|
content.clear();
|
|
for (uint r = 0; r < rows; r++) {
|
|
TQPtrList< MatrixSequenceElement >* list = new TQPtrList< MatrixSequenceElement >;
|
|
list->setAutoDelete(true);
|
|
content.append(list);
|
|
for (uint c = 0; c < cols; c++) {
|
|
MatrixSequenceElement* element = new MatrixSequenceElement(this);
|
|
list->append(element);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Reads our content from the node. Sets the node to the next node
|
|
* that needs to be read.
|
|
* Returns false if it failed.
|
|
*/
|
|
bool MatrixElement::readContentFromDom(TQDomNode& node)
|
|
{
|
|
if (!BasicElement::readContentFromDom(node)) {
|
|
return false;
|
|
}
|
|
|
|
uint rows = getRows();
|
|
uint cols = getColumns();
|
|
|
|
uint r = 0;
|
|
uint c = 0;
|
|
while ( !node.isNull() && r < rows ) {
|
|
if ( node.isElement() ) {
|
|
SequenceElement* element = getElement( r, c );
|
|
TQDomElement e = node.toElement();
|
|
if ( !element->buildFromDom( e ) ) {
|
|
return false;
|
|
}
|
|
c++;
|
|
if ( c == cols ) {
|
|
c = 0;
|
|
r++;
|
|
}
|
|
}
|
|
node = node.nextSibling();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool MatrixElement::readAttributesFromMathMLDom( const TQDomElement& element )
|
|
{
|
|
if ( ! BasicElement::readAttributesFromMathMLDom( element ) ) {
|
|
return false;
|
|
}
|
|
|
|
TQString alignStr = element.attribute( "align" ).lower();
|
|
if ( ! alignStr.isNull() ) {
|
|
if ( alignStr.find( "top" ) != -1 ) {
|
|
m_align = TopAlign;
|
|
}
|
|
else if ( alignStr.find( "bottom" ) != -1 ) {
|
|
m_align = BottomAlign;
|
|
}
|
|
else if ( alignStr.find( "center" ) != -1 ) {
|
|
m_align = CenterAlign;
|
|
}
|
|
else if ( alignStr.find( "baseline" ) != -1 ) {
|
|
m_align = BaselineAlign;
|
|
}
|
|
else if ( alignStr.find( "axis" ) != -1 ) {
|
|
m_align = AxisAlign;
|
|
}
|
|
int index = alignStr.findRev( ' ' );
|
|
if ( index != -1 ) {
|
|
m_rowNumber = alignStr.right( index + 1 ).toInt();
|
|
}
|
|
}
|
|
TQString rowalignStr = element.attribute( "rowalign" ).lower();
|
|
if ( ! rowalignStr.isNull() ) {
|
|
TQStringList list = TQStringList::split( ' ', rowalignStr );
|
|
for ( TQStringList::iterator it = list.begin(); it != list.end(); it++ ) {
|
|
if ( *it == "top" ) {
|
|
m_rowAlign.append( TopAlign );
|
|
}
|
|
else if ( *it == "bottom" ) {
|
|
m_rowAlign.append( BottomAlign );
|
|
}
|
|
else if ( *it == "center" ) {
|
|
m_rowAlign.append( CenterAlign );
|
|
}
|
|
else if ( *it == "baseline" ) {
|
|
m_rowAlign.append( BaselineAlign );
|
|
}
|
|
else if ( *it == "axis" ) {
|
|
m_rowAlign.append( AxisAlign );
|
|
}
|
|
}
|
|
}
|
|
TQString columnalignStr = element.attribute( "columnalign" ).lower();
|
|
if ( ! columnalignStr.isNull() ) {
|
|
TQStringList list = TQStringList::split( ' ', columnalignStr );
|
|
for ( TQStringList::iterator it = list.begin(); it != list.end(); it++ ) {
|
|
if ( *it == "left" ) {
|
|
m_columnAlign.append( LeftHorizontalAlign );
|
|
}
|
|
else if ( *it == "center" ) {
|
|
m_columnAlign.append( CenterHorizontalAlign );
|
|
}
|
|
else if ( *it == "right" ) {
|
|
m_columnAlign.append( RightHorizontalAlign );
|
|
}
|
|
}
|
|
}
|
|
TQString alignmentscopeStr = element.attribute( "alignmentscope" ).lower();
|
|
if ( ! alignmentscopeStr.isNull() ) {
|
|
TQStringList list = TQStringList::split( ' ', alignmentscopeStr );
|
|
for ( TQStringList::iterator it = list.begin(); it != list.end(); it++ ) {
|
|
if ( *it == "true" ) {
|
|
m_alignmentScope.append( true );
|
|
}
|
|
else if ( *it == "false" ) {
|
|
m_alignmentScope.append( false );
|
|
}
|
|
}
|
|
}
|
|
TQString columnwidthStr = element.attribute( "columnwidth" ).lower();
|
|
if ( columnwidthStr.isNull() ) {
|
|
TQStringList list = TQStringList::split( ' ', columnwidthStr );
|
|
for ( TQStringList::iterator it = list.begin(); it != list.end(); it++ ) {
|
|
SizeType type = NoSize;
|
|
double length;
|
|
if ( *it == "auto" ) {
|
|
type = AutoSize;
|
|
}
|
|
else if ( *it == "fit" ) {
|
|
type = FitSize;
|
|
}
|
|
else {
|
|
length = getSize( columnwidthStr, &type );
|
|
if ( type == NoSize ) {
|
|
type = getSpace( columnwidthStr );
|
|
}
|
|
}
|
|
if ( type != NoSize ) {
|
|
m_columnWidthType.append( type );
|
|
if ( type == RelativeSize || type == AbsoluteSize || type == PixelSize ) {
|
|
m_columnWidth.append( length );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
TQString widthStr = element.attribute( "width" ).lower();
|
|
if ( ! widthStr.isNull() ) {
|
|
if ( widthStr == "auto" ) {
|
|
m_widthType = AutoSize;
|
|
}
|
|
else {
|
|
m_width = getSize( widthStr, &m_widthType );
|
|
}
|
|
}
|
|
TQString rowspacingStr = element.attribute( "rowspacing" ).lower();
|
|
if ( ! rowspacingStr.isNull() ) {
|
|
TQStringList list = TQStringList::split( ' ', rowspacingStr );
|
|
for ( TQStringList::iterator it = list.begin(); it != list.end(); it++ ) {
|
|
SizeType type;
|
|
double length = getSize( *it, &type );
|
|
if ( type != NoSize ) {
|
|
m_rowSpacingType.append( type );
|
|
m_rowSpacing.append( length );
|
|
}
|
|
}
|
|
}
|
|
TQString columnspacingStr = element.attribute( "columnspacing" ).lower();
|
|
if ( ! columnspacingStr.isNull() ) {
|
|
TQStringList list = TQStringList::split( ' ', columnspacingStr );
|
|
for ( TQStringList::iterator it = list.begin(); it != list.end(); it++ ) {
|
|
SizeType type;
|
|
double length = getSize( *it, &type );
|
|
if ( type == NoSize ) {
|
|
type = getSpace( columnspacingStr );
|
|
}
|
|
if ( type != NoSize ) {
|
|
m_columnSpacingType.append( type );
|
|
if ( type == RelativeSize || type == AbsoluteSize || type == PixelSize ) {
|
|
m_columnSpacing.append( length );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
TQString rowlinesStr = element.attribute( "rowlines" ).lower();
|
|
if ( ! rowlinesStr.isNull() ) {
|
|
TQStringList list = TQStringList::split( ' ', rowlinesStr );
|
|
for ( TQStringList::iterator it = list.begin(); it != list.end(); it++ ) {
|
|
if ( *it == "none" ) {
|
|
m_rowLines.append( NoneLine );
|
|
}
|
|
else if ( *it == "solid" ) {
|
|
m_rowLines.append( SolidLine );
|
|
}
|
|
else if ( *it == "dashed" ) {
|
|
m_rowLines.append( DashedLine );
|
|
}
|
|
}
|
|
}
|
|
TQString columnlinesStr = element.attribute( "columnlines" ).lower();
|
|
if ( ! columnlinesStr.isNull() ) {
|
|
TQStringList list = TQStringList::split( ' ', columnlinesStr );
|
|
for ( TQStringList::iterator it = list.begin(); it != list.end(); it++ ) {
|
|
if ( *it == "none" ) {
|
|
m_columnLines.append( NoneLine );
|
|
}
|
|
else if ( *it == "solid" ) {
|
|
m_columnLines.append( SolidLine );
|
|
}
|
|
else if ( *it == "dashed" ) {
|
|
m_columnLines.append( DashedLine );
|
|
}
|
|
}
|
|
}
|
|
TQString frameStr = element.attribute( "frame" ).stripWhiteSpace().lower();
|
|
if ( ! frameStr.isNull() ) {
|
|
if ( frameStr == "none" ) {
|
|
m_frame = NoneLine;
|
|
}
|
|
else if ( frameStr == "solid" ) {
|
|
m_frame = SolidLine;
|
|
}
|
|
else if ( frameStr == "dashed" ) {
|
|
m_frame = DashedLine;
|
|
}
|
|
}
|
|
TQString framespacingStr = element.attribute( "framespacing" );
|
|
if ( ! framespacingStr.isNull() ) {
|
|
TQStringList list = TQStringList::split( ' ', framespacingStr );
|
|
m_frameHSpacing = getSize( list[0], &m_frameHSpacingType );
|
|
if ( m_frameHSpacingType == NoSize ) {
|
|
m_frameHSpacingType = getSpace( list[0] );
|
|
}
|
|
if ( list.count() > 1 ) {
|
|
m_frameVSpacing = getSize( list[1], &m_frameVSpacingType );
|
|
if ( m_frameVSpacingType == NoSize ) {
|
|
m_frameVSpacingType = getSpace( list[1] );
|
|
}
|
|
}
|
|
}
|
|
TQString equalrowsStr = element.attribute( "equalrows" ).stripWhiteSpace().lower();
|
|
if ( ! equalrowsStr.isNull() ) {
|
|
m_customEqualRows = true;
|
|
if ( equalrowsStr == "false" ) {
|
|
m_equalRows = false;
|
|
}
|
|
else {
|
|
m_equalRows = true;
|
|
}
|
|
}
|
|
TQString equalcolumnsStr = element.attribute( "equalcolumns" ).stripWhiteSpace().lower();
|
|
if ( ! equalcolumnsStr.isNull() ) {
|
|
m_customEqualColumns = true;
|
|
if ( equalcolumnsStr == "false" ) {
|
|
m_equalColumns = false;
|
|
}
|
|
else {
|
|
m_equalColumns = true;
|
|
}
|
|
}
|
|
TQString displaystyleStr = element.attribute( "displaystyle" ).stripWhiteSpace().lower();
|
|
if ( ! displaystyleStr.isNull() ) {
|
|
m_customDisplayStyle = true;
|
|
if ( displaystyleStr == "false" ) {
|
|
m_displayStyle = false;
|
|
}
|
|
else {
|
|
m_displayStyle = true;
|
|
}
|
|
}
|
|
TQString sideStr = element.attribute( "side" ).stripWhiteSpace().lower();
|
|
if ( ! sideStr.isNull() ) {
|
|
if ( sideStr == "left" ) {
|
|
m_side = LeftSide;
|
|
}
|
|
else if ( sideStr == "right" ) {
|
|
m_side = RightSide;
|
|
}
|
|
else if ( sideStr == "leftoverlap" ) {
|
|
m_side = LeftOverlapSide;
|
|
}
|
|
else if ( sideStr == "rightoverlap" ) {
|
|
m_side = RightOverlapSide;
|
|
}
|
|
}
|
|
TQString minlabelspacingStr = element.attribute( "minlabelspacing" ).stripWhiteSpace().lower();
|
|
if ( ! minlabelspacingStr.isNull() ) {
|
|
m_minLabelSpacing = getSize( minlabelspacingStr, &m_minLabelSpacingType );
|
|
if ( m_minLabelSpacingType == NoSize ) {
|
|
m_minLabelSpacingType = getSpace( minlabelspacingStr );
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Reads our content from the MathML node. Sets the node to the next node
|
|
* that needs to be read. It is sometimes needed to read more than one node
|
|
* (e. g. for fence operators).
|
|
* Returns the number of nodes processed or -1 if it failed.
|
|
*/
|
|
int MatrixElement::readContentFromMathMLDom( TQDomNode& node )
|
|
{
|
|
// We have twice, since there may be empty elements and we need to know how
|
|
// many of them we have. So, first pass, get number of rows and columns
|
|
|
|
if ( BasicElement::readContentFromMathMLDom( node ) == -1 ) {
|
|
return -1;
|
|
}
|
|
|
|
uint rows = 0;
|
|
uint cols = 0;
|
|
TQDomNode n = node;
|
|
while ( !n.isNull() ) {
|
|
if ( n.isElement() ) {
|
|
TQDomElement e = n.toElement();
|
|
if ( e.tagName().lower() == "mtr" || e.tagName().lower() == "mlabeledtr" )
|
|
{
|
|
rows++;
|
|
|
|
/* Determins the number of columns */
|
|
TQDomNode cellnode = e.firstChild();
|
|
int cc = 0;
|
|
|
|
while ( !cellnode.isNull() ) {
|
|
if ( cellnode.isElement() )
|
|
cc++;
|
|
cellnode = cellnode.nextSibling();
|
|
}
|
|
if ( cc > 0 && e.tagName().lower() == "mlabeledtr" )
|
|
cc--;
|
|
if ( cc > cols )
|
|
cols = cc;
|
|
}
|
|
}
|
|
n = n.nextSibling();
|
|
}
|
|
|
|
// Create elements
|
|
content.clear();
|
|
for (uint r = 0; r < rows; r++) {
|
|
TQPtrList< MatrixSequenceElement >* list = new TQPtrList< MatrixSequenceElement >;
|
|
list->setAutoDelete(true);
|
|
content.append(list);
|
|
for (uint c = 0; c < cols; c++) {
|
|
MatrixSequenceElement* element = new MatrixSequenceElement(this);
|
|
list->append(element);
|
|
}
|
|
}
|
|
|
|
// Second pass, read elements now
|
|
uint r = 0;
|
|
uint c = 0;
|
|
while ( !node.isNull() ) {
|
|
if ( node.isElement() ) {
|
|
TQDomElement e = node.toElement();
|
|
if ( e.tagName().lower() == "mtr" || e.tagName().lower() == "mlabeledtr" ) {
|
|
TQDomNode cellnode = e.firstChild();
|
|
if ( e.tagName().lower() == "mlabeledtr" ) {
|
|
while ( ! cellnode.isNull() && ! cellnode.isElement() )
|
|
cellnode = cellnode.nextSibling();
|
|
if ( ! cellnode.isNull() )
|
|
cellnode = cellnode.nextSibling();
|
|
}
|
|
while ( !cellnode.isNull() ) {
|
|
if ( cellnode.isElement() ) {
|
|
TQDomElement cellelement = cellnode.toElement();
|
|
if ( cellelement.tagName().lower() != "mtd" ) {
|
|
// TODO: Inferred mtd. Deprecated in MathML 2.0
|
|
kdWarning( DEBUGID ) << "Unsupported tag "
|
|
<< cellelement.tagName()
|
|
<< " inside matrix row\n";
|
|
}
|
|
else {
|
|
SequenceElement* element = getElement(r, c);
|
|
if ( element->buildFromMathMLDom( cellelement ) == -1 )
|
|
return -1;
|
|
c++;
|
|
}
|
|
}
|
|
cellnode = cellnode.nextSibling();
|
|
}
|
|
c = 0;
|
|
r++;
|
|
}
|
|
}
|
|
node = node.nextSibling();
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
TQString MatrixElement::toLatex()
|
|
{
|
|
//All the border handling must be implemented here too
|
|
|
|
TQString matrix;
|
|
uint cols=getColumns();
|
|
uint rows=getRows();
|
|
|
|
matrix="\\begin{array}{ ";
|
|
for(uint i=0;i<cols;i++)
|
|
matrix+="c ";
|
|
|
|
matrix+="} ";
|
|
|
|
for (uint r = 0; r < rows; r++) {
|
|
for (uint c = 0; c < cols; c++) {
|
|
matrix+=getElement(r, c)->toLatex();
|
|
if( c < cols-1) matrix+=" & ";
|
|
}
|
|
if(r < rows-1 ) matrix+=" \\\\ ";
|
|
}
|
|
|
|
matrix+=" \\end{array}";
|
|
|
|
return matrix;
|
|
}
|
|
|
|
TQString MatrixElement::formulaString()
|
|
{
|
|
TQString matrix = "[";
|
|
uint cols=getColumns();
|
|
uint rows=getRows();
|
|
for (uint r = 0; r < rows; r++) {
|
|
matrix += "[";
|
|
for (uint c = 0; c < cols; c++) {
|
|
matrix+=getElement(r, c)->formulaString();
|
|
if ( c < cols-1 ) matrix+=", ";
|
|
}
|
|
matrix += "]";
|
|
if ( r < rows-1 ) matrix += ", ";
|
|
}
|
|
matrix += "]";
|
|
return matrix;
|
|
}
|
|
|
|
|
|
SequenceElement* MatrixElement::elementAt(uint row, uint column)
|
|
{
|
|
return getElement( row, column );
|
|
}
|
|
|
|
void MatrixElement::writeMathMLAttributes( TQDomElement& element ) const
|
|
{
|
|
TQString rownumber;
|
|
if ( m_rowNumber ) {
|
|
rownumber = TQString( " %1" ).tqarg( m_rowNumber );
|
|
}
|
|
switch ( m_align ) {
|
|
case TopAlign:
|
|
element.setAttribute( "align", "top" + rownumber );
|
|
break;
|
|
case BottomAlign:
|
|
element.setAttribute( "align", "bottom" + rownumber );
|
|
break;
|
|
case CenterAlign:
|
|
element.setAttribute( "align", "center" + rownumber );
|
|
break;
|
|
case BaselineAlign:
|
|
element.setAttribute( "align", "baseline" + rownumber );
|
|
break;
|
|
case AxisAlign:
|
|
element.setAttribute( "align", "axis" + rownumber );
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
TQString rowalign;
|
|
for ( TQValueList<VerticalAlign >::const_iterator it = m_rowAlign.begin(); it != m_rowAlign.end(); it++ )
|
|
{
|
|
switch ( *it ) {
|
|
case TopAlign:
|
|
rowalign.append( "top " );
|
|
break;
|
|
case BottomAlign:
|
|
rowalign.append( "bottom " );
|
|
break;
|
|
case CenterAlign:
|
|
rowalign.append( "center " );
|
|
break;
|
|
case BaselineAlign:
|
|
rowalign.append( "baseline " );
|
|
break;
|
|
case AxisAlign:
|
|
rowalign.append( "axis " );
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
if ( ! rowalign.isNull() ) {
|
|
element.setAttribute( "rowalign", rowalign.stripWhiteSpace() );
|
|
}
|
|
TQString columnalign;
|
|
for ( TQValueList<HorizontalAlign >::const_iterator it = m_columnAlign.begin(); it != m_columnAlign.end(); it++ )
|
|
{
|
|
switch ( *it ) {
|
|
case LeftHorizontalAlign:
|
|
rowalign.append( "left " );
|
|
break;
|
|
case CenterHorizontalAlign:
|
|
rowalign.append( "center " );
|
|
break;
|
|
case RightHorizontalAlign:
|
|
rowalign.append( "right " );
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
if ( ! columnalign.isNull() ) {
|
|
element.setAttribute( "columnalign", columnalign.stripWhiteSpace() );
|
|
}
|
|
TQString alignmentscope;
|
|
for ( TQValueList< bool >::const_iterator it = m_alignmentScope.begin(); it != m_alignmentScope.end(); it++ )
|
|
{
|
|
if ( *it ) {
|
|
alignmentscope.append( "true " );
|
|
}
|
|
else {
|
|
alignmentscope.append( "false " );
|
|
}
|
|
}
|
|
if ( ! alignmentscope.isNull() ) {
|
|
element.setAttribute( "alignmentscope", alignmentscope.stripWhiteSpace() );
|
|
}
|
|
TQString columnwidth;
|
|
TQValueList< double >::const_iterator lengthIt = m_columnWidth.begin();
|
|
for ( TQValueList< SizeType >::const_iterator typeIt = m_columnWidthType.begin();
|
|
typeIt != m_columnWidthType.end(); typeIt ++ ) {
|
|
switch ( *typeIt ) {
|
|
case AutoSize:
|
|
columnwidth.append( "auto " );
|
|
break;
|
|
case FitSize:
|
|
columnwidth.append( "fit " );
|
|
break;
|
|
case AbsoluteSize:
|
|
columnwidth.append( TQString( "%1pt " ).tqarg( *lengthIt ) );
|
|
lengthIt++;
|
|
break;
|
|
case RelativeSize:
|
|
columnwidth.append( TQString( "%1% " ).tqarg( *lengthIt * 100.0 ) );
|
|
lengthIt++;
|
|
break;
|
|
case PixelSize:
|
|
columnwidth.append( TQString( "%1px " ).tqarg( *lengthIt ) );
|
|
lengthIt++;
|
|
break;
|
|
case NegativeVeryVeryThinMathSpace:
|
|
columnwidth.append( "negativeveryverythinmathspace " );
|
|
break;
|
|
case NegativeVeryThinMathSpace:
|
|
columnwidth.append( "negativeverythinmathspace " );
|
|
break;
|
|
case NegativeThinMathSpace:
|
|
columnwidth.append( "negativethinmathspace " );
|
|
break;
|
|
case NegativeMediumMathSpace:
|
|
columnwidth.append( "negativemediummathspace " );
|
|
break;
|
|
case NegativeThickMathSpace:
|
|
columnwidth.append( "negativethickmathspace " );
|
|
break;
|
|
case NegativeVeryThickMathSpace:
|
|
columnwidth.append( "negativeverythickmathspace " );
|
|
break;
|
|
case NegativeVeryVeryThickMathSpace:
|
|
columnwidth.append( "negativeveryverythickmathspace " );
|
|
break;
|
|
case VeryVeryThinMathSpace:
|
|
columnwidth.append( "veryverythinmathspace " );
|
|
break;
|
|
case VeryThinMathSpace:
|
|
columnwidth.append( "verythinmathspace " );
|
|
break;
|
|
case ThinMathSpace:
|
|
columnwidth.append( "thinmathspace " );
|
|
break;
|
|
case MediumMathSpace:
|
|
columnwidth.append( "mediummathspace " );
|
|
break;
|
|
case ThickMathSpace:
|
|
columnwidth.append( "thickmathspace " );
|
|
break;
|
|
case VeryThickMathSpace:
|
|
columnwidth.append( "verythickmathspace " );
|
|
break;
|
|
case VeryVeryThickMathSpace:
|
|
columnwidth.append( "veryverythickmathspace " );
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
if ( ! columnwidth.isNull() ) {
|
|
element.setAttribute( "columnwidth", columnwidth.stripWhiteSpace() );
|
|
}
|
|
switch ( m_widthType ) {
|
|
case AutoSize:
|
|
element.setAttribute( "width", "auto" );
|
|
break;
|
|
case AbsoluteSize:
|
|
element.setAttribute( "width", TQString( "%1pt" ).tqarg( m_width ) );
|
|
break;
|
|
case RelativeSize:
|
|
element.setAttribute( "width", TQString( "%1% " ).tqarg( m_width * 100.0 ) );
|
|
break;
|
|
case PixelSize:
|
|
element.setAttribute( "width", TQString( "%1px " ).tqarg( m_width ) );
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
TQString rowspacing;
|
|
lengthIt = m_rowSpacing.begin();
|
|
for ( TQValueList< SizeType >::const_iterator typeIt = m_rowSpacingType.begin();
|
|
typeIt != m_rowSpacingType.end(); typeIt++, lengthIt++ ) {
|
|
switch ( *typeIt ) {
|
|
case AbsoluteSize:
|
|
rowspacing.append( TQString( "%1pt " ).tqarg( *lengthIt ) );
|
|
break;
|
|
case RelativeSize:
|
|
rowspacing.append( TQString( "%1% " ).tqarg( *lengthIt * 100.0 ) );
|
|
break;
|
|
case PixelSize:
|
|
rowspacing.append( TQString( "%1px " ).tqarg( *lengthIt ) );
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
if ( ! rowspacing.isNull() ) {
|
|
element.setAttribute( "rowspacing", rowspacing.stripWhiteSpace() );
|
|
}
|
|
TQString columnspacing;
|
|
lengthIt = m_columnSpacing.begin();
|
|
for ( TQValueList< SizeType >::const_iterator typeIt = m_columnSpacingType.begin();
|
|
typeIt != m_columnSpacingType.end(); typeIt++ ) {
|
|
switch ( *typeIt ) {
|
|
case AbsoluteSize:
|
|
columnspacing.append( TQString( "%1pt " ).tqarg( *lengthIt ) );
|
|
lengthIt++;
|
|
break;
|
|
case RelativeSize:
|
|
columnspacing.append( TQString( "%1% " ).tqarg( *lengthIt * 100.0 ) );
|
|
lengthIt++;
|
|
break;
|
|
case PixelSize:
|
|
columnspacing.append( TQString( "%1px " ).tqarg( *lengthIt ) );
|
|
lengthIt++;
|
|
break;
|
|
case NegativeVeryVeryThinMathSpace:
|
|
columnspacing.append( "negativeveryverythinmathspace " );
|
|
break;
|
|
case NegativeVeryThinMathSpace:
|
|
columnspacing.append( "negativeverythinmathspace " );
|
|
break;
|
|
case NegativeThinMathSpace:
|
|
columnspacing.append( "negativethinmathspace " );
|
|
break;
|
|
case NegativeMediumMathSpace:
|
|
columnspacing.append( "negativemediummathspace " );
|
|
break;
|
|
case NegativeThickMathSpace:
|
|
columnspacing.append( "negativethickmathspace " );
|
|
break;
|
|
case NegativeVeryThickMathSpace:
|
|
columnspacing.append( "negativeverythickmathspace " );
|
|
break;
|
|
case NegativeVeryVeryThickMathSpace:
|
|
columnspacing.append( "negativeveryverythickmathspace " );
|
|
break;
|
|
case VeryVeryThinMathSpace:
|
|
columnspacing.append( "veryverythinmathspace " );
|
|
break;
|
|
case VeryThinMathSpace:
|
|
columnspacing.append( "verythinmathspace " );
|
|
break;
|
|
case ThinMathSpace:
|
|
columnspacing.append( "thinmathspace " );
|
|
break;
|
|
case MediumMathSpace:
|
|
columnspacing.append( "mediummathspace " );
|
|
break;
|
|
case ThickMathSpace:
|
|
columnspacing.append( "thickmathspace " );
|
|
break;
|
|
case VeryThickMathSpace:
|
|
columnspacing.append( "verythickmathspace " );
|
|
break;
|
|
case VeryVeryThickMathSpace:
|
|
columnspacing.append( "veryverythickmathspace " );
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
if ( ! rowspacing.isNull() ) {
|
|
element.setAttribute( "rowspacing", rowspacing.stripWhiteSpace() );
|
|
}
|
|
TQString rowlines;
|
|
for ( TQValueList< LineType >::const_iterator it = m_rowLines.begin(); it != m_rowLines.end(); it++ )
|
|
{
|
|
switch ( *it ) {
|
|
case NoneLine:
|
|
rowlines.append( "none " );
|
|
break;
|
|
case SolidLine:
|
|
rowlines.append( "solid " );
|
|
break;
|
|
case DashedLine:
|
|
rowlines.append( "dashed " );
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
if ( ! rowlines.isNull() ) {
|
|
element.setAttribute( "rowlines", rowlines.stripWhiteSpace() );
|
|
}
|
|
TQString columnlines;
|
|
for ( TQValueList< LineType >::const_iterator it = m_columnLines.begin(); it != m_columnLines.end(); it++ )
|
|
{
|
|
switch ( *it ) {
|
|
case NoneLine:
|
|
columnlines.append( "none " );
|
|
break;
|
|
case SolidLine:
|
|
columnlines.append( "solid " );
|
|
break;
|
|
case DashedLine:
|
|
columnlines.append( "dashed " );
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
if ( ! columnlines.isNull() ) {
|
|
element.setAttribute( "columnlines", columnlines.stripWhiteSpace() );
|
|
}
|
|
switch ( m_frame ) {
|
|
case NoneLine:
|
|
element.setAttribute( "frame", "none" );
|
|
break;
|
|
case SolidLine:
|
|
element.setAttribute( "frame", "solid" );
|
|
break;
|
|
case DashedLine:
|
|
element.setAttribute( "frame", "dashed" );
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
TQString framespacing;
|
|
switch ( m_frameHSpacingType ) {
|
|
case AbsoluteSize:
|
|
framespacing.append( TQString( "%1pt " ).tqarg( m_frameHSpacing ) );
|
|
break;
|
|
case RelativeSize:
|
|
framespacing.append( TQString( "%1% " ).tqarg( m_frameHSpacing * 100.0 ) );
|
|
break;
|
|
case PixelSize:
|
|
framespacing.append( TQString( "%1px " ).tqarg( m_frameHSpacing ) );
|
|
break;
|
|
case NegativeVeryVeryThinMathSpace:
|
|
framespacing.append( "negativeveryverythinmathspace " );
|
|
break;
|
|
case NegativeVeryThinMathSpace:
|
|
framespacing.append( "negativeverythinmathspace " );
|
|
break;
|
|
case NegativeThinMathSpace:
|
|
framespacing.append( "negativethinmathspace " );
|
|
break;
|
|
case NegativeMediumMathSpace:
|
|
framespacing.append( "negativemediummathspace " );
|
|
break;
|
|
case NegativeThickMathSpace:
|
|
framespacing.append( "negativethickmathspace " );
|
|
break;
|
|
case NegativeVeryThickMathSpace:
|
|
framespacing.append( "negativeverythickmathspace " );
|
|
break;
|
|
case NegativeVeryVeryThickMathSpace:
|
|
framespacing.append( "negativeveryverythickmathspace " );
|
|
break;
|
|
case VeryVeryThinMathSpace:
|
|
framespacing.append( "veryverythinmathspace " );
|
|
break;
|
|
case VeryThinMathSpace:
|
|
framespacing.append( "verythinmathspace " );
|
|
break;
|
|
case ThinMathSpace:
|
|
framespacing.append( "thinmathspace " );
|
|
break;
|
|
case MediumMathSpace:
|
|
framespacing.append( "mediummathspace " );
|
|
break;
|
|
case ThickMathSpace:
|
|
framespacing.append( "thickmathspace " );
|
|
break;
|
|
case VeryThickMathSpace:
|
|
framespacing.append( "verythickmathspace " );
|
|
break;
|
|
case VeryVeryThickMathSpace:
|
|
framespacing.append( "veryverythickmathspace " );
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
switch ( m_frameVSpacingType ) {
|
|
case AbsoluteSize:
|
|
framespacing.append( TQString( "%1pt " ).tqarg( m_frameVSpacing ) );
|
|
break;
|
|
case RelativeSize:
|
|
framespacing.append( TQString( "%1% " ).tqarg( m_frameVSpacing * 100.0 ) );
|
|
break;
|
|
case PixelSize:
|
|
framespacing.append( TQString( "%1px " ).tqarg( m_frameVSpacing ) );
|
|
break;
|
|
case NegativeVeryVeryThinMathSpace:
|
|
framespacing.append( "negativeveryverythinmathspace " );
|
|
break;
|
|
case NegativeVeryThinMathSpace:
|
|
framespacing.append( "negativeverythinmathspace " );
|
|
break;
|
|
case NegativeThinMathSpace:
|
|
framespacing.append( "negativethinmathspace " );
|
|
break;
|
|
case NegativeMediumMathSpace:
|
|
framespacing.append( "negativemediummathspace " );
|
|
break;
|
|
case NegativeThickMathSpace:
|
|
framespacing.append( "negativethickmathspace " );
|
|
break;
|
|
case NegativeVeryThickMathSpace:
|
|
framespacing.append( "negativeverythickmathspace " );
|
|
break;
|
|
case NegativeVeryVeryThickMathSpace:
|
|
framespacing.append( "negativeveryverythickmathspace " );
|
|
break;
|
|
case VeryVeryThinMathSpace:
|
|
framespacing.append( "veryverythinmathspace " );
|
|
break;
|
|
case VeryThinMathSpace:
|
|
framespacing.append( "verythinmathspace " );
|
|
break;
|
|
case ThinMathSpace:
|
|
framespacing.append( "thinmathspace " );
|
|
break;
|
|
case MediumMathSpace:
|
|
framespacing.append( "mediummathspace " );
|
|
break;
|
|
case ThickMathSpace:
|
|
framespacing.append( "thickmathspace " );
|
|
break;
|
|
case VeryThickMathSpace:
|
|
framespacing.append( "verythickmathspace " );
|
|
break;
|
|
case VeryVeryThickMathSpace:
|
|
framespacing.append( "veryverythickmathspace " );
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
if ( ! framespacing.isNull() ) {
|
|
element.setAttribute( "framespacing", framespacing.stripWhiteSpace() );
|
|
}
|
|
if ( m_customEqualRows ) {
|
|
element.setAttribute( "equalrows", m_equalRows ? "true" : "false" );
|
|
}
|
|
if ( m_customEqualColumns ) {
|
|
element.setAttribute( "equalcolumns", m_equalColumns ? "true" : "false" );
|
|
}
|
|
if ( m_customDisplayStyle ) {
|
|
element.setAttribute( "displaystyle", m_displayStyle ? "true" : "false" );
|
|
}
|
|
switch ( m_side ) {
|
|
case LeftSide:
|
|
element.setAttribute( "side", "left" );
|
|
break;
|
|
case RightSide:
|
|
element.setAttribute( "side", "right" );
|
|
break;
|
|
case LeftOverlapSide:
|
|
element.setAttribute( "side", "leftoverlap" );
|
|
break;
|
|
case RightOverlapSide:
|
|
element.setAttribute( "side", "rightoverlap" );
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
switch ( m_minLabelSpacingType ) {
|
|
case AbsoluteSize:
|
|
element.setAttribute( "minlabelspacing", TQString( "%1pt" ).tqarg( m_minLabelSpacing ) );
|
|
break;
|
|
case RelativeSize:
|
|
element.setAttribute( "minlabelspacing", TQString( "%1%" ).tqarg( m_minLabelSpacing * 100.0 ) );
|
|
break;
|
|
case PixelSize:
|
|
element.setAttribute( "minlabelspacing", TQString( "%1px" ).tqarg( m_minLabelSpacing ) );
|
|
break;
|
|
case NegativeVeryVeryThinMathSpace:
|
|
element.setAttribute( "minlabelspacing", "negativeveryverythinmathspace" );
|
|
break;
|
|
case NegativeVeryThinMathSpace:
|
|
element.setAttribute( "minlabelspacing", "negativeverythinmathspace" );
|
|
break;
|
|
case NegativeThinMathSpace:
|
|
element.setAttribute( "minlabelspacing", "negativethinmathspace" );
|
|
break;
|
|
case NegativeMediumMathSpace:
|
|
element.setAttribute( "minlabelspacing", "negativemediummathspace" );
|
|
break;
|
|
case NegativeThickMathSpace:
|
|
element.setAttribute( "minlabelspacing", "negativethickmathspace" );
|
|
break;
|
|
case NegativeVeryThickMathSpace:
|
|
element.setAttribute( "minlabelspacing", "negativeverythickmathspace" );
|
|
break;
|
|
case NegativeVeryVeryThickMathSpace:
|
|
element.setAttribute( "minlabelspacing", "negativeveryverythickmathspace" );
|
|
break;
|
|
case VeryVeryThinMathSpace:
|
|
element.setAttribute( "minlabelspacing", "veryverythinmathspace" );
|
|
break;
|
|
case VeryThinMathSpace:
|
|
element.setAttribute( "minlabelspacing", "verythinmathspace" );
|
|
break;
|
|
case ThinMathSpace:
|
|
element.setAttribute( "minlabelspacing", "thinmathspace" );
|
|
break;
|
|
case MediumMathSpace:
|
|
element.setAttribute( "minlabelspacing", "mediummathspace" );
|
|
break;
|
|
case ThickMathSpace:
|
|
element.setAttribute( "minlabelspacing", "thickmathspace" );
|
|
break;
|
|
case VeryThickMathSpace:
|
|
element.setAttribute( "minlabelspacing", "verythickmathspace" );
|
|
break;
|
|
case VeryVeryThickMathSpace:
|
|
element.setAttribute( "minlabelspacing", "veryverythickmathspace" );
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void MatrixElement::writeMathMLContent( TQDomDocument& doc,
|
|
TQDomElement& element,
|
|
bool oasisFormat ) const
|
|
{
|
|
TQDomElement row;
|
|
TQDomElement cell;
|
|
|
|
uint rows = getRows();
|
|
uint cols = getColumns();
|
|
|
|
for ( uint r = 0; r < rows; r++ )
|
|
{
|
|
row = doc.createElement( oasisFormat ? "math:mtr" : "mtr" );
|
|
element.appendChild( row );
|
|
for ( uint c = 0; c < cols; c++ )
|
|
{
|
|
cell = doc.createElement( oasisFormat ? "math:mtd" : "mtd" );
|
|
row.appendChild( cell );
|
|
getElement(r,c)->writeMathML( doc, cell, oasisFormat );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
/**
|
|
* The lines behaviour is (a little) different from that
|
|
* of ordinary sequences.
|
|
*/
|
|
class MultilineSequenceElement : public SequenceElement {
|
|
typedef SequenceElement inherited;
|
|
public:
|
|
|
|
MultilineSequenceElement( BasicElement* parent = 0 );
|
|
|
|
virtual MultilineSequenceElement* clone() {
|
|
return new MultilineSequenceElement( *this );
|
|
}
|
|
|
|
virtual BasicElement* goToPos( FormulaCursor*, bool& handled,
|
|
const LuPixelPoint& point, const LuPixelPoint& parentOrigin );
|
|
|
|
/**
|
|
* Calculates our width and height and
|
|
* our tqchildren's parentPosition.
|
|
*/
|
|
virtual void calcSizes( const ContextStyle& context,
|
|
ContextStyle::TextStyle tstyle,
|
|
ContextStyle::IndexStyle istyle,
|
|
StyleAttributes& style );
|
|
|
|
virtual void registerTab( BasicElement* tab );
|
|
|
|
/**
|
|
* This is called by the container to get a command depending on
|
|
* the current cursor position (this is how the element gets chosen)
|
|
* and the request.
|
|
*
|
|
* @returns the command that performs the requested action with
|
|
* the containers active cursor.
|
|
*/
|
|
virtual KCommand* buildCommand( Container*, Request* );
|
|
|
|
virtual KCommand* input( Container* container, TQKeyEvent* event );
|
|
|
|
virtual KCommand* input( Container* container, TQChar ch );
|
|
|
|
uint tabCount() const { return tabs.count(); }
|
|
|
|
BasicElement* tab( uint i ) { return tabs.at( i ); }
|
|
|
|
/// Change the width of tab i and move all elements after it.
|
|
void moveTabTo( uint i, luPixel pos );
|
|
|
|
/// Return the greatest tab number less than pos.
|
|
int tabBefore( uint pos );
|
|
|
|
/// Return the position of tab i.
|
|
int tabPos( uint i );
|
|
|
|
virtual void writeMathML( TQDomDocument& doc, TQDomNode& parent, bool oasisFormat = false ) const ;
|
|
|
|
private:
|
|
|
|
TQPtrList<BasicElement> tabs;
|
|
};
|
|
|
|
|
|
// Split the line at position pos.
|
|
class KFCNewLine : public Command {
|
|
public:
|
|
KFCNewLine( const TQString& name, Container* document,
|
|
MultilineSequenceElement* line, uint pos );
|
|
|
|
virtual ~KFCNewLine();
|
|
|
|
virtual void execute();
|
|
virtual void unexecute();
|
|
|
|
private:
|
|
MultilineSequenceElement* m_line;
|
|
MultilineSequenceElement* m_newline;
|
|
uint m_pos;
|
|
};
|
|
|
|
|
|
KFCNewLine::KFCNewLine( const TQString& name, Container* document,
|
|
MultilineSequenceElement* line, uint pos )
|
|
: Command( name, document ),
|
|
m_line( line ), m_pos( pos )
|
|
{
|
|
m_newline = new MultilineSequenceElement( m_line->getParent() );
|
|
}
|
|
|
|
|
|
KFCNewLine::~KFCNewLine()
|
|
{
|
|
delete m_newline;
|
|
}
|
|
|
|
|
|
void KFCNewLine::execute()
|
|
{
|
|
FormulaCursor* cursor = getExecuteCursor();
|
|
MultilineElement* parent = static_cast<MultilineElement*>( m_line->getParent() );
|
|
int linePos = parent->content.find( m_line );
|
|
parent->content.insert( linePos+1, m_newline );
|
|
|
|
// If there are tqchildren to be moved.
|
|
if ( m_line->countChildren() > static_cast<int>( m_pos ) ) {
|
|
|
|
// Remove anything after position pos from the current line
|
|
m_line->selectAllChildren( cursor );
|
|
cursor->setMark( m_pos );
|
|
TQPtrList<BasicElement> elementList;
|
|
m_line->remove( cursor, elementList, beforeCursor );
|
|
|
|
// Insert the removed stuff into the new line
|
|
m_newline->goInside( cursor );
|
|
m_newline->insert( cursor, elementList, beforeCursor );
|
|
cursor->setPos( cursor->getMark() );
|
|
}
|
|
else {
|
|
m_newline->goInside( cursor );
|
|
}
|
|
|
|
// The command no longer owns the new line.
|
|
m_newline = 0;
|
|
|
|
// Tell that something changed
|
|
FormulaElement* formula = m_line->formula();
|
|
formula->changed();
|
|
testDirty();
|
|
}
|
|
|
|
|
|
void KFCNewLine::unexecute()
|
|
{
|
|
FormulaCursor* cursor = getExecuteCursor();
|
|
MultilineElement* parent = static_cast<MultilineElement*>( m_line->getParent() );
|
|
int linePos = parent->content.find( m_line );
|
|
|
|
// Now the command owns the new line again.
|
|
m_newline = parent->content.at( linePos+1 );
|
|
|
|
// Tell all cursors to leave this sequence
|
|
FormulaElement* formula = m_line->formula();
|
|
formula->elementRemoval( m_newline );
|
|
|
|
// If there are tqchildren to be moved.
|
|
if ( m_newline->countChildren() > 0 ) {
|
|
|
|
// Remove anything from the line to be deleted
|
|
m_newline->selectAllChildren( cursor );
|
|
TQPtrList<BasicElement> elementList;
|
|
m_newline->remove( cursor, elementList, beforeCursor );
|
|
|
|
// Insert the removed stuff into the previous line
|
|
m_line->moveEnd( cursor );
|
|
m_line->insert( cursor, elementList, beforeCursor );
|
|
cursor->setPos( cursor->getMark() );
|
|
}
|
|
else {
|
|
m_line->moveEnd( cursor );
|
|
}
|
|
parent->content.take( linePos+1 );
|
|
|
|
// Tell that something changed
|
|
formula->changed();
|
|
testDirty();
|
|
}
|
|
|
|
|
|
MultilineSequenceElement::MultilineSequenceElement( BasicElement* parent )
|
|
: SequenceElement( parent )
|
|
{
|
|
tabs.setAutoDelete( false );
|
|
}
|
|
|
|
|
|
BasicElement* MultilineSequenceElement::goToPos( FormulaCursor* cursor, bool& handled,
|
|
const LuPixelPoint& point, const LuPixelPoint& parentOrigin )
|
|
{
|
|
//LuPixelPoint myPos(parentOrigin.x() + getX(),
|
|
// parentOrigin.y() + getY());
|
|
BasicElement* e = inherited::goToPos(cursor, handled, point, parentOrigin);
|
|
|
|
if (e == 0) {
|
|
// If the mouse was behind this line put the cursor to the last position.
|
|
if ( ( point.x() > getX()+getWidth() ) &&
|
|
( point.y() >= getY() ) &&
|
|
( point.y() < getY()+getHeight() ) ) {
|
|
cursor->setTo(this, countChildren());
|
|
handled = true;
|
|
return this;
|
|
}
|
|
}
|
|
return e;
|
|
}
|
|
|
|
|
|
void MultilineSequenceElement::calcSizes( const ContextStyle& context,
|
|
ContextStyle::TextStyle tstyle,
|
|
ContextStyle::IndexStyle istyle,
|
|
StyleAttributes& style )
|
|
{
|
|
tabs.clear();
|
|
inherited::calcSizes( context, tstyle, istyle, style );
|
|
}
|
|
|
|
|
|
void MultilineSequenceElement::registerTab( BasicElement* tab )
|
|
{
|
|
tabs.append( tab );
|
|
}
|
|
|
|
|
|
KCommand* MultilineSequenceElement::buildCommand( Container* container, Request* request )
|
|
{
|
|
FormulaCursor* cursor = container->activeCursor();
|
|
if ( cursor->isReadOnly() ) {
|
|
return 0;
|
|
}
|
|
|
|
switch ( *request ) {
|
|
case req_remove: {
|
|
// Remove this line if its empty.
|
|
// Remove the formula if this line was the only one.
|
|
break;
|
|
}
|
|
case req_addNewline: {
|
|
FormulaCursor* cursor = container->activeCursor();
|
|
return new KFCNewLine( i18n( "Add Newline" ), container, this, cursor->getPos() );
|
|
}
|
|
case req_addTabMark: {
|
|
KFCReplace* command = new KFCReplace( i18n("Add Tabmark"), container );
|
|
SpaceElement* element = new SpaceElement( THIN, true );
|
|
command->addElement( element );
|
|
return command;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return inherited::buildCommand( container, request );
|
|
}
|
|
|
|
|
|
KCommand* MultilineSequenceElement::input( Container* container, TQKeyEvent* event )
|
|
{
|
|
int action = event->key();
|
|
//int state = event->state();
|
|
//MoveFlag flag = movementFlag(state);
|
|
|
|
switch ( action ) {
|
|
case TQt::Key_Enter:
|
|
case TQt::Key_Return: {
|
|
Request newline( req_addNewline );
|
|
return buildCommand( container, &newline );
|
|
}
|
|
case TQt::Key_Tab: {
|
|
Request r( req_addTabMark );
|
|
return buildCommand( container, &r );
|
|
}
|
|
}
|
|
return inherited::input( container, event );
|
|
}
|
|
|
|
|
|
KCommand* MultilineSequenceElement::input( Container* container, TQChar ch )
|
|
{
|
|
int latin1 = ch.latin1();
|
|
switch (latin1) {
|
|
case '&': {
|
|
Request r( req_addTabMark );
|
|
return buildCommand( container, &r );
|
|
}
|
|
}
|
|
return inherited::input( container, ch );
|
|
}
|
|
|
|
|
|
void MultilineSequenceElement::moveTabTo( uint i, luPixel pos )
|
|
{
|
|
BasicElement* marker = tab( i );
|
|
luPixel diff = pos - marker->getX();
|
|
marker->setWidth( marker->getWidth() + diff );
|
|
|
|
for ( int p = childPos( marker )+1; p < countChildren(); ++p ) {
|
|
BasicElement* child = getChild( p );
|
|
child->setX( child->getX() + diff );
|
|
}
|
|
|
|
setWidth( getWidth()+diff );
|
|
}
|
|
|
|
|
|
int MultilineSequenceElement::tabBefore( uint pos )
|
|
{
|
|
if ( tabs.isEmpty() ) {
|
|
return -1;
|
|
}
|
|
uint tabNum = 0;
|
|
for ( uint i=0; i<pos; ++i ) {
|
|
BasicElement* child = getChild( i );
|
|
if ( tabs.at( tabNum ) == child ) {
|
|
if ( tabNum+1 == tabs.count() ) {
|
|
return tabNum;
|
|
}
|
|
++tabNum;
|
|
}
|
|
}
|
|
return static_cast<int>( tabNum )-1;
|
|
}
|
|
|
|
|
|
int MultilineSequenceElement::tabPos( uint i )
|
|
{
|
|
if ( i < tabs.count() ) {
|
|
return childPos( tabs.at( i ) );
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
|
|
void MultilineSequenceElement::writeMathML( TQDomDocument& doc,
|
|
TQDomNode& parent, bool oasisFormat ) const
|
|
{
|
|
// parent is required to be a <mtr> tag
|
|
|
|
TQDomElement tmp = doc.createElement( "TMP" );
|
|
|
|
inherited::writeMathML( doc, tmp, oasisFormat );
|
|
|
|
/* Now we re-parse the Dom tree, because of the TabMarkers
|
|
* that have no direct representation in MathML but mark the
|
|
* end of a <mtd> tag.
|
|
*/
|
|
|
|
TQDomElement mtd = doc.createElement( oasisFormat ? "math:mtd" : "mtd" );
|
|
|
|
// The mrow, if it exists.
|
|
TQDomNode n = tmp.firstChild().firstChild();
|
|
while ( !n.isNull() ) {
|
|
// the illegal TabMarkers are tqchildren of the mrow, child of tmp.
|
|
if ( n.isElement() && n.toElement().tagName() == "TAB" ) {
|
|
parent.appendChild( mtd );
|
|
mtd = doc.createElement( oasisFormat ? "math:mtd" : "mtd" );
|
|
}
|
|
else {
|
|
mtd.appendChild( n.cloneNode() ); // cloneNode needed?
|
|
}
|
|
n = n.nextSibling();
|
|
}
|
|
|
|
parent.appendChild( mtd );
|
|
}
|
|
|
|
|
|
MultilineElement::MultilineElement( BasicElement* parent )
|
|
: BasicElement( parent )
|
|
{
|
|
content.setAutoDelete( true );
|
|
content.append( new MultilineSequenceElement( this ) );
|
|
}
|
|
|
|
MultilineElement::~MultilineElement()
|
|
{
|
|
}
|
|
|
|
MultilineElement::MultilineElement( const MultilineElement& other )
|
|
: BasicElement( other )
|
|
{
|
|
content.setAutoDelete( true );
|
|
uint count = other.content.count();
|
|
for (uint i = 0; i < count; i++) {
|
|
MultilineSequenceElement* line = content.at(i)->clone();
|
|
line->setParent( this );
|
|
content.append( line );
|
|
}
|
|
}
|
|
|
|
|
|
bool MultilineElement::accept( ElementVisitor* visitor )
|
|
{
|
|
return visitor->visit( this );
|
|
}
|
|
|
|
|
|
void MultilineElement::entered( SequenceElement* /*child*/ )
|
|
{
|
|
formula()->tell( i18n( "Multi line element" ) );
|
|
}
|
|
|
|
|
|
/**
|
|
* Returns the element the point is in.
|
|
*/
|
|
BasicElement* MultilineElement::goToPos( FormulaCursor* cursor, bool& handled,
|
|
const LuPixelPoint& point, const LuPixelPoint& parentOrigin )
|
|
{
|
|
BasicElement* e = inherited::goToPos(cursor, handled, point, parentOrigin);
|
|
if ( e != 0 ) {
|
|
LuPixelPoint myPos(parentOrigin.x() + getX(),
|
|
parentOrigin.y() + getY());
|
|
|
|
uint count = content.count();
|
|
for ( uint i = 0; i < count; ++i ) {
|
|
MultilineSequenceElement* line = content.at(i);
|
|
e = line->goToPos(cursor, handled, point, myPos);
|
|
if (e != 0) {
|
|
return e;
|
|
}
|
|
}
|
|
return this;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void MultilineElement::goInside( FormulaCursor* cursor )
|
|
{
|
|
content.at( 0 )->goInside( cursor );
|
|
}
|
|
|
|
void MultilineElement::moveLeft( FormulaCursor* cursor, BasicElement* from )
|
|
{
|
|
// If you want to select more than one line you'll have to
|
|
// select the whole element.
|
|
if (cursor->isSelectionMode()) {
|
|
getParent()->moveLeft(cursor, this);
|
|
}
|
|
else {
|
|
// Coming from the parent (sequence) we go to
|
|
// the very last position
|
|
if (from == getParent()) {
|
|
content.at( content.count()-1 )->moveLeft(cursor, this);
|
|
}
|
|
else {
|
|
// Coming from one of the lines we go to the previous line
|
|
// or to the parent if there is none.
|
|
int pos = content.find( static_cast<MultilineSequenceElement*>( from ) );
|
|
if ( pos > -1 ) {
|
|
if ( pos > 0 ) {
|
|
content.at( pos-1 )->moveLeft( cursor, this );
|
|
}
|
|
else {
|
|
getParent()->moveLeft(cursor, this);
|
|
}
|
|
}
|
|
else {
|
|
kdDebug( DEBUGID ) << k_funcinfo << endl;
|
|
kdDebug( DEBUGID ) << "Serious confusion. Must never happen." << endl;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void MultilineElement::moveRight( FormulaCursor* cursor, BasicElement* from )
|
|
{
|
|
if (cursor->isSelectionMode()) {
|
|
getParent()->moveRight(cursor, this);
|
|
}
|
|
else {
|
|
if (from == getParent()) {
|
|
content.at( 0 )->moveRight(cursor, this);
|
|
}
|
|
else {
|
|
int pos = content.find( static_cast<MultilineSequenceElement*>( from ) );
|
|
if ( pos > -1 ) {
|
|
uint upos = pos;
|
|
if ( upos < content.count() ) {
|
|
if ( upos < content.count()-1 ) {
|
|
content.at( upos+1 )->moveRight( cursor, this );
|
|
}
|
|
else {
|
|
getParent()->moveRight(cursor, this);
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
kdDebug( DEBUGID ) << k_funcinfo << endl;
|
|
kdDebug( DEBUGID ) << "Serious confusion. Must never happen." << endl;
|
|
}
|
|
}
|
|
}
|
|
|
|
void MultilineElement::moveUp( FormulaCursor* cursor, BasicElement* from )
|
|
{
|
|
// If you want to select more than one line you'll have to
|
|
// select the whole element.
|
|
if (cursor->isSelectionMode()) {
|
|
getParent()->moveLeft(cursor, this);
|
|
}
|
|
else {
|
|
// Coming from the parent (sequence) we go to
|
|
// the very last position
|
|
if (from == getParent()) {
|
|
content.at( content.count()-1 )->moveLeft(cursor, this);
|
|
}
|
|
else {
|
|
// Coming from one of the lines we go to the previous line
|
|
// or to the parent if there is none.
|
|
int pos = content.find( static_cast<MultilineSequenceElement*>( from ) );
|
|
if ( pos > -1 ) {
|
|
if ( pos > 0 ) {
|
|
//content.at( pos-1 )->moveLeft( cursor, this );
|
|
// This is rather hackish.
|
|
// But we know what elements we have here.
|
|
int cursorPos = cursor->getPos();
|
|
MultilineSequenceElement* current = content.at( pos );
|
|
MultilineSequenceElement* newLine = content.at( pos-1 );
|
|
int tabNum = current->tabBefore( cursorPos );
|
|
if ( tabNum > -1 ) {
|
|
int oldTabPos = current->tabPos( tabNum );
|
|
int newTabPos = newLine->tabPos( tabNum );
|
|
if ( newTabPos > -1 ) {
|
|
cursorPos += newTabPos-oldTabPos;
|
|
int nextNewTabPos = newLine->tabPos( tabNum+1 );
|
|
if ( nextNewTabPos > -1 ) {
|
|
cursorPos = TQMIN( cursorPos, nextNewTabPos );
|
|
}
|
|
}
|
|
else {
|
|
cursorPos = newLine->countChildren();
|
|
}
|
|
}
|
|
else {
|
|
int nextNewTabPos = newLine->tabPos( 0 );
|
|
if ( nextNewTabPos > -1 ) {
|
|
cursorPos = TQMIN( cursorPos, nextNewTabPos );
|
|
}
|
|
}
|
|
cursor->setTo( newLine,
|
|
TQMIN( cursorPos,
|
|
newLine->countChildren() ) );
|
|
}
|
|
else {
|
|
getParent()->moveLeft(cursor, this);
|
|
}
|
|
}
|
|
else {
|
|
kdDebug( DEBUGID ) << k_funcinfo << endl;
|
|
kdDebug( DEBUGID ) << "Serious confusion. Must never happen." << endl;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void MultilineElement::moveDown( FormulaCursor* cursor, BasicElement* from )
|
|
{
|
|
if (cursor->isSelectionMode()) {
|
|
getParent()->moveRight(cursor, this);
|
|
}
|
|
else {
|
|
if (from == getParent()) {
|
|
content.at( 0 )->moveRight(cursor, this);
|
|
}
|
|
else {
|
|
int pos = content.find( static_cast<MultilineSequenceElement*>( from ) );
|
|
if ( pos > -1 ) {
|
|
uint upos = pos;
|
|
if ( upos < content.count() ) {
|
|
if ( upos < content.count()-1 ) {
|
|
//content.at( upos+1 )->moveRight( cursor, this );
|
|
// This is rather hackish.
|
|
// But we know what elements we have here.
|
|
int cursorPos = cursor->getPos();
|
|
MultilineSequenceElement* current = content.at( upos );
|
|
MultilineSequenceElement* newLine = content.at( upos+1 );
|
|
int tabNum = current->tabBefore( cursorPos );
|
|
if ( tabNum > -1 ) {
|
|
int oldTabPos = current->tabPos( tabNum );
|
|
int newTabPos = newLine->tabPos( tabNum );
|
|
if ( newTabPos > -1 ) {
|
|
cursorPos += newTabPos-oldTabPos;
|
|
int nextNewTabPos = newLine->tabPos( tabNum+1 );
|
|
if ( nextNewTabPos > -1 ) {
|
|
cursorPos = TQMIN( cursorPos, nextNewTabPos );
|
|
}
|
|
}
|
|
else {
|
|
cursorPos = newLine->countChildren();
|
|
}
|
|
}
|
|
else {
|
|
int nextNewTabPos = newLine->tabPos( 0 );
|
|
if ( nextNewTabPos > -1 ) {
|
|
cursorPos = TQMIN( cursorPos, nextNewTabPos );
|
|
}
|
|
}
|
|
cursor->setTo( newLine,
|
|
TQMIN( cursorPos,
|
|
newLine->countChildren() ) );
|
|
}
|
|
else {
|
|
getParent()->moveRight(cursor, this);
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
kdDebug( DEBUGID ) << k_funcinfo << endl;
|
|
kdDebug( DEBUGID ) << "Serious confusion. Must never happen." << endl;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void MultilineElement::calcSizes( const ContextStyle& context,
|
|
ContextStyle::TextStyle tstyle,
|
|
ContextStyle::IndexStyle istyle,
|
|
StyleAttributes& style )
|
|
{
|
|
double factor = style.sizeFactor();
|
|
luPt mySize = context.getAdjustedSize( tstyle, factor );
|
|
TQFont font = context.getDefaultFont();
|
|
font.setPointSizeFloat( context.layoutUnitPtToPt( mySize ) );
|
|
TQFontMetrics fm( font );
|
|
luPixel leading = context.ptToLayoutUnitPt( fm.leading() );
|
|
luPixel distY = context.ptToPixelY( context.getThinSpace( tstyle, factor ) );
|
|
|
|
uint count = content.count();
|
|
luPixel height = -leading;
|
|
luPixel width = 0;
|
|
uint tabCount = 0;
|
|
for ( uint i = 0; i < count; ++i ) {
|
|
MultilineSequenceElement* line = content.at(i);
|
|
line->calcSizes( context, tstyle, istyle, style );
|
|
tabCount = TQMAX( tabCount, line->tabCount() );
|
|
|
|
height += leading;
|
|
line->setX( 0 );
|
|
line->setY( height );
|
|
height += line->getHeight() + distY;
|
|
width = TQMAX( line->getWidth(), width );
|
|
}
|
|
|
|
// calculate the tab positions
|
|
for ( uint t = 0; t < tabCount; ++t ) {
|
|
luPixel pos = 0;
|
|
for ( uint i = 0; i < count; ++i ) {
|
|
MultilineSequenceElement* line = content.at(i);
|
|
if ( t < line->tabCount() ) {
|
|
pos = TQMAX( pos, line->tab( t )->getX() );
|
|
}
|
|
else {
|
|
pos = TQMAX( pos, line->getWidth() );
|
|
}
|
|
}
|
|
for ( uint i = 0; i < count; ++i ) {
|
|
MultilineSequenceElement* line = content.at(i);
|
|
if ( t < line->tabCount() ) {
|
|
line->moveTabTo( t, pos );
|
|
width = TQMAX( width, line->getWidth() );
|
|
}
|
|
}
|
|
}
|
|
|
|
setHeight( height );
|
|
setWidth( width );
|
|
if ( count == 1 ) {
|
|
setBaseline( content.at( 0 )->getBaseline() );
|
|
}
|
|
else {
|
|
// There's always a first line. No formulas without lines.
|
|
setBaseline( height/2 + context.axisHeight( tstyle, factor ) );
|
|
}
|
|
}
|
|
|
|
void MultilineElement::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() );
|
|
uint count = content.count();
|
|
|
|
if ( context.edit() ) {
|
|
uint tabCount = 0;
|
|
painter.setPen( context.getHelpColor() );
|
|
for ( uint i = 0; i < count; ++i ) {
|
|
MultilineSequenceElement* line = content.at(i);
|
|
if ( tabCount < line->tabCount() ) {
|
|
for ( uint t = tabCount; t < line->tabCount(); ++t ) {
|
|
BasicElement* marker = line->tab( t );
|
|
painter.drawLine( context.layoutUnitToPixelX( myPos.x()+marker->getX() ),
|
|
context.layoutUnitToPixelY( myPos.y() ),
|
|
context.layoutUnitToPixelX( myPos.x()+marker->getX() ),
|
|
context.layoutUnitToPixelY( myPos.y()+getHeight() ) );
|
|
}
|
|
tabCount = line->tabCount();
|
|
}
|
|
}
|
|
}
|
|
|
|
for ( uint i = 0; i < count; ++i ) {
|
|
MultilineSequenceElement* line = content.at(i);
|
|
line->draw( painter, r, context, tstyle, istyle, style, myPos );
|
|
}
|
|
}
|
|
|
|
|
|
void MultilineElement::dispatchFontCommand( FontCommand* cmd )
|
|
{
|
|
uint count = content.count();
|
|
for ( uint i = 0; i < count; ++i ) {
|
|
MultilineSequenceElement* line = content.at(i);
|
|
line->dispatchFontCommand( cmd );
|
|
}
|
|
}
|
|
|
|
void MultilineElement::insert( FormulaCursor* cursor,
|
|
TQPtrList<BasicElement>& newChildren,
|
|
Direction direction )
|
|
{
|
|
MultilineSequenceElement* e = static_cast<MultilineSequenceElement*>(newChildren.take(0));
|
|
e->setParent(this);
|
|
content.insert( cursor->getPos(), e );
|
|
|
|
if (direction == beforeCursor) {
|
|
e->moveLeft(cursor, this);
|
|
}
|
|
else {
|
|
e->moveRight(cursor, this);
|
|
}
|
|
cursor->setSelection(false);
|
|
formula()->changed();
|
|
}
|
|
|
|
void MultilineElement::remove( FormulaCursor* cursor,
|
|
TQPtrList<BasicElement>& removedChildren,
|
|
Direction direction )
|
|
{
|
|
if ( content.count() == 1 ) { //&& ( cursor->getPos() == 0 ) ) {
|
|
getParent()->selectChild(cursor, this);
|
|
getParent()->remove(cursor, removedChildren, direction);
|
|
}
|
|
else {
|
|
MultilineSequenceElement* e = content.take( cursor->getPos() );
|
|
removedChildren.append( e );
|
|
formula()->elementRemoval( e );
|
|
//cursor->setTo( this, denominatorPos );
|
|
formula()->changed();
|
|
}
|
|
}
|
|
|
|
void MultilineElement::normalize( FormulaCursor* cursor, Direction direction )
|
|
{
|
|
int pos = cursor->getPos();
|
|
if ( ( cursor->getElement() == this ) &&
|
|
( pos > -1 ) && ( static_cast<unsigned>( pos ) <= content.count() ) ) {
|
|
switch ( direction ) {
|
|
case beforeCursor:
|
|
if ( pos > 0 ) {
|
|
content.at( pos-1 )->moveLeft( cursor, this );
|
|
break;
|
|
}
|
|
// no break! intended!
|
|
case afterCursor:
|
|
if ( static_cast<unsigned>( pos ) < content.count() ) {
|
|
content.at( pos )->moveRight( cursor, this );
|
|
}
|
|
else {
|
|
content.at( pos-1 )->moveLeft( cursor, this );
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
else {
|
|
inherited::normalize( cursor, direction );
|
|
}
|
|
}
|
|
|
|
SequenceElement* MultilineElement::getMainChild()
|
|
{
|
|
return content.at( 0 );
|
|
}
|
|
|
|
void MultilineElement::selectChild(FormulaCursor* cursor, BasicElement* child)
|
|
{
|
|
int pos = content.find( dynamic_cast<MultilineSequenceElement*>( child ) );
|
|
if ( pos > -1 ) {
|
|
cursor->setTo( this, pos );
|
|
//content.at( pos )->moveRight( cursor, this );
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Appends our attributes to the dom element.
|
|
*/
|
|
void MultilineElement::writeDom(TQDomElement element)
|
|
{
|
|
BasicElement::writeDom(element);
|
|
|
|
uint lineCount = content.count();
|
|
element.setAttribute( "LINES", lineCount );
|
|
|
|
TQDomDocument doc = element.ownerDocument();
|
|
for ( uint i = 0; i < lineCount; ++i ) {
|
|
TQDomElement tmp = content.at( i )->getElementDom(doc);
|
|
element.appendChild(tmp);
|
|
}
|
|
}
|
|
|
|
void MultilineElement::writeMathML( TQDomDocument& doc, TQDomNode& parent, bool oasisFormat ) const
|
|
{
|
|
TQDomElement de = doc.createElement( oasisFormat ? "math:mtable" : "mtable" );
|
|
TQDomElement row; TQDomElement cell;
|
|
|
|
for ( TQPtrListIterator < MultilineSequenceElement > it( content ); it.current(); ++it ) {
|
|
row = doc.createElement( oasisFormat ? "math:mtr" : "mtr" );
|
|
de.appendChild( row );
|
|
//cell = doc.createElement( "mtd" );
|
|
//row.appendChild( cell );
|
|
|
|
//content.at( i )->writeMathML( doc, cell );
|
|
it.current()->writeMathML( doc, row, oasisFormat );
|
|
}
|
|
|
|
parent.appendChild( de );
|
|
}
|
|
|
|
/**
|
|
* Reads our attributes from the element.
|
|
* Returns false if it failed.
|
|
*/
|
|
bool MultilineElement::readAttributesFromDom(TQDomElement element)
|
|
{
|
|
if (!BasicElement::readAttributesFromDom(element)) {
|
|
return false;
|
|
}
|
|
uint lineCount = 0;
|
|
TQString lineCountStr = element.attribute("LINES");
|
|
if(!lineCountStr.isNull()) {
|
|
lineCount = lineCountStr.toInt();
|
|
}
|
|
if (lineCount == 0) {
|
|
kdWarning( DEBUGID ) << "lineCount <= 0 in MultilineElement." << endl;
|
|
return false;
|
|
}
|
|
|
|
content.clear();
|
|
for ( uint i = 0; i < lineCount; ++i ) {
|
|
MultilineSequenceElement* element = new MultilineSequenceElement(this);
|
|
content.append(element);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Reads our content from the node. Sets the node to the next node
|
|
* that needs to be read.
|
|
* Returns false if it failed.
|
|
*/
|
|
bool MultilineElement::readContentFromDom(TQDomNode& node)
|
|
{
|
|
if (!BasicElement::readContentFromDom(node)) {
|
|
return false;
|
|
}
|
|
|
|
uint lineCount = content.count();
|
|
uint i = 0;
|
|
while ( !node.isNull() && i < lineCount ) {
|
|
if ( node.isElement() ) {
|
|
SequenceElement* element = content.at( i );
|
|
TQDomElement e = node.toElement();
|
|
if ( !element->buildFromDom( e ) ) {
|
|
return false;
|
|
}
|
|
++i;
|
|
}
|
|
node = node.nextSibling();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
TQString MultilineElement::toLatex()
|
|
{
|
|
uint lineCount = content.count();
|
|
TQString muliline = "\\begin{split} ";
|
|
for ( uint i = 0; i < lineCount; ++i ) {
|
|
muliline += content.at( i )->toLatex();
|
|
muliline += " \\\\ ";
|
|
}
|
|
muliline += "\\end{split}";
|
|
return muliline;
|
|
}
|
|
|
|
// Does this make any sense at all?
|
|
TQString MultilineElement::formulaString()
|
|
{
|
|
uint lineCount = content.count();
|
|
TQString muliline = "";
|
|
for ( uint i = 0; i < lineCount; ++i ) {
|
|
muliline += content.at( i )->formulaString();
|
|
muliline += "\n";
|
|
}
|
|
//muliline += "";
|
|
return muliline;
|
|
}
|
|
|
|
|
|
KFORMULA_NAMESPACE_END
|