Tizen 2.1 base
[framework/osp/uifw.git] / src / ui / layout / FUi_LayoutTableLayout.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_LayoutTableLayout.cpp
19  * @brief       This is the implementation file for TableLayout class.
20  *
21  * This file contains the implementation of TableLayout class.
22  */
23
24 #include <new>
25 #include <string.h>
26 #include <stdlib.h>
27 #include <FBaseResult.h>
28 #include <FBaseInteger.h>
29 #include "FUi_LayoutTableLayout.h"
30 #include "FUi_LayoutLayoutItemProxy.h"
31 #include "FUi_LayoutProxyList.h"
32 #include "FUi_LayoutLayoutItemInfo.h"
33
34 using namespace Tizen::Base;
35
36 namespace Tizen { namespace Ui { namespace _Layout
37 {
38
39 TableLayout::TableLayout(void)
40         : Layout()
41         , __row(0)
42         , __column(0)
43         , __maxRow(0)
44         , __maxColumn(0)
45         , __shrinkRowCount(0)
46         , __shrinkColumnCount(0)
47         , __stretchRowCount(0)
48         , __stretchColumnCount(0)
49         , __rowShrinkable(false)
50         , __columnShrinkable(false)
51         , __rowStretchable(false)
52         , __columnStretchable(false)
53         , __pRowInfo(null)
54         , __pColInfo(null)
55 {
56         TableProxyList* pTableProxyList = new (std::nothrow) TableProxyList();
57         SysTryReturnVoidResult(NID_UI, pTableProxyList, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
58         SetItemList(pTableProxyList);
59 }
60
61 TableLayout::~TableLayout(void)
62 {
63         __mergedCellList.RemoveAll(true);
64
65         delete[] __pRowInfo;
66         delete[] __pColInfo;
67 }
68
69 TableLayout*
70 TableLayout::CreateTableLayoutN(void)
71 {
72         TableLayout* pLayout = new (std::nothrow) TableLayout();
73         SysTryReturn(NID_UI, pLayout != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Table layout core allocation failure.");
74         if (GetLastResult() != E_SUCCESS)
75         {
76                 delete pLayout;
77                 return null;
78         }
79
80         return pLayout;
81 }
82
83 result
84 TableLayout::CreateTable(int row, int column, int spacing)
85 {
86         if (row < 1 || column < 1)
87         {
88                 SysTryReturn(NID_UI, false, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Negative argument : row(%d), column(%d)", row,
89                                         column);
90         }
91
92         __row = row;
93         __column = column;
94         __maxRow = row;
95         __maxColumn = column;
96
97         __pColInfo = new (std::nothrow) ColumnInfo[__column];
98         SysTryReturn(NID_UI, __pColInfo != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
99
100         memset(__pColInfo, 0, sizeof(ColumnInfo) * __column);
101
102         for (int i = 0; i < __column; i++)
103         {
104                 __pColInfo[i].widthSpacing = spacing;
105         }
106
107         __pRowInfo = new (std::nothrow) RowInfo[__row];
108         SysTryReturn(NID_UI, __pRowInfo != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
109
110         memset(__pRowInfo, 0, sizeof(RowInfo) * __row);
111
112         for (int i = 0; i < __row; i++)
113         {
114                 __pRowInfo[i].heightSpacing = spacing;
115         }
116
117         return E_SUCCESS;
118 }
119
120 result
121 TableLayout::CalculateSize()
122 {
123         if (__row < 1 || __column < 1)
124         {
125                 return E_SUCCESS;
126         }
127
128         int nextPosX = 0; //-__pColInfo[0].widthSpacing + m_nPosX;
129         int nextPosY = 0; //-__pRowInfo[0].heightSpacing + m_nPosY;
130
131         __shrinkRowCount = 0;
132         __shrinkColumnCount = 0;
133         __stretchRowCount = 0;
134         __stretchColumnCount = 0;
135
136         for (int j = 0; j < __column; j++)
137         {
138                 __pColInfo[j].x = 0;
139                 __pColInfo[j].width = 0;
140                 __pColInfo[j].maxWidth = 0;
141                 __pColInfo[j].mergedWidth = 0;
142         }
143
144         ProxyListNode* pCurNode = null;
145         TableItemInfo* pItemInfo = null;
146         LayoutItemProxy* pItemProxy = null;
147
148         for (int i = 0; i < __row; i++)
149         {
150                 __pRowInfo[i].y = 0;
151                 __pRowInfo[i].height = 0;
152                 __pRowInfo[i].maxHeight = 0;
153                 __pRowInfo[i].mergedHeight = 0;
154
155                 for (int j = 0; j < __column; j++)
156                 {
157                         pCurNode = GetNode(i, j);
158                         if (pCurNode != null)
159                         {
160                                 pItemInfo = dynamic_cast <TableItemInfo*>(pCurNode->GetItemInfo());
161
162                                 pItemProxy = pCurNode->GetItemProxy();
163                                 if (pItemInfo == null || pItemProxy == null)
164                                 {
165                                         return E_INVALID_STATE;
166                                 }
167
168                                 if (pItemInfo->__enable)
169                                 {
170                                         pItemProxy->GetMinSize(pItemInfo->__minSize);
171                                         pItemProxy->GetMaxSize(pItemInfo->__maxSize);
172                                 }
173
174                                 LayoutRect rect = pItemProxy->GetItemBaseRect();
175
176                                 result r = pItemProxy->Measure(rect.w, rect.h);
177                                 if (r != E_SUCCESS)
178                                 {
179                                         return r;
180                                 }
181                                 pItemProxy->GetMeasuredSize(rect.w, rect.h);
182
183                                 ItemMargin margin = pItemProxy->GetItemMargin();
184                                 ItemAlign itemAlign = pItemProxy->GetItemAlignment();
185                                 if (itemAlign.HAlign == ITEM_HORIZONTAL_ALIGN_LEFT || itemAlign.HAlign == ITEM_HORIZONTAL_ALIGN_LEFT_RIGHT)
186                                 {
187                                         rect.w += margin.left;
188                                 }
189                                 if (itemAlign.HAlign == ITEM_HORIZONTAL_ALIGN_RIGHT || itemAlign.HAlign == ITEM_HORIZONTAL_ALIGN_LEFT_RIGHT)
190                                 {
191                                         rect.w += margin.right;
192                                 }
193                                 if (itemAlign.VAlign == ITEM_VERTICAL_ALIGN_TOP || itemAlign.VAlign == ITEM_VERTICAL_ALIGN_TOP_BOTTOM)
194                                 {
195                                         rect.h += margin.top;
196                                 }
197                                 if (itemAlign.VAlign == ITEM_VERTICAL_ALIGN_BOTTOM || itemAlign.VAlign == ITEM_VERTICAL_ALIGN_TOP_BOTTOM)
198                                 {
199                                         rect.h += margin.bottom;
200                                 }
201
202                                 if (!pItemInfo->__merged)
203                                 {
204                                         if (__pColInfo[j].maxWidth < rect.w && !__pRowInfo[i].rowCollapsed)
205                                         {
206                                                 __pColInfo[j].maxWidth = rect.w;
207                                         }
208
209                                         if (__pRowInfo[i].maxHeight < rect.h && !__pColInfo[j].columnCollapsed)
210                                         {
211                                                 __pRowInfo[i].maxHeight = rect.h;
212                                         }
213                                 }
214                                 else
215                                 {
216                                         if (__pColInfo[j].mergedWidth < rect.w)
217                                         {
218                                                 __pColInfo[j].mergedWidth = rect.w;
219                                         }
220                                         if (__pRowInfo[i].mergedHeight < rect.h)
221                                         {
222                                                 __pRowInfo[i].mergedHeight = rect.h;
223                                         }
224                                 }
225                         }
226                 }
227
228                 if (!__pRowInfo[i].rowCollapsed)
229                 {
230                         if (__pRowInfo[i].heightStretchable)
231                         {
232                                 __stretchRowCount++;
233                         }
234                         if (__pRowInfo[i].heightShrinkable)
235                         {
236                                 __shrinkRowCount++;
237                         }
238
239                         if (__pRowInfo[i].maxHeight != 0)
240                         {
241                                 __pRowInfo[i].height = __pRowInfo[i].maxHeight;
242                         }
243                 }
244         }
245
246         for (int j = 0; j < __column; j++)
247         {
248                 if (!__pColInfo[j].columnCollapsed)
249                 {
250                         if (__pColInfo[j].widthStretchable)
251                         {
252                                 __stretchColumnCount++;
253                         }
254                         if (__pColInfo[j].widthShrinkable)
255                         {
256                                 __shrinkColumnCount++;
257                         }
258
259                         if (__pColInfo[j].maxWidth != 0)
260                         {
261                                 __pColInfo[j].width = __pColInfo[j].maxWidth;
262                         }
263                 }
264         }
265
266         pCurNode = null;
267         pItemInfo = null;
268         pItemProxy = null;
269
270         int mergedHeight = 0;
271         int mergedWidth = 0;
272         for (int i = __row - 1; i >= 0; i--)
273         {
274                 if (!__pRowInfo[i].rowCollapsed)
275                 {
276                         for (int j = __column - 1; j >= 0; j--)
277                         {
278                                 if (!__pColInfo[j].columnCollapsed)
279                                 {
280                                         pCurNode = GetNode(i, j);
281                                         if (pCurNode != null)
282                                         {
283                                                 pItemInfo = dynamic_cast <TableItemInfo*>(pCurNode->GetItemInfo());
284                                                 if (pItemInfo == null)
285                                                 {
286                                                         return E_INVALID_STATE;
287                                                 }
288                                                 pItemProxy = pCurNode->GetItemProxy();
289                                                 if (pItemInfo->__mergeEndPoint.x != NOT_MERGED)
290                                                 {
291                                                         int startRow = i;
292                                                         int startColumn = j;
293                                                         int endRow = pItemInfo->__mergeEndPoint.x;
294                                                         int endColumn = pItemInfo->__mergeEndPoint.y;
295
296                                                         pItemProxy->GetMeasuredSize(mergedWidth, mergedHeight);
297
298                                                         int rowHeightSum = 0;
299                                                         if (startRow == 0)
300                                                         {
301                                                                 rowHeightSum -= __pRowInfo[startRow].heightSpacing;
302                                                         }
303                                                         for (int k = startRow; k <= endRow; k++)
304                                                         {
305                                                                 rowHeightSum += __pRowInfo[k].height + __pRowInfo[k].heightSpacing;
306                                                         }
307                                                         if (mergedHeight > rowHeightSum)
308                                                         {
309                                                                 __pRowInfo[startRow].height += mergedHeight - rowHeightSum;
310                                                         }
311
312                                                         int colWidthSum = 0;
313                                                         if (startColumn == 0)
314                                                         {
315                                                                 colWidthSum -= __pColInfo[startColumn].widthSpacing;
316                                                         }
317                                                         for (int k = startColumn; k <= endColumn; k++)
318                                                         {
319                                                                 colWidthSum += __pColInfo[k].width + __pColInfo[k].widthSpacing;
320                                                         }
321                                                         if (mergedWidth > colWidthSum)
322                                                         {
323                                                                 __pColInfo[startColumn].width += mergedWidth - colWidthSum;
324                                                         }
325                                                 }
326                                         }
327                                 }
328                         }
329                 }
330         }
331
332         LayoutRect layoutRect = GetLayoutRect();
333         nextPosY = -__pRowInfo[0].heightSpacing + layoutRect.y;
334         for (int i = 0; i < __row; i++)
335         {
336                 nextPosX = -__pColInfo[0].widthSpacing + layoutRect.x;
337                 if (!__pRowInfo[i].rowCollapsed)
338                 {
339                         for (int j = 0; j < __column; j++)
340                         {
341                                 if (!__pColInfo[j].columnCollapsed)
342                                 {
343                                         __pColInfo[j].x = nextPosX + __pColInfo[j].widthSpacing;
344                                         nextPosX = __pColInfo[j].x + __pColInfo[j].width;
345                                 }
346                         }
347                         __pRowInfo[i].y = nextPosY + __pRowInfo[i].heightSpacing;
348                         nextPosY = __pRowInfo[i].y + __pRowInfo[i].height;
349                 }
350         }
351
352         layoutRect.w = nextPosX;
353         layoutRect.h = nextPosY;
354         SetLayoutRect(layoutRect);
355
356         return E_SUCCESS;
357 }
358
359 result
360 TableLayout::CalculateShrinkCell(const LayoutRect windowRect)
361 {
362         __rowShrinkable = false;
363         __columnShrinkable = false;
364
365         LayoutItemProxy* pContainerProxy = GetContainerProxy();
366         if (pContainerProxy == null)
367         {
368                 return E_INVALID_STATE;
369         }
370
371         LayoutRect containerRect;
372         pContainerProxy->ConvertWindowToClientBounds(windowRect, containerRect);
373
374         LayoutRect layoutRect = GetLayoutRect();
375
376         int shrinkTotalWidth = layoutRect.w - containerRect.w;
377         int shrinkTotalHeight = layoutRect.h - containerRect.h;
378
379         int shrinkColumnCount = __shrinkColumnCount;
380         int shrinkRowCount = __shrinkRowCount;
381
382         int* pShrinkedColumns = null;
383         int* pShrinkedRows = null;
384
385         int lastShrinkRow = 0;
386         int lastShrinkColumn = 0;
387
388         ProxyListNode* pCurNode = null;
389         TableItemInfo* pItemInfo = null;
390
391         if (shrinkTotalWidth > 0 && __shrinkColumnCount > 0)
392         {
393                 if (pContainerProxy->GetItemWidthMatchMode() == WRAP_CONTENT)
394                 {
395                         return E_SUCCESS;
396                 }
397
398                 __columnShrinkable = true;
399
400                 pShrinkedColumns = new (std::nothrow) int[__shrinkColumnCount];
401                 SysTryReturn(NID_UI, pShrinkedColumns != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
402
403                 memset(pShrinkedColumns, 0x00, sizeof(int) * __shrinkColumnCount);
404
405                 int shrinkedColumnCount = 0;
406                 bool shrinkedItem = true;
407
408                 while (shrinkedItem && shrinkColumnCount != 0)
409                 {
410                         shrinkedItem = false;
411
412                         for (int j = 0; j < __column; j++)
413                         {
414                                 int shrinkWidth = shrinkTotalWidth / shrinkColumnCount;
415                                 int shrinkedColWidth = __pColInfo[j].width;
416
417                                 if (__pColInfo[j].widthShrinkable && !__pColInfo[j].columnCollapsed)
418                                 {
419                                         shrinkedColWidth -= shrinkWidth;
420
421                                         if (shrinkedColWidth < 0)
422                                         {
423                                                 shrinkWidth += shrinkedColWidth;
424
425                                                 __pColInfo[j].width = 0;
426                                                 shrinkedColWidth = 0;
427                                                 __pColInfo[j].widthShrinkable = false;
428
429                                         }
430
431                                         for (int i = 0; i < __row; i++)
432                                         {
433                                                 pCurNode = GetNode(i, j);
434                                                 pItemInfo = null;
435                                                 if (pCurNode != null)
436                                                 {
437                                                         pItemInfo = dynamic_cast <TableItemInfo*>(pCurNode->GetItemInfo());
438                                                 }
439                                                 if (pItemInfo != null && shrinkedColWidth < pItemInfo->__minSize.w)
440                                                 {
441                                                         shrinkWidth -= pItemInfo->__minSize.w - shrinkedColWidth;
442                                                         __pColInfo[j].width = pItemInfo->__minSize.w;
443                                                         __pColInfo[j].widthShrinkable = false;
444                                                 }
445                                         }
446
447                                         if (__pColInfo[j].widthShrinkable == false)
448                                         {
449                                                 shrinkTotalWidth -= shrinkWidth;
450                                                 layoutRect.w -= shrinkWidth;
451                                                 shrinkColumnCount--;
452
453                                                 pShrinkedColumns[shrinkedColumnCount++] = j;
454                                                 shrinkedItem = true;
455
456                                                 break;
457                                         }
458                                 }
459                         }
460                 }
461
462                 int nextPosX = -__pColInfo[0].widthSpacing + layoutRect.x;
463
464                 for (int j = 0; j < __column; j++)
465                 {
466                         __pColInfo[j].x = nextPosX + __pColInfo[j].widthSpacing;
467
468                         if (!__pColInfo[j].columnCollapsed)
469                         {
470                                 if (shrinkColumnCount != 0)
471                                 {
472                                         int shrinkWidth = shrinkTotalWidth / shrinkColumnCount;
473
474                                         if (__pColInfo[j].widthShrinkable)
475                                         {
476                                                 __pColInfo[j].width -= shrinkWidth;
477                                                 lastShrinkColumn = j;
478                                                 layoutRect.w -= shrinkWidth;
479                                         }
480                                 }
481                                 nextPosX = __pColInfo[j].width + __pColInfo[j].x;
482                         }
483                 }
484
485                 nextPosX = -__pColInfo[0].widthSpacing + layoutRect.x;
486                 int shrinkWidth = 0;
487                 if (shrinkTotalWidth != 0 && shrinkColumnCount != 0)
488                 {
489                         shrinkWidth = shrinkTotalWidth % shrinkColumnCount;
490                 }
491                 bool shrinkableColumn = true;
492
493                 while (shrinkWidth > 0 && shrinkableColumn)
494                 {
495                         shrinkableColumn = false;
496                         for (int j = 0; j < __column; j++)
497                         {
498                                 __pColInfo[j].x = nextPosX + __pColInfo[j].widthSpacing;
499
500                                 if (!__pColInfo[j].columnCollapsed)
501                                 {
502                                         if (shrinkColumnCount != 0)
503                                         {
504                                                 if (__pColInfo[j].widthShrinkable)
505                                                 {
506                                                         for (int i = 0; i < __row; i++)
507                                                         {
508                                                                 pCurNode = GetNode(i, j);
509                                                                 pItemInfo = null;
510                                                                 if (pCurNode != null)
511                                                                 {
512                                                                         pItemInfo = dynamic_cast <TableItemInfo*>(pCurNode->GetItemInfo());
513                                                                 }
514                                                                 if ((pItemInfo != null && ((__pColInfo[j].width - 1) < pItemInfo->__minSize.w)) || (__pColInfo[j].width - 1) < 0)
515                                                                 {
516                                                                         pShrinkedColumns[shrinkedColumnCount++] = j;
517                                                                         __pColInfo[j].widthShrinkable = false;
518                                                                         shrinkColumnCount--;
519                                                                         break;
520                                                                 }
521                                                         }
522
523                                                         if (__pColInfo[j].widthShrinkable && shrinkWidth > 0)
524                                                         {
525                                                                 __pColInfo[j].width--;
526                                                                 layoutRect.w--;
527                                                                 shrinkWidth--;
528                                                                 shrinkableColumn = true;
529                                                         }
530                                                 }
531                                         }
532                                         nextPosX = __pColInfo[j].width + __pColInfo[j].x;
533                                 }
534                         }
535                 }
536
537                 for (int j = 0; j < shrinkedColumnCount; j++)
538                 {
539                         __pColInfo[pShrinkedColumns[j]].widthShrinkable = true;
540                 }
541
542                 delete[] pShrinkedColumns;
543         }
544
545         if (shrinkTotalHeight > 0 && __shrinkRowCount > 0)
546         {
547                 if (pContainerProxy->GetItemHeightMatchMode() == WRAP_CONTENT)
548                 {
549                         return E_SUCCESS;
550                 }
551
552                 __rowShrinkable = true;
553
554                 pShrinkedRows = new (std::nothrow) int[__shrinkRowCount];
555                 SysTryReturn(NID_UI, pShrinkedRows != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
556
557                 memset(pShrinkedRows, 0x00, sizeof(int) * __shrinkRowCount);
558                 int shrinkedRowCount = 0;
559                 bool shrinkedItem = true;
560
561                 while (shrinkedItem && shrinkRowCount != 0)
562                 {
563                         shrinkedItem = false;
564
565                         for (int i = 0; i < __row; i++)
566                         {
567                                 int shrinkHeight = shrinkTotalHeight / shrinkRowCount;
568                                 int shrinkedRowHeight = __pRowInfo[i].height;
569
570                                 if (__pRowInfo[i].heightShrinkable && !__pRowInfo[i].rowCollapsed)
571                                 {
572                                         shrinkedRowHeight -= shrinkHeight;
573
574                                         if (shrinkedRowHeight < 0)
575                                         {
576                                                 shrinkHeight += shrinkedRowHeight;
577
578                                                 __pRowInfo[i].height = 0;
579                                                 shrinkedRowHeight = 0;
580                                                 __pRowInfo[i].heightShrinkable = false;
581
582                                         }
583
584                                         for (int j = 0; j < __column; j++)
585                                         {
586                                                 pCurNode = GetNode(i, j);
587                                                 pItemInfo = null;
588                                                 if (pCurNode != null)
589                                                 {
590                                                         pItemInfo = dynamic_cast <TableItemInfo*>(pCurNode->GetItemInfo());
591                                                 }
592                                                 if (pItemInfo != null && shrinkedRowHeight < pItemInfo->__minSize.h)
593                                                 {
594                                                         shrinkHeight -= pItemInfo->__minSize.h - shrinkedRowHeight;
595                                                         __pRowInfo[i].height = pItemInfo->__minSize.h;
596                                                         __pRowInfo[i].heightShrinkable = false;
597                                                 }
598                                         }
599
600                                         if (__pRowInfo[i].heightShrinkable == false)
601                                         {
602                                                 shrinkTotalHeight -= shrinkHeight;
603                                                 layoutRect.h -= shrinkHeight;
604                                                 shrinkRowCount--;
605
606                                                 pShrinkedRows[shrinkedRowCount++] = i;
607                                                 shrinkedItem = true;
608
609                                                 break;
610                                         }
611                                 }
612                         }
613                 }
614
615                 int nextPosY = -__pRowInfo[0].heightSpacing + layoutRect.y;
616
617                 for (int i = 0; i < __row; i++)
618                 {
619                         if (!__pRowInfo[i].rowCollapsed)
620                         {
621                                 if (shrinkRowCount != 0)
622                                 {
623                                         int shrinkHeight = shrinkTotalHeight / shrinkRowCount;
624
625                                         if (__pRowInfo[i].heightShrinkable)
626                                         {
627                                                 __pRowInfo[i].height -= shrinkHeight;
628                                                 lastShrinkRow = i;
629                                                 layoutRect.h -= shrinkHeight;
630                                         }
631                                 }
632                                 __pRowInfo[i].y = nextPosY + __pRowInfo[i].heightSpacing;
633                                 nextPosY = __pRowInfo[i].height + __pRowInfo[i].y;
634                         }
635                 }
636
637                 nextPosY = -__pRowInfo[0].heightSpacing + layoutRect.y;
638                 int shrinkHeight = 0;
639                 if (shrinkTotalHeight != 0 && shrinkRowCount != 0)
640                 {
641                         shrinkHeight = shrinkTotalHeight % shrinkRowCount;
642                 }
643                 bool shrinkableRow = true;
644
645                 while (shrinkHeight > 0 && shrinkableRow)
646                 {
647                         shrinkableRow = false;
648                         for (int i = 0; i < __row; i++)
649                         {
650                                 if (!__pRowInfo[i].rowCollapsed)
651                                 {
652                                         if (shrinkRowCount != 0)
653                                         {
654                                                 if (__pRowInfo[i].heightShrinkable)
655                                                 {
656                                                         for (int j = 0; j < __column; j++)
657                                                         {
658                                                                 pCurNode = GetNode(i, j);
659                                                                 pItemInfo = null;
660                                                                 if (pCurNode != null)
661                                                                 {
662                                                                         pItemInfo = dynamic_cast <TableItemInfo*>(pCurNode->GetItemInfo());
663                                                                 }
664                                                                 if ((pItemInfo != null && ((__pRowInfo[i].height - 1) < pItemInfo->__minSize.h)) || (__pRowInfo[i].height - 1) < 0)
665                                                                 {
666                                                                         pShrinkedRows[shrinkedRowCount++] = i;
667                                                                         __pRowInfo[i].heightShrinkable = false;
668                                                                         shrinkRowCount--;
669                                                                         break;
670                                                                 }
671                                                         }
672
673                                                         if (__pRowInfo[i].heightShrinkable && shrinkHeight > 0)
674                                                         {
675                                                                 __pRowInfo[i].height--;
676                                                                 layoutRect.h--;
677                                                                 shrinkHeight--;
678                                                                 shrinkableRow = true;
679                                                         }
680                                                 }
681                                         }
682                                         __pRowInfo[i].y = nextPosY + __pRowInfo[i].heightSpacing;
683                                         nextPosY = __pRowInfo[i].height + __pRowInfo[i].y;
684                                 }
685                         }
686                 }
687
688                 for (int i = 0; i < shrinkedRowCount; i++)
689                 {
690                         __pRowInfo[pShrinkedRows[i]].heightShrinkable = true;
691                 }
692
693                 delete[] pShrinkedRows;
694         }
695         SetLayoutRect(layoutRect);
696         return E_SUCCESS;
697 }
698
699 result
700 TableLayout::CalculateStretchCell(const LayoutRect windowRect)
701 {
702         __rowStretchable = false;
703         __columnStretchable = false;
704
705         LayoutItemProxy* pContainerProxy = GetContainerProxy();
706         if (pContainerProxy == null)
707         {
708                 return E_INVALID_STATE;
709         }
710
711         LayoutRect containerRect;
712         pContainerProxy->ConvertWindowToClientBounds(windowRect, containerRect);
713
714         LayoutRect layoutRect = GetLayoutRect();
715
716         int stretchTotalWidth = containerRect.w - layoutRect.w;
717         int stretchTotalHeight = containerRect.h - layoutRect.h;
718
719         int stretchColumnCount = __stretchColumnCount;
720         int stretchRowCount = __stretchRowCount;
721
722         int lastStretchRow = 0;
723         int lastStretchColumn = 0;
724
725         int* pStretchedColumns = null;
726         int* pStretchedRows = null;
727
728         ProxyListNode* pCurNode = null;
729         TableItemInfo* pItemInfo = null;
730
731         if (stretchTotalWidth > 0 && __stretchColumnCount > 0)
732         {
733                 if (pContainerProxy->GetItemWidthMatchMode() == WRAP_CONTENT)
734                 {
735                         return E_SUCCESS;
736                 }
737
738                 __columnStretchable = true;
739
740                 pStretchedColumns = new (std::nothrow) int[__stretchColumnCount];
741                 SysTryReturn(NID_UI, pStretchedColumns != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
742
743                 memset(pStretchedColumns, 0x00, sizeof(int) * __stretchColumnCount);
744                 int stretchedColumnCount = 0;
745                 bool stretchedItem = true;
746
747                 while (stretchedItem && stretchColumnCount != 0)
748                 {
749                         stretchedItem = false;
750                         int stretchWidth = stretchTotalWidth / stretchColumnCount;
751
752                         for (int j = 0; j < __column; j++)
753                         {
754                                 if (__pColInfo[j].widthStretchable && !__pColInfo[j].columnCollapsed)
755                                 {
756                                         int maxWidth = 0;
757                                         int stretchedColWidth = __pColInfo[j].width;
758                                         stretchedColWidth += stretchWidth;
759                                         for (int i = 0; i < __row; i++)
760                                         {
761                                                 pCurNode = GetNode(i, j);
762                                                 pItemInfo = null;
763                                                 if (pCurNode != null)
764                                                 {
765                                                         pItemInfo = dynamic_cast <TableItemInfo*>(pCurNode->GetItemInfo());
766                                                 }
767                                                 if (pItemInfo != null && maxWidth < pItemInfo->__maxSize.w)
768                                                 {
769                                                         maxWidth = pItemInfo->__maxSize.w;
770                                                 }
771                                         }
772
773                                         if (maxWidth < stretchedColWidth)
774                                         {
775                                                 stretchWidth -= stretchedColWidth - maxWidth;
776                                                 __pColInfo[j].width += stretchWidth;
777                                                 stretchTotalWidth -= stretchWidth;
778                                                 layoutRect.w += stretchWidth;
779                                                 stretchColumnCount--;
780                                                 __pColInfo[j].widthStretchable = false;
781
782                                                 pStretchedColumns[stretchedColumnCount++] = j;
783                                                 stretchedItem = true;
784                                                 break;
785                                         }
786                                 }
787                         }
788                 }
789
790                 int nextPosX = -__pColInfo[0].widthSpacing + layoutRect.x;
791
792                 for (int j = 0; j < __column; j++)
793                 {
794                         if (!__pColInfo[j].columnCollapsed)
795                         {
796                                 if (__pColInfo[j].widthStretchable && stretchColumnCount != 0)
797                                 {
798                                         int stretchWidth = stretchTotalWidth / stretchColumnCount;
799                                         __pColInfo[j].width += stretchWidth;
800                                         layoutRect.w += stretchWidth;
801                                         lastStretchColumn = j;
802                                 }
803                                 __pColInfo[j].x = nextPosX + __pColInfo[j].widthSpacing;
804                                 nextPosX = __pColInfo[j].x + __pColInfo[j].width;
805                         }
806                 }
807                 nextPosX = -__pColInfo[0].widthSpacing + layoutRect.x;
808                 int stretchWidth = 0;
809                 if (stretchTotalWidth != 0 && stretchColumnCount != 0)
810                 {
811                         stretchWidth = stretchTotalWidth % stretchColumnCount;
812                 }
813                 bool stretchableColumn = true;
814
815                 while (stretchWidth > 0 && stretchableColumn)
816                 {
817                         stretchableColumn = false;
818                         for (int j = 0; j < __column; j++)
819                         {
820                                 if (!__pColInfo[j].columnCollapsed)
821                                 {
822                                         if (stretchColumnCount != 0)
823                                         {
824                                                 if (__pColInfo[j].widthStretchable)
825                                                 {
826                                                         for (int i = 0; i < __row; i++)
827                                                         {
828                                                                 pCurNode = GetNode(i, j);
829                                                                 pItemInfo = null;
830                                                                 if (pCurNode != null)
831                                                                 {
832                                                                         pItemInfo = (TableItemInfo*) pCurNode->GetItemInfo();
833                                                                 }
834                                                                 if (pItemInfo != null && ((__pColInfo[j].width + 1) > pItemInfo->__maxSize.w)  && !pItemInfo->__merged)
835                                                                 {
836                                                                         pStretchedColumns[stretchedColumnCount++] = j;
837                                                                         __pColInfo[j].widthStretchable = false;
838                                                                         stretchColumnCount--;
839                                                                         break;
840                                                                 }
841                                                         }
842
843                                                         if (__pColInfo[j].widthStretchable && stretchWidth > 0)
844                                                         {
845                                                                 __pColInfo[j].width++;
846                                                                 layoutRect.w++;
847                                                                 stretchWidth--;
848                                                                 stretchableColumn = true;
849                                                         }
850                                                 }
851                                         }
852                                         __pColInfo[j].x = nextPosX + __pColInfo[j].widthSpacing;
853                                         nextPosX = __pColInfo[j].x + __pColInfo[j].width;
854                                 }
855                         }
856                 }
857
858                 for (int j = 0; j < stretchedColumnCount; j++)
859                 {
860                         __pColInfo[pStretchedColumns[j]].widthStretchable = true;
861                 }
862
863                 delete[] pStretchedColumns;
864         }
865
866         if (stretchTotalHeight > 0 && __stretchRowCount > 0)
867         {
868                 if (pContainerProxy->GetItemHeightMatchMode() == WRAP_CONTENT)
869                 {
870                         return E_SUCCESS;
871                 }
872
873                 __rowStretchable = true;
874
875                 pStretchedRows = new (std::nothrow) int[__stretchRowCount];
876                 SysTryReturn(NID_UI, pStretchedRows != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
877
878                 memset(pStretchedRows, 0x00, sizeof(int) * __stretchRowCount);
879                 int stretchedRowCount = 0;
880                 bool stretchedItem = true;
881
882                 while (stretchedItem && stretchRowCount != 0)
883                 {
884                         stretchedItem = false;
885                         int stretchHeight = stretchTotalHeight / stretchRowCount;
886
887                         for (int i = 0; i < __row; i++)
888                         {
889                                 if (__pRowInfo[i].heightStretchable && !__pRowInfo[i].rowCollapsed)
890                                 {
891                                         int maxHeight = 0;
892                                         int stretchedRowHeight = __pRowInfo[i].height;
893                                         stretchedRowHeight += stretchHeight;
894
895                                         for (int j = 0; j < __column; j++)
896                                         {
897                                                 pCurNode = GetNode(i, j);
898                                                 pItemInfo = null;
899                                                 if (pCurNode != null)
900                                                 {
901                                                         pItemInfo = dynamic_cast <TableItemInfo*>(pCurNode->GetItemInfo());
902                                                 }
903                                                 if (pItemInfo != null && maxHeight < pItemInfo->__maxSize.h)
904                                                 {
905                                                         maxHeight = pItemInfo->__maxSize.h;
906                                                 }
907                                         }
908
909                                         if (maxHeight < stretchedRowHeight)
910                                         {
911                                                 stretchHeight -= stretchedRowHeight - maxHeight;
912                                                 __pRowInfo[i].height += stretchHeight;
913                                                 stretchTotalHeight -= stretchHeight;
914                                                 layoutRect.h += stretchHeight;
915                                                 stretchRowCount--;
916                                                 __pRowInfo[i].heightStretchable = false;
917
918                                                 pStretchedRows[stretchedRowCount++] = i;
919                                                 stretchedItem = true;
920                                                 break;
921                                         }
922                                 }
923                         }
924                 }
925
926                 int nextPosY = -__pRowInfo[0].heightSpacing + layoutRect.y;
927                 for (int i = 0; i < __row; i++)
928                 {
929                         if (!__pRowInfo[i].rowCollapsed)
930                         {
931                                 if (__pRowInfo[i].heightStretchable && stretchRowCount != 0)
932                                 {
933                                         int stretchHeight = stretchTotalHeight / stretchRowCount;
934                                         __pRowInfo[i].height += stretchHeight;
935                                         layoutRect.h += stretchHeight;
936                                         lastStretchRow = i;
937                                 }
938                                 __pRowInfo[i].y = nextPosY + __pRowInfo[i].heightSpacing;
939                                 nextPosY = __pRowInfo[i].y + __pRowInfo[i].height;
940                         }
941                 }
942
943                 nextPosY = -__pRowInfo[0].heightSpacing + layoutRect.y;
944                 int stretchHeight = 0;
945                 if (stretchTotalHeight != 0 && stretchRowCount != 0)
946                 {
947                         stretchHeight = stretchTotalHeight % stretchRowCount;
948                 }
949                 bool stretchableRow = true;
950
951                 while (stretchHeight > 0 && stretchableRow)
952                 {
953                         stretchableRow = false;
954                         for (int i = 0; i < __row; i++)
955                         {
956                                 if (!__pRowInfo[i].rowCollapsed)
957                                 {
958                                         if (stretchRowCount != 0)
959                                         {
960                                                 if (__pRowInfo[i].heightStretchable)
961                                                 {
962                                                         for (int j = 0; j < __column; j++)
963                                                         {
964                                                                 pCurNode = GetNode(i, j);
965                                                                 pItemInfo = null;
966                                                                 if (pCurNode != null)
967                                                                 {
968                                                                         pItemInfo = dynamic_cast <TableItemInfo*>(pCurNode->GetItemInfo());
969                                                                 }
970                                                                 if (pItemInfo != null && ((__pRowInfo[i].height + 1) > pItemInfo->__maxSize.h)  && !pItemInfo->__merged)
971                                                                 {
972                                                                         pStretchedRows[stretchedRowCount++] = i;
973                                                                         __pRowInfo[i].heightStretchable = false;
974                                                                         stretchRowCount--;
975                                                                         break;
976                                                                 }
977                                                         }
978
979                                                         if (__pRowInfo[i].heightStretchable && stretchHeight > 0)
980                                                         {
981                                                                 __pRowInfo[i].height++;
982                                                                 layoutRect.h++;
983                                                                 stretchHeight--;
984                                                                 stretchableRow = true;
985                                                         }
986                                                 }
987                                         }
988                                         __pRowInfo[i].y = nextPosY + __pRowInfo[i].heightSpacing;
989                                         nextPosY = __pRowInfo[i].y + __pRowInfo[i].height;
990                                 }
991                         }
992                 }
993
994                 for (int i = 0; i < stretchedRowCount; i++)
995                 {
996                         __pRowInfo[pStretchedRows[i]].heightStretchable = true;
997                 }
998
999                 delete[] pStretchedRows;
1000         }
1001         SetLayoutRect(layoutRect);
1002         return E_SUCCESS;
1003 }
1004
1005 result
1006 TableLayout::Merge(int startRow, int startCol, int endRow, int endCol)
1007 {
1008         if (startRow < 0 || startRow >= __row || startCol < 0 || startCol >= __column
1009                 || endRow < 0 || endRow >= __row || endCol < 0 || endCol >= __column
1010                 || startRow > endRow || startCol > endCol)
1011         {
1012                 return E_INVALID_ARG;
1013         }
1014
1015         int realEndRow = endRow;
1016         int realEndColumn = endCol;
1017
1018         ProxyListNode* pCurNode = null;
1019         TableItemInfo* pItemInfo = null;
1020         for (int i = startRow; i <= realEndRow; i++)
1021         {
1022                 if (__pRowInfo[i].rowCollapsed)
1023                 {
1024                         realEndRow++;
1025                 }
1026
1027                 for (int j = startCol; j <= realEndColumn; j++)
1028                 {
1029                         int k = 0;
1030                         int mergedCellIndex = MakeCellID(i, j);
1031
1032                         for (k = 0; k < __mergedCellList.GetCount(); k++)
1033                         {
1034                                 Integer* cellID = static_cast <Integer*>(__mergedCellList.GetAt(k));
1035                                 if (cellID->ToInt() == mergedCellIndex)
1036                                 {
1037                                         return E_SYSTEM;
1038                                 }
1039                         }
1040
1041                         if (i != startRow || j != startCol)
1042                         {
1043                                 __mergedCellList.Add(*(new Integer(mergedCellIndex)));
1044                         }
1045
1046                         pCurNode = GetNode(i, j);
1047                         pItemInfo = null;
1048                         if (pCurNode != null)
1049                         {
1050                                 pItemInfo = dynamic_cast <TableItemInfo*>(pCurNode->GetItemInfo());
1051                         }
1052                         if (pItemInfo == null)
1053                         {
1054                                 continue;
1055                         }
1056                         if (pItemInfo->__merged)
1057                         {
1058                                 return E_SYSTEM;
1059                         }
1060                         if (__pColInfo[j].columnCollapsed)
1061                         {
1062                                 realEndColumn++;
1063                         }
1064
1065                         if (i == startRow && j == startCol)
1066                         {
1067                                 pItemInfo->__merged = true;
1068                                 continue;
1069                         }
1070
1071                         pItemInfo->__enable = false;
1072                         pItemInfo->__merged = true;
1073                         if (pCurNode->GetItemProxy() != null)
1074                         {
1075                                 pCurNode->GetItemProxy()->Visible(false);
1076                         }
1077                 }
1078         }
1079
1080         pCurNode = GetNode(startRow, startCol);
1081         if (pCurNode != null)
1082         {
1083                 pItemInfo = dynamic_cast <TableItemInfo*>(pCurNode->GetItemInfo());
1084                 if (pItemInfo == null)
1085                 {
1086                         return E_INVALID_STATE;
1087                 }
1088                 pItemInfo->__mergeEndPoint.x = realEndRow;
1089                 pItemInfo->__mergeEndPoint.y = realEndColumn;
1090         }
1091
1092         SetUpdateState(true);
1093         return E_SUCCESS;
1094 }
1095
1096 result
1097 TableLayout::OnLayout(int width, int height, bool updateLayouting)
1098 {
1099         LayoutRect layoutRect = GetLayoutRect();
1100         LayoutRect windowRect = {layoutRect.x, layoutRect.y, width, height};
1101
1102         result r = CalculateSize();
1103         if (r != E_SUCCESS)
1104         {
1105                 return r;
1106         }
1107
1108         r = CalculateShrinkCell(windowRect);
1109         if (r != E_SUCCESS)
1110         {
1111                 return r;
1112         }
1113
1114         r = CalculateStretchCell(windowRect);
1115         if (r != E_SUCCESS)
1116         {
1117                 return r;
1118         }
1119
1120         r = AdjustTableLayout(windowRect, updateLayouting);
1121         if (r != E_SUCCESS)
1122         {
1123                 return r;
1124         }
1125
1126         return E_SUCCESS;
1127 }
1128
1129 result
1130 TableLayout::AdjustTableLayout(const LayoutRect windowRect, bool updateLayouting)
1131 {
1132         LayoutItemProxy* pContainerProxy = GetContainerProxy();
1133         if (pContainerProxy == null)
1134         {
1135                 return E_INVALID_STATE;
1136         }
1137
1138         result r = E_SUCCESS;
1139         LayoutSize size = {0, 0};
1140         ProxyListNode* pCurNode = null;
1141         TableItemInfo* pItemInfo = null;
1142         LayoutItemProxy* pItemProxy = null;
1143         for (int i = 0; i < __row; i++)
1144         {
1145                 for (int j = 0; j < __column; j++)
1146                 {
1147                         pCurNode = GetNode(i, j);
1148                         pItemInfo = null;
1149                         if (pCurNode != null)
1150                         {
1151                                 pItemInfo = dynamic_cast <TableItemInfo*>(pCurNode->GetItemInfo());
1152                                 pItemProxy = pCurNode->GetItemProxy();
1153                         }
1154                         if (pItemInfo != null && pItemInfo->__enable)
1155                         {
1156                                 size.w = __pColInfo[j].width;
1157                                 size.h = __pRowInfo[i].height;
1158                                 if (pItemInfo->__mergeEndPoint.x != NOT_MERGED || pItemInfo->__mergeEndPoint.y != NOT_MERGED)
1159                                 {
1160                                         result r = CalculateMergeCell(i, j, size);
1161                                         if (r != E_SUCCESS)
1162                                         {
1163                                                 SysLog(NID_UI, "CalculateMergeCell() is Failed.");
1164                                         }
1165                                 }
1166                                 if (pItemProxy != null)
1167                                 {
1168                                         LayoutRect rect = pItemProxy->GetItemBaseRect();
1169                                         rect.x = __pColInfo[j].x;
1170                                         rect.y = __pRowInfo[i].y;
1171
1172                                         LayoutRect cellRect;
1173                                         cellRect.x = __pColInfo[j].x;
1174                                         cellRect.y = __pRowInfo[i].y;
1175                                         cellRect.w = size.w;
1176                                         cellRect.h = size.h;
1177
1178                                         r = pItemProxy->Measure(rect.w, rect.h);
1179                                         if (r != E_SUCCESS)
1180                                         {
1181                                                 return r;
1182                                         }
1183                                         pItemProxy->GetMeasuredSize(rect.w, rect.h);
1184
1185                                         if ((__pRowInfo[i].heightShrinkable && __rowShrinkable) ||
1186                                                 (__pRowInfo[i].heightStretchable && __rowStretchable) ||
1187                                                 pItemInfo->__fillHeight)
1188                                         {
1189                                                 int height = 0;
1190                                                 r = pItemProxy->Measure(rect.w, cellRect.h);
1191                                                 if (r != E_SUCCESS)
1192                                                 {
1193                                                         return r;
1194                                                 }
1195                                                 pItemProxy->GetMeasuredSize(rect.w, height);
1196
1197                                                 if ((__pRowInfo[i].heightShrinkable && __rowShrinkable) && rect.h > height)
1198                                                 {
1199                                                         rect.h = height;
1200                                                 }
1201                                                 else if ((__pRowInfo[i].heightStretchable && __rowStretchable) && rect.h < height)
1202                                                 {
1203                                                         rect.h = height;
1204                                                 }
1205                                                 else if (pItemInfo->__fillHeight)
1206                                                 {
1207                                                         rect.h = height;
1208                                                 }
1209                                         }
1210
1211                                         if ((__pColInfo[j].widthShrinkable && __columnShrinkable) ||
1212                                                 (__pColInfo[j].widthStretchable && __columnStretchable) ||
1213                                                 pItemInfo->__fillWidth)
1214                                         {
1215                                                 int width = 0;
1216                                                 r = pItemProxy->Measure(cellRect.w, rect.h);
1217                                                 if (r != E_SUCCESS)
1218                                                 {
1219                                                         return r;
1220                                                 }
1221                                                 pItemProxy->GetMeasuredSize(width, rect.h);
1222
1223                                                 if ((__pColInfo[j].widthShrinkable && __columnShrinkable) && rect.w > width)
1224                                                 {
1225                                                         rect.w = width;
1226                                                 }
1227                                                 else if ((__pColInfo[j].widthStretchable && __columnStretchable) && rect.w < width)
1228                                                 {
1229                                                         rect.w = width;
1230                                                 }
1231                                                 else if (pItemInfo->__fillWidth)
1232                                                 {
1233                                                         rect.w = width;
1234                                                 }
1235                                         }
1236
1237                                         ItemAlign align = pItemProxy->GetItemAlignment();
1238                                         rect = CalculateAlign(*pItemProxy, cellRect, rect, align.HAlign, align.VAlign);
1239
1240                                         r = pItemProxy->Measure(rect.w, rect.h);
1241                                         if (r != E_SUCCESS)
1242                                         {
1243                                                 return r;
1244                                         }
1245                                         pItemProxy->GetMeasuredSize(rect.w, rect.h);
1246                                         pItemProxy->SetItemWindowRect(rect);
1247                                 }
1248                         }
1249                 }
1250         }
1251
1252         LayoutMatchMode widthMode = pContainerProxy->GetItemWidthMatchMode();
1253         LayoutMatchMode heightMode = pContainerProxy->GetItemHeightMatchMode();
1254         LayoutRect containerRect;
1255         pContainerProxy->ConvertWindowToClientBounds(windowRect, containerRect);
1256
1257         containerRect.x = windowRect.x;
1258         containerRect.y = windowRect.y;
1259
1260         int correctionWidth = windowRect.w - containerRect.w;
1261         int correctionHeight = windowRect.h - containerRect.h;
1262
1263         LayoutRect layoutRect = GetLayoutRect();
1264         if (widthMode == WRAP_CONTENT)
1265         {
1266                 containerRect.w = layoutRect.w + correctionWidth;
1267         }
1268         else
1269         {
1270                 containerRect.w += correctionWidth;
1271         }
1272
1273         if (heightMode == WRAP_CONTENT)
1274         {
1275                 containerRect.h = layoutRect.h + correctionHeight;
1276         }
1277         else
1278         {
1279                 containerRect.h += correctionHeight;
1280         }
1281
1282         SetLayoutRect(containerRect);
1283
1284         LayoutRect clientRect;
1285         pContainerProxy->GetItemWindowRect(clientRect);
1286         containerRect.x = clientRect.x;
1287         containerRect.y = clientRect.y;
1288         if (updateLayouting)
1289         {
1290                 pContainerProxy->SetItemWindowRect(containerRect);
1291         }
1292         return E_SUCCESS;
1293 }
1294
1295 result
1296 TableLayout::AddItem(LayoutItem& item)
1297 {
1298         ProxyListNode* pCurNode = null;
1299
1300         int cellIndex = INVALID_CELL_ID;
1301         for (int i = 0; i < __row; i++)
1302         {
1303                 for (int j = 0; j < __column; j++)
1304                 {
1305                         pCurNode = GetNode(i, j);
1306                         if (pCurNode == null)
1307                         {
1308                                 if (!__pRowInfo[i].rowCollapsed && !__pColInfo[j].columnCollapsed)
1309                                 {
1310                                         cellIndex = MakeCellID(i, j);
1311                                         for (int k = 0; k < __mergedCellList.GetCount(); k++)
1312                                         {
1313                                                 Integer* cellID = static_cast <Integer*>(__mergedCellList.GetAt(k));
1314                                                 if (cellID->ToInt() == cellIndex)
1315                                                 {
1316                                                         return AddItem(item, i, j, true);
1317                                                 }
1318                                         }
1319
1320                                         return AddItem(item, i, j);
1321                                 }
1322                         }
1323                 }
1324         }
1325
1326         return E_SYSTEM;
1327 }
1328
1329 result
1330 TableLayout::AddItem(LayoutItem& item, int row, int column, bool mergedState)
1331 {
1332         ProxyList* pProxyList = GetProxyList();
1333         SysAssertf(pProxyList != null, "ProxyList is invalid");
1334
1335         if (row < 0 || row >= __row || column < 0 || column >= __column)
1336         {
1337                 return E_INVALID_ARG;
1338         }
1339         ProxyListNode* pGetNode = GetNode(row, column);
1340         if (pGetNode != null)
1341         {
1342                 return E_INVALID_STATE;
1343         }
1344
1345         int cellIndex = MakeCellID(row, column);
1346
1347         if (!mergedState)
1348         {
1349                 for (int k = 0; k < __mergedCellList.GetCount(); k++)
1350                 {
1351                         Integer* cellID = static_cast <Integer*>(__mergedCellList.GetAt(k));
1352                         if (cellID->ToInt() == cellIndex)
1353                         {
1354                                 return E_SYSTEM;
1355                         }
1356                 }
1357         }
1358
1359         result r = Layout::AddItem(item);
1360         if (r != E_SUCCESS)
1361         {
1362                 return r;
1363         }
1364
1365         ProxyListNode* pAddNode = pProxyList->GetNode(item);
1366         if (pAddNode == null)
1367         {
1368                 return E_INVALID_STATE;
1369         }
1370         TableItemInfo* pAddItemInfo = dynamic_cast <TableItemInfo*>(pAddNode->GetItemInfo());
1371         if (pAddItemInfo == null)
1372         {
1373                 return E_INVALID_STATE;
1374         }
1375
1376         cellIndex = MakeCellID(row, column);
1377         pAddItemInfo->__id = cellIndex;
1378
1379         if (mergedState)
1380         {
1381                 pAddItemInfo->__enable = false;
1382                 pAddItemInfo->__merged = true;
1383
1384                 if (pAddNode->GetItemProxy() != null)
1385                 {
1386                         pAddNode->GetItemProxy()->Visible(false);
1387                 }
1388         }
1389
1390         return E_SUCCESS;
1391 }
1392
1393 LayoutItem*
1394 TableLayout::GetItem(int row, int column) const
1395 {
1396         if (row < 0 || row >= __row)
1397         {
1398                 return null;
1399         }
1400
1401         if (column < 0 || column >= __column)
1402         {
1403                 return null;
1404         }
1405
1406         ProxyListNode* pCurNode = GetNode(row, column);
1407         if (pCurNode != null && pCurNode->GetItemProxy() != null)
1408         {
1409                 return pCurNode->GetItemProxy()->GetItem();
1410         }
1411         else
1412         {
1413                 return null;
1414         }
1415 }
1416
1417 result
1418 TableLayout::SetItemPosition(const LayoutItem& item, int row, int column)
1419 {
1420         SysTryReturn(NID_UI, row >= 0, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Negative input argument : row(%d)", row);
1421         SysTryReturn(NID_UI, row < __row, E_INVALID_ARG, E_INVALID_ARG,
1422                                 "[E_INVALID_ARG] Input Argument row over the max row : row(%d), maxRow(%d)", row, __row);
1423         SysTryReturn(NID_UI, column >= 0, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Negative input argument : column(%d)", column);
1424         SysTryReturn(NID_UI, column < __column, E_INVALID_ARG, E_INVALID_ARG,
1425                                 "[E_INVALID_ARG] Input Argument column over the max column : column(%d), maxColumn(%d)", column, __column);
1426
1427         ProxyList* pProxyList = GetProxyList();
1428         SysAssertf(pProxyList != null, "ProxyList is invalid");
1429
1430         ProxyListNode* pTargetNode = GetNode(row, column);
1431         ProxyListNode* pCurNode = pProxyList->GetNode(item);
1432         SysTryReturn(NID_UI, (pCurNode != null), E_INVALID_ARG, E_INVALID_ARG,
1433                                 "[E_INVALID_ARG] Controls have not been added to the container.");
1434
1435         if (pTargetNode == pCurNode)
1436         {
1437                 return E_SUCCESS;
1438         }
1439
1440         SysTryReturn(NID_UI, (pTargetNode == null), E_INVALID_STATE, E_INVALID_STATE, "[E_INVALID_STATE] The (%d, %d) cell is not available.", row, column);
1441
1442         int cellIndex = MakeCellID(row, column);
1443         TableItemInfo* pItemInfo = dynamic_cast <TableItemInfo*>(pCurNode->GetItemInfo());
1444         if (pItemInfo == null)
1445         {
1446                 return E_INVALID_STATE;
1447         }
1448
1449         if (pItemInfo->__merged || !pItemInfo->__enable)
1450         {
1451                 pItemInfo->__enable = true;
1452                 pItemInfo->__merged = false;
1453                 if (pCurNode->GetItemProxy() != null)
1454                 {
1455                         pCurNode->GetItemProxy()->Visible(true);
1456                 }
1457         }
1458
1459         pItemInfo->__id = cellIndex;
1460
1461         SetUpdateState(true);
1462         return E_SUCCESS;
1463 }
1464
1465 result
1466 TableLayout::GetItemPosition(const LayoutItem& item, int& row, int& column) const
1467 {
1468         ProxyList* pProxyList = GetProxyList();
1469         SysAssertf(pProxyList != null, "ProxyList is invalid");
1470
1471         ProxyListNode* pCurNode = pProxyList->GetNode(item);
1472         SysTryReturn(NID_UI, (pCurNode != null), E_INVALID_ARG, E_INVALID_ARG,
1473                                 "[E_INVALID_ARG] Controls have not been added to the container.");
1474
1475         TableItemInfo* pItemInfo = dynamic_cast <TableItemInfo*>(pCurNode->GetItemInfo());
1476         if (pItemInfo == null)
1477         {
1478                 return E_INVALID_STATE;
1479         }
1480         row = (GetRow(pItemInfo->__id));
1481         column = (GetColumn(pItemInfo->__id));
1482
1483         return E_SUCCESS;
1484 }
1485
1486 result
1487 TableLayout::AddRow(void)
1488 {
1489         if (__row == __maxRow)
1490         {
1491                 RowInfo* pRowInfo = new (std::nothrow) RowInfo[__maxRow + 1];
1492                 SysTryReturn(NID_UI, pRowInfo != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
1493
1494                 memset(pRowInfo, 0x0, sizeof(RowInfo) * (__maxRow + 1));
1495                 memcpy(pRowInfo, __pRowInfo, sizeof(RowInfo) * __maxRow);
1496                 delete[] __pRowInfo;
1497                 __pRowInfo = pRowInfo;
1498                 __maxRow++;
1499         }
1500         __row++;
1501         return E_SUCCESS;
1502 }
1503
1504 result
1505 TableLayout::AddColumn(void)
1506 {
1507         if (__column == __maxColumn)
1508         {
1509                 ColumnInfo* pColInfo = new (std::nothrow) ColumnInfo[__maxColumn + 1];
1510                 SysTryReturn(NID_UI, pColInfo != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
1511
1512                 memset(pColInfo, 0x0, sizeof(ColumnInfo) * (__maxColumn + 1));
1513                 memcpy(pColInfo, __pColInfo, sizeof(ColumnInfo) * __maxColumn);
1514                 delete[] __pColInfo;
1515                 __pColInfo = pColInfo;
1516                 __maxColumn++;
1517         }
1518         __column++;
1519         return E_SUCCESS;
1520 }
1521
1522 result
1523 TableLayout::DeleteRow(int row)
1524 {
1525         if (row < 0 || row >= __row)
1526         {
1527                 return E_INVALID_ARG;
1528         }
1529
1530         ProxyListNode* pCurNode = null;
1531         result r = E_SUCCESS;
1532         for (int j = 0; j < __column; j++)
1533         {
1534                 pCurNode = GetNode(row, j);
1535                 if (pCurNode != null)
1536                 {
1537                         r = RemoveItem(*(pCurNode->GetItemProxy()->GetItem()));
1538                         if (r != E_SUCCESS)
1539                         {
1540                                 return r;
1541                         }
1542                 }
1543         }
1544
1545         TableItemInfo* pItemInfo = null;
1546         for (int i = 0; i < __row; i++)
1547         {
1548                 for (int j = 0; j < __column; j++)
1549                 {
1550                         pCurNode = GetNode(i, j);
1551                         if (pCurNode != null)
1552                         {
1553                                 pItemInfo = dynamic_cast <TableItemInfo*>(pCurNode->GetItemInfo());
1554                                 if (pItemInfo == null)
1555                                 {
1556                                         return E_INVALID_STATE;
1557                                 }
1558                                 if (i > row)
1559                                 {
1560                                         pItemInfo->__id = MakeCellID((i - 1), j);
1561                                 }
1562                                 if (pItemInfo->__mergeEndPoint.x != NOT_MERGED)
1563                                 {
1564                                         if (pItemInfo->__mergeEndPoint.x >= row)
1565                                         {
1566                                                 pItemInfo->__mergeEndPoint.x--;
1567                                         }
1568                                         if (pItemInfo->__mergeEndPoint.x == GetRow(pItemInfo->__id))
1569                                         {
1570                                                 r = Unmerge(GetRow(pItemInfo->__id), GetColumn(pItemInfo->__id));
1571                                                 if (r != E_SUCCESS)
1572                                                 {
1573                                                         return r;
1574                                                 }
1575                                         }
1576                                 }
1577                         }
1578                 }
1579         }
1580
1581         memcpy(&__pRowInfo[row], &__pRowInfo[row + 1], sizeof(RowInfo) * (__row - row - 1));
1582
1583         __row--;
1584
1585         return r;
1586 }
1587
1588 result
1589 TableLayout::DeleteColumn(int column)
1590 {
1591         if (column < 0 || column >= __column)
1592         {
1593                 return E_INVALID_ARG;
1594         }
1595
1596         ProxyListNode* pCurNode = null;
1597         TableItemInfo* pItemInfo = null;
1598         result r = E_SUCCESS;
1599         for (int i = 0; i < __row; i++)
1600         {
1601                 pCurNode = GetNode(i, column);
1602                 if (pCurNode != null)
1603                 {
1604                         r = RemoveItem(*(pCurNode->GetItemProxy()->GetItem()));
1605                         if (r != E_SUCCESS)
1606                         {
1607                                 return r;
1608                         }
1609                 }
1610
1611                 for (int j = 0; j < __column; j++)
1612                 {
1613                         pCurNode = GetNode(i, j);
1614                         if (pCurNode != null)
1615                         {
1616                                 pItemInfo = dynamic_cast <TableItemInfo*>(pCurNode->GetItemInfo());
1617                                 if (pItemInfo == null)
1618                                 {
1619                                         return E_INVALID_STATE;
1620                                 }
1621                                 if (j > column)
1622                                 {
1623                                         pItemInfo->__id = MakeCellID(i, (j - 1));
1624                                 }
1625
1626                                 if (pItemInfo->__mergeEndPoint.y != NOT_MERGED)
1627                                 {
1628                                         if (pItemInfo->__mergeEndPoint.y >= column)
1629                                         {
1630                                                 pItemInfo->__mergeEndPoint.y--;
1631                                         }
1632                                         int mergeEndColumn = GetColumn(pItemInfo->__id);
1633                                         if (pItemInfo->__mergeEndPoint.y == mergeEndColumn)
1634                                         {
1635                                                 r = Unmerge(GetRow(pItemInfo->__id), GetColumn(pItemInfo->__id));
1636                                                 if (r != E_SUCCESS)
1637                                                 {
1638                                                         return r;
1639                                                 }
1640                                         }
1641                                 }
1642                         }
1643                 }
1644         }
1645
1646         memcpy(&__pColInfo[column], &__pColInfo[column + 1], sizeof(ColumnInfo) * (__column - column - 1));
1647
1648         __column--;
1649
1650         return E_SUCCESS;
1651 }
1652
1653 result
1654 TableLayout::CalculateMergeCell(int row, int column, LayoutSize& size)
1655 {
1656         if (row < 0 || row >= __row || column < 0 || column >= __column)
1657         {
1658                 return E_INVALID_ARG;
1659         }
1660
1661         ProxyListNode* pCurNode = GetNode(row, column);
1662         if (pCurNode == null)
1663         {
1664                 return E_INVALID_ARG;
1665         }
1666
1667         TableItemInfo* pItemInfo = dynamic_cast <TableItemInfo*>(pCurNode->GetItemInfo());
1668         if (pItemInfo == null)
1669         {
1670                 return E_INVALID_STATE;
1671         }
1672         if (pItemInfo->__mergeEndPoint.x > NOT_MERGED && !__pRowInfo[pItemInfo->__mergeEndPoint.x].rowCollapsed)
1673         {
1674                 int endRowPos = __pRowInfo[pItemInfo->__mergeEndPoint.x].y;
1675                 size.h = __pRowInfo[pItemInfo->__mergeEndPoint.x].height + endRowPos - __pRowInfo[row].y;
1676         }
1677         else
1678         {
1679                 size.h = __pRowInfo[row].height;
1680         }
1681
1682         if (pItemInfo->__mergeEndPoint.y > NOT_MERGED && !__pColInfo[pItemInfo->__mergeEndPoint.y].columnCollapsed)
1683         {
1684                 int endColPos = __pColInfo[pItemInfo->__mergeEndPoint.y].x;
1685                 size.w = __pColInfo[pItemInfo->__mergeEndPoint.y].width + endColPos - __pColInfo[column].x;
1686         }
1687         else
1688         {
1689                 size.w = __pColInfo[column].width;
1690         }
1691
1692         return E_SUCCESS;
1693 }
1694
1695 LayoutRect
1696 TableLayout::CalculateAlign(LayoutItemProxy& itemProxy, LayoutRect cellRect, LayoutRect itemRect, const HorizontalAlign horizonAlign, const VerticalAlign verticalAlign)
1697 {
1698         ItemMargin margin = itemProxy.GetItemMargin();
1699         itemRect.y = cellRect.y;
1700         itemRect.x = cellRect.x;
1701
1702         if (verticalAlign == ITEM_VERTICAL_ALIGN_TOP)
1703         {
1704                 if (itemRect.h > cellRect.h - margin.top)
1705                 {
1706                         itemRect.h = cellRect.h - margin.top;
1707                 }
1708                 itemRect.y = cellRect.y + margin.top;
1709         }
1710         else if (verticalAlign == ITEM_VERTICAL_ALIGN_BOTTOM)
1711         {
1712                 if (itemRect.h > cellRect.h - margin.bottom)
1713                 {
1714                         itemRect.h = cellRect.h - margin.bottom;
1715                 }
1716                 itemRect.y = cellRect.h + cellRect.y - itemRect.h - margin.bottom;
1717         }
1718         else if (verticalAlign == ITEM_VERTICAL_ALIGN_TOP_BOTTOM)
1719         {
1720                 itemRect.h = cellRect.h - margin.top - margin.bottom;
1721                 itemRect.y = cellRect.y + margin.top;
1722         }
1723         else if (verticalAlign == ITEM_VERTICAL_ALIGN_MIDDLE)
1724         {
1725                 if (cellRect.h > itemRect.h)
1726                 {
1727                         itemRect.y = cellRect.y + ((cellRect.h - itemRect.h) >> 1);
1728                 }
1729                 else
1730                 {
1731                         itemRect.h = cellRect.h;
1732                 }
1733         }
1734         if (horizonAlign == ITEM_HORIZONTAL_ALIGN_RIGHT)
1735         {
1736                 if (itemRect.w > cellRect.w - margin.right)
1737                 {
1738                         itemRect.w = cellRect.w - margin.right;
1739                 }
1740                 itemRect.x = cellRect.w + cellRect.x - itemRect.w - margin.right;
1741         }
1742         else if (horizonAlign == ITEM_HORIZONTAL_ALIGN_LEFT)
1743         {
1744                 if (itemRect.w > cellRect.w - margin.left)
1745                 {
1746                         itemRect.w = cellRect.w - margin.left;
1747                 }
1748                 itemRect.x = cellRect.x + margin.left;
1749         }
1750         else if (horizonAlign == ITEM_HORIZONTAL_ALIGN_CENTER)
1751         {
1752                 if (cellRect.w > itemRect.w)
1753                 {
1754                         itemRect.x = cellRect.x + ((cellRect.w - itemRect.w) >> 1);
1755                 }
1756                 else
1757                 {
1758                         itemRect.w = cellRect.w;
1759                 }
1760         }
1761         else if (horizonAlign == ITEM_HORIZONTAL_ALIGN_LEFT_RIGHT)
1762         {
1763                 itemRect.w = cellRect.w - margin.left - margin.right;
1764                 itemRect.x = cellRect.x + margin.left;
1765         }
1766
1767         return itemRect;
1768 }
1769
1770 result
1771 TableLayout::GetCellSize(int cellIndex, LayoutRect& rect)
1772 {
1773         if (cellIndex == INVALID_CELL_ID)
1774         {
1775                 return E_INVALID_ARG;
1776         }
1777
1778         int row = GetRow(cellIndex);
1779         if (row < 0 || row >= __row)
1780         {
1781                 return E_INVALID_ARG;
1782         }
1783
1784         int column = GetColumn(cellIndex);
1785         if (column < 0 || column >= __column)
1786         {
1787                 return E_INVALID_ARG;
1788         }
1789
1790         ProxyListNode* pCurNode = GetNode(row, column);
1791         if (pCurNode != null)
1792         {
1793                 TableItemInfo* pItemInfo = dynamic_cast <TableItemInfo*>(pCurNode->GetItemInfo());
1794                 if (pItemInfo == null)
1795                 {
1796                         return E_INVALID_STATE;
1797                 }
1798                 if (pItemInfo->__mergeEndPoint.x != NOT_MERGED || pItemInfo->__mergeEndPoint.y != NOT_MERGED)
1799                 {
1800                         LayoutSize size = {0, 0};
1801                         result r = CalculateMergeCell(row, column, size);
1802                         if (r != E_SUCCESS)
1803                         {
1804                                 rect.w = size.w;
1805                                 rect.h = size.h;
1806                         }
1807                 }
1808                 else
1809                 {
1810                         rect.h = __pRowInfo[row].height;
1811                         rect.w = __pColInfo[column].width;
1812                 }
1813         }
1814
1815         if (__pRowInfo[row].rowCollapsed)
1816         {
1817                 rect.h = 0;
1818         }
1819
1820         if (__pColInfo[column].columnCollapsed)
1821         {
1822                 rect.w = 0;
1823         }
1824
1825         return E_SUCCESS;
1826 }
1827
1828 result
1829 TableLayout::SetColumnCollapsed(int columnIndex, bool collapsed)
1830 {
1831         SysTryReturn(NID_UI, columnIndex >= 0, E_OUT_OF_RANGE, E_OUT_OF_RANGE,
1832                                 "[E_OUT_OF_RANGE] Negative input argument : column(%d)", columnIndex);
1833         SysTryReturn(NID_UI, columnIndex < __column, E_OUT_OF_RANGE, E_OUT_OF_RANGE,
1834                                 "[E_OUT_OF_RANGE] Input Argument column over the max column : column(%d), maxColumn(%d)", columnIndex, __column);
1835
1836         __pColInfo[columnIndex].columnCollapsed = collapsed;
1837
1838         ProxyListNode* pCurNode = null;
1839         TableItemInfo* pItemInfo = null;
1840         result r = E_SUCCESS;
1841         for (int i = 0; i < __row; i++)
1842         {
1843                 pCurNode = GetNode(i, columnIndex);
1844                 if (pCurNode != null)
1845                 {
1846                         pItemInfo = dynamic_cast <TableItemInfo*>(pCurNode->GetItemInfo());
1847                         if (pItemInfo == null)
1848                         {
1849                                 return E_INVALID_STATE;
1850                         }
1851                         if (pItemInfo->__merged == true)
1852                         {
1853                                 continue;
1854                         }
1855                         if (__pColInfo[columnIndex].columnCollapsed)
1856                         {
1857                                 pItemInfo->__enable = false;
1858                                 if (pCurNode->GetItemProxy() != null)
1859                                 {
1860                                         pCurNode->GetItemProxy()->Visible(false);
1861                                 }
1862                         }
1863                         else if (!__pRowInfo[i].rowCollapsed)
1864                         {
1865                                 pItemInfo->__enable = true;
1866                                 if (pCurNode->GetItemProxy() != null)
1867                                 {
1868                                         pCurNode->GetItemProxy()->Visible(true);
1869                                 }
1870                         }
1871                 }
1872         }
1873
1874         SetUpdateState(true);
1875         return r;
1876 }
1877
1878 bool
1879 TableLayout::GetColumnCollapsed(int columnIndex) const
1880 {
1881         if (columnIndex < 0 || columnIndex >= __column)
1882         {
1883                 return false;
1884         }
1885
1886         return __pColInfo[columnIndex].columnCollapsed;
1887 }
1888
1889 result
1890 TableLayout::SetRowCollapsed(int rowIndex, bool collapsed)
1891 {
1892         SysTryReturn(NID_UI, rowIndex >= 0, E_OUT_OF_RANGE, E_OUT_OF_RANGE,
1893                                 "[E_OUT_OF_RANGE] Negative input argument : row(%d)", rowIndex);
1894         SysTryReturn(NID_UI, rowIndex < __row, E_OUT_OF_RANGE, E_OUT_OF_RANGE,
1895                                 "[E_OUT_OF_RANGE] Input Argument row over the max row : row(%d), maxRow(%d)", rowIndex, __row);
1896
1897         __pRowInfo[rowIndex].rowCollapsed = collapsed;
1898
1899         ProxyListNode* pCurNode = null;
1900         TableItemInfo* pItemInfo = null;
1901
1902         for (int i = 0; i < __column; i++)
1903         {
1904                 pCurNode = GetNode(rowIndex, i);
1905                 if (pCurNode != null)
1906                 {
1907                         pItemInfo = dynamic_cast <TableItemInfo*>(pCurNode->GetItemInfo());
1908                         if (pItemInfo == null)
1909                         {
1910                                 return E_INVALID_STATE;
1911                         }
1912                         if (pItemInfo->__merged == true)
1913                         {
1914                                 continue;
1915                         }
1916                         if (__pRowInfo[rowIndex].rowCollapsed)
1917                         {
1918                                 pItemInfo->__enable = false;
1919                                 if (pCurNode->GetItemProxy() != null)
1920                                 {
1921                                         pCurNode->GetItemProxy()->Visible(false);
1922                                 }
1923                         }
1924                         else if (!__pColInfo[i].columnCollapsed)
1925                         {
1926                                 pItemInfo->__enable = true;
1927                                 if (pCurNode->GetItemProxy() != null)
1928                                 {
1929                                         pCurNode->GetItemProxy()->Visible(true);
1930                                 }
1931                         }
1932                 }
1933         }
1934
1935         SetUpdateState(true);
1936         return E_SUCCESS;
1937 }
1938
1939 bool
1940 TableLayout::GetRowCollapsed(int rowIndex) const
1941 {
1942         if (rowIndex < 0 || rowIndex >= __row)
1943         {
1944                 return false;
1945         }
1946
1947         return __pRowInfo[rowIndex].rowCollapsed;
1948 }
1949
1950 result
1951 TableLayout::SetRowShrinkable(int row, bool shrinkable)
1952 {
1953         SysTryReturn(NID_UI, row >= 0, E_OUT_OF_RANGE, E_OUT_OF_RANGE,
1954                                 "[E_OUT_OF_RANGE] Negative input argument : row(%d)", row);
1955         SysTryReturn(NID_UI, row < __row, E_OUT_OF_RANGE, E_OUT_OF_RANGE,
1956                                 "[E_OUT_OF_RANGE] Input Argument row over the max row : row(%d), maxRow(%d)", row, __row);
1957
1958         __pRowInfo[row].heightShrinkable = shrinkable;
1959
1960         SetUpdateState(true);
1961         SetPartialUpdateFlag(true);
1962         return E_SUCCESS;
1963 }
1964
1965 bool
1966 TableLayout::GetRowShrinkable(int row) const
1967 {
1968         SysTryReturn(NID_UI, row >= 0, false, E_OUT_OF_RANGE, "[E_OUT_OF_RANGE] Negative input argument : row(%d)", row);
1969         SysTryReturn(NID_UI, row < __row, false, E_OUT_OF_RANGE,
1970                                 "[E_OUT_OF_RANGE] Input Argument row over the max row : row(%d), maxRow(%d)", row, __row);
1971
1972         return __pRowInfo[row].heightShrinkable;
1973 }
1974
1975 result
1976 TableLayout::SetColumnShrinkable(int column, bool shrinkable)
1977 {
1978         SysTryReturn(NID_UI, column >= 0, E_OUT_OF_RANGE, E_OUT_OF_RANGE,
1979                                 "[E_OUT_OF_RANGE] Negative input argument : column(%d)", column);
1980         SysTryReturn(NID_UI, column < __column, E_OUT_OF_RANGE, E_OUT_OF_RANGE,
1981                                 "[E_OUT_OF_RANGE] Input Argument column over the max column : column(%d), maxColumn(%d)", column, __column);
1982
1983         __pColInfo[column].widthShrinkable = shrinkable;
1984
1985         SetUpdateState(true);
1986         SetPartialUpdateFlag(true);
1987         return E_SUCCESS;
1988 }
1989
1990 bool
1991 TableLayout::GetColumnShrinkable(int column) const
1992 {
1993         SysTryReturn(NID_UI, column >= 0, false, E_OUT_OF_RANGE,
1994                                 "[E_OUT_OF_RANGE] Negative input argument : column(%d)", column);
1995         SysTryReturn(NID_UI, column < __column, false, E_OUT_OF_RANGE,
1996                                 "[E_OUT_OF_RANGE] Input Argument column over the max column : column(%d), maxColumn(%d)", column, __column);
1997
1998         return __pColInfo[column].widthShrinkable;
1999 }
2000
2001 result
2002 TableLayout::SetRowStretchable(int row, bool stretchable)
2003 {
2004         SysTryReturn(NID_UI, row >= 0, E_OUT_OF_RANGE, E_OUT_OF_RANGE,
2005                                 "[E_OUT_OF_RANGE] Negative input argument : row(%d)", row);
2006         SysTryReturn(NID_UI, row < __row, E_OUT_OF_RANGE, E_OUT_OF_RANGE,
2007                                 "[E_OUT_OF_RANGE] Input Argument row over the max row : row(%d), maxRow(%d)", row, __row);
2008
2009         __pRowInfo[row].heightStretchable = stretchable;
2010
2011         SetUpdateState(true);
2012         SetPartialUpdateFlag(true);
2013         return E_SUCCESS;
2014 }
2015
2016 bool
2017 TableLayout::GetRowStretchable(int row) const
2018 {
2019         if (row < 0 || row >= __row)
2020         {
2021                 return false;
2022         }
2023
2024         return __pRowInfo[row].heightStretchable;
2025 }
2026
2027 result
2028 TableLayout::SetColumnStretchable(int column, bool stretchable)
2029 {
2030         SysTryReturn(NID_UI, column >= 0, E_OUT_OF_RANGE, E_OUT_OF_RANGE, "[E_OUT_OF_RANGE] Negative input argument : column(%d)",
2031                                 column);
2032         SysTryReturn(NID_UI, column < __column, E_OUT_OF_RANGE, E_OUT_OF_RANGE,
2033                                 "[E_OUT_OF_RANGE] Input Argument column over the max column : column(%d), maxColumn(%d)", column, __column);
2034
2035         __pColInfo[column].widthStretchable = stretchable;
2036
2037         SetUpdateState(true);
2038         SetPartialUpdateFlag(true);
2039         return E_SUCCESS;
2040 }
2041
2042 bool
2043 TableLayout::GetColumnStretchable(int column) const
2044 {
2045         SysTryReturn(NID_UI, column >= 0, false, E_OUT_OF_RANGE, "[E_OUT_OF_RANGE] Negative input argument : column(%d)", column);
2046         SysTryReturn(NID_UI, column < __column, false, E_OUT_OF_RANGE,
2047                                 "[E_OUT_OF_RANGE] Input Argument column over the max column : column(%d), maxColumn(%d)", column, __column);
2048
2049         return __pColInfo[column].widthStretchable;
2050 }
2051
2052 result
2053 TableLayout::SetRowSpacing(int row, int heightSpacing)
2054 {
2055         SysTryReturn(NID_UI, row >= 0, E_OUT_OF_RANGE, E_OUT_OF_RANGE,
2056                                 "[E_OUT_OF_RANGE] Negative input argument : row(%d)", row);
2057         SysTryReturn(NID_UI, row < __row, E_OUT_OF_RANGE, E_OUT_OF_RANGE,
2058                                 "[E_OUT_OF_RANGE] Input Argument row over the max row : row(%d), maxRow(%d)", row, __row);
2059         SysTryReturn(NID_UI, heightSpacing >= 0, E_OUT_OF_RANGE, E_OUT_OF_RANGE,
2060                                 "[E_OUT_OF_RANGE] Negative input argument : spacing(%d)", heightSpacing);
2061
2062         __pRowInfo[row].heightSpacing = heightSpacing;
2063
2064         SetUpdateState(true);
2065         return E_SUCCESS;
2066 }
2067
2068 result
2069 TableLayout::GetRowSpacing(int row, int& spacing) const
2070 {
2071         SysTryReturn(NID_UI, row >= 0, E_OUT_OF_RANGE, E_OUT_OF_RANGE,
2072                                 "[E_OUT_OF_RANGE] Negative input argument : row(%d)", row);
2073         SysTryReturn(NID_UI, row < __row, E_OUT_OF_RANGE, E_OUT_OF_RANGE,
2074                                 "[E_OUT_OF_RANGE] Input Argument row over the max row : row(%d), maxRow(%d)", row, __row);
2075
2076         spacing = __pRowInfo[row].heightSpacing;
2077         return E_SUCCESS;
2078 }
2079
2080 result
2081 TableLayout::SetColumnSpacing(int column, int widthSpacing)
2082 {
2083         SysTryReturn(NID_UI, column >= 0, E_OUT_OF_RANGE, E_OUT_OF_RANGE,
2084                                 "[E_OUT_OF_RANGE] Negative input argument : column(%d)", column);
2085         SysTryReturn(NID_UI, column < __column, E_OUT_OF_RANGE, E_OUT_OF_RANGE,
2086                                 "[E_OUT_OF_RANGE] Input Argument column over the max column : column(%d), maxColumn(%d)", column, __column);
2087         SysTryReturn(NID_UI, widthSpacing >= 0, E_OUT_OF_RANGE, E_OUT_OF_RANGE,
2088                                 "[E_OUT_OF_RANGE] Negative input argument : spacing(%d)", widthSpacing);
2089
2090         __pColInfo[column].widthSpacing = widthSpacing;
2091
2092         SetUpdateState(true);
2093         return E_SUCCESS;
2094 }
2095
2096 result
2097 TableLayout::GetColumnSpacing(int column, int& spacing) const
2098 {
2099         SysTryReturn(NID_UI, column >= 0, E_OUT_OF_RANGE, E_OUT_OF_RANGE,
2100                                 "[E_OUT_OF_RANGE] Negative input argument : column(%d)", column);
2101         SysTryReturn(NID_UI, column < __column, E_OUT_OF_RANGE, E_OUT_OF_RANGE,
2102                                 "[E_OUT_OF_RANGE] Input Argument column over the max column : column(%d), maxColumn(%d)", column, __column);
2103
2104         spacing = __pColInfo[column].widthSpacing;
2105
2106         return E_SUCCESS;
2107 }
2108
2109 result
2110 TableLayout::SetFillCell(int row, int column, bool fillWidth, bool fillHeight)
2111 {
2112         SysTryReturn(NID_UI, row >= 0, E_OUT_OF_RANGE, E_OUT_OF_RANGE,
2113                                 "[E_OUT_OF_RANGE] Negative input argument : row(%d)", row);
2114         SysTryReturn(NID_UI, row < __row, E_OUT_OF_RANGE, E_OUT_OF_RANGE,
2115                                 "[E_OUT_OF_RANGE] Input Argument row over the max row : row(%d), maxRow(%d)", row, __row);
2116         SysTryReturn(NID_UI, column >= 0, E_OUT_OF_RANGE, E_OUT_OF_RANGE,
2117                                 "[E_OUT_OF_RANGE] Negative input argument : column(%d)", column);
2118         SysTryReturn(NID_UI, column < __column, E_OUT_OF_RANGE, E_OUT_OF_RANGE,
2119                                 "[E_OUT_OF_RANGE] Input Argument column over the max column : column(%d), maxColumn(%d)", column, __column);
2120
2121         ProxyListNode* pNode = GetNode(row, column);
2122         if (pNode != null)
2123         {
2124                 TableItemInfo* pItemInfo = dynamic_cast <TableItemInfo*>(pNode->GetItemInfo());
2125                 if (pItemInfo == null)
2126                 {
2127                         return E_INVALID_STATE;
2128                 }
2129                 pItemInfo->__fillWidth = fillWidth;
2130                 pItemInfo->__fillHeight = fillHeight;
2131                 return E_SUCCESS;
2132         }
2133         return E_SYSTEM;
2134 }
2135
2136 result
2137 TableLayout::GetFillCell(int row, int column, bool& fillWidth, bool& fillHeight) const
2138 {
2139         SysTryReturn(NID_UI, row >= 0, E_OUT_OF_RANGE, E_OUT_OF_RANGE,
2140                                 "[E_OUT_OF_RANGE] Negative input argument : row(%d)", row);
2141         SysTryReturn(NID_UI, row < __row, E_OUT_OF_RANGE, E_OUT_OF_RANGE,
2142                                 "[E_OUT_OF_RANGE] Input Argument row over the max row : row(%d), maxRow(%d)", row, __row);
2143         SysTryReturn(NID_UI, column >= 0, E_OUT_OF_RANGE, E_OUT_OF_RANGE,
2144                                 "[E_OUT_OF_RANGE] Negative input argument : column(%d)", column);
2145         SysTryReturn(NID_UI, column < __column, E_OUT_OF_RANGE, E_OUT_OF_RANGE,
2146                                 "[E_OUT_OF_RANGE] Input Argument column over the max column : column(%d), maxColumn(%d)", column, __column);
2147
2148         ProxyListNode* pNode = GetNode(row, column);
2149         if (pNode != null)
2150         {
2151                 TableItemInfo* pItemInfo = dynamic_cast <TableItemInfo*>(pNode->GetItemInfo());
2152                 if (pItemInfo == null)
2153                 {
2154                         return E_INVALID_STATE;
2155                 }
2156                 fillWidth = pItemInfo->__fillWidth;
2157                 fillHeight = pItemInfo->__fillHeight;
2158                 return E_SUCCESS;
2159         }
2160         return E_SYSTEM;
2161 }
2162
2163 result
2164 TableLayout::SwapItemPosition(LayoutItem& item1, LayoutItem& item2)
2165 {
2166         ProxyList* pProxyList = GetProxyList();
2167         SysAssertf(pProxyList != null, "ProxyList is invalid");
2168
2169         ProxyListNode* pNode1 = pProxyList->GetNode(item1);
2170         ProxyListNode* pNode2 = pProxyList->GetNode(item2);
2171
2172         SysTryReturn(NID_UI, (pNode1 != null && pNode2 != null), E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Control dose not belong to layout.")
2173
2174         TableItemInfo* pItemInfo1 = dynamic_cast <TableItemInfo*>(pNode1->GetItemInfo());
2175         TableItemInfo* pItemInfo2 = dynamic_cast <TableItemInfo*>(pNode2->GetItemInfo());
2176         if (pItemInfo1 == null || pItemInfo2 == null)
2177         {
2178                 return E_INVALID_STATE;
2179         }
2180
2181         int cellIndex1 = pItemInfo1->__id;
2182         int cellIndex2 = pItemInfo2->__id;
2183         bool merged1 = pItemInfo1->__merged;
2184         bool merged2 = pItemInfo2->__merged;
2185         bool enable1 = pItemInfo1->__enable;
2186         bool enable2 = pItemInfo2->__enable;
2187
2188         pItemInfo1->__id = cellIndex2;
2189         pItemInfo2->__id = cellIndex1;
2190         pItemInfo1->__merged = merged2;
2191         pItemInfo2->__merged = merged1;
2192         pItemInfo1->__enable = enable2;
2193         pItemInfo2->__enable = enable1;
2194
2195         if (pNode1->GetItemProxy() != null)
2196         {
2197                 if (pItemInfo1->__merged || !pItemInfo1->__enable)
2198                 {
2199                         pNode1->GetItemProxy()->Visible(false);
2200                 }
2201                 else
2202                 {
2203                         pNode1->GetItemProxy()->Visible(true);
2204                 }
2205         }
2206
2207         if (pNode2->GetItemProxy() != null)
2208         {
2209                 if (pItemInfo2->__merged || !pItemInfo2->__enable)
2210                 {
2211                         pNode2->GetItemProxy()->Visible(false);
2212                 }
2213                 else
2214                 {
2215                         pNode2->GetItemProxy()->Visible(true);
2216                 }
2217         }
2218
2219         SetUpdateState(true);
2220         return E_SUCCESS;
2221 }
2222
2223 result
2224 TableLayout::Unmerge(int row, int column)
2225 {
2226         SysTryReturn(NID_UI, row >= 0, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Negative input argument : row(%d)", row);
2227         SysTryReturn(NID_UI, row < __row, E_INVALID_ARG, E_INVALID_ARG,
2228                                 "[E_INVALID_ARG] Input Argument row over the max row : row(%d), maxRow(%d)", row, __row);
2229         SysTryReturn(NID_UI, column >= 0, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Negative input argument : column(%d)", column);
2230         SysTryReturn(NID_UI, column < __column, E_INVALID_ARG, E_INVALID_ARG,
2231                                 "[E_INVALID_ARG] Input Argument column over the max column : column(%d), maxColumn(%d)", column, __column);
2232
2233         int endRow = 0;
2234         int endColumn = 0;
2235
2236         ProxyListNode* pCurNode = null;
2237         TableItemInfo* pItemInfo = null;
2238
2239         pCurNode = GetNode(row, column);
2240         SysTryReturn(NID_UI, pCurNode, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALIDE_ARG] (%d, %d) cell  is not merged.", row, column);
2241
2242         pItemInfo = dynamic_cast <TableItemInfo*>(pCurNode->GetItemInfo());
2243         if (pItemInfo == null)
2244         {
2245                 return E_INVALID_STATE;
2246         }
2247         endRow = pItemInfo->__mergeEndPoint.x;
2248         endColumn = pItemInfo->__mergeEndPoint.y;
2249
2250         if (pItemInfo->__enable == false || pItemInfo->__merged == false
2251                 || endRow == NOT_MERGED || endColumn == NOT_MERGED)
2252         {
2253                 return E_INVALID_STATE;
2254         }
2255
2256         pItemInfo->__mergeEndPoint.x = NOT_MERGED;
2257         pItemInfo->__mergeEndPoint.y = NOT_MERGED;
2258
2259         for (int i = row; i <= endRow; i++)
2260         {
2261                 for (int j = column; j <= endColumn; j++)
2262                 {
2263                         pCurNode = GetNode(i, j);
2264                         if (pCurNode != null)
2265                         {
2266                                 pItemInfo = dynamic_cast <TableItemInfo*>(pCurNode->GetItemInfo());
2267                                 if (pItemInfo == null)
2268                                 {
2269                                         return E_INVALID_STATE;
2270                                 }
2271                                 pItemInfo->__enable = true;
2272                                 pItemInfo->__merged = false;
2273
2274                                 for (int k = 0; k < __mergedCellList.GetCount(); k++)
2275                                 {
2276                                         Integer* cellID = static_cast <Integer*>(__mergedCellList.GetAt(k));
2277                                         if (cellID->ToInt() == MakeCellID(i, j))
2278                                         {
2279                                                 __mergedCellList.RemoveAt(k, true);
2280                                                 break;
2281                                         }
2282                                 }
2283
2284                                 if (pCurNode->GetItemProxy() != null)
2285                                 {
2286                                         pCurNode->GetItemProxy()->Visible(true);
2287                                 }
2288                         }
2289                 }
2290         }
2291
2292         SetUpdateState(true);
2293         return E_SUCCESS;
2294 }
2295
2296 result
2297 TableLayout::GetMergeSize(int row, int column, int& rowSize, int& colSize) const
2298 {
2299         rowSize = 0;
2300         colSize = 0;
2301
2302         SysTryReturn(NID_UI, row >= 0, E_OUT_OF_RANGE, E_OUT_OF_RANGE,
2303                                 "[E_OUT_OF_RANGE] Negative input argument : row(%d)", row);
2304         SysTryReturn(NID_UI, row < __row, E_OUT_OF_RANGE, E_OUT_OF_RANGE,
2305                                 "[E_OUT_OF_RANGE] Input Argument row over the max row : row(%d), maxRow(%d)", row, __row);
2306         SysTryReturn(NID_UI, column >= 0, E_OUT_OF_RANGE, E_OUT_OF_RANGE,
2307                                 "[E_OUT_OF_RANGE] Negative input argument : column(%d)", column);
2308         SysTryReturn(NID_UI, column < __column, E_OUT_OF_RANGE, E_OUT_OF_RANGE,
2309                                 "[E_OUT_OF_RANGE] Input Argument column over the max column : column(%d), maxColumn(%d)", column, __column);
2310
2311         ProxyListNode* pNode = GetNode(row, column);
2312         if (pNode == null)
2313         {
2314                 rowSize = 1;
2315                 colSize = 1;
2316                 return E_SUCCESS;
2317         }
2318         TableItemInfo* pItemInfo = dynamic_cast <TableItemInfo*>(pNode->GetItemInfo());
2319         if (pItemInfo == null || pItemInfo->__enable == false)
2320         {
2321                 return E_INVALID_STATE;
2322         }
2323
2324         if (pItemInfo->__merged == false)
2325         {
2326                 rowSize = 1;
2327                 colSize = 1;
2328         }
2329         else
2330         {
2331                 rowSize = pItemInfo->__mergeEndPoint.x - row + 1;
2332                 colSize = pItemInfo->__mergeEndPoint.y - column + 1;
2333         }
2334
2335         return E_SUCCESS;
2336 }
2337
2338 ProxyListNode*
2339 TableLayout::GetNode(int row, int column) const
2340 {
2341         ProxyList* pProxyList = GetProxyList();
2342         SysAssertf(pProxyList != null, "ProxyList is invalid");
2343
2344         ProxyListNode* pCurNode = pProxyList->GetFirstNode();
2345         TableItemInfo* pItemInfo = null;
2346         int rowIndex = 0;
2347         int columnIndex = 0;
2348         while (pCurNode)
2349         {
2350                 pItemInfo = dynamic_cast <TableItemInfo*>(pCurNode->GetItemInfo());
2351                 if (pItemInfo != null)
2352                 {
2353                         rowIndex = GetRow(pItemInfo->__id);
2354                         columnIndex = GetColumn(pItemInfo->__id);
2355                         if (row == rowIndex && column == columnIndex)
2356                         {
2357                                 return pCurNode;
2358                         }
2359                 }
2360                 pCurNode = pProxyList->GetNextNode(*pCurNode);
2361         }
2362         return null;
2363 }
2364
2365 int
2366 TableLayout::GetRow(int id) const
2367 {
2368         return id >> 16;
2369 }
2370
2371 int
2372 TableLayout::GetColumn(int id) const
2373 {
2374         return id & 0x0000FFFF;
2375 }
2376
2377 int
2378 TableLayout::MakeCellID(int row, int column) const
2379 {
2380         return (row << 16) | (column & 0x0000FFFF);
2381 }
2382
2383 } // Tizen::Ui::_Layout
2384 } // Tizen::Ui
2385 } // Osp