1 /* Copyright (C) 2007 The SpringLobby Team. All rights reserved. */
2 //
3 // Class: BattleMapTab
4 //
5 
6 #include <wx/splitter.h>
7 #include <wx/intl.h>
8 #include <wx/combobox.h>
9 #include <wx/stattext.h>
10 #include <wx/statline.h>
11 #include <wx/checkbox.h>
12 #include <wx/button.h>
13 #include <wx/sizer.h>
14 #include <wx/radiobox.h>
15 #include <wx/window.h>
16 #include <wx/listctrl.h>
17 #include <wx/settings.h>
18 #include <wx/arrstr.h>
19 #include <wx/choice.h>
20 
21 #include <stdexcept>
22 
23 #include "battlemaptab.h"
24 #include <lslutils/conversion.h>
25 #include "user.h"
26 #include "battle.h"
27 #include "utils/debug.h"
28 #include "utils/controls.h"
29 #include "chatpanel.h"
30 #include "mapctrl.h"
31 #include "mapselectdialog.h"
32 #include "uiutils.h"
33 #include "server.h"
34 #include "settings.h"
35 #include "aui/auimanager.h"
36 
BEGIN_EVENT_TABLE(BattleMapTab,wxPanel)37 BEGIN_EVENT_TABLE( BattleMapTab, wxPanel )
38 
39 	EVT_CHOICE      ( BMAP_MAP_SEL,     BattleMapTab::OnMapSelect       )
40 	EVT_BUTTON      ( BMAP_MAP_BROWSE,  BattleMapTab::OnMapBrowse       )
41 	EVT_RADIOBOX    ( BMAP_START_TYPE,  BattleMapTab::OnStartTypeSelect )
42 
43 END_EVENT_TABLE()
44 
45 
46 BattleMapTab::BattleMapTab( wxWindow* parent, Battle* battle )
47     : wxScrolledWindow( parent, -1 ),
48 	m_battle( battle )
49 {
50 	GetAui().manager->AddPane( this, wxLEFT, _T( "battlemaptab" ) );
51 
52 	wxBoxSizer* m_main_sizer = new wxBoxSizer( wxHORIZONTAL );
53 	wxBoxSizer* m_map_sizer = new wxBoxSizer( wxVERTICAL );
54 
55 	m_map_sizer->SetMinSize( wxSize( 352, -1 ) );
56 	m_minimap = new MapCtrl( this, 352, m_battle, true, false, true, false );
57 
58 	m_minimap->SetMinSize( wxSize( 352, 352 ) );
59 
60 	m_map_sizer->Add( m_minimap, 1, wxALL | wxEXPAND, 2 );
61 
62 	wxBoxSizer* m_selmap_sizer = new wxBoxSizer( wxHORIZONTAL );
63 
64 	m_map_combo = new wxChoice( this, BMAP_MAP_SEL, wxDefaultPosition, wxDefaultSize );
65 	m_selmap_sizer->Add( m_map_combo, 1, wxALL, 2 );
66 
67 	m_browse_btn = new wxButton( this, BMAP_MAP_BROWSE, _( "Select" ), wxDefaultPosition, wxDefaultSize, 0 );
68 
69 	m_selmap_sizer->Add( m_browse_btn, 0, wxALL, 2 );
70 
71 	m_map_sizer->Add( m_selmap_sizer, 0, wxEXPAND, 5 );
72 
73 	m_main_sizer->Add( m_map_sizer, 1, wxEXPAND, 5 );
74 
75 	wxBoxSizer* m_opts_sizer = new wxBoxSizer( wxVERTICAL );
76 
77 	//m_opts_sizer->SetMinSize(wxSize( 200,-1 ));
78 	m_map_opts_list = new wxListCtrl( this, wxID_ANY, wxDefaultPosition, wxSize( 150, 160 ), wxLC_NO_HEADER | wxLC_REPORT );
79 	m_map_opts_list->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) );
80 	m_map_opts_list->SetFont( wxFont( 8, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_LIGHT ) );
81 
82 	wxListItem col;
83 
84 	col.SetText( _( "Option" ) );
85 	m_map_opts_list->InsertColumn( 0, col );
86 	col.SetText( _( "Value" ) );
87 	m_map_opts_list->InsertColumn( 1, col );
88 	m_map_opts_list->SetColumnWidth( 0, 90 );
89 	m_map_opts_list->SetColumnWidth( 1, 50 );
90 
91 	m_map_opts_list->InsertItem( 0, _( "Size" ) );
92 	m_map_opts_list->InsertItem( 1, _( "Windspeed" ) );
93 	m_map_opts_list->InsertItem( 2, _( "Tidal strength" ) );
94 	m_map_opts_list->InsertItem( 3, _( "Gravity" ) );
95 	m_map_opts_list->InsertItem( 4, _( "Extractor radius" ) );
96 	m_map_opts_list->InsertItem( 5, _( "Max metal" ) );
97 
98 	m_opts_sizer->Add( m_map_opts_list, 0, wxALL, 2 );
99 
100 
101 	wxString m_start_radiosChoices[] = { _( "Fixed" ), _( "Random" ), _( "Choose in game" ), _( "Chose before game" ) };
102 	int m_start_radiosNChoices = sizeof( m_start_radiosChoices ) / sizeof( wxString );
103 	//TODO these need to be tooltipped, no idea how yet
104 	m_start_radios = new wxRadioBox( this, BMAP_START_TYPE, _( "Startpositions" ), wxDefaultPosition, wxSize( 150, -1 ), m_start_radiosNChoices, m_start_radiosChoices, 1, wxRA_SPECIFY_COLS );
105 
106 	m_opts_sizer->Add( m_start_radios, 0, wxALL, 2 );
107 
108 	m_map_desc = new wxStaticText(this,-1,wxEmptyString);
109     m_map_desc->Wrap(160);
110 
111     m_opts_sizer->Add( m_map_desc, 0, wxALL, 2 );
112 
113 	m_main_sizer->Add( m_opts_sizer, 0, wxEXPAND, 5 );
114 	//m_main_sizer->AddStretchSpacer();
115 	SetSizer( m_main_sizer );
116 	Layout();
117 
118 	SetBattle( battle );
119 
120 	SetScrollRate( SCROLL_RATE, SCROLL_RATE );
121 	Layout();
122 	ConnectGlobalEvent(this, GlobalEvent::OnUnitsyncReloaded, wxObjectEventFunction(&BattleMapTab::OnUnitsyncReloaded));
123 }
124 
125 
~BattleMapTab()126 BattleMapTab::~BattleMapTab()
127 {
128 	if ( GetAui().manager )
129         GetAui().manager->DetachPane( this );
130 }
131 
Update()132 void BattleMapTab::Update()
133 {
134 	if ( !m_battle ) return;
135     const long longval = LSL::Util::FromString<long>(
136                 m_battle->CustomBattleOptions().getSingleValue( "startpostype", LSL::OptionsWrapper::EngineOption ));
137 	m_start_radios->SetSelection( longval );
138 
139 	m_minimap->UpdateMinimap();
140 
141 	if ( !m_battle->MapExists() ) return;
142 
143 	LSL::UnitsyncMap map = m_battle->LoadMap();
144 
145 	m_map_opts_list->SetItem( 0, 1, wxFormat( _T( "%dx%d" ) ) % (map.info.width / 512) % (map.info.height / 512) );
146 	m_map_opts_list->SetItem( 1, 1, wxFormat( _T( "%d-%d" ) ) % map.info.minWind % map.info.maxWind );
147 	m_map_opts_list->SetItem( 2, 1, wxFormat( _T( "%d" ) ) % map.info.tidalStrength );
148 	m_map_opts_list->SetItem( 3, 1, wxFormat( _T( "%d" ) ) % map.info.gravity );
149 	m_map_opts_list->SetItem( 4, 1, wxFormat( _T( "%d" ) ) % map.info.extractorRadius );
150 	m_map_opts_list->SetItem( 5, 1, wxFormat( _T( "%.3f" ) ) % map.info.maxMetal );
151 
152     m_map_desc->SetLabel(TowxString(map.info.description));
153     m_map_desc->Wrap(160);
154 
155 	int index = m_map_combo->FindString( TowxString(map.name)  );
156 	if ( index == wxNOT_FOUND ) return;
157 	m_map_combo->SetSelection( index );
158 }
159 
160 
Update(const wxString & Tag)161 void BattleMapTab::Update( const wxString& Tag )
162 {
163 	if ( !m_battle ) return;
164 	long type;
165 	Tag.BeforeFirst( '_' ).ToLong( &type );
166     const std::string key = STD_STRING(Tag.AfterFirst( '_' ));
167     const long longval = LSL::Util::FromString<long>(
168                 m_battle->CustomBattleOptions().getSingleValue( key, ( LSL::OptionsWrapper::GameOption )type ));
169 	if ( type == LSL::OptionsWrapper::EngineOption )
170 	{
171         if ( key == "startpostype" )
172 		{
173 			m_start_radios->SetSelection( longval );
174 			m_minimap->UpdateMinimap();
175 		}
176 	}
177 	else if ( type == LSL::OptionsWrapper::PrivateOptions )
178 	{
179         if ( key == "mapname" )
180 		{
181 			Update();
182 		}
183 	}
184 }
185 
186 
ReloadMaplist()187 void BattleMapTab::ReloadMaplist()
188 {
189 	if ( !m_battle ) return;
190 	m_map_combo->Clear();
191     int i = 0;
192     for (auto map : LSL::usync().GetMapList())
193         m_map_combo->Insert( TowxString(map), i++ );
194 }
195 
196 
UpdateUser(User & user)197 void BattleMapTab::UpdateUser( User& user )
198 {
199 	if ( !m_battle ) return;
200 	if ( &m_battle->GetMe() == &user ) {
201 		try {
202 			m_minimap->UpdateMinimap();
203 		} catch ( ... ) { }
204 	}
205 }
206 
207 
SetMap(int index)208 void BattleMapTab::SetMap( int index )
209 {
210 	if ( !m_battle ) return;
211 	try
212 	{
213 		LSL::UnitsyncMap map = LSL::usync().GetMapEx( index );
214 		m_battle->SetLocalMap( map );
215 
216 		m_battle->SendHostInfo( IBattle::HI_Map );
217 	} catch ( ... ) {}
218 }
219 
220 
OnMapSelect(wxCommandEvent &)221 void BattleMapTab::OnMapSelect( wxCommandEvent& /*unused*/ )
222 {
223 	if ( !m_battle ) return;
224 	if ( !m_battle->IsFounderMe() )
225 	{
226 		try
227 		{
228             m_battle->DoAction(TowxString("suggests " + LSL::usync().GetMap( m_map_combo->GetCurrentSelection() ).name));
229 		}
230 		catch ( ... )
231 		{
232 		}
233 		return;
234 	}
235 	SetMap( m_map_combo->GetCurrentSelection() );
236 }
237 
238 
OnMapBrowse(wxCommandEvent &)239 void BattleMapTab::OnMapBrowse( wxCommandEvent& /*unused*/ )
240 {
241 	if ( !m_battle ) return;
242 	wxLogDebugFunc( wxEmptyString );
243 
244 	wxString mapname = mapSelectDialog();
245 	if ( !mapname.empty() )
246 	{
247 		wxLogDebugFunc( mapname );
248 		if ( !m_battle->IsFounderMe() )
249 		{
250 			m_battle->DoAction( _T( "suggests " ) + mapname  );
251 			return;
252 		}
253 		const int idx = m_map_combo->FindString( mapname, true /*case sensitive*/ );
254 		if ( idx != wxNOT_FOUND )
255             SetMap( idx );
256 	}
257 
258 }
259 
260 
OnStartTypeSelect(wxCommandEvent &)261 void BattleMapTab::OnStartTypeSelect( wxCommandEvent& /*unused*/ )
262 {
263 	if ( !m_battle ) return;
264     const std::string pos = wxFormat( _T( "%d" ) ) % m_start_radios->GetSelection();
265     m_battle->CustomBattleOptions().setSingleOption( "startpostype", pos, LSL::OptionsWrapper::EngineOption );
266 	m_battle->SendHostInfo( wxFormat( _T( "%d_startpostype" ) ) % LSL::OptionsWrapper::EngineOption );
267 }
268 
269 
OnUnitsyncReloaded(wxCommandEvent &)270 void BattleMapTab::OnUnitsyncReloaded( wxCommandEvent& /*data*/ )
271 {
272 	if ( !m_battle ) return;
273     ReloadMaplist();
274 }
275 
SetBattle(Battle * battle)276 void BattleMapTab::SetBattle( Battle* battle )
277 {
278 	m_battle = battle;
279 
280 	m_start_radios->Enable( m_battle );
281 	m_minimap->Enable( m_battle );
282 	m_map_combo->Enable( m_battle );
283 	m_browse_btn->Enable( m_battle );
284 	m_map_opts_list->Enable( m_battle );
285 	m_minimap->SetBattle( m_battle );
286 	if ( m_battle )
287 	{
288 		m_minimap->SetReadOnly( !m_battle->IsFounderMe() );
289 		m_start_radios->Enable( m_battle->IsFounderMe() );
290 		ReloadMaplist();
291 		Update();
292 	}
293 
294 }
295