mirror of
https://github.com/0ldsk00l/nestopia.git
synced 2025-04-02 10:31:51 -04:00
408 lines
12 KiB
C++
408 lines
12 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 "resource/resource.h"
|
|
#include "NstResourceString.hpp"
|
|
#include "NstResourceIcon.hpp"
|
|
#include "NstWindowParam.hpp"
|
|
#include "NstSystemKeyboard.hpp"
|
|
#include "NstDialogLauncher.hpp"
|
|
#include "NstDialogInesHeader.hpp"
|
|
|
|
namespace Nestopia
|
|
{
|
|
namespace Window
|
|
{
|
|
struct Launcher::Handlers
|
|
{
|
|
static const MsgHandler::Entry<Launcher> messages[];
|
|
static const Menu::CmdHandler::Entry<Launcher> commands[];
|
|
static const Control::NotificationHandler::Entry<Launcher> listNotifications[];
|
|
static const Control::NotificationHandler::Entry<Launcher> treeNotifications[];
|
|
};
|
|
|
|
const MsgHandler::Entry<Launcher> Launcher::Handlers::messages[] =
|
|
{
|
|
{ WM_INITDIALOG, &Launcher::OnInitDialog },
|
|
{ WM_CLOSE, &Launcher::OnClose },
|
|
{ WM_DESTROY, &Launcher::OnDestroy },
|
|
{ WM_SIZE, &Launcher::OnSize },
|
|
{ WM_DROPFILES, &Launcher::OnDropFiles }
|
|
};
|
|
|
|
const Menu::CmdHandler::Entry<Launcher> Launcher::Handlers::commands[] =
|
|
{
|
|
{ IDM_LAUNCHER_FILE_RUN, &Launcher::OnCmdFileRun },
|
|
{ IDM_LAUNCHER_FILE_EDITHEADER, &Launcher::OnCmdEditHeader },
|
|
{ IDM_LAUNCHER_FILE_REFRESH, &Launcher::OnCmdFileRefresh },
|
|
{ IDM_LAUNCHER_VIEW_SHOWGRIDS, &Launcher::OnCmdViewShowGrids },
|
|
{ IDM_LAUNCHER_VIEW_SHOWDATABASECORRECTED, &Launcher::OnCmdViewShowDatabaseCorrected },
|
|
{ IDM_LAUNCHER_VIEW_ONTOP, &Launcher::OnCmdViewShowOnTop },
|
|
{ IDM_LAUNCHER_OPTIONS_COLORS, &Launcher::OnCmdOptionsColors },
|
|
{ IDM_LAUNCHER_OPTIONS_PATHS, &Launcher::OnCmdOptionsPaths }
|
|
};
|
|
|
|
const Control::NotificationHandler::Entry<Launcher> Launcher::Handlers::listNotifications[] =
|
|
{
|
|
{ LVN_GETDISPINFO, &Launcher::OnListGetDisplayInfo },
|
|
{ LVN_KEYDOWN, &Launcher::OnListKeyDown },
|
|
{ LVN_COLUMNCLICK, &Launcher::OnListColumnClick },
|
|
{ LVN_ITEMACTIVATE, &Launcher::OnListItemActivate },
|
|
{ LVN_ITEMCHANGED, &Launcher::OnListItemChanged },
|
|
{ LVN_INSERTITEM, &Launcher::OnListInsertItem },
|
|
{ LVN_DELETEALLITEMS, &Launcher::OnListDeleteAllItems },
|
|
{ LVN_DELETEITEM, &Launcher::OnListDeleteItem }
|
|
};
|
|
|
|
const Control::NotificationHandler::Entry<Launcher> Launcher::Handlers::treeNotifications[] =
|
|
{
|
|
{ TVN_SELCHANGING, &Launcher::OnTreeSelectionChanging }
|
|
};
|
|
|
|
Launcher::Launcher(const Nes::Cartridge::Database& database,const Managers::Paths& p,const Configuration& cfg)
|
|
:
|
|
dialog ( IDD_LAUNCHER, this, Handlers::messages ),
|
|
menu ( IDR_MENU_LAUNCHER ),
|
|
listNotifications ( IDC_LAUNCHER_LIST, dialog.Messages() ),
|
|
treeNotifications ( IDC_LAUNCHER_TREE, dialog.Messages() ),
|
|
statusBar ( dialog, STATUSBAR_SECOND_FIELD_WIDTH ),
|
|
list ( dialog, menu.Commands(), p, cfg, database ),
|
|
colors ( cfg )
|
|
{
|
|
menu.Commands().Add( this, Handlers::commands );
|
|
dialog.Commands().Add( CMD_ENTER, this, &Launcher::OnCmdEnter );
|
|
listNotifications.Add( this, Handlers::listNotifications );
|
|
treeNotifications.Add( this, Handlers::treeNotifications );
|
|
|
|
{
|
|
Configuration::ConstSection launcher( cfg["launcher"] );
|
|
|
|
menu[IDM_LAUNCHER_VIEW_ONTOP].Check( launcher["view"]["show"]["on-top"].Yes() );
|
|
|
|
Configuration::ConstSection size( launcher["window-size"] );
|
|
|
|
initialSize.x = size["x"].Int();
|
|
initialSize.y = size["y"].Int();
|
|
|
|
if (!initialSize.x || !initialSize.y)
|
|
{
|
|
initialSize.x = 0;
|
|
initialSize.y = 0;
|
|
}
|
|
}
|
|
|
|
HeapString name;
|
|
|
|
for (uint i=0; i < 6; ++i)
|
|
{
|
|
static const ushort keys[6][2] =
|
|
{
|
|
{ IDM_LAUNCHER_FILE_RUN, VK_RETURN },
|
|
{ IDM_LAUNCHER_FILE_EDITHEADER, VK_F4 },
|
|
{ IDM_LAUNCHER_FILE_REFRESH, VK_F5 },
|
|
{ IDM_LAUNCHER_EDIT_FIND, VK_F3 },
|
|
{ IDM_LAUNCHER_EDIT_INSERT, VK_INSERT },
|
|
{ IDM_LAUNCHER_EDIT_REMOVE, VK_DELETE }
|
|
};
|
|
|
|
menu[keys[i][0]].Text() >> name;
|
|
menu[keys[i][0]].Text() << (name << '\t' << System::Keyboard::GetName( keys[i][1] ));
|
|
}
|
|
}
|
|
|
|
Launcher::~Launcher()
|
|
{
|
|
Close();
|
|
}
|
|
|
|
void Launcher::Save(Configuration& cfg,bool saveSize,bool saveFiles)
|
|
{
|
|
Configuration::Section launcher( cfg["launcher"] );
|
|
|
|
if (saveSize)
|
|
{
|
|
Configuration::Section size( cfg["window-size"] );
|
|
|
|
size["x"].Int() = initialSize.x;
|
|
size["y"].Int() = initialSize.y;
|
|
}
|
|
|
|
launcher["view"]["show"]["on-top"].YesNo() = menu[IDM_LAUNCHER_VIEW_ONTOP].Checked();
|
|
|
|
list.Save( cfg, saveFiles );
|
|
colors.Save( cfg );
|
|
}
|
|
|
|
void Launcher::Open(bool child)
|
|
{
|
|
menu[IDM_LAUNCHER_VIEW_ONTOP].Enable( !child );
|
|
dialog.Open( child ? Dialog::MODELESS_CHILD : Dialog::MODELESS_FREE );
|
|
}
|
|
|
|
void Launcher::Close()
|
|
{
|
|
dialog.Close();
|
|
}
|
|
|
|
void Launcher::Synchronize(HWND hWnd) const
|
|
{
|
|
if (dialog.IsOpen() && menu[IDM_LAUNCHER_VIEW_ONTOP].Enabled() && menu[IDM_LAUNCHER_VIEW_ONTOP].Unchecked())
|
|
dialog.Position().BringBehind( hWnd );
|
|
}
|
|
|
|
ibool Launcher::OnInitDialog(Param&)
|
|
{
|
|
menu.Hook( dialog );
|
|
menu.Show();
|
|
|
|
statusBar.Enable();
|
|
|
|
if (menu[IDM_LAUNCHER_VIEW_ONTOP].Enabled())
|
|
dialog.MakeTopMost( menu[IDM_LAUNCHER_VIEW_ONTOP].Checked() );
|
|
|
|
list = dialog.ListView( IDC_LAUNCHER_LIST );
|
|
tree = dialog.TreeView( IDC_LAUNCHER_TREE );
|
|
|
|
dialog.Send
|
|
(
|
|
WM_SETICON,
|
|
ICON_SMALL,
|
|
static_cast<HICON>(Resource::Icon(Application::Instance::GetIconStyle() == Application::Instance::ICONSTYLE_NES ? IDI_PAD : IDI_PAD_J))
|
|
);
|
|
|
|
margin = dialog.Coordinates().Corner() - list.GetWindow().Coordinates().Corner();
|
|
|
|
list.SetColors( colors.GetBackgroundColor(), colors.GetForegroundColor() );
|
|
tree.SetColors( colors.GetBackgroundColor(), colors.GetForegroundColor() );
|
|
|
|
menu[ IDM_LAUNCHER_VIEW_SHOWGRIDS ].Check( list.GetStyle() & LVS_EX_GRIDLINES );
|
|
menu[ IDM_LAUNCHER_VIEW_SHOWDATABASECORRECTED ].Check( list.DatabaseCorrectionEnabled() );
|
|
menu[ IDM_LAUNCHER_FILE_REFRESH ].Enable( list.CanRefresh() );
|
|
|
|
if (initialSize.x && initialSize.y)
|
|
dialog.Size() = initialSize;
|
|
else
|
|
initialSize = dialog.GetPlacement().Size();
|
|
|
|
return true;
|
|
}
|
|
|
|
ibool Launcher::OnClose(Param&)
|
|
{
|
|
Close();
|
|
return true;
|
|
}
|
|
|
|
ibool Launcher::OnDestroy(Param&)
|
|
{
|
|
tree.Close();
|
|
list.Close();
|
|
|
|
initialSize = dialog.GetPlacement().Size();
|
|
|
|
return true;
|
|
}
|
|
|
|
ibool Launcher::OnSize(Param& param)
|
|
{
|
|
if (param.wParam != SIZE_MINIMIZED)
|
|
{
|
|
const Point corner( dialog.Coordinates().Corner() - margin - list.GetWindow().Position() );
|
|
|
|
list.GetWindow().Size() = corner;
|
|
tree.GetWindow().Size() = Point( tree.GetWindow().Coordinates().Width(), corner.y );
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
ibool Launcher::OnCmdEnter(Param&)
|
|
{
|
|
OnCmdFileRun();
|
|
return true;
|
|
}
|
|
|
|
ibool Launcher::OnDropFiles(Param& param)
|
|
{
|
|
list.Insert( param );
|
|
return true;
|
|
}
|
|
|
|
void Launcher::UpdateItemCount(const uint count) const
|
|
{
|
|
if (count == 0 || count == 1)
|
|
{
|
|
menu[IDM_LAUNCHER_EDIT_FIND].Enable( count );
|
|
menu[IDM_LAUNCHER_EDIT_CLEAR].Enable( count );
|
|
}
|
|
|
|
static HeapString form( HeapString() << ' ' << Resource::String(IDS_TEXT_FILES) << ": " );
|
|
|
|
const uint length = form.Length();
|
|
statusBar.Text(StatusBar::SECOND_FIELD) << (form << count).Ptr();
|
|
form.ShrinkTo( length );
|
|
}
|
|
|
|
void Launcher::OnListGetDisplayInfo(const NMHDR& nmhdr)
|
|
{
|
|
list.OnGetDisplayInfo( reinterpret_cast<LPARAM>(&nmhdr) );
|
|
}
|
|
|
|
void Launcher::OnListKeyDown(const NMHDR& nmhdr)
|
|
{
|
|
switch (reinterpret_cast<const NMLVKEYDOWN&>(nmhdr).wVKey)
|
|
{
|
|
case VK_INSERT: if (menu[ IDM_LAUNCHER_EDIT_INSERT ].Enabled()) dialog.PostCommand( IDM_LAUNCHER_EDIT_INSERT ); break;
|
|
case VK_DELETE: if (menu[ IDM_LAUNCHER_EDIT_REMOVE ].Enabled()) dialog.PostCommand( IDM_LAUNCHER_EDIT_REMOVE ); break;
|
|
case VK_F3: if (menu[ IDM_LAUNCHER_EDIT_FIND ].Enabled()) dialog.PostCommand( IDM_LAUNCHER_EDIT_FIND ); break;
|
|
case VK_F4: if (menu[ IDM_LAUNCHER_FILE_EDITHEADER ].Enabled()) dialog.PostCommand( IDM_LAUNCHER_FILE_EDITHEADER ); break;
|
|
case VK_F5: if (menu[ IDM_LAUNCHER_FILE_REFRESH ].Enabled()) dialog.PostCommand( IDM_LAUNCHER_FILE_REFRESH ); break;
|
|
}
|
|
}
|
|
|
|
void Launcher::OnListColumnClick(const NMHDR& nmhdr)
|
|
{
|
|
Application::Instance::Waiter wait;
|
|
list.Sort( reinterpret_cast<const NMLISTVIEW&>(nmhdr).iSubItem );
|
|
}
|
|
|
|
void Launcher::OnListItemActivate(const NMHDR&)
|
|
{
|
|
OnCmdFileRun();
|
|
}
|
|
|
|
void Launcher::OnListItemChanged(const NMHDR& nmhdr)
|
|
{
|
|
const NMLISTVIEW& nmlv = reinterpret_cast<const NMLISTVIEW&>(nmhdr);
|
|
|
|
if ((nmlv.uOldState ^ nmlv.uNewState) & LVIS_SELECTED)
|
|
{
|
|
if (nmlv.uNewState & LVIS_SELECTED)
|
|
{
|
|
if (const List::Files::Entry* const entry = list[nmlv.iItem])
|
|
{
|
|
{
|
|
Path path( entry->GetPath(list.GetStrings()), entry->GetFile(list.GetStrings()) );
|
|
|
|
if (path.Length() > MAX_PATH)
|
|
{
|
|
path.ShrinkTo( MAX_PATH-3 );
|
|
path << "...";
|
|
}
|
|
|
|
statusBar.Text(StatusBar::FIRST_FIELD) << path.Ptr();
|
|
}
|
|
|
|
menu[IDM_LAUNCHER_FILE_RUN].Enable();
|
|
menu[IDM_LAUNCHER_FILE_EDITHEADER].Enable( entry->GetType() == List::Files::Entry::NES );
|
|
menu[IDM_LAUNCHER_EDIT_REMOVE].Enable();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
OnNoSelection();
|
|
}
|
|
}
|
|
}
|
|
|
|
void Launcher::OnListInsertItem(const NMHDR&)
|
|
{
|
|
UpdateItemCount( list.Size() );
|
|
}
|
|
|
|
void Launcher::OnListDeleteItem(const NMHDR&)
|
|
{
|
|
const uint size = list.Size();
|
|
UpdateItemCount( size - (size != 0) );
|
|
}
|
|
|
|
void Launcher::OnListDeleteAllItems(const NMHDR&)
|
|
{
|
|
OnNoSelection();
|
|
const uint size = list.Size();
|
|
UpdateItemCount( size - (size != 0) );
|
|
}
|
|
|
|
void Launcher::OnTreeSelectionChanging(const NMHDR& nmhdr)
|
|
{
|
|
Application::Instance::Events::Signal( Application::Instance::EVENT_SYSTEM_BUSY );
|
|
list.Draw( tree.GetType(reinterpret_cast<const NMTREEVIEW&>(nmhdr).itemNew.hItem) );
|
|
}
|
|
|
|
void Launcher::OnNoSelection() const
|
|
{
|
|
statusBar.Text(StatusBar::FIRST_FIELD).Clear();
|
|
|
|
menu[IDM_LAUNCHER_FILE_RUN].Disable();
|
|
menu[IDM_LAUNCHER_FILE_EDITHEADER].Disable();
|
|
menu[IDM_LAUNCHER_EDIT_REMOVE].Disable();
|
|
}
|
|
|
|
void Launcher::OnCmdFileRun(uint)
|
|
{
|
|
if (const List::Files::Entry* const entry = list.GetSelection())
|
|
Application::Instance::GetMainWindow().Send( Application::Instance::WM_NST_LAUNCH, 0, Path(entry->GetPath(list.GetStrings()),entry->GetFile(list.GetStrings())).Ptr() );
|
|
}
|
|
|
|
void Launcher::OnCmdFileRefresh(uint)
|
|
{
|
|
list.Refresh();
|
|
}
|
|
|
|
void Launcher::OnCmdEditHeader(uint)
|
|
{
|
|
if (const List::Files::Entry* const entry = list.GetSelection())
|
|
Window::InesHeader( list.GetPaths() ).Open( Path(entry->GetPath(list.GetStrings()),entry->GetFile(list.GetStrings())) );
|
|
}
|
|
|
|
void Launcher::OnCmdViewShowGrids(uint)
|
|
{
|
|
menu[IDM_LAUNCHER_VIEW_SHOWGRIDS].Check( list.ToggleGrids() );
|
|
}
|
|
|
|
void Launcher::OnCmdViewShowDatabaseCorrected(uint)
|
|
{
|
|
menu[IDM_LAUNCHER_VIEW_SHOWDATABASECORRECTED].Check( list.ToggleDatabase() );
|
|
}
|
|
|
|
void Launcher::OnCmdViewShowOnTop(uint)
|
|
{
|
|
dialog.MakeTopMost( menu[IDM_LAUNCHER_VIEW_ONTOP].ToggleCheck() );
|
|
}
|
|
|
|
void Launcher::OnCmdOptionsPaths(uint)
|
|
{
|
|
list.OpenPathDialog();
|
|
menu[IDM_LAUNCHER_FILE_REFRESH].Enable( list.CanRefresh() );
|
|
}
|
|
|
|
void Launcher::OnCmdOptionsColors(uint)
|
|
{
|
|
colors.Open();
|
|
|
|
list.SetColors( colors.GetBackgroundColor(), colors.GetForegroundColor(), List::REPAINT );
|
|
tree.SetColors( colors.GetBackgroundColor(), colors.GetForegroundColor(), Tree::REPAINT );
|
|
}
|
|
}
|
|
}
|