nestopia/source/win32/NstDialogPaths.cpp

490 lines
13 KiB
C++

////////////////////////////////////////////////////////////////////////////////////////
//
// Nestopia - NES/Famicom emulator written in C++
//
// Copyright (C) 2003-2008 Martin Freij
//
// This file is part of Nestopia.
//
// Nestopia 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.
//
// Nestopia 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 Nestopia; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
////////////////////////////////////////////////////////////////////////////////////////
#include "NstResourceString.hpp"
#include "NstApplicationInstance.hpp"
#include "NstWindowParam.hpp"
#include "NstWindowUser.hpp"
#include "NstDialogPaths.hpp"
#include "NstDialogBrowse.hpp"
namespace Nestopia
{
namespace Window
{
NST_COMPILE_ASSERT
(
IDC_PATHS_BATTERY - IDC_PATHS_IMAGE == IDC_PATHS_BATTERY_BROWSE - IDC_PATHS_IMAGE_BROWSE &&
IDC_PATHS_NST - IDC_PATHS_IMAGE == IDC_PATHS_NST_BROWSE - IDC_PATHS_IMAGE_BROWSE &&
IDC_PATHS_SAMPLES - IDC_PATHS_IMAGE == IDC_PATHS_SAMPLES_BROWSE - IDC_PATHS_IMAGE_BROWSE &&
IDC_PATHS_CHEATS - IDC_PATHS_IMAGE == IDC_PATHS_CHEATS_BROWSE - IDC_PATHS_IMAGE_BROWSE &&
IDC_PATHS_PATCHES - IDC_PATHS_IMAGE == IDC_PATHS_PATCHES_BROWSE - IDC_PATHS_IMAGE_BROWSE &&
IDC_PATHS_SCREENSHOTS - IDC_PATHS_IMAGE == IDC_PATHS_SCREENSHOTS_BROWSE - IDC_PATHS_IMAGE_BROWSE
);
struct Paths::Lut
{
struct A
{
ushort type;
ushort dlg;
wcstring def;
};
struct B
{
ushort type;
ushort dlg;
};
struct C
{
ushort type;
ushort dlg;
wcstring cfg;
};
static const A dirs[NUM_DIRS];
static const B flags[NUM_FLAGS];
static const C screenShots[NUM_SCREENSHOTS];
};
const Paths::Lut::A Paths::Lut::dirs[NUM_DIRS] =
{
{ DIR_IMAGE, IDC_PATHS_IMAGE, L"" },
{ DIR_SAVE, IDC_PATHS_BATTERY, L"save\\" },
{ DIR_STATE, IDC_PATHS_NST, L"states\\" },
{ DIR_SAMPLES, IDC_PATHS_SAMPLES, L"samples\\" },
{ DIR_CHEATS, IDC_PATHS_CHEATS, L"cheats\\" },
{ DIR_PATCHES, IDC_PATHS_PATCHES, L"patches\\" },
{ DIR_SCREENSHOT, IDC_PATHS_SCREENSHOTS, L"screenshots\\" }
};
const Paths::Lut::B Paths::Lut::flags[NUM_FLAGS] =
{
{ USE_LAST_IMAGE_DIR, IDC_PATHS_IMAGE_LAST },
{ READONLY_CARTRIDGE, IDC_PATHS_BATTERY_PROTECT },
{ AUTO_IMPORT_STATE_SLOTS, IDC_PATHS_NST_AUTO_IMPORT },
{ AUTO_EXPORT_STATE_SLOTS, IDC_PATHS_NST_AUTO_EXPORT },
{ CHEATS_AUTO_LOAD, IDC_PATHS_CHEATS_AUTO_LOAD },
{ CHEATS_AUTO_SAVE, IDC_PATHS_CHEATS_AUTO_SAVE },
{ PATCH_AUTO_APPLY, IDC_PATHS_PATCHES_AUTO_APPLY },
{ PATCH_BYPASS_VALIDATION, IDC_PATHS_PATCHES_BYPASS_VALIDATION },
{ COMPRESS_STATES, IDC_PATHS_NST_COMPRESS }
};
const Paths::Lut::C Paths::Lut::screenShots[NUM_SCREENSHOTS] =
{
{ SCREENSHOT_PNG, IDC_PATHS_SCREENSHOTS_PNG, L"png" },
{ SCREENSHOT_JPEG, IDC_PATHS_SCREENSHOTS_JPEG, L"jpg" },
{ SCREENSHOT_BMP, IDC_PATHS_SCREENSHOTS_BMP, L"bmp" }
};
struct Paths::Handlers
{
static const MsgHandler::Entry<Paths> messages[];
static const MsgHandler::Entry<Paths> commands[];
};
const MsgHandler::Entry<Paths> Paths::Handlers::messages[] =
{
{ WM_INITDIALOG, &Paths::OnInitDialog }
};
const MsgHandler::Entry<Paths> Paths::Handlers::commands[] =
{
{ IDC_PATHS_IMAGE_BROWSE, &Paths::OnCmdBrowse },
{ IDC_PATHS_BATTERY_BROWSE, &Paths::OnCmdBrowse },
{ IDC_PATHS_NST_BROWSE, &Paths::OnCmdBrowse },
{ IDC_PATHS_SAMPLES_BROWSE, &Paths::OnCmdBrowse },
{ IDC_PATHS_CHEATS_BROWSE, &Paths::OnCmdBrowse },
{ IDC_PATHS_PATCHES_BROWSE, &Paths::OnCmdBrowse },
{ IDC_PATHS_SCREENSHOTS_BROWSE, &Paths::OnCmdBrowse },
{ IDC_PATHS_IMAGE_LAST, &Paths::OnCmdLastVisited },
{ IDC_PATHS_DEFAULT, &Paths::OnCmdDefault },
{ IDOK, &Paths::OnCmdOk }
};
inline Paths::Settings::Flags::Flags()
: Collection::BitSet
(
1U << USE_LAST_IMAGE_DIR |
1U << AUTO_IMPORT_STATE_SLOTS |
1U << AUTO_EXPORT_STATE_SLOTS |
1U << COMPRESS_STATES
)
{}
Paths::Settings::Settings()
: screenShotFormat(SCREENSHOT_PNG) {}
Paths::Paths(const Configuration& cfg)
: dialog(IDD_PATHS,this,Handlers::messages,Handlers::commands)
{
Configuration::ConstSection paths( cfg["paths"] );
{
Configuration::ConstSection images( paths["images"] );
settings.dirs[DIR_IMAGE] = images["directory"].Str();
if (images["use-recent-directory"].Yes())
{
settings.flags[USE_LAST_IMAGE_DIR] = true;
}
else if (images["use-recent-directory"].No())
{
settings.flags[USE_LAST_IMAGE_DIR] = false;
}
}
{
Configuration::ConstSection saves( paths["saves"] );
settings.dirs[DIR_SAVE] = saves["directory"].Str();
if (saves["force-read-only"].Yes())
{
settings.flags[READONLY_CARTRIDGE] = true;
}
else if (saves["force-read-only"].No())
{
settings.flags[READONLY_CARTRIDGE] = false;
}
}
{
Configuration::ConstSection states( paths["states"] );
settings.dirs[DIR_STATE] = states["directory"].Str();
if (states["use-compression"].Yes())
{
settings.flags[COMPRESS_STATES] = true;
}
else if (states["use-compression"].No())
{
settings.flags[COMPRESS_STATES] = false;
}
if (states["auto-import"].Yes())
{
settings.flags[AUTO_IMPORT_STATE_SLOTS] = true;
}
else if (states["auto-import"].No())
{
settings.flags[AUTO_IMPORT_STATE_SLOTS] = false;
}
if (states["auto-export"].Yes())
{
settings.flags[AUTO_EXPORT_STATE_SLOTS] = true;
}
else if (states["auto-export"].No())
{
settings.flags[AUTO_EXPORT_STATE_SLOTS] = false;
}
}
{
Configuration::ConstSection samples( paths["samples"] );
settings.dirs[DIR_SAMPLES] = samples["directory"].Str();
}
{
Configuration::ConstSection patches( paths["cheats"] );
settings.dirs[DIR_CHEATS] = patches["directory"].Str();
if (patches["auto-load"].Yes())
{
settings.flags[CHEATS_AUTO_LOAD] = true;
}
else if (patches["auto-load"].No())
{
settings.flags[CHEATS_AUTO_LOAD] = false;
}
if (patches["auto-save"].Yes())
{
settings.flags[CHEATS_AUTO_SAVE] = true;
}
else if (patches["auto-save"].No())
{
settings.flags[CHEATS_AUTO_SAVE] = false;
}
}
{
Configuration::ConstSection patches( paths["patches"] );
settings.dirs[DIR_PATCHES] = patches["directory"].Str();
if (patches["auto-apply"].Yes())
{
settings.flags[PATCH_AUTO_APPLY] = true;
}
else if (patches["auto-apply"].No())
{
settings.flags[PATCH_AUTO_APPLY] = false;
}
if (patches["bypass-validation"].Yes())
{
settings.flags[PATCH_BYPASS_VALIDATION] = true;
}
else if (patches["bypass-validation"].No())
{
settings.flags[PATCH_BYPASS_VALIDATION] = false;
}
}
{
Configuration::ConstSection screenshots( paths["screenshots"] );
settings.dirs[DIR_SCREENSHOT] = screenshots["directory"].Str();
const GenericString format( screenshots["format"].Str() );
if (format.Length())
{
for (uint i=0; i < NUM_SCREENSHOTS; ++i)
{
if (format == Lut::screenShots[i].cfg)
{
settings.screenShotFormat = static_cast<ScreenShotFormat>(Lut::screenShots[i].type);
break;
}
}
}
}
for (uint i=0; i < NUM_DIRS; ++i)
UpdateDirectory( i );
}
Paths::~Paths()
{
}
void Paths::Save(Configuration& cfg) const
{
Configuration::Section paths( cfg["paths"] );
{
Configuration::Section images( paths["images"] );
images[ "directory" ].Str() = settings.dirs[DIR_IMAGE];
images[ "use-recent-directory" ].YesNo() = settings.flags[USE_LAST_IMAGE_DIR];
}
{
Configuration::Section saves( paths["saves"] );
saves[ "directory" ].Str() = settings.dirs[DIR_SAVE];
saves[ "force-read-only" ].YesNo() = settings.flags[READONLY_CARTRIDGE];
}
{
Configuration::Section states( paths["states"] );
states[ "directory" ].Str() = settings.dirs[DIR_STATE];
states[ "use-compression" ].YesNo() = settings.flags[COMPRESS_STATES];
states[ "auto-import" ].YesNo() = settings.flags[AUTO_IMPORT_STATE_SLOTS];
states[ "auto-export" ].YesNo() = settings.flags[AUTO_EXPORT_STATE_SLOTS];
}
{
Configuration::Section samples( paths["samples"] );
samples[ "directory" ].Str() = settings.dirs[DIR_SAMPLES];
}
{
Configuration::Section patches( paths["cheats"] );
patches[ "directory" ].Str() = settings.dirs[DIR_CHEATS];
patches[ "auto-load" ].YesNo() = settings.flags[CHEATS_AUTO_LOAD];
patches[ "auto-save" ].YesNo() = settings.flags[CHEATS_AUTO_SAVE];
}
{
Configuration::Section patches( paths["patches"] );
patches[ "directory" ].Str() = settings.dirs[DIR_PATCHES];
patches[ "auto-apply" ].YesNo() = settings.flags[PATCH_AUTO_APPLY];
patches[ "bypass-validation" ].YesNo() = settings.flags[PATCH_BYPASS_VALIDATION];
}
{
Configuration::Section screenshots( paths["screenshots"] );
screenshots[ "directory" ].Str() = settings.dirs[DIR_SCREENSHOT];
screenshots[ "format" ].Str() = Lut::screenShots[settings.screenShotFormat].cfg;
}
}
const GenericString Paths::GetScreenShotExtension() const
{
switch (settings.screenShotFormat)
{
case SCREENSHOT_JPEG: return L"jpg";
case SCREENSHOT_BMP: return L"bmp";
default: return L"png";
}
}
const Path Paths::GetDirectory(Type type) const
{
return Application::Instance::GetFullPath( settings.dirs[type] );
}
void Paths::UpdateDirectory(const uint i)
{
Path def( Application::Instance::GetExePath(Lut::dirs[i].def) );
Path& dir = settings.dirs[Lut::dirs[i].type];
bool useDef;
if (dir.Length())
{
dir.MakePretty( true );
useDef = (dir == def);
}
else
{
dir = def;
useDef = true;
}
def = Application::Instance::GetFullPath( dir );
if (::GetFileAttributes( def.Ptr() ) == INVALID_FILE_ATTRIBUTES)
{
if (useDef || User::Confirm( Resource::String(IDS_FILE_ASK_CREATE_DIR).Invoke(def) ))
{
if (!::CreateDirectory( def.Ptr(), NULL ))
{
if (useDef)
dir = Application::Instance::GetExePath().Directory();
else
User::Fail( IDS_FILE_ERR_CREATE_DIR );
}
}
}
}
void Paths::Update(const bool reset) const
{
for (uint i=0; i < NUM_DIRS; ++i)
dialog.Edit( Lut::dirs[i].dlg ) << (reset ? Application::Instance::GetExePath(Lut::dirs[i].def).Ptr() : settings.dirs[Lut::dirs[i].type].Ptr());
Settings::Flags flags;
if (!reset)
flags = settings.flags;
for (uint i=0; i < NUM_FLAGS; ++i)
dialog.CheckBox( Lut::flags[i].dlg ).Check( flags[Lut::flags[i].type] );
ScreenShotFormat screenShotFormat = SCREENSHOT_PNG;
if (!reset)
screenShotFormat = settings.screenShotFormat;
for (uint i=0; i < NUM_SCREENSHOTS; ++i)
dialog.RadioButton( Lut::screenShots[i].dlg ).Check( Lut::screenShots[i].type == screenShotFormat );
UpdateLastVisited();
}
void Paths::UpdateLastVisited() const
{
bool unchecked = dialog.CheckBox( IDC_PATHS_IMAGE_LAST ).Unchecked();
dialog.Control( IDC_PATHS_IMAGE ).Enable( unchecked );
dialog.Control( IDC_PATHS_IMAGE_BROWSE ).Enable( unchecked );
}
ibool Paths::OnInitDialog(Param&)
{
Update( false );
return true;
}
ibool Paths::OnCmdDefault(Param& param)
{
if (param.Button().Clicked())
Update( true );
return true;
}
ibool Paths::OnCmdBrowse(Param& param)
{
if (param.Button().Clicked())
{
const uint id = IDC_PATHS_IMAGE + (param.Button().GetId() - IDC_PATHS_IMAGE_BROWSE);
dialog.Edit( id ).Try() << Browser::SelectDirectory().Ptr();
}
return true;
}
ibool Paths::OnCmdLastVisited(Param& param)
{
if (param.Button().Clicked())
UpdateLastVisited();
return true;
}
ibool Paths::OnCmdOk(Param& param)
{
if (param.Button().Clicked())
{
for (uint i=0; i < NUM_DIRS; ++i)
{
dialog.Edit( Lut::dirs[i].dlg ) >> settings.dirs[Lut::dirs[i].type];
UpdateDirectory( i );
}
for (uint i=0; i < NUM_FLAGS; ++i)
settings.flags[Lut::flags[i].type] = dialog.CheckBox( Lut::flags[i].dlg ).Checked();
for (uint i=0; i < NUM_SCREENSHOTS; ++i)
{
if (dialog.RadioButton( Lut::screenShots[i].dlg ).Checked())
{
settings.screenShotFormat = static_cast<ScreenShotFormat>(Lut::screenShots[i].type);
break;
}
}
dialog.Close();
}
return true;
}
}
}