Merge lp:~rafalcieslak256/millenniumduel/containers into lp:millenniumduel
- containers
- Merge into trunk
Status: | Merged |
---|---|
Merged at revision: | 10 |
Proposed branch: | lp:~rafalcieslak256/millenniumduel/containers |
Merge into: | lp:millenniumduel |
Diff against target: |
765 lines (+408/-108) 18 files modified
src/Box.cpp (+59/-0) src/Box.hpp (+47/-0) src/Fixed.cpp (+28/-30) src/Fixed.hpp (+17/-16) src/HBox.cpp (+61/-0) src/HBox.hpp (+11/-0) src/VBox.cpp (+60/-0) src/VBox.hpp (+11/-0) src/build (+1/-1) src/button.cpp (+10/-4) src/button.hpp (+5/-2) src/display.cpp (+9/-10) src/display.hpp (+6/-4) src/drawable.cpp (+17/-7) src/drawable.hpp (+33/-11) src/label.cpp (+11/-4) src/label.hpp (+4/-1) src/main.cpp (+18/-18) |
To merge this branch: | bzr merge lp:~rafalcieslak256/millenniumduel/containers |
Related bugs: | |
Related blueprints: |
Container widgets
(Medium)
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Adam Malinowski | Approve | ||
Jakub Sękowski | Approve | ||
Review via email:
|
Commit message
Description of the change
This branch implements Container widgets (namely a custom VBox and a HBox).
[https:/
These widgets are meant to spread evenly widgets aligned horizontally or vertically.
They are kind of similar to GTK's boxes, but one should not assume any similarities.
This branch also significantly changes the way draw() is used. It is now called with a set of 4 values, representing coordinates of a rectangular area where the widget should draw itself.
This way all widgets can be drawn in variety of sizes.
All Drawables can also provide the minimal size they need for drawing (for example, a button cannot be too thin or its text will not fit). These can be learned by calling GetMinimalHeight and GetMinimalWidth.
Both boxes are used by appending widgets with Add(drawable). By default all items are shrinked to minimum, except for those that are added with BOX_EXPAND as a second argument to Add, these will be spread evenly.
One can set the space between boxes with SetSpacing, as well as the margin around the Box with SetMargin (both default to 0).
Of course, Boxes are also a Drawable, and therefore can be nested freely.
Another change introduced by this branch is that a View widget (renamed to Fixed) is now a Drawable.
The Display class requires now a Drawable to be the topmost widget, it does not have to be a Fixed (View).
The example in main() sets a VBox as the main menu, shrinking and expanding some of the buttons. The additional menu is left as it was, as a Fixed.
NOTE: This code does not fix bug #1198640.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Jakub Sękowski (sequba) wrote : | # |
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Rafał Cieślak (rafalcieslak256) wrote : | # |
My idea is that one may wish to insert a widget *between* some that already exist. This might be done using a vector too, but inserting items there may look more tricky, as the indexes might change in the meantime. The solution I implemented binds a (potentially) number to each item, so that one can freely insert the items wherever wanted.
Also please note that the struct BoxEntry would still be needed, as it also keeps info about the current size of the widget, the Drawables themselves do not store it, and it has to be recalculated from time to time to ensure proper widget resizing.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Jakub Sękowski (sequba) wrote : | # |
In my opinion, that's exactly what we need.
I'm still not fully convinced of set and that weird attribute "order", but it may indeed be more convenient to use it this way.
Approve.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Adam Malinowski (adayah) wrote : | # |
I love the code you wrote. It's elegant and very powerful, and is going to save us a lot of effort.
However, I discovered a minor bug. When examined carefully, it turns out, that buttons' click sensivity areas are a bit offset upwards with respect to their drawings.
I think I can tell which part of code needs a correction. In functions HBox::on_clicked and VBox::on_clicked, the 'sum' variable should be initialized with:
int sum = margin;
instead of actual:
int sum = 0;
Very nice job!
- 22. By Rafał Cieślak
-
Fixed click detection allignment
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Adam Malinowski (adayah) : | # |
Preview Diff
1 | === added file 'src/Box.cpp' |
2 | --- src/Box.cpp 1970-01-01 00:00:00 +0000 |
3 | +++ src/Box.cpp 2013-07-23 20:39:00 +0000 |
4 | @@ -0,0 +1,59 @@ |
5 | +#include "Box.hpp" |
6 | + |
7 | +Box::Box(){ |
8 | + spacing = 0; |
9 | + margin = 0; |
10 | +} |
11 | + |
12 | +void Box::_RecalculateSizes(int total, int (Drawable::*size_func)()){ |
13 | + if(children.size() == 0) return; |
14 | + |
15 | + int shrinked_sum = 0; |
16 | + int expand_count = 0; |
17 | + |
18 | + for(auto &i : children){ |
19 | + if(i.mode == BOX_SHRINK){ |
20 | + int h = ((i.item).*size_func)(); //use the size_func to get minimal width/height |
21 | + i.size = h; |
22 | + shrinked_sum += h; |
23 | + }else if(i.mode == BOX_EXPAND){ |
24 | + expand_count++; |
25 | + } |
26 | + shrinked_sum += spacing; |
27 | + } |
28 | + if (shrinked_sum > 0) shrinked_sum -= spacing; |
29 | + |
30 | + if(expand_count > 0){ |
31 | + int rest = total - 2*margin - shrinked_sum; |
32 | + int expand_size = rest / expand_count; |
33 | + int last_expand_size = rest - (expand_size * expand_count) + expand_size; |
34 | + |
35 | + if(expand_size < 0) expand_size = 0; |
36 | + if(last_expand_size < 0) last_expand_size = 0; |
37 | + |
38 | + for(auto &i : children){ |
39 | + if(i.mode == BOX_EXPAND){ |
40 | + if(expand_count != 1){ //this is not the last expanding item |
41 | + i.size = expand_size; |
42 | + }else{ |
43 | + i.size = last_expand_size; |
44 | + } |
45 | + expand_count--; |
46 | + } |
47 | + } |
48 | + } |
49 | +} |
50 | + |
51 | +void Box::Add(Drawable& item, int position, BoxPackingMode mode){ |
52 | + BoxEntry be(item); |
53 | + be.order = position; |
54 | + be.mode = mode; |
55 | + children.insert(be); |
56 | +} |
57 | + |
58 | +void Box::SetSpacing(int s){ |
59 | + spacing = s; |
60 | +} |
61 | +void Box::SetMargin(int m){ |
62 | + margin = m; |
63 | +} |
64 | |
65 | === added file 'src/Box.hpp' |
66 | --- src/Box.hpp 1970-01-01 00:00:00 +0000 |
67 | +++ src/Box.hpp 2013-07-23 20:39:00 +0000 |
68 | @@ -0,0 +1,47 @@ |
69 | +#include "drawable.hpp" |
70 | +#include <string> |
71 | +#include <set> |
72 | + |
73 | +enum BoxPackingMode{ |
74 | + BOX_SHRINK = 0, |
75 | + BOX_EXPAND = 1 |
76 | +}; |
77 | + |
78 | +class Box : public Drawable{ |
79 | +protected: |
80 | + Box(); |
81 | + |
82 | +public: |
83 | + void Add(Drawable& item, int position, BoxPackingMode mode = BOX_SHRINK); |
84 | + |
85 | + void SetSpacing(int spacing); |
86 | + void SetMargin(int margin); |
87 | + |
88 | + virtual void draw(SDrawArea a) = 0; |
89 | + |
90 | + virtual int GetMinimalHeight() = 0; |
91 | + virtual int GetMinimalWidth () = 0; |
92 | + |
93 | + virtual void on_clicked(SCoordinates p) = 0; |
94 | +protected: |
95 | + |
96 | + struct BoxEntry{ |
97 | + BoxEntry(Drawable& i) : item(i) {}; |
98 | + int order; // Used to determine item's position within the container |
99 | + BoxPackingMode mode; |
100 | + mutable int size; // size in px for this item, used temporarily for calculations |
101 | + Drawable& item; |
102 | + }; |
103 | + struct BoxEntryComparator{ |
104 | + bool operator()(const BoxEntry& x,const BoxEntry& y) const {return x.order < y.order;} |
105 | + }; |
106 | + |
107 | + /* This set contains all widgets contained within this container. */ |
108 | + std::set< BoxEntry, BoxEntryComparator> children; |
109 | + |
110 | + int spacing; |
111 | + int margin; |
112 | + int current_width, current_height; |
113 | + |
114 | + void _RecalculateSizes(int total, int (Drawable::*size_func)()); |
115 | +}; |
116 | |
117 | === renamed file 'src/view.cpp' => 'src/Fixed.cpp' |
118 | --- src/view.cpp 2013-07-07 08:48:44 +0000 |
119 | +++ src/Fixed.cpp 2013-07-23 20:39:00 +0000 |
120 | @@ -1,39 +1,37 @@ |
121 | -#include "view.hpp" |
122 | -#include <allegro5/allegro.h> |
123 | - |
124 | -void View::draw(){ |
125 | - al_clear_to_color(al_map_rgb(0,0,0)); |
126 | - |
127 | - ALLEGRO_TRANSFORM transform; |
128 | +#include "Fixed.hpp" |
129 | + |
130 | +Fixed::Fixed(int w, int h) : width(w), height(h){ |
131 | +} |
132 | + |
133 | +void Fixed::draw(SDrawArea a){ |
134 | for(auto q : items){ |
135 | Drawable* x = q.first; |
136 | - Coordinates c = q.second; |
137 | - al_identity_transform(&transform); |
138 | - al_translate_transform(&transform, c.x, c.y); |
139 | - al_use_transform(&transform); |
140 | + SCoordinates c = q.second; |
141 | |
142 | - x->draw(); |
143 | + int width = x->GetMinimalWidth (); |
144 | + int height = x->GetMinimalHeight(); |
145 | + |
146 | + x->draw(SDrawArea(a.x + c.x, a.y + c.y, width, height)); |
147 | } |
148 | - |
149 | - al_identity_transform(&transform); |
150 | - al_use_transform(&transform); |
151 | - |
152 | -} |
153 | - |
154 | -void View::add_item(Drawable* d, Coordinates c){ |
155 | - items[d] = c; |
156 | -} |
157 | - |
158 | -void View::remove_item(Drawable *d){ |
159 | - items.erase(d); |
160 | -} |
161 | - |
162 | -void View::on_clicked(int x, int y){ |
163 | +} |
164 | + |
165 | +void Fixed::add_item(Drawable& d, SCoordinates c){ |
166 | + items[&d] = c; |
167 | +} |
168 | + |
169 | +void Fixed::remove_item(Drawable& d){ |
170 | + items.erase(&d); |
171 | +} |
172 | + |
173 | +void Fixed::on_clicked(SCoordinates p){ |
174 | for(auto q : items){ |
175 | Drawable* d = q.first; |
176 | - Coordinates c = q.second; |
177 | - if(c.x <= x && c.y <= y && c.x+d->width >= x && c.y+d->height >= y){ |
178 | - d->on_clicked(); |
179 | + SCoordinates c = q.second; |
180 | + if(c.x <= p.x && c.y <= p.y && c.x+d->GetMinimalWidth() >= p.x && c.y+d->GetMinimalHeight() >= p.y){ |
181 | + d->on_clicked(SCoordinates(p.x - c.x, p.y - c.y)); |
182 | } |
183 | } |
184 | } |
185 | + |
186 | +int Fixed::GetMinimalHeight(){ return height; } |
187 | +int Fixed::GetMinimalWidth() { return width; } |
188 | |
189 | === renamed file 'src/view.hpp' => 'src/Fixed.hpp' |
190 | --- src/view.hpp 2013-07-07 08:48:44 +0000 |
191 | +++ src/Fixed.hpp 2013-07-23 20:39:00 +0000 |
192 | @@ -1,23 +1,24 @@ |
193 | -#ifndef __VIEW_HPP__ |
194 | -#define __VIEW_HPP__ |
195 | +#ifndef __FIXED_HPP__ |
196 | +#define __FIXED_HPP__ |
197 | |
198 | #include "drawable.hpp" |
199 | #include <map> |
200 | |
201 | -struct Coordinates{ |
202 | - int x; |
203 | - int y; |
204 | - Coordinates(int _x, int _y) : x(_x), y(_y) {} |
205 | - Coordinates() : x(0), y(0) {} |
206 | -}; |
207 | - |
208 | -class View{ |
209 | +class Fixed : public Drawable{ |
210 | public: |
211 | - std::map<Drawable*,Coordinates> items; |
212 | - void draw(); |
213 | - void add_item(Drawable* d, Coordinates c); |
214 | - void remove_item(Drawable * d); |
215 | - void on_clicked(int x, int y); |
216 | + Fixed(int w = 0, int h = 0); |
217 | + void draw(SDrawArea a); |
218 | + void add_item(Drawable& d, SCoordinates c); |
219 | + void remove_item(Drawable& d); |
220 | + void on_clicked(SCoordinates y); |
221 | + |
222 | + virtual int GetMinimalWidth () override; |
223 | + virtual int GetMinimalHeight() override; |
224 | +private: |
225 | + std::map<Drawable*,SCoordinates> items; |
226 | + |
227 | + int width; |
228 | + int height; |
229 | }; |
230 | |
231 | -#endif //__VIEW_HPP__ |
232 | +#endif //__FIXED_HPP__ |
233 | |
234 | === added file 'src/HBox.cpp' |
235 | --- src/HBox.cpp 1970-01-01 00:00:00 +0000 |
236 | +++ src/HBox.cpp 2013-07-23 20:39:00 +0000 |
237 | @@ -0,0 +1,61 @@ |
238 | +#include "HBox.hpp" |
239 | + |
240 | +void HBox::draw(SDrawArea a){ |
241 | + |
242 | + _RecalculateSizes(a.h, &Drawable::GetMinimalWidth); |
243 | + |
244 | + int x = a.x + margin, y = a.y + margin; |
245 | + |
246 | + for(auto i : children){ |
247 | + int width = i.size; |
248 | + int height = a.h - 2*margin; |
249 | + |
250 | + |
251 | + i.item.draw(SDrawArea(x,y,width,height)); |
252 | + |
253 | + x += i.size; |
254 | + x += spacing; |
255 | + } |
256 | + |
257 | + // Remember my size (for click recognition) |
258 | + current_height = a.h; |
259 | + current_width = a.w; |
260 | + |
261 | +} |
262 | + |
263 | +int HBox::GetMinimalHeight() { |
264 | + // Maximum of all items' heights |
265 | + int max = 0; |
266 | + for(auto i : children){ |
267 | + int w = i.item.GetMinimalHeight(); |
268 | + if (w > max) max = w; |
269 | + } |
270 | + return max + 2*margin; |
271 | + |
272 | +} |
273 | +int HBox::GetMinimalWidth () { |
274 | + // Sum of all items' widths and gaps |
275 | + int sum = 0; |
276 | + for(auto i : children){ |
277 | + sum += i.item.GetMinimalWidth(); |
278 | + sum += spacing; |
279 | + } |
280 | + if(sum >= 0) sum -= spacing; |
281 | + return sum + 2*margin; |
282 | +} |
283 | + |
284 | +void HBox::on_clicked(SCoordinates p){ |
285 | + if (p.x < margin || p.y < margin || p.y > current_height - margin) return; |
286 | + int sum = margin; |
287 | + for(auto i : children){ |
288 | + sum += i.size; |
289 | + if(p.x <= sum) { // This item was clicked! |
290 | + i.item.on_clicked(SCoordinates(p.x - sum, p.y)); |
291 | + return; |
292 | + } |
293 | + sum += spacing; |
294 | + if(p.x <= sum){ // Empty space between items was clicked |
295 | + return; |
296 | + } |
297 | + } |
298 | +} |
299 | |
300 | === added file 'src/HBox.hpp' |
301 | --- src/HBox.hpp 1970-01-01 00:00:00 +0000 |
302 | +++ src/HBox.hpp 2013-07-23 20:39:00 +0000 |
303 | @@ -0,0 +1,11 @@ |
304 | +#include "Box.hpp" |
305 | + |
306 | +class HBox : public Box{ |
307 | +public: |
308 | + virtual void draw(SDrawArea a) override; |
309 | + |
310 | + virtual int GetMinimalHeight() override; |
311 | + virtual int GetMinimalWidth () override; |
312 | + |
313 | + virtual void on_clicked(SCoordinates p) override; |
314 | +}; |
315 | |
316 | === added file 'src/VBox.cpp' |
317 | --- src/VBox.cpp 1970-01-01 00:00:00 +0000 |
318 | +++ src/VBox.cpp 2013-07-23 20:39:00 +0000 |
319 | @@ -0,0 +1,60 @@ |
320 | +#include "VBox.hpp" |
321 | + |
322 | +void VBox::draw(SDrawArea a){ |
323 | + |
324 | + _RecalculateSizes(a.h, &Drawable::GetMinimalHeight); |
325 | + |
326 | + int x = a.x + margin, y = a.y + margin; |
327 | + |
328 | + for(auto i : children){ |
329 | + int width = a.w - 2*margin; |
330 | + int height = i.size; |
331 | + |
332 | + |
333 | + i.item.draw(SDrawArea(x,y,width,height)); |
334 | + |
335 | + y += i.size; |
336 | + y += spacing; |
337 | + } |
338 | + |
339 | + // Remember my size (for click recognition) |
340 | + current_height = a.h; |
341 | + current_width = a.w; |
342 | + |
343 | +} |
344 | + |
345 | +int VBox::GetMinimalHeight() { |
346 | + // Sum of all items' heights and gaps |
347 | + int sum = 0; |
348 | + for(auto i : children){ |
349 | + sum += i.item.GetMinimalHeight(); |
350 | + sum += spacing; |
351 | + } |
352 | + if(sum >= 0) sum -= spacing; |
353 | + return sum + 2*margin; |
354 | +} |
355 | +int VBox::GetMinimalWidth () { |
356 | + // Maximum of all items' widths |
357 | + int max = 0; |
358 | + for(auto i : children){ |
359 | + int w = i.item.GetMinimalWidth(); |
360 | + if (w > max) max = w; |
361 | + } |
362 | + return max + 2*margin; |
363 | +} |
364 | + |
365 | +void VBox::on_clicked(SCoordinates p){ |
366 | + if (p.y < margin || p.x < margin || p.x > current_width - margin) return; |
367 | + int sum = margin; |
368 | + for(auto i : children){ |
369 | + sum += i.size; |
370 | + if(p.y <= sum) { // This item was clicked! |
371 | + i.item.on_clicked(SCoordinates(p.x, p.y - sum)); |
372 | + return; |
373 | + } |
374 | + sum += spacing; |
375 | + if(p.y <= sum){ // Empty space between items was clicked |
376 | + return; |
377 | + } |
378 | + } |
379 | +} |
380 | |
381 | === added file 'src/VBox.hpp' |
382 | --- src/VBox.hpp 1970-01-01 00:00:00 +0000 |
383 | +++ src/VBox.hpp 2013-07-23 20:39:00 +0000 |
384 | @@ -0,0 +1,11 @@ |
385 | +#include "Box.hpp" |
386 | + |
387 | +class VBox : public Box{ |
388 | +public: |
389 | + virtual void draw(SDrawArea a) override; |
390 | + |
391 | + virtual int GetMinimalHeight() override; |
392 | + virtual int GetMinimalWidth () override; |
393 | + |
394 | + virtual void on_clicked(SCoordinates p) override; |
395 | +}; |
396 | |
397 | === modified file 'src/build' |
398 | --- src/build 2013-07-14 19:38:45 +0000 |
399 | +++ src/build 2013-07-23 20:39:00 +0000 |
400 | @@ -1,2 +1,2 @@ |
401 | #!/bin/sh |
402 | -g++-4.8 -o main *.cpp `pkg-config --cflags --libs allegro-5.0 allegro_image-5.0 allegro_primitives-5.0 allegro_font-5.0 allegro_ttf-5.0` --std=c++11 |
403 | +g++-4.8 -o main *.cpp `pkg-config --cflags --libs allegro-5.0 allegro_image-5.0 allegro_primitives-5.0 allegro_font-5.0 allegro_ttf-5.0` --std=c++11 -Wall -g |
404 | |
405 | === modified file 'src/button.cpp' |
406 | --- src/button.cpp 2013-07-07 08:48:44 +0000 |
407 | +++ src/button.cpp 2013-07-23 20:39:00 +0000 |
408 | @@ -5,7 +5,7 @@ |
409 | #include <allegro5/allegro_font.h> |
410 | #include <allegro5/allegro_ttf.h> |
411 | |
412 | -Button::Button(std::string _text) : Drawable(60,20), text(_text){ |
413 | +Button::Button(std::string _text) : text(_text){ |
414 | |
415 | } |
416 | |
417 | @@ -13,13 +13,19 @@ |
418 | click_reaction = f; |
419 | } |
420 | |
421 | -void Button::draw(){ |
422 | +void Button::draw(SDrawArea a){ |
423 | + use_new_transform_to(a.x,a.y); |
424 | ALLEGRO_COLOR color = al_map_rgb(120, 140, 200); |
425 | - al_draw_filled_rectangle(0,0,width,height, color); |
426 | - al_draw_text(Display::main_font, al_map_rgb(255,255,255), 30, 0 ,ALLEGRO_ALIGN_CENTRE, text.c_str()); |
427 | + al_draw_filled_rectangle(0,0, a.w, a.h, color); |
428 | + al_draw_text(Display::main_font, al_map_rgb(255,255,255), a.w/2, a.h/2 - 8, ALLEGRO_ALIGN_CENTRE, text.c_str()); |
429 | } |
430 | |
431 | void Button::on_clicked(){ |
432 | if(click_reaction == nullptr) return; |
433 | click_reaction(); |
434 | } |
435 | + |
436 | +int Button::GetMinimalHeight() {return 20;} |
437 | +int Button::GetMinimalWidth () { |
438 | + return al_get_text_width(Display::main_font, text.c_str()) + 6; // 3px margin from both sides |
439 | +} |
440 | |
441 | === modified file 'src/button.hpp' |
442 | --- src/button.hpp 2013-07-07 08:48:44 +0000 |
443 | +++ src/button.hpp 2013-07-23 20:39:00 +0000 |
444 | @@ -9,6 +9,9 @@ |
445 | void (*click_reaction)() = nullptr; |
446 | std::string text; |
447 | |
448 | - virtual void draw(); |
449 | - virtual void on_clicked(); |
450 | + virtual void draw(SDrawArea a) override; |
451 | + virtual void on_clicked() override; |
452 | + |
453 | + virtual int GetMinimalHeight() override; |
454 | + virtual int GetMinimalWidth () override; |
455 | }; |
456 | |
457 | === modified file 'src/display.cpp' |
458 | --- src/display.cpp 2013-07-07 08:48:44 +0000 |
459 | +++ src/display.cpp 2013-07-23 20:39:00 +0000 |
460 | @@ -9,7 +9,7 @@ |
461 | |
462 | ALLEGRO_DISPLAY* Display::display = nullptr; |
463 | ALLEGRO_FONT* Display::main_font = nullptr; |
464 | -View* Display::current_view = nullptr; |
465 | +Drawable* Display::main_widget = nullptr; |
466 | |
467 | void Display::init(){ |
468 | al_init(); |
469 | @@ -18,7 +18,7 @@ |
470 | al_init_font_addon(); |
471 | al_init_ttf_addon(); |
472 | |
473 | - display = al_create_display(200,150); |
474 | + display = al_create_display(170,200); |
475 | |
476 | main_font = al_load_ttf_font("Ubuntu-R.ttf",12,0); |
477 | |
478 | @@ -27,10 +27,9 @@ |
479 | } |
480 | |
481 | void Display::redraw(){ |
482 | - if(current_view != nullptr){ |
483 | - current_view->draw(); |
484 | - }else{ |
485 | - al_clear_to_color(al_map_rgb(0,0,0)); |
486 | + al_clear_to_color(al_map_rgb(0,0,0)); |
487 | + if(main_widget != nullptr){ |
488 | + main_widget->draw( SDrawArea(0,0,al_get_display_width(display),al_get_display_height(display)) ); |
489 | } |
490 | al_flip_display(); |
491 | } |
492 | @@ -56,8 +55,8 @@ |
493 | }else if(ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN){ |
494 | int x = ev.mouse.x; |
495 | int y = ev.mouse.y; |
496 | - if(current_view != nullptr){ |
497 | - current_view->on_clicked(x,y); |
498 | + if(main_widget != nullptr){ |
499 | + main_widget->on_clicked(SCoordinates(x,y)); |
500 | } |
501 | } |
502 | } |
503 | @@ -73,6 +72,6 @@ |
504 | al_destroy_display(display); |
505 | } |
506 | |
507 | -void Display::set_view(View* v){ |
508 | - current_view = v; |
509 | +void Display::SetMainWidget(Drawable& v){ |
510 | + main_widget = &v; |
511 | } |
512 | |
513 | === modified file 'src/display.hpp' |
514 | --- src/display.hpp 2013-07-07 08:48:44 +0000 |
515 | +++ src/display.hpp 2013-07-23 20:39:00 +0000 |
516 | @@ -1,7 +1,7 @@ |
517 | #ifndef __DISPLAY_HPP__ |
518 | #define __DISPLAY_HPP__ |
519 | |
520 | -#include "view.hpp" |
521 | +#include "drawable.hpp" |
522 | #include <allegro5/allegro.h> |
523 | #include <allegro5/allegro_font.h> |
524 | |
525 | @@ -11,16 +11,18 @@ |
526 | static void main_loop(); |
527 | static void cleanup(); |
528 | |
529 | - static void set_view(View* v); |
530 | + static void SetMainWidget(Drawable& v); |
531 | |
532 | - static ALLEGRO_DISPLAY* display; |
533 | static ALLEGRO_FONT* main_font; |
534 | |
535 | - static View* current_view; |
536 | |
537 | private: |
538 | Display() = delete; |
539 | + |
540 | static void redraw(); |
541 | + |
542 | + static Drawable* main_widget; |
543 | + static ALLEGRO_DISPLAY* display; |
544 | }; |
545 | |
546 | #endif //__DISPLAY_HPP__ |
547 | |
548 | === modified file 'src/drawable.cpp' |
549 | --- src/drawable.cpp 2013-07-07 08:48:44 +0000 |
550 | +++ src/drawable.cpp 2013-07-23 20:39:00 +0000 |
551 | @@ -2,20 +2,30 @@ |
552 | #include "allegro5/allegro.h" |
553 | #include "allegro5/allegro_primitives.h" |
554 | #include <iostream> |
555 | - |
556 | -Drawable::Drawable(int _w, int _h){ |
557 | - width = _w; |
558 | - height = _h; |
559 | + |
560 | +void Drawable::use_new_transform_to(int x,int y){ |
561 | + ALLEGRO_TRANSFORM temp_transform; |
562 | + al_identity_transform(&temp_transform); |
563 | + al_translate_transform(&temp_transform, x, y); |
564 | + al_use_transform(&temp_transform); |
565 | +} |
566 | + |
567 | +Drawable::Drawable(){ |
568 | } |
569 | |
570 | Drawable::~Drawable(){ |
571 | } |
572 | |
573 | |
574 | -void Drawable::draw(){ |
575 | +void Drawable::draw(SDrawArea a){ |
576 | + use_new_transform_to(a.x,a.y); |
577 | ALLEGRO_COLOR red = al_map_rgb(255, 0, 0); |
578 | - al_draw_filled_rectangle(0,0,width,height, red); |
579 | - |
580 | + al_draw_filled_rectangle(0,0, a.w, a.h, red); |
581 | + |
582 | +} |
583 | + |
584 | +void Drawable::on_clicked(SCoordinates p){ |
585 | + on_clicked(); //by default, use the ignoring position version |
586 | } |
587 | |
588 | void Drawable::on_clicked(){ |
589 | |
590 | === modified file 'src/drawable.hpp' |
591 | --- src/drawable.hpp 2013-07-07 08:48:44 +0000 |
592 | +++ src/drawable.hpp 2013-07-23 20:39:00 +0000 |
593 | @@ -1,16 +1,38 @@ |
594 | - #ifndef __DRAWABLE_HPP__ |
595 | - #define __DRAWABLE_HPP__ |
596 | - |
597 | - class Drawable{ |
598 | - public: |
599 | - Drawable(int w, int h); |
600 | +#ifndef __DRAWABLE_HPP__ |
601 | +#define __DRAWABLE_HPP__ |
602 | + |
603 | +struct SDrawArea{ |
604 | + SDrawArea(int _x, int _y, int _w, int _h) : x(_x), y(_y), w(_w), h(_h) {}; |
605 | + int x; |
606 | + int y; |
607 | + int w; |
608 | + int h; |
609 | +}; |
610 | + |
611 | +struct SCoordinates{ |
612 | + int x; |
613 | + int y; |
614 | + SCoordinates(int _x, int _y) : x(_x), y(_y) {} |
615 | + SCoordinates() : x(0), y(0) {} |
616 | +}; |
617 | + |
618 | + |
619 | +class Drawable{ |
620 | +public: |
621 | + Drawable(); |
622 | virtual ~Drawable(); |
623 | |
624 | - int width; |
625 | - int height; |
626 | + virtual void draw(SDrawArea area); |
627 | + /* Click coordinates are relative to widget position */ |
628 | + virtual void on_clicked(SCoordinates p); |
629 | + /* This version ignores position */ |
630 | + virtual void on_clicked(); |
631 | + |
632 | + virtual int GetMinimalWidth () = 0; |
633 | + virtual int GetMinimalHeight() = 0; |
634 | |
635 | - virtual void draw(); |
636 | - virtual void on_clicked(); |
637 | - }; |
638 | + /* A helpful macro, used by probably every drawable in its draw() func */ |
639 | + static void use_new_transform_to(int x, int y); |
640 | +}; |
641 | |
642 | #endif //__DRAWABLE_HPP__ |
643 | |
644 | === modified file 'src/label.cpp' |
645 | --- src/label.cpp 2013-07-07 08:48:44 +0000 |
646 | +++ src/label.cpp 2013-07-23 20:39:00 +0000 |
647 | @@ -8,11 +8,18 @@ |
648 | extern ALLEGRO_FONT* main_font; |
649 | |
650 | |
651 | -Label::Label(std::string _text) : Drawable(60,20), text(_text){ |
652 | +Label::Label(std::string _text) : text(_text){ |
653 | |
654 | } |
655 | |
656 | -void Label::draw(){ |
657 | +void Label::draw(SDrawArea a){ |
658 | + use_new_transform_to(a.x,a.y); |
659 | ALLEGRO_COLOR white = al_map_rgb(255, 255, 255); |
660 | - al_draw_text(Display::main_font, white, 30, 0 ,ALLEGRO_ALIGN_CENTRE, text.c_str()); |
661 | -} |
662 | + al_draw_text(Display::main_font, white, a.w/2, a.h/2 - 8 ,ALLEGRO_ALIGN_CENTRE, text.c_str()); |
663 | +} |
664 | + |
665 | +int Label::GetMinimalHeight() {return 20;} |
666 | +int Label::GetMinimalWidth () { |
667 | + return al_get_text_width(Display::main_font, text.c_str()) + 6; // 3px margin from both sides |
668 | +} |
669 | + |
670 | |
671 | === modified file 'src/label.hpp' |
672 | --- src/label.hpp 2013-07-07 08:48:44 +0000 |
673 | +++ src/label.hpp 2013-07-23 20:39:00 +0000 |
674 | @@ -6,5 +6,8 @@ |
675 | Label(std::string); |
676 | std::string text; |
677 | |
678 | - virtual void draw(); |
679 | + virtual void draw(SDrawArea a) override; |
680 | + |
681 | + virtual int GetMinimalHeight() override; |
682 | + virtual int GetMinimalWidth () override; |
683 | }; |
684 | |
685 | === modified file 'src/main.cpp' |
686 | --- src/main.cpp 2013-07-07 08:48:44 +0000 |
687 | +++ src/main.cpp 2013-07-23 20:39:00 +0000 |
688 | @@ -1,13 +1,14 @@ |
689 | #include "display.hpp" |
690 | #include "button.hpp" |
691 | #include "label.hpp" |
692 | -#include "view.hpp" |
693 | +#include "Fixed.hpp" |
694 | +#include "VBox.hpp" |
695 | #include <iostream> |
696 | #include <cstdlib> |
697 | |
698 | -View* main_menu; |
699 | -View* additional_menu; |
700 | +Fixed additional_menu; |
701 | |
702 | +VBox main_menu_vbox; |
703 | |
704 | |
705 | void click_reaction1(){ |
706 | @@ -27,10 +28,10 @@ |
707 | } |
708 | |
709 | void switch_to_main_menu(){ |
710 | - Display::set_view(main_menu); |
711 | + Display::SetMainWidget(main_menu_vbox); |
712 | } |
713 | void switch_to_additional_menu(){ |
714 | - Display::set_view(additional_menu); |
715 | + Display::SetMainWidget(additional_menu); |
716 | } |
717 | |
718 | |
719 | @@ -38,11 +39,9 @@ |
720 | int main(){ |
721 | Display::init(); |
722 | |
723 | - main_menu = new View(); |
724 | - additional_menu = new View(); |
725 | - |
726 | Label label_main_menu("Main menu"); |
727 | |
728 | + |
729 | Button button1("Button1"); |
730 | button1.set_click_reaction(click_reaction1); |
731 | Button button2("Button2"); |
732 | @@ -61,22 +60,23 @@ |
733 | button_to_main.set_click_reaction(switch_to_main_menu); |
734 | |
735 | |
736 | - main_menu->add_item(&label_main_menu,Coordinates(40,25)); |
737 | - main_menu->add_item(&button1,Coordinates(40,50)); |
738 | - main_menu->add_item(&button2,Coordinates(40,75)); |
739 | - main_menu->add_item(&button_to_2,Coordinates(40,100)); |
740 | - main_menu->add_item(&button_quit,Coordinates(40,125)); |
741 | - additional_menu->add_item(&label_additional_menu,Coordinates(42,27)); |
742 | - additional_menu->add_item(&button3,Coordinates(42,52)); |
743 | - additional_menu->add_item(&button_to_main,Coordinates(42,77)); |
744 | + main_menu_vbox.SetSpacing(3); // gaps between buttons |
745 | + main_menu_vbox.SetMargin(5); // empty frame around the box |
746 | + main_menu_vbox.Add(label_main_menu, 0); |
747 | + main_menu_vbox.Add(button1, 1); |
748 | + main_menu_vbox.Add(button2, 2); |
749 | + main_menu_vbox.Add(button_to_2, 3, BOX_EXPAND); |
750 | + main_menu_vbox.Add(button_quit, 4); |
751 | + additional_menu.add_item(label_additional_menu,SCoordinates(42,27)); |
752 | + additional_menu.add_item(button3, SCoordinates(42,52)); |
753 | + additional_menu.add_item(button_to_main, SCoordinates(42,77)); |
754 | |
755 | - Display::set_view(main_menu); |
756 | + Display::SetMainWidget(main_menu_vbox); |
757 | |
758 | Display::main_loop(); |
759 | |
760 | Display::cleanup(); |
761 | |
762 | - delete main_menu, additional_menu; |
763 | |
764 | return 0; |
765 | } |
Why items in Box are stored in a set? I would use list or vector instead. Ordering of items would be clear and member order (of struct BoxEntry) wouldn't be needed.