nestopia/source/win32/NstDialogNetPlay.cpp

326 lines
8.7 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 "NstIoLog.hpp"
#include "NstIoStream.hpp"
#include "NstIoFile.hpp"
#include "NstApplicationInstance.hpp"
#include "NstWindowParam.hpp"
#include "NstWindowDropFiles.hpp"
#include "NstManagerPaths.hpp"
#include "NstDialogNetPlay.hpp"
#include "../core/NstXml.hpp"
#include <CommCtrl.h>
namespace Nestopia
{
namespace Window
{
struct Netplay::Handlers
{
static const MsgHandler::Entry<Netplay> messages[];
static const MsgHandler::Entry<Netplay> commands[];
static const Control::NotificationHandler::Entry<Netplay> notifications[];
};
const MsgHandler::Entry<Netplay> Netplay::Handlers::messages[] =
{
{ WM_INITDIALOG, &Netplay::OnInitDialog },
{ WM_DROPFILES, &Netplay::OnDropFiles }
};
const MsgHandler::Entry<Netplay> Netplay::Handlers::commands[] =
{
{ IDC_NETPLAY_ADD, &Netplay::OnAdd },
{ IDC_NETPLAY_REMOVE, &Netplay::OnRemove },
{ IDC_NETPLAY_CLEAR, &Netplay::OnClear },
{ IDC_NETPLAY_DEFAULT, &Netplay::OnDefault },
{ IDC_NETPLAY_LAUNCH, &Netplay::OnLaunch },
{ IDC_NETPLAY_PLAY_FULLSCREEN, &Netplay::OnFullscreen }
};
const Control::NotificationHandler::Entry<Netplay> Netplay::Handlers::notifications[] =
{
{ LVN_KEYDOWN, &Netplay::OnKeyDown },
{ LVN_ITEMCHANGED, &Netplay::OnItemChanged },
{ LVN_INSERTITEM, &Netplay::OnInsertItem },
{ LVN_DELETEITEM, &Netplay::OnDeleteItem }
};
bool Netplay::Games::Less::operator () (const Path& a,const Path& b) const
{
return a.Target().File() < b.Target().File();
}
Netplay::Games::Games()
: state(UNINITIALIZED) {}
Netplay::Netplay(Managers::Emulator& e,const Managers::Paths& p,bool fullscreen)
:
dialog ( IDD_NETPLAY, this, Handlers::messages, Handlers::commands ),
doFullscreen ( fullscreen ),
paths ( p ),
emulator ( e ),
notifications ( IDC_NETPLAY_GAMELIST, dialog.Messages(), this, Handlers::notifications )
{
}
Netplay::~Netplay()
{
}
void Netplay::LoadFile()
{
try
{
//const Path path( Application::Instance::GetExePath(L"netplaylist.xml") );
const Path path( Application::Instance::GetConfigPath(L"netplaylist.xml") );//bg
if (path.FileExists())
{
typedef Nes::Core::Xml Xml;
Xml xml;
{
Io::Stream::In stream( path );
xml.Read( stream );
}
if (!xml.GetRoot().IsType( L"netplaylist" ))
throw 1;
for (Xml::Node node(xml.GetRoot().GetFirstChild()); node; node=node.GetNextSibling())
{
if (!node.IsType( L"file" ))
throw 1;
Add( node.GetValue() );
}
Io::Log() << "Netplay: loaded game list from \"netplaylist.xml\"\r\n";
}
else
{
Io::Log() << "Netplay: game list file \"netplaylist.xml\" not present..\r\n";
}
}
catch (...)
{
games.state = Games::DIRTY;
Io::Log() << "Netplay: warning, couldn't load game list \"netplaylist.xml\"!\r\n";
}
}
void Netplay::SaveFile() const
{
if (games.state == Games::DIRTY)
{
//const Path path( Application::Instance::GetExePath(L"netplaylist.xml") );
const Path path( Application::Instance::GetConfigPath(L"netplaylist.xml") );//bg
if (!games.paths.empty())
{
try
{
typedef Nes::Core::Xml Xml;
Xml xml;
Xml::Node root( xml.Create( L"netplaylist" ) );
root.AddAttribute( L"version", L"1.0" );
for (Games::Paths::const_iterator it(games.paths.begin()), end(games.paths.end()); it != end; ++it)
root.AddChild( L"file", it->Ptr() );
Io::Stream::Out stream( path );
xml.Write( root, stream );
Io::Log() << "Netplay: saved game list to \"netplaylist.xml\"\r\n";
}
catch (...)
{
Io::Log() << "Netplay: warning, couldn't save game list to \"netplaylist.xml\"!\r\n";
}
}
else if (path.FileExists())
{
if (Io::File::Delete( path.Ptr() ))
Io::Log() << "Netplay: game list empty, deleted \"netplaylist.xml\"\r\n";
else
Io::Log() << "Netplay: warning, couldn't delete \"netplaylist.xml\"!\r\n";
}
}
}
wcstring Netplay::GetPath(wcstring const path) const
{
Games::Paths::const_iterator it(games.paths.find( path ));
return it != games.paths.end() ? it->Ptr() : NULL;
}
void Netplay::Add(Path path)
{
enum
{
TYPES = Managers::Paths::File::GAME|Managers::Paths::File::ARCHIVE
};
if (path.Length() && games.paths.size() < Games::LIMIT && paths.CheckFile( path, TYPES ) && games.paths.insert( path ).second)
{
games.state = Games::DIRTY;
if (dialog)
dialog.ListView( IDC_NETPLAY_GAMELIST ).Add( path.Target().File() );
}
}
ibool Netplay::OnInitDialog(Param&)
{
dialog.CheckBox( IDC_NETPLAY_PLAY_FULLSCREEN ).Check( doFullscreen );
dialog.CheckBox( IDC_NETPLAY_REMOVE ).Disable();
if (games.state == Games::UNINITIALIZED)
{
LoadFile();
}
else
{
Control::ListView list( dialog.ListView( IDC_NETPLAY_GAMELIST ) );
list.Reserve( games.paths.size() );
for (Games::Paths::const_iterator it(games.paths.begin()), end(games.paths.end()); it != end; ++it)
list.Add( it->Target().File().Ptr() );
}
dialog.CheckBox( IDC_NETPLAY_CLEAR ).Enable( games.paths.size() );
dialog.CheckBox( IDC_NETPLAY_LAUNCH ).Enable( games.paths.size() );
return true;
}
ibool Netplay::OnAdd(Param& param)
{
if (param.Button().Clicked())
Add( paths.BrowseLoad(Managers::Paths::File::GAME|Managers::Paths::File::ARCHIVE) );
return true;
}
ibool Netplay::OnRemove(Param& param)
{
if (param.Button().Clicked())
dialog.ListView( IDC_NETPLAY_GAMELIST ).Selection().Delete();
return true;
}
ibool Netplay::OnClear(Param& param)
{
if (param.Button().Clicked())
dialog.ListView( IDC_NETPLAY_GAMELIST ).Clear();
return true;
}
ibool Netplay::OnDefault(Param& param)
{
if (param.Button().Clicked())
{
doFullscreen = false;
dialog.CheckBox( IDC_NETPLAY_PLAY_FULLSCREEN ).Check( false );
}
return true;
}
ibool Netplay::OnLaunch(Param& param)
{
if (param.Button().Clicked())
dialog.Close( LAUNCH );
return true;
}
ibool Netplay::OnFullscreen(Param& param)
{
if (param.Button().Clicked())
doFullscreen = dialog.CheckBox( IDC_NETPLAY_PLAY_FULLSCREEN ).Checked();
return true;
}
ibool Netplay::OnDropFiles(Param& param)
{
DropFiles dropFiles( param );
if (dropFiles.Inside( dialog.ListView( IDC_NETPLAY_GAMELIST ).GetWindow() ))
{
for (uint i=0, n=dropFiles.Size(); i < n; ++i)
Add( dropFiles[i] );
}
return true;
}
void Netplay::OnKeyDown(const NMHDR& nmhdr)
{
switch (reinterpret_cast<const NMLVKEYDOWN&>(nmhdr).wVKey)
{
case VK_INSERT: dialog.PostCommand( IDC_NETPLAY_ADD ); break;
case VK_DELETE: dialog.PostCommand( IDC_NETPLAY_REMOVE ); break;
}
}
void Netplay::OnItemChanged(const NMHDR& nmhdr)
{
const NMLISTVIEW& nm = reinterpret_cast<const NMLISTVIEW&>(nmhdr);
if ((nm.uOldState ^ nm.uNewState) & LVIS_SELECTED)
dialog.CheckBox( IDC_NETPLAY_REMOVE ).Enable( nm.uNewState & LVIS_SELECTED );
}
void Netplay::OnInsertItem(const NMHDR&)
{
dialog.CheckBox( IDC_NETPLAY_CLEAR ).Enable();
dialog.CheckBox( IDC_NETPLAY_LAUNCH ).Enable();
}
void Netplay::OnDeleteItem(const NMHDR& nmhdr)
{
Games::Paths::iterator it(games.paths.begin());
for (int i=reinterpret_cast<const NMLISTVIEW&>(nmhdr).iItem; i > 0; --i)
++it;
games.paths.erase( it );
games.state = Games::DIRTY;
if (dialog.ListView( IDC_NETPLAY_GAMELIST ).Size() <= 1)
{
dialog.CheckBox( IDC_NETPLAY_CLEAR ).Disable();
dialog.CheckBox( IDC_NETPLAY_LAUNCH ).Disable();
dialog.CheckBox( IDC_NETPLAY_REMOVE ).Disable();
}
}
}
}