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