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