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