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