Return to previous window structure
[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
27 namespace {
28 char const* const PLATFORM_EDJ_PATH = "/usr/share/edje/wrt/Platform.edj";
29 char const* const DAEMON_EDJ_PATH = "/usr/share/edje/wrt/Daemon.edj";
30 char const* const THEME_EDJ_PATH = "/usr/share/edje/wrt/wrt_theme.edj";
31 char const* const ELM_STATE_SHOW_CONTENT = "elm,state,show,content";
32 char const* const ELM_SWALLOW_CONTENT = "elm.swallow.content";
33 char const* const ELM_SWALLOW_BACKWARD = "elm.swallow.backward";
34 char const* const ELM_SWALLOW_TOOLBAR = "elm.swallow.toolbar";
35 char const* const ELM_RECT_HIDDENOPTION = "elm.rect.hiddenOption";
36
37 const char *EDJE_SHOW_TOOLBAR_SIGNAL = "show,toolbar,signal";
38 const char *EDJE_HIDE_TOOLBAR_SIGNAL = "hide,toolbar,signal";
39 const char *EDJE_SHOW_HIDDENOPTION_SIGNAL = "show,hiddenOption,signal";
40 const char *EDJE_HIDE_HIDDENOPTION_SIGNAL = "hide,hiddenOption,signal";
41
42 char const* const ELM = "elm";
43 char const* const LAYOUT = "layout";
44 char const* const APPLICATION = "application";
45 char const* const INDICATOR = "indicator";
46 char const* const NOINDICATOR = "noindicator";
47 char const* const INTERNAL_LAYOUT = "internal_layout";
48 char const* const FLOATBACKWARD_BUTTON_STYLE = "wrt/backward";
49 } // anonymous namespace
50
51 WindowData::WindowData(unsigned long pid, bool manualInit) :
52     m_win(NULL), m_naviBackButton(NULL),
53     m_toolbarTimer(NULL),
54     m_debugMode(false)
55 {
56     m_win = createWindow(pid);
57
58     if (!manualInit)
59     {
60         init();
61     }
62 }
63
64 WindowData::~WindowData()
65 {
66     LogDebug("");
67     evas_object_del(m_win);
68 }
69
70 void WindowData::init()
71 {
72     Assert(m_win != NULL && "m_win is null");
73
74     // import button theme
75     elm_theme_overlay_add(NULL, THEME_EDJ_PATH);
76
77     m_platform_layout = createPlatformLayout(m_win);
78     evas_object_show(m_platform_layout);
79     m_navigation = createNavigationBar(m_platform_layout);
80     evas_object_show(m_navigation);
81     m_user_layout = createUserLayout(m_navigation);
82     evas_object_show(m_user_layout);
83     m_conformant = createConformant(m_user_layout);
84     evas_object_show(m_conformant);
85 }
86
87 void WindowData::setEvasObjectForLayout(Evas_Object* evas_object)
88 {
89     elm_object_content_set(m_conformant, evas_object);
90 }
91
92 void WindowData::unsetEvasObjectForLayout()
93 {
94     elm_object_content_unset(m_conformant);
95 }
96
97 void WindowData::toggleIndicator(bool fullscreen)
98 {
99     LogDebug(__PRETTY_FUNCTION__);
100     if (!fullscreen) {
101         elm_win_indicator_mode_set(m_win, ELM_WIN_INDICATOR_SHOW);
102         elm_layout_theme_set(m_platform_layout,
103                 LAYOUT,
104                 APPLICATION,
105                 INDICATOR);
106     } else {
107         elm_win_indicator_mode_set(m_win, ELM_WIN_INDICATOR_HIDE);
108         elm_layout_theme_set(m_platform_layout,
109                 LAYOUT,
110                 APPLICATION,
111                 NOINDICATOR);
112     }
113 }
114
115 void WindowData::setViewMode(
116         const char *title,
117         bool fullscreen,
118         CtxMenuItems ctxMenuItems)
119 {
120     LogDebug("setViewMode " <<m_debugMode);
121     LogDebug("fullscreen: " << fullscreen);
122
123     m_fullscreen = fullscreen;
124
125     toggleIndicator(m_fullscreen);
126
127     m_title = title;
128     m_ctxMenuItems = ctxMenuItems;
129
130     if(m_debugMode) {
131         if(fullscreen)
132             showHiddenOption(m_user_layout);
133         else
134             createTitle(m_title.c_str(), m_ctxMenuItems);
135
136         createToolbar(m_ctxMenuItems);
137     }
138     else
139         if(!fullscreen)
140             createTitle(m_title.c_str(), m_ctxMenuItems);
141 }
142
143 void WindowData::createTitle(const char *data, CtxMenuItems ctxMenuItems)
144 {
145     LogDebug("createTitle");
146     showTitle(data);
147     if(m_debugMode) {
148         createMoreButton();
149         createTitleToolbar(ctxMenuItems);
150     }
151 }
152
153 void WindowData::showTitle(const char *data)
154 {
155     LogInfo("showTitle");
156
157     Elm_Object_Item* naviIt = elm_naviframe_top_item_get(m_navigation);
158     elm_naviframe_item_title_visible_set(naviIt, EINA_TRUE);
159     elm_object_item_text_set(naviIt, data);
160 }
161
162 void WindowData::hideTitle()
163 {
164     LogInfo("hideTitle");
165
166     Elm_Object_Item* naviIt = elm_naviframe_top_item_get(m_navigation);
167     elm_object_item_signal_emit(naviIt, "elm,state,optionheader,instant_close", "");
168     optionheaderClose = FALSE;
169
170     elm_naviframe_item_title_visible_set(naviIt, EINA_FALSE);
171 }
172
173 void WindowData::createMoreButton()
174 {
175     Evas_Object *btn = elm_button_add(m_navigation);
176     if (!btn)
177         return;
178     Elm_Object_Item* naviIt = elm_naviframe_top_item_get(m_navigation);
179     elm_object_style_set(btn, "naviframe/more/default");
180     evas_object_smart_callback_add(btn, "clicked", moreButtonCallback, this);
181     elm_object_item_part_content_set(naviIt, "title_more_btn", btn);
182     evas_object_show(btn);
183
184 }
185
186 void WindowData::createTitleToolbar(CtxMenuItems ctxMenuItems)
187 {
188     Elm_Object_Item *toolbarIt;
189     Evas_Object *toolbarButton;
190     Elm_Object_Item *naviIt = elm_naviframe_top_item_get(m_navigation);
191
192     Evas_Object *toolbar = elm_toolbar_add(m_navigation);
193     if (!toolbar)
194         return;
195     elm_toolbar_shrink_mode_set(toolbar, ELM_TOOLBAR_SHRINK_EXPAND);
196
197     elm_object_style_set(toolbar, "naviframe");
198
199     toolbarButton = elm_button_add(m_navigation);
200     if (!toolbarButton)
201         return;
202
203     std::list<CtxMenuItem>::iterator itor;
204     for (itor = ctxMenuItems.begin(); itor != ctxMenuItems.end(); ++itor) {
205         toolbarButton = elm_button_add(toolbar);
206         elm_object_style_set(toolbarButton, "naviframe_contrl/default");
207         evas_object_size_hint_align_set(toolbarButton,
208                 EVAS_HINT_FILL,
209                 EVAS_HINT_FILL);
210         elm_object_text_set(toolbarButton, ((*itor).label).c_str());
211         evas_object_smart_callback_add(toolbarButton,
212                 "clicked",
213                 (*itor).callback,
214                 (*itor).data);
215         toolbarIt = elm_toolbar_item_append(toolbar, NULL, NULL, NULL, NULL);
216         elm_object_item_part_content_set(toolbarIt, "object", toolbarButton);
217     }
218
219     toolbarButton = elm_button_add(toolbar);
220     elm_object_style_set(toolbarButton, "naviframe_contrl/default");
221     evas_object_size_hint_align_set(toolbarButton,
222             EVAS_HINT_FILL,
223             EVAS_HINT_FILL);
224     elm_object_text_set(toolbarButton, WRT_OPTION_LABEL_FULLVIEW);
225     evas_object_smart_callback_add(toolbarButton,
226             "clicked",
227             changeViewModeCallback,
228             this);
229     toolbarIt = elm_toolbar_item_append(toolbar, NULL, NULL, NULL, NULL);
230     elm_object_item_part_content_set(toolbarIt, "object", toolbarButton);
231
232     elm_object_item_part_content_set(naviIt, "optionheader", toolbar);
233     elm_object_item_signal_emit(naviIt,
234             "elm,state,optionheader,instant_close",
235             "");
236     optionheaderClose = TRUE;
237 }
238
239 void WindowData::createToolbar(CtxMenuItems ctxMenuItems)
240 {
241     Elm_Object_Item *toolbarIt;
242     Evas_Object *toolbarButton;
243     Evas_Object *toolbar;
244     char buf[100];
245
246     toolbar = elm_toolbar_add(m_user_layout);
247     if (!toolbar)
248         return;
249
250     elm_object_style_set(toolbar, "naviframe");
251     elm_object_part_content_set(m_user_layout,
252             ELM_SWALLOW_TOOLBAR,
253             toolbar);
254
255     std::list<CtxMenuItem>::iterator itor;
256     for (itor = ctxMenuItems.begin(); itor != ctxMenuItems.end(); ++itor) {
257         toolbarButton = elm_button_add(toolbar);
258         if (!toolbarButton)
259             return;
260
261         evas_object_size_hint_align_set(toolbarButton,
262                 EVAS_HINT_FILL,
263                 EVAS_HINT_FILL);
264         evas_object_size_hint_weight_set(toolbarButton,
265                 EVAS_HINT_EXPAND,
266                 EVAS_HINT_EXPAND);
267
268         Evas_Object *ic = elm_icon_add(toolbar);
269          snprintf(buf, sizeof(buf), (*itor).icon.c_str());
270          elm_icon_file_set(ic, buf, NULL);
271         evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
272         elm_icon_resizable_set(ic, EINA_TRUE, EINA_TRUE);
273         elm_object_part_content_set(toolbarButton, "icon", ic);
274
275         evas_object_smart_callback_add(toolbarButton,
276                 "clicked",
277                 (*itor).callback,
278                 (*itor).data);
279         toolbarIt = elm_toolbar_item_append(toolbar, NULL, NULL, NULL, NULL);
280         elm_object_item_part_content_set(toolbarIt, "object", toolbarButton);
281
282         //for margin button between buttons
283         toolbarButton = elm_button_add(toolbar);
284         if (!toolbarButton)
285             return;
286         evas_object_color_set(
287                 toolbarButton,
288                 255,
289                 255,
290                 255,
291                 0);
292         toolbarIt = elm_toolbar_item_append(toolbar, NULL, NULL, NULL, NULL);
293         elm_object_item_part_content_set(toolbarIt, "object", toolbarButton);
294     }
295
296     toolbarButton = elm_button_add(toolbar);
297     if (!toolbarButton)
298         return;
299
300     Evas_Object *ic = elm_icon_add(toolbar);
301     snprintf(buf, sizeof(buf), WRT_OPTION_ICON_WINDOWVIEW);
302     elm_icon_file_set(ic, buf, NULL);
303     evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
304     elm_icon_resizable_set(ic, EINA_TRUE, EINA_TRUE);
305     elm_object_part_content_set(toolbarButton, "icon", ic);
306
307     evas_object_size_hint_align_set(toolbarButton,
308             EVAS_HINT_FILL,
309             EVAS_HINT_FILL);
310     evas_object_size_hint_weight_set(toolbarButton,
311             EVAS_HINT_EXPAND,
312             EVAS_HINT_EXPAND);
313     evas_object_smart_callback_add(toolbarButton,
314             "clicked",
315             changeViewModeCallback,
316             this);
317     toolbarIt = elm_toolbar_item_append(toolbar, NULL, NULL, NULL, NULL);
318     elm_object_item_part_content_set(toolbarIt, "object", toolbarButton);
319
320     optionheaderClose = TRUE;
321
322     elm_object_part_content_set(m_user_layout,
323             ELM_SWALLOW_TOOLBAR,
324             toolbar);
325 }
326
327 void WindowData::showToolbar()
328 {
329     emitSignalForUserLayout(EDJE_SHOW_TOOLBAR_SIGNAL, "");
330     m_toolbarTimer = ecore_timer_add(10.0, hideToolbarCallback, this);
331 }
332
333 void WindowData::hideToolbar()
334 {
335     emitSignalForUserLayout(EDJE_HIDE_TOOLBAR_SIGNAL, "");
336     if(m_toolbarTimer) {
337         ecore_timer_del(m_toolbarTimer);
338         m_toolbarTimer = NULL;
339     }
340 }
341
342 void WindowData::createTitleButton()
343 {
344     // Add left button for back action
345     m_naviBackButton = elm_button_add(m_navigation);
346     elm_object_style_set(m_naviBackButton, "navigationbar_backbutton/default");
347
348     Elm_Object_Item* naviIt = elm_naviframe_top_item_get(m_navigation);
349     elm_object_item_part_content_set(naviIt, "prev_btn", m_naviBackButton);
350 }
351
352 void WindowData::createFloatBackButton()
353 {
354     // Add float backbutton on the left coner
355     m_floatBackButton = elm_button_add(m_user_layout);
356     elm_object_style_set(m_floatBackButton, FLOATBACKWARD_BUTTON_STYLE);
357     elm_object_part_content_set(m_user_layout,
358                                 ELM_SWALLOW_BACKWARD,
359                                 m_floatBackButton);
360     evas_object_show(m_floatBackButton);
361 }
362
363 void WindowData::updateTitleButton(const bool display)
364 {
365     if (display) {
366         evas_object_show(m_naviBackButton);
367     } else {
368         evas_object_hide(m_naviBackButton);
369     }
370 }
371
372 Evas_Object* WindowData::createWindow(unsigned long pid)
373 {
374     Evas_Object* window = elm_win_add(NULL, "wrt-widget", ELM_WIN_BASIC);
375     ecore_x_window_prop_property_set(
376         elm_win_xwindow_get(window),
377         ECORE_X_ATOM_NET_WM_PID,
378         ECORE_X_ATOM_CARDINAL, 32, &pid, 1);
379     elm_win_title_set(window, "wrt-widget");
380     elm_win_borderless_set(window, EINA_TRUE);
381     elm_win_conformant_set(window, EINA_TRUE);
382     int w, h;
383     ecore_x_window_size_get(ecore_x_window_root_first_get(), &w, &h);
384     evas_object_resize(window, w, h);
385     return window;
386 }
387
388 Evas_Object* WindowData::createPlatformLayout(Evas_Object* parent)
389 {
390     Evas_Object*  platform_layout = elm_layout_add(parent);
391
392     if (!elm_layout_file_set(platform_layout, PLATFORM_EDJ_PATH, "platformlayout"))
393         elm_layout_theme_set(platform_layout, LAYOUT, APPLICATION, NOINDICATOR);
394
395     evas_object_size_hint_expand_set(platform_layout,
396                                      EVAS_HINT_EXPAND,
397                                      EVAS_HINT_EXPAND);
398
399     elm_win_resize_object_add(parent, platform_layout);
400
401     edje_object_signal_emit(
402             elm_layout_edje_get(platform_layout), ELM_STATE_SHOW_CONTENT, ELM);
403     return platform_layout;
404 }
405
406 Evas_Object* WindowData::createUserLayout(Evas_Object* parent)
407 {
408     Assert(parent != NULL && "Parent for User Layout is null");
409     Evas_Object* layout = elm_layout_add(parent);
410     elm_layout_file_set(layout, DAEMON_EDJ_PATH, "client");
411     evas_object_size_hint_weight_set(
412             layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
413     evas_object_size_hint_align_set(layout, EVAS_HINT_FILL, EVAS_HINT_FILL);
414     elm_win_resize_object_add(parent, layout);
415
416     Elm_Object_Item* naviIt = elm_naviframe_item_push(
417         /* Evas_Object *obj */
418         parent,
419         /* const char *title_label  */
420         "",
421         /* Evas_Object *prev_btn */
422         NULL,
423         /* Evas_Object *next_btn */
424         NULL,
425         /* Evas_Object *content */
426         layout,
427         /* const char *item_style */
428         NULL);
429
430     elm_naviframe_item_title_visible_set(naviIt, EINA_FALSE);
431
432     return layout;
433 }
434
435 Evas_Object* WindowData::createConformant(Evas_Object* parent)
436 {
437     Assert(parent != NULL && "Parent is null");
438     Evas_Object* conformant = elm_conformant_add(parent);
439     elm_object_style_set(conformant, INTERNAL_LAYOUT);
440     evas_object_size_hint_weight_set(
441             conformant, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
442     evas_object_size_hint_align_set(conformant, EVAS_HINT_FILL, EVAS_HINT_FILL);
443     elm_object_part_content_set(parent, ELM_SWALLOW_CONTENT, conformant);
444     evas_object_show(conformant);
445     return conformant;
446 }
447
448 Evas_Object* WindowData::createNavigationBar(Evas_Object* parent)
449 {
450     Assert(parent != NULL && "Parent for naviframe is null");
451     Evas_Object* navigation = elm_naviframe_add(parent);
452     elm_object_part_content_set(parent, ELM_SWALLOW_CONTENT, navigation);
453     return navigation;
454 }
455
456 void WindowData::showHiddenOption(Evas_Object* parent)
457 {
458     Assert(parent != NULL && "Parent for Hiden Option");
459
460     emitSignalForUserLayout(EDJE_SHOW_HIDDENOPTION_SIGNAL, "");
461
462     edje_object_signal_callback_add(elm_layout_edje_get(parent),
463             "mouse,clicked,1",
464             "elm.rect.hiddenOption",
465             controlHiddenOptionCallback,
466             this);
467 }
468
469 void WindowData::hideHiddenOption(Evas_Object* parent)
470 {
471     Assert(parent != NULL && "Parent for Hiden Option");
472
473     emitSignalForUserLayout(EDJE_HIDE_HIDDENOPTION_SIGNAL, "");
474
475     edje_object_signal_callback_del(elm_layout_edje_get(parent),
476             "mouse,clicked,1",
477             "elm.rect.hiddenOption",
478             controlHiddenOptionCallback);
479 }
480
481 void WindowData::initFullViewMode ()
482 {
483     hideToolbar();
484     showHiddenOption(m_user_layout);
485 }
486
487 void WindowData::addNaviBackButtonCallback(
488         const char* event,
489         CallbackType callback,
490         const void* data)
491 {
492     Assert(m_naviBackButton != NULL && "m_naviBackButton is null");
493     evas_object_smart_callback_add(m_naviBackButton, event, callback, data);
494 }
495
496 void* WindowData::delNaviBackButtonCallback(
497         const char* event,
498         CallbackType callBack)
499 {
500     Assert(m_naviBackButton != NULL && "m_naviBackButton is null");
501     return evas_object_smart_callback_del(m_naviBackButton, event, callBack);
502 }
503
504 void WindowData::addFloatBackButtonCallback(
505         const char* event,
506         CallbackType callback,
507         const void* data)
508 {
509     Assert(m_floatBackButton != NULL && "m_floatBackButton is null");
510     evas_object_smart_callback_add(m_floatBackButton, event, callback, data);
511 }
512
513 void* WindowData::delFloatBackButtonCallback(
514         const char* event,
515         CallbackType callBack)
516 {
517     Assert(m_floatBackButton != NULL && "m_floatBackButton is null");
518     return evas_object_smart_callback_del(m_floatBackButton, event, callBack);
519 }
520
521 void WindowData::userlayoutCallbackAdd(
522         const Evas_Callback_Type event,
523         EvasCallbackType callback,
524         const void* data)
525 {
526     Assert(m_user_layout != NULL && "m_user_layout is null");
527     evas_object_event_callback_add(m_user_layout, event, callback, data);
528 }
529
530 void* WindowData::userlayoutCallbackDel(
531         const Evas_Callback_Type event,
532         EvasCallbackType callBack)
533 {
534     Assert(m_user_layout != NULL && "m_user_layout is null");
535     return evas_object_event_callback_del(m_user_layout, event, callBack);
536 }
537
538 void WindowData::emitSignalForUserLayout(
539         const char* emission, const char* source)
540 {
541     LogInfo("emitSignalForUserLayout called");
542     Assert(m_user_layout != NULL && "m_user_layout is null");
543     Assert(emission != NULL && "emission is null");
544     Assert(source != NULL && "source is null");
545
546     edje_object_signal_emit(
547             elm_layout_edje_get(m_user_layout), emission, source);
548 }
549
550 void WindowData::moreButtonCallback(void *data,
551         Evas_Object */*obj*/,
552         void */*event_info*/)
553 {
554     WindowData* This = static_cast<WindowData*>(data);
555     Elm_Object_Item *naviIt = elm_naviframe_top_item_get(This->m_navigation);
556
557     if (This->optionheaderClose)
558         elm_object_item_signal_emit(naviIt, "elm,state,optionheader,open", "");
559     else
560         elm_object_item_signal_emit(naviIt, "elm,state,optionheader,close", "");
561
562     This->optionheaderClose = !This->optionheaderClose;
563 }
564
565
566 void WindowData::changeViewModeCallback(void *data,
567         Evas_Object */*obj*/,
568         void */*event_info*/)
569 {
570     WindowData* This = static_cast<WindowData*>(data);
571     Elm_Object_Item *naviIt = elm_naviframe_top_item_get(This->m_navigation);
572
573     if(elm_naviframe_item_title_visible_get(naviIt)) {
574         This->hideTitle();
575         This->showHiddenOption(This->m_user_layout);
576
577     } else {
578         This->createTitle(This->m_title.c_str(), This->m_ctxMenuItems);
579         This ->hideToolbar();
580     }
581 }
582
583 void WindowData::controlHiddenOptionCallback(void *data,
584         Evas_Object */*obj*/,
585         const char */*emission*/,
586         const char */*source*/)
587 {
588     LogDebug("controlHiddenOptionCallback");
589     WindowData* This = static_cast<WindowData *>(data);
590     Elm_Object_Item *naviIt = elm_naviframe_top_item_get(This->m_navigation);
591
592     if(!elm_naviframe_item_title_visible_get(naviIt)) {
593         const char* state = edje_object_part_state_get(
594                 elm_layout_edje_get(This->m_user_layout),
595                 "elm.swallow.toolbar",
596                 NULL);
597
598         if (state && !strncmp(state, "default", strlen("default"))) {
599             This->showToolbar();
600             This->hideHiddenOption(This->m_user_layout);
601         }
602         else {
603             This->initFullViewMode();
604         }
605
606     }
607 }
608
609 Eina_Bool WindowData::hideToolbarCallback(void *data)
610 {
611     WindowData *This = static_cast<WindowData *>(data);
612
613     This->initFullViewMode();
614     return TRUE;
615 }
616
617 void WindowData::toggleFullscreen(bool fullscreen)
618 {
619     LogDebug(__PRETTY_FUNCTION__);
620
621     static bool alreadyFullscreen = false;
622
623     if (alreadyFullscreen == fullscreen) {
624         // window is in fullscreen mode and fullscreen mode is requested, or
625         // window is not in fullscreen and a request is made to exit fullscreen
626         // In these two situations we don't have to do anything here.
627         return;
628     }
629
630     if (!m_fullscreen) //If ViewMode is not fullscreen, toggle the title bar.
631         fullscreen ? hideTitle() : showTitle(m_title.c_str());
632
633     if (m_indicator) //If indicator is shown by default, toggle it.
634         toggleIndicator(!fullscreen);
635
636     alreadyFullscreen = !alreadyFullscreen;
637 }