Tizen 2.1 base
[framework/osp/uifw.git] / src / ui / layout / FUi_LayoutLayoutContainer.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_LayoutLayoutContainer.cpp
19  * @brief       This is the implementation file for LayoutContainer class.
20  *
21  * This file contains the implementation of LayoutContainer class.
22  */
23
24 #include <new>
25 #include "FUi_Control.h"
26 #include "FUi_LayoutLayoutContainer.h"
27 #include "FUi_LayoutLayoutList.h"
28 #include "FUi_LayoutLayout.h"
29 #include "FUi_LayoutAbsoluteLayout.h"
30
31 namespace Tizen { namespace Ui { namespace _Layout
32 {
33
34 LayoutContainer::LayoutContainer(void)
35         : __pCurrentLayout(null)
36         , __defaultLayoutFlag(false)
37 {
38         LayoutSize zeroSize = {0, 0};
39         __intendedWindowSize = zeroSize;
40
41         __pLayoutList = new (std::nothrow) LayoutList();
42         SysTryReturnVoidResult(NID_UI, __pLayoutList, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
43 }
44
45 LayoutContainer::~LayoutContainer(void)
46 {
47         Layout* pDefaultLayout = GetDefaultLayout();
48         delete pDefaultLayout;
49
50         LayoutListNode* pLayoutNode = __pLayoutList->GetFirstNode();
51         while (pLayoutNode != null)
52         {
53                 Layout* pLayout = pLayoutNode->GetLayout();
54                 if (pLayout != null)
55                 {
56                         if (pLayout->SetContainer(null) != E_SUCCESS)
57                         {
58                                 SysAssert(false);
59                         }
60                 }
61                 pLayoutNode = __pLayoutList->GetNextNode(*pLayoutNode);
62         }
63         delete __pLayoutList;
64 }
65
66 result
67 LayoutContainer::SetCurrentLayout(Layout& layout)
68 {
69         if (!__pLayoutList->CheckNodeExists(layout))
70         {
71                 SysTryReturn(NID_UI, false, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] This layout does not exist.");
72         }
73
74         __pCurrentLayout = &layout;
75         __pCurrentLayout->SetUpdateState(true);
76
77         return E_SUCCESS;
78 }
79
80 result
81 LayoutContainer::AddLayout(Layout& layout)
82 {
83         result r = E_SUCCESS;
84
85         if (!__pLayoutList->CheckNodeExists(layout))
86         {
87                 SysTryReturn(NID_UI, !layout.HasLayoutContainer(), E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] This layout already belong to other container.");
88                 SysTryReturn(NID_UI, __pLayoutList->AddNode(layout), E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
89                 r = layout.SetContainer(this);
90         }
91
92         return r;
93 }
94
95 Layout*
96 LayoutContainer::GetLayout() const
97 {
98         return __pCurrentLayout;
99 }
100
101 result
102 LayoutContainer::AddItem(LayoutItem& addItem)
103 {
104         LayoutListNode* pCurNode = __pLayoutList->GetFirstNode();
105         Layout* pLayout = null;
106         result r = E_SUCCESS;
107
108         while (pCurNode)
109         {
110                 pLayout = pCurNode->GetLayout();
111                 if (pLayout)
112                 {
113                         r = pLayout->AddItem(addItem);
114                 }
115
116                 SysTryCatch(NID_UI, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
117
118                 pCurNode = __pLayoutList->GetNextNode(*pCurNode);
119         }
120         return E_SUCCESS;
121
122 CATCH:
123         LayoutListNode* pRollBackNode = __pLayoutList->GetFirstNode();
124         while (pRollBackNode != null && pRollBackNode != pCurNode)
125         {
126                 pLayout = pRollBackNode->GetLayout();
127                 if (pLayout)
128                 {
129                         pLayout->RemoveItem(addItem);
130                 }
131
132                 pRollBackNode = __pLayoutList->GetNextNode(*pCurNode);
133         }
134         return r;
135 }
136
137 result
138 LayoutContainer::RemoveItem(LayoutItem& removeItem)
139 {
140         LayoutListNode* pCurNode = __pLayoutList->GetFirstNode();
141         Layout* pLayout = null;
142         result r = E_SUCCESS;
143
144         while (pCurNode)
145         {
146                 pLayout = pCurNode->GetLayout();
147                 if (pLayout)
148                 {
149                         r |= pLayout->RemoveItem(removeItem);
150                 }
151                 pCurNode = __pLayoutList->GetNextNode(*pCurNode);
152         }
153
154         return (r == E_SUCCESS) ? E_SUCCESS : GetLastResult();
155 }
156
157 void
158 LayoutContainer::OnDestroyItem(LayoutItem& item)
159 {
160         LayoutListNode* pCurNode = __pLayoutList->GetFirstNode();
161         Layout* pLayout = null;
162
163         while (pCurNode)
164         {
165                 pLayout = pCurNode->GetLayout();
166                 if (pLayout)
167                 {
168                         pLayout->RemoveItem(item);
169                 }
170                 pCurNode = __pLayoutList->GetNextNode(*pCurNode);
171         }
172 }
173
174 result
175 LayoutContainer::OnSetDefaultLayout(Layout& deletedLayout)
176 {
177         LayoutListNode* pDefaultNode = __pLayoutList->GetFirstNode();
178         if (pDefaultNode == null)
179         {
180                 return E_INVALID_STATE;
181         }
182
183         Layout* pLayout = pDefaultNode->GetLayout();
184         if (pLayout == null)
185         {
186                 return E_INVALID_STATE;
187         }
188
189         if (__pCurrentLayout == &deletedLayout)
190         {
191                 SetCurrentLayout(*pLayout);
192                 return E_SUCCESS;
193         }
194
195         return E_SYSTEM;
196 }
197
198 void
199 LayoutContainer::SetIntendedWindowSize(const LayoutSize intendedWindowSize)
200 {
201         __intendedWindowSize = intendedWindowSize;
202 }
203
204 LayoutSize
205 LayoutContainer::GetIntendedWindowSize() const
206 {
207         return __intendedWindowSize;
208 }
209
210 result
211 LayoutContainer::Measure(int width, int height)
212 {
213         LayoutContainer* pContainer = GetParentContainer();
214         if (pContainer == null)
215         {
216                 return E_INVALID_STATE;
217         }
218
219         Layout* pLayout = pContainer->GetLayout();
220         if (pLayout == null)
221         {
222                 return E_INVALID_STATE;
223         }
224
225         LayoutMatchMode widthMode;
226         LayoutMatchMode heightMode;
227         result re = E_SYSTEM;
228         re = pLayout->GetItemWidthMatchMode(*this, widthMode);
229         if (re != E_SUCCESS)
230         {
231                 return re;
232         }
233         re = pLayout->GetItemHeightMatchMode(*this, heightMode);
234         if (re != E_SUCCESS)
235         {
236                 return re;
237         }
238
239         re = LayoutItem::Measure(width, height);
240         if (re != E_SUCCESS)
241         {
242                 return re;
243         }
244
245         int measuredWidth = 0;
246         int measuredHeight = 0;
247         GetMeasuredSize(measuredWidth, measuredHeight);
248
249         bool wrapContainer = true;
250         LayoutRect itemBounds;
251         pLayout->GetItemBaseRect(*this, itemBounds);
252
253         if (widthMode == WRAP_CONTENT || heightMode == WRAP_CONTENT)
254         {
255                 if (measuredWidth != itemBounds.w || measuredHeight != itemBounds.h)
256                 {
257                         wrapContainer = false;
258                 }
259         }
260
261         if (widthMode == WRAP_CONTENT && wrapContainer)
262         {
263                 measuredWidth = width;
264         }
265         if (heightMode == WRAP_CONTENT && wrapContainer)
266         {
267                 measuredHeight = height;
268         }
269
270         LayoutRect rect = {0, 0, measuredWidth, measuredHeight};
271
272         if (__pCurrentLayout != null)
273         {
274                 LayoutRect calculatedRect;
275                 GetItemWindowRect(calculatedRect);
276                 calculatedRect.w = measuredWidth;
277                 calculatedRect.h = measuredHeight;
278                 SetItemWindowRect(calculatedRect);
279
280                 ConvertWindowToClientBounds(calculatedRect, calculatedRect);
281
282                 LayoutSize containerSize = {calculatedRect.w, calculatedRect.h};
283
284                 SetIntendedWindowSize(containerSize);
285                 __pCurrentLayout->OnLayout(measuredWidth, measuredHeight, true);
286                 rect = __pCurrentLayout->GetLayoutRect();
287         }
288
289         if (widthMode == WRAP_CONTENT && wrapContainer)
290         {
291                 measuredWidth = rect.w;
292         }
293         if (heightMode == WRAP_CONTENT && wrapContainer)
294         {
295                 measuredHeight = rect.h;
296         }
297
298         RunItemMeasure(measuredWidth, measuredHeight);
299
300         LayoutSize minSize;
301         LayoutSize maxSize;
302
303         GetMinSize(minSize);
304         GetMaxSize(maxSize);
305
306         if (measuredWidth < minSize.w)
307         {
308                 measuredWidth = minSize.w;
309         }
310         else if (measuredWidth > maxSize.w)
311         {
312                 measuredWidth = maxSize.w;
313         }
314
315         if (measuredHeight < minSize.h)
316         {
317                 measuredHeight = minSize.h;
318         }
319         else if (measuredHeight > maxSize.h)
320         {
321                 measuredHeight = maxSize.h;
322         }
323
324         SetMeasuredSize(measuredWidth, measuredHeight);
325
326         return E_SUCCESS;
327 }
328
329 void
330 LayoutContainer::OnDestroyLayout(Layout& layout)
331 {
332         LayoutListNode* pLayoutNode = __pLayoutList->GetFirstNode();
333         while (pLayoutNode != null)
334         {
335                 if (pLayoutNode->GetLayout() == &layout)
336                 {
337                         __pLayoutList->RemoveNode(*pLayoutNode);
338                         break;
339                 }
340                 pLayoutNode = __pLayoutList->GetNextNode(*pLayoutNode);
341         }
342
343         if (&layout == __pCurrentLayout)
344         {
345                 pLayoutNode = __pLayoutList->GetFirstNode();
346
347                 if (pLayoutNode != null)
348                 {
349                         SetCurrentLayout(*pLayoutNode->GetLayout());
350                 }
351         }
352 }
353
354 result
355 LayoutContainer::SetDefaultLayout(Layout& layout)
356 {
357         if (__defaultLayoutFlag)
358         {
359                 return E_INVALID_STATE;
360         }
361
362         if (__pLayoutList->GetFirstNode() != null)
363         {
364                 return E_INVALID_STATE;
365         }
366         AddLayout(layout);
367         __defaultLayoutFlag = true;
368
369         return SetCurrentLayout(layout);
370 }
371
372 Layout*
373 LayoutContainer::GetDefaultLayout() const
374 {
375         LayoutListNode* pLayoutNode = __pLayoutList->GetFirstNode();
376         if (pLayoutNode == null)
377         {
378                 return null;
379         }
380         else
381         {
382                 return pLayoutNode->GetLayout();
383         }
384 }
385
386 bool
387 LayoutContainer::LayoutExists(Layout& layout)
388 {
389         return __pLayoutList->CheckNodeExists(layout);
390 }
391
392 void
393 LayoutContainer::OnDestroyContainerProxy()
394 {
395         LayoutListNode* pCurNode = __pLayoutList->GetFirstNode();
396         Layout* pLayout = null;
397
398         while (pCurNode)
399         {
400                 pLayout = pCurNode->GetLayout();
401                 if (pLayout)
402                 {
403                         pLayout->SetContainer(this);
404                 }
405                 pCurNode = __pLayoutList->GetNextNode(*pCurNode);
406         }
407 }
408
409 LayoutList*
410 LayoutContainer::GetLayoutList(void)
411 {
412         return __pLayoutList;
413 }
414
415
416 }}} // Tizen::Ui::_Layout