Back to index

extremetuxracer  0.5beta
textarea.cpp
Go to the documentation of this file.
00001 /* 
00002  * PPRacer 
00003  * Copyright (C) 2004-2005 Volker Stroebel <volker@planetpenguin.de>
00004  *
00005  * Copyright (C) 1999-2001 Jasmin F. Patry
00006  * 
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  * 
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  * 
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00020  */
00021 #include "checkbox.h"
00022  
00023 #include "textarea.h"
00024 #include "ui_mgr.h"
00025 
00026 #include "render_util.h"
00027 
00028 #include "translation.h"
00029 
00030 #define DEFAULT_ARROW_BUTTON_HEIGHT 15
00031 #define DEFAULT_ARROW_BUTTON_WIDTH  27
00032 #define DEFAULT_ARROW_REGION_WIDTH  36
00033 #define DEFAULT_ARROW_VERT_SEPARATION  4
00034 #define DEFAULT_BORDER_WIDTH 4
00035 #define DEFAULT_TEXT_PAD 4
00036 
00037 namespace pp {
00038 
00039 Textarea::Textarea( pp::Vec2d pos, pp::Vec2d size,
00040                           const char *binding, const char *text )
00041 {
00042     char *tempbinding;
00043     pp::Vec2d ll, ur;
00044        
00045        m_position = pos;
00046        m_size = size;
00047        
00048     m_arrowWidth = DEFAULT_ARROW_REGION_WIDTH;
00049     m_borderWidth = DEFAULT_BORDER_WIDTH;
00050     m_textPad = DEFAULT_TEXT_PAD;
00051        
00052     calcTextRegionDims();
00053 
00054        mp_font = pp::Font::get(binding);
00055        
00056     m_borderColor = theme.foreground;
00057     m_backgroundColor = theme.background;
00058 
00059     /* 
00060      * Create buttons 
00061      */
00062     mp_upButton = new pp::Button(
00063               pp::Vec2d( 0, 0 ), /* position will be set later */
00064               pp::Vec2d(DEFAULT_ARROW_BUTTON_WIDTH, DEFAULT_ARROW_BUTTON_HEIGHT),
00065               NULL,
00066               NULL );
00067 
00068     tempbinding = "textarea_arrows";
00069 
00070     ll = pp::Vec2d( 2.0/64.0, 17.0/64.0 );
00071     ur = pp::Vec2d( 29.0/64.0, 32.0/64.0 );
00072     mp_upButton->setImage( tempbinding, ll, ur, pp::Color::white );
00073 
00074     ll = pp::Vec2d( 34.0/64.0, 17.0/64.0 );
00075     ur = pp::Vec2d( 61.0/64.0, 32.0/64.0 );
00076     mp_upButton->setDisabledImage( tempbinding, ll, ur, pp::Color::white );
00077 
00078     ll = pp::Vec2d( 34.0/64.0, 49.0/64.0 );
00079     ur = pp::Vec2d( 61.0/64.0, 64.0/64.0 );
00080     mp_upButton->setHilitImage( tempbinding, ll, ur, pp::Color::white );
00081 
00082     ll = pp::Vec2d( 2.0/64.0, 49.0/64.0 );
00083     ur = pp::Vec2d( 29.0/64.0, 64.0/64.0 );
00084     mp_upButton->setClickedImage( tempbinding, ll, ur, pp::Color::white );
00085        
00086        mp_upButton->setActive(true);
00087     mp_upButton->signalClicked.Connect(pp::CreateSlot(this,&Textarea::upButtonClick));
00088 
00089     mp_downButton = new pp::Button(
00090               pp::Vec2d( 0, 0 ), /* position will be set later */
00091               pp::Vec2d(DEFAULT_ARROW_BUTTON_WIDTH,DEFAULT_ARROW_BUTTON_HEIGHT),
00092               NULL,
00093               NULL );
00094 
00095     tempbinding = "textarea_arrows";
00096 
00097     ll = pp::Vec2d( 2.0/64.0, 1.0/64.0 );
00098     ur = pp::Vec2d( 29.0/64.0, 16.0/64.0 );
00099     mp_downButton->setImage(tempbinding, ll, ur, pp::Color::white );
00100 
00101     ll = pp::Vec2d( 34.0/64.0, 1.0/64.0 );
00102     ur = pp::Vec2d( 61.0/64.0, 16.0/64.0 );
00103     mp_downButton->setDisabledImage(tempbinding, ll, ur, pp::Color::white );
00104 
00105     ll = pp::Vec2d( 34.0/64.0, 33.0/64.0 );
00106     ur = pp::Vec2d( 61.0/64.0, 48.0/64.0 );
00107     mp_downButton->setHilitImage(tempbinding, ll, ur, pp::Color::white );
00108 
00109     ll = pp::Vec2d( 2.0/64.0, 33.0/64.0 );
00110     ur = pp::Vec2d( 29.0/64.0, 48.0/64.0 );
00111     mp_downButton->setClickedImage(tempbinding, ll, ur, pp::Color::white );
00112 
00113        mp_downButton->setActive(true);
00114     mp_downButton->signalClicked.Connect(pp::CreateSlot(this,&Textarea::downButtonClick));
00115 
00116        updateButtonPositions();
00117     
00118 
00119     if ( text == NULL ) {
00120               text = "";
00121     }
00122        
00123        
00124     mp_textOrig = new char[strlen( text ) + 1];
00125        strcpy( mp_textOrig, text );
00126 
00127     mp_textLines = NULL;
00128 
00129     createLines();
00130 
00131     updateButtonEnabledStates();
00132 
00133     this->m_visible = false;
00134     this->m_active = false;
00135 }
00136 
00137 Textarea::~Textarea()
00138 {
00139     setVisible( false );
00140     setActive( false );
00141 
00142     if ( mp_upButton != NULL ) {
00143               delete mp_upButton;
00144     }
00145     if ( mp_downButton != NULL ) {
00146               delete mp_downButton;
00147     }
00148 
00149     if ( mp_textLines != NULL ) {
00150               delete( mp_textLines );
00151     }
00152 
00153     if ( mp_textOrig != NULL ) {
00154               delete( mp_textOrig );
00155     }  
00156 }
00157 
00158 void
00159 Textarea::calcTextRegionDims()
00160 {
00161     m_textRegionWidth = m_size.x - 2*m_borderWidth - 2*m_textPad - m_arrowWidth;
00162     m_textRegionHeight = m_size.y - 2*m_borderWidth - 2*m_textPad;
00163 }
00164 
00165 void
00166 Textarea::updateButtonPositions()
00167 {
00168        mp_upButton->setPosition(pp::Vec2d(
00169            m_position.x + m_size.x - m_borderWidth -
00170            mp_upButton->getWidth(),
00171            m_position.y + m_size.y - m_borderWidth -
00172            mp_upButton->getHeight() ) );
00173        
00174        mp_downButton->setPosition(pp::Vec2d(
00175            m_position.x + m_size.x - m_borderWidth -
00176            mp_downButton->getWidth(),
00177            m_position.y + m_borderWidth ) );
00178 }
00179 
00180 void
00181 Textarea::createLines()
00182 {
00183        /*font_t font;
00184 
00185     if ( !get_font_binding( m_binding, font ) ) {
00186               print_warning( IMPORTANT_WARNING,
00187                      "Couldn't get font for binding %s", m_binding );
00188               return;
00189     }
00190        */
00191        
00192        
00193        if ( mp_textLines != NULL ) {
00194               delete mp_textLines;
00195               mp_textLines = NULL;
00196     }
00197 
00198     if ( !m_lines.empty() ) {
00199               m_lines.clear();
00200     }
00201        
00202        char *cur_ptr;
00203        char *newline_ptr;
00204        
00205        mp_textLines = new char[strlen(mp_textOrig)+1];
00206        strcpy(mp_textLines,mp_textOrig);
00207        
00208        
00209     cur_ptr = mp_textLines;
00210 
00211        while ( *cur_ptr != '\0' ){
00212               newline_ptr = strchr( cur_ptr, '\n' );
00213               if( newline_ptr!=NULL){
00214                      *newline_ptr = '\0';
00215               }
00216               
00217               //if( string_width( cur_ptr, &font ) > m_textRegionWidth ) {
00218               if( mp_font->advance(cur_ptr) > m_textRegionWidth ) {
00219               
00220                      //text is too long for linear_attenuation
00221                      //try to find a suiteable space within this line
00222                      char* old_space_ptr = NULL;
00223                      char* space_ptr = strrchr( cur_ptr, ' ' );
00224                      
00225                      while (space_ptr !=NULL){
00226                             *space_ptr = '\0';
00227                             if(mp_font->advance(cur_ptr) < m_textRegionWidth ){
00228                                    if(newline_ptr!=NULL){
00229                                           *newline_ptr = '\n';
00230                                    }
00231                                    newline_ptr = space_ptr;
00232                                    break;
00233                             }
00234                             
00235                             if(old_space_ptr !=NULL){
00236                                    *old_space_ptr = ' ';
00237                             }
00238                             old_space_ptr = space_ptr;
00239                             space_ptr = strrchr( cur_ptr, ' ' );
00240                      }
00241                      if(old_space_ptr !=NULL){
00242                             *old_space_ptr = ' ';
00243                      }
00244               }
00245               m_lines.push_back(cur_ptr);
00246        
00247               if(newline_ptr==NULL){
00248                      break;
00249               }
00250               cur_ptr=newline_ptr+1;
00251        }
00252        
00253     mi_topLine = m_lines.begin();
00254 }
00255 
00256 void
00257 Textarea::updateButtonEnabledStates()
00258 {
00259     if ( m_lines.empty() ) {
00260               /* No lines */
00261               mp_upButton->setSensitive( false );
00262               mp_downButton->setSensitive( false );
00263     } else {
00264               if ( mi_topLine == m_lines.begin() ) {
00265                   mp_upButton->setSensitive( false );
00266               } else {
00267                   mp_upButton->setSensitive( true );
00268               }
00269               if ( mi_topLine == --m_lines.end() ) {
00270                   mp_downButton->setSensitive( false );
00271               } else {
00272                   mp_downButton->setSensitive( true );
00273               }
00274     }
00275 }
00276 
00277 void
00278 Textarea::setText( const char *text )
00279 {
00280     if ( mp_textOrig != NULL ) {
00281               delete mp_textOrig;
00282               mp_textOrig = NULL;
00283     }
00284 
00285     if ( text == NULL ) {
00286               text = "";
00287     }
00288 
00289     text = _(text);
00290 
00291     mp_textOrig = new char[strlen( text ) + 1];
00292        strcpy( mp_textOrig, text );
00293        
00294     createLines();
00295     updateButtonEnabledStates();   
00296 }
00297 
00298 void
00299 Textarea::setPosition(pp::Vec2d pos)
00300 {
00301        Widget::setPosition(pos);
00302        updateButtonPositions();
00303 }
00304 
00305 
00306 void 
00307 Textarea::upButtonClick()
00308 {
00309        if( mi_topLine != m_lines.begin()){
00310               mi_topLine--;
00311        updateButtonEnabledStates();
00312        UIMgr.setDirty();
00313        }
00314 }
00315 
00316 void 
00317 Textarea::downButtonClick()
00318 {
00319        if( mi_topLine != --m_lines.end() ){
00320               mi_topLine++;
00321               updateButtonEnabledStates();
00322               UIMgr.setDirty();
00323        }
00324 }
00325 
00326 void
00327 Textarea::drawTextLines()
00328 {
00329        if (m_lines.empty())return;
00330        
00331        std::list<char*>::iterator it;
00332        float desc = mp_font->descender();
00333        float asc = mp_font->ascender();
00334        float y = m_position.y + m_size.y - m_borderWidth - m_textPad - asc;
00335        float x = m_position.x + m_borderWidth + m_textPad;
00336        
00337        for(it=mi_topLine; it!=m_lines.end(); it++){
00338               mp_font->draw(*it, x, y);
00339               
00340               //float desc = mp_font->descender();
00341               //float asc = mp_font->ascender();
00342               
00343               y-=asc-desc;
00344               if(y < m_position.y + m_borderWidth) {
00345                      if ( mp_downButton ) {
00346                      mp_downButton->setSensitive( true );
00347                      }
00348                      break;
00349               }
00350        }
00351 }
00352 
00353 void
00354 Textarea::draw()
00355 {
00356        glDisable( GL_TEXTURE_2D );
00357 
00358     glColor3dv( (double*)&m_borderColor );
00359 
00360     glRectf( m_position.x, 
00361             m_position.y,
00362             m_position.x + m_size.x,
00363             m_position.y + m_size.y );
00364 
00365     glColor3dv( (double*)&m_backgroundColor );
00366 
00367     glRectf( m_position.x + m_borderWidth, 
00368             m_position.y + m_borderWidth,
00369             m_position.x + m_size.x - m_borderWidth,
00370             m_position.y + m_size.y - m_borderWidth );
00371 
00372     glEnable( GL_TEXTURE_2D );
00373 
00374        drawTextLines();
00375 
00376     if ( mp_upButton != NULL ) {
00377               mp_upButton->draw();
00378     }
00379 
00380     if ( mp_downButton != NULL ) {
00381               mp_downButton->draw(); 
00382     }
00383 }      
00384 
00385 
00386 } //namespace pp