1 #include "ModeratorActionsWnd.h"
2
3 #include "ClientUI.h"
4 #include "CUIControls.h"
5 #include "../util/i18n.h"
6 #include "../util/OptionsDB.h"
7 #include "../util/AppInterface.h"
8 #include "../Empire/EmpireManager.h"
9 #include "../Empire/Empire.h"
10 #include "../universe/Enums.h"
11 #include "TextBrowseWnd.h"
12
13 #include <GG/Button.h>
14
15 #include <iterator>
16
17
18 namespace {
19 const GG::X CONTROL_WIDTH(32);
20 const GG::Y CONTROL_HEIGHT(32);
21 const GG::X DROP_WIDTH(96);
22 const int PAD(3);
23 }
24
25 ////////////////////////////////////////////////
26 // ModeratorActionsWnd
27 ////////////////////////////////////////////////
ModeratorActionsWnd(const std::string & config_name)28 ModeratorActionsWnd::ModeratorActionsWnd(const std::string& config_name) :
29 CUIWnd(UserString("MODERATOR"),
30 GG::ONTOP | GG::INTERACTIVE | GG::DRAGABLE | GG::RESIZABLE | CLOSABLE | PINABLE,
31 config_name, false),
32 m_actions_enabled(true),
33 m_selected_action(MAS_NoAction)
34 {}
35
CompleteConstruction()36 void ModeratorActionsWnd::CompleteConstruction() {
37 ClientUI* ui = ClientUI::GetClientUI();
38 GG::Flags<GG::GraphicStyle> style = GG::GRAPHIC_CENTER | GG::GRAPHIC_VCENTER | GG::GRAPHIC_FITGRAPHIC | GG::GRAPHIC_PROPSCALE;
39
40 boost::filesystem::path button_texture_dir = ClientUI::ArtDir() / "icons" / "buttons";
41
42 // button for no action
43 m_no_action_button = Wnd::Create<CUIButton>(
44 GG::SubTexture(ClientUI::GetTexture(button_texture_dir / "nomoderatoraction.png")),
45 GG::SubTexture(ClientUI::GetTexture(button_texture_dir / "nomoderatoraction_clicked.png")),
46 GG::SubTexture(ClientUI::GetTexture(button_texture_dir / "nomoderatoraction_mouseover.png")));
47
48 m_no_action_button->SetBrowseModeTime(GetOptionsDB().Get<int>("ui.tooltip.delay"));
49 m_no_action_button->SetBrowseInfoWnd(GG::Wnd::Create<TextBrowseWnd>(
50 UserString("MOD_NONE"), UserString("MOD_NONE")));
51 AttachChild(m_no_action_button);
52 m_no_action_button->LeftClickedSignal.connect(boost::bind(&ModeratorActionsWnd::NoAction, this));
53
54 // button for create system and droplist to select system type to create
55 m_create_system_button = Wnd::Create<CUIButton>(
56 GG::SubTexture(ClientUI::GetTexture(button_texture_dir / "addstar.png")),
57 GG::SubTexture(ClientUI::GetTexture(button_texture_dir / "addstar_clicked.png")),
58 GG::SubTexture(ClientUI::GetTexture(button_texture_dir / "addstar_mouseover.png")));
59
60 m_create_system_button->SetBrowseModeTime(GetOptionsDB().Get<int>("ui.tooltip.delay"));
61 m_create_system_button->SetBrowseInfoWnd(GG::Wnd::Create<TextBrowseWnd>(
62 UserString("MOD_CREATE_SYSTEM"), UserString("MOD_CREATE_SYSTEM")));
63 AttachChild(m_create_system_button);
64
65 m_create_system_button->LeftClickedSignal.connect(boost::bind(&ModeratorActionsWnd::CreateSystem, this));
66 m_star_type_drop = GG::Wnd::Create<CUIDropDownList>(6);
67 m_star_type_drop->Resize(GG::Pt(DROP_WIDTH, CONTROL_HEIGHT));
68 for (StarType star_type = STAR_BLUE; star_type != NUM_STAR_TYPES; star_type = StarType(star_type + 1)) {
69 std::shared_ptr<GG::Texture> disc_texture = ui->GetModuloTexture(
70 ClientUI::ArtDir() / "stars", ClientUI::StarTypeFilePrefixes()[star_type], 0);
71 auto row = GG::Wnd::Create<GG::DropDownList::Row>();
72 auto icon = GG::Wnd::Create<GG::StaticGraphic>(disc_texture, style);
73 icon->Resize(GG::Pt(CONTROL_WIDTH, CONTROL_HEIGHT));
74 row->push_back(icon);
75 m_star_type_drop->Insert(row);
76 }
77 m_star_type_drop->Select(m_star_type_drop->begin()); // default select first type
78 m_star_type_drop->SelChangedSignal.connect(boost::bind(&ModeratorActionsWnd::CreateSystem, this));
79
80 // button for create planet and droplists to select planet type and size
81 m_create_planet_button = Wnd::Create<CUIButton>(
82 GG::SubTexture(ClientUI::GetTexture(button_texture_dir / "addplanet.png")),
83 GG::SubTexture(ClientUI::GetTexture(button_texture_dir / "addplanet_clicked.png")),
84 GG::SubTexture(ClientUI::GetTexture(button_texture_dir / "addplanet_mouseover.png")));
85
86 m_create_planet_button->SetBrowseModeTime(GetOptionsDB().Get<int>("ui.tooltip.delay"));
87 m_create_planet_button->SetBrowseInfoWnd(GG::Wnd::Create<TextBrowseWnd>(
88 UserString("MOD_CREATE_PLANET"), UserString("MOD_CREATE_PLANET")));
89 AttachChild(m_create_planet_button);
90 m_create_planet_button->LeftClickedSignal.connect(boost::bind(&ModeratorActionsWnd::CreatePlanet, this));
91
92 m_planet_type_drop = GG::Wnd::Create<CUIDropDownList>(6);
93 m_planet_type_drop->Resize(GG::Pt(DROP_WIDTH, CONTROL_HEIGHT));
94 for (PlanetType planet_type = PT_SWAMP; planet_type != NUM_PLANET_TYPES; planet_type = PlanetType(planet_type + 1)) {
95 std::shared_ptr<GG::Texture> texture = ClientUI::PlanetIcon(planet_type);
96 auto row = GG::Wnd::Create<GG::DropDownList::Row>();
97 auto icon = GG::Wnd::Create<GG::StaticGraphic>(texture, style);
98 icon->Resize(GG::Pt(CONTROL_WIDTH, CONTROL_HEIGHT));
99 row->push_back(icon);
100 m_planet_type_drop->Insert(row);
101 }
102 m_planet_type_drop->Select(m_planet_type_drop->begin()); // default select first type
103 m_planet_type_drop->SelChangedSignal.connect(boost::bind(&ModeratorActionsWnd::CreatePlanet, this));
104
105 m_planet_size_drop = GG::Wnd::Create<CUIDropDownList>(6);
106 m_planet_size_drop->Resize(GG::Pt(DROP_WIDTH, CONTROL_HEIGHT));
107 for (PlanetSize planet_size = SZ_TINY; planet_size != NUM_PLANET_SIZES; planet_size = PlanetSize(planet_size + 1)) {
108 std::shared_ptr<GG::Texture> texture = ClientUI::PlanetSizeIcon(planet_size);
109 auto row = GG::Wnd::Create<GG::DropDownList::Row>();
110 auto icon = GG::Wnd::Create<GG::StaticGraphic>(texture, style);
111 icon->Resize(GG::Pt(CONTROL_WIDTH, CONTROL_HEIGHT));
112 row->push_back(icon);
113 m_planet_size_drop->Insert(row);
114 }
115 GG::DropDownList::iterator it = m_planet_size_drop->begin();
116 std::advance(it, 2);
117 m_planet_size_drop->Select(it); // default select 3rd size (should be medium?)
118 m_planet_size_drop->SelChangedSignal.connect(boost::bind(&ModeratorActionsWnd::CreatePlanet, this));
119
120 // button for destroying object
121 m_delete_object_button = Wnd::Create<CUIButton>(
122 GG::SubTexture(ClientUI::GetTexture(button_texture_dir / "delete.png")),
123 GG::SubTexture(ClientUI::GetTexture(button_texture_dir / "delete_clicked.png")),
124 GG::SubTexture(ClientUI::GetTexture(button_texture_dir / "delete_mouseover.png")));
125
126 m_delete_object_button->SetBrowseModeTime(GetOptionsDB().Get<int>("ui.tooltip.delay"));
127 m_delete_object_button->SetBrowseInfoWnd(GG::Wnd::Create<TextBrowseWnd>(
128 UserString("MOD_DESTROY"), UserString("MOD_DESTROY")));
129 AttachChild(m_delete_object_button);
130 m_delete_object_button->LeftClickedSignal.connect(boost::bind(&ModeratorActionsWnd::DeleteObject, this));
131
132 // button for setting owner
133 m_set_owner_button = Wnd::Create<CUIButton>(
134 GG::SubTexture(ClientUI::GetTexture(button_texture_dir / "setowner.png")),
135 GG::SubTexture(ClientUI::GetTexture(button_texture_dir / "setowner_clicked.png")),
136 GG::SubTexture(ClientUI::GetTexture(button_texture_dir / "setowner_mouseover.png")));
137
138 m_set_owner_button->SetBrowseModeTime(GetOptionsDB().Get<int>("ui.tooltip.delay"));
139 m_set_owner_button->SetBrowseInfoWnd(GG::Wnd::Create<TextBrowseWnd>(
140 UserString("MOD_SET_OWNER"), UserString("MOD_SET_OWNER")));
141 AttachChild(m_set_owner_button);
142
143 m_set_owner_button->LeftClickedSignal.connect(boost::bind(&ModeratorActionsWnd::SetOwner, this));
144 m_empire_drop = GG::Wnd::Create<CUIDropDownList>(6);
145 m_empire_drop->SetStyle(GG::LIST_NOSORT);
146 // empires added later when gamestate info available
147 m_empire_drop->SelChangedSignal.connect(boost::bind(&ModeratorActionsWnd::SetOwner, this));
148
149 // button for creating starlane
150 m_add_starlane_button = Wnd::Create<CUIButton>(
151 GG::SubTexture(ClientUI::GetTexture(button_texture_dir / "addstarlane.png")),
152 GG::SubTexture(ClientUI::GetTexture(button_texture_dir / "addstarlane_clicked.png")),
153 GG::SubTexture(ClientUI::GetTexture(button_texture_dir / "addstarlane_mouseover.png")));
154
155 m_add_starlane_button->SetBrowseModeTime(GetOptionsDB().Get<int>("ui.tooltip.delay"));
156 m_add_starlane_button->SetBrowseInfoWnd(GG::Wnd::Create<TextBrowseWnd>(
157 UserString("MOD_ADD_STARLANE"), UserString("MOD_ADD_STARLANE")));
158 AttachChild(m_add_starlane_button);
159 m_add_starlane_button->LeftClickedSignal.connect(boost::bind(&ModeratorActionsWnd::AddStarlane, this));
160
161 // button for removing starlane
162 m_remove_starlane_button = Wnd::Create<CUIButton>(
163 GG::SubTexture(ClientUI::GetTexture(button_texture_dir / "removestarlane.png")),
164 GG::SubTexture(ClientUI::GetTexture(button_texture_dir / "removestarlane_clicked.png")),
165 GG::SubTexture(ClientUI::GetTexture(button_texture_dir / "removestarlane_mouseover.png")));
166
167 m_remove_starlane_button->SetBrowseModeTime(GetOptionsDB().Get<int>("ui.tooltip.delay"));
168 m_remove_starlane_button->SetBrowseInfoWnd(GG::Wnd::Create<TextBrowseWnd>(
169 UserString("MOD_REMOVE_STARLANE"), UserString("MOD_REMOVE_STARLANE")));
170 AttachChild(m_remove_starlane_button);
171 m_remove_starlane_button->LeftClickedSignal.connect(boost::bind(&ModeratorActionsWnd::RemoveStarlane, this));
172
173 CUIWnd::CompleteConstruction();
174
175 DoLayout();
176 SaveDefaultedOptions();
177 }
178
~ModeratorActionsWnd()179 ModeratorActionsWnd::~ModeratorActionsWnd()
180 {}
181
NoAction()182 void ModeratorActionsWnd::NoAction() {
183 m_selected_action = MAS_NoAction;
184 NoActionSelectedSignal();
185 DetachChild(m_star_type_drop);
186 DetachChild(m_planet_type_drop);
187 DetachChild(m_planet_size_drop);
188 DetachChild(m_empire_drop);
189 }
190
CreateSystem()191 void ModeratorActionsWnd::CreateSystem() {
192 m_selected_action = MAS_CreateSystem;
193 CreateSystemActionSelectedSignal(SelectedStarType());
194 AttachChild(m_star_type_drop);
195 DetachChild(m_planet_type_drop);
196 DetachChild(m_planet_size_drop);
197 DetachChild(m_empire_drop);
198 }
199
CreatePlanet()200 void ModeratorActionsWnd::CreatePlanet() {
201 m_selected_action = MAS_CreatePlanet;
202 CreatePlanetActionSelectedSignal(SelectedPlanetType());
203 DetachChild(m_star_type_drop);
204 AttachChild(m_planet_type_drop);
205 AttachChild(m_planet_size_drop);
206 DetachChild(m_empire_drop);
207 }
208
DeleteObject()209 void ModeratorActionsWnd::DeleteObject() {
210 m_selected_action = MAS_Destroy;
211 DeleteObjectActionSelectedSignal();
212 DetachChild(m_star_type_drop);
213 DetachChild(m_planet_type_drop);
214 DetachChild(m_planet_size_drop);
215 DetachChild(m_empire_drop);
216 }
217
SetOwner()218 void ModeratorActionsWnd::SetOwner() {
219 m_selected_action = MAS_SetOwner;
220 SetOwnerActionSelectedSignal(SelectedEmpire());
221 DetachChild(m_star_type_drop);
222 DetachChild(m_planet_type_drop);
223 DetachChild(m_planet_size_drop);
224 AttachChild(m_empire_drop);
225 }
226
AddStarlane()227 void ModeratorActionsWnd::AddStarlane() {
228 m_selected_action = MAS_AddStarlane;
229 AddStarlaneActionSelectedSignal();
230 DetachChild(m_star_type_drop);
231 DetachChild(m_planet_type_drop);
232 DetachChild(m_planet_size_drop);
233 DetachChild(m_empire_drop);
234 }
235
RemoveStarlane()236 void ModeratorActionsWnd::RemoveStarlane() {
237 m_selected_action = MAS_RemoveStarlane;
238 AddStarlaneActionSelectedSignal();
239 DetachChild(m_star_type_drop);
240 DetachChild(m_planet_type_drop);
241 DetachChild(m_planet_size_drop);
242 DetachChild(m_empire_drop);
243 }
244
SelectedAction() const245 ModeratorActionSetting ModeratorActionsWnd::SelectedAction() const
246 { return m_selected_action; }
247
SelectedPlanetType() const248 PlanetType ModeratorActionsWnd::SelectedPlanetType() const
249 { return PlanetTypeFromIndex(m_planet_type_drop->CurrentItemIndex()); }
250
SelectedPlanetSize() const251 PlanetSize ModeratorActionsWnd::SelectedPlanetSize() const
252 { return PlanetSizeFromIndex(m_planet_size_drop->CurrentItemIndex()); }
253
SelectedStarType() const254 StarType ModeratorActionsWnd::SelectedStarType() const
255 { return StarTypeFromIndex(m_star_type_drop->CurrentItemIndex()); }
256
SelectedEmpire() const257 int ModeratorActionsWnd::SelectedEmpire() const
258 { return EmpireIDFromIndex(m_empire_drop->CurrentItemIndex()); }
259
DoLayout()260 void ModeratorActionsWnd::DoLayout() {
261 GG::X left = GG::X0 + PAD;
262 GG::Y top = GG::Y0 + PAD;
263
264 m_no_action_button->SizeMove(GG::Pt(left, top), GG::Pt(left + CONTROL_WIDTH, top + CONTROL_HEIGHT));
265 left += CONTROL_WIDTH + PAD;
266
267 m_create_system_button->SizeMove(GG::Pt(left, top), GG::Pt(left + CONTROL_WIDTH, top + CONTROL_HEIGHT));
268 left += CONTROL_WIDTH + PAD;
269
270 m_create_planet_button->SizeMove(GG::Pt(left, top), GG::Pt(left + CONTROL_WIDTH, top + CONTROL_HEIGHT));
271 left += CONTROL_WIDTH + PAD;
272
273 m_delete_object_button->SizeMove(GG::Pt(left, top), GG::Pt(left + CONTROL_WIDTH, top + CONTROL_HEIGHT));
274 left += CONTROL_WIDTH + PAD;
275
276 m_set_owner_button->SizeMove(GG::Pt(left, top), GG::Pt(left + CONTROL_WIDTH, top + CONTROL_HEIGHT));
277 left += CONTROL_WIDTH + PAD;
278
279 m_add_starlane_button->SizeMove(GG::Pt(left, top), GG::Pt(left + CONTROL_WIDTH, top + CONTROL_HEIGHT));
280 left += CONTROL_WIDTH + PAD;
281
282 m_remove_starlane_button->SizeMove(GG::Pt(left, top), GG::Pt(left + CONTROL_WIDTH, top + CONTROL_HEIGHT));
283 left += CONTROL_WIDTH + PAD;
284
285 left = GG::X0 + PAD;
286 top += CONTROL_HEIGHT + PAD;
287
288 // all at same location; only one shown at a time
289 m_star_type_drop->SizeMove(GG::Pt(left, top), GG::Pt(left + DROP_WIDTH, top + CONTROL_HEIGHT));
290 m_empire_drop->SizeMove(GG::Pt(left, top), GG::Pt(left + DROP_WIDTH, top + CONTROL_HEIGHT));
291
292 m_planet_type_drop->SizeMove(GG::Pt(left, top), GG::Pt(left + DROP_WIDTH, top + CONTROL_HEIGHT));
293 left += DROP_WIDTH + PAD;
294 m_planet_size_drop->SizeMove(GG::Pt(left, top), GG::Pt(left + DROP_WIDTH, top + CONTROL_HEIGHT));
295 }
296
SizeMove(const GG::Pt & ul,const GG::Pt & lr)297 void ModeratorActionsWnd::SizeMove(const GG::Pt& ul, const GG::Pt& lr) {
298 GG::Pt old_size = GG::Wnd::Size();
299
300 CUIWnd::SizeMove(ul, lr);
301
302 if (old_size != GG::Wnd::Size())
303 DoLayout();
304 }
305
Refresh()306 void ModeratorActionsWnd::Refresh() {
307 // todo: get currently selected empire, if any, reselect after refresh
308
309 m_empire_drop->Clear();
310 for (const auto& entry : Empires()) {
311 const Empire* empire = entry.second;
312 auto row = GG::Wnd::Create<GG::DropDownList::Row>();
313 auto label = GG::Wnd::Create<CUILabel>(empire->Name(), GG::FORMAT_NOWRAP);
314 label->SetTextColor(empire->Color());
315 row->push_back(label);
316 m_empire_drop->Insert(row);
317 }
318
319 // no empire / monsters
320 auto row = GG::Wnd::Create<GG::DropDownList::Row>();
321 auto label = GG::Wnd::Create<CUILabel>(UserString("UNOWNED"), GG::FORMAT_NOWRAP);
322 label->SetTextColor(GG::CLR_RED);
323 row->push_back(label);
324 m_empire_drop->Insert(row);
325
326 if (!m_empire_drop->Empty())
327 m_empire_drop->Select(m_empire_drop->begin());
328 }
329
EnableActions(bool enable)330 void ModeratorActionsWnd::EnableActions(bool enable/* = true*/)
331 { m_actions_enabled = enable; }
332
CloseClicked()333 void ModeratorActionsWnd::CloseClicked()
334 { ClosingSignal(); }
335
StarTypeFromIndex(std::size_t i) const336 StarType ModeratorActionsWnd::StarTypeFromIndex(std::size_t i) const {
337 if (i == static_cast<std::size_t>(-1) || i >= NUM_STAR_TYPES)
338 return STAR_BLUE;
339 return StarType(i); // assumes first enum and first index are value 0, and that items in list are in same order as enum values
340 }
341
PlanetTypeFromIndex(std::size_t i) const342 PlanetType ModeratorActionsWnd::PlanetTypeFromIndex(std::size_t i) const {
343 if (i == static_cast<std::size_t>(-1) || i >= NUM_PLANET_TYPES)
344 return PT_SWAMP;
345 return PlanetType(i); // assumes first enum and first index are value 0, and that items in list are in same order as enum values
346 }
347
PlanetSizeFromIndex(std::size_t i) const348 PlanetSize ModeratorActionsWnd::PlanetSizeFromIndex(std::size_t i) const {
349 if (i == static_cast<std::size_t>(-1) || i + 1 >= NUM_PLANET_SIZES)
350 return SZ_MEDIUM;
351 return PlanetSize(i + 1);// enum index 0 is NO_WORLD, but don't put that into the list, so have to add 1 to all the list indices
352 }
353
EmpireIDFromIndex(std::size_t i) const354 int ModeratorActionsWnd::EmpireIDFromIndex(std::size_t i) const {
355 if (i == static_cast<std::size_t>(-1) ||
356 i >= static_cast<std::size_t>(Empires().NumEmpires()))
357 { return ALL_EMPIRES; }
358 return std::next(Empires().begin(), i)->first;
359 }
360