Initialize Tizen 2.3
[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         , __panelHeight(0)
152         , __orientation(_CONTROL_ORIENTATION_PORTRAIT)
153         , __pWebView(null)
154         , __pToggledArray(null)
155         , __url(L"")
156         , __pImpl(null)
157 {
158 }
159
160
161 _SelectBox::~_SelectBox(void)
162 {
163         if (__multiSelection)
164         {
165                 eina_inarray_flush(__pToggledArray);
166                 delete __pToggledArray;
167         }
168
169         __listElementArray.RemoveAll(true);
170 }
171
172
173 result
174 _SelectBox::Construct(Tizen::Web::Controls::_WebImpl* pImpl, bool isMultiSelect, const String& title, int listCount, Evas_Object* pWebView, const String& url)
175 {
176         result r = E_SUCCESS;
177         Rectangle rect;
178
179         int listItemHeight = 0;
180         int listMaxHeihgt = 0;
181         int listViewHeight = 0;
182
183         __pWebView = pWebView;
184         __url = const_cast< String& >(url);
185         __pImpl = pImpl;
186
187         GET_SHAPE_CONFIG(CONTEXTMENU::LIST_ITEM_HEIGHT, __orientation, listItemHeight);
188
189         __multiSelection = isMultiSelect;
190
191         _WebPopupData* pPopupData = _WebPopup::GetPopupData();
192         SysTryReturn(NID_WEB_CTRL, pPopupData, r = GetLastResult(), r, "[%s] Propagating.", GetErrorMessage(r));
193
194         listMaxHeihgt = listCount * listItemHeight;
195
196         rect.height = listMaxHeihgt;
197         rect.width = pPopupData->popupDim.width;
198         rect.x = 0;
199         rect.y = 0;
200
201         r = _WebPopup::Construct(!title.IsEmpty(), Dimension(rect.width, rect.height));
202         SysTryReturn(NID_WEB_CTRL, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
203
204         if (!title.IsEmpty())
205         {
206                 Popup::SetTitleText(title);
207         }
208
209         listViewHeight = listCount * listItemHeight;
210         std::unique_ptr<ListView> pListView(new (std::nothrow) ListView());
211         SysTryReturnResult(NID_WEB_CTRL, pListView.get(), E_OUT_OF_MEMORY, "Memory Allocation failed.");
212
213         r = pListView->Construct(Rectangle(0, 0, GetClientAreaBounds().width, listViewHeight), true, SCROLL_STYLE_FADE_OUT);
214         SysTryReturn(NID_WEB_CTRL, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
215
216         r = __listElementArray.Construct();
217         SysTryReturn(NID_WEB_CTRL, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
218
219         pListView->SetItemProvider(*this);
220         pListView->AddListViewItemEventListener(*this);
221         pListView->SetTextOfEmptyList(L"");
222
223         r = AddControl(*pListView);
224         SysTryReturn(NID_WEB_CTRL, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
225
226         __pListView = pListView.release();
227
228         if (__multiSelection)
229         {
230                 Panel* pButtonPanel = CreateAndAddPanel();
231                 SysTryReturn(NID_WEB_CTRL, pButtonPanel, r = GetLastResult(), r, "[%s] Propagating.", GetErrorMessage(r));
232
233                 __panelHeight = pButtonPanel->GetHeight();
234
235                 _SystemResource* pSysResource = _SystemResource::GetInstance();
236                 SysAssertf(pSysResource != null, "Failed to get _SystemResource instance");
237
238                 ArrayList idList(SingleObjectDeleter);
239                 r = idList.Construct();
240                 SysTryReturn(NID_WEB_CTRL, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
241
242                 idList.Add(*(new Integer(ID_BUTTON_SELECTION)));
243
244                 ArrayList titleList(SingleObjectDeleter);
245                 r = titleList.Construct();
246                 SysTryReturn(NID_WEB_CTRL, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
247
248                 titleList.Add(*(new String(pSysResource->GetString(_RESOURCE_DOMAIN_ID_OSP, "IDS_TPLATFORM_BUTTON_OK"))));
249
250                 __pToggledArray = eina_inarray_new(sizeof(int), 0);
251                 SysTryReturnResult(NID_WEB_CTRL, __pToggledArray, E_OUT_OF_MEMORY, "Memory Allocation failed.");
252
253                 r = CreateAndAddButtons(idList, titleList, pButtonPanel);
254                 SysTryReturn(NID_WEB_CTRL, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
255
256                 SetSize(GetSize().width,GetSize().height + __panelHeight);
257         }
258
259         SetPropagatedKeyEventListener(this);
260         
261         return r;
262 }
263
264 result
265 _SelectBox::AddListItem(const String& itemText, int itemType, bool slected)
266 {
267         result r = E_SUCCESS;
268         std::unique_ptr<_ListElement> pListElement(new (std::nothrow) _ListElement(itemText));
269         SysTryReturnResult(NID_WEB_CTRL, pListElement.get(), E_OUT_OF_MEMORY, "Memory Allocation failed.");
270
271         pListElement->ListElementSetItemType(itemType);
272         pListElement->ListElementSetItemSelected(slected);
273
274         r = __listElementArray.Add(*pListElement);
275         SysTryReturn(NID_WEB_CTRL, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r));
276
277         pListElement.release();
278         return r;
279 }
280
281
282 IList*
283 _SelectBox::GetSelectedListN(void) const
284 {
285         result r = E_SUCCESS;
286
287         std::unique_ptr<ArrayList, AllElementsDeleter> pSelectedList(new (std::nothrow) ArrayList());
288         SysTryReturn(NID_WEB_CTRL, pSelectedList.get(), null, E_OUT_OF_MEMORY, "[%s] Memory Allocation failed.",GetErrorMessage(E_OUT_OF_MEMORY));
289
290         r = pSelectedList->Construct();
291         SysTryReturn(NID_WEB_CTRL, r == E_SUCCESS, null, r, "[%s] Propagating.", GetErrorMessage(r));
292
293         for (int index = 0; index < __pListView->GetItemCount(); index++)
294         {
295                 if (__pListView->IsItemChecked(index))
296                 {
297                         std::unique_ptr<Integer> pIdxResult(new (std::nothrow) Integer(index));
298                         SysTryReturn(NID_WEB_CTRL, pIdxResult.get(), null, E_OUT_OF_MEMORY, "[%s] Memory Allocation failed.",GetErrorMessage(E_OUT_OF_MEMORY));
299
300                         r = pSelectedList->Add(*pIdxResult);
301                         SysTryReturn(NID_WEB_CTRL, r == E_SUCCESS, null, r, "[%s] Memory Allocation failed.",GetErrorMessage(r));
302
303                         pIdxResult.release();
304                 }
305         }
306
307         return pSelectedList.release();
308 }
309
310
311 //IListViewItemProvider
312 ListItemBase*
313 _SelectBox::CreateItem(int index, int itemWidth)
314 {
315         result r = E_SUCCESS;
316         int listItemXPos = 0;
317         int listItemYPos = 0;
318         int checkBoxWidth = 0;
319         int listItemHeight = 0;
320         int popupBetweenListNBtnGap = 0;
321
322         ListAnnexStyle subStyle = (__multiSelection) ? LIST_ANNEX_STYLE_MARK : LIST_ANNEX_STYLE_NORMAL;
323         ListAnnexStyle groupStyle = LIST_ANNEX_STYLE_NORMAL;
324
325         _ListElement* pListElement = static_cast< _ListElement* >(__listElementArray.GetAt(index));
326         SysTryReturn(NID_WEB_CTRL, pListElement, null, GetLastResult(), "[%s] Propagating.", GetErrorMessage(GetLastResult()));
327
328         GET_SHAPE_CONFIG(CONTEXTMENU::LIST_ITEM_HEIGHT, __orientation, listItemHeight);
329         GET_SHAPE_CONFIG(LISTVIEW::ITEM_ELEMENT_LEFT_MARGIN, __orientation, listItemXPos);
330         GET_SHAPE_CONFIG(LIST::LIST_CHECK_ITEM_WIDTH, __orientation, checkBoxWidth);
331         GET_SHAPE_CONFIG(MESSAGEBOX::BUTTON_TOP_MARGIN, __orientation, popupBetweenListNBtnGap);
332
333         std::unique_ptr<CustomItem> pItem(new (std::nothrow) CustomItem());
334         SysTryReturn(NID_WEB_CTRL, pItem.get(), null, E_OUT_OF_MEMORY, "[%s] Memory Allocation failed.",GetErrorMessage(E_OUT_OF_MEMORY));
335
336         int itemType = pListElement->ListElementGetItemType();
337         Rectangle popupRect = this->GetClientAreaBounds();
338
339         int listTxtMaxWidth = popupRect.width - listItemXPos - checkBoxWidth - popupBetweenListNBtnGap;
340
341         switch (itemType)
342         {
343         case LIST_ITEM_TYPE_NORMAL:
344         //fall through
345         case LIST_ITEM_TYPE_SUB:
346                 r = pItem->Construct(Dimension(itemWidth, listItemHeight), subStyle);
347                 SysTryReturn(NID_WEB_CTRL, r == E_SUCCESS, null, r, "[%s] Propagating.", GetErrorMessage(r));
348                 break;
349
350         case LIST_ITEM_TYPE_GROUP:
351                 SysLog(NID_WEB_CTRL, "The current value of index [%d] [%d]", index, pListElement->ListElementIsItemEnabled());
352                 r = pItem->Construct(Dimension(itemWidth, listItemHeight), groupStyle);
353                 SysTryReturn(NID_WEB_CTRL, r == E_SUCCESS, null, r, "[%s] Propagating.", GetErrorMessage(r));
354                 break;
355
356         default:
357                 return null;
358         }
359
360         String elementString = pListElement->ListElementGetString();
361
362         if (elementString.IsEmpty())
363         {
364                 elementString.Append(L" ");
365         }
366
367         r = pItem->AddElement(Rectangle(listItemXPos, listItemYPos, listTxtMaxWidth, listItemHeight),
368                                                   ID_FORMAT_STRING, elementString, true);
369         SysTryReturn(NID_WEB_CTRL, r == E_SUCCESS, null, r, "[%s] Propagating.", GetErrorMessage(r));
370
371         if (IsMultiSelectable())
372         {
373                 r = __pListView->SetItemChecked(index, pListElement->ListElementIsItemSelected());
374                 SysTryReturn(NID_WEB_CTRL, r == E_SUCCESS, null, r, "[%s] Propagating.", GetErrorMessage(r));
375         }
376
377         r = __pListView->SetItemEnabled(index, !(itemType == LIST_ITEM_TYPE_GROUP));
378         SysTryReturn(NID_WEB_CTRL, r == E_SUCCESS, null, r, "[%s] Propagating.", GetErrorMessage(r));
379
380         return pItem.release();
381 }
382
383
384 bool
385 _SelectBox::DeleteItem(int index, ListItemBase* pItem, int itemWidth)
386 {
387         delete pItem;
388         pItem = null;
389
390         return true;
391 }
392
393
394 int
395 _SelectBox::GetItemCount(void)
396 {
397         return __listElementArray.GetCount();
398 }
399
400
401 void
402 _SelectBox::OnListViewContextItemStateChanged(ListView& listView, int index, int elementId, ListContextItemStatus state)
403 {
404 }
405
406
407 void
408 _SelectBox::OnListViewItemStateChanged(ListView& listView, int index, int elementId, ListItemStatus status)
409 {
410         if (__multiSelection)
411         {
412                 int pos = eina_inarray_search(__pToggledArray, &index, CompareChangedItems);
413
414                 if (pos == POSITION_INVALID)
415                 {
416                         eina_inarray_push(__pToggledArray, &index);
417                 }
418                 else
419                 {
420                         eina_inarray_remove(__pToggledArray, &index);
421                 }
422         }
423         else
424         {
425                 //In case of single selection ... update the index.
426                 if (__url.GetLength() == 0)
427                 {
428                         __SelectedIndex = index;
429                         SysLog(NID_WEB_CTRL,"The current value of Update Selected index is %d",index);
430                         if (__pWebView)
431                         {
432                                 ewk_view_popup_menu_select(__pWebView, __SelectedIndex);
433                         }
434                 }
435                 else
436                 {
437                         result r = E_SUCCESS;
438
439                         RequestId reqId = 0;
440                         DownloadRequest request(__url);
441
442                         _DownloadManagerImpl* pManagerImpl = _DownloadManagerImpl::GetInstance();
443                         SysTryReturnVoidResult(NID_WEB_CTRL, pManagerImpl, GetLastResult(), "[%s] Propagating.", GetErrorMessage(GetLastResult()));
444
445                         r = pManagerImpl->Start(request, reqId);
446                         SysTryReturnVoidResult(NID_WEB_CTRL, r == E_SUCCESS, r, "[%s] Propagating.", GetErrorMessage(r));
447                 }
448
449                 result r = HidePopup();
450                 SysTryReturnVoidResult(NID_WEB_CTRL, r == E_SUCCESS, r, "[%s] Propagating.", GetErrorMessage(r));
451                 
452                 __pImpl->SendUserEvent(ID_USER_SCRIPT_SELECTBOX_CLOSE, null);
453         }
454 }
455
456
457 void
458 _SelectBox::OnListViewItemSwept(ListView& listView, int index, SweepDirection direction)
459 {
460
461 }
462
463
464 void
465 _SelectBox::OnActionPerformed(const Control& source, int actionId)
466 {
467         result r = HidePopup();
468         SysTryReturnVoidResult(NID_WEB_CTRL, r == E_SUCCESS, r, "[%s] Propagating.", GetErrorMessage(r));
469
470         if (__url.GetLength() == 0)
471         {
472                 switch (actionId)
473                 {
474                 case ID_BUTTON_SELECTION:
475                 {
476                         ewk_view_popup_menu_multiple_select(__pWebView, __pToggledArray);
477                         break;
478                 }
479                 case ID_BUTTON_CANCEL:
480                 {
481                         if (__multiSelection)
482                         {
483                                 ewk_view_popup_menu_multiple_select(__pWebView, null);
484                         }
485                         else
486                         {
487                                 ewk_view_popup_menu_select(__pWebView, __prevIndex);
488                         }
489                         break;
490                 }
491                 default:
492                         SysAssertf(false, "Invalid Action ID");
493                 }
494         }
495
496         __pImpl->SendUserEvent(ID_USER_SCRIPT_SELECTBOX_CLOSE, null);
497 }
498
499 bool
500 _SelectBox::OnKeyPressed(Control& source, const KeyEventInfo& keyEventInfo)
501 {
502         return false;
503 }
504
505 bool
506 _SelectBox::OnKeyReleased(Control& source, const KeyEventInfo& keyEventInfo)
507 {
508         if ((keyEventInfo.GetKeyCode() == KEY_ESC || keyEventInfo.GetKeyCode() == KEY_BACK) && source.GetShowState() == true)
509         {
510                 result r = HidePopup();
511                 if (IsFailed(r))
512                 {
513                         SysLogException(NID_WEB_CTRL, r, "[%s] Propagating.", GetErrorMessage(r));
514                 }
515
516                 if (__url.GetLength() == 0)
517                 {
518                         if (__multiSelection)
519                         {
520                                 ewk_view_popup_menu_multiple_select(__pWebView, null);
521                         }
522                         else
523                         {
524                                 ewk_view_popup_menu_select(__pWebView, __prevIndex);
525                         }
526                 }
527
528                 __pImpl->SendUserEvent(ID_USER_SCRIPT_SELECTBOX_CLOSE, null);
529         }
530
531         return false;
532 }
533
534 bool
535 _SelectBox::OnPreviewKeyPressed(Control& source, const KeyEventInfo& keyEventInfo)
536 {
537         return false;
538 }
539
540 bool
541 _SelectBox::OnPreviewKeyReleased(Control& source, const KeyEventInfo& keyEventInfo)
542 {
543         return false;
544 }
545
546 bool
547 _SelectBox::TranslateKeyEventInfo(Control& source, KeyEventInfo& keyEventInfo)
548 {
549         return false;
550 }
551
552 result
553 _SelectBox::UpdateList(Eina_List* pItems, int prevIndex, bool clearPrevList, bool isGroupdList)
554 {
555         SysTryReturnResult(NID_WEB_CTRL, __pListView, E_INVALID_STATE, "List View is in an invalid state");
556
557         if (clearPrevList)
558         {
559                 __listElementArray.RemoveAll(true);
560                 if (__multiSelection)
561                 {
562                         eina_inarray_flush(__pToggledArray);
563                 }
564         }
565
566         //Create list required for selectBox
567         int itemCount = eina_list_count(pItems);
568         SysTryReturn(NID_WEB_CTRL, itemCount > 0, E_SYSTEM, E_SYSTEM, "[%s]  A system error has been occurred. ItemCount is invalid.", GetErrorMessage(E_SYSTEM));
569
570         bool isSelected = false;
571
572         if (!__multiSelection)
573         {
574                 __prevIndex = prevIndex;
575         }
576
577         for (int itemIndex = 0; itemIndex < itemCount; itemIndex++)
578         {
579                 Ewk_Popup_Menu_Item* pItem = static_cast<Ewk_Popup_Menu_Item*>(eina_list_nth(pItems, itemIndex));
580                 SysTryReturn(NID_WEB_CTRL, pItem, E_SYSTEM, E_SYSTEM, "[%s]  A system error has been occurred. Failed to get item.", GetErrorMessage(E_SYSTEM));
581
582                 if (ewk_popup_menu_item_type_get(pItem) == EWK_POPUP_MENU_ITEM)
583                 {
584                         String text(ewk_popup_menu_item_text_get(pItem));
585
586                         if (__multiSelection)
587                         {
588                                 isSelected = ( ewk_popup_menu_item_selected_get(pItem) == EINA_TRUE ) ? true : false;
589                         }
590                         else
591                         {
592                                 isSelected = (itemIndex == prevIndex) ? true : false;
593                         }
594
595                         if (isGroupdList)
596                         {
597                                 AddListItem(text, _SelectBox::LIST_ITEM_TYPE_GROUP, isSelected);
598                         }
599                         else
600                         {
601                                 AddListItem(text, _SelectBox::LIST_ITEM_TYPE_NORMAL, isSelected);
602                         }
603                 }
604         }
605
606         int listItemHeight = 0;
607         GET_SHAPE_CONFIG(CONTEXTMENU::LIST_ITEM_HEIGHT, __orientation, listItemHeight);
608         int prevCount = (__pListView->GetSize()).height / listItemHeight;
609         int defaultCount = __multiSelection ? DEFAULT_LIST_ITEM_COUNT -1 : DEFAULT_LIST_ITEM_COUNT;
610
611         if ((prevCount != itemCount)
612                 && ((prevCount < defaultCount && itemCount < defaultCount)
613                 || (prevCount < defaultCount && itemCount >= defaultCount)
614                 || (prevCount >= defaultCount && itemCount < defaultCount)))
615         {
616                 int listViewNewHeight = ((itemCount < defaultCount) ? itemCount : defaultCount) * listItemHeight;
617                 int popupHeight = __multiSelection ? (listViewNewHeight + __panelHeight) : listViewNewHeight;
618
619                 __pListView->SetSize((__pListView->GetSize()).width, listViewNewHeight);
620                 SetSize(GetSize().width, popupHeight);
621         }
622
623         __pListView->UpdateList();
624
625         return E_SUCCESS;
626 }
627
628
629 }}} // Tizen::Web::Controls