2012-06-14 01:33:50 +00:00
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers , whose names
* are too numerous to list here . Please refer to the COPYRIGHT
* file distributed with this source distribution .
*
* 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 . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 , USA .
2014-02-18 01:34:20 +00:00
*
2012-06-14 01:33:50 +00:00
*/
# include "gui/saveload-dialog.h"
2016-06-05 09:44:05 +00:00
2016-10-17 16:45:12 +00:00
# if defined(USE_CLOUD) && defined(USE_LIBCURL)
2016-06-05 09:44:05 +00:00
# include "backends/cloud/cloudmanager.h"
# include "backends/cloud/savessyncrequest.h"
# include "backends/networking/curl/connectionmanager.h"
2016-07-05 07:30:24 +00:00
# endif
2016-06-05 09:44:05 +00:00
2012-06-14 01:33:50 +00:00
# include "common/translation.h"
2012-07-01 13:58:42 +00:00
# include "common/config-manager.h"
2012-06-14 01:33:50 +00:00
# include "gui/message.h"
# include "gui/gui-manager.h"
# include "gui/ThemeEval.h"
2012-07-13 15:17:58 +00:00
# include "gui/widgets/edittext.h"
2012-06-14 01:33:50 +00:00
# include "graphics/scaler.h"
2016-06-05 16:26:51 +00:00
# include <common/savefile.h>
2012-06-14 01:33:50 +00:00
namespace GUI {
2016-10-17 16:45:12 +00:00
# if defined(USE_CLOUD) && defined(USE_LIBCURL)
2016-07-05 07:30:24 +00:00
2016-06-05 14:20:22 +00:00
enum {
kCancelSyncCmd = ' PDCS ' ,
kBackgroundSyncCmd = ' PDBS '
} ;
2016-06-07 13:52:36 +00:00
SaveLoadCloudSyncProgressDialog : : SaveLoadCloudSyncProgressDialog ( bool canRunInBackground ) : Dialog ( " SaveLoadCloudSyncProgress " ) , _close ( false ) {
2016-06-06 09:08:44 +00:00
_label = new StaticTextWidget ( this , " SaveLoadCloudSyncProgress.TitleText " , " Downloading saves... " ) ;
2016-06-05 15:07:55 +00:00
uint32 progress = ( uint32 ) ( 100 * CloudMan . getSyncDownloadingProgress ( ) ) ;
2016-06-06 09:08:44 +00:00
_progressBar = new SliderWidget ( this , " SaveLoadCloudSyncProgress.ProgressBar " ) ;
2016-06-06 07:37:38 +00:00
_progressBar - > setMinValue ( 0 ) ;
_progressBar - > setMaxValue ( 100 ) ;
_progressBar - > setValue ( progress ) ;
2016-06-06 11:48:08 +00:00
_progressBar - > setEnabled ( false ) ;
2016-06-06 09:08:44 +00:00
_percentLabel = new StaticTextWidget ( this , " SaveLoadCloudSyncProgress.PercentText " , Common : : String : : format ( " %u %% " , progress ) ) ;
2016-07-21 05:44:36 +00:00
new ButtonWidget ( this , " SaveLoadCloudSyncProgress.Cancel " , " Cancel " , 0 , kCancelSyncCmd , Common : : ASCII_ESCAPE ) ; // Cancel dialog
2016-06-07 13:52:36 +00:00
ButtonWidget * backgroundButton = new ButtonWidget ( this , " SaveLoadCloudSyncProgress.Background " , " Run in background " , 0 , kBackgroundSyncCmd , Common : : ASCII_RETURN ) ; // Confirm dialog
backgroundButton - > setEnabled ( canRunInBackground ) ;
draw ( ) ;
2016-06-05 14:20:22 +00:00
}
2016-06-06 11:48:08 +00:00
SaveLoadCloudSyncProgressDialog : : ~ SaveLoadCloudSyncProgressDialog ( ) {
CloudMan . setSyncTarget ( nullptr ) ; //not that dialog, at least
}
2016-06-05 14:20:22 +00:00
void SaveLoadCloudSyncProgressDialog : : handleCommand ( CommandSender * sender , uint32 cmd , uint32 data ) {
switch ( cmd ) {
2016-07-21 05:44:36 +00:00
case kSavesSyncProgressCmd :
2016-06-06 07:37:38 +00:00
_percentLabel - > setLabel ( Common : : String : : format ( " %u%% " , data ) ) ;
_progressBar - > setValue ( data ) ;
_progressBar - > draw ( ) ;
2016-06-05 14:20:22 +00:00
break ;
case kCancelSyncCmd :
setResult ( kCancelSyncCmd ) ;
close ( ) ;
break ;
case kSavesSyncEndedCmd :
case kBackgroundSyncCmd :
2016-06-05 15:07:36 +00:00
_close = true ;
2016-06-05 14:20:22 +00:00
break ;
}
Dialog : : handleCommand ( sender , cmd , data ) ;
}
2016-06-05 15:07:36 +00:00
void SaveLoadCloudSyncProgressDialog : : handleTickle ( ) {
if ( _close ) {
setResult ( kBackgroundSyncCmd ) ;
close ( ) ;
}
Dialog : : handleTickle ( ) ;
}
2016-07-05 07:30:24 +00:00
# endif
2016-06-05 15:07:36 +00:00
2012-07-24 21:46:54 +00:00
# ifndef DISABLE_SAVELOADCHOOSER_GRID
2012-07-13 15:17:58 +00:00
SaveLoadChooserType getRequestedSaveLoadDialog ( const MetaEngine & metaEngine ) {
2012-07-01 14:07:48 +00:00
const Common : : String & userConfig = ConfMan . get ( " gui_saveload_chooser " , Common : : ConfigManager : : kApplicationDomain ) ;
2012-10-28 20:42:22 +00:00
// Check (and update if necessary) the theme config here. This catches
// resolution changes, which happened after the GUI was closed. This
// should assure that the correct GUI width/height are returned below and
// prevent the logic from picking the grid dialog, even though it is not
// possible to use it.
g_gui . checkScreenChange ( ) ;
2012-07-13 15:17:58 +00:00
if ( g_gui . getWidth ( ) > = 640 & & g_gui . getHeight ( ) > = 400
2016-07-22 12:48:46 +00:00
& & metaEngine . hasFeature ( MetaEngine : : kSavesSupportMetaInfo )
& & metaEngine . hasFeature ( MetaEngine : : kSavesSupportThumbnail )
& & userConfig . equalsIgnoreCase ( " grid " ) ) {
2012-07-01 14:07:48 +00:00
// In case we are 640x400 or higher, this dialog is not in save mode,
// the user requested the grid dialog and the engines supports it we
// try to set it up.
return kSaveLoadDialogGrid ;
} else {
// In all other cases we want to use the list dialog.
return kSaveLoadDialogList ;
}
}
2012-06-29 13:52:56 +00:00
enum {
kListSwitchCmd = ' LIST ' ,
kGridSwitchCmd = ' GRID '
} ;
2012-07-24 21:46:54 +00:00
# endif // !DISABLE_SAVELOADCHOOSER_GRID
2012-06-29 13:52:56 +00:00
SaveLoadChooserDialog : : SaveLoadChooserDialog ( const Common : : String & dialogName , const bool saveMode )
2012-06-14 01:33:50 +00:00
: Dialog ( dialogName ) , _metaEngine ( 0 ) , _delSupport ( false ) , _metaInfoSupport ( false ) ,
2016-06-05 14:20:22 +00:00
_thumbnailSupport ( false ) , _saveDateSupport ( false ) , _playTimeSupport ( false ) , _saveMode ( saveMode ) ,
_dialogWasShown ( false )
2012-07-24 21:46:54 +00:00
# ifndef DISABLE_SAVELOADCHOOSER_GRID
, _listButton ( 0 ) , _gridButton ( 0 )
# endif // !DISABLE_SAVELOADCHOOSER_GRID
{
# ifndef DISABLE_SAVELOADCHOOSER_GRID
2012-06-29 13:52:56 +00:00
addChooserButtons ( ) ;
2012-07-24 21:46:54 +00:00
# endif // !DISABLE_SAVELOADCHOOSER_GRID
2012-06-14 01:33:50 +00:00
}
2012-06-29 13:52:56 +00:00
SaveLoadChooserDialog : : SaveLoadChooserDialog ( int x , int y , int w , int h , const bool saveMode )
2012-06-14 01:33:50 +00:00
: Dialog ( x , y , w , h ) , _metaEngine ( 0 ) , _delSupport ( false ) , _metaInfoSupport ( false ) ,
2016-06-05 14:20:22 +00:00
_thumbnailSupport ( false ) , _saveDateSupport ( false ) , _playTimeSupport ( false ) , _saveMode ( saveMode ) ,
_dialogWasShown ( false )
2012-07-24 21:46:54 +00:00
# ifndef DISABLE_SAVELOADCHOOSER_GRID
, _listButton ( 0 ) , _gridButton ( 0 )
# endif // !DISABLE_SAVELOADCHOOSER_GRID
{
# ifndef DISABLE_SAVELOADCHOOSER_GRID
2012-06-29 13:52:56 +00:00
addChooserButtons ( ) ;
2012-07-24 21:46:54 +00:00
# endif // !DISABLE_SAVELOADCHOOSER_GRID
2012-06-14 01:33:50 +00:00
}
2016-06-06 11:48:08 +00:00
SaveLoadChooserDialog : : ~ SaveLoadChooserDialog ( ) {
2016-10-17 16:45:12 +00:00
# if defined(USE_CLOUD) && defined(USE_LIBCURL)
2016-06-06 11:48:08 +00:00
CloudMan . setSyncTarget ( nullptr ) ; //not that dialog, at least
2016-07-05 07:30:24 +00:00
# endif
2016-06-06 11:48:08 +00:00
}
2012-06-14 01:33:50 +00:00
void SaveLoadChooserDialog : : open ( ) {
Dialog : : open ( ) ;
// So that quitting ScummVM will not cause the dialog result to say a
2014-08-19 18:42:20 +00:00
// saved game was selected.
2012-06-14 01:33:50 +00:00
setResult ( - 1 ) ;
2016-06-05 14:20:22 +00:00
_dialogWasShown = false ;
2012-06-14 01:33:50 +00:00
}
2016-07-04 11:45:50 +00:00
void SaveLoadChooserDialog : : close ( ) {
2016-10-17 16:45:12 +00:00
# if defined(USE_CLOUD) && defined(USE_LIBCURL)
2016-07-04 11:45:50 +00:00
CloudMan . setSyncTarget ( nullptr ) ; //not that dialog, at least
2016-07-05 07:30:24 +00:00
# endif
2016-07-04 11:45:50 +00:00
Dialog : : close ( ) ;
}
2012-06-14 01:33:50 +00:00
int SaveLoadChooserDialog : : run ( const Common : : String & target , const MetaEngine * metaEngine ) {
_metaEngine = metaEngine ;
_target = target ;
_delSupport = _metaEngine - > hasFeature ( MetaEngine : : kSupportsDeleteSave ) ;
_metaInfoSupport = _metaEngine - > hasFeature ( MetaEngine : : kSavesSupportMetaInfo ) ;
_thumbnailSupport = _metaInfoSupport & & _metaEngine - > hasFeature ( MetaEngine : : kSavesSupportThumbnail ) ;
_saveDateSupport = _metaInfoSupport & & _metaEngine - > hasFeature ( MetaEngine : : kSavesSupportCreationDate ) ;
_playTimeSupport = _metaInfoSupport & & _metaEngine - > hasFeature ( MetaEngine : : kSavesSupportPlayTime ) ;
return runIntern ( ) ;
}
2012-07-24 21:27:59 +00:00
void SaveLoadChooserDialog : : handleCommand ( CommandSender * sender , uint32 cmd , uint32 data ) {
2012-07-24 21:46:54 +00:00
# ifndef DISABLE_SAVELOADCHOOSER_GRID
2012-06-29 13:52:56 +00:00
switch ( cmd ) {
case kListSwitchCmd :
2012-07-01 14:07:48 +00:00
setResult ( kSwitchSaveLoadDialog ) ;
2012-07-01 13:58:42 +00:00
// We save the requested dialog type here to avoid the setting to be
// overwritten when our reflowLayout logic selects a different dialog
// type.
ConfMan . set ( " gui_saveload_chooser " , " list " , Common : : ConfigManager : : kApplicationDomain ) ;
2012-06-29 13:52:56 +00:00
close ( ) ;
break ;
case kGridSwitchCmd :
2012-07-01 14:07:48 +00:00
setResult ( kSwitchSaveLoadDialog ) ;
2012-07-01 13:58:42 +00:00
// See above.
ConfMan . set ( " gui_saveload_chooser " , " grid " , Common : : ConfigManager : : kApplicationDomain ) ;
2012-06-29 13:52:56 +00:00
close ( ) ;
break ;
default :
break ;
}
2012-07-24 21:46:54 +00:00
# endif // !DISABLE_SAVELOADCHOOSER_GRID
2012-06-29 13:52:56 +00:00
2016-10-17 16:45:12 +00:00
# if defined(USE_CLOUD) && defined(USE_LIBCURL)
2016-06-05 14:20:22 +00:00
if ( cmd = = kSavesSyncProgressCmd | | cmd = = kSavesSyncEndedCmd ) {
//this dialog only gets these commands if the progress dialog was shown and user clicked "run in background"
2016-06-06 04:25:49 +00:00
return updateSaveList ( ) ;
2016-06-05 14:20:22 +00:00
}
2016-07-05 07:30:24 +00:00
# endif
2016-06-05 14:20:22 +00:00
2012-06-29 13:52:56 +00:00
return Dialog : : handleCommand ( sender , cmd , data ) ;
}
2016-10-17 16:45:12 +00:00
# if defined(USE_CLOUD) && defined(USE_LIBCURL)
2016-06-05 09:44:05 +00:00
void SaveLoadChooserDialog : : runSaveSync ( bool hasSavepathOverride ) {
if ( ! CloudMan . isSyncing ( ) ) {
if ( hasSavepathOverride ) {
2016-09-18 11:05:16 +00:00
CloudMan . showCloudDisabledIcon ( ) ;
2016-06-05 09:44:05 +00:00
} else {
Cloud : : SavesSyncRequest * request = CloudMan . syncSaves ( ) ;
2016-07-22 12:48:46 +00:00
if ( request )
request - > setTarget ( this ) ;
2016-06-05 09:44:05 +00:00
}
}
}
2016-07-05 07:30:24 +00:00
# endif
2016-06-05 09:44:05 +00:00
2016-06-05 14:20:22 +00:00
void SaveLoadChooserDialog : : handleTickle ( ) {
2016-10-17 16:45:12 +00:00
# if defined(USE_CLOUD) && defined(USE_LIBCURL)
2016-06-05 14:20:22 +00:00
if ( ! _dialogWasShown & & CloudMan . isSyncing ( ) ) {
Common : : Array < Common : : String > files = CloudMan . getSyncingFiles ( ) ;
if ( ! files . empty ( ) ) {
2016-06-06 11:48:08 +00:00
{
2016-07-25 08:32:04 +00:00
SaveLoadCloudSyncProgressDialog dialog ( _metaEngine ? _metaEngine - > hasFeature ( MetaEngine : : kSimpleSavesNames ) : false ) ;
2016-06-06 11:48:08 +00:00
CloudMan . setSyncTarget ( & dialog ) ;
int result = dialog . runModal ( ) ;
if ( result = = kCancelSyncCmd ) {
CloudMan . cancelSync ( ) ;
}
2016-06-05 14:20:22 +00:00
}
2016-06-06 11:48:08 +00:00
//dialog changes syncTarget to nullptr after that }
2016-06-05 14:20:22 +00:00
CloudMan . setSyncTarget ( this ) ;
_dialogWasShown = true ;
2016-06-05 16:26:51 +00:00
updateSaveList ( ) ;
2016-06-05 14:20:22 +00:00
}
}
2016-07-05 07:30:24 +00:00
# endif
2016-06-05 14:20:22 +00:00
Dialog : : handleTickle ( ) ;
}
2012-07-24 21:46:54 +00:00
void SaveLoadChooserDialog : : reflowLayout ( ) {
# ifndef DISABLE_SAVELOADCHOOSER_GRID
addChooserButtons ( ) ;
const SaveLoadChooserType currentType = getType ( ) ;
const SaveLoadChooserType requestedType = getRequestedSaveLoadDialog ( * _metaEngine ) ;
// Change the dialog type if there is any need for it.
if ( requestedType ! = currentType ) {
setResult ( kSwitchSaveLoadDialog ) ;
close ( ) ;
}
# endif // !DISABLE_SAVELOADCHOOSER_GRID
Dialog : : reflowLayout ( ) ;
}
2016-07-05 07:30:24 +00:00
void SaveLoadChooserDialog : : updateSaveList ( ) {
2016-10-17 16:45:12 +00:00
# if defined(USE_CLOUD) && defined(USE_LIBCURL)
2016-07-21 05:44:36 +00:00
Common : : Array < Common : : String > files = CloudMan . getSyncingFiles ( ) ; //returns empty array if not syncing
2016-06-05 16:26:51 +00:00
g_system - > getSavefileManager ( ) - > updateSavefilesList ( files ) ;
2016-07-05 07:30:24 +00:00
# endif
2016-06-06 06:22:22 +00:00
listSaves ( ) ;
}
void SaveLoadChooserDialog : : listSaves ( ) {
2016-06-06 11:48:08 +00:00
if ( ! _metaEngine ) return ; //very strange
2016-06-06 06:22:22 +00:00
_saveList = _metaEngine - > listSaves ( _target . c_str ( ) ) ;
2016-10-17 16:45:12 +00:00
# if defined(USE_CLOUD) && defined(USE_LIBCURL)
2016-07-05 07:30:24 +00:00
//if there is Cloud support, add currently synced files as "locked" saves in the list
2016-07-25 08:32:04 +00:00
if ( _metaEngine - > hasFeature ( MetaEngine : : kSimpleSavesNames ) ) {
2016-06-07 13:33:00 +00:00
Common : : String pattern = _target + " .### " ;
Common : : Array < Common : : String > files = CloudMan . getSyncingFiles ( ) ; //returns empty array if not syncing
for ( uint32 i = 0 ; i < files . size ( ) ; + + i ) {
2016-07-22 12:48:46 +00:00
if ( ! files [ i ] . matchString ( pattern , true ) )
continue ;
2016-06-07 13:33:00 +00:00
//make up some slot number
int slotNum = 0 ;
2016-07-21 05:44:36 +00:00
for ( uint32 j = ( files [ i ] . size ( ) > 3 ? files [ i ] . size ( ) - 3 : 0 ) ; j < files [ i ] . size ( ) ; + + j ) { //3 last chars
2016-06-07 13:33:00 +00:00
char c = files [ i ] [ j ] ;
2016-07-22 12:48:46 +00:00
if ( c < ' 0 ' | | c > ' 9 ' )
continue ;
2016-06-07 13:33:00 +00:00
slotNum = slotNum * 10 + ( c - ' 0 ' ) ;
}
SaveStateDescriptor slot ( slotNum , files [ i ] ) ;
slot . setLocked ( true ) ;
_saveList . push_back ( slot ) ;
2016-06-06 06:22:22 +00:00
}
2016-06-07 13:33:00 +00:00
Common : : sort ( _saveList . begin ( ) , _saveList . end ( ) , SaveStateDescriptorSlotComparator ( ) ) ;
2016-06-06 06:22:22 +00:00
}
2016-07-05 07:30:24 +00:00
# endif
2016-06-05 16:26:51 +00:00
}
2012-07-24 21:46:54 +00:00
# ifndef DISABLE_SAVELOADCHOOSER_GRID
2012-06-29 13:52:56 +00:00
void SaveLoadChooserDialog : : addChooserButtons ( ) {
if ( _listButton ) {
removeWidget ( _listButton ) ;
delete _listButton ;
}
if ( _gridButton ) {
removeWidget ( _gridButton ) ;
delete _gridButton ;
}
_listButton = createSwitchButton ( " SaveLoadChooser.ListSwitch " , " L " , _ ( " List view " ) , ThemeEngine : : kImageList , kListSwitchCmd ) ;
_gridButton = createSwitchButton ( " SaveLoadChooser.GridSwitch " , " G " , _ ( " Grid view " ) , ThemeEngine : : kImageGrid , kGridSwitchCmd ) ;
2012-07-24 21:25:10 +00:00
if ( ! _metaInfoSupport | | ! _thumbnailSupport | | ! ( g_gui . getWidth ( ) > = 640 & & g_gui . getHeight ( ) > = 400 ) ) {
2012-06-29 13:52:56 +00:00
_gridButton - > setEnabled ( false ) ;
2012-07-24 21:25:10 +00:00
_listButton - > setEnabled ( false ) ;
}
2012-06-29 13:52:56 +00:00
}
2012-07-24 21:27:59 +00:00
ButtonWidget * SaveLoadChooserDialog : : createSwitchButton ( const Common : : String & name , const char * desc , const char * tooltip , const char * image , uint32 cmd ) {
2012-06-29 13:52:56 +00:00
ButtonWidget * button ;
# ifndef DISABLE_FANCY_THEMES
if ( g_gui . xmlEval ( ) - > getVar ( " Globals.ShowChooserPics " ) = = 1 & & g_gui . theme ( ) - > supportsImages ( ) ) {
button = new PicButtonWidget ( this , name , tooltip , cmd ) ;
( ( PicButtonWidget * ) button ) - > useThemeTransparency ( true ) ;
( ( PicButtonWidget * ) button ) - > setGfx ( g_gui . theme ( ) - > getImageSurface ( image ) ) ;
} else
# endif
button = new ButtonWidget ( this , name , desc , tooltip , cmd ) ;
return button ;
}
2012-07-24 21:46:54 +00:00
# endif // !DISABLE_SAVELOADCHOOSER_GRID
2012-06-29 13:52:56 +00:00
2012-06-14 01:33:50 +00:00
// SaveLoadChooserSimple implementation
enum {
kChooseCmd = ' CHOS ' ,
kDelCmd = ' DEL '
} ;
SaveLoadChooserSimple : : SaveLoadChooserSimple ( const String & title , const String & buttonLabel , bool saveMode )
2012-06-29 13:52:56 +00:00
: SaveLoadChooserDialog ( " SaveLoadChooser " , saveMode ) , _list ( 0 ) , _chooseButton ( 0 ) , _deleteButton ( 0 ) , _gfxWidget ( 0 ) {
2012-06-14 01:33:50 +00:00
_backgroundType = ThemeEngine : : kDialogBackgroundSpecial ;
new StaticTextWidget ( this , " SaveLoadChooser.Title " , title ) ;
// Add choice list
2012-07-24 21:27:59 +00:00
_list = new ListWidget ( this , " SaveLoadChooser.List " ) ;
_list - > setNumberingMode ( kListNumberingZero ) ;
2012-06-14 01:33:50 +00:00
_list - > setEditable ( saveMode ) ;
2012-07-24 21:27:59 +00:00
_gfxWidget = new GraphicsWidget ( this , 0 , 0 , 10 , 10 ) ;
2012-06-14 01:33:50 +00:00
_date = new StaticTextWidget ( this , 0 , 0 , 10 , 10 , _ ( " No date saved " ) , Graphics : : kTextAlignCenter ) ;
_time = new StaticTextWidget ( this , 0 , 0 , 10 , 10 , _ ( " No time saved " ) , Graphics : : kTextAlignCenter ) ;
_playtime = new StaticTextWidget ( this , 0 , 0 , 10 , 10 , _ ( " No playtime saved " ) , Graphics : : kTextAlignCenter ) ;
// Buttons
2012-07-24 21:27:59 +00:00
new ButtonWidget ( this , " SaveLoadChooser.Cancel " , _ ( " Cancel " ) , 0 , kCloseCmd ) ;
_chooseButton = new ButtonWidget ( this , " SaveLoadChooser.Choose " , buttonLabel , 0 , kChooseCmd ) ;
2012-06-14 01:33:50 +00:00
_chooseButton - > setEnabled ( false ) ;
2012-07-24 21:27:59 +00:00
_deleteButton = new ButtonWidget ( this , " SaveLoadChooser.Delete " , _ ( " Delete " ) , 0 , kDelCmd ) ;
2012-06-14 01:33:50 +00:00
_deleteButton - > setEnabled ( false ) ;
_delSupport = _metaInfoSupport = _thumbnailSupport = false ;
2012-07-24 21:27:59 +00:00
_container = new ContainerWidget ( this , 0 , 0 , 10 , 10 ) ;
// _container->setHints(THEME_HINT_USE_SHADOW);
2012-06-14 01:33:50 +00:00
}
int SaveLoadChooserSimple : : runIntern ( ) {
if ( _gfxWidget )
_gfxWidget - > setGfx ( 0 ) ;
_resultString . clear ( ) ;
reflowLayout ( ) ;
updateSaveList ( ) ;
return Dialog : : runModal ( ) ;
}
const Common : : String & SaveLoadChooserSimple : : getResultString ( ) const {
int selItem = _list - > getSelected ( ) ;
return ( selItem > = 0 ) ? _list - > getSelectedString ( ) : _resultString ;
}
void SaveLoadChooserSimple : : handleCommand ( CommandSender * sender , uint32 cmd , uint32 data ) {
int selItem = _list - > getSelected ( ) ;
switch ( cmd ) {
2012-07-24 21:27:59 +00:00
case kListItemActivatedCmd :
case kListItemDoubleClickedCmd :
2012-06-14 01:33:50 +00:00
if ( selItem > = 0 & & _chooseButton - > isEnabled ( ) ) {
if ( _list - > isEditable ( ) | | ! _list - > getSelectedString ( ) . empty ( ) ) {
_list - > endEditMode ( ) ;
if ( ! _saveList . empty ( ) ) {
setResult ( _saveList [ selItem ] . getSaveSlot ( ) ) ;
_resultString = _list - > getSelectedString ( ) ;
}
close ( ) ;
}
}
break ;
case kChooseCmd :
_list - > endEditMode ( ) ;
if ( ! _saveList . empty ( ) ) {
setResult ( _saveList [ selItem ] . getSaveSlot ( ) ) ;
_resultString = _list - > getSelectedString ( ) ;
}
close ( ) ;
break ;
2012-07-24 21:27:59 +00:00
case kListSelectionChangedCmd :
2012-06-14 01:33:50 +00:00
updateSelection ( true ) ;
break ;
case kDelCmd :
if ( selItem > = 0 & & _delSupport ) {
2014-08-19 18:42:20 +00:00
MessageDialog alert ( _ ( " Do you really want to delete this saved game? " ) ,
2012-06-14 01:33:50 +00:00
_ ( " Delete " ) , _ ( " Cancel " ) ) ;
2012-07-24 21:27:59 +00:00
if ( alert . runModal ( ) = = kMessageOK ) {
2012-06-14 01:33:50 +00:00
_metaEngine - > removeSaveState ( _target . c_str ( ) , _saveList [ selItem ] . getSaveSlot ( ) ) ;
setResult ( - 1 ) ;
_list - > setSelected ( - 1 ) ;
updateSaveList ( ) ;
updateSelection ( true ) ;
}
}
break ;
case kCloseCmd :
setResult ( - 1 ) ;
2013-07-15 11:44:24 +00:00
// Fall through
2012-06-14 01:33:50 +00:00
default :
SaveLoadChooserDialog : : handleCommand ( sender , cmd , data ) ;
}
}
void SaveLoadChooserSimple : : reflowLayout ( ) {
if ( g_gui . xmlEval ( ) - > getVar ( " Globals.SaveLoadChooser.ExtInfo.Visible " ) = = 1 & & _thumbnailSupport ) {
int16 x , y ;
uint16 w , h ;
if ( ! g_gui . xmlEval ( ) - > getWidgetData ( " SaveLoadChooser.Thumbnail " , x , y , w , h ) )
error ( " Error when loading position data for Save/Load Thumbnails " ) ;
int thumbW = kThumbnailWidth ;
int thumbH = kThumbnailHeight2 ;
int thumbX = x + ( w > > 1 ) - ( thumbW > > 1 ) ;
int thumbY = y + kLineHeight ;
int textLines = 0 ;
if ( ! _saveDateSupport )
textLines + + ;
if ( ! _playTimeSupport )
textLines + + ;
_container - > resize ( x , y , w , h - ( kLineHeight * textLines ) ) ;
_gfxWidget - > resize ( thumbX , thumbY , thumbW , thumbH ) ;
int height = thumbY + thumbH + kLineHeight ;
if ( _saveDateSupport ) {
_date - > resize ( thumbX , height , kThumbnailWidth , kLineHeight ) ;
height + = kLineHeight ;
_time - > resize ( thumbX , height , kThumbnailWidth , kLineHeight ) ;
height + = kLineHeight ;
}
if ( _playTimeSupport )
_playtime - > resize ( thumbX , height , kThumbnailWidth , kLineHeight ) ;
_container - > setVisible ( true ) ;
_gfxWidget - > setVisible ( true ) ;
_date - > setVisible ( _saveDateSupport ) ;
_time - > setVisible ( _saveDateSupport ) ;
_playtime - > setVisible ( _playTimeSupport ) ;
updateSelection ( false ) ;
} else {
_container - > setVisible ( false ) ;
_gfxWidget - > setVisible ( false ) ;
_date - > setVisible ( false ) ;
_time - > setVisible ( false ) ;
_playtime - > setVisible ( false ) ;
}
SaveLoadChooserDialog : : reflowLayout ( ) ;
}
void SaveLoadChooserSimple : : updateSelection ( bool redraw ) {
int selItem = _list - > getSelected ( ) ;
bool isDeletable = _delSupport ;
bool isWriteProtected = false ;
bool startEditMode = _list - > isEditable ( ) ;
2016-06-06 06:22:22 +00:00
bool isLocked = false ;
2012-06-14 01:33:50 +00:00
2012-08-12 12:56:20 +00:00
// We used to support letting the themes specify the fill color with our
// initial theme based GUI. But this support was dropped.
_gfxWidget - > setGfx ( - 1 , - 1 , 0 , 0 , 0 ) ;
2012-06-14 01:33:50 +00:00
_date - > setLabel ( _ ( " No date saved " ) ) ;
_time - > setLabel ( _ ( " No time saved " ) ) ;
_playtime - > setLabel ( _ ( " No playtime saved " ) ) ;
if ( selItem > = 0 & & _metaInfoSupport ) {
2016-06-06 06:22:22 +00:00
SaveStateDescriptor desc = ( _saveList [ selItem ] . getLocked ( ) ? _saveList [ selItem ] : _metaEngine - > querySaveMetaInfos ( _target . c_str ( ) , _saveList [ selItem ] . getSaveSlot ( ) ) ) ;
2012-06-14 01:33:50 +00:00
isDeletable = desc . getDeletableFlag ( ) & & _delSupport ;
isWriteProtected = desc . getWriteProtectedFlag ( ) ;
2016-06-06 06:22:22 +00:00
isLocked = desc . getLocked ( ) ;
2012-06-14 01:33:50 +00:00
// Don't allow the user to change the description of write protected games
if ( isWriteProtected )
startEditMode = false ;
if ( _thumbnailSupport ) {
const Graphics : : Surface * thumb = desc . getThumbnail ( ) ;
if ( thumb ) {
_gfxWidget - > setGfx ( thumb ) ;
_gfxWidget - > useAlpha ( 256 ) ;
}
}
if ( _saveDateSupport ) {
const Common : : String & saveDate = desc . getSaveDate ( ) ;
if ( ! saveDate . empty ( ) )
_date - > setLabel ( _ ( " Date: " ) + saveDate ) ;
const Common : : String & saveTime = desc . getSaveTime ( ) ;
if ( ! saveTime . empty ( ) )
_time - > setLabel ( _ ( " Time: " ) + saveTime ) ;
}
if ( _playTimeSupport ) {
const Common : : String & playTime = desc . getPlayTime ( ) ;
if ( ! playTime . empty ( ) )
_playtime - > setLabel ( _ ( " Playtime: " ) + playTime ) ;
}
}
if ( _list - > isEditable ( ) ) {
2016-06-06 06:22:22 +00:00
// Disable the save button if slot is locked, nothing is selected,
// or if the selected game is write protected
_chooseButton - > setEnabled ( ! isLocked & & selItem > = 0 & & ! isWriteProtected ) ;
2012-06-14 01:33:50 +00:00
if ( startEditMode ) {
_list - > startEditMode ( ) ;
2016-11-29 10:43:57 +00:00
if ( _chooseButton - > isEnabled ( ) & & _list - > getSelectedString ( ) = = _ ( " Untitled saved game " ) & &
2012-06-14 01:33:50 +00:00
_list - > getSelectionColor ( ) = = ThemeEngine : : kFontColorAlternate ) {
_list - > setEditString ( " " ) ;
_list - > setEditColor ( ThemeEngine : : kFontColorNormal ) ;
}
}
} else {
2016-06-06 06:22:22 +00:00
// Disable the load button if slot is locked, nothing is selected,
// or if an empty list item is selected.
_chooseButton - > setEnabled ( ! isLocked & & selItem > = 0 & & ! _list - > getSelectedString ( ) . empty ( ) ) ;
2012-06-14 01:33:50 +00:00
}
// Delete will always be disabled if the engine doesn't support it.
2016-06-06 06:22:22 +00:00
_deleteButton - > setEnabled ( isDeletable & & ! isLocked & & ( selItem > = 0 ) & & ( ! _list - > getSelectedString ( ) . empty ( ) ) ) ;
2012-06-14 01:33:50 +00:00
if ( redraw ) {
_gfxWidget - > draw ( ) ;
_date - > draw ( ) ;
_time - > draw ( ) ;
_playtime - > draw ( ) ;
_chooseButton - > draw ( ) ;
_deleteButton - > draw ( ) ;
draw ( ) ;
}
}
2012-09-26 00:45:34 +00:00
void SaveLoadChooserSimple : : open ( ) {
SaveLoadChooserDialog : : open ( ) ;
// Scroll the list to the last used entry.
_list - > scrollTo ( ConfMan . getInt ( " gui_saveload_last_pos " ) ) ;
}
2012-06-14 01:33:50 +00:00
void SaveLoadChooserSimple : : close ( ) {
2012-09-26 00:45:34 +00:00
// Save the current scroll position/used entry.
const int result = getResult ( ) ;
if ( result > = 0 ) {
ConfMan . setInt ( " gui_saveload_last_pos " , result ) ;
} else {
// Use the current scroll position here.
// TODO: This means we canceled the dialog (or switch to the grid). Do
// we want to save this position here? Does the user want that?
// TODO: Do we want to save the current scroll position or the
// currently selected item here? The scroll position is what the user
// currently sees and seems to make more sense.
ConfMan . setInt ( " gui_saveload_last_pos " , _list - > getCurrentScrollPos ( ) ) ;
}
2012-06-14 01:33:50 +00:00
_metaEngine = 0 ;
_target . clear ( ) ;
_saveList . clear ( ) ;
_list - > setList ( StringArray ( ) ) ;
SaveLoadChooserDialog : : close ( ) ;
}
void SaveLoadChooserSimple : : updateSaveList ( ) {
2016-06-05 16:26:51 +00:00
SaveLoadChooserDialog : : updateSaveList ( ) ;
2012-06-14 01:33:50 +00:00
int curSlot = 0 ;
int saveSlot = 0 ;
StringArray saveNames ;
ListWidget : : ColorList colors ;
for ( SaveStateList : : const_iterator x = _saveList . begin ( ) ; x ! = _saveList . end ( ) ; + + x ) {
// Handle gaps in the list of save games
saveSlot = x - > getSaveSlot ( ) ;
if ( curSlot < saveSlot ) {
while ( curSlot < saveSlot ) {
SaveStateDescriptor dummySave ( curSlot , " " ) ;
_saveList . insert_at ( curSlot , dummySave ) ;
saveNames . push_back ( dummySave . getDescription ( ) ) ;
colors . push_back ( ThemeEngine : : kFontColorNormal ) ;
curSlot + + ;
}
// Sync the save list iterator
for ( x = _saveList . begin ( ) ; x ! = _saveList . end ( ) ; + + x ) {
if ( x - > getSaveSlot ( ) = = saveSlot )
break ;
}
}
2016-11-29 10:43:57 +00:00
// Show "Untitled saved game" for empty/whitespace saved game descriptions
2012-06-14 01:33:50 +00:00
Common : : String description = x - > getDescription ( ) ;
Common : : String trimmedDescription = description ;
trimmedDescription . trim ( ) ;
if ( trimmedDescription . empty ( ) ) {
2016-11-29 10:43:57 +00:00
description = _ ( " Untitled saved game " ) ;
2012-06-14 01:33:50 +00:00
colors . push_back ( ThemeEngine : : kFontColorAlternate ) ;
} else {
2016-06-06 06:22:22 +00:00
colors . push_back ( ( x - > getLocked ( ) ? ThemeEngine : : kFontColorAlternate : ThemeEngine : : kFontColorNormal ) ) ;
2012-06-14 01:33:50 +00:00
}
saveNames . push_back ( description ) ;
curSlot + + ;
}
// Fill the rest of the save slots with empty saves
int maximumSaveSlots = _metaEngine - > getMaximumSaveSlot ( ) ;
# ifdef __DS__
// Low memory on the DS means too many save slots are impractical, so limit
// the maximum here.
if ( maximumSaveSlots > 99 ) {
maximumSaveSlots = 99 ;
}
# endif
Common : : String emptyDesc ;
for ( int i = curSlot ; i < = maximumSaveSlots ; i + + ) {
saveNames . push_back ( emptyDesc ) ;
SaveStateDescriptor dummySave ( i , " " ) ;
_saveList . push_back ( dummySave ) ;
colors . push_back ( ThemeEngine : : kFontColorNormal ) ;
}
_list - > setList ( saveNames , & colors ) ;
2016-06-05 16:26:51 +00:00
draw ( ) ;
2012-06-14 01:33:50 +00:00
}
2012-07-24 21:24:17 +00:00
// SaveLoadChooserGrid implementation
2012-06-15 20:39:57 +00:00
2012-07-24 21:46:54 +00:00
# ifndef DISABLE_SAVELOADCHOOSER_GRID
2012-06-15 20:39:57 +00:00
enum {
kNextCmd = ' NEXT ' ,
2012-07-13 15:17:58 +00:00
kPrevCmd = ' PREV ' ,
kNewSaveCmd = ' SAVE '
2012-06-15 20:39:57 +00:00
} ;
2012-07-24 21:24:17 +00:00
SaveLoadChooserGrid : : SaveLoadChooserGrid ( const Common : : String & title , bool saveMode )
2012-07-13 15:17:58 +00:00
: SaveLoadChooserDialog ( " SaveLoadChooser " , saveMode ) , _lines ( 0 ) , _columns ( 0 ) , _entriesPerPage ( 0 ) ,
_curPage ( 0 ) , _newSaveContainer ( 0 ) , _nextFreeSaveSlot ( 0 ) , _buttons ( ) {
2012-06-15 20:39:57 +00:00
_backgroundType = ThemeEngine : : kDialogBackgroundSpecial ;
new StaticTextWidget ( this , " SaveLoadChooser.Title " , title ) ;
// Buttons
2012-07-24 21:27:59 +00:00
new ButtonWidget ( this , " SaveLoadChooser.Delete " , _ ( " Cancel " ) , 0 , kCloseCmd ) ;
_nextButton = new ButtonWidget ( this , " SaveLoadChooser.Choose " , _ ( " Next " ) , 0 , kNextCmd ) ;
2012-06-15 20:39:57 +00:00
_nextButton - > setEnabled ( false ) ;
2012-07-24 21:27:59 +00:00
_prevButton = new ButtonWidget ( this , " SaveLoadChooser.Cancel " , _ ( " Prev " ) , 0 , kPrevCmd ) ;
2012-06-15 20:39:57 +00:00
_prevButton - > setEnabled ( false ) ;
2012-07-01 14:47:40 +00:00
// Page display
2012-07-24 21:27:59 +00:00
_pageDisplay = new StaticTextWidget ( this , " SaveLoadChooser.PageDisplay " , Common : : String ( ) ) ;
2012-07-01 14:47:40 +00:00
_pageDisplay - > setAlign ( Graphics : : kTextAlignRight ) ;
2012-06-15 20:39:57 +00:00
}
2012-07-24 21:24:17 +00:00
SaveLoadChooserGrid : : ~ SaveLoadChooserGrid ( ) {
2012-07-01 15:17:04 +00:00
removeWidget ( _pageDisplay ) ;
delete _pageDisplay ;
}
2012-07-24 21:24:17 +00:00
const Common : : String & SaveLoadChooserGrid : : getResultString ( ) const {
2012-07-13 15:17:58 +00:00
return _resultString ;
2012-06-15 20:39:57 +00:00
}
2012-07-24 21:27:59 +00:00
void SaveLoadChooserGrid : : handleCommand ( CommandSender * sender , uint32 cmd , uint32 data ) {
2012-08-14 21:48:24 +00:00
if ( cmd < = _entriesPerPage & & cmd + _curPage * _entriesPerPage < = _saveList . size ( ) ) {
2012-07-13 15:17:58 +00:00
const SaveStateDescriptor & desc = _saveList [ cmd - 1 + _curPage * _entriesPerPage ] ;
if ( _saveMode ) {
_resultString = desc . getDescription ( ) ;
}
setResult ( desc . getSaveSlot ( ) ) ;
2012-06-15 20:39:57 +00:00
close ( ) ;
}
switch ( cmd ) {
case kNextCmd :
+ + _curPage ;
updateSaves ( ) ;
draw ( ) ;
break ;
case kPrevCmd :
- - _curPage ;
updateSaves ( ) ;
draw ( ) ;
break ;
2012-07-13 15:17:58 +00:00
case kNewSaveCmd :
setResult ( _nextFreeSaveSlot ) ;
close ( ) ;
break ;
2012-06-15 20:39:57 +00:00
case kCloseCmd :
setResult ( - 1 ) ;
2013-07-15 11:44:24 +00:00
// Fall through
2012-06-15 20:39:57 +00:00
default :
SaveLoadChooserDialog : : handleCommand ( sender , cmd , data ) ;
}
}
2012-07-24 21:24:17 +00:00
void SaveLoadChooserGrid : : handleMouseWheel ( int x , int y , int direction ) {
2012-06-15 20:39:57 +00:00
if ( direction > 0 ) {
if ( _nextButton - > isEnabled ( ) ) {
+ + _curPage ;
updateSaves ( ) ;
draw ( ) ;
}
} else {
if ( _prevButton - > isEnabled ( ) ) {
- - _curPage ;
updateSaves ( ) ;
draw ( ) ;
}
}
}
2016-06-05 16:26:51 +00:00
void SaveLoadChooserGrid : : updateSaveList ( ) {
SaveLoadChooserDialog : : updateSaveList ( ) ;
updateSaves ( ) ;
draw ( ) ;
}
2012-07-24 21:24:17 +00:00
void SaveLoadChooserGrid : : open ( ) {
2012-06-15 20:39:57 +00:00
SaveLoadChooserDialog : : open ( ) ;
2016-06-06 06:22:22 +00:00
listSaves ( ) ;
2012-07-13 15:17:58 +00:00
_resultString . clear ( ) ;
2012-09-26 00:11:39 +00:00
// Load information to restore the last page the user had open.
assert ( _entriesPerPage ! = 0 ) ;
const uint lastPos = ConfMan . getInt ( " gui_saveload_last_pos " ) ;
const uint listSize = _saveList . size ( ) ;
2012-09-26 14:10:35 +00:00
uint bestMatch = 0 ;
uint diff = 0xFFFFFFFF ;
// We look for the nearest available slot, since a slot might be missing
// due to the user deleting it via the list based chooser, by deleting
// it by hand, etc.
for ( uint i = 0 ; i < listSize ; + + i ) {
uint curDiff = ABS ( _saveList [ i ] . getSaveSlot ( ) - ( int ) lastPos ) ;
if ( curDiff < diff ) {
diff = curDiff ;
bestMatch = i ;
}
2012-09-26 00:11:39 +00:00
}
2012-09-26 14:10:35 +00:00
_curPage = bestMatch / _entriesPerPage ;
2012-07-13 15:17:58 +00:00
// Determine the next free save slot for save mode
if ( _saveMode ) {
int lastSlot = - 1 ;
_nextFreeSaveSlot = - 1 ;
for ( SaveStateList : : const_iterator x = _saveList . begin ( ) ; x ! = _saveList . end ( ) ; + + x ) {
const int curSlot = x - > getSaveSlot ( ) ;
// In case there was a gap found use the slot.
if ( lastSlot + 1 < curSlot ) {
2014-12-29 13:56:02 +00:00
// Check that the save slot can be used for user saves.
SaveStateDescriptor desc = _metaEngine - > querySaveMetaInfos ( _target . c_str ( ) , lastSlot + 1 ) ;
if ( ! desc . getWriteProtectedFlag ( ) ) {
_nextFreeSaveSlot = lastSlot + 1 ;
break ;
}
2012-07-13 15:17:58 +00:00
}
lastSlot = curSlot ;
}
// Use the next available slot otherwise.
2014-12-29 13:56:02 +00:00
const int maxSlot = _metaEngine - > getMaximumSaveSlot ( ) ;
for ( int i = lastSlot ; _nextFreeSaveSlot = = - 1 & & i < maxSlot ; + + i ) {
// Check that the save slot can be used for user saves.
SaveStateDescriptor desc = _metaEngine - > querySaveMetaInfos ( _target . c_str ( ) , i + 1 ) ;
if ( ! desc . getWriteProtectedFlag ( ) ) {
_nextFreeSaveSlot = i + 1 ;
}
2012-07-13 15:17:58 +00:00
}
}
2012-06-15 20:39:57 +00:00
updateSaves ( ) ;
}
2012-07-24 21:24:17 +00:00
void SaveLoadChooserGrid : : reflowLayout ( ) {
2012-08-12 13:16:27 +00:00
// HACK: The page display is not available in low resolution layout. We
// remove and readd the widget here to avoid our GUI from erroring out.
2012-07-01 14:47:40 +00:00
removeWidget ( _pageDisplay ) ;
if ( g_gui . xmlEval ( ) - > getVar ( " Globals.ShowChooserPageDisplay " ) = = 1 ) {
_pageDisplay - > init ( ) ;
2012-07-24 21:34:35 +00:00
}
2012-07-01 14:47:40 +00:00
2012-06-15 20:39:57 +00:00
SaveLoadChooserDialog : : reflowLayout ( ) ;
destroyButtons ( ) ;
2012-08-12 13:16:27 +00:00
// HACK: The whole code below really works around the fact, that we have
// no easy way to dynamically layout widgets.
2012-06-15 20:39:57 +00:00
const uint16 availableWidth = getWidth ( ) - 20 ;
uint16 availableHeight ;
int16 x , y ;
uint16 w ;
g_gui . xmlEval ( ) - > getWidgetData ( " SaveLoadChooser.List " , x , y , w , availableHeight ) ;
const int16 buttonWidth = kThumbnailWidth + 6 ;
const int16 buttonHeight = kThumbnailHeight2 + 6 ;
const int16 containerFrameWidthAdd = 10 ;
const int16 containerFrameHeightAdd = 0 ;
const int16 containerWidth = buttonWidth + containerFrameWidthAdd ;
const int16 containerHeight = buttonHeight + kLineHeight + containerFrameHeightAdd ;
const int16 defaultSpacingHorizontal = 4 ;
2012-06-29 14:16:36 +00:00
const int16 defaultSpacingVertical = 8 ;
2012-06-15 20:39:57 +00:00
const int16 slotAreaWidth = containerWidth + defaultSpacingHorizontal ;
2012-06-29 12:58:33 +00:00
const int16 slotAreaHeight = containerHeight + defaultSpacingVertical ;
2012-06-15 20:39:57 +00:00
const uint oldEntriesPerPage = _entriesPerPage ;
_columns = MAX < uint > ( 1 , availableWidth / slotAreaWidth ) ;
_lines = MAX < uint > ( 1 , availableHeight / slotAreaHeight ) ;
_entriesPerPage = _columns * _lines ;
2012-07-13 15:17:58 +00:00
// In save mode the first button is always "New Save", thus we need to
// adjust the entries per page here.
if ( _saveMode ) {
- - _entriesPerPage ;
}
2012-06-15 20:39:57 +00:00
// Recalculate the page number
if ( ! _saveList . empty ( ) & & oldEntriesPerPage ! = 0 ) {
2012-07-13 15:17:58 +00:00
if ( _entriesPerPage ! = 0 ) {
_curPage = ( _curPage * oldEntriesPerPage ) / _entriesPerPage ;
} else {
_curPage = 0 ;
}
2012-06-15 20:39:57 +00:00
}
const uint addX = _columns > 1 ? ( availableWidth % slotAreaWidth ) / ( _columns - 1 ) : 0 ;
2012-06-29 12:57:54 +00:00
//const uint addY = _lines > 1 ? (availableHeight % slotAreaHeight) / (_lines - 1) : 0;
2012-06-15 20:39:57 +00:00
_buttons . reserve ( _lines * _columns ) ;
y + = defaultSpacingVertical / 2 ;
2012-06-29 12:57:54 +00:00
for ( uint curLine = 0 ; curLine < _lines ; + + curLine , y + = slotAreaHeight /* + addY*/ ) {
2012-06-15 20:39:57 +00:00
for ( uint curColumn = 0 , curX = x + defaultSpacingHorizontal / 2 ; curColumn < _columns ; + + curColumn , curX + = slotAreaWidth + addX ) {
2012-07-09 00:17:57 +00:00
int dstY = containerFrameHeightAdd / 2 ;
int dstX = containerFrameWidthAdd / 2 ;
2012-06-15 20:39:57 +00:00
2012-07-13 15:17:58 +00:00
// In the save mode we will always create a new save button as the first button.
if ( _saveMode & & curLine = = 0 & & curColumn = = 0 ) {
_newSaveContainer = new ContainerWidget ( this , curX , y , containerWidth , containerHeight ) ;
2016-09-18 15:39:11 +00:00
ButtonWidget * newSave = new ButtonWidget ( _newSaveContainer , dstX , dstY , buttonWidth , buttonHeight , _ ( " New Save " ) , _ ( " Create a new saved game " ) , kNewSaveCmd ) ;
2012-07-13 15:17:58 +00:00
// In case no more slots are free, we will disable the new save button
if ( _nextFreeSaveSlot = = - 1 ) {
newSave - > setEnabled ( false ) ;
}
continue ;
}
ContainerWidget * container = new ContainerWidget ( this , curX , y , containerWidth , containerHeight ) ;
container - > setVisible ( false ) ;
// Command 0 cannot be used, since it won't be send. Thus we will adjust
// command number here, if required. This is only the case for load mode
// since for save mode, the first button used is index 1 anyway.
uint buttonCmd = curLine * _columns + curColumn ;
if ( ! _saveMode ) {
buttonCmd + = 1 ;
}
2012-09-26 02:17:31 +00:00
2012-07-13 15:17:58 +00:00
PicButtonWidget * button = new PicButtonWidget ( container , dstX , dstY , buttonWidth , buttonHeight , 0 , buttonCmd ) ;
2012-06-15 20:39:57 +00:00
dstY + = buttonHeight ;
2012-07-09 00:17:57 +00:00
StaticTextWidget * description = new StaticTextWidget ( container , dstX , dstY , buttonWidth , kLineHeight , Common : : String ( ) , Graphics : : kTextAlignLeft ) ;
2012-06-15 20:39:57 +00:00
_buttons . push_back ( SlotButton ( container , button , description ) ) ;
}
}
if ( ! _target . empty ( ) )
updateSaves ( ) ;
}
2012-07-24 21:24:17 +00:00
void SaveLoadChooserGrid : : close ( ) {
2012-09-26 00:11:39 +00:00
// Save the current page.
const int result = getResult ( ) ;
if ( result > = 0 & & result ! = _nextFreeSaveSlot ) {
// If the user selected a slot we use that one. We ignore new slots
// here, since otherwise the dialog would reset to page 0 when the
// user cancels the savename dialog.
ConfMan . setInt ( " gui_saveload_last_pos " , result ) ;
} else {
// Otherwise save the first entry on the current page.
// This is less precise than the solution above, since the number of
// entries shown differs between save and load version of the dialog,
// thus it might wrap to a different page than expected.
// Similar things happen on resolution changes.
// TODO: Should we ignore this here? Is the user likely to be
// interested in having this page restored when he canceled?
2012-09-26 14:10:35 +00:00
ConfMan . setInt ( " gui_saveload_last_pos " , ! _saveList . empty ( ) ? _saveList [ _curPage * _entriesPerPage ] . getSaveSlot ( ) : 0 ) ;
2012-09-26 00:11:39 +00:00
}
2012-06-15 20:39:57 +00:00
SaveLoadChooserDialog : : close ( ) ;
hideButtons ( ) ;
}
2012-07-24 21:24:17 +00:00
int SaveLoadChooserGrid : : runIntern ( ) {
2012-07-13 15:17:58 +00:00
int slot ;
do {
const SaveLoadChooserType currentType = getType ( ) ;
const SaveLoadChooserType requestedType = getRequestedSaveLoadDialog ( * _metaEngine ) ;
// Catch resolution changes when the save name dialog was open.
if ( currentType ! = requestedType ) {
setResult ( kSwitchSaveLoadDialog ) ;
return kSwitchSaveLoadDialog ;
}
slot = runModal ( ) ;
} while ( _saveMode & & slot > = 0 & & ! selectDescription ( ) ) ;
2012-09-26 00:11:39 +00:00
// Special case for new save games. We need to handle this here, since
2012-09-26 02:17:31 +00:00
// we cannot handle it in close() without problems.
2012-09-26 00:11:39 +00:00
if ( slot = = _nextFreeSaveSlot ) {
ConfMan . setInt ( " gui_saveload_last_pos " , slot ) ;
}
2012-07-13 15:17:58 +00:00
return slot ;
}
2012-07-24 21:24:17 +00:00
bool SaveLoadChooserGrid : : selectDescription ( ) {
2012-07-13 15:17:58 +00:00
_savenameDialog . setDescription ( _resultString ) ;
_savenameDialog . setTargetSlot ( getResult ( ) ) ;
if ( _savenameDialog . runModal ( ) = = 0 ) {
_resultString = _savenameDialog . getDescription ( ) ;
return true ;
} else {
return false ;
}
2012-06-15 20:39:57 +00:00
}
2012-07-24 21:24:17 +00:00
void SaveLoadChooserGrid : : destroyButtons ( ) {
2012-07-13 15:17:58 +00:00
if ( _newSaveContainer ) {
removeWidget ( _newSaveContainer ) ;
delete _newSaveContainer ;
_newSaveContainer = 0 ;
}
2012-06-15 20:39:57 +00:00
for ( ButtonArray : : iterator i = _buttons . begin ( ) , end = _buttons . end ( ) ; i ! = end ; + + i ) {
removeWidget ( i - > container ) ;
2012-06-29 13:55:46 +00:00
delete i - > container ;
2012-06-15 20:39:57 +00:00
}
_buttons . clear ( ) ;
}
2012-07-24 21:24:17 +00:00
void SaveLoadChooserGrid : : hideButtons ( ) {
2012-06-15 20:39:57 +00:00
for ( ButtonArray : : iterator i = _buttons . begin ( ) , end = _buttons . end ( ) ; i ! = end ; + + i ) {
i - > button - > setGfx ( 0 ) ;
i - > setVisible ( false ) ;
}
}
2012-07-24 21:24:17 +00:00
void SaveLoadChooserGrid : : updateSaves ( ) {
2012-06-15 20:39:57 +00:00
hideButtons ( ) ;
for ( uint i = _curPage * _entriesPerPage , curNum = 0 ; i < _saveList . size ( ) & & curNum < _entriesPerPage ; + + i , + + curNum ) {
const uint saveSlot = _saveList [ i ] . getSaveSlot ( ) ;
2016-06-06 06:22:22 +00:00
SaveStateDescriptor desc = ( _saveList [ i ] . getLocked ( ) ? _saveList [ i ] : _metaEngine - > querySaveMetaInfos ( _target . c_str ( ) , saveSlot ) ) ;
2012-06-15 20:39:57 +00:00
SlotButton & curButton = _buttons [ curNum ] ;
curButton . setVisible ( true ) ;
2012-06-29 14:15:46 +00:00
const Graphics : : Surface * thumbnail = desc . getThumbnail ( ) ;
if ( thumbnail ) {
curButton . button - > setGfx ( desc . getThumbnail ( ) ) ;
} else {
curButton . button - > setGfx ( kThumbnailWidth , kThumbnailHeight2 , 0 , 0 , 0 ) ;
}
2012-06-15 20:39:57 +00:00
curButton . description - > setLabel ( Common : : String : : format ( " %d. %s " , saveSlot , desc . getDescription ( ) . c_str ( ) ) ) ;
2012-06-20 01:42:32 +00:00
Common : : String tooltip ( _ ( " Name: " ) ) ;
tooltip + = desc . getDescription ( ) ;
if ( _saveDateSupport ) {
const Common : : String & saveDate = desc . getSaveDate ( ) ;
if ( ! saveDate . empty ( ) ) {
tooltip + = " \n " ;
tooltip + = _ ( " Date: " ) + saveDate ;
}
const Common : : String & saveTime = desc . getSaveTime ( ) ;
if ( ! saveTime . empty ( ) ) {
tooltip + = " \n " ;
tooltip + = _ ( " Time: " ) + saveTime ;
}
}
if ( _playTimeSupport ) {
const Common : : String & playTime = desc . getPlayTime ( ) ;
if ( ! playTime . empty ( ) ) {
tooltip + = " \n " ;
tooltip + = _ ( " Playtime: " ) + playTime ;
}
}
curButton . button - > setTooltip ( tooltip ) ;
2012-07-13 15:17:58 +00:00
// In save mode we disable the button, when it's write protected.
// TODO: Maybe we should not display it at all then?
if ( _saveMode & & desc . getWriteProtectedFlag ( ) ) {
curButton . button - > setEnabled ( false ) ;
} else {
curButton . button - > setEnabled ( true ) ;
}
2016-06-06 11:48:08 +00:00
//that would make it look "disabled" if slot is locked
curButton . button - > setEnabled ( ! desc . getLocked ( ) ) ;
curButton . description - > setEnabled ( ! desc . getLocked ( ) ) ;
2012-06-15 20:39:57 +00:00
}
2012-09-26 00:49:24 +00:00
const uint numPages = ( _entriesPerPage ! = 0 & & ! _saveList . empty ( ) ) ? ( ( _saveList . size ( ) + _entriesPerPage - 1 ) / _entriesPerPage ) : 1 ;
2012-07-01 14:47:40 +00:00
_pageDisplay - > setLabel ( Common : : String : : format ( " %u/%u " , _curPage + 1 , numPages ) ) ;
2012-06-15 20:39:57 +00:00
if ( _curPage > 0 )
_prevButton - > setEnabled ( true ) ;
else
_prevButton - > setEnabled ( false ) ;
if ( ( _curPage + 1 ) * _entriesPerPage < _saveList . size ( ) )
_nextButton - > setEnabled ( true ) ;
else
_nextButton - > setEnabled ( false ) ;
}
2012-07-13 15:17:58 +00:00
SavenameDialog : : SavenameDialog ( )
: Dialog ( " SavenameDialog " ) {
_title = new StaticTextWidget ( this , " SavenameDialog.DescriptionText " , Common : : String ( ) ) ;
new ButtonWidget ( this , " SavenameDialog.Cancel " , _ ( " Cancel " ) , 0 , kCloseCmd ) ;
2012-07-25 15:21:36 +00:00
new ButtonWidget ( this , " SavenameDialog.Ok " , _ ( " OK " ) , 0 , kOKCmd ) ;
2012-07-13 15:17:58 +00:00
_description = new EditTextWidget ( this , " SavenameDialog.Description " , Common : : String ( ) , 0 , 0 , kOKCmd ) ;
2016-06-01 09:18:17 +00:00
_targetSlot = 0 ;
2012-07-13 15:17:58 +00:00
}
void SavenameDialog : : setDescription ( const Common : : String & desc ) {
_description - > setEditString ( desc ) ;
}
const Common : : String & SavenameDialog : : getDescription ( ) {
return _description - > getEditString ( ) ;
}
void SavenameDialog : : open ( ) {
Dialog : : open ( ) ;
setResult ( - 1 ) ;
_title - > setLabel ( Common : : String : : format ( _ ( " Enter a description for slot %d: " ) , _targetSlot ) ) ;
}
2012-07-24 21:27:59 +00:00
void SavenameDialog : : handleCommand ( CommandSender * sender , uint32 cmd , uint32 data ) {
2012-07-13 15:17:58 +00:00
switch ( cmd ) {
case kOKCmd :
setResult ( 0 ) ;
close ( ) ;
break ;
default :
Dialog : : handleCommand ( sender , cmd , data ) ;
}
}
2012-07-24 21:46:54 +00:00
# endif // !DISABLE_SAVELOADCHOOSER_GRID
2012-06-14 01:33:50 +00:00
} // End of namespace GUI