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

Proposed by GunChleoc
Status: Merged
Approved by: kaputtnik
Approved revision: no longer in the source branch.
Merged at revision: 7662
Proposed branch: lp:~widelands-dev/widelands/spinbox
Merge into: lp:widelands
Diff against target: 376 lines (+94/-69)
6 files modified
src/ui_basic/spinbox.cc (+46/-20)
src/ui_basic/spinbox.h (+5/-1)
src/ui_basic/textarea.cc (+10/-1)
src/ui_basic/textarea.h (+8/-1)
src/ui_fsmenu/options.cc (+25/-42)
src/ui_fsmenu/options.h (+0/-4)
To merge this branch: bzr merge lp:~widelands-dev/widelands/spinbox
Reviewer Review Type Date Requested Status
Widelands Developers Pending
Review via email: mp+279153@code.launchpad.net

Description of the change

Cleaned up buggy text positioning and width for spinboxes. Also, spinboxes now own their labels, just like checkboxes.

Labels will automatically take up more than 1 line if needed - we don't have a test case for this right now, but it safeguards us against text overflow with translations.

For testing: Spinboxes are only used in the Options window so far.

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

Code looks good to me as far as I can tell, please test it somebody...

Revision history for this message
kaputtnik (franku) wrote :

I've tested the option window and the spin boxes with resolution 800x600 and 1024x768.

Looks good :-)

Revision history for this message
GunChleoc (gunchleoc) wrote :

When approving, please use the "Review" dropdown on the bottom. Setting it on top hid this from view for some nebulous reason.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/ui_basic/spinbox.cc'
2--- src/ui_basic/spinbox.cc 2015-10-23 10:17:13 +0000
3+++ src/ui_basic/spinbox.cc 2015-12-05 17:19:12 +0000
4@@ -29,6 +29,7 @@
5 #include "graphic/text/font_set.h"
6 #include "graphic/text_constants.h"
7 #include "ui_basic/button.h"
8+#include "ui_basic/multilinetextarea.h"
9 #include "ui_basic/textarea.h"
10
11 namespace UI {
12@@ -76,13 +77,14 @@
13 */
14 SpinBox::SpinBox
15 (Panel * const parent,
16- const int32_t x, const int32_t y, const uint32_t w,
17+ const int32_t x, const int32_t y, const uint32_t w, const uint32_t unit_w,
18 int32_t const startval, int32_t const minval, int32_t const maxval,
19+ const std::string& label_text,
20 const std::string& unit,
21 const Image* background,
22 bool const big)
23 :
24- Panel(parent, x, y, w, 0),
25+ Panel(parent, x, y, std::max(w, unit_w), 0),
26 big_(big),
27 sbi_(new SpinBoxImpl)
28 {
29@@ -93,28 +95,52 @@
30 sbi_->background = background;
31
32 uint32_t padding = 2;
33-
34+ uint32_t actual_w = std::max(w, unit_w);
35+ uint32_t no_padding = (big_ ? 6 : 4);
36 uint32_t texth = UI::g_fh1->render(as_uifont("."))->height();
37- box_ = new UI::Box(this, 0, 0, UI::Box::Horizontal, w, texth, padding);
38+ uint32_t buttonh = 20;
39+
40+ // 40 is an ad hoc width estimate for the MultilineTextarea scrollbar + a bit of text.
41+ if (!label_text.empty() && (w + padding) <= unit_w - 40) {
42+ throw wexception(
43+ "SpinBox: Overall width %d must be bigger than unit width %d + %d * %d + 40 for padding",
44+ w, unit_w, no_padding, padding);
45+ }
46
47 #ifndef NDEBUG // only in debug builds
48- if (w < (big_ ? 7 * texth : 3 * texth)) {
49+ if (unit_w < (big_ ? 7 * buttonh : 3 * buttonh)) {
50 throw wexception("Not enough space to draw spinbox. Width %d is smaller than required width %d",
51- w, (big_ ? 7 * texth : 3 * texth));
52+ unit_w, (big_ ? 7 * buttonh : 3 * buttonh));
53 }
54 #endif
55
56+ box_ = new UI::Box(this, 0, 0, UI::Box::Horizontal, actual_w, texth, padding);
57+
58+ // Find out how much height we need for the label. We give it 6 rows maximum.
59+ const Image* rendered_text = UI::g_fh1->render(as_uifont(label_text));
60+ uint32_t available_width = w - unit_w - no_padding * padding;
61+ uint32_t extra_rows =
62+ available_width > 0 ?
63+ std::min(static_cast<int>(rendered_text->width() / available_width), 6) : 0;
64+
65+ UI::MultilineTextarea* label = new UI::MultilineTextarea(box_, 0, 0, available_width,
66+ texth * (extra_rows + 1), label_text);
67+
68+ box_->add(label, UI::Box::AlignCenter);
69+
70+ sbi_->text = new UI::Textarea(box_, "", Align_Center);
71+
72 sbi_->button_minus =
73 new Button
74 (box_, "-",
75- 0, 0, texth, texth,
76+ 0, 0, buttonh, buttonh,
77 sbi_->background,
78 g_gr->images().get(big_? "pics/scrollbar_left.png" : "pics/scrollbar_down.png"),
79 _("Decrease the value"));
80 sbi_->button_plus =
81 new Button
82 (box_, "+",
83- 0, 0, texth, texth,
84+ 0, 0, buttonh, buttonh,
85 sbi_->background,
86 g_gr->images().get(big_? "pics/scrollbar_right.png" : "pics/scrollbar_up.png"),
87 _("Increase the value"));
88@@ -123,14 +149,14 @@
89 sbi_->button_ten_minus =
90 new Button
91 (box_, "--",
92- 0, 0, 2 * texth, texth,
93+ 0, 0, 2 * buttonh, buttonh,
94 sbi_->background,
95 g_gr->images().get("pics/scrollbar_left_fast.png"),
96 _("Decrease the value by 10"));
97 sbi_->button_ten_plus =
98 new Button
99 (box_, "++",
100- 0, 0, 2 * texth, texth,
101+ 0, 0, 2 * buttonh, buttonh,
102 sbi_->background,
103 g_gr->images().get("pics/scrollbar_right_fast.png"),
104 _("Increase the value by 10"));
105@@ -142,11 +168,10 @@
106 buttons_.push_back(sbi_->button_ten_minus);
107 buttons_.push_back(sbi_->button_ten_plus);
108
109- sbi_->text =
110- new UI::Textarea(
111- box_, 0, 0,
112- w - 2 * sbi_->button_ten_plus->get_w() - 2 * sbi_->button_minus->get_w() - 4 * padding, texth,
113- "", Align_Center);
114+ sbi_->text->set_fixed_width(unit_w
115+ - 2 * sbi_->button_ten_plus->get_w()
116+ - 2 * sbi_->button_minus->get_w()
117+ - 4 * padding);
118
119 box_->add(sbi_->button_ten_minus, UI::Box::AlignCenter);
120 box_->add(sbi_->button_minus, UI::Box::AlignCenter);
121@@ -154,9 +179,8 @@
122 box_->add(sbi_->button_plus, UI::Box::AlignCenter);
123 box_->add(sbi_->button_ten_plus, UI::Box::AlignCenter);
124 } else {
125- sbi_->text = new UI::Textarea(box_, 0, 0,
126- w - 2 * sbi_->button_minus->get_w() - 2 * padding, texth,
127- "", Align_Center);
128+ sbi_->text->set_fixed_width(unit_w - 2 * sbi_->button_minus->get_w() - 2 * padding);
129+
130 box_->add(sbi_->button_minus, UI::Box::AlignCenter);
131 box_->add(sbi_->text, UI::Box::AlignCenter);
132 box_->add(sbi_->button_plus, UI::Box::AlignCenter);
133@@ -168,8 +192,10 @@
134 sbi_->button_minus->set_repeating(true);
135 buttons_.push_back(sbi_->button_minus);
136 buttons_.push_back(sbi_->button_plus);
137- box_->set_size(w, texth);
138- set_size(w, texth);
139+ uint32_t box_height = std::max(label->get_h(), static_cast<int32_t>(buttonh));
140+ box_->set_size(actual_w, box_height);
141+ set_desired_size(actual_w, box_height);
142+ set_size(actual_w, box_height);
143 update();
144 }
145
146
147=== modified file 'src/ui_basic/spinbox.h'
148--- src/ui_basic/spinbox.h 2015-10-23 10:17:13 +0000
149+++ src/ui_basic/spinbox.h 2015-12-05 17:19:12 +0000
150@@ -35,12 +35,16 @@
151 struct TextStyle;
152
153 /// A spinbox is an UI element for setting the integer value of a variable.
154+/// w is the overall width of the SpinBox and must be wide enough to fit 2 labels and the buttons.
155+/// unit_w is the width alotted for all buttons and the text between them (the actual spinbox).
156+/// label_text is a text that precedes the actual spinbox.
157 class SpinBox : public Panel {
158 public:
159 SpinBox
160 (Panel*,
161- int32_t x, int32_t y, uint32_t w,
162+ int32_t x, int32_t y, uint32_t w, uint32_t unit_w,
163 int32_t startval, int32_t minval, int32_t maxval,
164+ const std::string& label_text = std::string(),
165 const std::string& unit = std::string(),
166 const Image* buttonbackground = g_gr->images().get("pics/but3.png"),
167 bool big = false);
168
169=== modified file 'src/ui_basic/textarea.cc'
170--- src/ui_basic/textarea.cc 2015-11-22 08:20:56 +0000
171+++ src/ui_basic/textarea.cc 2015-12-05 17:19:12 +0000
172@@ -80,6 +80,7 @@
173 */
174 void Textarea::init()
175 {
176+ fixed_width_ = 0;
177 set_handle_mouse(false);
178 set_thinks(false);
179 set_textstyle(UI::TextStyle::ui_small());
180@@ -147,6 +148,14 @@
181
182
183 /**
184+ * Set the fixed width. The Textarea will still collapse, but then restore this width when expand() is called.
185+ */
186+void Textarea::set_fixed_width(uint32_t w) {
187+ fixed_width_ = w;
188+}
189+
190+
191+/**
192 * Redraw the Textarea
193 */
194 void Textarea::draw(RenderTarget & dst)
195@@ -223,7 +232,7 @@
196 uint16_t h = 0;
197
198 if (rendered_text_) {
199- w = rendered_text_->width();
200+ w = fixed_width_ > 0 ? fixed_width_ : rendered_text_->width();
201 h = rendered_text_->height();
202 // We want empty textareas to have height
203 if (m_text.empty()) {
204
205=== modified file 'src/ui_basic/textarea.h'
206--- src/ui_basic/textarea.h 2015-11-22 08:20:56 +0000
207+++ src/ui_basic/textarea.h 2015-12-05 17:19:12 +0000
208@@ -68,7 +68,13 @@
209 const std::string & text = std::string(),
210 Align align = Align_Left);
211
212- void set_fixed_size(const std::string & text);
213+ /**
214+ * If fixed_width > 0, the Textarea will not change its width.
215+ * Use this if you need a Textarea that keeps changing its contents, but you don't want the
216+ * surrounding elements to shift, e.g. in a Box.
217+ */
218+ void set_fixed_width(uint32_t w);
219+
220 void set_text(const std::string &);
221 const std::string& get_text();
222
223@@ -99,6 +105,7 @@
224 const Image* rendered_text_;
225 Align m_align;
226 UI::TextStyle m_textstyle;
227+ uint32_t fixed_width_;
228 };
229
230 }
231
232=== modified file 'src/ui_fsmenu/options.cc'
233--- src/ui_fsmenu/options.cc 2015-10-10 20:45:27 +0000
234+++ src/ui_fsmenu/options.cc 2015-12-05 17:19:12 +0000
235@@ -150,16 +150,12 @@
236 m_fullscreen.get_y() +
237 m_fullscreen.get_h() + m_padding),
238 _("Grab Input")),
239- m_label_maxfps
240+ m_sb_maxfps
241 (this,
242 m_hmargin,
243 m_inputgrab.get_y() + m_inputgrab.get_h() + m_padding,
244- m_reslist.get_w() - 105, m_inputgrab.get_h(),
245- _("Maximum FPS:"), UI::Align_VCenter),
246- m_sb_maxfps
247- (this,
248- m_hmargin + m_reslist.get_w() - 105, m_label_maxfps.get_y(), 105,
249- opt.maxfps, 0, 99, ""),
250+ m_reslist.get_w(), 105,
251+ opt.maxfps, 0, 99, _("Maximum FPS:"), ""),
252
253
254 // First options block 'general options', second column
255@@ -216,38 +212,29 @@
256 _("Dock windows to edges")),
257 m_sb_autosave
258 (this,
259- get_w() - m_hmargin - 240,
260+ m_hmargin,
261 m_dock_windows_to_edges.get_y() + m_dock_windows_to_edges.get_h() + m_padding,
262+ get_w() - 2 * m_hmargin,
263 240,
264+ opt.autosave / 60, 0, 100,
265+ _("Save game automatically every"),
266 /** TRANSLATORS: Options: Save game automatically every: */
267 /** TRANSLATORS: This will have a number added in front of it */
268- opt.autosave / 60, 0, 100, ngettext("minute", "minutes", opt.autosave / 60),
269+ ngettext("minute", "minutes", opt.autosave / 60),
270 g_gr->images().get("pics/but3.png"), true),
271- m_label_autosave
272- (this,
273- m_dock_windows_to_edges.get_x(),
274- m_sb_autosave.get_y(),
275- get_w() - m_sb_autosave.get_w() - 2 * m_hmargin,
276- m_dock_windows_to_edges.get_h(),
277- _("Save game automatically every"), UI::Align_VCenter),
278
279 m_sb_remove_replays
280 (this,
281- get_w() - m_hmargin - 240,
282+ m_hmargin,
283 m_sb_autosave.get_y() + m_sb_autosave.get_h() + m_padding,
284+ get_w() - 2 * m_hmargin,
285 240,
286+ opt.remove_replays, 0, 365,
287+ _("Remove replays older than:"),
288 /** TRANSLATORS: Options: Remove Replays older than: */
289 /** TRANSLATORS: This will have a number added in front of it */
290- opt.remove_replays, 0, 365, ngettext("day", "days", opt.remove_replays),
291+ ngettext("day", "days", opt.remove_replays),
292 g_gr->images().get("pics/but3.png"), true),
293- m_label_remove_replays
294- (this,
295- m_label_autosave.get_x(),
296- m_sb_remove_replays.get_y(),
297- get_w() - m_sb_remove_replays.get_w() - 2 * m_hmargin,
298- m_dock_windows_to_edges.get_h(),
299- _("Remove replays older than:"), UI::Align_VCenter),
300-
301 os(opt)
302 {
303 m_advanced_options.sigclicked.connect
304@@ -469,30 +456,26 @@
305 get_w() / 2, get_h() * 17 / 150,
306 _("Advanced Options"), UI::Align_HCenter),
307
308-// First options block
309- m_label_snap_dis_panel
310- (this,
311- m_hmargin, get_h() * 9 / 30,
312- _("Distance for windows to snap to other panels:"), UI::Align_VCenter),
313- m_label_snap_dis_border
314- (this,
315- m_hmargin, m_label_snap_dis_panel.get_y() + m_label_snap_dis_panel.get_h() + 2 * m_padding,
316- _("Distance for windows to snap to borders:"), UI::Align_VCenter),
317-
318 // Spinboxes
319 m_sb_dis_panel
320 (this,
321- get_w() - m_hmargin - (get_w() / 5), m_label_snap_dis_panel.get_y(), get_w() / 5,
322- opt.panel_snap_distance, 0, 99, ngettext("pixel", "pixels", opt.panel_snap_distance)),
323+ m_hmargin, get_h() * 9 / 30,
324+ get_w() - 2 * m_hmargin, get_w() / 5,
325+ opt.panel_snap_distance, 0, 99,
326+ _("Distance for windows to snap to other panels:"),
327+ ngettext("pixel", "pixels", opt.panel_snap_distance)),
328
329 m_sb_dis_border
330 (this,
331- get_w() - m_hmargin - (get_w() / 5), m_label_snap_dis_border.get_y(), get_w() / 5,
332- opt.border_snap_distance, 0, 99, ngettext("pixel", "pixels", opt.border_snap_distance)),
333+ m_hmargin, m_sb_dis_panel.get_y() + m_sb_dis_panel.get_h() + 2 * m_padding,
334+ get_w() - 2 * m_hmargin, get_w() / 5,
335+ opt.border_snap_distance, 0, 99,
336+ _("Distance for windows to snap to borders:"),
337+ ngettext("pixel", "pixels", opt.border_snap_distance)),
338
339 m_transparent_chat (this, Point(m_hmargin,
340- m_label_snap_dis_border.get_y() +
341- m_label_snap_dis_border.get_h() + m_space),
342+ m_sb_dis_border.get_y() +
343+ m_sb_dis_border.get_h() + m_space),
344 _("Show in-game chat with transparent background"),
345 "", get_w() - 2 * m_hmargin),
346
347
348=== modified file 'src/ui_fsmenu/options.h'
349--- src/ui_fsmenu/options.h 2015-10-09 18:06:41 +0000
350+++ src/ui_fsmenu/options.h 2015-12-05 17:19:12 +0000
351@@ -102,7 +102,6 @@
352 UI::Listselect<void *> m_reslist;
353 UI::Checkbox m_fullscreen;
354 UI::Checkbox m_inputgrab;
355- UI::Textarea m_label_maxfps;
356 UI::SpinBox m_sb_maxfps;
357
358 UI::Textarea m_label_language;
359@@ -117,9 +116,7 @@
360 UI::Checkbox m_snap_win_overlap_only;
361 UI::Checkbox m_dock_windows_to_edges;
362 UI::SpinBox m_sb_autosave;
363- UI::Textarea m_label_autosave;
364 UI::SpinBox m_sb_remove_replays;
365- UI::Textarea m_label_remove_replays;
366
367 OptionsCtrl::OptionsStruct os;
368
369@@ -164,7 +161,6 @@
370 UI::Button m_cancel, m_apply;
371 UI::Textarea m_title;
372
373- UI::Textarea m_label_snap_dis_panel, m_label_snap_dis_border;
374 UI::SpinBox m_sb_dis_panel, m_sb_dis_border;
375 UI::Checkbox m_transparent_chat;
376 UI::Checkbox m_message_sound;

Subscribers

People subscribed via source and target branches

to status/vote changes: