From: Igor Olshevskyi Date: Tue, 4 Jul 2017 06:12:10 +0000 (+0300) Subject: TizenRefApp-8793 [Call UI] Implement visual cue for the bezel interaction on Incoming... X-Git-Tag: submit/tizen/20170811.141832^2~6 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=4c4078c8575b0b281fd65d413b3ac70f0d615652;p=profile%2Fwearable%2Fapps%2Fnative%2Fcall-ui.git TizenRefApp-8793 [Call UI] Implement visual cue for the bezel interaction on Incoming Call Change-Id: Iaa55224d257713721236aff1ca68add60f564af9 --- diff --git a/edc/accept_reject.edc b/edc/accept_reject.edc index b590692..179e042 100644 --- a/edc/accept_reject.edc +++ b/edc/accept_reject.edc @@ -20,8 +20,120 @@ #define CU_BTN_HIDE_ANIM_TIME 0.2 +#define CU_ARROW_WH 24 + +#define CU_ARROW1_LR 68 +#define CU_ARROW1_T 57 +#define CU_ARROW1_TIME 0.23 + +#define CU_ARROW2_LR 49 +#define CU_ARROW2_T 75 +#define CU_ARROW2_TIME 0.26 + +#define CU_ARROW3_LR 35 +#define CU_ARROW3_T 96 +#define CU_ARROW3_TIME 0.30 + +#define CU_ARROW4_LR 25 +#define CU_ARROW4_T 119 +#define CU_ARROW4_TIME 0.16 + +#define CU_INCOMING_CALL_IMG_DIR "Incoming/" + +#define CU_BEZELCUE_ANIMATE_COUNT_MAX 3 +#define CU_BEZELCUE_HIDE_DURATION 0.5 + +#define CU_PATH_ICON_ARROW1_L CU_INCOMING_CALL_IMG_DIR"w_alert_interaction_cue_l_01.png" +#define CU_PATH_ICON_ARROW2_L CU_INCOMING_CALL_IMG_DIR"w_alert_interaction_cue_l_02.png" +#define CU_PATH_ICON_ARROW3_L CU_INCOMING_CALL_IMG_DIR"w_alert_interaction_cue_l_03.png" +#define CU_PATH_ICON_ARROW4_L CU_INCOMING_CALL_IMG_DIR"w_alert_interaction_cue_l_04.png" + +#define CU_PATH_ICON_ARROW1_R CU_INCOMING_CALL_IMG_DIR"w_alert_interaction_cue_r_01.png" +#define CU_PATH_ICON_ARROW2_R CU_INCOMING_CALL_IMG_DIR"w_alert_interaction_cue_r_02.png" +#define CU_PATH_ICON_ARROW3_R CU_INCOMING_CALL_IMG_DIR"w_alert_interaction_cue_r_03.png" +#define CU_PATH_ICON_ARROW4_R CU_INCOMING_CALL_IMG_DIR"w_alert_interaction_cue_r_04.png" + +#define CU_ARROW_PARTS(NAME, SIDE, ICON_PATH, POS_X, POS_Y, ALIGN_X) \ + spacer { "spacer."NAME"."SIDE"_top"; \ + scale; \ + desc { "default"; \ + fixed: 1 1; \ + min: POS_X POS_Y; \ + align: ALIGN_X 0.0; \ + rel1 { relative: ALIGN_X 0.0; to_x: "spacer."SIDE; } \ + rel2 { relative: ALIGN_X 0.0; to_x: "spacer."SIDE; } \ + } \ + } \ + image { "image."NAME"_"SIDE; \ + scale; \ + images.image: ICON_PATH COMP; \ + clip: "rect.arrows_"SIDE".clipper"; \ + desc { "default"; \ + fixed: 1 1; \ + min: CU_ARROW_WH CU_ARROW_WH; \ + align: ALIGN_X 0.0; \ + rel1 { relative: (1.0-ALIGN_X) 1.0; to: "spacer."NAME"."SIDE"_top"; } \ + rel2 { relative: (1.0-ALIGN_X) 1.0; to: "spacer."NAME"."SIDE"_top"; } \ + image.normal: ICON_PATH; \ + color: 255 255 255 64; \ + } \ + desc { "active"; \ + inherit: "default"; \ + color: 255 255 255 255; \ + } \ + } + +//"image.arrow1_left" "image.arrow2_left" "image.arrow3_left" "image.arrow4_left" "image.arrow1_right" "image.arrow2_right" "image.arrow3_right" "image.arrow4_right" + + +#define CU_ARROW_PROGRAMS(ARROW_NAME, NEXT_ARROW_NAME, DURATION_IN, DURATION_OUT) \ + program { \ + name: "activate_"ARROW_NAME; \ + action: STATE_SET "active"; \ + targets: "image."ARROW_NAME"_left" "image."ARROW_NAME"_right"; \ + transition: LINEAR DURATION_IN; \ + after: "deactivate_"ARROW_NAME; \ + after: "activate_"NEXT_ARROW_NAME; \ + } \ + program { \ + name: "deactivate_"ARROW_NAME; \ + action: STATE_SET "default"; \ + targets: "image."ARROW_NAME"_left" "image."ARROW_NAME"_right"; \ + transition: LINEAR DURATION_OUT; \ + } + group { "elm/layout/callui/accept_reject"; parts { + CU_ARROW_PARTS("arrow1", "left", CU_PATH_ICON_ARROW1_L, CU_ARROW1_LR, CU_ARROW1_T, 0.0) + CU_ARROW_PARTS("arrow2", "left", CU_PATH_ICON_ARROW2_L, CU_ARROW2_LR, CU_ARROW2_T, 0.0) + CU_ARROW_PARTS("arrow3", "left", CU_PATH_ICON_ARROW3_L, CU_ARROW3_LR, CU_ARROW3_T, 0.0) + CU_ARROW_PARTS("arrow4", "left", CU_PATH_ICON_ARROW4_L, CU_ARROW4_LR, CU_ARROW4_T, 0.0) + CU_ARROW_PARTS("arrow1", "right", CU_PATH_ICON_ARROW1_R, CU_ARROW1_LR, CU_ARROW1_T, 1.0) + CU_ARROW_PARTS("arrow2", "right", CU_PATH_ICON_ARROW2_R, CU_ARROW2_LR, CU_ARROW2_T, 1.0) + CU_ARROW_PARTS("arrow3", "right", CU_PATH_ICON_ARROW3_R, CU_ARROW3_LR, CU_ARROW3_T, 1.0) + CU_ARROW_PARTS("arrow4", "right", CU_PATH_ICON_ARROW4_R, CU_ARROW4_LR, CU_ARROW4_T, 1.0) + rect { "rect.arrows_left.clipper"; + desc { "default"; + rel1 { to_x: "image.arrow4_left"; to_y: "image.arrow1_left"; } + rel2 { to_x: "image.arrow1_left"; to_y: "image.arrow4_left"; } + color_class: "TRANSPARENT"; + } + desc { "visible"; + inherit: "default"; + color_class: "AO0113"; + } + } + rect { "rect.arrows_right.clipper"; + desc { "default"; + rel1.to: "image.arrow1_right"; + rel2.to: "image.arrow4_right"; + color_class: "TRANSPARENT"; + } + desc { "visible"; + inherit: "default"; + color_class: "AO0115"; + } + } spacer { "spacer.left"; scale; desc { "default"; @@ -86,16 +198,59 @@ group { "elm/layout/callui/accept_reject"; } } programs { + script { + public arrow_anim_counter; + public is_arrow_anim; + } + program { + signal: "arrows,show"; + source: "*"; + after: "start_arrow_anim"; + } + program { "start_arrow_anim"; + script { + if (get_int(is_arrow_anim) == 0) { + set_int(is_arrow_anim, 1); + set_int(arrow_anim_counter, get_int(arrow_anim_counter) + 1); + run_program(PROGRAM:"show_arrows"); + run_program(PROGRAM:"activate_arrow4"); + } + } + } + program { "activate_check"; + script { + if (get_int(is_arrow_anim) == 1) { + if (get_int(arrow_anim_counter) < CU_BEZELCUE_ANIMATE_COUNT_MAX) { + set_int(is_arrow_anim, 1); + set_int(arrow_anim_counter, get_int(arrow_anim_counter) + 1); + run_program(PROGRAM:"activate_arrow4"); + } else { + set_int(is_arrow_anim, 0); + set_int(arrow_anim_counter, 0); + run_program(PROGRAM:"hide_arrows_anim"); + } + } + } + } + CU_ARROW_PROGRAMS("arrow4", "arrow3", CU_ARROW4_TIME, CU_ARROW3_TIME) + CU_ARROW_PROGRAMS("arrow3", "arrow2", CU_ARROW3_TIME, CU_ARROW2_TIME) + CU_ARROW_PROGRAMS("arrow2", "arrow1", CU_ARROW2_TIME, CU_ARROW1_TIME) + CU_ARROW_PROGRAMS("arrow1", "check", CU_ARROW1_TIME, CU_ARROW4_TIME) program { signal: "accept,show"; source: "*"; action: STATE_SET "default"; target: "spacer.left"; transition: TRANSITION_GLIDE(CU_BTN_HIDE_ANIM_TIME); + after: "try_show_arrows"; } program { signal: "accept,hide"; source: "*"; + after: "hide_arrows"; + after: "accept,hide,anim"; + } + program { "accept,hide,anim"; action: STATE_SET "hidden"; target: "spacer.left"; transition: TRANSITION_GLIDE(CU_BTN_HIDE_ANIM_TIME); @@ -106,10 +261,15 @@ group { "elm/layout/callui/accept_reject"; action: STATE_SET "default"; target: "spacer.right"; transition: TRANSITION_GLIDE(CU_BTN_HIDE_ANIM_TIME); + after: "try_show_arrows"; } program { signal: "reject,hide"; source: "*"; + after: "hide_arrows"; + after: "reject,hide,anim"; + } + program { "reject,hide,anim"; action: STATE_SET "hidden"; target: "spacer.right"; transition: TRANSITION_GLIDE(CU_BTN_HIDE_ANIM_TIME); @@ -119,6 +279,29 @@ group { "elm/layout/callui/accept_reject"; source: "*"; action: STATE_SET "default"; targets: "spacer.right" "spacer.left"; + after: "try_show_arrows"; + } + program { "try_show_arrows"; + script { + if (get_int(is_arrow_anim) == 1) { + run_program(PROGRAM:"show_arrows"); + } else { + run_program(PROGRAM:"hide_arrows"); + } + } + } + program { "show_arrows"; + action: STATE_SET "visible"; + targets: "rect.arrows_left.clipper" "rect.arrows_right.clipper"; + } + program { "hide_arrows"; + action: STATE_SET "default"; + targets: "rect.arrows_left.clipper" "rect.arrows_right.clipper"; + } + program { "hide_arrows_anim"; + action: STATE_SET "default"; + targets: "rect.arrows_left.clipper" "rect.arrows_right.clipper"; + transition: LINEAR CU_BEZELCUE_HIDE_DURATION; } } } \ No newline at end of file diff --git a/edc/images/Incoming/w_alert_interaction_cue_l_01.png b/edc/images/Incoming/w_alert_interaction_cue_l_01.png new file mode 100644 index 0000000..87cfaaa Binary files /dev/null and b/edc/images/Incoming/w_alert_interaction_cue_l_01.png differ diff --git a/edc/images/Incoming/w_alert_interaction_cue_l_02.png b/edc/images/Incoming/w_alert_interaction_cue_l_02.png new file mode 100644 index 0000000..6342aac Binary files /dev/null and b/edc/images/Incoming/w_alert_interaction_cue_l_02.png differ diff --git a/edc/images/Incoming/w_alert_interaction_cue_l_03.png b/edc/images/Incoming/w_alert_interaction_cue_l_03.png new file mode 100644 index 0000000..bd204e1 Binary files /dev/null and b/edc/images/Incoming/w_alert_interaction_cue_l_03.png differ diff --git a/edc/images/Incoming/w_alert_interaction_cue_l_04.png b/edc/images/Incoming/w_alert_interaction_cue_l_04.png new file mode 100644 index 0000000..6845552 Binary files /dev/null and b/edc/images/Incoming/w_alert_interaction_cue_l_04.png differ diff --git a/edc/images/Incoming/w_alert_interaction_cue_r_01.png b/edc/images/Incoming/w_alert_interaction_cue_r_01.png new file mode 100644 index 0000000..8d6ae40 Binary files /dev/null and b/edc/images/Incoming/w_alert_interaction_cue_r_01.png differ diff --git a/edc/images/Incoming/w_alert_interaction_cue_r_02.png b/edc/images/Incoming/w_alert_interaction_cue_r_02.png new file mode 100644 index 0000000..955eff8 Binary files /dev/null and b/edc/images/Incoming/w_alert_interaction_cue_r_02.png differ diff --git a/edc/images/Incoming/w_alert_interaction_cue_r_03.png b/edc/images/Incoming/w_alert_interaction_cue_r_03.png new file mode 100644 index 0000000..f19a064 Binary files /dev/null and b/edc/images/Incoming/w_alert_interaction_cue_r_03.png differ diff --git a/edc/images/Incoming/w_alert_interaction_cue_r_04.png b/edc/images/Incoming/w_alert_interaction_cue_r_04.png new file mode 100644 index 0000000..270f651 Binary files /dev/null and b/edc/images/Incoming/w_alert_interaction_cue_r_04.png differ diff --git a/inc/presenters/AcceptRejectPresenter.h b/inc/presenters/AcceptRejectPresenter.h index 5268f0d..41f426e 100644 --- a/inc/presenters/AcceptRejectPresenter.h +++ b/inc/presenters/AcceptRejectPresenter.h @@ -62,6 +62,7 @@ namespace callui { ucl::Result createWidget(ucl::ElmWidget &parent); ucl::Result createAcceptBtn(); ucl::Result createRejectBtn(); + ucl::Result createMotionSensorPresenter(); ucl::StyledWidgetSRef createBtn(const ucl::ElmStyle &style, const ucl::EdjePart &part); @@ -75,12 +76,14 @@ namespace callui { void onBtnClicked(ucl::Widget &widget, void *eventInfo); Eina_Bool onRotaryEvent(Eext_Rotary_Event_Info *info); + void onMotionEvent(); bool onAcceptPopupEvent(AcceptDialog &popup, AcceptDialogEvent event); private: ucl::LayoutSRef m_widget; AcceptDialogWRef m_popup; + MotionSensorPresenterSRef m_motionPrs; ucl::StyledWidgetSRef m_accept; ucl::StyledWidgetSRef m_reject; diff --git a/inc/presenters/MotionSensorPresenter.h b/inc/presenters/MotionSensorPresenter.h new file mode 100644 index 0000000..4e6041f --- /dev/null +++ b/inc/presenters/MotionSensorPresenter.h @@ -0,0 +1,54 @@ +/* + * Copyright 2017 Samsung Electronics Co., Ltd + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CALLUI_PRESENTERS_MOTION_SENSOR_PRESENTER_H__ +#define __CALLUI_PRESENTERS_MOTION_SENSOR_PRESENTER_H__ + +#include + +#include "types.h" + +namespace callui { + + class MotionSensorPresenter final + { + public: + class Builder { + public: + Builder(); + ~Builder(); + MotionSensorPresenterSRef build(const MotionSensorHandler handler) const; + }; + private: + friend class ucl::ReffedObj; + MotionSensorPresenter(const MotionSensorHandler &handler); + virtual ~MotionSensorPresenter(); + + ucl::Result prepare(); + + void onGestureCb(gesture_type_e motion, + const gesture_data_h data, + double timeStamp, + gesture_error_e error); + + private: + MotionSensorHandler m_handler; + gesture_h m_gesture; + }; + +} + +#endif // __CALLUI_PRESENTERS_MOTION_SENSOR_PRESENTER_H__ diff --git a/inc/presenters/types.h b/inc/presenters/types.h index 4978b78..516fc87 100644 --- a/inc/presenters/types.h +++ b/inc/presenters/types.h @@ -75,10 +75,12 @@ namespace callui { UCL_DECLARE_REF_ALIASES(MoreOptionsPresenter); UCL_DECLARE_REF_ALIASES(DeviceStatePresenter); + UCL_DECLARE_REF_ALIASES(MotionSensorPresenter); using AcceptDialogHandler = ucl::WeakDelegate; using RejectMsgStateHandler = ucl::WeakDelegate; using RejectMsgSelectHandler = ucl::WeakDelegate; + using MotionSensorHandler = ucl::WeakDelegate; } #endif // __CALLUI_PRESENTERS_TYPES_H__ diff --git a/src/presenters/AcceptRejectPresenter.cpp b/src/presenters/AcceptRejectPresenter.cpp index 97d00ac..33ba40c 100644 --- a/src/presenters/AcceptRejectPresenter.cpp +++ b/src/presenters/AcceptRejectPresenter.cpp @@ -18,6 +18,7 @@ #include "model/IIncomingCall.h" #include "presenters/AcceptDialog.h" +#include "presenters/MotionSensorPresenter.h" #include "../view/common.h" #include "common.h" @@ -34,6 +35,7 @@ namespace callui { namespace { namespace impl { constexpr EdjeSignal SIGNAL_REJECT_SHOW {"reject,show"}; constexpr EdjeSignal SIGNAL_REJECT_HIDE {"reject,hide"}; + constexpr EdjeSignal SIGNAL_ARROWS_SHOW {"arrows,show"}; constexpr EdjeSignal SIGNAL_RESET {"reset"}; constexpr EdjePart PART_SWL_BTN_ACCEPT {"swl.button_accept"}; @@ -136,6 +138,11 @@ namespace callui { FAIL_RETURN(createRejectBtn(), "createRejectBtn() failed!"); + // Motion sensor not supported on Emulator + if (createMotionSensorPresenter() != RES_OK) { + ELOG("createMotionSensorPresenter() failed!"); + } + addRotaryEventHandler(CALLBACK_A( AcceptRejectPresenter::onRotaryEvent), this); @@ -194,6 +201,25 @@ namespace callui { return RES_OK; } + Result AcceptRejectPresenter::createMotionSensorPresenter() + { + m_motionPrs = MotionSensorPresenter::Builder(). + build(WEAK_DELEGATE(AcceptRejectPresenter::onMotionEvent, + asWeak(*this))); + + if (!m_motionPrs) { + LOG_RETURN(RES_FAIL, + "MotionSensorPresenter::build() failed!"); + } + + return RES_OK; + } + + void AcceptRejectPresenter::onMotionEvent() + { + m_widget->emit(impl::SIGNAL_ARROWS_SHOW); + } + void AcceptRejectPresenter::onBtnPressed(Widget &widget, void *eventInfo) { if (widget == (*m_accept)) { diff --git a/src/presenters/MotionSensorPresenter.cpp b/src/presenters/MotionSensorPresenter.cpp new file mode 100644 index 0000000..4914528 --- /dev/null +++ b/src/presenters/MotionSensorPresenter.cpp @@ -0,0 +1,100 @@ +/* + * Copyright 2017 Samsung Electronics Co., Ltd + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "presenters/MotionSensorPresenter.h" + +#include "common.h" + +namespace callui { + + using namespace ucl; + + MotionSensorPresenter::Builder::Builder() + { + } + + MotionSensorPresenter::Builder::~Builder() + { + } + + MotionSensorPresenterSRef + MotionSensorPresenter::Builder::build( + const MotionSensorHandler handler) const + { + auto result = makeShared(handler); + FAIL_RETURN_VALUE(result->prepare(), + {}, "result->prepare() failed!"); + return result; + } + + MotionSensorPresenter::MotionSensorPresenter( + const MotionSensorHandler &handler): + m_handler(handler), + m_gesture(nullptr) + { + } + + MotionSensorPresenter::~MotionSensorPresenter() + { + if (m_gesture) { + gesture_stop_recognition(m_gesture); + gesture_release(m_gesture); + } + } + + Result MotionSensorPresenter::prepare() + { + int res = gesture_create(&m_gesture); + if (res != GESTURE_ERROR_NONE) { + LOG_RETURN(RES_FAIL, "gesture_create() failed. " + "res[%d] msg[%s]", res, get_error_message(res)); + } + + res = gesture_start_recognition(m_gesture, GESTURE_WRIST_UP, + GESTURE_OPTION_ALWAYS_ON, + CALLBACK_B(MotionSensorPresenter::onGestureCb), + this); + if (res != GESTURE_ERROR_NONE) { + LOG_RETURN(RES_FAIL, "gesture_start_recognition() failed. " + "res[%d] msg[%s]", res, get_error_message(res)); + } + return RES_OK; + } + + void MotionSensorPresenter::onGestureCb(gesture_type_e motion, + const gesture_data_h data, + double timeStamp, + gesture_error_e error) + { + if (error) { + LOG_RETURN_VOID(RES_FAIL, "Error occured. " + "err[%d] msg[%s]", error, get_error_message(error)); + } + + if (motion == GESTURE_WRIST_UP) { + gesture_event_e event; + int res = gesture_get_event(data, &event); + if (res != GESTURE_ERROR_NONE) { + LOG_RETURN_VOID(RES_FAIL, "gesture_get_event() failed. " + "err[%d] msg[%s]", res, get_error_message(res)); + } + + if (event == GESTURE_EVENT_DETECTED && m_handler) { + m_handler(); + } + } + } +}