Merge lp:~rafalcieslak256/millenniumduel/containers into lp:millenniumduel

Proposed by Rafał Cieślak
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
Reviewer Review Type Date Requested Status
Adam Malinowski Approve
Jakub Sękowski Approve
Review via email: mp+176052@code.launchpad.net

Description of the change

This branch implements Container widgets (namely a custom VBox and a HBox).
[https://blueprints.launchpad.net/millenniumduel/+spec/millenniumduel-containers]

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.

To post a comment you must log in.
Revision history for this message
Jakub Sękowski (sequba) wrote :

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.

Revision history for this message
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.

Revision history for this message
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.

review: Approve
Revision history for this message
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!

review: Needs Fixing
22. By Rafał Cieślak

Fixed click detection allignment

Revision history for this message
Adam Malinowski (adayah) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
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 }

Subscribers

People subscribed via source and target branches