From: Igor Olshevskyi Date: Thu, 4 May 2017 09:28:19 +0000 (+0300) Subject: TizenRefApp-8513 [Call UI] Implement CallInfoPresenter & TizenRefApp-8514 [Call UI... X-Git-Tag: submit/tizen/20170630.111746~8 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=664fe472aa1a5ab518b7a2782b478b35c494f2e5;p=profile%2Fwearable%2Fapps%2Fnative%2Fcall-ui.git TizenRefApp-8513 [Call UI] Implement CallInfoPresenter & TizenRefApp-8514 [Call UI] Implement CallStatus Change-Id: I7db3f6f0043d866e98dd0c6203e4929628c536de --- diff --git a/.cproject b/.cproject index e2edb59..eb6f60d 100644 --- a/.cproject +++ b/.cproject @@ -401,12 +401,16 @@ + + + + - + - - - + + + diff --git a/edc/call_info.edc b/edc/call_info.edc new file mode 100644 index 0000000..5bcef54 --- /dev/null +++ b/edc/call_info.edc @@ -0,0 +1,637 @@ +/* + * 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. + */ + +styles { + style { + name: "call_status"; + base: "font=Tizen font_weight=Regular font_width=Condensed font_size=24 align=center valign=center color=#FFFFFF ellipsis=1.0"; + } + style { + name: "call_status_with_photo"; + base: "font=Tizen font_weight=Regular font_width=Condensed font_size=24 align=center valign=center color=#FFFFFF ellipsis=1.0"; + } + style { + name: "main_text"; + base: "font=Tizen font_weight=Regular font_width=Condensed font_size=40 align=center valign=center color=#FFFFFF wrap=mixed ellipsis=1.0"; + tag: "br" "\n"; + tag: "ps" "ps"; + tag: "whitecolor" "+ color=#ffffff"; + tag: "tab" "\t"; + } + style { + name: "main_text_with_photo"; + base: "font=Tizen font_weight=Regular font_width=Condensed font_size=40 align=center valign=center color=#FFFFFF wrap=mixed ellipsis=1.0"; + tag: "br" "\n"; + tag: "ps" "ps"; + tag: "whitecolor" "+ color=#ffffff"; + tag: "tab" "\t"; + } + style { + name: "main_text_emergency"; + base: "font=Tizen font_weight=Regular font_width=Condensed font_size=38 align=center valign=center color=#FF870F wrap=mixed ellipsis=1.0"; + tag: "br" "\n"; + tag: "ps" "ps"; + tag: "whitecolor" "+ color=#ffffff"; + tag: "tab" "\t"; + } +} + +#define CU_DOT(_name, _ltr_offset, _rtl_offset) \ + image { _name; \ + scale; \ + desc { "default"; \ + fixed: 1 1; \ + align: 0.0 0.5; \ + min: 4 4; \ + max: 4 4; \ + image.normal: "w_call_dot.png"; \ + rel1 { relative: 1.0 0.0; offset: _ltr_offset 0; to: "text_info"; } \ + rel2 { relative: 1.0 1.0; offset: _ltr_offset 0; to: "text_info"; } \ + visible: 0; \ + } \ + desc { "on"; \ + inherit: "default"; \ + color_class: AO031; \ + visible: 1; \ + } \ + desc { "off"; \ + inherit: "default"; \ + color_class: AO031D; \ + visible: 1; \ + } \ + desc { "on_photo"; \ + inherit: "default"; \ + color_class: AO0311; \ + visible: 1; \ + } \ + desc { "off_photo"; \ + inherit: "default"; \ + color_class: AO0311D; \ + visible: 1; \ + } \ + desc { "default_rtl"; \ + inherit: "default"; \ + align: 1.0 0.5; \ + rel1 { relative: 0.0 0.0; offset: _rtl_offset 0; to: "text_info"; } \ + rel2 { relative: 0.0 1.0; offset: _rtl_offset 0; to: "text_info"; } \ + } \ + desc { "rtl_on"; \ + inherit: "default_rtl"; \ + color_class: AO031; \ + visible: 1; \ + } \ + desc { "rtl_off"; \ + inherit: "default_rtl"; \ + color_class: AO031D; \ + visible: 1; \ + } \ + desc { "rtl_on_photo"; \ + inherit: "default_rtl"; \ + color_class: AO0311; \ + visible: 1; \ + } \ + desc { "rtl_off_photo"; \ + inherit: "default_rtl"; \ + color_class: AO0311D; \ + visible: 1; \ + } \ + } + +#define CU_TOP_PADDING_1_LINE 0 95 +#define CU_TOP_PADDING_2_LINE 0 95 + +group { "elm/layout/callui/call_info"; + images { + image: "w_call_dot.png" COMP; + } + parts { + spacer { "bg"; + scale; + } + swallow { "caller_id"; + scale; + desc { "default"; + rel1 { relative: 0.0 0.0; to: "bg"; } + rel2 { relative: 1.0 1.0; to: "bg"; } + } + } + rect { "caller_id.mask"; + scale; + desc { "default"; + rel1 { relative: 0.0 0.0; to: "bg"; } + rel2 { relative: 1.0 1.0; to: "bg"; } + color_class: TRANSPARENT; + } + desc { "incoming"; + inherit: "default"; + color_class: AO0242; + } + } + spacer { "top.pad"; + scale; + desc { "default"; + min: 0 95; + fixed: 0 1; + align: 0.5 0.0; + rel1 { relative: 0.0 0.0; to: "bg"; } + rel2 { relative: 1.0 0.0; to: "bg"; } + } + desc { "1line"; + inherit: "default"; + min: 0 119; + } + desc { "incom_1line"; + inherit: "default"; + min: 0 119; + } + desc { "incom_2line"; + inherit: "default"; + min: 0 95; + } + desc { "2line_1text"; + inherit: "default"; + min: 0 99; + } + desc { "2line_2text"; + inherit: "default"; + min: 0 75; + } + } + spacer { "left.pad"; + scale; + desc { "default"; + min: 76 0; + fixed: 1 0; + align: 0.0 0.5; + rel1 { relative: 0.0 0.0; to: "bg"; } + rel2 { relative: 0.0 1.0; to: "bg"; } + } + } + spacer { "right.pad"; + scale; + desc { "default"; + min: 76 0; + fixed: 1 0; + align: 1.0 0.0; + rel1 { relative: 1.0 0.0; to: "bg"; } + rel2 { relative: 1.0 1.0; to: "bg"; } + } + } + spacer { "zone.text_info"; + scale; + desc { "default"; + fixed: 1 1; + align: 0.0 0.0; + min: 208 32; + max: 208 32; + rel1 { relative: 1.0 1.0; to_x: "left.pad"; to_y: "top.pad"; } + rel2 { relative: 0.0 1.0; to_x: "right.pad"; to_y: "top.pad"; } + } + desc { "incom"; + inherit: "default"; + min: 191 32; + max: 191 32; + rel2 { relative: 0.0 1.0; offset: -17 0; to_x: "right.pad"; to_y: "top.pad"; } + } + desc { "incom_rtl"; + inherit: "default"; + min: 191 32; + max: 191 32; + rel1 { relative: 1.0 1.0; offset: 17 0; to_x: "left.pad"; to_y: "top.pad"; } + } + } + textblock { "text_info"; + nomouse; + scale; + desc { "default"; + rel1 { relative: 0.5 0.0; to: "zone.text_info"; } + rel2 { relative: 0.5 1.0; to: "zone.text_info"; } + text { + style: "call_status"; + min: 1 0; + } + } + desc { "photo"; + inherit: "default"; + text { + style: "call_status_with_photo"; + min: 1 0; + } + } + } + CU_DOT("dot.first", 3, -3) + CU_DOT("dot.second", 9, -9) + CU_DOT("dot.third", 15, -15) + rect { "ao_text_info"; + mouse; + scale; + desc { "default"; + rel1.to: "text_info"; + rel2.to: "text_info"; + color: 0 0 0 0; + } + } + spacer { "zone.text_info.bottom.pad"; + scale; + desc { "default"; + align: 0.5 1.0; + min: 0 2; + rel1 { relative: 0.0 1.0; to: "zone.text_info"; } + rel2 { relative: 1.0 1.0; to: "zone.text_info"; } + } + } + spacer { "zone.text_1line"; + scale; + desc { "default"; + fixed: 0 1; + align: 0.5 0.0; + min: 208 107; + max: 208 107; + rel1 { relative: 1.0 1.0; to_x: "left.pad"; to_y: "zone.text_info.bottom.pad"; } + rel2 { relative: 0.0 1.0; to_x: "right.pad"; to_y: "zone.text_info.bottom.pad"; } + } + desc { "1line"; + inherit: "default"; + min: 208 52; + max: 208 52; + } + desc { "incom_2line"; + inherit: "default"; + min: 190 107; + max: 190 107; + } + desc { "incom_1line"; + inherit: "default"; + min: 190 52; + max: 190 52; + } + } + textblock { "text_1line"; + nomouse; + scale; + desc { "default"; + fixed: 1 1; + rel1.to: "zone.text_1line"; + rel2.to: "zone.text_1line"; + text.style: "main_text"; + } + desc { "photo"; + inherit: "default"; + text.style: "main_text_with_photo"; + } + desc { "emergency"; + inherit: "default"; + text.style: "main_text_emergency"; + } + } + rect { "ao_text_1line"; + mouse; + scale; + desc { "default"; + rel1.to: "text_1line"; + rel2.to: "text_1line"; + color: 0 0 0 0; + } + } + spacer { "zone.text_1line.bottom.pad"; + scale; + desc { "default"; + align: 0.5 1.0; + min: 0 6; + rel1 { relative: 0.0 1.0; to: "zone.text_1line"; } + rel2 { relative: 1.0 1.0; to: "zone.text_1line"; } + } + } + spacer { "zone.text_2line"; + scale; + desc { "default"; + fixed: 0 1; + align: 0.0 0.0; + min: 208 32; + max: 208 32; + rel1 { relative: 1.0 1.0; to_x: "left.pad"; to_y: "zone.text_1line.bottom.pad"; } + rel2 { relative: 0.0 1.0; to_x: "right.pad"; to_y: "zone.text_1line.bottom.pad"; } + } + } + swallow { "text_2line"; + nomouse; + scale; + desc { "default"; + fixed: 1 1; + rel1.to: "zone.text_2line"; + rel2.to: "zone.text_2line"; + } + } + rect { "ao_text_2line"; + mouse; + scale; + desc { "default"; + rel1.to: "text_2line"; + rel2.to: "text_2line"; + color: 0 0 0 0; + } + } + } + programs { + script { + public b_set_photo; + public blink_dot_timer; + + public do_blinking(count, part_state) { + if (count%6 == 0) { + if (get_int(b_set_photo) == 1) { + set_state(PART:"dot.first", "on_photo", 0.0); + set_state(PART:"dot.second", "off_photo", 0.0); + set_state(PART:"dot.third", "off_photo", 0.0); + } else { + set_state(PART:"dot.first", "on", 0.0); + set_state(PART:"dot.second", "off", 0.0); + set_state(PART:"dot.third", "off", 0.0); + } + set_int(blink_dot_timer, timer(0.5, "do_blinking", count+1)); + } + else if (count%6 == 1) { + if (get_int(b_set_photo) == 1) { + set_state(PART:"dot.first", "on_photo", 0.0); + set_state(PART:"dot.second", "on_photo", 0.0); + set_state(PART:"dot.third", "off_photo", 0.0); + } else { + set_state(PART:"dot.first", "on", 0.0); + set_state(PART:"dot.second", "on", 0.0); + set_state(PART:"dot.third", "off", 0.0); + } + set_int(blink_dot_timer, timer(0.5, "do_blinking", count+1)); + } + else if (count%6 == 2) { + if (get_int(b_set_photo) == 1) { + set_state(PART:"dot.first", "on_photo", 0.0); + set_state(PART:"dot.second", "on_photo", 0.0); + set_state(PART:"dot.third", "on_photo", 0.0); + } else { + set_state(PART:"dot.first", "on", 0.0); + set_state(PART:"dot.second", "on", 0.0); + set_state(PART:"dot.third", "on", 0.0); + } + set_int(blink_dot_timer, timer(0.5, "do_blinking", count+1)); + } + else if (count%6 == 3) { + if (get_int(b_set_photo) == 1) { + set_state(PART:"dot.first", "off_photo", 0.0); + set_state(PART:"dot.second", "on_photo", 0.0); + set_state(PART:"dot.third", "on_photo", 0.0); + } else { + set_state(PART:"dot.first", "off", 0.0); + set_state(PART:"dot.second", "on", 0.0); + set_state(PART:"dot.third", "on", 0.0); + } + set_int(blink_dot_timer, timer(0.5, "do_blinking", count+1)); + } + else if (count%6 == 4) { + if (get_int(b_set_photo) == 1) { + set_state(PART:"dot.first", "off_photo", 0.0); + set_state(PART:"dot.second", "off_photo", 0.0); + set_state(PART:"dot.third", "on_photo", 0.0); + } else { + set_state(PART:"dot.first", "off", 0.0); + set_state(PART:"dot.second", "off", 0.0); + set_state(PART:"dot.third", "on", 0.0); + } + set_int(blink_dot_timer, timer(0.5, "do_blinking", count+1)); + } + else if (count%6 == 5) { + if (get_int(b_set_photo) == 1) { + set_state(PART:"dot.first", "off_photo", 0.0); + set_state(PART:"dot.second", "off_photo", 0.0); + set_state(PART:"dot.third", "off_photo", 0.0); + } else { + set_state(PART:"dot.first", "off", 0.0); + set_state(PART:"dot.second", "off", 0.0); + set_state(PART:"dot.third", "off", 0.0); + } + set_int(blink_dot_timer, timer(0.5, "do_blinking", count+1)); + } + } + public do_blinking_rtl(count, part_state) { + if (count%6 == 0) { + if (get_int(b_set_photo) == 1) { + set_state(PART:"dot.first", "rtl_on_photo", 0.0); + set_state(PART:"dot.second", "rtl_off_photo", 0.0); + set_state(PART:"dot.third", "rtl_off_photo", 0.0); + } else { + set_state(PART:"dot.first", "rtl_on", 0.0); + set_state(PART:"dot.second", "rtl_off", 0.0); + set_state(PART:"dot.third", "rtl_off", 0.0); + } + set_int(blink_dot_timer, timer(0.5, "do_blinking_rtl", count+1)); + } + else if (count%6 == 1) { + if (get_int(b_set_photo) == 1) { + set_state(PART:"dot.first", "rtl_on_photo", 0.0); + set_state(PART:"dot.second", "rtl_on_photo", 0.0); + set_state(PART:"dot.third", "rtl_off_photo", 0.0); + } else { + set_state(PART:"dot.first", "rtl_on", 0.0); + set_state(PART:"dot.second", "rtl_on", 0.0); + set_state(PART:"dot.third", "rtl_off", 0.0); + } + set_int(blink_dot_timer, timer(0.5, "do_blinking_rtl", count+1)); + } + else if (count%6 == 2) { + if (get_int(b_set_photo) == 1) { + set_state(PART:"dot.first", "rtl_on_photo", 0.0); + set_state(PART:"dot.second", "rtl_on_photo", 0.0); + set_state(PART:"dot.third", "rtl_on_photo", 0.0); + } else { + set_state(PART:"dot.first", "rtl_on", 0.0); + set_state(PART:"dot.second", "rtl_on", 0.0); + set_state(PART:"dot.third", "rtl_on", 0.0); + } + set_int(blink_dot_timer, timer(0.5, "do_blinking_rtl", count+1)); + } + else if (count%6 == 3) { + if (get_int(b_set_photo) == 1) { + set_state(PART:"dot.first", "rtl_off_photo", 0.0); + set_state(PART:"dot.second", "rtl_on_photo", 0.0); + set_state(PART:"dot.third", "rtl_on_photo", 0.0); + } else { + set_state(PART:"dot.first", "rtl_off", 0.0); + set_state(PART:"dot.second", "rtl_on", 0.0); + set_state(PART:"dot.third", "rtl_on", 0.0); + } + set_int(blink_dot_timer, timer(0.5, "do_blinking_rtl", count+1)); + } + else if (count%6 == 4) { + if (get_int(b_set_photo) == 1) { + set_state(PART:"dot.first", "rtl_off_photo", 0.0); + set_state(PART:"dot.second", "rtl_off_photo", 0.0); + set_state(PART:"dot.third", "rtl_on_photo", 0.0); + } else { + set_state(PART:"dot.first", "rtl_off", 0.0); + set_state(PART:"dot.second", "rtl_off", 0.0); + set_state(PART:"dot.third", "rtl_on", 0.0); + } + set_int(blink_dot_timer, timer(0.5, "do_blinking_rtl", count+1)); + } + else if (count%6 == 5) { + if (get_int(b_set_photo) == 1) { + set_state(PART:"dot.first", "rtl_off_photo", 0.0); + set_state(PART:"dot.second", "rtl_off_photo", 0.0); + set_state(PART:"dot.third", "rtl_off_photo", 0.0); + } else { + set_state(PART:"dot.first", "rtl_off", 0.0); + set_state(PART:"dot.second", "rtl_off", 0.0); + set_state(PART:"dot.third", "rtl_off", 0.0); + } + set_int(blink_dot_timer, timer(0.5, "do_blinking_rtl", count+1)); + } + } + } + program { + signal: "reset"; + source: "top_padding"; + script { + set_state(PART:"top.pad", "default", 0.0); + set_state(PART:"zone.text_1line", "default", 0.0); + set_state(PART:"text_1line", "default", 0.0); + } + } + program { + signal: "reset"; + source: "dot"; + script { + set_state(PART:"zone.text_info", "default", 0.0); + cancel_timer(get_int(blink_dot_timer)); + set_int(blink_dot_timer, 0); + set_state(PART:"dot.first", "default", 0.0); + set_state(PART:"dot.second", "default", 0.0); + set_state(PART:"dot.third", "default", 0.0); + } + } + program { + signal: "default:RTL"; + source: "dot"; + script { + set_state(PART:"zone.text_info", "incom_rtl", 0.0); + set_int(blink_dot_timer, timer(0.1, "do_blinking_rtl", 0)); + } + } + program { + signal: "default:LTR"; + source: "dot"; + script { + set_state(PART:"zone.text_info", "incom", 0.0); + set_int(blink_dot_timer, timer(0.1, "do_blinking", 0)); + } + } + program { + signal: "1line"; + source: "top_padding"; + script { + set_state(PART:"top.pad", "1line", 0.0); + set_state(PART:"zone.text_1line", "1line", 0.0); + } + } + program { + signal: "2line"; + source: "top_padding"; + script { + set_state(PART:"top.pad", "default", 0.0); + set_state(PART:"zone.text_1line", "default", 0.0); + } + } + program { + signal: "incom_1line"; + source: "top_padding"; + script { + set_state(PART:"top.pad", "incom_1line", 0.0); + set_state(PART:"zone.text_1line", "incom_1line", 0.0); + } + } + program { + signal: "incom_2line"; + source: "top_padding"; + script { + set_state(PART:"top.pad", "incom_2line", 0.0); + set_state(PART:"zone.text_1line", "incom_2line", 0.0); + } + } + program { + signal: "emergency"; + source: "top_padding"; + script { + set_state(PART:"top.pad", "default", 0.0); + set_state(PART:"zone.text_1line", "default", 0.0); + } + } + program { + signal: "2line_2text"; + source: "top_padding"; + script { + set_state(PART:"top.pad", "2line_2text", 0.0); + set_state(PART:"text_1line", "default", 0.0); + } + } + program { + signal: "1line_2text"; + source: "top_padding"; + script { + set_state(PART:"top.pad", "default", 0.0); + set_state(PART:"zone.text_1line", "1line", 0.0); + set_state(PART:"text_1line", "default", 0.0); + } + } + program { + signal: "caller_id_enable"; + source: "text_1line"; + script { + set_int(b_set_photo, 1); + set_state(PART:"text_1line", "photo", 0.0); + set_state(PART:"text_info", "photo", 0.0); + } + } + program { + signal: "caller_id_disable"; + source: "text_1line"; + script { + set_int(b_set_photo, 0); + set_state(PART:"text_1line", "default", 0.0); + set_state(PART:"text_info", "default", 0.0); + } + } + program { + signal: "emergency"; + source: "text_1line"; + script { + set_state(PART:"text_1line", "emergency", 0.0); + set_state(PART:"text_info", "default", 0.0); + } + } + program { + signal: "caller_id_enable"; + source: "caller_id"; + script { + set_state(PART:"caller_id.mask", "incoming", 0.0); + } + } + program { + signal: "caller_id_disable"; + source: "caller_id"; + script { + set_state(PART:"caller_id.mask", "default", 0.0); + } + } + } +} diff --git a/edc/color_classes.edc b/edc/color_classes.edc index 10b781f..df4e2d2 100644 --- a/edc/color_classes.edc +++ b/edc/color_classes.edc @@ -15,6 +15,9 @@ */ color_classes { + color_class { name: "TRANSPARENT"; + color: 0 0 0 0; + } // Incoming call circles color_class { name: "AO0115"; @@ -54,4 +57,19 @@ color_classes { color_class { name: "AO0254"; color: 255 0 0 255; } + color_class { name: "AO0242"; + color: 0 0 0 127; + } + color_class { name: "AO031"; + color: 255 255 255 255; + } + color_class { name: "AO031D"; + color: 255 255 255 77; + } + color_class { name: "AO0311"; + color: 255 255 255 255; + } + color_class { name: "AO0311D"; + color: 255 255 255 77; + } } diff --git a/edc/layouts.edc b/edc/layouts.edc index bc300ca..fb1b3bc 100644 --- a/edc/layouts.edc +++ b/edc/layouts.edc @@ -53,6 +53,11 @@ group { "elm/layout/callui/main"; parts { + swallow { "swl.call_info"; + scale; + desc { "default"; + } + } swallow { "swl.indicator"; scale; desc { "default"; diff --git a/inc/model/IBaseCallInfo.h b/inc/model/IBaseCallInfo.h index 3d1dd6a..f369898 100644 --- a/inc/model/IBaseCallInfo.h +++ b/inc/model/IBaseCallInfo.h @@ -25,7 +25,7 @@ namespace callui { public: virtual unsigned int getCallId() const = 0; virtual const std::string &getPhoneNumber() const = 0; - virtual IContactInfoSCRef getContactInfo() const = 0; + virtual IContactInfoWCRef getContactInfo() const = 0; }; } diff --git a/inc/model/ICallInfo.h b/inc/model/ICallInfo.h index fbe8de6..8088931 100644 --- a/inc/model/ICallInfo.h +++ b/inc/model/ICallInfo.h @@ -19,13 +19,15 @@ #include "IBaseCallInfo.h" +#include + #include "types.h" namespace callui { class ICallInfo : public IBaseCallInfo { public: - virtual long getStartTime() const = 0; + virtual struct tm getDuration() const = 0; virtual bool isEmergency() const = 0; virtual bool isHDVoice() const = 0; virtual bool isForwarded() const = 0; diff --git a/inc/presenters/CallInfoPresenter.h b/inc/presenters/CallInfoPresenter.h new file mode 100644 index 0000000..3320306 --- /dev/null +++ b/inc/presenters/CallInfoPresenter.h @@ -0,0 +1,96 @@ +/* + * 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_CALL_INFO_PRESENTER_H__ +#define __CALLUI_PRESENTERS_CALL_INFO_PRESENTER_H__ + +#include "ucl/gui/Layout.h" +#include "ucl/gui/StyledWidget.h" + +#include "types.h" + +namespace callui { + + class CallInfoPresenter final : public ucl::RefCountAware { + public: + class Builder { + public: + Builder(); + virtual ~Builder(); + Builder &setCallManager(const ICallManagerSRef &cm); + Builder &setMode(CallInfoMode mode); + CallInfoPresenterSRef build(ucl::ElmWidget &parent) const; + private: + ICallManagerSRef m_cm; + CallInfoMode m_mode; + }; + + public: + virtual ~CallInfoPresenter(); + + ucl::Widget &getWidget(); + CallInfoMode getMode() const; + ucl::Result update(CallInfoMode mode, const ICallManagerSRef &cm); + + private: + friend class ucl::RefCountObj; + CallInfoPresenter(ucl::RefCountObjBase &rc, + const ICallManagerSRef &cm, + CallInfoMode mode); + + ucl::Result prepare(ucl::Widget &parent); + + void initCallInfos(const ICallManagerSRef &cm); + + ucl::Result createWidget(ucl::Widget &parent); + ucl::Result createLabel(const std::string &text); + ucl::Result createCallStatus(); + + ucl::Result update(); + ucl::Result updateCallerId(); + ucl::Result updateSubText(); + ucl::Result updateMainTxt(); + + std::string getNumberSubText(const ICallInfoWCRef &callInfo) const; + std::string getIncomingCallSubText() const; + std::string getOutgoingCallSubText() const; + std::string getDuringCallSubText() const; + std::string getEndCallSubText() const; + + std::string generateMainTxt(const ICallInfoWCRef &callInfo); + + void displayMainTxt(const std::string &text) const; + void displaySubTxt(const std::string &text) const; + + private: + ucl::LayoutSRef m_widget; + ucl::StyledWidgetSRef m_callerId; + ucl::StyledWidgetSRef m_label; + CallInfoMode m_mode; + ICallInfoSCRef m_incomCallInfo; + ICallInfoSCRef m_activeCallInfo; + ICallInfoSCRef m_heldCallInfo; + ICallInfoSCRef m_endCallInfo; + CallStatusSRef m_callStatus; + bool m_isCallerIdEnable; + bool m_isEmergency; + bool m_isSubTxtEnable; + bool m_needModifyCallStatus; + }; + +} + +#endif // __CALLUI_PRESENTERS_CALL_INFO_PRESENTER_H__ diff --git a/inc/presenters/CallStatus.h b/inc/presenters/CallStatus.h new file mode 100644 index 0000000..3e4bf4c --- /dev/null +++ b/inc/presenters/CallStatus.h @@ -0,0 +1,78 @@ +/* + * 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_CALL_STATUS_H__ +#define __CALLUI_PRESENTERS_CALL_STATUS_H__ + +#include + +#include "ucl/gui/Layout.h" + +#include "types.h" + +namespace callui { + + class CallStatus final : public ucl::RefCountAware { + public: + class Builder { + public: + Builder(); + virtual ~Builder(); + Builder &setMode(CallInfoMode mode); + Builder &setCallInfo(const ICallInfoWCRef &info); + Builder &setCallHoldState(bool isOnHold); + Builder &setLayout(const ucl::LayoutSRef &layout); + CallStatusSRef build() const; + private: + ucl::LayoutSRef m_ly; + CallInfoMode m_mode; + ICallInfoWCRef m_info; + bool m_isOnHold; + }; + public: + virtual ~CallStatus(); + + private: + friend class ucl::RefCountObj; + CallStatus(ucl::RefCountObjBase &rc, + const ucl::LayoutSRef &layout, + CallInfoMode mode, + const ICallInfoWCRef &info, + bool isOnHold); + + ucl::Result prepare(); + + ucl::Result processIncomingMode(); + ucl::Result processOutgoingMode(); + ucl::Result processDuringMode(); + ucl::Result processEndMode(); + + Eina_Bool onCallDurationTimerCb(); + Eina_Bool onBlinkingTimerCb(); + + private: + ucl::LayoutSRef m_ly; + CallInfoMode m_mode; + ICallInfoWCRef m_info; + bool m_isOnHold; + Ecore_Timer *m_timer; + struct tm m_duration; + int m_blinkCount; + }; + +} + +#endif // __CALLUI_PRESENTERS_CALL_STATUS_H__ diff --git a/inc/presenters/MainPage.h b/inc/presenters/MainPage.h index 0139b7b..1ff6005 100644 --- a/inc/presenters/MainPage.h +++ b/inc/presenters/MainPage.h @@ -51,6 +51,7 @@ namespace callui { ucl::Result prepare(); ucl::Result createAcceptRejectPresenter(); + ucl::Result createCallInfoPresenter(CallInfoMode mode); // Page @@ -65,6 +66,7 @@ namespace callui { ucl::LayoutSRef m_widget; ICallSRef m_call; IndicatorSRef m_indicator; + CallInfoPresenterSRef m_callInfoPrs; AcceptRejectPresenterSRef m_acceptReject; }; } diff --git a/inc/presenters/types.h b/inc/presenters/types.h index 6b7c33c..f793cfc 100644 --- a/inc/presenters/types.h +++ b/inc/presenters/types.h @@ -30,6 +30,14 @@ namespace callui { BACK }; + enum class CallInfoMode { + UNDEFINED, + INCOMING, + OUTGOING, + DURING, + END + }; + UCL_DECLARE_REF_ALIASES(Page); UCL_DECLARE_REF_ALIASES(MainPage); @@ -37,6 +45,8 @@ namespace callui { UCL_DECLARE_REF_ALIASES(AcceptDialog); UCL_DECLARE_REF_ALIASES(Indicator); + UCL_DECLARE_REF_ALIASES(CallInfoPresenter); + UCL_DECLARE_REF_ALIASES(CallStatus); using AcceptDialogHandler = ucl::WeakDelegate; } diff --git a/inc/resources.h b/inc/resources.h index 5135942..0b89fc7 100644 --- a/inc/resources.h +++ b/inc/resources.h @@ -28,6 +28,18 @@ namespace callui { extern const ucl::TString STR_ANSWER_CALL; extern const ucl::TString STR_HOLD_AND_ACCEPT; extern const ucl::TString STR_END_AND_ACCEPT; + + extern const ucl::TString STR_CALL_WITH_PS_WILL_END; + extern const ucl::TString STR_CALL_ON_HOLD; + extern const ucl::TString STR_WITH_PD_PEOPLE; + extern const ucl::TString STR_CONFERENCE_CALL; + extern const ucl::TString STR_UNKNOWN; + extern const ucl::TString STR_EMERGENCY_CALL; + + extern const ucl::TString STR_INCOMING_CALL; + extern const ucl::TString STR_DIALING_CALL; + extern const ucl::TString STR_ON_HOLD; + extern const ucl::TString STR_CALL_ENDED; } #endif // __CALLUI_RESOURCES_H__ diff --git a/res/edje/theme.edc b/res/edje/theme.edc index b74f147..1f05ee2 100644 --- a/res/edje/theme.edc +++ b/res/edje/theme.edc @@ -44,4 +44,6 @@ collections { #include "../../edc/buttons.edc" #include "../../edc/indicator.edc" + #include "../../edc/call_info.edc" + } diff --git a/src/model/CallInfo.cpp b/src/model/CallInfo.cpp index f9ed5ff..9e70afe 100644 --- a/src/model/CallInfo.cpp +++ b/src/model/CallInfo.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include "ContactInfo.h" #include "CallClient.h" @@ -26,6 +27,34 @@ #include "common.h" +namespace callui { namespace { namespace impl { + + using namespace ucl; + + Result getCurrTimeDiffInTm(const long time, struct tm &tmTime) + { + if (time == 0) { + ILOG("Call start time does not set"); + } + + long currTime = 0; + struct sysinfo info; + + if (sysinfo(&info) == 0) { + currTime = info.uptime; + } else { + LOG_RETURN(RES_FAIL, "sysinfo() failed!"); + } + + long callTime = currTime - time; + struct tm tmp{0}; + gmtime_r((const time_t *)&callTime, &tmp); + tmTime = tmp; + + return RES_OK; + } +}}} + namespace callui { using namespace ucl; @@ -146,14 +175,17 @@ namespace callui { return m_phoneNum; } - IContactInfoSCRef CallInfo::getContactInfo() const + IContactInfoWCRef CallInfo::getContactInfo() const { return m_contactInfo; } - long CallInfo::getStartTime() const + struct tm CallInfo::getDuration() const { - return m_startTime; + struct tm tmp{0}; + FAIL_RETURN_VALUE(impl::getCurrTimeDiffInTm(m_startTime, tmp), + {0}, "getCurrTimeDiffInTm() failed"); + return tmp; } bool CallInfo::isEmergency() const diff --git a/src/model/CallInfo.h b/src/model/CallInfo.h index b689f97..b3b9aff 100644 --- a/src/model/CallInfo.h +++ b/src/model/CallInfo.h @@ -34,8 +34,8 @@ namespace callui { virtual unsigned int getCallId() const override final; virtual const std::string &getPhoneNumber() const override final; - virtual IContactInfoSCRef getContactInfo() const override final; - virtual long getStartTime() const override final; + virtual IContactInfoWCRef getContactInfo() const override final; + virtual struct tm getDuration() const override final; virtual bool isEmergency() const override final; virtual bool isHDVoice() const override final; virtual bool isForwarded() const override final; diff --git a/src/model/ConferenceCallInfo.cpp b/src/model/ConferenceCallInfo.cpp index 2f026e2..669f24f 100644 --- a/src/model/ConferenceCallInfo.cpp +++ b/src/model/ConferenceCallInfo.cpp @@ -81,7 +81,7 @@ namespace callui { return m_phoneNum; } - IContactInfoSCRef ConferenceCallInfo::getContactInfo() const + IContactInfoWCRef ConferenceCallInfo::getContactInfo() const { return m_contactInfo; } diff --git a/src/model/ConferenceCallInfo.h b/src/model/ConferenceCallInfo.h index fe9ab9a..374c46f 100644 --- a/src/model/ConferenceCallInfo.h +++ b/src/model/ConferenceCallInfo.h @@ -34,7 +34,7 @@ namespace callui { virtual unsigned int getCallId() const override final; virtual const std::string &getPhoneNumber() const override final; - virtual IContactInfoSCRef getContactInfo() const override final; + virtual IContactInfoWCRef getContactInfo() const override final; private: friend class ucl::RefCountObj; diff --git a/src/presenters/CallInfoPresenter.cpp b/src/presenters/CallInfoPresenter.cpp new file mode 100644 index 0000000..7699ddc --- /dev/null +++ b/src/presenters/CallInfoPresenter.cpp @@ -0,0 +1,599 @@ +/* + * 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/CallInfoPresenter.h" + +#include "ucl/gui/Window.h" + +#include "presenters/CallStatus.h" + +#include "model/ICallManager.h" +#include "model/IIncomingCall.h" +#include "model/IActiveCall.h" +#include "model/IHeldCall.h" +#include "model/IEndCall.h" +#include "model/ICallInfo.h" +#include "model/IContactInfo.h" + +#include "common.h" +#include "resources.h" + +namespace callui { namespace { namespace impl { + + using namespace ucl; + + constexpr int SUB_TXT_WIDTH = 208; + constexpr int MAIN_TXT_WIDTH_SIMPLE = 208; + constexpr int MAIN_TXT_WIDTH_INCOM = 190; + constexpr int SLIDE_LABEL_DURATION_KOEFF = 8; + + constexpr LayoutTheme LAYOUT_CALLER_INFO_WIDGET + {"layout", "callui", "call_info"}; + + constexpr ElmStyle STYLE_SLIDING_LABEL {"slide_roll"}; + + constexpr EdjeSignal SIGN_EMERGENCY_MODE{"emergency"}; + + constexpr EdjeSignal SIGN_RESET{"reset"}; + + constexpr EdjeSignal SIGN_CALLER_ID_DISABLE{"caller_id_disable"}; + constexpr EdjeSignal SIGN_CALLER_ID_ENABLE{"caller_id_enable"}; + + constexpr EdjeSignal SIGN_INCOM_1LINE{"incom_1line"}; + constexpr EdjeSignal SIGN_INCOM_2LINE{"incom_2line"}; + + constexpr EdjeSignal SIGN_1LINE{"1line"}; + constexpr EdjeSignal SIGN_1LINE_2TXT{"1line_2text"}; + constexpr EdjeSignal SIGN_2LINE{"2line"}; + constexpr EdjeSignal SIGN_2LINE_2TXT{"2line_2text"}; + + constexpr EdjeSignalSrc SRC_TOP_PAD{"top_padding"}; + constexpr EdjeSignalSrc SRC_TXT_1LINE{"text_1line"}; + + constexpr EdjeSignalSrc SRC_CALLER_ID{"caller_id"}; + + constexpr EdjePart PART_TXT_MAIN{"text_1line"}; + + constexpr EdjePart PART_SWL_CALLER_ID{"caller_id"}; + constexpr EdjePart PART_SWL_2LINE{"text_2line"}; + + const TString STR_LABEL_CALLER_ID_ENABLE{ + "%s"}; + const TString STR_LABEL_CALLER_ID_DISABLE{ + "%s"}; + + int getTextBlockActualWidth(const Evas_Object *obj) + { + int resWidth = 0; + evas_object_textblock_size_native_get(obj, &resWidth, NULL); + return resWidth; + } + +}}} + +namespace callui { + + using namespace ucl; + + CallInfoPresenter::Builder::Builder(): + m_mode(CallInfoMode::UNDEFINED) + { + } + + CallInfoPresenter::Builder::~Builder() + { + } + + CallInfoPresenter::Builder &CallInfoPresenter::Builder::setCallManager(const ICallManagerSRef &cm) + { + m_cm = cm; + return *this; + } + + CallInfoPresenter::Builder &CallInfoPresenter::Builder::setMode(CallInfoMode mode) + { + m_mode = mode; + return *this; + } + + CallInfoPresenterSRef CallInfoPresenter::Builder::build(ElmWidget &parent) const + { + if (m_mode == CallInfoMode::UNDEFINED || !m_cm) { + LOG_RETURN_VALUE(RES_FAIL, {}, "Not all params are set"); + } + + auto result = makeShared(m_cm, m_mode); + FAIL_RETURN_VALUE(result->prepare(parent), {}, + "result->prepare() failed!"); + return result; + } + + CallInfoPresenter::CallInfoPresenter(RefCountObjBase &rc, + const ICallManagerSRef &cm, + CallInfoMode mode): + RefCountAware(&rc), + m_mode(mode), + m_isCallerIdEnable(false), + m_isEmergency(false), + m_isSubTxtEnable(false), + m_needModifyCallStatus(false) + { + initCallInfos(cm); + } + + CallInfoPresenter::~CallInfoPresenter() + { + } + + Result CallInfoPresenter::prepare(Widget &parent) + { + FAIL_RETURN(createWidget(parent), "createWidget() failed!"); + + FAIL_RETURN(createCallStatus(), "createCallStatus() failed!"); + + FAIL_RETURN(update(), "update() failed!"); + + return RES_OK; + } + + Result CallInfoPresenter::createWidget(Widget &parent) + { + m_widget = Layout::Builder(). + setTheme(impl::LAYOUT_CALLER_INFO_WIDGET). + setIsOwner(true). + build(parent); + if (!m_widget) { + LOG_RETURN(RES_FAIL, "Layout::build() failed!"); + } + return RES_OK; + } + + Widget &CallInfoPresenter::getWidget() + { + return *m_widget; + } + + CallInfoMode CallInfoPresenter::getMode() const + { + return m_mode; + } + + void CallInfoPresenter::initCallInfos(const ICallManagerSRef &cm) + { + auto incom = cm->getIncomingCall(); + if (incom) { + m_incomCallInfo = incom->getInfo(); + } else { + m_incomCallInfo.reset(); + } + + auto active = cm->getActiveCall(); + if (active) { + m_activeCallInfo = active->getInfo(); + } else { + m_activeCallInfo.reset(); + } + + auto held = cm->getHeldCall(); + if (held) { + m_heldCallInfo = held->getInfo(); + } else { + m_heldCallInfo.reset(); + } + + auto end = cm->getEndCall(); + if (end) { + m_endCallInfo = end->getInfo(); + } else { + m_endCallInfo.reset(); + } + } + + Result CallInfoPresenter::update(CallInfoMode mode, const ICallManagerSRef &cm) + { + m_needModifyCallStatus = false; + if (mode != m_mode || mode == CallInfoMode::DURING) { + m_needModifyCallStatus = true; + } + + m_mode = mode; + initCallInfos(cm); + + return update(); + } + + std::string CallInfoPresenter::getNumberSubText(const ICallInfoWCRef &callInfo) const + { + if (!callInfo) { + FAIL_RETURN_VALUE(RES_FAIL, "", "callInfo is NULL!"); + } + + IContactInfoSCRef contactInfo = callInfo->getContactInfo(); + if (contactInfo) { + return callInfo->getPhoneNumber(); + } + return ""; + } + + + std::string CallInfoPresenter::getIncomingCallSubText() const + { + if (!m_incomCallInfo) { + FAIL_RETURN_VALUE(RES_FAIL, "", "incom is NULL!"); + } + if (m_activeCallInfo && m_heldCallInfo) { + auto displStr = m_activeCallInfo->getPhoneNumber(); + auto contactInfo = m_activeCallInfo->getContactInfo(); + if (contactInfo) { + const auto contName = contactInfo->getName(); + if (!contName.empty()) { + displStr = contName; + } + } + if (displStr.empty()) { + displStr = STR_UNKNOWN.translate(); + } + return TString{STR_CALL_WITH_PS_WILL_END.translate()}.format(displStr.c_str()); + } + + return getNumberSubText(m_incomCallInfo); + } + + std::string CallInfoPresenter::getDuringCallSubText() const + { + if (m_activeCallInfo) { + auto confMemberCount = m_activeCallInfo->getConferenceMemberCount(); + if (m_heldCallInfo) { + return STR_CALL_ON_HOLD.translate(); + } else if (confMemberCount > 1) { + return TString{STR_WITH_PD_PEOPLE.translate()}.format(confMemberCount); + } + } else if (m_heldCallInfo) { + auto confMemberCount = m_heldCallInfo->getConferenceMemberCount(); + if (confMemberCount > 1) { + return TString{STR_WITH_PD_PEOPLE.translate()}.format(confMemberCount); + } + } + + ELOG("Invalid call data"); + return ""; + } + + std::string CallInfoPresenter::getEndCallSubText() const + { + if (!m_endCallInfo) { + FAIL_RETURN_VALUE(RES_FAIL, "", "end is NULL!"); + } + + auto confMemberCount = m_endCallInfo->getConferenceMemberCount(); + if (confMemberCount > 1) { + return TString{STR_WITH_PD_PEOPLE.translate()}.format(confMemberCount); + } + + return ""; + } + + Result CallInfoPresenter::createLabel(const std::string &text) + { + TString tmp; + if (m_isCallerIdEnable) { + tmp = impl::STR_LABEL_CALLER_ID_ENABLE.format(text.c_str()); + } else { + tmp = impl::STR_LABEL_CALLER_ID_DISABLE.format(text.c_str()); + } + int duration = text.size() / impl::SLIDE_LABEL_DURATION_KOEFF; + + auto label = makeShared(elm_label_add(*m_widget), true); + if (!label) { + LOG_RETURN(RES_FAIL, "Create label failed!"); + } + label->setStyle(impl::STYLE_SLIDING_LABEL); + label->setText(tmp); + + elm_label_slide_mode_set(*label, ELM_LABEL_SLIDE_MODE_AUTO); + elm_label_wrap_width_set(*label, ELM_SCALE_SIZE(impl::SUB_TXT_WIDTH)); + elm_label_slide_duration_set(*label, duration); + elm_label_slide_go(*label); + + m_widget->setContent(*label, impl::PART_SWL_2LINE); + + m_label = label; + + return RES_OK; + } + + Result CallInfoPresenter::updateCallerId() + { + m_isCallerIdEnable = false; + + m_callerId.reset(); + m_widget->emit(impl::SIGN_CALLER_ID_DISABLE, impl::SRC_CALLER_ID); + + if (m_mode == CallInfoMode::INCOMING) { + + if (!m_incomCallInfo) { + LOG_RETURN(RES_FAIL, "m_incomCallInfo is NULL"); + } + + auto contactInfo = m_incomCallInfo->getContactInfo(); + if (!contactInfo) { + ILOG("No contact info"); + return RES_OK; + } + + auto callerIdPath = contactInfo->getImagePath(); + if (callerIdPath.empty()) { + ILOG("No caller id content to set"); + return RES_OK; + } + + auto callerId = makeShared( + elm_image_add(*m_widget), true); + if (!callerId) { + LOG_RETURN(RES_FAIL, "Create callerId failed!"); + } + + elm_image_file_set(*callerId, callerIdPath.c_str(), NULL); + elm_image_aspect_fixed_set(*callerId, EINA_TRUE); + elm_image_fill_outside_set(*callerId, EINA_TRUE); + + auto window = callerId->getWindow(); + if (!window) { + LOG_RETURN(RES_FAIL, "Window is NULL!"); + } + int w = 0, h = 0; + window->getScreenSize(&w, &h); + ILOG("size w[%d] h[%d]", w, h); + evas_object_size_hint_min_set(*callerId, w, h); + + m_widget->setContent(*callerId, + impl::PART_SWL_CALLER_ID); + + m_widget->emit(impl::SIGN_CALLER_ID_ENABLE, impl::SRC_CALLER_ID); + + m_callerId = callerId; + + m_isCallerIdEnable = true; + } + + return RES_OK; + } + + Result CallInfoPresenter::updateSubText() + { + std::string subTxt; + m_isSubTxtEnable = false; + + m_label.reset(); + + switch (m_mode) { + case CallInfoMode::INCOMING: + subTxt = getIncomingCallSubText(); + break; + case CallInfoMode::DURING: + subTxt = getDuringCallSubText(); + break; + case CallInfoMode::OUTGOING: + ILOG("Outgoing call not supported"); + break; + case CallInfoMode::END: + subTxt = getEndCallSubText(); + break; + case CallInfoMode::UNDEFINED: + LOG_RETURN(RES_FAIL, "Undefined caller info mode!"); + break; + default: + break; + } + + if (!subTxt.empty()) { + m_isSubTxtEnable = true; + + TString tmp; + if (m_isCallerIdEnable) { + tmp = impl::STR_LABEL_CALLER_ID_ENABLE.format(subTxt.c_str()); + } else { + tmp = impl::STR_LABEL_CALLER_ID_DISABLE.format(subTxt.c_str()); + } + FAIL_RETURN(createLabel(tmp), "createLabel() failed"); + } + + return RES_OK; + } + + std::string CallInfoPresenter::generateMainTxt(const ICallInfoWCRef &callInfo) + { + if (!callInfo) { + LOG_RETURN_VALUE(RES_FAIL, "", "callInfo is NULL"); + } + + if (callInfo->getConferenceMemberCount() > 1) { + return STR_CONFERENCE_CALL.translate(); + } + + if (callInfo->isEmergency()) { + m_isEmergency = true; + return STR_EMERGENCY_CALL.translate(); + } + + std::string mainTxt; + auto contactInfo = callInfo->getContactInfo(); + if (contactInfo) { + mainTxt = contactInfo->getName(); + } + + if (mainTxt.empty()) { + mainTxt = callInfo->getPhoneNumber(); + if (mainTxt.empty()) { + return STR_UNKNOWN.translate(); + } + } + return mainTxt; + } + + void CallInfoPresenter::displayMainTxt(const std::string &text) const + { + m_widget->setText(text.c_str(), impl::PART_TXT_MAIN); + + const Evas_Object *tempEo = edje_object_part_object_get( + elm_layout_edje_get(*m_widget), impl::PART_TXT_MAIN.name); + + if (tempEo) { + + int lineWidth = m_incomCallInfo ? + impl::MAIN_TXT_WIDTH_INCOM : impl::MAIN_TXT_WIDTH_SIMPLE; + bool isMainTxtSingleLine = + (impl::getTextBlockActualWidth(tempEo) <= lineWidth); + + m_widget->emit(impl::SIGN_CALLER_ID_DISABLE, impl::SRC_TXT_1LINE); + + if (m_mode == CallInfoMode::END) { + + if (isMainTxtSingleLine) { + m_widget->emit(impl::SIGN_1LINE, impl::SRC_TOP_PAD); + } else { + m_widget->emit(impl::SIGN_2LINE, impl::SRC_TOP_PAD); + + } + } else if (m_mode == CallInfoMode::INCOMING) { + + if (m_isCallerIdEnable) { + m_widget->emit(impl::SIGN_CALLER_ID_ENABLE, impl::SRC_TXT_1LINE); + } else { + m_widget->emit(impl::SIGN_CALLER_ID_DISABLE, impl::SRC_TXT_1LINE); + } + if (isMainTxtSingleLine) { + m_widget->emit(impl::SIGN_INCOM_1LINE, impl::SRC_TOP_PAD); + } else { + m_widget->emit(impl::SIGN_INCOM_2LINE, impl::SRC_TOP_PAD); + } + + } else { + + if (m_isEmergency) { + m_widget->emit(impl::SIGN_EMERGENCY_MODE, impl::SRC_TXT_1LINE); + } + + if (isMainTxtSingleLine) { + if (m_isSubTxtEnable) { + m_widget->emit(impl::SIGN_1LINE_2TXT, impl::SRC_TOP_PAD); + } else { + m_widget->emit(impl::SIGN_1LINE, impl::SRC_TOP_PAD); + } + } else { + if (m_isSubTxtEnable) { + m_widget->emit(impl::SIGN_2LINE_2TXT, impl::SRC_TOP_PAD); + } else { + m_widget->emit(impl::SIGN_2LINE, impl::SRC_TOP_PAD); + } + } + } + } + } + + Result CallInfoPresenter::updateMainTxt() + { + std::string mainTxt; + switch (m_mode) { + case CallInfoMode::INCOMING: + mainTxt = generateMainTxt(m_incomCallInfo); + break; + case CallInfoMode::OUTGOING: + mainTxt = generateMainTxt(m_activeCallInfo); + break; + case CallInfoMode::DURING: + if (m_activeCallInfo) { + mainTxt = generateMainTxt(m_activeCallInfo); + } else if (m_heldCallInfo) { + mainTxt = generateMainTxt(m_heldCallInfo); + } + break; + case CallInfoMode::END: + mainTxt = generateMainTxt(m_endCallInfo); + break; + default: + LOG_RETURN(RES_FAIL, "Unknown mode"); + break; + } + + if (mainTxt.empty()) { + LOG_RETURN(RES_FAIL, "Main text is empty"); + } + + displayMainTxt(mainTxt); + + return RES_OK; + } + + Result CallInfoPresenter::createCallStatus() + { + ICallInfoWCRef callInfo; + bool isOnHold = false; + + m_callStatus.reset(); + + switch (m_mode) { + case CallInfoMode::INCOMING: + callInfo = m_incomCallInfo; + break; + case CallInfoMode::OUTGOING: + callInfo = m_activeCallInfo; + break; + case CallInfoMode::DURING: + if (m_activeCallInfo) { + callInfo = m_activeCallInfo; + } else if (m_heldCallInfo) { + callInfo = m_heldCallInfo; + isOnHold = true; + } + break; + case CallInfoMode::END: + callInfo = m_endCallInfo; + break; + default: + LOG_RETURN(RES_FAIL, "Unknown mode"); + break; + } + + m_callStatus = CallStatus::Builder().setLayout(m_widget). + setMode(m_mode). + setCallInfo(callInfo). + setCallHoldState(isOnHold). + build(); + + if (!m_callStatus) { + LOG_RETURN(RES_FAIL, "CallStatus::Builder()::build() failed!"); + } + + return RES_OK; + } + + Result CallInfoPresenter::update() + { + m_widget->emit(impl::SIGN_RESET, impl::SRC_TOP_PAD); + + FAIL_RETURN(updateCallerId(), "displayCallerId() failed!"); + FAIL_RETURN(updateSubText(), "diplaySubText() failed!"); + FAIL_RETURN(updateMainTxt(), "diplayMainTxt() failed!"); + + if (m_needModifyCallStatus) { + return createCallStatus(); + } + + return RES_OK; + } + +} diff --git a/src/presenters/CallStatus.cpp b/src/presenters/CallStatus.cpp new file mode 100644 index 0000000..d6a8d52 --- /dev/null +++ b/src/presenters/CallStatus.cpp @@ -0,0 +1,265 @@ +/* + * 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/CallStatus.h" + +#include "model/ICallInfo.h" + +#include "common.h" +#include "resources.h" + +namespace callui { namespace { namespace impl { + + using namespace ucl; + + constexpr double CALL_DURATION_TIMER_INTERVAL = 0.1; + constexpr double BLINKING_TIMER_INTERVAL = 0.5; + constexpr int BLINKING_MAX_COUNT = 5; + + constexpr EdjePart PART_TXT_TEXT_INFO{"text_info"}; + + constexpr EdjeSignal SIGN_DOT_RTL{"default:RTL"}; + constexpr EdjeSignal SIGN_DOT_LTR{"default:LTR"}; + constexpr EdjeSignal SIGN_RESET{"reset"}; + + constexpr EdjeSignalSrc SIGN_SRC_DOT{"dot"}; + + const TString STR_HH_MM_SS_TIME{"%02d:%02d:%02d"}; + const TString STR_MM_SS_TIME{"%02d:%02d"}; + + void setCallDuration(const struct tm &time, + EdjeWidget &widget, + const EdjePart &part) + { + TString tmp; + if (time.tm_hour > 0) { + tmp = STR_HH_MM_SS_TIME.format(time.tm_hour, time.tm_min, time.tm_sec); + } else { + tmp = STR_MM_SS_TIME.format(time.tm_min, time.tm_sec); + } + widget.setText(tmp, part); + } + + void tryUpdateCallDurationTime( + struct tm &curTime, + struct tm &compTime, + EdjeWidget &widget, + const EdjePart &part) + { + if ((compTime.tm_sec - curTime.tm_sec) != 0) { + curTime = compTime; + setCallDuration(curTime, widget, part); + } + } + +}}} + +namespace callui { + + using namespace ucl; + + CallStatus::Builder::Builder(): + m_mode(CallInfoMode::UNDEFINED), + m_isOnHold(false) + { + } + + CallStatus::Builder::~Builder() + { + } + + CallStatus::Builder &CallStatus::Builder::setMode(CallInfoMode mode) + { + m_mode = mode; + return *this; + } + + CallStatus::Builder &CallStatus::Builder::setCallInfo(const ICallInfoWCRef &info) + { + m_info = info; + return *this; + } + + CallStatus::Builder &CallStatus::Builder::setCallHoldState(bool isOnHold) + { + m_isOnHold = isOnHold; + return *this; + } + + CallStatus::Builder &CallStatus::Builder::setLayout(const LayoutSRef &layout) + { + m_ly = layout; + return *this; + } + + CallStatusSRef CallStatus::Builder::build() const + { + if (m_mode == CallInfoMode::UNDEFINED || !m_ly) { + LOG_RETURN_VALUE(RES_FAIL, {}, "Not all params are set"); + } + + auto result = makeShared(m_ly, m_mode, + m_info, m_isOnHold); + + FAIL_RETURN_VALUE(result->prepare(), {}, + "result->prepare() failed!"); + return result; + } + + + CallStatus::CallStatus(RefCountObjBase &rc, + const LayoutSRef &layout, + CallInfoMode mode, + const ICallInfoWCRef &info, + bool isHeld): + RefCountAware(&rc), + m_ly(layout), + m_mode(mode), + m_info(info), + m_isOnHold(isHeld), + m_timer(nullptr), + m_duration{0}, + m_blinkCount(0) + { + } + + CallStatus::~CallStatus() + { + m_ly.reset(); + if (m_timer) { + ecore_timer_del(m_timer); + m_timer = nullptr; + } + } + + Result CallStatus::prepare() + { + m_ly->emit(impl::SIGN_RESET, impl::SIGN_SRC_DOT); + + switch (m_mode) { + case CallInfoMode::INCOMING: return processIncomingMode(); + case CallInfoMode::OUTGOING: return processOutgoingMode(); + case CallInfoMode::DURING: return processDuringMode(); + case CallInfoMode::END: return processEndMode(); + default: + LOG_RETURN(RES_FAIL, "Unknown mode"); + break; + } + + return RES_OK; + } + + Result CallStatus::processIncomingMode() + { + m_ly->setText(STR_INCOMING_CALL, impl::PART_TXT_TEXT_INFO); + + // TODO: need add logic for RTL mode in the future + m_ly->emit(impl::SIGN_DOT_LTR, impl::SIGN_SRC_DOT); + + return RES_OK; + } + + Result CallStatus::processOutgoingMode() + { + m_duration = m_info->getDuration(); + + m_ly->setText(STR_DIALING_CALL, impl::PART_TXT_TEXT_INFO); + + // TODO: need add logic for RTL mode in the future + m_ly->emit(impl::SIGN_DOT_LTR, impl::SIGN_SRC_DOT); + + return RES_OK; + } + + Eina_Bool CallStatus::onCallDurationTimerCb() + { + if (!m_info) { + m_timer = nullptr; + LOG_RETURN_VALUE(RES_FAIL, ECORE_CALLBACK_CANCEL, "m_info is NULL"); + } + + struct tm tmp = m_info->getDuration(); + impl::tryUpdateCallDurationTime( + m_duration, + tmp, + *m_ly, + impl::PART_TXT_TEXT_INFO); + + return ECORE_CALLBACK_RENEW; + } + + Result CallStatus::processDuringMode() + { + + if (m_isOnHold) { + m_ly->setText(STR_ON_HOLD, impl::PART_TXT_TEXT_INFO); + } else { + m_duration = m_info->getDuration(); + impl::setCallDuration(m_duration, *m_ly, impl::PART_TXT_TEXT_INFO); + + if (m_timer) { + ecore_timer_del(m_timer); + m_timer = nullptr; + } + + m_timer = ecore_timer_add(impl::CALL_DURATION_TIMER_INTERVAL, + CALLBACK_B(CallStatus::onCallDurationTimerCb), + this); + + if (!m_timer) { + LOG_RETURN(RES_FAIL, "m_timer is NULL"); + } + } + return RES_OK; + } + + Eina_Bool CallStatus::onBlinkingTimerCb() + { + if ((m_blinkCount % 2) == 0) { + impl::setCallDuration(m_duration, *m_ly, impl::PART_TXT_TEXT_INFO); + } else if ((m_blinkCount % 2) == 1) { + m_ly->setText("", impl::PART_TXT_TEXT_INFO); + } + + m_blinkCount++; + + if (m_blinkCount == impl::BLINKING_MAX_COUNT) { + m_ly->setText(STR_CALL_ENDED, impl::PART_TXT_TEXT_INFO); + m_timer = nullptr; + return ECORE_CALLBACK_CANCEL; + } + return ECORE_CALLBACK_RENEW; + } + + Result CallStatus::processEndMode() + { + if (m_timer) { + ecore_timer_del(m_timer); + m_timer = nullptr; + } + + m_duration = m_info->getDuration(); + + m_timer = ecore_timer_add(impl::BLINKING_TIMER_INTERVAL, + CALLBACK_B(CallStatus::onBlinkingTimerCb), this); + if (!m_timer) { + LOG_RETURN(RES_FAIL, "m_timer is NULL"); + } + + return RES_OK; + } + +} diff --git a/src/presenters/Indicator.cpp b/src/presenters/Indicator.cpp index 07997bf..284373d 100644 --- a/src/presenters/Indicator.cpp +++ b/src/presenters/Indicator.cpp @@ -176,7 +176,7 @@ namespace callui { return *this; } - IndicatorSRef Indicator::Builder::build(ucl::ElmWidget &parent) const + IndicatorSRef Indicator::Builder::build(ElmWidget &parent) const { if (!m_provider) { LOG_RETURN_VALUE(RES_FAIL, {}, "Not all params are set"); @@ -188,7 +188,7 @@ namespace callui { return result; } - Indicator::Indicator(ucl::RefCountObjBase &rc, + Indicator::Indicator(RefCountObjBase &rc, const IIndicatorStateProviderSRef &provider): RefCountAware(&rc), m_provider(provider) @@ -199,7 +199,7 @@ namespace callui { { } - Result Indicator::prepare(ucl::Widget &parent) + Result Indicator::prepare(Widget &parent) { FAIL_RETURN(createWidget(parent), "createWidget() failed!"); @@ -224,7 +224,7 @@ namespace callui { return RES_OK; } - Result Indicator::createWidget(ucl::Widget &parent) + Result Indicator::createWidget(Widget &parent) { m_widget = Layout::Builder(). setTheme(impl::LAYOUT_INDICATOR_WIDGET). diff --git a/src/presenters/MainPage.cpp b/src/presenters/MainPage.cpp index d73755e..07218bc 100644 --- a/src/presenters/MainPage.cpp +++ b/src/presenters/MainPage.cpp @@ -29,6 +29,7 @@ #include "presenters/Indicator.h" #include "presenters/AcceptRejectPresenter.h" +#include "presenters/CallInfoPresenter.h" #include "common.h" @@ -41,6 +42,8 @@ namespace callui { namespace { namespace impl { constexpr EdjePart PART_SWL_INDICATOR {"swl.indicator"}; constexpr EdjePart PART_SWL_ACCEPT_REJECT {"swl.accept_reject"}; + constexpr EdjePart PART_SWL_CALL_INFO {"swl.call_info"}; + }}} namespace callui { @@ -137,6 +140,7 @@ namespace callui { void MainPage::onBackKey() { + auto callMng = m_call->getCallManager(); if (m_call->getCallManager()->getAvailableCalls() == CALL_FLAG_END) { requestExit(); @@ -148,7 +152,11 @@ namespace callui { ILOG("CallEventType [%d]", static_cast(type)); auto cm = m_call->getCallManager(); - auto mask = cm->getAvailableCalls(); + auto incom = cm->getIncomingCall(); + auto active = cm->getActiveCall(); + auto held = cm->getHeldCall(); + auto end = cm->getEndCall(); + auto win = getNaviframe().getWindow(); if (!win) { @@ -161,18 +169,27 @@ namespace callui { show(*win); } - if (mask & CALL_FLAG_INCOMING) { - if (!m_acceptReject) { - FAIL_RETURN_VOID(createAcceptRejectPresenter(), - "createAcceptRejectPresenter() failed!"); - } else { - m_acceptReject->update(cm->getAvailableCalls()); - } + if (incom) { + FAIL_RETURN_VOID(createAcceptRejectPresenter(), + "createAcceptRejectPresenter() failed!"); } else { - if (m_acceptReject) - m_acceptReject.reset(); + m_acceptReject.reset(); } + CallInfoMode mode = CallInfoMode::UNDEFINED; + if (incom) { + mode = CallInfoMode::INCOMING; + } else if (active && active->isDialingMode()) { + mode = CallInfoMode::OUTGOING; + } else if (active || held) { + mode = CallInfoMode::DURING; + } else if (end) { + mode = CallInfoMode::END; + } + FAIL_RETURN_VOID(createCallInfoPresenter(mode), + "createCallInfoPresenter() failed!"); + + if (type == CallEventType::END) { if (m_call->getCallManager()->getAvailableCalls() == CALL_FLAG_END) { @@ -184,20 +201,51 @@ namespace callui { Result MainPage::createAcceptRejectPresenter() { auto callMng = m_call->getCallManager(); + + if (m_acceptReject) { + m_acceptReject->update(callMng->getAvailableCalls()); + return RES_OK; + } + m_acceptReject = AcceptRejectPresenter::Builder(). setIncomingCall(callMng->getIncomingCall()). setAvailableCallsFlag(callMng->getAvailableCalls()). build(*m_widget); + if (!m_acceptReject) { LOG_RETURN(RES_FAIL, "AcceptRejectPresenter::Builder().build() failed!"); } + m_widget->setContent(m_acceptReject->getWidget().getEo(), impl::PART_SWL_ACCEPT_REJECT); return RES_OK; } + Result MainPage::createCallInfoPresenter(CallInfoMode mode) + { + auto callMng = m_call->getCallManager(); + + if (m_callInfoPrs) { + return m_callInfoPrs->update(mode, callMng); + } + + m_callInfoPrs = CallInfoPresenter::Builder(). + setCallManager(callMng). + setMode(mode). + build(*m_widget); + + if (!m_callInfoPrs) { + LOG_RETURN(RES_FAIL, + "CallerInfo::Builder().build() failed!"); + } + m_widget->setContent(m_callInfoPrs->getWidget().getEo(), + impl::PART_SWL_CALL_INFO); + + return RES_OK; + } + void MainPage::onError(CallErr err) { if (!m_call->getCallManager()->getAvailableCalls()) { diff --git a/src/resources.cpp b/src/resources.cpp index bb609ab..a7a13b8 100644 --- a/src/resources.cpp +++ b/src/resources.cpp @@ -24,4 +24,15 @@ namespace callui { const ucl::TString STR_HOLD_AND_ACCEPT {"Hold and Accept"}; const ucl::TString STR_END_AND_ACCEPT {"End and Accept"}; + const ucl::TString STR_CALL_WITH_PS_WILL_END {"Call with %s will end."}; + const ucl::TString STR_CALL_ON_HOLD {"Call on hold"}; + const ucl::TString STR_WITH_PD_PEOPLE {"With %d people"}; + const ucl::TString STR_CONFERENCE_CALL {"Conference call"}; + const ucl::TString STR_UNKNOWN {"Unknown"}; + const ucl::TString STR_EMERGENCY_CALL {"Emergency call"}; + + const ucl::TString STR_INCOMING_CALL {"Incoming call"}; + const ucl::TString STR_DIALING_CALL {"Dialing"}; + const ucl::TString STR_ON_HOLD {"On hold"}; + const ucl::TString STR_CALL_ENDED {"Call ended"}; } diff --git a/tizen-manifest.xml b/tizen-manifest.xml index e8fdd0f..b7dd00d 100644 --- a/tizen-manifest.xml +++ b/tizen-manifest.xml @@ -12,16 +12,16 @@ + http://tizen.org/privilege/telephony + http://tizen.org/privilege/telephony.admin http://tizen.org/privilege/keygrab http://tizen.org/privilege/appmanager.launch http://tizen.org/privilege/window.priority.set + http://tizen.org/privilege/systemsettings.admin http://tizen.org/privilege/contact.read http://tizen.org/privilege/message.write http://tizen.org/privilege/notification http://tizen.org/privilege/message.read http://tizen.org/privilege/display - http://tizen.org/privilege/telephony - http://tizen.org/privilege/telephony.admin - http://tizen.org/privilege/systemsettings.admin