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