26#include "elementtype.h"
27#include "sequenceelement.h"
28#include "textelement.h"
30#include "operatordictionary.h"
31#include "operatorelement.h"
32#include "identifierelement.h"
33#include "numberelement.h"
34#include "kformulacommand.h"
35#include "kformulacontainer.h"
36#include "kformuladocument.h"
37#include "formulaelement.h"
38#include "creationstrategy.h"
40KFORMULA_NAMESPACE_BEGIN
42OperatorElement::OperatorElement(
BasicElement* parent ) : TokenElement( parent ),
44 m_lspaceType( ThickMathSpace ),
45 m_rspaceType( ThickMathSpace ),
46 m_maxSizeType( InfinitySize ),
47 m_minSizeType( RelativeSize ),
54 m_movableLimits( false ),
56 m_customForm( false ),
57 m_customFence( false ),
58 m_customSeparator( false ),
59 m_customLSpace( false ),
60 m_customRSpace( false ),
61 m_customStretchy( false ),
62 m_customSymmetric( false ),
63 m_customMaxSize( false ),
64 m_customMinSize( false ),
65 m_customLargeOp( false ),
66 m_customMovableLimits( false ),
67 m_customAccent( false )
71void OperatorElement::setForm( FormType type )
73 if ( ! m_customForm ) {
77 if ( ! isTextOnly() ) {
81 for ( uint i = 0; i < countChildren(); i++ ) {
82 text.append( getChild( i )->getCharacter() );
97 kdWarning( DEBUGID ) <<
"Invalid `form' attribute value\n";
100 DictionaryKey key = { text.utf8(), form.ascii() };
101 const OperatorDictionary* begin = operators;
102 const OperatorDictionary* end = operators + OperatorDictionary::size();
103 const OperatorDictionary* pos = std::lower_bound( begin, end, key );
104 if ( pos != end && pos->key == key ) {
105 if ( ! m_customFence ) {
106 m_fence = pos->fence;
108 if ( ! m_customSeparator ) {
109 m_separator = pos->separator;
111 if ( ! m_customLSpace ) {
112 m_lspace = getSize( pos->lspace, &m_lspaceType );
113 if ( m_lspaceType == NoSize ) {
114 m_lspaceType = getSpace( pos->lspace );
117 if ( ! m_customRSpace ) {
118 m_rspace = getSize( pos->rspace, &m_rspaceType );
119 if ( m_rspaceType == NoSize ) {
120 m_rspaceType = getSpace( pos->rspace );
123 if ( ! m_customStretchy ) {
124 m_stretchy = pos->stretchy;
126 if ( ! m_customSymmetric ) {
127 m_symmetric = pos->symmetric;
129 if ( ! m_customMaxSize ) {
130 if ( qstrcmp( pos->maxsize,
"infinity" ) == 0 ) {
131 m_maxSizeType = InfinitySize;
134 m_maxSize = getSize( pos->maxsize, &m_maxSizeType );
135 if ( m_maxSizeType == NoSize ) {
136 m_maxSizeType = getSpace( pos->maxsize );
140 if ( ! m_customMinSize ) {
141 m_minSize = getSize( pos->minsize, &m_minSizeType );
142 if ( m_minSizeType == NoSize ) {
143 m_minSizeType = getSpace( pos->minsize );
146 if ( ! m_customLargeOp ) {
147 m_largeOp = pos->largeop;
149 if ( ! m_customMovableLimits ) {
150 m_movableLimits = pos->movablelimits;
152 if ( ! m_customAccent ) {
153 m_accent = pos->accent;
168 formula()->tell( i18n(
"write protection" ) );
172 if ( *request == req_addOperator ) {
174 OperatorRequest* opr =
static_cast<OperatorRequest*
>( request );
175 TextElement* element = creationStrategy->createTextElement( opr->ch(), true );
180 if ( countChildren() == 0 || cursor->getPos() == countChildren() ) {
185 uint pos = parent->childPos(
this );
186 cursor->
setTo( parent, pos + 1);
190 if ( cursor->getPos() == 0 ) {
193 uint pos = parent->childPos(
this );
194 cursor->
setTo( parent, pos );
206 case req_addTextChar: {
208 TextCharRequest* tr =
static_cast<TextCharRequest*
>( request );
209 IdentifierElement*
id = creationStrategy->createIdentifierElement();
210 TextElement* text = creationStrategy->createTextElement( tr->ch() );
216 cursor->
setTo( parent, parent->childPos(
this ) + 1 );
223 TextRequest* tr =
static_cast<TextRequest*
>( request );
224 IdentifierElement*
id = creationStrategy->createIdentifierElement();
227 for ( uint i = 0; i < tr->text().length(); i++ ) {
228 TextElement* text = creationStrategy->createTextElement( tr->text()[i] );
233 cursor->
setTo( parent, parent->childPos(
this ) + 1 );
238 case req_addNumber: {
240 NumberRequest* nr =
static_cast<NumberRequest*
>( request );
241 NumberElement* num = creationStrategy->createNumberElement();
242 TextElement* text = creationStrategy->createTextElement( nr->ch() );
248 cursor->
setTo( parent, parent->childPos(
this ) + 1 );
252 case req_addEmptyBox:
253 case req_addNameSequence:
256 case req_addFraction:
259 case req_addOneByTwoMatrix:
260 case req_addMatrix: {
261 uint pos =
static_cast<SequenceElement*
>(getParent())->childPos(
this );
262 cursor->
setTo( getParent(), pos + 1);
263 return getParent()->buildCommand( container, request );
272bool OperatorElement::readAttributesFromMathMLDom(
const TQDomElement &element )
278 TQString formStr = element.attribute(
"form" ).stripWhiteSpace().lower();
279 if ( ! formStr.isNull() ) {
281 if ( formStr ==
"prefix" ) {
284 else if ( formStr ==
"infix" ) {
287 else if ( formStr ==
"postfix" ) {
288 m_form = PostfixForm;
291 kdWarning( DEBUGID ) <<
"Invalid value for attribute `form': " << formStr << endl;
292 m_customForm =
false;
295 TQString fenceStr = element.attribute(
"fence" ).stripWhiteSpace().lower();
296 if ( ! fenceStr.isNull() ) {
297 m_customFence =
true;
298 if ( fenceStr ==
"true" ) {
301 else if ( fenceStr ==
"false" ) {
305 kdWarning( DEBUGID ) <<
"Invalid value for attribute `fence': " << fenceStr << endl;
306 m_customFence =
false;
309 TQString separatorStr = element.attribute(
"separator" ).stripWhiteSpace().lower();
310 if ( ! separatorStr.isNull() ) {
311 m_customSeparator =
true;
312 if ( separatorStr ==
"true" ) {
315 else if ( separatorStr ==
"false" ) {
319 kdWarning( DEBUGID ) <<
"Invalid value for attribute `separator': " << separatorStr << endl;
320 m_customSeparator =
false;
323 TQString lspaceStr = element.attribute(
"lspace" ).stripWhiteSpace().lower();
324 if ( ! lspaceStr.isNull() ) {
325 m_customLSpace =
true;
326 m_lspace = getSize( lspaceStr, &m_lspaceType );
327 if ( m_lspaceType == NoSize ) {
328 m_lspaceType = getSpace( lspaceStr );
331 TQString rspaceStr = element.attribute(
"rspace" ).stripWhiteSpace().lower();
332 if ( ! rspaceStr.isNull() ) {
333 m_customRSpace =
true;
334 m_rspace = getSize( rspaceStr, &m_rspaceType );
335 if ( m_rspaceType == NoSize ) {
336 m_rspaceType = getSpace( rspaceStr );
339 TQString stretchyStr = element.attribute(
"stretchy" ).stripWhiteSpace().lower();
340 if ( ! stretchyStr.isNull() ) {
341 m_customStretchy =
true;
342 if ( stretchyStr ==
"true" ) {
345 else if ( stretchyStr ==
"false" ) {
349 kdWarning( DEBUGID ) <<
"Invalid value for attribute `stretchy': " << stretchyStr << endl;
350 m_customStretchy =
false;
353 TQString symmetricStr = element.attribute(
"symmetric" ).stripWhiteSpace().lower();
354 if ( ! symmetricStr.isNull() ) {
355 m_customSymmetric =
true;
356 if ( symmetricStr ==
"true" ) {
359 else if ( symmetricStr ==
"false" ) {
363 kdWarning( DEBUGID ) <<
"Invalid value for attribute `symmetric': " << symmetricStr << endl;
364 m_customSymmetric =
false;
367 TQString maxsizeStr = element.attribute(
"maxsize" ).stripWhiteSpace().lower();
368 if ( ! maxsizeStr.isNull() ) {
369 m_customMaxSize =
true;
370 if ( maxsizeStr ==
"infinity" ) {
371 m_maxSizeType = InfinitySize;
374 m_maxSize = getSize( maxsizeStr, &m_maxSizeType );
375 if ( m_maxSizeType == NoSize ) {
376 m_maxSizeType = getSpace( maxsizeStr );
380 TQString minsizeStr = element.attribute(
"minsize" ).stripWhiteSpace().lower();
381 if ( ! minsizeStr.isNull() ) {
382 m_customMinSize =
true;
383 m_minSize = getSize( minsizeStr, &m_minSizeType );
384 if ( m_minSizeType == NoSize ) {
385 m_minSizeType = getSpace( minsizeStr );
388 TQString largeopStr = element.attribute(
"largeop" ).stripWhiteSpace().lower();
389 if ( ! largeopStr.isNull() ) {
390 m_customLargeOp =
true;
391 if ( largeopStr ==
"true" ) {
394 else if ( largeopStr ==
"false" ) {
398 kdWarning( DEBUGID ) <<
"Invalid value for attribute `largeop': " << largeopStr << endl;
399 m_customLargeOp =
false;
402 TQString movablelimitsStr = element.attribute(
"movablelimits" ).stripWhiteSpace().lower();
403 if ( ! movablelimitsStr.isNull() ) {
404 m_customMovableLimits =
true;
405 if ( movablelimitsStr ==
"true" ) {
406 m_movableLimits =
true;
408 else if ( movablelimitsStr ==
"false" ) {
409 m_movableLimits =
false;
412 kdWarning( DEBUGID ) <<
"Invalid value for attribute `movablelimits': " << movablelimitsStr << endl;
413 m_customMovableLimits =
false;
416 TQString accentStr = element.attribute(
"accent" ).stripWhiteSpace().lower();
417 if ( ! accentStr.isNull() ) {
418 m_customAccent =
true;
419 if ( accentStr ==
"true" ) {
422 else if ( accentStr ==
"false" ) {
426 kdWarning( DEBUGID ) <<
"Invalid value for attribute `accent': " << accentStr << endl;
427 m_customAccent =
false;
433void OperatorElement::writeMathMLAttributes( TQDomElement& element )
const
435 if ( m_customForm ) {
438 element.setAttribute(
"form",
"prefix" );
441 element.setAttribute(
"form",
"infix" );
444 element.setAttribute(
"form",
"postfix" );
449 if ( m_customFence ) {
450 element.setAttribute(
"fence", m_fence ?
"true" :
"false" );
452 if ( m_customSeparator ) {
453 element.setAttribute(
"separator", m_separator ?
"true" :
"false" );
455 if ( m_customLSpace ) {
456 writeSizeAttribute( element,
"lspace", m_lspaceType, m_lspace );
458 if ( m_customRSpace ) {
459 writeSizeAttribute( element,
"rspace", m_rspaceType, m_rspace );
461 if ( m_customStretchy ) {
462 element.setAttribute(
"stretchy", m_stretchy ?
"true" :
"false" );
464 if ( m_customSymmetric ) {
465 element.setAttribute(
"symmetric", m_symmetric ?
"true" :
"false" );
467 if ( m_customMaxSize ) {
468 writeSizeAttribute( element,
"maxsize", m_maxSizeType, m_maxSize );
470 if ( m_customMinSize ) {
471 writeSizeAttribute( element,
"minsize", m_minSizeType, m_minSize );
473 if ( m_customLargeOp ) {
474 element.setAttribute(
"largeop", m_largeOp ?
"true" :
"false" );
476 if ( m_customMovableLimits ) {
477 element.setAttribute(
"movablelimits", m_movableLimits ?
"true" :
"false" );
479 if ( m_customAccent ) {
480 element.setAttribute(
"accent", m_accent ?
"true" :
"false" );
484void OperatorElement::writeSizeAttribute( TQDomElement& element,
const TQString &attr, SizeType type,
double length )
const
488 element.setAttribute( attr,
"infinity" );
491 element.setAttribute( attr, TQString(
"%1pt" ).arg( length ) );
494 element.setAttribute( attr, TQString(
"%1% " ).arg( length * 100.0 ) );
497 element.setAttribute( attr, TQString(
"%1px " ).arg( length ) );
499 case NegativeVeryVeryThinMathSpace:
500 element.setAttribute( attr,
"negativeveryverythinmathspace" );
502 case NegativeVeryThinMathSpace:
503 element.setAttribute( attr,
"negativeverythinmathspace" );
505 case NegativeThinMathSpace:
506 element.setAttribute( attr,
"negativethinmathspace" );
508 case NegativeMediumMathSpace:
509 element.setAttribute( attr,
"negativemediummathspace" );
511 case NegativeThickMathSpace:
512 element.setAttribute( attr,
"negativethickmathspace" );
514 case NegativeVeryThickMathSpace:
515 element.setAttribute( attr,
"negativeverythickmathspace" );
517 case NegativeVeryVeryThickMathSpace:
518 element.setAttribute( attr,
"negativeveryverythickmathspace" );
520 case VeryVeryThinMathSpace:
521 element.setAttribute( attr,
"veryverythinmathspace" );
523 case VeryThinMathSpace:
524 element.setAttribute( attr,
"verythinmathspace" );
527 element.setAttribute( attr,
"thinmathspace" );
529 case MediumMathSpace:
530 element.setAttribute( attr,
"mediummathspace" );
533 element.setAttribute( attr,
"thickmathspace" );
535 case VeryThickMathSpace:
536 element.setAttribute( attr,
"verythickmathspace" );
538 case VeryVeryThickMathSpace:
539 element.setAttribute( attr,
"veryverythickmathspace" );
547KFORMULA_NAMESPACE_END
Basis of every formula element.
virtual bool readAttributesFromMathMLDom(const TQDomElement &element)
Reads our attributes from the MathML element.
FormulaCursor * activeCursor()
void addContent(BasicElement *element, BasicElement *content)
Collect content for each token.
void addToken(BasicElement *element)
Collect all tokens that are to be added.
void addElement(BasicElement *element)
Collects all elements that are to be added.
Removes the current selection and adds any new elements afterwards.
Add and remove arbitrary token elements and their contents.
void addCursor(FormulaCursor *cursor)
Collect cursor data that will be needed to do the stuff properly.
The element that contains a number of children.
virtual KCommand * buildCommand(Container *, Request *)
This is called by the container to get a command depending on the current cursor position (this is ho...
An element that represents one char.