Play-/Source/ui_win32/VFSManagerWnd.cpp
2018-04-30 21:01:23 +01:00

301 lines
7.1 KiB
C++

#include <shlobj.h>
#include "resource.h"
#include "VFSManagerWnd.h"
#include "../AppConfig.h"
#include "../PS2VM_Preferences.h"
#include "CdromSelectionWnd.h"
#include "string_cast.h"
#include "string_format.h"
CVFSManagerWnd::CVFSManagerWnd(HWND parentWindow)
: CDialog(MAKEINTRESOURCE(IDD_VFSMANAGER), parentWindow)
{
SetClassPtr();
m_deviceList = Framework::Win32::CListView(GetItem(IDC_VFSMANAGER_DEVICES));
m_deviceList.SetExtendedListViewStyle(m_deviceList.GetExtendedListViewStyle() | LVS_EX_FULLROWSELECT);
m_devices[0] = std::make_unique<CDirectoryDevice>("mc0", PREF_PS2_MC0_DIRECTORY);
m_devices[1] = std::make_unique<CDirectoryDevice>("mc1", PREF_PS2_MC1_DIRECTORY);
m_devices[2] = std::make_unique<CDirectoryDevice>("host", PREF_PS2_HOST_DIRECTORY);
m_devices[3] = std::make_unique<CCdrom0Device>();
CreateListColumns();
UpdateList();
}
long CVFSManagerWnd::OnCommand(unsigned short nID, unsigned short nCmd, HWND hSender)
{
switch(nID)
{
case IDOK:
Save();
Destroy();
return TRUE;
break;
case IDCANCEL:
Destroy();
return TRUE;
break;
}
return FALSE;
}
LRESULT CVFSManagerWnd::OnNotify(WPARAM wParam, NMHDR* hdr)
{
if(hdr->idFrom == IDC_VFSMANAGER_DEVICES)
{
switch(hdr->code)
{
case NM_DBLCLK:
int nSel = m_deviceList.GetSelection();
if(nSel != -1)
{
const auto deviceIterator = m_devices.find(m_deviceList.GetItemData(nSel));
if(deviceIterator != m_devices.end())
{
const auto& device = deviceIterator->second;
if(device->RequestModification(m_hWnd))
{
UpdateList();
}
}
}
break;
}
}
return FALSE;
}
void CVFSManagerWnd::CreateListColumns()
{
LVCOLUMN col;
RECT rc = m_deviceList.GetClientRect();
memset(&col, 0, sizeof(LVCOLUMN));
col.pszText = _T("Device");
col.mask = LVCF_TEXT | LVCF_WIDTH;
col.cx = rc.right / 4;
m_deviceList.InsertColumn(0, col);
memset(&col, 0, sizeof(LVCOLUMN));
col.pszText = _T("Binding Type");
col.mask = LVCF_TEXT | LVCF_WIDTH;
col.cx = rc.right / 4;
m_deviceList.InsertColumn(1, col);
memset(&col, 0, sizeof(LVCOLUMN));
col.pszText = _T("Binding Value");
col.mask = LVCF_TEXT | LVCF_WIDTH;
col.cx = rc.right / 2;
m_deviceList.InsertColumn(2, col);
}
void CVFSManagerWnd::UpdateList()
{
for(const auto& devicePair : m_devices)
{
const auto& device = devicePair.second;
auto key = devicePair.first;
unsigned int index = m_deviceList.FindItemData(key);
if(index == -1)
{
auto deviceName = string_cast<std::tstring>(device->GetDeviceName());
LVITEM itm;
memset(&itm, 0, sizeof(LVITEM));
itm.mask = LVIF_TEXT | LVIF_PARAM;
itm.pszText = const_cast<TCHAR*>(deviceName.c_str());
itm.lParam = key;
index = m_deviceList.InsertItem(itm);
}
m_deviceList.SetItemText(index, 1, string_cast<std::tstring>(device->GetBindingType()).c_str());
m_deviceList.SetItemText(index, 2, device->GetBinding().c_str());
}
}
void CVFSManagerWnd::Save()
{
for(const auto& devicePair : m_devices)
{
const auto& device = devicePair.second;
device->Save();
}
}
///////////////////////////////////////////
//CDirectoryDevice Implementation
///////////////////////////////////////////
CVFSManagerWnd::CDirectoryDevice::CDirectoryDevice(const char* name, const char* preference)
: m_name(name)
, m_preference(preference)
{
auto path = CAppConfig::GetInstance().GetPreferencePath(m_preference);
m_path = path.native();
}
const char* CVFSManagerWnd::CDirectoryDevice::GetDeviceName()
{
return m_name;
}
const char* CVFSManagerWnd::CDirectoryDevice::GetBindingType()
{
return "Directory";
}
std::tstring CVFSManagerWnd::CDirectoryDevice::GetBinding()
{
return m_path;
}
bool CVFSManagerWnd::CDirectoryDevice::RequestModification(HWND hParent)
{
BROWSEINFO bi;
memset(&bi, 0, sizeof(BROWSEINFO));
bi.hwndOwner = hParent;
bi.lpszTitle = _T("Select new folder for device");
bi.ulFlags = BIF_RETURNONLYFSDIRS;
bi.lpfn = BrowseCallback;
bi.lParam = (LPARAM)this;
auto item = SHBrowseForFolder(&bi);
if(item == NULL)
{
return false;
}
TCHAR path[MAX_PATH];
if(SHGetPathFromIDList(item, path) == 0)
{
MessageBox(hParent, _T("Invalid directory."), NULL, 16);
CoTaskMemFree(item);
return false;
}
CoTaskMemFree(item);
m_path = path;
return true;
}
void CVFSManagerWnd::CDirectoryDevice::Save()
{
CAppConfig::GetInstance().SetPreferencePath(m_preference, m_path);
}
int CVFSManagerWnd::CDirectoryDevice::BrowseCallback(HWND hFrom, unsigned int nMsg, LPARAM lParam, LPARAM pData)
{
auto device = reinterpret_cast<CDirectoryDevice*>(pData);
switch(nMsg)
{
case BFFM_INITIALIZED:
SendMessage(hFrom, BFFM_SETSELECTION, TRUE, reinterpret_cast<LPARAM>(device->m_path.c_str()));
break;
}
return 0;
}
///////////////////////////////////////////
//CCdrom0Device Implementation
///////////////////////////////////////////
CVFSManagerWnd::CCdrom0Device::CCdrom0Device()
{
auto cdrom0Path = CAppConfig::GetInstance().GetPreferencePath(PREF_PS2_CDROM0_PATH);
auto cdrom0PathString = cdrom0Path.string();
//Detect the binding type from the path format
if(cdrom0Path.empty())
{
m_bindingType = CCdromSelectionWnd::BINDING_IMAGE;
m_imagePath = _T("");
}
else if((cdrom0PathString.length() == 6) && !cdrom0PathString.compare(0, 4, "\\\\.\\"))
{
m_bindingType = CCdromSelectionWnd::BINDING_PHYSICAL;
m_devicePath = string_format("%c:\\", toupper(cdrom0PathString[4]));
}
else
{
m_bindingType = CCdromSelectionWnd::BINDING_IMAGE;
m_imagePath = cdrom0Path.native();
}
}
const char* CVFSManagerWnd::CCdrom0Device::GetDeviceName()
{
return "cdrom0";
}
const char* CVFSManagerWnd::CCdrom0Device::GetBindingType()
{
if(m_bindingType == CCdromSelectionWnd::BINDING_PHYSICAL)
{
return "Physical Device";
}
else if(m_bindingType == CCdromSelectionWnd::BINDING_IMAGE)
{
return "Disk Image";
}
return "";
}
std::tstring CVFSManagerWnd::CCdrom0Device::GetBinding()
{
if(m_bindingType == CCdromSelectionWnd::BINDING_IMAGE)
{
if(m_imagePath.empty())
{
return _T("(None)");
}
else
{
return m_imagePath;
}
}
else if(m_bindingType == CCdromSelectionWnd::BINDING_PHYSICAL)
{
return string_cast<std::tstring>(m_devicePath.c_str());
}
return _T("");
}
bool CVFSManagerWnd::CCdrom0Device::RequestModification(HWND hParent)
{
CCdromSelectionWnd::CDROMBINDING binding;
binding.type = static_cast<CCdromSelectionWnd::BINDINGTYPE>(m_bindingType);
binding.imagePath = m_imagePath;
binding.physicalDevice = m_devicePath[0] - 'A';
CCdromSelectionWnd selectionWnd(hParent, _T("Modify cdrom0 Binding"));
selectionWnd.SetBindingInfo(binding);
selectionWnd.DoModal();
if(!selectionWnd.WasConfirmed()) return false;
binding = selectionWnd.GetBindingInfo();
m_bindingType = binding.type;
m_imagePath = binding.imagePath;
m_devicePath = string_format("%c:\\", binding.physicalDevice + 'A');
return true;
}
void CVFSManagerWnd::CCdrom0Device::Save()
{
if(m_bindingType == CCdromSelectionWnd::BINDING_IMAGE)
{
CAppConfig::GetInstance().SetPreferencePath(PREF_PS2_CDROM0_PATH, m_imagePath);
}
else if(m_bindingType == CCdromSelectionWnd::BINDING_PHYSICAL)
{
auto devicePath = string_format("\\\\.\\%c:", m_devicePath[0]);
CAppConfig::GetInstance().SetPreferencePath(PREF_PS2_CDROM0_PATH, devicePath);
}
}