Tizen 2.2.1
[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 <FCntDownloadRequest.h>
30 #include <FGrpDimension.h>
31 #include <FGrpRectangle.h>
32 #include <FUiCtrlButton.h>
33 #include <FUiCtrlCustomItem.h>
34 #include <FUiCtrlGroupedList.h>
35 #include <FUiCtrlListItemBase.h>
36 #include <FUiCtrlListView.h>
37 #include <FUiCtrlPanel.h>
38 #include <FUiIActionEventListener.h>
39 #include <FUiKeyEventInfo.h>
40 #include <FUiVerticalBoxLayout.h>
41 #include <FCnt_DownloadManagerImpl.h>
42 #include <FSys_SystemResource.h>
43 #include <FUi_ResourceManager.h>
44 #include "FWebCtrl_SelectBox.h"
45 #include "FWebCtrl_WebImpl.h"
46
47
48 using namespace Tizen::Base;
49 using namespace Tizen::Base::Collection;
50 using namespace Tizen::Content;
51 using namespace Tizen::Graphics;
52 using namespace Tizen::System;
53 using namespace Tizen::Ui;
54 using namespace Tizen::Ui::Controls;
55
56
57 namespace Tizen { namespace Web { namespace Controls
58 {
59
60
61 static const int POSITION_INVALID = -1;
62
63
64 template< class Type > Type
65 Max(Type a, Type b)
66 {
67         return a > b ? a : b;
68 }
69
70
71 int CompareChangedItems(const void* pData1, const void* pData2)
72 {
73         SysAssertf(pData1 && pData2, "input parameters are null");
74
75     const int* pLeft = static_cast<const int*>(pData1);
76     const int* pRight = static_cast<const int*>(pData2);
77
78     return (*pLeft - *pRight);
79 }
80
81
82 //Internal class for maintaining states of list elements
83 class _ListElement
84         : public Object
85 {
86 public:
87         _ListElement(const String& itemText);
88
89         virtual ~_ListElement(void) {}
90
91         //Set functions
92         void ListElementSetItemEnabled(bool isEnabled);
93         void ListElementSetItemType(short itemType);
94         void ListElementSetItemSelected(bool isSelected);
95
96         //Get functions
97         short ListElementGetItemType(void) const { return __itemType; }
98
99         String ListElementGetString(void) const { return __itemStr; }
100
101         bool ListElementIsItemEnabled(void) const { return __isEnabled; }
102
103         bool ListElementIsItemSelected(void) const { return __isSelected; }
104
105 private:
106         _ListElement(void);
107
108 private:
109         String __itemStr;
110         short __itemType;
111         bool __isEnabled;
112         bool __isSelected;
113 }; // _ListElement
114
115
116 _ListElement::_ListElement(const String& itemText)
117         : __itemType(_SelectBox::LIST_ITEM_TYPE_NORMAL)
118         , __isEnabled(true)
119         , __isSelected(false)
120 {
121         __itemStr = itemText;
122 }
123
124
125 void
126 _ListElement::ListElementSetItemEnabled(bool isEnabled)
127 {
128         __isEnabled = isEnabled;
129 }
130
131
132 void
133 _ListElement::ListElementSetItemType(short itemType)
134 {
135         __itemType = itemType;
136 }
137
138
139 void
140 _ListElement::ListElementSetItemSelected(bool isSelected)
141 {
142         __isSelected = isSelected;
143 }
144
145
146 _SelectBox::_SelectBox(void)
147         : __pListView(null)
148         , __multiSelection(false)
149         , __SelectedIndex(-1)
150         , __prevIndex(-1)
151         , __orientation(_CONTROL_ORIENTATION_PORTRAIT)
152         , __pWebView(null)
153         , __pToggledArray(null)
154         , __url(L"")
155         , __pImpl(null)
156 {
157 }
158
159
160 _SelectBox::~_SelectBox(void)
161 {
162         if (__multiSelection)
163         {
164                 eina_inarray_flush(__pToggledArray);
165                 delete __pToggledArray;
166         }
167
168         __listElementArray.RemoveAll(true);
169 }
170
171
172 result
173 _SelectBox::Construct(Tizen::Web::Controls::_WebImpl* pImpl, bool isMultiSelect, const String& title, int listCount, Evas_Object* pWebView, const String& url)
174 {
175         result r = E_SUCCESS;
176         Rectangle rect;
177
178         int listItemHeight = 0;
179         int listMaxHeihgt = 0;
180         int listViewHeight = 0;
181
182         __pWebView = pWebView;
183         __url = const_cast< String& >(url);
184         __pImpl = pImpl;
185
186         GET_SHAPE_CONFIG(CONTEXTMENU::LIST_ITEM_HEIGHT, __orientation, listItemHeight);
187
188         __multiSelection = isMultiSelect;
189
190         _WebPopupData* pPopupData = _WebPopup::GetPopupData();
191         SysTryReturn(NID_WEB_CTRL, pPopupData, r = GetLastResult(), r, "[%s] Propagating.", GetErrorMessage(r));
192
193         listMaxHeihgt = listCount * listItemHeight;
194
195         rect.height = listMaxHeihgt;
196         rect.width = pPopupData->popupDim.width;
197         rect.x = 0;
198         rect.y = 0;
199
200         r = _WebPopup::Construct(!title.IsEmpty(), Dimension(rect.width, rect.height));
201         SysTryReturn(NID_WEB_CTRL, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
202
203         if (!title.IsEmpty())
204         {
205                 Popup::SetTitleText(title);
206         }
207
208         listViewHeight = listCount * listItemHeight;
209         std::unique_ptr<ListView> pListView(new (std::nothrow) ListView());
210         SysTryReturnResult(NID_WEB_CTRL, pListView.get(), E_OUT_OF_MEMORY, "Memory Allocation failed.");
211
212         r = pListView->Construct(Rectangle(0, 0, GetClientAreaBounds().width, listViewHeight), true, SCROLL_STYLE_FADE_OUT);
213         SysTryReturn(NID_WEB_CTRL, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
214
215         r = __listElementArray.Construct();
216         SysTryReturn(NID_WEB_CTRL, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
217
218         pListView->SetItemProvider(*this);
219         pListView->AddListViewItemEventListener(*this);
220         pListView->SetTextOfEmptyList(L"");
221
222         r = AddControl(*pListView);
223         SysTryReturn(NID_WEB_CTRL, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
224
225         __pListView = pListView.release();
226
227         if (__multiSelection)
228         {
229                 Panel* pButtonPanel = CreateAndAddPanel();
230                 SysTryReturn(NID_WEB_CTRL, pButtonPanel, r = GetLastResult(), r, "[%s] Propagating.", GetErrorMessage(r));
231
232                 _SystemResource* pSysResource = _SystemResource::GetInstance();
233                 SysAssertf(pSysResource != null, "Failed to get _SystemResource instance");
234
235                 ArrayList idList;
236                 r = idList.Construct();
237                 SysTryReturn(NID_WEB_CTRL, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
238
239                 idList.Add(*(new Integer(ID_BUTTON_SELECTION)));
240
241                 ArrayList titleList;
242                 r = titleList.Construct();
243                 SysTryReturn(NID_WEB_CTRL, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
244
245                 titleList.Add(*(new String(pSysResource->GetString(_RESOURCE_DOMAIN_ID_OSP, "IDS_TPLATFORM_BUTTON_OK"))));
246
247                 __pToggledArray = eina_inarray_new(sizeof(int), 0);
248                 SysTryReturnResult(NID_WEB_CTRL, __pToggledArray, E_OUT_OF_MEMORY, "Memory Allocation failed.");
249
250                 r = CreateAndAddButtons(idList, titleList, pButtonPanel);
251                 SysTryReturn(NID_WEB_CTRL, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
252         }
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                 if (__url.GetLength() == 0)
422                 {
423                         __SelectedIndex = index;
424                         SysLog(NID_WEB_CTRL,"The current value of Update Selected index is %d",index);
425                         if (__pWebView)
426                         {
427                                 ewk_view_popup_menu_select(__pWebView, __SelectedIndex);
428                         }
429                 }
430                 else
431                 {
432                         result r = E_SUCCESS;
433
434                         RequestId reqId = 0;
435                         DownloadRequest request(__url);
436
437                         _DownloadManagerImpl* pManagerImpl = _DownloadManagerImpl::GetInstance();
438                         SysTryReturnVoidResult(NID_WEB_CTRL, pManagerImpl, GetLastResult(), "[%s] Propagating.", GetErrorMessage(GetLastResult()));
439
440                         r = pManagerImpl->Start(request, reqId);
441                         SysTryReturnVoidResult(NID_WEB_CTRL, r == E_SUCCESS, r, "[%s] Propagating.", GetErrorMessage(r));
442                 }
443
444                 result r = HidePopup();
445                 SysTryReturnVoidResult(NID_WEB_CTRL, r == E_SUCCESS, r, "[%s] Propagating.", GetErrorMessage(r));
446                 
447                 __pImpl->SendUserEvent(ID_USER_SCRIPT_SELECTBOX_CLOSE, null);
448         }
449 }
450
451
452 void
453 _SelectBox::OnListViewItemSwept(ListView& listView, int index, SweepDirection direction)
454 {
455
456 }
457
458
459 void
460 _SelectBox::OnActionPerformed(const Control& source, int actionId)
461 {
462         result r = HidePopup();
463         SysTryReturnVoidResult(NID_WEB_CTRL, r == E_SUCCESS, r, "[%s] Propagating.", GetErrorMessage(r));
464
465         if (__url.GetLength() == 0)
466         {
467                 switch (actionId)
468                 {
469                 case ID_BUTTON_SELECTION:
470                 {
471                         ewk_view_popup_menu_multiple_select(__pWebView, __pToggledArray);
472                         break;
473                 }
474                 case ID_BUTTON_CANCEL:
475                 {
476                         if (__multiSelection)
477                         {
478                                 ewk_view_popup_menu_multiple_select(__pWebView, null);
479                         }
480                         else
481                         {
482                                 ewk_view_popup_menu_select(__pWebView, __prevIndex);
483                         }
484                         break;
485                 }
486                 default:
487                         SysAssertf(false, "Invalid Action ID");
488                 }
489         }
490
491         __pImpl->SendUserEvent(ID_USER_SCRIPT_SELECTBOX_CLOSE, null);
492 }
493
494 bool
495 _SelectBox::OnKeyPressed(Control& source, const KeyEventInfo& keyEventInfo)
496 {
497         return false;
498 }
499
500 bool
501 _SelectBox::OnKeyReleased(Control& source, const KeyEventInfo& keyEventInfo)
502 {
503         if ((keyEventInfo.GetKeyCode() == KEY_ESC || keyEventInfo.GetKeyCode() == KEY_BACK) && source.GetShowState() == true)
504         {
505                 result r = HidePopup();
506                 if (IsFailed(r))
507                 {
508                         SysLogException(NID_WEB_CTRL, r, "[%s] Propagating.", GetErrorMessage(r));
509                 }
510
511                 if (__url.GetLength() == 0)
512                 {
513                         if (__multiSelection)
514                         {
515                                 ewk_view_popup_menu_multiple_select(__pWebView, null);
516                         }
517                         else
518                         {
519                                 ewk_view_popup_menu_select(__pWebView, __prevIndex);
520                         }
521                 }
522
523                 __pImpl->SendUserEvent(ID_USER_SCRIPT_SELECTBOX_CLOSE, null);
524         }
525
526         return false;
527 }
528
529 bool
530 _SelectBox::OnPreviewKeyPressed(Control& source, const KeyEventInfo& keyEventInfo)
531 {
532         return false;
533 }
534
535 bool
536 _SelectBox::OnPreviewKeyReleased(Control& source, const KeyEventInfo& keyEventInfo)
537 {
538         return false;
539 }
540
541 bool
542 _SelectBox::TranslateKeyEventInfo(Control& source, KeyEventInfo& keyEventInfo)
543 {
544         return false;
545 }
546
547 result
548 _SelectBox::UpdateList(Eina_List* pItems, int prevIndex, bool clearPrevList, bool isGroupdList)
549 {
550         SysTryReturnResult(NID_WEB_CTRL, __pListView, E_INVALID_STATE, "List View is in an invalid state");
551
552         if (clearPrevList)
553         {
554                 __listElementArray.RemoveAll(true);
555                 if (__multiSelection)
556                 {
557                         eina_inarray_flush(__pToggledArray);
558                 }
559         }
560
561         //Create list required for selectBox
562         int itemCount = eina_list_count(pItems);
563         SysTryReturn(NID_WEB_CTRL, itemCount > 0, E_SYSTEM, E_SYSTEM, "[%s]  A system error has been occurred. ItemCount is invalid.", GetErrorMessage(E_SYSTEM));
564
565         bool isSelected = false;
566
567         if (!__multiSelection)
568         {
569                 __prevIndex = prevIndex;
570         }
571
572         for (int itemIndex = 0; itemIndex < itemCount; itemIndex++)
573         {
574                 Ewk_Popup_Menu_Item* pItem = static_cast<Ewk_Popup_Menu_Item*>(eina_list_nth(pItems, itemIndex));
575                 SysTryReturn(NID_WEB_CTRL, pItem, E_SYSTEM, E_SYSTEM, "[%s]  A system error has been occurred. Failed to get item.", GetErrorMessage(E_SYSTEM));
576
577                 if (ewk_popup_menu_item_type_get(pItem) == EWK_POPUP_MENU_ITEM)
578                 {
579                         String text(ewk_popup_menu_item_text_get(pItem));
580
581                         if (__multiSelection)
582                         {
583                                 isSelected = ( ewk_popup_menu_item_selected_get(pItem) == EINA_TRUE ) ? true : false;
584                         }
585                         else
586                         {
587                                 isSelected = (itemIndex == prevIndex) ? true : false;
588                         }
589
590                         if (isGroupdList)
591                         {
592                                 AddListItem(text, _SelectBox::LIST_ITEM_TYPE_GROUP, isSelected);
593                         }
594                         else
595                         {
596                                 AddListItem(text, _SelectBox::LIST_ITEM_TYPE_NORMAL, isSelected);
597                         }
598                 }
599         }
600
601         __pListView->UpdateList();
602
603         return E_SUCCESS;
604 }
605
606
607 }}} // Tizen::Web::Controls