fixed bug (TapGesture improvement)
[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                 curItemRect.x = targetPosition.x + curItemMargin.left;
560         }
561
562         if (pCurItemInfo->__pTarget[EDGE_TOP] != null)
563         {
564                 r = GetTargetPosition(pCurItemInfo->__pTarget[EDGE_TOP], pCurItemInfo->__targetEdge[EDGE_TOP], targetPosition);
565                 if (r != E_SUCCESS)
566                 {
567                         return r;
568                 }
569                 curItemRect.y = targetPosition.y + curItemMargin.top;
570         }
571
572         if (pCurItemInfo->__pTarget[EDGE_RIGHT] != null)
573         {
574                 r = GetTargetPosition(pCurItemInfo->__pTarget[EDGE_RIGHT], pCurItemInfo->__targetEdge[EDGE_RIGHT], targetPosition);
575                 if (r != E_SUCCESS)
576                 {
577                         return r;
578                 }
579
580                 if (pCurItemInfo->__pTarget[EDGE_LEFT] != null)
581                 {
582                         curItemRect.w = targetPosition.x - curItemRect.x - curItemMargin.right;
583                 }
584                 curItemRect.x = targetPosition.x - curItemMargin.right - curItemRect.w;
585         }
586
587         if (pCurItemInfo->__pTarget[EDGE_BOTTOM] != null)
588         {
589                 r = GetTargetPosition(pCurItemInfo->__pTarget[EDGE_BOTTOM], pCurItemInfo->__targetEdge[EDGE_BOTTOM], targetPosition);
590                 if (r != E_SUCCESS)
591                 {
592                         return r;
593                 }
594
595                 if (pCurItemInfo->__pTarget[EDGE_TOP] != null)
596                 {
597                         curItemRect.h = targetPosition.y - curItemRect.y - curItemMargin.bottom;
598                 }
599                 curItemRect.y = targetPosition.y - curItemMargin.bottom - curItemRect.h;
600         }
601
602         r = pCurProxy->Measure(curItemRect.w, curItemRect.h);
603         if (r != E_SUCCESS)
604         {
605                 return r;
606         }
607         pCurProxy->GetMeasuredSize(curItemRect.w, curItemRect.h);
608
609         r = pCurProxy->SetItemWindowRect(curItemRect);
610         if (r != E_SUCCESS)
611         {
612                 return r;
613         }
614
615         return r;
616 }
617
618 result
619 RelativeLayout::CalculateCenter(ProxyListNode& curNode, bool calcPosition)
620 {
621         LayoutRect targetRect;
622         RelativeItemInfo* pCurItemInfo = null;
623         LayoutItemProxy* pCurProxy = null;
624         LayoutRect curItemRect = {0.0f, 0.0f, 0.0f, 0.0f};
625         result r = E_SYSTEM;
626
627         pCurItemInfo = static_cast <RelativeItemInfo*>(curNode.GetItemInfo());
628         pCurProxy = curNode.GetItemProxy();
629
630         if (pCurItemInfo == null || pCurProxy == null)
631         {
632                 return E_INVALID_STATE;
633         }
634
635         if (pCurItemInfo->__pTarget[EDGE_HCENTER] == null && pCurItemInfo->__pTarget[EDGE_VCENTER] == null)
636         {
637                 return E_SUCCESS;
638         }
639
640         if (calcPosition)
641         {
642                 pCurProxy->GetItemWindowRect(curItemRect);
643         }
644         else
645         {
646                 curItemRect = pCurProxy->GetItemBaseRect();
647         }
648
649         r = pCurProxy->Measure(curItemRect.w, curItemRect.h);
650         if (r != E_SUCCESS)
651         {
652                 return r;
653         }
654         pCurProxy->GetMeasuredSize(curItemRect.w, curItemRect.h);
655
656         if (pCurItemInfo->__pTarget[EDGE_HCENTER] == __pTargetParent)
657         {
658                 targetRect = GetLayoutRect();
659                 float targetWidth = targetRect.w;
660                 float margin = ((targetWidth - curItemRect.w) / 2);
661                 curItemRect.x = margin + targetRect.x;
662         }
663
664         if (pCurItemInfo->__pTarget[EDGE_VCENTER] == __pTargetParent)
665         {
666                 targetRect = GetLayoutRect();
667                 float targetHeight = targetRect.h;
668                 float margin = ((targetHeight - curItemRect.h) / 2);
669                 curItemRect.y = margin + targetRect.y;
670         }
671
672         r = pCurProxy->Measure(curItemRect.w, curItemRect.h);
673         if (r != E_SUCCESS)
674         {
675                 return r;
676         }
677         pCurProxy->GetMeasuredSize(curItemRect.w, curItemRect.h);
678
679         r = pCurProxy->SetItemWindowRect(curItemRect);
680         if (r != E_SUCCESS)
681         {
682                 return r;
683         }
684
685         return r;
686 }
687
688 bool
689 RelativeLayout::CheckTargetEdge(const RelativeLayoutEdge sourceEdge, const RelativeLayoutEdge targetEdge) const
690 {
691         if (sourceEdge & 0x1)
692         {
693                 if (targetEdge & 0x1)
694                 {
695                         return true;
696                 }
697                 else
698                 {
699                         return false;
700                 }
701         }
702         else if (!(sourceEdge & 0x1))
703         {
704                 if (targetEdge & 0x1)
705                 {
706                         return false;
707                 }
708                 else
709                 {
710                         return true;
711                 }
712         }
713
714         return false;
715 }
716
717 result
718 RelativeLayout::SetAlignment(ProxyListNode& sourceNode, const RelativeLayoutEdge sourceEdge, ProxyListNode* pTargetNode, const RelativeLayoutEdge targetEdge)
719 {
720         RelativeLayoutEdge realTargetEdge = targetEdge;
721         if (realTargetEdge == EDGE_NONE)
722         {
723                 realTargetEdge = sourceEdge;
724         }
725
726         if (!CheckTargetEdge(sourceEdge, realTargetEdge))
727         {
728                 return E_INVALID_ARG;
729         }
730
731         RelativeItemInfo* pSourceItemInfo = static_cast <RelativeItemInfo*>(sourceNode.GetItemInfo());
732
733         if (pSourceItemInfo == null || pSourceItemInfo->__targetEdge[sourceEdge] != EDGE_NONE || pSourceItemInfo->__pTarget[sourceEdge] != null)
734         {
735                 return E_INVALID_STATE;
736         }
737
738         LayoutItemProxy* pTargetProxy = null;
739         if (pTargetNode == null)
740         {
741                 pTargetProxy = const_cast <LayoutItemProxy*>(__pTargetParent);
742         }
743         else
744         {
745                 pTargetProxy = pTargetNode->GetItemProxy();
746         }
747         if (pTargetProxy == null)
748         {
749                 return E_INVALID_ARG;
750         }
751
752         pSourceItemInfo->__targetEdge[sourceEdge] = realTargetEdge;
753         pSourceItemInfo->__pTarget[sourceEdge] = pTargetProxy;
754
755         return E_SUCCESS;
756 }
757
758 result
759 RelativeLayout::UnsetAlignment(ProxyListNode& sourceNode, const RelativeLayoutEdge sourceEdge, LayoutItemProxy** ppTargetProxy)
760 {
761         RelativeItemInfo* pSourceItemInfo = static_cast <RelativeItemInfo*>(sourceNode.GetItemInfo());
762
763         if (pSourceItemInfo == null)
764         {
765                 return E_INVALID_STATE;
766         }
767
768         if (sourceEdge != EDGE_NONE)
769         {
770                 pSourceItemInfo->__targetEdge[sourceEdge] = EDGE_NONE;
771                 if (pSourceItemInfo->__pTarget[sourceEdge] != null)
772                 {
773                         if (ppTargetProxy != null)
774                         {
775                                 if (pSourceItemInfo->__pTarget[sourceEdge] != __pTargetParent)
776                                 {
777                                         *ppTargetProxy = pSourceItemInfo->__pTarget[sourceEdge];
778                                 }
779                                 else
780                                 {
781                                         *ppTargetProxy = null;
782                                 }
783                         }
784                         pSourceItemInfo->__pTarget[sourceEdge] = null;
785                 }
786                 else
787                 {
788                         return E_INVALID_STATE;
789                 }
790                 return E_SUCCESS;
791         }
792
793         return E_SYSTEM;
794 }
795
796 LayoutItemProxy*
797 RelativeLayout::GetAlignment(ProxyListNode& sourceNode, const RelativeLayoutEdge sourceEdge, RelativeLayoutEdge* pTargetEdge)
798 {
799         SysTryReturn(NID_UI, sourceEdge >= EDGE_NONE, null, E_OUT_OF_RANGE, "[E_OUT_OF_RANGE] Argument is out of range.");
800         SysTryReturn(NID_UI, sourceEdge <= EDGE_VCENTER, null, E_OUT_OF_RANGE, "[E_OUT_OF_RANGE] Argument is out of range.");
801         RelativeItemInfo* pSourceItemInfo = static_cast <RelativeItemInfo*>(sourceNode.GetItemInfo());
802
803         SysTryReturn(NID_UI, pSourceItemInfo, null, E_INVALID_STATE, "[E_INVALID_STATE] RelativeItemInfo is invalid.");
804
805         if (pTargetEdge != null)
806         {
807                 *pTargetEdge = pSourceItemInfo->__targetEdge[sourceEdge];
808         }
809
810         if (pSourceItemInfo->__pTarget[sourceEdge] != __pTargetParent)
811         {
812                 return pSourceItemInfo->__pTarget[sourceEdge];
813         }
814         else
815         {
816                 return GetContainerProxy();
817         }
818 }
819
820 result
821 RelativeLayout::IncreaseReference(ProxyListNode& targetNode, ProxyListNode& sourceNode)
822 {
823         ProxyList* pProxyList = GetProxyList();
824         SysAssertf(pProxyList != null, "ProxyList is invalid.");
825
826         RelativeItemInfo* pTargetItemInfo = static_cast <RelativeItemInfo*>(targetNode.GetItemInfo());
827         RelativeItemInfo* pSourceItemInfo = static_cast <RelativeItemInfo*>(sourceNode.GetItemInfo());
828
829         if (pTargetItemInfo == null || pSourceItemInfo == null)
830         {
831                 return E_INVALID_STATE;
832         }
833
834         int refCount = pSourceItemInfo->__refCount + 1;
835
836         if (refCount > pProxyList->GetNodeCount() - 1)
837         {
838                 return E_INVALID_STATE;
839         }
840
841         if (refCount > pTargetItemInfo->__refCount)
842         {
843                 pTargetItemInfo->__refCount = refCount;
844         }
845         return E_SUCCESS;
846 }
847
848 ProxyListNode*
849 RelativeLayout::GetTargetNode(ProxyListNode& node, RelativeLayoutEdge sourceEdge)
850 {
851         ProxyList* pProxyList = GetProxyList();
852         SysAssertf(pProxyList != null, "ProxyList is invalid.");
853
854         LayoutItemProxy* pProxy = GetAlignment(node, sourceEdge);
855         if (pProxy == null || pProxy == GetContainerProxy())
856         {
857                 return null;
858         }
859         return pProxyList->GetNode(*(pProxy->GetItem()));
860 }
861
862 result
863 RelativeLayout::SetZeroReference(ProxyListNode& node, ProxyListNode& baseNode)
864 {
865         RelativeItemInfo* pTargetItemInfo = static_cast <RelativeItemInfo*>(node.GetItemInfo());
866         if (pTargetItemInfo == null)
867         {
868                 return E_INVALID_STATE;
869         }
870
871         pTargetItemInfo->__refCount = 0;
872
873         return E_SUCCESS;
874 }
875
876 result
877 RelativeLayout::GetTargetPosition(LayoutItemProxy* pTargetProxy, const RelativeLayoutEdge targetEdge, LayoutPoint& targetPoint) const
878 {
879         if (pTargetProxy == null)
880         {
881                 return E_INVALID_ARG;
882         }
883
884         LayoutRect targetRect;
885         if (pTargetProxy == __pTargetParent)
886         {
887                 targetRect = GetLayoutRect();
888         }
889         else
890         {
891                 pTargetProxy->GetItemWindowRect(targetRect);
892         }
893
894         switch (targetEdge)
895         {
896         case EDGE_LEFT:
897                 targetPoint.x = targetRect.x;
898                 break;
899
900         case EDGE_TOP:
901                 targetPoint.y = targetRect.y;
902                 break;
903
904         case EDGE_RIGHT:
905                 targetPoint.x = targetRect.x + targetRect.w;
906                 break;
907
908         case EDGE_BOTTOM:
909                 targetPoint.y = targetRect.y + targetRect.h;
910                 break;
911
912         default:
913                 return E_SYSTEM;
914         }
915
916         return E_SUCCESS;
917 }
918
919 RelativeProxyList*
920 RelativeLayout::GetRelativeProxyList(void)
921 {
922         return static_cast <RelativeProxyList*>(GetProxyList());
923 }
924
925 }}} // Tizen::Ui::_Layout