00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
#include <qfontmetrics.h>
00022
#include <qpainter.h>
00023
00024
#include <kdebug.h>
00025
00026
#include "basicelement.h"
00027
#include "contextstyle.h"
00028
#include "elementtype.h"
00029
#include "elementvisitor.h"
00030
#include "fontstyle.h"
00031
#include "formulaelement.h"
00032
#include "kformulacommand.h"
00033
#include "sequenceelement.h"
00034
#include "symboltable.h"
00035
#include "textelement.h"
00036
00037
00038 KFORMULA_NAMESPACE_BEGIN
00039
00040 TextElement::TextElement(
QChar ch,
bool beSymbol,
BasicElement* parent)
00041 :
BasicElement(parent), character(ch), symbol(beSymbol)
00042 {
00043 charStyle( anyChar );
00044 charFamily( anyFamily );
00045 }
00046
00047
00048 TextElement::TextElement(
const TextElement& other )
00049 :
BasicElement( other ),
00050 character( other.character ),
00051 symbol( other.symbol ),
00052 m_format( other.m_format )
00053 {
00054 }
00055
00056
00057 bool TextElement::accept(
ElementVisitor* visitor )
00058 {
00059
return visitor->
visit(
this );
00060 }
00061
00062
00063 TokenType
TextElement::getTokenType()
const
00064
{
00065
if (
isSymbol() ) {
00066
return getSymbolTable().
charClass( character );
00067 }
00068
00069
switch ( character.unicode() ) {
00070
case '+':
00071
case '-':
00072
case '*':
00073
00074
return BINOP;
00075
case '=':
00076
case '<':
00077
case '>':
00078
return RELATION;
00079
case ',':
00080
case ';':
00081
case ':':
00082
return PUNCTUATION;
00083
case '\\':
00084
return SEPARATOR;
00085
case '\0':
00086
return ELEMENT;
00087
default:
00088
if ( character.isNumber() ) {
00089
return NUMBER;
00090 }
00091
else {
00092
return ORDINARY;
00093 }
00094 }
00095 }
00096
00097
00098 bool TextElement::isInvisible()
const
00099
{
00100
if (
getElementType() != 0) {
00101
return getElementType()->
isInvisible(*
this);
00102 }
00103
return false;
00104 }
00105
00106
00111 void TextElement::calcSizes(
const ContextStyle& context, ContextStyle::TextStyle tstyle, ContextStyle::IndexStyle )
00112 {
00113 luPt mySize = context.
getAdjustedSize( tstyle );
00114
00115
00116
QFont font =
getFont( context );
00117 font.setPointSizeFloat( context.
layoutUnitPtToPt( mySize ) );
00118
00119
QFontMetrics fm( font );
00120
QChar ch =
getRealCharacter(context);
00121
if ( ch != QChar::null ) {
00122
QRect bound = fm.boundingRect( ch );
00123 setWidth( context.
ptToLayoutUnitPt( fm.width( ch ) ) );
00124 setHeight( context.
ptToLayoutUnitPt( bound.height() ) );
00125 setBaseline( context.
ptToLayoutUnitPt( -bound.top() ) );
00126
00127
00128
00129
if ( getBaseline() == 0 ) {
00130
00131 setBaseline( -1 );
00132 }
00133 }
00134
else {
00135 setWidth( qRound( context.
getEmptyRectWidth() * 2./3. ) );
00136 setHeight( qRound( context.
getEmptyRectHeight() * 2./3. ) );
00137 setBaseline( getHeight() );
00138 }
00139
00140
00141
00142 }
00143
00149 void TextElement::draw(
QPainter& painter,
const LuPixelRect& ,
00150
const ContextStyle& context,
00151 ContextStyle::TextStyle tstyle,
00152 ContextStyle::IndexStyle ,
00153
const LuPixelPoint& parentOrigin )
00154 {
00155
LuPixelPoint myPos( parentOrigin.x()+getX(), parentOrigin.y()+getY() );
00156
00157
00158
00159
setUpPainter( context, painter );
00160
00161 luPt mySize = context.
getAdjustedSize( tstyle );
00162
QFont font =
getFont( context );
00163 font.setPointSizeFloat( context.
layoutUnitToFontSize( mySize,
false ) );
00164 painter.setFont( font );
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
ElementType* token =
getElementType();
00175
if ( ( token != 0 ) && !symbol ) {
00176
QString text = token->
text( static_cast<SequenceElement*>( getParent() ) );
00177
00178
00179
00180 painter.drawText( context.
layoutUnitToPixelX( myPos.x() ),
00181 context.
layoutUnitToPixelY( myPos.y()+getBaseline() ),
00182 text );
00183 }
00184
else {
00185
00186
QChar ch =
getRealCharacter(context);
00187
if ( ch != QChar::null ) {
00188 luPixel bl = getBaseline();
00189
if ( bl == -1 ) {
00190
00191
00192
00193
00194 bl = -( getHeight()/2 + context.
axisHeight( tstyle ) );
00195 }
00196 painter.drawText( context.
layoutUnitToPixelX( myPos.x() ),
00197 context.
layoutUnitToPixelY( myPos.y()+bl ),
00198 ch );
00199 }
00200
else {
00201 painter.setPen(
QPen( context.
getErrorColor(),
00202 context.
layoutUnitToPixelX( context.
getLineWidth() ) ) );
00203 painter.drawRect( context.
layoutUnitToPixelX( myPos.x() ),
00204 context.
layoutUnitToPixelY( myPos.y() ),
00205 context.
layoutUnitToPixelX( getWidth() ),
00206 context.
layoutUnitToPixelY( getHeight() ) );
00207 }
00208 }
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222 }
00223
00224
00225 void TextElement::dispatchFontCommand(
FontCommand* cmd )
00226 {
00227 cmd->
addTextElement(
this );
00228 }
00229
00230
void TextElement::setCharStyle( CharStyle cs )
00231 {
00232 charStyle( cs );
00233
formula()->
changed();
00234 }
00235
00236
void TextElement::setCharFamily( CharFamily cf )
00237 {
00238 charFamily( cf );
00239
formula()->
changed();
00240 }
00241
00242 QChar TextElement::getRealCharacter(
const ContextStyle& context)
00243 {
00244
if ( !
isSymbol() ) {
00245
const FontStyle& fontStyle = context.
fontStyle();
00246
const AlphaTable* alphaTable = fontStyle.
alphaTable();
00247
if ( alphaTable != 0 ) {
00248
AlphaTableEntry ate = alphaTable->
entry( character,
00249 charFamily(),
00250 charStyle() );
00251
if ( ate.
valid() ) {
00252
return ate.
pos;
00253 }
00254 }
00255
return character;
00256 }
00257
else {
00258
return getSymbolTable().
character(character, charStyle());
00259 }
00260 }
00261
00262
00263 QFont TextElement::getFont(
const ContextStyle& context)
00264 {
00265
if ( !
isSymbol() ) {
00266
const FontStyle& fontStyle = context.
fontStyle();
00267
const AlphaTable* alphaTable = fontStyle.
alphaTable();
00268
if ( alphaTable != 0 ) {
00269
AlphaTableEntry ate = alphaTable->
entry( character,
00270 charFamily(),
00271 charStyle() );
00272
if ( ate.
valid() ) {
00273
return ate.
font;
00274 }
00275 }
00276
QFont font;
00277
if (
getElementType() != 0) {
00278 font =
getElementType()->
getFont(context);
00279 }
00280
else {
00281 font = context.
getDefaultFont();
00282 }
00283
switch ( charStyle() ) {
00284
case anyChar:
00285
break;
00286
case normalChar:
00287 font.setItalic(
false );
00288 font.setBold(
false );
00289
break;
00290
case boldChar:
00291 font.setItalic(
false );
00292 font.setBold(
true );
00293
break;
00294
case italicChar:
00295 font.setItalic(
true );
00296 font.setBold(
false );
00297
break;
00298
case boldItalicChar:
00299 font.setItalic(
true );
00300 font.setBold(
true );
00301
break;
00302 }
00303
return font;
00304 }
00305
return context.
symbolTable().
font( character, charStyle() );
00306 }
00307
00308
00309 void TextElement::setUpPainter(
const ContextStyle& context,
QPainter& painter)
00310 {
00311
if (
getElementType() != 0) {
00312
getElementType()->
setUpPainter(context, painter);
00313 }
00314
else {
00315 painter.setPen(Qt::red);
00316 }
00317 }
00318
00319
const SymbolTable& TextElement::getSymbolTable()
const
00320
{
00321
return formula()->
getSymbolTable();
00322 }
00323
00324
00328 void TextElement::writeDom(
QDomElement element)
00329 {
00330 BasicElement::writeDom(element);
00331 element.setAttribute(
"CHAR",
QString(character));
00332
00333
00334
if (symbol) element.setAttribute(
"SYMBOL",
"3");
00335
00336
switch ( charStyle() ) {
00337
case anyChar:
break;
00338
case normalChar: element.setAttribute(
"STYLE",
"normal");
break;
00339
case boldChar: element.setAttribute(
"STYLE",
"bold");
break;
00340
case italicChar: element.setAttribute(
"STYLE",
"italic");
break;
00341
case boldItalicChar: element.setAttribute(
"STYLE",
"bolditalic");
break;
00342 }
00343
00344
switch ( charFamily() ) {
00345
case normalFamily: element.setAttribute(
"FAMILY",
"normal");
break;
00346
case scriptFamily: element.setAttribute(
"FAMILY",
"script");
break;
00347
case frakturFamily: element.setAttribute(
"FAMILY",
"fraktur");
break;
00348
case doubleStruckFamily: element.setAttribute(
"FAMILY",
"doublestruck");
break;
00349
case anyFamily:
break;
00350 }
00351 }
00352
00357 bool TextElement::readAttributesFromDom(
QDomElement element)
00358 {
00359
if (!BasicElement::readAttributesFromDom(element)) {
00360
return false;
00361 }
00362
QString charStr = element.attribute(
"CHAR");
00363
if(!charStr.isNull()) {
00364 character = charStr.at(0);
00365 }
00366
QString symbolStr = element.attribute(
"SYMBOL");
00367
if(!symbolStr.isNull()) {
00368
int symbolInt = symbolStr.toInt();
00369
if ( symbolInt == 1 ) {
00370 character = getSymbolTable().
unicodeFromSymbolFont(character);
00371 }
00372
if ( symbolInt == 2 ) {
00373
switch ( character.unicode() ) {
00374
case 0x03D5: character = 0x03C6;
break;
00375
case 0x03C6: character = 0x03D5;
break;
00376
case 0x03Ba: character = 0x03BA;
break;
00377
case 0x00B4: character = 0x2032;
break;
00378
case 0x2215: character = 0x2244;
break;
00379
case 0x00B7: character = 0x2022;
break;
00380
case 0x1D574: character = 0x2111;
break;
00381
case 0x1D579: character = 0x211C;
break;
00382
case 0x2219: character = 0x22C5;
break;
00383
case 0x2662: character = 0x26C4;
break;
00384
case 0x220B: character = 0x220D;
break;
00385
case 0x224C: character = 0x2245;
break;
00386
case 0x03DB: character = 0x03C2;
break;
00387 }
00388 }
00389 symbol = symbolInt != 0;
00390 }
00391
00392
QString styleStr = element.attribute(
"STYLE");
00393
if ( styleStr ==
"normal" ) {
00394 charStyle( normalChar );
00395 }
00396
else if ( styleStr ==
"bold" ) {
00397 charStyle( boldChar );
00398 }
00399
else if ( styleStr ==
"italic" ) {
00400 charStyle( italicChar );
00401 }
00402
else if ( styleStr ==
"bolditalic" ) {
00403 charStyle( boldItalicChar );
00404 }
00405
else {
00406 charStyle( anyChar );
00407 }
00408
00409
QString familyStr = element.attribute(
"FAMILY" );
00410
if ( familyStr ==
"normal" ) {
00411 charFamily( normalFamily );
00412 }
00413
else if ( familyStr ==
"script" ) {
00414 charFamily( scriptFamily );
00415 }
00416
else if ( familyStr ==
"fraktur" ) {
00417 charFamily( frakturFamily );
00418 }
00419
else if ( familyStr ==
"doublestruck" ) {
00420 charFamily( doubleStruckFamily );
00421 }
00422
else {
00423 charFamily( anyFamily );
00424 }
00425
00426
00427
00428
00429
00430
return true;
00431 }
00432
00438 bool TextElement::readContentFromDom(
QDomNode& node)
00439 {
00440
return BasicElement::readContentFromDom(node);
00441 }
00442
00443 QString TextElement::toLatex()
00444 {
00445
if (
isSymbol() ) {
00446
QString texName = getSymbolTable().
name( character );
00447
if ( !texName.isNull() )
00448
return "\\" + texName;
00449
return " ? ";
00450 }
00451
else {
00452
return character;
00453 }
00454 }
00455
00456
QString TextElement::formulaString()
00457 {
00458
if (
isSymbol() ) {
00459
QString texName = getSymbolTable().
name( character );
00460
if ( !texName.isNull() )
00461
return " " + texName +
" ";
00462
return " ? ";
00463 }
00464
else {
00465
return character;
00466 }
00467 }
00468
00469
00470 EmptyElement::EmptyElement(
BasicElement* parent )
00471 :
BasicElement( parent )
00472 {
00473 }
00474
00475 EmptyElement::EmptyElement(
const EmptyElement& other )
00476 :
BasicElement( other )
00477 {
00478 }
00479
00480
00481 bool EmptyElement::accept(
ElementVisitor* visitor )
00482 {
00483
return visitor->
visit(
this );
00484 }
00485
00486
00487 void EmptyElement::calcSizes(
const ContextStyle& context,
00488 ContextStyle::TextStyle tstyle,
00489 ContextStyle::IndexStyle )
00490 {
00491 luPt mySize = context.
getAdjustedSize( tstyle );
00492
00493
00494
QFont font = context.
getDefaultFont();
00495 font.setPointSizeFloat( context.
layoutUnitPtToPt( mySize ) );
00496
00497
QFontMetrics fm( font );
00498
QChar ch =
'A';
00499
QRect bound = fm.boundingRect( ch );
00500 setWidth( 0 );
00501 setHeight( context.
ptToLayoutUnitPt( bound.height() ) );
00502 setBaseline( context.
ptToLayoutUnitPt( -bound.top() ) );
00503 }
00504
00505 void EmptyElement::draw(
QPainter& painter,
const LuPixelRect& ,
00506
const ContextStyle& context,
00507 ContextStyle::TextStyle ,
00508 ContextStyle::IndexStyle ,
00509
const LuPixelPoint& parentOrigin )
00510 {
00511
LuPixelPoint myPos( parentOrigin.x()+getX(), parentOrigin.y()+getY() );
00512
00513
00514
00515
00516
00517
if ( context.
edit() ) {
00518 painter.setPen( context.
getHelpColor() );
00519 painter.drawLine( context.
layoutUnitToPixelX( myPos.x() ),
00520 context.
layoutUnitToPixelY( myPos.y() ),
00521 context.
layoutUnitToPixelX( myPos.x() ),
00522 context.
layoutUnitToPixelY( myPos.y()+getHeight() ) );
00523 }
00524 }
00525
00526 QString EmptyElement::toLatex()
00527 {
00528
return "{}";
00529 }
00530
00531 KFORMULA_NAMESPACE_END