1be14b6ab9336b5615792737f6817240febf6204
[platform/framework/web/wrt.git] / src / wrt-client / window_data.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        window_data.cpp
18  * @author      Jaroslaw Osmanski (j.osmanski@samsung.com)
19  * @version     1.0
20  * @brief       Window data class implementation
21  */
22 #include "window_data.h"
23
24 #include <ui-gadget.h>
25 #include <dpl/log/log.h>
26 #include <dpl/foreach.h>
27
28 namespace {
29 char const* const PLATFORM_EDJ_PATH = "/usr/share/edje/wrt/Platform.edj";
30 char const* const DAEMON_EDJ_PATH = "/usr/share/edje/wrt/Daemon.edj";
31 char const* const THEME_EDJ_PATH = "/usr/share/edje/wrt/wrt_theme.edj";
32 char const* const ELM_STATE_SHOW_CONTENT = "elm,state,show,content";
33 char const* const ELM_SWALLOW_CONTENT = "elm.swallow.content";
34 char const* const ELM_SWALLOW_BACKWARD = "elm.swallow.backward";
35 char const* const ELM_SWALLOW_PROGRESS = "elm.swallow.progress";
36 char const* const ELM_STATE_TOOLBAR_INSTANT_OPEN = "elm,state,toolbar,instant_open";
37 char const* const ELM_STATE_TOOLBAR_INSTANT_CLOSE = "elm,state,toolbar,instant_close";
38
39 const char *ELM_EVENT_PROFILE_CHANGED = "profile,changed";
40
41 char const* const ELM = "elm";
42 char const* const LAYOUT = "layout";
43 char const* const APPLICATION = "application";
44 char const* const INDICATOR = "indicator";
45 char const* const NOINDICATOR = "noindicator";
46 char const* const INTERNAL_LAYOUT = "internal_layout";
47 char const* const FLOATBACKWARD_BUTTON_STYLE = "wrt/backward";
48 const std::string DESKTOP_PROFILE("desktop");
49 const int PROGRESS_H = 10;
50 } // anonymous namespace
51
52 WindowData::WindowData(unsigned long pid, bool manualInit) :
53     m_win(NULL),
54     m_user_layout(NULL),
55     m_conformant(NULL),
56     m_platform_layout(NULL),
57     m_navigation(NULL),
58     m_floatBackButton(NULL),
59     m_progressbar(NULL),
60     m_ctxpopup(NULL),
61     m_initialized(false)
62 {
63     m_win = createWindow(pid);
64
65     if (!manualInit) {
66         init();
67     }
68 }
69
70 WindowData::~WindowData()
71 {
72     LogDebug("");
73     evas_object_del(m_win);
74 }
75
76 void WindowData::init()
77 {
78     Assert(m_win != NULL && "m_win is null");
79
80     if (m_initialized == true)
81     {
82         LogInfo("Already initilized");
83         return;
84     }
85
86     // import button theme
87     elm_theme_overlay_add(NULL, THEME_EDJ_PATH);
88
89     m_conformant = createConformant(m_win);
90     evas_object_show(m_conformant);
91     m_platform_layout = createPlatformLayout(m_conformant);
92     evas_object_show(m_platform_layout);
93     m_navigation = createNavigationBar(m_platform_layout);
94     evas_object_show(m_navigation);
95     m_user_layout = createUserLayout(m_navigation);
96     evas_object_show(m_user_layout);
97     m_focus = createFocus(m_user_layout);
98     evas_object_show(m_focus);
99     m_progressbar = createProgressBar(m_win, m_user_layout);
100     evas_object_show(m_progressbar);
101
102     UG_INIT_EFL(m_win, UG_OPT_INDICATOR_ENABLE);
103     m_initialized = true;
104 }
105
106 void WindowData::setEvasObjectForLayout(Evas_Object* obj)
107 {
108     elm_object_part_content_set(m_focus, ELM_SWALLOW_CONTENT, obj);
109     elm_object_focus_set(m_focus, EINA_TRUE);
110 }
111
112 void WindowData::unsetEvasObjectForLayout()
113 {
114     elm_object_part_content_unset(m_focus, ELM_SWALLOW_CONTENT);
115 }
116
117 void WindowData::toggleIndicator(bool fullscreen)
118 {
119     LogDebug("fullscreen=" << (fullscreen ? "true" : "false"));
120
121     if (!fullscreen) {
122         elm_win_indicator_mode_set(m_win, ELM_WIN_INDICATOR_SHOW);
123     } else {
124         elm_win_indicator_mode_set(m_win, ELM_WIN_INDICATOR_HIDE);
125     }
126 }
127
128 void WindowData::setViewMode(
129     bool fullscreen,
130     bool backbutton)
131 {
132     LogDebug("setViewMode");
133     LogDebug("fullscreen: " << fullscreen);
134     LogDebug("backbutton: " << backbutton);
135
136     toggleIndicator(fullscreen);
137 }
138
139 void WindowData::setOrientation(int angle)
140 {
141     LogDebug("setOrientation");
142     Assert(m_win);
143     elm_win_wm_rotation_preferred_rotation_set(
144         m_win,
145         angle);
146 }
147
148 void WindowData::createFloatBackButton()
149 {
150     // Add float backbutton on the left coner
151     m_floatBackButton = elm_button_add(m_user_layout);
152     elm_object_style_set(m_floatBackButton, FLOATBACKWARD_BUTTON_STYLE);
153     elm_object_part_content_set(m_user_layout,
154                                 ELM_SWALLOW_BACKWARD,
155                                 m_floatBackButton);
156     evas_object_show(m_floatBackButton);
157 }
158
159 Evas_Object* WindowData::createWindow(unsigned long pid)
160 {
161     ADD_PROFILING_POINT("elm_win_add", "start");
162     Evas_Object* window = elm_win_add(NULL, "wrt-widget", ELM_WIN_BASIC);
163     ADD_PROFILING_POINT("elm_win_add", "stop");
164     ecore_x_window_prop_property_set(
165         elm_win_xwindow_get(window),
166         ECORE_X_ATOM_NET_WM_PID,
167         ECORE_X_ATOM_CARDINAL, 32, &pid, 1);
168     elm_win_conformant_set(window, EINA_TRUE);
169     int w, h;
170     ecore_x_window_size_get(ecore_x_window_root_first_get(), &w, &h);
171     evas_object_resize(window, w, h);
172
173     evas_object_smart_callback_add(window,
174                                    ELM_EVENT_PROFILE_CHANGED,
175                                    winProfileChangedCallback,
176                                    this);
177     return window;
178 }
179
180 Evas_Object* WindowData::createConformant(Evas_Object* parent)
181 {
182     Assert(parent != NULL && "Parent is null");
183     Evas_Object* conformant = elm_conformant_add(parent);
184
185     evas_object_size_hint_weight_set(
186         conformant, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
187     evas_object_size_hint_align_set(conformant, EVAS_HINT_FILL, EVAS_HINT_FILL);
188     elm_win_resize_object_add(parent, conformant);
189     return conformant;
190 }
191
192 Evas_Object* WindowData::createPlatformLayout(Evas_Object* parent)
193 {
194     Evas_Object*  platform_layout = elm_layout_add(parent);
195
196     ADD_PROFILING_POINT("elm_layout_theme_set", "start");
197     elm_layout_file_set(platform_layout, PLATFORM_EDJ_PATH, "platformlayout");
198     ADD_PROFILING_POINT("elm_layout_theme_set", "stop");
199
200     evas_object_size_hint_align_set(platform_layout,
201                                     EVAS_HINT_FILL,
202                                     EVAS_HINT_FILL);
203     evas_object_size_hint_weight_set(platform_layout,
204                                      EVAS_HINT_EXPAND,
205                                      EVAS_HINT_EXPAND);
206
207     elm_object_content_set(parent, platform_layout);
208     edje_object_signal_emit(
209         elm_layout_edje_get(platform_layout), ELM_STATE_SHOW_CONTENT, ELM);
210     return platform_layout;
211 }
212
213 Evas_Object* WindowData::createNavigationBar(Evas_Object* parent)
214 {
215     Assert(parent != NULL && "Parent for naviframe is null");
216     Evas_Object* navigation = elm_naviframe_add(parent);
217
218     evas_object_size_hint_align_set(navigation,
219                                     EVAS_HINT_FILL,
220                                     EVAS_HINT_FILL);
221     evas_object_size_hint_weight_set(navigation,
222                                      EVAS_HINT_EXPAND,
223                                      EVAS_HINT_EXPAND);
224     elm_object_part_content_set(parent, ELM_SWALLOW_CONTENT, navigation);
225     //elm_object_content_set(parent, navigation);
226     return navigation;
227 }
228
229 Evas_Object* WindowData::createUserLayout(Evas_Object* parent)
230 {
231     Assert(parent != NULL && "Parent for User Layout is null");
232     Evas_Object* layout = elm_layout_add(parent);
233     elm_layout_file_set(layout, DAEMON_EDJ_PATH, "client");
234     evas_object_size_hint_weight_set(
235         layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
236     evas_object_size_hint_align_set(layout, EVAS_HINT_FILL, EVAS_HINT_FILL);
237
238     ADD_PROFILING_POINT("elm_naviframe_item_push", "start");
239     Elm_Object_Item* naviIt = elm_naviframe_item_push(
240             /* Evas_Object *obj */
241             parent,
242             /* const char *title_label  */
243             NULL,
244             /* Evas_Object *prev_btn */
245             NULL,
246             /* Evas_Object *next_btn */
247             NULL,
248             /* Evas_Object *content */
249             layout,
250             /* const char *item_style */
251             NULL);
252     ADD_PROFILING_POINT("elm_naviframe_item_push", "stop");
253     elm_naviframe_item_title_visible_set(naviIt, EINA_FALSE);
254     return layout;
255 }
256
257 Evas_Object* WindowData::createFocus(Evas_Object* parent)
258 {
259     Assert(parent != NULL && "Parent for Focus is null");
260     // ewkview isn't elementary widget style. This is reason why ewkview focus
261     // doesn't restore after focus-out and focus-in. To support focus restore
262     // for ewkview, WRT add selectable elementary(button) to manage focus
263     Evas_Object* focus = elm_button_add(parent);
264     elm_object_style_set(focus, "focus");
265     elm_object_part_content_set(parent, ELM_SWALLOW_CONTENT, focus);
266     evas_object_size_hint_weight_set(focus,
267                                      EVAS_HINT_EXPAND,
268                                      EVAS_HINT_EXPAND);
269     evas_object_size_hint_align_set(focus, EVAS_HINT_FILL, EVAS_HINT_FILL);
270     return focus;
271 }
272
273 Evas_Object* WindowData::createProgressBar(Evas_Object* window, Evas_Object* parent)
274 {
275     Assert(parent != NULL && "Parent is null");
276     Evas_Object* progressbar = evas_object_rectangle_add(evas_object_evas_get(window));
277     evas_object_color_set(progressbar, 91, 166, 255, 255);
278     elm_object_part_content_set(parent, ELM_SWALLOW_PROGRESS, progressbar);
279     evas_object_resize(progressbar, 0, 0);
280     return progressbar;
281 }
282
283 Evas_Object* WindowData::createCtxPopup(Evas_Object* parent)
284 {
285     Assert(parent != NULL && "Parent is null");
286     if (m_ctxpopupItemDataList.empty()) {
287         LogError("menu data is empty");
288         return NULL;
289     }
290
291     Evas_Object* object = elm_ctxpopup_add(parent);
292     FOREACH(it, m_ctxpopupItemDataList) {
293         Evas_Object* icon = NULL;
294         if (!it->iconPath.empty()) {
295             // create icon
296         }
297         elm_ctxpopup_item_append(object,
298                                  it->text.c_str(),
299                                  icon,
300                                  ctxpopupItemCallback,
301                                  this);
302     }
303
304     Elm_Object_Item* naviIt = elm_naviframe_top_item_get(parent);
305     Evas_Object* moreButton =
306         elm_object_item_part_content_get(naviIt, "toolbar_more_btn");
307     if (moreButton) {
308         Evas_Coord x, y, w, h;
309         evas_object_geometry_get(moreButton, &x, &y, &w, &h);
310         evas_object_move(object, x+w/2, y+h/2);
311     }
312     evas_object_smart_callback_add(object,
313                                    "dismissed",
314                                    ctxpopupDismissedCallback,
315                                    this);
316     return object;
317 }
318
319 void WindowData::setDesktopIcon()
320 {
321     // set window icon
322     Evas_Object *icon = evas_object_image_add(evas_object_evas_get(m_win));
323     evas_object_image_file_set(icon,
324                                "/opt/share/icons/default/small/tizenScmgz.png",
325                                NULL);
326     elm_win_icon_object_set(m_win, icon);
327 }
328
329 void WindowData::addFloatBackButtonCallback(
330     const char* event,
331     CallbackType callback,
332     const void* data)
333 {
334     Assert(m_floatBackButton != NULL && "m_floatBackButton is null");
335     evas_object_smart_callback_add(m_floatBackButton, event, callback, data);
336 }
337
338 void* WindowData::delFloatBackButtonCallback(
339     const char* event,
340     CallbackType callBack)
341 {
342     Assert(m_floatBackButton != NULL && "m_floatBackButton is null");
343     return evas_object_smart_callback_del(m_floatBackButton, event, callBack);
344 }
345
346 void WindowData::userlayoutCallbackAdd(
347     const Evas_Callback_Type event,
348     EvasCallbackType callback,
349     const void* data)
350 {
351     Assert(m_user_layout != NULL && "m_user_layout is null");
352     evas_object_event_callback_add(m_user_layout, event, callback, data);
353 }
354
355 void* WindowData::userlayoutCallbackDel(
356     const Evas_Callback_Type event,
357     EvasCallbackType callBack)
358 {
359     Assert(m_user_layout != NULL && "m_user_layout is null");
360     return evas_object_event_callback_del(m_user_layout, event, callBack);
361 }
362
363 void WindowData::focusCallbackAdd(
364     const char* event,
365     CallbackType callback,
366     const void* data)
367 {
368     Assert(m_focus != NULL && "m_focus is null");
369     evas_object_smart_callback_add(m_focus, event, callback, data);
370 }
371
372 void* WindowData::focusCallbackDel(
373     const char* event,
374     CallbackType callback)
375 {
376     Assert(m_focus != NULL && "m_focus is null");
377     return evas_object_smart_callback_del(m_focus, event, callback);
378 }
379
380 void WindowData::emitSignalForUserLayout(
381     const char* emission, const char* source)
382 {
383     LogInfo("emitSignalForUserLayout called");
384     Assert(m_user_layout != NULL && "m_user_layout is null");
385     Assert(emission != NULL && "emission is null");
386     Assert(source != NULL && "source is null");
387
388     edje_object_signal_emit(
389         elm_layout_edje_get(m_user_layout), emission, source);
390 }
391
392 void WindowData::toggleFullscreen(bool fullscreen)
393 {
394     LogDebug(__PRETTY_FUNCTION__);
395     toggleIndicator(fullscreen);
396 }
397
398 void WindowData::winProfileChangedCallback(void *data,
399                                            Evas_Object* /*obj*/,
400                                            void* /*eventInfo*/)
401 {
402     LogDebug("winProfileChangedCallback");
403     if (data == NULL) {
404         return;
405     }
406     WindowData* This = static_cast<WindowData *>(data);
407     const char *profile = elm_config_profile_get();
408
409     if (DESKTOP_PROFILE == profile) {
410         elm_win_indicator_mode_set(This->m_win, ELM_WIN_INDICATOR_HIDE);
411         This->setDesktopIcon();
412     }
413 }
414
415 void WindowData::showCtxpopup(void)
416 {
417     m_ctxpopup = createCtxPopup(m_navigation);
418     if (!m_ctxpopup) {
419         return;
420     }
421     evas_object_show(m_ctxpopup);
422 }
423
424 void WindowData::setCtxpopupItemData(CtxpopupItemDataList data)
425 {
426     m_ctxpopupItemDataList = data;
427 }
428
429 void WindowData::updateProgress(double value)
430 {
431     int x, y, w, h;
432     evas_object_geometry_get(m_user_layout, &x, &y, &w, &h);
433     evas_object_resize(m_progressbar,
434                        static_cast<int>(w * value),
435                        static_cast<int>(PROGRESS_H * elm_config_scale_get()));
436 }
437
438 void WindowData::ctxpopupItemCallback(void* data,
439                                       Evas_Object* obj,
440                                       void* eventInfo)
441 {
442     LogDebug("ctxpopupItemCallback");
443     Assert(data);
444     WindowData* This = static_cast<WindowData*>(data);
445
446     Assert(eventInfo);
447     Elm_Object_Item* it = static_cast<Elm_Object_Item*>(eventInfo);
448     const char* text = elm_object_item_text_get(it);
449     LogDebug("text " << text);
450
451     FOREACH(it, This->m_ctxpopupItemDataList) {
452         if (it->text == text) {
453             it->function();
454             break;
455         }
456     }
457     Assert(obj);
458     elm_ctxpopup_dismiss(obj);
459 }
460
461 void WindowData::ctxpopupDismissedCallback(void* data,
462                                            Evas_Object* obj,
463                                            void* /*eventInfo*/)
464 {
465     LogDebug("ctxpopupDismissedCallback");
466     Assert(obj);
467     evas_object_del(obj);
468
469     Assert(data);
470     WindowData* This = static_cast<WindowData*>(data);
471     This->m_ctxpopup = NULL;
472 }