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