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