Logical reorderring of the GUI boot sequence. Also a little clean up in the OpenGL...
[dolphin.git] / Source / Core / DolphinWX / Src / GameListCtrl.cpp
blob69de42764071353907ffed0b430875306f4b53c7
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 #if USE_XPM_BITMAPS
39 #include "../resources/Flag_Europe.xpm"
40 #include "../resources/Flag_France.xpm"
41 #include "../resources/Flag_Italy.xpm"
42 #include "../resources/Flag_Japan.xpm"
43 #include "../resources/Flag_USA.xpm"
44 #include "../resources/Flag_Taiwan.xpm"
45 #include "../resources/Flag_Korea.xpm"
46 #include "../resources/Flag_Unknown.xpm"
48 #include "../resources/Platform_Wad.xpm"
49 #include "../resources/Platform_Wii.xpm"
50 #include "../resources/Platform_Gamecube.xpm"
52 #include "../resources/rating_gamelist.h"
53 #endif // USE_XPM_BITMAPS
55 size_t CGameListCtrl::m_currentItem = 0;
56 size_t CGameListCtrl::m_numberItem = 0;
57 std::string CGameListCtrl::m_currentFilename;
59 static int currentColumn = 0;
60 bool operator < (const GameListItem &one, const GameListItem &other)
62 int indexOne = 0;
63 int indexOther = 0;
65 switch (one.GetCountry())
67 case DiscIO::IVolume::COUNTRY_JAPAN:;
68 case DiscIO::IVolume::COUNTRY_USA:indexOne = 0; break;
69 default: indexOne = (int)SConfig::GetInstance().m_InterfaceLanguage;
72 switch (other.GetCountry())
74 case DiscIO::IVolume::COUNTRY_JAPAN:;
75 case DiscIO::IVolume::COUNTRY_USA:indexOther = 0; break;
76 default: indexOther = (int)SConfig::GetInstance().m_InterfaceLanguage;
79 switch(currentColumn)
81 case CGameListCtrl::COLUMN_TITLE: return strcasecmp(one.GetName(indexOne).c_str(), other.GetName(indexOther).c_str()) < 0;
82 case CGameListCtrl::COLUMN_NOTES:
84 // On Gamecube we show the company string, while it's empty on other platforms, so we show the description instead
85 std::string cmp1 = (one.GetPlatform() == GameListItem::GAMECUBE_DISC) ? one.GetCompany() : one.GetDescription(indexOne);
86 std::string cmp2 = (other.GetPlatform() == GameListItem::GAMECUBE_DISC) ? other.GetCompany() : other.GetDescription(indexOther);
87 return strcasecmp(cmp1.c_str(), cmp2.c_str()) < 0;
89 case CGameListCtrl::COLUMN_COUNTRY: return (one.GetCountry() < other.GetCountry());
90 case CGameListCtrl::COLUMN_SIZE: return (one.GetFileSize() < other.GetFileSize());
91 case CGameListCtrl::COLUMN_PLATFORM: return (one.GetPlatform() < other.GetPlatform());
92 default: return strcasecmp(one.GetName(indexOne).c_str(), other.GetName(indexOther).c_str()) < 0;
97 BEGIN_EVENT_TABLE(wxEmuStateTip, wxTipWindow)
98 EVT_KEY_DOWN(wxEmuStateTip::OnKeyDown)
99 END_EVENT_TABLE()
101 BEGIN_EVENT_TABLE(CGameListCtrl, wxListCtrl)
102 #ifdef _WIN32
103 EVT_PAINT(CGameListCtrl::OnPaintDrawImages)
104 #endif
105 EVT_SIZE(CGameListCtrl::OnSize)
106 EVT_RIGHT_DOWN(CGameListCtrl::OnRightClick)
107 EVT_LEFT_DOWN(CGameListCtrl::OnLeftClick)
108 EVT_LIST_KEY_DOWN(LIST_CTRL, CGameListCtrl::OnKeyPress)
109 EVT_MOTION(CGameListCtrl::OnMouseMotion)
110 EVT_LIST_COL_BEGIN_DRAG(LIST_CTRL, CGameListCtrl::OnColBeginDrag)
111 EVT_LIST_COL_CLICK(LIST_CTRL, CGameListCtrl::OnColumnClick)
112 EVT_MENU(IDM_PROPERTIES, CGameListCtrl::OnProperties)
113 EVT_MENU(IDM_OPENCONTAININGFOLDER, CGameListCtrl::OnOpenContainingFolder)
114 EVT_MENU(IDM_OPENSAVEFOLDER, CGameListCtrl::OnOpenSaveFolder)
115 EVT_MENU(IDM_EXPORTSAVE, CGameListCtrl::OnExportSave)
116 EVT_MENU(IDM_SETDEFAULTGCM, CGameListCtrl::OnSetDefaultGCM)
117 EVT_MENU(IDM_COMPRESSGCM, CGameListCtrl::OnCompressGCM)
118 EVT_MENU(IDM_MULTICOMPRESSGCM, CGameListCtrl::OnMultiCompressGCM)
119 EVT_MENU(IDM_MULTIDECOMPRESSGCM, CGameListCtrl::OnMultiDecompressGCM)
120 EVT_MENU(IDM_DELETEGCM, CGameListCtrl::OnDeleteGCM)
121 EVT_MENU(IDM_INSTALLWAD, CGameListCtrl::OnInstallWAD)
122 END_EVENT_TABLE()
125 CGameListCtrl::CGameListCtrl(wxWindow* parent, const wxWindowID id, const wxPoint& pos, const wxSize& size, long style)
126 : wxListCtrl(parent, id, pos, size, style), toolTip(0)
130 CGameListCtrl::~CGameListCtrl()
132 if (m_imageListSmall)
133 delete m_imageListSmall;
136 void CGameListCtrl::InitBitmaps()
138 m_imageListSmall = new wxImageList(96, 32);
139 SetImageList(m_imageListSmall, wxIMAGE_LIST_SMALL);
140 wxIcon iconTemp;
142 m_FlagImageIndex.resize(DiscIO::IVolume::NUMBER_OF_COUNTRIES);
143 iconTemp.CopyFromBitmap(wxBitmap(Flag_Europe_xpm));
144 m_FlagImageIndex[DiscIO::IVolume::COUNTRY_EUROPE] = m_imageListSmall->Add(iconTemp);
145 iconTemp.CopyFromBitmap(wxBitmap(Flag_France_xpm));
146 m_FlagImageIndex[DiscIO::IVolume::COUNTRY_FRANCE] = m_imageListSmall->Add(iconTemp);
147 iconTemp.CopyFromBitmap(wxBitmap(Flag_USA_xpm));
148 m_FlagImageIndex[DiscIO::IVolume::COUNTRY_USA] = m_imageListSmall->Add(iconTemp);
149 iconTemp.CopyFromBitmap(wxBitmap(Flag_Japan_xpm));
150 m_FlagImageIndex[DiscIO::IVolume::COUNTRY_JAPAN] = m_imageListSmall->Add(iconTemp);
151 iconTemp.CopyFromBitmap(wxBitmap(Flag_Korea_xpm));
152 m_FlagImageIndex[DiscIO::IVolume::COUNTRY_KOREA] = m_imageListSmall->Add(iconTemp);
153 iconTemp.CopyFromBitmap(wxBitmap(Flag_Italy_xpm));
154 m_FlagImageIndex[DiscIO::IVolume::COUNTRY_ITALY] = m_imageListSmall->Add(iconTemp);
155 iconTemp.CopyFromBitmap(wxBitmap(Flag_Taiwan_xpm));
156 m_FlagImageIndex[DiscIO::IVolume::COUNTRY_TAIWAN] = m_imageListSmall->Add(iconTemp);
157 iconTemp.CopyFromBitmap(wxBitmap(Flag_Unknown_xpm));
158 m_FlagImageIndex[DiscIO::IVolume::COUNTRY_SDK] = m_imageListSmall->Add(iconTemp);
159 iconTemp.CopyFromBitmap(wxBitmap(Flag_Unknown_xpm));
160 m_FlagImageIndex[DiscIO::IVolume::COUNTRY_UNKNOWN] = m_imageListSmall->Add(iconTemp);
162 m_PlatformImageIndex.resize(3);
163 iconTemp.CopyFromBitmap(wxBitmap(Platform_Gamecube_xpm));
164 m_PlatformImageIndex[0] = m_imageListSmall->Add(iconTemp);
165 iconTemp.CopyFromBitmap(wxBitmap(Platform_Wii_xpm));
166 m_PlatformImageIndex[1] = m_imageListSmall->Add(iconTemp);
167 iconTemp.CopyFromBitmap(wxBitmap(Platform_Wad_xpm));
168 m_PlatformImageIndex[2] = m_imageListSmall->Add(iconTemp);
170 m_EmuStateImageIndex.resize(6);
171 iconTemp.CopyFromBitmap(wxBitmap(rating_0));
172 m_EmuStateImageIndex[0] = m_imageListSmall->Add(iconTemp);
173 iconTemp.CopyFromBitmap(wxBitmap(rating_1));
174 m_EmuStateImageIndex[1] = m_imageListSmall->Add(iconTemp);
175 iconTemp.CopyFromBitmap(wxBitmap(rating_2));
176 m_EmuStateImageIndex[2] = m_imageListSmall->Add(iconTemp);
177 iconTemp.CopyFromBitmap(wxBitmap(rating_3));
178 m_EmuStateImageIndex[3] = m_imageListSmall->Add(iconTemp);
179 iconTemp.CopyFromBitmap(wxBitmap(rating_4));
180 m_EmuStateImageIndex[4] = m_imageListSmall->Add(iconTemp);
181 iconTemp.CopyFromBitmap(wxBitmap(rating_5));
182 m_EmuStateImageIndex[5] = m_imageListSmall->Add(iconTemp);
185 void CGameListCtrl::BrowseForDirectory()
187 wxString dirHome;
188 wxGetHomeDir(&dirHome);
190 // browse
191 wxDirDialog dialog(this, _("Browse for a directory to add"), dirHome, wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST);
193 if (dialog.ShowModal() == wxID_OK)
195 std::string sPath(dialog.GetPath().mb_str());
196 std::vector<std::string>::iterator itResult = std::find(
197 SConfig::GetInstance().m_ISOFolder.begin(), SConfig::GetInstance().m_ISOFolder.end(), sPath
200 if (itResult == SConfig::GetInstance().m_ISOFolder.end())
202 SConfig::GetInstance().m_ISOFolder.push_back(sPath);
203 SConfig::GetInstance().SaveSettings();
206 Update();
210 void CGameListCtrl::Update()
212 // Don't let the user refresh it while a game is running
213 if (Core::GetState() != Core::CORE_UNINITIALIZED)
214 return;
216 if (m_imageListSmall)
218 delete m_imageListSmall;
219 m_imageListSmall = NULL;
222 // NetPlay : Set/Reset the GameList string
223 m_gameList.clear();
224 m_gamePath.clear();
226 Hide();
228 ScanForISOs();
230 ClearAll();
232 if (m_ISOFiles.size() != 0)
234 // Don't load bitmaps unless there are games to list
235 InitBitmaps();
237 // add columns
238 InsertColumn(COLUMN_PLATFORM, _(""));
239 InsertColumn(COLUMN_BANNER, _("Banner"));
240 InsertColumn(COLUMN_TITLE, _("Title"));
242 // Instead of showing the notes + the company, which is unknown with wii titles
243 // We show in the same column : company for GC games and description for wii/wad games
244 InsertColumn(COLUMN_NOTES, _("Notes"));
245 InsertColumn(COLUMN_COUNTRY, _(""));
246 InsertColumn(COLUMN_SIZE, _("Size"));
247 InsertColumn(COLUMN_EMULATION_STATE, _("State"));
250 // set initial sizes for columns
251 SetColumnWidth(COLUMN_PLATFORM, 35);
252 SetColumnWidth(COLUMN_BANNER, 96);
253 SetColumnWidth(COLUMN_TITLE, 200);
254 SetColumnWidth(COLUMN_NOTES, 200);
255 SetColumnWidth(COLUMN_COUNTRY, 32);
256 SetColumnWidth(COLUMN_EMULATION_STATE, 50);
258 // add all items
259 for (int i = 0; i < (int)m_ISOFiles.size(); i++)
261 InsertItemInReportView(i);
262 if (m_ISOFiles[i].IsCompressed())
263 SetItemTextColour(i, wxColour(0xFF0000));
266 // Sort items by Title
267 wxListEvent event;
268 event.m_col = COLUMN_TITLE; last_column = 0;
269 OnColumnClick(event);
271 SetColumnWidth(COLUMN_SIZE, wxLIST_AUTOSIZE);
273 else
275 wxString errorString;
276 // We just check for one hide setting to be enabled, as we may only have GC games
277 // for example, and hide them, so we should show the second message instead
278 if ((SConfig::GetInstance().m_ListGC &&
279 SConfig::GetInstance().m_ListWii &&
280 SConfig::GetInstance().m_ListWad) &&
281 (SConfig::GetInstance().m_ListJap &&
282 SConfig::GetInstance().m_ListUsa &&
283 SConfig::GetInstance().m_ListPal))
285 errorString = _("Dolphin could not find any GC/Wii ISOs. Doubleclick here to browse for files...");
287 else
289 errorString = _("Dolphin is currently set to hide all games. Doubleclick here to show all games...");
291 InsertColumn(0, _("No ISOs or WADS found"));
292 long index = InsertItem(0, errorString);
293 SetItemFont(index, *wxITALIC_FONT);
294 SetColumnWidth(0, wxLIST_AUTOSIZE);
297 Show();
299 AutomaticColumnWidth();
302 wxString NiceSizeFormat(s64 _size)
304 const char* sizes[] = {"b", "KB", "MB", "GB", "TB", "PB", "EB"};
305 int s = 0;
306 int frac = 0;
308 while (_size > (s64)1024)
310 s++;
311 frac = (int)_size & 1023;
312 _size /= (s64)1024;
315 float f = (float)_size + ((float)frac / 1024.0f);
317 wxString NiceString;
318 char tempstr[32];
319 sprintf(tempstr,"%3.1f %s", f, sizes[s]);
320 NiceString = wxString::FromAscii(tempstr);
321 return(NiceString);
324 std::string CGameListCtrl::GetGamePaths() const
326 return m_gamePath;
328 std::string CGameListCtrl::GetGameNames() const
330 return m_gameList;
333 #ifdef _WIN32
334 // This draws our icons on top of the gamelist, it's only used on Windows
335 void CGameListCtrl::OnPaintDrawImages(wxPaintEvent& event)
337 int i = 0, nState = 0;
338 IniFile ini;
339 wxRect itemRect;
340 wxPaintDC dc(this);
342 // Calls the default drawing code
343 wxControl::OnPaint(event);
345 // Draw the flags, platform icons and emustate icons on top if there's games to show
346 if (m_ISOFiles.size() != 0)
348 // Retrieve the topmost shown item and get drawing offsets
349 long top = GetTopItem();
350 int flagOffset = GetColumnWidth(0) + GetColumnWidth(1) + GetColumnWidth(2) + GetColumnWidth(3);
351 int stateOffset = flagOffset + GetColumnWidth(4) + GetColumnWidth(5);
353 // Only redraw shown lines
354 for (i = top; i < top + GetCountPerPage() + 2; i++)
356 if (GetItemRect(i, itemRect))
358 int itemY = itemRect.GetTop();
359 const GameListItem& rISOFile = m_ISOFiles[GetItemData(i)];
361 m_imageListSmall->Draw(m_PlatformImageIndex[rISOFile.GetPlatform()], dc, itemRect.GetX()+3, itemY);
362 m_imageListSmall->Draw(m_FlagImageIndex[rISOFile.GetCountry()], dc, flagOffset, itemY);
364 ini.Load((std::string(File::GetUserPath(D_GAMECONFIG_IDX)) + (rISOFile.GetUniqueID()) + ".ini").c_str());
365 ini.Get("EmuState", "EmulationStateId", &nState);
366 m_imageListSmall->Draw(m_EmuStateImageIndex[nState], dc, stateOffset, itemY);
371 #endif
373 void CGameListCtrl::InsertItemInReportView(long _Index)
375 // When using wxListCtrl, there is no hope of per-column text colors.
376 // But for reference, here are the old colors that were used: (BGR)
377 // title: 0xFF0000
378 // company: 0x007030
379 int ImageIndex = -1;
380 wxCSConv SJISConv(wxFontMapper::GetEncodingName(wxFONTENCODING_SHIFT_JIS));
381 GameListItem& rISOFile = m_ISOFiles[_Index];
382 m_gamePath.append(rISOFile.GetFileName() + '\n');
384 // Insert a first row with the platform image, that will be used as the Index
385 #ifndef _WIN32
386 long ItemIndex = InsertItem(_Index, wxEmptyString, m_PlatformImageIndex[rISOFile.GetPlatform()]);
387 #else
388 long ItemIndex = InsertItem(_Index, wxEmptyString, -1);
389 #endif
391 if (rISOFile.GetImage().IsOk())
392 ImageIndex = m_imageListSmall->Add(rISOFile.GetImage());
394 // Set the game's banner in the second column
395 SetItemColumnImage(_Index, COLUMN_BANNER, ImageIndex);
397 if (rISOFile.GetPlatform() != GameListItem::WII_WAD)
399 std::string company;
401 // We show the company string on Gamecube only
402 // On Wii we show the description instead as the company string is empty
403 if (rISOFile.GetPlatform() == GameListItem::GAMECUBE_DISC)
404 company = rISOFile.GetCompany().c_str();
406 switch (rISOFile.GetCountry())
408 case DiscIO::IVolume::COUNTRY_TAIWAN:
409 case DiscIO::IVolume::COUNTRY_JAPAN:
411 wxString name = wxString(rISOFile.GetName(0).c_str(), SJISConv);
412 m_gameList.append(StringFromFormat("%s (J)\n", (const char*)name.c_str()));
413 SetItem(_Index, COLUMN_TITLE, name, -1);
414 SetItem(_Index, COLUMN_NOTES, wxString(company.size() ? company.c_str() : rISOFile.GetDescription(0).c_str(), SJISConv), -1);
416 break;
417 case DiscIO::IVolume::COUNTRY_USA:
418 m_gameList.append(StringFromFormat("%s (U)\n", rISOFile.GetName(0).c_str()));
419 SetItem(_Index, COLUMN_TITLE,
420 wxString::From8BitData(rISOFile.GetName(0).c_str()), -1);
421 SetItem(_Index, COLUMN_NOTES,
422 wxString::From8BitData(company.size() ? company.c_str() : rISOFile.GetDescription(0).c_str()), -1);
423 break;
424 default:
425 m_gameList.append(StringFromFormat("%s (E)\n", rISOFile.GetName((int)SConfig::GetInstance().m_InterfaceLanguage).c_str()));
426 SetItem(_Index, COLUMN_TITLE,
427 wxString::From8BitData(rISOFile.GetName((int)SConfig::GetInstance().m_InterfaceLanguage).c_str()), -1);
428 SetItem(_Index, COLUMN_NOTES, wxString::From8BitData(
429 company.size() ? company.c_str() : rISOFile.GetDescription((int)SConfig::GetInstance().m_InterfaceLanguage).c_str()), -1);
430 break;
433 else // It's a Wad file
435 m_gameList.append(StringFromFormat("%s (WAD)\n", rISOFile.GetName(0).c_str()));
436 SetItem(_Index, COLUMN_TITLE, wxString(rISOFile.GetName(0).c_str(), SJISConv), -1);
437 SetItem(_Index, COLUMN_NOTES, wxString(rISOFile.GetDescription(0).c_str(), SJISConv), -1);
440 #ifndef _WIN32
441 // Load the INI file for columns that read from it
442 IniFile ini;
443 ini.Load((std::string(File::GetUserPath(D_GAMECONFIG_IDX)) + (rISOFile.GetUniqueID()) + ".ini").c_str());
445 // Emulation status
446 int nState;
447 ini.Get("EmuState", "EmulationStateId", &nState);
449 // Emulation state
450 SetItemColumnImage(_Index, COLUMN_EMULATION_STATE, m_EmuStateImageIndex[nState]);
452 // Country
453 SetItemColumnImage(_Index, COLUMN_COUNTRY, m_FlagImageIndex[rISOFile.GetCountry()]);
454 #endif
456 // File size
457 SetItem(_Index, COLUMN_SIZE, NiceSizeFormat(rISOFile.GetFileSize()), -1);
459 // Background color
460 SetBackgroundColor();
462 // Item data
463 SetItemData(_Index, ItemIndex);
466 wxColour blend50(const wxColour& c1, const wxColour& c2)
468 unsigned char r,g,b,a;
469 r = c1.Red()/2 + c2.Red()/2;
470 g = c1.Green()/2 + c2.Green()/2;
471 b = c1.Blue()/2 + c2.Blue()/2;
472 a = c1.Alpha()/2 + c2.Alpha()/2;
473 return a << 24 | b << 16 | g << 8 | r;
476 void CGameListCtrl::SetBackgroundColor()
478 for(long i = 0; i < GetItemCount(); i++)
480 wxColour color = (i & 1) ? blend50(wxSystemSettings::GetColour(wxSYS_COLOUR_3DLIGHT), wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)) : wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
481 CGameListCtrl::SetItemBackgroundColour(i, color);
485 void CGameListCtrl::ScanForISOs()
487 m_ISOFiles.clear();
488 CFileSearch::XStringVector Directories(SConfig::GetInstance().m_ISOFolder);
490 if (SConfig::GetInstance().m_RecursiveISOFolder)
492 for (u32 i = 0; i < Directories.size(); i++)
494 File::FSTEntry FST_Temp;
495 File::ScanDirectoryTree(Directories.at(i).c_str(), FST_Temp);
496 for (u32 j = 0; j < FST_Temp.children.size(); j++)
498 if (FST_Temp.children.at(j).isDirectory)
500 bool duplicate = false;
501 NormalizeDirSep(&(FST_Temp.children.at(j).physicalName));
502 for (u32 k = 0; k < Directories.size(); k++)
504 NormalizeDirSep(&Directories.at(k));
505 if (strcmp(Directories.at(k).c_str(), FST_Temp.children.at(j).physicalName.c_str()) == 0)
507 duplicate = true;
508 break;
511 if (!duplicate)
512 Directories.push_back(FST_Temp.children.at(j).physicalName.c_str());
518 CFileSearch::XStringVector Extensions;
520 if (SConfig::GetInstance().m_ListGC)
521 Extensions.push_back("*.gcm");
522 if (SConfig::GetInstance().m_ListWii || SConfig::GetInstance().m_ListGC)
524 Extensions.push_back("*.iso");
525 Extensions.push_back("*.gcz");
527 if (SConfig::GetInstance().m_ListWad)
528 Extensions.push_back("*.wad");
530 CFileSearch FileSearch(Extensions, Directories);
531 const CFileSearch::XStringVector& rFilenames = FileSearch.GetFileNames();
533 if (rFilenames.size() > 0)
535 wxProgressDialog dialog(_T("Scanning for ISOs"),
536 _T("Scanning..."),
537 (int)rFilenames.size(), // range
538 this, // parent
539 wxPD_APP_MODAL |
540 // wxPD_AUTO_HIDE | -- try this as well
541 wxPD_ELAPSED_TIME |
542 wxPD_ESTIMATED_TIME |
543 wxPD_REMAINING_TIME |
544 wxPD_SMOOTH // - makes indeterminate mode bar on WinXP very small
546 dialog.CenterOnParent();
548 for (u32 i = 0; i < rFilenames.size(); i++)
550 std::string FileName;
551 SplitPath(rFilenames[i], NULL, &FileName, NULL);
553 wxString msg;
554 char tempstring[128];
555 sprintf(tempstring,"Scanning %s", FileName.c_str());
556 msg = wxString(tempstring, *wxConvCurrent);
558 // Update with the progress (i) and the message (msg)
559 bool Cont = dialog.Update(i, msg);
560 if (!Cont)
562 break;
564 GameListItem ISOFile(rFilenames[i]);
565 if (ISOFile.IsValid())
567 bool list = true;
569 switch(ISOFile.GetPlatform())
571 case GameListItem::WII_DISC:
572 if (!SConfig::GetInstance().m_ListWii)
573 list = false;
574 break;
575 case GameListItem::WII_WAD:
576 if (!SConfig::GetInstance().m_ListWad)
577 list = false;
578 break;
579 default:
580 if (!SConfig::GetInstance().m_ListGC)
581 list = false;
582 break;
585 switch(ISOFile.GetCountry())
587 case DiscIO::IVolume::COUNTRY_TAIWAN:
588 if (!SConfig::GetInstance().m_ListTaiwan)
589 list = false;
590 case DiscIO::IVolume::COUNTRY_KOREA:
591 if (!SConfig::GetInstance().m_ListKorea)
592 list = false;
593 break;
594 case DiscIO::IVolume::COUNTRY_JAPAN:
595 if (!SConfig::GetInstance().m_ListJap)
596 list = false;
597 break;
598 case DiscIO::IVolume::COUNTRY_USA:
599 if (!SConfig::GetInstance().m_ListUsa)
600 list = false;
601 break;
602 case DiscIO::IVolume::COUNTRY_FRANCE:
603 if (!SConfig::GetInstance().m_ListFrance)
604 list = false;
605 break;
606 case DiscIO::IVolume::COUNTRY_ITALY:
607 if (!SConfig::GetInstance().m_ListItaly)
608 list = false;
609 break;
610 default:
611 if (!SConfig::GetInstance().m_ListPal)
612 list = false;
613 break;
616 if (list) m_ISOFiles.push_back(ISOFile);
621 if (SConfig::GetInstance().m_ListDrives)
623 std::vector<std::string> drives = cdio_get_devices();
624 GameListItem * Drive[24];
625 // Another silly Windows limitation of 24 drive letters
626 for (u32 i = 0; i < drives.size() && i < 24; i++)
628 Drive[i] = new GameListItem(drives[i].c_str());
629 if (Drive[i]->IsValid()) m_ISOFiles.push_back(*Drive[i]);
633 std::sort(m_ISOFiles.begin(), m_ISOFiles.end());
636 void CGameListCtrl::OnColBeginDrag(wxListEvent& event)
638 if (event.GetColumn() != COLUMN_TITLE && event.GetColumn() != COLUMN_NOTES)
639 event.Veto();
642 const GameListItem *CGameListCtrl::GetISO(int index) const
644 return &m_ISOFiles[index];
647 CGameListCtrl *caller;
648 int wxCALLBACK wxListCompare(long item1, long item2, long sortData)
650 //return 1 if item1 > item2
651 //return -1 if item1 < item2
652 //0 for identity
653 const GameListItem *iso1 = caller->GetISO(item1);
654 const GameListItem *iso2 = caller->GetISO(item2);
656 int t = 1;
658 if (sortData < 0)
660 t = -1;
661 sortData = -sortData;
664 int indexOne = 0;
665 int indexOther = 0;
667 switch (iso1->GetCountry())
669 case DiscIO::IVolume::COUNTRY_JAPAN:;
670 case DiscIO::IVolume::COUNTRY_USA:indexOne = 0; break;
671 default: indexOne = (int)SConfig::GetInstance().m_InterfaceLanguage;
674 switch (iso2->GetCountry())
676 case DiscIO::IVolume::COUNTRY_JAPAN:;
677 case DiscIO::IVolume::COUNTRY_USA:indexOther = 0; break;
678 default: indexOther = (int)SConfig::GetInstance().m_InterfaceLanguage;
681 switch(sortData)
683 case CGameListCtrl::COLUMN_TITLE:
684 return strcasecmp(iso1->GetName(indexOne).c_str(),iso2->GetName(indexOther).c_str()) *t;
685 case CGameListCtrl::COLUMN_NOTES:
687 std::string cmp1 = (iso1->GetPlatform() == GameListItem::GAMECUBE_DISC) ? iso1->GetCompany() : iso1->GetDescription(indexOne);
688 std::string cmp2 = (iso2->GetPlatform() == GameListItem::GAMECUBE_DISC) ? iso2->GetCompany() : iso2->GetDescription(indexOther);
689 return strcasecmp(cmp1.c_str(), cmp2.c_str()) *t;
691 case CGameListCtrl::COLUMN_COUNTRY:
692 if(iso1->GetCountry() > iso2->GetCountry()) return 1 *t;
693 if(iso1->GetCountry() < iso2->GetCountry()) return -1 *t;
694 return 0;
695 case CGameListCtrl::COLUMN_SIZE:
696 if (iso1->GetFileSize() > iso2->GetFileSize()) return 1 *t;
697 if (iso1->GetFileSize() < iso2->GetFileSize()) return -1 *t;
698 return 0;
699 case CGameListCtrl::COLUMN_PLATFORM:
700 if(iso1->GetPlatform() > iso2->GetPlatform()) return 1 *t;
701 if(iso1->GetPlatform() < iso2->GetPlatform()) return -1 *t;
702 return 0;
703 case CGameListCtrl::COLUMN_EMULATION_STATE:
704 IniFile ini; int nState1 = 0, nState2 = 0;
705 std::string GameIni1 = std::string(File::GetUserPath(D_GAMECONFIG_IDX)) + iso1->GetUniqueID() + ".ini";
706 std::string GameIni2 = std::string(File::GetUserPath(D_GAMECONFIG_IDX)) + iso2->GetUniqueID() + ".ini";
708 ini.Load(GameIni1.c_str());
709 ini.Get("EmuState", "EmulationStateId", &nState1);
710 ini.Load(GameIni2.c_str());
711 ini.Get("EmuState", "EmulationStateId", &nState2);
713 if(nState1 > nState2) return 1 *t;
714 if(nState1 < nState2) return -1 *t;
715 return 0;
718 return 0;
721 void CGameListCtrl::OnColumnClick(wxListEvent& event)
723 if(event.GetColumn() != COLUMN_BANNER)
725 int current_column = event.GetColumn();
727 if(last_column == current_column)
729 last_sort = -last_sort;
731 else
733 last_column = current_column;
734 last_sort = current_column;
737 caller = this;
738 SortItems(wxListCompare, last_sort);
741 SetBackgroundColor();
743 event.Skip();
746 // This is used by keyboard gamelist search
747 void CGameListCtrl::OnKeyPress(wxListEvent& event)
749 static int lastKey = 0, sLoop = 0;
750 int Loop = 0;
752 for (int i = 0; i < (int)m_ISOFiles.size(); i++)
754 // Easy way to get game string
755 wxListItem bleh;
756 bleh.SetId(i);
757 bleh.SetColumn(COLUMN_TITLE);
758 bleh.SetMask(wxLIST_MASK_TEXT);
759 GetItem(bleh);
761 wxString text = bleh.GetText();
763 if (text.MakeUpper().at(0) == event.GetKeyCode())
765 if (lastKey == event.GetKeyCode() && Loop < sLoop)
767 Loop++;
768 if (i+1 == (int)m_ISOFiles.size())
769 i = -1;
770 continue;
772 else if (lastKey != event.GetKeyCode())
773 sLoop = 0;
775 lastKey = event.GetKeyCode();
776 sLoop++;
778 UnselectAll();
779 SetItemState(i, wxLIST_STATE_SELECTED|wxLIST_STATE_FOCUSED, wxLIST_STATE_SELECTED|wxLIST_STATE_FOCUSED);
780 EnsureVisible(i);
781 break;
784 // If we get past the last game in the list, we'll have to go back to the first one.
785 if (i+1 == (int)m_ISOFiles.size() && sLoop > 0 && Loop > 0)
786 i = -1;
789 event.Skip();
792 // This shows a little tooltip with the current Game's emulation state
793 void CGameListCtrl::OnMouseMotion(wxMouseEvent& event)
795 int flags; long subitem = 0;
796 long item = HitTest(event.GetPosition(), flags, &subitem);
797 static int lastItem = -1;
799 if (item != wxNOT_FOUND)
801 if (subitem == COLUMN_EMULATION_STATE)
803 if (toolTip || lastItem == item || this != FindFocus()) {
804 event.Skip();
805 return;
808 const GameListItem& rISO = m_ISOFiles[GetItemData(item)];
810 IniFile ini;
811 ini.Load((std::string(File::GetUserPath(D_GAMECONFIG_IDX)) + (rISO.GetUniqueID()) + ".ini").c_str());
813 // Emulation status
814 std::string emuState[5] = {"Broken", "Intro", "In-Game", "Playable", "Perfect"}, issues;
816 int nState;
817 ini.Get("EmuState", "EmulationStateId", &nState);
818 ini.Get("EmuState", "EmulationIssues", &issues, "");
820 // Get item Coords then convert from wxWindow coord to Screen coord
821 wxRect Rect;
822 this->GetItemRect(item, Rect);
823 int mx = Rect.GetWidth();
824 int my = Rect.GetY();
825 this->ClientToScreen(&mx, &my);
827 // Show a tooltip containing the EmuState and the state description
828 if (nState > 0 && nState < 6)
830 char temp[2048];
831 sprintf(temp, "^ %s%s%s", emuState[nState -1].c_str(), issues.size() > 0 ? " :\n" : "", issues.c_str());
832 toolTip = new wxEmuStateTip(this, wxString(temp, *wxConvCurrent), &toolTip);
834 else
835 toolTip = new wxEmuStateTip(this, wxT("Not Set"), &toolTip);
837 toolTip->SetBoundingRect(wxRect(mx - GetColumnWidth(subitem), my, GetColumnWidth(subitem), Rect.GetHeight()));
838 toolTip->SetPosition(wxPoint(mx - GetColumnWidth(subitem), my - 5 + Rect.GetHeight()));
840 lastItem = item;
844 event.Skip();
847 void CGameListCtrl::OnLeftClick(wxMouseEvent& event)
849 // Focus the clicked item.
850 int flags;
851 long item = HitTest(event.GetPosition(), flags);
852 if ((item != wxNOT_FOUND) && (GetSelectedItemCount() == 0) && (!event.ControlDown()) && (!event.ShiftDown()))
854 SetItemState(item, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED );
855 SetItemState(item, wxLIST_STATE_FOCUSED, wxLIST_STATE_FOCUSED);
856 wxGetApp().GetCFrame()->UpdateGUI();
859 event.Skip();
862 void CGameListCtrl::OnRightClick(wxMouseEvent& event)
864 // Focus the clicked item.
865 int flags;
866 long item = HitTest(event.GetPosition(), flags);
867 if (item != wxNOT_FOUND)
869 if (GetItemState(item, wxLIST_STATE_SELECTED) != wxLIST_STATE_SELECTED)
871 UnselectAll();
872 SetItemState(item, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED );
874 SetItemState(item, wxLIST_STATE_FOCUSED, wxLIST_STATE_FOCUSED);
877 if (GetSelectedItemCount() == 1)
879 const GameListItem *selected_iso = GetSelectedISO();
880 if (selected_iso)
882 wxMenu* popupMenu = new wxMenu;
883 popupMenu->Append(IDM_PROPERTIES, _("&Properties"));
884 popupMenu->AppendSeparator();
886 if (selected_iso->GetPlatform() != GameListItem::GAMECUBE_DISC)
888 popupMenu->Append(IDM_OPENSAVEFOLDER, _("Open Wii &save folder"));
889 popupMenu->Append(IDM_EXPORTSAVE, _("Export Wii save (Experimental)"));
891 popupMenu->Append(IDM_OPENCONTAININGFOLDER, _("Open &containing folder"));
892 popupMenu->AppendCheckItem(IDM_SETDEFAULTGCM, _("Set as &default ISO"));
894 // First we have to decide a starting value when we append it
895 if(selected_iso->GetFileName() == SConfig::GetInstance().
896 m_LocalCoreStartupParameter.m_strDefaultGCM)
897 popupMenu->FindItem(IDM_SETDEFAULTGCM)->Check();
899 popupMenu->AppendSeparator();
900 popupMenu->Append(IDM_DELETEGCM, _("&Delete ISO..."));
902 if (selected_iso->GetPlatform() != GameListItem::WII_WAD)
904 if (selected_iso->IsCompressed())
905 popupMenu->Append(IDM_COMPRESSGCM, _("Decompress ISO..."));
906 else
907 popupMenu->Append(IDM_COMPRESSGCM, _("Compress ISO..."));
908 } else
909 popupMenu->Append(IDM_INSTALLWAD, _("Install to Wii Menu"));
911 PopupMenu(popupMenu);
914 else if (GetSelectedItemCount() > 1)
916 wxMenu* popupMenu = new wxMenu;
917 popupMenu->Append(IDM_DELETEGCM, _("&Delete selected ISOs..."));
918 popupMenu->AppendSeparator();
919 popupMenu->Append(IDM_MULTICOMPRESSGCM, _("Compress selected ISOs..."));
920 popupMenu->Append(IDM_MULTIDECOMPRESSGCM, _("Decompress selected ISOs..."));
921 PopupMenu(popupMenu);
925 const GameListItem * CGameListCtrl::GetSelectedISO()
927 if (m_ISOFiles.size() == 0)
929 return NULL;
931 else if (GetSelectedItemCount() == 0)
933 return NULL;
935 else
937 long item = GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
938 if (item == wxNOT_FOUND)
939 return new GameListItem("");
940 else
942 // Here is a little workaround for multiselections:
943 // when > 1 item is selected, return info on the first one
944 // and deselect it so the next time GetSelectedISO() is called,
945 // the next item's info is returned
946 if (GetSelectedItemCount() > 1)
947 SetItemState(item, 0, wxLIST_STATE_SELECTED);
949 return &m_ISOFiles[GetItemData(item)];
954 void CGameListCtrl::OnOpenContainingFolder(wxCommandEvent& WXUNUSED (event))
956 const GameListItem *iso = GetSelectedISO();
957 if (!iso)
958 return;
959 std::string path;
960 SplitPath(iso->GetFileName(), &path, 0, 0);
961 WxUtils::Explore(path.c_str());
964 void CGameListCtrl::OnOpenSaveFolder(wxCommandEvent& WXUNUSED (event))
966 const GameListItem *iso = GetSelectedISO();
967 if (!iso)
968 return;
969 if (iso->GetWiiFSPath() != "NULL")
970 WxUtils::Explore(iso->GetWiiFSPath().c_str());
973 void CGameListCtrl::OnExportSave(wxCommandEvent& WXUNUSED (event))
975 const GameListItem *iso = GetSelectedISO();
976 if (!iso)
977 return;
978 u64 title;
979 DiscIO::IVolume *Iso = DiscIO::CreateVolumeFromFilename(iso->GetFileName());
980 if (Iso)
982 if (Iso->GetTitleID((u8*)&title))
984 title = Common::swap64(title);
985 CWiiSaveCrypted* exportSave = new CWiiSaveCrypted("", title);
986 delete exportSave;
988 delete Iso;
992 // =======================================================
993 // Save this file as the default file
994 // -------------
995 void CGameListCtrl::OnSetDefaultGCM(wxCommandEvent& event)
997 const GameListItem *iso = GetSelectedISO();
998 if (!iso) return;
1000 if (event.IsChecked()) // Write the new default value and save it the ini file
1002 SConfig::GetInstance().m_LocalCoreStartupParameter.m_strDefaultGCM = iso->GetFileName();
1003 SConfig::GetInstance().SaveSettings();
1005 else // Othwerise blank the value and save it
1007 SConfig::GetInstance().m_LocalCoreStartupParameter.m_strDefaultGCM = "";
1008 SConfig::GetInstance().SaveSettings();
1011 // =============
1014 void CGameListCtrl::OnDeleteGCM(wxCommandEvent& WXUNUSED (event))
1016 if (GetSelectedItemCount() == 1)
1018 const GameListItem *iso = GetSelectedISO();
1019 if (!iso)
1020 return;
1021 if (wxMessageBox(_("Are you sure you want to delete this file?\nIt will be gone forever!"),
1022 wxMessageBoxCaptionStr, wxYES_NO | wxICON_EXCLAMATION) == wxYES)
1024 File::Delete(iso->GetFileName().c_str());
1025 Update();
1028 else
1030 if (wxMessageBox(_("Are you sure you want to delete these files?\nThey will be gone forever!"),
1031 wxMessageBoxCaptionStr, wxYES_NO | wxICON_EXCLAMATION) == wxYES)
1033 int selected = GetSelectedItemCount();
1035 for (int i = 0; i < selected; i++)
1037 const GameListItem *iso = GetSelectedISO();
1038 File::Delete(iso->GetFileName().c_str());
1040 Update();
1045 void CGameListCtrl::OnProperties(wxCommandEvent& WXUNUSED (event))
1047 const GameListItem *iso = GetSelectedISO();
1048 if (!iso)
1049 return;
1050 CISOProperties ISOProperties(iso->GetFileName(), this);
1051 if(ISOProperties.ShowModal() == wxID_OK)
1052 Update();
1055 void CGameListCtrl::OnInstallWAD(wxCommandEvent& WXUNUSED (event))
1057 const GameListItem *iso = GetSelectedISO();
1058 if (!iso)
1059 return;
1061 wxProgressDialog dialog(_T("Installing WAD to Wii Menu..."),
1062 _T("Working..."),
1063 1000, // range
1064 this, // parent
1065 wxPD_APP_MODAL |
1066 // wxPD_AUTO_HIDE | -- try this as well
1067 wxPD_ELAPSED_TIME |
1068 wxPD_ESTIMATED_TIME |
1069 wxPD_REMAINING_TIME |
1070 wxPD_SMOOTH // - makes indeterminate mode bar on WinXP very small
1073 dialog.CenterOnParent();
1075 CBoot::Install_WiiWAD(iso->GetFileName().c_str());
1078 void CGameListCtrl::MultiCompressCB(const char* text, float percent, void* arg)
1080 percent = (((float)m_currentItem) + percent) / (float)m_numberItem;
1082 wxString textString(wxString::Format(wxT("%s (%i/%i) - %s"), m_currentFilename.c_str(), (int)m_currentItem+1, (int)m_numberItem, text));
1084 ((wxProgressDialog*)arg)->Update((int)(percent*1000), textString);
1087 void CGameListCtrl::OnMultiCompressGCM(wxCommandEvent& /*event*/)
1089 CompressSelection(true);
1092 void CGameListCtrl::OnMultiDecompressGCM(wxCommandEvent& /*event*/)
1094 CompressSelection(false);
1097 void CGameListCtrl::CompressSelection(bool _compress)
1099 wxString dirHome;
1100 wxGetHomeDir(&dirHome);
1102 wxDirDialog browseDialog(this, _("Browse for output directory"), dirHome, wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST);
1103 if (browseDialog.ShowModal() != wxID_OK)
1104 return;
1106 wxProgressDialog progressDialog(_compress ? _("Compressing ISO") : _("Decompressing ISO"),
1107 _("Working..."),
1108 1000, // range
1109 this, // parent
1110 wxPD_APP_MODAL |
1111 // wxPD_AUTO_HIDE | -- try this as well
1112 wxPD_ELAPSED_TIME |
1113 wxPD_ESTIMATED_TIME |
1114 wxPD_REMAINING_TIME |
1115 wxPD_SMOOTH // - makes indeterminate mode bar on WinXP very small
1118 progressDialog.SetSize(wxSize(600, 180));
1119 progressDialog.CenterOnParent();
1121 m_currentItem = 0;
1122 m_numberItem = GetSelectedItemCount();
1123 for (u32 i=0; i<m_numberItem; i++)
1125 const GameListItem *iso = GetSelectedISO();
1127 if (!iso->IsCompressed() && _compress)
1129 std::string FileName;
1130 SplitPath(iso->GetFileName(), NULL, &FileName, NULL);
1131 m_currentFilename = FileName;
1132 FileName.append(".gcz");
1134 std::string OutputFileName;
1135 BuildCompleteFilename(OutputFileName, (const char *)browseDialog.GetPath().mb_str(wxConvUTF8), FileName);
1137 DiscIO::CompressFileToBlob(iso->GetFileName().c_str(), OutputFileName.c_str(), (iso->GetPlatform() == GameListItem::WII_DISC) ? 1 : 0, 16384, &MultiCompressCB, &progressDialog);
1139 else if (iso->IsCompressed() && !_compress)
1141 std::string FileName;
1142 SplitPath(iso->GetFileName(), NULL, &FileName, NULL);
1143 m_currentFilename = FileName;
1144 FileName.append(".gcm");
1146 std::string OutputFileName;
1147 BuildCompleteFilename(OutputFileName, (const char *)browseDialog.GetPath().mb_str(wxConvUTF8), FileName);
1149 DiscIO::DecompressBlobToFile(iso->GetFileName().c_str(), OutputFileName.c_str(), &MultiCompressCB, &progressDialog);
1151 m_currentItem++;
1153 Update();
1156 void CGameListCtrl::CompressCB(const char* text, float percent, void* arg)
1158 ((wxProgressDialog*)arg)->Update((int)(percent*1000), wxString(text, *wxConvCurrent));
1161 void CGameListCtrl::OnCompressGCM(wxCommandEvent& WXUNUSED (event))
1163 const GameListItem *iso = GetSelectedISO();
1164 if (!iso)
1165 return;
1167 wxString path;
1169 std::string FileName;
1170 SplitPath(iso->GetFileName(), NULL, &FileName, NULL);
1172 if (iso->IsCompressed())
1174 path = wxFileSelector(
1175 _T("Save decompressed ISO"),
1176 wxEmptyString, wxString(FileName.c_str(), *wxConvCurrent), wxEmptyString,
1177 wxString::Format
1179 _T("All GC/Wii ISO files (gcm)|*.gcm|All files (%s)|%s"),
1180 wxFileSelectorDefaultWildcardStr,
1181 wxFileSelectorDefaultWildcardStr
1183 wxFD_SAVE,
1184 this);
1186 if (!path)
1188 return;
1191 else
1193 path = wxFileSelector(
1194 _T("Save compressed ISO"),
1195 wxEmptyString, wxString(FileName.c_str(), *wxConvCurrent), wxEmptyString,
1196 wxString::Format
1198 _T("All compressed GC/Wii ISO files (gcz)|*.gcz|All files (%s)|%s"),
1199 wxFileSelectorDefaultWildcardStr,
1200 wxFileSelectorDefaultWildcardStr
1202 wxFD_SAVE,
1203 this);
1205 if (!path)
1207 return;
1211 wxProgressDialog dialog(iso->IsCompressed() ? _T("Decompressing ISO") : _T("Compressing ISO"),
1212 _T("Working..."),
1213 1000, // range
1214 this, // parent
1215 wxPD_APP_MODAL |
1216 // wxPD_AUTO_HIDE | -- try this as well
1217 wxPD_ELAPSED_TIME |
1218 wxPD_ESTIMATED_TIME |
1219 wxPD_REMAINING_TIME |
1220 wxPD_SMOOTH // - makes indeterminate mode bar on WinXP very small
1223 dialog.SetSize(wxSize(280, 180));
1224 dialog.CenterOnParent();
1226 if (iso->IsCompressed())
1227 DiscIO::DecompressBlobToFile(iso->GetFileName().c_str(), path.char_str(), &CompressCB, &dialog);
1228 else
1229 DiscIO::CompressFileToBlob(iso->GetFileName().c_str(), path.char_str(), (iso->GetPlatform() == GameListItem::WII_DISC) ? 1 : 0, 16384, &CompressCB, &dialog);
1231 Update();
1234 void CGameListCtrl::OnSize(wxSizeEvent& event)
1236 if (lastpos == event.GetSize()) return;
1237 lastpos = event.GetSize();
1238 AutomaticColumnWidth();
1240 event.Skip();
1243 void CGameListCtrl::AutomaticColumnWidth()
1245 wxRect rc(GetClientRect());
1247 if (GetColumnCount() == 1)
1249 SetColumnWidth(0, rc.GetWidth());
1251 else if (GetColumnCount() > 4)
1253 int resizable = rc.GetWidth() - (
1254 GetColumnWidth(COLUMN_BANNER)
1255 + GetColumnWidth(COLUMN_COUNTRY)
1256 + GetColumnWidth(COLUMN_SIZE)
1257 + GetColumnWidth(COLUMN_EMULATION_STATE)
1258 + GetColumnWidth(COLUMN_PLATFORM)
1259 + 5); // some pad to keep the horizontal scrollbar away :)
1261 // We hide the Company column if the window is too small
1262 if (0.5*resizable > 200)
1264 SetColumnWidth(COLUMN_TITLE, 0.5*resizable);
1265 SetColumnWidth(COLUMN_NOTES, 0.5*resizable);
1267 else
1269 SetColumnWidth(COLUMN_TITLE, resizable);
1270 SetColumnWidth(COLUMN_NOTES, 0);
1275 void CGameListCtrl::UnselectAll()
1277 for (int i=0; i<GetItemCount(); i++)
1279 SetItemState(i, 0, wxLIST_STATE_SELECTED);