Tizen 2.1 base
[framework/osp/uifw.git] / src / ui / controls / FUiCtrl_ContextMenuListPresenter.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                FUiCtrl_ContextMenuListPresenter.cpp
19  * @brief               This is the implementation file for the _ContextMenuListPresenter class.
20  */
21
22 #include <FBaseErrorDefine.h>
23 #include <FBaseSysLog.h>
24 #include <FGrp_CanvasImpl.h>
25 #include <FGrp_BitmapImpl.h>
26 #include <FGrp_TextTextSimple.h>
27 #include "FUiCtrl_ContextMenuListPresenter.h"
28 #include "FUiCtrl_IActionEventListener.h"
29 #include "FUiCtrl_ActionEvent.h"
30 #include "FUi_ResourceManager.h"
31 #include "FUi_AccessibilityContainer.h"
32 #include "FUi_AccessibilityElement.h"
33
34 using namespace Tizen::Graphics;
35 using namespace Tizen::Ui;
36 using namespace Tizen::Base;
37 using namespace Tizen::Base::Runtime;
38 using namespace Tizen::Graphics::_Text;
39
40 static const int CONTEXT_MENU_LIST_ELEMENT_TEXT = 0;
41 static const int CONTEXT_MENU_LIST_ELEMENT_BITMAP = 1;
42
43 namespace Tizen { namespace Ui { namespace Controls
44 {
45
46 _ContextMenuListPresenter::_ContextMenuListPresenter(_ContextMenu* pContextMenu)
47         : __pContextMenu(pContextMenu)
48         , __pModel(null)
49         , __pFont(null)
50         , __layoutSize(Dimension(0, 0))
51         , __touchOutRect(false)
52         , __selectedIndex(-1)
53         , __scrollEnable(false)
54         , __maxWidth(0)
55         , __minWidth(0)
56         , __topMargin(0)
57         , __bottomMargin(0)
58         , __leftMargin(0)
59         , __rightMargin(0)
60         , __screenTopMargin(0)
61         , __screenBottomMargin(0)
62         , __screenLeftMargin(0)
63         , __screenRightMargin(0)
64         , __arrowMargin(0)
65         , __arrowWidth(0)
66         , __arrowHeight(0)
67         , __itemWidth(0)
68         , __itemMinWidth(0)
69         , __itemHeight(0)
70         , __itemMaxWidth(0)
71         , __itemGap(0)
72         , __itemBitmapWidth(0)
73         , __itemBitmapHeight(0)
74         , __itemFontSize(0)
75         , __dividerHeight(0)
76 {
77
78 }
79
80 _ContextMenuListPresenter::~_ContextMenuListPresenter(void)
81 {
82         __pContextMenu = null;
83
84         delete __pModel;
85         __pModel = null;
86
87         __pFont = null;
88
89 }
90
91 result
92 _ContextMenuListPresenter::Install(void)
93 {
94         result r = E_SUCCESS;
95
96         LoadShape();
97
98         __pModel = new (std::nothrow) _ContextMenuModel;
99         SysTryCatch(NID_UI_CTRL, __pModel != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory shortage.");
100
101         r = __pModel->Construct();
102         SysTryCatch(NID_UI_CTRL, r == E_SUCCESS, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Unable to create data instance.");
103
104         __pFont = __pContextMenu->GetFallbackFont();
105         r = GetLastResult();
106         SysTryCatch(NID_UI_CTRL, (__pFont != null), , r, "[%s] Propagating.", GetErrorMessage(r));
107
108         return r;
109
110 CATCH:
111         delete __pModel;
112         __pModel = null;
113
114         __pFont = null;
115
116         return r;
117 }
118
119
120 void
121 _ContextMenuListPresenter::LoadShape(void)
122 {
123         GET_SHAPE_CONFIG(CONTEXTMENU::LIST_MIN_WIDTH, _CONTROL_ORIENTATION_PORTRAIT, __itemMinWidth);
124         GET_SHAPE_CONFIG(CONTEXTMENU::LIST_MAX_WIDTH, _CONTROL_ORIENTATION_PORTRAIT, __itemMaxWidth);
125         GET_SHAPE_CONFIG(CONTEXTMENU::LIST_ITEM_HEIGHT, _CONTROL_ORIENTATION_PORTRAIT, __itemHeight);
126         GET_SHAPE_CONFIG(CONTEXTMENU::LIST_ITEM_GAP, _CONTROL_ORIENTATION_PORTRAIT, __itemGap);
127
128         GET_SHAPE_CONFIG(CONTEXTMENU::LIST_TOP_MARGIN, _CONTROL_ORIENTATION_PORTRAIT, __topMargin);
129         GET_SHAPE_CONFIG(CONTEXTMENU::LIST_BOTTOM_MARGIN, _CONTROL_ORIENTATION_PORTRAIT, __bottomMargin);
130         GET_SHAPE_CONFIG(CONTEXTMENU::LIST_LEFT_MARGIN, _CONTROL_ORIENTATION_PORTRAIT, __leftMargin);
131         GET_SHAPE_CONFIG(CONTEXTMENU::LIST_RIGHT_MARGIN, _CONTROL_ORIENTATION_PORTRAIT, __rightMargin);
132
133         GET_SHAPE_CONFIG(CONTEXTMENU::SCREEN_TOP_MARGIN, _CONTROL_ORIENTATION_PORTRAIT, __screenTopMargin);
134         GET_SHAPE_CONFIG(CONTEXTMENU::SCREEN_BOTTOM_MARGIN, _CONTROL_ORIENTATION_PORTRAIT, __screenBottomMargin);
135         GET_SHAPE_CONFIG(CONTEXTMENU::SCREEN_LEFT_MARGIN, _CONTROL_ORIENTATION_PORTRAIT, __screenLeftMargin);
136         GET_SHAPE_CONFIG(CONTEXTMENU::SCREEN_RIGHT_MARGIN, _CONTROL_ORIENTATION_PORTRAIT, __screenRightMargin);
137         GET_SHAPE_CONFIG(CONTEXTMENU::ANCHOR_MARGIN, _CONTROL_ORIENTATION_PORTRAIT, __arrowMargin);
138         GET_SHAPE_CONFIG(CONTEXTMENU::ANCHOR_WIDTH, _CONTROL_ORIENTATION_PORTRAIT, __arrowWidth);
139         GET_SHAPE_CONFIG(CONTEXTMENU::ANCHOR_HEIGHT, _CONTROL_ORIENTATION_PORTRAIT, __arrowHeight);
140         GET_SHAPE_CONFIG(CONTEXTMENU::LIST_ICON_WIDTH, _CONTROL_ORIENTATION_PORTRAIT, __itemBitmapWidth);
141         GET_SHAPE_CONFIG(CONTEXTMENU::LIST_ICON_HEIGHT, _CONTROL_ORIENTATION_PORTRAIT, __itemBitmapHeight);
142
143         GET_SHAPE_CONFIG(CONTEXTMENU::LIST_ITEM_FONT_SIZE, _CONTROL_ORIENTATION_PORTRAIT, __itemFontSize);
144         GET_SHAPE_CONFIG(CONTEXTMENU::LIST_DIVIDER_HEIGHT, _CONTROL_ORIENTATION_PORTRAIT, __dividerHeight);
145
146         __itemWidth = __itemMinWidth;
147 }
148
149 _ContextMenuItem*
150 _ContextMenuListPresenter::CreateItem(const Base::String& text, int actionId, const Tizen::Graphics::Bitmap* pNormalBitmap, const Tizen::Graphics::Bitmap* pPressedBitmap, const Tizen::Graphics::Bitmap* pHighlightedBitmap)
151 {
152         _ContextMenuItem* pItem = _ContextMenuItem::CreateContextMenuItemN();
153         SysTryReturn(NID_UI_CTRL, pItem != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
154
155         ContextMenuItemDrawingType itemType = CONTEXT_MENU_ITEM_DRAWING_TYPE_TEXT;
156
157         result r = E_SUCCESS;
158         _Label* pLabel = null;
159
160         if (pNormalBitmap != null)
161         {
162                 r = pItem->SetBitmap(CONTEXT_MENU_ITEM_DRAWING_STATUS_NORMAL, pNormalBitmap);
163                 if (r != E_SUCCESS)
164                 {
165                         delete pItem;
166                         return null;
167                 }
168
169                 // add bitmap label
170                 pLabel = _Label::CreateLabelN();
171                 pLabel->SetBackgroundBitmap(*pNormalBitmap);
172                 pLabel->SetBackgroundColor(Color(0, 0, 0, 0));
173
174                 int bitmapY = (__itemHeight - __itemBitmapHeight ) / 2;
175                 pLabel->SetBounds(Rectangle(__leftMargin, bitmapY,  __itemBitmapWidth, __itemBitmapHeight));
176                 pItem->AttachChild(*pLabel);
177                 _AccessibilityContainer* pContainer = pLabel->GetAccessibilityContainer();
178                 if (pContainer)
179                 {
180                         pContainer->Activate(false);
181                 }
182                 pItem->SetBitmapLabel(pLabel);
183
184                 itemType = CONTEXT_MENU_ITEM_DRAWING_TYPE_BITMAP;
185         }
186
187         if (pPressedBitmap != null)
188         {
189                 r = pItem->SetBitmap(CONTEXT_MENU_ITEM_DRAWING_STATUS_PRESSED, pPressedBitmap);
190                 if (r != E_SUCCESS)
191                 {
192                         delete pItem;
193                         return null;
194                 }
195         }
196
197         pItem->SetType(itemType);
198         pItem->SetActionId(actionId);
199
200         pItem->SetTextSize(__itemFontSize);
201         r = pItem->SetText(text);
202         if (r != E_SUCCESS)
203         {
204                 delete pItem;
205                 return null;
206         }
207
208         // calculate item size
209         int bitmapWidth = (itemType == CONTEXT_MENU_ITEM_DRAWING_TYPE_BITMAP) ? __itemBitmapWidth : 0;
210
211         Dimension textArea(0, 0);
212         Dimension itemSize(0, 0);
213
214         __pFont->GetTextExtent(text, text.GetLength(), textArea);
215         int labelLeftMargin, labelTopMargin;
216         GET_SHAPE_CONFIG(LABEL::LEFT_MARGIN, _CONTROL_ORIENTATION_PORTRAIT, labelLeftMargin);
217         GET_SHAPE_CONFIG(LABEL::TOP_MARGIN,  _CONTROL_ORIENTATION_PORTRAIT, labelTopMargin);
218         textArea.width  += 2 * labelLeftMargin;
219         textArea.height += 2 * labelTopMargin;
220         itemSize.height = __itemHeight + __dividerHeight;
221         itemSize.width =  __leftMargin + textArea.width + __rightMargin + bitmapWidth;
222
223         itemSize.width = itemSize.width < __itemMinWidth ? __itemMinWidth : itemSize.width;
224         itemSize.width = itemSize.width > __itemMaxWidth ? __itemMaxWidth : itemSize.width;
225
226         pItem->SetSize(itemSize);
227
228         // add text label
229         int textLabelX = __leftMargin + bitmapWidth;
230         int textLabelWidth = textArea.width;
231
232         pLabel = _Label::CreateLabelN();
233         pLabel->SetText(text);
234         ContextMenuCoreItemStatus itemStatus = CONTEXT_MENU_CORE_ITEM_STATUS_NORMAL;
235         pLabel->SetTextColor(__pContextMenu->GetTextColor(itemStatus));
236         pLabel->SetBackgroundColor(Color(0, 0, 0, 0));
237
238         itemSize = pItem->GetSize();
239         pLabel->SetBounds(Rectangle(textLabelX, (itemSize.height - textArea.height) / 2, textLabelWidth, textArea.height));
240         pLabel->SetTextVerticalAlignment(ALIGNMENT_MIDDLE);
241         pLabel->SetTextHorizontalAlignment(ALIGNMENT_LEFT);
242         pLabel->SetTextConfig(__itemFontSize, LABEL_TEXT_STYLE_NORMAL);
243
244         pItem->AttachChild(*pLabel);
245         _AccessibilityContainer* pContainer = pLabel->GetAccessibilityContainer();
246         if (pContainer)
247         {
248                 pContainer->Activate(false);
249         }
250         pItem->SetTextLabel(pLabel);
251
252         __itemWidth = __itemWidth < itemSize.width ? itemSize.width : __itemWidth;
253
254         return pItem;
255 }
256
257 result
258 _ContextMenuListPresenter::AddItem(const Base::String& text, int actionId, const Tizen::Graphics::Bitmap* normalBitmap,
259                                                                    const Tizen::Graphics::Bitmap* pPressedBitmap,
260                                                                    const Tizen::Graphics::Bitmap* pHighlightedBitmap)
261 {
262         _ContextMenuItem* pItem = CreateItem(text, actionId, normalBitmap, pPressedBitmap, pHighlightedBitmap);
263         SysTryReturn(NID_UI_CTRL, pItem != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "The memory is insufficient.");
264
265         result r = __pModel->AddItem(pItem);
266
267         if (r != E_SUCCESS)
268         {
269                 delete pItem;
270                 SysTryReturn(NID_UI_CTRL, false, r, r, "Failed to add item.");
271         }
272
273         return r;
274 }
275
276 result
277 _ContextMenuListPresenter::InsertItem(int index, const Tizen::Base::String& text, int actionId,
278                                                                           const Tizen::Graphics::Bitmap* normalBitmap, const Tizen::Graphics::Bitmap* pPressedBitmap,
279                                                                           const Tizen::Graphics::Bitmap* pHighlightedBitmap)
280 {
281         if (text.GetLength() == 0 && normalBitmap == null && pPressedBitmap == null)
282         {
283                 return E_INVALID_ARG;
284         }
285
286         _ContextMenuItem* pItem = null;
287
288         pItem = CreateItem(text, actionId, normalBitmap, pPressedBitmap, pHighlightedBitmap);
289         SysTryReturn(NID_UI_CTRL, pItem != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "The memory is insufficient.");
290
291         result r = __pModel->InsertItem(pItem, index);
292         if (r != E_SUCCESS)
293         {
294                 delete pItem;
295                 SysTryReturn(NID_UI_CTRL, false, r, r, "Failed to add item.");
296         }
297
298         return E_SUCCESS;
299 }
300
301 result
302 _ContextMenuListPresenter::SetItem(int index, const Tizen::Base::String& text, int actionId,
303                                                                    const Tizen::Graphics::Bitmap* normalBitmap, const Tizen::Graphics::Bitmap* pPressedBitmap,
304                                                                    const Tizen::Graphics::Bitmap* pHighlightedBitmap)
305 {
306         if (text.GetLength() == 0 && normalBitmap == null && pPressedBitmap == null)
307         {
308                 return E_INVALID_ARG;
309         }
310
311         result r = __pContextMenu->GetScrollPanel()->DetachChild(*__pModel->GetItem(index));
312         SysTryReturn(NID_UI_CTRL, r == E_SUCCESS, r, r, "Failed to detach item.");
313
314         _ContextMenuItem* pItem = null;
315         pItem = CreateItem(text, actionId, normalBitmap, pPressedBitmap, pHighlightedBitmap);
316         SysTryReturn(NID_UI_CTRL, pItem != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "The memory is insufficient.");
317
318         r = __pModel->SetItem(pItem, index);
319         if (r != E_SUCCESS)
320         {
321                 delete pItem;
322                 SysTryReturn(NID_UI_CTRL, false, r, r, "Failed to add item.");
323         }
324
325         return E_SUCCESS;
326 }
327
328 result
329 _ContextMenuListPresenter::DeleteItem(int index)
330 {
331         if (__pContextMenu->GetItemCount() <= 0)
332         {
333                 SysLogException(NID_UI_CTRL, E_INVALID_STATE, "Invalid argument.");
334                 return E_INVALID_STATE;
335         }
336
337         result r = __pContextMenu->GetScrollPanel()->DetachChild(*__pModel->GetItem(index));
338         SysTryReturn(NID_UI_CTRL, r == E_SUCCESS, r, r, "Failed to detach item.");
339
340         r = __pModel->RemoveItem(index);
341         SysTryReturn(NID_UI_CTRL, r == E_SUCCESS, r, r, "Failed to delete item.");
342
343         return r;
344 }
345
346 result
347 _ContextMenuListPresenter::DeleteItemAll(void)
348 {
349         if (__pContextMenu->GetItemCount() <= 0)
350         {
351                 SysLogException(NID_UI_CTRL, E_INVALID_STATE, "Invalid argument.");
352                 return E_INVALID_STATE;
353         }
354
355         __pContextMenu->GetScrollPanel()->DetachAllChildren();
356
357         result r =  __pModel->RemoveAllItem();
358         SysTryReturn(NID_UI_CTRL, r == E_SUCCESS, r, r, "Failed to delete item all.");
359
360         return r;
361 }
362
363
364 int
365 _ContextMenuListPresenter::CalculateShowItemCount(void)
366 {
367         int itemMaxCount = 0;
368         GET_SHAPE_CONFIG(CONTEXTMENU::ITEM_MAX_COUNT, _CONTROL_ORIENTATION_PORTRAIT, itemMaxCount);
369
370         int maxVisibleCount = __pContextMenu->GetShowItemCount();
371
372         return maxVisibleCount > itemMaxCount ? itemMaxCount : maxVisibleCount;
373 }
374
375 result
376 _ContextMenuListPresenter::CalculateWindowRect(void)
377 {
378         result r = CalculateRect();
379         AdjustItemPosition();
380
381         return r;
382 }
383
384 result
385 _ContextMenuListPresenter::ApplyColorProperty(void)
386 {
387         return E_SUCCESS;
388 }
389
390
391 result
392 _ContextMenuListPresenter::CalculateRect(void)
393 {
394         Tizen::Graphics::Rectangle windowRect = Tizen::Graphics::Rectangle(0, 0, 0, 0); // Window Rect is bodyRect + arrowRect
395         Tizen::Graphics::Rectangle bodyRect = Tizen::Graphics::Rectangle(0, 0, 0, 0);   // ContextMenu rect except arrowRect
396         Tizen::Graphics::Rectangle arrowRect = Tizen::Graphics::Rectangle(0, 0, 0, 0);  // Arrow rect of the ContextMenu
397
398         int bodyTopMargin = __topMargin;
399         int bodyBottomMargin = __bottomMargin;
400         int bodyLeftMargin = __leftMargin;
401         int bodyRightMargin = __rightMargin;
402
403         int screenTopMargin = __screenTopMargin;
404         int screenBottomMargin = __screenBottomMargin;
405         int screenLeftMargin = __screenLeftMargin;
406         int screenRightMargin = __screenRightMargin;
407         int arrowMargin = __arrowMargin;
408
409         Point anchorPosition = __pContextMenu->GetAnchorPosition();
410
411         Dimension screen = _ControlManager::GetInstance()->GetScreenSize();
412         if (__pContextMenu->GetLayout() == _CONTROL_ORIENTATION_LANDSCAPE)
413         {
414                 screen.SetSize(screen.height, screen.width);
415         }
416
417         // calculate arrow area
418         enum ContextMenuCoreDropPosition dropPosition = __pContextMenu->GetDropPosition();
419         if (dropPosition == CONTEXT_MENU_CORE_DROP_POSITION_UP || dropPosition == CONTEXT_MENU_CORE_DROP_POSITION_DOWN) // down, up Arrow
420         {
421                 arrowRect.width = __arrowWidth;
422                 arrowRect.height = __arrowHeight;
423         }
424         else //  left, right Arrow
425         {
426                 arrowRect.width = __arrowHeight;
427                 arrowRect.height = __arrowWidth;
428         }
429
430         // calculate body rect
431         // calculate real drawing margin for contextmenu
432         int leftMargin = screenLeftMargin;
433         int rightMargin = screen.width - screenRightMargin;
434         int topMargin = screenTopMargin;
435         int bottomMargin = screen.height - screenBottomMargin;
436
437         // calculate layout size (__layoutSize)
438         AdjustItemLayout();
439
440         bodyRect.width = __layoutSize.width + bodyLeftMargin + bodyRightMargin;
441         bodyRect.height = __layoutSize.height + bodyTopMargin + bodyBottomMargin;
442
443         // calculate the position of the arrow and body rect.
444         if (dropPosition == CONTEXT_MENU_CORE_DROP_POSITION_UP)   // down Arrow
445         {
446                 // Check touch position
447                 //  - Check left margin
448                 if (anchorPosition.x <= leftMargin + arrowRect.width)
449                 {
450                         anchorPosition.x = leftMargin + arrowRect.width;
451                 }
452                 //  - check right margin
453                 if (anchorPosition.x >= (rightMargin - arrowRect.width))
454                 {
455                         anchorPosition.x = rightMargin - arrowRect.width;
456                 }
457                 //  - check top margin
458                 if (anchorPosition.y <= topMargin)
459                 {
460                         anchorPosition.y = topMargin + bodyRect.height;
461                 }
462                 //  - check bottom margin
463                 if (anchorPosition.y >= bottomMargin)
464                 {
465                         anchorPosition.y = bottomMargin;
466                 }
467
468                 // Set body position x
469                 bodyRect.x = anchorPosition.x - (bodyRect.width / 2);
470                 //  - Check left margin
471                 if (bodyRect.x <= leftMargin)
472                 {
473                         bodyRect.x = leftMargin;
474                 }
475                 //  - check right margin
476                 if ((bodyRect.x + bodyRect.width) >= rightMargin)
477                 {
478                         bodyRect.x = rightMargin - bodyRect.width;
479                 }
480                 // Set body position y
481                 bodyRect.y = anchorPosition.y - arrowRect.height - bodyRect.height;
482                 //  - check top margin
483                 if (bodyRect.y <= topMargin)
484                 {
485                         bodyRect.y = topMargin;
486                 }
487
488                 windowRect.x = bodyRect.x;
489                 windowRect.y = bodyRect.y;
490                 windowRect.width = bodyRect.width;
491                 windowRect.height = bodyRect.height + arrowRect.height;
492
493                 bodyRect.x = 0;
494                 bodyRect.y = arrowMargin;
495
496                 // Set arrow position
497                 arrowRect.x = anchorPosition.x - (arrowRect.width / 2) - windowRect.x;
498                 arrowRect.y = bodyRect.height;
499         }
500         else if (dropPosition == CONTEXT_MENU_CORE_DROP_POSITION_DOWN)    // up Arrow
501         {
502                 // Check touch position
503                 //  - Check left margin
504                 if (anchorPosition.x <= leftMargin + arrowRect.width)
505                 {
506                         anchorPosition.x = leftMargin + arrowRect.width;
507                 }
508                 //  - check right margin
509                 if (anchorPosition.x >= (rightMargin - arrowRect.width))
510                 {
511                         anchorPosition.x = rightMargin - arrowRect.width;
512                 }
513                 //  - check top margin
514                 if (anchorPosition.y <= topMargin)
515                 {
516                         anchorPosition.y = topMargin;
517                 }
518                 //  - check bottom margin
519                 if (anchorPosition.y >= bottomMargin)
520                 {
521                         anchorPosition.y = bottomMargin;
522                 }
523
524                 // Set body position x
525                 bodyRect.x = anchorPosition.x - (bodyRect.width / 2);
526                 //  - Check left margin
527                 if (bodyRect.x <= leftMargin)
528                 {
529                         bodyRect.x = leftMargin;
530                 }
531                 //  - check right margin
532                 if ((bodyRect.x + bodyRect.width) >= rightMargin)
533                 {
534                         bodyRect.x = rightMargin - bodyRect.width;
535                 }
536                 // Set body position y
537                 bodyRect.y = anchorPosition.y + arrowRect.height;
538                 //  - Check bottom margin
539                 if ((bodyRect.y + bodyRect.height) >= bottomMargin)
540                 {
541                         bodyRect.y = bottomMargin - bodyRect.height;
542                 }
543
544                 windowRect.x = bodyRect.x;
545                 windowRect.y = bodyRect.y - arrowRect.height;
546                 windowRect.width = bodyRect.width;
547                 windowRect.height = bodyRect.height + arrowRect.height;
548
549                 bodyRect.x = 0;
550                 bodyRect.y = arrowRect.height - arrowMargin;
551
552                 // Set arrow position
553                 arrowRect.x = anchorPosition.x - (arrowRect.width / 2) - windowRect.x;
554                 arrowRect.y = 0;
555         }
556         else if (dropPosition == CONTEXT_MENU_CORE_DROP_POSITION_LEFT)    // right Arrow
557         {
558                 // Check touch position
559                 //  - Check left margin
560                 if (anchorPosition.x <= leftMargin)
561                 {
562                         anchorPosition.x = leftMargin + bodyRect.width;
563                 }
564                 //  - check right margin
565                 if (anchorPosition.x >= rightMargin)
566                 {
567                         anchorPosition.x = rightMargin;
568                 }
569                 //  - Check top margin
570                 if (anchorPosition.y <= topMargin + arrowRect.height)
571                 {
572                         anchorPosition.y = topMargin + arrowRect.height;
573                 }
574                 //  - check bottom margin
575                 if (anchorPosition.y >= (bottomMargin - arrowRect.height))
576                 {
577                         anchorPosition.y = bottomMargin - arrowRect.height;
578                 }
579
580                 // Set body position x
581                 bodyRect.x = anchorPosition.x - arrowRect.width - bodyRect.width;
582                 //  - Check left margin
583                 if (bodyRect.x <= leftMargin)
584                 {
585                         bodyRect.x = leftMargin;
586                 }
587                 //  - check right margin
588                 if ((bodyRect.x + bodyRect.width + arrowRect.width) >= rightMargin)
589                 {
590                         bodyRect.x = rightMargin - bodyRect.width - arrowRect.width;
591                 }
592
593                 // Set body position y
594                 bodyRect.y = anchorPosition.y - (bodyRect.height / 2);
595                 // - check top margin
596                 if (bodyRect.y <= topMargin)
597                 {
598                         bodyRect.y = topMargin;
599                 }
600                 // - check bottom margin
601                 if ((bodyRect.y + bodyRect.height) >= bottomMargin)
602                 {
603                         bodyRect.y = bottomMargin - bodyRect.height;
604                 }
605
606                 windowRect.x = bodyRect.x;
607                 windowRect.y = bodyRect.y;
608                 windowRect.width = bodyRect.width + arrowRect.width;
609                 windowRect.height = bodyRect.height;
610
611                 bodyRect.x = arrowMargin;
612                 bodyRect.y = 0;
613
614                 // Set arrow position
615                 arrowRect.x = bodyRect.width;
616                 arrowRect.y = anchorPosition.y - (arrowRect.height / 2) - windowRect.y;
617         }
618         else    // left Arrow
619         {
620                 // Check touch position
621                 //  - Check top margin
622                 if (anchorPosition.x <= leftMargin)
623                 {
624                         anchorPosition.x = leftMargin;
625                 }
626                 //  - check right margin
627                 if (anchorPosition.x >= rightMargin)
628                 {
629                         anchorPosition.x = rightMargin - bodyRect.width;
630                 }
631                 //  - Check top margin
632                 if (anchorPosition.y <= topMargin + arrowRect.height)
633                 {
634                         anchorPosition.y = topMargin + arrowRect.height;
635                 }
636                 //  - check bottom margin
637                 if (anchorPosition.y >= (bottomMargin - arrowRect.height))
638                 {
639                         anchorPosition.y = bottomMargin - arrowRect.height;
640                 }
641
642                 // Set body position x
643                 bodyRect.x = anchorPosition.x + arrowRect.width;
644                 //  - Check left margin
645                 if (bodyRect.x <= leftMargin)
646                 {
647                         bodyRect.x = leftMargin;
648                 }
649                 //  - check right margin
650                 if ((bodyRect.x + bodyRect.width) >= rightMargin)
651                 {
652                         bodyRect.x = rightMargin - bodyRect.width;
653                 }
654                 // Set body position y
655                 bodyRect.y = anchorPosition.y - (bodyRect.height / 2);
656                 // - check top margin
657                 if (bodyRect.y <= topMargin)
658                 {
659                         bodyRect.y = topMargin;
660                 }
661                 // - check bottom margin
662                 if ((bodyRect.y + bodyRect.height) >= bottomMargin)
663                 {
664                         bodyRect.y = bottomMargin - bodyRect.height;
665                 }
666
667                 windowRect.x = bodyRect.x + arrowRect.width;
668                 windowRect.y = bodyRect.y;
669                 windowRect.width = bodyRect.width + arrowRect.width;
670                 windowRect.height = bodyRect.height;
671
672                 bodyRect.x = arrowRect.width - arrowMargin;
673                 bodyRect.y = 0;
674
675                 // Set arrow position
676                 arrowRect.x = 0;
677                 arrowRect.y = anchorPosition.y - (arrowRect.height / 2) - windowRect.y;
678         }
679
680         __pContextMenu->SetBodyRect(bodyRect);
681         __pContextMenu->SetArrowRect(arrowRect);
682         __pContextMenu->SetWindowRect(windowRect);
683
684         // _ScrollPanel API call sequence: SetBounds() -> SetScrollAreaBounds()
685         // _Scroll visual interaction if Bounds < ScrollAreaBounds
686         if (__pContextMenu->IsVisible()) {
687                 __pContextMenu->GetScrollPanel()->SetBounds(Rectangle(bodyRect.x + bodyLeftMargin, bodyRect.y + bodyTopMargin, __layoutSize.width, __layoutSize.height));
688                 int itemCount = __pModel->GetItemCount();
689                 int itemHeight = __itemHeight + __dividerHeight;
690                 int layoutClientHeight = itemCount * itemHeight - __dividerHeight;
691                 __pContextMenu->GetScrollPanel()->SetClientAreaHeight(layoutClientHeight);
692         }
693
694         __pContextMenu->SetMovable(true);     // To do Modify a enabling
695         __pContextMenu->SetResizable(true);   // To do Modify a enabling
696         __pContextMenu->SetMinimumSize(Dimension(0, 0));    // To do Modify
697         __pContextMenu->SetMaximumSize(screen);             // To do Modify
698         __pContextMenu->SetBounds(windowRect);
699         __pContextMenu->SetMovable(false);    // To do Modify a enabling
700         __pContextMenu->SetResizable(false);  // To do Modify a enabling
701
702         return E_SUCCESS;
703 }
704
705 void
706 _ContextMenuListPresenter::AdjustItemLayout(void)
707 {
708         Dimension layoutSize(0, 0);
709
710         int itemCount = __pModel->GetItemCount();
711         if (itemCount <= 0)
712         {
713                 __layoutSize.width = __itemWidth;
714                 __layoutSize.height = __itemHeight;
715                 return;
716         }
717
718         layoutSize = AdjustItemLayoutStyle();
719
720         Dimension screen = _ControlManager::GetInstance()->GetScreenSize();
721         if (__pContextMenu->GetLayout() == _CONTROL_ORIENTATION_LANDSCAPE)
722         {
723                 screen.SetSize(screen.height, screen.width);
724         }
725
726         int maxHeight = screen.height - __screenTopMargin - __screenBottomMargin - __arrowHeight;
727         if (layoutSize.height > maxHeight)
728         {
729                 layoutSize.height = maxHeight;
730         }
731
732         __layoutSize = layoutSize;
733 }
734
735
736 Tizen::Graphics::Dimension
737 _ContextMenuListPresenter::AdjustItemLayoutStyle(void)
738 {
739         int itemMaxCount = CalculateShowItemCount();
740
741         int itemCount = __pModel->GetItemCount();
742         int itemHeight = __itemHeight + __dividerHeight;
743
744         Dimension layoutSize(__itemWidth, 0);
745
746         int layoutClientHeight = itemCount * itemHeight - __dividerHeight;
747         int layoutMaxHeight = itemMaxCount * itemHeight - __dividerHeight;
748         if (layoutClientHeight > layoutMaxHeight)
749         {
750                 __scrollEnable = true;
751                 layoutSize.height = layoutMaxHeight;
752         }
753         else
754         {
755                 __scrollEnable = false;
756                 layoutSize.height = layoutClientHeight;
757         }
758
759         return layoutSize;
760 }
761
762 void
763 _ContextMenuListPresenter::AdjustItemPosition(void)
764 {
765         int itemCount = __pModel->GetItemCount();
766         if (itemCount <= 0)
767         {
768                 return;
769         }
770
771         int itemHeight = __itemHeight + __dividerHeight;
772         int drawItemY = 0;
773
774         int x = __pContextMenu->GetBodyRect().x + __leftMargin;
775         int y = __pContextMenu->GetBodyRect().y +  __topMargin;
776
777         _ContextMenuItem* pItem = null;
778
779         for (int i = 0; i < itemCount; i++)
780         {
781                 pItem = __pModel->GetItem(i);
782
783                 if (pItem == null)
784                 {
785                         break;
786                 }
787
788                 Rectangle drawRect(x, drawItemY + y, __itemWidth, itemHeight);
789
790                 pItem->SetDrawRect(drawRect);
791                 pItem->SetDivider(true);
792                 pItem->SetParentScrollEnable(__scrollEnable);
793                 pItem->SetBounds(Rectangle(0, drawItemY, drawRect.width, drawRect.height));
794
795                 if (pItem->HasParent() == false)
796                 {
797                         __pContextMenu->GetScrollPanel()->AttachChild(*pItem);
798                 }
799
800                 drawItemY += itemHeight;
801         }
802 }
803
804 int
805 _ContextMenuListPresenter::GetItemIndexFromPosition(const Tizen::Graphics::Point& point) const
806 {
807         int index = -1;
808         int itemCount = __pModel->GetItemCount();
809
810         if (itemCount < 0)
811         {
812                 return -1;
813         }
814
815         _ContextMenuItem* pItem = null;
816
817         int scrollPosition = __pContextMenu->GetScrollPanel()->GetScrollPosition();
818         Point position(point.x, point.y + scrollPosition);
819
820         for (int i = 0; i < itemCount; i++)
821         {
822                 pItem = __pModel->GetItem(i);
823
824                 if (pItem == null)
825                 {
826                         break;
827                 }
828
829                 Rectangle drawRect = pItem->GetDrawRect();
830
831                 if (drawRect.Contains(position) == true)
832                 {
833                         index = i;
834                         break;
835                 }
836         }
837
838         return index;
839 }
840
841
842 result
843 _ContextMenuListPresenter::Draw(void)
844 {
845         result r = E_SUCCESS;
846
847         Canvas* pCanvas = __pContextMenu->GetCanvasN();
848         SysTryReturn(NID_UI_CTRL, pCanvas != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "The memory is insufficient.");
849
850         // Clear canvas for drawing area of the ContextMenu.
851         pCanvas->SetBackgroundColor(Color(0, 0, 0, 0));
852         Tizen::Graphics::Rectangle bounds(__pContextMenu->GetWindowRect());
853         pCanvas->Clear(Tizen::Graphics::Rectangle(0, 0, bounds.width, bounds.height));
854
855         r = DrawBackground(pCanvas);
856         SysTryReturn(NID_UI_CTRL, r == E_SUCCESS, r, r, "Failed to draw background.");
857
858         r = DrawArrow(pCanvas);
859         SysTryReturn(NID_UI_CTRL, r == E_SUCCESS, r, r, "Failed to draw arrow.");
860
861         delete pCanvas;
862
863         return r;
864 }
865
866 result
867 _ContextMenuListPresenter::DrawBackground(Canvas* pCanvas)
868 {
869         SysTryReturn(NID_UI_CTRL, pCanvas != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
870
871         result r = E_SUCCESS;
872
873         Tizen::Graphics::Rectangle bodyRect = __pContextMenu->GetBodyRect();
874
875         const Bitmap* pBackgroundNormalBitmap = __pContextMenu->GetBackgroundNormalBitmap();
876         const Bitmap* pBackgroundEffectBitmap = __pContextMenu->GetBackgroundEffectBitmap();
877
878         if (pBackgroundNormalBitmap == null && pBackgroundEffectBitmap == null)
879         {
880                 pCanvas->SetForegroundColor(__pContextMenu->GetColor());
881                 pCanvas->DrawRectangle(bodyRect);
882         }
883         else
884         {
885                 if (pBackgroundNormalBitmap != null)
886                 {
887                         r = pCanvas->DrawNinePatchedBitmap(bodyRect, *pBackgroundNormalBitmap);
888                 }
889
890                 if (pBackgroundEffectBitmap != null)
891                 {
892                         r = pCanvas->DrawNinePatchedBitmap(bodyRect, *pBackgroundEffectBitmap);
893                 }
894         }
895
896         return r;
897 }
898
899
900 result
901 _ContextMenuListPresenter::DrawArrow(Canvas* pCanvas)
902 {
903         SysTryReturn(NID_UI_CTRL, pCanvas != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
904
905         result r = E_SUCCESS;
906         Tizen::Graphics::Rectangle arrowRect = __pContextMenu->GetArrowRect();
907         ContextMenuCoreDropPosition dropPosition = __pContextMenu->GetDropPosition();
908
909         const Bitmap* pArrowNormalBitmap = __pContextMenu->GetArrowNormalBitmap(dropPosition);
910         const Bitmap* pEffectArrowBitmap = __pContextMenu->GetArrowEffectBitmap(dropPosition);
911
912         if (pArrowNormalBitmap != null)
913         {
914                 r = DrawBitmap(*pCanvas, arrowRect, *pArrowNormalBitmap);
915         }
916
917         if (pEffectArrowBitmap != null)
918         {
919                 r = DrawBitmap(*pCanvas, arrowRect, *pEffectArrowBitmap);
920         }
921
922         return r;
923 }
924
925 _UiTouchEventDelivery
926 _ContextMenuListPresenter::OnPreviewTouchPressed(const _Control& source, const _TouchInfo& touchinfo)
927 {
928         return _UI_TOUCH_EVENT_DELIVERY_FORCED_YES;
929 }
930
931 bool
932 _ContextMenuListPresenter::OnTouchPressed(const _Control& source, const _TouchInfo& touchinfo)
933 {
934         Rectangle bodyRect = __pContextMenu->GetBodyRect();
935         if (!bodyRect.Contains(touchinfo.GetCurrentPosition()))
936         {
937                 __selectedIndex = -1;
938                 __touchOutRect = true;
939                 return true;
940         }
941
942         __selectedIndex = GetItemIndexFromPosition(touchinfo.GetCurrentPosition());
943         __touchOutRect = false;
944         return true;
945 }
946
947 _UiTouchEventDelivery
948 _ContextMenuListPresenter::OnPreviewTouchReleased(const _Control& source, const _TouchInfo& touchinfo)
949 {
950         return _UI_TOUCH_EVENT_DELIVERY_FORCED_YES;
951 }
952
953 bool
954 _ContextMenuListPresenter::OnTouchReleased(const _Control& source, const _TouchInfo& touchinfo)
955 {
956         if (__touchOutRect)
957         {
958                 Rectangle bodyRect = __pContextMenu->GetBodyRect();
959                 if (!bodyRect.Contains(touchinfo.GetCurrentPosition()))
960                 {
961                         __pContextMenu->SetVisibleState(false);
962                 }
963         }
964
965         int currentSelectedIndex = GetItemIndexFromPosition(touchinfo.GetCurrentPosition());
966         if (__selectedIndex != -1 && (__selectedIndex == currentSelectedIndex))
967         {
968                 _ContextMenuItem* pItem = null;
969                 pItem = __pModel->GetItem(__selectedIndex);
970
971                 __selectedIndex = -1;
972                 __pContextMenu->SetVisibleState(false);
973
974                 int actionId = pItem->GetActionId();
975
976                 _ActionEvent* pActionEvent = __pContextMenu->GetActionEvent();
977                 if (pActionEvent == null)
978                 {
979                         return true;
980                 }
981
982                 IEventArg* pEventArg = _ActionEvent::CreateActionEventArgN(actionId);
983                 if (pEventArg == null)
984                 {
985                         return true;
986                 }
987
988                 pActionEvent->Fire(*pEventArg);
989         }
990
991         return true;
992 }
993
994 _UiTouchEventDelivery
995 _ContextMenuListPresenter::OnPreviewTouchMoved(const _Control& source, const _TouchInfo& touchinfo)
996 {
997         if (__scrollEnable)
998         {
999                 __selectedIndex = -1;
1000         }
1001
1002         return _UI_TOUCH_EVENT_DELIVERY_FORCED_YES;
1003 }
1004
1005 bool
1006 _ContextMenuListPresenter::OnTouchMoved(const _Control& source, const _TouchInfo& touchinfo)
1007 {
1008         if (__scrollEnable)
1009         {
1010                 __selectedIndex = -1;
1011         }
1012
1013         return true;
1014 }
1015
1016 bool
1017 _ContextMenuListPresenter::OnTouchCanceled(const _Control& source, const _TouchInfo& touchinfo)
1018 {
1019         __pModel->ResetAllItem();
1020
1021         return true;
1022 }
1023
1024 void
1025 _ContextMenuListPresenter::OnFontChanged(Tizen::Graphics::Font* pFont)
1026 {
1027         __pFont = pFont;
1028         String fontName = __pContextMenu->GetFont();
1029
1030         int itemCount = __pModel->GetItemCount();
1031         for (int i = 0; i < itemCount; i++)
1032         {
1033                 _ContextMenuItem* pItem = __pModel->GetItem(i);
1034                 if (pItem != null)
1035                 {
1036                         pItem->SetFont(fontName);
1037                 }
1038         }
1039 }
1040
1041 void
1042 _ContextMenuListPresenter::OnFontInfoRequested(unsigned long& style, int& size)
1043 {
1044         style = FONT_STYLE_PLAIN;
1045         size = __itemFontSize;
1046 }
1047
1048 void
1049 _ContextMenuListPresenter::SetAllAccessibilityElement(void)
1050 {
1051         _AccessibilityContainer* pContainer = __pContextMenu->GetAccessibilityContainer();
1052         if (pContainer != null)
1053         {
1054                 int itemCount = __pModel->GetItemCount();
1055                 for (int i = 0; i < itemCount; i++)
1056                 {
1057                         _ContextMenuItem* pItem = __pModel->GetItem(i);
1058                         _AccessibilityElement* pElement = new (std::nothrow) _AccessibilityElement(true);
1059                         if (pItem != null && pElement != null)
1060                         {
1061                                 pElement->SetLabel(pItem->GetText());
1062 //                              pElement->SetTrait(ACCESSIBILITY_TRAITS_CONTEXTMENU);
1063                                 pElement->SetTrait(ACCESSIBILITY_TRAITS_LIST);  // not yet
1064                                 pElement->SetBounds(pItem->GetDrawRect());
1065                                 if (i == 0)
1066                                 {
1067                                         pElement->SetHint(L"The first of Contextual popup");
1068                                 }
1069                                 else if(i == itemCount - 1)
1070                                 {
1071                                         pElement->SetHint(L"The last of Contextual popup");
1072                                 }
1073                                 pContainer->AddElement(*pElement);
1074                                 __pContextMenu->AddAccessibilityElement(*pElement);
1075                         }
1076                         else
1077                         {
1078                                 delete pElement;
1079                         }
1080                 }
1081         }
1082
1083 }
1084
1085 _ContextMenuItemInfo
1086 _ContextMenuListPresenter::GetItemFromPosition(const Point& position)
1087 {
1088         _ContextMenuItemInfo itemInfo;
1089         int index = GetItemIndexFromPosition(position);
1090         itemInfo.pContextMenuItem = __pModel->GetItem(index);
1091
1092         itemInfo.bListItem = false;
1093         itemInfo.pListItem = null;
1094         return itemInfo;
1095 }
1096
1097 _ContextMenuItemInfo
1098 _ContextMenuListPresenter::FindItem(int index)
1099 {
1100         _ContextMenuItemInfo itemInfo;
1101         itemInfo.bListItem = false;
1102         itemInfo.pListItem = null;
1103         itemInfo.pContextMenuItem = __pModel->GetItem(index);
1104         return itemInfo;
1105 }
1106
1107 result
1108 _ContextMenuListPresenter::SetTopDrawnItemIndex(int index)
1109 {
1110         return E_SUCCESS;
1111 }
1112
1113 result
1114 _ContextMenuListPresenter::DrawBitmap(Tizen::Graphics::Canvas& canvas, const Tizen::Graphics::Rectangle& bounds, const Tizen::Graphics::Bitmap& bitmap)
1115 {
1116         result r = E_SUCCESS;
1117         if (bitmap.IsNinePatchedBitmap())
1118         {
1119                 r = canvas.DrawNinePatchedBitmap(bounds, bitmap);
1120                 SysTryReturnResult(NID_UI_CTRL, r == E_SUCCESS, r, "Fail to draw ninepatched bitmap.")
1121         }
1122         else
1123         {
1124                 r = canvas.DrawBitmap(bounds, bitmap);
1125                 SysTryReturnResult(NID_UI_CTRL, r == E_SUCCESS, r, "Fail to draw bitmap.")
1126         }
1127
1128         return r;
1129 }
1130
1131 }}} // Tizen::Ui: Control