716676ebefe93417fb5ba83ec9f87048f0d33912
[framework/web/wrt-commons.git] / modules / popup / src / popup_renderer.cpp
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *    Licensed under the Apache License, Version 2.0 (the "License");
5  *    you may not use this file except in compliance with the License.
6  *    You may obtain a copy of the License at
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *    Unless required by applicable law or agreed to in writing, software
11  *    distributed under the License is distributed on an "AS IS" BASIS,
12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *    See the License for the specific language governing permissions and
14  *    limitations under the License.
15  */
16 /*
17  * @file        popup_renderer.cpp
18  * @author      Lukasz Wrzosek (l.wrzosek@samsung.com)
19  * @version     1.0
20  * @brief       This is efl specific implementation for PopupRenderer
21  */
22
23 #include <dpl/popup/popup_manager.h>
24 #include <dpl/popup/popup_renderer.h>
25 #include <dpl/popup/popup_manager.h>
26 #include <dpl/popup/evas_object.h>
27 #include <dpl/shared_ptr.h>
28 #include <dpl/scoped_array.h>
29 #include <dpl/assert.h>
30 #include <dpl/log/log.h>
31 #include <dpl/foreach.h>
32 #include <dpl/framework_efl.h>
33 #include <dpl/lexical_cast.h>
34 #include <queue>
35
36 namespace DPL {
37
38 namespace {
39 using namespace Popup;
40 const char* EDJ_NAME = "/usr/share/edje/ace/generic_popup.edj";
41 const char* POPUP_LAYOUT1 = "popup_layout1";
42 const char* POPUP_LAYOUT2 = "popup_layout2";
43 const char* POPUP_PART_TITLE = "title,text";
44 const char* POPUP_PART_BUTTON1 = "button1";
45 const char* POPUP_PART_BUTTON2 = "button2";
46 const char* POPUP_PART_BUTTON3 = "button3";
47 const char* BUTTON_CLICKED_CALLBACK_NAME = "clicked";
48 const char* CHANGED_CALLBACK_NAME = "changed";
49 const unsigned int MAX_NUMBER_OF_VERTICAL = 2;
50
51 Evas_Object* create_layout_main(Evas_Object* parent, int totalV)
52 {
53     Evas_Object *layout = elm_layout_add(parent);
54
55     if (totalV == 1) {
56         elm_layout_file_set(layout, EDJ_NAME, POPUP_LAYOUT1);
57     } else if (totalV == 2) {
58         elm_layout_file_set(layout, EDJ_NAME, POPUP_LAYOUT2);
59     } else {
60         Assert("popup needs define new group in the edc");
61     }
62
63     evas_object_size_hint_weight_set(layout, EVAS_HINT_EXPAND,
64                                      EVAS_HINT_EXPAND);
65     return layout;
66 }
67 } //namespace
68
69 namespace Popup {
70 class PopupRenderer::Impl
71 {
72   public:
73     Impl() :
74         m_popupsToRender(),
75         m_current(),
76         m_initialized(false)
77     {
78     }
79
80     ~Impl()
81     {
82         Assert(!m_initialized);
83     }
84
85     void Initialize()
86     {
87         Assert(!m_initialized);
88         m_initialized = true;
89     }
90
91     void Deinitialize()
92     {
93         Assert(m_initialized);
94         m_current.Reset(NULL);
95         while (!m_popupsToRender.empty()) {
96             m_popupsToRender.pop();
97         }
98         m_initialized = false;
99     }
100
101     void ButtonCallback(EvasObject::IConnection* /*connection*/,
102             void* /*event_info*/,
103             void* data)
104     {
105         LogInfo("ButtonCallback");
106         Assert(m_initialized);
107         AnswerCallbackData answerData;
108
109         answerData.buttonAnswer = reinterpret_cast<int>(data);
110         answerData.chackState = m_checkState;
111         answerData.password = m_password;
112         m_current->ForwardAnswer(answerData);
113         m_current.Reset();
114
115         FOREACH(it, m_createdObjects)
116         {
117             if (it->IsValid()) {
118                 evas_object_del(*it);
119             }
120         }
121         m_createdObjects.clear();
122         m_checkState = false;
123         DoRender();
124     }
125
126     void CheckCallback(EvasObject::IConnection* connection,
127             void* /*event_info*/,
128             void* /* unused */)
129     {
130         m_checkState =
131             elm_check_state_get(connection->GetEvasObject());
132     }
133
134     void Render (PopupPtr popup)
135     {
136         Assert(m_initialized);
137         m_popupsToRender.push(popup);
138         DoRender();
139     }
140
141     void DoRender(const PopupObject::Label& object,
142             EvasObject& parent,
143             EvasObject& layout,
144             int themeIndex)
145     {
146         EvasObject label(elm_label_add(parent));
147
148         elm_object_style_set(label, "popup_description/default");
149         elm_label_line_wrap_set(label, ELM_WRAP_WORD);
150         elm_object_text_set(label, object.getLabel().c_str());
151         evas_object_size_hint_weight_set(label, EVAS_HINT_EXPAND, 0.0);
152         evas_object_size_hint_align_set(label, EVAS_HINT_FILL, EVAS_HINT_FILL);
153         evas_object_show(label);
154
155         elm_object_part_content_set(
156             layout,
157             DPL::lexical_cast<std::string>(themeIndex).c_str(),
158             label);
159         m_createdObjects.push_back(label);
160     }
161
162     void DoRender(const PopupObject::Check& object,
163             EvasObject& parent,
164             EvasObject& layout,
165             int themeIndex)
166     {
167         EvasObject check(elm_check_add(parent));
168
169         evas_object_size_hint_align_set(check, EVAS_HINT_FILL, EVAS_HINT_FILL);
170         evas_object_size_hint_weight_set(check, EVAS_HINT_EXPAND, 0.0);
171         elm_object_text_set(check,
172                             object.getCheckLabel().c_str());
173         elm_object_part_content_set(
174             layout,
175             DPL::lexical_cast<std::string>(themeIndex).c_str(),
176             check);
177
178         check.ConnectMemberSmartCallback(CHANGED_CALLBACK_NAME,
179                                          &Impl::CheckCallback,
180                                          this,
181                                          static_cast<void*>(NULL));
182         evas_object_show(check);
183         m_createdObjects.push_back(check);
184     }
185
186     void DoRender(const PopupObject::Button& object,
187             EvasObject &parent)
188     {
189         EvasObject btn(elm_button_add(parent));
190
191         elm_object_text_set(btn, object.getLabel().c_str());
192         elm_object_part_content_set(parent, POPUP_PART_BUTTON1, btn);
193         btn.ConnectMemberSmartCallback(BUTTON_CLICKED_CALLBACK_NAME,
194                                        &Impl::ButtonCallback,
195                                        this,
196                                        reinterpret_cast<void*>(object.getLabelId()));
197         m_createdObjects.push_back(btn);
198     }
199
200     void DoRender(const PopupObject::Button& object1,
201             const PopupObject::Button& object2,
202             EvasObject &parent)
203     {
204         EvasObject btn1(elm_button_add(parent));
205         EvasObject btn2(elm_button_add(parent));
206
207         elm_object_text_set(btn1, object1.getLabel().c_str());
208         elm_object_part_content_set(parent, POPUP_PART_BUTTON1, btn1);
209         btn1.ConnectMemberSmartCallback(BUTTON_CLICKED_CALLBACK_NAME,
210                                         &Impl::ButtonCallback,
211                                         this,
212                                         reinterpret_cast<void*>(object1.getLabelId()));
213
214         elm_object_text_set(btn2, object2.getLabel().c_str());
215         elm_object_part_content_set(parent, POPUP_PART_BUTTON2, btn2);
216         btn2.ConnectMemberSmartCallback(BUTTON_CLICKED_CALLBACK_NAME,
217                                         &Impl::ButtonCallback,
218                                         this,
219                                         reinterpret_cast<void*>(object2.getLabelId()));
220         m_createdObjects.push_back(btn1);
221         m_createdObjects.push_back(btn2);
222     }
223
224     void DoRender(const PopupObject::Button& object1,
225             const PopupObject::Button& object2,
226             const PopupObject::Button& object3,
227             EvasObject &parent)
228     {
229         EvasObject btn1(elm_button_add(parent));
230         EvasObject btn2(elm_button_add(parent));
231         EvasObject btn3(elm_button_add(parent));
232
233         elm_object_text_set(btn1, object1.getLabel().c_str());
234         elm_object_part_content_set(parent, POPUP_PART_BUTTON1, btn1);
235         btn1.ConnectMemberSmartCallback(BUTTON_CLICKED_CALLBACK_NAME,
236                                         &Impl::ButtonCallback,
237                                         this,
238                                         reinterpret_cast<void*>(object1.getLabelId()));
239
240         elm_object_text_set(btn2, object2.getLabel().c_str());
241         elm_object_part_content_set(parent, POPUP_PART_BUTTON2, btn2);
242         btn2.ConnectMemberSmartCallback(BUTTON_CLICKED_CALLBACK_NAME,
243                                         &Impl::ButtonCallback,
244                                         this,
245                                         reinterpret_cast<void*>(object2.getLabelId()));
246
247         elm_object_text_set(btn3, object3.getLabel().c_str());
248         elm_object_part_content_set(parent, POPUP_PART_BUTTON3, btn3);
249         btn3.ConnectMemberSmartCallback(BUTTON_CLICKED_CALLBACK_NAME,
250                                         &Impl::ButtonCallback,
251                                         this,
252                                         reinterpret_cast<void*>(object3.getLabelId()));
253         m_createdObjects.push_back(btn1);
254         m_createdObjects.push_back(btn2);
255         m_createdObjects.push_back(btn3);
256     }
257
258     EvasObject getBaseObject()
259     {
260         if (getExternalCanvas() == NULL) {
261             LogInfo("Create old style popup");
262             EvasObject win(elm_win_add(NULL, "Popup", ELM_WIN_DIALOG_BASIC));
263             elm_win_borderless_set(win, EINA_TRUE);
264             elm_win_alpha_set(win, EINA_TRUE);
265             elm_win_raise(win);
266             {
267                 int w, h, x, y;
268                 ecore_x_window_geometry_get(ecore_x_window_root_first_get(),
269                                             &x,
270                                             &y,
271                                             &w,
272                                             &h);
273                 evas_object_resize(win, w, h);
274                 evas_object_move(win, x, y);
275             }
276             m_createdObjects.push_back(win);
277             evas_object_show(win);
278             return win;
279         } else {
280             LogInfo("Create new style popup");
281             EvasObject win(getExternalCanvas());
282             evas_object_show(win);
283             return win;
284         }
285     }
286
287     void DoRender()
288     {
289         if (!m_current && !m_popupsToRender.empty()) {
290             m_current = m_popupsToRender.front();
291             m_popupsToRender.pop();
292
293             m_themeIndexV = 0;
294
295             // preprocessing
296             std::vector<int> countPopupObjects = {0 /* PopupObject::BUTTON */,
297                                                   0 /* PopupObject::LABEL */,
298                                                   0 /* PopupObject::CHECK */};
299             FOREACH(it, m_current->GetPopupObjects()) {
300                 Assert((*it)->getType() < countPopupObjects.size() &&
301                     "Wrong PopupObject assigned");
302                 countPopupObjects[(*it)->getType()]++;
303             }
304             int needsIndexV = countPopupObjects[PopupObject::LABEL] +
305                 countPopupObjects[PopupObject::CHECK];
306
307             EvasObject win = getBaseObject();
308             EvasObject main(elm_popup_add(win));
309
310             evas_object_size_hint_weight_set(main,
311                                              EVAS_HINT_EXPAND,
312                                              EVAS_HINT_EXPAND);
313             elm_object_part_text_set(main,
314                                      POPUP_PART_TITLE,
315                                      m_current->GetTitle().c_str());
316
317             m_createdObjects.push_back(main);
318             std::vector<PopupObject::Button> buttonObjectList;
319             EvasObject layout(create_layout_main(main, needsIndexV));
320             m_createdObjects.push_back(layout);
321
322             FOREACH(it, m_current->GetPopupObjects()) {
323                 switch ((*it)->getType()) {
324                 case PopupObject::BUTTON:
325                     buttonObjectList.push_back(*(*it)->asButton());
326                     break;
327                 case PopupObject::LABEL:
328                     DoRender(*(*it)->asLabel(),
329                              main,
330                              layout,
331                              m_themeIndexV++);
332                     break;
333                 case PopupObject::CHECK:
334                     DoRender(*(*it)->asCheck(),
335                              main,
336                              layout,
337                              m_themeIndexV++);
338                     break;
339                 default:
340                     Assert("incorrect type");
341                 }
342                 Assert(m_themeIndexV <= MAX_NUMBER_OF_VERTICAL);
343             }
344             elm_object_content_set(main,
345                                    layout);
346
347             // show buution
348             switch(buttonObjectList.size()) {
349             case 0:
350                 LogInfo("no button");
351                 break;
352             case 1:
353                 DoRender(buttonObjectList.at(0),
354                          main);
355                 break;
356             case 2:
357                 DoRender(buttonObjectList.at(0),
358                          buttonObjectList.at(1),
359                          main);
360                 break;
361             case 3:
362                 DoRender(buttonObjectList.at(0),
363                          buttonObjectList.at(1),
364                          buttonObjectList.at(2),
365                          main);
366                 break;
367             default:
368                 Assert("incorrect button number");
369                 break;
370             }
371
372             evas_object_show(main);
373         }
374     }
375
376     void setExternalCanvas(void* externalCanvas)
377     {
378         m_externalCanvas = static_cast<Evas_Object*>(externalCanvas);
379     }
380
381     Evas_Object* getExternalCanvas() const
382     {
383         return m_externalCanvas;
384     }
385
386     std::queue<PopupPtr> m_popupsToRender;
387     std::list<EvasObject> m_createdObjects;
388     PopupPtr m_current;
389     bool m_initialized;
390     bool m_checkState;
391     DPL::Optional<std::string> m_password;
392     unsigned int m_themeIndexV;
393
394   private:
395     Evas_Object* m_externalCanvas;
396 };
397
398 PopupRenderer::PopupRenderer()
399 {
400     m_impl = new PopupRenderer::Impl();
401 }
402
403 PopupRenderer::~PopupRenderer()
404 {
405     delete m_impl;
406 }
407
408 void PopupRenderer::Initialize()
409 {
410     Assert(m_impl);
411     m_impl->Initialize();
412 }
413
414 void PopupRenderer::Deinitialize()
415 {
416     Assert(m_impl);
417     m_impl->Deinitialize();
418 }
419
420 IPopupPtr PopupRenderer::CreatePopup()
421 {
422     return DPL::StaticPointerCast<IPopup>(IPopupPtr
423                                               (new Popup(SharedFromThis())));
424 }
425
426 void PopupRenderer::Render(PopupPtr popup)
427 {
428     m_impl->Render(popup);
429 }
430
431 void PopupRenderer::setExternalCanvas(void* externalCanvas)
432 {
433     m_impl->setExternalCanvas(externalCanvas);
434 }
435
436 } // namespace Popup
437 } // namespace DPL