]> git.mxchange.org Git - simgear.git/blob - simgear/canvas/layout/canvas_layout_test.cxx
canvas::BoxLayout: add custom additional whitespace (spacer/stretch)
[simgear.git] / simgear / canvas / layout / canvas_layout_test.cxx
1 // Testing canvas layouting system
2 //
3 // Copyright (C) 2014  Thomas Geymayer <tomgey@gmail.com>
4 //
5 // This library is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU Library General Public
7 // License as published by the Free Software Foundation; either
8 // version 2 of the License, or (at your option) any later version.
9 //
10 // This library is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 // Library General Public License for more details.
14 //
15 // You should have received a copy of the GNU Library General Public
16 // License along with this library; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA
18
19 #define BOOST_TEST_MODULE canvas_layout
20 #include <BoostTestTargetConfig.h>
21
22 #include "BoxLayout.hxx"
23 #include "NasalWidget.hxx"
24
25 #include <simgear/debug/logstream.hxx>
26 #include <cstdlib>
27
28 //------------------------------------------------------------------------------
29 struct SetLogLevelFixture
30 {
31   SetLogLevelFixture()
32   {
33     sglog().set_log_priority(SG_DEBUG);
34   }
35 };
36 BOOST_GLOBAL_FIXTURE(SetLogLevelFixture);
37
38 //------------------------------------------------------------------------------
39 namespace sc = simgear::canvas;
40
41 class TestWidget:
42   public sc::LayoutItem
43 {
44   public:
45     TestWidget( const SGVec2i& min_size,
46                 const SGVec2i& size_hint,
47                 const SGVec2i& max_size )
48     {
49       _size_hint = size_hint;
50       _min_size = min_size;
51       _max_size = max_size;
52     }
53
54     TestWidget(const TestWidget& rhs)
55     {
56       _size_hint = rhs._size_hint;
57       _min_size = rhs._min_size;
58       _max_size = rhs._max_size;
59     }
60
61     void setMinSize(const SGVec2i& size) { _min_size = size; }
62     void setMaxSize(const SGVec2i& size) { _max_size = size; }
63     void setSizeHint(const SGVec2i& size) { _size_hint = size; }
64
65     virtual void setGeometry(const SGRecti& geom) { _geom = geom; }
66     virtual SGRecti geometry() const { return _geom; }
67
68   protected:
69
70     SGRecti _geom;
71
72     virtual SGVec2i sizeHintImpl() const { return _size_hint; }
73     virtual SGVec2i minimumSizeImpl() const { return _min_size; }
74     virtual SGVec2i maximumSizeImpl() const { return _max_size; }
75 };
76
77 typedef SGSharedPtr<TestWidget> TestWidgetRef;
78
79 //------------------------------------------------------------------------------
80 BOOST_AUTO_TEST_CASE( horizontal_layout )
81 {
82   sc::BoxLayout box_layout(sc::BoxLayout::BottomToTop);
83   box_layout.setSpacing(5);
84
85   BOOST_CHECK_EQUAL(box_layout.direction(), sc::BoxLayout::BottomToTop);
86   BOOST_CHECK_EQUAL(box_layout.spacing(), 5);
87
88   box_layout.setDirection(sc::BoxLayout::LeftToRight);
89   box_layout.setSpacing(9);
90
91   BOOST_CHECK_EQUAL(box_layout.direction(), sc::BoxLayout::LeftToRight);
92   BOOST_CHECK_EQUAL(box_layout.spacing(), 9);
93
94   TestWidgetRef fixed_size_widget( new TestWidget( SGVec2i(16, 16),
95                                                    SGVec2i(16, 16),
96                                                    SGVec2i(16, 16) ) );
97   box_layout.addItem(fixed_size_widget);
98
99   BOOST_CHECK_EQUAL(box_layout.minimumSize(), SGVec2i(16, 16));
100   BOOST_CHECK_EQUAL(box_layout.sizeHint(), SGVec2i(16, 16));
101   BOOST_CHECK_EQUAL(box_layout.maximumSize(), SGVec2i(16, 16));
102
103   TestWidgetRef limited_resize_widget( new TestWidget( SGVec2i(16, 16),
104                                                        SGVec2i(32, 32),
105                                                        SGVec2i(256, 64) ) );
106   box_layout.addItem(limited_resize_widget);
107
108   // Combined sizes of both widget plus the padding between them
109   BOOST_CHECK_EQUAL(box_layout.minimumSize(), SGVec2i(41, 16));
110   BOOST_CHECK_EQUAL(box_layout.sizeHint(), SGVec2i(57, 32));
111   BOOST_CHECK_EQUAL(box_layout.maximumSize(), SGVec2i(281, 64));
112
113   // Test with different spacing/padding
114   box_layout.setSpacing(5);
115
116   BOOST_CHECK_EQUAL(box_layout.minimumSize(), SGVec2i(37, 16));
117   BOOST_CHECK_EQUAL(box_layout.sizeHint(), SGVec2i(53, 32));
118   BOOST_CHECK_EQUAL(box_layout.maximumSize(), SGVec2i(277, 64));
119
120   box_layout.setGeometry(SGRecti(0, 0, 128, 32));
121
122   // Fixed size for first widget and remaining space goes to second widget
123   BOOST_CHECK_EQUAL(fixed_size_widget->geometry(), SGRecti(0, 8, 16, 16));
124   BOOST_CHECK_EQUAL(limited_resize_widget->geometry(), SGRecti(21, 0, 107, 32));
125
126   TestWidgetRef stretch_widget( new TestWidget( SGVec2i(16, 16),
127                                                 SGVec2i(32, 32),
128                                                 SGVec2i(128, 32) ) );
129   box_layout.addItem(stretch_widget, 1);
130   box_layout.update();
131
132   BOOST_CHECK_EQUAL(box_layout.minimumSize(), SGVec2i(58, 16));
133   BOOST_CHECK_EQUAL(box_layout.sizeHint(), SGVec2i(90, 32));
134   BOOST_CHECK_EQUAL(box_layout.maximumSize(), SGVec2i(410, 64));
135
136   // Due to the stretch factor only the last widget gets additional space. All
137   // other widgets get the preferred size.
138   BOOST_CHECK_EQUAL(fixed_size_widget->geometry(), SGRecti(0, 8, 16, 16));
139   BOOST_CHECK_EQUAL(limited_resize_widget->geometry(), SGRecti(21, 0, 32, 32));
140   BOOST_CHECK_EQUAL(stretch_widget->geometry(), SGRecti(58, 0, 70, 32));
141
142   // Test stretch factor
143   TestWidgetRef fast_stretch( new TestWidget(*stretch_widget) );
144   sc::BoxLayout box_layout_stretch(sc::BoxLayout::LeftToRight);
145
146   box_layout_stretch.addItem(stretch_widget, 1);
147   box_layout_stretch.addItem(fast_stretch, 2);
148
149   box_layout_stretch.setGeometry(SGRecti(0,0,128,32));
150
151   BOOST_CHECK_EQUAL(stretch_widget->geometry(), SGRecti(0, 0, 41, 32));
152   BOOST_CHECK_EQUAL(fast_stretch->geometry(), SGRecti(46, 0, 82, 32));
153
154   box_layout_stretch.setGeometry(SGRecti(0,0,256,32));
155
156   BOOST_CHECK_EQUAL(stretch_widget->geometry(), SGRecti(0, 0, 123, 32));
157   BOOST_CHECK_EQUAL(fast_stretch->geometry(), SGRecti(128, 0, 128, 32));
158
159   // Test superflous space to padding
160   box_layout_stretch.setGeometry(SGRecti(0,0,512,32));
161
162   BOOST_CHECK_EQUAL(stretch_widget->geometry(), SGRecti(83, 0, 128, 32));
163   BOOST_CHECK_EQUAL(fast_stretch->geometry(), SGRecti(300, 0, 128, 32));
164
165   // Test more space then preferred, but less than maximum
166   {
167     sc::HBoxLayout hbox;
168     TestWidgetRef w1( new TestWidget( SGVec2i(16,   16),
169                                       SGVec2i(32,   32),
170                                       SGVec2i(9999, 32) ) ),
171                   w2( new TestWidget(*w1) );
172
173     hbox.addItem(w1);
174     hbox.addItem(w2);
175
176     hbox.setGeometry( SGRecti(0, 0, 256, 32) );
177
178     BOOST_CHECK_EQUAL(w1->geometry(), SGRecti(0,   0, 126, 32));
179     BOOST_CHECK_EQUAL(w2->geometry(), SGRecti(131, 0, 125, 32));
180
181     hbox.setStretch(0, 1);
182     hbox.setStretch(1, 1);
183
184     BOOST_CHECK_EQUAL(hbox.stretch(0), 1);
185     BOOST_CHECK_EQUAL(hbox.stretch(1), 1);
186
187     hbox.update();
188
189     BOOST_CHECK_EQUAL(w1->geometry(), SGRecti(0,   0, 125, 32));
190     BOOST_CHECK_EQUAL(w2->geometry(), SGRecti(130, 0, 126, 32));
191   }
192 }
193
194 //------------------------------------------------------------------------------
195 BOOST_AUTO_TEST_CASE( spacer_layouting )
196 {
197   sc::HBoxLayout hbox;
198   TestWidgetRef w1( new TestWidget( SGVec2i(16, 16),
199                                     SGVec2i(32, 32),
200                                     SGVec2i(9999, 9999) ) ),
201                 w2( new TestWidget(*w1) );
202
203   hbox.addItem(w1);
204   hbox.addItem(w2);
205   hbox.addStretch(1);
206
207   BOOST_CHECK_EQUAL(hbox.minimumSize(), SGVec2i(37, 16));
208   BOOST_CHECK_EQUAL(hbox.sizeHint(), SGVec2i(69, 32));
209   BOOST_CHECK_EQUAL(hbox.maximumSize(), sc::LayoutItem::MAX_SIZE);
210
211   hbox.setGeometry(SGRecti(0, 0, 256, 40));
212
213   BOOST_CHECK_EQUAL(w1->geometry(), SGRecti(0,  0, 32, 40));
214   BOOST_CHECK_EQUAL(w2->geometry(), SGRecti(37, 0, 32, 40));
215
216   // now center with increased spacing between both widgets
217   hbox.insertStretch(0, 1);
218   hbox.insertSpacing(2, 10);
219
220   BOOST_CHECK_EQUAL(hbox.minimumSize(), SGVec2i(47, 16));
221   BOOST_CHECK_EQUAL(hbox.sizeHint(), SGVec2i(79, 32));
222   BOOST_CHECK_EQUAL(hbox.maximumSize(), sc::LayoutItem::MAX_SIZE);
223
224   hbox.update();
225
226   BOOST_CHECK_EQUAL(w1->geometry(), SGRecti(88,  0, 32, 40));
227   BOOST_CHECK_EQUAL(w2->geometry(), SGRecti(135, 0, 32, 40));
228 }
229
230 //------------------------------------------------------------------------------
231 BOOST_AUTO_TEST_CASE( vertical_layout)
232 {
233   sc::BoxLayout vbox(sc::BoxLayout::TopToBottom);
234   vbox.setSpacing(7);
235
236   TestWidgetRef fixed_size_widget( new TestWidget( SGVec2i(16, 16),
237                                                    SGVec2i(16, 16),
238                                                    SGVec2i(16, 16) ) );
239   TestWidgetRef limited_resize_widget( new TestWidget( SGVec2i(16, 16),
240                                                        SGVec2i(32, 32),
241                                                        SGVec2i(256, 64) ) );
242
243   vbox.addItem(fixed_size_widget);
244   vbox.addItem(limited_resize_widget);
245
246   BOOST_CHECK_EQUAL(vbox.minimumSize(), SGVec2i(16, 39));
247   BOOST_CHECK_EQUAL(vbox.sizeHint(), SGVec2i(32, 55));
248   BOOST_CHECK_EQUAL(vbox.maximumSize(), SGVec2i(256, 87));
249
250   vbox.setGeometry(SGRecti(10, 20, 16, 55));
251
252   BOOST_CHECK_EQUAL(fixed_size_widget->geometry(), SGRecti(10, 20, 16, 16));
253   BOOST_CHECK_EQUAL(limited_resize_widget->geometry(), SGRecti(10, 43, 16, 32));
254
255   vbox.setDirection(sc::BoxLayout::BottomToTop);
256 }
257
258 //------------------------------------------------------------------------------
259 BOOST_AUTO_TEST_CASE( nasal_layout )
260 {
261   naContext c = naNewContext();
262   naRef me = naNewHash(c);
263
264   sc::LayoutItemRef nasal_item( new sc::NasalWidget(me) );
265
266   naFreeContext(c);
267 }