Fork for IVI: mesa fixing
[profile/ivi/uifw.git] / src / ui / layout / FUi_LayoutLinearLayout.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Flora License, Version 1.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://floralicense.org/license/
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an AS IS BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 /**
18  * @file                FUi_LayoutLinearLayout.cpp
19  * @brief       This is the implementation file for LinearLayout class.
20  *
21  * This file contains the implementation of LinearLayout class.
22  */
23
24 #include <new>
25 #include <FBaseResult.h>
26 #include "FUi_Math.h"
27 #include "FUi_LayoutLinearLayout.h"
28 #include "FUi_LayoutLayoutItemProxy.h"
29 #include "FUi_LayoutProxyList.h"
30 #include "FUi_LayoutLayoutItemInfo.h"
31
32 namespace Tizen { namespace Ui { namespace _Layout
33 {
34
35 LinearLayout::LinearLayout(void)
36         : __orientation(LINEAR_NONE_ORIENTATION)
37         , __direction(LINEAR_NONE_DIRECTION)
38         , __weightSum(0.0)
39 {
40         LinearProxyList* pLinearProxyList = new (std::nothrow) LinearProxyList();
41         SysTryReturnVoidResult(NID_UI, pLinearProxyList, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
42         SetItemList(pLinearProxyList);
43 }
44
45 LinearLayout::~LinearLayout(void)
46 {
47 }
48
49 LinearLayout*
50 LinearLayout::CreateLinearLayoutN(void)
51 {
52         LinearLayout* pLayout = new (std::nothrow) LinearLayout();
53         SysTryReturn(NID_UI, pLayout != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Linear layout core allocation failure.");
54         if (GetLastResult() != E_SUCCESS)
55         {
56                 delete pLayout;
57                 return null;
58         }
59
60         return pLayout;
61 }
62
63 result
64 LinearLayout::Initialize(const LinearLayoutOrientation orientation, const LinearLayoutDirection direction)
65 {
66         if (orientation == LINEAR_NONE_ORIENTATION || direction == LINEAR_NONE_DIRECTION)
67         {
68                 return E_INVALID_ARG;
69         }
70
71         __orientation = orientation;
72
73         if (orientation == LINEAR_HORIZONTAL)
74         {
75                 if (direction != LINEAR_LEFT_TO_RIGHT && direction != LINEAR_RIGHT_TO_LEFT)
76                 {
77                         return E_INVALID_ARG;
78                 }
79         }
80         else
81         {
82                 if (direction != LINEAR_TOP_TO_BOTTOM && direction != LINEAR_BOTTOM_TO_TOP)
83                 {
84                         return E_INVALID_ARG;
85                 }
86         }
87
88         __direction = direction;
89
90         SetPartialUpdateFlag(true);
91
92         return E_SUCCESS;
93 }
94
95 result
96 LinearLayout::AddItemToIndex(LayoutItem& addItem, int index)
97 {
98         result r = Layout::AddItem(addItem);
99         if (r != E_SUCCESS)
100         {
101                 return r;
102         }
103
104         return MoveItem(addItem, index);
105 }
106
107 result
108 LinearLayout::MoveItem(LayoutItem& item, int index)
109 {
110         ProxyList* pProxyList = GetProxyList();
111         SysAssertf(pProxyList != null, "ProxyList is invalid.");
112
113         if (index < 0 || pProxyList->GetNodeCount() <= index)
114         {
115                 return E_INVALID_ARG;
116         }
117
118         ProxyListNode* pItemNode = pProxyList->GetNode(item);
119         SysTryReturn(NID_UI, pItemNode != null, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Control dose not belong to layout.");
120
121         int indexCount = -1;
122         int targetIndex = -1;
123         int itemIndex = -1;
124         ProxyListNode* pTargetNode = null;
125         ProxyListNode* pNode = pProxyList->GetFirstNode();
126         while (pNode != null)
127         {
128                 indexCount++;
129                 if (indexCount == index)
130                 {
131                         targetIndex = indexCount;
132                         pTargetNode = pNode;
133                 }
134                 if (pItemNode == pNode)
135                 {
136                         itemIndex = indexCount;
137                 }
138
139                 pNode = pProxyList->GetNextNode(*pNode);
140         }
141
142         if (targetIndex == -1 || itemIndex == -1)
143         {
144                 return E_INVALID_STATE;
145         }
146
147         if (targetIndex == itemIndex)
148         {
149                 return E_SUCCESS;
150         }
151
152         result r = pProxyList->DetachNode(*pItemNode);
153         if (r != E_SUCCESS)
154         {
155                 return r;
156         }
157
158         if (targetIndex < itemIndex)
159         {
160                 r = pProxyList->InsertIntoLeft(*pTargetNode, *pItemNode);
161                 pProxyList->RefreshIndex();
162
163                 return r;
164         }
165         else
166         {
167                 r = pProxyList->InsertIntoRight(*pTargetNode, *pItemNode);
168                 pProxyList->RefreshIndex();
169
170                 return r;
171         }
172 }
173
174 result
175 LinearLayout::SwapItem(LayoutItem& targetItem, LayoutItem& destItem)
176 {
177         result r = E_SUCCESS;
178
179         ProxyList* pProxyList = GetProxyList();
180         SysAssertf(pProxyList != null, "ProxyList is invalid.");
181
182         ProxyListNode* pTargetNode = pProxyList->GetNode(targetItem);
183         SysTryReturn(NID_UI, pTargetNode != null, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Control dose not belong to layout.");
184
185         ProxyListNode* pDestNode = pProxyList->GetNode(destItem);
186         SysTryReturn(NID_UI, pDestNode != null, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Control dose not belong to layout.");
187
188         r = pProxyList->SwapNode(*pTargetNode, *pDestNode);
189         pProxyList->RefreshIndex();
190
191         SetUpdateState(true);
192         return r;
193 }
194
195 int
196 LinearLayout::GetItemCount(void) const
197 {
198         ProxyList* pProxyList = GetProxyList();
199         SysAssertf(pProxyList != null, "ProxyList is invalid.");
200
201         return pProxyList->GetNodeCount();
202 }
203
204 result
205 LinearLayout::GetItemIndex(LayoutItem& item, int& index) const
206 {
207         ProxyList* pProxyList = GetProxyList();
208         SysAssertf(pProxyList != null, "ProxyList is invalid.");
209
210         ProxyListNode* pTargetNode = pProxyList->GetNode(item);
211         SysTryReturn(NID_UI, pTargetNode != null, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Control dose not belong to layout.");
212
213         index = pProxyList->GetIndex(*pTargetNode);
214
215         return E_SUCCESS;
216 }
217
218 result
219 LinearLayout::SetOrientation(const LinearLayoutOrientation orientation)
220 {
221         if (orientation == LINEAR_NONE_ORIENTATION)
222         {
223                 return E_INVALID_ARG;
224         }
225
226         if (__orientation != orientation)
227         {
228                 if (orientation == LINEAR_HORIZONTAL)
229                 {
230                         __direction = LINEAR_LEFT_TO_RIGHT;
231                 }
232                 else
233                 {
234                         __direction = LINEAR_TOP_TO_BOTTOM;
235                 }
236         }
237
238         __orientation = orientation;
239
240         SetUpdateState(true);
241         return E_SUCCESS;
242 }
243
244 result
245 LinearLayout::GetOrientation(LinearLayoutOrientation& orientation) const
246 {
247         if (__orientation == LINEAR_NONE_ORIENTATION)
248         {
249                 return E_INVALID_STATE;
250         }
251
252         orientation = __orientation;
253
254         return E_SUCCESS;
255 }
256
257 result
258 LinearLayout::SetDirection(const LinearLayoutDirection direction)
259 {
260         if (direction == LINEAR_NONE_DIRECTION)
261         {
262                 return E_INVALID_ARG;
263         }
264
265         if (__orientation == LINEAR_HORIZONTAL &&
266                 (direction == LINEAR_TOP_TO_BOTTOM || direction == LINEAR_BOTTOM_TO_TOP))
267         {
268                 return E_INVALID_ARG;
269         }
270
271         if (__orientation == LINEAR_VERTICAL &&
272                 (direction == LINEAR_LEFT_TO_RIGHT || direction == LINEAR_RIGHT_TO_LEFT))
273         {
274                 return E_INVALID_ARG;
275         }
276
277         __direction = direction;
278
279         SetUpdateState(true);
280         return E_SUCCESS;
281 }
282
283 result
284 LinearLayout::GetDirection(LinearLayoutDirection& direction) const
285 {
286         if (__direction == LINEAR_NONE_DIRECTION)
287         {
288                 return E_INVALID_STATE;
289         }
290
291         direction = __direction;
292
293         return E_SUCCESS;
294 }
295
296 result
297 LinearLayout::SetItemWeight(LayoutItem& item, const float weight)
298 {
299         SysTryReturn(NID_UI, weight >= 0, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The weight value is negative.");
300
301         ProxyList* pProxyList = GetProxyList();
302         SysAssertf(pProxyList != null, "ProxyList is invalid.");
303
304         ProxyListNode* pNode = pProxyList->GetNode(item);
305         SysTryReturn(NID_UI, pNode != null, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Control dose not belong to layout.");
306
307         LinearItemInfo* pItemInfo = dynamic_cast <LinearItemInfo*>(pNode->GetItemInfo());
308         if (pItemInfo == null)
309         {
310                 return E_INVALID_STATE;
311         }
312
313         __weightSum -= pItemInfo->__weight;
314         pItemInfo->__weight = weight;
315         __weightSum += pItemInfo->__weight;
316
317         SetUpdateState(true);
318         return E_SUCCESS;
319 }
320
321 result
322 LinearLayout::GetItemWeight(const LayoutItem& item, float& weight) const
323 {
324         ProxyList* pProxyList = GetProxyList();
325         SysAssertf(pProxyList != null, "ProxyList is invalid.");
326
327         ProxyListNode* pNode = pProxyList->GetNode(item);
328         SysTryReturn(NID_UI, pNode != null, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Control dose not belong to layout.");
329
330         LinearItemInfo* pItemInfo = dynamic_cast <LinearItemInfo*>(pNode->GetItemInfo());
331         if (pItemInfo == null)
332         {
333                 return E_INVALID_STATE;
334         }
335
336         weight = pItemInfo->__weight;
337
338         return E_SUCCESS;
339 }
340
341 result
342 LinearLayout::SetItemSpacing(LayoutItem& item, int spacing)
343 {
344         ProxyList* pProxyList = GetProxyList();
345         SysAssertf(pProxyList != null, "ProxyList is invalid.");
346
347         ProxyListNode* pNode = pProxyList->GetNode(item);
348         SysTryReturn(NID_UI, pNode != null, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Control dose not belong to layout.");
349
350         LinearItemInfo* pItemInfo = dynamic_cast <LinearItemInfo*>(pNode->GetItemInfo());
351         if (pItemInfo == null)
352         {
353                 return E_INVALID_STATE;
354         }
355
356         pItemInfo->__spacing = spacing;
357
358         SetUpdateState(true);
359         return E_SUCCESS;
360 }
361
362 result
363 LinearLayout::GetItemSpacing(const LayoutItem& item, int& spacing) const
364 {
365         ProxyList* pProxyList = GetProxyList();
366         SysAssertf(pProxyList != null, "ProxyList is invalid.");
367
368         ProxyListNode* pNode = pProxyList->GetNode(item);
369         SysTryReturn(NID_UI, pNode != null, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Control dose not belong to layout.");
370
371         LinearItemInfo* pItemInfo = dynamic_cast <LinearItemInfo*>(pNode->GetItemInfo());
372         if (pItemInfo == null)
373         {
374                 return E_INVALID_STATE;
375         }
376
377         spacing = pItemInfo->__spacing;
378
379         return E_SUCCESS;
380 }
381
382 result
383 LinearLayout::OnLayout(int width, int height, bool layoutUpdating)
384 {
385         result r = E_SUCCESS;
386
387         ProxyList* pProxyList = GetProxyList();
388         SysAssertf(pProxyList != null, "ProxyList is invalid.");
389
390         if (__orientation == LINEAR_NONE_ORIENTATION || __direction == LINEAR_NONE_DIRECTION)
391         {
392                 return E_INVALID_STATE;
393         }
394
395         LayoutItemProxy* pContainerProxy = GetContainerProxy();
396         if (pContainerProxy == null)
397         {
398                 return E_INVALID_STATE;
399         }
400
401         LayoutRect intendedRect = {0, 0, width, height};
402         pContainerProxy->ConvertWindowToClientBounds(intendedRect, intendedRect);
403
404         LayoutRect layoutRect = GetLayoutRect();
405         layoutRect.w = intendedRect.w;
406         layoutRect.h = intendedRect.h;
407         SetLayoutRect(layoutRect);
408
409         int rightBound = 0;
410         int bottomBound = 0;
411         r = CalculatePositionSize(rightBound, bottomBound);
412         if (r != E_SUCCESS)
413         {
414                 return r;
415         }
416
417         if (_FloatHardCompare(__weightSum, 0.0f) == false)
418         {
419                 r = CalculateWeight(rightBound, bottomBound);
420                 if (r != E_SUCCESS)
421                 {
422                         return r;
423                 }
424         }
425
426         r = CalculateWrapContent(*pContainerProxy, rightBound, bottomBound, layoutUpdating);
427         if (r != E_SUCCESS)
428         {
429                 return r;
430         }
431
432         if (__orientation == LINEAR_HORIZONTAL)
433         {
434                 r = CalculateAlignment(VERTICALONLY);
435         }
436         else
437         {
438                 r = CalculateAlignment(HORIZONTALONLY);
439         }
440         if (r != E_SUCCESS)
441         {
442                 return r;
443         }
444
445         r = CalculateCorrectedAlignment();
446         if (r != E_SUCCESS)
447         {
448                 return r;
449         }
450
451         r = CalculateMatchParent();
452         if (r != E_SUCCESS)
453         {
454                 return r;
455         }
456
457         ProxyListNode* pNode = pProxyList->GetFirstNode();
458         while (pNode != null)
459         {
460                 LayoutItemProxy* pItemProxy = pNode->GetItemProxy();
461                 LinearItemInfo* pItemInfo = dynamic_cast <LinearItemInfo*>(pNode->GetItemInfo());
462                 if (pItemProxy == null || pItemInfo == null)
463                 {
464                         return E_INVALID_STATE;
465                 }
466
467                 r = pItemProxy->SetItemWindowRect(pItemInfo->__itemRect);
468                 if (r != E_SUCCESS)
469                 {
470                         return r;
471                 }
472
473                 pNode = pProxyList->GetNextNode(*pNode);
474         }
475
476         return E_SUCCESS;
477 }
478
479 result
480 LinearLayout::CalculatePositionSize(int& rightBound, int& bottomBound)
481 {
482         ProxyList* pProxyList = GetProxyList();
483         SysAssertf(pProxyList != null, "ProxyList is invalid.");
484
485         if (pProxyList->GetNodeCount() == 0)
486         {
487                 return E_SUCCESS;
488         }
489
490         if (__orientation == LINEAR_HORIZONTAL)
491         {
492                 return CalculateHorizontalPositionSize(rightBound, bottomBound);
493         }
494         else
495         {
496                 return CalculateVerticalPositonSize(rightBound, bottomBound);
497         }
498 }
499
500 result
501 LinearLayout::CalculateHorizontalPositionSize(int& rightBound, int& bottomBound)
502 {
503         ProxyList* pProxyList = GetProxyList();
504         SysAssertf(pProxyList != null, "ProxyList is invalid.");
505
506         LayoutRect layoutRect = GetLayoutRect();
507         int x = layoutRect.x;
508         if (__direction == LINEAR_RIGHT_TO_LEFT)
509         {
510                 x += layoutRect.w;
511         }
512
513         ProxyListNode* pNode = pProxyList->GetFirstNode();
514         ProxyListNode* pFirstNode = pNode;
515         while (pNode != null)
516         {
517                 LayoutItemProxy* pItemProxy = pNode->GetItemProxy();
518                 LinearItemInfo* pItemInfo = dynamic_cast <LinearItemInfo*>(pNode->GetItemInfo());
519                 if (pItemProxy == null || pItemInfo == null)
520                 {
521                         return E_INVALID_STATE;
522                 }
523
524                 bool changedProperty = false;
525                 if (pItemProxy->GetItemWidthMatchMode() == MATCH_PARENT)
526                 {
527                         pItemProxy->SetItemWidthMatchMode(NONE_MODE);
528                         changedProperty = true;
529                 }
530
531                 LayoutRect itemRect = pItemProxy->GetItemBaseRect();
532                 result r = pItemProxy->Measure(itemRect.w, itemRect.h);
533                 if (r != E_SUCCESS)
534                 {
535                         return r;
536                 }
537                 pItemProxy->GetMeasuredSize(itemRect.w, itemRect.h);
538                 if (__direction == LINEAR_LEFT_TO_RIGHT)
539                 {
540                         itemRect.x = x;
541                         if (pNode != pFirstNode)
542                         {
543                                 itemRect.x += pItemInfo->__spacing;
544                         }
545                         x = itemRect.x + itemRect.w;
546                 }
547                 else
548                 {
549                         x -= itemRect.w;
550                         if (pNode != pFirstNode)
551                         {
552                                 x -= pItemInfo->__spacing;
553                         }
554                         itemRect.x = x;
555                 }
556                 itemRect.y = layoutRect.y;
557                 pItemInfo->__itemRect = itemRect;
558
559                 if (__direction == LINEAR_LEFT_TO_RIGHT)
560                 {
561                         rightBound = x;
562                 }
563                 else
564                 {
565                         rightBound = layoutRect.x + layoutRect.w;
566                 }
567
568                 ItemAlign align = pItemProxy->GetItemAlignment();
569                 ItemMargin margin = pItemProxy->GetItemMargin();
570                 if (pItemProxy->GetItemHeightMatchMode() != MATCH_PARENT)
571                 {
572                         int itemBottomPosition = 0;
573                         if (align.VAlign == ITEM_VERTICAL_ALIGN_TOP)
574                         {
575                                 itemBottomPosition = margin.top + itemRect.h;
576                         }
577                         else if (align.VAlign == ITEM_VERTICAL_ALIGN_BOTTOM)
578                         {
579                                 itemBottomPosition = margin.bottom + itemRect.h;
580                         }
581                         else if (align.VAlign == ITEM_VERTICAL_ALIGN_TOP_BOTTOM)
582                         {
583                                 itemBottomPosition = margin.top + itemRect.h + margin.bottom;
584                         }
585                         else
586                         {
587                                 itemBottomPosition = itemRect.h;
588                         }
589
590                         if (itemBottomPosition > bottomBound)
591                         {
592                                 bottomBound = itemBottomPosition;
593                         }
594                 }
595
596                 if (changedProperty)
597                 {
598                         pItemProxy->SetItemWidthMatchMode(MATCH_PARENT);
599                 }
600
601                 pNode = pProxyList->GetNextNode(*pNode);
602         }
603
604         return E_SUCCESS;
605 }
606
607 result
608 LinearLayout::CalculateVerticalPositonSize(int& rightBound, int& bottomBound)
609 {
610         ProxyList* pProxyList = GetProxyList();
611         SysAssertf(pProxyList != null, "ProxyList is invalid.");
612
613         LayoutRect layoutRect = GetLayoutRect();
614         int y = layoutRect.y;
615         if (__direction == LINEAR_BOTTOM_TO_TOP)
616         {
617                 y += layoutRect.h;
618         }
619
620         ProxyListNode* pNode = pProxyList->GetFirstNode();
621         ProxyListNode* pFirstNode = pNode;
622         while (pNode != null)
623         {
624                 LayoutItemProxy* pItemProxy = pNode->GetItemProxy();
625                 LinearItemInfo* pItemInfo = dynamic_cast <LinearItemInfo*>(pNode->GetItemInfo());
626                 if (pItemProxy == null || pItemInfo == null)
627                 {
628                         return E_INVALID_STATE;
629                 }
630
631                 bool changedProperty = false;
632                 if (pItemProxy->GetItemHeightMatchMode() == MATCH_PARENT)
633                 {
634                         pItemProxy->SetItemHeightMatchMode(NONE_MODE);
635                         changedProperty = true;
636                 }
637
638                 LayoutRect itemRect = pItemProxy->GetItemBaseRect();
639                 result r = pItemProxy->Measure(itemRect.w, itemRect.h);
640                 if (r != E_SUCCESS)
641                 {
642                         return r;
643                 }
644                 pItemProxy->GetMeasuredSize(itemRect.w, itemRect.h);
645                 if (__direction == LINEAR_TOP_TO_BOTTOM)
646                 {
647                         itemRect.y = y;
648                         if (pNode != pFirstNode)
649                         {
650                                 itemRect.y += pItemInfo->__spacing;
651                         }
652                         y = itemRect.y + itemRect.h;
653                 }
654                 else
655                 {
656                         y -= itemRect.h;
657                         if (pNode != pFirstNode)
658                         {
659                                 y -= pItemInfo->__spacing;
660                         }
661                         itemRect.y = y;
662                 }
663                 itemRect.x = layoutRect.x;
664                 pItemInfo->__itemRect = itemRect;
665
666                 if (__direction == LINEAR_TOP_TO_BOTTOM)
667                 {
668                         bottomBound = y;
669                 }
670                 else
671                 {
672                         bottomBound = layoutRect.y + layoutRect.h;
673                 }
674
675                 ItemAlign align = pItemProxy->GetItemAlignment();
676                 ItemMargin margin = pItemProxy->GetItemMargin();
677                 if (pItemProxy->GetItemWidthMatchMode() != MATCH_PARENT)
678                 {
679                         int itemRightPosition = 0;
680                         if (align.HAlign == ITEM_HORIZONTAL_ALIGN_LEFT)
681                         {
682                                 itemRightPosition = margin.left + itemRect.w;
683                         }
684                         else if (align.HAlign == ITEM_HORIZONTAL_ALIGN_RIGHT)
685                         {
686                                 itemRightPosition = margin.right + itemRect.w;
687                         }
688                         else if (align.HAlign == ITEM_HORIZONTAL_ALIGN_LEFT_RIGHT)
689                         {
690                                 itemRightPosition = margin.left + itemRect.w + margin.right;
691                         }
692                         else
693                         {
694                                 itemRightPosition = itemRect.w;
695                         }
696
697                         if (itemRightPosition > rightBound)
698                         {
699                                 rightBound = itemRightPosition;
700                         }
701                 }
702
703                 if (changedProperty)
704                 {
705                         pItemProxy->SetItemHeightMatchMode(MATCH_PARENT);
706                 }
707
708                 pNode = pProxyList->GetNextNode(*pNode);
709         }
710
711         return E_SUCCESS;
712 }
713
714 result
715 LinearLayout::CalculateWeight(int& rightBound, int& bottomBound)
716 {
717         float originalWeightSum = __weightSum;
718         LayoutRect layoutRect = GetLayoutRect();
719         int emptySpace = 0;
720         result r = E_SUCCESS;
721
722         ProxyList* pProxyList = GetProxyList();
723         SysAssertf(pProxyList != null, "ProxyList is invalid.");
724
725         if (__orientation == LINEAR_HORIZONTAL)
726         {
727                 if (__direction == LINEAR_LEFT_TO_RIGHT)
728                 {
729                         emptySpace = (layoutRect.x + layoutRect.w) - rightBound;
730                 }
731                 else
732                 {
733                         ProxyListNode* pNode = pProxyList->GetLastNode();
734                         if (pNode == null)
735                         {
736                                 return E_INVALID_STATE;
737                         }
738                         LinearItemInfo* pItemInfo = dynamic_cast <LinearItemInfo*>(pNode->GetItemInfo());
739                         if (pItemInfo == null)
740                         {
741                                 return E_INVALID_STATE;
742                         }
743
744                         emptySpace = pItemInfo->__itemRect.x - layoutRect.x;
745                 }
746
747                 while (emptySpace != 0)
748                 {
749                         r = CalculateHorizontalWeight(emptySpace);
750                         if (r != E_SUCCESS)
751                         {
752                                 return r;
753                         }
754                 }
755
756                 ProxyListNode* pBoundNode = null;
757                 if (__direction == LINEAR_TOP_TO_BOTTOM)
758                 {
759                         pBoundNode = pProxyList->GetLastNode();
760                 }
761                 else
762                 {
763                         pBoundNode = pProxyList->GetFirstNode();
764                 }
765                 if (pBoundNode == null)
766                 {
767                         return E_INVALID_STATE;
768                 }
769                 LinearItemInfo* pBoundInfo = dynamic_cast <LinearItemInfo*>(pBoundNode->GetItemInfo());
770                 if (pBoundInfo == null)
771                 {
772                         return E_INVALID_STATE;
773                 }
774                 rightBound = pBoundInfo->__itemRect.x + pBoundInfo->__itemRect.w;
775         }
776         else
777         {
778                 if (__direction == LINEAR_TOP_TO_BOTTOM)
779                 {
780                         emptySpace = (layoutRect.y + layoutRect.h) - bottomBound;
781                 }
782                 else
783                 {
784                         ProxyListNode* pNode = pProxyList->GetLastNode();
785                         if (pNode == null)
786                         {
787                                 return E_INVALID_STATE;
788                         }
789                         LinearItemInfo* pItemInfo = dynamic_cast <LinearItemInfo*>(pNode->GetItemInfo());
790                         if (pItemInfo == null)
791                         {
792                                 return E_INVALID_STATE;
793                         }
794
795                         emptySpace = pItemInfo->__itemRect.y - layoutRect.y;
796                 }
797
798                 while (emptySpace != 0)
799                 {
800                         r = CalculateVerticalWeight(emptySpace);
801                         if (r != E_SUCCESS)
802                         {
803                                 return r;
804                         }
805                 }
806
807                 ProxyListNode* pBoundNode = null;
808                 if (__direction == LINEAR_TOP_TO_BOTTOM)
809                 {
810                         pBoundNode = pProxyList->GetLastNode();
811                 }
812                 else
813                 {
814                         pBoundNode = pProxyList->GetFirstNode();
815                 }
816                 if (pBoundNode == null)
817                 {
818                         return E_INVALID_STATE;
819                 }
820                 LinearItemInfo* pBoundInfo = dynamic_cast <LinearItemInfo*>(pBoundNode->GetItemInfo());
821                 if (pBoundInfo == null)
822                 {
823                         return E_INVALID_STATE;
824                 }
825                 bottomBound = pBoundInfo->__itemRect.y + pBoundInfo->__itemRect.h;
826         }
827
828         ProxyListNode* pNode = pProxyList->GetFirstNode();
829         while (pNode != null)
830         {
831                 LinearItemInfo* pItemInfo = dynamic_cast <LinearItemInfo*>(pNode->GetItemInfo());
832                 if (pItemInfo == null)
833                 {
834                         return E_INVALID_STATE;
835                 }
836                 pItemInfo->__fixedSize = false;
837
838                 pNode = pProxyList->GetNextNode(*pNode);
839         }
840
841         __weightSum = originalWeightSum;
842
843         return E_SUCCESS;
844 }
845
846 result
847 LinearLayout::CalculateHorizontalWeight(int& emptySpace)
848 {
849         ProxyList* pProxyList = GetProxyList();
850         SysAssertf(pProxyList != null, "ProxyList is invalid.");
851
852         if (_FloatHardCompare(__weightSum, 0.0f) == true)
853         {
854                 emptySpace = 0;
855                 return E_SUCCESS;
856         }
857
858         result r = E_SUCCESS;
859         int x = 0;
860         int measuredWidth = 0;
861         int usedEmptySpace = emptySpace;
862         int itemCount = pProxyList->GetNodeCount();
863
864         if (usedEmptySpace <= itemCount && usedEmptySpace >= -itemCount)
865         {
866                 ProxyListNode* pNode = pProxyList->GetFirstNode();
867                 while (pNode != null)
868                 {
869                         LayoutItemProxy* pItemProxy = pNode->GetItemProxy();
870                         LinearItemInfo* pItemInfo = dynamic_cast <LinearItemInfo*>(pNode->GetItemInfo());
871                         if (pItemProxy == null || pItemInfo == null)
872                         {
873                                 return E_INVALID_STATE;
874                         }
875                         LayoutRect itemRect = pItemInfo->__itemRect;
876                         itemRect.x += x;
877                         if (pItemInfo->__fixedSize == false && usedEmptySpace != 0)
878                         {
879                                 if (usedEmptySpace > 0)
880                                 {
881                                         itemRect.w++;
882
883                                         r = pItemProxy->Measure(itemRect.w, itemRect.h);
884                                         if (r != E_SUCCESS)
885                                         {
886                                                 return r;
887                                         }
888
889                                         pItemProxy->GetMeasuredSize(measuredWidth, itemRect.h);
890                                         if (measuredWidth == itemRect.w)
891                                         {
892                                                 usedEmptySpace--;
893                                                 if (__direction == LINEAR_LEFT_TO_RIGHT)
894                                                 {
895                                                         x++;
896                                                 }
897                                                 else
898                                                 {
899                                                         itemRect.x--;
900                                                         x--;
901                                                 }
902                                         }
903                                         else
904                                         {
905                                                 itemRect.w = measuredWidth;
906                                                 __weightSum -= pItemInfo->__weight;
907                                                 pItemInfo->__fixedSize = true;
908                                         }
909                                 }
910                                 else
911                                 {
912                                         itemRect.w--;
913 #ifdef NOT_SUPPORT_NEGATIVE_SIZE
914                                         if (itemRect.w < 0)
915                                         {
916                                                 itemRect.w = 0;
917                                         }
918 #endif
919                                         r = pItemProxy->Measure(itemRect.w, itemRect.h);
920                                         if (r != E_SUCCESS)
921                                         {
922                                                 return r;
923                                         }
924
925                                         pItemProxy->GetMeasuredSize(measuredWidth, itemRect.h);
926                                         if (measuredWidth == itemRect.w)
927                                         {
928                                                 usedEmptySpace++;
929                                                 if (__direction == LINEAR_LEFT_TO_RIGHT)
930                                                 {
931                                                         x--;
932                                                 }
933                                                 else
934                                                 {
935                                                         itemRect.x++;
936                                                         x++;
937                                                 }
938                                         }
939                                         else
940                                         {
941                                                 itemRect.w = measuredWidth;
942                                                 __weightSum -= pItemInfo->__weight;
943                                                 pItemInfo->__fixedSize = true;
944                                         }
945                                 }
946                         }
947                         pItemInfo->__itemRect = itemRect;
948
949                         pNode = pProxyList->GetNextNode(*pNode);
950                 }
951                 emptySpace = usedEmptySpace;
952
953                 return E_SUCCESS;
954         }
955
956         float unitSize = emptySpace / __weightSum;
957         int correctionValue = emptySpace - (int) (unitSize * 100.0) * (int) (__weightSum) / 100;
958         if (correctionValue < 0)
959         {
960                 correctionValue = -correctionValue;
961         }
962
963         ProxyListNode* pNode = pProxyList->GetFirstNode();
964         while (pNode != null)
965         {
966                 LayoutItemProxy* pItemProxy = pNode->GetItemProxy();
967                 LinearItemInfo* pItemInfo = dynamic_cast <LinearItemInfo*>(pNode->GetItemInfo());
968                 if (pItemProxy == null || pItemInfo == null)
969                 {
970                         return E_INVALID_STATE;
971                 }
972                 LayoutRect itemRect = pItemInfo->__itemRect;
973                 int correctionSize = (int) (unitSize * pItemInfo->__weight);
974                 if (correctionValue)
975                 {
976                         if (correctionSize < 0)
977                         {
978                                 correctionSize--;
979                         }
980                         else
981                         {
982                                 correctionSize++;
983                         }
984                         correctionValue--;
985                 }
986
987                 if (__direction == LINEAR_LEFT_TO_RIGHT)
988                 {
989                         itemRect.x += x;
990                 }
991
992                 if (pItemInfo->__fixedSize == false)
993                 {
994                         itemRect.w += correctionSize;
995                         x += correctionSize;
996                         usedEmptySpace -= correctionSize;
997                 }
998
999                 if (__direction == LINEAR_RIGHT_TO_LEFT)
1000                 {
1001                         itemRect.x -= x;
1002                 }
1003
1004                 r = pItemProxy->Measure(itemRect.w, itemRect.h);
1005                 if (r != E_SUCCESS)
1006                 {
1007                         return r;
1008                 }
1009                 pItemProxy->GetMeasuredSize(measuredWidth, itemRect.h);
1010                 if (measuredWidth != itemRect.w)
1011                 {
1012                         usedEmptySpace = usedEmptySpace - (measuredWidth - itemRect.w);
1013                         x = x + (measuredWidth - itemRect.w);
1014                         itemRect.w = measuredWidth;
1015                         __weightSum -= pItemInfo->__weight;
1016                         pItemInfo->__fixedSize = true;
1017                 }
1018 #ifdef NOT_SUPPORT_NEGATIVE_SIZE
1019                 if (itemRect.w < 0)
1020                 {
1021                         itemRect.w = 0;
1022                 }
1023 #endif
1024                 pItemInfo->__itemRect = itemRect;
1025
1026                 pNode = pProxyList->GetNextNode(*pNode);
1027         }
1028         emptySpace = usedEmptySpace;
1029
1030         return E_SUCCESS;
1031 }
1032
1033 result
1034 LinearLayout::CalculateVerticalWeight(int& emptySpace)
1035 {
1036         if (_FloatHardCompare(__weightSum, 0.0f))
1037         {
1038                 emptySpace = 0;
1039                 return E_SUCCESS;
1040         }
1041
1042         ProxyList* pProxyList = GetProxyList();
1043         SysAssertf(pProxyList != null, "ProxyList is invalid.");
1044
1045         result r = E_SUCCESS;
1046         int y = 0;
1047         int measuredHeight = 0;
1048         int usedEmptySpace = emptySpace;
1049         int itemCount = pProxyList->GetNodeCount();
1050
1051         if (usedEmptySpace <= itemCount && usedEmptySpace >= -itemCount)
1052         {
1053                 ProxyListNode* pNode = pProxyList->GetFirstNode();
1054                 while (pNode != null)
1055                 {
1056                         LayoutItemProxy* pItemProxy = pNode->GetItemProxy();
1057                         LinearItemInfo* pItemInfo = dynamic_cast <LinearItemInfo*>(pNode->GetItemInfo());
1058                         if (pItemProxy == null || pItemInfo == null)
1059                         {
1060                                 return E_INVALID_STATE;
1061                         }
1062                         LayoutRect itemRect = pItemInfo->__itemRect;
1063                         itemRect.y += y;
1064                         if (pItemInfo->__fixedSize == false && usedEmptySpace != 0)
1065                         {
1066                                 if (usedEmptySpace > 0)
1067                                 {
1068                                         itemRect.h++;
1069
1070                                         r = pItemProxy->Measure(itemRect.w, itemRect.h);
1071                                         if (r != E_SUCCESS)
1072                                         {
1073                                                 return r;
1074                                         }
1075
1076                                         pItemProxy->GetMeasuredSize(itemRect.w, measuredHeight);
1077                                         if (measuredHeight == itemRect.h)
1078                                         {
1079                                                 usedEmptySpace--;
1080                                                 if (__direction == LINEAR_TOP_TO_BOTTOM)
1081                                                 {
1082                                                         y++;
1083                                                 }
1084                                                 else
1085                                                 {
1086                                                         itemRect.y--;
1087                                                         y--;
1088                                                 }
1089                                         }
1090                                         else
1091                                         {
1092                                                 itemRect.h = measuredHeight;
1093                                                 __weightSum -= pItemInfo->__weight;
1094                                                 pItemInfo->__fixedSize = true;
1095                                         }
1096                                 }
1097                                 else
1098                                 {
1099                                         itemRect.h--;
1100 #ifdef NOT_SUPPORT_NEGATIVE_SIZE
1101                                         if (itemRect.h < 0)
1102                                         {
1103                                                 itemRect.h = 0;
1104                                         }
1105 #endif
1106                                         r = pItemProxy->Measure(itemRect.w, itemRect.h);
1107                                         if (r != E_SUCCESS)
1108                                         {
1109                                                 return r;
1110                                         }
1111
1112                                         pItemProxy->GetMeasuredSize(itemRect.w, measuredHeight);
1113                                         if (measuredHeight == itemRect.h)
1114                                         {
1115                                                 usedEmptySpace++;
1116                                                 if (__direction == LINEAR_TOP_TO_BOTTOM)
1117                                                 {
1118                                                         y--;
1119                                                 }
1120                                                 else
1121                                                 {
1122                                                         itemRect.y++;
1123                                                         y++;
1124                                                 }
1125                                         }
1126                                         else
1127                                         {
1128                                                 itemRect.h = measuredHeight;
1129                                                 __weightSum -= pItemInfo->__weight;
1130                                                 pItemInfo->__fixedSize = true;
1131                                         }
1132                                 }
1133                         }
1134                         pItemInfo->__itemRect = itemRect;
1135
1136                         pNode = pProxyList->GetNextNode(*pNode);
1137                 }
1138                 emptySpace = usedEmptySpace;
1139
1140                 return E_SUCCESS;
1141         }
1142
1143         float unitSize = emptySpace / __weightSum;
1144         int correctionValue = emptySpace - (int) (unitSize * 100.0) * (int) (__weightSum) / 100;
1145         if (correctionValue < 0)
1146         {
1147                 correctionValue = -correctionValue;
1148         }
1149
1150         ProxyListNode* pNode = pProxyList->GetFirstNode();
1151         while (pNode != null)
1152         {
1153                 LayoutItemProxy* pItemProxy = pNode->GetItemProxy();
1154                 LinearItemInfo* pItemInfo = dynamic_cast <LinearItemInfo*>(pNode->GetItemInfo());
1155                 if (pItemProxy == null || pItemInfo == null)
1156                 {
1157                         return E_INVALID_STATE;
1158                 }
1159                 LayoutRect itemRect = pItemInfo->__itemRect;
1160                 int correctionSize = (int) (unitSize * pItemInfo->__weight);
1161                 if (correctionValue)
1162                 {
1163                         if (correctionSize < 0)
1164                         {
1165                                 correctionSize--;
1166                         }
1167                         else
1168                         {
1169                                 correctionSize++;
1170                         }
1171                         correctionValue--;
1172                 }
1173
1174                 if (__direction == LINEAR_TOP_TO_BOTTOM)
1175                 {
1176                         itemRect.y += y;
1177                 }
1178
1179                 if (pItemInfo->__fixedSize == false)
1180                 {
1181                         itemRect.h += correctionSize;
1182                         y += correctionSize;
1183                         usedEmptySpace -= correctionSize;
1184                 }
1185
1186                 if (__direction == LINEAR_BOTTOM_TO_TOP)
1187                 {
1188                         itemRect.y -= y;
1189                 }
1190
1191                 r = pItemProxy->Measure(itemRect.w, itemRect.h);
1192                 if (r != E_SUCCESS)
1193                 {
1194                         return r;
1195                 }
1196                 pItemProxy->GetMeasuredSize(itemRect.w, measuredHeight);
1197                 if (measuredHeight != itemRect.h)
1198                 {
1199                         usedEmptySpace = usedEmptySpace - (measuredHeight - itemRect.h);
1200                         y = y + (measuredHeight - itemRect.h);
1201                         itemRect.h = measuredHeight;
1202                         __weightSum -= pItemInfo->__weight;
1203                         pItemInfo->__fixedSize = true;
1204                 }
1205 #ifdef NOT_SUPPORT_NEGATIVE_SIZE
1206                 if (itemRect.h < 0)
1207                 {
1208                         itemRect.h = 0;
1209                 }
1210 #endif
1211                 pItemInfo->__itemRect = itemRect;
1212
1213                 pNode = pProxyList->GetNextNode(*pNode);
1214         }
1215         emptySpace = usedEmptySpace;
1216
1217         return E_SUCCESS;
1218 }
1219
1220 result
1221 LinearLayout::CalculateWrapContent(LayoutItemProxy& containerProxy, int rightBound, int bottomBound, bool layoutUpdating)
1222 {
1223         LayoutMatchMode widthMatchMode = containerProxy.GetItemWidthMatchMode();
1224         LayoutMatchMode heightMatchMode = containerProxy.GetItemHeightMatchMode();
1225
1226         if (widthMatchMode != WRAP_CONTENT && heightMatchMode != WRAP_CONTENT)
1227         {
1228                 return E_SUCCESS;
1229         }
1230
1231         LayoutRect containerRect;
1232         LayoutRect clientRect;
1233         containerProxy.GetItemWindowRect(containerRect);
1234         containerProxy.ConvertWindowToClientBounds(containerRect, clientRect);
1235
1236         int correctionWidth = containerRect.w - clientRect.w;
1237         int correctionHeight = containerRect.h - clientRect.h;
1238         LayoutSize minSize;
1239         LayoutSize maxSize;
1240         containerProxy.GetMinSize(minSize);
1241         containerProxy.GetMaxSize(maxSize);
1242         LayoutRect layoutRect = GetLayoutRect();
1243
1244         if (widthMatchMode == WRAP_CONTENT)
1245         {
1246                 layoutRect.w = rightBound - layoutRect.x;
1247                 if (layoutRect.w < 0)
1248                 {
1249                         layoutRect.w = 0;
1250                 }
1251                 containerRect.w = layoutRect.w + (containerRect.w - clientRect.w);
1252                 containerRect.w = layoutRect.w + correctionWidth;
1253 #ifdef NOT_SUPPORT_NEGATIVE_SIZE
1254                 if (containerRect.w < 0)
1255                 {
1256                         containerRect.w = 0;
1257                 }
1258 #endif
1259                 if (containerRect.w < minSize.w)
1260                 {
1261                         containerRect.w = minSize.w;
1262                 }
1263                 if (containerRect.w > maxSize.w)
1264                 {
1265                         containerRect.w = maxSize.w;
1266                 }
1267                 layoutRect.w = containerRect.w - correctionWidth;
1268         }
1269         if (heightMatchMode == WRAP_CONTENT)
1270         {
1271                 layoutRect.h = bottomBound - layoutRect.y;
1272                 if (layoutRect.h < 0)
1273                 {
1274                         layoutRect.h = 0;
1275                 }
1276                 containerRect.h = layoutRect.h + (containerRect.h - clientRect.h);
1277                 containerRect.h = layoutRect.h + correctionHeight;
1278 #ifdef NOT_SUPPORT_NEGATIVE_SIZE
1279                 if (containerRect.h < 0)
1280                 {
1281                         containerRect.h = 0;
1282                 }
1283 #endif
1284                 if (containerRect.h < minSize.h)
1285                 {
1286                         containerRect.h = minSize.h;
1287                 }
1288                 if (containerRect.h > maxSize.h)
1289                 {
1290                         containerRect.h = maxSize.h;
1291                 }
1292                 layoutRect.h = containerRect.h - correctionHeight;
1293         }
1294         SetLayoutRect(layoutRect);
1295         if (layoutUpdating)
1296         {
1297                 result r = containerProxy.SetItemWindowRect(containerRect);
1298                 if (r != E_SUCCESS)
1299                 {
1300                         return r;
1301                 }
1302         }
1303
1304         return E_SUCCESS;
1305 }
1306
1307 result
1308 LinearLayout::CalculateMatchParent(void)
1309 {
1310         ProxyList* pProxyList = GetProxyList();
1311         SysAssertf(pProxyList != null, "ProxyList is invalid.");
1312
1313         LayoutRect layoutRect = GetLayoutRect();
1314
1315         ProxyListNode* pNode = pProxyList->GetFirstNode();
1316         while (pNode != null)
1317         {
1318                 LayoutItemProxy* pItemProxy = pNode->GetItemProxy();
1319                 LinearItemInfo* pItemInfo = dynamic_cast <LinearItemInfo*>(pNode->GetItemInfo());
1320                 if (pItemProxy == null || pItemInfo == null)
1321                 {
1322                         return E_INVALID_STATE;
1323                 }
1324
1325                 bool changedProperty = false;
1326                 if (pItemProxy->GetItemHeightMatchMode() == MATCH_PARENT && __orientation == LINEAR_HORIZONTAL)
1327                 {
1328                         if (pItemProxy->GetItemWidthMatchMode() == MATCH_PARENT)
1329                         {
1330                                 pItemProxy->SetItemWidthMatchMode(NONE_MODE);
1331                                 changedProperty = true;
1332                         }
1333                         LayoutRect itemRect = pItemInfo->__itemRect;
1334                         result r = pItemProxy->Measure(itemRect.w, itemRect.h);
1335                         if (r != E_SUCCESS)
1336                         {
1337                                 return r;
1338                         }
1339                         pItemProxy->GetMeasuredSize(itemRect.w, itemRect.h);
1340                         itemRect.y = layoutRect.y;
1341                         pItemInfo->__itemRect = itemRect;
1342
1343                         if (changedProperty == true)
1344                         {
1345                                 pItemProxy->SetItemWidthMatchMode(MATCH_PARENT);
1346                         }
1347                 }
1348                 if (pItemProxy->GetItemWidthMatchMode() == MATCH_PARENT && __orientation == LINEAR_VERTICAL)
1349                 {
1350                         if (pItemProxy->GetItemHeightMatchMode() == MATCH_PARENT)
1351                         {
1352                                 pItemProxy->SetItemHeightMatchMode(NONE_MODE);
1353                                 changedProperty = true;
1354                         }
1355                         LayoutRect itemRect = pItemInfo->__itemRect;
1356                         result r = pItemProxy->Measure(itemRect.w, itemRect.h);
1357                         if (r != E_SUCCESS)
1358                         {
1359                                 return r;
1360                         }
1361                         pItemProxy->GetMeasuredSize(itemRect.w, itemRect.h);
1362                         itemRect.x = layoutRect.x;
1363                         pItemInfo->__itemRect = itemRect;
1364
1365                         if (changedProperty == true)
1366                         {
1367                                 pItemProxy->SetItemHeightMatchMode(MATCH_PARENT);
1368                         }
1369                 }
1370
1371                 pNode = pProxyList->GetNextNode(*pNode);
1372         }
1373
1374         return E_SUCCESS;
1375 }
1376
1377 result
1378 LinearLayout::CalculateCorrectedAlignment(void)
1379 {
1380         ProxyList* pProxyList = GetProxyList();
1381         SysAssertf(pProxyList != null, "ProxyList is invalid.");
1382
1383         ProxyListNode* pNode = pProxyList->GetFirstNode();
1384         while (pNode != null)
1385         {
1386                 LayoutItemProxy* pItemProxy = pNode->GetItemProxy();
1387                 LinearItemInfo* pItemInfo = dynamic_cast <LinearItemInfo*>(pNode->GetItemInfo());
1388                 if (pItemProxy == null || pItemInfo == null)
1389                 {
1390                         return E_INVALID_STATE;
1391                 }
1392                 ItemAlign align = pItemProxy->GetItemAlignment();
1393                 LayoutRect itemWindowRect;
1394                 pItemProxy->GetItemWindowRect(itemWindowRect);
1395
1396                 if (__orientation == LINEAR_HORIZONTAL)
1397                 {
1398                         pItemInfo->__itemRect.y = itemWindowRect.y;
1399                         if (align.VAlign == ITEM_VERTICAL_ALIGN_TOP_BOTTOM)
1400                         {
1401                                 pItemInfo->__itemRect.h = itemWindowRect.h;
1402                         }
1403                 }
1404                 else
1405                 {
1406                         pItemInfo->__itemRect.x = itemWindowRect.x;
1407                         if (align.HAlign == ITEM_HORIZONTAL_ALIGN_LEFT_RIGHT)
1408                         {
1409                                 pItemInfo->__itemRect.w = itemWindowRect.w;
1410                         }
1411                 }
1412
1413                 pNode = pProxyList->GetNextNode(*pNode);
1414         }
1415
1416         return E_SUCCESS;
1417 }
1418
1419 }}} // Tizen::Ui::_Layout