modify Klockwork bug
[platform/framework/native/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 Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0/
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 /**
18  * @file                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_BitmapImpl.h>
25 #include <FGrp_CanvasImpl.h>
26 #include <FGrp_TextTextSimple.h>
27 #include "FUi_AccessibilityContainer.h"
28 #include "FUi_AccessibilityElement.h"
29 #include "FUi_CoordinateSystemUtils.h"
30 #include "FUi_Math.h"
31 #include "FUi_ResourceManager.h"
32 #include "FUiCtrl_ActionEvent.h"
33 #include "FUiCtrl_IActionEventListener.h"
34
35 #include "FUiCtrl_ContextMenuListPresenter.h"
36
37 using namespace Tizen::Graphics;
38 using namespace Tizen::Ui;
39 using namespace Tizen::Base;
40 using namespace Tizen::Base::Runtime;
41 using namespace Tizen::Graphics::_Text;
42
43 namespace {
44 static const float TOUCH_PRESS_THRESHOLD_INSENSITIVE = 0.16f;
45 static const int CONTEXT_MENU_LIST_ELEMENT_TEXT = 0;
46 static const int CONTEXT_MENU_LIST_ELEMENT_BITMAP = 1;
47 }
48
49 namespace Tizen { namespace Ui { namespace Controls
50 {
51
52 _ContextMenuListPresenter::_ContextMenuListPresenter(_ContextMenu* pContextMenu)
53         : __pContextMenu(pContextMenu)
54         , __pModel(null)
55         , __pFont(null)
56         , __layoutSize(FloatDimension(0.0f, 0.0f))
57         , __touchOutRect(false)
58         , __selectedIndex(-1)
59         , __scrollEnable(false)
60         , __maxWidth(0.0f)
61         , __minWidth(0.0f)
62         , __topMargin(0.0f)
63         , __bottomMargin(0.0f)
64         , __leftMargin(0.0f)
65         , __rightMargin(0.0f)
66         , __screenTopMargin(0.0f)
67         , __screenBottomMargin(0.0f)
68         , __screenLeftMargin(0.0f)
69         , __screenRightMargin(0.0f)
70         , __arrowTopMargin(0.0f)
71         , __arrowBottomMargin(0.0f)
72         , __arrowRightMargin(0.0f)
73         , __arrowLeftMargin(0.0f)
74         , __arrowWidth(0.0f)
75         , __arrowHeight(0.0f)
76         , __itemWidth(0.0f)
77         , __itemMinWidth(0.0f)
78         , __itemHeight(0.0f)
79         , __itemMaxWidth(0.0f)
80         , __itemGap(0.0f)
81         , __itemBitmapWidth(0.0f)
82         , __itemBitmapHeight(0.0f)
83         , __itemFontSize(0.0f)
84         , __dividerHeight(0.0f)
85         , __anchorPopupOverlap(0.0f)
86         , __enterKeyPressed(false)
87         , __backKeyPressed(false)
88         , __focusedIndex(-1)
89 {
90
91 }
92
93 _ContextMenuListPresenter::~_ContextMenuListPresenter(void)
94 {
95         __pContextMenu = null;
96
97         delete __pModel;
98         __pModel = null;
99
100         __pFont = null;
101
102 }
103
104 result
105 _ContextMenuListPresenter::Install(void)
106 {
107         result r = E_SUCCESS;
108
109         LoadShape();
110
111         __pModel = new (std::nothrow) _ContextMenuModel;
112         SysTryReturnResult(NID_UI_CTRL, __pModel != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
113
114         r = __pModel->Construct();
115         SysTryCatch(NID_UI_CTRL, r == E_SUCCESS, r = GetLastResult(), GetLastResult(), "[%s] Memory allocation failed.", GetErrorMessage(GetLastResult()));
116
117         __pFont = __pContextMenu->GetFallbackFont();
118         r = GetLastResult();
119         SysTryCatch(NID_UI_CTRL, (__pFont != null), , r, "[%s] Propagating.", GetErrorMessage(r));
120
121         return r;
122
123 CATCH:
124         delete __pModel;
125         __pModel = null;
126
127         __pFont = null;
128
129         return r;
130 }
131
132
133 void
134 _ContextMenuListPresenter::LoadShape(void)
135 {
136         GET_SHAPE_CONFIG(CONTEXTMENU::LIST_MIN_WIDTH, _CONTROL_ORIENTATION_PORTRAIT, __itemMinWidth);
137         GET_SHAPE_CONFIG(CONTEXTMENU::LIST_MAX_WIDTH, _CONTROL_ORIENTATION_PORTRAIT, __itemMaxWidth);
138         GET_SHAPE_CONFIG(CONTEXTMENU::LIST_ITEM_HEIGHT, _CONTROL_ORIENTATION_PORTRAIT, __itemHeight);
139         GET_SHAPE_CONFIG(CONTEXTMENU::LIST_ITEM_GAP, _CONTROL_ORIENTATION_PORTRAIT, __itemGap);
140
141         GET_SHAPE_CONFIG(CONTEXTMENU::LIST_TOP_MARGIN, _CONTROL_ORIENTATION_PORTRAIT, __topMargin);
142         GET_SHAPE_CONFIG(CONTEXTMENU::LIST_BOTTOM_MARGIN, _CONTROL_ORIENTATION_PORTRAIT, __bottomMargin);
143         GET_SHAPE_CONFIG(CONTEXTMENU::LIST_LEFT_MARGIN, _CONTROL_ORIENTATION_PORTRAIT, __leftMargin);
144         GET_SHAPE_CONFIG(CONTEXTMENU::LIST_RIGHT_MARGIN, _CONTROL_ORIENTATION_PORTRAIT, __rightMargin);
145
146         GET_SHAPE_CONFIG(CONTEXTMENU::SCREEN_TOP_MARGIN, _CONTROL_ORIENTATION_PORTRAIT, __screenTopMargin);
147         GET_SHAPE_CONFIG(CONTEXTMENU::SCREEN_BOTTOM_MARGIN, _CONTROL_ORIENTATION_PORTRAIT, __screenBottomMargin);
148         GET_SHAPE_CONFIG(CONTEXTMENU::SCREEN_LEFT_MARGIN, _CONTROL_ORIENTATION_PORTRAIT, __screenLeftMargin);
149         GET_SHAPE_CONFIG(CONTEXTMENU::SCREEN_RIGHT_MARGIN, _CONTROL_ORIENTATION_PORTRAIT, __screenRightMargin);
150         GET_SHAPE_CONFIG(CONTEXTMENU::ANCHOR_TOP_MARGIN, _CONTROL_ORIENTATION_PORTRAIT, __arrowTopMargin);
151         GET_SHAPE_CONFIG(CONTEXTMENU::ANCHOR_BOTTOM_MARGIN, _CONTROL_ORIENTATION_PORTRAIT, __arrowBottomMargin);
152         GET_SHAPE_CONFIG(CONTEXTMENU::ANCHOR_LEFT_MARGIN, _CONTROL_ORIENTATION_PORTRAIT, __arrowLeftMargin);
153         GET_SHAPE_CONFIG(CONTEXTMENU::ANCHOR_RIGHT_MARGIN, _CONTROL_ORIENTATION_PORTRAIT, __arrowRightMargin);
154         GET_SHAPE_CONFIG(CONTEXTMENU::ANCHOR_WIDTH, _CONTROL_ORIENTATION_PORTRAIT, __arrowWidth);
155         GET_SHAPE_CONFIG(CONTEXTMENU::ANCHOR_HEIGHT, _CONTROL_ORIENTATION_PORTRAIT, __arrowHeight);
156         GET_SHAPE_CONFIG(CONTEXTMENU::LIST_ICON_WIDTH, _CONTROL_ORIENTATION_PORTRAIT, __itemBitmapWidth);
157         GET_SHAPE_CONFIG(CONTEXTMENU::LIST_ICON_HEIGHT, _CONTROL_ORIENTATION_PORTRAIT, __itemBitmapHeight);
158
159         GET_SHAPE_CONFIG(CONTEXTMENU::LIST_ITEM_FONT_SIZE, _CONTROL_ORIENTATION_PORTRAIT, __itemFontSize);
160         GET_SHAPE_CONFIG(CONTEXTMENU::LIST_DIVIDER_HEIGHT, _CONTROL_ORIENTATION_PORTRAIT, __dividerHeight);
161         GET_SHAPE_CONFIG(CONTEXTMENU::ANCHOR_POPUP_OVERLAP, _CONTROL_ORIENTATION_PORTRAIT, __anchorPopupOverlap);
162
163         __itemWidth = __itemMinWidth;
164 }
165
166 _ContextMenuItem*
167 _ContextMenuListPresenter::CreateItemN(const Base::String& text, int actionId, const Bitmap* pNormalBitmap, const Bitmap* pPressedBitmap, const Bitmap* pHighlightedBitmap)
168 {
169         _ContextMenuItem* pItem = _ContextMenuItem::CreateContextMenuItemN();
170     SysTryReturn(NID_UI_CTRL, pItem != null, null, GetLastResult(), "[%s] pItem must not be null.", GetErrorMessage(GetLastResult()));
171
172         ContextMenuItemDrawingType itemType = CONTEXT_MENU_ITEM_DRAWING_TYPE_TEXT;
173         _Label* pLabel = null;
174         result r = E_SUCCESS;
175
176         if (pNormalBitmap != null)
177         {
178                 r = pItem->SetBitmap(CONTEXT_MENU_ITEM_DRAWING_STATUS_NORMAL, pNormalBitmap);
179                 if (r != E_SUCCESS)
180                 {
181                         delete pItem;
182                         return null;
183                 }
184
185                 // add bitmap label
186                 pLabel = _Label::CreateLabelN();
187                 pLabel->SetBackgroundBitmap(*pNormalBitmap);
188                 pLabel->SetBackgroundColor(Color(0, 0, 0, 0));
189
190                 int bitmapY = (__itemHeight - __itemBitmapHeight) / 2;
191                 pLabel->SetBounds(FloatRectangle(__leftMargin, bitmapY,  __itemBitmapWidth, __itemBitmapHeight));
192                 pLabel->SetTouchPressThreshold(TOUCH_PRESS_THRESHOLD_INSENSITIVE);
193                 pItem->AttachChild(*pLabel);
194                 _AccessibilityContainer* pContainer = pLabel->GetAccessibilityContainer();
195                 if (pContainer)
196                 {
197                         pContainer->Activate(false);
198                 }
199                 pItem->SetBitmapLabel(pLabel);
200
201                 itemType = CONTEXT_MENU_ITEM_DRAWING_TYPE_BITMAP;
202         }
203
204         if (pPressedBitmap != null)
205         {
206                 r = pItem->SetBitmap(CONTEXT_MENU_ITEM_DRAWING_STATUS_PRESSED, pPressedBitmap);
207                 if (r != E_SUCCESS)
208                 {
209                         delete pItem;
210                         return null;
211                 }
212         }
213
214         pItem->SetType(itemType);
215         pItem->SetActionId(actionId);
216
217         pItem->SetTextSize(__itemFontSize);
218         r = pItem->SetText(text);
219         if (r != E_SUCCESS)
220         {
221                 delete pItem;
222                 return null;
223         }
224
225         FloatDimension textArea(0.0f, 0.0f);
226         FloatDimension itemSize(0.0f, 0.0f);
227
228         CalculateItemSize(text, itemType, textArea, itemSize);
229
230         pItem->SetSize(itemSize);
231
232         float textLabelX = 0.0f;
233         if (itemType == CONTEXT_MENU_ITEM_DRAWING_TYPE_BITMAP)
234         {
235                 textLabelX = __itemGap + __itemBitmapWidth;
236         }
237
238         // add text label
239         pLabel = _Label::CreateLabelN();
240         pLabel->SetText(text);
241         ContextMenuCoreItemStatus itemStatus = CONTEXT_MENU_CORE_ITEM_STATUS_NORMAL;
242         pLabel->SetTextColor(__pContextMenu->GetTextColor(itemStatus));
243         pLabel->SetBackgroundColor(Color(0, 0, 0, 0));
244
245         itemSize = pItem->GetSize();
246         pLabel->SetBounds(FloatRectangle(textLabelX, (itemSize.height - textArea.height) / 2.0f, textArea.width, textArea.height));
247         pLabel->SetTextVerticalAlignment(ALIGNMENT_MIDDLE);
248         pLabel->SetTextHorizontalAlignment(ALIGNMENT_CENTER);
249         pLabel->SetTextConfig(__itemFontSize, LABEL_TEXT_STYLE_NORMAL);
250
251         pLabel->SetTouchPressThreshold(TOUCH_PRESS_THRESHOLD_INSENSITIVE);
252         pItem->AttachChild(*pLabel);
253         _AccessibilityContainer* pContainer = pLabel->GetAccessibilityContainer();
254         if (pContainer)
255         {
256                 pContainer->Activate(false);
257         }
258         pItem->SetTextLabel(pLabel);
259
260         __itemWidth = __itemWidth < itemSize.width ? itemSize.width : __itemWidth;
261
262         pItem->SetTouchPressThreshold(TOUCH_PRESS_THRESHOLD_INSENSITIVE);
263         return pItem;
264 }
265
266 void
267 _ContextMenuListPresenter::CalculateItemSize(const String &text, ContextMenuItemDrawingType itemType, FloatDimension &textArea, FloatDimension &itemSize)
268 {
269         float bitmapWidth = (itemType == CONTEXT_MENU_ITEM_DRAWING_TYPE_BITMAP) ? __itemBitmapWidth : 0.0f;
270
271         __pFont->GetTextExtent(text, text.GetLength(), textArea);
272         float labelTopMargin = 0.0f;
273         float iconGap = 0.0f;
274         float textGap = 0.0f;
275         GET_SHAPE_CONFIG(LABEL::TOP_MARGIN,  _CONTROL_ORIENTATION_PORTRAIT, labelTopMargin);
276         GET_SHAPE_CONFIG(CONTEXTMENU::LIST_TEXT_GAP, _CONTROL_ORIENTATION_PORTRAIT, textGap);
277         iconGap = __itemGap;
278
279         if (itemType == CONTEXT_MENU_ITEM_DRAWING_TYPE_BITMAP)
280         {
281                 textArea.width  +=  2.0 * iconGap;
282                 itemSize.width =  textArea.width + bitmapWidth + textGap;
283         }
284         else
285         {
286                 textArea.width  += 2.0f * textGap;
287                 itemSize.width = textArea.width;
288         }
289
290         textArea.height += 2.0f * labelTopMargin;
291         itemSize.height = __itemHeight + (__dividerHeight * 2.0f);
292
293         itemSize.width = itemSize.width < __itemMinWidth ? __itemMinWidth : itemSize.width;
294
295         if (itemSize.width > __itemMaxWidth)
296         {
297                 textArea.width -= itemSize.width - __itemMaxWidth;
298                 itemSize.width = __itemMaxWidth;
299         }
300
301         return;
302 }
303
304 result
305 _ContextMenuListPresenter::AddItem(const Base::String& text, int actionId, const Bitmap* pNormalBitmap,
306                                                                    const Bitmap* pPressedBitmap,
307                                                                    const Bitmap* pHighlightedBitmap)
308 {
309         _ContextMenuItem* pItem = CreateItemN(text, actionId, pNormalBitmap, pPressedBitmap, pHighlightedBitmap);
310         SysTryReturnResult(NID_UI_CTRL, pItem != null, GetLastResult(), "Failed to create item.");
311
312         result r = __pModel->AddItem(pItem);
313
314         if (r != E_SUCCESS)
315         {
316                 delete pItem;
317                 SysTryReturnResult(NID_UI_CTRL, false, r, "Failed to add item.");
318         }
319
320         return r;
321 }
322
323 result
324 _ContextMenuListPresenter::InsertItem(int index, const String& text, int actionId,
325                                                                           const Bitmap* pNormalBitmap, const Bitmap* pPressedBitmap,
326                                                                           const Bitmap* pHighlightedBitmap)
327 {
328
329         SysTryReturnResult(NID_UI_CTRL, (text.GetLength() != 0 || pNormalBitmap != null || pPressedBitmap != null), E_INVALID_ARG,
330                 "Invalid argument(s) is used. If text is empty then pNormalBitmap or pPressedBitmap must not be null.");
331
332         _ContextMenuItem* pItem = null;
333
334         pItem = CreateItemN(text, actionId, pNormalBitmap, pPressedBitmap, pHighlightedBitmap);
335         SysTryReturnResult(NID_UI_CTRL, pItem != null, GetLastResult(), "Failed to create item.");
336
337         result r = __pModel->InsertItem(pItem, index);
338         if (r != E_SUCCESS)
339         {
340                 delete pItem;
341                 SysTryReturnResult(NID_UI_CTRL, false, r, "Failed to add item.");
342         }
343
344         return E_SUCCESS;
345 }
346
347 result
348 _ContextMenuListPresenter::SetItem(int index, const String& text, int actionId,
349                                                                    const Bitmap* pNormalBitmap, const Bitmap* pPressedBitmap,
350                                                                    const Bitmap* pHighlightedBitmap)
351 {
352         _ContextMenuItem* pItem = null;
353         result r = E_SUCCESS;
354
355         SysTryReturnResult(NID_UI_CTRL, (text.GetLength() != 0 || pNormalBitmap != null || pPressedBitmap != null), E_INVALID_ARG,
356                  "Invalid argument(s) is used. If text is empty then pNormalBitmap or pPressedBitmap must not be null.");
357
358         pItem = __pModel->GetItem(index);
359         r = GetLastResult();
360         SysTryReturnResult(NID_UI_CTRL, pItem != null, r, "Failed to get the item.");
361
362         if (pItem->HasParent())
363         {
364                 r = __pContextMenu->GetScrollPanel()->DetachChild(*pItem);
365                 SysTryReturnResult(NID_UI_CTRL, r == E_SUCCESS, r, "Failed to detach item.");
366         }
367
368         pItem = CreateItemN(text, actionId, pNormalBitmap, pPressedBitmap, pHighlightedBitmap);
369         SysTryReturnResult(NID_UI_CTRL, pItem != null, GetLastResult(), "Failed to create item.");
370
371         r = __pModel->SetItem(pItem, index);
372         if (r != E_SUCCESS)
373         {
374                 delete pItem;
375                 SysTryReturnResult(NID_UI_CTRL, false, r, "Failed to add item.");
376         }
377
378         CalculateItemMaximumWidth();
379
380         return E_SUCCESS;
381 }
382
383 result
384 _ContextMenuListPresenter::DeleteItem(int index)
385 {
386         _ContextMenuItem* pItem = null;
387         result r = E_SUCCESS;
388
389         SysTryReturnResult(NID_UI_CTRL, __pContextMenu->GetItemCount() > 0, E_INVALID_STATE, "__pContextMenu is in invalid state. Item count is less than or equal to zero.");
390
391         pItem = __pModel->GetItem(index);
392         r = GetLastResult();
393         SysTryReturnResult(NID_UI_CTRL, pItem != null, r, "Failed to get the item.");
394
395         if (pItem->HasParent())
396         {
397                 r = __pContextMenu->GetScrollPanel()->DetachChild(*pItem);
398                 SysTryReturnResult(NID_UI_CTRL, r == E_SUCCESS, r, "Failed to detach item.");
399         }
400
401         r = __pModel->RemoveItem(index);
402         SysTryReturnResult(NID_UI_CTRL, r == E_SUCCESS, r, "Failed to delete item.");
403
404         CalculateItemMaximumWidth();
405
406         return r;
407 }
408
409 result
410 _ContextMenuListPresenter::DeleteItemAll(void)
411 {
412         SysTryReturnResult(NID_UI_CTRL, __pContextMenu->GetItemCount() > 0, E_INVALID_STATE, "__pContextMenu is in invalid state. Item count is less than or equal to zero.");
413
414         __pContextMenu->GetScrollPanel()->DetachAllChildren();
415
416         result r =  __pModel->RemoveAllItem();
417         SysTryReturnResult(NID_UI_CTRL, r == E_SUCCESS, r, "Failed to delete item all.");
418
419         return r;
420 }
421
422
423 int
424 _ContextMenuListPresenter::CalculateShowItemCount(void)
425 {
426         int itemMaxCount = 0;
427         GET_SHAPE_CONFIG(CONTEXTMENU::ITEM_MAX_COUNT, _CONTROL_ORIENTATION_PORTRAIT, itemMaxCount);
428
429         int maxVisibleCount = __pContextMenu->GetShowItemCount();
430
431         return maxVisibleCount > itemMaxCount ? itemMaxCount : maxVisibleCount;
432 }
433
434 result
435 _ContextMenuListPresenter::CalculateWindowRect(void)
436 {
437         result r = CalculateRect();
438         AdjustItemPosition();
439
440         return r;
441 }
442
443 result
444 _ContextMenuListPresenter::ApplyColorProperty(void)
445 {
446         int count;
447         count = __pContextMenu->GetItemCount();
448
449         for (int i = 0; i < count; i++)
450         {
451                 _ContextMenuItem* pItem = null;
452                 Color color = __pContextMenu->GetItemColor(CONTEXT_MENU_CORE_ITEM_STATUS_PRESSED);
453
454                 pItem = __pModel->GetItem(i);
455                 SysTryReturnResult(NID_UI_CTRL, pItem != null, E_SYSTEM, "A system error has occured. pItem must not be null.");
456
457                 pItem->SetPressedItemColor(color);
458         }
459         return E_SUCCESS;
460 }
461
462
463 result
464 _ContextMenuListPresenter::CalculateRect(void)
465 {
466         FloatRectangle windowRect = FloatRectangle(0.0f, 0.0f, 0.0f, 0.0f);     // ContextMenu window itself
467         FloatRectangle bodyRect   = FloatRectangle(0.0f, 0.0f, 0.0f, 0.0f);     // bg surronding showing items, relative to window
468         FloatRectangle arrowRect  = FloatRectangle(0.0f, 0.0f, 0.0f, 0.0f);     // relative to window
469         FloatRectangle itemRect   = FloatRectangle(0.0f, 0.0f, 0.0f, 0.0f);     // relative to window
470
471         float bodyTopMargin = __topMargin;
472         float bodyBottomMargin = __bottomMargin;
473         float bodyLeftMargin = __leftMargin;
474         float bodyRightMargin = __rightMargin;
475
476         float screenTopMargin = __screenTopMargin;
477         float screenBottomMargin = __screenBottomMargin;
478         float screenLeftMargin = __screenLeftMargin;
479         float screenRightMargin = __screenRightMargin;
480
481         int scrollPanelMargin;
482         GET_SHAPE_CONFIG(CONTEXTMENU::SCROLL_PANEL_MARGIN, _CONTROL_ORIENTATION_PORTRAIT, scrollPanelMargin);
483
484         FloatPoint anchorPosition = __pContextMenu->GetAnchorPosition();
485         FloatDimension screen = _ControlManager::GetInstance()->GetScreenSizeF();
486
487         if (__pContextMenu->GetLayout() == _CONTROL_ORIENTATION_LANDSCAPE)
488         {
489                 screen.SetSize(screen.height, screen.width);
490         }
491
492         // calculate arrow area
493         enum ContextMenuCoreDropPosition dropPosition = __pContextMenu->GetDropPosition();
494         if (dropPosition == CONTEXT_MENU_CORE_DROP_POSITION_UP || dropPosition == CONTEXT_MENU_CORE_DROP_POSITION_DOWN) // down, up Arrow
495         {
496                 arrowRect.width = __arrowWidth;
497                 arrowRect.height = __arrowHeight;
498         }
499         else //  left, right Arrow
500         {
501                 arrowRect.width = __arrowHeight;
502                 arrowRect.height = __arrowWidth;
503         }
504
505         // calculate body rect
506         // calculate drawable boundaries for contextmenu
507         float leftBoundary = screenLeftMargin;
508         float rightBoundary = screen.width - screenRightMargin;
509         float topBoundary = screenTopMargin;
510         float bottomBoundary = screen.height - screenBottomMargin;
511
512         // calculate layout size (__layoutSize)
513         AdjustItemLayout();
514
515         bodyRect.width = __layoutSize.width + bodyLeftMargin + bodyRightMargin;
516         bodyRect.height = __layoutSize.height + bodyTopMargin + bodyBottomMargin + 2 * scrollPanelMargin;
517
518         // calculate the position of the arrow and body rect.
519         if (dropPosition == CONTEXT_MENU_CORE_DROP_POSITION_UP)   // down Arrow
520         {
521                 // Check touch position
522                 //  - Check left margin
523                 if (anchorPosition.x <= leftBoundary + arrowRect.width)
524                 {
525                         anchorPosition.x = leftBoundary + arrowRect.width;
526                 }
527                 //  - check right margin
528                 if (anchorPosition.x >= (rightBoundary - arrowRect.width))
529                 {
530                         anchorPosition.x = rightBoundary - arrowRect.width;
531                 }
532                 //  - check top margin
533                 if (anchorPosition.y <= topBoundary)
534                 {
535                         anchorPosition.y = topBoundary + bodyRect.height;
536                 }
537                 //  - check bottom margin
538                 if (anchorPosition.y >= bottomBoundary)
539                 {
540                         anchorPosition.y = bottomBoundary;
541                 }
542
543                 // Set body position x
544                 bodyRect.x = anchorPosition.x - (bodyRect.width / 2.0f);
545                 //  - Check left margin
546                 if (bodyRect.x <= leftBoundary)
547                 {
548                         bodyRect.x = leftBoundary;
549                 }
550                 //  - check right margin
551                 if ((bodyRect.x + bodyRect.width) >= rightBoundary)
552                 {
553                         bodyRect.x = rightBoundary - bodyRect.width;
554                 }
555                 // Set body position y
556                 bodyRect.y = anchorPosition.y - arrowRect.height - bodyRect.height;
557                 //  - check top margin
558                 if (bodyRect.y <= topBoundary)
559                 {
560                         bodyRect.y = topBoundary;
561                 }
562
563                 float correctLength = __arrowTopMargin - __anchorPopupOverlap;
564                 windowRect.x = bodyRect.x;
565                 windowRect.y = bodyRect.y + correctLength;
566                 windowRect.width = bodyRect.width;
567                 windowRect.height = bodyRect.height + arrowRect.height - correctLength;
568
569                 bodyRect.x = 0.0f;
570                 bodyRect.y = 0.0f;
571
572                 // Set arrow position
573                 arrowRect.x = anchorPosition.x - (arrowRect.width / 2.0f) - windowRect.x;
574                 arrowRect.y = bodyRect.height - correctLength;
575         }
576         else if (dropPosition == CONTEXT_MENU_CORE_DROP_POSITION_DOWN)    // up Arrow
577         {
578                 // Check touch position
579                 //  - Check left margin
580                 if (anchorPosition.x <= leftBoundary + arrowRect.width)
581                 {
582                         anchorPosition.x = leftBoundary + arrowRect.width;
583                 }
584                 //  - check right margin
585                 if (anchorPosition.x >= (rightBoundary - arrowRect.width))
586                 {
587                         anchorPosition.x = rightBoundary - arrowRect.width;
588                 }
589                 //  - check top margin
590                 if (anchorPosition.y <= topBoundary)
591                 {
592                         anchorPosition.y = topBoundary;
593                 }
594                 //  - check bottom margin
595                 if (anchorPosition.y >= bottomBoundary)
596                 {
597                         anchorPosition.y = bottomBoundary;
598                 }
599
600                 // Set body position x
601                 bodyRect.x = anchorPosition.x - (bodyRect.width / 2.0f);
602                 //  - Check left margin
603                 if (bodyRect.x <= leftBoundary)
604                 {
605                         bodyRect.x = leftBoundary;
606                 }
607                 //  - check right margin
608                 if ((bodyRect.x + bodyRect.width) >= rightBoundary)
609                 {
610                         bodyRect.x = rightBoundary - bodyRect.width;
611                 }
612                 // Set body position y
613                 bodyRect.y = anchorPosition.y + arrowRect.height;
614                 //  - Check bottom margin
615                 if ((bodyRect.y + bodyRect.height) >= bottomBoundary)
616                 {
617                         bodyRect.y = bottomBoundary - bodyRect.height;
618                 }
619
620                 float correctLength = __arrowBottomMargin - __anchorPopupOverlap;
621                 windowRect.x = bodyRect.x;
622                 windowRect.y = bodyRect.y - arrowRect.height;
623                 windowRect.width = bodyRect.width;
624                 windowRect.height = bodyRect.height + arrowRect.height - correctLength;
625
626                 bodyRect.x = 0.0f;
627                 bodyRect.y = arrowRect.height - correctLength;
628
629                 // Set arrow position
630                 arrowRect.x = anchorPosition.x - (arrowRect.width / 2.0f) - windowRect.x;
631                 arrowRect.y = 0.0f;
632         }
633         else if (dropPosition == CONTEXT_MENU_CORE_DROP_POSITION_LEFT)    // right Arrow
634         {
635                 // Check touch position
636                 //  - Check left margin
637                 if (anchorPosition.x <= leftBoundary)
638                 {
639                         anchorPosition.x = leftBoundary + bodyRect.width;
640                 }
641                 //  - check right margin
642                 if (anchorPosition.x >= rightBoundary)
643                 {
644                         anchorPosition.x = rightBoundary;
645                 }
646                 //  - Check top margin
647                 if (anchorPosition.y <= topBoundary + arrowRect.height)
648                 {
649                         anchorPosition.y = topBoundary + arrowRect.height;
650                 }
651                 //  - check bottom margin
652                 if (anchorPosition.y >= (bottomBoundary - arrowRect.height))
653                 {
654                         anchorPosition.y = bottomBoundary - arrowRect.height;
655                 }
656
657                 // Set body position x
658                 bodyRect.x = anchorPosition.x - arrowRect.width - bodyRect.width;
659                 //  - Check left margin
660                 if (bodyRect.x <= leftBoundary)
661                 {
662                         bodyRect.x = leftBoundary;
663                 }
664                 //  - check right margin
665                 if ((bodyRect.x + bodyRect.width + arrowRect.width) >= rightBoundary)
666                 {
667                         bodyRect.x = rightBoundary - bodyRect.width - arrowRect.width;
668                 }
669
670                 // Set body position y
671                 bodyRect.y = anchorPosition.y - (bodyRect.height / 2.0f);
672                 // - check top margin
673                 if (bodyRect.y <= topBoundary)
674                 {
675                         bodyRect.y = topBoundary;
676                 }
677                 // - check bottom margin
678                 if ((bodyRect.y + bodyRect.height) >= bottomBoundary)
679                 {
680                         bodyRect.y = bottomBoundary - bodyRect.height;
681                 }
682
683                 float correctLength = __arrowRightMargin - __anchorPopupOverlap;
684                 windowRect.x = bodyRect.x + correctLength;
685                 windowRect.y = bodyRect.y;
686                 windowRect.width = bodyRect.width + arrowRect.width - correctLength;
687                 windowRect.height = bodyRect.height;
688
689                 bodyRect.x = 0.0f;
690                 bodyRect.y = 0.0f;
691
692                 // Set arrow position
693                 arrowRect.x = bodyRect.width - correctLength;
694                 arrowRect.y = anchorPosition.y - (arrowRect.height / 2.0f) - windowRect.y;
695         }
696         else    // left Arrow
697         {
698                 // Check touch position
699                 //  - Check top margin
700                 if (anchorPosition.x <= leftBoundary)
701                 {
702                         anchorPosition.x = leftBoundary;
703                 }
704                 //  - check right margin
705                 if (anchorPosition.x >= rightBoundary)
706                 {
707                         anchorPosition.x = rightBoundary - bodyRect.width;
708                 }
709                 //  - Check top margin
710                 if (anchorPosition.y <= topBoundary + arrowRect.height)
711                 {
712                         anchorPosition.y = topBoundary + arrowRect.height;
713                 }
714                 //  - check bottom margin
715                 if (anchorPosition.y >= (bottomBoundary - arrowRect.height))
716                 {
717                         anchorPosition.y = bottomBoundary - arrowRect.height;
718                 }
719
720                 // Set body position x
721                 bodyRect.x = anchorPosition.x;
722                 //  - Check left margin
723                 if (bodyRect.x <= leftBoundary)
724                 {
725                         bodyRect.x = leftBoundary;
726                 }
727                 //  - check right margin
728                 if ((bodyRect.x + bodyRect.width + arrowRect.width) >= rightBoundary)
729                 {
730                         bodyRect.x = rightBoundary - bodyRect.width - arrowRect.width;
731                 }
732                 // Set body position y
733                 bodyRect.y = anchorPosition.y - (bodyRect.height / 2.0f);
734                 // - check top margin
735                 if (bodyRect.y <= topBoundary)
736                 {
737                         bodyRect.y = topBoundary;
738                 }
739                 // - check bottom margin
740                 if ((bodyRect.y + bodyRect.height) >= bottomBoundary)
741                 {
742                         bodyRect.y = bottomBoundary - bodyRect.height;
743                 }
744
745                 float correctLength = __arrowLeftMargin - __anchorPopupOverlap;
746                 windowRect.x = bodyRect.x;
747                 windowRect.y = bodyRect.y;
748                 windowRect.width = bodyRect.width + arrowRect.width - correctLength;
749                 windowRect.height = bodyRect.height;
750
751                 bodyRect.x = arrowRect.width - correctLength;
752                 bodyRect.y = 0.0f;
753
754                 // Set arrow position
755                 arrowRect.x = 0.0f;
756                 arrowRect.y = anchorPosition.y - (arrowRect.height / 2.0f) - windowRect.y;
757         }
758
759         itemRect.x      = bodyRect.x + bodyLeftMargin;
760         itemRect.y      = bodyRect.y + bodyTopMargin + scrollPanelMargin;
761         itemRect.width  = __layoutSize.width;
762         itemRect.height = __layoutSize.height;
763
764         __pContextMenu->SetWindowRect(windowRect);
765         __pContextMenu->SetBodyRect(bodyRect);
766         __pContextMenu->SetArrowRect(arrowRect);
767         __pContextMenu->SetItemRect(itemRect);
768
769         // _ScrollPanel API call sequence: SetBounds() -> SetScrollAreaBounds()
770         // _Scroll visual interaction if Bounds < ScrollAreaBounds
771         if (__pContextMenu->IsVisible())
772         {
773                 __pContextMenu->GetScrollPanel()->SetBounds(FloatRectangle(bodyRect.x + bodyLeftMargin, bodyRect.y + bodyTopMargin + scrollPanelMargin,
774                                 __layoutSize.width, __layoutSize.height));
775                 int itemCount = __pModel->GetItemCount();
776                 float itemHeight = __itemHeight + (__dividerHeight * 2.0f);
777                 float layoutClientHeight = itemCount * itemHeight - (__dividerHeight * 2.0f);
778                 __pContextMenu->GetScrollPanel()->SetClientAreaHeight(layoutClientHeight);
779         }
780
781         __pContextMenu->SetMovable(true);
782         __pContextMenu->SetResizable(true);
783
784         __pContextMenu->SetMinimumSize(FloatDimension(0.0f, 0.0f));
785         __pContextMenu->SetMaximumSize(screen);
786         __pContextMenu->SetBounds(windowRect);
787
788         __pContextMenu->SetMovable(false);
789         __pContextMenu->SetResizable(false);
790
791         return E_SUCCESS;
792 }
793
794 void
795 _ContextMenuListPresenter::AdjustItemLayout(void)
796 {
797         FloatDimension layoutSize(0.0f, 0.0f);
798
799         int itemCount = __pModel->GetItemCount();
800         if (itemCount <= 0)
801         {
802                 __layoutSize.width = __itemWidth;
803                 __layoutSize.height = __itemHeight;
804                 return;
805         }
806
807         layoutSize = AdjustItemLayoutStyle();
808
809         FloatDimension screen = _ControlManager::GetInstance()->GetScreenSizeF();
810         if (__pContextMenu->GetLayout() == _CONTROL_ORIENTATION_LANDSCAPE)
811         {
812                 screen.SetSize(screen.height, screen.width);
813         }
814
815         int maxHeight = screen.height - __screenTopMargin - __screenBottomMargin - __arrowHeight;
816         if (layoutSize.height > maxHeight)
817         {
818                 layoutSize.height = maxHeight;
819         }
820
821         __layoutSize = layoutSize;
822 }
823
824
825 FloatDimension
826 _ContextMenuListPresenter::AdjustItemLayoutStyle(void)
827 {
828         int itemMaxCount = CalculateShowItemCount();
829
830         int itemCount = __pModel->GetItemCount();
831         float itemHeight = __itemHeight + (__dividerHeight * 2.0f);
832
833         FloatDimension layoutSize(__itemWidth, 0.0f);
834
835         float layoutClientHeight = itemCount * itemHeight - (__dividerHeight * 2.0f);
836         float layoutMaxHeight = itemMaxCount * itemHeight - (__dividerHeight * 2.0f);
837         if (layoutClientHeight > layoutMaxHeight)
838         {
839                 __scrollEnable = true;
840                 layoutSize.height = layoutMaxHeight;
841         }
842         else
843         {
844                 __scrollEnable = false;
845                 layoutSize.height = layoutClientHeight;
846         }
847
848         return layoutSize;
849 }
850
851 void
852 _ContextMenuListPresenter::AdjustItemPosition(void)
853 {
854         int itemCount = __pModel->GetItemCount();
855         if (itemCount <= 0)
856         {
857                 return;
858         }
859
860         float itemHeight = __itemHeight + (__dividerHeight * 2.0f);
861         float drawItemY = 0.0f;
862
863         float x = __pContextMenu->GetBodyRect().x + __leftMargin;
864         float y = __pContextMenu->GetBodyRect().y +  __topMargin;
865
866         _ContextMenuItem* pItem = null;
867
868         for (int i = 0; i < itemCount; i++)
869         {
870                 pItem = __pModel->GetItem(i);
871
872                 if (pItem == null)
873                 {
874                         break;
875                 }
876
877                 FloatRectangle drawRect(x, drawItemY + y, __itemWidth, itemHeight);
878
879                 pItem->SetDrawRect(drawRect);
880                 pItem->SetUpperDivider(i > 0);
881                 pItem->SetLowerDivider(i < itemCount - 1);
882                 pItem->SetParentScrollEnable(__scrollEnable);
883                 pItem->SetBounds(FloatRectangle(0.0f, drawItemY, drawRect.width, drawRect.height));
884
885                 if (pItem->HasParent() == false)
886                 {
887                         __pContextMenu->GetScrollPanel()->AttachChild(*pItem);
888                 }
889
890                 drawItemY += itemHeight;
891         }
892 }
893
894 void
895 _ContextMenuListPresenter::CalculateItemMaximumWidth(void)
896 {
897         FloatDimension itemSize(0.0f, 0.0f);
898         FloatDimension textArea(0.0f, 0.0f);
899         float maxItemWidth = __itemMinWidth;
900
901         for (int i = 0; i < __pModel->GetItemCount(); i++)
902         {
903                 _ContextMenuItem* pItem = null;
904
905                 pItem = __pModel->GetItem(i);
906                 SysTryReturnVoidResult(NID_UI_CTRL, pItem != null, E_SYSTEM, "[%s] A system error occurred. Unable to get the item.", GetErrorMessage(E_SYSTEM));
907
908                 CalculateItemSize(pItem->GetText(), pItem->GetType(), textArea, itemSize);
909
910                 if (maxItemWidth < itemSize.width)
911                 {
912                         maxItemWidth = itemSize.width;
913                 }
914         }
915         __itemWidth = maxItemWidth;
916 }
917
918 int
919 _ContextMenuListPresenter::GetItemIndexFromPosition(const FloatPoint& point) const
920 {
921         int index = -1;
922         int itemCount = __pModel->GetItemCount();
923
924         if (itemCount < 0)
925         {
926                 return -1;
927         }
928
929         _ContextMenuItem* pItem = null;
930
931         float scrollPosition = __pContextMenu->GetScrollPanel()->GetScrollPosition();
932         FloatPoint position(point.x, point.y + scrollPosition);
933
934         for (int i = 0; i < itemCount; i++)
935         {
936                 pItem = __pModel->GetItem(i);
937
938                 if (pItem == null)
939                 {
940                         break;
941                 }
942
943                 FloatRectangle drawRect = pItem->GetDrawRect();
944
945                 if (drawRect.Contains(position) == true)
946                 {
947                         index = i;
948                         break;
949                 }
950         }
951
952         return index;
953 }
954
955
956 result
957 _ContextMenuListPresenter::Draw(void)
958 {
959         result r = E_SUCCESS;
960
961         Canvas* pCanvas = __pContextMenu->GetCanvasN();
962         SysTryReturnResult(NID_UI_CTRL, pCanvas != null, GetLastResult(), "Propagating.");
963
964         // Clear canvas for drawing area of the ContextMenu.
965         pCanvas->SetBackgroundColor(Color(0, 0, 0, 0));
966         FloatRectangle bounds(__pContextMenu->GetWindowRect());
967         pCanvas->Clear(FloatRectangle(0.0f, 0.0f, bounds.width, bounds.height));
968
969         r = DrawBackground(pCanvas);
970         SysTryReturnResult(NID_UI_CTRL, r == E_SUCCESS, r, "Failed to draw background.");
971
972         r = DrawArrow(pCanvas);
973         SysTryReturnResult(NID_UI_CTRL, r == E_SUCCESS, r, "Failed to draw arrow.");
974
975         delete pCanvas;
976
977         return r;
978 }
979
980 result
981 _ContextMenuListPresenter::DrawBackground(Canvas* pCanvas)
982 {
983         SysTryReturnResult(NID_UI_CTRL, pCanvas != null, E_SYSTEM, "A system error has occurred. pCanvas is null.");
984
985         result r = E_SUCCESS;
986
987         FloatRectangle bodyRect = __pContextMenu->GetBodyRect();
988
989         const Bitmap* pBackgroundNormalBitmap = __pContextMenu->GetBackgroundNormalBitmap();
990         const Bitmap* pBackgroundEffectBitmap = __pContextMenu->GetBackgroundEffectBitmap();
991
992         if (pBackgroundNormalBitmap == null && pBackgroundEffectBitmap == null)
993         {
994                 pCanvas->SetForegroundColor(__pContextMenu->GetColor());
995                 pCanvas->DrawRectangle(bodyRect);
996         }
997         else
998         {
999                 if (pBackgroundNormalBitmap != null)
1000                 {
1001                         r = DrawBitmap(*pCanvas, bodyRect, *pBackgroundNormalBitmap);
1002                 }
1003
1004                 if (pBackgroundEffectBitmap != null)
1005                 {
1006                         r = DrawBitmap(*pCanvas, bodyRect, *pBackgroundEffectBitmap);
1007                 }
1008         }
1009
1010         return r;
1011 }
1012
1013
1014 result
1015 _ContextMenuListPresenter::DrawArrow(Canvas* pCanvas)
1016 {
1017         SysTryReturnResult(NID_UI_CTRL, pCanvas != null, E_SYSTEM, "A system error has occurred. pCanvas is null.");
1018
1019         result r = E_SUCCESS;
1020         FloatRectangle arrowRect = __pContextMenu->GetArrowRect();
1021         ContextMenuCoreDropPosition dropPosition = __pContextMenu->GetDropPosition();
1022
1023         const Bitmap* pArrowNormalBitmap = __pContextMenu->GetArrowNormalBitmap(dropPosition);
1024         const Bitmap* pEffectArrowBitmap = __pContextMenu->GetArrowEffectBitmap(dropPosition);
1025
1026         if (pArrowNormalBitmap != null)
1027         {
1028                 r = DrawBitmap(*pCanvas, arrowRect, *pArrowNormalBitmap);
1029         }
1030
1031         if (pEffectArrowBitmap != null)
1032         {
1033                 r = DrawBitmap(*pCanvas, arrowRect, *pEffectArrowBitmap);
1034         }
1035
1036         return r;
1037 }
1038
1039 _UiTouchEventDelivery
1040 _ContextMenuListPresenter::OnPreviewTouchPressed(const _Control& source, const _TouchInfo& touchinfo)
1041 {
1042         return _UI_TOUCH_EVENT_DELIVERY_FORCED_YES;
1043 }
1044
1045 bool
1046 _ContextMenuListPresenter::OnTouchPressed(const _Control& source, const _TouchInfo& touchinfo)
1047 {
1048         FloatPoint touchPosition = touchinfo.GetCurrentPosition();
1049         FloatRectangle itemRect = __pContextMenu->GetItemRect();
1050
1051         if (!itemRect.Contains(touchPosition))
1052         {
1053                 __selectedIndex = -1;
1054                 __touchOutRect = true;
1055                 return true;
1056         }
1057
1058         __selectedIndex = GetItemIndexFromPosition(touchPosition);
1059         __touchOutRect = false;
1060         return true;
1061 }
1062
1063 _UiTouchEventDelivery
1064 _ContextMenuListPresenter::OnPreviewTouchReleased(const _Control& source, const _TouchInfo& touchinfo)
1065 {
1066         return _UI_TOUCH_EVENT_DELIVERY_FORCED_YES;
1067 }
1068
1069 bool
1070 _ContextMenuListPresenter::OnTouchReleased(const _Control& source, const _TouchInfo& touchinfo)
1071 {
1072         FloatPoint touchPosition = touchinfo.GetCurrentPosition();
1073
1074         if (__touchOutRect)
1075         {
1076                 FloatRectangle itemRect = __pContextMenu->GetItemRect();
1077                 if (!itemRect.Contains(touchPosition))
1078                 {
1079                         __selectedIndex = -1;
1080                         __focusedIndex = -1;
1081                         __pContextMenu->SetFocused(false);
1082                         __pContextMenu->SetVisibleState(false);
1083
1084                         return true;
1085                 }
1086         }
1087
1088         int currentSelectedIndex = GetItemIndexFromPosition(touchPosition);
1089         if (__selectedIndex != -1 && (__selectedIndex == currentSelectedIndex))
1090         {
1091                 _ContextMenuItem* pItem = null;
1092                 pItem = __pModel->GetItem(__selectedIndex);
1093                 if (pItem == null)
1094                 {
1095                         return true;
1096                 }
1097
1098                 __selectedIndex = -1;
1099                 __focusedIndex = -1;
1100                 __pContextMenu->SetFocused(false);
1101                 __pContextMenu->SetVisibleState(false);
1102
1103                 int actionId = pItem->GetActionId();
1104
1105                 _ActionEvent* pActionEvent = __pContextMenu->GetActionEvent();
1106                 if (pActionEvent == null)
1107                 {
1108                         return true;
1109                 }
1110
1111                 IEventArg* pEventArg = _ActionEvent::CreateActionEventArgN(actionId);
1112                 if (pEventArg == null)
1113                 {
1114                         return true;
1115                 }
1116
1117                 PLAY_FEEDBACK(_RESOURCE_FEEDBACK_PATTERN_TAP, __pContextMenu);
1118                 pActionEvent->Fire(*pEventArg);
1119         }
1120
1121         return true;
1122 }
1123
1124 _UiTouchEventDelivery
1125 _ContextMenuListPresenter::OnPreviewTouchMoved(const _Control& source, const _TouchInfo& touchinfo)
1126 {
1127         return _UI_TOUCH_EVENT_DELIVERY_FORCED_YES;
1128 }
1129
1130 bool
1131 _ContextMenuListPresenter::OnTouchMoved(const _Control& source, const _TouchInfo& touchinfo)
1132 {
1133         if (__scrollEnable)
1134         {
1135                 __selectedIndex = -1;
1136         }
1137
1138         return true;
1139 }
1140
1141 _UiTouchEventDelivery
1142 _ContextMenuListPresenter::OnPreviewTouchCanceled(const _Control& source, const _TouchInfo& touchinfo)
1143 {
1144         return _UI_TOUCH_EVENT_DELIVERY_FORCED_YES;
1145 }
1146
1147 bool
1148 _ContextMenuListPresenter::OnTouchCanceled(const _Control& source, const _TouchInfo& touchinfo)
1149 {
1150         __pModel->ResetAllItem();
1151         __selectedIndex = -1;
1152
1153         return true;
1154 }
1155
1156 bool
1157 _ContextMenuListPresenter::OnKeyPressed(const _Control& source, const _KeyInfo& keyInfo)
1158 {
1159         _KeyCode keyCode = keyInfo.GetKeyCode();
1160
1161         switch (keyCode)
1162         {
1163         case _KEY_UP:
1164         {
1165                 if (__enterKeyPressed)
1166                 {
1167                         __enterKeyPressed = false;
1168                         _ContextMenuItem* pItem = __pModel->GetItem(__focusedIndex);
1169                         if (pItem != null)
1170                         {
1171                                 pItem->SetAndInvalidate(false);
1172                         }
1173                 }
1174
1175                 if (--__focusedIndex < 0)
1176                 {
1177                         __focusedIndex = 0;
1178                 }
1179
1180                 _ContextMenuItem* pItem = __pModel->GetItem(__focusedIndex);
1181                 if(pItem == null)
1182                 {
1183                         __focusedIndex = -1;
1184                         break;
1185                 }
1186
1187                 pItem->SetFocused(true);
1188                 pItem->DrawFocus();
1189                 __pContextMenu->GetScrollPanel()->OnChildControlFocusMoved(*pItem);
1190
1191                 break;
1192         }
1193         case _KEY_DOWN:
1194         {
1195                 if (__enterKeyPressed)
1196                 {
1197                         __enterKeyPressed = false;
1198                         _ContextMenuItem* pItem = __pModel->GetItem(__focusedIndex);
1199                         if(pItem != null)
1200                         {
1201                                 pItem->SetAndInvalidate(false);
1202                         }
1203                 }
1204
1205                 _ContextMenuItem* pItem = __pModel->GetItem(++__focusedIndex);
1206                 if(pItem == null)
1207                 {
1208                         --__focusedIndex;
1209                         break;
1210                 }
1211
1212                 pItem->SetFocused(true);
1213                 pItem->DrawFocus();
1214                 __pContextMenu->GetScrollPanel()->OnChildControlFocusMoved(*pItem);
1215
1216                 break;
1217         }
1218         case _KEY_TAB:
1219         {
1220                 if (__enterKeyPressed)
1221                 {
1222                         __enterKeyPressed = false;
1223                         _ContextMenuItem* pItem = __pModel->GetItem(__focusedIndex);
1224                         if (pItem != null)
1225                         {
1226                                 pItem->SetAndInvalidate(false);
1227                         }
1228                 }
1229
1230                 __focusedIndex = 0;
1231
1232                 _ContextMenuItem* pItem = __pModel->GetItem(__focusedIndex);
1233                 if(pItem == null)
1234                 {
1235                         __focusedIndex = -1;
1236                         break;
1237                 }
1238
1239                 pItem->SetFocused(true);
1240                 pItem->DrawFocus();
1241                 __pContextMenu->GetScrollPanel()->OnChildControlFocusMoved(*pItem);
1242
1243                 break;
1244         }
1245         case _KEY_ENTER:
1246         {
1247                 __enterKeyPressed = true;
1248
1249                 _ContextMenuItem* pItem = __pModel->GetItem(__focusedIndex);
1250                 if(pItem != null)
1251                 {
1252                         pItem->SetAndInvalidate(true);
1253                 }
1254
1255                 break;
1256         }
1257         case _KEY_BACKSPACE:
1258         {
1259                 _ContextMenuItem* pItem = __pModel->GetItem(__focusedIndex);
1260                 if (pItem != null)
1261                 {
1262                         pItem->SetFocused(false);
1263                         pItem->SetAndInvalidate(false);
1264                 }
1265
1266                 __enterKeyPressed = false;
1267                 __backKeyPressed = false;
1268                 __selectedIndex = -1;
1269                 __focusedIndex = -1;
1270                 __pContextMenu->SetFocused(false);
1271                 __pContextMenu->SetVisibleState(false);
1272
1273                 break;
1274         }
1275         case _KEY_ESC:
1276                 // fall through
1277         case _KEY_MENU:
1278                 // fall through
1279         case _KEY_CONTEXT_MENU:
1280                 // fall through
1281         case _KEY_BACK:
1282                 __backKeyPressed = true;
1283                 break;
1284         default:
1285                 return false;
1286         }
1287
1288         return true;
1289 }
1290
1291 bool
1292 _ContextMenuListPresenter::OnKeyReleased(const _Control& source, const _KeyInfo& keyInfo)
1293 {
1294         _KeyCode keyCode = keyInfo.GetKeyCode();
1295
1296         switch (keyCode)
1297         {
1298         case _KEY_UP:
1299                 // fall through
1300         case _KEY_DOWN:
1301                 // fall through
1302         case _KEY_BACKSPACE:
1303                 // fall through
1304         case _KEY_TAB:
1305                 break;
1306         case _KEY_ENTER:
1307         {
1308                 if (!__enterKeyPressed)
1309                 {
1310                         return true;
1311                 }
1312
1313                 __enterKeyPressed = false;
1314                 __backKeyPressed = false;
1315
1316                 _ContextMenuItem* pItem = __pModel->GetItem(__focusedIndex);
1317
1318                 if (pItem == null)
1319                 {
1320                         __selectedIndex = -1;
1321                         __focusedIndex = -1;
1322                         __pContextMenu->SetFocused(false);
1323                         __pContextMenu->SetVisibleState(false);
1324
1325                         break;
1326                 }
1327
1328                 int actionId = pItem->GetActionId();
1329
1330                 _ActionEvent* pActionEvent = __pContextMenu->GetActionEvent();
1331                 if (pActionEvent == null)
1332                 {
1333                         break;
1334                 }
1335
1336                 IEventArg* pEventArg = _ActionEvent::CreateActionEventArgN(actionId);
1337                 if (pEventArg == null)
1338                 {
1339                         break;
1340                 }
1341
1342                 pItem->SetFocused(false);
1343                 pItem->SetAndInvalidate(false);
1344
1345                 __selectedIndex = -1;
1346                 __focusedIndex = -1;
1347                 __pContextMenu->SetFocused(false);
1348                 __pContextMenu->SetVisibleState(false);
1349
1350                 pActionEvent->Fire(*pEventArg);
1351
1352                 break;
1353         }
1354         case _KEY_ESC:
1355                 // fall through
1356         case _KEY_MENU:
1357                 // fall through
1358         case _KEY_CONTEXT_MENU:
1359                 // fall through
1360         case _KEY_BACK:
1361         {
1362                 if (!__backKeyPressed)
1363                 {
1364                         return true;
1365                 }
1366
1367                 _ContextMenuItem* pItem = __pModel->GetItem(__focusedIndex);
1368                 if (pItem != null)
1369                 {
1370                         pItem->SetFocused(false);
1371                         pItem->SetAndInvalidate(false);
1372                 }
1373
1374                 __enterKeyPressed = false;
1375                 __backKeyPressed = false;
1376                 __selectedIndex = -1;
1377                 __focusedIndex = -1;
1378                 __pContextMenu->SetFocused(false);
1379                 __pContextMenu->SetVisibleState(false);
1380
1381                 break;
1382         }
1383         default:
1384                 return false;
1385         }
1386
1387         return true;
1388 }
1389
1390 bool
1391 _ContextMenuListPresenter::IsChildControlFocusManage(void) const
1392 {
1393         return true;
1394
1395 }
1396
1397 void
1398 _ContextMenuListPresenter::OnFocusModeStateChanged(void)
1399 {
1400          _Control* pFocusedControl = null;
1401         _Window* pTop = __pContextMenu->GetRootWindow();
1402         if (pTop)
1403         {
1404                 pFocusedControl = pTop->GetCurrentFocusControl();
1405         }
1406
1407          if (pFocusedControl != null)
1408          {
1409                  pFocusedControl->SetFocused(false);
1410          }
1411 }
1412
1413 void
1414 _ContextMenuListPresenter::OnFontChanged(Font* pFont)
1415 {
1416         __pFont = pFont;
1417         String fontName = __pContextMenu->GetFont();
1418
1419         int itemCount = __pModel->GetItemCount();
1420         for (int i = 0; i < itemCount; i++)
1421         {
1422                 _ContextMenuItem* pItem = __pModel->GetItem(i);
1423                 if (pItem != null)
1424                 {
1425                         pItem->SetFont(fontName);
1426                 }
1427         }
1428 }
1429
1430 void
1431 _ContextMenuListPresenter::OnFontInfoRequested(unsigned long& style, float& size)
1432 {
1433         style = FONT_STYLE_PLAIN;
1434         size = __itemFontSize;
1435 }
1436
1437 void
1438 _ContextMenuListPresenter::SetAllAccessibilityElement(void)
1439 {
1440         _AccessibilityContainer* pContainerContextMenu = __pContextMenu->GetAccessibilityContainer();
1441         if (pContainerContextMenu != null)
1442         {
1443                 _AccessibilityElement* pElementContextMenu = new (std::nothrow) _AccessibilityElement(true);
1444                 SysTryReturnVoidResult(NID_UI_CTRL, pElementContextMenu, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
1445
1446                 pElementContextMenu->SetSupportOperatingGesture(false);
1447                 pElementContextMenu->SetTraitWithStringId("IDS_TPLATFORM_BODY_CONTEXTUAL_POP_UP_T_TTS");
1448                 pElementContextMenu->SetHintWithStringId("IDS_TPLATFORM_BODY_CONTEXTUAL_POP_UP_IS_OPEN_DOUBLE_TAP_TO_CLOSE_THE_POP_UP_T_TTS");
1449                 pElementContextMenu->SetBounds(FloatRectangle(0.0f, 0.0f, __pContextMenu->GetBoundsF().width, __pContextMenu->GetBoundsF().height));
1450                 pContainerContextMenu->AddElement(*pElementContextMenu);
1451                 __pContextMenu->AddAccessibilityElement(*pElementContextMenu);
1452
1453                 int itemCount = __pModel->GetItemCount();
1454                 for (int i = 0; i < itemCount; i++)
1455                 {
1456                         _ContextMenuItem* pItem = __pModel->GetItem(i);
1457                         if (pItem)
1458                         {
1459                                 _AccessibilityContainer* pContainer = pItem->GetAccessibilityContainer();
1460                                 if (pContainer != null)
1461                                 {
1462                                         LinkedListT<_AccessibilityElement*> accessibilityElements;
1463                                         _AccessibilityElement* pElement = null;
1464
1465                                         pContainer->GetElements(accessibilityElements);
1466                                         if (accessibilityElements.GetAt(0, pElement) == E_SUCCESS)
1467                                         {
1468                                                 pElement->SetName(L"ContextMenuItem" + Integer::ToString(i));
1469                                                 if (pItem->GetType() == CONTEXT_MENU_ITEM_DRAWING_TYPE_BITMAP)
1470                                                 {
1471                                                         String string;
1472                                                         GET_STRING_CONFIG(IDS_TPLATFORM_BODY_ICON, string);
1473                                                         pElement->SetLabel(string + pItem->GetText());
1474                                                 }
1475                                                 else
1476                                                 {
1477                                                         pElement->SetLabel(pItem->GetText());
1478                                                 }
1479
1480                                                 pElement->SetBounds(FloatRectangle(0.0f, 0.0f, pItem->GetBoundsF().width, pItem->GetBoundsF().height));
1481                                         }
1482                                         pContainerContextMenu->AddChildContainer(*pContainer);
1483                                 }
1484                         }
1485                 }
1486         }
1487 }
1488
1489 _ContextMenuItemInfo
1490 _ContextMenuListPresenter::GetItemFromPosition(const FloatPoint& position)
1491 {
1492         _ContextMenuItemInfo itemInfo;
1493         int index = GetItemIndexFromPosition(position);
1494         itemInfo.pContextMenuItem = __pModel->GetItem(index);
1495
1496         itemInfo.bListItem = false;
1497         itemInfo.pListItem = null;
1498         return itemInfo;
1499 }
1500
1501 _ContextMenuItemInfo
1502 _ContextMenuListPresenter::FindItem(int index)
1503 {
1504         _ContextMenuItemInfo itemInfo;
1505         itemInfo.bListItem = false;
1506         itemInfo.pListItem = null;
1507         itemInfo.pContextMenuItem = __pModel->GetItem(index);
1508         return itemInfo;
1509 }
1510
1511 result
1512 _ContextMenuListPresenter::SetTopDrawnItemIndex(int index)
1513 {
1514         return E_SUCCESS;
1515 }
1516
1517 result
1518 _ContextMenuListPresenter::DrawBitmap(Canvas& canvas, const FloatRectangle& bounds, const Bitmap& bitmap)
1519 {
1520         result r = E_SUCCESS;
1521         if (_BitmapImpl::CheckNinePatchedBitmapStrictly(bitmap))
1522         {
1523                 r = canvas.DrawNinePatchedBitmap(bounds, bitmap);
1524                 SysTryReturnResult(NID_UI_CTRL, r == E_SUCCESS, r, "Fail to draw ninepatched bitmap.")
1525         }
1526         else
1527         {
1528                 r = canvas.DrawBitmap(FloatPoint(bounds.x, bounds.y), bitmap);
1529                 SysTryReturnResult(NID_UI_CTRL, r == E_SUCCESS, r, "Fail to draw bitmap.")
1530         }
1531
1532         return r;
1533 }
1534
1535 }}} // Tizen::Ui: Control