Nux

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

Proposed by Haggai Eran
Status: Superseded
Proposed branch: lp:~haggai-eran/nux/rtl-rebased
Merge into: lp:nux/2.0
Diff against target: 678 lines (+207/-97)
7 files modified
Nux/Area.cpp (+11/-0)
Nux/Area.h (+16/-0)
Nux/HLayout.cpp (+146/-97)
Nux/Layout.cpp (+16/-0)
Nux/Layout.h (+3/-0)
Nux/Nux.cpp (+12/-0)
Nux/Nux.h (+3/-0)
To merge this branch: bzr merge lp:~haggai-eran/nux/rtl-rebased
Reviewer Review Type Date Requested Status
Jay Taoko Pending
Review via email: mp+82225@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,

Here's my branch rebased against trunk. I hope the changes are more clear now.

There's still a problem with this patch to HLayout, though. When in right-to-left state, it packs child elements to the layout starting from the last on the list, instead of starting from the first, in order to get them in reverse order. However, it seems that for some of the widgets this doesn't work very well. I checked the CheckBox example, and the AbstractCheckedButton::ComputeContentSize code depends on the fact that the HLayout will first allocate space to the checkbox, and afterwards to the label. When using a right-to-left direction, the label is laid out first, and then the checkbox is positioned out of the widget's bounds.

Should I change my patch to pack the children in their logical order, starting from the rightmost edge, or should I leave the code as it is, and try to fix uses like the AbstractCheckedButton?

Regards,
Haggai

To post a comment you must log in.
Revision history for this message
Jay Taoko (jaytaoko) wrote :

Haggai

Selecting right to left has to be done per layout. Lets say you have an horizontal layout that has a checkbox followed by a button, and the button is followed by a combobox. In LTR order you get this:
 checkbox | button | combobox

If you make the HLayout to be RTL then the content will look like this:

 combobox| button | checkbox

This should work out fine because only a specific HLayout has been been changed to RTL.

So you have to select only the layouts of the interface that need to be inverted. Rather than having SetDefaultDirection in Nux.cpp, it should be a function member of LinearLayout. Then for each layout (HLayout or VLayout), you will be able to decide if it goes from LTR or RTL. Individual views like the Checkbox, will remain un-affected.

How about that?

Revision history for this message
Haggai Eran (haggai-eran) wrote :

Jay,

I agree that we should be able to set directionality on per-layout basis. I even implemented it as a member of Area. However, I think that the default when using an RTL locale should be right to left, for all widgets, and not just specific HLayouts.

In the example you described, you could show the detailed widgets like this (in LTR):

[ combobox ↓ | button | [x] checkbox ]

Then, I expect the RTL rendering to be like this:

[ checkbox [x] | button | ↓ combobox ]

The internal layout of comboboxes and checkboxes should also be mirrored.

Please compare how GTK looks in LTR and RTL in the following two screenshots of the widget factory:
http://i44.tinypic.com/2lks0e8.jpg
http://i43.tinypic.com/25ri0ds.png

Haggai

Revision history for this message
Jay Taoko (jaytaoko) wrote :

Ok, I see how it is. I think many widget will have to have support for a RTL design.
But first we can get this branch in since it has global support for RTL at the layout level. Then the next step would be to go to each individual widgets that requires it and review the design.

It is up to me now to review and adapt this branch and see that we can merge it. We now have the requirement of proposing tests along side major features. Can you think of some way we can test the features of this branch?

Revision history for this message
Haggai Eran (haggai-eran) wrote :

Hi,

I think that perhaps rewriting the code to pack in the same order as in LTR might still have some advantages. I've tried to think on how that would work. Instead of walking the list of HLayout children in reverse, and packing them to the left, I'll walk the list in the usual order, and pack from right to left.

As far as I can see, I would only need to change HLayout::ComputeContentSize, and HLayout::ComputeContentPosition, which would make the changes simpler. I'm sure in both cases other widget will need to be modified, but if any widget's layout depends on the order of children's placement, then that order wouldn't change.

Regarding tests, I suppose that a tests for HLayout can be modified to test the RTL case as well, but I cannot find such a test (perhaps my tree isn't updated). I imagine a test that creates an HLayout, with several children that are using different settings for scaling, vertical placement, etc. and asserting there placement. What do you think?

Unmerged revisions

521. By Haggai Eran

Change LayoutContentDistribution only when in RTL mode.

520. By Haggai Eran

More HLayout changes toward right-to-left support.

519. By Haggai Eran

Add right-to-left mirroring support. Implement mirroring for HLayout.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'Nux/Area.cpp'
--- Nux/Area.cpp 2011-10-18 21:10:05 +0000
+++ Nux/Area.cpp 2011-11-14 21:17:09 +0000
@@ -39,6 +39,7 @@
39 , geometry_(0, 0, DEFAULT_WIDGET_WIDTH, DEFAULT_WIDGET_HEIGHT)39 , geometry_(0, 0, DEFAULT_WIDGET_WIDTH, DEFAULT_WIDGET_HEIGHT)
40 , min_size_(AREA_MIN_WIDTH, AREA_MIN_HEIGHT)40 , min_size_(AREA_MIN_WIDTH, AREA_MIN_HEIGHT)
41 , max_size_(AREA_MAX_WIDTH, AREA_MAX_HEIGHT)41 , max_size_(AREA_MAX_WIDTH, AREA_MAX_HEIGHT)
42 , _direction (GetDefaultDirection())
42 {43 {
43 visible_ = true;44 visible_ = true;
44 view_enabled_ = true;45 view_enabled_ = true;
@@ -1026,5 +1027,15 @@
10261027
1027 return false;1028 return false;
1028 }1029 }
1030
1031 Direction Area::GetDirection() const
1032 {
1033 return _direction;
1034 }
1035
1036 void Area::SetDirection(Direction direction)
1037 {
1038 _direction = direction;
1039 }
1029}1040}
10301041
10311042
=== modified file 'Nux/Area.h'
--- Nux/Area.h 2011-10-17 21:23:50 +0000
+++ Nux/Area.h 2011-11-14 21:17:09 +0000
@@ -140,6 +140,12 @@
140 KEY_NAV_ENTER,140 KEY_NAV_ENTER,
141 };141 };
142142
143 typedef enum
144 {
145 LeftToRight,
146 RightToLeft
147 } Direction;
148
143 class Layout;149 class Layout;
144 class View;150 class View;
145 class Area;151 class Area;
@@ -547,6 +553,14 @@
547 */553 */
548 bool AcceptMouseWheelEvent() const;554 bool AcceptMouseWheelEvent() const;
549555
556 //! Return the direction of the area.
557 Direction GetDirection() const;
558 //! Sets the direction of the area.
559 /*!
560 @param direction Either nux::LeftToRight or nux::RightToLeft
561 */
562 void SetDirection(Direction direction);
563
550 protected:564 protected:
551 /*565 /*
552 This function is reimplemented in Layout as it need to perform some special operations.566 This function is reimplemented in Layout as it need to perform some special operations.
@@ -633,6 +647,8 @@
633 bool _accept_mouse_wheel_event;647 bool _accept_mouse_wheel_event;
634 bool _accept_keyboard_event;648 bool _accept_keyboard_event;
635649
650 Direction _direction;
651
636 friend class Layout;652 friend class Layout;
637 friend class View;653 friend class View;
638 friend class WindowThread;654 friend class WindowThread;
639655
=== modified file 'Nux/HLayout.cpp'
--- Nux/HLayout.cpp 2011-10-21 22:06:35 +0000
+++ Nux/HLayout.cpp 2011-11-14 21:17:09 +0000
@@ -127,7 +127,7 @@
127 margin = 0;127 margin = 0;
128 }128 }
129129
130 LayoutContentDistribution stacking = GetContentDistribution();130 LayoutContentDistribution stacking = GetEffectiveContentDistribution();
131131
132 switch(stacking)132 switch(stacking)
133 {133 {
@@ -178,6 +178,8 @@
178 }178 }
179179
180 std::list<Area *>::iterator it;180 std::list<Area *>::iterator it;
181 std::list<Area *>::reverse_iterator revit;
182 Area* area;
181183
182 for (it = _layout_element_list.begin(); it != _layout_element_list.end(); it++)184 for (it = _layout_element_list.begin(); it != _layout_element_list.end(); it++)
183 {185 {
@@ -248,19 +250,24 @@
248 ComputeStacking(width, offset_space, space_after_element);250 ComputeStacking(width, offset_space, space_after_element);
249 current_x += offset_space;251 current_x += offset_space;
250252
251 for (it = _layout_element_list.begin(); it != _layout_element_list.end(); it++)253 revit = _layout_element_list.rbegin();
254 for (it = _layout_element_list.begin(); it != _layout_element_list.end(); it++, revit++)
252 {255 {
253 if (!(*it)->IsVisible())256 if (GetDirection() == LeftToRight)
257 area = *it;
258 else
259 area = *revit;
260 if (!area->IsVisible())
254 continue;261 continue;
255262
256 current_x += space_after_element;263 current_x += space_after_element;
257264
258 (*it)->SetBaseX(current_x);265 area->SetBaseX(current_x);
259 (*it)->SetBaseY(current_y);266 area->SetBaseY(current_y);
260267
261 MinorDimensionSize extend = (*it)->GetExtend();268 MinorDimensionSize extend = area->GetExtend();
262 MinorDimensionPosition positioning = (*it)->GetPositioning();269 MinorDimensionPosition positioning = area->GetPositioning();
263 float percentage = (*it)->GetPercentage();270 float percentage = area->GetPercentage();
264271
265 // Compute the size of an ellement in the minor dimension(vertical)272 // Compute the size of an ellement in the minor dimension(vertical)
266 switch(extend)273 switch(extend)
@@ -270,7 +277,7 @@
270 // The size of the processed element in the minor dimension is a percentage of layout minor dimension size.277 // The size of the processed element in the minor dimension is a percentage of layout minor dimension size.
271 // Note that children of the processed element may force it to have a bigger size.278 // Note that children of the processed element may force it to have a bigger size.
272 int percentage_height = (height * percentage) / 100.0f;279 int percentage_height = (height * percentage) / 100.0f;
273 (*it)->SetBaseHeight(percentage_height);280 area->SetBaseHeight(percentage_height);
274 break;281 break;
275 }282 }
276283
@@ -278,7 +285,7 @@
278 {285 {
279 // Force the element height to be the minimum has defined with SetMinimumHeight.286 // Force the element height to be the minimum has defined with SetMinimumHeight.
280 // The children of this element can force it to get larger.287 // The children of this element can force it to get larger.
281 (*it)->ApplyMinHeight();288 area->ApplyMinHeight();
282 break;289 break;
283 }290 }
284291
@@ -291,30 +298,30 @@
291 case MINOR_SIZE_FULL:298 case MINOR_SIZE_FULL:
292 default:299 default:
293 {300 {
294 (*it)->SetBaseHeight(height);301 area->SetBaseHeight(height);
295 break;302 break;
296 }303 }
297 }304 }
298305
299 // Compute the position of an element in the minor dimension.306 // Compute the position of an element in the minor dimension.
300 if ((*it)->GetBaseHeight() < height)307 if (area->GetBaseHeight() < height)
301 {308 {
302 int widget_height = (*it)->GetBaseHeight();309 int widget_height = area->GetBaseHeight();
303310
304 switch(positioning)311 switch(positioning)
305 {312 {
306 case MINOR_POSITION_START:313 case MINOR_POSITION_START:
307 {314 {
308 // do nothing315 // do nothing
309 (*it)->SetBaseY(current_y);316 area->SetBaseY(current_y);
310 break;317 break;
311 }318 }
312 case MINOR_POSITION_END:319 case MINOR_POSITION_END:
313 {320 {
314 if (widget_height < height)321 if (widget_height < height)
315 (*it)->SetBaseY(current_y + height - widget_height);322 area->SetBaseY(current_y + height - widget_height);
316 else323 else
317 (*it)->SetBaseY(current_y);324 area->SetBaseY(current_y);
318325
319 break;326 break;
320 }327 }
@@ -323,14 +330,14 @@
323 default:330 default:
324 {331 {
325 if (widget_height < height)332 if (widget_height < height)
326 (*it)->SetBaseY(current_y + (height - widget_height) / 2);333 area->SetBaseY(current_y + (height - widget_height) / 2);
327 else334 else
328 (*it)->SetBaseY(current_y);335 area->SetBaseY(current_y);
329 }336 }
330 }337 }
331 }338 }
332339
333 current_x += (*it)->GetBaseWidth() + space_after_element + space_between_children_;340 current_x += area->GetBaseWidth() + space_after_element + space_between_children_;
334 }341 }
335342
336 // Manage child layout343 // Manage child layout
@@ -351,9 +358,15 @@
351 // We check if that is the case and force a recompute.358 // We check if that is the case and force a recompute.
352 std::vector<int> FullSizeUnadjusted;359 std::vector<int> FullSizeUnadjusted;
353360
354 for (it = _layout_element_list.begin(); it != _layout_element_list.end(); it++)361 revit = _layout_element_list.rbegin();
362 for (it = _layout_element_list.begin(); it != _layout_element_list.end(); it++, revit++)
355 {363 {
356 if (!(*it)->IsVisible())364 if (GetDirection() == LeftToRight)
365 area = *it;
366 else
367 area = *revit;
368
369 if (!area->IsVisible())
357 continue;370 continue;
358 bool smaller_height = false;371 bool smaller_height = false;
359 bool larger_height = false;372 bool larger_height = false;
@@ -361,16 +374,16 @@
361 bool smaller_width = false;374 bool smaller_width = false;
362 int ret = 0;375 int ret = 0;
363376
364 if (((*it)->IsLayout() || (*it)->IsView()) /*&& ((*it)->IsLayoutDone() == false)*/ /*&& ((*it)->GetScaleFactor() != 0)*/)377 if ((area->IsLayout() || area->IsView()) /*&& (area->IsLayoutDone() == false)*/ /*&& (area->GetScaleFactor() != 0)*/)
365 {378 {
366 ret = (*it)->ComputeContentSize();379 ret = area->ComputeContentSize();
367380
368 larger_width = (ret & eLargerWidth) ? true : false;381 larger_width = (ret & eLargerWidth) ? true : false;
369 smaller_width = (ret & eSmallerWidth) ? true : false;382 smaller_width = (ret & eSmallerWidth) ? true : false;
370 smaller_height = (ret & eSmallerHeight) ? true : false;383 smaller_height = (ret & eSmallerHeight) ? true : false;
371 larger_height = (ret & eLargerHeight) ? true : false;384 larger_height = (ret & eLargerHeight) ? true : false;
372385
373 if ((larger_width || smaller_width) && ((*it)->IsLayoutDone() == false))386 if ((larger_width || smaller_width) && (area->IsLayoutDone() == false))
374 {387 {
375 // Stop computing the size of this layout. Its size was not convenient to its children. So the children size take priority388 // Stop computing the size of this layout. Its size was not convenient to its children. So the children size take priority
376 // over the layout. In ComputeContentSize, the dimension of the layout has been set so it encompasses its children(and the margins).389 // over the layout. In ComputeContentSize, the dimension of the layout has been set so it encompasses its children(and the margins).
@@ -383,37 +396,37 @@
383396
384 {397 {
385 unadjusted_layout = true;398 unadjusted_layout = true;
386 (*it)->SetLayoutDone(true);399 area->SetLayoutDone(true);
387 }400 }
388 }401 }
389402
390 if ((smaller_height == false) && ((*it)->GetExtend() == MINOR_SIZE_FULL) && ((*it)->GetBaseHeight() < (*it)->GetMaximumHeight()))403 if ((smaller_height == false) && (area->GetExtend() == MINOR_SIZE_FULL) && (area->GetBaseHeight() < area->GetMaximumHeight()))
391 {404 {
392 // We catch all object whose size is possibly larger than the layout. We check there size at the end and405 // We catch all object whose size is possibly larger than the layout. We check there size at the end and
393 // recompute the layout if necessary.406 // recompute the layout if necessary.
394 // For layout elements, make sure that the stretch factor is not 0. If it is, it means it will not use the407 // For layout elements, make sure that the stretch factor is not 0. If it is, it means it will not use the
395 // size provided by the parent layout. Its size will be adjusted to the minimum size of the layout content.408 // size provided by the parent layout. Its size will be adjusted to the minimum size of the layout content.
396 if (! ((*it)->IsLayout() && (*it)->GetScaleFactor() == 0))409 if (! (area->IsLayout() && area->GetScaleFactor() == 0))
397 FullSizeUnadjusted.push_back((*it)->GetBaseHeight());410 FullSizeUnadjusted.push_back(area->GetBaseHeight());
398 }411 }
399412
400 if ((smaller_height || larger_height) && ((*it)->GetExtend() == MINOR_SIZE_MATCHCONTENT))413 if ((smaller_height || larger_height) && (area->GetExtend() == MINOR_SIZE_MATCHCONTENT))
401 {414 {
402 (*it)->SetMinimumHeight((*it)->GetBaseHeight());415 area->SetMinimumHeight(area->GetBaseHeight());
403 unadjusted_layout = true;416 unadjusted_layout = true;
404 }417 }
405418
406 // Should be reactivate so that if the parent Layout does not call419 // Should be reactivate so that if the parent Layout does not call
407 // ComputeContentPosition, at least it is done here to arrange the internal420 // ComputeContentPosition, at least it is done here to arrange the internal
408 // element of the children.421 // element of the children.
409 //(*it)->ComputeContentPosition(0,0);422 //area->ComputeContentPosition(0,0);
410 }423 }
411424
412 m_fittingWidth += (*it)->GetBaseWidth();425 m_fittingWidth += area->GetBaseWidth();
413426
414 element_height = (*it)->GetBaseHeight();427 element_height = area->GetBaseHeight();
415428
416 if ((*it)->IsSpaceLayout() == false)429 if (area->IsSpaceLayout() == false)
417 {430 {
418 if ((GetScaleFactor() != 0) /* && (ret & eSmallerHeight)*/)431 if ((GetScaleFactor() != 0) /* && (ret & eSmallerHeight)*/)
419 {432 {
@@ -434,7 +447,7 @@
434 m_contentHeight = element_height;447 m_contentHeight = element_height;
435 }448 }
436449
437// else if ((*it)->GetExtend() == MINOR_SIZE_FULL)450// else if (area->GetExtend() == MINOR_SIZE_FULL)
438// {451// {
439// unadjusted_layout = true;452// unadjusted_layout = true;
440// }453// }
@@ -525,15 +538,22 @@
525 int available_width = width;538 int available_width = width;
526 unsigned int max_stretchfactor = GetMaxStretchFactor();539 unsigned int max_stretchfactor = GetMaxStretchFactor();
527 std::list<Area *>::iterator it;540 std::list<Area *>::iterator it;
541 std::list<Area *>::reverse_iterator revit;
542 Area* area;
528543
529 for (it = _layout_element_list.begin(); it != _layout_element_list.end(); it++)544 revit = _layout_element_list.rbegin();
545 for (it = _layout_element_list.begin(); it != _layout_element_list.end(); it++, revit++)
530 {546 {
531 if (!(*it)->IsVisible())547 if (GetDirection() == LeftToRight)
548 area = *it;
549 else
550 area = *revit;
551 if (!area->IsVisible())
532 continue;552 continue;
533553
534 if (((*it)->GetScaleFactor() == 0) && ((*it)->IsLayoutDone() != true))554 if ((area->GetScaleFactor() == 0) && (area->IsLayoutDone() != true))
535 {555 {
536 (*it)->ApplyMinWidth();556 area->ApplyMinWidth();
537 }557 }
538 }558 }
539559
@@ -570,27 +590,32 @@
570590
571 if (available_width <= 2)591 if (available_width <= 2)
572 {592 {
573 for (it = _layout_element_list.begin(); it != _layout_element_list.end(); it++)593 revit = _layout_element_list.rbegin();
594 for (it = _layout_element_list.begin(); it != _layout_element_list.end(); it++, revit++)
574 {595 {
575 if (!(*it)->IsVisible())596 if (GetDirection() == LeftToRight)
597 area = *it;
598 else
599 area = *revit;
600 if (!area->IsVisible())
576 continue;601 continue;
577602
578 if (((*it)->GetScaleFactor() != 0) && (*it)->IsArea())603 if ((area->GetScaleFactor() != 0) && area->IsArea())
579 {604 {
580 // If it is not an object of type eInputArea, do not set layout_done_ to true,605 // If it is not an object of type eInputArea, do not set layout_done_ to true,
581 // so, the layout management function will later be called on the object.606 // so, the layout management function will later be called on the object.
582 (*it)->ApplyMinWidth();607 area->ApplyMinWidth();
583 (*it)->SetLayoutDone(true);608 area->SetLayoutDone(true);
584 }609 }
585 else if (((*it)->GetScaleFactor() != 0) && ((*it)->IsLayout()) && ((*it)->IsLayoutDone() == false)) // layout and not fixed by child610 else if ((area->GetScaleFactor() != 0) && (area->IsLayout()) && (area->IsLayoutDone() == false)) // layout and not fixed by child
586 {611 {
587 // The out of bound must be reset to false.612 // The out of bound must be reset to false.
588 (*it)->ApplyMinWidth();613 area->ApplyMinWidth();
589 (*it)->SetLayoutDone(false);614 area->SetLayoutDone(false);
590 }615 }
591 else if (((*it)->GetScaleFactor() != 0) && ((*it)->IsLayoutDone() == false)) // layout and not fixed616 else if ((area->GetScaleFactor() != 0) && (area->IsLayoutDone() == false)) // layout and not fixed
592 {617 {
593 (*it)->ApplyMinWidth();618 area->ApplyMinWidth();
594 // A layout must never have layout_done_ set to true "here" because it must continue619 // A layout must never have layout_done_ set to true "here" because it must continue
595 // doing the layout of its children and finally resize itself to fit them.620 // doing the layout of its children and finally resize itself to fit them.
596 // The same way, A layout size factor should never be set to 0.621 // The same way, A layout size factor should never be set to 0.
@@ -604,20 +629,26 @@
604 Area *LastElementThatCanBeResized = 0;629 Area *LastElementThatCanBeResized = 0;
605 int total_distributed_size = 0;630 int total_distributed_size = 0;
606631
607 for (it = _layout_element_list.begin(); it != _layout_element_list.end(); it++)632 revit = _layout_element_list.rbegin();
633 for (it = _layout_element_list.begin(); it != _layout_element_list.end(); it++, revit++)
608 {634 {
609 if (!(*it)->IsVisible())635 if (GetDirection() == LeftToRight)
636 area = *it;
637 else
638 area = *revit;
639
640 if (!area->IsVisible())
610 continue;641 continue;
611642
612 if (((*it)->GetScaleFactor() != 0) && ((*it)->IsLayoutDone() == false))643 if ((area->GetScaleFactor() != 0) && (area->IsLayoutDone() == false))
613 {644 {
614 float sf = (float) (*it)->GetScaleFactor();645 float sf = (float) area->GetScaleFactor();
615 cumul += sf / max_stretchfactor;646 cumul += sf / max_stretchfactor;
616 LastElementThatCanBeResized = (*it);647 LastElementThatCanBeResized = area;
617 }648 }
618 else649 else
619 {650 {
620 total_distributed_size += (*it)->GetBaseWidth();651 total_distributed_size += area->GetBaseWidth();
621 }652 }
622 }653 }
623654
@@ -633,14 +664,20 @@
633664
634 need_recompute = false;;665 need_recompute = false;;
635666
636 for (it = _layout_element_list.begin(); it != _layout_element_list.end() && !need_recompute; it++)667 revit = _layout_element_list.rbegin();
668 for (it = _layout_element_list.begin(); it != _layout_element_list.end() && !need_recompute; it++, revit++)
637 {669 {
638 if (!(*it)->IsVisible())670 if (GetDirection() == LeftToRight)
671 area = *it;
672 else
673 area = *revit;
674
675 if (!area->IsVisible())
639 continue;676 continue;
640 677
641 if (((*it)->GetScaleFactor() != 0) && ((*it)->IsLayoutDone() == false))678 if ((area->GetScaleFactor() != 0) && (area->IsLayoutDone() == false))
642 {679 {
643 unsigned int sf = (*it)->GetScaleFactor();680 unsigned int sf = area->GetScaleFactor();
644 int new_width;681 int new_width;
645682
646 if (sf == max_stretchfactor)683 if (sf == max_stretchfactor)
@@ -654,7 +691,7 @@
654691
655 total_distributed_size += new_width;692 total_distributed_size += new_width;
656693
657 if (LastElementThatCanBeResized == (*it))694 if (LastElementThatCanBeResized == area)
658 {695 {
659 // Redistribute the remaining size to the last element(at the right).696 // Redistribute the remaining size to the last element(at the right).
660 // This is necessary because of imprecision. For instance if available_height = 451 and we have 2 elements697 // This is necessary because of imprecision. For instance if available_height = 451 and we have 2 elements
@@ -667,8 +704,8 @@
667 }704 }
668 }705 }
669706
670 int elemt_max_width = (*it)->GetMaximumSize().width;707 int elemt_max_width = area->GetMaximumSize().width;
671 int elemt_min_width = (*it)->GetMinimumSize().width;708 int elemt_min_width = area->GetMinimumSize().width;
672709
673 // A layout must never have layout_done_ set to true "here" because it must continue710 // A layout must never have layout_done_ set to true "here" because it must continue
674 // doing the layout of its children and finally resize itself to fit them.711 // doing the layout of its children and finally resize itself to fit them.
@@ -679,22 +716,22 @@
679 if (new_width < elemt_min_width)716 if (new_width < elemt_min_width)
680 {717 {
681 // assume the minimum width718 // assume the minimum width
682 (*it)->SetBaseWidth(elemt_min_width);719 area->SetBaseWidth(elemt_min_width);
683720
684 if ((*it)->IsLayout() == false || (*it)->IsSpaceLayout())721 if (area->IsLayout() == false || area->IsSpaceLayout())
685 {722 {
686 (*it)->SetLayoutDone(true);723 area->SetLayoutDone(true);
687 need_recompute = true;724 need_recompute = true;
688 }725 }
689 }726 }
690 else if (new_width > elemt_max_width)727 else if (new_width > elemt_max_width)
691 {728 {
692 // assume the maximum width729 // assume the maximum width
693 (*it)->SetBaseWidth(elemt_max_width);730 area->SetBaseWidth(elemt_max_width);
694731
695 if ((*it)->IsLayout() == false || (*it)->IsSpaceLayout())732 if (area->IsLayout() == false || area->IsSpaceLayout())
696 {733 {
697 (*it)->SetLayoutDone(true);734 area->SetLayoutDone(true);
698 need_recompute = true;735 need_recompute = true;
699 }736 }
700737
@@ -706,7 +743,7 @@
706 }743 }
707 else744 else
708 {745 {
709 (*it)->SetBaseWidth(new_width);746 area->SetBaseWidth(new_width);
710 }747 }
711 }748 }
712 else749 else
@@ -714,10 +751,10 @@
714 // For fixed element, reset their size to the same so it is checked against751 // For fixed element, reset their size to the same so it is checked against
715 // the min and max. This is necessary in case you have set the size of the element first then latter,752 // the min and max. This is necessary in case you have set the size of the element first then latter,
716 // you define its MinimumSize and/or MaximumSize size.753 // you define its MinimumSize and/or MaximumSize size.
717 unsigned int w = (*it)->GetBaseWidth();754 unsigned int w = area->GetBaseWidth();
718 unsigned int h = (*it)->GetBaseHeight();755 unsigned int h = area->GetBaseHeight();
719 (*it)->SetBaseWidth(w);756 area->SetBaseWidth(w);
720 (*it)->SetBaseHeight(h);757 area->SetBaseHeight(h);
721 }758 }
722 }759 }
723 }760 }
@@ -754,6 +791,8 @@
754 void HLayout::ComputeContentPosition(float offsetX, float offsetY)791 void HLayout::ComputeContentPosition(float offsetX, float offsetY)
755 {792 {
756 std::list<Area *>::iterator it;793 std::list<Area *>::iterator it;
794 std::list<Area *>::reverse_iterator revit;
795 Area* area;
757 {796 {
758 unsigned int num_element = 0;797 unsigned int num_element = 0;
759 for (it = _layout_element_list.begin(); it != _layout_element_list.end(); it++)798 for (it = _layout_element_list.begin(); it != _layout_element_list.end(); it++)
@@ -778,37 +817,42 @@
778 ComputeStacking(width, offset_space, element_margin);817 ComputeStacking(width, offset_space, element_margin);
779 current_x += offset_space;818 current_x += offset_space;
780819
781 for (it = _layout_element_list.begin(); it != _layout_element_list.end(); it++)820 revit = _layout_element_list.rbegin();
821 for (it = _layout_element_list.begin(); it != _layout_element_list.end(); it++, revit++)
782 {822 {
783 if (!(*it)->IsVisible())823 if (GetDirection() == LeftToRight)
824 area = *it;
825 else
826 area = *revit;
827 if (!area->IsVisible())
784 continue;828 continue;
785829
786 current_x += element_margin;830 current_x += element_margin;
787831
788 (*it)->SetBaseX(current_x);832 area->SetBaseX(current_x);
789 (*it)->SetBaseY(current_y);833 area->SetBaseY(current_y);
790834
791 MinorDimensionSize extend = (*it)->GetExtend();835 MinorDimensionSize extend = area->GetExtend();
792 MinorDimensionPosition positioning = (*it)->GetPositioning();836 MinorDimensionPosition positioning = area->GetPositioning();
793837
794 if ((*it)->GetBaseHeight() < height)838 if (area->GetBaseHeight() < height)
795 {839 {
796 int widget_height = (*it)->GetBaseHeight();840 int widget_height = area->GetBaseHeight();
797841
798 switch(positioning)842 switch(positioning)
799 {843 {
800 case MINOR_POSITION_START:844 case MINOR_POSITION_START:
801 {845 {
802 // do nothing846 // do nothing
803 (*it)->SetBaseY(current_y);847 area->SetBaseY(current_y);
804 break;848 break;
805 }849 }
806 case MINOR_POSITION_END:850 case MINOR_POSITION_END:
807 {851 {
808 if (widget_height < height)852 if (widget_height < height)
809 (*it)->SetBaseY(current_y + height - widget_height);853 area->SetBaseY(current_y + height - widget_height);
810 else854 else
811 (*it)->SetBaseY(current_y);855 area->SetBaseY(current_y);
812856
813 break;857 break;
814 }858 }
@@ -817,29 +861,34 @@
817 default:861 default:
818 {862 {
819 if (widget_height < height)863 if (widget_height < height)
820 (*it)->SetBaseY(current_y + (height - widget_height) / 2);864 area->SetBaseY(current_y + (height - widget_height) / 2);
821 else865 else
822 (*it)->SetBaseY(current_y);866 area->SetBaseY(current_y);
823 }867 }
824 }868 }
825 }869 }
826870
827 current_x += (*it)->GetBaseWidth() + element_margin + space_between_children_;871 current_x += area->GetBaseWidth() + element_margin + space_between_children_;
828 }872 }
829 }873 }
830874
831 for (it = _layout_element_list.begin(); it != _layout_element_list.end(); it++)875 revit = _layout_element_list.rbegin();
876 for (it = _layout_element_list.begin(); it != _layout_element_list.end(); it++, revit++)
832 {877 {
833 if (!(*it)->IsVisible())878 if (GetDirection() == LeftToRight)
879 area = *it;
880 else
881 area = *revit;
882 if (!area->IsVisible())
834 continue;883 continue;
835884
836 if ((*it)->Type().IsDerivedFromType(Layout::StaticObjectType))885 if (area->Type().IsDerivedFromType(Layout::StaticObjectType))
837 {886 {
838 (*it)->ComputeContentPosition(offsetX, offsetY);887 area->ComputeContentPosition(offsetX, offsetY);
839 }888 }
840 else if ((*it)->Type().IsDerivedFromType(View::StaticObjectType))889 else if (area->Type().IsDerivedFromType(View::StaticObjectType))
841 {890 {
842 (*it)->ComputeContentPosition(offsetX, offsetY);891 area->ComputeContentPosition(offsetX, offsetY);
843 }892 }
844 }893 }
845 }894 }
846895
=== modified file 'Nux/Layout.cpp'
--- Nux/Layout.cpp 2011-10-17 20:57:35 +0000
+++ Nux/Layout.cpp 2011-11-14 21:17:09 +0000
@@ -557,6 +557,22 @@
557 return m_ContentStacking;557 return m_ContentStacking;
558 }558 }
559559
560 LayoutContentDistribution Layout::GetEffectiveContentDistribution()
561 {
562 LayoutContentDistribution stacking = GetContentDistribution();
563 if (GetDirection() == LeftToRight)
564 return stacking;
565 switch (stacking)
566 {
567 case eStackLeft:
568 return eStackRight;
569 case eStackRight:
570 return eStackLeft;
571 default:
572 return stacking;
573 }
574 }
575
560 void Layout::RequestBottomUpLayoutComputation(Area *bo_initiator)576 void Layout::RequestBottomUpLayoutComputation(Area *bo_initiator)
561 {577 {
562578
563579
=== modified file 'Nux/Layout.h'
--- Nux/Layout.h 2011-10-10 01:52:00 +0000
+++ Nux/Layout.h 2011-11-14 21:17:09 +0000
@@ -201,6 +201,9 @@
201 virtual void SetContentDistribution(LayoutContentDistribution stacking_order);201 virtual void SetContentDistribution(LayoutContentDistribution stacking_order);
202 virtual LayoutContentDistribution GetContentDistribution();202 virtual LayoutContentDistribution GetContentDistribution();
203203
204 //! Switch the content distribution in case a RightToLeft direction is used
205 LayoutContentDistribution GetEffectiveContentDistribution();
206
204 virtual bool FindWidget(Area *WidgetObject) const;207 virtual bool FindWidget(Area *WidgetObject) const;
205 virtual bool IsEmpty() const;208 virtual bool IsEmpty() const;
206 /*209 /*
207210
=== modified file 'Nux/Nux.cpp'
--- Nux/Nux.cpp 2011-11-10 17:28:44 +0000
+++ Nux/Nux.cpp 2011-11-14 21:17:09 +0000
@@ -349,4 +349,16 @@
349 return NUX_STATIC_CAST(WindowThread *, thread)->GetGraphicsEngine();349 return NUX_STATIC_CAST(WindowThread *, thread)->GetGraphicsEngine();
350 }350 }
351351
352 static Direction defaultDirection = LeftToRight;
353
354 Direction GetDefaultDirection()
355 {
356 return defaultDirection;
357 }
358
359 void SetDefaultDirection(Direction direction)
360 {
361 defaultDirection = direction;
362 }
363
352}364}
353365
=== modified file 'Nux/Nux.h'
--- Nux/Nux.h 2011-10-21 22:06:35 +0000
+++ Nux/Nux.h 2011-11-14 21:17:09 +0000
@@ -150,6 +150,9 @@
150150
151 inlDeclareThreadLocalStorage(NThread *, 0, ThreadLocal_InalogicAppImpl);151 inlDeclareThreadLocalStorage(NThread *, 0, ThreadLocal_InalogicAppImpl);
152152
153 Direction GetDefaultDirection();
154 void SetDefaultDirection(Direction direction);
155
153}156}
154157
155#endif // NUX_H158#endif // NUX_H

Subscribers

People subscribed via source and target branches

to all changes: