Nux

Merge lp:~haggai-eran/nux/rtl-logical-packing into lp:nux/2.0

Proposed by Haggai Eran
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
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

To post a comment you must log in.
Revision history for this message
Tim Penhey (thumper) wrote :

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.

review: Needs Fixing
532. By Haggai Eran

Fix several coding style issues.

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

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

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

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

[1] https://lists.launchpad.net/unity-design/msg08745.html

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

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

Subscribers

People subscribed via source and target branches