From debb46f02a5f276f33fe92a71c44e0085eae803a Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Fri, 11 Mar 2016 23:08:01 +0900 Subject: [PATCH] + basic view transition bahavior. Change-Id: I8a1a320a1f78be5b12934754af78bce66ad2c60a --- data/edc/ui-viewmgr.edc | 84 ++++++++++++++++- src/include/efl/ui_viewmgr.h | 19 ++++ src/include/interface/ui_iface_view.h | 22 ++--- src/lib/efl/mobile/ui_basic_view.cpp | 5 +- src/lib/efl/ui_viewmgr.cpp | 167 ++++++++++++++++++++++++++++----- src/lib/interface/ui_iface_view.cpp | 6 +- src/lib/interface/ui_iface_viewmgr.cpp | 23 ++--- 7 files changed, 266 insertions(+), 60 deletions(-) diff --git a/data/edc/ui-viewmgr.edc b/data/edc/ui-viewmgr.edc index 793e2c6..64dd08b 100644 --- a/data/edc/ui-viewmgr.edc +++ b/data/edc/ui-viewmgr.edc @@ -23,6 +23,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + #define TIZEN_VIEW_BG_PORTRAIT_HEIGHT_INC 1280 #define TIZEN_VIEW_BG_LANDSPACPE_HEIGHT_INC 720 #define TIZEN_VIEW_TITLE_HEIGHT_INC 110 @@ -49,6 +50,7 @@ #define TIZEN_VIEW_TOOLBAR_TITLE_CLIPPER_HEIGHT_INC 80 #define TIZEN_VIEW_TOOLBAR_LIGHT_VIEW_HEIGHT_INC 86 #define TIZEN_VIEW_TOOLBAR_TOP_DIVIDER_HEIGHT_INC 0 +#define TRANSITION_TIME 0.25 collections { base_scale: 2.6; @@ -69,7 +71,7 @@ collections { tag: "tab" "\t"; } } - group { "elm/layout/tizen_view/default"; + group { "tizen_view/default"; images { image: "images/core_theme_bg_01.png" COMP; image: "images/core_icon_badge_container.#.png" COMP; @@ -1086,4 +1088,84 @@ collections { } } } + /* Sliding Effect */ + group { "transition/default"; + alias: "transition/slide"; + parts { + swallow { "pcontent"; + desc { "default"; + } + desc {"pushed"; + rel1.relative: -1.0 0.0; + rel2.relative: 0.0 1.0; + } + desc {"popped"; + rel1.relative: 1.0 0.0; + rel2.relative: 2.0 1.0; + } + } + swallow { "content"; + desc { "default"; + } + desc { "push_ready"; + rel1.relative: 1.0 0.0; + rel2.relative: 2.0 1.0; + } + desc { "pop_ready"; + rel1.relative: -1.0 0.0; + rel2.relative: 0.0 1.0; + } + } + } + programs { + program { "push_finished"; + action: SIGNAL_EMIT "push,finished" "viewmgr"; + } + program { "push_pcontent"; + action: STATE_SET "pushed"; + target: "pcontent"; + transition: DECELERATE TRANSITION_TIME; + after: "push_finished"; + } + program { "push_content"; + action: STATE_SET "default"; + target: "content"; + transition: DECELERATE TRANSITION_TIME; + } + program { "push"; + signal: "view,push"; + source: "viewmgr"; + script { + set_state(PART:"pcontent", "default", 0.0); + set_state(PART:"content", "push_ready", 0.0); + run_program(PROGRAM:"push_pcontent"); + run_program(PROGRAM:"push_content"); + } + } + program { "pop_finished"; + action: SIGNAL_EMIT "pop,finished" "viewmgr"; + } + program { "pop_pcontent"; + action: STATE_SET "popped"; + target: "pcontent"; + transition: DECELERATE TRANSITION_TIME; + after: "pop_finished"; + } + program { "pop_content"; + action: STATE_SET "default"; + target: "content"; + transition: DECELERATE TRANSITION_TIME; + } + program { "pop"; + signal: "view,pop"; + source: "viewmgr"; + script { + set_state(PART:"pcontent", "default", 0.0); + set_state(PART:"content", "pop_ready", 0.0); + run_program(PROGRAM:"pop_pcontent"); + run_program(PROGRAM:"pop_content"); + } + } + } + } } diff --git a/src/include/efl/ui_viewmgr.h b/src/include/efl/ui_viewmgr.h index 9477f92..6ade0d2 100644 --- a/src/include/efl/ui_viewmgr.h +++ b/src/include/efl/ui_viewmgr.h @@ -47,6 +47,9 @@ private: Evas_Object *layout; //Viewmgr's base layout. ui_key_listener *key_listener; //HW Key Handler such as "BACK" key... ui_view_indicator indicator; //Mode of indicator. + string transition_style; //Current transiton effect style name + + Evas_Object *set_transition_layout(string transition_style); /** * @brief Create a conformant. @@ -169,6 +172,22 @@ public: /** @brief Get a last view of current view stack. */ ui_view *get_last_view(); + + /** + * @brief Return a view which is matched with the index @p idx. + * + * @param idx A index of the view which you are looking for. + * + * @return The view which index is matched with @p idx. + * If there were no views with index @p idx, @c NULL will be returned. + * + * @note You could use the index as the page numbers of the views. + * @warning the index number of views are variable since the view list is variable. + * + * @see get_view_index() + * @see get_view_count() + */ + ui_view *get_view(unsigned int idx); }; } diff --git a/src/include/interface/ui_iface_view.h b/src/include/interface/ui_iface_view.h index 597ce37..62f5b92 100644 --- a/src/include/interface/ui_iface_view.h +++ b/src/include/interface/ui_iface_view.h @@ -59,10 +59,10 @@ private: }; T content; ///< A content instance for a screen as a view. - ui_iface_controller *controller; ///< View life-cycle controller interface. + ui_iface_controller *controller; ///< View life-cycle controller interface. string name; ///< View name. - string style; ///< View style name. - ui_iface_viewmgr *viewmgr; ///< Viewmgr which this view belongs to. + string transition_style; ///< View transition style name. + ui_iface_viewmgr *viewmgr; ///< Viewmgr which this view belongs to. ui_view_state state; ///< View state. ui_view_indicator indicator; ///< View indicator mode. bool event_block; ///< State of event block. @@ -205,19 +205,20 @@ public: */ T set_content(T content); - /** @brief set style of the view. + /** @brief set transition style of a view. * - * @note style is reserved for supporting various kinds of view as well as it's transition effects. - * The actual behaviors with this style is up to your frameworks. Default value of the style is NULL. + * @note @p style is reserved for supporting various kinds of view transition effects. + * The actual behaviors with this transition style is up to your frameworks. Default value of the style is NULL. + * and "none" represents none transition. If you don't like give any transition effects to this view, you can pass "none" as @p style. * - * @param style a new style name. + * @param style a transition style name. * * @return true if the given @c style is available, otherwise false. * * @warning When you override this member function, you should implement the logic to check the given style name is available or not. * If your framework doesn't support any styles then just allow a @c NULL argument and return true. Otherwise return false. */ - bool set_style(const char *style); + bool set_transition_style(const char *style); /** @brief set name of the view. * @@ -249,9 +250,9 @@ public: * * @return style name of view. */ - const char *get_style() + const char *get_transition_style() { - return this->style.c_str(); + return this->transition_style.c_str(); } /** @brief Return a name of this view. @@ -281,7 +282,6 @@ public: return this->state; } - /** @brief Return a state of removeable content. * * @return true if the view's content is removable, otherwise false. diff --git a/src/lib/efl/mobile/ui_basic_view.cpp b/src/lib/efl/mobile/ui_basic_view.cpp index f7f68d0..3d8f93b 100644 --- a/src/lib/efl/mobile/ui_basic_view.cpp +++ b/src/lib/efl/mobile/ui_basic_view.cpp @@ -17,10 +17,8 @@ #include "../../../include/efl/mobile/ui_viewmanager_mobile.h" //FIXME: is it correct to define here? -//#define EDJ_PATH "/opt/usr/apps/org.tizen.ui-viewmgr/res/ui-viewmgr.edj" #define EDJ_PATH "/usr/share/edje/ui-viewmgr/ui-viewmgr.edj" -#define GROUP "elm/layout/tizen_view/default" -#define TOOLBAR "elm/layout/tizen_view/toolbar" +#define GROUP "tizen_view/default" using namespace efl_viewmgr; using namespace viewmgr; @@ -228,7 +226,6 @@ bool ui_basic_view::set_toolbar(Evas_Object *toolbar) if (layout) { - if ((!strcmp(elm_object_style_get(toolbar), "toolbar_with_title")) && ((elm_toolbar_shrink_mode_get(toolbar) != ELM_TOOLBAR_SHRINK_EXPAND))) { diff --git a/src/lib/efl/ui_viewmgr.cpp b/src/lib/efl/ui_viewmgr.cpp index 3667607..53a61ff 100644 --- a/src/lib/efl/ui_viewmgr.cpp +++ b/src/lib/efl/ui_viewmgr.cpp @@ -19,23 +19,48 @@ using namespace efl_viewmgr; using namespace viewmgr; +//FIXME: is it correct to define here? +#define EDJ_PATH "/usr/share/edje/ui-viewmgr/ui-viewmgr.edj" + +Evas_Object *ui_viewmgr::set_transition_layout(string transition_style) +{ + elm_object_part_content_unset(this->get_base(), "pcontent"); + elm_object_part_content_unset(this->get_base(), "content"); + + if (transition_style == this->transition_style) return this->layout; + + //FIXME: 1. Find current style effect layout + Evas_Object *effect = this->get_base(); + + //2. Switch effect layout to base layout + elm_object_part_content_unset(this->get_conformant(), "elm.swallow.content"); + elm_object_part_content_set(this->get_conformant(), "elm.swallow.content", effect); + + this->layout = effect; + this->transition_style = transition_style; + + return this->layout; +} + void ui_viewmgr::active_top_view() { - elm_object_part_content_unset(this->get_base(), "elm.swallow.content"); + elm_object_part_content_unset(this->get_base(), "content"); - ui_view *view = dynamic_cast(this->get_last_view()); + ui_view *view = this->get_last_view(); - //TODO: get parent? - Evas_Object *content = view->get_base(); - if (content == this->get_base()) + //In case of ui_view, it doesn't have any base form. It uses viewmgr base instead. + Evas_Object *content; + if (view->get_base() == this->get_base()) { - elm_object_part_content_set(this->get_base(), "elm.swallow.content", CONVERT_TO_EO(view->get_content())); + content = CONVERT_TO_EO(view->get_content()); } else { - elm_object_part_content_set(this->get_base(), "elm.swallow.content", CONVERT_TO_EO(view->get_base())); + content = CONVERT_TO_EO(view->get_base()); } + elm_object_part_content_set(this->get_base(), "content", content); + this->set_indicator(view->get_indicator()); } @@ -93,16 +118,41 @@ bool ui_viewmgr::create_base_layout(Evas_Object *conform) Evas_Object *layout = elm_layout_add(conform); if (!layout) return false; - elm_layout_theme_set(layout, "layout", "application", "default"); + //default transition layout + elm_layout_file_set(layout, EDJ_PATH, "transition/default"); elm_object_content_set(conform, layout); + //Push Finished Event + elm_layout_signal_callback_add(layout, "push,finished", "viewmgr", + [](void *data, Evas_Object *obj, const char *emission, const char *source) -> void + { + ui_viewmgr *viewmgr = static_cast(data); + ui_view *pview = viewmgr->get_view(viewmgr->get_view_count() - 2); + ui_view *view = viewmgr->get_last_view(); + if (pview) viewmgr->push_view_finished(pview); + if (view) viewmgr->push_view_finished(view); + }, + this); + + //Pop Finished Event + elm_layout_signal_callback_add(layout, "pop,finished", "viewmgr", + [](void *data, Evas_Object *obj, const char *emission, const char *source) -> void + { + ui_viewmgr *viewmgr = static_cast(data); + ui_view *pview = viewmgr->get_view(viewmgr->get_view_count() - 2); + ui_view *view = viewmgr->get_last_view(); + if (pview) viewmgr->pop_view_finished(pview); + if (view) viewmgr->pop_view_finished(view); + }, + this); + this->layout = layout; return true; } ui_viewmgr::ui_viewmgr(const char *pkg, ui_key_listener *key_listener) - : ui_iface_viewmgr(), key_listener(key_listener) + : ui_iface_viewmgr(), key_listener(key_listener), transition_style("") { if (!pkg) { @@ -177,7 +227,7 @@ bool ui_viewmgr::activate() this->active_top_view(); //FIXME: Necessary?? - ui_view *view = dynamic_cast(this->get_last_view()); + ui_view *view = this->get_last_view(); view->active(); evas_object_show(this->win); @@ -187,12 +237,12 @@ bool ui_viewmgr::activate() bool ui_viewmgr::deactivate() { - ui_iface_viewmgr::deactivate(); + if (!ui_iface_viewmgr::deactivate()) return false; //FIXME: based on the profile, we should app to go behind or terminate. if (true) { - ui_view *view = dynamic_cast(this->get_last_view()); + ui_view *view = this->get_last_view(); if (view) view->inactive(); evas_object_lower(this->win); } @@ -207,23 +257,49 @@ bool ui_viewmgr::deactivate() bool ui_viewmgr::pop_view() { - if (this->get_view_count() == 1) this->deactivate(); - else if(!ui_iface_viewmgr::pop_view()) return false; - - ui_view *view = dynamic_cast(this->get_last_view()); + if (this->get_view_count() == 1) + { + this->deactivate(); + return true; + } - //TODO: get parent? - Evas_Object *content = view->get_base(); - if (content == this->get_base()) + if(!ui_iface_viewmgr::pop_view()) { - elm_object_part_content_set(this->get_base(), "elm.swallow.content", CONVERT_TO_EO(view->get_content())); + return false; } - else + + ui_view *pview = this->get_view(this->get_view_count() - 2); + ui_view *view = this->get_last_view(); + + //In case, if view doesn't have transition effect + if (!strcmp(view->get_transition_style(), "none")) { - elm_object_part_content_set(this->get_base(), "elm.swallow.content", CONVERT_TO_EO(view->get_base())); + this->pop_view_finished(pview); + this->pop_view_finished(view); + this->active_top_view(); + return true; } - this->set_indicator(view->get_indicator()); + //Choose an effect layout. + Evas_Object *effect = this->set_transition_layout(view->get_transition_style()); + if (!effect) { + LOGE("invalid effect transition style?! = %s", view->get_transition_style()); + this->pop_view_finished(pview); + this->pop_view_finished(view); + this->active_top_view(); + return true; + } + + //Trigger Effects. + Evas_Object *prv = CONVERT_TO_EO(this->get_base() == pview->get_base() ? pview->get_content() : pview->get_base()); + elm_layout_content_set(effect, "content", prv); + + Evas_Object *cur = CONVERT_TO_EO(this->get_base() == view->get_base() ? view->get_content() : view->get_base()); + elm_layout_content_set(effect, "pcontent", cur); + + elm_layout_signal_emit(effect, "view,pop", "viewmgr"); + + this->set_indicator(pview->get_indicator()); return true; } @@ -234,12 +310,53 @@ ui_view * ui_viewmgr::push_view(ui_view *view) if (!this->is_activated()) return view; - this->active_top_view(); + //In case, if viewmgr has one view, we skip effect. + if (this->get_view_count() == 1) { + this->active_top_view(); + this->push_view_finished(view); + return view; + } + + ui_view *pview = this->get_view(this->get_view_count() - 2); + + //In case, if view doesn't have transition effect + if (!strcmp(view->get_transition_style(), "none")) { + this->active_top_view(); + this->push_view_finished(pview); + this->push_view_finished(view); + return view; + } + + //Choose an effect layout. + Evas_Object *effect = this->set_transition_layout(view->get_transition_style()); + if (!effect) { + LOGE("invalid effect transition style?! = %s", view->get_transition_style()); + this->active_top_view(); + this->push_view_finished(pview); + this->push_view_finished(view); + return view; + } + + //Trigger Effects. + Evas_Object *prv = CONVERT_TO_EO(this->get_base() == pview->get_base() ? pview->get_content() : pview->get_base()); + elm_layout_content_set(effect, "pcontent", prv); + + Evas_Object *cur = CONVERT_TO_EO(this->get_base() == view->get_base() ? view->get_content() : view->get_base()); + elm_layout_content_set(effect, "content", cur); + + elm_layout_signal_emit(effect, "view,push", "viewmgr"); + + this->set_indicator(view->get_indicator()); return view; } +ui_view *ui_viewmgr::get_view(unsigned int idx) +{ + return dynamic_cast(ui_iface_viewmgr::get_view(idx)); +} + ui_view *ui_viewmgr::get_last_view() { - return dynamic_cast(ui_iface_viewmgr::get_last_view()); + return dynamic_cast(ui_iface_viewmgr::get_last_view()); } diff --git a/src/lib/interface/ui_iface_view.cpp b/src/lib/interface/ui_iface_view.cpp index ca9b444..39a3dad 100644 --- a/src/lib/interface/ui_iface_view.cpp +++ b/src/lib/interface/ui_iface_view.cpp @@ -83,7 +83,7 @@ void ui_iface_view::destroy() } ui_iface_view::ui_iface_view(ui_iface_controller *controller, const char *name) - : content(NULL), controller(controller), name(string(name ? name : "")), style(string("")), viewmgr(NULL), state(UI_VIEW_STATE_LOAD), + : content(NULL), controller(controller), name(string(name ? name : "")), transition_style(string("")), viewmgr(NULL), state(UI_VIEW_STATE_LOAD), indicator(UI_VIEW_INDICATOR_DEFAULT), event_block(false), removable_content(true) { this->state = UI_VIEW_STATE_UNLOAD; @@ -118,9 +118,9 @@ T ui_iface_view::set_content(T content) return prev; } -bool ui_iface_view::set_style(const char *style) +bool ui_iface_view::set_transition_style(const char *style) { - this->style.assign(style); + this->transition_style.assign(style); return true; } diff --git a/src/lib/interface/ui_iface_viewmgr.cpp b/src/lib/interface/ui_iface_viewmgr.cpp index 5f19c90..3cdfd77 100644 --- a/src/lib/interface/ui_iface_viewmgr.cpp +++ b/src/lib/interface/ui_iface_viewmgr.cpp @@ -70,7 +70,7 @@ bool ui_iface_viewmgr::push_view_finished(ui_iface_view *view) //A new view has been pushed. This should be active. view->active(); - this->set_event_block(view, true); + this->set_event_block(view, false); return true; } @@ -90,7 +90,7 @@ bool ui_iface_viewmgr::pop_view_finished(ui_iface_view *view) //The previous view has been popped. It should become active. view->active(); - this->set_event_block(view, true); + this->set_event_block(view, false); return true; } @@ -134,14 +134,11 @@ ui_iface_viewmgr::push_view(ui_iface_view *view) ui_iface_view *pview; //Previous view - if (this->view_list.size()) + if (this->view_list.size() > 0) { pview = this->view_list.back(); pview->inactive(); this->set_event_block(pview, true); - - //FIXME: Since we have no transition - pview->unload(); } view_list.push_back(view); @@ -159,13 +156,14 @@ ui_iface_viewmgr::push_view(ui_iface_view *view) bool ui_iface_viewmgr::pop_view() { - //No more view? destroy viewmgr? + //FIXME: No more view? if (this->get_view_count() == 0) { + LOGE("No Views. Can't pop anymore!"); return false; } - //This is the last page. destroy viewmgr? + //This is the last page. if (this->get_view_count() == 1) { //destroy viewmgr? @@ -175,7 +173,7 @@ bool ui_iface_viewmgr::pop_view() view->destroy(); delete(view); - return false; + return true; } //last page to be popped. @@ -192,13 +190,6 @@ bool ui_iface_viewmgr::pop_view() pview->inactive(); this->set_event_block(pview, true); - //FIXME: since we have no transition effect - pview->active(); - view->inactive(); - view->unload(); - view->destroy(); - delete (view); - return true; } -- 2.7.4