#include <string>
#include <vector>
#include <Ecore.h>
+#include "log.h"
namespace model {
- class Counter {
+ using namespace std::chrono;
+
+ template <typename Type>
+ struct isDuration {
+ static constexpr bool value = false;
+ };
+
+ template <typename Rep, typename Period>
+ struct isDuration <duration<Rep, Period>>{
+ static constexpr bool value = true;
+ };
+
+ template <typename Duration = milliseconds> class Counter {
public:
- Counter();
- ~Counter();
+ Counter() {
+ start_time_ = Duration::zero();
+ pause_time_ = Duration::zero();
+ }
+
+ bool Run()
+ {
+ start_time_ = GetTimeSinceEpoch();
+ if (start_time_.count() < 0)
+ return false;
+ return true;
+ }
+
+ bool Reset()
+ {
+ pause_time_ = Duration::zero();
+ if (pause_time_ != Duration(0)) {
+ ERR("Could not set pause time to zero");
+ return false;
+ }
+ return true;
+ }
+
+ bool Resume()
+ {
+ if (!Run()) {
+ ERR("Run time counter failed");
+ return false;
+ }
+ return true;
+ }
+
+ bool Stop()
+ {
+ pause_time_ += GetTimeSinceEpoch() - start_time_;
+ if (pause_time_.count() < 0)
+ return false;
+ return true;
+ }
+
+ Duration GetTime()
+ {
+ return GetTimeSinceEpoch() - start_time_ + pause_time_;
+ }
+
+ Duration GetTimeSinceEpoch()
+ {
+ return duration_cast<Duration>(system_clock::now().time_since_epoch());
+ }
- bool Run(void);
- bool Stop(void);
- bool Reset(void);
- bool Resume(void);
+ Duration GetStartTime()
+ {
+ return start_time_;
+ }
- std::chrono::milliseconds GetTime(void);
- std::chrono::milliseconds GetTimeSinceEpoch(void);
- std::chrono::milliseconds GetStartTime(void);
+ private:
+ Duration start_time_;
+ Duration pause_time_;
- private:
- std::chrono::milliseconds start_time_;
- std::chrono::milliseconds pause_time_;
+ static_assert(isDuration<Duration>::value, "duration must be a std::chrono::duration type");
};
}
std::chrono::milliseconds lap_time_;
};
- class StopWatch : public Counter {
+ class StopWatch : public Counter<milliseconds> {
public:
void ClearList(void);
void AddLap(void);
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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 _CLOCK_TIMER_H_
#define _CLOCK_TIMER_H_
+#include "Model/Counter.h"
+
+using namespace std::chrono;
+
namespace model {
- class Timer {
- public:
- void Start(time_t delay);
- time_t StartTime();
- time_t RemainingTime();
+ class Timer : public Counter<seconds> {
+ public:
+ Timer();
+ ~Timer();
+
+ void SetHour(int hour);
+ void SetMinute(int minute);
+ void SetSecond(int second);
+
+ unsigned GetHour(void) const;
+ unsigned GetMinute(void) const;
+ unsigned GetSecond(void) const;
+
+ void SetTime(int hour, int minute, int second);
+
+ seconds GetRemainingTime(void);
+ private:
+ seconds time_;
+ unsigned hour_;
+ unsigned minute_;
+ unsigned second_;
+
};
} /* model */
--- /dev/null
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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 _CLOCK_PRESENTER_TIMER_H_
+#define _CLOCK_PRESENTER_TIMER_H_
+
+#include "View/TimerView.h"
+#include "View/CounterView.h"
+#include "Model/Timer.h"
+#include "Common/CounterAnimator.h"
+
+namespace presenter {
+
+ class TimerPresenter {
+ public:
+ TimerPresenter(view::TimerView *view, model::Timer *model);
+ ~TimerPresenter();
+
+ private:
+ view::TimerView *view_;
+ model::Timer *model_;
+ common::CounterAnimator animator_;
+
+ void StartButtonClicked();
+ void PauseButtonClicked();
+ void ResumeButtonClicked();
+ void ResetButtonClicked();
+ void CancelButtonClicked();
+
+ void TimeUpdateRequest();
+ };
+
+}
+
+#endif //_CLOCK_PRESENTER_TIMER_H_
Evas_Object *GetEvasObject(void);
- void DisplayTime(int hour, int min, int sec, int msec);
+ void DisplayTime(int hour, int min, int sec, int msec = 0);
void Expand(void);
void Contract(void);
};
}
-
#endif //_CLOCK_VIEW_COUNTER_H_
#ifndef _CLOCK_VIEW_TIMER_H_
#define _CLOCK_VIEW_TIMER_H_
-#include "View/PageView.h"
+#include <vector>
+#include <functional>
+
+#include <vector>
+#include <functional>
+
#include "View/View.h"
+#include "View/PageView.h"
+#include "View/CounterView.h"
+#include "Utils/Time.h"
namespace view {
+
+ enum class TimerSignal {
+ BUTTON_HOUR_INCREASE_CLICKED,
+ BUTTON_MINUTE_INCREASE_CLICKED,
+ BUTTON_SECOND_INCREASE_CLICKED,
+
+ BUTTON_HOUR_DECREASE_CLICKED,
+ BUTTON_MINUTE_DECREASE_CLICKED,
+ BUTTON_SECOND_DECREASE_CLICKED,
+
+ BUTTON_START_CLICKED,
+ BUTTON_PAUSE_CLICKED,
+ BUTTON_CANCEL_CLICKED,
+ BUTTON_RESUME_CLICKED,
+ BUTTON_RESET_CLICKED,
+
+ ON_COUNTER_FOCUS,
+ ON_COUNTER_UNFOCUS,
+
+ MAX,
+ };
+
class TimerView : public ui::IView {
- public:
- TimerView();
- Evas_Object *GetEvasObject(){return timer_;};
+ public:
+
+ TimerView();
+ ~TimerView();
+
+ Evas_Object *GetEvasObject();
+
+ void RegisterSignal(std::function<void(void)>func, TimerSignal type);
+
+ void SetEnabledStartButton(bool enable);
+ void ShowTimeIsUpAlert();
+ void DisplayTime(int hour, int min, int sec);
+
+ void GetTime(int *hour, int *minute, int *second);
+
+ void ShowStartupMenu(void);
+ void ShowRunningMenu(void);
+ void ShowPausedMenu(void);
+ void ShowEditingMenu(void);
+
+ private:
+ Evas_Object *layout_ = NULL;
+ Evas_Object *selector_ = NULL;
+ Evas_Object *alarmWin = NULL; //after RingProvider or any other implementation it needs to be removed
+ view::CounterView *counter_ = NULL;
+
+ utils::Time set_time_;
+
+ std::vector<std::function<void(void)>> signals
+ = std::vector<std::function<void(void)>>((int)TimerSignal::MAX, nullptr);
+
+ void CreateButton(Evas_Object *parent, const char *name,
+ const char *part, Evas_Smart_Cb cb);
+
+ void CreateSelector();
+ void CreateMenuButtons();
+ void CreateEntry(Evas_Object *parent, const char *part);
+ void CreateEntries(Evas_Object *parent);
+
+ void UpdateView();
+ void UpdateTime();
+
+ void UnfocusEntries();
+
+ void EmitSignal(TimerSignal type);
+
+ static const char *EDJE_FILE;
+ static const char *GROUP;
+ static const char *GetEdjeFilePath(void);
+
+ static void StartButtonClicked(void *data, Evas_Object *obj, void *event_info);
+ static void PauseButtonClicked(void *data, Evas_Object *obj, void *event_info);
+ static void CancelButtonClicked(void *data, Evas_Object *obj, void *event_info);
+ static void ResumeButtonClicked(void *data, Evas_Object *obj, void *event_info);
+ static void ResetButtonClicked(void *data, Evas_Object *obj, void *event_info);
+
+ static void ButtonClickedCb(void *data, Evas_Object *obj, const char *emission, const char *source);
+ static void EntryFocusedCb(void *data, Evas_Object *obj, void *event_info);
+ static void EntryUnfocusedCb(void *data, Evas_Object *obj, void *event_info);
+ static void EntryChangedCb(void *data, Evas_Object *obj, void *event_info);
+ static void EntryEditDoneCb(void *data, Evas *e, Evas_Object *obj, void *event_info);
- private:
- Evas_Object *timer_;
+ static void AlarmDismiss(void *data, Evas_Object *obj, const char *emission, const char *source);
};
}
group { "Digit";
parts {
- textblock { "digit";
+ textblock { "digit"; scale;
desc { "default";
text.style: "ATO011";
}
textblock { "digit"; scale;
desc { "default";
max: -1 145;
- rel1.offset: 0 65;
- rel2.offset: 0 -17;
+ align: 0.5 0.0;
text.style: "ATO012";
+ rel1 { relative: 0.0 1.0; to_y: "pd.top"; }
+ rel2 { relative: 1.0 0.0; to_y: "pd.bottom"; }
}
desc { "default.expanded";
inherit: "default";
max: -1 117;
- rel1.offset: 0 66;
- rel2.offset: 0 -17;
text.style: "ATO012L";
}
desc { "simple";
text.style: "ATO012L";
}
}
+ spacer { "pd.top"; scale;
+ desc { "default";
+ align: 0.5 0.0;
+ min: 0 65;
+ max: -1 65;
+ }
+ }
+ spacer { "pd.bottom"; scale;
+ desc { "default";
+ align: 0.5 1.0;
+ min: 0 17;
+ max: -1 17;
+ }
+ }
program {
signal: "digits,set,stopwatch,expand";
source: "counter";
group { "Colon";
parts {
- textblock { "colon";
+ textblock { "colon"; scale;
desc { "default";
text {
style: "ATO011";
parts {
textblock { "dot"; scale;
desc { "default";
- rel1.offset: 0 66;
- rel2.offset: 0 -17;
text {
style: "ATO012";
text: ".";
}
+ rel1 { relative: 0.0 1.0; to_y: "pd.top"; }
+ rel2 { relative: 1.0 0.0; to_y: "pd.bottom"; }
}
desc { "default.expanded";
inherit: "default";
text.style: "ATO012L";
- rel1.offset: 0 65;
}
desc { "simple";
text.style: "ATO012L";
text.text: ".";
}
}
+ spacer { "pd.top"; scale;
+ desc { "default";
+ align: 0.5 0.0;
+ min: 0 65;
+ max: -1 65;
+ }
+ }
+ spacer { "pd.bottom"; scale;
+ desc { "default";
+ align: 0.5 1.0;
+ min: 0 17;
+ max: -1 17;
+ }
+ }
program {
signal: "digits,set,stopwatch,expand";
source: "counter";
group { "Counter.timer";
parts {
- textblock { "sign"; scale;
- desc { "default";
- max: 36 -1;
- align: 1.0 0.5;
- rel1 { to_y: "digits"; }
- rel2 { relative: 0.0 1.0; to: "digits"; }
- text {
- style: "ATO010";
- text: "-";
- align: 1.0 0.5;
- }
- hid;
- }
- desc { "visible";
- inherit: "default";
- vis;
- }
- desc { "hidden";
- inherit: "default";
- }
- }
table { "digits"; scale;
desc { "default";
max: 620 -1;
signal: "counter,set,hidden";
source: "counter";
action: STATE_SET "hidden";
- target: "sign";
target: "digits";
}
program {
action: STATE_SET "visible";
target: "digits";
}
- program {
- signal: "counter,show,sign";
- source: "counter";
- action: STATE_SET "visible";
- target: "sign";
- }
}
}
}
--- /dev/null
+
+collections {
+
+ images {
+ image: "alarm_picker_arrow_up.png" COMP;
+ image: "alarm_picker_arrow_down.png" COMP;
+ image: "arrow_bg_horizontal.png" COMP;
+ }
+
+ styles {
+ style {
+ name: "ATO009";
+ base: "font=Tizen:style=Regular color=#FAFAFA5E wrap=none font_size=31 align=center";
+ }
+ style {
+ name: "ATO009L";
+ base: "font=Tizen:style=Regular color=#FAFAFA5E wrap=none font_size=31";
+ }
+ style {
+ name: "ATO010";
+ base: "font=Tizen:style=Thin color=#FAFAFA wrap=none font_size=160 align=center";
+ }
+ }
+
+ base_scale: 2.6;
+
+ group { "Timer";
+
+ parts {
+ rect { "btn.bg"; scale;
+ desc { "default";
+ max: -1 150;
+ align: 0.5 1.0;
+ color: 255 255 255 255;
+ }
+ }
+ swallow { "sw.counter"; scale;
+ desc { "default";
+ fixed: 1 1;
+ min: 620 227;
+ max: 620 227;
+ rel1 { relative: 1.0 0.0; to_x: "pd.left"; }
+ rel2 { relative: 0.0 0.0; to_x: "pd.right"; to_y: "pd.btn.bg"; }
+ hid;
+ }
+ desc { "hidden";
+ inherit: "default";
+ }
+ desc { "visible";
+ inherit: "default";
+ vis;
+ }
+ }
+ spacer { "pd.left"; scale;
+ desc { "default";
+ fixed: 1 0;
+ min: 50 0;
+ max: 50 -1;
+ align: 0.0 0.5;
+ }
+ }
+ spacer { "pd.right"; scale;
+ desc { "default";
+ fixed: 1 0;
+ min: 50 0;
+ max: 50 -1;
+ align: 1.0 0.5;
+ }
+ }
+ spacer { "pd.btn.bg"; scale;
+ desc { "default";
+ fixed: 0 1;
+ min: 0 58;
+ max: -1 58;
+ align: 0.5 1.0;
+ rel2 { relative: 1.0 0.0; to: "btn.bg"; }
+ }
+ }
+ swallow { "sw.time.selector"; scale;
+ source: "Time_selector";
+ desc { "default";
+ max: 620 -1;
+ rel1 { relative: 1.0 0.0; to_x: "pd.left"; }
+ rel2 { relative: 0.0 0.0; to_x: "pd.right"; to_y: "pd.btn.bg"; }
+ }
+ desc { "hidden";
+ inherit: "default";
+ hid;
+ }
+ desc { "visible";
+ inherit: "default";
+ }
+ }
+ swallow { "sw.btn.start"; scale;
+ desc { "default";
+ align: 0.5 0.5;
+ max: 500 -1;
+ rel1.to: "btn.bg";
+ rel2.to: "btn.bg";
+ }
+ desc { "contracted";
+ inherit: "default";
+ align: 0.1 0.5;
+ max: 300 -1;
+ }
+ desc { "hidden";
+ inherit: "default";
+ hid;
+ }
+ desc { "visible";
+ inherit: "default";
+ }
+ }
+ swallow { "sw.btn.reset"; scale;
+ desc { "default";
+ align: 0.9 0.5;
+ max: 300 -1;
+ rel1.to: "btn.bg";
+ rel2.to: "btn.bg";
+ hid;
+ }
+ desc { "hidden";
+ inherit: "default";
+ }
+ desc { "visible";
+ inherit: "default";
+ vis;
+ }
+ }
+ swallow { "sw.btn.pause"; scale;
+ desc { "default";
+ align: 0.1 0.5;
+ max: 300 -1;
+ rel1.to: "btn.bg";
+ rel2.to: "btn.bg";
+ hid;
+ }
+ desc { "hidden";
+ inherit: "default";
+ }
+ desc { "visible";
+ inherit: "default";
+ vis;
+ }
+ }
+ swallow { "sw.btn.resume"; scale;
+ desc { "default";
+ align: 0.1 0.5;
+ max: 300 -1;
+ rel1.to: "btn.bg";
+ rel2.to: "btn.bg";
+ hid;
+ }
+ desc { "hidden";
+ inherit: "default";
+ }
+ desc { "visible";
+ inherit: "default";
+ vis;
+ }
+ }
+ swallow { "sw.btn.cancel"; scale;
+ desc { "default";
+ align: 0.9 0.5;
+ max: 300 -1;
+ rel1.to: "btn.bg";
+ rel2.to: "btn.bg";
+ hid;
+ }
+ desc { "hidden";
+ inherit: "default";
+ }
+ desc { "visible";
+ inherit: "default";
+ vis;
+ }
+ }
+ program {
+ signal: "menu.startup.show";
+ source: "timer";
+ action: STATE_SET "default";
+ target: "sw.btn.start";
+ target: "sw.btn.reset";
+ target: "sw.btn.pause";
+ target: "sw.btn.resume";
+ target: "sw.btn.cancel";
+ target: "sw.counter";
+ target: "sw.time.selector";
+ }
+ program {
+ signal: "menu.running.show";
+ source: "timer";
+ script {
+ set_state(PART:"sw.btn.start", "hidden", 0.0);
+ set_state(PART:"sw.btn.reset", "hidden", 0.0);
+ set_state(PART:"sw.btn.resume", "hidden", 0.0);
+ set_state(PART:"sw.btn.pause", "visible", 0.0);
+ set_state(PART:"sw.btn.cancel", "visible", 0.0);
+ set_state(PART:"sw.counter", "visible", 0.0);
+ set_state(PART:"sw.time.selector", "hidden", 0.0);
+ }
+ }
+ program {
+ signal: "menu.editing.show";
+ source: "timer";
+ script {
+ set_state(PART:"sw.btn.start", "contracted", 0.0);
+ set_state(PART:"sw.btn.reset", "visible", 0.0);
+ set_state(PART:"sw.btn.pause", "hidden", 0.0);
+ set_state(PART:"sw.btn.resume", "hidden", 0.0);
+ set_state(PART:"sw.btn.cancel", "hidden", 0.0);
+ set_state(PART:"sw.counter", "hidden", 0.0);
+ set_state(PART:"sw.time.selector", "visible", 0.0);
+ }
+ }
+ program {
+ signal: "menu.paused.show";
+ source: "timer";
+ script {
+ set_state(PART:"sw.btn.start", "hidden", 0.0);
+ set_state(PART:"sw.btn.reset", "hidden", 0.0);
+ set_state(PART:"sw.btn.pause", "hidden", 0.0);
+ set_state(PART:"sw.btn.resume", "visible", 0.0);
+ set_state(PART:"sw.btn.cancel", "visible", 0.0);
+ set_state(PART:"sw.counter", "visible", 0.0);
+ set_state(PART:"sw.time.selector", "hidden", 0.0);
+ }
+ }
+ }
+ }
+
+ group { "Time_selector";
+ parts {
+ spacer { "pd.left"; scale;
+ desc {
+ fixed: 1 0;
+ min: 46 0;
+ max: 46 -1;
+ align: 0.0 0.5;
+ }
+ }
+ spacer { "pd.right"; scale;
+ desc {
+ fixed: 1 0;
+ min: 46 0;
+ max: 46 -1;
+ align: 1.0 0.5;
+ }
+ }
+ swallow { "sw.entry.hour"; scale;
+ desc {
+ max: -1 204;
+ align: 0.5 0.5;
+ rel1.relative: 0.0 0.0;
+ rel2.relative: 0.3 1.0;
+ }
+ }
+ textblock { scale;
+ desc {
+ text.style: "ATO010";
+ text.text: ":";
+ rel1 { relative: 1.0 0.0; to: "sw.entry.hour"; }
+ rel2 { relative: 0.0 1.0; to: "sw.entry.minute"; }
+ }
+ }
+ swallow { "sw.entry.minute"; scale;
+ desc {
+ max: -1 204;
+ align: 0.5 0.5;
+ rel1.relative: 0.35 0.0;
+ rel2.relative: 0.65 1.0;
+ }
+ }
+ textblock { scale;
+ desc {
+ text.style: "ATO010";
+ text.text: ":";
+ rel1 { relative: 1.0 0.0; to: "sw.entry.minute"; }
+ rel2 { relative: 0.0 1.0; to: "sw.entry.second"; }
+ }
+ }
+ swallow { "sw.entry.second"; scale;
+ desc {
+ max: -1 204;
+ align: 1.0 0.5;
+ rel1.relative: 0.70 0.0;
+ rel2.relative: 1.0 1.0;
+ }
+ }
+ group { "btn.hour.inc"; scale;
+ source: "timer_button_inc";
+ desc { "default";
+ fixed: 1 1;
+ min: 146 76;
+ max: 146 76;
+ align: 0.0 1.0;
+ rel1 { relative: 1.0 0.0; to_x: "pd.left"; }
+ rel2 { relative: 1.0 0.0; to_y: "sw.entry.hour"; }
+ }
+ }
+ group { "btn.minute.inc"; scale;
+ source: "timer_button_inc";
+ desc { "default";
+ fixed: 1 1;
+ min: 146 76;
+ max: 146 76;
+ align: 0.5 1.0;
+ rel1 { relative: 1.0 0.0; to_x: "btn.hour.inc"; }
+ rel2 { relative: 0.0 0.0; to_x: "btn.second.inc"; to_y: "sw.entry.minute"; }
+ }
+ }
+ group { "btn.second.inc"; scale;
+ source: "timer_button_inc";
+ desc { "default";
+ fixed: 1 1;
+ min: 146 76;
+ max: 146 76;
+ align: 1.0 1.0;
+ rel2 { relative: 0.0 0.0; to_x: "pd.right"; to_y: "sw.entry.second"; }
+ }
+ }
+ group { "btn.hour.dec"; scale;
+ source: "timer_button_dec";
+ desc { "default";
+ fixed: 1 1;
+ min: 146 76;
+ max: 146 76;
+ align: 0.0 0.0;
+ rel1 { relative: 1.0 1.0; to_x: "pd.left"; to_y: "sw.entry.hour"; }
+ }
+ }
+ group { "btn.minute.dec"; scale;
+ source: "timer_button_dec";
+ desc { "default";
+ fixed: 1 1;
+ min: 146 76;
+ max: 146 76;
+ align: 0.5 0.0;
+ rel1 { relative: 1.0 1.0; to_x: "btn.hour.dec"; to_y: "sw.entry.minute"; }
+ rel2 { relative: 0.0 1.0; to_x: "btn.second.dec"; }
+ }
+ }
+ group { "btn.second.dec"; scale;
+ source: "timer_button_dec";
+ desc { "default";
+ fixed: 1 1;
+ min: 146 76;
+ max: 146 76;
+ align: 1.0 0.0;
+ rel1 { relative: 0.0 1.0; to_y: "sw.entry.second"; }
+ rel2 { relative: 0.0 1.0; to_x: "pd.right"; }
+ }
+ }
+ textblock { "txt.hours"; scale;
+ desc { "default";
+ fixed: 1 1;
+ min: 146 42;
+ max: 146 42;
+ align: 0.5 1.0;
+ rel1.to_x: "btn.hour.inc";
+ rel2 { relative: 1.0 0.0; to: "btn.hour.inc";}
+ text {
+ style: "ATO009";
+ text: "Hours";
+ }
+ }
+ }
+ textblock { "txt.minutes"; scale;
+ desc { "default";
+ fixed: 1 1;
+ min: 146 42;
+ max: 146 42;
+ align: 0.5 1.0;
+ rel1.to_x: "btn.minute.inc";
+ rel2 { relative: 1.0 0.0; to: "btn.minute.inc";}
+ text {
+ style: "ATO009";
+ text: "Minutes";
+ }
+ }
+ }
+ textblock { "txt.seconds"; scale;
+ desc { "default";
+ fixed: 1 1;
+ min: 146 42;
+ max: 146 42;
+ align: 0.5 1.0;
+ rel1.to_x: "btn.second.inc";
+ rel2 { relative: 1.0 0.0; to: "btn.second.inc";}
+ text {
+ style: "ATO009";
+ text: "Seconds";
+ }
+ }
+ }
+ }
+ }
+
+ group { "timer_button_inc";
+
+ parts {
+ image { "btn.arrow.up";
+ desc { "default";
+ image.normal: "alarm_picker_arrow_up.png";
+ color: 250 250 250 60;
+ }
+ }
+ image { "btn.bg"; scale;
+ desc { "default";
+ color: 0 0 0 20;
+ rel1.to: "btn.arrow.up";
+ rel2.to: "btn.arrow.up";
+ image.normal: "arrow_bg_horizontal.png";
+ hid;
+ }
+ desc { "pressed";
+ inherit: "default";
+ fixed: 1 1;
+ min: 102 53;
+ max: 102 53;
+ vis;
+ }
+ desc { "expanded";
+ inherit: "default";
+ vis;
+ }
+ desc { "contracted";
+ inherit: "pressed";
+ }
+ }
+ program {
+ signal: "mouse,clicked,*";
+ source: "btn.arrow.up";
+ action: SIGNAL_EMIT "btn,clicked" "";
+ }
+ program {
+ signal: "mouse,down,*";
+ source: "btn.arrow.up";
+ action: STATE_SET "pressed";
+ target: "btn.bg";
+ after: "btn.bg.expand";
+ }
+ program {
+ name: "btn.bg.expand";
+ action: STATE_SET "expanded";
+ target: "btn.bg";
+ transition: DECEL 0.03;
+ }
+ program {
+ signal: "mouse,up,*";
+ source: "btn.arrow.up";
+ action: STATE_SET "contracted";
+ target: "btn.bg";
+ transition: DECEL 0.03;
+ after: "btn.bg.hide";
+ }
+ program {
+ name: "btn.bg.hide";
+ action: STATE_SET "default";
+ target: "btn.bg";
+ }
+ }
+ }
+
+ group { "timer_button_dec";
+
+ parts {
+ image { "btn.arrow.down";
+ desc { "default";
+ image.normal: "alarm_picker_arrow_down.png";
+ color: 250 250 250 60;
+ }
+ }
+ image { "btn.bg"; scale;
+ desc { "default";
+ color: 0 0 0 20;
+ rel1.to: "btn.arrow.down";
+ rel2.to: "btn.arrow.down";
+ image.normal: "arrow_bg_horizontal.png";
+ hid;
+ }
+ desc { "pressed";
+ inherit: "default";
+ fixed: 1 1;
+ min: 102 53;
+ max: 102 53;
+ vis;
+ }
+ desc { "expanded";
+ inherit: "default";
+ vis;
+ }
+ desc { "contracted";
+ inherit: "pressed";
+ }
+ }
+ program {
+ signal: "mouse,clicked,*";
+ source: "btn.arrow.down";
+ action: SIGNAL_EMIT "btn,clicked" "";
+ }
+ program {
+ signal: "mouse,down,*";
+ source: "btn.arrow.down";
+ action: STATE_SET "pressed";
+ target: "btn.bg";
+ after: "btn.bg.expand";
+ }
+ program {
+ name: "btn.bg.expand";
+ action: STATE_SET "expanded";
+ target: "btn.bg";
+ transition: DECEL 0.03;
+ }
+ program {
+ signal: "mouse,up,*";
+ source: "btn.arrow.down";
+ action: STATE_SET "contracted";
+ target: "btn.bg";
+ transition: DECEL 0.03;
+ after: "btn.bg.hide";
+ }
+ program {
+ name: "btn.bg.hide";
+ action: STATE_SET "default";
+ target: "btn.bg";
+ }
+ }
+ }
+}
+
//TODO below valuse are HSBA schem, but need to be converted to RGBA
color_classes {
+
+ color_class {
+ name: "AO003";
+ color: 224 34 34 255;
+ }
+ color_class {
+ name: "AO003P";
+ color: 135 20 20 255;
+ }
+ color_class {
+ name: "AO004";
+ color: 255 179 0 255;
+ }
+ color_class {
+ name: "AO004P";
+ color: 166 116 0 255;
+ }
+
color_class {
name: "AO009";
color: 75 75 75 77;
--- /dev/null
+#include "color_classes.edc"
+
+#define ALARM_TITLE_HEIGHT 69
+#define ALARM_TITLE_AMPM_PADDING_HEIGHT 100
+#define ALARM_TITLE_HOUR_PADDING_HEIGHT 127
+
+collections {
+
+ styles {
+ style {
+ name: "ATO006";
+ base: "font=Tizen:style=Light color=#FAFAFA wrap=none font_size=52 align=center";
+ }
+ style {
+ name: "ATO007";
+ base: "font=Tizen:style=Thin color=#FAFAFA wrap=none font_size=183 align=center";
+ }
+ style {
+ name: "ATO008";
+ base: "font=Tizen:style=Light color=#FAFAFA wrap=none font_size=48 align=center";
+ }
+ }
+
+ images {
+ image: "alarm_btn_bg.png" COMP;
+ image: "alarm_btn_ic_dismiss.png" COMP;
+ image: "alarm_btn_ic_snooze.png" COMP;
+ image: "alarm_btn_circle_line.png" COMP;
+ image: "alarm_btn_circle_drag.png" COMP;
+ }
+
+ base_scale: 2.6;
+
+ group { "main";
+ parts {
+ rect { "bg"; scale; nomouse;
+ desc { "default";
+ color: 20 107 147 255;
+ align: 0.0 0.0;
+ rel1 { relative: 0.0 0.0; }
+ rel2 { relative: 1.0 0.0; to_y: "sw.swipe.area"; }
+ }
+ }
+ spacer { "pd.top"; scale; nomouse;
+ desc { "default";
+ min: 0 120;
+ max: -1 120;
+ align: 0.5 0.0;
+ rel1.to: "bg";
+ rel2.to: "bg";
+ }
+ }
+ spacer { "pd.bottom"; scale; nomouse;
+ desc { "default";
+ min: 0 120+60;
+ max: -1 120+60;
+ align: 0.0 1.0;
+ rel1.to: "bg";
+ rel2.to: "bg";
+ }
+ }
+ textblock { "txt.title"; scale; nomouse;
+ effect: FAR_SOFT_SHADOW;
+ desc { "default";
+ fixed: 1 1;
+ min: 0 ALARM_TITLE_HEIGHT;
+ max: -1 ALARM_TITLE_HEIGHT;
+ align: 0.5 0.0;
+ rel1 { relative: 0.0 1.0; to_y: "pd.top"; }
+ text { style: "ATO006"; }
+ }
+ }
+ textblock { "txt.ampm"; scale; nomouse;
+ effect: FAR_SOFT_SHADOW;
+ desc { "default";
+ min: 0 ALARM_TITLE_HEIGHT;
+ max: -1 ALARM_TITLE_HEIGHT;
+ align: 0.5 0.0;
+ rel1 { relative: 0.0 1.0; to_y: "pd.top";
+ offset: 0 ALARM_TITLE_HEIGHT+ALARM_TITLE_AMPM_PADDING_HEIGHT; }
+ text { style: "ATO006"; }
+ }
+ }
+ textblock { "txt.time"; scale; nomouse;
+ effect: FAR_SOFT_SHADOW;
+ desc { "default";
+ min: 0 230;
+ max: -1 230;
+ align: 0.5 0.0;
+ rel1 { relative: 0.0 1.0; to_y: "pd.top";
+ offset: 0 ALARM_TITLE_HEIGHT+ALARM_TITLE_HOUR_PADDING_HEIGHT; }
+ text { style: "ATO007"; }
+ }
+ }
+ textblock { "txt.date"; scale; nomouse;
+ effect: FAR_SOFT_SHADOW;
+ desc { "default";
+ min: 0 64;
+ max: -1 64;
+ align: 0.5 1.0;
+ rel2 { to_y: "pd.bottom"; relative: 1.0 0.0; }
+ text { style: "ATO008"; }
+ }
+ }
+ group { "sw.swipe.area"; scale;
+ source: "swipe_area";
+ desc { "default";
+ fixed: 1 1;
+ min: 0 438;
+ max: -1 438;
+ align: 0.0 1.0;
+ rel1 { relative: 0.0 1.0; to: "bg"; }
+ rel2 { relative: 1.0 1.0; }
+ }
+ }
+ }
+ }
+ group {
+ name: "swipe_area";
+ parts {
+ rect { "bg"; scale; nomouse;
+ desc {
+ state: "default" 0.0;
+ color: 255 255 255 255;
+ }
+ }
+ spacer { "left.padding";
+ desc { "default";
+ min: 36 0;
+ max: 36 -1;
+ align: 0.0 0.5;
+ }
+ }
+ spacer { "right.padding";
+ desc { "default";
+ min: 36 0;
+ max: 36 -1;
+ align: 1.0 0.5;
+ }
+ }
+ swallow { "swipe.left.button"; scale;
+ desc { "default";
+ fixed: 1 1;
+ align: 0.0 0.5;
+ rel1 { relative: 1.0 0.0; to_x: "left.padding"; }
+ rel2 { relative: 1.0 1.0; }
+ }
+ }
+ swallow { "swipe.right.button"; scale;
+ desc { "default";
+ fixed: 1 1;
+ align: 1.0 0.5;
+ rel1 { relative: 0.0 0.0; }
+ rel2 { relative: 0.0 1.0; to_x: "right.padding"; }
+ }
+ }
+ group { "swipe.center.button"; scale;
+ source: "button_dismiss";
+ desc { "default";
+ fixed: 1 1;
+ align: 0.5 0.5;
+ }
+ }
+ }
+ }
+ group { "button_dismiss";
+ parts {
+ image { "ic.circle.line"; nomouse;
+ desc { "default";
+ hid;
+ fixed: 1 1;
+ max: 180 180;
+ rel1 { relative: -0.2 -0.2; to: "bg"; }
+ rel2 { relative: 1.2 1.2; to: "bg"; }
+ color_class: "AO003P";
+ image.normal: "alarm_btn_circle_line.png";
+ }
+ desc {
+ "pressed";
+ inherit: "default";
+ vis;
+ min: 612 612;
+ max: -1 -1;
+ }
+ }
+ image { "ic.circle.fill"; nomouse;
+ desc { "default";
+ hid;
+ max: 180 180;
+ rel1 { relative: -0.2 -0.2; to: "bg"; }
+ rel2 { relative: 1.2 1.2; to: "bg"; }
+ color_class: "AO003";
+ image.normal: "alarm_btn_circle_drag.png";
+ }
+ desc { "pressed";
+ inherit: "default";
+ vis;
+ }
+ }
+ image { "bg"; scale;
+ desc { "default";
+ fixed: 1 1;
+ min: 180 180;
+ max: 180 180;
+ align: 0.5 0.5;
+ color_class: "AO003";
+ image.normal: "alarm_btn_bg.png";
+ }
+ desc { "pressed";
+ inherit: "default" 0.0;
+ color_class: "AO003P";
+ }
+ }
+ image { "ic.dismiss"; nomouse;
+ desc { "default";
+ max: 80 80;
+ align: 0.5 0.5;
+ rel1.to: "bg";
+ rel2.to: "bg";
+ image.normal: "alarm_btn_ic_dismiss.png";
+ }
+ }
+ program {
+ signal: "mouse,down,*";
+ source: "bg";
+ action: STATE_SET "pressed";
+ transition: DECEL 0.3;
+ target: "bg";
+ target: "ic.circle.line";
+ }
+ program {
+ name: "button,drag,finished";
+ action: STATE_SET "default";
+ transition: DECEL 0.3;
+ target: "bg";
+ target: "ic.circle.line";
+ target: "ic.circle.fill";
+ }
+ program {
+ signal: "mouse,move";
+ source: "bg";
+ script {
+ new mx,my,x,y,w,h;
+ get_mouse(mx, my);
+
+ get_geometry(PART:"bg", x, y, w, h);
+
+ new cx, cy;
+ cx = x + w/2;
+ cy = y + h/2;
+
+ new Float:dx = abs(cx - mx) * 2;
+ new Float:dy = abs(cy - my) * 2;
+
+ new min = round(sqrt((dx * dx) + (dy * dy)));
+
+ new lx, ly, lw, lh;
+ get_geometry(PART:"ic.circle.line", lx, ly, lw, lh);
+
+ if (min >= lw) {
+ emit("button,swipe,accept", "button");
+ run_program(PROGRAM:"button,drag,finished");
+ } else {
+ custom_state(PART:"ic.circle.fill", "pressed", 0.0);
+ set_state_val(PART:"ic.circle.fill", STATE_MIN, min, min);
+ set_state_val(PART:"ic.circle.fill", STATE_MAX, min, min);
+ set_state(PART:"ic.circle.fill", "custom", 0.0);
+ }
+ }
+ }
+ program {
+ signal: "mouse,up,*";
+ source: "bg";
+ after: "button,drag,finished";
+ }
+ }
+ }
+ group { "button_snooze";
+ parts {
+ image { "ic.circle.line"; nomouse;
+ desc { "default";
+ hid;
+ fixed: 1 1;
+ max: 180 180;
+ rel1 { relative: -0.2 -0.2; to: "bg"; }
+ rel2 { relative: 1.2 1.2; to: "bg"; }
+ color_class: "AO004P";
+ image.normal: "alarm_btn_circle_line.png";
+ }
+ desc {
+ "pressed";
+ inherit: "default";
+ vis;
+ min: 612 612;
+ max: -1 -1;
+ }
+ }
+ image { "ic.circle.fill"; nomouse;
+ desc { "default";
+ hid;
+ max: 180 180;
+ rel1 { relative: -0.2 -0.2; to: "bg"; }
+ rel2 { relative: 1.2 1.2; to: "bg"; }
+ color_class: "AO004";
+ image.normal: "alarm_btn_circle_drag.png";
+ }
+ desc { "pressed";
+ inherit: "default";
+ vis;
+ }
+ }
+ image { "bg"; scale;
+ desc { "default";
+ fixed: 1 1;
+ min: 180 180;
+ max: 180 180;
+ align: 1.0 0.5;
+ color_class: "AO004";
+ image.normal: "alarm_btn_bg.png";
+ }
+ desc { "pressed";
+ inherit: "default" 0.0;
+ color_class: "AO004P";
+ }
+ }
+ image { "ic.dismiss"; nomouse;
+ desc { "default";
+ max: 80 80;
+ align: 0.5 0.5;
+ rel1.to: "bg";
+ rel2.to: "bg";
+ image.normal: "alarm_btn_ic_snooze.png";
+ }
+ }
+ program {
+ signal: "mouse,down,*";
+ source: "bg";
+ action: STATE_SET "pressed";
+ transition: DECEL 0.3;
+ target: "bg";
+ target: "ic.circle.line";
+ }
+ program {
+ name: "button,drag,finished";
+ action: STATE_SET "default";
+ transition: DECEL 0.3;
+ target: "bg";
+ target: "ic.circle.line";
+ target: "ic.circle.fill";
+ }
+ program {
+ signal: "mouse,move";
+ source: "bg";
+ script {
+ new mx,my,x,y,w,h;
+ get_mouse(mx, my);
+
+ get_geometry(PART:"bg", x, y, w, h);
+
+ new cx, cy;
+ cx = x + w/2;
+ cy = y + h/2;
+
+ new Float:dx = abs(cx - mx) * 2;
+ new Float:dy = abs(cy - my) * 2;
+
+ new min = round(sqrt((dx * dx) + (dy * dy)));
+
+ new lx, ly, lw, lh;
+ get_geometry(PART:"ic.circle.line", lx, ly, lw, lh);
+
+ if (min >= lw) {
+ emit("button,swipe,accept", "button");
+ run_program(PROGRAM:"button,drag,finished");
+ } else {
+ custom_state(PART:"ic.circle.fill", "pressed", 0.0);
+ set_state_val(PART:"ic.circle.fill", STATE_MIN, min, min);
+ set_state_val(PART:"ic.circle.fill", STATE_MAX, min, min);
+ set_state(PART:"ic.circle.fill", "custom", 0.0);
+ }
+ }
+ }
+ program {
+ signal: "mouse,up,*";
+ source: "bg";
+ after: "button,drag,finished";
+ }
+ }
+ }
+}
+++ /dev/null
-/*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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 "Model/Counter.h"
-#include "log.h"
-
-namespace model {
-
-using namespace std;
-using namespace std::chrono;
-
-Counter::Counter()
-{
- start_time_ = milliseconds::zero();
- pause_time_ = milliseconds::zero();
-}
-
-Counter::~Counter()
-{
-}
-
-bool Counter::Run()
-{
- start_time_ = GetTimeSinceEpoch();
-
- if (start_time_.count() < 0) {
- ERR("Failed to get start time");
- return false;
- }
-
- return true;
-}
-
-bool Counter::Reset()
-{
- pause_time_ = milliseconds::zero();
-
- if (pause_time_ != milliseconds(0)) {
- ERR("Could not set pause time to zero");
- return false;
- }
-
- return true;
-}
-
-bool Counter::Resume()
-{
- if (!Run()) {
- ERR("Run time counter failed");
- return false;
- }
-
- return true;
-}
-
-bool Counter::Stop()
-{
- pause_time_ += duration_cast<milliseconds>(GetTimeSinceEpoch() - start_time_);
-
- if (pause_time_.count() < 0)
- return false;
-
- return true;
-}
-
-milliseconds Counter::GetTime()
-{
- return GetTimeSinceEpoch() - start_time_ + pause_time_;
-}
-
-milliseconds Counter::GetTimeSinceEpoch()
-{
- return duration_cast<milliseconds>(system_clock::now().time_since_epoch());
-}
-
-milliseconds Counter::GetStartTime()
-{
- return start_time_;
-}
-
-} //namespace model
--- /dev/null
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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 "Model/Timer.h"
+#include "log.h"
+
+using namespace model;
+
+Timer::Timer() : hour_(0), minute_(0), second_(0)
+{
+}
+
+Timer::~Timer()
+{
+}
+
+void Timer::SetHour(int hour)
+{
+ if (hour > 99)
+ hour = 0;
+ else if (hour < 0)
+ hour = 99;
+
+ hour_ = hour;
+}
+
+void Timer::SetMinute(int minute)
+{
+ if (minute > 59)
+ minute = 0;
+ else if (minute < 0)
+ minute = 59;
+
+ minute_ = minute;
+}
+
+void Timer::SetSecond(int second)
+{
+ if (second > 59)
+ second = 0;
+ else if (second < 0)
+ second = 59;
+
+ second_ = second;
+}
+
+void Timer::SetTime(int hour, int minute, int second)
+{
+ SetHour(hour);
+ SetMinute(minute);
+ SetSecond(second);
+}
+
+unsigned Timer::GetHour(void) const
+{
+ return hour_;
+}
+
+unsigned Timer::GetMinute(void) const
+{
+ return minute_;
+}
+
+unsigned Timer::GetSecond(void) const
+{
+ return second_;
+}
+
+seconds Timer::GetRemainingTime(void)
+{
+ seconds time = seconds(hour_ * 3600 + minute_ * 60 + second_);
+
+ return time - GetTime();
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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 "Presenter/TimerPresenter.h"
+#include "log.h"
+
+using namespace presenter;
+using namespace std::chrono;
+
+TimerPresenter::TimerPresenter(view::TimerView *view, model::Timer *model)
+ : model_(model), view_(view)
+{
+
+ view_->RegisterSignal(std::bind(&TimerPresenter::StartButtonClicked, this),
+ view::TimerSignal::BUTTON_START_CLICKED);
+ view_->RegisterSignal(std::bind(&TimerPresenter::PauseButtonClicked, this),
+ view::TimerSignal::BUTTON_PAUSE_CLICKED);
+ view_->RegisterSignal(std::bind(&TimerPresenter::ResumeButtonClicked, this),
+ view::TimerSignal::BUTTON_RESUME_CLICKED);
+ view_->RegisterSignal(std::bind(&TimerPresenter::CancelButtonClicked, this),
+ view::TimerSignal::BUTTON_CANCEL_CLICKED);
+ view_->RegisterSignal(std::bind(&TimerPresenter::ResetButtonClicked, this),
+ view::TimerSignal::BUTTON_RESET_CLICKED);
+
+ animator_.RegisterSignal(std::bind(&TimerPresenter::TimeUpdateRequest, this));
+}
+
+TimerPresenter::~TimerPresenter()
+{
+
+}
+
+void TimerPresenter::TimeUpdateRequest()
+{
+ seconds time = model_->GetRemainingTime();
+
+ unsigned h = std::abs(duration_cast<hours>(time).count() % 100);
+ unsigned m = std::abs(duration_cast<minutes>(time).count() % 60);
+ unsigned s = std::abs(duration_cast<seconds>(time).count() % 60);
+
+ view_->DisplayTime(h, m, s);
+
+ if (!h && !m && !s)
+ view_->ShowTimeIsUpAlert();
+}
+
+void TimerPresenter::StartButtonClicked()
+{
+ int hour = 0, minute = 0, second = 0;
+
+ view_->GetTime(&hour, &minute, &second);
+ model_->SetTime(hour, minute, second);
+
+ if (!model_->Run())
+ return;
+
+ view_->ShowRunningMenu();
+ animator_.Start();
+}
+
+void TimerPresenter::PauseButtonClicked()
+{
+ model_->Stop();
+ animator_.Stop();
+ view_->ShowPausedMenu();
+}
+
+void TimerPresenter::ResumeButtonClicked()
+{
+ model_->Resume();
+ animator_.Resume();
+ view_->ShowRunningMenu();
+}
+
+void TimerPresenter::ResetButtonClicked()
+{
+}
+
+void TimerPresenter::CancelButtonClicked()
+{
+ model_->Stop();
+ model_->Reset();
+ animator_.Stop();
+ view_->ShowStartupMenu();
+}
{
msec /= 10;
+ SetDigitText(std::to_string((unsigned)(hour/10)).c_str(), 0);
+ SetDigitText(std::to_string((unsigned)(hour%10)).c_str(), 1);
+
if (hour > 0) {
- SetDigitText(std::to_string((unsigned)(hour/10)).c_str(), 0);
- SetDigitText(std::to_string((unsigned)(hour%10)).c_str(), 1);
Expand();
} else
Contract();
#include "Model/AlarmProvider.h"
#include "Presenter/StopWatchPresenter.h"
+#include "Presenter/TimerPresenter.h"
using namespace view;
using namespace presenter;
NaviframeAdd();
evas_object_show(window_);
-
}
MainView::~MainView()
StopWatchView *stopWatch = new StopWatchView();
model::StopWatch *stopWatchModel = new model::StopWatch();
new StopWatchPresenter(stopWatch, stopWatchModel);
-
stop_watch_ = stopWatch;
+
timer_ = new TimerView();
+
+ TimerView *timer = new TimerView();
+ model::Timer *timerModel = new model::Timer();
+ new TimerPresenter(timer, timerModel);
+ timer_ = timer;
}
* limitations under the License.
*/
+#include <sstream>
+#include <efl_util.h>
+
#include "View/TimerView.h"
#include "View/MainView.h"
#include "Utils/Utils.h"
+#include "log.h"
namespace view {
using namespace utils;
-TimerView::TimerView()
+const char *TimerView::EDJE_FILE = "edje/Timer.edj";
+const char *TimerView::GROUP = "Timer";
+
+static Elm_Entry_Filter_Limit_Size limit_size = {
+ .max_char_count = 2,
+ .max_byte_count = 0
+};
+
+TimerView::TimerView() : set_time_()
+{
+ layout_ = elm_layout_add(MainView::GetInstance().GetEvasObject());
+
+ if (!elm_layout_file_set(layout_, GetEdjeFilePath(), GROUP)) {
+ ERR("elm_layout_file_set failed");
+ evas_object_del(layout_);
+
+ return;
+ }
+
+ evas_object_size_hint_weight_set(layout_, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ evas_object_size_hint_align_set(layout_, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+ CreateMenuButtons();
+ CreateSelector();
+
+ counter_ = new CounterView(*this, CounterType::COUNTER_TYPE_TIMER);
+}
+
+TimerView::~TimerView()
+{
+ delete(counter_);
+}
+
+Evas_Object *TimerView::GetEvasObject()
+{
+ return layout_;
+}
+
+const char *TimerView::GetEdjeFilePath()
+{
+ return utils::Utils::GetAppResourcePath(utils::Utils::APP_DIR_RESOURCE, EDJE_FILE);
+}
+
+void TimerView::AlarmDismiss(void *data, Evas_Object *obj, const char *emission, const char *source)
+{
+ TimerView *object = static_cast<TimerView *>(data);
+
+ evas_object_del(object->alarmWin);
+ object->alarmWin = NULL;
+
+ object->EmitSignal(TimerSignal::BUTTON_CANCEL_CLICKED);
+
+ elm_object_signal_emit(object->layout_, "menu.startup.show", "timer");
+}
+
+void TimerView::ButtonClickedCb(void *data, Evas_Object *obj, const char *emission, const char *source)
+{
+ DBG("Button clicked: %s", source);
+
+ TimerView *object = static_cast<TimerView *>(data);
+
+ object->UnfocusEntries();
+
+ if (!strcmp(source, "btn.hour.inc:")) {
+ object->set_time_.Hour++;
+ if (object->set_time_.Hour > 99)
+ object->set_time_.Hour = 0;
+ } else if (!strcmp(source, "btn.minute.inc:")) {
+ object->set_time_.Min++;
+ if (object->set_time_.Min > 59)
+ object->set_time_.Min = 0;
+ } else if (!strcmp(source, "btn.second.inc:")) {
+ object->set_time_.Sec++;
+ if (object->set_time_.Sec > 59)
+ object->set_time_.Sec = 0;
+ } else if (!strcmp(source, "btn.hour.dec:")) {
+ object->set_time_.Hour--;
+ if (object->set_time_.Hour > 99)
+ object->set_time_.Hour = 99;
+ } else if (!strcmp(source, "btn.minute.dec:")) {
+ object->set_time_.Min--;
+ if (object->set_time_.Min > 59)
+ object->set_time_.Min = 59;
+ } else if (!strcmp(source, "btn.second.dec:")) {
+ object->set_time_.Sec--;
+ if (object->set_time_.Sec > 59)
+ object->set_time_.Sec = 59;
+ }
+
+ object->UpdateView();
+}
+
+void TimerView::DisplayTime(int hour, int min, int sec)
+{
+ counter_->DisplayTime(hour, min, sec);
+}
+
+void TimerView::UpdateTime()
+{
+ Evas_Object *entry = elm_object_part_content_get(selector_, "sw.entry.hour");
+ if (!entry)
+ return;
+
+ set_time_.Hour = std::atoi(elm_object_text_get(entry));
+
+ entry = elm_object_part_content_get(selector_, "sw.entry.minute");
+ if (!entry)
+ return;
+
+ set_time_.Min = std::atoi(elm_object_text_get(entry));
+
+ entry = elm_object_part_content_get(selector_, "sw.entry.second");
+ if (!entry)
+ return;
+
+ set_time_.Sec = std::atoi(elm_object_text_get(entry));
+}
+
+void TimerView::UpdateView()
+{
+ Evas_Object *entry = elm_object_part_content_get(selector_, "sw.entry.hour");
+ if (!entry)
+ return;
+
+ auto text = (set_time_.Hour < 10 ? "0" : "") + std::to_string(set_time_.Hour);
+ elm_entry_entry_set(entry, text.c_str());
+
+ entry = elm_object_part_content_get(selector_, "sw.entry.minute");
+ if (!entry)
+ return;
+
+ text = (set_time_.Min < 10 ? "0" : "") + std::to_string(set_time_.Min);
+ elm_entry_entry_set(entry, text.c_str());
+
+ entry = elm_object_part_content_get(selector_, "sw.entry.second");
+ if (!entry)
+ return;
+
+ text = (set_time_.Sec < 10 ? "0" : "") + std::to_string(set_time_.Sec);
+ elm_entry_entry_set(entry, text.c_str());
+}
+
+void TimerView::GetTime(int *hour, int *minute, int *second)
+{
+ *hour = set_time_.Hour;
+ *minute = set_time_.Min;
+ *second = set_time_.Sec;
+}
+
+void TimerView::CreateSelector()
+{
+ selector_ = elm_layout_add(layout_);
+
+ if (!elm_layout_file_set(selector_, GetEdjeFilePath(), "Time_selector"))
+ return;
+
+ elm_object_part_content_set(layout_, "sw.time.selector", selector_);
+
+ CreateEntries(selector_);
+
+ elm_object_signal_callback_add(selector_, "btn,clicked", "btn.hour.inc:", ButtonClickedCb, this);
+ elm_object_signal_callback_add(selector_, "btn,clicked", "btn.minute.inc:", ButtonClickedCb, this);
+ elm_object_signal_callback_add(selector_, "btn,clicked", "btn.second.inc:", ButtonClickedCb, this);
+
+ elm_object_signal_callback_add(selector_, "btn,clicked", "btn.hour.dec:", ButtonClickedCb, this);
+ elm_object_signal_callback_add(selector_, "btn,clicked", "btn.minute.dec:", ButtonClickedCb, this);
+ elm_object_signal_callback_add(selector_, "btn,clicked", "btn.second.dec:", ButtonClickedCb, this);
+
+}
+
+void TimerView::CreateEntries(Evas_Object *parent)
+{
+ CreateEntry(parent, "sw.entry.hour");
+ CreateEntry(parent, "sw.entry.minute");
+ CreateEntry(parent, "sw.entry.second");
+}
+
+void TimerView::CreateEntry(Evas_Object *parent, const char *part)
+{
+ Evas_Object *entry = elm_entry_add(parent);
+
+ elm_object_part_content_set(parent, part, entry);
+
+ evas_object_size_hint_weight_set(entry, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ evas_object_size_hint_align_set(entry, 0.5, EVAS_HINT_FILL);
+
+ elm_entry_context_menu_disabled_set(entry, EINA_TRUE);
+ elm_entry_input_panel_layout_set(entry, ELM_INPUT_PANEL_LAYOUT_DATETIME);
+ elm_entry_single_line_set(entry, EINA_TRUE);
+ elm_entry_markup_filter_append(entry, elm_entry_filter_limit_size, &limit_size);
+
+ elm_entry_text_style_user_push(entry, "DEFAULT='font=Tizen:style=Thin color=#FAFAFA font_size=160 wrap=none align=center'");
+ elm_entry_entry_set(entry, "00");
+
+ evas_object_smart_callback_add(entry, "focused", EntryFocusedCb, this);
+ evas_object_smart_callback_add(entry, "unfocused", EntryUnfocusedCb, part);
+ evas_object_smart_callback_add(entry, "changed", EntryChangedCb, this);
+
+ evas_object_event_callback_add(entry, EVAS_CALLBACK_KEY_DOWN, EntryEditDoneCb, this);
+
+ evas_object_show(entry);
+}
+
+void TimerView::EntryFocusedCb(void *data, Evas_Object *obj, void *event_info)
+{
+ TimerView *object = static_cast<TimerView *>(data);
+
+ elm_entry_select_all(obj);
+
+ elm_object_signal_emit(object->layout_, "menu.editing.show", "timer");
+}
+
+void TimerView::EntryUnfocusedCb(void *data, Evas_Object *obj, void *event_info)
+{
+ const char *text = elm_entry_entry_get(obj);
+ const char *part = static_cast<const char *>(data);
+
+ int val = std::atoi(text);
+ if (val > (strcmp(part, "sw.entry.hour") ? 59 : 99))
+ elm_entry_entry_set(obj, std::to_string(59).c_str());
+ else if (val < 10) {
+ std::stringstream stream;
+ stream << "0" << val;
+ elm_entry_entry_set(obj, stream.str().c_str());
+ }
+}
+
+void TimerView::EntryChangedCb(void *data, Evas_Object *obj, void *event_info)
+{
+ TimerView *object = static_cast<TimerView *>(data);
+
+ object->UpdateTime();
+
+ if (object->set_time_.Hour || object->set_time_.Min || object->set_time_.Sec)
+ object->SetEnabledStartButton(true);
+ else
+ object->SetEnabledStartButton(false);
+
+ object->counter_->DisplayTime(
+ object->set_time_.Hour,
+ object->set_time_.Min,
+ object->set_time_.Sec
+ );
+}
+
+void TimerView::EntryEditDoneCb(void *data, Evas *e, Evas_Object *obj, void *event_info)
+{
+ TimerView *object = static_cast<TimerView *>(data);
+ Evas_Event_Key_Down *keyDown = static_cast<Evas_Event_Key_Down *>(event_info);
+
+ if (keyDown && !strcmp("Return", keyDown->key)) {
+ object->ShowStartupMenu();
+ object->UnfocusEntries();
+ }
+}
+
+void TimerView::UnfocusEntries()
+{
+ Evas_Object *entry = elm_object_part_content_get(selector_, "sw.entry.hour");
+ if (!entry) {
+ ERR("!entry");
+ return;
+ }
+
+ elm_object_focus_set(entry, EINA_FALSE);
+
+ entry = elm_object_part_content_get(selector_, "sw.entry.minute");
+ if (!entry) {
+ ERR("!entry");
+ return;
+ }
+
+ elm_object_focus_set(entry, EINA_FALSE);
+
+ entry = elm_object_part_content_get(selector_, "sw.entry.second");
+ if (!entry) {
+ ERR("!entry");
+ return;
+ }
+
+ elm_object_focus_set(entry, EINA_FALSE);
+}
+
+void TimerView::ShowTimeIsUpAlert()
+{
+ if (alarmWin)
+ return;
+
+ alarmWin = elm_win_add(NULL, "Alarm", ELM_WIN_NOTIFICATION);
+ if (!alarmWin) {
+ ERR("Could not create alarm window");
+ return;
+ }
+
+ int ret = efl_util_set_notification_window_level(alarmWin, EFL_UTIL_NOTIFICATION_LEVEL_HIGH);
+ if (ret != EFL_UTIL_ERROR_NONE) {
+ ERR("efl_util_set_notification_window_level failed");
+ return;
+ }
+
+ ret = efl_util_set_window_opaque_state(alarmWin, 1);
+ if (ret != EFL_UTIL_ERROR_NONE) {
+ ERR("efl_util_set_window_opaque_state failed");
+ return;
+ }
+
+ elm_win_indicator_mode_set(alarmWin, ELM_WIN_INDICATOR_SHOW);
+ elm_win_indicator_opacity_set(alarmWin, ELM_WIN_INDICATOR_OPAQUE);
+ elm_win_autodel_set(alarmWin, EINA_FALSE);
+
+ Evas_Object *alarmLy = elm_layout_add(alarmWin);
+ if (!alarmLy) {
+ ERR("Could not create alarm layout");
+ return;
+ }
+
+ if (!elm_layout_file_set(alarmLy, utils::Utils::GetAppResourcePath(
+ utils::Utils::APP_DIR_RESOURCE, "edje/ring.edj"), "main")) {
+ ERR("Could not load ring edje file");
+ return;
+ }
+
+ evas_object_size_hint_align_set(alarmLy, EVAS_HINT_FILL, EVAS_HINT_FILL);
+ evas_object_size_hint_weight_set(alarmLy, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+
+ elm_win_resize_object_add(alarmWin, alarmLy);
+
+ elm_object_part_text_set(alarmLy, "txt.title", "Time is up");
+
+ evas_object_show(alarmLy);
+ evas_object_show(alarmWin);
+
+ elm_object_signal_callback_add(alarmLy, "button,swipe,accept", "sw.swipe.area:swipe.center.button:button", AlarmDismiss, this);
+}
+
+void TimerView::ShowStartupMenu(void)
+{
+ if (!layout_)
+ return;
+
+ counter_->DisplayTime(set_time_.Hour, set_time_.Min, set_time_.Sec);
+
+ elm_object_signal_emit(layout_, "menu.startup.show", "timer");
+}
+
+void TimerView::ShowRunningMenu(void)
+{
+ if (!layout_)
+ return;
+
+ elm_object_signal_emit(layout_, "menu.running.show", "timer");
+}
+
+void TimerView::ShowPausedMenu(void)
+{
+ if (!layout_)
+ return;
+
+ elm_object_signal_emit(layout_, "menu.paused.show", "timer");
+}
+
+void TimerView::ShowEditingMenu(void)
+{
+ if (!layout_)
+ return;
+
+ elm_object_signal_emit(layout_, "menu.editing.show", "timer");
+}
+
+void TimerView::CreateMenuButtons()
+{
+ CreateButton(layout_, "Start", "sw.btn.start", StartButtonClicked);
+ CreateButton(layout_, "Reset", "sw.btn.reset", ResetButtonClicked);
+ CreateButton(layout_, "Pause", "sw.btn.pause", PauseButtonClicked);
+ CreateButton(layout_, "Cancel", "sw.btn.cancel", CancelButtonClicked);
+ CreateButton(layout_, "Resume", "sw.btn.resume", ResumeButtonClicked);
+
+ SetEnabledStartButton(false);
+}
+
+void TimerView::SetEnabledStartButton(bool enable)
+{
+ Evas_Object *startButton = elm_object_part_content_get(layout_, "sw.btn.start");
+ if (!startButton)
+ return;
+
+ Eina_Bool isDisabled = elm_object_disabled_get(startButton);
+
+ if (isDisabled && enable)
+ elm_object_disabled_set(startButton, EINA_FALSE);
+ else if (!isDisabled && !enable)
+ elm_object_disabled_set(startButton, EINA_TRUE);
+}
+
+void TimerView::CreateButton(Evas_Object *parent, const char *name,
+ const char *part, Evas_Smart_Cb cb)
+{
+ Evas_Object *button = elm_object_part_content_unset(layout_, part);
+ if (button) {
+ evas_object_del(button);
+ return;
+ }
+
+ button = elm_button_add(parent);
+
+ elm_object_text_set(button, name);
+
+ elm_object_style_set(button, "bottom");
+ elm_object_part_content_set(layout_, part, button);
+
+ evas_object_smart_callback_add(button, "clicked", cb, this);
+
+ evas_object_show(button);
+}
+
+void TimerView::StartButtonClicked(void *data, Evas_Object *obj, void *event_info)
+{
+ TimerView *object = static_cast<TimerView *>(data);
+
+ object->EmitSignal(TimerSignal::BUTTON_START_CLICKED);
+
+ elm_object_signal_emit(object->layout_, "menu.running.show", "timer");
+}
+
+void TimerView::PauseButtonClicked(void *data, Evas_Object *obj, void *event_info)
+{
+ TimerView *object = static_cast<TimerView *>(data);
+
+ object->EmitSignal(TimerSignal::BUTTON_PAUSE_CLICKED);
+
+ elm_object_signal_emit(object->layout_, "menu.paused.show", "timer");
+}
+
+void TimerView::CancelButtonClicked(void *data, Evas_Object *obj, void *event_info)
+{
+ TimerView *object = static_cast<TimerView *>(data);
+
+ object->EmitSignal(TimerSignal::BUTTON_CANCEL_CLICKED);
+
+ elm_object_signal_emit(object->layout_, "menu.startup.show", "timer");
+}
+
+void TimerView::ResumeButtonClicked(void *data, Evas_Object *obj, void *event_info)
{
- /*Create content here and use main_layout_ as a parent*/
+ TimerView *object = static_cast<TimerView *>(data);
+
+ object->EmitSignal(TimerSignal::BUTTON_RESUME_CLICKED);
- /*Temporary Code*/
- timer_ = elm_layout_add(MainView::GetInstance().GetEvasObject());
+ elm_object_signal_emit(object->layout_, "menu.running.show", "timer");
+}
- elm_layout_file_set(timer_, Utils::GetAppResourcePath(Utils::APP_DIR_RESOURCE, "edje/clock.edj"), "main");
+void TimerView::ResetButtonClicked(void *data, Evas_Object *obj, void *event_info)
+{
+ TimerView *object = static_cast<TimerView *>(data);
- evas_object_size_hint_align_set(timer_, EVAS_HINT_FILL, EVAS_HINT_FILL);
- evas_object_size_hint_weight_set(timer_, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ object->EmitSignal(TimerSignal::BUTTON_RESET_CLICKED);
- Evas_Object *label = elm_label_add(timer_);
+ object->set_time_.Hour = 0;
+ object->set_time_.Min = 0;
+ object->set_time_.Sec = 0;
- elm_object_text_set(label, "Timer");
- elm_layout_content_set(timer_, "bg", label);
+ object->UpdateView();
+}
+
+void TimerView::RegisterSignal(std::function<void(void)>func, TimerSignal type)
+{
+ signals.at((int)type) = func;
+}
+
+void TimerView::EmitSignal(TimerSignal type)
+{
+ if (signals.at((int)type) != nullptr)
+ signals.at((int)type)();
}
} //namespace view
<privileges>
<privilege>http://tizen.org/privilege/alarm</privilege>
<privilege>http://tizen.org/privilege/alarm.set</privilege>
+ <privilege>http://tizen.org/privilege/window.priority.set</privilege>
</privileges>
</manifest>