1 /* Author: Tobi Vollebregt */
2 
3 #include "mapselectdialog.h"
4 
5 #include "battle.h"
6 #include "server.h"
7 #include "settings.h"
8 #include "ui.h"
9 #include "uiutils.h"
10 #include "utils/controls.h"
11 #include "utils/conversion.h"
12 #include "utils/debug.h"
13 #include "settings.h"
14 #include <lslutils/globalsmanager.h>
15 #include <wx/settings.h>
16 #include <lslutils/misc.h>
17 
18 //(*InternalHeaders(MapSelectDialog)
19 #include <wx/listctrl.h>
20 #include <wx/sizer.h>
21 #include <wx/stattext.h>
22 #include <wx/textctrl.h>
23 #include <wx/radiobut.h>
24 #include "mapgridctrl.h"
25 #include <wx/choice.h>
26 #include <wx/intl.h>
27 #include <wx/button.h>
28 #include <wx/string.h>
29 //*)
30 
31 //(*IdInit(MapSelectDialog)
32 const long MapSelectDialog::ID_STATICTEXT2          = wxNewId();
33 const long MapSelectDialog::ID_VERTICAL_CHOICE      = wxNewId();
34 const long MapSelectDialog::ID_STATICTEXT1          = wxNewId();
35 const long MapSelectDialog::ID_HORIZONTAL_CHOICE    = wxNewId();
36 const long MapSelectDialog::ID_FILTER_ALL           = wxNewId();
37 const long MapSelectDialog::ID_FILTER_POPULAR       = wxNewId();
38 const long MapSelectDialog::ID_FILTER_RECENT        = wxNewId();
39 const long MapSelectDialog::ID_FILTER_TEXT          = wxNewId();
40 const long MapSelectDialog::ID_MAP_NAME             = wxNewId();
41 const long MapSelectDialog::ID_MAP_OPTS_LIST        = wxNewId();
42 const long MapSelectDialog::ID_MAPGRID              = wxNewId();
43 //*)
44 const long MapSelectDialog::ID_VERTICAL_DIRECTION   = wxNewId();
45 const long MapSelectDialog::ID_HORIZONTAL_DIRECTION = wxNewId();
46 
47 const wxString MapSelectDialog::m_dialog_name = _T("MapSelector");
48 
BEGIN_EVENT_TABLE(MapSelectDialog,wxDialog)49 BEGIN_EVENT_TABLE(MapSelectDialog,wxDialog)
50 	//(*EventTable(MapSelectDialog)
51 	//*)
52 END_EVENT_TABLE()
53 
54 MapSelectDialog::MapSelectDialog( wxWindow* parent )
55 	: // WindowHintsPickle( m_dialog_name, this, wxSize( DEFSETT_MW_WIDTH, DEFSETT_MW_HEIGHT ) ),
56 	m_horizontal_direction( sett().GetHorizontalSortorder() ),
57 	m_vertical_direction( sett().GetVerticalSortorder() )
58 {
59 	//(*Initialize(MapSelectDialog)
60 	wxStaticBoxSizer* StaticBoxSizer2;
61 	wxStaticText* StaticText2;
62 	wxStaticText* StaticText1;
63 	wxBoxSizer* BoxSizer2;
64 	wxBoxSizer* boxSizerHorizontal;
65 	wxBoxSizer* BoxSizer1;
66 	wxStaticBoxSizer* StaticBoxSizer1;
67 	wxBoxSizer* boxSizerVertical;
68 	wxStdDialogButtonSizer* StdDialogButtonSizer1;
69 
70 	Create(parent, wxID_ANY, _("Select map (click and drag to scroll)"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER|wxMAXIMIZE_BOX, _T("wxID_ANY"));
71 	BoxSizer1 = new wxBoxSizer(wxHORIZONTAL);
72 	BoxSizer2 = new wxBoxSizer(wxVERTICAL);
73 	StaticText2 = new wxStaticText(this, ID_STATICTEXT2, _("Vertical sort key"), wxDefaultPosition, wxDefaultSize, 0, _T("ID_STATICTEXT2"));
74 	BoxSizer2->Add(StaticText2, 0, wxALL|wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL, 5);
75 	boxSizerVertical = new wxBoxSizer(wxHORIZONTAL);
76 	m_vertical_choice = new wxChoice(this, ID_VERTICAL_CHOICE, wxDefaultPosition, wxDefaultSize, 0, 0, 0, wxDefaultValidator, _T("ID_VERTICAL_CHOICE"));
77 	boxSizerVertical->Add(m_vertical_choice, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
78 	BoxSizer2->Add(boxSizerVertical, 0, wxALL|wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
79 	StaticText1 = new wxStaticText(this, ID_STATICTEXT1, _("Horizontal sort key"), wxDefaultPosition, wxDefaultSize, 0, _T("ID_STATICTEXT1"));
80 	BoxSizer2->Add(StaticText1, 0, wxALL|wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL, 5);
81 	boxSizerHorizontal = new wxBoxSizer(wxHORIZONTAL);
82 	m_horizontal_choice = new wxChoice(this, ID_HORIZONTAL_CHOICE, wxDefaultPosition, wxDefaultSize, 0, 0, 0, wxDefaultValidator, _T("ID_HORIZONTAL_CHOICE"));
83 	boxSizerHorizontal->Add(m_horizontal_choice, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
84 	BoxSizer2->Add(boxSizerHorizontal, 0, wxALL|wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
85 	StaticBoxSizer1 = new wxStaticBoxSizer(wxVERTICAL, this, _("Show"));
86 	m_filter_all = new wxRadioButton(this, ID_FILTER_ALL, _("All maps"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_FILTER_ALL"));
87 	m_filter_all->SetToolTip(_("Shows all available maps"));
88 	StaticBoxSizer1->Add(m_filter_all, 0, wxALL|wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
89 	m_filter_popular = new wxRadioButton(this, ID_FILTER_POPULAR, _("Popular maps"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_FILTER_POPULAR"));
90 	m_filter_popular->SetToolTip(_("Shows only maps which are currently being player on the server. You must be online to use this."));
91 	StaticBoxSizer1->Add(m_filter_popular, 0, wxALL|wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
92 	m_filter_recent = new wxRadioButton(this, ID_FILTER_RECENT, _("Recently played maps"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_FILTER_RECENT"));
93 	m_filter_recent->SetValue(true);
94 	m_filter_recent->SetToolTip(_("Shows only maps you played recently. (Based on your replays.)"));
95 	StaticBoxSizer1->Add(m_filter_recent, 0, wxALL|wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
96 	BoxSizer2->Add(StaticBoxSizer1, 0, wxALL|wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
97 	StaticBoxSizer2 = new wxStaticBoxSizer(wxHORIZONTAL, this, _("Filter"));
98 	m_filter_text = new wxTextCtrl(this, ID_FILTER_TEXT, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_FILTER_TEXT"));
99 	m_filter_text->SetToolTip(_("Shows only maps which contain this text in their name or description."));
100 	StaticBoxSizer2->Add(m_filter_text, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
101 	BoxSizer2->Add(StaticBoxSizer2, 0, wxALL|wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
102 	m_map_details = new wxStaticBoxSizer(wxVERTICAL, this, _("Map details"));
103 	m_map_name = new wxStaticText(this, ID_MAP_NAME, wxEmptyString, wxDefaultPosition, wxSize(170,90), wxST_NO_AUTORESIZE, _T("ID_MAP_NAME"));
104 	m_map_name->SetLabel( wxEmptyString );
105 	m_map_details->Add(m_map_name, 0, wxTOP|wxLEFT|wxRIGHT|wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
106 	m_map_opts_list = new wxListCtrl(this, ID_MAP_OPTS_LIST, wxDefaultPosition, wxSize(170,120), wxLC_REPORT|wxLC_NO_HEADER|wxNO_BORDER, wxDefaultValidator, _T("ID_MAP_OPTS_LIST"));
107 	m_map_details->Add(m_map_opts_list, 1, wxBOTTOM|wxLEFT|wxRIGHT|wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
108 	BoxSizer2->Add(m_map_details, 1, wxALL|wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
109 	StdDialogButtonSizer1 = new wxStdDialogButtonSizer();
110 	StdDialogButtonSizer1->AddButton(new wxButton(this, wxID_OK, wxEmptyString));
111 	StdDialogButtonSizer1->AddButton(new wxButton(this, wxID_CANCEL, wxEmptyString));
112 	StdDialogButtonSizer1->Realize();
113 	BoxSizer2->Add(StdDialogButtonSizer1, 0, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
114 	BoxSizer1->Add(BoxSizer2, 0, wxALL|wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
115 	m_mapgrid = new MapGridCtrl(this, wxSize(600,400), ID_MAPGRID);
116 	BoxSizer1->Add(m_mapgrid, 1, wxALL|wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
117 	SetSizer(BoxSizer1);
118 	BoxSizer1->Fit(this);
119 	BoxSizer1->SetSizeHints(this);
120 	Center();
121 
122 	Connect(ID_VERTICAL_CHOICE,wxEVT_COMMAND_CHOICE_SELECTED,(wxObjectEventFunction)&MapSelectDialog::OnSortKeySelect);
123 	Connect(ID_HORIZONTAL_CHOICE,wxEVT_COMMAND_CHOICE_SELECTED,(wxObjectEventFunction)&MapSelectDialog::OnSortKeySelect);
124 	Connect(ID_FILTER_ALL,wxEVT_COMMAND_RADIOBUTTON_SELECTED,(wxObjectEventFunction)&MapSelectDialog::OnFilterAllSelect);
125 	Connect(ID_FILTER_POPULAR,wxEVT_COMMAND_RADIOBUTTON_SELECTED,(wxObjectEventFunction)&MapSelectDialog::OnFilterPopularSelect);
126 	Connect(ID_FILTER_RECENT,wxEVT_COMMAND_RADIOBUTTON_SELECTED,(wxObjectEventFunction)&MapSelectDialog::OnFilterRecentSelect);
127 	Connect(ID_FILTER_TEXT,wxEVT_COMMAND_TEXT_UPDATED,(wxObjectEventFunction)&MapSelectDialog::OnFilterTextChanged);
128 	m_mapgrid->Connect(ID_MAPGRID,wxEVT_LEFT_DCLICK,(wxObjectEventFunction)&MapSelectDialog::OnMapGridLeftDClick,0,this);
129 	Connect(wxID_ANY,wxEVT_INIT_DIALOG,(wxObjectEventFunction)&MapSelectDialog::OnInit);
130 	//*)
131 
132 	Connect(ID_MAPGRID,MapGridCtrl::MapSelectedEvt,(wxObjectEventFunction)&MapSelectDialog::OnMapSelected,0,this);
133 	Connect(ID_MAPGRID,MapGridCtrl::LoadingCompletedEvt,(wxObjectEventFunction)&MapSelectDialog::OnMapLoadingCompleted,0,this);
134 
135 	// Ugh.. Can not have these created by generated code because wxSmith doesn't accept a symbolic size,
136 	// (ie. wxSize(CONTROL_HEIGHT,CONTROL_HEIGHT)) and all Set*Size() methods don't seem to have any effect.
137 	m_vertical_direction_button = new wxButton(this, ID_VERTICAL_DIRECTION, _T("ᴧ"), wxDefaultPosition, wxSize(CONTROL_HEIGHT,CONTROL_HEIGHT), 0, wxDefaultValidator, _T("ID_VERTICAL_DIRECTION"));
138 	boxSizerVertical->Add(m_vertical_direction_button, 0, wxALL|wxEXPAND|wxSHAPED|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
139 	m_horizontal_direction_button = new wxButton(this, ID_HORIZONTAL_DIRECTION, _T("<"), wxDefaultPosition, wxSize(CONTROL_HEIGHT,CONTROL_HEIGHT), 0, wxDefaultValidator, _T("ID_HORIZONTAL_DIRECTION"));
140 	boxSizerHorizontal->Add(m_horizontal_direction_button, 0, wxALL|wxEXPAND|wxSHAPED|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
141 	//<>ᴠᴧ
142 
143 	Connect(ID_VERTICAL_DIRECTION, wxEVT_COMMAND_BUTTON_CLICKED, (wxObjectEventFunction)&MapSelectDialog::OnVerticalDirectionClicked);
144 	Connect(ID_HORIZONTAL_DIRECTION, wxEVT_COMMAND_BUTTON_CLICKED, (wxObjectEventFunction)&MapSelectDialog::OnHorizontalDirectionClicked);
145 
146 	// TODO: refactor, this is copied from battlemaptab.cpp
147 	m_map_opts_list->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) );
148 	m_map_opts_list->SetFont( wxFont( 8, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_LIGHT ) );
149 
150 	wxListItem col;
151 
152 	col.SetText( _("Option") );
153 	m_map_opts_list->InsertColumn( 0, col );
154 	col.SetText( _("Value") );
155 	m_map_opts_list->InsertColumn( 1, col );
156 	m_map_opts_list->SetColumnWidth( 0, 90 );
157 	m_map_opts_list->SetColumnWidth( 1, 80 );
158 
159 	m_map_opts_list->InsertItem( 0, _("Size") );
160 	m_map_opts_list->InsertItem( 1, _("Windspeed") );
161 	m_map_opts_list->InsertItem( 2, _("Tidal strength") );
162 	m_map_opts_list->InsertItem( 3, _("Gravity") );
163 	m_map_opts_list->InsertItem( 4, _("Extractor radius") );
164 	m_map_opts_list->InsertItem( 5, _("Max metal") );
165 	m_map_opts_list->InsertItem( 6, _("Start positions") );
166 
167     Layout();
168 	ConnectGlobalEvent(this, GlobalEvent::OnUnitsyncReloaded, wxObjectEventFunction(&MapSelectDialog::OnUnitsyncReloaded));
169 }
170 
~MapSelectDialog()171 MapSelectDialog::~MapSelectDialog()
172 {
173 	//(*Destroy(MapSelectDialog)
174 	//*)
175 	sett().SetHorizontalSortkeyIndex( m_horizontal_choice->GetSelection() );
176 	sett().SetVerticalSortkeyIndex( m_vertical_choice->GetSelection() );
177 	sett().SetHorizontalSortorder( m_horizontal_direction );
178 	sett().SetVerticalSortorder( m_vertical_direction );
179     if ( m_filter_all->GetValue() )
180         sett().SetMapSelectorFilterRadio( m_filter_all_sett );
181     else if ( m_filter_recent->GetValue() )
182         sett().SetMapSelectorFilterRadio( m_filter_recent_sett );
183     else
184         sett().SetMapSelectorFilterRadio( m_filter_popular_sett );
185 	if ( IsShown() )
186 		EndModal( 0 );
187 }
188 
189 
OnInit(wxInitDialogEvent &)190 void MapSelectDialog::OnInit( wxInitDialogEvent& /*unused*/ )
191 {
192 	wxLogDebugFunc( wxEmptyString );
193 
194 	AppendSortKeys( m_horizontal_choice );
195 	AppendSortKeys( m_vertical_choice );
196 
197 	m_horizontal_choice->SetSelection( sett().GetHorizontalSortkeyIndex() );
198 	m_vertical_choice->SetSelection( sett().GetVerticalSortkeyIndex() );
199 
200     m_horizontal_direction_button->SetLabel( m_horizontal_direction ? _T(">") : _T("<") );
201     m_vertical_direction_button->SetLabel( m_vertical_direction ? _T("ᴠ") : _T("ᴧ") );
202 
203     m_maps = LSL::Util::vectorToArrayString(LSL::usync().GetMapList());
204     //true meaning replays, flase meaning savegames
205     m_replays = LSL::Util::vectorToArrayString(LSL::usync().GetPlaybackList(true));
206 
207     const unsigned int lastFilter = sett().GetMapSelectorFilterRadio();
208 	m_filter_popular->Enable( ui().IsConnected() );
209 
210 	// due to a bug / crappy design in SpringUnitSync / unitsync itself we
211 	// get a replay list with one empty item when there are no replays..
212 	bool no_replays = m_replays.empty() || ( m_replays.size() == 1 && m_replays[0] == wxEmptyString );
213 	if ( no_replays ) {
214 		m_filter_all->SetValue( true );
215 		m_filter_recent->Enable( false );
216 	}
217 
218 	if ( lastFilter == m_filter_popular_sett ) {
219 	    if ( ui().IsConnected() ) {
220 	        m_filter_popular->SetValue( true );
221             LoadPopular();
222 	    }
223 	    else {
224 	        m_filter_all->SetValue( true );
225 	        LoadAll();
226 	    }
227 	}
228 	else if ( lastFilter == m_filter_recent_sett ) {
229 	    if ( !no_replays ) {
230             m_filter_recent->Enable( true );
231             m_filter_recent->SetValue( true );
232             LoadRecent();
233 	    }
234 	    else {
235 	        m_filter_all->SetValue( true );
236 	        LoadAll();
237 	    }
238 	}
239 	else {
240 	        m_filter_all->SetValue( true );
241 	        LoadAll();
242     }
243 
244     UpdateSortAndFilter();
245 
246 	m_filter_text->SetFocus();
247 }
248 
249 
OnSortKeySelect(wxCommandEvent &)250 void MapSelectDialog::OnSortKeySelect( wxCommandEvent& /*unused*/ )
251 {
252 	wxLogDebugFunc( wxEmptyString );
253 	UpdateSortAndFilter();
254 }
255 
256 
AppendSortKeys(wxChoice * choice)257 void MapSelectDialog::AppendSortKeys( wxChoice* choice )
258 {
259 	// see MapGridCtrl for available SortKeys
260 	choice->Append( _("Name"), (void*) MapGridCtrl::SortKey_Name );
261 	choice->Append( _("Tidal strength"), (void*) MapGridCtrl::SortKey_TidalStrength );
262 	choice->Append( _("Gravity"), (void*) MapGridCtrl::SortKey_Gravity );
263 	choice->Append( _("Max metal"), (void*) MapGridCtrl::SortKey_MaxMetal );
264 	choice->Append( _("Extractor radius"), (void*) MapGridCtrl::SortKey_ExtractorRadius );
265 	choice->Append( _("Minimum wind"), (void*) MapGridCtrl::SortKey_MinWind );
266 	choice->Append( _("Maximum wind"), (void*) MapGridCtrl::SortKey_MaxWind );
267 	choice->Append( _("Average wind"), (void*) MapGridCtrl::SortKey_Wind );
268 	choice->Append( _("Size (map area)"), (void*) MapGridCtrl::SortKey_Area );
269 	choice->Append( _("Aspect ratio"), (void*) MapGridCtrl::SortKey_AspectRatio );
270 	choice->Append( _("Number of start positions"), (void*) MapGridCtrl::SortKey_PosCount );
271 }
272 
GetSelectedSortKey(wxChoice * choice)273 static MapGridCtrl::SortKey GetSelectedSortKey( wxChoice* choice )
274 {
275 	const int selection = choice->GetSelection();
276 	if (selection == wxNOT_FOUND) //default to first entry
277 		return MapGridCtrl::SortKey_Name;
278 	return (MapGridCtrl::SortKey) (int) (long) choice->GetClientData( selection );
279 }
280 
281 namespace {
282 struct FilterPredicate
283 {
FilterPredicate__anonbc46f5b40111::FilterPredicate284     FilterPredicate( const wxString& _searchText ) : searchText(STD_STRING(_searchText.Lower())) {}
operator ()__anonbc46f5b40111::FilterPredicate285 	bool operator () ( const LSL::UnitsyncMap& map ) const
286 	{
287         return boost::to_lower_copy(map.name).find(searchText) != std::string::npos
288             || boost::to_lower_copy(map.info.description).find(searchText) != std::string::npos
289             || boost::to_lower_copy(map.info.author).find(searchText) != std::string::npos;
290 	}
291     const std::string searchText;
292 };
293 }
294 
UpdateSortAndFilter()295 void MapSelectDialog::UpdateSortAndFilter()
296 {
297 	FilterPredicate predicate( m_filter_text->GetValue() );
298 	m_mapgrid->Filter( predicate );
299 	m_mapgrid->Sort( GetSelectedSortKey( m_vertical_choice ), GetSelectedSortKey( m_horizontal_choice ), m_vertical_direction, m_horizontal_direction );
300 	m_mapgrid->Refresh();
301 }
302 
GetSelectedMap() const303 LSL::UnitsyncMap* MapSelectDialog::GetSelectedMap() const
304 {
305 	wxLogDebugFunc( wxEmptyString );
306 	return m_mapgrid->GetSelectedMap();
307 }
308 
OnMapSelected(wxCommandEvent & event)309 void MapSelectDialog::OnMapSelected( wxCommandEvent& event )
310 {
311 	const wxString& mapname = event.GetString();
312 
313 	wxLogDebugFunc( mapname );
314 
315 	const LSL::UnitsyncMap* pMap = m_mapgrid->GetSelectedMap();
316 	if ( pMap == NULL) return;
317 	const LSL::UnitsyncMap& map = *pMap;
318 
319     m_map_name->SetLabel(TowxString(map.name + "\n\n" + map.info.description));
320 
321 	// TODO: refactor, this is copied from battlemaptab.cpp
322 	m_map_opts_list->SetItem( 0, 1, wxFormat( _T("%dx%d") ) % (map.info.width/512) % (map.info.height/512) );
323 	m_map_opts_list->SetItem( 1, 1, wxFormat( _T("%d-%d") ) % map.info.minWind % map.info.maxWind );
324 	m_map_opts_list->SetItem( 2, 1, wxFormat( _T("%d") ) % map.info.tidalStrength );
325 	m_map_opts_list->SetItem( 3, 1, wxFormat( _T("%d") ) % map.info.gravity );
326 	m_map_opts_list->SetItem( 4, 1, wxFormat( _T("%d") ) % map.info.extractorRadius );
327 	m_map_opts_list->SetItem( 5, 1, wxFormat( _T("%.3f") ) % map.info.maxMetal );
328 	m_map_opts_list->SetItem( 6, 1, wxFormat( _T("%d") ) % map.info.positions.size() );
329 }
330 
OnMapLoadingCompleted(wxCommandEvent &)331 void MapSelectDialog::OnMapLoadingCompleted( wxCommandEvent& /*unused*/ )
332 {
333 	wxLogDebugFunc( wxEmptyString );
334 	// to apply stored sorting settings we need to re-apply sorting after loading finished
335 	UpdateSortAndFilter();
336 }
337 
OnVerticalDirectionClicked(wxCommandEvent &)338 void MapSelectDialog::OnVerticalDirectionClicked( wxCommandEvent& /*unused*/ )
339 {
340 	wxLogDebugFunc( wxEmptyString );
341 	m_vertical_direction = !m_vertical_direction;
342 	m_vertical_direction_button->SetLabel( m_vertical_direction ? _T("ᴠ") : _T("ᴧ") );
343 	UpdateSortAndFilter();
344 }
345 
OnHorizontalDirectionClicked(wxCommandEvent &)346 void MapSelectDialog::OnHorizontalDirectionClicked( wxCommandEvent& /*unused*/ )
347 {
348 	wxLogDebugFunc( wxEmptyString );
349 	m_horizontal_direction = !m_horizontal_direction;
350 	m_horizontal_direction_button->SetLabel( m_horizontal_direction ? _T(">") : _T("<") );
351 	UpdateSortAndFilter();
352 }
353 
OnMapGridLeftDClick(wxMouseEvent &)354 void MapSelectDialog::OnMapGridLeftDClick(wxMouseEvent& /*unused*/)
355 {
356 	wxLogDebugFunc( wxEmptyString );
357 
358 	if ( m_mapgrid->GetSelectedMap() ) {
359 		EndModal( wxID_OK );
360 	}
361 }
362 
LoadAll()363 void MapSelectDialog::LoadAll()
364 {
365 	wxLogDebugFunc( wxEmptyString );
366 	const int count = m_maps.size();
367 
368 	m_mapgrid->Clear();
369 
370 	for ( int i = 0; i < count; ++i ) {
371 		m_mapgrid->AddMap( m_maps[i] );
372 	}
373 
374 	m_mapgrid->Refresh();
375 }
376 
LoadPopular()377 void MapSelectDialog::LoadPopular()
378 {
379 	wxLogDebugFunc( wxEmptyString );
380 
381 	m_mapgrid->Clear();
382 
383 	try {
384 		serverSelector().GetServer().battles_iter->IteratorBegin();
385 		while ( !serverSelector().GetServer().battles_iter->EOL() ) {
386 			Battle* b = serverSelector().GetServer().battles_iter->GetBattle();
387 			const wxString mapname = b->GetHostMapName();
388 			assert(!mapname.empty());
389 			if ( b != NULL ) m_mapgrid->AddMap( mapname );
390 		}
391 	}
392 	catch (...) {} // ui().GetServer may throw when disconnected...
393 
394 	m_mapgrid->Refresh();
395 }
396 
LoadRecent()397 void MapSelectDialog::LoadRecent()
398 {
399 	wxLogDebugFunc( wxEmptyString );
400 	const int count = m_maps.size();
401 
402 	m_mapgrid->Clear();
403 
404 	// just check whether map names are contained in replay names
405 	// not the most elegant solution but, hey, it works
406 	for ( int i = 0; i < count; ++i ) {
407 		// prefix and suffix with underscore to prevent most common partial matches
408 		const wxString mapname = _T("_") + m_maps[i].BeforeLast( '.' ) + _T("_");
409 		long replaycount = long(m_replays.GetCount());
410 		for ( int replaynum = 0; replaynum < replaycount; replaynum++ ) {
411 			if ( m_replays[replaynum].Find( mapname ) != wxNOT_FOUND )
412 				m_mapgrid->AddMap( m_maps[i] );
413 		}
414 	}
415 
416 	m_mapgrid->Refresh();
417 }
418 
419 // filter event handlers
420 
OnFilterAllSelect(wxCommandEvent &)421 void MapSelectDialog::OnFilterAllSelect(wxCommandEvent& /*unused*/)
422 {
423 	wxLogDebugFunc( wxEmptyString );
424 	LoadAll();
425 }
426 
OnFilterPopularSelect(wxCommandEvent &)427 void MapSelectDialog::OnFilterPopularSelect(wxCommandEvent& /*unused*/)
428 {
429 	wxLogDebugFunc( wxEmptyString );
430 	LoadPopular();
431 }
432 
OnFilterRecentSelect(wxCommandEvent &)433 void MapSelectDialog::OnFilterRecentSelect(wxCommandEvent& /*unused*/)
434 {
435 	wxLogDebugFunc( wxEmptyString );
436 	LoadRecent();
437 }
438 
OnFilterTextChanged(wxCommandEvent &)439 void MapSelectDialog::OnFilterTextChanged(wxCommandEvent& /*unused*/)
440 {
441 	wxLogDebugFunc( wxEmptyString );
442 	UpdateSortAndFilter();
443 }
444 
OnUnitsyncReloaded(wxCommandEvent &)445 void MapSelectDialog::OnUnitsyncReloaded( wxCommandEvent& /*data*/ )
446 {
447 	wxInitDialogEvent dummy;
448 	AddPendingEvent( dummy );
449 }
450 
mapSelectDialog(bool hidden,wxWindow * parent)451 wxString mapSelectDialog(bool hidden, wxWindow* parent){
452 	wxString mapname = wxEmptyString;
453 	assert( (hidden && parent!=NULL) || (!hidden && parent==NULL)); //at the first call, the window is created hidden
454 	static MapSelectDialog* m = new MapSelectDialog(parent);
455 	if ( (!hidden) && (m->ShowModal() == wxID_OK) && (m->GetSelectedMap() != NULL) ) {
456 		mapname = TowxString(m->GetSelectedMap()->name);
457 	}
458 	return mapname;
459 }
460 
461