Fix some more resizing and saving of such.
[dolphin.git] / Source / Core / DolphinWX / Src / GameListCtrl.cpp
blobb65c48555d9f417d6f156086e1eb71d1beda978c
1 // Copyright (C) 2003 Dolphin Project.
3 // This program is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation, version 2.0.
7 // This program is distributed in the hope that it will be useful,
8 // but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 // GNU General Public License 2.0 for more details.
12 // A copy of the GPL 2.0 should have been included with the program.
13 // If not, see http://www.gnu.org/licenses/
15 // Official SVN repository and contact information can be found at
16 // http://code.google.com/p/dolphin-emu/
18 #include "Globals.h"
20 #include <wx/imaglist.h>
21 #include <wx/fontmap.h>
23 #include <algorithm>
25 #include "FileSearch.h"
26 #include "StringUtil.h"
27 #include "ConfigManager.h"
28 #include "GameListCtrl.h"
29 #include "Blob.h"
30 #include "Core.h"
31 #include "ISOProperties.h"
32 #include "IniFile.h"
33 #include "FileUtil.h"
34 #include "CDUtils.h"
35 #include "WxUtils.h"
36 #include "Main.h"
38 #include "../resources/Flag_Europe.xpm"
39 #include "../resources/Flag_France.xpm"
40 #include "../resources/Flag_Italy.xpm"
41 #include "../resources/Flag_Japan.xpm"
42 #include "../resources/Flag_USA.xpm"
43 #include "../resources/Flag_Taiwan.xpm"
44 #include "../resources/Flag_Korea.xpm"
45 #include "../resources/Flag_Unknown.xpm"
46 #include "../resources/Platform_Wad.xpm"
47 #include "../resources/Platform_Wii.xpm"
48 #include "../resources/Platform_Gamecube.xpm"
49 #include "../resources/rating_gamelist.h"
51 size_t CGameListCtrl::m_currentItem = 0;
52 size_t CGameListCtrl::m_numberItem = 0;
53 std::string CGameListCtrl::m_currentFilename;
55 static int currentColumn = 0;
56 bool operator < (const GameListItem &one, const GameListItem &other)
58 int indexOne = 0;
59 int indexOther = 0;
61 switch (one.GetCountry())
63 case DiscIO::IVolume::COUNTRY_JAPAN:;
64 case DiscIO::IVolume::COUNTRY_USA:indexOne = 0; break;
65 default: indexOne = (int)SConfig::GetInstance().m_InterfaceLanguage;
68 switch (other.GetCountry())
70 case DiscIO::IVolume::COUNTRY_JAPAN:;
71 case DiscIO::IVolume::COUNTRY_USA:indexOther = 0; break;
72 default: indexOther = (int)SConfig::GetInstance().m_InterfaceLanguage;
75 switch(currentColumn)
77 case CGameListCtrl::COLUMN_TITLE: return strcasecmp(one.GetName(indexOne).c_str(), other.GetName(indexOther).c_str()) < 0;
78 case CGameListCtrl::COLUMN_NOTES:
80 // On Gamecube we show the company string, while it's empty on other platforms, so we show the description instead
81 std::string cmp1 = (one.GetPlatform() == GameListItem::GAMECUBE_DISC) ? one.GetCompany() : one.GetDescription(indexOne);
82 std::string cmp2 = (other.GetPlatform() == GameListItem::GAMECUBE_DISC) ? other.GetCompany() : other.GetDescription(indexOther);
83 return strcasecmp(cmp1.c_str(), cmp2.c_str()) < 0;
85 case CGameListCtrl::COLUMN_COUNTRY: return (one.GetCountry() < other.GetCountry());
86 case CGameListCtrl::COLUMN_SIZE: return (one.GetFileSize() < other.GetFileSize());
87 case CGameListCtrl::COLUMN_PLATFORM: return (one.GetPlatform() < other.GetPlatform());
88 default: return strcasecmp(one.GetName(indexOne).c_str(), other.GetName(indexOther).c_str()) < 0;
93 BEGIN_EVENT_TABLE(wxEmuStateTip, wxTipWindow)
94 EVT_KEY_DOWN(wxEmuStateTip::OnKeyDown)
95 END_EVENT_TABLE()
97 BEGIN_EVENT_TABLE(CGameListCtrl, wxListCtrl)
98 #ifdef _WIN32
99 EVT_PAINT(CGameListCtrl::OnPaintDrawImages)
100 #endif
101 EVT_SIZE(CGameListCtrl::OnSize)
102 EVT_RIGHT_DOWN(CGameListCtrl::OnRightClick)
103 EVT_LEFT_DOWN(CGameListCtrl::OnLeftClick)
104 EVT_LIST_KEY_DOWN(LIST_CTRL, CGameListCtrl::OnKeyPress)
105 EVT_MOTION(CGameListCtrl::OnMouseMotion)
106 EVT_LIST_COL_BEGIN_DRAG(LIST_CTRL, CGameListCtrl::OnColBeginDrag)
107 EVT_LIST_COL_CLICK(LIST_CTRL, CGameListCtrl::OnColumnClick)
108 EVT_MENU(IDM_PROPERTIES, CGameListCtrl::OnProperties)
109 EVT_MENU(IDM_OPENCONTAININGFOLDER, CGameListCtrl::OnOpenContainingFolder)
110 EVT_MENU(IDM_OPENSAVEFOLDER, CGameListCtrl::OnOpenSaveFolder)
111 EVT_MENU(IDM_EXPORTSAVE, CGameListCtrl::OnExportSave)
112 EVT_MENU(IDM_SETDEFAULTGCM, CGameListCtrl::OnSetDefaultGCM)
113 EVT_MENU(IDM_COMPRESSGCM, CGameListCtrl::OnCompressGCM)
114 EVT_MENU(IDM_MULTICOMPRESSGCM, CGameListCtrl::OnMultiCompressGCM)
115 EVT_MENU(IDM_MULTIDECOMPRESSGCM, CGameListCtrl::OnMultiDecompressGCM)
116 EVT_MENU(IDM_DELETEGCM, CGameListCtrl::OnDeleteGCM)
117 EVT_MENU(IDM_INSTALLWAD, CGameListCtrl::OnInstallWAD)
118 END_EVENT_TABLE()
121 CGameListCtrl::CGameListCtrl(wxWindow* parent, const wxWindowID id, const wxPoint& pos, const wxSize& size, long style)
122 : wxListCtrl(parent, id, pos, size, style), toolTip(0)
126 CGameListCtrl::~CGameListCtrl()
128 if (m_imageListSmall)
129 delete m_imageListSmall;
132 void CGameListCtrl::InitBitmaps()
134 m_imageListSmall = new wxImageList(96, 32);
135 SetImageList(m_imageListSmall, wxIMAGE_LIST_SMALL);
137 m_FlagImageIndex.resize(DiscIO::IVolume::NUMBER_OF_COUNTRIES);
138 m_FlagImageIndex[DiscIO::IVolume::COUNTRY_EUROPE] =
139 m_imageListSmall->Add(wxBitmap(Flag_Europe_xpm), wxNullBitmap);
140 m_FlagImageIndex[DiscIO::IVolume::COUNTRY_FRANCE] =
141 m_imageListSmall->Add(wxBitmap(Flag_France_xpm), wxNullBitmap);
142 m_FlagImageIndex[DiscIO::IVolume::COUNTRY_USA] =
143 m_imageListSmall->Add(wxBitmap(Flag_USA_xpm), wxNullBitmap);
144 m_FlagImageIndex[DiscIO::IVolume::COUNTRY_JAPAN] =
145 m_imageListSmall->Add(wxBitmap(Flag_Japan_xpm), wxNullBitmap);
146 m_FlagImageIndex[DiscIO::IVolume::COUNTRY_KOREA] =
147 m_imageListSmall->Add(wxBitmap(Flag_Korea_xpm), wxNullBitmap);
148 m_FlagImageIndex[DiscIO::IVolume::COUNTRY_ITALY] =
149 m_imageListSmall->Add(wxBitmap(Flag_Italy_xpm), wxNullBitmap);
150 m_FlagImageIndex[DiscIO::IVolume::COUNTRY_TAIWAN] =
151 m_imageListSmall->Add(wxBitmap(Flag_Taiwan_xpm), wxNullBitmap);
152 m_FlagImageIndex[DiscIO::IVolume::COUNTRY_SDK] =
153 m_imageListSmall->Add(wxBitmap(Flag_Unknown_xpm), wxNullBitmap);
154 m_FlagImageIndex[DiscIO::IVolume::COUNTRY_UNKNOWN] =
155 m_imageListSmall->Add(wxBitmap(Flag_Unknown_xpm), wxNullBitmap);
157 m_PlatformImageIndex.resize(3);
158 m_PlatformImageIndex[0] =
159 m_imageListSmall->Add(wxBitmap(Platform_Gamecube_xpm), wxNullBitmap);
160 m_PlatformImageIndex[1] =
161 m_imageListSmall->Add(wxBitmap(Platform_Wii_xpm), wxNullBitmap);
162 m_PlatformImageIndex[2] =
163 m_imageListSmall->Add(wxBitmap(Platform_Wad_xpm), wxNullBitmap);
165 m_EmuStateImageIndex.resize(6);
166 m_EmuStateImageIndex[0] =
167 m_imageListSmall->Add(wxBitmap(rating_0), wxNullBitmap);
168 m_EmuStateImageIndex[1] =
169 m_imageListSmall->Add(wxBitmap(rating_1), wxNullBitmap);
170 m_EmuStateImageIndex[2] =
171 m_imageListSmall->Add(wxBitmap(rating_2), wxNullBitmap);
172 m_EmuStateImageIndex[3] =
173 m_imageListSmall->Add(wxBitmap(rating_3), wxNullBitmap);
174 m_EmuStateImageIndex[4] =
175 m_imageListSmall->Add(wxBitmap(rating_4), wxNullBitmap);
176 m_EmuStateImageIndex[5] =
177 m_imageListSmall->Add(wxBitmap(rating_5), wxNullBitmap);
180 void CGameListCtrl::BrowseForDirectory()
182 wxString dirHome;
183 wxGetHomeDir(&dirHome);
185 // browse
186 wxDirDialog dialog(this, _("Browse for a directory to add"), dirHome, wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST);
188 if (dialog.ShowModal() == wxID_OK)
190 std::string sPath(dialog.GetPath().mb_str());
191 std::vector<std::string>::iterator itResult = std::find(
192 SConfig::GetInstance().m_ISOFolder.begin(), SConfig::GetInstance().m_ISOFolder.end(), sPath
195 if (itResult == SConfig::GetInstance().m_ISOFolder.end())
197 SConfig::GetInstance().m_ISOFolder.push_back(sPath);
198 SConfig::GetInstance().SaveSettings();
201 Update();
205 void CGameListCtrl::Update()
207 // Don't let the user refresh it while a game is running
208 if (Core::GetState() != Core::CORE_UNINITIALIZED)
209 return;
211 if (m_imageListSmall)
213 delete m_imageListSmall;
214 m_imageListSmall = NULL;
217 // NetPlay : Set/Reset the GameList string
218 m_gameList.clear();
219 m_gamePath.clear();
221 Hide();
223 ScanForISOs();
225 ClearAll();
227 if (m_ISOFiles.size() != 0)
229 // Don't load bitmaps unless there are games to list
230 InitBitmaps();
232 // add columns
233 InsertColumn(COLUMN_PLATFORM, _(""));
234 InsertColumn(COLUMN_BANNER, _("Banner"));
235 InsertColumn(COLUMN_TITLE, _("Title"));
237 // Instead of showing the notes + the company, which is unknown with wii titles
238 // We show in the same column : company for GC games and description for wii/wad games
239 InsertColumn(COLUMN_NOTES, _("Notes"));
240 InsertColumn(COLUMN_COUNTRY, _(""));
241 InsertColumn(COLUMN_SIZE, _("Size"));
242 InsertColumn(COLUMN_EMULATION_STATE, _("State"));
245 // set initial sizes for columns
246 SetColumnWidth(COLUMN_PLATFORM, 35);
247 SetColumnWidth(COLUMN_BANNER, 96);
248 SetColumnWidth(COLUMN_TITLE, 200);
249 SetColumnWidth(COLUMN_NOTES, 200);
250 SetColumnWidth(COLUMN_COUNTRY, 32);
251 SetColumnWidth(COLUMN_EMULATION_STATE, 50);
253 // add all items
254 for (int i = 0; i < (int)m_ISOFiles.size(); i++)
256 InsertItemInReportView(i);
257 if (m_ISOFiles[i].IsCompressed())
258 SetItemTextColour(i, wxColour(0xFF0000));
261 // Sort items by Title
262 wxListEvent event;
263 event.m_col = COLUMN_TITLE; last_column = 0;
264 OnColumnClick(event);
266 SetColumnWidth(COLUMN_SIZE, wxLIST_AUTOSIZE);
268 else
270 wxString errorString;
271 // We just check for one hide setting to be enabled, as we may only have GC games
272 // for example, and hide them, so we should show the second message instead
273 if ((SConfig::GetInstance().m_ListGC &&
274 SConfig::GetInstance().m_ListWii &&
275 SConfig::GetInstance().m_ListWad) &&
276 (SConfig::GetInstance().m_ListJap &&
277 SConfig::GetInstance().m_ListUsa &&
278 SConfig::GetInstance().m_ListPal))
280 errorString = _("Dolphin could not find any GC/Wii ISOs. Doubleclick here to browse for files...");
282 else
284 errorString = _("Dolphin is currently set to hide all games. Doubleclick here to show all games...");
286 InsertColumn(0, _("No ISOs or WADS found"));
287 long index = InsertItem(0, errorString);
288 SetItemFont(index, *wxITALIC_FONT);
289 SetColumnWidth(0, wxLIST_AUTOSIZE);
292 Show();
294 AutomaticColumnWidth();
297 wxString NiceSizeFormat(s64 _size)
299 const char* sizes[] = {"b", "KB", "MB", "GB", "TB", "PB", "EB"};
300 int s = 0;
301 int frac = 0;
303 while (_size > (s64)1024)
305 s++;
306 frac = (int)_size & 1023;
307 _size /= (s64)1024;
310 float f = (float)_size + ((float)frac / 1024.0f);
312 wxString NiceString;
313 char tempstr[32];
314 sprintf(tempstr,"%3.1f %s", f, sizes[s]);
315 NiceString = wxString::FromAscii(tempstr);
316 return(NiceString);
319 std::string CGameListCtrl::GetGamePaths() const
321 return m_gamePath;
323 std::string CGameListCtrl::GetGameNames() const
325 return m_gameList;
328 #ifdef _WIN32
329 // This draws our icons on top of the gamelist, it's only used on Windows
330 void CGameListCtrl::OnPaintDrawImages(wxPaintEvent& event)
332 int i = 0, nState = 0;
333 IniFile ini;
334 wxRect itemRect;
335 wxPaintDC dc(this);
337 // Calls the default drawing code
338 wxControl::OnPaint(event);
340 // Draw the flags, platform icons and emustate icons on top if there's games to show
341 if (m_ISOFiles.size() != 0)
343 // Retrieve the topmost shown item and get drawing offsets
344 long top = GetTopItem();
345 int flagOffset = GetColumnWidth(0) + GetColumnWidth(1) + GetColumnWidth(2) + GetColumnWidth(3);
346 int stateOffset = flagOffset + GetColumnWidth(4) + GetColumnWidth(5);
348 // Only redraw shown lines
349 for (i = top; i < top + GetCountPerPage() + 2; i++)
351 if (GetItemRect(i, itemRect))
353 int itemY = itemRect.GetTop();
354 const GameListItem& rISOFile = m_ISOFiles[GetItemData(i)];
356 m_imageListSmall->Draw(m_PlatformImageIndex[rISOFile.GetPlatform()], dc, itemRect.GetX()+3, itemY);
357 m_imageListSmall->Draw(m_FlagImageIndex[rISOFile.GetCountry()], dc, flagOffset, itemY);
359 ini.Load((std::string(File::GetUserPath(D_GAMECONFIG_IDX)) + (rISOFile.GetUniqueID()) + ".ini").c_str());
360 ini.Get("EmuState", "EmulationStateId", &nState);
361 m_imageListSmall->Draw(m_EmuStateImageIndex[nState], dc, stateOffset, itemY);
366 #endif
368 void CGameListCtrl::InsertItemInReportView(long _Index)
370 // When using wxListCtrl, there is no hope of per-column text colors.
371 // But for reference, here are the old colors that were used: (BGR)
372 // title: 0xFF0000
373 // company: 0x007030
374 int ImageIndex = -1;
375 #ifdef __linux__
376 wxCSConv SJISConv(wxFontMapper::GetEncodingName(wxFONTENCODING_EUC_JP));
377 #else
378 wxCSConv SJISConv(wxFontMapper::GetEncodingName(wxFONTENCODING_SHIFT_JIS));
379 #endif
380 GameListItem& rISOFile = m_ISOFiles[_Index];
381 m_gamePath.append(rISOFile.GetFileName() + '\n');
383 // Insert a first row with the platform image, that will be used as the Index
384 #ifndef _WIN32
385 long ItemIndex = InsertItem(_Index, wxEmptyString, m_PlatformImageIndex[rISOFile.GetPlatform()]);
386 #else
387 long ItemIndex = InsertItem(_Index, wxEmptyString, -1);
388 #endif
390 if (rISOFile.GetImage().IsOk())
391 ImageIndex = m_imageListSmall->Add(rISOFile.GetImage());
393 // Set the game's banner in the second column
394 SetItemColumnImage(_Index, COLUMN_BANNER, ImageIndex);
396 if (rISOFile.GetPlatform() != GameListItem::WII_WAD)
398 std::string company;
400 // We show the company string on Gamecube only
401 // On Wii we show the description instead as the company string is empty
402 if (rISOFile.GetPlatform() == GameListItem::GAMECUBE_DISC)
403 company = rISOFile.GetCompany().c_str();
405 switch (rISOFile.GetCountry())
407 case DiscIO::IVolume::COUNTRY_TAIWAN:
408 case DiscIO::IVolume::COUNTRY_JAPAN:
410 wxString name = wxString(rISOFile.GetName(0).c_str(), SJISConv);
411 m_gameList.append(StringFromFormat("%s (J)\n", (const char*)name.c_str()));
412 SetItem(_Index, COLUMN_TITLE, name, -1);
413 SetItem(_Index, COLUMN_NOTES, wxString(company.size() ? company.c_str() : rISOFile.GetDescription(0).c_str(), SJISConv), -1);
415 break;
416 case DiscIO::IVolume::COUNTRY_USA:
417 m_gameList.append(StringFromFormat("%s (U)\n", rISOFile.GetName(0).c_str()));
418 SetItem(_Index, COLUMN_TITLE,
419 wxString::From8BitData(rISOFile.GetName(0).c_str()), -1);
420 SetItem(_Index, COLUMN_NOTES,
421 wxString::From8BitData(company.size() ? company.c_str() : rISOFile.GetDescription(0).c_str()), -1);
422 break;
423 default:
424 m_gameList.append(StringFromFormat("%s (E)\n", rISOFile.GetName((int)SConfig::GetInstance().m_InterfaceLanguage).c_str()));
425 SetItem(_Index, COLUMN_TITLE,
426 wxString::From8BitData(rISOFile.GetName((int)SConfig::GetInstance().m_InterfaceLanguage).c_str()), -1);
427 SetItem(_Index, COLUMN_NOTES, wxString::From8BitData(
428 company.size() ? company.c_str() : rISOFile.GetDescription((int)SConfig::GetInstance().m_InterfaceLanguage).c_str()), -1);
429 break;
432 else // It's a Wad file
434 m_gameList.append(StringFromFormat("%s (WAD)\n", rISOFile.GetName(0).c_str()));
435 SetItem(_Index, COLUMN_TITLE, wxString(rISOFile.GetName(0).c_str(), SJISConv), -1);
436 SetItem(_Index, COLUMN_NOTES, wxString(rISOFile.GetDescription(0).c_str(), SJISConv), -1);
439 #ifndef _WIN32
440 // Load the INI file for columns that read from it
441 IniFile ini;
442 ini.Load((std::string(File::GetUserPath(D_GAMECONFIG_IDX)) + (rISOFile.GetUniqueID()) + ".ini").c_str());
444 // Emulation status
445 int nState;
446 ini.Get("EmuState", "EmulationStateId", &nState);
448 // Emulation state
449 SetItemColumnImage(_Index, COLUMN_EMULATION_STATE, m_EmuStateImageIndex[nState]);
451 // Country
452 SetItemColumnImage(_Index, COLUMN_COUNTRY, m_FlagImageIndex[rISOFile.GetCountry()]);
453 #endif
455 // File size
456 SetItem(_Index, COLUMN_SIZE, NiceSizeFormat(rISOFile.GetFileSize()), -1);
458 // Background color
459 SetBackgroundColor();
461 // Item data
462 SetItemData(_Index, ItemIndex);
465 wxColour blend50(const wxColour& c1, const wxColour& c2)
467 unsigned char r,g,b,a;
468 r = c1.Red()/2 + c2.Red()/2;
469 g = c1.Green()/2 + c2.Green()/2;
470 b = c1.Blue()/2 + c2.Blue()/2;
471 a = c1.Alpha()/2 + c2.Alpha()/2;
472 return a << 24 | b << 16 | g << 8 | r;
475 void CGameListCtrl::SetBackgroundColor()
477 for(long i = 0; i < GetItemCount(); i++)
479 wxColour color = (i & 1) ? blend50(wxSystemSettings::GetColour(wxSYS_COLOUR_3DLIGHT), wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)) : wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
480 CGameListCtrl::SetItemBackgroundColour(i, color);
484 void CGameListCtrl::ScanForISOs()
486 m_ISOFiles.clear();
487 CFileSearch::XStringVector Directories(SConfig::GetInstance().m_ISOFolder);
489 if (SConfig::GetInstance().m_RecursiveISOFolder)
491 for (u32 i = 0; i < Directories.size(); i++)
493 File::FSTEntry FST_Temp;
494 File::ScanDirectoryTree(Directories.at(i).c_str(), FST_Temp);
495 for (u32 j = 0; j < FST_Temp.children.size(); j++)
497 if (FST_Temp.children.at(j).isDirectory)
499 bool duplicate = false;
500 NormalizeDirSep(&(FST_Temp.children.at(j).physicalName));
501 for (u32 k = 0; k < Directories.size(); k++)
503 NormalizeDirSep(&Directories.at(k));
504 if (strcmp(Directories.at(k).c_str(), FST_Temp.children.at(j).physicalName.c_str()) == 0)
506 duplicate = true;
507 break;
510 if (!duplicate)
511 Directories.push_back(FST_Temp.children.at(j).physicalName.c_str());
517 CFileSearch::XStringVector Extensions;
519 if (SConfig::GetInstance().m_ListGC)
520 Extensions.push_back("*.gcm");
521 if (SConfig::GetInstance().m_ListWii || SConfig::GetInstance().m_ListGC)
523 Extensions.push_back("*.iso");
524 Extensions.push_back("*.gcz");
526 if (SConfig::GetInstance().m_ListWad)
527 Extensions.push_back("*.wad");
529 CFileSearch FileSearch(Extensions, Directories);
530 const CFileSearch::XStringVector& rFilenames = FileSearch.GetFileNames();
532 if (rFilenames.size() > 0)
534 wxProgressDialog dialog(_T("Scanning for ISOs"),
535 _T("Scanning..."),
536 (int)rFilenames.size(), // range
537 this, // parent
538 wxPD_APP_MODAL |
539 // wxPD_AUTO_HIDE | -- try this as well
540 wxPD_ELAPSED_TIME |
541 wxPD_ESTIMATED_TIME |
542 wxPD_REMAINING_TIME |
543 wxPD_SMOOTH // - makes indeterminate mode bar on WinXP very small
545 dialog.CenterOnParent();
547 for (u32 i = 0; i < rFilenames.size(); i++)
549 std::string FileName;
550 SplitPath(rFilenames[i], NULL, &FileName, NULL);
552 wxString msg;
553 char tempstring[128];
554 sprintf(tempstring,"Scanning %s", FileName.c_str());
555 msg = wxString(tempstring, *wxConvCurrent);
557 // With wxWidgets 2.9.1, each Update() sleeps for several seconds
558 #ifndef __APPLE__
559 // Update with the progress (i) and the message (msg)
560 bool Cont = dialog.Update(i, msg);
561 if (!Cont)
563 break;
565 #endif
566 GameListItem ISOFile(rFilenames[i]);
567 if (ISOFile.IsValid())
569 bool list = true;
571 switch(ISOFile.GetPlatform())
573 case GameListItem::WII_DISC:
574 if (!SConfig::GetInstance().m_ListWii)
575 list = false;
576 break;
577 case GameListItem::WII_WAD:
578 if (!SConfig::GetInstance().m_ListWad)
579 list = false;
580 break;
581 default:
582 if (!SConfig::GetInstance().m_ListGC)
583 list = false;
584 break;
587 switch(ISOFile.GetCountry())
589 case DiscIO::IVolume::COUNTRY_TAIWAN:
590 if (!SConfig::GetInstance().m_ListTaiwan)
591 list = false;
592 case DiscIO::IVolume::COUNTRY_KOREA:
593 if (!SConfig::GetInstance().m_ListKorea)
594 list = false;
595 break;
596 case DiscIO::IVolume::COUNTRY_JAPAN:
597 if (!SConfig::GetInstance().m_ListJap)
598 list = false;
599 break;
600 case DiscIO::IVolume::COUNTRY_USA:
601 if (!SConfig::GetInstance().m_ListUsa)
602 list = false;
603 break;
604 case DiscIO::IVolume::COUNTRY_FRANCE:
605 if (!SConfig::GetInstance().m_ListFrance)
606 list = false;
607 break;
608 case DiscIO::IVolume::COUNTRY_ITALY:
609 if (!SConfig::GetInstance().m_ListItaly)
610 list = false;
611 break;
612 default:
613 if (!SConfig::GetInstance().m_ListPal)
614 list = false;
615 break;
618 if (list) m_ISOFiles.push_back(ISOFile);
623 if (SConfig::GetInstance().m_ListDrives)
625 std::vector<std::string> drives = cdio_get_devices();
626 GameListItem * Drive[24];
627 // Another silly Windows limitation of 24 drive letters
628 for (u32 i = 0; i < drives.size() && i < 24; i++)
630 Drive[i] = new GameListItem(drives[i].c_str());
631 if (Drive[i]->IsValid()) m_ISOFiles.push_back(*Drive[i]);
635 std::sort(m_ISOFiles.begin(), m_ISOFiles.end());
638 void CGameListCtrl::OnColBeginDrag(wxListEvent& event)
640 if (event.GetColumn() != COLUMN_TITLE && event.GetColumn() != COLUMN_NOTES)
641 event.Veto();
644 const GameListItem *CGameListCtrl::GetISO(int index) const
646 return &m_ISOFiles[index];
649 CGameListCtrl *caller;
650 int wxCALLBACK wxListCompare(long item1, long item2, long sortData)
652 //return 1 if item1 > item2
653 //return -1 if item1 < item2
654 //0 for identity
655 const GameListItem *iso1 = caller->GetISO(item1);
656 const GameListItem *iso2 = caller->GetISO(item2);
658 int t = 1;
660 if (sortData < 0)
662 t = -1;
663 sortData = -sortData;
666 int indexOne = 0;
667 int indexOther = 0;
669 switch (iso1->GetCountry())
671 case DiscIO::IVolume::COUNTRY_JAPAN:;
672 case DiscIO::IVolume::COUNTRY_USA:indexOne = 0; break;
673 default: indexOne = (int)SConfig::GetInstance().m_InterfaceLanguage;
676 switch (iso2->GetCountry())
678 case DiscIO::IVolume::COUNTRY_JAPAN:;
679 case DiscIO::IVolume::COUNTRY_USA:indexOther = 0; break;
680 default: indexOther = (int)SConfig::GetInstance().m_InterfaceLanguage;
683 switch(sortData)
685 case CGameListCtrl::COLUMN_TITLE:
686 return strcasecmp(iso1->GetName(indexOne).c_str(),iso2->GetName(indexOther).c_str()) *t;
687 case CGameListCtrl::COLUMN_NOTES:
689 std::string cmp1 = (iso1->GetPlatform() == GameListItem::GAMECUBE_DISC) ? iso1->GetCompany() : iso1->GetDescription(indexOne);
690 std::string cmp2 = (iso2->GetPlatform() == GameListItem::GAMECUBE_DISC) ? iso2->GetCompany() : iso2->GetDescription(indexOther);
691 return strcasecmp(cmp1.c_str(), cmp2.c_str()) *t;
693 case CGameListCtrl::COLUMN_COUNTRY:
694 if(iso1->GetCountry() > iso2->GetCountry()) return 1 *t;
695 if(iso1->GetCountry() < iso2->GetCountry()) return -1 *t;
696 return 0;
697 case CGameListCtrl::COLUMN_SIZE:
698 if (iso1->GetFileSize() > iso2->GetFileSize()) return 1 *t;
699 if (iso1->GetFileSize() < iso2->GetFileSize()) return -1 *t;
700 return 0;
701 case CGameListCtrl::COLUMN_PLATFORM:
702 if(iso1->GetPlatform() > iso2->GetPlatform()) return 1 *t;
703 if(iso1->GetPlatform() < iso2->GetPlatform()) return -1 *t;
704 return 0;
705 case CGameListCtrl::COLUMN_EMULATION_STATE:
706 IniFile ini; int nState1 = 0, nState2 = 0;
707 std::string GameIni1 = std::string(File::GetUserPath(D_GAMECONFIG_IDX)) + iso1->GetUniqueID() + ".ini";
708 std::string GameIni2 = std::string(File::GetUserPath(D_GAMECONFIG_IDX)) + iso2->GetUniqueID() + ".ini";
710 ini.Load(GameIni1.c_str());
711 ini.Get("EmuState", "EmulationStateId", &nState1);
712 ini.Load(GameIni2.c_str());
713 ini.Get("EmuState", "EmulationStateId", &nState2);
715 if(nState1 > nState2) return 1 *t;
716 if(nState1 < nState2) return -1 *t;
717 return 0;
720 return 0;
723 void CGameListCtrl::OnColumnClick(wxListEvent& event)
725 if(event.GetColumn() != COLUMN_BANNER)
727 int current_column = event.GetColumn();
729 if(last_column == current_column)
731 last_sort = -last_sort;
733 else
735 last_column = current_column;
736 last_sort = current_column;
739 caller = this;
740 SortItems(wxListCompare, last_sort);
743 SetBackgroundColor();
745 event.Skip();
748 // This is used by keyboard gamelist search
749 void CGameListCtrl::OnKeyPress(wxListEvent& event)
751 static int lastKey = 0, sLoop = 0;
752 int Loop = 0;
754 for (int i = 0; i < (int)m_ISOFiles.size(); i++)
756 // Easy way to get game string
757 wxListItem bleh;
758 bleh.SetId(i);
759 bleh.SetColumn(COLUMN_TITLE);
760 bleh.SetMask(wxLIST_MASK_TEXT);
761 GetItem(bleh);
763 wxString text = bleh.GetText();
765 if (text.MakeUpper().at(0) == event.GetKeyCode())
767 if (lastKey == event.GetKeyCode() && Loop < sLoop)
769 Loop++;
770 if (i+1 == (int)m_ISOFiles.size())
771 i = -1;
772 continue;
774 else if (lastKey != event.GetKeyCode())
775 sLoop = 0;
777 lastKey = event.GetKeyCode();
778 sLoop++;
780 UnselectAll();
781 SetItemState(i, wxLIST_STATE_SELECTED|wxLIST_STATE_FOCUSED, wxLIST_STATE_SELECTED|wxLIST_STATE_FOCUSED);
782 EnsureVisible(i);
783 break;
786 // If we get past the last game in the list, we'll have to go back to the first one.
787 if (i+1 == (int)m_ISOFiles.size() && sLoop > 0 && Loop > 0)
788 i = -1;
791 event.Skip();
794 // This shows a little tooltip with the current Game's emulation state
795 void CGameListCtrl::OnMouseMotion(wxMouseEvent& event)
797 int flags; long subitem = 0;
798 long item = HitTest(event.GetPosition(), flags, &subitem);
799 static int lastItem = -1;
801 if (item != wxNOT_FOUND)
803 if (subitem == COLUMN_EMULATION_STATE)
805 if (toolTip || lastItem == item || this != FindFocus()) {
806 event.Skip();
807 return;
810 const GameListItem& rISO = m_ISOFiles[GetItemData(item)];
812 IniFile ini;
813 ini.Load((std::string(File::GetUserPath(D_GAMECONFIG_IDX)) + (rISO.GetUniqueID()) + ".ini").c_str());
815 // Emulation status
816 std::string emuState[5] = {"Broken", "Intro", "In-Game", "Playable", "Perfect"}, issues;
818 int nState;
819 ini.Get("EmuState", "EmulationStateId", &nState);
820 ini.Get("EmuState", "EmulationIssues", &issues, "");
822 // Get item Coords then convert from wxWindow coord to Screen coord
823 wxRect Rect;
824 this->GetItemRect(item, Rect);
825 int mx = Rect.GetWidth();
826 int my = Rect.GetY();
827 this->ClientToScreen(&mx, &my);
829 // Show a tooltip containing the EmuState and the state description
830 if (nState > 0 && nState < 6)
832 char temp[2048];
833 sprintf(temp, "^ %s%s%s", emuState[nState -1].c_str(), issues.size() > 0 ? " :\n" : "", issues.c_str());
834 toolTip = new wxEmuStateTip(this, wxString(temp, *wxConvCurrent), &toolTip);
836 else
837 toolTip = new wxEmuStateTip(this, wxT("Not Set"), &toolTip);
839 toolTip->SetBoundingRect(wxRect(mx - GetColumnWidth(subitem), my, GetColumnWidth(subitem), Rect.GetHeight()));
840 toolTip->SetPosition(wxPoint(mx - GetColumnWidth(subitem), my - 5 + Rect.GetHeight()));
842 lastItem = item;
846 event.Skip();
849 void CGameListCtrl::OnLeftClick(wxMouseEvent& event)
851 // Focus the clicked item.
852 int flags;
853 long item = HitTest(event.GetPosition(), flags);
854 if ((item != wxNOT_FOUND) && (GetSelectedItemCount() == 0) && (!event.ControlDown()) && (!event.ShiftDown()))
856 SetItemState(item, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED );
857 SetItemState(item, wxLIST_STATE_FOCUSED, wxLIST_STATE_FOCUSED);
858 wxGetApp().GetCFrame()->UpdateGUI();
861 event.Skip();
864 void CGameListCtrl::OnRightClick(wxMouseEvent& event)
866 // Focus the clicked item.
867 int flags;
868 long item = HitTest(event.GetPosition(), flags);
869 if (item != wxNOT_FOUND)
871 if (GetItemState(item, wxLIST_STATE_SELECTED) != wxLIST_STATE_SELECTED)
873 UnselectAll();
874 SetItemState(item, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED );
876 SetItemState(item, wxLIST_STATE_FOCUSED, wxLIST_STATE_FOCUSED);
879 if (GetSelectedItemCount() == 1)
881 const GameListItem *selected_iso = GetSelectedISO();
882 if (selected_iso)
884 wxMenu* popupMenu = new wxMenu;
885 popupMenu->Append(IDM_PROPERTIES, _("&Properties"));
886 popupMenu->AppendSeparator();
888 if (selected_iso->GetPlatform() != GameListItem::GAMECUBE_DISC)
890 popupMenu->Append(IDM_OPENSAVEFOLDER, _("Open Wii &save folder"));
891 popupMenu->Append(IDM_EXPORTSAVE, _("Export Wii save (Experimental)"));
893 popupMenu->Append(IDM_OPENCONTAININGFOLDER, _("Open &containing folder"));
894 popupMenu->AppendCheckItem(IDM_SETDEFAULTGCM, _("Set as &default ISO"));
896 // First we have to decide a starting value when we append it
897 if(selected_iso->GetFileName() == SConfig::GetInstance().
898 m_LocalCoreStartupParameter.m_strDefaultGCM)
899 popupMenu->FindItem(IDM_SETDEFAULTGCM)->Check();
901 popupMenu->AppendSeparator();
902 popupMenu->Append(IDM_DELETEGCM, _("&Delete ISO..."));
904 if (selected_iso->GetPlatform() != GameListItem::WII_WAD)
906 if (selected_iso->IsCompressed())
907 popupMenu->Append(IDM_COMPRESSGCM, _("Decompress ISO..."));
908 else
909 popupMenu->Append(IDM_COMPRESSGCM, _("Compress ISO..."));
910 } else
911 popupMenu->Append(IDM_INSTALLWAD, _("Install to Wii Menu"));
913 PopupMenu(popupMenu);
916 else if (GetSelectedItemCount() > 1)
918 wxMenu* popupMenu = new wxMenu;
919 popupMenu->Append(IDM_DELETEGCM, _("&Delete selected ISOs..."));
920 popupMenu->AppendSeparator();
921 popupMenu->Append(IDM_MULTICOMPRESSGCM, _("Compress selected ISOs..."));
922 popupMenu->Append(IDM_MULTIDECOMPRESSGCM, _("Decompress selected ISOs..."));
923 PopupMenu(popupMenu);
927 const GameListItem * CGameListCtrl::GetSelectedISO()
929 if (m_ISOFiles.size() == 0)
931 return NULL;
933 else if (GetSelectedItemCount() == 0)
935 return NULL;
937 else
939 long item = GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
940 if (item == wxNOT_FOUND)
941 return new GameListItem("");
942 else
944 // Here is a little workaround for multiselections:
945 // when > 1 item is selected, return info on the first one
946 // and deselect it so the next time GetSelectedISO() is called,
947 // the next item's info is returned
948 if (GetSelectedItemCount() > 1)
949 SetItemState(item, 0, wxLIST_STATE_SELECTED);
951 return &m_ISOFiles[GetItemData(item)];
956 void CGameListCtrl::OnOpenContainingFolder(wxCommandEvent& WXUNUSED (event))
958 const GameListItem *iso = GetSelectedISO();
959 if (!iso)
960 return;
961 std::string path;
962 SplitPath(iso->GetFileName(), &path, 0, 0);
963 WxUtils::Explore(path.c_str());
966 void CGameListCtrl::OnOpenSaveFolder(wxCommandEvent& WXUNUSED (event))
968 const GameListItem *iso = GetSelectedISO();
969 if (!iso)
970 return;
971 if (iso->GetWiiFSPath() != "NULL")
972 WxUtils::Explore(iso->GetWiiFSPath().c_str());
975 void CGameListCtrl::OnExportSave(wxCommandEvent& WXUNUSED (event))
977 const GameListItem *iso = GetSelectedISO();
978 if (!iso)
979 return;
980 u64 title;
981 DiscIO::IVolume *Iso = DiscIO::CreateVolumeFromFilename(iso->GetFileName());
982 if (Iso)
984 if (Iso->GetTitleID((u8*)&title))
986 title = Common::swap64(title);
987 CWiiSaveCrypted* exportSave = new CWiiSaveCrypted("", title);
988 delete exportSave;
990 delete Iso;
994 // =======================================================
995 // Save this file as the default file
996 // -------------
997 void CGameListCtrl::OnSetDefaultGCM(wxCommandEvent& event)
999 const GameListItem *iso = GetSelectedISO();
1000 if (!iso) return;
1002 if (event.IsChecked()) // Write the new default value and save it the ini file
1004 SConfig::GetInstance().m_LocalCoreStartupParameter.m_strDefaultGCM = iso->GetFileName();
1005 SConfig::GetInstance().SaveSettings();
1007 else // Othwerise blank the value and save it
1009 SConfig::GetInstance().m_LocalCoreStartupParameter.m_strDefaultGCM = "";
1010 SConfig::GetInstance().SaveSettings();
1013 // =============
1016 void CGameListCtrl::OnDeleteGCM(wxCommandEvent& WXUNUSED (event))
1018 if (GetSelectedItemCount() == 1)
1020 const GameListItem *iso = GetSelectedISO();
1021 if (!iso)
1022 return;
1023 if (wxMessageBox(_("Are you sure you want to delete this file?\nIt will be gone forever!"),
1024 wxMessageBoxCaptionStr, wxYES_NO | wxICON_EXCLAMATION) == wxYES)
1026 File::Delete(iso->GetFileName().c_str());
1027 Update();
1030 else
1032 if (wxMessageBox(_("Are you sure you want to delete these files?\nThey will be gone forever!"),
1033 wxMessageBoxCaptionStr, wxYES_NO | wxICON_EXCLAMATION) == wxYES)
1035 int selected = GetSelectedItemCount();
1037 for (int i = 0; i < selected; i++)
1039 const GameListItem *iso = GetSelectedISO();
1040 File::Delete(iso->GetFileName().c_str());
1042 Update();
1047 void CGameListCtrl::OnProperties(wxCommandEvent& WXUNUSED (event))
1049 const GameListItem *iso = GetSelectedISO();
1050 if (!iso)
1051 return;
1052 CISOProperties ISOProperties(iso->GetFileName(), this);
1053 ISOProperties.Center();
1054 if(ISOProperties.ShowModal() == wxID_OK)
1055 Update();
1058 void CGameListCtrl::OnInstallWAD(wxCommandEvent& WXUNUSED (event))
1060 const GameListItem *iso = GetSelectedISO();
1061 if (!iso)
1062 return;
1064 wxProgressDialog dialog(_T("Installing WAD to Wii Menu..."),
1065 _T("Working..."),
1066 1000, // range
1067 this, // parent
1068 wxPD_APP_MODAL |
1069 // wxPD_AUTO_HIDE | -- try this as well
1070 wxPD_ELAPSED_TIME |
1071 wxPD_ESTIMATED_TIME |
1072 wxPD_REMAINING_TIME |
1073 wxPD_SMOOTH // - makes indeterminate mode bar on WinXP very small
1076 dialog.CenterOnParent();
1078 CBoot::Install_WiiWAD(iso->GetFileName().c_str());
1081 void CGameListCtrl::MultiCompressCB(const char* text, float percent, void* arg)
1083 percent = (((float)m_currentItem) + percent) / (float)m_numberItem;
1084 wxString textString(StringFromFormat("%s (%i/%i) - %s", m_currentFilename.c_str(), (int)m_currentItem+1, (int)m_numberItem, text).c_str(), *wxConvCurrent);
1086 ((wxProgressDialog*)arg)->Update((int)(percent*1000), textString);
1089 void CGameListCtrl::OnMultiCompressGCM(wxCommandEvent& /*event*/)
1091 CompressSelection(true);
1094 void CGameListCtrl::OnMultiDecompressGCM(wxCommandEvent& /*event*/)
1096 CompressSelection(false);
1099 void CGameListCtrl::CompressSelection(bool _compress)
1101 wxString dirHome;
1102 wxGetHomeDir(&dirHome);
1104 wxDirDialog browseDialog(this, _("Browse for output directory"), dirHome, wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST);
1105 if (browseDialog.ShowModal() != wxID_OK)
1106 return;
1108 wxProgressDialog progressDialog(_compress ? _("Compressing ISO") : _("Decompressing ISO"),
1109 _("Working..."),
1110 1000, // range
1111 this, // parent
1112 wxPD_APP_MODAL |
1113 // wxPD_AUTO_HIDE | -- try this as well
1114 wxPD_ELAPSED_TIME |
1115 wxPD_ESTIMATED_TIME |
1116 wxPD_REMAINING_TIME |
1117 wxPD_SMOOTH // - makes indeterminate mode bar on WinXP very small
1120 progressDialog.SetSize(wxSize(600, 180));
1121 progressDialog.CenterOnParent();
1123 m_currentItem = 0;
1124 m_numberItem = GetSelectedItemCount();
1125 for (u32 i=0; i<m_numberItem; i++)
1127 const GameListItem *iso = GetSelectedISO();
1129 if (!iso->IsCompressed() && _compress)
1131 std::string FileName;
1132 SplitPath(iso->GetFileName(), NULL, &FileName, NULL);
1133 m_currentFilename = FileName;
1134 FileName.append(".gcz");
1136 std::string OutputFileName;
1137 BuildCompleteFilename(OutputFileName, (const char *)browseDialog.GetPath().mb_str(wxConvUTF8), FileName);
1139 DiscIO::CompressFileToBlob(iso->GetFileName().c_str(), OutputFileName.c_str(), (iso->GetPlatform() == GameListItem::WII_DISC) ? 1 : 0, 16384, &MultiCompressCB, &progressDialog);
1141 else if (iso->IsCompressed() && !_compress)
1143 std::string FileName;
1144 SplitPath(iso->GetFileName(), NULL, &FileName, NULL);
1145 m_currentFilename = FileName;
1146 if (iso->GetPlatform() == GameListItem::WII_DISC)
1148 FileName.append(".iso");
1150 else
1152 FileName.append(".gcm");
1155 std::string OutputFileName;
1156 BuildCompleteFilename(OutputFileName, (const char *)browseDialog.GetPath().mb_str(wxConvUTF8), FileName);
1158 DiscIO::DecompressBlobToFile(iso->GetFileName().c_str(), OutputFileName.c_str(), &MultiCompressCB, &progressDialog);
1160 m_currentItem++;
1162 Update();
1165 void CGameListCtrl::CompressCB(const char* text, float percent, void* arg)
1167 ((wxProgressDialog*)arg)->Update((int)(percent*1000), wxString(text, *wxConvCurrent));
1170 void CGameListCtrl::OnCompressGCM(wxCommandEvent& WXUNUSED (event))
1172 const GameListItem *iso = GetSelectedISO();
1173 if (!iso)
1174 return;
1176 wxString path, Ext;
1178 std::string FileName;
1179 SplitPath(iso->GetFileName(), NULL, &FileName, NULL);
1181 if (iso->IsCompressed())
1183 if (iso->GetPlatform() == GameListItem::WII_DISC)
1185 Ext = wxT("*.iso");
1187 else
1189 Ext = wxT("*.gcm");
1191 path = wxFileSelector(
1192 _T("Save decompressed ISO"),
1193 wxEmptyString, wxString(FileName.c_str(), *wxConvCurrent), wxEmptyString,
1194 wxString::Format
1196 _T("All GC/Wii ISO files (%s)|%s|All files (%s)|%s"),
1197 (char *)Ext.After('.').char_str(wxConvUTF8),
1198 (char *)Ext.char_str(wxConvUTF8),
1199 wxFileSelectorDefaultWildcardStr,
1200 wxFileSelectorDefaultWildcardStr
1202 wxFD_SAVE,
1203 this);
1205 if (!path)
1207 return;
1210 else
1212 path = wxFileSelector(
1213 _T("Save compressed ISO"),
1214 wxEmptyString, wxString(FileName.c_str(), *wxConvCurrent), wxEmptyString,
1215 wxString::Format
1217 _T("All compressed GC/Wii ISO files (gcz)|*.gcz|All files (%s)|%s"),
1218 wxFileSelectorDefaultWildcardStr,
1219 wxFileSelectorDefaultWildcardStr
1221 wxFD_SAVE,
1222 this);
1224 if (!path)
1226 return;
1230 wxProgressDialog dialog(iso->IsCompressed() ? _T("Decompressing ISO") : _T("Compressing ISO"),
1231 _T("Working..."),
1232 1000, // range
1233 this, // parent
1234 wxPD_APP_MODAL |
1235 // wxPD_AUTO_HIDE | -- try this as well
1236 wxPD_ELAPSED_TIME |
1237 wxPD_ESTIMATED_TIME |
1238 wxPD_REMAINING_TIME |
1239 wxPD_SMOOTH // - makes indeterminate mode bar on WinXP very small
1242 dialog.SetSize(wxSize(280, 180));
1243 dialog.CenterOnParent();
1245 if (iso->IsCompressed())
1246 DiscIO::DecompressBlobToFile(iso->GetFileName().c_str(), path.char_str(), &CompressCB, &dialog);
1247 else
1248 DiscIO::CompressFileToBlob(iso->GetFileName().c_str(), path.char_str(), (iso->GetPlatform() == GameListItem::WII_DISC) ? 1 : 0, 16384, &CompressCB, &dialog);
1250 Update();
1253 void CGameListCtrl::OnSize(wxSizeEvent& event)
1255 if (lastpos == event.GetSize()) return;
1256 lastpos = event.GetSize();
1257 AutomaticColumnWidth();
1259 event.Skip();
1262 void CGameListCtrl::AutomaticColumnWidth()
1264 wxRect rc(GetParent()->GetRect());
1266 if (GetColumnCount() == 1)
1268 SetColumnWidth(0, rc.GetWidth());
1270 else if (GetColumnCount() > 4)
1272 int resizable = rc.GetWidth() - (
1273 GetColumnWidth(COLUMN_BANNER)
1274 + GetColumnWidth(COLUMN_COUNTRY)
1275 + GetColumnWidth(COLUMN_SIZE)
1276 + GetColumnWidth(COLUMN_EMULATION_STATE)
1277 + GetColumnWidth(COLUMN_PLATFORM)
1278 + 5); // some pad to keep the horizontal scrollbar away :)
1280 // We hide the Company column if the window is too small
1281 if (0.5*resizable > 200)
1283 SetColumnWidth(COLUMN_TITLE, 0.5*resizable);
1284 SetColumnWidth(COLUMN_NOTES, 0.5*resizable);
1286 else
1288 SetColumnWidth(COLUMN_TITLE, resizable);
1289 SetColumnWidth(COLUMN_NOTES, 0);
1294 void CGameListCtrl::UnselectAll()
1296 for (int i=0; i<GetItemCount(); i++)
1298 SetItemState(i, 0, wxLIST_STATE_SELECTED);