Back to index

supertuxkart  0.5+dfsg1
widget_manager.cpp
Go to the documentation of this file.
00001 //
00002 //  SuperTuxKart - a fun racing game with go-kart
00003 //  This code originally from Neverball copyright (C) 2003 Robert Kooima
00004 //
00005 //  This program is free software; you can redistribute it and/or
00006 //  modify it under the terms of the GNU General Public License
00007 //  as published by the Free Software Foundation; either version 2
00008 //  of the License, or (at your option) any later version.
00009 //
00010 //  This program is distributed in the hope that it will be useful,
00011 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 //  GNU General Public License for more details.
00014 //
00015 //  You should have received a copy of the GNU General Public License
00016 //  along with this program; if not, write to the Free Software
00017 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00018 
00019 #include "widget_manager.hpp"
00020 
00021 #include "user_config.hpp"
00022 
00023 #ifdef __APPLE__
00024 #  include <OpenGL/glu.h>
00025 #else
00026 #  include <GL/glu.h>
00027 #endif
00028 
00029 #include <iostream>
00030 #include <cstdlib>
00031 #include <iterator>
00032 #include <algorithm>
00033 #include <cassert>
00034 #include <stack>
00035 
00036 WidgetManager *widget_manager;
00037 
00038 const int WidgetManager::WGT_NONE = -1;
00039 
00040 WidgetManager::WidgetManager() :
00041 m_prev_layout_pos(WGT_AREA_NONE),
00042 m_x( -1 ), m_y( -1 ),
00043 m_selected_wgt_token( WGT_NONE ),
00044 m_selection_change( false )
00045 {
00046     restoreDefaultStates();
00047 }
00048 
00049 //-----------------------------------------------------------------------------
00050 WidgetManager::~WidgetManager()
00051 {
00052     reset();
00053 }
00054 
00055 //-----------------------------------------------------------------------------
00056 bool WidgetManager::addWgt
00057 (
00058     const int TOKEN,
00059     const int MIN_WIDTH,
00060     const int MIN_HEIGHT
00061 )
00062 {
00063     if( TOKEN != WGT_NONE && findId( TOKEN ) != WGT_NONE )
00064     {
00065         std::cerr << "WARNING: tried to create widget with token " <<
00066             TOKEN << " but it is already in use.\n";
00067         return false;
00068     }
00069 
00070     WidgetID new_id;
00071     new_id.token = TOKEN;
00072 
00073     //There is no reason to make a token-less widget active, so if the token
00074     //WGT_NONE, the widget is forced to be inactive, preventing bugs.
00075     new_id.active = TOKEN != WGT_NONE ? m_default_active : false;
00076 
00077     new_id.min_width = MIN_WIDTH;
00078     new_id.min_height = MIN_HEIGHT;
00079     new_id.min_radius = m_default_rect_radius;
00080 
00081     new_id.last_preset_scroll_x = m_default_scroll_preset_x;
00082     new_id.last_preset_scroll_y = m_default_scroll_preset_y;
00083 
00084     new_id.resize_to_text = m_default_resize_to_text;
00085 
00086     new_id.widget = new Widget(0, 0, 0, 0);
00087 
00088     new_id.widget->m_enable_rect = m_default_show_rect;
00089     new_id.widget->m_round_corners = m_default_rect_round_corners;
00090     new_id.widget->m_rect_color = m_default_rect_color;
00091 
00092     new_id.widget->m_enable_border = m_default_show_border;
00093     new_id.widget->m_border_percentage = m_default_border_percentage;
00094     new_id.widget->m_border_color = m_default_border_color;
00095 
00096     new_id.widget->m_enable_texture = m_default_show_texture;
00097     new_id.widget->m_texture = m_default_texture;
00098 
00099     new_id.widget->m_enable_text = m_default_show_text;
00100     new_id.widget->m_text.assign(m_default_text);
00101     new_id.widget->m_text_size = m_default_text_size;
00102     new_id.widget->setFont( m_default_font );
00103     new_id.widget->m_text_color = m_default_text_color;
00104 
00105     new_id.widget->m_enable_scroll  = m_default_enable_scroll;
00106     new_id.widget->m_scroll_pos_x   = (float)m_default_scroll_preset_x;
00107     new_id.widget->m_scroll_pos_y   = (float)m_default_scroll_preset_y;
00108     new_id.widget->m_scroll_speed_x = m_default_scroll_x_speed;
00109     new_id.widget->m_scroll_speed_y = m_default_scroll_y_speed;
00110 
00111     new_id.widget->m_enable_rotation = m_default_enable_rotation;
00112     new_id.widget->m_rotation_angle = m_default_rotation_angle;
00113     new_id.widget->m_rotation_speed = m_default_rotation_speed;
00114 
00115     new_id.widget->m_enable_track = m_default_show_track;
00116     new_id.widget->m_track_num = m_default_track_num;
00117 
00118     m_elems.push_back(WidgetElement(ET_WGT, (int)m_widgets.size()));
00119     m_widgets.push_back(new_id);
00120 
00121     return true;
00122 }
00123 
00124 //-----------------------------------------------------------------------------
00125 void WidgetManager::switchOrder()
00126 {
00127     m_elems.push_back( WidgetElement( ET_SWITCH, 0 ));
00128 }
00129 
00130 //-----------------------------------------------------------------------------
00131 bool WidgetManager::breakLine()
00132 {
00133     const int LAST_WGT = (int)m_widgets.size() - 1;
00134 
00135     if( LAST_WGT < 0 )
00136     {
00137         std::cerr << "WARNING: tried to add a break before adding any " <<
00138             "widgets.\n";
00139         return false;
00140     }
00141 
00142     const int LAST_ELEM = (int)m_elems.size() - 1;
00143     if( m_elems[LAST_ELEM].type == ET_SWITCH )
00144     {
00145         std::cerr << "WARNING: tried to add a break after a switch, last " <<
00146             "widget had token " << m_widgets[ LAST_WGT ].token << ".\n";
00147         return false;
00148     }
00149 
00150     m_elems.push_back(WidgetElement( ET_BREAK, 0 ));
00151 
00152     return true;
00153 }
00154 
00155 //-----------------------------------------------------------------------------
00156 void WidgetManager::reset()
00157 {
00158     const int NUM_WIDGETS = (int)m_widgets.size();
00159 
00160     for(int i = 0; i < NUM_WIDGETS; ++i)
00161     {
00162         delete m_widgets[i].widget;
00163     }
00164 
00165     m_widgets.clear();
00166     m_elems.clear();
00167 
00168     restoreDefaultStates();
00169 
00170     m_selected_wgt_token = WGT_NONE;
00171     m_selection_change = false;
00172 }
00173 
00174 //-----------------------------------------------------------------------------
00175 int WidgetManager::findId(const int TOKEN) const
00176 {
00177     const int NUM_WIDGETS = (int)m_widgets.size();
00178 
00179     for( int i = 0; i < NUM_WIDGETS; ++i )
00180     {
00181         if( TOKEN == m_widgets[i].token )
00182             return i;
00183     }
00184 
00185     return WGT_NONE;
00186 }
00187 
00188 //-----------------------------------------------------------------------------
00189 void WidgetManager::update(const float DELTA)
00190 {
00191     m_selection_change = false;
00192 
00193     //Enable 2D rendering
00194     glMatrixMode(GL_PROJECTION);
00195     glPushMatrix();
00196     glLoadIdentity();
00197     glOrtho(0.0, user_config->m_width, 0.0, user_config->m_height, -1.0, 1.0);
00198     glMatrixMode(GL_MODELVIEW);
00199 
00200     glPushAttrib(GL_LIGHTING_BIT |
00201         GL_COLOR_BUFFER_BIT |
00202         GL_DEPTH_BUFFER_BIT |
00203         GL_STENCIL_BUFFER_BIT);
00204 
00205     glEnable(GL_BLEND);
00206     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00207     glEnable(GL_COLOR_MATERIAL);
00208     glDisable(GL_LIGHTING);
00209     glDisable(GL_DEPTH_TEST);
00210     glDisable(GL_CULL_FACE);
00211     glEnable (GL_STENCIL_TEST);
00212 
00213     const int NUM_WIDGETS = (int)m_widgets.size();
00214     for( int i = 0; i < NUM_WIDGETS; ++i)
00215     {
00216         m_widgets[i].widget->update(DELTA);
00217     }
00218 
00219     glPopAttrib();
00220 
00221     glMatrixMode(GL_PROJECTION);
00222     glPopMatrix();
00223     glMatrixMode(GL_MODELVIEW);
00224 
00225 }
00226 
00235 bool WidgetManager::layout()
00236 {
00237     if( m_prev_layout_pos == WGT_AREA_NONE )
00238     {
00239         std::cerr << "WARNING: tried to call layout() with the previous " <<
00240             "layout position, but layout(WidgetArea POSITION) has never " <<
00241             "been called.\n";
00242         return false;
00243     }
00244 
00245 
00246     const int NUM_WIDGETS = (int)m_widgets.size();
00247     for( int i = 0; i < NUM_WIDGETS; ++i )
00248     {
00249         m_widgets[i].widget->m_scroll_pos_x =
00250             (float)m_widgets[i].last_preset_scroll_x;
00251 
00252         m_widgets[i].widget->m_scroll_pos_y =
00253             (float)m_widgets[i].last_preset_scroll_y;
00254     }
00255 
00256 
00257     const int PREV_SELECTED_WGT_TOKEN = m_selected_wgt_token;
00258 
00259     if( !layout( m_prev_layout_pos )) return false;
00260 
00261     if( findId( PREV_SELECTED_WGT_TOKEN ) != WGT_NONE )
00262     {
00263         setSelectedWgtToken( PREV_SELECTED_WGT_TOKEN );
00264     }
00265 
00266     return true;
00267 }
00268 
00269 //-----------------------------------------------------------------------------
00270 bool WidgetManager::layout(const WidgetArea POSITION)
00271 {
00272     //TODO: split layout(WidgetArea) into smaller functions
00273     if( POSITION == WGT_AREA_NONE )
00274     {
00275         std::cerr << "WARNING: called layout with WGT_AREA_NONE.\n";
00276         return false;
00277     }
00278 
00279     m_prev_layout_pos = POSITION;
00280 
00281     const int NUM_WIDGETS = (int)m_widgets.size();
00282     if( NUM_WIDGETS < 1 ) return true;
00283 
00284     const int SCREEN_WIDTH = user_config->m_width;
00285     const int SCREEN_HEIGHT = user_config->m_height;
00286 
00287     {
00288         int width, height;
00289         //Set the widgets' rect shape properties in pixels.
00290         for( int i = 0; i < NUM_WIDGETS; ++i )
00291         {
00292             width = (int)(SCREEN_WIDTH * m_widgets[i].min_width * 0.01);
00293             height = (int)(SCREEN_HEIGHT * m_widgets[i].min_height * 0.01);
00294 
00295             m_widgets[i].widget->m_width = width;
00296             m_widgets[i].widget->m_height = height;
00297 
00298             if( m_widgets[i].resize_to_text ) m_widgets[i].widget->
00299                 resizeToText();
00300 
00301             if( width < height )
00302             {
00303                 m_widgets[i].widget->m_radius = (int)( m_widgets[i].min_radius *
00304                     m_widgets[i].widget->m_width * 0.01 );
00305             }
00306             else
00307             {
00308                 m_widgets[i].widget->m_radius = (int)( m_widgets[i].min_radius *
00309                     m_widgets[i].widget->m_height * 0.01 );
00310             }
00311 
00312             if( m_widgets[i].widget->m_radius < 1 )
00313             {
00314                 m_widgets[i].widget->m_radius = 1;
00315             }
00316         }
00317     }
00318 
00319     const int WGTS_WIDTH = calcWidth();
00320     const int WGTS_HEIGHT = calcHeight();
00321 
00322     if( WGTS_WIDTH > SCREEN_WIDTH )
00323     {
00324         std::cerr << "WARNING: total width of the widgets is bigger than " <<
00325             "the screen, because the total minimum width given is bigger " <<
00326             "than 100%.\n";
00327     }
00328     if( WGTS_HEIGHT > SCREEN_HEIGHT )
00329     {
00330         std::cerr << "WARNING: total height of the widgets is bigger " <<
00331             "than the screen, because the total minimum height given is " <<
00332             "bigger than 100%.\n";
00333     }
00334 
00335     //To position things on the screen, remember that with OpenGL, in the
00336     //Y-axis the position 0 is in the bottom of the screen, just like the top
00337     //right quad of a cartesian plane.
00338     switch(POSITION)
00339     {
00340     case WGT_AREA_NW:
00341         m_x = 0;
00342         m_y = SCREEN_HEIGHT;
00343         break;
00344 
00345     case WGT_AREA_SW:
00346         m_x = 0;
00347         m_y = 0;
00348         break;
00349 
00350     case WGT_AREA_NE:
00351         m_x = SCREEN_WIDTH - WGTS_WIDTH;
00352         m_y = SCREEN_HEIGHT;
00353         break;
00354 
00355     case WGT_AREA_SE:
00356         m_x = SCREEN_WIDTH - WGTS_WIDTH;
00357         m_y = 0;
00358         break;
00359 
00360     case WGT_AREA_LFT:
00361         m_x = 0;
00362         m_y = (int)(SCREEN_HEIGHT * 0.5 + WGTS_HEIGHT * 0.5f );
00363         break;
00364 
00365     case WGT_AREA_RGT:
00366         m_x = SCREEN_WIDTH - WGTS_WIDTH;
00367         m_y = (int)(SCREEN_HEIGHT * 0.5 + WGTS_HEIGHT * 0.5f );
00368         break;
00369 
00370     case WGT_AREA_TOP:
00371         m_x = (int)(SCREEN_WIDTH * 0.5f - WGTS_WIDTH * 0.5f );
00372         m_y = SCREEN_HEIGHT;
00373         break;
00374 
00375     case WGT_AREA_BOT:
00376         m_x = (int)(SCREEN_WIDTH * 0.5f - WGTS_WIDTH * 0.5f );
00377         m_y = 0;
00378         break;
00379 
00380     case WGT_AREA_ALL:
00381         m_x = (int)(SCREEN_WIDTH * 0.5f - WGTS_WIDTH * 0.5f );
00382         m_y = (int)(SCREEN_HEIGHT * 0.5 + WGTS_HEIGHT * 0.5f );
00383         break;
00384 
00385     //This is just here to avoid a warning
00386     case WGT_AREA_NONE:
00387         break;
00388     }
00389 
00390     /* We have to give each widget it's pixel position and create their rect.
00391      * The position given to the widgets is their bottom left corner; since
00392      * OpenGL the bottom left corner of the screen for (0,0), it's easier
00393      * that way. Widgets are centered on the X-axis around their line or
00394      * column (if it's inside one), but are always stuck to the top of their
00395      * line or column.
00396      */
00397 
00398     int cursor_x = m_x + ( WGTS_WIDTH - calcLineWidth( 0 )) / 2;
00399     int cursor_y = m_y;
00400     int line_pos = 0;
00401     WidgetID* curr_wgt = 0;
00402 
00403     const int NUM_ELEMS = (int)m_elems.size();
00404 
00405     for( int i = 0; i < NUM_ELEMS; ++i )
00406     {
00407         switch( m_elems[ i ].type )
00408         {
00409         case ET_WGT:
00410             curr_wgt = &m_widgets[ m_elems[ i ].pos ];
00411 
00412             curr_wgt->widget->m_x = cursor_x;
00413 
00414             //We have to give createRect() the bottom left corner
00415             curr_wgt->widget->m_y = cursor_y - curr_wgt->widget->m_height;
00416 
00417             if( !(curr_wgt->widget->createRect()) ) return false;
00418 
00419             cursor_x += curr_wgt->widget->m_width;
00420             break;
00421 
00422         case ET_BREAK:
00423             cursor_x = m_x + ( WGTS_WIDTH - calcLineWidth( i + 1 )) / 2;
00424             cursor_y -= calcLineHeight( line_pos );
00425             line_pos = i + 1;
00426             break;
00427 
00428         case ET_SWITCH:
00429             ++i;
00430 
00431             if( !layoutColumn( cursor_x, cursor_y, i )) return false;
00432 
00433             break;
00434         }
00435     }
00436 
00437     //Select the first active widget by default
00438     setSelectedWgtToken( WGT_NONE );
00439 
00440     for( int i = 0; i < NUM_WIDGETS; ++i )
00441     {
00442         if( m_widgets[i].active )
00443         {
00444             setSelectedWgtToken( m_widgets[i].token );
00445             break;
00446         }
00447     }
00448 
00449     return true;
00450 }
00451 
00452 //-----------------------------------------------------------------------------
00453 bool WidgetManager::layoutLine( int& x, int& y, int& pos )
00454 {
00455     int cursor_x = x;
00456     int cursor_y = y;
00457     WidgetID* curr_wgt = 0;
00458 
00459     const int NUM_ELEMS = (int)m_elems.size();
00460     int i;
00461 
00462     for( i = pos; i < NUM_ELEMS; ++i )
00463     {
00464         switch( m_elems[ i ].type )
00465         {
00466         case ET_WGT:
00467             curr_wgt = &m_widgets[ m_elems[ i ].pos ];
00468 
00469             curr_wgt->widget->m_x = cursor_x;
00470 
00471             //We have to give createRect() the bottom left corner
00472             curr_wgt->widget->m_y = cursor_y - curr_wgt->widget->m_height;
00473 
00474             if( !(curr_wgt->widget->createRect()) ) return false;
00475 
00476             cursor_x += curr_wgt->widget->m_width;
00477             break;
00478 
00479         case ET_BREAK:
00480             x += ( calcLineWidth( pos ) - calcColumnWidth( i + 1 )) / 2;
00481             y = cursor_y - calcLineHeight( pos );
00482             pos = i;
00483             return true;
00484 
00485         case ET_SWITCH:
00486             ++i;
00487             layoutColumn( cursor_x, cursor_y, i );
00488             break;
00489         }
00490     }
00491 
00492     pos = i;
00493     return true;
00494 }
00495 
00496 //-----------------------------------------------------------------------------
00497 bool WidgetManager::layoutColumn( int& x, int& y, int& pos )
00498 {
00499     int cursor_x = x + calcColumnX( pos );
00500     int cursor_y = y;
00501     WidgetID* curr_wgt = 0;
00502 
00503     const int NUM_ELEMS = (int)m_elems.size();
00504     int i;
00505 
00506     for( i = pos; i < NUM_ELEMS; ++i )
00507     {
00508         switch( m_elems[i].type )
00509         {
00510         case ET_WGT:
00511             curr_wgt = &m_widgets[ m_elems[ i ].pos ];
00512 
00513             curr_wgt->widget->m_x = cursor_x;
00514 
00515             //We have to give createRect() the bottom left corner
00516             curr_wgt->widget->m_y = cursor_y - curr_wgt->widget->m_height;
00517 
00518             if( !(curr_wgt->widget->createRect()) ) return false;
00519 
00520             if( i + 1 < NUM_ELEMS )
00521             {
00522                 switch( m_elems[ i + 1 ].type )
00523                 {
00524                     case ET_WGT:
00525                         cursor_x += ( curr_wgt->widget->m_width -
00526                             m_widgets[ m_elems[ i + 1 ].pos ].widget->
00527                             m_width ) / 2;
00528                         break;
00529 
00530                     case ET_SWITCH:
00531                         cursor_x += ( curr_wgt->widget->m_width -
00532                             calcLineWidth( i + 2 ) ) / 2;
00533                         break;
00534 
00535                     case ET_BREAK:
00536                         break;
00537                 }
00538 
00539                 cursor_y -= curr_wgt->widget->m_height;
00540             }
00541             break;
00542 
00543         case ET_BREAK:
00544             x += calcColumnWidth( pos );
00545             pos = i;
00546             return true;
00547 
00548         case ET_SWITCH:
00549             ++i;
00550             layoutLine( cursor_x, cursor_y, i );
00551             break;
00552         }
00553     }
00554 
00555     pos = i;
00556     return true;
00557 }
00558 
00559 
00565 int WidgetManager::getLineWidth( int& pos )
00566 {
00567     const int NUM_ELEMS = (int)m_elems.size();
00568     int width = 0;
00569 
00570     for( ; pos < NUM_ELEMS; ++pos )
00571     {
00572         switch( m_elems[ pos ].type)
00573         {
00574         case ET_WGT:
00575             width += m_widgets[ m_elems[ pos ].pos ].widget->m_width;
00576             break;
00577 
00578         case ET_BREAK:
00579             return width;
00580 
00581         case ET_SWITCH:
00582             ++pos;
00583             width += getColumnWidth( pos );
00584             break;
00585         }
00586     }
00587 
00588     return width;
00589 }
00590 
00596 int WidgetManager::getLineHeight( int& pos )
00597 {
00598     const int NUM_ELEMS = (int)m_elems.size();
00599     int height = 0;
00600     int column_height;
00601 
00602     for( ; pos < NUM_ELEMS; ++pos )
00603     {
00604         switch( m_elems[ pos ].type)
00605         {
00606         case ET_WGT:
00607             if( m_widgets[ m_elems[ pos ].pos ].widget->m_height > height )
00608             {
00609                 height = m_widgets[ m_elems[ pos ].pos ].widget->m_height;
00610             }
00611             break;
00612 
00613         case ET_BREAK:
00614             return height;
00615 
00616         case ET_SWITCH:
00617             ++pos;
00618             column_height = getColumnHeight( pos );
00619             if( column_height > height ) height = column_height;
00620             break;
00621         }
00622     }
00623 
00624     return height;
00625 }
00626 
00632 int WidgetManager::getColumnWidth( int& pos )
00633 {
00634     const int NUM_ELEMS = (int)m_elems.size();
00635     int width = 0;
00636     int line_width;
00637 
00638     for( ; pos < NUM_ELEMS; ++pos )
00639     {
00640         switch( m_elems[ pos ].type )
00641         {
00642             case ET_WGT:
00643             if( m_widgets[ m_elems[ pos ].pos ].widget->m_width > width )
00644             {
00645                 width = m_widgets[ m_elems[ pos ].pos ].widget->m_width;
00646             }
00647             break;
00648 
00649             case ET_BREAK:
00650                 return width;
00651 
00652             case ET_SWITCH:
00653                 ++pos;
00654                 line_width = getLineWidth( pos );
00655                 if( line_width > width ) width = line_width;
00656                 break;
00657 
00658         }
00659     }
00660 
00661     return width;
00662 }
00663 
00669 int WidgetManager::getColumnHeight( int& pos )
00670 {
00671     const int NUM_ELEMS = (int)m_elems.size();
00672     int height = 0;
00673 
00674     for( ; pos < NUM_ELEMS; ++pos )
00675     {
00676         switch( m_elems[ pos ].type)
00677         {
00678         case ET_WGT:
00679             height += m_widgets[ m_elems[ pos ].pos ].widget->m_height;
00680             break;
00681 
00682         case ET_BREAK:
00683             return height;
00684 
00685         case ET_SWITCH:
00686             ++pos;
00687             height += getLineHeight( pos );
00688             break;
00689         }
00690     }
00691 
00692     return height;
00693 }
00694 
00699 int WidgetManager::calcLineWidth( const int POS )
00700 {
00701     const int NUM_ELEMS = (int)m_elems.size();
00702     int width = 0;
00703 
00704     for( int i = POS; i < NUM_ELEMS; ++i )
00705     {
00706         switch( m_elems[i].type)
00707         {
00708         case ET_WGT:
00709             width += m_widgets[ m_elems[ i ].pos ].widget->m_width;
00710             break;
00711 
00712         case ET_BREAK:
00713             return width;
00714 
00715         case ET_SWITCH:
00716             ++i;
00717             width += getColumnWidth( i );
00718             break;
00719         }
00720     }
00721 
00722     return width;
00723 }
00724 
00729 int WidgetManager::calcLineHeight( const int POS )
00730 {
00731     const int NUM_ELEMS = (int)m_elems.size();
00732     int height = 0;
00733     int column_height;
00734 
00735     for( int i = POS; i < NUM_ELEMS; ++i )
00736     {
00737         switch( m_elems[i].type)
00738         {
00739         case ET_WGT:
00740             if( m_widgets[ m_elems[ i ].pos ].widget->m_height > height )
00741             {
00742                 height = m_widgets[ m_elems[ i ].pos ].widget->m_height;
00743             }
00744             break;
00745 
00746         case ET_BREAK:
00747             return height;
00748 
00749         case ET_SWITCH:
00750             ++i;
00751             column_height = getColumnHeight( i );
00752             if( column_height > height ) height = column_height;
00753             break;
00754         }
00755     }
00756 
00757     return height;
00758 }
00759 
00764 int WidgetManager::calcColumnWidth( const int POS )
00765 {
00766     const int NUM_ELEMS = (int)m_elems.size();
00767     int width = 0;
00768     int line_width;
00769 
00770     for( int i = POS; i < NUM_ELEMS; ++i )
00771     {
00772         switch( m_elems[ i ].type )
00773         {
00774             case ET_WGT:
00775             if( m_widgets[ m_elems[ i ].pos ].widget->m_width > width )
00776             {
00777                 width = m_widgets[ m_elems[ i ].pos ].widget->m_width;
00778             }
00779             break;
00780 
00781             case ET_BREAK:
00782                 return width;
00783 
00784             case ET_SWITCH:
00785                 ++i;
00786                 line_width = getLineWidth( i );
00787                 if( line_width > width ) width = line_width;
00788                 break;
00789 
00790         }
00791     }
00792 
00793     return width;
00794 }
00795 
00800 int WidgetManager::calcColumnHeight( const int POS )
00801 {
00802     const int NUM_ELEMS = (int)m_elems.size();
00803     int height = 0;
00804 
00805     for( int i = POS; i < NUM_ELEMS; ++i )
00806     {
00807         switch( m_elems[i].type)
00808         {
00809         case ET_WGT:
00810             height += m_widgets[ m_elems[ i ].pos ].widget->m_height;
00811             break;
00812 
00813         case ET_BREAK:
00814             return height;
00815 
00816         case ET_SWITCH:
00817             ++i;
00818             height += getLineHeight( i );
00819             break;
00820         }
00821     }
00822 
00823     return height;
00824 }
00825 
00826 //-----------------------------------------------------------------------------
00827 int WidgetManager::calcLineX( const int POS )
00828 {
00829     int width = 0;
00830     WidgetID* curr_wgt = 0;
00831 
00832     const int NUM_ELEMS = m_elems.size();
00833 
00834     for( int i = POS; i < NUM_ELEMS; ++i )
00835     {
00836         switch( m_elems[ i ].type )
00837         {
00838         case ET_WGT:
00839             curr_wgt = &m_widgets[ m_elems[ i ].pos ];
00840 
00841             width += curr_wgt->widget->m_width;
00842             break;
00843 
00844         case ET_SWITCH:
00845             break;
00846 
00847         case ET_BREAK:
00848             return width;
00849         }
00850     }
00851 
00852     return width;
00853 }
00854 
00855 //-----------------------------------------------------------------------------
00856 int WidgetManager::calcColumnX( const int POS )
00857 {
00858     if( POS >= (int)m_elems.size() ) return 0;
00859 
00860     WidgetID* curr_wgt = &m_widgets[ m_elems[ POS ].pos ];
00861 
00862     if( m_elems[ POS ].type == ET_WGT )
00863     {
00864         return ( calcColumnWidth( POS ) - curr_wgt->widget->m_width ) / 2;
00865     }
00866 
00867     return 0;
00868 }
00869 
00873 int WidgetManager::calcWidth()
00874 {
00875     const int NUM_ELEMS = (int)m_elems.size();
00876     int width = 0;
00877     int line_width;
00878 
00879     for( int i = 0; i < NUM_ELEMS; ++i )
00880     {
00881         line_width = getLineWidth( i );
00882         if( line_width > width ) width = line_width;
00883     }
00884 
00885     return width;
00886 }
00887 
00891 int WidgetManager::calcHeight()
00892 {
00893     const int NUM_ELEMS = (int)m_elems.size();
00894     int height = 0;
00895 
00896     for( int i = 0; i < NUM_ELEMS; ++i )
00897     {
00898         height += getLineHeight( i );
00899     }
00900 
00901     return height;
00902 }
00903 
00904 //-----------------------------------------------------------------------------
00905 void WidgetManager::setSelectedWgt(const int TOKEN)
00906 {
00907     const int ID = findId(TOKEN);
00908     if( ID != WGT_NONE )
00909     {
00910         setSelectedWgtToken( TOKEN );
00911     }
00912     else std::cerr << "WARNING: tried to select unnamed widget with " <<
00913         "token " << TOKEN << '\n';
00914 }
00915 
00916 //-----------------------------------------------------------------------------
00917 bool WidgetManager::addTitleWgt
00918 (
00919     const int TOKEN,
00920     const int MIN_WIDTH,
00921     const int MIN_HEIGHT,
00922     const std::string TEXT
00923 )
00924 {
00925     if( !( addWgt( TOKEN, MIN_WIDTH, MIN_HEIGHT ))) return false;
00926 
00927     showWgtRect( TOKEN );
00928     setWgtTextSize( TOKEN, WGT_FNT_LRG );
00929     showWgtText( TOKEN );
00930     setWgtText( TOKEN, TEXT );
00931     setWgtRoundCorners( TOKEN, WGT_AREA_ALL );
00932     setWgtCornerRadius( TOKEN, 20 );
00933 
00934     return true;
00935 }
00936 
00937 //-----------------------------------------------------------------------------
00938 bool WidgetManager::addTextWgt
00939 (
00940     const int TOKEN,
00941     const int MIN_WIDTH,
00942     const int MIN_HEIGHT,
00943     const std::string TEXT
00944 )
00945 {
00946     if( !( addWgt( TOKEN, MIN_WIDTH, MIN_HEIGHT ))) return false;
00947 
00948     showWgtRect( TOKEN );
00949     setWgtRoundCorners( TOKEN, WGT_AREA_ALL );
00950     setWgtCornerRadius( TOKEN, 20 );
00951     showWgtText( TOKEN );
00952     setWgtText( TOKEN, TEXT );
00953 
00954     return true;
00955 }
00956 
00957 //-----------------------------------------------------------------------------
00958 bool WidgetManager::addTextButtonWgt
00959 (
00960     const int TOKEN,
00961     const int MIN_WIDTH,
00962     const int MIN_HEIGHT,
00963     const std::string TEXT
00964 )
00965 {
00966     if( !( addWgt( TOKEN, MIN_WIDTH, MIN_HEIGHT ))) return false;
00967 
00968     showWgtRect( TOKEN );
00969     setWgtRoundCorners( TOKEN, WGT_AREA_ALL );
00970     setWgtCornerRadius( TOKEN, 20 );
00971     showWgtText( TOKEN );
00972     setWgtText( TOKEN, TEXT );
00973     activateWgt( TOKEN );
00974 
00975     return true;
00976 }
00977 
00978 //-----------------------------------------------------------------------------
00979 bool WidgetManager::addImgWgt
00980 (
00981     const int TOKEN,
00982     const int MIN_WIDTH,
00983     const int MIN_HEIGHT,
00984     const int IMG
00985 )
00986 {
00987     if( !( addWgt( TOKEN, MIN_WIDTH, MIN_HEIGHT ))) return false;
00988 
00989     setWgtColor( TOKEN, WGT_WHITE );
00990     showWgtRect( TOKEN );
00991     setWgtBorderPercentage( TOKEN, 5 );
00992     setWgtBorderColor( TOKEN, WGT_BLACK );
00993     showWgtBorder( TOKEN );
00994     setWgtTexture( TOKEN, IMG );
00995     showWgtTexture( TOKEN );
00996 
00997     return true;
00998 }
00999 
01000 //-----------------------------------------------------------------------------
01001 bool WidgetManager::addImgWgt
01002 (
01003     const int TOKEN,
01004     const int MIN_WIDTH,
01005     const int MIN_HEIGHT,
01006     const char* FILENAME
01007 )
01008 {
01009     if( !( addWgt( TOKEN, MIN_WIDTH, MIN_HEIGHT ))) return false;
01010 
01011     setWgtColor( TOKEN, WGT_WHITE );
01012     showWgtRect( TOKEN );
01013     setWgtBorderPercentage( TOKEN, 5 );
01014     setWgtBorderColor( TOKEN, WGT_BLACK );
01015     showWgtBorder( TOKEN );
01016     setWgtTexture( TOKEN, FILENAME );
01017     showWgtTexture( TOKEN );
01018 
01019     return true;
01020 }
01021 
01022 //-----------------------------------------------------------------------------
01023 bool WidgetManager::addImgButtonWgt
01024 (
01025     const int TOKEN,
01026     const int MIN_WIDTH,
01027     const int MIN_HEIGHT,
01028     const int IMG
01029 )
01030 {
01031     if( !( addWgt( TOKEN, MIN_WIDTH, MIN_HEIGHT ))) return false;
01032 
01033     setWgtColor( TOKEN, WGT_GRAY );
01034     showWgtRect( TOKEN );
01035     setWgtRoundCorners( TOKEN, WGT_AREA_ALL );
01036     setWgtCornerRadius( TOKEN, 20 );
01037     setWgtTexture( TOKEN, IMG );
01038     showWgtTexture( TOKEN );
01039     activateWgt( TOKEN );
01040 
01041     return true;
01042 }
01043 
01044 //-----------------------------------------------------------------------------
01045 bool WidgetManager::addImgButtonWgt
01046 (
01047     const int TOKEN,
01048     const int MIN_WIDTH,
01049     const int MIN_HEIGHT,
01050     const char* FILENAME
01051 )
01052 {
01053     if( !( addWgt( TOKEN, MIN_WIDTH, MIN_HEIGHT ))) return false;
01054 
01055     setWgtColor( TOKEN, WGT_GRAY );
01056     showWgtRect( TOKEN );
01057     setWgtRoundCorners( TOKEN, WGT_AREA_ALL );
01058     setWgtCornerRadius( TOKEN, 20 );
01059     setWgtTexture( TOKEN, FILENAME );
01060     showWgtTexture( TOKEN );
01061     activateWgt( TOKEN );
01062 
01063     return true;
01064 }
01065 
01066 //-----------------------------------------------------------------------------
01067 void WidgetManager::setInitialActivationState( const bool ACTIVE)
01068 {
01069     m_default_active = ACTIVE;
01070 }
01071 
01072 //-----------------------------------------------------------------------------
01073 void WidgetManager::setInitialRectState
01074 (
01075     const bool SHOW,
01076     const WidgetArea ROUND_CORNERS,
01077     const int RADIUS,
01078     const GLfloat* const COLOR
01079 )
01080 {
01081     m_default_show_rect = SHOW;
01082     m_default_rect_round_corners = ROUND_CORNERS;
01083     m_default_rect_radius = RADIUS;
01084     m_default_rect_color = COLOR;
01085 }
01086 
01087 //-----------------------------------------------------------------------------
01088 void WidgetManager::setInitialBorderState
01089 (
01090     const bool SHOW,
01091     const int PERCENTAGE,
01092     const GLfloat* const COLOR
01093 )
01094 {
01095     m_default_show_border = SHOW;
01096     m_default_border_percentage = PERCENTAGE * 0.01f;
01097     m_default_border_color = COLOR;
01098 }
01099 
01100 //-----------------------------------------------------------------------------
01101 void WidgetManager::setInitialTextureState
01102 (
01103     const bool SHOW,
01104     const int TEXTURE
01105 )
01106 {
01107     m_default_show_texture = SHOW;
01108     m_default_texture = TEXTURE;
01109 }
01110 
01111 //-----------------------------------------------------------------------------
01112 void WidgetManager::setInitialTextState
01113 (
01114     const bool SHOW,
01115     const std::string TEXT,
01116     const WidgetFontSize SIZE,
01117     const WidgetFont FONT,
01118     const GLfloat* const COLOR,
01119     const bool RESIZE
01120 )
01121 {
01122     m_default_show_text = SHOW;
01123     m_default_text = TEXT;
01124     m_default_text_size = SIZE;
01125     m_default_font = FONT;
01126     m_default_text_color = COLOR;
01127     m_default_resize_to_text = RESIZE;
01128 }
01129 
01130 //-----------------------------------------------------------------------------
01131 void WidgetManager::setInitialScrollState
01132 (
01133     const bool ENABLE,
01134     const WidgetScrollPos X_POS,
01135     const WidgetScrollPos Y_POS,
01136     const int X_SPEED,
01137     const int Y_SPEED
01138 )
01139 {
01140     m_default_enable_scroll = ENABLE;
01141     m_default_scroll_preset_x = X_POS;
01142     m_default_scroll_preset_y = Y_POS;
01143     m_default_scroll_x_speed = X_SPEED;
01144     m_default_scroll_y_speed = Y_SPEED;
01145 }
01146 
01147 //-----------------------------------------------------------------------------
01148 void WidgetManager::setInitialRotationState
01149 (
01150         const bool ENABLE,
01151         const float ANGLE,
01152         const int SPEED
01153 )
01154 {
01155     m_default_enable_rotation = ENABLE;
01156     m_default_rotation_angle = ANGLE;
01157     m_default_rotation_speed = SPEED;
01158 }
01159 
01160 //-----------------------------------------------------------------------------
01161 void WidgetManager::setInitialTrackState
01162 (
01163     const bool SHOW,
01164     const int TRACK
01165 )
01166 {
01167     m_default_show_track = SHOW;
01168     m_default_track_num = TRACK;
01169 }
01170 
01171 //-----------------------------------------------------------------------------
01172 void WidgetManager::restoreDefaultStates()
01173 {
01174     //FIXME: maybe instead of 'default' these variables should be 'initial'
01175     m_default_active = false;
01176     m_default_show_rect = false;
01177     m_default_rect_color = WGT_TRANS_BLACK;
01178     m_default_rect_round_corners = WGT_AREA_NONE;
01179     m_default_rect_radius = 1;
01180     m_default_show_border = false;
01181     m_default_border_percentage = 0.0;
01182     m_default_border_color = WGT_TRANS_WHITE;
01183     m_default_show_texture = false;
01184     m_default_texture = 0;
01185     m_default_show_text = false;
01186     m_default_text = "";
01187     m_default_text_size = WGT_FNT_MED;
01188     m_default_font = WGT_FONT_GUI;
01189     m_default_text_color = WGT_WHITE;
01190     m_default_resize_to_text = true;
01191     m_default_enable_scroll = false;
01192     m_default_scroll_preset_x = WGT_SCROLL_CENTER;
01193     m_default_scroll_preset_y = WGT_SCROLL_CENTER;
01194     m_default_scroll_x_speed = 0;
01195     m_default_scroll_y_speed = 0;
01196     m_default_enable_rotation = false;
01197     m_default_rotation_angle = 0.0f;
01198     m_default_rotation_speed = 0;
01199     m_default_show_track = false;
01200     m_default_track_num = -1;
01201 }
01202 
01203 //-----------------------------------------------------------------------------
01204 void WidgetManager::activateWgt(const int TOKEN)
01205 {
01206     const int ID = findId(TOKEN);
01207     if( ID != WGT_NONE ) m_widgets[ID].active = true;
01208     else
01209     {
01210         std::cerr << "WARNING: tried to activate unnamed widget with token "
01211             << TOKEN << '\n';
01212     }
01213 }
01214 
01215 //-----------------------------------------------------------------------------
01216 void WidgetManager::deactivateWgt(const int TOKEN)
01217 {
01218     const int ID = findId(TOKEN);
01219     if( ID != WGT_NONE ) m_widgets[ID].active = false;
01220     else
01221     {
01222         std::cerr << "WARNING: tried to deactivate unnamed widget with " <<
01223             TOKEN << '\n';
01224     }
01225 }
01226 
01227 //-----------------------------------------------------------------------------
01228 void WidgetManager::setWgtColor(const int TOKEN, const GLfloat *COLOR)
01229 {
01230     const int ID = findId(TOKEN);
01231     if( ID != WGT_NONE ) m_widgets[ID].widget->m_rect_color = COLOR;
01232     else
01233     {
01234         std::cerr << "WARNING: tried to change the rect color of an " <<
01235             "unnamed widget with token " << TOKEN << '\n';
01236     }
01237 }
01238 
01239 //-----------------------------------------------------------------------------
01240 void WidgetManager::setWgtRoundCorners(const int TOKEN, const WidgetArea CORNERS)
01241 {
01242     const int ID = findId(TOKEN);
01243     if( ID != WGT_NONE ) m_widgets[ID].widget->m_round_corners = CORNERS;
01244     else
01245     {
01246         std::cerr << "WARNING: tried to change the round corners of an " <<
01247             "unnamed widget with token " << TOKEN << '\n';
01248     }
01249 }
01250 
01251 //-----------------------------------------------------------------------------
01252 void WidgetManager::setWgtCornerRadius(const int TOKEN, const int RADIUS)
01253 {
01254     if( RADIUS > 50 )
01255     {
01256         std::cerr << "WARNING: tried to set the corner's radius " <<
01257             "percentage of a widget with token " << TOKEN << " to " <<
01258             "something bigger than 50% \n";
01259         return;
01260     }
01261     else if( RADIUS < 1 )
01262     {
01263         std::cerr << "WARNING: tried to set the corner's radius " <<
01264             "percentage of a widget with token " << TOKEN << " to " <<
01265             "something smaller than 1% \n";
01266         return;
01267     }
01268 
01269     const int ID = findId(TOKEN);
01270     if( ID != WGT_NONE ) m_widgets[ID].min_radius = RADIUS;
01271     else
01272     {
01273         std::cerr << "WARNING: tried to change the corner radius of an " <<
01274             "unnamed widget with token " << TOKEN << '\n';
01275     }
01276 }
01277 
01278 //-----------------------------------------------------------------------------
01279 void WidgetManager::showWgtRect(const int TOKEN)
01280 {
01281     const int ID = findId(TOKEN);
01282     if( ID != WGT_NONE ) m_widgets[ID].widget->m_enable_rect = true;
01283     else
01284     {
01285         std::cerr << "WARNING: tried to show the rect of an unnamed widget "
01286             << "with token " << TOKEN << '\n';
01287     }
01288 }
01289 
01290 //-----------------------------------------------------------------------------
01291 void WidgetManager::hideWgtRect(const int TOKEN)
01292 {
01293     const int ID = findId(TOKEN);
01294     if( ID != WGT_NONE ) m_widgets[ID].widget->m_enable_rect = false;
01295     else
01296     {
01297         std::cerr << "WARNING: tried to hide the rect of an unnamed widget "
01298             << "with token " << TOKEN << '\n';
01299     }
01300 }
01301 
01302 //-----------------------------------------------------------------------------
01303 void WidgetManager::setWgtBorderColor(const int TOKEN, const GLfloat* const COLOR)
01304 {
01305     const int ID = findId(TOKEN);
01306     if( ID != WGT_NONE ) m_widgets[ID].widget->m_border_color = COLOR;
01307     else
01308     {
01309         std::cerr << "WARNING: tried to change the border color of an " <<
01310             "unnamed widget with token " << TOKEN << '\n';
01311     }
01312 }
01313 
01314 //-----------------------------------------------------------------------------
01315 void WidgetManager::setWgtBorderPercentage(const int TOKEN, const int PERCENTAGE)
01316 {
01317     if( PERCENTAGE > 100 )
01318     {
01319         std::cerr << "WARNING: tried to set the border's percentage of " <<
01320             "widget with token " << TOKEN << " to something bigger than " <<
01321             "100% \n";
01322         return;
01323     }
01324     else if( PERCENTAGE < 1 )
01325     {
01326         std::cerr << "WARNING: tried to set the border's percentage of " <<
01327             "widget with token " << TOKEN << " to something smaller than " <<
01328             "1% \n";
01329         return;
01330     }
01331 
01332     const int ID = findId(TOKEN);
01333     if( ID != WGT_NONE ) m_widgets[ID].widget->m_border_percentage = PERCENTAGE * 0.01f;
01334     else
01335     {
01336         std::cerr << "WARNING: tried to change the rect color of an " <<
01337             "unnamed widget with token " << TOKEN << '\n';
01338     }
01339 }
01340 
01341 //-----------------------------------------------------------------------------
01342 void WidgetManager::showWgtBorder(const int TOKEN)
01343 {
01344     const int ID = findId(TOKEN);
01345     if( ID != WGT_NONE ) m_widgets[ID].widget->m_enable_border = true;
01346     else
01347     {
01348         std::cerr << "WARNING: tried to show the border of an unnamed widget "
01349             << "with token " << TOKEN << '\n';
01350     }
01351 }
01352 
01353 //-----------------------------------------------------------------------------
01354 void WidgetManager::hideWgtBorder(const int TOKEN)
01355 {
01356     const int ID = findId(TOKEN);
01357     if( ID != WGT_NONE ) m_widgets[ID].widget->m_enable_border = false;
01358     else
01359     {
01360         std::cerr << "WARNING: tried to hide the border of an unnamed widget "
01361             << "with token " << TOKEN << '\n';
01362     }
01363 }
01364 
01365 
01366 //-----------------------------------------------------------------------------
01367 void WidgetManager::setWgtTexture(const int TOKEN, const int TEXTURE)
01368 {
01369     const int ID = findId(TOKEN);
01370     if( ID != WGT_NONE ) m_widgets[ID].widget->m_texture = TEXTURE;
01371     else
01372     {
01373         std::cerr << "WARNING: tried to set the texture of an unnamed " <<
01374             "widget with token " << TOKEN << '\n';
01375     }
01376 }
01377 
01378 //-----------------------------------------------------------------------------
01379 void WidgetManager::setWgtTexture(const int TOKEN, const char* FILENAME, 
01380                                   const bool is_full_path)
01381 {
01382     const int ID = findId(TOKEN);
01383     if( ID != WGT_NONE ) m_widgets[ID].widget->setTexture( FILENAME, is_full_path );
01384     else
01385     {
01386         std::cerr << "WARNING: tried to set the texture of an unnamed " <<
01387             "widget with token " << TOKEN << '\n';
01388     }
01389 }
01390 
01391 //-----------------------------------------------------------------------------
01392 void WidgetManager::showWgtTexture(const int TOKEN)
01393 {
01394     const int ID = findId(TOKEN);
01395     if( ID != WGT_NONE ) m_widgets[ID].widget->m_enable_texture = true;
01396     else
01397     {
01398         std::cerr << "WARNING: tried to show the texture of an unnamed " <<
01399             "widget with token " << TOKEN << '\n';
01400     }
01401 }
01402 
01403 //-----------------------------------------------------------------------------
01404 void WidgetManager::hideWgtTexture(const int TOKEN)
01405 {
01406     const int ID = findId(TOKEN);
01407     if( ID != WGT_NONE ) m_widgets[ID].widget->m_enable_texture = false;
01408     else
01409     {
01410         std::cerr << "WARNING: tried to hide the texture of an unnamed " <<
01411             "widget with token " << TOKEN << '\n';
01412     }
01413 }
01414 
01415 //-----------------------------------------------------------------------------
01416 void WidgetManager::setWgtText( const int TOKEN, const char* TEXT )
01417 {
01418     const int ID = findId(TOKEN);
01419     if( ID != WGT_NONE )
01420     {
01421         m_widgets[ID].widget->m_text = TEXT;
01422 
01423         //Reset the scroll position, because it will be the wrong value if
01424         //new text has a different size
01425         m_widgets[ID].widget->m_scroll_pos_x = (float)m_widgets[ID].last_preset_scroll_x;
01426         m_widgets[ID].widget->m_scroll_pos_y = (float)m_widgets[ID].last_preset_scroll_y;
01427     }
01428     else
01429     {
01430         std::cerr << "WARNING: tried to set text to an unnamed widget " <<
01431             "with token " << TOKEN << '\n';
01432     }
01433 }
01434 
01435 //-----------------------------------------------------------------------------
01436 void WidgetManager::setWgtText( const int TOKEN, const std::string TEXT )
01437 {
01438     setWgtText( TOKEN, TEXT.c_str());
01439 }
01440 
01441 //-----------------------------------------------------------------------------
01442 void WidgetManager::setWgtTextSize( const int TOKEN, const WidgetFontSize SIZE)
01443 {
01444     const int ID = findId(TOKEN);
01445     if( ID != WGT_NONE ) m_widgets[ID].widget->m_text_size = SIZE;
01446     else
01447     {
01448         std::cerr << "WARNING: tried to set the text size of an unnamed " <<
01449             "widget with token " << TOKEN << '\n';
01450     }
01451 }
01452 
01453 //-----------------------------------------------------------------------------
01454 void WidgetManager::setWgtFont( const int TOKEN, const WidgetFont FONT )
01455 {
01456     const int ID = findId(TOKEN);
01457     if( ID != WGT_NONE ) m_widgets[ID].widget->setFont( FONT );
01458     else
01459     {
01460         std::cerr << "WARNING: tried to set the font of an unnamed " <<
01461             "widget with token " << TOKEN << '\n';
01462     }
01463 }
01464 
01465 //-----------------------------------------------------------------------------
01466 void WidgetManager::setWgtTextColor( const int TOKEN, const GLfloat* const COLOR)
01467 {
01468     const int ID = findId(TOKEN);
01469     if( ID != WGT_NONE ) m_widgets[ID].widget->m_text_color = COLOR;
01470     else
01471     {
01472         std::cerr << "WARNING: tried to set the text color of an unnamed " <<
01473             "widget with token " << TOKEN << '\n';
01474     }
01475 }
01476 
01477 //-----------------------------------------------------------------------------
01478 void WidgetManager::setWgtResizeToText( const int TOKEN, const bool RESIZE )
01479 {
01480     const int ID = findId(TOKEN);
01481     if( ID != WGT_NONE ) m_widgets[ID].resize_to_text = RESIZE;
01482     else
01483     {
01484         std::cerr << "WARNING: tried to set the resize to text value of an " <<
01485             "unnamed widget with token " << TOKEN << '\n';
01486     }
01487 }
01488 
01489 //-----------------------------------------------------------------------------
01490 void WidgetManager::showWgtText( const int TOKEN )
01491 {
01492     const int ID = findId(TOKEN);
01493     if( ID != WGT_NONE ) m_widgets[ID].widget->m_enable_text = true;
01494     else
01495     {
01496         std::cerr << "WARNING: tried to show the text of an unnamed " <<
01497             "widget with token " << TOKEN << '\n';
01498     }
01499 }
01500 
01501 //-----------------------------------------------------------------------------
01502 void WidgetManager::hideWgtText( const int TOKEN )
01503 {
01504     const int ID = findId(TOKEN);
01505     if( ID != WGT_NONE ) m_widgets[ID].widget->m_enable_text = false;
01506     else
01507     {
01508         std::cerr << "WARNING: tried to hide the text of an unnamed widget " <<
01509             "with token " << TOKEN << '\n';
01510     }
01511 }
01512 
01513 //-----------------------------------------------------------------------------
01514 void WidgetManager::enableWgtScroll( const int TOKEN )
01515 {
01516     const int ID = findId(TOKEN);
01517     if( ID != WGT_NONE ) m_widgets[ID].widget->m_enable_scroll = true;
01518     else
01519     {
01520         std::cerr << "WARNING: tried to enable scrolling of an unnamed " <<
01521             "widget with token " << TOKEN << '\n';
01522     }
01523 }
01524 
01525 //-----------------------------------------------------------------------------
01526 void WidgetManager::disableWgtScroll( const int TOKEN )
01527 {
01528     const int ID = findId(TOKEN);
01529     if( ID != WGT_NONE ) m_widgets[ID].widget->m_enable_scroll = false;
01530     else
01531     {
01532         std::cerr << "WARNING: tried to disable scrolling of an unnamed " <<
01533             "widget with token " << TOKEN << '\n';
01534     }
01535 }
01536 
01537 //-----------------------------------------------------------------------------
01538 void WidgetManager::setWgtXScrollPos
01539 (
01540     const int TOKEN,
01541     const WidgetScrollPos POS
01542 )
01543 {
01544     if( POS == WGT_SCROLL_START_TOP || POS == WGT_SCROLL_START_BOTTOM ||
01545         POS == WGT_SCROLL_END_TOP || POS == WGT_SCROLL_END_BOTTOM )
01546     {
01547         std::cerr << "WARNING: tried to set the X scroll position to a " <<
01548             "position for the Y axis, on widget with token " << TOKEN <<
01549             '\n';
01550         return;
01551     }
01552 
01553     const int ID = findId(TOKEN);
01554     if( ID != WGT_NONE )
01555     {
01556         m_widgets[ID].widget->m_scroll_pos_x = (float)POS;
01557         m_widgets[ID].last_preset_scroll_x = POS;
01558     }
01559     else
01560     {
01561         std::cerr << "WARNING: tried to set the X scroll position of an " <<
01562             "unnamed widget with token " << TOKEN << '\n';
01563     }
01564 }
01565 
01566 //-----------------------------------------------------------------------------
01567 void WidgetManager::setWgtYScrollPos
01568 (
01569     const int TOKEN,
01570     const WidgetScrollPos POS
01571 )
01572 {
01573     if( POS == WGT_SCROLL_START_LEFT || POS == WGT_SCROLL_START_RIGHT ||
01574         POS == WGT_SCROLL_END_LEFT || POS == WGT_SCROLL_END_RIGHT )
01575     {
01576         std::cerr << "WARNING: tried to set the Y scroll position to a " <<
01577             "position for the X axis, on widget with token " << TOKEN <<
01578             '\n';
01579         return;
01580     }
01581 
01582     const int ID = findId(TOKEN);
01583     if( ID != WGT_NONE )
01584     {
01585         m_widgets[ID].widget->m_scroll_pos_y = (float)POS;
01586         m_widgets[ID].last_preset_scroll_y = POS;
01587     }
01588     else
01589     {
01590         std::cerr << "WARNING: tried to set the Y scroll position of an " <<
01591             "unnamed widget with token " << TOKEN << '\n';
01592     }
01593 }
01594 
01595 //-----------------------------------------------------------------------------
01596 void WidgetManager::setWgtXScrollSpeed( const int TOKEN, const int SPEED )
01597 {
01598     const int ID = findId(TOKEN);
01599     if( ID != WGT_NONE ) m_widgets[ID].widget->m_scroll_speed_x = SPEED;
01600     else
01601     {
01602         std::cerr << "WARNING: tried to set the X scroll speed of an " <<
01603             "unnamed widget with token " << TOKEN << '\n';
01604     }
01605 }
01606 
01607 //-----------------------------------------------------------------------------
01608 void WidgetManager::setWgtYScrollSpeed( const int TOKEN, const int SPEED )
01609 {
01610     const int ID = findId(TOKEN);
01611     if( ID != WGT_NONE ) m_widgets[ID].widget->m_scroll_speed_y = SPEED;
01612     else
01613     {
01614         std::cerr << "WARNING: tried to set the Y scroll speed of an " <<
01615             "unnamed widget with token " << TOKEN << '\n';
01616     }
01617 }
01618 
01619 //-----------------------------------------------------------------------------
01620 void WidgetManager::enableWgtRotation( const int TOKEN )
01621 {
01622     const int ID = findId(TOKEN);
01623     if( ID != WGT_NONE ) m_widgets[ID].widget->m_enable_rotation = true;
01624     else
01625     {
01626         std::cerr << "WARNING: tried to enable rotation of an unnamed " <<
01627             "widget with token " << TOKEN << '\n';
01628     }
01629 }
01630 
01631 //-----------------------------------------------------------------------------
01632 void WidgetManager::disableWgtRotation( const int TOKEN )
01633 {
01634     const int ID = findId(TOKEN);
01635     if( ID != WGT_NONE ) m_widgets[ID].widget->m_enable_rotation = false;
01636     else
01637     {
01638         std::cerr << "WARNING: tried to disable rotation of an unnamed " <<
01639             "widget with token " << TOKEN << '\n';
01640     }
01641 }
01642 
01643 //-----------------------------------------------------------------------------
01644 void WidgetManager::setWgtRotationAngle( const int TOKEN, const float ANGLE )
01645 {
01646     const int ID = findId(TOKEN);
01647     if( ID != WGT_NONE ) m_widgets[ID].widget->m_rotation_angle = ANGLE;
01648     else
01649     {
01650         std::cerr << "WARNING: tried to set the rotation angle of an "
01651             "unnamed widget with token " << TOKEN << '\n';
01652     }
01653 }
01654 
01655 //-----------------------------------------------------------------------------
01656 void WidgetManager::setWgtRotationSpeed( const int TOKEN, const int SPEED )
01657 {
01658     const int ID = findId(TOKEN);
01659     if( ID != WGT_NONE ) m_widgets[ID].widget->m_rotation_speed = SPEED;
01660     else
01661     {
01662         std::cerr << "WARNING: tried to set the rotation speed of an "
01663             "unnamed widget with token " << TOKEN << '\n';
01664     }
01665 }
01666 
01667 //-----------------------------------------------------------------------------
01668 void WidgetManager::showWgtTrack( const int TOKEN )
01669 {
01670     const int ID = findId( TOKEN );
01671     if( ID != WGT_NONE ) m_widgets[ID].widget->m_enable_track = true;
01672     else
01673     {
01674         std::cerr << "WARNING: tried to show the track of an unnamed widget "
01675             << "with token " << TOKEN << '\n';
01676     }
01677 }
01678 
01679 //-----------------------------------------------------------------------------
01680 void WidgetManager::hideWgtTrack( const int TOKEN )
01681 {
01682     const int ID = findId( TOKEN );
01683     if( ID != WGT_NONE ) m_widgets[ID].widget->m_enable_track = false;
01684     else
01685     {
01686         std::cerr << "WARNING: tried to hide the track of an unnamed widget "
01687             << "with token " << TOKEN << '\n';
01688     }
01689 }
01690 
01691 //-----------------------------------------------------------------------------
01692 void WidgetManager::setWgtTrackNum( const int TOKEN, const int TRACK )
01693 {
01694     const int ID = findId(TOKEN);
01695     if( ID != WGT_NONE ) m_widgets[ID].widget->m_track_num = TRACK;
01696     else
01697     {
01698         std::cerr << "WARNING: tried to set the track number of an unnamed "
01699             << "widget with token " << TOKEN << '\n';
01700     }
01701 }
01702 
01705 void WidgetManager::pulseWgt(const int TOKEN) const
01706 {
01707     const int ID = findId(TOKEN);
01708     if( ID != WGT_NONE ) m_widgets[ID].widget->pulse();
01709     else
01710     {
01711         std::cerr << "WARNING: tried to pulse unnamed widget with token " <<
01712             TOKEN << '\n';
01713     }
01714 }
01715 
01716 //-----------------------------------------------------------------------------
01717 void WidgetManager::lightenWgtColor(const int TOKEN)
01718 {
01719     const int ID = findId(TOKEN);
01720     if( ID != WGT_NONE ) m_widgets[ID].widget->lightenColor();
01721     else
01722     {
01723         std::cerr << "WARNING: tried to lighten an unnamed widget with " <<
01724             "token " << TOKEN << '\n';
01725     }
01726 }
01727 
01728 //-----------------------------------------------------------------------------
01729 void WidgetManager::darkenWgtColor(const int TOKEN)
01730 {
01731     const int ID = findId(TOKEN);
01732     if( ID != WGT_NONE ) m_widgets[ID].widget->darkenColor();
01733     else
01734     {
01735         std::cerr << "WARNING: tried to darken an unnamed widget with " <<
01736             "token " << TOKEN << '\n';
01737     }
01738 }
01739 
01744 int WidgetManager::handlePointer(const int X, const int Y )
01745 {
01746     const int NUM_WGTS = (int)m_widgets.size();
01747     if( NUM_WGTS < 1 ) return WGT_NONE;
01748 
01749     //OpenGL provides a mechanism to select objects; simply 'draw' named
01750     //objects, and for each non-culled visible object a 'hit' will be saved
01751     //into a selection buffer. Objects are named by using OpenGL's name
01752     //stack. The information in each hit is the number of names in the name
01753     //stack, two hard-to-explain depth values that aren't used in this
01754     //function, and the contents of the name stack at the time of the hit.
01755 
01756     //This function loads 1 name into the stack (because if you pop an empty
01757     //stack you get an error), then uses glLoadName (which is a shortcut for
01758     //popping then pushing) to change the name. That means that each time a
01759     //hit is recorded, only the last drawn widget will be on the name stack.
01760 
01761     const int HIT_SIZE = 4; //1 Gluint for the number of names, 2 depth
01762                             //values, and 1 for the token of the widget.
01763     const int BUFFER_SIZE = HIT_SIZE * NUM_WGTS;
01764 
01765     GLuint* select_buffer = new GLuint[BUFFER_SIZE];
01766     glSelectBuffer(BUFFER_SIZE, select_buffer);
01767 
01768     glRenderMode(GL_SELECT);
01769 
01770     //Set the viewport to draw only what's under the mouse
01771     glMatrixMode(GL_PROJECTION);
01772     glPushMatrix();
01773     glLoadIdentity();
01774 
01775     GLint viewport[4];
01776     glGetIntegerv(GL_VIEWPORT,viewport);
01777     gluPickMatrix(X, Y, 1,1,viewport);
01778     glOrtho(0.0, user_config->m_width, 0.0, user_config->m_height, -1.0, 1.0);
01779 
01780     glMatrixMode(GL_MODELVIEW);
01781 
01782     glInitNames();
01783     glPushName(WGT_NONE);
01784 
01785     glPushMatrix();
01786 
01787     for( int i = 0; i < NUM_WGTS; ++i )
01788     {
01789         if(!(m_widgets[i].active)) continue;
01790 
01791         glLoadName( i );
01792 
01793         glPushMatrix();
01794         m_widgets[i].widget->applyTransformations();
01795         //In case this ever becomes a performance bottleneck:
01796         //the m_rect_list includes texture coordinates, which are not
01797         //needed for selection.
01798         glCallList( m_widgets[i].widget->m_rect_list );
01799         glPopMatrix();
01800     }
01801     glFlush();
01802     glPopMatrix();
01803 
01804     glMatrixMode(GL_PROJECTION);
01805     glPopMatrix();
01806     glMatrixMode(GL_MODELVIEW);
01807     glFlush();
01808 
01809     GLuint* position = select_buffer;
01810     const GLint NUM_HITS = glRenderMode(GL_RENDER);
01811 
01812     if( NUM_HITS > 0 )
01813     {
01814         float dist;
01815         float near_dist = 9999999.0f;
01816         int curr_wgt_id;
01817         int nearest_id = WGT_NONE;
01818         int wgt_x_center, wgt_y_center;
01819         for( int i = 0; i < NUM_HITS; ++i )
01820         {
01821             position += 3;
01822             curr_wgt_id = *position;
01823 
01824             wgt_x_center = m_widgets[curr_wgt_id].widget->m_x +
01825                 (m_widgets[i].widget->m_width / 2);
01826             wgt_y_center = m_widgets[curr_wgt_id].widget->m_y +
01827                 (m_widgets[i].widget->m_height / 2);
01828 
01829             //Check if it's the closest one to the mouse
01830             dist = (float)( abs(X - wgt_x_center) + abs(Y - wgt_y_center));
01831             if(dist < near_dist )
01832             {
01833                 near_dist = dist;
01834                 nearest_id = curr_wgt_id;
01835             }
01836 
01837             ++position;
01838         }
01839         delete[] select_buffer;
01840 
01841         if( m_widgets[nearest_id].token == m_selected_wgt_token )
01842         {
01843             return WGT_NONE;
01844         }
01845 
01846         setSelectedWgtToken( m_widgets[nearest_id].token );
01847         return m_selected_wgt_token;
01848     }
01849 
01850     delete[] select_buffer;
01851     return WGT_NONE;
01852 }
01853 
01857 int
01858 WidgetManager::handleLeft()
01859 {
01860     if( m_selected_wgt_token == WGT_NONE ) return WGT_NONE;
01861 
01862        return handleFinish(findLeftWidget(findId(m_selected_wgt_token)));
01863 }
01864 
01865     int
01866 WidgetManager::handleRight()
01867 {
01868     if( m_selected_wgt_token == WGT_NONE ) return WGT_NONE;
01869 
01870        return handleFinish(findRightWidget(findId(m_selected_wgt_token)));
01871 }
01872 
01873 int
01874 WidgetManager::handleUp()
01875 {
01876     if( m_selected_wgt_token == WGT_NONE ) return WGT_NONE;
01877 
01878        return handleFinish(findTopWidget(findId(m_selected_wgt_token)));
01879 }
01880 
01881 int
01882 WidgetManager::handleDown()
01883 {
01884     if( m_selected_wgt_token == WGT_NONE ) return WGT_NONE;
01885 
01886        return handleFinish(findBottomWidget(findId(m_selected_wgt_token)));
01887 }
01888 
01889 int
01890 WidgetManager::handleFinish(const int next_wgt)
01891 {
01892     if( next_wgt == WGT_NONE)
01893               return WGT_NONE;
01894 
01895     setSelectedWgtToken( m_widgets[next_wgt].token );
01896        return m_selected_wgt_token;
01897 }
01898 
01899 void
01900 WidgetManager::increaseScrollSpeed(const bool fast)
01901 {
01902     //FIXME: to increase the scroll speed we substract, and to decrease
01903     //we add; this goes against logic, making code harder to read.
01904        const int ID = findId(m_selected_wgt_token);
01905        if( m_widgets[ID].widget->m_enable_scroll )
01906        {
01907         int &speed = m_widgets[ID].widget->m_scroll_speed_y;
01908               //FIXME: these increases shouldn't be in pixels, but in percentages.
01909               //This should increase it by 1%, and the page buttons by 5%.
01910         if( fast )
01911         {
01912             if( speed > 0 && speed < 50 ) speed = 0;
01913             else speed -= 50;
01914         }
01915         else
01916         {
01917             if( speed > 0 && speed < 10 ) speed = 0;
01918             else speed -= 10;
01919         }
01920        }
01921 }
01922 
01923 void
01924 WidgetManager::decreaseScrollSpeed(const bool fast)
01925 {
01926        const int ID = findId(m_selected_wgt_token);
01927        if( m_widgets[ID].widget->m_enable_scroll )
01928        {
01929         int &speed = m_widgets[ID].widget->m_scroll_speed_y;
01930               //FIXME: these increases shouldn't be in pixels, but in percentages.
01931               //This should increase it by 1%, and the page buttons by 5%.
01932         if( fast )
01933         {
01934             if( speed < 0 && speed > -50 ) speed = 0;
01935             else speed += 50;
01936         }
01937         else
01938         {
01939             if( speed < 0 && speed > -10 ) speed = 0;
01940             else speed += 10;
01941         }
01942        }
01943 }
01944 
01953 int WidgetManager::findLeftWidget(const int START_WGT) const
01954 {
01955     const int NUM_WIDGETS = (int)m_widgets.size();
01956     int closest_wgt = WGT_NONE;
01957     int closest_x_dist = user_config->m_width;
01958     int closest_y_dist = user_config->m_height;
01959 
01960     const int START_WGT_Y_CENTER = m_widgets[START_WGT].widget->m_y +
01961         ( m_widgets[START_WGT].widget->m_height / 2 );
01962     const int START_WGT_X_CENTER = m_widgets[START_WGT].widget->m_x +
01963         ( m_widgets[START_WGT].widget->m_width / 2 );
01964 
01965     int curr_wgt_x_center, curr_wgt_y_center;
01966     int x_dist, y_dist;
01967 
01968     for( int i = 0; i < NUM_WIDGETS; ++i )
01969     {
01970         if(!(m_widgets[i].active)) continue;
01971 
01972         curr_wgt_y_center = m_widgets[i].widget->m_y + ( m_widgets[i].widget->m_height / 2 );
01973         curr_wgt_x_center = m_widgets[i].widget->m_x + ( m_widgets[i].widget->m_width / 2 );
01974 
01975         x_dist = START_WGT_X_CENTER - curr_wgt_x_center;
01976         y_dist = abs( curr_wgt_y_center - START_WGT_Y_CENTER );
01977 
01978         //Filter out all widgets that are not to the left and choose the
01979         //widget that is closest in the Y-axis
01980         if( x_dist > 0 && y_dist <= closest_y_dist )
01981         {
01982             closest_y_dist = y_dist;
01983 
01984             //If this is the first widget with this vertical distance, pick
01985             //it as the current closest widget
01986             if( y_dist != closest_y_dist )
01987             {
01988                 closest_x_dist = user_config->m_width; //Reset the distance
01989                 closest_wgt = i;
01990             }
01991             //If there is more than one widget with the same vertical
01992             //distance, choose the one that is closest in the X-axis
01993             else if( x_dist <= closest_x_dist )
01994             {
01995                 closest_x_dist = x_dist;
01996                 closest_wgt = i;
01997             }
01998         }
01999     }
02000 
02001     return closest_wgt;
02002 }
02003 
02006 int WidgetManager::findRightWidget(const int START_WGT) const
02007 {
02008     const int NUM_WIDGETS = (int)m_widgets.size();
02009     int closest_wgt = WGT_NONE;
02010     int closest_x_dist = user_config->m_width;
02011     int closest_y_dist = user_config->m_height;
02012 
02013     const int START_WGT_Y_CENTER = m_widgets[START_WGT].widget->m_y +
02014         ( m_widgets[START_WGT].widget->m_height / 2 );
02015     const int START_WGT_X_CENTER = m_widgets[START_WGT].widget->m_x +
02016         ( m_widgets[START_WGT].widget->m_width / 2 );
02017 
02018     int curr_wgt_x_center, curr_wgt_y_center;
02019     int x_dist, y_dist;
02020 
02021     for( int i = 0; i < NUM_WIDGETS; ++i )
02022     {
02023         if(!(m_widgets[i].active)) continue;
02024 
02025         curr_wgt_y_center = m_widgets[i].widget->m_y + ( m_widgets[i].widget->m_height / 2 );
02026         curr_wgt_x_center = m_widgets[i].widget->m_x + ( m_widgets[i].widget->m_width / 2 );
02027 
02028         //Notice that the order of this substraction is the *only* difference
02029         //from the findLeftWidget() function
02030         x_dist = curr_wgt_x_center - START_WGT_X_CENTER;
02031         y_dist = abs( curr_wgt_y_center - START_WGT_Y_CENTER );
02032 
02033         if( x_dist > 0 && y_dist <= closest_y_dist )
02034         {
02035             closest_y_dist = y_dist;
02036 
02037             if( y_dist != closest_y_dist )
02038             {
02039                 closest_x_dist = user_config->m_width;
02040                 closest_wgt = i;
02041             }
02042             else if( x_dist <= closest_x_dist )
02043             {
02044                 closest_x_dist = x_dist;
02045                 closest_wgt = i;
02046             }
02047         }
02048     }
02049 
02050     return closest_wgt;
02051 }
02056 int WidgetManager::findTopWidget(const int START_WGT) const
02057 {
02058     const int NUM_WIDGETS = (int)m_widgets.size();
02059     int closest_wgt = WGT_NONE;
02060     int closest_x_dist = user_config->m_width;
02061     int closest_y_dist = user_config->m_height;
02062 
02063     const int START_WGT_Y_CENTER = m_widgets[START_WGT].widget->m_y +
02064         ( m_widgets[START_WGT].widget->m_height / 2 );
02065     const int START_WGT_X_CENTER = m_widgets[START_WGT].widget->m_x +
02066         ( m_widgets[START_WGT].widget->m_width / 2 );
02067 
02068     int curr_wgt_x_center, curr_wgt_y_center;
02069     int x_dist, y_dist;
02070 
02071     for( int i = 0; i < NUM_WIDGETS; ++i )
02072     {
02073         if(!(m_widgets[i].active)) continue;
02074 
02075         curr_wgt_y_center = m_widgets[i].widget->m_y + ( m_widgets[i].widget->m_height / 2 );
02076         curr_wgt_x_center = m_widgets[i].widget->m_x + ( m_widgets[i].widget->m_width / 2 );
02077 
02078         y_dist = curr_wgt_y_center - START_WGT_Y_CENTER;
02079         x_dist = abs( curr_wgt_x_center - START_WGT_X_CENTER );
02080 
02081         //Filter out all widgets that are not on top and choose the
02082         //widget that is closest in the X-axis
02083         if( y_dist > 0 && x_dist <= closest_x_dist )
02084         {
02085             closest_x_dist = x_dist;
02086 
02087             //If this is the first widget with this vertical distance, pick
02088             //it as the current closest widget
02089             if( x_dist != closest_x_dist )
02090             {
02091                 closest_y_dist = user_config->m_height;
02092                 closest_wgt = i;
02093             }
02094             //If there is more than one widget with the same horizontal
02095             //distance, choose the one that is closest in the Y-axis
02096             else if( y_dist <= closest_y_dist )
02097             {
02098                 closest_y_dist = y_dist;
02099                 closest_wgt = i;
02100             }
02101         }
02102     }
02103 
02104     return closest_wgt;
02105 }
02106 
02111 int WidgetManager::findBottomWidget(const int START_WGT) const
02112 {
02113     const int NUM_WIDGETS = (int)m_widgets.size();
02114     int closest_wgt = WGT_NONE;
02115     int closest_x_dist = user_config->m_width;
02116     int closest_y_dist = user_config->m_height;
02117 
02118     const int START_WGT_Y_CENTER = m_widgets[START_WGT].widget->m_y +
02119         ( m_widgets[START_WGT].widget->m_height / 2 );
02120     const int START_WGT_X_CENTER = m_widgets[START_WGT].widget->m_x +
02121         ( m_widgets[START_WGT].widget->m_width / 2 );
02122 
02123     int curr_wgt_x_center, curr_wgt_y_center;
02124     int x_dist, y_dist;
02125 
02126     for( int i = 0; i < NUM_WIDGETS; ++i )
02127     {
02128         if(!(m_widgets[i].active)) continue;
02129 
02130         curr_wgt_y_center = m_widgets[i].widget->m_y + ( m_widgets[i].widget->m_height / 2 );
02131         curr_wgt_x_center = m_widgets[i].widget->m_x + ( m_widgets[i].widget->m_width / 2 );
02132 
02133         //Notice that the order of this substraction is the *only* difference
02134         //from the findTopWidget() function
02135         y_dist = START_WGT_Y_CENTER - curr_wgt_y_center;
02136         x_dist = abs( curr_wgt_x_center - START_WGT_X_CENTER );
02137 
02138         if( y_dist > 0 && x_dist <= closest_x_dist )
02139         {
02140             closest_x_dist = x_dist;
02141 
02142             if( x_dist != closest_x_dist )
02143             {
02144                 closest_y_dist = user_config->m_height;
02145                 closest_wgt = i;
02146             }
02147             else if( y_dist <= closest_y_dist )
02148             {
02149                 closest_y_dist = y_dist;
02150                 closest_wgt = i;
02151             }
02152         }
02153     }
02154 
02155     return closest_wgt;
02156 }
02157 
02158 //-----------------------------------------------------------------------------
02159 void WidgetManager::setSelectedWgtToken(const int TOKEN)
02160 {
02161     if( m_selected_wgt_token != TOKEN )
02162     {
02163         m_selected_wgt_token = TOKEN;
02164         m_selection_change = true;
02165     }
02166 }
02167 
02168 //-----------------------------------------------------------------------------
02169 void WidgetManager::resizeWgtToText( const int TOKEN )
02170 {
02171     const int ID = findId(TOKEN);
02172     if( ID != WGT_NONE )
02173     {
02174         m_widgets[ID].widget->resizeToText();
02175 
02176         const int SCREEN_WIDTH = user_config->m_width;
02177         const int SCREEN_HEIGHT = user_config->m_height;
02178 
02179         m_widgets[ID].min_width = ( m_widgets[ID].widget->m_width * 100 ) /
02180             SCREEN_WIDTH;
02181         m_widgets[ID].min_height = ( m_widgets[ID].widget->m_height * 100 ) /
02182             SCREEN_HEIGHT;
02183 
02184         layout();
02185     }
02186     else
02187     {
02188         std::cerr << "WARNING: tried to resize the text of an unnamed " <<
02189             "widget with token " << TOKEN << '\n';
02190     }
02191 }
02192 
02199 void WidgetManager::reloadFonts()
02200 {
02201     const int NUM_WIDGETS = (int)m_widgets.size();
02202     for( int i = 0; i < NUM_WIDGETS; ++i )
02203     {
02204         m_widgets[i].widget->setFont(
02205             m_widgets[i].widget->m_curr_widget_font );
02206     }
02207 }
02208