Back to index

supertuxkart  0.5+dfsg1
config_display.cpp
Go to the documentation of this file.
00001 //  $Id: config_display.cpp 2111 2008-05-31 07:04:30Z cosmosninja $
00002 //
00003 //  SuperTuxKart - a fun racing game with go-kart
00004 //  Copyright (C) 2006 SuperTuxKart-Team
00005 //
00006 //  This program is free software; you can redistribute it and/or
00007 //  modify it under the terms of the GNU General Public License
00008 //  as published by the Free Software Foundation; either version 2
00009 //  of the License, or (at your option) any later version.
00010 //
00011 //  This program is distributed in the hope that it will be useful,
00012 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 //  GNU General Public License for more details.
00015 //
00016 //  You should have received a copy of the GNU General Public License
00017 //  along with this program; if not, write to the Free Software
00018 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00019 
00020 #include "config_display.hpp"
00021 #include "widget_manager.hpp"
00022 #include "user_config.hpp"
00023 #include "menu_manager.hpp"
00024 #include "sdldrv.hpp"
00025 #include "translation.hpp"
00026 
00027 #include <algorithm>
00028 
00029 #if defined(WIN32) && !defined(__CYGWIN__)
00030 #  define snprintf _snprintf
00031 #endif
00032 
00033 enum WidgetTokens
00034 {
00035     WTOK_TITLE,
00036 
00037     WTOK_FULLSCREEN,
00038     WTOK_INCR_RES,
00039     WTOK_DECR_RES,
00040     WTOK_CURRENT_RES,
00041     WTOK_APPLY_RES,
00042     WTOK_CLEAR_BLACKLIST,
00043 
00044     WTOK_QUIT
00045 };
00046 
00047 ConfigDisplay::ConfigDisplay()
00048 {
00049     getScreenModes(); //Fill the vector m_sizes with possible resolutions
00050 
00051     m_curr_width = m_sizes[m_curr_res].first;
00052     m_curr_height = m_sizes[m_curr_res].second;
00053 
00054     widget_manager->switchOrder();
00055     widget_manager->addTitleWgt( WTOK_TITLE, 60, 7, _("Display Settings"));
00056 
00057     if( isBlacklisted( m_curr_width, m_curr_height ))
00058     {
00059         widget_manager->addEmptyWgt( WTOK_FULLSCREEN, 1, 7);
00060 
00061         if (user_config->m_fullscreen)
00062         {
00063             std::cerr << "Warning: current screen mode is blacklisted.\n";
00064         }
00065     }
00066     else
00067     {
00068         if(user_config->m_fullscreen)
00069         {
00070             widget_manager->addTextButtonWgt( WTOK_FULLSCREEN, 60, 7,
00071                 _("Window mode"));
00072         }
00073         else
00074         {
00075             widget_manager->addTextButtonWgt( WTOK_FULLSCREEN, 60, 7,
00076                 _("Fullscreen mode"));
00077         }
00078     }
00079 
00080     widget_manager->addEmptyWgt( WidgetManager::WGT_NONE, 60, 2 );
00081 
00082     char msg [MAX_MESSAGE_LENGTH];
00083     snprintf( msg, MAX_MESSAGE_LENGTH, _("Current: %dx%d"), m_curr_width, m_curr_height );
00084     widget_manager->addTextWgt( WTOK_CURRENT_RES, 60, 7, msg);
00085 
00086     widget_manager->addTextButtonWgt( WTOK_INCR_RES, 60, 7,
00087         _("Increase Resolution"));
00088     widget_manager->addTextButtonWgt( WTOK_DECR_RES, 60, 7,
00089         _("Decrease Resolution"));
00090 
00091     widget_manager->addEmptyWgt( WidgetManager::WGT_NONE, 1, 2 );
00092     widget_manager->addTextButtonWgt( WTOK_APPLY_RES, 60, 7, _("Apply "));
00093     widget_manager->addEmptyWgt( WidgetManager::WGT_NONE, 1, 2 );
00094 
00095     widget_manager->addEmptyWgt( WTOK_CLEAR_BLACKLIST, 60, 7);
00096     widget_manager->setWgtText( WTOK_CLEAR_BLACKLIST,
00097         _("Clear from Blacklist") );
00098 
00099     widget_manager->addEmptyWgt( WidgetManager::WGT_NONE, 1, 2 );
00100 
00101     widget_manager->addTextButtonWgt( WTOK_QUIT, 60, 7, _("Press <ESC> to go back"));
00102     widget_manager->setWgtTextSize( WTOK_QUIT, WGT_FNT_SML );
00103 
00104     widget_manager->layout( WGT_AREA_ALL );
00105 }
00106 
00107 //-----------------------------------------------------------------------------
00108 ConfigDisplay::~ConfigDisplay()
00109 {
00110     widget_manager->reset();
00111 }
00112 
00113 //-----------------------------------------------------------------------------
00114 void ConfigDisplay::select()
00115 {
00116     switch ( widget_manager->getSelectedWgt() )
00117     {
00118     case WTOK_FULLSCREEN:
00119         inputDriver->toggleFullscreen();
00120         if( user_config->m_fullscreen )
00121         {
00122             menu_manager->pushMenu( MENUID_RESOLUTION_CONFIRM_WIN );
00123         }
00124         else
00125         {
00126             //FIXME: maybe instead of 'Fullscreen mode' something like
00127             //'Switch to fullscreen mode' would be more user friendly?
00128             widget_manager->setWgtText(WTOK_FULLSCREEN, _("Fullscreen mode"));
00129         }
00130         changeApplyButton();
00131         break;
00132 
00133     case WTOK_INCR_RES:
00134         {
00135             const int NUM_RES = (int)m_sizes.size();
00136             m_curr_res = std::min(NUM_RES - 1, m_curr_res + 1);
00137 
00138             if ( user_config->m_fullscreen &&
00139                 isBlacklisted( m_curr_width, m_curr_height ))
00140             {
00141                 showBlacklistButtons();
00142             }
00143             else changeApplyButton();
00144         }
00145         break;
00146 
00147     case WTOK_DECR_RES:
00148         m_curr_res = std::max(0,m_curr_res-1);
00149         if ( user_config->m_fullscreen &&
00150             isBlacklisted( m_curr_width, m_curr_height ))
00151         {
00152             showBlacklistButtons();
00153         }
00154         else changeApplyButton();
00155         break;
00156 
00157     case WTOK_APPLY_RES:
00158         if (m_curr_width != m_sizes[m_curr_res].first ||
00159             m_curr_height != m_sizes[m_curr_res].second)
00160         {
00161             changeResolution(m_sizes[m_curr_res].first,m_sizes[m_curr_res].second/*, false*/);
00162 
00163             if (user_config->m_fullscreen)
00164             {
00165                 menu_manager->pushMenu(MENUID_RESOLUTION_CONFIRM_FS);
00166             }
00167             else
00168             {
00169                 char msg [MAX_MESSAGE_LENGTH];
00170                 snprintf (msg, MAX_MESSAGE_LENGTH, "Current: %dx%d",
00171                 user_config->m_width, user_config->m_height);
00172                 widget_manager->setWgtText(WTOK_CURRENT_RES, msg);
00173 
00174                 if ( isBlacklisted( user_config->m_width,
00175                     user_config->m_height ))
00176                 {
00177                     widget_manager->hideWgtText(WTOK_FULLSCREEN);
00178                     widget_manager->hideWgtRect(WTOK_FULLSCREEN);
00179                     widget_manager->deactivateWgt(WTOK_FULLSCREEN);
00180                 }
00181                 else
00182                 {
00183                     widget_manager->setWgtText(WTOK_FULLSCREEN, _("Fullscreen mode"));
00184                     widget_manager->showWgtText(WTOK_FULLSCREEN);
00185                     widget_manager->showWgtRect(WTOK_FULLSCREEN);
00186                     widget_manager->activateWgt(WTOK_FULLSCREEN);
00187                 }
00188                 widget_manager->layout();
00189 
00190                 user_config->m_prev_width = m_curr_width = user_config->m_width;
00191                 user_config->m_prev_height = m_curr_height = user_config->m_height;
00192             }
00193         }
00194         break;
00195 
00196     case WTOK_CLEAR_BLACKLIST:
00197         {
00198             const int NUM_BLACKLISTED = (int)user_config->m_blacklist_res.size();
00199             int black_width, black_height = 0;
00200             int id = -1;
00201 
00202             for ( int i = 0; i < NUM_BLACKLISTED; ++i )
00203             {
00204                 sscanf(user_config->m_blacklist_res[i].c_str(),
00205                        "%dx%d",& black_width, & black_height);
00206 
00207                 if ( m_sizes[m_curr_res].first == black_width &&
00208                      m_sizes[m_curr_res].second == black_height )
00209                 {
00210                     id = i;
00211                     break;
00212                 }
00213             }
00214 
00215             if( id != -1 )
00216             {
00217                 user_config->m_blacklist_res.erase(
00218                     user_config->m_blacklist_res.begin() + id );
00219             }
00220             else
00221             {
00222                 std::cerr << "Warning: tried to erase a resolution that " <<
00223                     "is not blacklisted.\n";
00224             }
00225         }
00226 
00227         changeApplyButton();
00228         widget_manager->layout();
00229         break;
00230 
00231     case WTOK_QUIT:
00232         menu_manager->popMenu();
00233         break;
00234 
00235     default: break;
00236     }
00237 }
00238 
00239 //-----------------------------------------------------------------------------
00240 void ConfigDisplay::changeResolution(int width, int height/*, bool reverse*/)
00241 {
00242     if (user_config->m_fullscreen )
00243     {
00244         //store previous width and height
00245         user_config->m_prev_width = user_config->m_width;
00246         user_config->m_prev_height = user_config->m_height;
00247     }
00248 
00249     //change to new height and width
00250     user_config->m_width = width;
00251     user_config->m_height = height;
00252 
00253 #if 0
00254     // if returning to prev res, change m_crashed to false as we didn't crash and save config
00255     if (reverse && user_config->m_fullscreen)
00256     {
00257         user_config->m_crashed = false;
00258         user_config->saveConfig();
00259     }
00260 #endif
00261 
00262     if (user_config->m_fullscreen )
00263     {
00264         // Store settings in user config file in case new video mode
00265         // causes a crash
00266         user_config->m_crashed = true;
00267         user_config->saveConfig();
00268     }
00269 
00270     inputDriver->setVideoMode();
00271     glViewport(0,0,user_config->m_width, user_config->m_height);
00272 }
00273 
00277 void ConfigDisplay::getScreenModes()
00278 {
00279     SDL_Rect **modes = SDL_ListModes( NULL, SDL_OPENGL | SDL_FULLSCREEN | SDL_HWSURFACE );
00280 
00281     if (modes == NULL)
00282     {
00283         std::cerr << "No fullscreen modes available.\n";
00284 
00285         loadDefaultModes();
00286 
00287         //FIXME: blacklist all resolutions
00288 
00289     }
00290     else if (modes == (SDL_Rect **)-1) //Any screen size can be used
00291     {
00292         loadDefaultModes();
00293     }
00294     else
00295     {
00296         //modes[i] is used as the breaking condition because that's how SDL's
00297         //docs use it in their examples.
00298         for (int i = 0; modes[i]; ++i)
00299         {
00300             m_sizes.push_back (std::pair <int, int> (modes[i]->w,
00301                 modes[i]->h));
00302         }
00303 
00304         std::sort (m_sizes.begin(), m_sizes.end());
00305 
00306         //Prevent use of very small resolutions
00307         const int MIN_WIDTH = 640;
00308         const int MIN_HEIGHT = 480;
00309         const int NUM_RES = (int)m_sizes.size();
00310 
00311         for (int i = NUM_RES - 1; i >= 0; --i)
00312         {
00313             if ( m_sizes[i].first < MIN_WIDTH )
00314             {
00315                 //Remove the resolutions with a width smaller than MIN_WIDTH
00316                 m_sizes.erase( m_sizes.begin(), m_sizes.begin() + i + 1 );
00317                 break;
00318             }
00319             else if ( m_sizes[i].first == MIN_WIDTH &&
00320                 m_sizes[i].second < MIN_HEIGHT )
00321             {
00322                 m_sizes.erase( m_sizes.begin(), m_sizes.begin() + i + 1 );
00323                 break;
00324             }
00325         }
00326     }
00327 
00328     //Set the same resolution as the one in the config file; if it's not
00329     //found, set it to the lowest resolution available as a sane default.
00330     m_curr_res = -1;
00331     const int NUM_RES = (int)m_sizes.size();
00332 
00333     for (int i = 0; i < NUM_RES; ++i)
00334     {
00335         if (m_sizes[i].first == user_config->m_width
00336          && m_sizes[i].second == user_config->m_height)
00337         {
00338             m_curr_res = i;
00339             return;
00340         }
00341     }
00342 
00343     m_curr_res = 0;
00344 }
00345 
00346 //-----------------------------------------------------------------------------
00347 void ConfigDisplay::changeApplyButton()
00348 {
00349     // change Apply button text
00350     char msg [MAX_MESSAGE_LENGTH];
00351     snprintf(msg, MAX_MESSAGE_LENGTH, _("Apply %dx%d"),
00352       m_sizes[m_curr_res].first,m_sizes[m_curr_res].second);
00353     widget_manager->setWgtText(WTOK_APPLY_RES, msg);
00354     widget_manager->activateWgt(WTOK_APPLY_RES);
00355 
00356     // hide Remove from blacklist button
00357     widget_manager->hideWgtRect(WTOK_CLEAR_BLACKLIST);
00358     widget_manager->hideWgtText(WTOK_CLEAR_BLACKLIST);
00359     widget_manager->deactivateWgt(WTOK_CLEAR_BLACKLIST);
00360 }
00361 
00362 //-----------------------------------------------------------------------------
00363 bool ConfigDisplay::isBlacklisted(int width, int height)
00364 {
00365     int black_width, black_height;
00366     const int NUM_BLACKLISTED = (int)user_config->m_blacklist_res.size();
00367 
00368     for (int i = 0; i < NUM_BLACKLISTED; ++i)
00369     {
00370         sscanf(user_config->m_blacklist_res[i].c_str(),
00371         "%dx%d", &black_width, &black_height );
00372 
00373         if (width == black_width && height == black_height) return true;
00374     }
00375 
00376     return false;
00377 
00378 }
00379 
00380 //-----------------------------------------------------------------------------
00381 void ConfigDisplay::showBlacklistButtons()
00382 {
00383     //change Apply button to Blacklisted button
00384     char msg [MAX_MESSAGE_LENGTH];
00385     snprintf(msg, MAX_MESSAGE_LENGTH, _("%dx%d Blacklisted"),
00386       m_sizes[m_curr_res].first,m_sizes[m_curr_res].second);
00387     widget_manager->setWgtText(WTOK_APPLY_RES, msg);
00388     widget_manager->deactivateWgt(WTOK_APPLY_RES);
00389 
00390     //show Remove from blacklist button
00391     widget_manager->showWgtRect( WTOK_CLEAR_BLACKLIST);
00392     widget_manager->showWgtText( WTOK_CLEAR_BLACKLIST);
00393     widget_manager->activateWgt( WTOK_CLEAR_BLACKLIST);
00394 }
00395 
00402 void ConfigDisplay::loadDefaultModes()
00403 {
00404     m_sizes.clear();
00405 
00406     m_sizes.push_back( std::pair <int, int> (800, 600) );
00407     m_sizes.push_back( std::pair <int, int> (1024, 768) );
00408     m_sizes.push_back( std::pair <int, int> (1152, 864) );
00409     m_sizes.push_back( std::pair <int, int> (1280, 768) );
00410     m_sizes.push_back( std::pair <int, int> (1280, 800) );
00411     m_sizes.push_back( std::pair <int, int> (1280, 960) );
00412     m_sizes.push_back( std::pair <int, int> (1280, 1024) );
00413     m_sizes.push_back( std::pair <int, int> (1440, 900) );
00414     m_sizes.push_back( std::pair <int, int> (1680, 1050) );
00415     m_sizes.push_back( std::pair <int, int> (1920, 1200) );
00416 };
00417