00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "OSDLTextWidget.h"
00028
00029 #include "OSDLFont.h"
00030
00031
00032 #ifdef OSDL_USES_CONFIG_H
00033 #include <OSDLConfig.h>
00034 #endif // OSDL_USES_CONFIG_H
00035
00036
00037
00038 using std::string ;
00039
00040 using namespace Ceylan::Log ;
00041
00042 using namespace OSDL::Video ;
00043 using namespace OSDL::Video::TwoDimensional ;
00044 using namespace OSDL::Video::TwoDimensional::Text ;
00045
00046
00047 const Length TextWidget::DefaultEdgeWidth = 3 ;
00048
00049
00050 const Length TextWidget::_TextWidthOffset = 4 ;
00051 const Length TextWidget::_TextHeightOffset = 4 ;
00052
00053
00054
00055
00056 TextWidget::TextWidget(
00057 Surface & container,
00058 const Point2D & relativePosition,
00059 Length width,
00060 Length maximumHeight,
00061 Shape shape,
00062 Pixels::ColorDefinition textColor,
00063 Pixels::ColorDefinition edgeColor,
00064 Pixels::ColorDefinition backgroundColor,
00065 const std::string & text,
00066 Text::Font & font,
00067 bool minimumHeight,
00068 bool verticallyAligned,
00069 bool justified,
00070 Text::Font::RenderQuality quality,
00071 const string & title,
00072 bool minMaximizable,
00073 bool draggable,
00074 bool wrappable,
00075 bool closable ) :
00076 BackBufferedWidget(
00077 container,
00078 relativePosition,
00079 width,
00080 maximumHeight ,
00081 NotInitialized ,
00082
00083 backgroundColor,
00084 title,
00085 minMaximizable,
00086 draggable,
00087 wrappable,
00088 closable ),
00089 _minimumHeight( minimumHeight ),
00090 _maximumHeight( maximumHeight ),
00091 _shape( shape ),
00092 _textColor( textColor ),
00093 _edgeColor( edgeColor ),
00094 _backColorForRoundCorners( backgroundColor ),
00095 _roundOffset(),
00096 _text( text ),
00097 _font( & font ),
00098 _verticallyAligned( verticallyAligned ) ,
00099 _justified( justified ),
00100 _quality( quality ),
00101 _currentIndex( 0 )
00102 {
00103
00104 #if OSDL_DEBUG_WIDGET
00105 LogPlug::trace( "Text widget constructor" ) ;
00106 #endif // OSDL_DEBUG_WIDGET
00107
00108 switch( _shape )
00109 {
00110
00111 case SquareCorners:
00112 setBaseColorMode( BackgroundColor, backgroundColor ) ;
00113 break ;
00114
00115 case RoundCorners:
00116
00117 setBaseColorMode( Colorkey,
00118 Pixels::selectColorDifferentFrom( _textColor, _edgeColor,
00119 _backColorForRoundCorners ) ) ;
00120 break ;
00121
00122 default:
00123 LogPlug::error(
00124 "TextWidget constructor: unexpected shape specified." ) ;
00125 break ;
00126
00127 }
00128
00129
00130
00131
00132
00133
00134
00135 updateClientArea() ;
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146 }
00147
00148
00149
00150 TextWidget::~TextWidget() throw()
00151 {
00152
00153 #if OSDL_DEBUG_WIDGET
00154 LogPlug::trace( "TextWidget widget destructor" ) ;
00155 #endif // OSDL_DEBUG_WIDGET
00156
00157
00158
00159 }
00160
00161
00162
00163 void TextWidget::setText( const std::string & newText )
00164 {
00165
00166 _text = newText ;
00167
00168
00169 setHeight( _maximumHeight ) ;
00170
00171 updateClientArea() ;
00172
00173 }
00174
00175
00176
00177 const std::string & TextWidget::getText() const
00178 {
00179
00180 return _text ;
00181
00182 }
00183
00184
00185
00186 Text::TextIndex TextWidget::getRenderIndex() const
00187 {
00188
00189 return _currentIndex ;
00190
00191 }
00192
00193
00194
00195 void TextWidget::redrawBackBuffer()
00196 {
00197
00198 #if OSDL_DEBUG_WIDGET
00199 LogPlug::trace( "TextWidget::redrawBackBuffer" ) ;
00200 #endif // OSDL_DEBUG_WIDGET
00201
00202 Coordinate lastOrdinateUsed ;
00203 Surface * renderedText = 0 ;
00204
00205 Coordinate blitWidth, blitHeight ;
00206
00207 try
00208 {
00209
00210
00211 renderedText = & _font->renderLatin1MultiLineText(
00212 _clientArea.getWidth(), _clientArea.getHeight(), _text,
00213 _currentIndex, lastOrdinateUsed,
00214 _quality, _textColor, _justified ) ;
00215
00216 }
00217 catch( const FontException & e )
00218 {
00219
00220 LogPlug::error( "TextWidget::redrawBackBuffer failed: "
00221 + e.toString() ) ;
00222
00223 return ;
00224
00225 }
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235 if ( _shape == SquareCorners )
00236 {
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251 if ( _minimumHeight && ( lastOrdinateUsed < _clientArea.getHeight() ) )
00252 {
00253
00254 #if OSDL_DEBUG_WIDGET
00255
00256
00257 if ( lastOrdinateUsed + 2 * _ClientOffsetHeight
00258 + _TitleBarOffsetOrdinate > getHeight() )
00259 Ceylan::emergencyShutdown( "TextWidget::redrawBackBuffer: "
00260 "specified maximum height exceeded whereas shrinking" ) ;
00261
00262 #endif // OSDL_DEBUG_WIDGET
00263
00264
00265
00266
00267
00268
00269 setHeight( lastOrdinateUsed + 2 * _ClientOffsetHeight
00270 + _TitleBarOffsetOrdinate ) ;
00271
00272
00273
00274
00275
00276
00277 drawFundamentals( *this ) ;
00278
00279 if ( _decorated )
00280 drawDecorations( *this ) ;
00281
00282 }
00283
00284 blitWidth = _clientArea.getUpperLeftAbscissa() ;
00285 blitHeight = _clientArea.getUpperLeftOrdinate() ;
00286
00287 if ( _verticallyAligned )
00288 blitHeight += ( _clientArea.getHeight() - lastOrdinateUsed ) / 2 ;
00289
00290 }
00291 else
00292 {
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320 if ( _minimumHeight && ( lastOrdinateUsed < _clientArea.getHeight() ) )
00321 {
00322
00323 #if OSDL_DEBUG_WIDGET
00324
00325 LogPlug::trace(
00326 "TextWidget::redrawBackBuffer for round rectangle: "
00327 "lastOrdinateUsed = " + Ceylan::toString( lastOrdinateUsed )
00328 + ", client area height = "
00329 + Ceylan::toString( _clientArea.getHeight() ) ) ;
00330
00331 #endif // OSDL_DEBUG_WIDGET
00332
00333
00334
00335
00336
00337
00338 setHeight( lastOrdinateUsed + 2 * _roundOffset ) ;
00339
00340
00341 #if OSDL_DEBUG_WIDGET
00342
00343 if ( _clientArea.getWidth() < renderedText->getWidth() )
00344 Ceylan::emergencyShutdown( "TextWidget::redrawBackBuffer: "
00345 "resize for round rectangle led to a client area "
00346 "not wide enough: client area width = "
00347 + Ceylan::toString( _clientArea.getWidth() )
00348 + ", rendered text width = "
00349 + Ceylan::toString( renderedText->getWidth() ) ) ;
00350
00351 if ( _clientArea.getHeight() < lastOrdinateUsed )
00352 Ceylan::emergencyShutdown( "TextWidget::redrawBackBuffer: "
00353 "resize for round rectangle led to a client area "
00354 "not tall enough: client area height = "
00355 + Ceylan::toString( _clientArea.getHeight() )
00356 + ", rendered text height = "
00357 + Ceylan::toString( renderedText->getHeight() ) ) ;
00358
00359 #endif // OSDL_DEBUG_WIDGET
00360
00361
00362 }
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372 fill( _baseColor ) ;
00373
00374
00375
00376 drawWithRoundedCorners( *this, DefaultEdgeWidth,
00377 _edgeColor, _backColorForRoundCorners ) ;
00378
00379
00380
00381
00382
00383
00384
00385
00386 blitWidth = _clientArea.getUpperLeftAbscissa() +
00387 ( _clientArea.getWidth() - renderedText->getWidth() ) / 2 ;
00388
00389 blitHeight = _clientArea.getUpperLeftOrdinate() +
00390 ( _clientArea.getHeight() - lastOrdinateUsed ) / 2 ;
00391
00392 }
00393
00394
00395 #if OSDL_DEBUG_WIDGET
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415 #endif // OSDL_DEBUG_WIDGET
00416
00417
00418
00419
00420
00421
00422
00423 renderedText->blitTo( *this, blitWidth, blitHeight ) ;
00424
00425 delete renderedText ;
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435 setBackBufferRedrawState( false ) ;
00436
00437 }
00438
00439
00440
00441 const string TextWidget::toString( Ceylan::VerbosityLevels level ) const
00442 {
00443
00444 std::list<string> textWidgetList ;
00445
00446
00447 string shapeText = "Widget shape is " ;
00448
00449
00450 switch( _shape )
00451 {
00452
00453 case SquareCorners:
00454 shapeText += "a rectangle with square corners" ;
00455 break ;
00456
00457 case RoundCorners:
00458 shapeText += "a rectangle with round corners" ;
00459 break ;
00460
00461 default:
00462 shapeText += "unknown (abnormal)" ;
00463 break ;
00464
00465 }
00466
00467
00468 textWidgetList.push_back( shapeText ) ;
00469
00470 if ( _minimumHeight )
00471 {
00472 textWidgetList.push_back( "Widget height (currently: "
00473 + Ceylan::toString( getHeight() )
00474 + ") will shrink, if text is short enough, "
00475 "for recorded maximum height, "
00476 + Ceylan::toString( _maximumHeight ) ) ;
00477 }
00478 else
00479 {
00480
00481 textWidgetList.push_back( "Widget height ("
00482 + Ceylan::toString( getHeight() )
00483 + ") will not shrink even if text short enough." ) ;
00484 }
00485
00486 textWidgetList.push_back( "Text color is "
00487 + Pixels::toString( _textColor ) ) ;
00488
00489 textWidgetList.push_back( "Edge color is "
00490 + Pixels::toString( _edgeColor ) ) ;
00491
00492 textWidgetList.push_back( "Text to display is '" + _text + "'." ) ;
00493
00494 textWidgetList.push_back( "Font informations: "
00495 + _font->toString( level ) ) ;
00496
00497 if ( _justified )
00498 textWidgetList.push_back( "Text will be justified" ) ;
00499 else
00500 textWidgetList.push_back( "Text will not be justified" ) ;
00501
00502 if ( _verticallyAligned )
00503 textWidgetList.push_back( "Text will be vertically aligned" ) ;
00504 else
00505 textWidgetList.push_back( "Text will not be vertically aligned "
00506 "unless it takes the full height of client area" ) ;
00507
00508 switch( _quality )
00509 {
00510
00511 case Text::Font::Solid:
00512 textWidgetList.push_back(
00513 "Text will be rendered in Solid quality" ) ;
00514 break ;
00515
00516 case Text::Font::Shaded:
00517 textWidgetList.push_back(
00518 "Text will be rendered in Shaded quality" ) ;
00519 break ;
00520
00521 case Text::Font::Blended:
00522 textWidgetList.push_back(
00523 "Text will be rendered in Blended quality" ) ;
00524 break ;
00525
00526 default:
00527 textWidgetList.push_back(
00528 "Text will be rendered in unknown quality (abnormal)" ) ;
00529 break ;
00530
00531 }
00532
00533
00534 string res = "Text widget: " + Ceylan::formatStringList( textWidgetList ) ;
00535
00536 if ( level == Ceylan::low )
00537 return res ;
00538
00539 return res + BackBufferedWidget::toString( level ) ;
00540
00541 }
00542
00543
00544
00545 void TextWidget::updateClientArea()
00546 {
00547
00548 #if OSDL_DEBUG_WIDGET
00549 LogPlug::trace( "TextWidget::updateClientArea" ) ;
00550 #endif // OSDL_DEBUG_WIDGET
00551
00552
00553 if ( _shape == SquareCorners )
00554 {
00555 Widget::updateClientArea() ;
00556 return ;
00557 }
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573 Length radius = 0 ;
00574
00575 try
00576 {
00577 radius = computeRadiusForRoundRectangle( DefaultEdgeWidth ) ;
00578 }
00579 catch( const VideoException & e )
00580 {
00581
00582 LogPlug::error( "TextWidget::updateClientArea: no possible radius: "
00583 + e.toString() ) ;
00584
00585 Widget::updateClientArea() ;
00586
00587 }
00588
00589
00590 Length projectedRadius = static_cast<Length>(
00591 radius * Ceylan::Maths::Sqrt_2 / 2 ) ;
00592
00593 _roundOffset = DefaultEdgeWidth + radius - projectedRadius ;
00594
00595 _clientArea.setUpperLeftAbscissa( _roundOffset ) ;
00596 _clientArea.setWidth( getWidth() - 2 * _roundOffset ) ;
00597
00598 _clientArea.setUpperLeftOrdinate( _roundOffset ) ;
00599 _clientArea.setHeight( getHeight() - 2 * _roundOffset ) ;
00600
00601
00602
00603 }
00604