2010-02-04 13:33:47 +02:00
/***************************************************************************
2011-10-23 17:43:56 +03:00
* Copyright ( C ) 2006 by Massimiliano Torromeo *
* massimiliano . torromeo @ gmail . com *
2010-02-04 13:33:47 +02:00
* *
* This program is free software ; you can redistribute it and / or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation ; either version 2 of the License , or *
* ( at your option ) any later version . *
* *
* This program is distributed in the hope that it will be useful , *
* but WITHOUT ANY WARRANTY ; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the *
* GNU General Public License for more details . *
* *
* You should have received a copy of the GNU General Public License *
* along with this program ; if not , write to the *
* Free Software Foundation , Inc . , *
* 59 Temple Place - Suite 330 , Boston , MA 02111 - 1307 , USA . *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2011-10-23 18:32:46 +03:00
# include "gp2x.h"
2013-08-09 19:01:51 +03:00
# include "background.h"
2011-10-23 18:32:46 +03:00
# include "cpu.h"
# include "debug.h"
# include "filedialog.h"
# include "filelister.h"
2013-08-03 23:30:12 +03:00
# include "font.h"
2011-10-23 18:32:46 +03:00
# include "gmenu2x.h"
2013-08-06 02:55:32 +03:00
# include "helppopup.h"
2011-10-23 18:32:46 +03:00
# include "iconbutton.h"
# include "inputdialog.h"
# include "linkapp.h"
2013-07-19 19:37:56 +03:00
# include "mediamonitor.h"
2011-10-23 18:32:46 +03:00
# include "menu.h"
# include "menusettingbool.h"
# include "menusettingdir.h"
# include "menusettingfile.h"
# include "menusettingimage.h"
# include "menusettingint.h"
# include "menusettingmultistring.h"
# include "menusettingrgba.h"
# include "menusettingstring.h"
# include "messagebox.h"
# include "powersaver.h"
# include "settingsdialog.h"
# include "textdialog.h"
# include "wallpaperdialog.h"
# include "utilities.h"
2010-02-04 13:33:47 +02:00
# include <iostream>
# include <sstream>
# include <fstream>
2010-07-28 04:31:41 +03:00
# include <algorithm>
2010-02-04 13:33:47 +02:00
# include <stdlib.h>
# include <unistd.h>
# include <math.h>
# include <SDL.h>
# include <SDL_gfxPrimitives.h>
# include <signal.h>
# include <sys/statvfs.h>
# include <errno.h>
# include <sys/fcntl.h> //for battery
2011-10-23 18:32:46 +03:00
# ifdef PLATFORM_PANDORA
//#include <pnd_container.h>
//#include <pnd_conf.h>
//#include <pnd_discovery.h>
# endif
2010-02-04 13:33:47 +02:00
//for browsing the filesystem
# include <sys/stat.h>
# include <sys/types.h>
# include <dirent.h>
//for soundcard
# include <sys/ioctl.h>
# include <linux/soundcard.h>
# include <sys/mman.h>
2011-10-23 17:43:56 +03:00
using namespace std ;
2011-10-23 18:27:29 +03:00
# ifndef DEFAULT_WALLPAPER_PATH
# define DEFAULT_WALLPAPER_PATH \
GMENU2X_SYSTEM_DIR " /skins/Default/wallpapers/default.png "
# endif
2010-09-01 18:37:27 +03:00
# ifdef _CARD_ROOT
const char * CARD_ROOT = _CARD_ROOT ;
2012-11-27 07:14:08 +02:00
# elif defined(PLATFORM_A320) || defined(PLATFORM_GCW0)
2013-07-19 18:54:09 +03:00
const char * CARD_ROOT = " /media " ;
2010-09-01 18:37:27 +03:00
# else
2013-07-19 18:54:09 +03:00
const char * CARD_ROOT = " /card " ;
2010-09-01 18:37:27 +03:00
# endif
2010-07-04 04:19:52 +03:00
2010-09-17 23:32:41 +03:00
static GMenu2X * app ;
2011-03-29 13:15:16 +03:00
static string gmenu2x_home ;
2010-09-17 23:32:41 +03:00
2010-07-28 17:15:52 +03:00
// Note: Keep this in sync with the enum!
static const char * colorNames [ NUM_COLORS ] = {
" topBarBg " ,
" bottomBarBg " ,
" selectionBg " ,
" messageBoxBg " ,
" messageBoxBorder " ,
" messageBoxSelection " ,
} ;
static enum color stringToColor ( const string & name )
{
for ( unsigned int i = 0 ; i < NUM_COLORS ; i + + ) {
if ( strcmp ( colorNames [ i ] , name . c_str ( ) ) = = 0 ) {
return ( enum color ) i ;
}
}
return ( enum color ) - 1 ;
}
static const char * colorToString ( enum color c )
{
return colorNames [ c ] ;
}
2010-09-17 23:32:41 +03:00
static void quit_all ( int err ) {
delete app ;
exit ( err ) ;
}
2011-03-29 13:15:16 +03:00
const string GMenu2X : : getHome ( void )
{
return gmenu2x_home ;
}
2013-07-19 20:58:12 +03:00
static void set_handler ( int signal , void ( * handler ) ( int ) )
{
struct sigaction sig ;
sigaction ( signal , NULL , & sig ) ;
sig . sa_handler = handler ;
sigaction ( signal , & sig , NULL ) ;
}
2010-09-17 23:31:09 +03:00
int main ( int /*argc*/ , char * /*argv*/ [ ] ) {
2013-07-19 00:03:01 +03:00
INFO ( " ---- GMenu2X starting ---- \n " ) ;
2010-02-04 13:33:47 +02:00
2013-07-19 20:58:12 +03:00
set_handler ( SIGINT , & quit_all ) ;
set_handler ( SIGSEGV , & quit_all ) ;
set_handler ( SIGTERM , & quit_all ) ;
2010-09-17 23:31:09 +03:00
2011-03-29 13:15:16 +03:00
char * home = getenv ( " HOME " ) ;
if ( home = = NULL ) {
ERROR ( " Unable to find gmenu2x home directory. The $HOME variable is not defined. \n " ) ;
return 1 ;
}
gmenu2x_home = ( string ) home + ( string ) " /.gmenu2x " ;
if ( ! fileExists ( gmenu2x_home ) & & mkdir ( gmenu2x_home . c_str ( ) , 0770 ) < 0 ) {
ERROR ( " Unable to create gmenu2x home directory. \n " ) ;
return 1 ;
}
DEBUG ( " Home path: %s. \n " , gmenu2x_home . c_str ( ) ) ;
2010-09-17 23:32:41 +03:00
app = new GMenu2X ( ) ;
2010-09-17 23:31:09 +03:00
DEBUG ( " Starting main() \n " ) ;
2010-09-17 23:32:41 +03:00
app - > main ( ) ;
2010-09-17 23:31:09 +03:00
2010-02-04 13:33:47 +02:00
return 0 ;
}
2012-12-08 06:03:33 +02:00
# ifdef ENABLE_CPUFREQ
2011-09-18 19:27:03 +03:00
void GMenu2X : : initCPULimits ( ) {
// Note: These values are for the Dingoo.
// The NanoNote does not have cpufreq enabled in its kernel and
// other devices are not actively maintained.
// TODO: Read min and max from sysfs.
cpuFreqMin = 30 ;
cpuFreqMax = 500 ;
cpuFreqSafeMax = 420 ;
cpuFreqMenuDefault = 200 ;
cpuFreqAppDefault = 384 ;
cpuFreqMultiple = 24 ;
// Round min and max values to the specified multiple.
cpuFreqMin = ( ( cpuFreqMin + cpuFreqMultiple - 1 ) / cpuFreqMultiple )
* cpuFreqMultiple ;
cpuFreqMax = ( cpuFreqMax / cpuFreqMultiple ) * cpuFreqMultiple ;
cpuFreqSafeMax = ( cpuFreqSafeMax / cpuFreqMultiple ) * cpuFreqMultiple ;
cpuFreqMenuDefault = ( cpuFreqMenuDefault / cpuFreqMultiple ) * cpuFreqMultiple ;
cpuFreqAppDefault = ( cpuFreqAppDefault / cpuFreqMultiple ) * cpuFreqMultiple ;
}
2012-12-08 06:03:33 +02:00
# endif
2011-09-18 19:27:03 +03:00
2011-07-29 02:13:35 +03:00
GMenu2X : : GMenu2X ( )
2013-08-16 11:41:16 +03:00
: appToLaunch ( nullptr )
2011-07-29 02:13:35 +03:00
{
2010-02-04 13:33:47 +02:00
usbnet = samba = inet = web = false ;
useSelectionPng = false ;
2012-12-08 06:03:33 +02:00
# ifdef ENABLE_CPUFREQ
2011-09-18 19:27:03 +03:00
initCPULimits ( ) ;
2012-12-08 06:03:33 +02:00
# endif
2010-02-04 13:33:47 +02:00
//load config data
readConfig ( ) ;
2011-07-29 02:13:35 +03:00
2010-02-04 13:33:47 +02:00
halfX = resX / 2 ;
halfY = resY / 2 ;
bottomBarIconY = resY - 18 ;
bottomBarTextY = resY - 10 ;
2011-07-28 02:48:12 +03:00
/* Do not clear the screen on exit.
* This may require an SDL patch available at
* https : //github.com/mthuurne/opendingux-buildroot/blob
* / opendingux - 2010.11 / package / sdl / sdl - fbcon - clear - onexit . patch
*/
setenv ( " SDL_FBCON_DONT_CLEAR " , " 1 " , 0 ) ;
2010-02-04 13:33:47 +02:00
//Screen
2013-07-29 23:54:12 +03:00
if ( SDL_Init ( SDL_INIT_VIDEO | SDL_INIT_TIMER ) < 0 ) {
2010-09-17 23:31:09 +03:00
ERROR ( " Could not initialize SDL: %s \n " , SDL_GetError ( ) ) ;
2010-02-04 13:33:47 +02:00
quit ( ) ;
}
2011-06-02 18:59:26 +03:00
s = Surface : : openOutputSurface ( resX , resY , confInt [ " videoBpp " ] ) ;
2010-02-04 13:33:47 +02:00
bg = NULL ;
font = NULL ;
2012-12-04 19:21:22 +02:00
setSkin ( confStr [ " skin " ] , ! fileExists ( confStr [ " wallpaper " ] ) ) ;
2013-08-09 19:01:51 +03:00
layers . insert ( layers . begin ( ) , make_shared < Background > ( * this ) ) ;
2010-02-04 13:33:47 +02:00
initMenu ( ) ;
2013-09-19 18:26:32 +03:00
# ifdef ENABLE_INOTIFY
2013-07-19 19:37:56 +03:00
monitor = new MediaMonitor ( CARD_ROOT ) ;
2013-09-19 18:26:32 +03:00
# endif
2013-07-19 19:37:56 +03:00
2010-02-04 13:33:47 +02:00
if ( ! fileExists ( confStr [ " wallpaper " ] ) ) {
2011-04-03 12:49:00 +03:00
DEBUG ( " No wallpaper defined; we will take the default one. \n " ) ;
confStr [ " wallpaper " ] = DEFAULT_WALLPAPER_PATH ;
2010-02-04 13:33:47 +02:00
}
initBG ( ) ;
2011-03-29 13:31:43 +03:00
/* If a user-specified input.conf file exists, we load it;
* otherwise , we load the default one . */
2012-01-23 13:29:58 +02:00
string input_file = getHome ( ) + " /input.conf " ;
if ( fileExists ( input_file . c_str ( ) ) ) {
DEBUG ( " Loading user-specific input.conf file: %s. \n " , input_file . c_str ( ) ) ;
2011-03-29 13:31:43 +03:00
} else {
input_file = GMENU2X_SYSTEM_DIR " /input.conf " ;
2012-01-23 13:29:58 +02:00
DEBUG ( " Loading system input.conf file: %s. \n " , input_file . c_str ( ) ) ;
2011-03-29 13:31:43 +03:00
}
2013-08-06 03:34:03 +03:00
input . init ( input_file , menu . get ( ) ) ;
2011-08-17 01:46:11 +03:00
if ( confInt [ " backlightTimeout " ] > 0 )
PowerSaver : : getInstance ( ) - > setScreenTimeout ( confInt [ " backlightTimeout " ] ) ;
2010-02-04 13:33:47 +02:00
setInputSpeed ( ) ;
2012-12-08 06:03:33 +02:00
# ifdef ENABLE_CPUFREQ
2010-02-04 13:33:47 +02:00
setClock ( confInt [ " menuClock " ] ) ;
2012-12-08 06:03:33 +02:00
# endif
2010-06-19 04:50:23 +03:00
}
2010-02-04 13:33:47 +02:00
2010-06-19 04:50:23 +03:00
GMenu2X : : ~ GMenu2X ( ) {
2011-08-17 01:46:11 +03:00
if ( PowerSaver : : isRunning ( ) )
delete PowerSaver : : getInstance ( ) ;
2010-02-04 13:33:47 +02:00
quit ( ) ;
2011-07-20 14:43:25 +03:00
delete font ;
2013-09-19 18:26:32 +03:00
# ifdef ENABLE_INOTIFY
2013-07-19 19:37:56 +03:00
delete monitor ;
2013-09-19 18:26:32 +03:00
# endif
2010-02-04 13:33:47 +02:00
}
void GMenu2X : : quit ( ) {
fflush ( NULL ) ;
sc . clear ( ) ;
2011-07-20 14:43:25 +03:00
delete s ;
2011-07-11 12:27:38 +03:00
2010-02-04 13:33:47 +02:00
SDL_Quit ( ) ;
2011-07-28 02:48:12 +03:00
unsetenv ( " SDL_FBCON_DONT_CLEAR " ) ;
2010-02-04 13:33:47 +02:00
}
void GMenu2X : : initBG ( ) {
sc . del ( " bgmain " ) ;
2011-06-03 12:46:36 +03:00
// Load wallpaper.
2011-07-20 14:43:25 +03:00
delete bg ;
2011-06-03 12:46:36 +03:00
bg = Surface : : loadImage ( confStr [ " wallpaper " ] ) ;
if ( ! bg ) {
bg = Surface : : emptySurface ( resX , resY ) ;
2010-02-04 13:33:47 +02:00
}
drawTopBar ( bg ) ;
drawBottomBar ( bg ) ;
Surface * bgmain = new Surface ( bg ) ;
sc . add ( bgmain , " bgmain " ) ;
2011-06-02 23:09:03 +03:00
Surface * sd = Surface : : loadImage ( " imgs/sd.png " , confStr [ " skin " ] ) ;
2011-06-03 12:46:36 +03:00
if ( sd ) sd - > blit ( bgmain , 3 , bottomBarIconY ) ;
2011-09-18 13:42:08 +03:00
2012-11-27 07:14:08 +02:00
# if defined(PLATFORM_A320) || defined(PLATFORM_GCW0)
2011-09-18 13:42:08 +03:00
string df = getDiskFree ( " /boot " ) ;
# else
string df = getDiskFree ( CARD_ROOT ) ;
# endif
2013-08-03 23:30:12 +03:00
bgmain - > write ( font , df , 22 , bottomBarTextY , Font : : HAlignLeft , Font : : VAlignMiddle ) ;
2011-07-20 14:43:25 +03:00
delete sd ;
2010-05-03 15:21:00 +03:00
2011-11-19 15:47:55 +02:00
cpuX = font - > getTextWidth ( df ) + 32 ;
2012-12-08 06:03:33 +02:00
# ifdef ENABLE_CPUFREQ
Surface * cpu = Surface : : loadImage ( " imgs/cpu.png " , confStr [ " skin " ] ) ;
2011-06-03 12:46:36 +03:00
if ( cpu ) cpu - > blit ( bgmain , cpuX , bottomBarIconY ) ;
2010-02-04 13:33:47 +02:00
cpuX + = 19 ;
2011-09-19 17:33:19 +03:00
manualX = cpuX + font - > getTextWidth ( " 300MHz " ) + 5 ;
2011-07-20 14:43:25 +03:00
delete cpu ;
2012-12-08 06:03:33 +02:00
# else
manualX = cpuX ;
# endif
2010-02-04 13:33:47 +02:00
int serviceX = resX - 38 ;
if ( usbnet ) {
if ( web ) {
2011-06-02 23:09:03 +03:00
Surface * webserver = Surface : : loadImage (
" imgs/webserver.png " , confStr [ " skin " ] ) ;
2011-06-03 12:46:36 +03:00
if ( webserver ) webserver - > blit ( bgmain , serviceX , bottomBarIconY ) ;
2010-02-04 13:33:47 +02:00
serviceX - = 19 ;
2011-07-20 14:43:25 +03:00
delete webserver ;
2010-02-04 13:33:47 +02:00
}
if ( samba ) {
2011-06-02 23:09:03 +03:00
Surface * sambaS = Surface : : loadImage (
" imgs/samba.png " , confStr [ " skin " ] ) ;
2011-06-03 12:46:36 +03:00
if ( sambaS ) sambaS - > blit ( bgmain , serviceX , bottomBarIconY ) ;
2010-02-04 13:33:47 +02:00
serviceX - = 19 ;
2011-07-20 14:43:25 +03:00
delete sambaS ;
2010-02-04 13:33:47 +02:00
}
if ( inet ) {
2011-06-02 23:09:03 +03:00
Surface * inetS = Surface : : loadImage ( " imgs/inet.png " , confStr [ " skin " ] ) ;
2011-06-03 12:46:36 +03:00
if ( inetS ) inetS - > blit ( bgmain , serviceX , bottomBarIconY ) ;
2010-02-04 13:33:47 +02:00
serviceX - = 19 ;
2011-07-20 14:43:25 +03:00
delete inetS ;
2010-02-04 13:33:47 +02:00
}
}
2011-06-03 12:46:36 +03:00
bgmain - > convertToDisplayFormat ( ) ;
2010-02-04 13:33:47 +02:00
}
void GMenu2X : : initFont ( ) {
2014-01-15 23:02:30 +02:00
if ( font ) {
delete font ;
font = NULL ;
}
string path = skinConfStr [ " font " ] ;
2014-01-15 21:32:17 +02:00
if ( ! path . empty ( ) ) {
unsigned int size = skinConfInt [ " fontsize " ] ;
if ( ! size )
size = 12 ;
2014-01-15 23:02:30 +02:00
if ( path . substr ( 0 , 5 ) = = " skin: " )
path = sc . getSkinFilePath ( path . substr ( 5 , path . length ( ) ) ) ;
2014-01-15 21:32:17 +02:00
font = new Font ( path , size ) ;
} else {
font = Font : : defaultFont ( ) ;
}
2013-08-04 01:58:32 +03:00
if ( ! font ) {
ERROR ( " Cannot function without font; aborting... \n " ) ;
2010-02-04 13:33:47 +02:00
quit ( ) ;
exit ( - 1 ) ;
}
}
void GMenu2X : : initMenu ( ) {
//Menu structure handler
2013-08-06 03:34:03 +03:00
menu . reset ( new Menu ( this , ts ) ) ;
2010-07-27 22:12:15 +03:00
for ( uint i = 0 ; i < menu - > getSections ( ) . size ( ) ; i + + ) {
2010-02-04 13:33:47 +02:00
//Add virtual links in the applications section
2010-07-27 22:12:15 +03:00
if ( menu - > getSections ( ) [ i ] = = " applications " ) {
2013-07-29 19:58:25 +03:00
menu - > addActionLink ( i , " Explorer " , BIND ( & GMenu2X : : explorer ) , tr [ " Launch an application " ] , " skin:icons/explorer.png " ) ;
2010-02-04 13:33:47 +02:00
}
//Add virtual links in the setting section
2010-07-27 22:12:15 +03:00
else if ( menu - > getSections ( ) [ i ] = = " settings " ) {
2013-08-09 19:01:51 +03:00
menu - > addActionLink ( i , " GMenu2X " , BIND ( & GMenu2X : : showSettings ) , tr [ " Configure GMenu2X's options " ] , " skin:icons/configure.png " ) ;
2013-07-29 19:58:25 +03:00
menu - > addActionLink ( i , tr [ " Skin " ] , BIND ( & GMenu2X : : skinMenu ) , tr [ " Configure skin " ] , " skin:icons/skin.png " ) ;
menu - > addActionLink ( i , tr [ " Wallpaper " ] , BIND ( & GMenu2X : : changeWallpaper ) , tr [ " Change GMenu2X wallpaper " ] , " skin:icons/wallpaper.png " ) ;
2013-11-08 12:27:34 +02:00
if ( fileExists ( LOG_FILE ) )
2013-07-29 19:58:25 +03:00
menu - > addActionLink ( i , tr [ " Log Viewer " ] , BIND ( & GMenu2X : : viewLog ) , tr [ " Displays last launched program's output " ] , " skin:icons/ebook.png " ) ;
menu - > addActionLink ( i , tr [ " About " ] , BIND ( & GMenu2X : : about ) , tr [ " Info about GMenu2X " ] , " skin:icons/about.png " ) ;
2010-02-04 13:33:47 +02:00
}
}
2013-08-06 20:59:35 +03:00
menu - > skinUpdated ( ) ;
2010-02-04 13:33:47 +02:00
menu - > setSectionIndex ( confInt [ " section " ] ) ;
menu - > setLinkIndex ( confInt [ " link " ] ) ;
2013-08-06 02:55:32 +03:00
layers . push_back ( menu ) ;
2010-02-04 13:33:47 +02:00
}
void GMenu2X : : about ( ) {
vector < string > text ;
2012-04-27 18:42:09 +03:00
string line ;
string fn ( GMENU2X_SYSTEM_DIR ) ;
string build_date ( " Build date: " ) ;
fn . append ( " /about.txt " ) ;
build_date . append ( __DATE__ ) ;
ifstream inf ( fn . c_str ( ) , ios_base : : in ) ;
while ( getline ( inf , line , ' \n ' ) )
text . push_back ( line ) ;
inf . close ( ) ;
TextDialog td ( this , " GMenu2X " , build_date , " icons/about.png " , & text ) ;
2010-02-04 13:33:47 +02:00
td . exec ( ) ;
}
void GMenu2X : : viewLog ( ) {
2013-11-08 12:27:34 +02:00
string logfile = LOG_FILE ;
2010-02-04 13:33:47 +02:00
if ( fileExists ( logfile ) ) {
ifstream inf ( logfile . c_str ( ) , ios_base : : in ) ;
if ( inf . is_open ( ) ) {
vector < string > log ;
string line ;
while ( getline ( inf , line , ' \n ' ) )
log . push_back ( line ) ;
inf . close ( ) ;
TextDialog td ( this , tr [ " Log Viewer " ] , tr [ " Displays last launched program's output " ] , " icons/ebook.png " , & log ) ;
td . exec ( ) ;
MessageBox mb ( this , tr [ " Do you want to delete the log file? " ] , " icons/ebook.png " ) ;
2011-10-23 09:57:52 +03:00
mb . setButton ( InputManager : : ACCEPT , tr [ " Yes " ] ) ;
mb . setButton ( InputManager : : CANCEL , tr [ " No " ] ) ;
if ( mb . exec ( ) = = InputManager : : ACCEPT ) {
2010-02-04 13:33:47 +02:00
unlink ( logfile . c_str ( ) ) ;
menu - > deleteSelectedLink ( ) ;
}
}
}
}
void GMenu2X : : readConfig ( ) {
2011-08-11 04:40:36 +03:00
string conffile = GMENU2X_SYSTEM_DIR " /gmenu2x.conf " ;
readConfig ( conffile ) ;
conffile = getHome ( ) + " /gmenu2x.conf " ;
readConfig ( conffile ) ;
}
void GMenu2X : : readConfig ( string conffile ) {
2010-02-04 13:33:47 +02:00
if ( fileExists ( conffile ) ) {
ifstream inf ( conffile . c_str ( ) , ios_base : : in ) ;
if ( inf . is_open ( ) ) {
string line ;
while ( getline ( inf , line , ' \n ' ) ) {
string : : size_type pos = line . find ( " = " ) ;
string name = trim ( line . substr ( 0 , pos ) ) ;
string value = trim ( line . substr ( pos + 1 , line . length ( ) ) ) ;
if ( value . length ( ) > 1 & & value . at ( 0 ) = = ' " ' & & value . at ( value . length ( ) - 1 ) = = ' " ' )
confStr [ name ] = value . substr ( 1 , value . length ( ) - 2 ) ;
else
confInt [ name ] = atoi ( value . c_str ( ) ) ;
}
inf . close ( ) ;
}
}
2011-07-11 13:39:31 +03:00
if ( ! confStr [ " lang " ] . empty ( ) )
tr . setLang ( confStr [ " lang " ] ) ;
if ( ! confStr [ " wallpaper " ] . empty ( ) & & ! fileExists ( confStr [ " wallpaper " ] ) )
confStr [ " wallpaper " ] = " " ;
if ( confStr [ " skin " ] . empty ( ) | | SurfaceCollection : : getSkinPath ( confStr [ " skin " ] ) . empty ( ) )
confStr [ " skin " ] = " Default " ;
2010-02-04 13:33:47 +02:00
evalIntConf ( & confInt [ " outputLogs " ] , 0 , 0 , 1 ) ;
2012-12-08 06:03:33 +02:00
# ifdef ENABLE_CPUFREQ
2011-09-18 19:27:03 +03:00
evalIntConf ( & confInt [ " maxClock " ] ,
cpuFreqSafeMax , cpuFreqMin , cpuFreqMax ) ;
evalIntConf ( & confInt [ " menuClock " ] ,
cpuFreqMenuDefault , cpuFreqMin , cpuFreqSafeMax ) ;
2012-12-08 06:03:33 +02:00
# endif
2011-06-02 06:04:35 +03:00
evalIntConf ( & confInt [ " backlightTimeout " ] , 15 , 0 , 120 ) ;
2011-09-19 02:12:34 +03:00
evalIntConf ( & confInt [ " videoBpp " ] , 32 , 16 , 32 ) ;
2010-02-04 13:33:47 +02:00
if ( confStr [ " tvoutEncoding " ] ! = " PAL " ) confStr [ " tvoutEncoding " ] = " NTSC " ;
resX = constrain ( confInt [ " resolutionX " ] , 320 , 1920 ) ;
resY = constrain ( confInt [ " resolutionY " ] , 240 , 1200 ) ;
}
2012-12-20 23:01:30 +02:00
void GMenu2X : : saveSelection ( ) {
if ( confInt [ " saveSelection " ] & & (
confInt [ " section " ] ! = menu - > selSectionIndex ( )
| | confInt [ " link " ] ! = menu - > selLinkIndex ( )
) ) {
writeConfig ( ) ;
}
}
2010-02-04 13:33:47 +02:00
void GMenu2X : : writeConfig ( ) {
2011-03-29 13:33:56 +03:00
string conffile = getHome ( ) + " /gmenu2x.conf " ;
2010-02-04 13:33:47 +02:00
ofstream inf ( conffile . c_str ( ) ) ;
if ( inf . is_open ( ) ) {
ConfStrHash : : iterator endS = confStr . end ( ) ;
for ( ConfStrHash : : iterator curr = confStr . begin ( ) ; curr ! = endS ; curr + + )
inf < < curr - > first < < " = \" " < < curr - > second < < " \" " < < endl ;
ConfIntHash : : iterator endI = confInt . end ( ) ;
for ( ConfIntHash : : iterator curr = confInt . begin ( ) ; curr ! = endI ; curr + + )
inf < < curr - > first < < " = " < < curr - > second < < endl ;
inf . close ( ) ;
}
}
void GMenu2X : : writeSkinConfig ( ) {
2011-04-12 11:19:00 +03:00
string conffile = getHome ( ) + " /skins/ " ;
if ( ! fileExists ( conffile ) )
mkdir ( conffile . c_str ( ) , 0770 ) ;
conffile = conffile + confStr [ " skin " ] ;
if ( ! fileExists ( conffile ) )
mkdir ( conffile . c_str ( ) , 0770 ) ;
conffile = conffile + " /skin.conf " ;
2010-02-04 13:33:47 +02:00
ofstream inf ( conffile . c_str ( ) ) ;
if ( inf . is_open ( ) ) {
ConfStrHash : : iterator endS = skinConfStr . end ( ) ;
for ( ConfStrHash : : iterator curr = skinConfStr . begin ( ) ; curr ! = endS ; curr + + )
inf < < curr - > first < < " = \" " < < curr - > second < < " \" " < < endl ;
ConfIntHash : : iterator endI = skinConfInt . end ( ) ;
for ( ConfIntHash : : iterator curr = skinConfInt . begin ( ) ; curr ! = endI ; curr + + )
inf < < curr - > first < < " = " < < curr - > second < < endl ;
2010-05-02 20:53:06 +03:00
int i ;
for ( i = 0 ; i < NUM_COLORS ; + + i ) {
2011-06-06 10:38:26 +03:00
inf < < colorToString ( ( enum color ) i ) < < " =# " ;
inf . width ( 2 ) ; inf . fill ( ' 0 ' ) ;
inf < < right < < hex < < skinConfColors [ i ] . r ;
inf . width ( 2 ) ; inf . fill ( ' 0 ' ) ;
inf < < right < < hex < < skinConfColors [ i ] . g ;
inf . width ( 2 ) ; inf . fill ( ' 0 ' ) ;
inf < < right < < hex < < skinConfColors [ i ] . b ;
inf . width ( 2 ) ; inf . fill ( ' 0 ' ) ;
inf < < right < < hex < < skinConfColors [ i ] . a < < endl ;
2010-05-02 20:53:06 +03:00
}
2010-02-04 13:33:47 +02:00
inf . close ( ) ;
}
}
void GMenu2X : : readTmp ( ) {
lastSelectorElement = - 1 ;
if ( fileExists ( " /tmp/gmenu2x.tmp " ) ) {
ifstream inf ( " /tmp/gmenu2x.tmp " , ios_base : : in ) ;
if ( inf . is_open ( ) ) {
string line ;
string section = " " ;
while ( getline ( inf , line , ' \n ' ) ) {
string : : size_type pos = line . find ( " = " ) ;
string name = trim ( line . substr ( 0 , pos ) ) ;
string value = trim ( line . substr ( pos + 1 , line . length ( ) ) ) ;
if ( name = = " section " )
menu - > setSectionIndex ( atoi ( value . c_str ( ) ) ) ;
else if ( name = = " link " )
menu - > setLinkIndex ( atoi ( value . c_str ( ) ) ) ;
else if ( name = = " selectorelem " )
lastSelectorElement = atoi ( value . c_str ( ) ) ;
else if ( name = = " selectordir " )
lastSelectorDir = value ;
}
inf . close ( ) ;
}
}
}
2010-05-02 15:29:09 +03:00
void GMenu2X : : writeTmp ( int selelem , const string & selectordir ) {
2010-02-04 13:33:47 +02:00
string conffile = " /tmp/gmenu2x.tmp " ;
ofstream inf ( conffile . c_str ( ) ) ;
if ( inf . is_open ( ) ) {
inf < < " section= " < < menu - > selSectionIndex ( ) < < endl ;
inf < < " link= " < < menu - > selLinkIndex ( ) < < endl ;
if ( selelem > - 1 )
inf < < " selectorelem= " < < selelem < < endl ;
2013-08-16 10:16:04 +03:00
if ( ! selectordir . empty ( ) )
2010-02-04 13:33:47 +02:00
inf < < " selectordir= " < < selectordir < < endl ;
inf . close ( ) ;
}
}
2013-08-04 04:47:23 +03:00
void GMenu2X : : main ( ) {
if ( ! fileExists ( CARD_ROOT ) )
CARD_ROOT = " " ;
2010-02-04 13:33:47 +02:00
2013-08-16 11:41:16 +03:00
appToLaunch = nullptr ;
2013-09-08 00:02:38 +03:00
// Recover last session
readTmp ( ) ;
if ( lastSelectorElement > - 1 & & menu - > selLinkApp ( ) & &
( ! menu - > selLinkApp ( ) - > getSelectorDir ( ) . empty ( )
| | ! lastSelectorDir . empty ( ) ) )
menu - > selLinkApp ( ) - > selector ( lastSelectorElement , lastSelectorDir ) ;
2013-08-16 11:41:16 +03:00
while ( true ) {
2013-08-12 20:41:56 +03:00
// Remove dismissed layers from the stack.
2013-08-11 01:05:18 +03:00
for ( auto it = layers . begin ( ) ; it ! = layers . end ( ) ; ) {
2013-08-12 20:41:56 +03:00
if ( ( * it ) - > getStatus ( ) = = Layer : : Status : : DISMISSED ) {
it = layers . erase ( it ) ;
} else {
+ + it ;
2013-08-11 01:05:18 +03:00
}
}
2013-08-12 20:41:56 +03:00
// Run animations.
bool animating = false ;
for ( auto layer : layers ) {
animating | = layer - > runAnimations ( ) ;
}
2013-08-09 20:09:57 +03:00
// Paint layers.
for ( auto layer : layers ) {
layer - > paint ( * s ) ;
}
2013-08-16 11:41:16 +03:00
if ( appToLaunch ) {
break ;
}
2010-02-04 13:33:47 +02:00
s - > flip ( ) ;
2013-08-09 20:09:57 +03:00
// Handle touchscreen events.
2011-12-23 13:30:15 +02:00
if ( ts . available ( ) ) {
2010-02-04 13:33:47 +02:00
ts . poll ( ) ;
2013-08-09 19:01:51 +03:00
for ( auto it = layers . rbegin ( ) ; it ! = layers . rend ( ) ; + + it ) {
if ( ( * it ) - > handleTouchscreen ( ts ) ) {
break ;
}
2013-08-06 02:55:32 +03:00
}
2010-02-04 13:33:47 +02:00
}
2013-08-09 20:09:57 +03:00
// Handle other input events.
2013-09-07 18:00:57 +03:00
InputManager : : Button button ;
2013-08-11 01:05:18 +03:00
bool gotEvent ;
const bool wait = ! animating ;
do {
2013-09-07 18:00:57 +03:00
gotEvent = input . getButton ( & button , wait ) ;
2013-08-11 01:05:18 +03:00
} while ( wait & & ! gotEvent ) ;
if ( gotEvent ) {
for ( auto it = layers . rbegin ( ) ; it ! = layers . rend ( ) ; + + it ) {
2013-09-07 18:00:57 +03:00
if ( ( * it ) - > handleButtonPress ( button ) ) {
2013-08-11 01:05:18 +03:00
break ;
}
2013-08-06 02:55:32 +03:00
}
}
2010-02-04 13:33:47 +02:00
}
2013-08-16 11:41:16 +03:00
if ( appToLaunch ) {
appToLaunch - > drawRun ( ) ;
appToLaunch - > launch ( fileToLaunch ) ;
}
2010-02-04 13:33:47 +02:00
}
void GMenu2X : : explorer ( ) {
2013-07-08 09:27:53 +03:00
FileDialog fd ( this , ts , tr [ " Select an application " ] , " dge,sh,bin,py,elf, " ) ;
2010-02-04 13:33:47 +02:00
if ( fd . exec ( ) ) {
if ( confInt [ " saveSelection " ] & & ( confInt [ " section " ] ! = menu - > selSectionIndex ( ) | | confInt [ " link " ] ! = menu - > selLinkIndex ( ) ) )
writeConfig ( ) ;
2010-05-03 20:58:28 +03:00
string command = cmdclean ( fd . getPath ( ) + " / " + fd . getFile ( ) ) ;
chdir ( fd . getPath ( ) . c_str ( ) ) ;
2010-02-04 13:33:47 +02:00
quit ( ) ;
2012-12-08 06:03:33 +02:00
# ifdef ENABLE_CPUFREQ
2011-09-18 19:27:03 +03:00
setClock ( cpuFreqAppDefault ) ;
2012-12-08 06:03:33 +02:00
# endif
2010-02-04 13:33:47 +02:00
execlp ( " /bin/sh " , " /bin/sh " , " -c " , command . c_str ( ) , NULL ) ;
//if execution continues then something went wrong and as we already called SDL_Quit we cannot continue
//try relaunching gmenu2x
2010-09-17 23:31:09 +03:00
ERROR ( " Error executing selected application, re-launching gmenu2x \n " ) ;
2012-06-25 00:01:28 +03:00
main ( ) ;
2010-02-04 13:33:47 +02:00
}
}
2013-08-16 11:41:16 +03:00
void GMenu2X : : queueLaunch ( LinkApp * app , const std : : string & file ) {
appToLaunch = app ;
fileToLaunch = file ;
}
2013-08-09 19:01:51 +03:00
void GMenu2X : : showHelpPopup ( ) {
layers . push_back ( make_shared < HelpPopup > ( * this ) ) ;
}
void GMenu2X : : showSettings ( ) {
2012-12-08 06:03:33 +02:00
# ifdef ENABLE_CPUFREQ
2010-02-04 13:33:47 +02:00
int curMenuClock = confInt [ " menuClock " ] ;
2012-12-08 06:03:33 +02:00
# endif
2010-07-04 04:19:52 +03:00
bool showRootFolder = fileExists ( CARD_ROOT ) ;
2010-02-04 13:33:47 +02:00
2013-07-19 00:14:21 +03:00
FileLister fl_tr ( GMENU2X_SYSTEM_DIR " /translations " ) ;
2010-02-04 13:33:47 +02:00
fl_tr . browse ( ) ;
2013-07-19 00:14:21 +03:00
string tr_path = getHome ( ) + " /translations " ;
if ( fileExists ( tr_path ) ) {
fl_tr . setPath ( tr_path , false ) ;
fl_tr . browse ( false ) ;
}
2011-04-12 10:59:32 +03:00
2010-07-27 22:41:35 +03:00
fl_tr . insertFile ( " English " ) ;
2010-02-04 13:33:47 +02:00
string lang = tr . lang ( ) ;
vector < string > encodings ;
encodings . push_back ( " NTSC " ) ;
encodings . push_back ( " PAL " ) ;
2010-07-28 00:09:16 +03:00
SettingsDialog sd ( this , input , ts , tr [ " Settings " ] ) ;
2011-12-23 15:03:05 +02:00
sd . addSetting ( new MenuSettingMultiString ( this , ts , tr [ " Language " ] , tr [ " Set the language used by GMenu2X " ] , & lang , & fl_tr . getFiles ( ) ) ) ;
sd . addSetting ( new MenuSettingBool ( this , ts , tr [ " Save last selection " ] , tr [ " Save the last selected link and section on exit " ] , & confInt [ " saveSelection " ] ) ) ;
2012-12-08 06:03:33 +02:00
# ifdef ENABLE_CPUFREQ
2011-12-23 15:03:05 +02:00
sd . addSetting ( new MenuSettingInt ( this , ts , tr [ " Clock for GMenu2X " ] , tr [ " Set the cpu working frequency when running GMenu2X " ] , & confInt [ " menuClock " ] , cpuFreqMin , cpuFreqSafeMax , cpuFreqMultiple ) ) ;
sd . addSetting ( new MenuSettingInt ( this , ts , tr [ " Maximum overclock " ] , tr [ " Set the maximum overclock for launching links " ] , & confInt [ " maxClock " ] , cpuFreqMin , cpuFreqMax , cpuFreqMultiple ) ) ;
2012-12-08 06:03:33 +02:00
# endif
2011-12-23 15:03:05 +02:00
sd . addSetting ( new MenuSettingBool ( this , ts , tr [ " Output logs " ] , tr [ " Logs the output of the links. Use the Log Viewer to read them. " ] , & confInt [ " outputLogs " ] ) ) ;
sd . addSetting ( new MenuSettingInt ( this , ts , tr [ " Screen Timeout " ] , tr [ " Set screen's backlight timeout in seconds " ] , & confInt [ " backlightTimeout " ] , 0 , 120 ) ) ;
// sd.addSetting(new MenuSettingMultiString(this, ts, tr["Tv-Out encoding"], tr["Encoding of the tv-out signal"], &confStr["tvoutEncoding"], &encodings));
sd . addSetting ( new MenuSettingBool ( this , ts , tr [ " Show root " ] , tr [ " Show root folder in the file selection dialogs " ] , & showRootFolder ) ) ;
2010-02-04 13:33:47 +02:00
if ( sd . exec ( ) & & sd . edited ( ) ) {
2012-12-08 06:03:33 +02:00
# ifdef ENABLE_CPUFREQ
2011-12-23 15:03:05 +02:00
if ( curMenuClock ! = confInt [ " menuClock " ] ) setClock ( confInt [ " menuClock " ] ) ;
2012-12-08 06:03:33 +02:00
# endif
2011-08-17 01:46:11 +03:00
if ( confInt [ " backlightTimeout " ] = = 0 ) {
if ( PowerSaver : : isRunning ( ) )
delete PowerSaver : : getInstance ( ) ;
} else {
PowerSaver : : getInstance ( ) - > setScreenTimeout ( confInt [ " backlightTimeout " ] ) ;
}
2010-02-04 13:33:47 +02:00
if ( lang = = " English " ) lang = " " ;
2011-04-12 14:24:35 +03:00
if ( lang ! = tr . lang ( ) ) {
tr . setLang ( lang ) ;
confStr [ " lang " ] = lang ;
}
2010-09-01 23:50:43 +03:00
/*if (fileExists(CARD_ROOT) && !showRootFolder)
2010-07-04 04:19:52 +03:00
unlink ( CARD_ROOT ) ;
2010-09-01 23:50:43 +03:00
else if ( ! fileExists ( CARD_ROOT ) & & showRootFolder )
symlink ( " / " , CARD_ROOT ) ; */
2010-09-01 18:37:27 +03:00
//WARNING: the above might be dangerous with CARD_ROOT set to /
2010-02-04 13:33:47 +02:00
writeConfig ( ) ;
}
}
void GMenu2X : : skinMenu ( ) {
2011-04-14 12:16:16 +03:00
FileLister fl_sk ( getHome ( ) + " /skins " , true , false ) ;
2010-07-27 22:41:35 +03:00
fl_sk . addExclude ( " .. " ) ;
2010-02-04 13:33:47 +02:00
fl_sk . browse ( ) ;
2011-04-14 12:16:16 +03:00
fl_sk . setPath ( GMENU2X_SYSTEM_DIR " /skins " , false ) ;
2011-04-12 11:16:28 +03:00
fl_sk . browse ( false ) ;
2010-02-04 13:33:47 +02:00
string curSkin = confStr [ " skin " ] ;
2010-07-28 00:09:16 +03:00
SettingsDialog sd ( this , input , ts , tr [ " Skin " ] ) ;
2011-12-23 15:03:05 +02:00
sd . addSetting ( new MenuSettingMultiString ( this , ts , tr [ " Skin " ] , tr [ " Set the skin used by GMenu2X " ] , & confStr [ " skin " ] , & fl_sk . getDirectories ( ) ) ) ;
2013-08-14 07:16:18 +03:00
sd . addSetting ( new MenuSettingRGBA ( this , ts , tr [ " Top Bar " ] , tr [ " Color of the top bar " ] , & skinConfColors [ COLOR_TOP_BAR_BG ] ) ) ;
sd . addSetting ( new MenuSettingRGBA ( this , ts , tr [ " Bottom Bar " ] , tr [ " Color of the bottom bar " ] , & skinConfColors [ COLOR_BOTTOM_BAR_BG ] ) ) ;
sd . addSetting ( new MenuSettingRGBA ( this , ts , tr [ " Selection " ] , tr [ " Color of the selection and other interface details " ] , & skinConfColors [ COLOR_SELECTION_BG ] ) ) ;
sd . addSetting ( new MenuSettingRGBA ( this , ts , tr [ " Message Box " ] , tr [ " Background color of the message box " ] , & skinConfColors [ COLOR_MESSAGE_BOX_BG ] ) ) ;
sd . addSetting ( new MenuSettingRGBA ( this , ts , tr [ " Message Box Border " ] , tr [ " Border color of the message box " ] , & skinConfColors [ COLOR_MESSAGE_BOX_BORDER ] ) ) ;
sd . addSetting ( new MenuSettingRGBA ( this , ts , tr [ " Message Box Selection " ] , tr [ " Color of the selection of the message box " ] , & skinConfColors [ COLOR_MESSAGE_BOX_SELECTION ] ) ) ;
2010-02-04 13:33:47 +02:00
if ( sd . exec ( ) & & sd . edited ( ) ) {
if ( curSkin ! = confStr [ " skin " ] ) {
setSkin ( confStr [ " skin " ] ) ;
writeConfig ( ) ;
}
writeSkinConfig ( ) ;
initBG ( ) ;
}
}
2010-05-02 15:29:09 +03:00
void GMenu2X : : setSkin ( const string & skin , bool setWallpaper ) {
2010-02-04 13:33:47 +02:00
confStr [ " skin " ] = skin ;
//Clear previous skin settings
skinConfStr . clear ( ) ;
skinConfInt . clear ( ) ;
2011-07-11 13:39:31 +03:00
DEBUG ( " GMenu2X: setting new skin %s. \n " , skin . c_str ( ) ) ;
2010-02-04 13:33:47 +02:00
//clear collection and change the skin path
sc . clear ( ) ;
sc . setSkin ( skin ) ;
//reset colors to the default values
2010-05-02 20:53:06 +03:00
skinConfColors [ COLOR_TOP_BAR_BG ] = ( RGBAColor ) { 255 , 255 , 255 , 130 } ;
skinConfColors [ COLOR_BOTTOM_BAR_BG ] = ( RGBAColor ) { 255 , 255 , 255 , 130 } ;
skinConfColors [ COLOR_SELECTION_BG ] = ( RGBAColor ) { 255 , 255 , 255 , 130 } ;
skinConfColors [ COLOR_MESSAGE_BOX_BG ] = ( RGBAColor ) { 255 , 255 , 255 , 255 } ;
skinConfColors [ COLOR_MESSAGE_BOX_BORDER ] = ( RGBAColor ) { 80 , 80 , 80 , 255 } ;
skinConfColors [ COLOR_MESSAGE_BOX_SELECTION ] = ( RGBAColor ) { 160 , 160 , 160 , 255 } ;
2010-02-04 13:33:47 +02:00
2011-03-29 13:37:53 +03:00
/* Load skin settings from user directory if present,
* or from the system directory . */
string skinconfname = getHome ( ) + " /skins/ " + skin + " /skin.conf " ;
if ( ! fileExists ( skinconfname ) )
skinconfname = GMENU2X_SYSTEM_DIR " /skins/ " + skin + " /skin.conf " ;
2010-02-04 13:33:47 +02:00
if ( fileExists ( skinconfname ) ) {
ifstream skinconf ( skinconfname . c_str ( ) , ios_base : : in ) ;
if ( skinconf . is_open ( ) ) {
string line ;
while ( getline ( skinconf , line , ' \n ' ) ) {
line = trim ( line ) ;
2010-09-17 23:31:09 +03:00
DEBUG ( " skinconf: '%s' \n " , line . c_str ( ) ) ;
2010-02-04 13:33:47 +02:00
string : : size_type pos = line . find ( " = " ) ;
string name = trim ( line . substr ( 0 , pos ) ) ;
string value = trim ( line . substr ( pos + 1 , line . length ( ) ) ) ;
if ( value . length ( ) > 0 ) {
if ( value . length ( ) > 1 & & value . at ( 0 ) = = ' " ' & & value . at ( value . length ( ) - 1 ) = = ' " ' )
skinConfStr [ name ] = value . substr ( 1 , value . length ( ) - 2 ) ;
else if ( value . at ( 0 ) = = ' # ' )
2010-05-02 20:53:06 +03:00
skinConfColors [ stringToColor ( name ) ] = strtorgba ( value . substr ( 1 , value . length ( ) ) ) ;
2010-02-04 13:33:47 +02:00
else
skinConfInt [ name ] = atoi ( value . c_str ( ) ) ;
}
}
skinconf . close ( ) ;
2012-12-04 19:21:22 +02:00
if ( setWallpaper & & ! skinConfStr [ " wallpaper " ] . empty ( ) ) {
string fp = sc . getSkinFilePath ( " wallpapers/ " + skinConfStr [ " wallpaper " ] ) ;
if ( ! fp . empty ( ) )
confStr [ " wallpaper " ] = fp ;
else
WARNING ( " Unable to find wallpaper defined on skin %s \n " , skin . c_str ( ) ) ;
}
2010-02-04 13:33:47 +02:00
}
}
2013-08-14 13:23:15 +03:00
evalIntConf ( & skinConfInt [ " topBarHeight " ] , 40 , 32 , 120 ) ;
evalIntConf ( & skinConfInt [ " bottomBarHeight " ] , 20 , 20 , 120 ) ;
evalIntConf ( & skinConfInt [ " linkHeight " ] , 40 , 32 , 120 ) ;
evalIntConf ( & skinConfInt [ " linkWidth " ] , 60 , 32 , 120 ) ;
2010-02-04 13:33:47 +02:00
2013-08-05 01:51:36 +03:00
if ( menu ! = NULL ) menu - > skinUpdated ( ) ;
2010-02-04 13:33:47 +02:00
//Selection png
2011-07-11 14:34:52 +03:00
useSelectionPng = sc . addSkinRes ( " imgs/selection.png " , false ) ! = NULL ;
2010-02-04 13:33:47 +02:00
//font
initFont ( ) ;
}
2011-09-15 12:18:07 +03:00
void GMenu2X : : showManual ( ) {
menu - > selLinkApp ( ) - > showManual ( ) ;
}
2013-08-12 00:46:04 +03:00
void GMenu2X : : showContextMenu ( ) {
layers . push_back ( make_shared < ContextMenu > ( * this , * menu ) ) ;
2010-02-04 13:33:47 +02:00
}
void GMenu2X : : changeWallpaper ( ) {
2011-12-23 15:03:05 +02:00
WallpaperDialog wp ( this , ts ) ;
2010-02-04 13:33:47 +02:00
if ( wp . exec ( ) & & confStr [ " wallpaper " ] ! = wp . wallpaper ) {
confStr [ " wallpaper " ] = wp . wallpaper ;
initBG ( ) ;
writeConfig ( ) ;
}
}
void GMenu2X : : addLink ( ) {
2013-07-08 09:27:53 +03:00
FileDialog fd ( this , ts , tr [ " Select an application " ] , " dge,sh,bin,py,elf, " ) ;
2013-09-27 00:56:27 +03:00
if ( fd . exec ( ) )
2010-05-03 20:58:28 +03:00
menu - > addLink ( fd . getPath ( ) , fd . getFile ( ) ) ;
2010-02-04 13:33:47 +02:00
}
void GMenu2X : : editLink ( ) {
2013-08-12 01:08:28 +03:00
LinkApp * linkApp = menu - > selLinkApp ( ) ;
if ( ! linkApp ) return ;
2010-02-04 13:33:47 +02:00
vector < string > pathV ;
2013-08-12 01:08:28 +03:00
split ( pathV , linkApp - > getFile ( ) , " / " ) ;
2010-02-04 13:33:47 +02:00
string oldSection = " " ;
if ( pathV . size ( ) > 1 )
oldSection = pathV [ pathV . size ( ) - 2 ] ;
string newSection = oldSection ;
2013-08-12 01:08:28 +03:00
string linkTitle = linkApp - > getTitle ( ) ;
string linkDescription = linkApp - > getDescription ( ) ;
string linkIcon = linkApp - > getIcon ( ) ;
string linkManual = linkApp - > getManual ( ) ;
string linkSelFilter = linkApp - > getSelectorFilter ( ) ;
string linkSelDir = linkApp - > getSelectorDir ( ) ;
bool linkSelBrowser = linkApp - > getSelectorBrowser ( ) ;
string linkSelScreens = linkApp - > getSelectorScreens ( ) ;
string linkSelAliases = linkApp - > getAliasFile ( ) ;
int linkClock = linkApp - > clock ( ) ;
2010-02-04 13:33:47 +02:00
string diagTitle = tr . translate ( " Edit link: $1 " , linkTitle . c_str ( ) , NULL ) ;
2013-08-12 01:08:28 +03:00
string diagIcon = linkApp - > getIconPath ( ) ;
2010-02-04 13:33:47 +02:00
2010-07-28 00:09:16 +03:00
SettingsDialog sd ( this , input , ts , diagTitle , diagIcon ) ;
2013-08-12 01:08:28 +03:00
if ( ! linkApp - > isOpk ( ) ) {
2013-08-12 01:13:18 +03:00
sd . addSetting ( new MenuSettingString ( this , ts , tr [ " Title " ] , tr [ " Link title " ] , & linkTitle , diagTitle , diagIcon ) ) ;
sd . addSetting ( new MenuSettingString ( this , ts , tr [ " Description " ] , tr [ " Link description " ] , & linkDescription , diagTitle , diagIcon ) ) ;
sd . addSetting ( new MenuSettingMultiString ( this , ts , tr [ " Section " ] , tr [ " The section this link belongs to " ] , & newSection , & menu - > getSections ( ) ) ) ;
sd . addSetting ( new MenuSettingImage ( this , ts , tr [ " Icon " ] ,
tr . translate ( " Select an icon for the link: $1 " ,
linkTitle . c_str ( ) , NULL ) , & linkIcon , " png " ) ) ;
sd . addSetting ( new MenuSettingFile ( this , ts , tr [ " Manual " ] ,
tr [ " Select a graphic/textual manual or a readme " ] ,
& linkManual , " man.png,txt " ) ) ;
2012-12-08 06:45:21 +02:00
}
2013-08-12 01:08:28 +03:00
if ( ! linkApp - > isOpk ( ) | | ! linkApp - > getSelectorDir ( ) . empty ( ) ) {
2013-08-12 01:13:18 +03:00
sd . addSetting ( new MenuSettingDir ( this , ts , tr [ " Selector Directory " ] , tr [ " Directory to scan for the selector " ] , & linkSelDir ) ) ;
sd . addSetting ( new MenuSettingBool ( this , ts , tr [ " Selector Browser " ] , tr [ " Allow the selector to change directory " ] , & linkSelBrowser ) ) ;
2012-10-23 07:33:27 +03:00
}
2012-12-08 06:03:33 +02:00
# ifdef ENABLE_CPUFREQ
2012-12-07 01:53:39 +02:00
sd . addSetting ( new MenuSettingInt ( this , ts , tr [ " Clock frequency " ] , tr [ " Cpu clock frequency to set when launching this link " ] , & linkClock , cpuFreqMin , confInt [ " maxClock " ] , cpuFreqMultiple ) ) ;
2012-12-08 06:03:33 +02:00
# endif
2013-08-12 01:08:28 +03:00
if ( ! linkApp - > isOpk ( ) ) {
2013-08-12 01:13:18 +03:00
sd . addSetting ( new MenuSettingString ( this , ts , tr [ " Selector Filter " ] , tr [ " Selector filter (Separate values with a comma) " ] , & linkSelFilter , diagTitle , diagIcon ) ) ;
sd . addSetting ( new MenuSettingDir ( this , ts , tr [ " Selector Screenshots " ] , tr [ " Directory of the screenshots for the selector " ] , & linkSelScreens ) ) ;
sd . addSetting ( new MenuSettingFile ( this , ts , tr [ " Selector Aliases " ] , tr [ " File containing a list of aliases for the selector " ] , & linkSelAliases ) ) ;
2012-11-27 07:14:08 +02:00
# if defined(PLATFORM_A320) || defined(PLATFORM_GCW0)
2013-08-12 01:13:18 +03:00
sd . addSetting ( new MenuSettingBool ( this , ts , tr [ " Display Console " ] , tr [ " Must be enabled for console-based applications " ] , & linkApp - > consoleApp ) ) ;
2012-04-13 20:21:49 +03:00
# endif
2012-10-23 07:33:27 +03:00
}
2010-02-04 13:33:47 +02:00
if ( sd . exec ( ) & & sd . edited ( ) ) {
2013-08-12 01:08:28 +03:00
linkApp - > setTitle ( linkTitle ) ;
linkApp - > setDescription ( linkDescription ) ;
linkApp - > setIcon ( linkIcon ) ;
linkApp - > setManual ( linkManual ) ;
linkApp - > setSelectorFilter ( linkSelFilter ) ;
linkApp - > setSelectorDir ( linkSelDir ) ;
linkApp - > setSelectorBrowser ( linkSelBrowser ) ;
linkApp - > setSelectorScreens ( linkSelScreens ) ;
linkApp - > setAliasFile ( linkSelAliases ) ;
linkApp - > setClock ( linkClock ) ;
2010-02-04 13:33:47 +02:00
2010-09-17 23:31:09 +03:00
INFO ( " New Section: '%s' \n " , newSection . c_str ( ) ) ;
2010-02-04 13:33:47 +02:00
//if section changed move file and update link->file
if ( oldSection ! = newSection ) {
2010-07-27 22:12:15 +03:00
vector < string > : : const_iterator newSectionIndex = find ( menu - > getSections ( ) . begin ( ) , menu - > getSections ( ) . end ( ) , newSection ) ;
if ( newSectionIndex = = menu - > getSections ( ) . end ( ) ) return ;
2010-02-04 13:33:47 +02:00
string newFileName = " sections/ " + newSection + " / " + linkTitle ;
uint x = 2 ;
while ( fileExists ( newFileName ) ) {
string id = " " ;
stringstream ss ; ss < < x ; ss > > id ;
newFileName = " sections/ " + newSection + " / " + linkTitle + id ;
x + + ;
}
2013-08-12 01:08:28 +03:00
rename ( linkApp - > getFile ( ) . c_str ( ) , newFileName . c_str ( ) ) ;
linkApp - > renameFile ( newFileName ) ;
2010-09-17 23:31:09 +03:00
INFO ( " New section index: %i. \n " , newSectionIndex - menu - > getSections ( ) . begin ( ) ) ;
2010-07-27 22:12:15 +03:00
menu - > linkChangeSection ( menu - > selLinkIndex ( ) , menu - > selSectionIndex ( ) , newSectionIndex - menu - > getSections ( ) . begin ( ) ) ;
2010-02-04 13:33:47 +02:00
}
2013-08-12 01:08:28 +03:00
linkApp - > save ( ) ;
2010-02-04 13:33:47 +02:00
}
}
void GMenu2X : : deleteLink ( ) {
if ( menu - > selLinkApp ( ) ! = NULL ) {
MessageBox mb ( this , tr . translate ( " Deleting $1 " , menu - > selLink ( ) - > getTitle ( ) . c_str ( ) , NULL ) + " \n " + tr [ " Are you sure? " ] , menu - > selLink ( ) - > getIconPath ( ) ) ;
2011-10-23 09:57:52 +03:00
mb . setButton ( InputManager : : ACCEPT , tr [ " Yes " ] ) ;
mb . setButton ( InputManager : : CANCEL , tr [ " No " ] ) ;
2013-09-27 00:56:27 +03:00
if ( mb . exec ( ) = = InputManager : : ACCEPT )
2010-02-04 13:33:47 +02:00
menu - > deleteSelectedLink ( ) ;
}
}
void GMenu2X : : addSection ( ) {
2010-07-27 23:56:03 +03:00
InputDialog id ( this , input , ts , tr [ " Insert a name for the new section " ] ) ;
2010-02-04 13:33:47 +02:00
if ( id . exec ( ) ) {
//only if a section with the same name does not exist
2010-07-27 22:12:15 +03:00
if ( find ( menu - > getSections ( ) . begin ( ) , menu - > getSections ( ) . end ( ) , id . getInput ( ) )
= = menu - > getSections ( ) . end ( ) ) {
2010-02-04 13:33:47 +02:00
//section directory doesn't exists
2013-09-27 00:56:27 +03:00
if ( menu - > addSection ( id . getInput ( ) ) )
2010-07-27 22:12:15 +03:00
menu - > setSectionIndex ( menu - > getSections ( ) . size ( ) - 1 ) ; //switch to the new section
2010-02-04 13:33:47 +02:00
}
}
}
void GMenu2X : : renameSection ( ) {
2010-07-27 23:56:03 +03:00
InputDialog id ( this , input , ts , tr [ " Insert a new name for this section " ] , menu - > selSection ( ) ) ;
2010-02-04 13:33:47 +02:00
if ( id . exec ( ) ) {
//only if a section with the same name does not exist & !samename
2010-07-26 06:58:06 +03:00
if ( menu - > selSection ( ) ! = id . getInput ( )
2010-07-27 22:12:15 +03:00
& & find ( menu - > getSections ( ) . begin ( ) , menu - > getSections ( ) . end ( ) , id . getInput ( ) )
= = menu - > getSections ( ) . end ( ) ) {
2010-02-04 13:33:47 +02:00
//section directory doesn't exists
2011-04-14 13:08:10 +03:00
string newsectiondir = getHome ( ) + " /sections/ " + id . getInput ( ) ;
string sectiondir = getHome ( ) + " /sections/ " + menu - > selSection ( ) ;
if ( ! rename ( sectiondir . c_str ( ) , newsectiondir . c_str ( ) ) ) {
string oldpng = menu - > selSection ( ) + " .png " ;
string newpng = id . getInput ( ) + " .png " ;
string oldicon = sc . getSkinFilePath ( oldpng ) ;
string newicon = sc . getSkinFilePath ( newpng ) ;
2010-02-04 13:33:47 +02:00
if ( ! oldicon . empty ( ) & & newicon . empty ( ) ) {
newicon = oldicon ;
2010-06-19 06:10:19 +03:00
newicon . replace ( newicon . find ( oldpng ) , oldpng . length ( ) , newpng ) ;
2010-02-04 13:33:47 +02:00
if ( ! fileExists ( newicon ) ) {
2011-04-14 13:08:10 +03:00
rename ( oldicon . c_str ( ) , newicon . c_str ( ) ) ;
2010-02-04 13:33:47 +02:00
sc . move ( " skin: " + oldpng , " skin: " + newpng ) ;
}
}
2010-07-27 22:12:15 +03:00
menu - > renameSection ( menu - > selSectionIndex ( ) , id . getInput ( ) ) ;
2010-02-04 13:33:47 +02:00
}
}
}
}
void GMenu2X : : deleteSection ( ) {
MessageBox mb ( this , tr [ " You will lose all the links in this section. " ] + " \n " + tr [ " Are you sure? " ] ) ;
2011-10-23 09:57:52 +03:00
mb . setButton ( InputManager : : ACCEPT , tr [ " Yes " ] ) ;
mb . setButton ( InputManager : : CANCEL , tr [ " No " ] ) ;
if ( mb . exec ( ) = = InputManager : : ACCEPT ) {
2012-06-15 00:45:57 +03:00
2013-09-27 00:56:27 +03:00
if ( rmtree ( getHome ( ) + " /sections/ " + menu - > selSection ( ) ) )
2010-02-04 13:33:47 +02:00
menu - > deleteSelectedSection ( ) ;
}
}
void GMenu2X : : scanner ( ) {
Surface scanbg ( bg ) ;
2011-09-18 04:40:33 +03:00
drawButton ( & scanbg , " cancel " , tr [ " Exit " ] ,
drawButton ( & scanbg , " accept " , " " , 5 ) - 10 ) ;
2013-08-03 23:30:12 +03:00
scanbg . write ( font , tr [ " Link Scanner " ] , halfX , 7 , Font : : HAlignCenter , Font : : VAlignMiddle ) ;
2011-06-03 12:46:36 +03:00
scanbg . convertToDisplayFormat ( ) ;
2010-02-04 13:33:47 +02:00
uint lineY = 42 ;
2011-07-29 02:13:35 +03:00
# ifdef PLATFORM_PANDORA
2010-02-04 13:33:47 +02:00
//char *configpath = pnd_conf_query_searchpath();
# else
2012-12-08 06:03:33 +02:00
# ifdef ENABLE_CPUFREQ
2012-12-07 01:53:39 +02:00
setSafeMaxClock ( ) ;
2012-12-08 06:03:33 +02:00
# endif
2010-02-04 13:33:47 +02:00
2012-06-24 23:19:36 +03:00
scanbg . write ( font , tr [ " Scanning filesystem... " ] , 5 , lineY ) ;
2010-02-04 13:33:47 +02:00
scanbg . blit ( s , 0 , 0 ) ;
s - > flip ( ) ;
lineY + = 26 ;
vector < string > files ;
2010-07-04 04:19:52 +03:00
scanPath ( CARD_ROOT , & files ) ;
2010-02-04 13:33:47 +02:00
stringstream ss ;
ss < < files . size ( ) ;
string str = " " ;
ss > > str ;
scanbg . write ( font , tr . translate ( " $1 files found. " , str . c_str ( ) , NULL ) , 5 , lineY ) ;
lineY + = 26 ;
scanbg . write ( font , tr [ " Creating links... " ] , 5 , lineY ) ;
scanbg . blit ( s , 0 , 0 ) ;
s - > flip ( ) ;
lineY + = 26 ;
string path , file ;
string : : size_type pos ;
uint linkCount = 0 ;
for ( uint i = 0 ; i < files . size ( ) ; i + + ) {
pos = files [ i ] . rfind ( " / " ) ;
if ( pos ! = string : : npos & & pos > 0 ) {
path = files [ i ] . substr ( 0 , pos + 1 ) ;
file = files [ i ] . substr ( pos + 1 , files [ i ] . length ( ) ) ;
if ( menu - > addLink ( path , file , " found " + file . substr ( file . length ( ) - 3 , 3 ) ) )
linkCount + + ;
}
}
ss . clear ( ) ;
ss < < linkCount ;
ss > > str ;
scanbg . write ( font , tr . translate ( " $1 links created. " , str . c_str ( ) , NULL ) , 5 , lineY ) ;
scanbg . blit ( s , 0 , 0 ) ;
s - > flip ( ) ;
lineY + = 26 ;
2012-12-08 06:03:33 +02:00
# ifdef ENABLE_CPUFREQ
2012-12-07 01:53:39 +02:00
setMenuClock ( ) ;
2012-12-08 06:03:33 +02:00
# endif
2010-02-04 13:33:47 +02:00
# endif
2011-10-23 09:57:52 +03:00
InputManager : : Button button ;
2010-09-17 23:34:26 +03:00
do {
button = input . waitForPressedButton ( ) ;
2011-10-23 09:57:52 +03:00
} while ( ( button ! = InputManager : : SETTINGS )
& & ( button ! = InputManager : : ACCEPT )
& & ( button ! = InputManager : : CANCEL ) ) ;
2010-02-04 13:33:47 +02:00
}
void GMenu2X : : scanPath ( string path , vector < string > * files ) {
DIR * dirp ;
struct stat st ;
struct dirent * dptr ;
string filepath , ext ;
if ( path [ path . length ( ) - 1 ] ! = ' / ' ) path + = " / " ;
if ( ( dirp = opendir ( path . c_str ( ) ) ) = = NULL ) return ;
while ( ( dptr = readdir ( dirp ) ) ) {
if ( dptr - > d_name [ 0 ] = = ' . ' )
continue ;
filepath = path + dptr - > d_name ;
int statRet = stat ( filepath . c_str ( ) , & st ) ;
if ( S_ISDIR ( st . st_mode ) )
scanPath ( filepath , files ) ;
if ( statRet ! = - 1 ) {
ext = filepath . substr ( filepath . length ( ) - 4 , 4 ) ;
2012-11-27 07:14:08 +02:00
# if defined(PLATFORM_A320) || defined(PLATFORM_GCW0) || defined(PLATFORM_NANONOTE)
2011-07-29 02:13:35 +03:00
if ( ext = = " .dge " )
2010-02-04 13:33:47 +02:00
# else
if ( ext = = " .pxml " )
# endif
files - > push_back ( filepath ) ;
}
}
closedir ( dirp ) ;
}
2011-10-23 18:27:29 +03:00
typedef struct {
unsigned short batt ;
unsigned short remocon ;
} MMSP2ADC ;
2010-02-04 13:33:47 +02:00
void GMenu2X : : setInputSpeed ( ) {
2013-08-09 19:18:51 +03:00
SDL_EnableKeyRepeat ( 250 , 150 ) ;
2010-02-04 13:33:47 +02:00
}
2012-12-08 06:03:33 +02:00
# ifdef ENABLE_CPUFREQ
2010-02-04 13:33:47 +02:00
void GMenu2X : : setClock ( unsigned mhz ) {
2011-09-19 17:26:42 +03:00
mhz = constrain ( mhz , cpuFreqMin , confInt [ " maxClock " ] ) ;
2012-11-27 07:14:08 +02:00
# if defined(PLATFORM_A320) || defined(PLATFORM_GCW0) || defined(PLATFORM_NANONOTE)
2010-07-04 04:04:42 +03:00
jz_cpuspeed ( mhz ) ;
2010-02-04 13:33:47 +02:00
# endif
}
2012-12-08 06:03:33 +02:00
# endif
2010-02-04 13:33:47 +02:00
2011-09-18 13:42:08 +03:00
string GMenu2X : : getDiskFree ( const char * path ) {
2010-02-04 13:33:47 +02:00
string df = " " ;
struct statvfs b ;
2011-09-18 13:42:08 +03:00
int ret = statvfs ( path , & b ) ;
2013-08-05 03:02:04 +03:00
if ( ret = = 0 ) {
2010-06-18 04:16:44 +03:00
// Make sure that the multiplication happens in 64 bits.
2013-08-05 03:02:04 +03:00
unsigned long freeMiB =
( ( unsigned long long ) b . f_bfree * b . f_bsize ) / ( 1024 * 1024 ) ;
unsigned long totalMiB =
( ( unsigned long long ) b . f_blocks * b . f_frsize ) / ( 1024 * 1024 ) ;
stringstream ss ;
if ( totalMiB > = 10000 ) {
ss < < ( freeMiB / 1024 ) < < " . " < < ( ( freeMiB % 1024 ) * 10 ) / 1024 < < " / "
< < ( totalMiB / 1024 ) < < " . " < < ( ( totalMiB % 1024 ) * 10 ) / 1024 < < " GiB " ;
} else {
ss < < freeMiB < < " / " < < totalMiB < < " MiB " ;
}
2010-02-04 13:33:47 +02:00
ss > > df ;
2010-09-17 23:31:09 +03:00
} else WARNING ( " statvfs failed with error '%s'. \n " , strerror ( errno ) ) ;
2010-02-04 13:33:47 +02:00
return df ;
}
2013-08-12 23:17:26 +03:00
int GMenu2X : : drawButton ( IconButton * btn , int x , int y ) {
2010-02-04 13:33:47 +02:00
if ( y < 0 ) y = resY + y ;
btn - > setPosition ( x , y - 7 ) ;
btn - > paint ( ) ;
return x + btn - > getRect ( ) . w + 6 ;
}
2010-05-02 15:29:09 +03:00
int GMenu2X : : drawButton ( Surface * s , const string & btn , const string & text , int x , int y ) {
2010-02-04 13:33:47 +02:00
if ( y < 0 ) y = resY + y ;
2012-04-11 00:01:16 +03:00
SDL_Rect re = { static_cast < Sint16 > ( x ) , static_cast < Sint16 > ( y - 7 ) , 0 , 16 } ;
2010-02-04 13:33:47 +02:00
if ( sc . skinRes ( " imgs/buttons/ " + btn + " .png " ) ! = NULL ) {
sc [ " imgs/buttons/ " + btn + " .png " ] - > blit ( s , x , y - 7 ) ;
2011-06-02 23:44:04 +03:00
re . w = sc [ " imgs/buttons/ " + btn + " .png " ] - > width ( ) + 3 ;
2013-08-03 23:30:12 +03:00
s - > write ( font , text , x + re . w , y , Font : : HAlignLeft , Font : : VAlignMiddle ) ;
2010-02-04 13:33:47 +02:00
re . w + = font - > getTextWidth ( text ) ;
}
return x + re . w + 6 ;
}
2010-05-02 15:29:09 +03:00
int GMenu2X : : drawButtonRight ( Surface * s , const string & btn , const string & text , int x , int y ) {
2010-02-04 13:33:47 +02:00
if ( y < 0 ) y = resY + y ;
if ( sc . skinRes ( " imgs/buttons/ " + btn + " .png " ) ! = NULL ) {
x - = 16 ;
sc [ " imgs/buttons/ " + btn + " .png " ] - > blit ( s , x , y - 7 ) ;
x - = 3 ;
2013-08-03 23:30:12 +03:00
s - > write ( font , text , x , y , Font : : HAlignRight , Font : : VAlignMiddle ) ;
2010-02-04 13:33:47 +02:00
return x - 6 - font - > getTextWidth ( text ) ;
}
return x - 6 ;
}
2013-08-14 11:49:09 +03:00
void GMenu2X : : drawScrollBar ( uint pageSize , uint totalSize , uint pagePos ) {
if ( totalSize < = pageSize ) {
// Everything fits on one screen, no scroll bar needed.
return ;
}
2010-02-04 13:33:47 +02:00
2013-08-14 13:56:15 +03:00
unsigned int top , height ;
tie ( top , height ) = getContentArea ( ) ;
top + = 1 ;
height - = 2 ;
2010-02-04 13:33:47 +02:00
2013-08-14 11:49:09 +03:00
s - > rectangle ( resX - 8 , top , 7 , height , skinConfColors [ COLOR_SELECTION_BG ] ) ;
2013-08-14 13:56:15 +03:00
top + = 2 ;
height - = 4 ;
2010-02-04 13:33:47 +02:00
2013-08-14 13:56:15 +03:00
const uint barSize = height * pageSize / totalSize ;
const uint barPos = ( height - barSize ) * pagePos / ( totalSize - pageSize ) ;
2010-02-04 13:33:47 +02:00
2013-08-14 13:56:15 +03:00
s - > box ( resX - 6 , top + barPos , 3 , barSize ,
2013-08-14 11:49:09 +03:00
skinConfColors [ COLOR_SELECTION_BG ] ) ;
2010-02-04 13:33:47 +02:00
}
void GMenu2X : : drawTopBar ( Surface * s ) {
2011-07-11 14:34:52 +03:00
Surface * bar = sc . skinRes ( " imgs/topbar.png " , false ) ;
2013-08-14 13:23:15 +03:00
if ( bar ) {
2010-02-04 13:33:47 +02:00
bar - > blit ( s , 0 , 0 ) ;
2013-08-14 13:23:15 +03:00
} else {
const int h = skinConfInt [ " topBarHeight " ] ;
s - > box ( 0 , 0 , resX , h , skinConfColors [ COLOR_TOP_BAR_BG ] ) ;
}
2010-02-04 13:33:47 +02:00
}
void GMenu2X : : drawBottomBar ( Surface * s ) {
2011-07-11 14:34:52 +03:00
Surface * bar = sc . skinRes ( " imgs/bottombar.png " , false ) ;
2013-08-14 13:23:15 +03:00
if ( bar ) {
2011-06-02 23:44:04 +03:00
bar - > blit ( s , 0 , resY - bar - > height ( ) ) ;
2013-08-14 13:23:15 +03:00
} else {
const int h = skinConfInt [ " bottomBarHeight " ] ;
s - > box ( 0 , resY - h , resX , h , skinConfColors [ COLOR_BOTTOM_BAR_BG ] ) ;
}
2010-02-04 13:33:47 +02:00
}