1 /*
2  *  The ManaPlus Client
3  *  Copyright (C) 2004-2009  The Mana World Development Team
4  *  Copyright (C) 2009-2010  The Mana Developers
5  *  Copyright (C) 2011-2019  The ManaPlus Developers
6  *  Copyright (C) 2019-2021  Andrei Karas
7  *
8  *  This file is part of The ManaPlus Client.
9  *
10  *  This program is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License as published by
12  *  the Free Software Foundation; either version 2 of the License, or
13  *  any later version.
14  *
15  *  This program is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU General Public License for more details.
19  *
20  *  You should have received a copy of the GNU General Public License
21  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
22  */
23 
24 #include "gui/windows/setupwindow.h"
25 
26 #include "configuration.h"
27 #include "game.h"
28 #include "main.h"
29 
30 #include "gui/windows/chatwindow.h"
31 #include "gui/windows/statuswindow.h"
32 
33 #include "gui/widgets/createwidget.h"
34 
35 #include "gui/widgets/tabs/setup_audio.h"
36 #include "gui/widgets/tabs/setup_chat.h"
37 #include "gui/widgets/tabs/setup_colors.h"
38 #include "gui/widgets/tabs/setup_input.h"
39 #include "gui/widgets/tabs/setup_joystick.h"
40 #include "gui/widgets/tabs/setup_misc.h"
41 #include "gui/widgets/tabs/setup_mods.h"
42 #include "gui/widgets/tabs/setup_perfomance.h"
43 #include "gui/widgets/tabs/setup_players.h"
44 #include "gui/widgets/tabs/setup_quick.h"
45 #include "gui/widgets/tabs/setup_relations.h"
46 #include "gui/widgets/tabs/setup_theme.h"
47 #include "gui/widgets/tabs/setup_touch.h"
48 #include "gui/widgets/tabs/setup_video.h"
49 #include "gui/widgets/tabs/setup_visual.h"
50 
51 #include "gui/widgets/button.h"
52 #include "gui/widgets/label.h"
53 #include "gui/widgets/tabbedarea.h"
54 
55 #include "input/touch/touchmanager.h"
56 
57 #include "utils/delete2.h"
58 #include "utils/dtor.h"
59 #include "utils/foreach.h"
60 #include "utils/gettext.h"
61 
62 #include "debug.h"
63 
64 SetupWindow *setupWindow = nullptr;
65 
SetupWindow()66 SetupWindow::SetupWindow() :
67     // TRANSLATORS: setup window name
68     Window(_("Setup"), Modal_false, nullptr, "setup.xml"),
69     ActionListener(),
70     mTabs(),
71     mWindowsToReset(),
72     mButtons(),
73     mModsTab(nullptr),
74     mQuickTab(nullptr),
75     mResetWindows(nullptr),
76     mPanel(CREATEWIDGETR(TabbedArea, this)),
77     mVersion(new Label(this, FULL_VERSION)),
78     mButtonPadding(5)
79 {
80     setCloseButton(true);
81     setResizable(true);
82     setStickyButtonLock(true);
83 }
84 
postInit()85 void SetupWindow::postInit()
86 {
87     Window::postInit();
88     int width = 620;
89     const int height = 450;
90 
91     if (config.getIntValue("screenwidth") >= 730)
92         width += 100;
93 
94     setContentSize(width, height);
95     setMinWidth(310);
96     setMinHeight(210);
97 
98     mPanel->setSelectable(false);
99     mPanel->getTabContainer()->setSelectable(false);
100     mPanel->getWidgetContainer()->setSelectable(false);
101 
102     static const char *const buttonNames[] =
103     {
104         // TRANSLATORS: setup button
105         N_("Apply"),
106         // TRANSLATORS: setup button
107         N_("Cancel"),
108         // TRANSLATORS: setup button
109         N_("Store"),
110         // TRANSLATORS: setup button
111         N_("Reset Windows"),
112         nullptr
113     };
114     int x = width;
115     mButtonPadding = getOption("buttonPadding", 5);
116     for (const char *const * curBtn = buttonNames;
117          *curBtn != nullptr;
118          ++ curBtn)
119     {
120         Button *const btn = new Button(this,
121             gettext(*curBtn),
122             *curBtn,
123             BUTTON_SKIN,
124             this);
125         mButtons.push_back(btn);
126         x -= btn->getWidth() + mButtonPadding;
127         btn->setPosition(x, height - btn->getHeight() - mButtonPadding);
128         add(btn);
129 
130         // Store this button, as it needs to be enabled/disabled
131         if (strcmp(*curBtn, "Reset Windows") == 0)
132             mResetWindows = btn;
133     }
134 
135     mPanel->setDimension(Rect(5, 5, width - 10, height - 40));
136     mPanel->enableScrollButtons(true);
137 
138     mTabs.push_back(new Setup_Video(this));
139     mTabs.push_back(new Setup_Visual(this));
140     mTabs.push_back(new Setup_Audio(this));
141     mTabs.push_back(new Setup_Perfomance(this));
142     mTabs.push_back(new Setup_Touch(this));
143     mTabs.push_back(new Setup_Input(this));
144     mTabs.push_back(new Setup_Joystick(this));
145     mTabs.push_back(new Setup_Colors(this));
146     mTabs.push_back(new Setup_Chat(this));
147     mTabs.push_back(new Setup_Players(this));
148     mTabs.push_back(new Setup_Relations(this));
149     mTabs.push_back(new Setup_Theme(this));
150     mTabs.push_back(new Setup_Misc(this));
151 
152     FOR_EACH (std::list<SetupTab*>::const_iterator, i, mTabs)
153     {
154         SetupTab *const tab = *i;
155         mPanel->addTab(tab->getName(), tab);
156     }
157     add(mPanel);
158 
159     if (mResetWindows != nullptr)
160     {
161         mVersion->setPosition(9,
162             height - mVersion->getHeight() - mResetWindows->getHeight() - 9);
163     }
164     else
165     {
166         mVersion->setPosition(9, height - mVersion->getHeight() - 30);
167     }
168     add(mVersion);
169 
170     center();
171 
172     widgetResized(Event(nullptr));
173     setInGame(false);
174     enableVisibleSound(true);
175 }
176 
~SetupWindow()177 SetupWindow::~SetupWindow()
178 {
179     delete_all(mTabs);
180     mButtons.clear();
181     setupWindow = nullptr;
182 }
183 
action(const ActionEvent & event)184 void SetupWindow::action(const ActionEvent &event)
185 {
186     if (Game::instance() != nullptr)
187         Game::instance()->resetAdjustLevel();
188     const std::string &eventId = event.getId();
189 
190     if (eventId == "Apply")
191     {
192         setVisible(Visible_false);
193         FOR_EACH (std::list<SetupTab*>::iterator, it, mTabs)
194         {
195             (*it)->apply();
196         }
197     }
198     else if (eventId == "Cancel")
199     {
200         doCancel();
201     }
202     else if (eventId == "Store")
203     {
204         if (chatWindow != nullptr)
205             chatWindow->saveState();
206         config.write();
207         serverConfig.write();
208     }
209     else if (eventId == "Reset Windows")
210     {
211         // Bail out if this action happens to be activated before the windows
212         // are created (though it should be disabled then)
213         if (statusWindow == nullptr)
214             return;
215 
216         FOR_EACH (std::list<Window*>::const_iterator, it, mWindowsToReset)
217         {
218             if (*it != nullptr)
219                 (*it)->resetToDefaultSize();
220         }
221     }
222 }
223 
setInGame(const bool inGame)224 void SetupWindow::setInGame(const bool inGame)
225 {
226     if (mResetWindows != nullptr)
227         mResetWindows->setEnabled(inGame);
228 }
229 
externalUpdate()230 void SetupWindow::externalUpdate()
231 {
232     unloadAdditionalTabs();
233     mModsTab = new Setup_Mods(this);
234     mTabs.push_back(mModsTab);
235     mPanel->addTab(mModsTab->getName(), mModsTab);
236     mQuickTab = new Setup_Quick(this);
237     mTabs.push_back(mQuickTab);
238     mPanel->addTab(mQuickTab->getName(), mQuickTab);
239     FOR_EACH (std::list<SetupTab*>::const_iterator, it, mTabs)
240     {
241         if (*it != nullptr)
242             (*it)->externalUpdated();
243     }
244 }
245 
unloadTab(SetupTab * const page)246 void SetupWindow::unloadTab(SetupTab *const page)
247 {
248     if (page != nullptr)
249     {
250         mTabs.remove(page);
251         mPanel->removeTab(mPanel->getTab(page->getName()));
252     }
253 }
254 
unloadAdditionalTabs()255 void SetupWindow::unloadAdditionalTabs()
256 {
257     unloadTab(mModsTab);
258     unloadTab(mQuickTab);
259     delete2(mModsTab)
260     delete2(mQuickTab)
261 }
262 
externalUnload()263 void SetupWindow::externalUnload()
264 {
265     FOR_EACH (std::list<SetupTab*>::const_iterator, it, mTabs)
266     {
267         if (*it != nullptr)
268             (*it)->externalUnloaded();
269     }
270     unloadAdditionalTabs();
271 }
272 
registerWindowForReset(Window * const window)273 void SetupWindow::registerWindowForReset(Window *const window)
274 {
275     mWindowsToReset.push_back(window);
276 }
277 
unregisterWindowForReset(const Window * const window)278 void SetupWindow::unregisterWindowForReset(const Window *const window)
279 {
280     FOR_EACH (std::list<Window*>::iterator, it, mWindowsToReset)
281     {
282         if (*it == window)
283         {
284             mWindowsToReset.erase(it);
285             return;
286         }
287     }
288 }
289 
hideWindows()290 void SetupWindow::hideWindows()
291 {
292     FOR_EACH (std::list<Window*>::const_iterator, it, mWindowsToReset)
293     {
294         Window *const window = *it;
295         if ((window != nullptr) && !window->isSticky())
296             window->setVisible(Visible_false);
297     }
298     setVisible(Visible_false);
299 }
300 
doCancel()301 void SetupWindow::doCancel()
302 {
303     setVisible(Visible_false);
304     FOR_EACH (std::list<SetupTab*>::iterator, it, mTabs)
305     {
306         (*it)->cancel();
307     }
308 }
309 
activateTab(const std::string & name)310 void SetupWindow::activateTab(const std::string &name)
311 {
312     std::string tmp = gettext(name.c_str());
313     mPanel->setSelectedTabByName(tmp);
314 }
315 
setVisible(Visible visible)316 void SetupWindow::setVisible(Visible visible)
317 {
318     touchManager.setTempHide(visible == Visible_true);
319     Window::setVisible(visible);
320 }
321 
widgetResized(const Event & event)322 void SetupWindow::widgetResized(const Event &event)
323 {
324     Window::widgetResized(event);
325 
326     const Rect area = getChildrenArea();
327     int x = area.width;
328     const int height = area.height;
329     const int width = area.width;
330     mPanel->setDimension(Rect(5, 5, width - 10, height - 40));
331     FOR_EACH (STD_VECTOR<Button*>::iterator, it, mButtons)
332     {
333         Button *const btn = *it;
334         x -= btn->getWidth() + mButtonPadding;
335         btn->setPosition(x, height - btn->getHeight() - mButtonPadding);
336     }
337     if (mResetWindows != nullptr)
338     {
339         mVersion->setPosition(9,
340             height - mVersion->getHeight() - mResetWindows->getHeight() - 9);
341     }
342     else
343     {
344         mVersion->setPosition(9, height - mVersion->getHeight() - 30);
345     }
346 }
347