Merge lp:~haggai-eran/nux/rtl-logical-packing into lp:nux/2.0
- rtl-logical-packing
- Merge into 2.0
Status: | Superseded |
---|---|
Proposed branch: | lp:~haggai-eran/nux/rtl-logical-packing |
Merge into: | lp:nux/2.0 |
Diff against target: |
1076 lines (+421/-95) 14 files modified
Nux/Area.cpp (+15/-0) Nux/Area.h (+16/-0) Nux/HLayout.cpp (+24/-10) Nux/HScrollBar.cpp (+4/-0) Nux/Nux.cpp (+13/-0) Nux/Nux.h (+3/-0) Nux/RangeValue.cpp (+15/-1) Nux/ScrollView.cpp (+49/-10) Nux/VSplitter.cpp (+103/-33) tests/Helpers.cpp (+50/-3) tests/Helpers.h (+2/-1) tests/Makefile.am (+4/-1) tests/gtest-nux-cairo-wrapper.cpp (+2/-36) tests/gtest-nux-hlayout.cpp (+121/-0) |
To merge this branch: | bzr merge lp:~haggai-eran/nux/rtl-logical-packing |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Tim Penhey (community) | Needs Fixing | ||
Jay Taoko | Pending | ||
Review via email: mp+85526@code.launchpad.net |
This proposal has been superseded by a proposal from 2012-04-27.
Commit message
Add right-to-left mirroring support. Implement mirroring for HLayout.
Description of the change
Hi,
I've implemented the mirroring for right-to-left locales in this branch, in a way that is different from lp:~haggai-eran/nux/rtl-rebased. I believe this implementation is simpler, requires less changes, and works better with existing widgets.
I've also added a test to make sure the HLayout mirroring is working properly, as a part of the gtest-nux-core test suite.
I'm not sure if I should delete the merge proposal for the rtl-rebased branch, since launchpad says this will also delete all comments. Perhaps it can be archived somehow.
Regards,
Haggai
- 532. By Haggai Eran
-
Fix several coding style issues.
Haggai Eran (haggai-eran) wrote : | # |
Hi,
It's been 3 months since I posted this request, and except for the coding style comment I haven't gotten any feedback to this patch. Could you tell me if you need any more information or any more work to be done on it?
Shahar Or (mightyiam) wrote : | # |
Dear Unity/Nux developers,
This is really important for us, RTL users. And It is precious and rare that we have such a willing and able contributor in the RTL community.
So please give this merge even more love! :)
We appreciate it!
Thanks and Blessings,
Shahar
In service of Ubuntu RTL users
Jay Taoko (jaytaoko) wrote : | # |
It hasn't been easy to come to a decision regarding the proposal of this branch. Supporting Right-to-Left languages is very important and it as do be done right. With regard to Unity which is the main focus, the team hasn't finalised the design for Right-to-Left language support. And how it would impact Unity. That is why I can't approve the branch at this stage.
There are also other technical considerations with the branch. Activating the Right-to-Left mode will not make every widget correct. Some widgets have to be specifically designed with Right-to-Left language support in mind and we can't do it just yet.
Haggai Eran (haggai-eran) wrote : | # |
Hi Jay,
Thanks for your reply. I understand it is important for the Unity team to make a complete design for right-to-left language support, before accepting any changes. I'm interested in helping advancing this issue, and I would like to take part in this discussion, if that's okay. Can you tell me where is it taking place?
Regarding the branch itself, it is true that I haven't tested all the widgets, as I was focused on what was needed to make the most prominent features of unity mirrored, and hoping to continue to improve it later on.
Finally, since it doesn't seem that Unity will have right-to-left support soon, while Unity2D has right-to-left support since Oneiric (using Qt's excellent mirroring support), I'd like to offer that users of right-to-left languages will have their default desktop set to Unity2D. I wrote about it in the unity-design mailing list [1], and proposed a patch to do so at lp:~haggai-eran/nux/rtl-fallback-to-unity-2d. Would you consider implementing such workaround for Precise?
Best regards,
Haggai
- 533. By Haggai Eran
-
Merge version 2.10.0 from trunk.
- 534. By Haggai Eran
-
RangeValue right-to-left mirroring support.
- 535. By Haggai Eran
-
Support right-to-left mirroring in HScrollBar and ScrollView.
- 536. By Haggai Eran
-
Right-to-left mirroring support for VSplitter.
Unmerged revisions
- 536. By Haggai Eran
-
Right-to-left mirroring support for VSplitter.
- 535. By Haggai Eran
-
Support right-to-left mirroring in HScrollBar and ScrollView.
- 534. By Haggai Eran
-
RangeValue right-to-left mirroring support.
- 533. By Haggai Eran
-
Merge version 2.10.0 from trunk.
- 532. By Haggai Eran
-
Fix several coding style issues.
- 531. By Haggai Eran
-
Add simple HLayout test, testing both left-to-right and right-to-left modes.
Moved the run_test wrapper from test_cairo_
wrapper. cpp to Helpers.cpp so that it can be reused. - 530. By Haggai Eran
-
HLayout right-to-left support.
- 529. By Haggai Eran
-
Basic right-to-left directionality support.
Preview Diff
1 | === modified file 'Nux/Area.cpp' |
2 | --- Nux/Area.cpp 2012-03-12 21:45:30 +0000 |
3 | +++ Nux/Area.cpp 2012-04-18 22:03:19 +0000 |
4 | @@ -39,6 +39,7 @@ |
5 | , geometry_(0, 0, DEFAULT_WIDGET_WIDTH, DEFAULT_WIDGET_HEIGHT) |
6 | , min_size_(AREA_MIN_WIDTH, AREA_MIN_HEIGHT) |
7 | , max_size_(AREA_MAX_WIDTH, AREA_MAX_HEIGHT) |
8 | + , direction_(GetDefaultDirection()) |
9 | { |
10 | window_thread_ = GetWindowThread(); |
11 | visible_ = true; |
12 | @@ -336,9 +337,13 @@ |
13 | |
14 | void Area::SetGeometry(int x, int y, int w, int h) |
15 | { |
16 | + const int original_width = w; |
17 | h = nux::Clamp<int> (h, min_size_.height, max_size_.height); |
18 | w = nux::Clamp<int> (w, min_size_.width, max_size_.width); |
19 | |
20 | + if (GetDirection() == RightToLeft) |
21 | + x = x + original_width - w; |
22 | + |
23 | nux::Geometry geometry(x, y, w, h); |
24 | if (geometry_ == geometry) |
25 | return; |
26 | @@ -1035,5 +1040,15 @@ |
27 | |
28 | return false; |
29 | } |
30 | + |
31 | + Direction Area::GetDirection() const |
32 | + { |
33 | + return direction_; |
34 | + } |
35 | + |
36 | + void Area::SetDirection(Direction direction) |
37 | + { |
38 | + direction_ = direction; |
39 | + } |
40 | } |
41 | |
42 | |
43 | === modified file 'Nux/Area.h' |
44 | --- Nux/Area.h 2012-03-12 21:45:30 +0000 |
45 | +++ Nux/Area.h 2012-04-18 22:03:19 +0000 |
46 | @@ -140,6 +140,12 @@ |
47 | KEY_NAV_ENTER, |
48 | }; |
49 | |
50 | + enum Direction |
51 | + { |
52 | + LeftToRight, |
53 | + RightToLeft |
54 | + }; |
55 | + |
56 | class Layout; |
57 | class View; |
58 | class Area; |
59 | @@ -572,6 +578,14 @@ |
60 | */ |
61 | bool AcceptMouseWheelEvent() const; |
62 | |
63 | + //! Return the direction of the area. |
64 | + Direction GetDirection() const; |
65 | + //! Sets the direction of the area. |
66 | + /*! |
67 | + @param direction Either nux::LeftToRight or nux::RightToLeft |
68 | + */ |
69 | + void SetDirection(Direction direction); |
70 | + |
71 | protected: |
72 | /* |
73 | This function is reimplemented in Layout as it need to perform some special operations. |
74 | @@ -668,6 +682,8 @@ |
75 | |
76 | WindowThread* window_thread_; |
77 | |
78 | + Direction direction_; |
79 | + |
80 | friend class Layout; |
81 | friend class View; |
82 | friend class WindowThread; |
83 | |
84 | === modified file 'Nux/HLayout.cpp' |
85 | --- Nux/HLayout.cpp 2011-12-10 06:39:14 +0000 |
86 | +++ Nux/HLayout.cpp 2012-04-18 22:03:19 +0000 |
87 | @@ -172,6 +172,9 @@ |
88 | |
89 | long HLayout::ComputeContentSize() |
90 | { |
91 | + const bool ltr = GetDirection() == LeftToRight; |
92 | + const int ltr_factor = ltr ? 1 : -1; |
93 | + |
94 | if (_layout_element_list.size() == 0) |
95 | { |
96 | return eCompliantHeight | eCompliantWidth; |
97 | @@ -240,22 +243,26 @@ |
98 | HLayoutManagement(width, height); |
99 | |
100 | // Objects have been resized, now position them. |
101 | - int current_x = GetBaseX() + left_padding_; |
102 | + int current_x; |
103 | + if (ltr) |
104 | + current_x = GetBaseX() + left_padding_; |
105 | + else |
106 | + current_x = GetBaseX() + GetBaseWidth() - right_padding_; |
107 | int current_y = GetBaseY() + top_padding_; |
108 | |
109 | int offset_space = 0; |
110 | int space_after_element = 0; |
111 | ComputeStacking(width, offset_space, space_after_element); |
112 | - current_x += offset_space; |
113 | + current_x += ltr_factor * offset_space; |
114 | |
115 | for (it = _layout_element_list.begin(); it != _layout_element_list.end(); it++) |
116 | { |
117 | if (!(*it)->IsVisible()) |
118 | continue; |
119 | |
120 | - current_x += space_after_element; |
121 | + current_x += ltr_factor * space_after_element; |
122 | |
123 | - (*it)->SetBaseX(current_x); |
124 | + (*it)->SetBaseX(current_x - (!ltr ? (*it)->GetBaseWidth() : 0)); |
125 | (*it)->SetBaseY(current_y); |
126 | |
127 | MinorDimensionSize extend = (*it)->GetExtend(); |
128 | @@ -330,7 +337,7 @@ |
129 | } |
130 | } |
131 | |
132 | - current_x += (*it)->GetBaseWidth() + space_after_element + space_between_children_; |
133 | + current_x += ltr_factor * ((*it)->GetBaseWidth() + space_after_element + space_between_children_); |
134 | } |
135 | |
136 | // Manage child layout |
137 | @@ -756,6 +763,9 @@ |
138 | |
139 | void HLayout::ComputeContentPosition(float offsetX, float offsetY) |
140 | { |
141 | + const bool ltr = GetDirection() == LeftToRight; |
142 | + const int ltr_factor = ltr ? 1 : -1; |
143 | + |
144 | std::list<Area *>::iterator it; |
145 | { |
146 | unsigned int num_element = 0; |
147 | @@ -773,22 +783,26 @@ |
148 | height -= (top_padding_ + bottom_padding_); |
149 | |
150 | // Objects have been resized, now position them. |
151 | - int current_x = GetBaseX() + left_padding_ + offsetX; // add base offset in X(used for scrolling) |
152 | + int current_x; |
153 | + if (ltr) |
154 | + current_x = GetBaseX() + left_padding_ + offsetX; // add base offset in X(used for scrolling) |
155 | + else |
156 | + current_x = GetBaseX() + GetBaseWidth() - right_padding_ + offsetX; |
157 | int current_y = GetBaseY() + top_padding_ + offsetY; // add base offset in Y(used for scrolling) |
158 | |
159 | int offset_space = 0; |
160 | int element_margin = 0; |
161 | ComputeStacking(width, offset_space, element_margin); |
162 | - current_x += offset_space; |
163 | + current_x += ltr_factor * offset_space; |
164 | |
165 | for (it = _layout_element_list.begin(); it != _layout_element_list.end(); it++) |
166 | { |
167 | if (!(*it)->IsVisible()) |
168 | continue; |
169 | |
170 | - current_x += element_margin; |
171 | + current_x += ltr_factor * element_margin; |
172 | |
173 | - (*it)->SetBaseX(current_x); |
174 | + (*it)->SetBaseX(current_x - (!ltr ? (*it)->GetBaseWidth() : 0)); |
175 | (*it)->SetBaseY(current_y); |
176 | |
177 | MinorDimensionPosition positioning = (*it)->GetPositioning(); |
178 | @@ -826,7 +840,7 @@ |
179 | } |
180 | } |
181 | |
182 | - current_x += (*it)->GetBaseWidth() + element_margin + space_between_children_; |
183 | + current_x += ltr_factor * ((*it)->GetBaseWidth() + element_margin + space_between_children_); |
184 | } |
185 | } |
186 | |
187 | |
188 | === modified file 'Nux/HScrollBar.cpp' |
189 | --- Nux/HScrollBar.cpp 2011-10-17 20:57:35 +0000 |
190 | +++ Nux/HScrollBar.cpp 2012-04-18 22:03:19 +0000 |
191 | @@ -52,6 +52,7 @@ |
192 | m_RightTimerHandler = 0; |
193 | |
194 | hlayout = new HLayout(NUX_TRACKER_LOCATION); |
195 | + hlayout->SetDirection(LeftToRight); |
196 | _scroll_left_button = new InputArea(NUX_TRACKER_LOCATION); |
197 | _track = new InputArea(NUX_TRACKER_LOCATION); |
198 | _scroll_right_button = new InputArea(NUX_TRACKER_LOCATION); |
199 | @@ -302,6 +303,9 @@ |
200 | |
201 | void HScrollBar::SetContentSize(int x, int y, int w, int h) |
202 | { |
203 | + if (GetDirection() == RightToLeft) |
204 | + content_offset_x_ = w - container_width_ + content_offset_x_; |
205 | + |
206 | // x and y are not needed |
207 | content_width_ = w; |
208 | content_height_ = h; |
209 | |
210 | === modified file 'Nux/Nux.cpp' |
211 | --- Nux/Nux.cpp 2011-12-29 18:06:53 +0000 |
212 | +++ Nux/Nux.cpp 2012-04-18 22:03:19 +0000 |
213 | @@ -379,4 +379,17 @@ |
214 | NThread *thread = GetWindowThread(); |
215 | return NUX_STATIC_CAST(WindowThread *, thread)->GetTimerHandler(); |
216 | } |
217 | + |
218 | + static Direction defaultDirection = LeftToRight; |
219 | + |
220 | + Direction GetDefaultDirection() |
221 | + { |
222 | + return defaultDirection; |
223 | + } |
224 | + |
225 | + void SetDefaultDirection(Direction direction) |
226 | + { |
227 | + defaultDirection = direction; |
228 | + } |
229 | + |
230 | } |
231 | |
232 | === modified file 'Nux/Nux.h' |
233 | --- Nux/Nux.h 2012-02-19 00:02:14 +0000 |
234 | +++ Nux/Nux.h 2012-04-18 22:03:19 +0000 |
235 | @@ -235,6 +235,9 @@ |
236 | |
237 | inlDeclareThreadLocalStorage(NThread *, 0, ThreadLocal_InalogicAppImpl); |
238 | |
239 | + Direction GetDefaultDirection(); |
240 | + void SetDefaultDirection(Direction direction); |
241 | + |
242 | } |
243 | |
244 | #endif // NUX_H |
245 | |
246 | === modified file 'Nux/RangeValue.cpp' |
247 | --- Nux/RangeValue.cpp 2012-01-17 04:34:19 +0000 |
248 | +++ Nux/RangeValue.cpp 2012-04-18 22:03:19 +0000 |
249 | @@ -92,11 +92,15 @@ |
250 | void RangeValue::DrawMarker(GraphicsEngine &graphics_engine) |
251 | { |
252 | int marker_position_x; |
253 | + int relative_position_x; |
254 | int marker_position_y; |
255 | |
256 | graphics_engine.PushClippingRectangle(m_Percentage->GetGeometry()); |
257 | |
258 | - marker_position_x = m_Percentage->GetBaseX() + (m_Value - m_min) * m_Percentage->GetBaseWidth() * 1 / (m_max - m_min); |
259 | + relative_position_x = (m_Value - m_min) * m_Percentage->GetBaseWidth() * 1 / (m_max - m_min); |
260 | + if (GetDirection() == RightToLeft) |
261 | + relative_position_x = m_Percentage->GetBaseWidth() - relative_position_x; |
262 | + marker_position_x = m_Percentage->GetBaseX() + relative_position_x; |
263 | marker_position_y = m_Percentage->GetBaseY() + m_Percentage->GetBaseHeight(); |
264 | GetPainter().Draw2DTriangleColor(graphics_engine, marker_position_x - 5, marker_position_y, |
265 | marker_position_x, marker_position_y - 5, |
266 | @@ -121,6 +125,8 @@ |
267 | if (m_EnableDrawProgress) |
268 | { |
269 | P.SetWidth((m_Value - m_min) * (float) P.GetWidth() / (m_max - m_min)); |
270 | + if (GetDirection() == RightToLeft) |
271 | + P.OffsetPosition(m_Percentage->GetBaseWidth() - P.GetWidth(), 0); |
272 | GetPainter().Paint2DQuadColor(graphics_engine, P, m_ProgressColor); |
273 | } |
274 | |
275 | @@ -186,6 +192,9 @@ |
276 | //////////////// |
277 | void RangeValue::OnReceiveMouseDown(int x, int y, unsigned long button_flags, unsigned long key_flags) |
278 | { |
279 | + if (GetDirection() == RightToLeft) |
280 | + x = m_Percentage->GetBaseWidth() - x; |
281 | + |
282 | if (x < 0) |
283 | m_Value = m_min; |
284 | else if (x > m_Percentage->GetBaseWidth()) |
285 | @@ -203,6 +212,8 @@ |
286 | |
287 | void RangeValue::OnReceiveMouseUp(int x, int y, unsigned long button_flags, unsigned long key_flags) |
288 | { |
289 | + if (GetDirection() == RightToLeft) |
290 | + x = m_Percentage->GetBaseWidth() - x; |
291 | |
292 | if (x < 0) |
293 | m_Value = m_min; |
294 | @@ -221,6 +232,9 @@ |
295 | |
296 | void RangeValue::OnReceiveMouseDrag(int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags) |
297 | { |
298 | + if (GetDirection() == RightToLeft) |
299 | + x = m_Percentage->GetBaseWidth() - x; |
300 | + |
301 | if (x < 0) |
302 | m_Value = m_min; |
303 | else if (x > m_Percentage->GetBaseWidth()) |
304 | |
305 | === modified file 'Nux/ScrollView.cpp' |
306 | --- Nux/ScrollView.cpp 2011-12-13 08:20:18 +0000 |
307 | +++ Nux/ScrollView.cpp 2012-04-18 22:03:19 +0000 |
308 | @@ -316,6 +316,8 @@ |
309 | { |
310 | // Give the managed layout the same size and position as the Control. |
311 | |
312 | + bool ltr = GetDirection() == LeftToRight; |
313 | + |
314 | Geometry geo = GetGeometry(); |
315 | int ScrollBarWidth = _vscrollbar->GetBaseWidth(); |
316 | int ScrollBarHeight = _hscrollbar->GetBaseHeight(); |
317 | @@ -324,6 +326,8 @@ |
318 | nuxAssertMsg(ScrollBarHeight > 0, "[ScrollView::PreLayoutManagement] Invalid scrollbar height: %d", ScrollBarHeight); |
319 | |
320 | m_ViewX = GetBaseX() + m_border + m_ViewContentLeftMargin; |
321 | + if (!ltr) |
322 | + m_ViewX += ScrollBarWidth; |
323 | m_ViewY = GetBaseY() + m_top_border + m_ViewContentTopMargin; |
324 | |
325 | if (m_vertical_scrollbar_enable == false) |
326 | @@ -383,7 +387,10 @@ |
327 | else |
328 | _hscrollbar->SetBaseWidth(GetBaseWidth() - ScrollBarWidth - 2 * m_border); |
329 | |
330 | - _hscrollbar->SetBaseX(geo.x + m_border); |
331 | + if (ltr || !m_vertical_scrollbar_enable) |
332 | + _hscrollbar->SetBaseX(geo.x + m_border); |
333 | + else |
334 | + _hscrollbar->SetBaseX(geo.x + m_border + ScrollBarWidth); |
335 | _hscrollbar->SetBaseY(geo.y + geo.GetHeight() - _hscrollbar->GetBaseHeight() - m_border); |
336 | _hscrollbar->ComputeContentSize(); |
337 | } |
338 | @@ -391,7 +398,10 @@ |
339 | { |
340 | // The horizontal scrollbar won't be visible but give it a proper size anyway. |
341 | _hscrollbar->SetBaseWidth(GetBaseWidth() - ScrollBarWidth - 2 * m_border); |
342 | - _hscrollbar->SetBaseX(geo.x + m_border); |
343 | + if (ltr) |
344 | + _hscrollbar->SetBaseX(geo.x + m_border); |
345 | + else |
346 | + _hscrollbar->SetBaseX(geo.x + m_border + ScrollBarWidth); |
347 | _hscrollbar->SetBaseY(geo.y + geo.GetHeight() - _hscrollbar->GetBaseHeight() - m_border); |
348 | _hscrollbar->ComputeContentSize(); |
349 | } |
350 | @@ -408,7 +418,10 @@ |
351 | else |
352 | _vscrollbar->SetBaseHeight(GetBaseHeight() - ScrollBarHeight - m_top_border - m_border); |
353 | |
354 | - _vscrollbar->SetBaseX(geo.x + geo.GetWidth() - ScrollBarWidth - m_border); |
355 | + if (ltr) |
356 | + _vscrollbar->SetBaseX(geo.x + geo.GetWidth() - ScrollBarWidth - m_border); |
357 | + else |
358 | + _vscrollbar->SetBaseX(geo.x + m_border); |
359 | _vscrollbar->SetBaseY(geo.y + m_top_border); |
360 | _vscrollbar->ComputeContentSize(); |
361 | } |
362 | @@ -416,7 +429,11 @@ |
363 | { |
364 | // The vertical scrollbar won't be visible but give it a proper size anyway. |
365 | _vscrollbar->SetBaseHeight(GetBaseHeight() - ScrollBarHeight - m_top_border - m_border); |
366 | - _vscrollbar->SetBaseX(geo.x + geo.GetWidth() - ScrollBarWidth - m_border); |
367 | + if (ltr) |
368 | + _vscrollbar->SetBaseX(geo.x + geo.GetWidth() - ScrollBarWidth - m_border); |
369 | + else |
370 | + _vscrollbar->SetBaseX(geo.x + m_border); |
371 | + |
372 | _vscrollbar->SetBaseY(geo.y + m_top_border); |
373 | _vscrollbar->ComputeContentSize(); |
374 | } |
375 | @@ -510,6 +527,7 @@ |
376 | long ScrollView::PostLayoutManagement2(long LayoutResult) |
377 | { |
378 | // In case IsSizeMatchContent returns True, The scroll view is resized to match its content. |
379 | + bool ltr = GetDirection() == LeftToRight; |
380 | int ScrollbarWidth = 0; |
381 | int ScrollbarHeight = 0; |
382 | |
383 | @@ -564,7 +582,10 @@ |
384 | else |
385 | _hscrollbar->SetBaseWidth(GetBaseWidth() - ScrollbarWidth - 2 * m_border); |
386 | |
387 | - _hscrollbar->SetBaseX(geo.x + m_border); |
388 | + if (ltr || !m_vertical_scrollbar_enable) |
389 | + _hscrollbar->SetBaseX(geo.x + m_border); |
390 | + else |
391 | + _hscrollbar->SetBaseX(geo.x + m_border + ScrollbarWidth); |
392 | _hscrollbar->SetBaseY(geo.y + geo.GetHeight() - _hscrollbar->GetBaseHeight() - m_border); |
393 | _hscrollbar->ComputeContentSize(); |
394 | |
395 | @@ -590,7 +611,10 @@ |
396 | else |
397 | { |
398 | _hscrollbar->SetBaseWidth(GetBaseWidth() - ScrollbarWidth - 2 * m_border); |
399 | - _hscrollbar->SetBaseX(geo.x + m_border); |
400 | + if (ltr) |
401 | + _hscrollbar->SetBaseX(geo.x + m_border); |
402 | + else |
403 | + _hscrollbar->SetBaseX(geo.x + m_border + ScrollbarWidth); |
404 | _hscrollbar->SetBaseY(geo.y + geo.GetHeight() - _hscrollbar->GetBaseHeight() - m_border); |
405 | _hscrollbar->ComputeContentSize(); |
406 | |
407 | @@ -613,7 +637,10 @@ |
408 | else |
409 | _vscrollbar->SetBaseHeight(GetBaseHeight() - ScrollbarHeight - m_top_border - m_border); |
410 | |
411 | - _vscrollbar->SetBaseX(geo.x + geo.GetWidth() - ScrollbarWidth - m_border); |
412 | + if (ltr) |
413 | + _vscrollbar->SetBaseX(geo.x + geo.GetWidth() - ScrollbarWidth - m_border); |
414 | + else |
415 | + _vscrollbar->SetBaseX(geo.x + m_border); |
416 | _vscrollbar->SetBaseY(geo.y + m_top_border); |
417 | _vscrollbar->ComputeContentSize(); |
418 | |
419 | @@ -639,7 +666,10 @@ |
420 | else |
421 | { |
422 | _vscrollbar->SetBaseHeight(GetBaseHeight() - ScrollbarHeight - m_top_border - m_border); |
423 | - _vscrollbar->SetBaseX(geo.x + geo.GetWidth() - ScrollbarWidth - m_border); |
424 | + if (ltr) |
425 | + _vscrollbar->SetBaseX(geo.x + geo.GetWidth() - ScrollbarWidth - m_border); |
426 | + else |
427 | + _vscrollbar->SetBaseX(geo.x + m_border); |
428 | _vscrollbar->SetBaseY(geo.y + m_top_border); |
429 | _vscrollbar->ComputeContentSize(); |
430 | |
431 | @@ -667,6 +697,7 @@ |
432 | // This function is called when the ScrollView is embedded within a Layout. |
433 | void ScrollView::ComputeContentPosition(float offsetX, float offsetY) |
434 | { |
435 | + bool ltr = GetDirection() == LeftToRight; |
436 | Geometry geo = GetGeometry(); |
437 | int w = 0; |
438 | int h = 0; |
439 | @@ -675,6 +706,8 @@ |
440 | h = _hscrollbar->GetBaseHeight(); |
441 | |
442 | m_ViewX = GetBaseX() + m_border + m_ViewContentLeftMargin; |
443 | + if (!ltr) |
444 | + m_ViewX += w; |
445 | m_ViewY = GetBaseY() + m_top_border + m_ViewContentTopMargin; |
446 | |
447 | if (m_vertical_scrollbar_enable == false) |
448 | @@ -712,7 +745,10 @@ |
449 | else |
450 | _hscrollbar->SetBaseWidth(GetBaseWidth() - w - 2 * m_border); |
451 | |
452 | - _hscrollbar->SetBaseX(geo.x + m_border); |
453 | + if (ltr || !m_vertical_scrollbar_enable) |
454 | + _hscrollbar->SetBaseX(geo.x + m_border); |
455 | + else |
456 | + _hscrollbar->SetBaseX(geo.x + m_border + w); |
457 | _hscrollbar->SetBaseY(geo.y + geo.GetHeight() - _hscrollbar->GetBaseHeight() - m_border); |
458 | _hscrollbar->ComputeContentSize(); |
459 | } |
460 | @@ -725,7 +761,10 @@ |
461 | else |
462 | _vscrollbar->SetBaseHeight(GetBaseHeight() - h - m_top_border - m_border); |
463 | |
464 | - _vscrollbar->SetBaseX(geo.x + geo.GetWidth() - w - m_border); |
465 | + if (ltr) |
466 | + _vscrollbar->SetBaseX(geo.x + geo.GetWidth() - w - m_border); |
467 | + else |
468 | + _vscrollbar->SetBaseX(geo.x + m_border); |
469 | _vscrollbar->SetBaseY(geo.y + m_top_border); |
470 | _vscrollbar->ComputeContentSize(); |
471 | } |
472 | |
473 | === modified file 'Nux/VSplitter.cpp' |
474 | --- Nux/VSplitter.cpp 2011-12-06 16:29:06 +0000 |
475 | +++ Nux/VSplitter.cpp 2012-04-18 22:03:19 +0000 |
476 | @@ -118,6 +118,7 @@ |
477 | graphics_engine.PushClippingRectangle(GetGeometry()); |
478 | Geometry base = GetGeometry(); |
479 | bool need_redraw = IsRedrawNeeded(); |
480 | + bool ltr = GetDirection() == LeftToRight; |
481 | |
482 | std::vector<MySplitter *>::iterator it_splitter; |
483 | std::vector<Area *>::iterator it; |
484 | @@ -127,10 +128,17 @@ |
485 | it++, it_splitter++) |
486 | { |
487 | Geometry sgeo = (*it_splitter)->GetGeometry(); |
488 | - graphics_engine.PushClippingRectangle(Rect( |
489 | - base.x, base.y, sgeo.x - base.x, base.GetHeight())); |
490 | + Rect clip; |
491 | + if (ltr) |
492 | + clip = Rect(base.x, base.y, sgeo.x - base.x, base.GetHeight()); |
493 | + else |
494 | + clip = Rect(sgeo.x + sgeo.GetWidth(), base.y, base.x + base.GetWidth() - sgeo.x - sgeo.GetWidth(), base.GetHeight()); |
495 | + graphics_engine.PushClippingRectangle(clip); |
496 | |
497 | - base.SetX(sgeo.x + sgeo.GetWidth()); |
498 | + if (ltr) |
499 | + base.SetX(sgeo.x + sgeo.GetWidth()); |
500 | + else |
501 | + base.SetWidth(sgeo.x - base.x); |
502 | |
503 | if (force_draw || need_redraw) |
504 | { |
505 | @@ -193,6 +201,7 @@ |
506 | void VSplitter::OverlayDrawing(GraphicsEngine &graphics_engine) |
507 | { |
508 | unsigned int num_element = (unsigned int) m_SplitterObject.size(); |
509 | + bool ltr = GetDirection() == LeftToRight; |
510 | |
511 | Geometry base = GetGeometry(); |
512 | |
513 | @@ -203,27 +212,33 @@ |
514 | |
515 | if (m_focus_splitter_index == 0 && num_element > 1) |
516 | { |
517 | - if (geo.x < base.x) |
518 | + if (( ltr && geo.x < base.x) || |
519 | + (!ltr && geo.x > base.x + base.GetWidth() - VSPLITTERWIDTH)) |
520 | { |
521 | - geo.SetX(base.x); |
522 | + geo.SetX(base.x + (ltr ? 0 : (base.GetWidth() - VSPLITTERWIDTH))); |
523 | } |
524 | |
525 | - if (geo.x + VSPLITTERWIDTH > m_SplitterObject[m_focus_splitter_index + 1]->GetGeometry().x) |
526 | + if (( ltr && geo.x + VSPLITTERWIDTH > m_SplitterObject[m_focus_splitter_index + 1]->GetGeometry().x) || |
527 | + (!ltr && geo.x - VSPLITTERWIDTH < m_SplitterObject[m_focus_splitter_index + 1]->GetGeometry().x)) |
528 | { |
529 | - geo.SetX(m_SplitterObject[m_focus_splitter_index+1]->GetGeometry().x - VSPLITTERWIDTH); |
530 | + geo.SetX(m_SplitterObject[m_focus_splitter_index+1]->GetGeometry().x + (ltr ? - VSPLITTERWIDTH : + VSPLITTERWIDTH)); |
531 | } |
532 | } |
533 | |
534 | if ((m_focus_splitter_index > 0) && m_focus_splitter_index < (int) num_element - 1) |
535 | { |
536 | - if (geo.x < m_SplitterObject[m_focus_splitter_index - 1]->GetGeometry().x + VSPLITTERWIDTH) |
537 | + if (( ltr && geo.x < m_SplitterObject[m_focus_splitter_index - 1]->GetGeometry().x + VSPLITTERWIDTH) || |
538 | + (!ltr && geo.x > m_SplitterObject[m_focus_splitter_index - 1]->GetGeometry().x - VSPLITTERWIDTH)) |
539 | { |
540 | - geo.SetX(m_SplitterObject[m_focus_splitter_index - 1]->GetGeometry().x + VSPLITTERWIDTH); |
541 | + geo.SetX(m_SplitterObject[m_focus_splitter_index - 1]->GetGeometry().x + |
542 | + (ltr ? VSPLITTERWIDTH : - VSPLITTERWIDTH)); |
543 | } |
544 | |
545 | - if (geo.x + VSPLITTERWIDTH > m_SplitterObject[m_focus_splitter_index + 1]->GetGeometry().x) |
546 | + if (( ltr && geo.x + VSPLITTERWIDTH > m_SplitterObject[m_focus_splitter_index + 1]->GetGeometry().x) || |
547 | + (!ltr && geo.x - VSPLITTERWIDTH < m_SplitterObject[m_focus_splitter_index + 1]->GetGeometry().x)) |
548 | { |
549 | - geo.SetX(m_SplitterObject[m_focus_splitter_index + 1]->GetGeometry().x - VSPLITTERWIDTH); |
550 | + geo.SetX(m_SplitterObject[m_focus_splitter_index + 1]->GetGeometry().x + |
551 | + (ltr ? - VSPLITTERWIDTH : VSPLITTERWIDTH)); |
552 | } |
553 | } |
554 | |
555 | @@ -265,6 +280,7 @@ |
556 | |
557 | long VSplitter::ComputeContentSize() |
558 | { |
559 | + bool ltr = GetDirection() == LeftToRight; |
560 | unsigned int num_element = (unsigned int) m_InterfaceObject.size(); |
561 | int x = GetBaseX(); |
562 | int y = GetBaseY(); |
563 | @@ -312,7 +328,11 @@ |
564 | { |
565 | int size_to_distribute = w - num_element * VSPLITTERWIDTH; |
566 | int previous_spliter_end = m_current_x; |
567 | + if (!ltr) |
568 | + previous_spliter_end += m_current_width; |
569 | int new_spliter_end = x; |
570 | + if (!ltr) |
571 | + new_spliter_end += w; |
572 | |
573 | for (unsigned int i = 0; i < num_element; i++) |
574 | { |
575 | @@ -320,37 +340,64 @@ |
576 | // compute percentage of space occupied by the element i; |
577 | // width of element i = m_SplitterObject[i]->GetX() - previous_splliter_end |
578 | int splitter_start = m_SplitterObject[i]->GetBaseX(); |
579 | + if (!ltr) |
580 | + splitter_start += VSPLITTERWIDTH; |
581 | float percent = float(splitter_start - previous_spliter_end) / float(m_current_width - num_element * VSPLITTERWIDTH); |
582 | + if (!ltr) |
583 | + percent = -percent; |
584 | |
585 | if (percent > 1.0f) |
586 | percent = 1.0f; |
587 | |
588 | - splitter_geo.SetX(new_spliter_end + size_to_distribute * percent); |
589 | - previous_spliter_end = splitter_start + VSPLITTERWIDTH; |
590 | - new_spliter_end = new_spliter_end + size_to_distribute * percent + VSPLITTERWIDTH; |
591 | + if (ltr) |
592 | + { |
593 | + splitter_geo.SetX(new_spliter_end + size_to_distribute * percent); |
594 | + previous_spliter_end = splitter_start + VSPLITTERWIDTH; |
595 | + new_spliter_end = new_spliter_end + size_to_distribute * percent + VSPLITTERWIDTH; |
596 | + } |
597 | + else |
598 | + { |
599 | + splitter_geo.SetX(new_spliter_end - size_to_distribute * percent - VSPLITTERWIDTH); |
600 | + previous_spliter_end = splitter_start - VSPLITTERWIDTH; |
601 | + new_spliter_end = new_spliter_end - size_to_distribute * percent + VSPLITTERWIDTH; |
602 | + } |
603 | m_SplitterObject[i]->SetGeometry(splitter_geo); |
604 | } |
605 | |
606 | - if (m_SplitterObject[0]->GetBaseX() < x) |
607 | + if (ltr && m_SplitterObject[0]->GetBaseX() < x) |
608 | { |
609 | m_SplitterObject[0]->SetBaseX(x); |
610 | } |
611 | + else if (!ltr && m_SplitterObject[0]->GetBaseX() > x + w - VSPLITTERWIDTH) |
612 | + { |
613 | + m_SplitterObject[0]->SetBaseX(x + w - VSPLITTERWIDTH); |
614 | + } |
615 | |
616 | - m_SplitterObject[num_element-1]->SetBaseX(x + w - VSPLITTERWIDTH); |
617 | + if (ltr) |
618 | + m_SplitterObject[num_element-1]->SetBaseX(x + w - VSPLITTERWIDTH); |
619 | + else |
620 | + m_SplitterObject[num_element-1]->SetBaseX(x); |
621 | } |
622 | |
623 | int accwidth = x; |
624 | + if (!ltr) |
625 | + accwidth += w; |
626 | |
627 | for (unsigned int i = 0; i < num_element; i++) |
628 | { |
629 | Geometry splitter_geo = m_SplitterObject[i]->GetGeometry(); |
630 | + Geometry element_geo; |
631 | + if (ltr) |
632 | + element_geo = Geometry(accwidth, y, splitter_geo.x - accwidth, h); |
633 | + else |
634 | + element_geo = Geometry(splitter_geo.x + VSPLITTERWIDTH, y, accwidth - splitter_geo.x - VSPLITTERWIDTH, h); |
635 | |
636 | - //m_InterfaceObject[i]->SetGeometry(Geometry(accwidth, y, splitter_geo.x - accwidth, h)); |
637 | + //m_InterfaceObject[i]->SetGeometry(element_geo); |
638 | |
639 | if (m_InterfaceObject[i]->Type().IsDerivedFromType(View::StaticObjectType)) |
640 | { |
641 | View *ic = NUX_STATIC_CAST(View *, m_InterfaceObject[i]); |
642 | - ic->SetGeometry(Geometry(accwidth, y, splitter_geo.x - accwidth, h)); |
643 | + ic->SetGeometry(element_geo); |
644 | // if we are already computing the layout from the main window down, we need to call |
645 | // ComputeElementLayout to force the computing of this element layout. |
646 | GetWindowThread()->ComputeElementLayout(ic); |
647 | @@ -358,18 +405,21 @@ |
648 | else if (m_InterfaceObject[i]->Type().IsObjectType(InputArea::StaticObjectType)) |
649 | { |
650 | InputArea *base_area = NUX_STATIC_CAST(InputArea *, m_InterfaceObject[i]); |
651 | - base_area->SetGeometry(Geometry(accwidth, y, splitter_geo.x - accwidth, h)); |
652 | + base_area->SetGeometry(element_geo); |
653 | } |
654 | else if (m_InterfaceObject[i]->Type().IsDerivedFromType(Layout::StaticObjectType)) |
655 | { |
656 | Layout *layout = NUX_STATIC_CAST(Layout *, m_InterfaceObject[i]); |
657 | - layout->SetGeometry(Geometry(accwidth, y, splitter_geo.x - accwidth, h)); |
658 | + layout->SetGeometry(element_geo); |
659 | // if we are already computing the layout from the main window down, we need to call |
660 | // ComputeElementLayout to force the computing of this element layout. |
661 | GetWindowThread()->ComputeElementLayout(layout); |
662 | } |
663 | |
664 | - accwidth += splitter_geo.x - accwidth + VSPLITTERWIDTH; |
665 | + if (ltr) |
666 | + accwidth += splitter_geo.x - accwidth + VSPLITTERWIDTH; |
667 | + else |
668 | + accwidth = splitter_geo.x; |
669 | } |
670 | |
671 | m_current_height = h; |
672 | @@ -382,7 +432,10 @@ |
673 | |
674 | void VSplitter::ResetSplitConfig() |
675 | { |
676 | + bool ltr = GetDirection() == LeftToRight; |
677 | int x = GetBaseX(); |
678 | + if (!ltr) |
679 | + x += GetBaseWidth(); |
680 | int y = GetBaseY(); |
681 | int w = GetBaseWidth(); |
682 | int h = GetBaseHeight(); |
683 | @@ -420,12 +473,18 @@ |
684 | for (unsigned int i = 0; i < (unsigned int) m_SplitConfig.size(); i++) |
685 | { |
686 | stretchfactor = m_SplitConfig[i]; |
687 | - x += stretchfactor * max_size / max_stretch; |
688 | + if (ltr) |
689 | + x += stretchfactor * max_size / max_stretch; |
690 | + else |
691 | + x -= stretchfactor * max_size / max_stretch + VSPLITTERWIDTH; |
692 | Geometry geo(x, y, VSPLITTERWIDTH, h); |
693 | m_SplitterObject[i]->SetGeometry(geo); |
694 | } |
695 | |
696 | - m_SplitterObject[num_element-1]->SetBaseX(x + w - VSPLITTERWIDTH); |
697 | + if (ltr) |
698 | + m_SplitterObject[num_element-1]->SetBaseX(GetBaseX() + w - VSPLITTERWIDTH); |
699 | + else |
700 | + m_SplitterObject[num_element-1]->SetBaseX(GetBaseX()); |
701 | |
702 | m_initial_config = true; |
703 | } |
704 | @@ -443,6 +502,7 @@ |
705 | |
706 | void VSplitter::OnSplitterMouseUp(int x, int y, unsigned long button_flags, unsigned long key_flags, int header_pos) |
707 | { |
708 | + bool ltr = GetDirection() == LeftToRight; |
709 | if (mvt_dx) |
710 | { |
711 | Geometry geo = m_SplitterObject[header_pos]->GetGeometry(); |
712 | @@ -453,8 +513,9 @@ |
713 | if (header_pos < (int) num_element - 1) |
714 | { |
715 | // Make the splitter bar stick to the next one if the distance between them is less than VSTICK_SIZE |
716 | - if (m_SplitterObject[header_pos + 1]->GetGeometry().x - geo.x - VSPLITTERWIDTH < VSTICK_SIZE) |
717 | - geo.SetX( m_SplitterObject[header_pos + 1]->GetGeometry().x - VSPLITTERWIDTH ); |
718 | + if (( ltr && m_SplitterObject[header_pos + 1]->GetGeometry().x - geo.x - VSPLITTERWIDTH < VSTICK_SIZE) || |
719 | + (!ltr && m_SplitterObject[header_pos + 1]->GetGeometry().x - geo.x + VSPLITTERWIDTH > -VSTICK_SIZE)) |
720 | + geo.SetX( m_SplitterObject[header_pos + 1]->GetGeometry().x + (ltr ? - VSPLITTERWIDTH : + VSPLITTERWIDTH)); |
721 | } |
722 | |
723 | m_SplitterObject[header_pos]->SetGeometry(geo); |
724 | @@ -505,15 +566,22 @@ |
725 | { |
726 | Geometry geo = m_SplitterObject[header_pos]->GetGeometry(); |
727 | int num_element = (int) m_SplitterObject.size(); |
728 | + bool ltr = GetDirection() == LeftToRight; |
729 | + int leftmost_x = GetBaseX(); |
730 | + int rightmost_x = GetBaseX() + GetBaseWidth() - VSPLITTERWIDTH; |
731 | |
732 | - if ((header_pos == 0) && (m_SplitterObject[header_pos]->GetBaseX() < GetBaseX())) |
733 | + if ((header_pos == 0) && ( |
734 | + ( ltr && m_SplitterObject[header_pos]->GetBaseX() < leftmost_x) || |
735 | + (!ltr && m_SplitterObject[header_pos]->GetBaseX() > rightmost_x))) |
736 | { |
737 | - m_SplitterObject[header_pos]->SetBaseX(GetBaseX()); |
738 | + m_SplitterObject[header_pos]->SetBaseX(ltr ? leftmost_x : rightmost_x); |
739 | } |
740 | |
741 | - if ((header_pos == num_element - 1) && (m_SplitterObject[header_pos]->GetBaseX() > GetBaseX() + GetBaseWidth() - VSPLITTERWIDTH)) |
742 | + if ((header_pos == num_element - 1) && ( |
743 | + ( ltr && m_SplitterObject[header_pos]->GetBaseX() > rightmost_x) || |
744 | + (!ltr && m_SplitterObject[header_pos]->GetBaseX() < leftmost_x))) |
745 | { |
746 | - m_SplitterObject[header_pos]->SetBaseX(GetBaseX() + GetBaseWidth() - VSPLITTERWIDTH); |
747 | + m_SplitterObject[header_pos]->SetBaseX(ltr ? rightmost_x : leftmost_x); |
748 | } |
749 | |
750 | if (header_pos < (int) num_element - 1) |
751 | @@ -522,9 +590,10 @@ |
752 | posx0 = m_SplitterObject[header_pos]->GetBaseX(); |
753 | posx1 = m_SplitterObject[header_pos + 1]->GetBaseX(); |
754 | |
755 | - if (posx0 > posx1 - VSPLITTERWIDTH) |
756 | + if (( ltr && posx0 > posx1 - VSPLITTERWIDTH) || |
757 | + (!ltr && posx0 < posx1 + VSPLITTERWIDTH)) |
758 | { |
759 | - posx0 = posx1 - VSPLITTERWIDTH; |
760 | + posx0 = posx1 + (ltr ? - VSPLITTERWIDTH : + VSPLITTERWIDTH); |
761 | m_SplitterObject[header_pos]->SetBaseX(posx0); |
762 | } |
763 | } |
764 | @@ -535,9 +604,10 @@ |
765 | posx0 = m_SplitterObject[header_pos]->GetBaseX(); |
766 | posx1 = m_SplitterObject[header_pos - 1]->GetBaseX(); |
767 | |
768 | - if (posx0 < posx1 + VSPLITTERWIDTH) |
769 | + if (( ltr && posx0 < posx1 + VSPLITTERWIDTH) || |
770 | + (!ltr && posx0 > posx1 - VSPLITTERWIDTH)) |
771 | { |
772 | - posx0 = posx1 + VSPLITTERWIDTH; |
773 | + posx0 = posx1 + (ltr ? VSPLITTERWIDTH : - VSPLITTERWIDTH); |
774 | m_SplitterObject[header_pos]->SetBaseX(posx0); |
775 | } |
776 | } |
777 | |
778 | === modified file 'tests/Helpers.cpp' |
779 | --- tests/Helpers.cpp 2011-07-15 04:00:00 +0000 |
780 | +++ tests/Helpers.cpp 2012-04-18 22:03:19 +0000 |
781 | @@ -25,11 +25,16 @@ |
782 | #include <fstream> |
783 | #include <stdexcept> |
784 | |
785 | +#include <Nux/Nux.h> |
786 | + |
787 | namespace nux |
788 | { |
789 | namespace testing |
790 | { |
791 | |
792 | +nux::TimerFunctor* g_timer = NULL; |
793 | +nux::TimerHandle g_handler = NULL; |
794 | + |
795 | std::string ReadFile(std::string const& filename) |
796 | { |
797 | std::ifstream input(filename.c_str()); |
798 | @@ -47,6 +52,48 @@ |
799 | } |
800 | } |
801 | |
802 | - |
803 | -} |
804 | -} |
805 | +struct ThreadData |
806 | +{ |
807 | + TestFunc func; |
808 | + nux::TimerFunctor* timer; |
809 | + nux::TimerHandle handler; |
810 | + |
811 | + ThreadData(TestFunc func) : func(func), timer(NULL) {} |
812 | +}; |
813 | + |
814 | +void |
815 | +terminate (void* data) |
816 | +{ |
817 | + nux::WindowThread* thread = NUX_STATIC_CAST (nux::WindowThread*, data); |
818 | + thread->ExitMainLoop(); |
819 | +} |
820 | + |
821 | +void |
822 | +init (nux::NThread* thread, void* data) |
823 | +{ |
824 | + TestFunc func = (TestFunc) data; |
825 | + |
826 | + (func) (); |
827 | + |
828 | + g_timer = new nux::TimerFunctor (); |
829 | + g_timer->time_expires.connect (sigc::ptr_fun (&terminate)); |
830 | + g_handler = nux::GetTimer().AddTimerHandler (100, |
831 | + g_timer, |
832 | + nux::GetWindowThread ()); |
833 | +} |
834 | + |
835 | +void |
836 | +run_test (TestFunc func) |
837 | +{ |
838 | + nux::WindowThread* wt = NULL; |
839 | + |
840 | + wt = nux::CreateGUIThread (TEXT ("Canvas Test"), 400, 400, 0, &init, (void*) func); |
841 | + wt->Run (NULL); |
842 | + delete wt; |
843 | + delete g_timer; |
844 | + g_timer = NULL; |
845 | +} |
846 | + |
847 | +} |
848 | +} |
849 | + |
850 | |
851 | === modified file 'tests/Helpers.h' |
852 | --- tests/Helpers.h 2011-07-15 04:00:00 +0000 |
853 | +++ tests/Helpers.h 2012-04-18 22:03:19 +0000 |
854 | @@ -26,7 +26,6 @@ |
855 | #include <glib.h> |
856 | #include <sigc++/sigc++.h> |
857 | |
858 | - |
859 | namespace nux |
860 | { |
861 | namespace testing |
862 | @@ -56,6 +55,8 @@ |
863 | bool happened; |
864 | }; |
865 | |
866 | +typedef void (*TestFunc)(void); |
867 | +void run_test(TestFunc func); |
868 | |
869 | } |
870 | } |
871 | |
872 | === modified file 'tests/Makefile.am' |
873 | --- tests/Makefile.am 2012-03-28 18:29:23 +0000 |
874 | +++ tests/Makefile.am 2012-04-18 22:03:19 +0000 |
875 | @@ -64,6 +64,8 @@ |
876 | -lboost_filesystem -lboost_system |
877 | |
878 | gtest_nux_SOURCES = \ |
879 | + Helpers.h \ |
880 | + Helpers.cpp \ |
881 | gtest-nux-area.cpp \ |
882 | gtest-nux-cairo-wrapper.cpp \ |
883 | gtest-nux-emmetrics.cpp \ |
884 | @@ -72,7 +74,8 @@ |
885 | gtest-nux-textentry.cpp \ |
886 | gtest-nux-view.cpp \ |
887 | gtest-nux-windowcompositor.cpp \ |
888 | - gtest-nux-windowthread.cpp |
889 | + gtest-nux-windowthread.cpp \ |
890 | + gtest-nux-hlayout.cpp |
891 | |
892 | gtest_nux_CPPFLAGS = \ |
893 | -I$(srcdir) \ |
894 | |
895 | === modified file 'tests/gtest-nux-cairo-wrapper.cpp' |
896 | --- tests/gtest-nux-cairo-wrapper.cpp 2012-02-24 05:40:23 +0000 |
897 | +++ tests/gtest-nux-cairo-wrapper.cpp 2012-04-18 22:03:19 +0000 |
898 | @@ -26,10 +26,9 @@ |
899 | |
900 | #include <iostream> |
901 | |
902 | -typedef void (*TestFunc)(void); |
903 | +#include "Helpers.h" |
904 | |
905 | -nux::TimerFunctor* g_timer = NULL; |
906 | -nux::TimerHandle g_handler = NULL; |
907 | +using nux::testing::run_test; |
908 | |
909 | void |
910 | callback_one (nux::Geometry const& geom, cairo_t* cr) |
911 | @@ -70,39 +69,6 @@ |
912 | } |
913 | |
914 | void |
915 | -terminate (void* data) |
916 | -{ |
917 | - nux::WindowThread* thread = NUX_STATIC_CAST (nux::WindowThread*, data); |
918 | - thread->ExitMainLoop(); |
919 | -} |
920 | - |
921 | -void |
922 | -init (nux::NThread* thread, void* data) |
923 | -{ |
924 | - TestFunc func = (TestFunc) data; |
925 | - |
926 | - (func) (); |
927 | - |
928 | - g_timer = new nux::TimerFunctor (); |
929 | - g_timer->time_expires.connect (sigc::ptr_fun (&terminate)); |
930 | - g_handler = nux::GetTimer().AddTimerHandler (100, |
931 | - g_timer, |
932 | - nux::GetWindowThread ()); |
933 | -} |
934 | - |
935 | -void |
936 | -run_test (TestFunc func) |
937 | -{ |
938 | - nux::WindowThread* wt = NULL; |
939 | - |
940 | - wt = nux::CreateGUIThread (TEXT ("Canvas Test"), 400, 400, 0, &init, (void*) func); |
941 | - wt->Run (NULL); |
942 | - delete wt; |
943 | - delete g_timer; |
944 | - g_timer = NULL; |
945 | -} |
946 | - |
947 | -void |
948 | test_construction () |
949 | { |
950 | nux::Geometry geom_one = {0, 0, 100, 100}; |
951 | |
952 | === added file 'tests/gtest-nux-hlayout.cpp' |
953 | --- tests/gtest-nux-hlayout.cpp 1970-01-01 00:00:00 +0000 |
954 | +++ tests/gtest-nux-hlayout.cpp 2012-04-18 22:03:19 +0000 |
955 | @@ -0,0 +1,121 @@ |
956 | +/* |
957 | + * Copyright 2011 |
958 | + * |
959 | + * This program is free software: you can redistribute it and/or modify it |
960 | + * under the terms of the GNU Lesser General Public License version 3, as |
961 | + * published by the Free Software Foundation. |
962 | + * |
963 | + * This program is distributed in the hope that it will be useful, but |
964 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
965 | + * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR |
966 | + * PURPOSE. See the applicable version of the GNU Lesser General Public |
967 | + * License for more details. |
968 | + * |
969 | + * You should have received a copy of both the GNU Lesser General Public |
970 | + * License version 3 along with this program. If not, see |
971 | + * <http://www.gnu.org/licenses/> |
972 | + * |
973 | + * Authored by: Haggai Eran <haggai.eran@gmail.com> |
974 | + * |
975 | + */ |
976 | + |
977 | +#include <gmock/gmock.h> |
978 | + |
979 | +#include "Nux/Nux.h" |
980 | +#include "Nux/HLayout.h" |
981 | + |
982 | +#include "Helpers.h" |
983 | + |
984 | +#include <iostream> |
985 | +#include <list> |
986 | + |
987 | +using namespace testing; |
988 | +using nux::testing::run_test; |
989 | + |
990 | +using nux::HLayout; |
991 | +using nux::Area; |
992 | +using nux::Geometry; |
993 | + |
994 | +using std::ostream; |
995 | +using std::list; |
996 | + |
997 | +namespace { |
998 | + |
999 | +ostream& operator<<(ostream& out, const Geometry& r) |
1000 | +{ |
1001 | + return out << "Geometry(" << r.x << ", " << r.y << ", " << r.width << ", " << r.height << ")"; |
1002 | +} |
1003 | + |
1004 | +list<Area*> fill_test_layout(HLayout* layout) |
1005 | +{ |
1006 | + EXPECT_THAT(layout, NotNull()); |
1007 | + |
1008 | + list<Area*> areas; |
1009 | + |
1010 | + for (int i = 0; i < 3; ++i) |
1011 | + { |
1012 | + Area* area = new Area(NUX_TRACKER_LOCATION); |
1013 | + EXPECT_THAT(area, NotNull()); |
1014 | + area->SetMinimumSize(50, 60); |
1015 | + layout->AddView(area); |
1016 | + areas.push_back(area); |
1017 | + } |
1018 | + |
1019 | + return areas; |
1020 | +} |
1021 | + |
1022 | +void test_hlayout_ltr() |
1023 | +{ |
1024 | + nux::SetDefaultDirection(nux::LeftToRight); |
1025 | + |
1026 | + HLayout* layout = new HLayout(NUX_TRACKER_LOCATION); |
1027 | + list<Area*> areas = fill_test_layout(layout); |
1028 | + |
1029 | + Geometry geo(10,10,300,100); |
1030 | + layout->SetGeometry(geo); |
1031 | + layout->ComputeContentPosition(0, 0); |
1032 | + |
1033 | + EXPECT_EQ(geo, layout->GetGeometry()); |
1034 | + |
1035 | + list<Area*>::const_iterator it = areas.begin(); |
1036 | + for (int i = 0; it != areas.end(); ++i, ++it) |
1037 | + { |
1038 | + geo = Geometry(10 + 50 * i, 10, 50, 60); |
1039 | + EXPECT_EQ(geo, (*it)->GetGeometry()); |
1040 | + } |
1041 | + |
1042 | + layout->UnReference(); |
1043 | +} |
1044 | + |
1045 | +void test_hlayout_rtl() |
1046 | +{ |
1047 | + nux::SetDefaultDirection(nux::RightToLeft); |
1048 | + |
1049 | + HLayout* layout = new HLayout(NUX_TRACKER_LOCATION); |
1050 | + list<Area*> areas = fill_test_layout(layout); |
1051 | + |
1052 | + Geometry geo(10,10,300,100); |
1053 | + layout->SetGeometry(geo); |
1054 | + layout->ComputeContentPosition(0, 0); |
1055 | + |
1056 | + EXPECT_EQ(geo, layout->GetGeometry()); |
1057 | + |
1058 | + list<Area*>::const_iterator it = areas.begin(); |
1059 | + for (int i = 0; it != areas.end(); ++i, ++it) |
1060 | + { |
1061 | + geo = Geometry(310 - 50 * (i + 1), 10, 50, 60); |
1062 | + EXPECT_EQ(geo, (*it)->GetGeometry()); |
1063 | + } |
1064 | + |
1065 | + layout->UnReference(); |
1066 | +} |
1067 | + |
1068 | +TEST(TestHLayout, LTR) { |
1069 | + run_test(test_hlayout_ltr); |
1070 | +} |
1071 | + |
1072 | +TEST(TestHLayout, RTL) { |
1073 | + run_test(test_hlayout_rtl); |
1074 | +} |
1075 | + |
1076 | +} |
Just a few minor style things from me:
* member variables should have trailing not leading underscore
(parts being updated as we get to them)
* no space before function call parenthesis
* please use C++ style enum definitions (not typedef)
enum Direction
{
// values...
};
I'll let Jay do the actual functionality bits.