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