add H/W backkey action
[framework/osp/web.git] / src / controls / FWebCtrl_SelectBox.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012 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 /**
19  * @file                FWebCtrl_SelectBox.cpp
20  * @brief               The file contains the definition of _SelectBox class.
21  *
22  * The file contains the definition of _SelectBox class.
23  */
24 #include <ewk_view.h>
25 #include <ewk_popup_menu_item.h>
26 #include <unique_ptr.h>
27 #include <FBaseColAllElementsDeleter.h>
28 #include <FBaseSysLog.h>
29 #include <FGrpDimension.h>
30 #include <FGrpRectangle.h>
31 #include <FUiCtrlButton.h>
32 #include <FUiCtrlCustomItem.h>
33 #include <FUiCtrlGroupedList.h>
34 #include <FUiCtrlListItemBase.h>
35 #include <FUiCtrlListView.h>
36 #include <FUiCtrlPanel.h>
37 #include <FUiIActionEventListener.h>
38 #include <FUiKeyEventInfo.h>
39 #include <FUiVerticalBoxLayout.h>
40 #include <FSys_SystemResource.h>
41 #include <FUi_ResourceManager.h>
42 #include "FWebCtrl_SelectBox.h"
43
44
45 using namespace Tizen::Base;
46 using namespace Tizen::Base::Collection;
47 using namespace Tizen::Graphics;
48 using namespace Tizen::System;
49 using namespace Tizen::Ui;
50 using namespace Tizen::Ui::Controls;
51
52
53 namespace Tizen { namespace Web { namespace Controls
54 {
55
56
57 static const int POSITION_INVALID = -1;
58
59
60 template< class Type > Type
61 Max(Type a, Type b)
62 {
63         return a > b ? a : b;
64 }
65
66
67 int CompareChangedItems(const void* pData1, const void* pData2)
68 {
69         SysAssertf(pData1 && pData2, "input parameters are null");
70
71     const int* pLeft = static_cast<const int*>(pData1);
72     const int* pRight = static_cast<const int*>(pData2);
73
74     return (*pLeft - *pRight);
75 }
76
77
78 //Internal class for maintaining states of list elements
79 class _ListElement
80         : public Object
81 {
82 public:
83         _ListElement(const String& itemText);
84
85         virtual ~_ListElement(void) {}
86
87         //Set functions
88         void ListElementSetItemEnabled(bool isEnabled);
89         void ListElementSetItemType(short itemType);
90         void ListElementSetItemSelected(bool isSelected);
91
92         //Get functions
93         short ListElementGetItemType(void) const { return __itemType; }
94
95         String ListElementGetString(void) const { return __itemStr; }
96
97         bool ListElementIsItemEnabled(void) const { return __isEnabled; }
98
99         bool ListElementIsItemSelected(void) const { return __isSelected; }
100
101 private:
102         _ListElement(void);
103
104 private:
105         String __itemStr;
106         short __itemType;
107         bool __isEnabled;
108         bool __isSelected;
109 }; // _ListElement
110
111
112 _ListElement::_ListElement(const String& itemText)
113         : __itemType(_SelectBox::LIST_ITEM_TYPE_NORMAL)
114         , __isEnabled(true)
115         , __isSelected(false)
116 {
117         __itemStr = itemText;
118 }
119
120
121 void
122 _ListElement::ListElementSetItemEnabled(bool isEnabled)
123 {
124         __isEnabled = isEnabled;
125 }
126
127
128 void
129 _ListElement::ListElementSetItemType(short itemType)
130 {
131         __itemType = itemType;
132 }
133
134
135 void
136 _ListElement::ListElementSetItemSelected(bool isSelected)
137 {
138         __isSelected = isSelected;
139 }
140
141
142 _SelectBox::_SelectBox(void)
143         : __pListView(null)
144         , __multiSelection(false)
145         , __SelectedIndex(-1)
146         , __prevIndex(-1)
147         , __orientation(_CONTROL_ORIENTATION_PORTRAIT)
148         , __pWebView(null)
149         , __pToggledArray(null)
150 {
151 }
152
153
154 _SelectBox::~_SelectBox(void)
155 {
156         if (__multiSelection)
157         {
158                 eina_inarray_flush(__pToggledArray);
159                 delete __pToggledArray;
160         }
161
162         __listElementArray.RemoveAll(true);
163 }
164
165
166 result
167 _SelectBox::Construct(bool isMultiSelect, const String& title, int listCount, Evas_Object* pWebView)
168 {
169         result r = E_SUCCESS;
170         Rectangle rect;
171
172         int listItemHeight = 0;
173         int listMaxHeihgt = 0;
174         int listViewHeight = 0;
175
176         __pWebView = pWebView;
177
178         GET_SHAPE_CONFIG(CONTEXTMENU::LIST_ITEM_HEIGHT, __orientation, listItemHeight);
179
180         __multiSelection = isMultiSelect;
181
182         _WebPopupData* pPopupData = _WebPopup::GetPopupData();
183         SysTryReturn(NID_WEB_CTRL, pPopupData, r = GetLastResult(), r, "[%s] Propagating.", GetErrorMessage(r));
184
185         listMaxHeihgt = listCount * listItemHeight + pPopupData->btnDim.height + pPopupData->spacePad;
186
187         rect.height = listMaxHeihgt;
188         rect.width = pPopupData->popupDim.width;
189         rect.x = 0;
190         rect.y = 0;
191
192         r = _WebPopup::Construct(!title.IsEmpty(), Dimension(rect.width, rect.height));
193         SysTryReturn(NID_WEB_CTRL, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
194
195         if (!title.IsEmpty())
196         {
197                 Popup::SetTitleText(title);
198         }
199
200         listViewHeight = listCount * listItemHeight;
201         std::unique_ptr<ListView> pListView(new (std::nothrow) ListView());
202         SysTryReturnResult(NID_WEB_CTRL, pListView.get(), E_OUT_OF_MEMORY, "Memory Allocation failed.");
203
204         r = pListView->Construct(Rectangle(0, 0, GetClientAreaBounds().width, listViewHeight), true, SCROLL_STYLE_FADE_OUT);
205         SysTryReturn(NID_WEB_CTRL, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
206
207         r = __listElementArray.Construct();
208         SysTryReturn(NID_WEB_CTRL, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
209
210         pListView->SetItemProvider(*this);
211         pListView->AddListViewItemEventListener(*this);
212         pListView->SetTextOfEmptyList(L"");
213
214         r = AddControl(*pListView);
215         SysTryReturn(NID_WEB_CTRL, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
216
217         __pListView = pListView.release();
218
219         Panel* pButtonPanel = CreateAndAddPanel();
220         SysTryReturn(NID_WEB_CTRL, pButtonPanel, r = GetLastResult(), r, "[%s] Propagating.", GetErrorMessage(r));
221
222         _SystemResource* pSysResource = _SystemResource::GetInstance();
223         SysAssertf(pSysResource != null, "Failed to get _SystemResource instance");
224
225         ArrayList idList;
226         r = idList.Construct();
227         SysTryReturn(NID_WEB_CTRL, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
228         if (__multiSelection)
229         {
230                 idList.Add(*(new Integer(ID_BUTTON_SELECTION)));
231         }
232         idList.Add(*(new Integer(ID_BUTTON_CANCEL)));
233
234         ArrayList titleList;
235         r = titleList.Construct();
236         SysTryReturn(NID_WEB_CTRL, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
237         if (__multiSelection)
238         {
239                 titleList.Add(*(new String(pSysResource->GetString("sys_string", "IDS_COM_BODY_DONE"))));
240
241                 __pToggledArray = eina_inarray_new(sizeof(int), 0);
242                 SysTryReturnResult(NID_WEB_CTRL, __pToggledArray, E_OUT_OF_MEMORY, "Memory Allocation failed.");
243         }
244         titleList.Add(*(new String(pSysResource->GetString("sys_string", "IDS_COM_POP_CANCEL"))));
245
246         r = CreateAndAddButtons(idList, titleList, pButtonPanel);
247         SysTryReturn(NID_WEB_CTRL, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
248
249         std::unique_ptr<VerticalBoxLayout> pLayout(dynamic_cast< VerticalBoxLayout* >(GetLayoutN()));
250         SysTryReturn(NID_WEB_CTRL, pLayout.get(), r = GetLastResult(), r, "[%s] Propagating.", GetErrorMessage(r));
251
252         pLayout->SetSpacing(*pButtonPanel,  pPopupData->spacePad);
253
254         SetPropagatedKeyEventListener(this);
255         
256         return r;
257 }
258
259 result
260 _SelectBox::AddListItem(const String& itemText, int itemType, bool slected)
261 {
262         result r = E_SUCCESS;
263         std::unique_ptr<_ListElement> pListElement(new (std::nothrow) _ListElement(itemText));
264         SysTryReturnResult(NID_WEB_CTRL, pListElement.get(), E_OUT_OF_MEMORY, "Memory Allocation failed.");
265
266         pListElement->ListElementSetItemType(itemType);
267         pListElement->ListElementSetItemSelected(slected);
268
269         r = __listElementArray.Add(*pListElement);
270         SysTryReturn(NID_WEB_CTRL, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
271
272         pListElement.release();
273         return r;
274 }
275
276
277 IList*
278 _SelectBox::GetSelectedListN(void) const
279 {
280         result r = E_SUCCESS;
281
282         std::unique_ptr<ArrayList, AllElementsDeleter> pSelectedList(new (std::nothrow) ArrayList());
283         SysTryReturn(NID_WEB_CTRL, pSelectedList.get(), null, E_OUT_OF_MEMORY, "[%s] Memory Allocation failed.",GetErrorMessage(E_OUT_OF_MEMORY));
284
285         r = pSelectedList->Construct();
286         SysTryReturn(NID_WEB_CTRL, r == E_SUCCESS, null, r, "[%s] Propagating.", GetErrorMessage(r));
287
288         for (int index = 0; index < __pListView->GetItemCount(); index++)
289         {
290                 if (__pListView->IsItemChecked(index))
291                 {
292                         std::unique_ptr<Integer> pIdxResult(new (std::nothrow) Integer(index));
293                         SysTryReturn(NID_WEB_CTRL, pIdxResult.get(), null, E_OUT_OF_MEMORY, "[%s] Memory Allocation failed.",GetErrorMessage(E_OUT_OF_MEMORY));
294
295                         r = pSelectedList->Add(*pIdxResult);
296                         SysTryReturn(NID_WEB_CTRL, r == E_SUCCESS, null, r, "[%s] Memory Allocation failed.",GetErrorMessage(r));
297
298                         pIdxResult.release();
299                 }
300         }
301
302         return pSelectedList.release();
303 }
304
305
306 //IListViewItemProvider
307 ListItemBase*
308 _SelectBox::CreateItem(int index, int itemWidth)
309 {
310         result r = E_SUCCESS;
311         int listItemXPos = 0;
312         int listItemYPos = 0;
313         int checkBoxWidth = 0;
314         int listItemHeight = 0;
315         int popupBetweenListNBtnGap = 0;
316
317         ListAnnexStyle subStyle = (__multiSelection) ? LIST_ANNEX_STYLE_MARK : LIST_ANNEX_STYLE_NORMAL;
318         ListAnnexStyle groupStyle = LIST_ANNEX_STYLE_NORMAL;
319
320         _ListElement* pListElement = static_cast< _ListElement* >(__listElementArray.GetAt(index));
321         SysTryReturn(NID_WEB_CTRL, pListElement, null, GetLastResult(), "[%s] Propagating.", GetErrorMessage(GetLastResult()));
322
323         GET_SHAPE_CONFIG(CONTEXTMENU::LIST_ITEM_HEIGHT, __orientation, listItemHeight);
324         GET_SHAPE_CONFIG(LISTVIEW::ITEM_ELEMENT_LEFT_MARGIN, __orientation, listItemXPos);
325         GET_SHAPE_CONFIG(LIST::LIST_CHECK_ITEM_WIDTH, __orientation, checkBoxWidth);
326         GET_SHAPE_CONFIG(MESSAGEBOX::BUTTON_TOP_MARGIN, __orientation, popupBetweenListNBtnGap);
327
328         std::unique_ptr<CustomItem> pItem(new (std::nothrow) CustomItem());
329         SysTryReturn(NID_WEB_CTRL, pItem.get(), null, E_OUT_OF_MEMORY, "[%s] Memory Allocation failed.",GetErrorMessage(E_OUT_OF_MEMORY));
330
331         int itemType = pListElement->ListElementGetItemType();
332         Rectangle popupRect = this->GetClientAreaBounds();
333
334         int listTxtMaxWidth = popupRect.width - listItemXPos - checkBoxWidth - popupBetweenListNBtnGap;
335
336         switch (itemType)
337         {
338         case LIST_ITEM_TYPE_NORMAL:
339         //fall through
340         case LIST_ITEM_TYPE_SUB:
341                 r = pItem->Construct(Dimension(itemWidth, listItemHeight), subStyle);
342                 SysTryReturn(NID_WEB_CTRL, r == E_SUCCESS, null, r, "[%s] Propagating.", GetErrorMessage(r));
343                 break;
344
345         case LIST_ITEM_TYPE_GROUP:
346                 SysLog(NID_WEB_CTRL, "The current value of index [%d] [%d]", index, pListElement->ListElementIsItemEnabled());
347                 r = pItem->Construct(Dimension(itemWidth, listItemHeight), groupStyle);
348                 SysTryReturn(NID_WEB_CTRL, r == E_SUCCESS, null, r, "[%s] Propagating.", GetErrorMessage(r));
349                 break;
350
351         default:
352                 return null;
353         }
354
355         String elementString = pListElement->ListElementGetString();
356
357         if (elementString.IsEmpty())
358         {
359                 elementString.Append(L" ");
360         }
361
362         r = pItem->AddElement(Rectangle(listItemXPos, listItemYPos, listTxtMaxWidth, listItemHeight),
363                                                   ID_FORMAT_STRING, elementString, true);
364         SysTryReturn(NID_WEB_CTRL, r == E_SUCCESS, null, r, "[%s] Propagating.", GetErrorMessage(r));
365
366         if (IsMultiSelectable())
367         {
368                 r = __pListView->SetItemChecked(index, pListElement->ListElementIsItemSelected());
369                 SysTryReturn(NID_WEB_CTRL, r == E_SUCCESS, null, r, "[%s] Propagating.", GetErrorMessage(r));
370         }
371
372         r = __pListView->SetItemEnabled(index, !(itemType == LIST_ITEM_TYPE_GROUP));
373         SysTryReturn(NID_WEB_CTRL, r == E_SUCCESS, null, r, "[%s] Propagating.", GetErrorMessage(r));
374
375         return pItem.release();
376 }
377
378
379 bool
380 _SelectBox::DeleteItem(int index, ListItemBase* pItem, int itemWidth)
381 {
382         delete pItem;
383         pItem = null;
384
385         return true;
386 }
387
388
389 int
390 _SelectBox::GetItemCount(void)
391 {
392         return __listElementArray.GetCount();
393 }
394
395
396 void
397 _SelectBox::OnListViewContextItemStateChanged(ListView& listView, int index, int elementId, ListContextItemStatus state)
398 {
399 }
400
401
402 void
403 _SelectBox::OnListViewItemStateChanged(ListView& listView, int index, int elementId, ListItemStatus status)
404 {
405         if (__multiSelection)
406         {
407                 int pos = eina_inarray_search(__pToggledArray, &index, CompareChangedItems);
408
409                 if (pos == POSITION_INVALID)
410                 {
411                         eina_inarray_push(__pToggledArray, &index);
412                 }
413                 else
414                 {
415                         eina_inarray_remove(__pToggledArray, &index);
416                 }
417         }
418         else
419         {
420                 //In case of single selection ... update the index.
421                 __SelectedIndex = index;
422                 SysLog(NID_WEB_CTRL,"The current value of Update Selected index is %d",index);
423                 if (__pWebView)
424                 {
425                         ewk_view_popup_menu_select(__pWebView, __SelectedIndex);
426                 }
427
428                 result r = HidePopup(__SelectedIndex);
429                 SysTryReturnVoidResult(NID_WEB_CTRL, r == E_SUCCESS, r, "[%s] Propagating.", GetErrorMessage(r));
430         }
431 }
432
433
434 void
435 _SelectBox::OnListViewItemSwept(ListView& listView, int index, SweepDirection direction)
436 {
437
438 }
439
440
441 void
442 _SelectBox::OnActionPerformed(const Control& source, int actionId)
443 {
444         switch (actionId)
445         {
446         case ID_BUTTON_SELECTION:
447         {
448                 ewk_view_popup_menu_multiple_select(__pWebView, __pToggledArray);
449                 break;
450         }
451         case ID_BUTTON_CANCEL:
452         {
453                 if (__multiSelection)
454                 {
455                         ewk_view_popup_menu_multiple_select(__pWebView, null);
456                 }
457                 else
458                 {
459                         ewk_view_popup_menu_select(__pWebView, __prevIndex);
460                 }
461                 break;
462         }
463         default:
464                 SysAssertf(false, "Invalid Action ID");
465         }
466
467         result r = HidePopup(__SelectedIndex);
468         SysTryReturnVoidResult(NID_WEB_CTRL, r == E_SUCCESS, r, "[%s] Propagating.", GetErrorMessage(r));
469 }
470
471 bool
472 _SelectBox::OnKeyPressed(Control& source, const KeyEventInfo& keyEventInfo)
473 {
474         return true;
475 }
476
477 bool
478 _SelectBox::OnKeyReleased(Control& source, const KeyEventInfo& keyEventInfo)
479 {
480         if ((keyEventInfo.GetKeyCode() == KEY_ESC || keyEventInfo.GetKeyCode() == KEY_BACK) && source.GetShowState() == true)
481         {
482                 if (__multiSelection)
483                 {
484                         ewk_view_popup_menu_multiple_select(__pWebView, null);
485                 }
486                 else
487                 {
488                         ewk_view_popup_menu_select(__pWebView, __prevIndex);
489                 }
490                 result r = HidePopup(__SelectedIndex);
491                 if (IsFailed(r))
492                 {
493                         SysLogException(NID_WEB_CTRL, r, "[%s] Propagating.", GetErrorMessage(r));
494                 }
495         }
496
497         return true;
498 }
499
500 bool
501 _SelectBox::OnPreviewKeyPressed(Control& source, const KeyEventInfo& keyEventInfo)
502 {
503         return false;
504 }
505
506 bool
507 _SelectBox::OnPreviewKeyReleased(Control& source, const KeyEventInfo& keyEventInfo)
508 {
509         return false;
510 }
511
512 bool
513 _SelectBox::TranslateKeyEventInfo(Control& source, KeyEventInfo& keyEventInfo)
514 {
515         return false;
516 }
517
518 result
519 _SelectBox::UpdateList(Eina_List* pItems, int prevIndex, bool clearPrevList, bool isGroupdList)
520 {
521         SysTryReturnResult(NID_WEB_CTRL, __pListView, E_INVALID_STATE, "List View is in an invalid state");
522
523         if (clearPrevList)
524         {
525                 __listElementArray.RemoveAll(true);
526                 if (__multiSelection)
527                 {
528                         eina_inarray_flush(__pToggledArray);
529                 }
530         }
531
532         //Create list required for selectBox
533         int itemCount = eina_list_count(pItems);
534         SysTryReturn(NID_WEB_CTRL, itemCount > 0, E_SYSTEM, E_SYSTEM, "[%s]  A system error has been occurred. ItemCount is invalid.", GetErrorMessage(E_SYSTEM));
535
536         bool isSelected = false;
537
538         if (!__multiSelection)
539         {
540                 __prevIndex = prevIndex;
541         }
542
543         for (int itemIndex = 0; itemIndex < itemCount; itemIndex++)
544         {
545                 Ewk_Popup_Menu_Item* pItem = static_cast<Ewk_Popup_Menu_Item*>(eina_list_nth(pItems, itemIndex));
546                 SysTryReturn(NID_WEB_CTRL, pItem, E_SYSTEM, E_SYSTEM, "[%s]  A system error has been occurred. Failed to get item.", GetErrorMessage(E_SYSTEM));
547
548                 if (ewk_popup_menu_item_type_get(pItem) == EWK_POPUP_MENU_ITEM)
549                 {
550                         String text(ewk_popup_menu_item_text_get(pItem));
551
552                         if (__multiSelection)
553                         {
554                                 isSelected = ( ewk_popup_menu_item_selected_get(pItem) == EINA_TRUE ) ? true : false;
555                         }
556                         else
557                         {
558                                 isSelected = (itemIndex == prevIndex) ? true : false;
559                         }
560
561                         if (isGroupdList)
562                         {
563                                 AddListItem(text, _SelectBox::LIST_ITEM_TYPE_GROUP, isSelected);
564                         }
565                         else
566                         {
567                                 AddListItem(text, _SelectBox::LIST_ITEM_TYPE_NORMAL, isSelected);
568                         }
569                 }
570         }
571
572         __pListView->UpdateList();
573
574         return E_SUCCESS;
575 }
576
577
578 }}} // Tizen::Web::Controls