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