Tizen 2.1 base
[framework/web/wrt-plugins-common.git] / src / 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
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 namespace Renderer {
71
72 class PopupRenderer::Impl
73 {
74   public:
75     Impl() :
76         m_popupsToRender(),
77         m_current(),
78         m_initialized(false)
79     {
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         LogInfo("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_text_set(btn, object.getLabel().c_str());
196         elm_object_part_content_set(parent, POPUP_PART_BUTTON1, btn);
197         btn.ConnectMemberSmartCallback(BUTTON_CLICKED_CALLBACK_NAME,
198                                        &Impl::ButtonCallback,
199                                        this,
200                                        reinterpret_cast<void*>(object.getLabelId()));
201         m_createdObjects.push_back(btn);
202     }
203
204     void DoRender(const PopupObject::Button& object1,
205             const PopupObject::Button& object2,
206             EvasObject &parent)
207     {
208         DoRender(object1, parent);
209
210         EvasObject btn2(elm_button_add(parent));
211
212         elm_object_text_set(btn2, object2.getLabel().c_str());
213         elm_object_part_content_set(parent, POPUP_PART_BUTTON2, btn2);
214         btn2.ConnectMemberSmartCallback(BUTTON_CLICKED_CALLBACK_NAME,
215                                         &Impl::ButtonCallback,
216                                         this,
217                                         reinterpret_cast<void*>(object2.getLabelId()));
218         m_createdObjects.push_back(btn2);
219     }
220
221     void DoRender(const PopupObject::Button& object1,
222             const PopupObject::Button& object2,
223             const PopupObject::Button& object3,
224             EvasObject &parent)
225     {
226         DoRender(object1, object2, parent);
227
228         EvasObject btn3(elm_button_add(parent));
229
230         elm_object_text_set(btn3, object3.getLabel().c_str());
231         elm_object_part_content_set(parent, POPUP_PART_BUTTON3, btn3);
232         btn3.ConnectMemberSmartCallback(BUTTON_CLICKED_CALLBACK_NAME,
233                                         &Impl::ButtonCallback,
234                                         this,
235                                         reinterpret_cast<void*>(object3.getLabelId()));
236         m_createdObjects.push_back(btn3);
237     }
238
239     EvasObject getBaseObject()
240     {
241         if (getExternalCanvas() == NULL) {
242             LogInfo("Create old style popup");
243             EvasObject win(elm_win_add(NULL, "Popup", ELM_WIN_DIALOG_BASIC));
244             elm_win_borderless_set(win, EINA_TRUE);
245             elm_win_alpha_set(win, EINA_TRUE);
246             elm_win_raise(win);
247             {
248                 int w, h, x, y;
249                 ecore_x_window_geometry_get(ecore_x_window_root_first_get(),
250                                             &x,
251                                             &y,
252                                             &w,
253                                             &h);
254                 evas_object_resize(win, w, h);
255                 evas_object_move(win, x, y);
256             }
257             m_createdObjects.push_back(win);
258             evas_object_show(win);
259             return win;
260         } else {
261             LogInfo("Create new style popup");
262             EvasObject win(getExternalCanvas());
263             evas_object_show(win);
264             return win;
265         }
266     }
267
268     void DoRender()
269     {
270         if (!m_current && !m_popupsToRender.empty()) {
271             m_current = m_popupsToRender.front();
272             m_popupsToRender.pop();
273
274             m_themeIndexV = 0;
275
276             // preprocessing
277             std::vector<int> countPopupObjects = {0 /* PopupObject::BUTTON */,
278                                                   0 /* PopupObject::LABEL */,
279                                                   0 /* PopupObject::CHECK */};
280             FOREACH(it, m_current->GetPopupObjects()) {
281                 Assert((*it)->getType() < countPopupObjects.size() &&
282                     "Wrong PopupObject assigned");
283                 countPopupObjects[(*it)->getType()]++;
284             }
285             int needsIndexV = countPopupObjects[PopupObject::LABEL] +
286                 countPopupObjects[PopupObject::CHECK];
287
288             EvasObject win = getBaseObject();
289             EvasObject main(elm_popup_add(win));
290
291             evas_object_size_hint_weight_set(main,
292                                              EVAS_HINT_EXPAND,
293                                              EVAS_HINT_EXPAND);
294             elm_object_part_text_set(main,
295                                      POPUP_PART_TITLE,
296                                      m_current->GetTitle().c_str());
297
298             m_createdObjects.push_back(main);
299             std::vector<PopupObject::Button> buttonObjectList;
300             EvasObject layout(create_layout_main(main, needsIndexV));
301             m_createdObjects.push_back(layout);
302
303             FOREACH(it, m_current->GetPopupObjects()) {
304                 switch ((*it)->getType()) {
305                 case PopupObject::BUTTON:
306                     buttonObjectList.push_back(*(*it)->asButton());
307                     break;
308                 case PopupObject::LABEL:
309                     DoRender(*(*it)->asLabel(),
310                              main,
311                              layout,
312                              m_themeIndexV++);
313                     break;
314                 case PopupObject::CHECK:
315                     DoRender(*(*it)->asCheck(),
316                              main,
317                              layout,
318                              m_themeIndexV++);
319                     break;
320                 default:
321                     Assert("incorrect type");
322                 }
323                 Assert(m_themeIndexV <= MAX_NUMBER_OF_VERTICAL);
324             }
325             elm_object_content_set(main,
326                                    layout);
327
328             // show buution
329             switch(buttonObjectList.size()) {
330             case 0:
331                 LogInfo("no button");
332                 break;
333             case 1:
334                 DoRender(buttonObjectList.at(0),
335                          main);
336                 break;
337             case 2:
338                 DoRender(buttonObjectList.at(0),
339                          buttonObjectList.at(1),
340                          main);
341                 break;
342             case 3:
343                 DoRender(buttonObjectList.at(0),
344                          buttonObjectList.at(1),
345                          buttonObjectList.at(2),
346                          main);
347                 break;
348             default:
349                 Assert("incorrect button number");
350                 break;
351             }
352
353             evas_object_show(main);
354         }
355     }
356
357     void setExternalCanvas(void* externalCanvas)
358     {
359         m_externalCanvas = static_cast<Evas_Object*>(externalCanvas);
360     }
361
362     Evas_Object* getExternalCanvas() const
363     {
364         return m_externalCanvas;
365     }
366
367     std::queue<PopupPtr> m_popupsToRender;
368     std::list<EvasObject> m_createdObjects;
369     PopupPtr m_current;
370     bool m_initialized;
371     bool m_checkState;
372     DPL::Optional<std::string> m_password;
373     unsigned int m_themeIndexV;
374
375   private:
376     Evas_Object* m_externalCanvas;
377 };
378
379 PopupRenderer::PopupRenderer()
380 {
381     m_impl = new PopupRenderer::Impl();
382 }
383
384 PopupRenderer::~PopupRenderer()
385 {
386     delete m_impl;
387 }
388
389 void PopupRenderer::Initialize()
390 {
391     Assert(m_impl);
392     m_impl->Initialize();
393 }
394
395 void PopupRenderer::Deinitialize()
396 {
397     Assert(m_impl);
398     m_impl->Deinitialize();
399 }
400
401 IPopupPtr PopupRenderer::CreatePopup()
402 {
403     return std::static_pointer_cast<IPopup>(IPopupPtr
404                                               (new Popup(shared_from_this())));
405 }
406
407 void PopupRenderer::Render(PopupPtr popup)
408 {
409     m_impl->Render(popup);
410 }
411
412 void PopupRenderer::setExternalCanvas(void* externalCanvas)
413 {
414     m_impl->setExternalCanvas(externalCanvas);
415 }
416
417 }
418 } // namespace Popup
419 } // namespace Wrt