Merge "fixed bug (TapGesture improvement)" into tizen_2.1
[platform/framework/native/uifw.git] / src / ui / layout / FUi_LayoutRelativeLayout.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Apache License, Version 2.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://www.apache.org/licenses/LICENSE-2.0/
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_LayoutRelativeLayout.cpp
19  * @brief       This is the implementation file for RelativeLayout class.
20  *
21  * This file contains the implementation of RelativeLayout class.
22  */
23
24 #include <new>
25 #include <string.h>
26 #include <FBaseResult.h>
27 #include "FUi_LayoutRelativeLayout.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 // relative layout
36 RelativeLayout::RelativeLayout()
37         : __pTargetParent(reinterpret_cast <LayoutItemProxy*>(0xffff))
38 {
39         RelativeProxyList* pRelativeProxyList = new (std::nothrow) RelativeProxyList();
40         SysTryReturnVoidResult(NID_UI, pRelativeProxyList, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
41         SetItemList(pRelativeProxyList);
42
43         pRelativeProxyList->SetRelativeLayout(this);
44 }
45
46 RelativeLayout::~RelativeLayout()
47 {
48 }
49
50 RelativeLayout*
51 RelativeLayout::CreateRelativeLayoutN()
52 {
53         RelativeLayout* pLayout = new (std::nothrow) RelativeLayout();
54         SysTryReturn(NID_UI, pLayout != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Relative layout core allocation failure.");
55         if (GetLastResult() != E_SUCCESS)
56         {
57                 delete pLayout;
58                 return null;
59         }
60
61         return pLayout;
62 }
63
64 result
65 RelativeLayout::SetRelation(LayoutItem& item, const RelativeLayoutEdge itemEdge, LayoutItem* pTarget,
66                                                         const RelativeLayoutEdge targetEdge)
67 {
68         ProxyList* pProxyList = GetProxyList();
69         SysAssertf(pProxyList != null, "ProxyList is invalid.");
70
71         ProxyListNode* pSourceNode = pProxyList->GetNode(item);
72         ProxyListNode* pTargetNode = pProxyList->GetNode(*pTarget);
73         LayoutItemProxy* pContainerProxy = GetContainerProxy();
74
75         if (pContainerProxy == null)
76         {
77                 return E_INVALID_STATE;
78         }
79
80         if (pSourceNode == null ||
81                 (pTarget != null && pTarget != pContainerProxy->GetItem() && pTargetNode == null))
82         {
83                 return E_INVALID_ARG;
84         }
85
86         if (itemEdge == EDGE_ALL)
87         {
88                 return E_INVALID_ARG;
89         }
90
91         if (itemEdge == EDGE_NONE)
92         {
93                 for (int i = EDGE_LEFT; i < EDGE_ALL; i++)
94                 {
95                         UnsetRelation(item, static_cast <RelativeLayoutEdge>(i));
96                 }
97
98                 SetUpdateState(true);
99                 SetPartialUpdateFlag(true);
100                 return E_SUCCESS;
101         }
102
103         if (itemEdge == EDGE_HCENTER || itemEdge == EDGE_VCENTER)
104         {
105                 if (pTarget != null || targetEdge != EDGE_NONE)
106                 {
107                         return E_INVALID_ARG;
108                 }
109         }
110
111         // release to relation if exist relation
112         result r = E_SYSTEM;
113         if (GetRelation(item, itemEdge, null) != null)
114         {
115                 r = UnsetRelation(item, itemEdge);
116                 if (r != E_SUCCESS)
117                 {
118                         return r;
119                 }
120         }
121
122         int rollBackRefCount = 0;
123         RelativeItemInfo* pTargetItemInfo = null;
124         if (pTargetNode != null)
125         {
126                 pTargetItemInfo = static_cast <RelativeItemInfo*>(pTargetNode->GetItemInfo());
127                 if (pTargetItemInfo == null)
128                 {
129                         return E_INVALID_STATE;
130                 }
131                 rollBackRefCount = pTargetItemInfo->__refCount;
132         }
133         r = SetAlignment(*pSourceNode, itemEdge, pTargetNode, targetEdge);
134         if (r != E_SUCCESS)
135         {
136                 return r;
137         }
138
139         if (pTargetItemInfo != null && IncreaseReferenceCount(*pSourceNode) != E_SUCCESS)
140         {
141                 r = UnsetAlignment(*pSourceNode, itemEdge, null);
142                 if (r != E_SUCCESS)
143                 {
144                         SysAssert(false);
145                 }
146                 DecreaseReferenceCount(*pSourceNode, *pTargetNode);
147                 pTargetItemInfo->__refCount = rollBackRefCount;
148                 r = IncreaseReferenceCount(*pTargetNode);
149                 if (r != E_SUCCESS)
150                 {
151                         SysAssert(false);
152                 }
153
154                 ProxyListNode* pCurNode = pProxyList->GetFirstNode();
155                 while (pCurNode)
156                 {
157                         r = IncreaseReferenceCount(*pCurNode);
158                         if (r != E_SUCCESS)
159                         {
160                                 SysAssert(false);
161                         }
162                         pCurNode = pProxyList->GetNextNode(*pCurNode);
163                 }
164
165                 return E_SYSTEM;
166         }
167
168         SetUpdateState(true);
169         SetPartialUpdateFlag(true);
170         return E_SUCCESS;
171 }
172
173 result
174 RelativeLayout::UnsetRelation(LayoutItem& item, const RelativeLayoutEdge itemEdge)
175 {
176         RelativeProxyList* pRelativeProxyList = GetRelativeProxyList();
177         SysTryReturn(NID_UI, pRelativeProxyList, E_INVALID_STATE, E_INVALID_STATE, "[E_INVALID_STATE] RelativeProxyList is invalid.");
178
179         ProxyListNode* pItemNode = pRelativeProxyList->GetNode(item);
180         if (pItemNode == null)
181         {
182                 return E_INVALID_ARG;
183         }
184
185         if (itemEdge == EDGE_NONE || itemEdge == EDGE_ALL)
186         {
187                 return E_INVALID_ARG;
188         }
189
190         result r = E_SYSTEM;
191         ProxyListNode* pTargetNode = null;
192         LayoutItemProxy* pTargetProxy = null;
193         r = UnsetAlignment(*pItemNode, itemEdge, &pTargetProxy);
194         if (r != E_SUCCESS)
195         {
196                 return r;
197         }
198         if (pTargetProxy != null)
199         {
200                 pTargetNode = pRelativeProxyList->GetNode(*(pTargetProxy->GetItem()));
201                 if (pTargetNode == null)
202                 {
203                         return E_INVALID_STATE;
204                 }
205         }
206
207         if (pTargetNode == null)
208         {
209                 SetUpdateState(true);
210                 SetPartialUpdateFlag(true);
211
212                 return E_SUCCESS;
213         }
214
215         // Refcount of all nodes is set to 0.
216         DecreaseReferenceCount(*pItemNode, *pTargetNode);
217
218         // find another node to refer to pTargetNode.
219         ProxyListNode* pCurNode = pRelativeProxyList->GetFirstNode();
220         int maxRefCount = 0;
221         int nodeIndex = 0;
222         while (pCurNode != null)
223         {
224                 for (int i = EDGE_LEFT; i <= EDGE_BOTTOM; i++)
225                 {
226                         LayoutItemProxy* pTargetProxy = GetAlignment(*pCurNode, static_cast <RelativeLayoutEdge>(i));
227                         if (pTargetProxy != null && pTargetProxy != GetContainerProxy())
228                         {
229                                 ProxyListNode* pCurTargetNode = pRelativeProxyList->GetNode(*(pTargetProxy->GetItem()));
230                                 if (pTargetNode == pCurTargetNode)
231                                 {
232                                         if (maxRefCount < pRelativeProxyList->GetReferenceCount(*pCurNode))
233                                         {
234                                                 maxRefCount = pRelativeProxyList->GetReferenceCount(*pCurNode);
235                                                 nodeIndex = pRelativeProxyList->GetIndex(*pCurNode);
236                                         }
237                                 }
238                         }
239                 }
240                 pCurNode = pRelativeProxyList->GetNextNode(*pCurNode);
241         }
242
243         if (nodeIndex != 0)
244         {
245                 pCurNode = pRelativeProxyList->GetNode(nodeIndex);
246                 IncreaseReference(*pTargetNode, *pCurNode);
247         }
248
249         // Nodes Recalculation
250         r = IncreaseReferenceCount(*pTargetNode);
251         if (r != E_SUCCESS)
252         {
253                 return r;
254         }
255
256         SetUpdateState(true);
257         SetPartialUpdateFlag(true);
258         return E_SUCCESS;
259 }
260
261 LayoutItem*
262 RelativeLayout::GetRelation(LayoutItem& item, const RelativeLayoutEdge itemEdge, RelativeLayoutEdge* pTargetEdge)
263 {
264         ProxyList* pProxyList = GetProxyList();
265         SysAssertf(pProxyList != null, "ProxyList is invalid.");
266
267         ProxyListNode* pNode = pProxyList->GetNode(item);
268
269         if (pNode != null)
270         {
271                 LayoutItemProxy* pItemProxy = GetAlignment(*pNode, itemEdge, pTargetEdge);
272                 if (pItemProxy)
273                 {
274                         return pItemProxy->GetItem();
275                 }
276         }
277
278         return null;
279 }
280
281 result
282 RelativeLayout::OnLayout(float width, float height, bool updateLayouting)
283 {
284         result r = E_SUCCESS;
285         ProxyList* pProxyList = GetProxyList();
286         SysAssertf(pProxyList != null, "ProxyList is invalid.");
287
288         LayoutItemProxy* pContainerProxy = GetContainerProxy();
289         if (pContainerProxy == null)
290         {
291                 return E_INVALID_STATE;
292         }
293
294         LayoutRect windowRect = {0.0f, 0.0f, width, height};
295         LayoutRect clientRect;
296         pContainerProxy->ConvertWindowToClientBounds(windowRect, clientRect);
297
298         LayoutRect layoutRect = GetLayoutRect();
299         clientRect.x = layoutRect.x;
300         clientRect.y = layoutRect.y;
301
302         float correctionWidth = windowRect.w - clientRect.w;
303         float correctionHeight = windowRect.h - clientRect.h;
304
305         if (correctionWidth < 0.0f)
306         {
307                 correctionWidth = 0.0f;
308         }
309         if (correctionHeight < 0.0f)
310         {
311                 correctionHeight = 0.0f;
312         }
313
314         LayoutMatchMode widthMatchMode = pContainerProxy->GetItemWidthMatchMode();
315         LayoutMatchMode heightMatchMode = pContainerProxy->GetItemHeightMatchMode();
316
317         SetLayoutRect(clientRect);
318
319         float childrenMaxPosX = 0.0f;
320         float childrenMaxPosY = 0.0f;
321         LayoutRect childRect = {0.0f, 0.0f, 0.0f, 0.0f};
322
323         ProxyListNode* pCurNode = pProxyList->GetFirstNode();
324
325         while (pCurNode != null)
326         {
327                 r = CalculatePosition(*pCurNode);
328                 r = CalculateCenter(*pCurNode, r == E_SUCCESS);
329                 if (r != E_SUCCESS)
330                 {
331                         return r;
332                 }
333
334                 LayoutItemProxy* pItemProxy = pCurNode->GetItemProxy();
335                 if (pItemProxy == null)
336                 {
337                         return E_INVALID_STATE;
338                 }
339
340                 pItemProxy->GetItemWindowRect(childRect);
341
342                 if (childrenMaxPosX < childRect.x + childRect.w)
343                 {
344                         childrenMaxPosX = childRect.x + childRect.w;
345                         if (GetAlignment(*pCurNode, EDGE_RIGHT) != null)
346                         {
347                                 ItemMargin margin = pItemProxy->GetItemMargin();
348                                 childrenMaxPosX += margin.right;
349                         }
350                 }
351
352                 if (childrenMaxPosY < childRect.y + childRect.h)
353                 {
354                         childrenMaxPosY = childRect.y + childRect.h;
355                         if (GetAlignment(*pCurNode, EDGE_BOTTOM) != null)
356                         {
357                                 ItemMargin margin = pItemProxy->GetItemMargin();
358                                 childrenMaxPosY += margin.bottom;
359                         }
360                 }
361
362                 pCurNode = pProxyList->GetNextNode(*pCurNode);
363         }
364
365         if (widthMatchMode == WRAP_CONTENT)
366         {
367                 clientRect.w = childrenMaxPosX + correctionWidth;
368         }
369         else
370         {
371                 clientRect.w += correctionWidth;
372         }
373
374         if (heightMatchMode == WRAP_CONTENT)
375         {
376                 clientRect.h = childrenMaxPosY + correctionHeight;
377         }
378         else
379         {
380                 clientRect.h += correctionHeight;
381         }
382
383         SetLayoutRect(clientRect);
384         LayoutRect containerRect;
385         pContainerProxy->GetItemWindowRect(containerRect);
386         clientRect.x = containerRect.x;
387         clientRect.y = containerRect.y;
388         if (windowRect.w != clientRect.w || windowRect.h != clientRect.h)
389         {
390                 if (updateLayouting)
391                 {
392                         pContainerProxy->SetItemWindowRect(clientRect);
393                 }
394                 // Recalculate
395                 pCurNode = pProxyList->GetFirstNode();
396                 while (pCurNode)
397                 {
398                         r = CalculatePosition(*pCurNode);
399                         r = CalculateCenter(*pCurNode, r == E_SUCCESS);
400                         pCurNode = pProxyList->GetNextNode(*pCurNode);
401                 }
402         }
403
404         return r;
405 }
406
407 result
408 RelativeLayout::IncreaseReferenceCount(ProxyListNode& node)
409 {
410         ProxyList* pProxyList = GetProxyList();
411         SysAssertf(pProxyList != null, "ProxyList is invalid.");
412
413         ProxyListNode* pTargetNode = null;
414         result r = E_SUCCESS;
415         for (int i = EDGE_LEFT; i < EDGE_ALL; i++)
416         {
417                 LayoutItemProxy* pProxy = GetAlignment(node, static_cast <RelativeLayoutEdge>(i));
418                 if (pProxy == null || pProxy == GetContainerProxy())
419                 {
420                         continue;
421                 }
422                 pTargetNode = pProxyList->GetNode(*(pProxy->GetItem()));
423                 if (pTargetNode != null)
424                 {
425                         r = IncreaseReference(*pTargetNode, node);
426                         if (r == E_SUCCESS)
427                         {
428                                 r = IncreaseReferenceCount(*pTargetNode);
429                                 if (r != E_SUCCESS)
430                                 {
431                                         return r;
432                                 }
433                         }
434                         else
435                         {
436                                 return r;
437                         }
438                 }
439         }
440         // Order of nodes is recalculate
441         return AlignItemNodeMaxRefMove();
442 }
443
444 void
445 RelativeLayout::DecreaseReferenceCount(ProxyListNode& node, ProxyListNode& pTargetNode)
446 {
447         ProxyListNode* pTargetTargetNode = null;
448         for (int i = EDGE_LEFT; i <= EDGE_BOTTOM; i++)
449         {
450                 pTargetTargetNode = GetTargetNode(pTargetNode, static_cast <RelativeLayoutEdge>(i));
451                 if (pTargetTargetNode != null)
452                 {
453                         DecreaseReferenceCount(pTargetNode, *pTargetTargetNode);
454                 }
455         }
456         //if (pTargetNode != null)
457         //{
458         SetZeroReference(pTargetNode, node);
459         //}
460 }
461
462 result
463 RelativeLayout::AlignItemNodeMaxRefMove()
464 {
465         result r = E_SUCCESS;
466
467         RelativeProxyList* pRelativeProxyList = GetRelativeProxyList();
468         SysTryReturn(NID_UI, pRelativeProxyList, E_INVALID_STATE, E_INVALID_STATE, "[E_INVALID_STATE] RelativeProxyList is invalid.");
469
470         ProxyListNode* pCurNode = pRelativeProxyList->GetFirstNode();
471         ProxyListNode* pNextNode = pCurNode;
472         int maxRefCount = 0;
473
474         while (pCurNode != null)
475         {
476                 pNextNode = pRelativeProxyList->GetNextNode(*pCurNode);
477                 maxRefCount = pRelativeProxyList->GetReferenceCount(*pCurNode);
478
479                 if (pNextNode != null && maxRefCount < pRelativeProxyList->GetReferenceCount(*pNextNode))
480                 {
481                         ProxyListNode* pMoveNode = pNextNode;
482                         if (pRelativeProxyList->DetachNode(*pMoveNode) != E_SUCCESS)
483                         {
484                                 break;
485                         }
486
487                         maxRefCount = pRelativeProxyList->GetReferenceCount(*pMoveNode);
488
489                         pCurNode = pRelativeProxyList->GetFirstNode();
490                         while (pRelativeProxyList->GetReferenceCount(*pCurNode) >= maxRefCount)
491                         {
492                                 pCurNode = pRelativeProxyList->GetNextNode(*pCurNode);
493                         }
494                         pRelativeProxyList->InsertIntoLeft(*pCurNode, *pMoveNode);
495                         return E_SUCCESS;
496                 }
497                 else
498                 {
499                         pCurNode = pRelativeProxyList->GetNextNode(*pCurNode);
500                 }
501         }
502
503         return r;
504 }
505
506 result
507 RelativeLayout::DeleteTargetInfo(ProxyListNode& targetNode, ProxyListNode& deleteNode)
508 {
509         RelativeItemInfo* pItemInfo = static_cast <RelativeItemInfo*>(targetNode.GetItemInfo());
510         if (pItemInfo == null)
511         {
512                 return E_INVALID_STATE;
513         }
514         for (int i = EDGE_LEFT; i < EDGE_ALL; i++)
515         {
516                 if (pItemInfo->__pTarget[i] == deleteNode.GetItemProxy())
517                 {
518                         UnsetRelation(*(targetNode.GetItemProxy()->GetItem()), static_cast <RelativeLayoutEdge>(i));
519                 }
520         }
521         return E_SUCCESS;
522 }
523
524 result
525 RelativeLayout::CalculatePosition(ProxyListNode& curNode)
526 {
527         RelativeItemInfo* pCurItemInfo = null;
528         LayoutItemProxy* pCurProxy = null;
529         ItemMargin curItemMargin = {0.0f, 0.0f, 0.0f, 0.0f};
530         LayoutRect curItemRect = {0.0f, 0.0f, 0.0f, 0.0f};
531         LayoutPoint targetPosition = {0.0f, 0.0f};
532         result r = E_SYSTEM;
533
534         pCurItemInfo = static_cast <RelativeItemInfo*>(curNode.GetItemInfo());
535         pCurProxy = curNode.GetItemProxy();
536
537         if (pCurItemInfo == null || pCurProxy == null)
538         {
539                 return E_INVALID_STATE;
540         }
541
542         curItemRect = pCurProxy->GetItemBaseRect();
543         GetItemMargin(*(pCurProxy->GetItem()), curItemMargin);
544
545         r = pCurProxy->Measure(curItemRect.w, curItemRect.h);
546         if (r != E_SUCCESS)
547         {
548                 return r;
549         }
550         pCurProxy->GetMeasuredSize(curItemRect.w, curItemRect.h);
551
552         if (pCurItemInfo->__pTarget[EDGE_LEFT] != null)
553         {
554                 r = GetTargetPosition(pCurItemInfo->__pTarget[EDGE_LEFT], pCurItemInfo->__targetEdge[EDGE_LEFT], targetPosition);
555                 if (r != E_SUCCESS)
556                 {
557                         return r;
558                 }
559                 AlignToDevice(curItemRect, curItemRect);
560                 curItemRect.x = targetPosition.x + curItemMargin.left;
561         }
562
563         if (pCurItemInfo->__pTarget[EDGE_TOP] != null)
564         {
565                 r = GetTargetPosition(pCurItemInfo->__pTarget[EDGE_TOP], pCurItemInfo->__targetEdge[EDGE_TOP], targetPosition);
566                 if (r != E_SUCCESS)
567                 {
568                         return r;
569                 }
570                 AlignToDevice(curItemRect, curItemRect);
571                 curItemRect.y = targetPosition.y + curItemMargin.top;
572         }
573
574         if (pCurItemInfo->__pTarget[EDGE_RIGHT] != null)
575         {
576                 r = GetTargetPosition(pCurItemInfo->__pTarget[EDGE_RIGHT], pCurItemInfo->__targetEdge[EDGE_RIGHT], targetPosition);
577                 if (r != E_SUCCESS)
578                 {
579                         return r;
580                 }
581
582                 AlignToDevice(curItemRect, curItemRect);
583                 if (pCurItemInfo->__pTarget[EDGE_LEFT] != null)
584                 {
585                         curItemRect.w = targetPosition.x - curItemRect.x - curItemMargin.right;
586                 }
587                 curItemRect.x = targetPosition.x - curItemMargin.right - curItemRect.w;
588         }
589
590         if (pCurItemInfo->__pTarget[EDGE_BOTTOM] != null)
591         {
592                 r = GetTargetPosition(pCurItemInfo->__pTarget[EDGE_BOTTOM], pCurItemInfo->__targetEdge[EDGE_BOTTOM], targetPosition);
593                 if (r != E_SUCCESS)
594                 {
595                         return r;
596                 }
597
598                 AlignToDevice(curItemRect, curItemRect);
599                 if (pCurItemInfo->__pTarget[EDGE_TOP] != null)
600                 {
601                         curItemRect.h = targetPosition.y - curItemRect.y - curItemMargin.bottom;
602                 }
603                 curItemRect.y = targetPosition.y - curItemMargin.bottom - curItemRect.h;
604         }
605
606         r = pCurProxy->Measure(curItemRect.w, curItemRect.h);
607         if (r != E_SUCCESS)
608         {
609                 return r;
610         }
611         pCurProxy->GetMeasuredSize(curItemRect.w, curItemRect.h);
612
613         r = pCurProxy->SetItemWindowRect(curItemRect);
614         if (r != E_SUCCESS)
615         {
616                 return r;
617         }
618
619         return r;
620 }
621
622 result
623 RelativeLayout::CalculateCenter(ProxyListNode& curNode, bool calcPosition)
624 {
625         LayoutRect targetRect;
626         RelativeItemInfo* pCurItemInfo = null;
627         LayoutItemProxy* pCurProxy = null;
628         LayoutRect curItemRect = {0.0f, 0.0f, 0.0f, 0.0f};
629         result r = E_SYSTEM;
630
631         pCurItemInfo = static_cast <RelativeItemInfo*>(curNode.GetItemInfo());
632         pCurProxy = curNode.GetItemProxy();
633
634         if (pCurItemInfo == null || pCurProxy == null)
635         {
636                 return E_INVALID_STATE;
637         }
638
639         if (pCurItemInfo->__pTarget[EDGE_HCENTER] == null && pCurItemInfo->__pTarget[EDGE_VCENTER] == null)
640         {
641                 return E_SUCCESS;
642         }
643
644         if (calcPosition)
645         {
646                 pCurProxy->GetItemWindowRect(curItemRect);
647         }
648         else
649         {
650                 curItemRect = pCurProxy->GetItemBaseRect();
651         }
652
653         r = pCurProxy->Measure(curItemRect.w, curItemRect.h);
654         if (r != E_SUCCESS)
655         {
656                 return r;
657         }
658         pCurProxy->GetMeasuredSize(curItemRect.w, curItemRect.h);
659
660         if (pCurItemInfo->__pTarget[EDGE_HCENTER] == __pTargetParent)
661         {
662                 targetRect = GetLayoutRect();
663                 float targetWidth = targetRect.w;
664                 float margin = ((targetWidth - curItemRect.w) / 2);
665                 curItemRect.x = margin + targetRect.x;
666         }
667
668         if (pCurItemInfo->__pTarget[EDGE_VCENTER] == __pTargetParent)
669         {
670                 targetRect = GetLayoutRect();
671                 float targetHeight = targetRect.h;
672                 float margin = ((targetHeight - curItemRect.h) / 2);
673                 curItemRect.y = margin + targetRect.y;
674         }
675
676         r = pCurProxy->Measure(curItemRect.w, curItemRect.h);
677         if (r != E_SUCCESS)
678         {
679                 return r;
680         }
681         pCurProxy->GetMeasuredSize(curItemRect.w, curItemRect.h);
682
683         r = pCurProxy->SetItemWindowRect(curItemRect);
684         if (r != E_SUCCESS)
685         {
686                 return r;
687         }
688
689         return r;
690 }
691
692 bool
693 RelativeLayout::CheckTargetEdge(const RelativeLayoutEdge sourceEdge, const RelativeLayoutEdge targetEdge) const
694 {
695         if (sourceEdge & 0x1)
696         {
697                 if (targetEdge & 0x1)
698                 {
699                         return true;
700                 }
701                 else
702                 {
703                         return false;
704                 }
705         }
706         else if (!(sourceEdge & 0x1))
707         {
708                 if (targetEdge & 0x1)
709                 {
710                         return false;
711                 }
712                 else
713                 {
714                         return true;
715                 }
716         }
717
718         return false;
719 }
720
721 result
722 RelativeLayout::SetAlignment(ProxyListNode& sourceNode, const RelativeLayoutEdge sourceEdge, ProxyListNode* pTargetNode, const RelativeLayoutEdge targetEdge)
723 {
724         RelativeLayoutEdge realTargetEdge = targetEdge;
725         if (realTargetEdge == EDGE_NONE)
726         {
727                 realTargetEdge = sourceEdge;
728         }
729
730         if (!CheckTargetEdge(sourceEdge, realTargetEdge))
731         {
732                 return E_INVALID_ARG;
733         }
734
735         RelativeItemInfo* pSourceItemInfo = static_cast <RelativeItemInfo*>(sourceNode.GetItemInfo());
736
737         if (pSourceItemInfo == null || pSourceItemInfo->__targetEdge[sourceEdge] != EDGE_NONE || pSourceItemInfo->__pTarget[sourceEdge] != null)
738         {
739                 return E_INVALID_STATE;
740         }
741
742         LayoutItemProxy* pTargetProxy = null;
743         if (pTargetNode == null)
744         {
745                 pTargetProxy = const_cast <LayoutItemProxy*>(__pTargetParent);
746         }
747         else
748         {
749                 pTargetProxy = pTargetNode->GetItemProxy();
750         }
751         if (pTargetProxy == null)
752         {
753                 return E_INVALID_ARG;
754         }
755
756         pSourceItemInfo->__targetEdge[sourceEdge] = realTargetEdge;
757         pSourceItemInfo->__pTarget[sourceEdge] = pTargetProxy;
758
759         return E_SUCCESS;
760 }
761
762 result
763 RelativeLayout::UnsetAlignment(ProxyListNode& sourceNode, const RelativeLayoutEdge sourceEdge, LayoutItemProxy** ppTargetProxy)
764 {
765         RelativeItemInfo* pSourceItemInfo = static_cast <RelativeItemInfo*>(sourceNode.GetItemInfo());
766
767         if (pSourceItemInfo == null)
768         {
769                 return E_INVALID_STATE;
770         }
771
772         if (sourceEdge != EDGE_NONE)
773         {
774                 pSourceItemInfo->__targetEdge[sourceEdge] = EDGE_NONE;
775                 if (pSourceItemInfo->__pTarget[sourceEdge] != null)
776                 {
777                         if (ppTargetProxy != null)
778                         {
779                                 if (pSourceItemInfo->__pTarget[sourceEdge] != __pTargetParent)
780                                 {
781                                         *ppTargetProxy = pSourceItemInfo->__pTarget[sourceEdge];
782                                 }
783                                 else
784                                 {
785                                         *ppTargetProxy = null;
786                                 }
787                         }
788                         pSourceItemInfo->__pTarget[sourceEdge] = null;
789                 }
790                 else
791                 {
792                         return E_INVALID_STATE;
793                 }
794                 return E_SUCCESS;
795         }
796
797         return E_SYSTEM;
798 }
799
800 LayoutItemProxy*
801 RelativeLayout::GetAlignment(ProxyListNode& sourceNode, const RelativeLayoutEdge sourceEdge, RelativeLayoutEdge* pTargetEdge)
802 {
803         SysTryReturn(NID_UI, sourceEdge >= EDGE_NONE, null, E_OUT_OF_RANGE, "[E_OUT_OF_RANGE] Argument is out of range.");
804         SysTryReturn(NID_UI, sourceEdge <= EDGE_VCENTER, null, E_OUT_OF_RANGE, "[E_OUT_OF_RANGE] Argument is out of range.");
805         RelativeItemInfo* pSourceItemInfo = static_cast <RelativeItemInfo*>(sourceNode.GetItemInfo());
806
807         SysTryReturn(NID_UI, pSourceItemInfo, null, E_INVALID_STATE, "[E_INVALID_STATE] RelativeItemInfo is invalid.");
808
809         if (pTargetEdge != null)
810         {
811                 *pTargetEdge = pSourceItemInfo->__targetEdge[sourceEdge];
812         }
813
814         if (pSourceItemInfo->__pTarget[sourceEdge] != __pTargetParent)
815         {
816                 return pSourceItemInfo->__pTarget[sourceEdge];
817         }
818         else
819         {
820                 return GetContainerProxy();
821         }
822 }
823
824 result
825 RelativeLayout::IncreaseReference(ProxyListNode& targetNode, ProxyListNode& sourceNode)
826 {
827         ProxyList* pProxyList = GetProxyList();
828         SysAssertf(pProxyList != null, "ProxyList is invalid.");
829
830         RelativeItemInfo* pTargetItemInfo = static_cast <RelativeItemInfo*>(targetNode.GetItemInfo());
831         RelativeItemInfo* pSourceItemInfo = static_cast <RelativeItemInfo*>(sourceNode.GetItemInfo());
832
833         if (pTargetItemInfo == null || pSourceItemInfo == null)
834         {
835                 return E_INVALID_STATE;
836         }
837
838         int refCount = pSourceItemInfo->__refCount + 1;
839
840         if (refCount > pProxyList->GetNodeCount() - 1)
841         {
842                 return E_INVALID_STATE;
843         }
844
845         if (refCount > pTargetItemInfo->__refCount)
846         {
847                 pTargetItemInfo->__refCount = refCount;
848         }
849         return E_SUCCESS;
850 }
851
852 ProxyListNode*
853 RelativeLayout::GetTargetNode(ProxyListNode& node, RelativeLayoutEdge sourceEdge)
854 {
855         ProxyList* pProxyList = GetProxyList();
856         SysAssertf(pProxyList != null, "ProxyList is invalid.");
857
858         LayoutItemProxy* pProxy = GetAlignment(node, sourceEdge);
859         if (pProxy == null || pProxy == GetContainerProxy())
860         {
861                 return null;
862         }
863         return pProxyList->GetNode(*(pProxy->GetItem()));
864 }
865
866 result
867 RelativeLayout::SetZeroReference(ProxyListNode& node, ProxyListNode& baseNode)
868 {
869         RelativeItemInfo* pTargetItemInfo = static_cast <RelativeItemInfo*>(node.GetItemInfo());
870         if (pTargetItemInfo == null)
871         {
872                 return E_INVALID_STATE;
873         }
874
875         pTargetItemInfo->__refCount = 0;
876
877         return E_SUCCESS;
878 }
879
880 result
881 RelativeLayout::GetTargetPosition(LayoutItemProxy* pTargetProxy, const RelativeLayoutEdge targetEdge, LayoutPoint& targetPoint) const
882 {
883         if (pTargetProxy == null)
884         {
885                 return E_INVALID_ARG;
886         }
887
888         LayoutRect targetRect;
889         if (pTargetProxy == __pTargetParent)
890         {
891                 targetRect = GetLayoutRect();
892         }
893         else
894         {
895                 pTargetProxy->GetItemWindowRect(targetRect);
896         }
897
898         switch (targetEdge)
899         {
900         case EDGE_LEFT:
901                 targetPoint.x = targetRect.x;
902                 break;
903
904         case EDGE_TOP:
905                 targetPoint.y = targetRect.y;
906                 break;
907
908         case EDGE_RIGHT:
909                 targetPoint.x = targetRect.x + targetRect.w;
910                 break;
911
912         case EDGE_BOTTOM:
913                 targetPoint.y = targetRect.y + targetRect.h;
914                 break;
915
916         default:
917                 return E_SYSTEM;
918         }
919
920         return E_SUCCESS;
921 }
922
923 RelativeProxyList*
924 RelativeLayout::GetRelativeProxyList(void)
925 {
926         return static_cast <RelativeProxyList*>(GetProxyList());
927 }
928
929 }}} // Tizen::Ui::_Layout