Merge lp:~widelands-dev/widelands/options_window into lp:widelands

Proposed by GunChleoc
Status: Merged
Approved by: kaputtnik
Approved revision: no longer in the source branch.
Merged at revision: 7685
Proposed branch: lp:~widelands-dev/widelands/options_window
Merge into: lp:widelands
Diff against target: 1821 lines (+767/-632)
5 files modified
src/ui_basic/tabpanel.cc (+232/-147)
src/ui_basic/tabpanel.h (+51/-15)
src/ui_fsmenu/base.h (+1/-1)
src/ui_fsmenu/options.cc (+388/-383)
src/ui_fsmenu/options.h (+95/-86)
To merge this branch: bzr merge lp:~widelands-dev/widelands/options_window
Reviewer Review Type Date Requested Status
Tino Approve
kaputtnik (community) Approve
Review via email: mp+280355@code.launchpad.net

Description of the change

The Options window now has a tabbed layout. I added textual tabs to TabPanel and did a couple of fixes there as well - the tab brightening on mouseover was never executed, and tabs now also play click on mouseclick.

Exposed rolling autosave option to the UI.

We are discussing some changes to the options themselves in the forum, e.g. some rephrasing and tooltips, but those can always be added later.

options.h/cc is probably best viewed with an offline diff tool.

To post a comment you must log in.
Revision history for this message
kaputtnik (franku) wrote :

As i can see all works as expected. Not tested are some time related things (like autosave)

Maybe we should reorder some things, but this could be done later.

review: Approve
Revision history for this message
TiborB (tiborb95) wrote :

I went through code. LGTM though this is another huge and hard-to-read change...

Should I merge this as well?

Revision history for this message
bunnybot (widelandsofficial) wrote :

Hi, I am bunnybot (https://github.com/widelands/bunnybot).

I am keeping the source branch lp:~widelands-dev/widelands/options_window mirrored to
  https://github.com/widelands/widelands/tree/_widelands_dev_widelands_options_window

The latest continuous integration build can always be found here:
  https://travis-ci.org/widelands/widelands/branches
Please do not merge without making sure that it passes.

You can give me commands by starting a line with @bunnybot <command>. I understand:
 merge: Merges the source branch into the target branch, closing the pull request.

Revision history for this message
Tino (tino79) wrote :

Looks good to me and bunnybot ;).

@bunnybot merge

review: Approve
Revision history for this message
bunnybot (widelandsofficial) wrote :

Travis build 130 has changed state to: passed. Details: https://travis-ci.org/widelands/widelands/builds/99817066.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== removed file 'pics/optionsmenu.jpg'
2Binary files pics/optionsmenu.jpg 2008-07-23 15:48:24 +0000 and pics/optionsmenu.jpg 1970-01-01 00:00:00 +0000 differ
3=== modified file 'src/ui_basic/tabpanel.cc'
4--- src/ui_basic/tabpanel.cc 2014-12-04 09:00:20 +0000
5+++ src/ui_basic/tabpanel.cc 2016-01-01 19:10:55 +0000
6@@ -19,41 +19,51 @@
7
8 #include "ui_basic/tabpanel.h"
9
10+#include "graphic/font_handler1.h"
11 #include "graphic/rendertarget.h"
12+#include "graphic/text_layout.h"
13 #include "ui_basic/mouse_constants.h"
14
15 namespace UI {
16
17-// Button size of tab buttons in pixels.
18-constexpr int kTabPanelButtonSize = 34;
19+// Button height of tab buttons in pixels. Is also used for width with pictorial buttons.
20+constexpr int kTabPanelButtonHeight = 34;
21
22 // Margin around image. The image will be scaled down to fit into this rectangle with preserving size.
23 constexpr int kTabPanelImageMargin = 2;
24
25+// Left and right margin around text.
26+constexpr int kTabPanelTextMargin = 4;
27+
28 // height of the bar separating buttons and tab contents
29 constexpr int kTabPanelSeparatorHeight = 4;
30
31+// Constant to flag up when we're not at a tab.
32+constexpr uint32_t kNotFound = std::numeric_limits<uint32_t>::max();
33+
34 /*
35 * =================
36 * class Tab
37 * =================
38 */
39 Tab::Tab
40- (TabPanel * const parent,
41- uint32_t const id,
42- const std::string & name,
43- const Image* gpic,
44- const std::string & gtooltip,
45- Panel * const gpanel)
46+ (TabPanel* const tab_parent,
47+ size_t const tab_id,
48+ int32_t x,
49+ int32_t w,
50+ const std::string& name,
51+ const std::string& _title,
52+ const Image* _pic,
53+ const std::string& tooltip_text,
54+ Panel* const contents)
55 :
56- NamedPanel
57- (parent, name, id * kTabPanelButtonSize, 0, kTabPanelButtonSize,
58- kTabPanelButtonSize, gtooltip),
59- m_parent(parent),
60- m_id(id),
61- pic(gpic),
62- tooltip(gtooltip),
63- panel(gpanel)
64+ NamedPanel(tab_parent, name, x, 0, w, kTabPanelButtonHeight, tooltip_text),
65+ parent(tab_parent),
66+ id(tab_id),
67+ pic(_pic),
68+ title(_title),
69+ tooltip(tooltip_text),
70+ panel(contents)
71 {
72 }
73
74@@ -61,10 +71,15 @@
75 * Currently active tab
76 */
77 bool Tab::active() {
78- return m_parent->m_active == m_id;
79+ return parent->active_ == id;
80 }
81 void Tab::activate() {
82- return m_parent->activate(m_id);
83+ return parent->activate(id);
84+}
85+
86+bool Tab::handle_mousepress(uint8_t, int32_t, int32_t) {
87+ play_click();
88+ return false;
89 }
90
91 /*
92@@ -78,22 +93,26 @@
93 TabPanel::TabPanel
94 (Panel * const parent,
95 int32_t const x, int32_t const y,
96- const Image* background)
97+ const Image* background,
98+ TabPanel::Type border_type)
99 :
100- Panel (parent, x, y, 0, 0),
101- m_active (0),
102- m_highlight (-1),
103- m_pic_background (background)
104+ Panel (parent, x, y, 0, 0),
105+ active_ (0),
106+ highlight_ (kNotFound),
107+ pic_background_ (background),
108+ border_type_ (border_type)
109 {}
110 TabPanel::TabPanel
111 (Panel * const parent,
112 int32_t const x, int32_t const y, int32_t const w, int32_t const h,
113- const Image* background)
114+ const Image* background,
115+ TabPanel::Type border_type)
116 :
117- Panel (parent, x, y, w, h),
118- m_active (0),
119- m_highlight (-1),
120- m_pic_background (background)
121+ Panel (parent, x, y, w, h),
122+ active_ (0),
123+ highlight_ (kNotFound),
124+ pic_background_ (background),
125+ border_type_ (border_type)
126 {}
127
128 /**
129@@ -101,12 +120,16 @@
130 */
131 void TabPanel::layout()
132 {
133- if (m_active < m_tabs.size()) {
134- Panel * const panel = m_tabs[m_active]->panel;
135+ if (active_ < tabs_.size()) {
136+ Panel * const panel = tabs_[active_]->panel;
137 uint32_t h = get_h();
138
139 // avoid excessive craziness in case there is a wraparound
140- h = std::min(h, h - (kTabPanelButtonSize + kTabPanelSeparatorHeight));
141+ h = std::min(h, h - (kTabPanelButtonHeight + kTabPanelSeparatorHeight));
142+ // If we have a border, we will also want some margin to the bottom
143+ if (border_type_ == TabPanel::Type::kBorder) {
144+ h = h - kTabPanelSeparatorHeight;
145+ }
146 panel->set_size(get_w(), h);
147 }
148 }
149@@ -120,12 +143,12 @@
150 uint32_t h;
151
152 // size of button row
153- w = kTabPanelButtonSize * m_tabs.size();
154- h = kTabPanelButtonSize + kTabPanelSeparatorHeight;
155+ w = kTabPanelButtonHeight * tabs_.size();
156+ h = kTabPanelButtonHeight + kTabPanelSeparatorHeight;
157
158 // size of contents
159- if (m_active < m_tabs.size()) {
160- Panel * const panel = m_tabs[m_active]->panel;
161+ if (active_ < tabs_.size()) {
162+ Panel * const panel = tabs_[active_]->panel;
163 uint32_t panelw, panelh;
164
165 panel->get_desired_size(panelw, panelh);
166@@ -146,7 +169,25 @@
167 }
168
169 /**
170- * Add a new tab
171+ * Add a new textual tab
172+*/
173+uint32_t TabPanel::add
174+ (const std::string & name,
175+ const std::string & title,
176+ Panel * const panel,
177+ const std::string & tooltip_text)
178+{
179+ const Image* pic = UI::g_fh1->render(as_uifont(title));
180+ return add_tab(std::max(kTabPanelButtonHeight, pic->width() + 2 * kTabPanelTextMargin),
181+ name,
182+ title,
183+ pic,
184+ tooltip_text,
185+ panel);
186+}
187+
188+/**
189+ * Add a new pictorial tab
190 */
191 uint32_t TabPanel::add
192 (const std::string & name,
193@@ -154,14 +195,38 @@
194 Panel * const panel,
195 const std::string & tooltip_text)
196 {
197+ return add_tab(kTabPanelButtonHeight,
198+ name,
199+ "",
200+ pic,
201+ tooltip_text,
202+ panel);
203+}
204+
205+/** Common adding function for textual and pictorial tabs. */
206+uint32_t TabPanel::add_tab(int32_t width,
207+ const std::string& name,
208+ const std::string& title,
209+ const Image* pic,
210+ const std::string& tooltip_text,
211+ Panel* panel) {
212 assert(panel);
213 assert(panel->get_parent() == this);
214
215- uint32_t id = m_tabs.size();
216- m_tabs.push_back(new Tab(this, id, name, pic, tooltip_text, panel));
217-
218- panel->set_pos(Point(0, kTabPanelButtonSize + kTabPanelSeparatorHeight));
219- panel->set_visible(id == m_active);
220+ size_t id = tabs_.size();
221+ int32_t x = id > 0 ? tabs_[id - 1]->get_x() + tabs_[id - 1]->get_w() : 0;
222+ tabs_.push_back(new Tab(this, id, x, width, name, title, pic, tooltip_text, panel));
223+
224+ // Add a margin if there is a border
225+ if (border_type_ == TabPanel::Type::kBorder) {
226+ panel->set_border(kTabPanelSeparatorHeight + 1, kTabPanelSeparatorHeight + 1,
227+ kTabPanelSeparatorHeight, kTabPanelSeparatorHeight);
228+ panel->set_pos(Point(0, kTabPanelButtonHeight));
229+ } else {
230+ panel->set_pos(Point(0, kTabPanelButtonHeight + kTabPanelSeparatorHeight));
231+ }
232+
233+ panel->set_visible(id == active_);
234 update_desired_size();
235
236 return id;
237@@ -173,20 +238,20 @@
238 */
239 void TabPanel::activate(uint32_t idx)
240 {
241- if (m_active < m_tabs.size())
242- m_tabs[m_active]->panel->set_visible(false);
243- if (idx < m_tabs.size())
244- m_tabs[idx]->panel->set_visible(true);
245+ if (active_ < tabs_.size())
246+ tabs_[active_]->panel->set_visible(false);
247+ if (idx < tabs_.size())
248+ tabs_[idx]->panel->set_visible(true);
249
250- m_active = idx;
251+ active_ = idx;
252
253 update_desired_size();
254 }
255
256 void TabPanel::activate(const std::string & name)
257 {
258- for (uint32_t t = 0; t < m_tabs.size(); ++t)
259- if (m_tabs[t]->get_name() == name)
260+ for (uint32_t t = 0; t < tabs_.size(); ++t)
261+ if (tabs_[t]->get_name() == name)
262 activate(t);
263 }
264
265@@ -194,7 +259,7 @@
266 * Return the tab names in order
267 */
268 const TabPanel::TabList & TabPanel::tabs() {
269- return m_tabs;
270+ return tabs_;
271 }
272
273 /**
274@@ -202,96 +267,118 @@
275 */
276 void TabPanel::draw(RenderTarget & dst)
277 {
278- uint32_t idx;
279- uint32_t x;
280-
281 // draw the background
282- static_assert(2 < kTabPanelButtonSize, "assert(2 < kTabPanelButtonSize) failed.");
283- static_assert(4 < kTabPanelButtonSize, "assert(4 < kTabPanelButtonSize) failed.");
284+ static_assert(2 < kTabPanelButtonHeight, "assert(2 < kTabPanelButtonSize) failed.");
285+ static_assert(4 < kTabPanelButtonHeight, "assert(4 < kTabPanelButtonSize) failed.");
286
287- if (m_pic_background) {
288- dst.tile
289- (Rect(Point(0, 0), m_tabs.size() * kTabPanelButtonSize, kTabPanelButtonSize - 2),
290- m_pic_background, Point(get_x(), get_y()));
291- assert(kTabPanelButtonSize - 2 <= get_h());
292- dst.tile
293- (Rect
294- (Point(0, kTabPanelButtonSize - 2),
295- get_w(), get_h() - kTabPanelButtonSize + 2),
296- m_pic_background,
297- Point(get_x(), get_y() + kTabPanelButtonSize - 2));
298+ if (pic_background_) {
299+ if (!tabs_.empty()) {
300+ dst.tile
301+ (Rect(Point(0, 0), tabs_.back()->get_x() + tabs_.back()->get_w(), kTabPanelButtonHeight - 2),
302+ pic_background_,
303+ Point(get_x(), get_y()));
304+ }
305+ assert(kTabPanelButtonHeight - 2 <= get_h());
306+ dst.tile
307+ (Rect(Point(0, kTabPanelButtonHeight - 2), get_w(), get_h() - kTabPanelButtonHeight + 2),
308+ pic_background_,
309+ Point(get_x(), get_y() + kTabPanelButtonHeight - 2));
310 }
311
312+ RGBColor black(0, 0, 0);
313+
314 // draw the buttons
315- for (idx = 0, x = 0; idx < m_tabs.size(); idx++, x += kTabPanelButtonSize) {
316- if (m_highlight == static_cast<int32_t>(idx))
317- dst.brighten_rect
318- (Rect(Point(x, 0), kTabPanelButtonSize, kTabPanelButtonSize),
319- MOUSE_OVER_BRIGHT_FACTOR);
320-
321- // Draw the icon
322- assert(m_tabs[idx]->pic);
323-
324- // Scale the image down if needed, but keep the ratio.
325- constexpr int kMaxImageSize = kTabPanelButtonSize - 2 * kTabPanelImageMargin;
326- double image_scale =
327- std::min(1.,
328- std::min(static_cast<double>(kMaxImageSize) / m_tabs[idx]->pic->width(),
329- static_cast<double>(kMaxImageSize) / m_tabs[idx]->pic->height()));
330-
331- uint16_t picture_width = image_scale * m_tabs[idx]->pic->width();
332- uint16_t picture_height = image_scale * m_tabs[idx]->pic->height();
333- dst.blitrect_scale(Rect(x + (kTabPanelButtonSize - picture_width) / 2,
334- (kTabPanelButtonSize - picture_height) / 2,
335- picture_width,
336- picture_height),
337- m_tabs[idx]->pic,
338- Rect(0, 0, m_tabs[idx]->pic->width(), m_tabs[idx]->pic->height()),
339- 1.,
340- BlendMode::UseAlpha);
341+ int32_t x = 0;
342+ int tab_width = 0;
343+ for (size_t idx = 0; idx < tabs_.size(); ++idx) {
344+ x = tabs_[idx]->get_x();
345+ tab_width = tabs_[idx]->get_w();
346+
347+ if (highlight_ == idx) {
348+ dst.brighten_rect(Rect(Point(x, 0), tab_width, kTabPanelButtonHeight), MOUSE_OVER_BRIGHT_FACTOR);
349+ }
350+
351+ assert(tabs_[idx]->pic);
352+
353+ // If the title is empty, we will assume a pictorial tab
354+ if (tabs_[idx]->title.empty()) {
355+ // Scale the image down if needed, but keep the ratio.
356+ constexpr int kMaxImageSize = kTabPanelButtonHeight - 2 * kTabPanelImageMargin;
357+ double image_scale =
358+ std::min(1.,
359+ std::min(static_cast<double>(kMaxImageSize) / tabs_[idx]->pic->width(),
360+ static_cast<double>(kMaxImageSize) / tabs_[idx]->pic->height()));
361+
362+ uint16_t picture_width = image_scale * tabs_[idx]->pic->width();
363+ uint16_t picture_height = image_scale * tabs_[idx]->pic->height();
364+ dst.blitrect_scale(Rect(x + (kTabPanelButtonHeight - picture_width) / 2,
365+ (kTabPanelButtonHeight - picture_height) / 2,
366+ picture_width,
367+ picture_height),
368+ tabs_[idx]->pic,
369+ Rect(0, 0, tabs_[idx]->pic->width(), tabs_[idx]->pic->height()),
370+ 1.,
371+ BlendMode::UseAlpha);
372+ } else {
373+ dst.blit(Point(x + kTabPanelTextMargin, (kTabPanelButtonHeight - tabs_[idx]->pic->height()) / 2),
374+ tabs_[idx]->pic,
375+ BlendMode::UseAlpha,
376+ UI::Align_Left);
377+ }
378
379 // Draw top part of border
380- RGBColor black(0, 0, 0);
381-
382- dst.brighten_rect
383- (Rect(Point(x, 0), kTabPanelButtonSize, 2), BUTTON_EDGE_BRIGHT_FACTOR);
384- dst.brighten_rect
385- (Rect(Point(x, 2), 2, kTabPanelButtonSize - 4),
386+ dst.brighten_rect
387+ (Rect(Point(x, 0), tab_width, 2), BUTTON_EDGE_BRIGHT_FACTOR);
388+ dst.brighten_rect
389+ (Rect(Point(x, 2), 2, kTabPanelButtonHeight - 4),
390 BUTTON_EDGE_BRIGHT_FACTOR);
391 dst.fill_rect
392- (Rect(Point(x + kTabPanelButtonSize - 2, 2), 1, kTabPanelButtonSize - 4),
393+ (Rect(Point(x + tab_width - 2, 2), 1, kTabPanelButtonHeight - 4),
394 black);
395 dst.fill_rect
396- (Rect(Point(x + kTabPanelButtonSize - 1, 1), 1, kTabPanelButtonSize - 3),
397+ (Rect(Point(x + tab_width - 1, 1), 1, kTabPanelButtonHeight - 3),
398 black);
399
400 // Draw bottom part
401- if (m_active != idx)
402+ if (active_ != idx)
403 dst.brighten_rect
404- (Rect(Point(x, kTabPanelButtonSize - 2), kTabPanelButtonSize, 2),
405+ (Rect(Point(x, kTabPanelButtonHeight - 2), tab_width, 2),
406 2 * BUTTON_EDGE_BRIGHT_FACTOR);
407 else {
408 dst.brighten_rect
409- (Rect(Point(x, kTabPanelButtonSize - 2), 2, 2),
410+ (Rect(Point(x, kTabPanelButtonHeight - 2), 2, 2),
411 BUTTON_EDGE_BRIGHT_FACTOR);
412
413 dst.brighten_rect
414- (Rect(Point(x + kTabPanelButtonSize - 2, kTabPanelButtonSize - 2), 2, 2),
415+ (Rect(Point(x + tab_width - 2, kTabPanelButtonHeight - 2), 2, 2),
416 2 * BUTTON_EDGE_BRIGHT_FACTOR);
417 dst.fill_rect
418- (Rect(Point(x + kTabPanelButtonSize - 2, kTabPanelButtonSize - 1), 1, 1),
419+ (Rect(Point(x + tab_width - 2, kTabPanelButtonHeight - 1), 1, 1),
420 black);
421 dst.fill_rect
422- (Rect(Point(x + kTabPanelButtonSize - 2, kTabPanelButtonSize - 2), 2, 1),
423+ (Rect(Point(x + tab_width - 2, kTabPanelButtonHeight - 2), 2, 1),
424 black);
425 }
426 }
427
428 // draw the remaining separator
429- assert(x <= static_cast<uint32_t>(get_w()));
430+ assert(x <= get_w());
431 dst.brighten_rect
432- (Rect(Point(x, kTabPanelButtonSize - 2), get_w() - x, 2),
433+ (Rect(Point(x + tab_width, kTabPanelButtonHeight - 2), get_w() - x, 2),
434 2 * BUTTON_EDGE_BRIGHT_FACTOR);
435+
436+ // Draw border around the main panel
437+ if (border_type_ == TabPanel::Type::kBorder) {
438+ // left edge
439+ dst.brighten_rect
440+ (Rect(Point(0, kTabPanelButtonHeight), 2, get_h() - 2), BUTTON_EDGE_BRIGHT_FACTOR);
441+ // bottom edge
442+ dst.fill_rect(Rect(Point(2, get_h() - 2), get_w() - 2, 1), black);
443+ dst.fill_rect(Rect(Point(1, get_h() - 1), get_w() - 1, 1), black);
444+ // right edge
445+ dst.fill_rect(Rect(Point(get_w() - 2, kTabPanelButtonHeight - 1), 1, get_h() - 2), black);
446+ dst.fill_rect(Rect(Point(get_w() - 1, kTabPanelButtonHeight - 2), 1, get_h() - 1), black);
447+ }
448 }
449
450
451@@ -300,11 +387,9 @@
452 */
453 void TabPanel::handle_mousein(bool inside)
454 {
455- if (!inside && m_highlight >= 0) {
456- update
457- (m_highlight * kTabPanelButtonSize, 0, kTabPanelButtonSize, kTabPanelButtonSize);
458-
459- m_highlight = -1;
460+ if (!inside && highlight_ != kNotFound) {
461+ update(tabs_[highlight_]->get_x(), 0, tabs_[highlight_]->get_w(), kTabPanelButtonHeight);
462+ highlight_ = kNotFound;
463 }
464 }
465
466@@ -315,31 +400,17 @@
467 bool TabPanel::handle_mousemove
468 (uint8_t, int32_t const x, int32_t const y, int32_t, int32_t)
469 {
470- int32_t hl;
471-
472- if (y < 0 || y >= kTabPanelButtonSize)
473- hl = -1;
474- else {
475- hl = x / kTabPanelButtonSize;
476-
477- if (m_tabs.size() <= static_cast<size_t>(hl))
478- hl = -1;
479- }
480-
481- if (hl != m_highlight) {
482- {
483- if (hl >= 0)
484- set_tooltip(m_tabs[hl]->tooltip);
485- }
486- if (m_highlight >= 0)
487- update
488- (m_highlight * kTabPanelButtonSize, 0,
489- kTabPanelButtonSize, kTabPanelButtonSize);
490- if (hl >= 0)
491- update
492- (hl * kTabPanelButtonSize, 0, kTabPanelButtonSize, kTabPanelButtonSize);
493-
494- m_highlight = hl;
495+ size_t hl = find_tab(x, y);
496+
497+ if (hl != highlight_) {
498+ if (hl != kNotFound) {
499+ update(tabs_[hl]->get_x(), 0, tabs_[hl]->get_w(), kTabPanelButtonHeight);
500+ }
501+ if (highlight_ != kNotFound) {
502+ update(tabs_[highlight_]->get_x(), 0, tabs_[highlight_]->get_w(), kTabPanelButtonHeight);
503+ }
504+ highlight_ = hl;
505+ set_tooltip(highlight_ != kNotFound ? tabs_[highlight_]->tooltip : "");
506 }
507 return true;
508 }
509@@ -350,25 +421,39 @@
510 */
511 bool TabPanel::handle_mousepress(const uint8_t btn, int32_t x, int32_t y) {
512 if (btn == SDL_BUTTON_LEFT) {
513- int32_t id;
514-
515- if (y >= kTabPanelButtonSize)
516- return false;
517-
518- id = x / kTabPanelButtonSize;
519-
520- if (static_cast<size_t>(id) < m_tabs.size()) {
521+ size_t id = find_tab(x, y);
522+ if (id != kNotFound) {
523 activate(id);
524-
525 return true;
526 }
527 }
528-
529 return false;
530 }
531+
532 bool TabPanel::handle_mouserelease(uint8_t, int32_t, int32_t)
533 {
534 return false;
535 }
536
537+
538+/**
539+ * Find the tab at the coordinates x, y
540+ * Returns kNotFound if no tab was found
541+ */
542+size_t TabPanel::find_tab(int32_t x, int32_t y) const {
543+ if (y < 0 || y >= kTabPanelButtonHeight) {
544+ return kNotFound;
545+ }
546+
547+ int32_t width = 0;
548+ for (size_t id = 0; id < tabs_.size(); ++id) {
549+ width += tabs_[id]->get_w();
550+ if (width > x) {
551+ return id;
552+ }
553+ }
554+ return kNotFound;
555+}
556+
557+
558 }
559
560=== modified file 'src/ui_basic/tabpanel.h'
561--- src/ui_basic/tabpanel.h 2014-09-14 11:31:58 +0000
562+++ src/ui_basic/tabpanel.h 2016-01-01 19:10:55 +0000
563@@ -35,11 +35,16 @@
564 struct Tab : public NamedPanel {
565 friend struct TabPanel;
566
567+ /** If title is not empty, this will be a textual tab.
568+ * In that case, pic will need to be the rendered title */
569 Tab
570 (TabPanel * parent,
571- uint32_t,
572+ size_t id,
573+ int32_t x,
574+ int32_t w,
575 const std::string & name,
576- const Image*,
577+ const std::string & title,
578+ const Image* pic,
579 const std::string & gtooltip,
580 Panel * gpanel);
581
582@@ -47,12 +52,18 @@
583 void activate();
584
585 private:
586- TabPanel * m_parent;
587- uint32_t m_id;
588+ // Leave handling the mouse move to the TabPanel.
589+ bool handle_mousemove(uint8_t, int32_t, int32_t, int32_t, int32_t) override {return false;}
590+ // Play click
591+ bool handle_mousepress(uint8_t, int32_t, int32_t) override;
592+
593+ TabPanel* parent;
594+ uint32_t id;
595
596 const Image* pic;
597+ std::string title;
598 std::string tooltip;
599- Panel * panel;
600+ Panel* panel;
601 };
602
603 /**
604@@ -66,15 +77,30 @@
605 *
606 */
607 struct TabPanel : public Panel {
608+ enum class Type {
609+ kNoBorder,
610+ kBorder
611+ };
612+
613 friend struct Tab;
614
615- TabPanel(Panel * parent, int32_t x, int32_t y, const Image* background);
616+ TabPanel(Panel * parent, int32_t x, int32_t y, const Image* background,
617+ TabPanel::Type border_type = TabPanel::Type::kNoBorder);
618 // For Fullscreen menus
619 TabPanel
620 (Panel * parent,
621 int32_t x, int32_t y, int32_t w, int32_t h,
622- const Image* background);
623-
624+ const Image* background,
625+ TabPanel::Type border_type = TabPanel::Type::kNoBorder);
626+
627+ /** Add textual tab */
628+ uint32_t add
629+ (const std::string & name,
630+ const std::string & title,
631+ Panel * panel,
632+ const std::string & tooltip = std::string());
633+
634+ /** Add pictorial tab */
635 uint32_t add
636 (const std::string & name,
637 const Image* pic,
638@@ -86,13 +112,21 @@
639 const TabList & tabs();
640 void activate(uint32_t idx);
641 void activate(const std::string &);
642- uint32_t active() {return m_active;}
643+ uint32_t active() {return active_;}
644
645 protected:
646 void layout() override;
647 void update_desired_size() override;
648
649 private:
650+ // Common adding function for textual and pictorial tabs
651+ uint32_t add_tab(int32_t width,
652+ const std::string& name,
653+ const std::string& title,
654+ const Image* pic,
655+ const std::string& tooltip,
656+ Panel* contents);
657+
658 // Drawing and event handlers
659 void draw(RenderTarget &) override;
660
661@@ -102,12 +136,14 @@
662 (uint8_t state, int32_t x, int32_t y, int32_t xdiff, int32_t ydiff) override;
663 void handle_mousein(bool inside) override;
664
665-
666- TabList m_tabs;
667- uint32_t m_active; ///< index of the currently active tab
668- int32_t m_highlight; ///< index of the highlighted button
669-
670- const Image* m_pic_background; ///< picture used to draw background
671+ size_t find_tab(int32_t x, int32_t y) const;
672+
673+ TabList tabs_;
674+ size_t active_; ///< index of the currently active tab
675+ size_t highlight_; ///< index of the highlighted button
676+
677+ const Image* pic_background_; ///< picture used to draw background
678+ TabPanel::Type border_type_; ///< whether there will be a border around the panels.
679 };
680 }
681
682
683=== modified file 'src/ui_fsmenu/base.h'
684--- src/ui_fsmenu/base.h 2015-08-10 19:55:41 +0000
685+++ src/ui_fsmenu/base.h 2016-01-01 19:10:55 +0000
686@@ -45,7 +45,7 @@
687 kOk = static_cast<int>(UI::Panel::Returncodes::kOk),
688
689 // Options
690- kRestart,
691+ kApplyOptions,
692
693 // Main menu
694 kTutorial,
695
696=== modified file 'src/ui_fsmenu/options.cc'
697--- src/ui_fsmenu/options.cc 2015-12-01 21:52:24 +0000
698+++ src/ui_fsmenu/options.cc 2016-01-01 19:10:55 +0000
699@@ -96,184 +96,241 @@
700 FullscreenMenuOptions::FullscreenMenuOptions
701 (OptionsCtrl::OptionsStruct opt)
702 :
703- FullscreenMenuBase("optionsmenu.jpg"),
704+ FullscreenMenuBase("ui_fsmenu.jpg"),
705
706 // Values for alignment and size
707- m_vbutw (get_h() * 333 / 10000),
708- m_butw (get_w() / 4),
709- m_buth (get_h() * 9 / 200),
710- m_hmargin (get_w() * 19 / 200),
711- m_padding (10),
712- m_space (25),
713- m_offset_first_group (get_h() * 1417 / 10000),
714- m_offset_second_group(get_h() * 5833 / 10000),
715-
716-// Buttons
717- m_advanced_options
718- (this, "advanced_options",
719- get_w() * 9 / 80, get_h() * 19 / 20, m_butw, m_buth,
720- g_gr->images().get("pics/but2.png"),
721- _("Advanced Options"), std::string(), true, false),
722- m_cancel
723- (this, "cancel",
724- get_w() * 51 / 80, get_h() * 19 / 20, m_butw, m_buth,
725- g_gr->images().get("pics/but0.png"),
726- _("Cancel"), std::string(), true, false),
727- m_apply
728- (this, "apply",
729- get_w() * 3 / 8, get_h() * 19 / 20, m_butw, m_buth,
730- g_gr->images().get("pics/but2.png"),
731- _("Apply"), std::string(), true, false),
732+ butw_ (get_w() / 5),
733+ buth_ (get_h() * 9 / 200),
734+ hmargin_ (get_w() * 19 / 200),
735+ padding_ (10),
736+ space_ (25),
737+ tab_panel_width_(get_inner_w() - 2 * hmargin_),
738+ column_width_(tab_panel_width_ - padding_),
739+ tab_panel_y_(get_h() * 14 / 100),
740
741 // Title
742- m_title
743- (this,
744- get_w() / 2, get_h() / 40,
745- _("General Options"), UI::Align_HCenter),
746-
747- // First options block 'general options', first column
748- m_label_resolution
749- (this,
750- m_hmargin, m_offset_first_group,
751- _("In-game resolution"), UI::Align_VCenter),
752- m_reslist
753- (this,
754- m_hmargin, m_label_resolution.get_y() + m_label_resolution.get_h(),
755- (get_w() - 2 * m_hmargin - m_space) / 2, 95,
756- UI::Align_Left, true),
757-
758- m_fullscreen (this, Point(m_hmargin,
759- m_reslist.get_y() +
760- m_reslist.get_h() + m_padding),
761- _("Fullscreen")),
762- m_inputgrab (this, Point(m_hmargin,
763- m_fullscreen.get_y() +
764- m_fullscreen.get_h() + m_padding),
765- _("Grab Input")),
766- m_sb_maxfps
767- (this,
768- m_hmargin,
769- m_inputgrab.get_y() + m_inputgrab.get_h() + m_padding,
770- m_reslist.get_w(), 105,
771- opt.maxfps, 0, 99, _("Maximum FPS:"), ""),
772-
773-
774- // First options block 'general options', second column
775- m_label_language
776- (this,
777- get_w() - m_hmargin - (get_w() - 2 * m_hmargin - m_space) / 2, m_offset_first_group,
778- _("Language"), UI::Align_VCenter),
779- // same height as m_reslist
780- m_language_list
781- (this,
782- m_label_language.get_x(), m_label_language.get_y() + m_label_language.get_h(),
783- (get_w() - 2 * m_hmargin - m_space) / 2, m_reslist.get_h(),
784- UI::Align_Left, true),
785-
786- m_music (this, Point(m_label_language.get_x(),
787- m_language_list.get_y() +
788- m_language_list.get_h() + m_padding),
789- _("Enable Music")),
790- m_fx (this, Point(m_label_language.get_x(),
791- m_music.get_y() +
792- m_music.get_h() + m_padding),
793- _("Enable Sound Effects")),
794-
795- // Second options block 'In-game options'
796- // Title 2
797- m_label_game_options
798- (this,
799- get_w() / 2, get_h() / 2,
800- _("In-game Options"), UI::Align_HCenter),
801-
802- /** TRANSLATORS: A watchwindow is a window where you keep watching an object or a map region,*/
803- /** TRANSLATORS: and it also lets you jump to it on the map. */
804- m_single_watchwin (this, Point(m_hmargin, m_offset_second_group), _("Use single watchwindow mode")),
805-
806- m_auto_roadbuild_mode (this, Point(m_single_watchwin.get_x(),
807- m_single_watchwin.get_y() +
808- m_single_watchwin.get_h() + m_padding),
809- _("Start building road after placing a flag")),
810- m_show_workarea_preview
811- (this, Point(m_auto_roadbuild_mode.get_x(),
812- m_auto_roadbuild_mode.get_y() +
813- m_auto_roadbuild_mode.get_h() + m_padding),
814- _("Show buildings area preview")),
815-
816- m_snap_win_overlap_only
817- (this, Point(m_show_workarea_preview.get_x(),
818- m_show_workarea_preview.get_y() +
819- m_show_workarea_preview.get_h() + m_padding),
820- _("Snap windows only when overlapping")),
821-
822- m_dock_windows_to_edges (this, Point(m_snap_win_overlap_only.get_x(),
823- m_snap_win_overlap_only.get_y() +
824- m_snap_win_overlap_only.get_h() + m_padding),
825- _("Dock windows to edges")),
826- m_sb_autosave
827- (this,
828- m_hmargin,
829- m_dock_windows_to_edges.get_y() + m_dock_windows_to_edges.get_h() + m_padding,
830- get_w() - 2 * m_hmargin,
831- 240,
832- opt.autosave / 60, 0, 100,
833- _("Save game automatically every"),
834+ title_
835+ (this,
836+ get_w() / 2, buth_,
837+ _("Options"), UI::Align_HCenter),
838+
839+ // Buttons
840+ cancel_
841+ (this, "cancel",
842+ get_w() * 1 / 4 - butw_ / 2,
843+ get_inner_h() - hmargin_,
844+ butw_, buth_,
845+ g_gr->images().get("pics/but0.png"),
846+ _("Cancel"), std::string(), true, false),
847+ apply_
848+ (this, "apply",
849+ get_w() * 2 / 4 - butw_ / 2,
850+ get_inner_h() - hmargin_,
851+ butw_, buth_,
852+ g_gr->images().get("pics/but0.png"),
853+ _("Apply"), std::string(), true, false),
854+ ok_
855+ (this, "ok",
856+ get_w() * 3 / 4 - butw_ / 2,
857+ get_inner_h() - hmargin_,
858+ butw_, buth_,
859+ g_gr->images().get("pics/but2.png"),
860+ _("OK"), std::string(), true, false),
861+
862+ tabs_(this, hmargin_, 0,
863+ tab_panel_width_, get_inner_h() - tab_panel_y_ - buth_ - hmargin_,
864+ g_gr->images().get("pics/but1.png"),
865+ UI::TabPanel::Type::kBorder),
866+
867+ box_interface_(&tabs_, 0, 0, UI::Box::Vertical, 0, 0, padding_),
868+ box_windows_(&tabs_, 0, 0, UI::Box::Vertical, 0, 0, padding_),
869+ box_sound_(&tabs_, 0, 0, UI::Box::Vertical, 0, 0, padding_),
870+ box_saving_(&tabs_, 0, 0, UI::Box::Vertical, 0, 0, padding_),
871+ box_game_(&tabs_, 0, 0, UI::Box::Vertical, 0, 0, padding_),
872+ box_language_(&tabs_, 0, 0, UI::Box::Vertical, 0, 0, padding_),
873+
874+ // Interface options
875+ label_resolution_(&box_interface_, _("In-game resolution"), UI::Align_Left),
876+ resolution_list_(&box_interface_, 0, 0, column_width_ / 2, 80, UI::Align_Left, true),
877+
878+ fullscreen_ (&box_interface_, Point(0, 0), _("Fullscreen"), "", column_width_),
879+ inputgrab_ (&box_interface_, Point(0, 0), _("Grab Input"), "", column_width_),
880+
881+ sb_maxfps_(&box_interface_, 0, 0, column_width_ / 2, column_width_ / 4,
882+ opt.maxfps, 0, 99,
883+ _("Maximum FPS:"), ""),
884+
885+
886+ // Windows options
887+ snap_win_overlap_only_(&box_windows_, Point(0, 0), _("Snap windows only when overlapping"),
888+ "", column_width_),
889+ dock_windows_to_edges_(&box_windows_, Point(0, 0), _("Dock windows to edges"),
890+ "", column_width_),
891+
892+ sb_dis_panel_
893+ (&box_windows_, 0, 0, column_width_, 200,
894+ opt.panel_snap_distance, 0, 99, _("Distance for windows to snap to other panels:"),
895+ /** TRANSLATORS: Options: Distance for windows to snap to other panels: */
896+ /** TRANSLATORS: This will have a number added in front of it */
897+ ngettext("pixel", "pixels", opt.panel_snap_distance)),
898+
899+ sb_dis_border_
900+ (&box_windows_, 0, 0, column_width_, 200,
901+ opt.border_snap_distance, 0, 99,
902+ _("Distance for windows to snap to borders:"),
903+ /** TRANSLATORS: Options: Distance for windows to snap to borders: */
904+ /** TRANSLATORS: This will have a number added in front of it */
905+ ngettext("pixel", "pixels", opt.border_snap_distance)),
906+
907+ // Sound options
908+ music_ (&box_sound_, Point(0, 0), _("Enable Music"), "", column_width_),
909+ fx_ (&box_sound_, Point(0, 0), _("Enable Sound Effects"), "", column_width_),
910+ message_sound_(&box_sound_, Point(0, 0), _("Play a sound at message arrival"),
911+ "", column_width_),
912+
913+ // Saving options
914+ sb_autosave_
915+ (&box_saving_, 0, 0, column_width_, 240,
916+ opt.autosave / 60, 0, 100, _("Save game automatically every"),
917 /** TRANSLATORS: Options: Save game automatically every: */
918 /** TRANSLATORS: This will have a number added in front of it */
919 ngettext("minute", "minutes", opt.autosave / 60),
920 g_gr->images().get("pics/but3.png"), UI::SpinBox::Type::kBig),
921
922- m_sb_remove_replays
923- (this,
924- m_hmargin,
925- m_sb_autosave.get_y() + m_sb_autosave.get_h() + m_padding,
926- get_w() - 2 * m_hmargin,
927- 240,
928- opt.remove_replays, 0, 365,
929- _("Remove replays older than:"),
930+ sb_rolling_autosave_
931+ (&box_saving_, 0, 0, column_width_, 240,
932+ opt.rolling_autosave, 1, 20, _("Maximum number of autosave files"),
933+ "",
934+ g_gr->images().get("pics/but3.png"), UI::SpinBox::Type::kBig),
935+
936+ sb_remove_replays_
937+ (&box_saving_, 0, 0, column_width_, 240,
938+ opt.remove_replays, 0, 365, _("Remove replays older than:"),
939 /** TRANSLATORS: Options: Remove Replays older than: */
940 /** TRANSLATORS: This will have a number added in front of it */
941 ngettext("day", "days", opt.remove_replays),
942 g_gr->images().get("pics/but3.png"), UI::SpinBox::Type::kBig),
943- os(opt)
944+
945+ nozip_(&box_saving_, Point(0, 0), _("Do not zip widelands data files (maps, replays and savegames)"),
946+ "", column_width_),
947+ remove_syncstreams_(&box_saving_, Point(0, 0), _("Remove Syncstream dumps on startup"),
948+ "", column_width_),
949+
950+ // Game options
951+ auto_roadbuild_mode_(&box_game_, Point(0, 0), _("Start building road after placing a flag")),
952+ show_workarea_preview_(&box_game_, Point(0, 0), _("Show buildings area preview")),
953+ transparent_chat_(&box_game_, Point(0, 0), _("Show in-game chat with transparent background"),
954+ "", column_width_),
955+
956+ /** TRANSLATORS: A watchwindow is a window where you keep watching an object or a map region,*/
957+ /** TRANSLATORS: and it also lets you jump to it on the map. */
958+ single_watchwin_(&box_game_, Point(0, 0), _("Use single watchwindow mode")),
959+
960+ // Language options
961+ label_language_(&box_language_, _("Language"), UI::Align_Left),
962+ language_list_(&box_language_, 0, 0, column_width_ / 2,
963+ get_inner_h() - tab_panel_y_ - buth_ - hmargin_ - 5 * padding_,
964+ UI::Align_Left, true),
965+
966+ os_(opt)
967 {
968- m_advanced_options.sigclicked.connect
969- (boost::bind(&FullscreenMenuOptions::advanced_options, boost::ref(*this)));
970- m_cancel.sigclicked.connect(boost::bind(&FullscreenMenuOptions::clicked_back, this));
971- m_apply.sigclicked.connect(boost::bind(&FullscreenMenuOptions::clicked_ok, this));
972+ // Set up UI Elements
973+ title_ .set_textstyle(UI::TextStyle::ui_big());
974+
975+ tabs_.add("options_interface", _("Interface"), &box_interface_, "");
976+ tabs_.add("options_windows", _("Windows"), &box_windows_, "");
977+ tabs_.add("options_sound", _("Sound"), &box_sound_, "");
978+ tabs_.add("options_saving", _("Saving"), &box_saving_, "");
979+ tabs_.add("options_game", _("Game"), &box_game_, "");
980+ tabs_.add("options_language", _("Language"), &box_language_, "");
981+
982+ // We want the last active tab when "Apply" was clicked.
983+ if (os_.active_tab < tabs_.tabs().size()) {
984+ tabs_.activate(os_.active_tab);
985+ }
986+
987+ tabs_.set_pos(Point(hmargin_, tab_panel_y_));
988+
989+ box_interface_.set_size(tabs_.get_inner_w(), tabs_.get_inner_h());
990+ box_windows_.set_size(tabs_.get_inner_w(), tabs_.get_inner_h());
991+ box_sound_.set_size(tabs_.get_inner_w(), tabs_.get_inner_h());
992+ box_saving_.set_size(tabs_.get_inner_w(), tabs_.get_inner_h());
993+ box_game_.set_size(tabs_.get_inner_w(), tabs_.get_inner_h());
994+ box_language_.set_size(tabs_.get_inner_w(), tabs_.get_inner_h());
995+
996+ // Interface
997+ box_interface_.add(&label_resolution_, UI::Align_Left);
998+ box_interface_.add(&resolution_list_, UI::Align_Left);
999+ box_interface_.add(&fullscreen_, UI::Align_Left);
1000+ box_interface_.add(&inputgrab_, UI::Align_Left);
1001+ box_interface_.add(&sb_maxfps_, UI::Align_Left);
1002+
1003+ // Windows
1004+ box_windows_.add(&snap_win_overlap_only_, UI::Align_Left);
1005+ box_windows_.add(&dock_windows_to_edges_, UI::Align_Left);
1006+ box_windows_.add(&sb_dis_panel_, UI::Align_Left);
1007+ box_windows_.add(&sb_dis_border_, UI::Align_Left);
1008+
1009+ // Sound
1010+ box_sound_.add(&music_, UI::Align_Left);
1011+ box_sound_.add(&fx_, UI::Align_Left);
1012+ box_sound_.add(&message_sound_, UI::Align_Left);
1013+
1014+ // Saving
1015+ box_saving_.add(&sb_autosave_, UI::Align_Left);
1016+ box_saving_.add(&sb_rolling_autosave_, UI::Align_Left);
1017+ box_saving_.add(&sb_remove_replays_, UI::Align_Left);
1018+ box_saving_.add(&nozip_, UI::Align_Left);
1019+ box_saving_.add(&remove_syncstreams_, UI::Align_Left);
1020+
1021+ // Game
1022+ box_game_.add(&auto_roadbuild_mode_, UI::Align_Left);
1023+ box_game_.add(&show_workarea_preview_, UI::Align_Left);
1024+ box_game_.add(&transparent_chat_, UI::Align_Left);
1025+ box_game_.add(&single_watchwin_, UI::Align_Left);
1026+
1027+ // Language
1028+ box_language_.add(&label_language_, UI::Align_Left);
1029+ box_language_.add(&language_list_, UI::Align_Left);
1030+
1031+
1032+ // Bind actions
1033+ cancel_.sigclicked.connect(boost::bind(&FullscreenMenuOptions::clicked_back, this));
1034+ apply_.sigclicked.connect(boost::bind(&FullscreenMenuOptions::clicked_apply, this));
1035+ ok_.sigclicked.connect(boost::bind(&FullscreenMenuOptions::clicked_ok, this));
1036
1037 /** TRANSLATORS Options: Save game automatically every: */
1038- m_sb_autosave .add_replacement(0, _("Off"));
1039- for (UI::Button* temp_button : m_sb_autosave.get_buttons()) {
1040+ sb_autosave_ .add_replacement(0, _("Off"));
1041+ for (UI::Button* temp_button : sb_autosave_.get_buttons()) {
1042 temp_button->sigclicked.connect
1043 (boost::bind
1044 (&FullscreenMenuOptions::update_sb_autosave_unit,
1045 boost::ref(*this)));
1046 }
1047 /** TRANSLATORS Options: Remove Replays older than: */
1048- m_sb_remove_replays.add_replacement(0, _("Never"));
1049- for (UI::Button* temp_button : m_sb_remove_replays.get_buttons()) {
1050+ sb_remove_replays_.add_replacement(0, _("Never"));
1051+ for (UI::Button* temp_button : sb_remove_replays_.get_buttons()) {
1052 temp_button->sigclicked.connect
1053 (boost::bind
1054 (&FullscreenMenuOptions::update_sb_remove_replays_unit,
1055 boost::ref(*this)));
1056 }
1057-
1058- m_title .set_textstyle(UI::TextStyle::ui_big());
1059- m_fullscreen .set_state(opt.fullscreen);
1060- m_inputgrab .set_state(opt.inputgrab);
1061- m_music .set_state(opt.music);
1062- m_music .set_enabled(!g_sound_handler.lock_audio_disabling_);
1063- m_fx .set_state(opt.fx);
1064- m_fx .set_enabled(!g_sound_handler.lock_audio_disabling_);
1065-
1066- m_label_game_options .set_textstyle(UI::TextStyle::ui_big());
1067- m_single_watchwin .set_state(opt.single_watchwin);
1068- m_auto_roadbuild_mode .set_state(opt.auto_roadbuild_mode);
1069- m_show_workarea_preview .set_state(opt.show_warea);
1070- m_snap_win_overlap_only .set_state(opt.snap_win_overlap_only);
1071- m_dock_windows_to_edges .set_state(opt.dock_windows_to_edges);
1072-
1073+ for (UI::Button* temp_button : sb_dis_panel_.get_buttons()) {
1074+ temp_button->sigclicked.connect
1075+ (boost::bind
1076+ (&FullscreenMenuOptions::update_sb_dis_panel_unit,
1077+ boost::ref(*this)));
1078+ }
1079+
1080+ for (UI::Button* temp_button : sb_dis_border_.get_buttons()) {
1081+ temp_button->sigclicked.connect
1082+ (boost::bind
1083+ (&FullscreenMenuOptions::update_sb_dis_border_unit,
1084+ boost::ref(*this)));
1085+ }
1086+
1087+ // Fill in data
1088+ // Interface options
1089 for (int modes = 0; modes < SDL_GetNumDisplayModes(0); ++modes) {
1090 SDL_DisplayMode mode;
1091 SDL_GetDisplayMode(0, modes, & mode);
1092@@ -281,64 +338,89 @@
1093 (SDL_BITSPERPIXEL(mode.format) == 32 ||
1094 SDL_BITSPERPIXEL(mode.format) == 24)) {
1095 ScreenResolution this_res = {
1096- mode.w, mode.h, static_cast<int32_t>(SDL_BITSPERPIXEL(mode.format))};
1097+ mode.w, mode.h, static_cast<int32_t>(SDL_BITSPERPIXEL(mode.format))};
1098 if (this_res.depth == 24) this_res.depth = 32;
1099- if (m_resolutions.empty()
1100- || this_res.xres != m_resolutions.rbegin()->xres
1101- || this_res.yres != m_resolutions.rbegin()->yres) {
1102- m_resolutions.push_back(this_res);
1103+ if (resolutions_.empty()
1104+ || this_res.xres != resolutions_.rbegin()->xres
1105+ || this_res.yres != resolutions_.rbegin()->yres) {
1106+ resolutions_.push_back(this_res);
1107 }
1108 }
1109 }
1110
1111 bool did_select_a_res = false;
1112- for (uint32_t i = 0; i < m_resolutions.size(); ++i) {
1113+ for (uint32_t i = 0; i < resolutions_.size(); ++i) {
1114 const bool selected =
1115- m_resolutions[i].xres == opt.xres &&
1116- m_resolutions[i].yres == opt.yres;
1117+ resolutions_[i].xres == opt.xres &&
1118+ resolutions_[i].yres == opt.yres;
1119 did_select_a_res |= selected;
1120 /** TRANSLATORS: Screen resolution, e.g. 800 x 600*/
1121- m_reslist.add((boost::format(_("%1% x %2%"))
1122- % m_resolutions[i].xres
1123- % m_resolutions[i].yres).str(),
1124+ resolution_list_.add((boost::format(_("%1% x %2%"))
1125+ % resolutions_[i].xres
1126+ % resolutions_[i].yres).str(),
1127 nullptr, nullptr, selected);
1128 }
1129 if (!did_select_a_res) {
1130- m_reslist.add((boost::format(_("%1% x %2%"))
1131+ resolution_list_.add((boost::format(_("%1% x %2%"))
1132 % opt.xres
1133 % opt.yres).str(),
1134 nullptr, nullptr, true);
1135- uint32_t entry = m_resolutions.size();
1136- m_resolutions.resize(entry + 1);
1137- m_resolutions[entry].xres = opt.xres;
1138- m_resolutions[entry].yres = opt.yres;
1139+ uint32_t entry = resolutions_.size();
1140+ resolutions_.resize(entry + 1);
1141+ resolutions_[entry].xres = opt.xres;
1142+ resolutions_[entry].yres = opt.yres;
1143 }
1144
1145+ fullscreen_ .set_state(opt.fullscreen);
1146+ inputgrab_ .set_state(opt.inputgrab);
1147+
1148+ // Windows options
1149+ snap_win_overlap_only_.set_state(opt.snap_win_overlap_only);
1150+ dock_windows_to_edges_.set_state(opt.dock_windows_to_edges);
1151+
1152+ // Sound options
1153+ music_ .set_state(opt.music);
1154+ music_ .set_enabled(!g_sound_handler.lock_audio_disabling_);
1155+ fx_ .set_state(opt.fx);
1156+ fx_ .set_enabled(!g_sound_handler.lock_audio_disabling_);
1157+ message_sound_ .set_state(opt.message_sound);
1158+
1159+ // Saving options
1160+ nozip_ .set_state(opt.nozip);
1161+ remove_syncstreams_ .set_state(opt.remove_syncstreams);
1162+
1163+ // Game options
1164+ auto_roadbuild_mode_ .set_state(opt.auto_roadbuild_mode);
1165+ show_workarea_preview_.set_state(opt.show_warea);
1166+ transparent_chat_ .set_state(opt.transparent_chat);
1167+ single_watchwin_ .set_state(opt.single_watchwin);
1168+
1169+ // Language options
1170 add_languages_to_list(opt.language);
1171- m_language_list.focus();
1172+ language_list_.focus();
1173 }
1174
1175 void FullscreenMenuOptions::update_sb_autosave_unit() {
1176- m_sb_autosave.set_unit(ngettext("minute", "minutes", m_sb_autosave.get_value()));
1177+ sb_autosave_.set_unit(ngettext("minute", "minutes", sb_autosave_.get_value()));
1178 }
1179
1180 void FullscreenMenuOptions::update_sb_remove_replays_unit() {
1181- m_sb_remove_replays.set_unit(ngettext("day", "days", m_sb_remove_replays.get_value()));
1182-}
1183-
1184-void FullscreenMenuOptions::advanced_options() {
1185- FullscreenMenuAdvancedOptions aom(os);
1186- if (aom.run<FullscreenMenuBase::MenuTarget>() == FullscreenMenuBase::MenuTarget::kOk) {
1187- os = aom.get_values();
1188- end_modal<FullscreenMenuBase::MenuTarget>(FullscreenMenuBase::MenuTarget::kRestart);
1189- }
1190+ sb_remove_replays_.set_unit(ngettext("day", "days", sb_remove_replays_.get_value()));
1191+}
1192+
1193+void FullscreenMenuOptions::update_sb_dis_panel_unit() {
1194+ sb_dis_panel_.set_unit(ngettext("pixel", "pixels", sb_dis_panel_.get_value()));
1195+}
1196+
1197+void FullscreenMenuOptions::update_sb_dis_border_unit() {
1198+ sb_dis_border_.set_unit(ngettext("pixel", "pixels", sb_dis_border_.get_value()));
1199 }
1200
1201 void FullscreenMenuOptions::add_languages_to_list(const std::string& current_locale) {
1202
1203 // We want these two entries on top - the most likely user's choice and the default.
1204- m_language_list.add(_("Try system language"), "", nullptr, current_locale == "");
1205- m_language_list.add("English", "en", nullptr, current_locale == "en");
1206+ language_list_.add(_("Try system language"), "", nullptr, current_locale == "");
1207+ language_list_.add("English", "en", nullptr, current_locale == "en");
1208
1209 // We start with the locale directory so we can pick up locales
1210 // that don't have a configuration file yet.
1211@@ -391,241 +473,164 @@
1212
1213 std::sort(entries.begin(), entries.end());
1214 for (const LanguageEntry& entry : entries) {
1215- m_language_list.add(entry.descname.c_str(), entry.localename, nullptr,
1216+ language_list_.add(entry.descname.c_str(), entry.localename, nullptr,
1217 entry.localename == selected_locale, "", entry.fontname);
1218 }
1219 }
1220
1221
1222+void FullscreenMenuOptions::clicked_apply() {
1223+ end_modal<FullscreenMenuBase::MenuTarget>(FullscreenMenuBase::MenuTarget::kApplyOptions);
1224+}
1225+
1226+
1227 OptionsCtrl::OptionsStruct FullscreenMenuOptions::get_values() {
1228- const uint32_t res_index = m_reslist.selection_index();
1229-
1230 // Write all data from UI elements
1231- os.xres = m_resolutions[res_index].xres;
1232- os.yres = m_resolutions[res_index].yres;
1233- os.inputgrab = m_inputgrab.get_state();
1234- os.fullscreen = m_fullscreen.get_state();
1235- os.single_watchwin = m_single_watchwin.get_state();
1236- os.auto_roadbuild_mode = m_auto_roadbuild_mode.get_state();
1237- os.show_warea = m_show_workarea_preview.get_state();
1238- os.snap_win_overlap_only = m_snap_win_overlap_only.get_state();
1239- os.dock_windows_to_edges = m_dock_windows_to_edges.get_state();
1240- os.music = m_music.get_state();
1241- os.fx = m_fx.get_state();
1242- if (m_language_list.has_selection())
1243- os.language = m_language_list.get_selected();
1244- os.autosave = m_sb_autosave.get_value();
1245- os.maxfps = m_sb_maxfps.get_value();
1246- os.remove_replays = m_sb_remove_replays.get_value();
1247-
1248- return os;
1249-}
1250-
1251-
1252-/**
1253- * The advanced option menu
1254- */
1255-FullscreenMenuAdvancedOptions::FullscreenMenuAdvancedOptions
1256- (OptionsCtrl::OptionsStruct const opt)
1257- :
1258- FullscreenMenuBase("ui_fsmenu.jpg"),
1259-
1260-// Values for alignment and size
1261- m_vbutw (get_h() * 333 / 10000),
1262- m_butw (get_w() / 4),
1263- m_buth (get_h() * 9 / 200),
1264- m_hmargin (get_w() * 19 / 200),
1265- m_padding (10),
1266- m_space (25),
1267-
1268-// Buttons
1269- m_cancel
1270- (this, "cancel",
1271- get_w() * 41 / 80, get_h() * 19 / 20, m_butw, m_buth,
1272- g_gr->images().get("pics/but0.png"),
1273- _("Cancel"), std::string(), true, false),
1274- m_apply
1275- (this, "apply",
1276- get_w() / 4, get_h() * 19 / 20, m_butw, m_buth,
1277- g_gr->images().get("pics/but2.png"),
1278- _("Apply"), std::string(), true, false),
1279-
1280-// Title
1281- m_title
1282- (this,
1283- get_w() / 2, get_h() * 17 / 150,
1284- _("Advanced Options"), UI::Align_HCenter),
1285-
1286- // Spinboxes
1287- m_sb_dis_panel
1288- (this,
1289- m_hmargin, get_h() * 9 / 30,
1290- get_w() - 2 * m_hmargin, get_w() / 5,
1291- opt.panel_snap_distance, 0, 99,
1292- _("Distance for windows to snap to other panels:"),
1293- ngettext("pixel", "pixels", opt.panel_snap_distance)),
1294-
1295- m_sb_dis_border
1296- (this,
1297- m_hmargin, m_sb_dis_panel.get_y() + m_sb_dis_panel.get_h() + 2 * m_padding,
1298- get_w() - 2 * m_hmargin, get_w() / 5,
1299- opt.border_snap_distance, 0, 99,
1300- _("Distance for windows to snap to borders:"),
1301- ngettext("pixel", "pixels", opt.border_snap_distance)),
1302-
1303- m_transparent_chat (this, Point(m_hmargin,
1304- m_sb_dis_border.get_y() +
1305- m_sb_dis_border.get_h() + m_space),
1306- _("Show in-game chat with transparent background"),
1307- "", get_w() - 2 * m_hmargin),
1308-
1309- m_message_sound
1310- (this, Point(m_hmargin,
1311- m_transparent_chat.get_y() +
1312- m_transparent_chat.get_h() + m_padding),
1313- _("Play a sound at message arrival"),
1314- "", get_w() - 2 * m_hmargin),
1315-
1316- m_nozip (this, Point(m_hmargin,
1317- m_message_sound.get_y() +
1318- m_message_sound.get_h() + m_padding),
1319- _("Do not zip widelands data files (maps, replays and savegames)"),
1320- "", get_w() - 2 * m_hmargin),
1321-
1322- m_remove_syncstreams (this, Point(m_hmargin,
1323- m_nozip.get_y() +
1324- m_nozip.get_h() + m_padding),
1325- _("Remove Syncstream dumps on startup"),
1326- "", get_w() - 2 * m_hmargin),
1327-
1328- os(opt)
1329-{
1330- for (UI::Button* temp_button : m_sb_dis_panel.get_buttons()) {
1331- temp_button->sigclicked.connect
1332- (boost::bind
1333- (&FullscreenMenuAdvancedOptions::update_sb_dis_panel_unit,
1334- boost::ref(*this)));
1335- }
1336-
1337- for (UI::Button* temp_button : m_sb_dis_border.get_buttons()) {
1338- temp_button->sigclicked.connect
1339- (boost::bind
1340- (&FullscreenMenuAdvancedOptions::update_sb_dis_border_unit,
1341- boost::ref(*this)));
1342- }
1343-
1344- m_cancel.sigclicked.connect(boost::bind(&FullscreenMenuAdvancedOptions::clicked_back, boost::ref(*this)));
1345- m_apply.sigclicked.connect(boost::bind(&FullscreenMenuAdvancedOptions::clicked_ok, boost::ref(*this)));
1346-
1347- m_title .set_textstyle(UI::TextStyle::ui_big());
1348- m_message_sound .set_state(opt.message_sound);
1349- m_nozip .set_state(opt.nozip);
1350- m_remove_syncstreams .set_state(opt.remove_syncstreams);
1351- m_transparent_chat .set_state(opt.transparent_chat);
1352-}
1353-
1354-void FullscreenMenuAdvancedOptions::update_sb_dis_panel_unit() {
1355- m_sb_dis_panel.set_unit(ngettext("pixel", "pixels", m_sb_dis_panel.get_value()));
1356-}
1357-
1358-void FullscreenMenuAdvancedOptions::update_sb_dis_border_unit() {
1359- m_sb_dis_border.set_unit(ngettext("pixel", "pixels", m_sb_dis_border.get_value()));
1360-}
1361-
1362-OptionsCtrl::OptionsStruct FullscreenMenuAdvancedOptions::get_values() {
1363- // Write all remaining data from UI elements
1364- os.message_sound = m_message_sound.get_state();
1365- os.nozip = m_nozip.get_state();
1366- os.panel_snap_distance = m_sb_dis_panel.get_value();
1367- os.border_snap_distance = m_sb_dis_border.get_value();
1368- os.remove_syncstreams = m_remove_syncstreams.get_state();
1369- os.transparent_chat = m_transparent_chat.get_state();
1370- return os;
1371-}
1372-
1373+ // Interface options
1374+ const uint32_t res_index = resolution_list_.selection_index();
1375+ os_.xres = resolutions_[res_index].xres;
1376+ os_.yres = resolutions_[res_index].yres;
1377+ os_.fullscreen = fullscreen_.get_state();
1378+ os_.inputgrab = inputgrab_.get_state();
1379+ os_.maxfps = sb_maxfps_.get_value();
1380+
1381+ // Windows options
1382+ os_.snap_win_overlap_only = snap_win_overlap_only_.get_state();
1383+ os_.dock_windows_to_edges = dock_windows_to_edges_.get_state();
1384+ os_.panel_snap_distance = sb_dis_panel_.get_value();
1385+ os_.border_snap_distance = sb_dis_border_.get_value();
1386+
1387+ // Sound options
1388+ os_.music = music_.get_state();
1389+ os_.fx = fx_.get_state();
1390+ os_.message_sound = message_sound_.get_state();
1391+
1392+ // Saving options
1393+ os_.autosave = sb_autosave_.get_value();
1394+ os_.rolling_autosave = sb_rolling_autosave_.get_value();
1395+ os_.remove_replays = sb_remove_replays_.get_value();
1396+ os_.nozip = nozip_.get_state();
1397+ os_.remove_syncstreams = remove_syncstreams_.get_state();
1398+
1399+ // Game options
1400+ os_.auto_roadbuild_mode = auto_roadbuild_mode_.get_state();
1401+ os_.show_warea = show_workarea_preview_.get_state();
1402+ os_.transparent_chat = transparent_chat_.get_state();
1403+ os_.single_watchwin = single_watchwin_.get_state();
1404+
1405+ // Language options
1406+ if (language_list_.has_selection()) {
1407+ os_.language = language_list_.get_selected();
1408+ }
1409+
1410+ // Last tab for reloading the options menu
1411+ os_.active_tab = tabs_.active();
1412+ return os_;
1413+}
1414
1415 /**
1416 * Handles communication between window class and options
1417 */
1418 OptionsCtrl::OptionsCtrl(Section & s)
1419-: m_opt_section(s), m_opt_dialog(new FullscreenMenuOptions(options_struct()))
1420+: opt_section_(s), opt_dialog_(std::unique_ptr<FullscreenMenuOptions>(new FullscreenMenuOptions(options_struct(0))))
1421 {
1422 handle_menu();
1423 }
1424
1425-OptionsCtrl::~OptionsCtrl() {
1426- delete m_opt_dialog;
1427-}
1428-
1429 void OptionsCtrl::handle_menu()
1430 {
1431- FullscreenMenuBase::MenuTarget i = m_opt_dialog->run<FullscreenMenuBase::MenuTarget>();
1432+ FullscreenMenuBase::MenuTarget i = opt_dialog_->run<FullscreenMenuBase::MenuTarget>();
1433 if (i != FullscreenMenuBase::MenuTarget::kBack)
1434 save_options();
1435- if (i == FullscreenMenuBase::MenuTarget::kRestart) {
1436- delete m_opt_dialog;
1437- m_opt_dialog = new FullscreenMenuOptions(options_struct());
1438+ if (i == FullscreenMenuBase::MenuTarget::kApplyOptions) {
1439+ uint32_t active_tab = opt_dialog_->get_values().active_tab;
1440+ g_gr->change_resolution(opt_dialog_->get_values().xres, opt_dialog_->get_values().yres);
1441+ g_gr->set_fullscreen(opt_dialog_->get_values().fullscreen);
1442+ opt_dialog_.reset(new FullscreenMenuOptions(options_struct(active_tab)));
1443 handle_menu(); // Restart general options menu
1444 }
1445 }
1446
1447-OptionsCtrl::OptionsStruct OptionsCtrl::options_struct() {
1448+OptionsCtrl::OptionsStruct OptionsCtrl::options_struct(uint32_t active_tab) {
1449 OptionsStruct opt;
1450- opt.xres = m_opt_section.get_int("xres", DEFAULT_RESOLUTION_W);
1451- opt.yres = m_opt_section.get_int("yres", DEFAULT_RESOLUTION_H);
1452- opt.inputgrab = m_opt_section.get_bool("inputgrab", false);
1453- opt.fullscreen = m_opt_section.get_bool("fullscreen", false);
1454- opt.single_watchwin = m_opt_section.get_bool("single_watchwin", false);
1455- opt.auto_roadbuild_mode = m_opt_section.get_bool("auto_roadbuild_mode", true);
1456- opt.show_warea = m_opt_section.get_bool("workareapreview", true);
1457+ // Interface options
1458+ opt.xres = opt_section_.get_int("xres", DEFAULT_RESOLUTION_W);
1459+ opt.yres = opt_section_.get_int("yres", DEFAULT_RESOLUTION_H);
1460+ opt.fullscreen = opt_section_.get_bool("fullscreen", false);
1461+ opt.inputgrab = opt_section_.get_bool("inputgrab", false);
1462+ opt.maxfps = opt_section_.get_int("maxfps", 25);
1463+
1464+ // Windows options
1465 opt.snap_win_overlap_only =
1466- m_opt_section.get_bool("snap_windows_only_when_overlapping", false);
1467- opt.dock_windows_to_edges = m_opt_section.get_bool("dock_windows_to_edges", false);
1468- opt.language = m_opt_section.get_string("language", "");
1469- opt.music = !m_opt_section.get_bool("disable_music", false);
1470- opt.fx = !m_opt_section.get_bool("disable_fx", false);
1471- opt.autosave = m_opt_section.get_int("autosave", DEFAULT_AUTOSAVE_INTERVAL * 60);
1472- opt.rolling_autosave = m_opt_section.get_int("rolling_autosave", 5);
1473- opt.maxfps = m_opt_section.get_int("maxfps", 25);
1474-
1475- opt.message_sound = m_opt_section.get_bool("sound_at_message", true);
1476- opt.nozip = m_opt_section.get_bool("nozip", false);
1477- opt.border_snap_distance = m_opt_section.get_int("border_snap_distance", 0);
1478- opt.panel_snap_distance = m_opt_section.get_int("panel_snap_distance", 0);
1479- opt.remove_replays = m_opt_section.get_int("remove_replays", 0);
1480- opt.remove_syncstreams = m_opt_section.get_bool("remove_syncstreams", true);
1481- opt.transparent_chat = m_opt_section.get_bool("transparent_chat", true);
1482+ opt_section_.get_bool("snap_windows_only_when_overlapping", false);
1483+ opt.dock_windows_to_edges = opt_section_.get_bool("dock_windows_to_edges", false);
1484+ opt.panel_snap_distance = opt_section_.get_int("panel_snap_distance", 0);
1485+ opt.border_snap_distance = opt_section_.get_int("border_snap_distance", 0);
1486+
1487+ // Sound options
1488+ opt.music = !opt_section_.get_bool("disable_music", false);
1489+ opt.fx = !opt_section_.get_bool("disable_fx", false);
1490+ opt.message_sound = opt_section_.get_bool("sound_at_message", true);
1491+
1492+ // Saving options
1493+ opt.autosave = opt_section_.get_int("autosave", DEFAULT_AUTOSAVE_INTERVAL * 60);
1494+ opt.rolling_autosave = opt_section_.get_int("rolling_autosave", 5);
1495+ opt.remove_replays = opt_section_.get_int("remove_replays", 0);
1496+ opt.nozip = opt_section_.get_bool("nozip", false);
1497+ opt.remove_syncstreams = opt_section_.get_bool("remove_syncstreams", true);
1498+
1499+ // Game options
1500+ opt.auto_roadbuild_mode = opt_section_.get_bool("auto_roadbuild_mode", true);
1501+ opt.show_warea = opt_section_.get_bool("workareapreview", true);
1502+ opt.transparent_chat = opt_section_.get_bool("transparent_chat", true);
1503+ opt.single_watchwin = opt_section_.get_bool("single_watchwin", false);
1504+
1505+ // Language options
1506+ opt.language = opt_section_.get_string("language", "");
1507+
1508+ // Last tab for reloading the options menu
1509+ opt.active_tab = active_tab;
1510 return opt;
1511 }
1512
1513 void OptionsCtrl::save_options() {
1514- OptionsCtrl::OptionsStruct opt = m_opt_dialog->get_values();
1515- m_opt_section.set_int ("xres", opt.xres);
1516- m_opt_section.set_int ("yres", opt.yres);
1517- m_opt_section.set_bool("fullscreen", opt.fullscreen);
1518- m_opt_section.set_bool("inputgrab", opt.inputgrab);
1519- m_opt_section.set_bool("single_watchwin", opt.single_watchwin);
1520- m_opt_section.set_bool("auto_roadbuild_mode", opt.auto_roadbuild_mode);
1521- m_opt_section.set_bool("workareapreview", opt.show_warea);
1522- m_opt_section.set_bool
1523+ OptionsCtrl::OptionsStruct opt = opt_dialog_->get_values();
1524+
1525+ // Interface options
1526+ opt_section_.set_int ("xres", opt.xres);
1527+ opt_section_.set_int ("yres", opt.yres);
1528+ opt_section_.set_bool("fullscreen", opt.fullscreen);
1529+ opt_section_.set_bool("inputgrab", opt.inputgrab);
1530+ opt_section_.set_int("maxfps", opt.maxfps);
1531+
1532+ // Windows options
1533+ opt_section_.set_bool
1534 ("snap_windows_only_when_overlapping",
1535 opt.snap_win_overlap_only);
1536- m_opt_section.set_bool("dock_windows_to_edges", opt.dock_windows_to_edges);
1537- m_opt_section.set_bool("disable_music", !opt.music);
1538- m_opt_section.set_bool("disable_fx", !opt.fx);
1539- m_opt_section.set_string("language", opt.language);
1540- m_opt_section.set_int("autosave", opt.autosave * 60);
1541- m_opt_section.set_int("rolling_autosave", opt.rolling_autosave);
1542- m_opt_section.set_int("maxfps", opt.maxfps);
1543-
1544- m_opt_section.set_bool("sound_at_message", opt.message_sound);
1545- m_opt_section.set_bool("nozip", opt.nozip);
1546- m_opt_section.set_int("border_snap_distance", opt.border_snap_distance);
1547- m_opt_section.set_int("panel_snap_distance", opt.panel_snap_distance);
1548-
1549- m_opt_section.set_int("remove_replays", opt.remove_replays);
1550- m_opt_section.set_bool("remove_syncstreams", opt.remove_syncstreams);
1551- m_opt_section.set_bool("transparent_chat", opt.transparent_chat);
1552+ opt_section_.set_bool("dock_windows_to_edges", opt.dock_windows_to_edges);
1553+ opt_section_.set_int("panel_snap_distance", opt.panel_snap_distance);
1554+ opt_section_.set_int("border_snap_distance", opt.border_snap_distance);
1555+
1556+ // Sound options
1557+ opt_section_.set_bool("disable_music", !opt.music);
1558+ opt_section_.set_bool("disable_fx", !opt.fx);
1559+ opt_section_.set_bool("sound_at_message", opt.message_sound);
1560+
1561+ // Saving options
1562+ opt_section_.set_int("autosave", opt.autosave * 60);
1563+ opt_section_.set_int("rolling_autosave", opt.rolling_autosave);
1564+ opt_section_.set_int("remove_replays", opt.remove_replays);
1565+ opt_section_.set_bool("nozip", opt.nozip);
1566+ opt_section_.set_bool("remove_syncstreams", opt.remove_syncstreams);
1567+
1568+ // Game options
1569+ opt_section_.set_bool("auto_roadbuild_mode", opt.auto_roadbuild_mode);
1570+ opt_section_.set_bool("workareapreview", opt.show_warea);
1571+ opt_section_.set_bool("transparent_chat", opt.transparent_chat);
1572+ opt_section_.set_bool("single_watchwin", opt.single_watchwin);
1573+
1574+ // Language options
1575+ opt_section_.set_string("language", opt.language);
1576
1577 WLApplication::get()->set_input_grab(opt.inputgrab);
1578 i18n::set_locale(opt.language);
1579
1580=== modified file 'src/ui_fsmenu/options.h'
1581--- src/ui_fsmenu/options.h 2015-12-01 16:58:54 +0000
1582+++ src/ui_fsmenu/options.h 2016-01-01 19:10:55 +0000
1583@@ -21,6 +21,7 @@
1584 #define WL_UI_FSMENU_OPTIONS_H
1585
1586 #include <cstring>
1587+#include <memory>
1588 #include <string>
1589 #include <vector>
1590
1591@@ -31,6 +32,7 @@
1592 #include "ui_basic/multilinetextarea.h"
1593 #include "ui_basic/spinbox.h"
1594 #include "ui_basic/textarea.h"
1595+#include "ui_basic/tabpanel.h"
1596
1597 class FullscreenMenuOptions;
1598 class Section;
1599@@ -39,41 +41,52 @@
1600 class OptionsCtrl {
1601 public:
1602 struct OptionsStruct {
1603+
1604+ // Interface options
1605 int32_t xres;
1606 int32_t yres;
1607+ bool fullscreen;
1608 bool inputgrab;
1609- bool fullscreen;
1610- bool single_watchwin;
1611- bool auto_roadbuild_mode;
1612- bool show_warea;
1613+ uint32_t maxfps;
1614+
1615+ // Windows options
1616 bool snap_win_overlap_only;
1617 bool dock_windows_to_edges;
1618+ int32_t panel_snap_distance;
1619+ int32_t border_snap_distance;
1620+
1621+ // Sound options
1622 bool music;
1623 bool fx;
1624- std::string language;
1625+ bool message_sound;
1626+
1627+ // Saving options
1628 int32_t autosave; // autosave interval in minutes
1629- int32_t rolling_autosave; //number of file to use for rolling autosave
1630- uint32_t maxfps;
1631+ int32_t rolling_autosave; // number of file to use for rolling autosave
1632 uint32_t remove_replays;
1633+ bool nozip;
1634 bool remove_syncstreams;
1635+
1636+ // Game options
1637+ bool auto_roadbuild_mode;
1638+ bool show_warea;
1639 bool transparent_chat;
1640-
1641- // advanced options
1642- bool message_sound;
1643- bool nozip;
1644- std::string ui_font;
1645- int32_t border_snap_distance;
1646- int32_t panel_snap_distance;
1647+ bool single_watchwin;
1648+
1649+ // Language options
1650+ std::string language;
1651+
1652+ // Last tab for reloading the options menu
1653+ uint32_t active_tab;
1654 };
1655
1656 OptionsCtrl(Section &);
1657- ~OptionsCtrl();
1658 void handle_menu();
1659- OptionsCtrl::OptionsStruct options_struct();
1660+ OptionsCtrl::OptionsStruct options_struct(uint32_t active_tab);
1661 void save_options();
1662 private:
1663- Section & m_opt_section;
1664- FullscreenMenuOptions * m_opt_dialog;
1665+ Section & opt_section_;
1666+ std::unique_ptr<FullscreenMenuOptions> opt_dialog_;
1667 };
1668
1669 /**
1670@@ -86,47 +99,75 @@
1671 OptionsCtrl::OptionsStruct get_values();
1672
1673 private:
1674- uint32_t const m_vbutw;
1675- uint32_t const m_butw;
1676- uint32_t const m_buth;
1677- uint32_t const m_hmargin;
1678- uint32_t const m_padding;
1679- uint32_t const m_space;
1680- uint32_t const m_offset_first_group;
1681- uint32_t const m_offset_second_group;
1682-
1683- UI::Button m_advanced_options, m_cancel, m_apply;
1684-
1685- UI::Textarea m_title;
1686- UI::Textarea m_label_resolution;
1687- UI::Listselect<void *> m_reslist;
1688- UI::Checkbox m_fullscreen;
1689- UI::Checkbox m_inputgrab;
1690- UI::SpinBox m_sb_maxfps;
1691-
1692- UI::Textarea m_label_language;
1693- UI::Listselect<std::string> m_language_list;
1694- UI::Checkbox m_music;
1695- UI::Checkbox m_fx;
1696-
1697- UI::Textarea m_label_game_options;
1698- UI::Checkbox m_single_watchwin;
1699- UI::Checkbox m_auto_roadbuild_mode;
1700- UI::Checkbox m_show_workarea_preview;
1701- UI::Checkbox m_snap_win_overlap_only;
1702- UI::Checkbox m_dock_windows_to_edges;
1703- UI::SpinBox m_sb_autosave;
1704- UI::SpinBox m_sb_remove_replays;
1705-
1706- OptionsCtrl::OptionsStruct os;
1707-
1708 void update_sb_autosave_unit();
1709 void update_sb_remove_replays_unit();
1710- void advanced_options();
1711+ void update_sb_dis_panel_unit();
1712+ void update_sb_dis_border_unit();
1713
1714 // Fills the language selection list
1715 void add_languages_to_list(const std::string& current_locale);
1716
1717+ // Saves the options and reloads the active tab
1718+ void clicked_apply();
1719+
1720+ uint32_t const butw_;
1721+ uint32_t const buth_;
1722+ uint32_t const hmargin_;
1723+ uint32_t const padding_;
1724+ uint32_t const space_;
1725+ uint32_t const tab_panel_width_;
1726+ uint32_t const column_width_;
1727+ uint32_t const tab_panel_y_;
1728+
1729+ UI::Textarea title_;
1730+ UI::Button cancel_, apply_, ok_;
1731+
1732+ // UI elements
1733+ UI::TabPanel tabs_;
1734+ UI::Box box_interface_;
1735+ UI::Box box_windows_;
1736+ UI::Box box_sound_;
1737+ UI::Box box_saving_;
1738+ UI::Box box_game_;
1739+ UI::Box box_language_;
1740+
1741+ // Interface options
1742+ UI::Textarea label_resolution_;
1743+ UI::Listselect<void *> resolution_list_;
1744+ UI::Checkbox fullscreen_;
1745+ UI::Checkbox inputgrab_;
1746+ UI::SpinBox sb_maxfps_;
1747+
1748+ // Windows options
1749+ UI::Checkbox snap_win_overlap_only_;
1750+ UI::Checkbox dock_windows_to_edges_;
1751+ UI::SpinBox sb_dis_panel_;
1752+ UI::SpinBox sb_dis_border_;
1753+
1754+ // Sound options
1755+ UI::Checkbox music_;
1756+ UI::Checkbox fx_;
1757+ UI::Checkbox message_sound_;
1758+
1759+ // Saving options
1760+ UI::SpinBox sb_autosave_;
1761+ UI::SpinBox sb_rolling_autosave_;
1762+ UI::SpinBox sb_remove_replays_;
1763+ UI::Checkbox nozip_;
1764+ UI::Checkbox remove_syncstreams_;
1765+
1766+ // Game options
1767+ UI::Checkbox auto_roadbuild_mode_;
1768+ UI::Checkbox show_workarea_preview_;
1769+ UI::Checkbox transparent_chat_;
1770+ UI::Checkbox single_watchwin_;
1771+
1772+ // Language options
1773+ UI::Textarea label_language_;
1774+ UI::Listselect<std::string> language_list_;
1775+
1776+ OptionsCtrl::OptionsStruct os_;
1777+
1778 class ScreenResolution {
1779 public:
1780 int32_t xres;
1781@@ -135,39 +176,7 @@
1782 };
1783
1784 /// All supported screen resolutions.
1785- std::vector<ScreenResolution> m_resolutions;
1786-};
1787-
1788-/**
1789- * Fullscreen Optionsmenu. A modal optionsmenu
1790- */
1791-
1792-class FullscreenMenuAdvancedOptions : public FullscreenMenuBase {
1793-public:
1794- FullscreenMenuAdvancedOptions(OptionsCtrl::OptionsStruct opt);
1795- OptionsCtrl::OptionsStruct get_values();
1796-
1797-private:
1798- void update_sb_dis_panel_unit();
1799- void update_sb_dis_border_unit();
1800-
1801- uint32_t const m_vbutw;
1802- uint32_t const m_butw;
1803- uint32_t const m_buth;
1804- uint32_t const m_hmargin;
1805- uint32_t const m_padding;
1806- uint32_t const m_space;
1807-
1808- UI::Button m_cancel, m_apply;
1809- UI::Textarea m_title;
1810-
1811- UI::SpinBox m_sb_dis_panel, m_sb_dis_border;
1812- UI::Checkbox m_transparent_chat;
1813- UI::Checkbox m_message_sound;
1814- UI::Checkbox m_nozip;
1815- UI::Checkbox m_remove_syncstreams;
1816-
1817- OptionsCtrl::OptionsStruct os;
1818+ std::vector<ScreenResolution> resolutions_;
1819 };
1820
1821 #endif // end of include guard: WL_UI_FSMENU_OPTIONS_H

Subscribers

People subscribed via source and target branches

to status/vote changes: