Add Delete Alarm view and presenter.
authorLukasz Stanislawski <l.stanislaws@samsung.com>
Tue, 6 Sep 2016 12:30:06 +0000 (14:30 +0200)
committerr.czerski <r.czerski@samsung.com>
Tue, 13 Sep 2016 14:04:53 +0000 (16:04 +0200)
Add possibility to delete exitsing alarms by using "menu"
hardware button and pressing "delete" item.
The new view with selectable alarms is being pushed.

When alarms are begin deleted the AlarmRemovedEvent is being
triggered, which allows to synchronize other views (eg. AlarmView)

Change-Id: Ifa41318fdb5c9930bb6b7e3dfb6931ee3e21db13

19 files changed:
clock/inc/Controller/MainController.h
clock/inc/Internal/AlarmProviderFile.h
clock/inc/Model/AlarmEvent.h
clock/inc/Model/AlarmProvider.h
clock/inc/Model/AlarmProviderEvent.h
clock/inc/Presenter/AlarmPresenter.h
clock/inc/Presenter/DeleteAlarmPresenter.h [new file with mode: 0644]
clock/inc/View/AlarmView.h
clock/inc/View/DeleteAlarmView.h [new file with mode: 0644]
clock/res/edje/alarm.edc
clock/src/Controller/MainController.cpp
clock/src/Model/AlarmEvent.cpp
clock/src/Model/AlarmProviderEvent.cpp
clock/src/Model/AlarmProviderFile.cpp
clock/src/Presenter/AlarmPresenter.cpp
clock/src/Presenter/DeleteAlarmPresenter.cpp [new file with mode: 0644]
clock/src/Utils/EventBus.cpp
clock/src/View/AlarmView.cpp
clock/src/View/DeleteAlarmView.cpp [new file with mode: 0644]

index 06d4f92..20bc60d 100644 (file)
@@ -17,6 +17,8 @@
 #ifndef _CLOCK_MAIN_CONTROLLER_H_
 #define _CLOCK_MAIN_CONTROLLER_H_
 
+#include "Utils/EventBus.h"
+
 /**
  * @file MainController.h
  */
@@ -89,7 +91,12 @@ namespace controller {
                        /**
                         * @brief Creates new "Edit/Create" alarm page.
                         */
-                       void CreateNewAlarmPage();
+                       void CreateNewAlarmPage(utils::Event *e);
+
+                       /**
+                        * @brief Creates new "Delete" alarm page.
+                        */
+                       void CreateNewDeleteAlarmsPage(utils::Event *e);
        };
 }
 
index 2d530ea..bc146eb 100644 (file)
@@ -13,7 +13,7 @@ namespace internal {
                        std::vector<std::reference_wrapper<model::Alarm>> GetAlarms();
                        model::Alarm* GetAlarmWithId(model::AlarmId id);
                        void Add(model::Alarm& alarm);
-                       void Remove(model::Alarm& alarm);
+                       void Remove(std::reference_wrapper<model::Alarm> alarm);
                        AlarmProviderFile(utils::IReader &r);
                        ~AlarmProviderFile();
                        void Serialize(utils::IWriter &w) const;
index 347ee35..be7bc77 100644 (file)
@@ -27,6 +27,13 @@ namespace model {
                private:
                        static int custom_type_;
        };
+       class AlarmDeleteRequestEvent : public utils::Event {
+               public:
+                       AlarmDeleteRequestEvent();
+                       static int EventType();
+               private:
+                       static int custom_type_;
+       };
 } /* model */
 
 #endif
index 0d37997..0409727 100644 (file)
@@ -34,7 +34,7 @@ namespace model {
                        virtual std::vector<std::reference_wrapper<Alarm>> GetAlarms() = 0;
                        virtual Alarm *GetAlarmWithId(AlarmId id) = 0;
                        virtual void Add(Alarm& alarm) = 0;
-                       virtual void Remove(Alarm& alarm) = 0;
+                       virtual void Remove(std::reference_wrapper<Alarm> alarm) = 0;
                protected:
                        AlarmProvider() {}
                        virtual ~AlarmProvider() {}
index 630e507..5350566 100644 (file)
@@ -24,7 +24,7 @@ namespace model {
        class AlarmAddedEvent : public utils::Event {
                public:
                        AlarmAddedEvent(Alarm &alarm);
-                       const Alarm& GetAlarm() const { return alarm_; }
+                       Alarm& GetAlarm() { return alarm_; }
                        static int EventType();
                private:
                        Alarm &alarm_;
@@ -33,7 +33,7 @@ namespace model {
        class AlarmRemovedEvent : public utils::Event {
                public:
                        AlarmRemovedEvent(Alarm &alarm);
-                       const Alarm& GetAlarm() const { return alarm_; }
+                       Alarm& GetAlarm() { return alarm_; }
                        static int EventType();
                private:
                        Alarm &alarm_;
index 3528843..95cc15c 100644 (file)
@@ -21,6 +21,8 @@
 #include "Model/AlarmProvider.h"
 #include "Model/AlarmProviderEvent.h"
 
+#include <map>
+
 namespace presenter {
        class AlarmPresenter {
                public:
@@ -34,6 +36,9 @@ namespace presenter {
                        void OnAddButtonClicked();
                        void OnItemActiveStatusChanged(int idx);
                        void OnAlarmAddedEvent(utils::Event *e);
+                       void OnAlarmRemovedEvent(utils::Event *e);
+                       void OnDeleteItemClicked();
+                       std::map<int, std::reference_wrapper<model::Alarm>> alarms_;
        };
 } /* presenters */
 
diff --git a/clock/inc/Presenter/DeleteAlarmPresenter.h b/clock/inc/Presenter/DeleteAlarmPresenter.h
new file mode 100644 (file)
index 0000000..14a737c
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * 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_DELETE_ALARM_H_
+#define _CLOCK_PRESENTER_DELETE_ALARM_H_
+
+#include "Model/AlarmProvider.h"
+#include "View/DeleteAlarmView.h"
+
+#include <map>
+
+namespace presenter {
+       class DeleteAlarmPresenter {
+               public:
+                       DeleteAlarmPresenter(view::DeleteAlarmView *view, model::AlarmProvider *model);
+               private:
+                       view::DeleteAlarmView *view_;
+                       model::AlarmProvider *model_;
+                       void OnDeleteButtonClicked();
+                       void OnCancelButtonClicked();
+                       std::map<int, std::reference_wrapper<model::Alarm>> alarms_;
+       };
+} /* presenter */
+
+#endif
index 4ae65a2..3cbfae2 100644 (file)
@@ -33,7 +33,7 @@ namespace view {
                        AlarmView();
                        void Clear();
                        int ItemAppend(utils::Time time, const char *name,
-                                       const  model::WeekFlags flags, bool active);
+                                       const model::WeekFlags flags, bool active);
                        void RemoveItem(int idx);
                        void ItemUpdate(int idx, utils::Time time, const char *name,
                                        const model::WeekFlags flags, bool active);
@@ -43,6 +43,7 @@ namespace view {
                        void SetItemToggleCallback(ToggleCallback func);
                        void SetItemSelectCallback(SelectCallback func);;
                        void SetButtonClickedCallback(ButtonClickedCallback func);
+                       void SetDeleteItemClickedCallback(ButtonClickedCallback func) { onDeleteClicked_ = func;}
                        Evas_Object *GetEvasObject();
                private:
                        static Elm_Genlist_Item_Class alarm_itc;
@@ -52,11 +53,18 @@ namespace view {
                        static void ItemClicked(void *data, Evas_Object *obj, void *info);
                        static void ItemRealized(void *data, Evas_Object *obj, void *info);
                        static void ButtonClicked(void *data, Evas_Object *obj, void *info);
-                       Evas_Object *genlist;
-                       Evas_Object *content;
-                       SelectCallback onSelected;
-                       ToggleCallback onToggled;
-                       ButtonClickedCallback onClicked;;
+                       static void MoreButtonClicked(void *data, Evas_Object *obj, void *info);
+                       static void DismissPopupCallback(void *data, Evas_Object *obj, void *info);
+                       static void PopupDeleteItemCallback(void *data, Evas_Object *obj, void *info);
+
+                       Evas_Object *genlist_;
+                       Evas_Object *content_;
+                       Evas_Object *popup_;
+                       SelectCallback onSelected_;
+                       ToggleCallback onToggled_;
+                       ButtonClickedCallback onClicked_;
+                       ButtonClickedCallback onDeleteClicked_;
+                       void ShowDeletePopup();
        };
 }
 
diff --git a/clock/inc/View/DeleteAlarmView.h b/clock/inc/View/DeleteAlarmView.h
new file mode 100644 (file)
index 0000000..3fa9083
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * 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_DELETE_ALARM_VIEW_
+#define _CLOCK_DELETE_ALARM_VIEW_
+
+#include "View/PageView.h"
+#include "Model/WeekFlags.h"
+#include "Utils/Time.h"
+
+#include <vector>
+
+namespace view {
+       class DeleteAlarmView : public PageView {
+               public:
+                       typedef std::function<void(void)> ButtonClickedCallback;
+
+                       DeleteAlarmView();
+
+                       void RegisterCancelButtonClickedCallback(ButtonClickedCallback cb) { onCancelButtonClicked_ = cb; }
+                       void RegisterDeleteButtonClickedCallback(ButtonClickedCallback cb) { onDeleteButtonClicked_ = cb; }
+                       Evas_Object *GetEvasObject() { return content_; }
+
+                       int ItemAppend(utils::Time time, const char *name,
+                                       const model::WeekFlags flags, bool active);
+                       std::vector<int> GetSelectedItems() const;
+               protected:
+                       virtual void CreateContent();
+                       virtual void DestroyContent();
+               private:
+                       Evas_Object *content_;
+                       Evas_Object *left_btn_;
+                       Evas_Object *right_btn_;
+
+                       ButtonClickedCallback onDeleteButtonClicked_;
+                       ButtonClickedCallback onCancelButtonClicked_;
+
+                       void SelectAllStateSet(bool value);
+                       void UpdateTitle(void);
+
+                       bool all_selected_;
+                       Evas_Object *all_selected_check_;
+
+                       // EFL callbacks
+                       static void OnCancelButtonClickedCb(void *data, Evas_Object *obj, void *event);
+                       static void OnDeleteButtonClickedCb(void *data, Evas_Object *obj, void *event);
+                       static void ItemRealized(void *data, Evas_Object *obj, void *event);
+                       static void ItemSelectToggle(void *data, Evas_Object *obj, void *event);
+                       static void ItemSelected(void *data, Evas_Object *obj, void *event);
+                       static void ItemSelectAllClicked(void *data, Evas_Object *obj, void *event);
+
+                       void CreateSelectAllItem();
+       };
+} /* view */
+
+#endif
index 6859a1b..1b8a96c 100644 (file)
@@ -158,4 +158,67 @@ collections {
                        target: "time";
                }
        }
+       group { name: "elm/genlist/item/select_all/default";
+               styles {
+                       style { name: "font_normal";
+                               base: "font=Tizen:style=Light color=#000000FF font_size=40 ellipsis=1.0";
+                       }
+               }
+               data.item: "texts" "elm.text";
+               data.item: "contents" "sw.check";
+               data.item: "banded_bg_area" "elm.swallow.bg";
+               parts {
+                       spacer { "base"; scale;
+                               desc { "default";
+                                       min: 0 120;
+                               }
+                       }
+                       swallow { "elm.swallow.bg";
+                               desc { "default";
+                                       rel1.to: "base";
+                                       rel2.to: "base";
+                               }
+                       }
+                       spacer { "padding.left"; scale;
+                               desc { "default";
+                                       fixed: 1 0;
+                                       min: 32 0;
+                                       max: 32 -1;
+                                       align: 0.0 0.5;
+                                       rel1.to: "base";
+                                       rel2.to: "base";
+                               }
+                       }
+                       spacer { "padding.right"; scale;
+                               desc { "default";
+                                       fixed: 1 0;
+                                       min: 32 0;
+                                       max: 32 -1;
+                                       align: 1.0 0.5;
+                                       rel1.to: "base";
+                                       rel2.to: "base";
+                               }
+                       }
+                       textblock { "elm.text"; scale;
+                               desc { "default";
+                                       fixed: 0 1;
+                                       min: 0 93;
+                                       max: -1 93;
+                                       rel1 { relative: 1.0 0.0; to_x: "padding.left"; to_y: "base"; }
+                                       rel2.to: "base";
+                                       text.style: "font_normal";
+                               }
+                       }
+                       swallow { "sw.check"; scale;
+                               desc { "default";
+                                       fixed: 1 1;
+                                       align: 1.0 0.5;
+                                       min: 80 80;
+                                       max: 80 80;
+                                       rel1.to: "base";
+                                       rel2 { relative: 0.0 1.0; to: "padding.right"; }
+                               }
+                       }
+               }
+       }
 }
index a2d2beb..13b191d 100644 (file)
 #include "View/EditAlarmView.h"
 #include "Presenter/EditAlarmPresenter.h"
 #include "Model/AlarmEvent.h"
+#include "View/DeleteAlarmView.h"
+#include "Presenter/DeleteAlarmPresenter.h"
 
 using namespace controller;
 using namespace view;
 using namespace utils;
 using namespace presenter;
 using namespace model;
+using std::placeholders::_1;
 
 MainController &MainController::GetInstance()
 {
@@ -54,17 +57,23 @@ int MainController::Init()
        MainView::GetInstance();
        MainView::GetInstance().CreateContent();
 
-       EventBus::RegisterHandler(AlarmCreateRequestEvent::EventType(), std::bind(&MainController::CreateNewAlarmPage, this));
+       EventBus::RegisterHandler(AlarmCreateRequestEvent::EventType(),
+                       std::bind(&MainController::CreateNewAlarmPage, this, _1));
+       EventBus::RegisterHandler(AlarmDeleteRequestEvent::EventType(),
+                       std::bind(&MainController::CreateNewDeleteAlarmsPage, this, _1));
 
        return 0;
 }
 
 void MainController::Deinit()
 {
-       EventBus::DeregisterHandler(AlarmCreateRequestEvent::EventType(), std::bind(&MainController::CreateNewAlarmPage, this));
+       EventBus::DeregisterHandler(AlarmCreateRequestEvent::EventType(),
+                       std::bind(&MainController::CreateNewAlarmPage, this, _1));
+       EventBus::DeregisterHandler(AlarmDeleteRequestEvent::EventType(),
+                       std::bind(&MainController::CreateNewDeleteAlarmsPage, this, _1));
 }
 
-void MainController::CreateNewAlarmPage()
+void MainController::CreateNewAlarmPage(Event *e)
 {
        static EditAlarmView *view;
        static EditAlarmPresenter *presenter;
@@ -75,3 +84,15 @@ void MainController::CreateNewAlarmPage()
        view = new EditAlarmView();
        presenter = new EditAlarmPresenter(nullptr, *view);
 }
+
+void MainController::CreateNewDeleteAlarmsPage(Event *e)
+{
+       static DeleteAlarmView *view;
+       static DeleteAlarmPresenter *presenter;
+
+       if (view) delete view;
+       if (presenter) delete presenter;
+
+       view = new DeleteAlarmView();
+       presenter = new DeleteAlarmPresenter(view, AlarmProvider::GetInstance());
+}
index 636704a..8fcc0c6 100644 (file)
@@ -4,6 +4,7 @@ using namespace model;
 using namespace utils;
 
 int AlarmCreateRequestEvent::custom_type_;
+int AlarmDeleteRequestEvent::custom_type_;
 
 AlarmCreateRequestEvent::AlarmCreateRequestEvent() :
        Event(AlarmCreateRequestEvent::EventType())
@@ -17,3 +18,16 @@ int AlarmCreateRequestEvent::EventType()
        }
        return custom_type_;
 }
+
+AlarmDeleteRequestEvent::AlarmDeleteRequestEvent() :
+       Event(AlarmDeleteRequestEvent::EventType())
+{
+}
+
+int AlarmDeleteRequestEvent::EventType()
+{
+       if (custom_type_ == 0) {
+               custom_type_ = EventBus::RegisterNewEventType();
+       }
+       return custom_type_;
+}
index 5507bd9..99cb2ae 100644 (file)
@@ -20,7 +20,7 @@ int AlarmAddedEvent::EventType()
 }
 
 AlarmRemovedEvent::AlarmRemovedEvent(Alarm &alarm) :
-       Event(AlarmAddedEvent::EventType()), alarm_(alarm)
+       Event(AlarmRemovedEvent::EventType()), alarm_(alarm)
 {
 }
 
index 3ebf038..abbe694 100644 (file)
@@ -22,16 +22,19 @@ void AlarmProviderFile::Add(model::Alarm& alarm)
                alarms.push_back(alarm);
                EventBus::FireEvent(new AlarmAddedEvent(alarm));
        }
+       Sync();
 }
 
-void AlarmProviderFile::Remove(model::Alarm& alarm)
+void AlarmProviderFile::Remove(std::reference_wrapper<Alarm> alarm)
 {
-       auto it = std::find(alarms.begin(), alarms.end(), alarm);
+       auto it = std::find(alarms.begin(), alarms.end(), alarm.get());
 
        if (it != alarms.end()) {
-               alarms.erase(it);
                EventBus::FireEvent(new AlarmRemovedEvent(alarm));
+               alarm.get().Deactivate();
+               alarms.erase(it);
        }
+       Sync();
 }
 
 AlarmProviderFile::AlarmProviderFile(IReader &r)
index e396774..60a701b 100644 (file)
@@ -13,9 +13,12 @@ using std::placeholders::_1;
 AlarmPresenter::AlarmPresenter(AlarmView *v, AlarmProvider *m) : view(v), model(m)
 {
        view->SetButtonClickedCallback(std::bind(&AlarmPresenter::OnAddButtonClicked, this));
+       view->SetDeleteItemClickedCallback(std::bind(&AlarmPresenter::OnDeleteItemClicked, this));
 
        EventBus::RegisterHandler(AlarmAddedEvent::EventType(),
                        std::bind(&AlarmPresenter::OnAlarmAddedEvent, this, _1));
+       EventBus::RegisterHandler(AlarmRemovedEvent::EventType(),
+                       std::bind(&AlarmPresenter::OnAlarmRemovedEvent, this, _1));
 
        ShowAll();
 }
@@ -24,6 +27,8 @@ AlarmPresenter::~AlarmPresenter()
 {
        EventBus::DeregisterHandler(AlarmAddedEvent::EventType(),
                        std::bind(&AlarmPresenter::OnAlarmAddedEvent, this, _1));
+       EventBus::DeregisterHandler(AlarmRemovedEvent::EventType(),
+                       std::bind(&AlarmPresenter::OnAlarmRemovedEvent, this, _1));
 }
 
 void AlarmPresenter::ShowAll()
@@ -33,11 +38,12 @@ void AlarmPresenter::ShowAll()
        view->Clear();
 
        for (auto a: alarms) {
-               view->ItemAppend(
+               int id = view->ItemAppend(
                                a.get().GetTime(),
                                a.get().GetName().c_str(),
                                a.get().GetWeekFlags(),
                                a.get().IsActivated());
+               alarms_.insert(std::map<int, std::reference_wrapper<Alarm>>::value_type (id, std::reference_wrapper<Alarm>(a)));
        }
 }
 
@@ -77,9 +83,30 @@ void AlarmPresenter::OnAlarmAddedEvent(Event *e)
 
        AlarmAddedEvent *ev = dynamic_cast<AlarmAddedEvent*>(e);
 
-       view->ItemAppend(
+       int id = view->ItemAppend(
                        ev->GetAlarm().GetTime(),
                        ev->GetAlarm().GetName().c_str(),
                        ev->GetAlarm().GetWeekFlags(),
                        ev->GetAlarm().IsActivated());
+       alarms_.insert(std::map<int, std::reference_wrapper<Alarm>>::value_type (id, std::reference_wrapper<Alarm>(ev->GetAlarm())));
+}
+
+void AlarmPresenter::OnDeleteItemClicked()
+{
+       EventBus::FireEvent(new AlarmDeleteRequestEvent());
+}
+
+void AlarmPresenter::OnAlarmRemovedEvent(Event *e)
+{
+       if (!e || (e->GetType() != AlarmRemovedEvent::EventType()))
+               return;
+
+       AlarmRemovedEvent *ev = dynamic_cast<AlarmRemovedEvent*>(e);
+       for (auto it = alarms_.begin(); it != alarms_.end(); ++it) {
+               if (ev->GetAlarm() == it->second.get()) {
+                       view->RemoveItem(it->first);
+                       alarms_.erase(it);
+                       break;
+               }
+       }
 }
diff --git a/clock/src/Presenter/DeleteAlarmPresenter.cpp b/clock/src/Presenter/DeleteAlarmPresenter.cpp
new file mode 100644 (file)
index 0000000..7d55ec8
--- /dev/null
@@ -0,0 +1,44 @@
+#include "Presenter/DeleteAlarmPresenter.h"
+
+using namespace model;
+using namespace view;
+
+namespace presenter {
+DeleteAlarmPresenter::DeleteAlarmPresenter(DeleteAlarmView *view, AlarmProvider *model)
+       : view_(view), model_(model)
+{
+       view->RegisterCancelButtonClickedCallback(
+                       std::bind(&DeleteAlarmPresenter::OnCancelButtonClicked, this)
+                       );
+       view->RegisterDeleteButtonClickedCallback(
+                       std::bind(&DeleteAlarmPresenter::OnDeleteButtonClicked, this)
+                       );
+
+       std::vector<std::reference_wrapper<Alarm>> alarms = model_->GetAlarms();
+
+       for (auto a: alarms) {
+               int id = view_->ItemAppend(
+                               a.get().GetTime(),
+                               a.get().GetName().c_str(),
+                               a.get().GetWeekFlags(),
+                               a.get().IsActivated());
+               alarms_.insert(std::map<int, std::reference_wrapper<Alarm>>::value_type (id, std::reference_wrapper<Alarm>(a)));
+       }
+}
+
+void DeleteAlarmPresenter::OnDeleteButtonClicked()
+{
+       std::vector<int> deleted = view_->GetSelectedItems();
+
+       for (auto idx: deleted) {
+               model_->Remove(alarms_.find(idx)->second);
+       }
+       view_->PopPage();
+}
+
+void DeleteAlarmPresenter::OnCancelButtonClicked()
+{
+       view_->PopPage();
+}
+
+}
index d28c847..44cb84e 100644 (file)
@@ -1,6 +1,8 @@
 #include "Utils/EventBus.h"
 #include <algorithm>
 
+#include "log.h"
+
 using namespace utils;
 
 int EventBus::RegisterNewEventType()
@@ -37,6 +39,7 @@ void EventBus::DeregisterHandler(int type, std::function<void(Event*)> func)
 void EventBus::FireEvent(Event *event)
 {
        EventBus &bus = GetInstance();
+       DBG("Fire %d event", event->GetType());
        for (auto func: bus.callbacks_[event->GetType()]) {
                func(event);
        }
index 78e2409..fc920e9 100644 (file)
@@ -132,24 +132,24 @@ void AlarmView::Del(void *data, Evas_Object *obj)
 AlarmView::AlarmView()
 {
        /* Base Layout */
-       content = elm_layout_add(MainView::GetInstance().GetEvasObject());
-       evas_object_size_hint_weight_set(content, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
-       elm_layout_theme_set(content, "layout", "application", "default");
-       evas_object_show(content);
+       content_ = elm_layout_add(MainView::GetInstance().GetEvasObject());
+       evas_object_size_hint_weight_set(content_, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+       elm_layout_theme_set(content_, "layout", "application", "default");
+       evas_object_show(content_);
 
        /* Genlist */
-       genlist = elm_genlist_add(content);
-       elm_genlist_homogeneous_set(genlist, EINA_TRUE);
-       evas_object_size_hint_expand_set(genlist, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
-       evas_object_size_hint_align_set(genlist, EVAS_HINT_FILL, EVAS_HINT_FILL);
-       evas_object_smart_callback_add(genlist, "realized", AlarmView::ItemRealized, this);
-       evas_object_show(genlist);
+       genlist_ = elm_genlist_add(content_);
+       elm_genlist_homogeneous_set(genlist_, EINA_TRUE);
+       evas_object_size_hint_expand_set(genlist_, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+       evas_object_size_hint_align_set(genlist_, EVAS_HINT_FILL, EVAS_HINT_FILL);
+       evas_object_smart_callback_add(genlist_, "realized", AlarmView::ItemRealized, this);
+       evas_object_show(genlist_);
 
-       elm_object_content_set(content, genlist);
+       elm_object_content_set(content_, genlist_);
 
        /* Floating Button */
-       Evas_Object *fb = eext_floatingbutton_add(content);
-       elm_object_part_content_set(content, "elm.swallow.floatingbutton", fb);
+       Evas_Object *fb = eext_floatingbutton_add(content_);
+       elm_object_part_content_set(content_, "elm.swallow.floatingbutton", fb);
 
        /* Floating Button 1 */
        Evas_Object *btn = elm_button_add(fb);
@@ -161,11 +161,22 @@ AlarmView::AlarmView()
        elm_object_part_content_set(fb, "button1", btn);
 
        elm_theme_extension_add(NULL, Utils::GetAppResourcePath(Utils::APP_DIR_RESOURCE, "edje/alarm.edj"));
+
+        eext_object_event_callback_add(content_, EEXT_CALLBACK_MORE,
+                        AlarmView::MoreButtonClicked, this);
+}
+
+void AlarmView::MoreButtonClicked(void *data, Evas_Object *obj, void *info)
+{
+       AlarmView *view = static_cast<AlarmView*>(data);
+
+       DBG("More button clicked");
+       view->ShowDeletePopup();
 }
 
 void AlarmView::Clear()
 {
-       elm_genlist_clear(genlist);
+       elm_genlist_clear(genlist_);
 }
 
 int AlarmView::ItemAppend(Time time, const char *name, const  WeekFlags flags, bool active)
@@ -178,20 +189,20 @@ int AlarmView::ItemAppend(Time time, const char *name, const  WeekFlags flags, b
        data->active = active;
        data->time = time;
 
-       data->it = elm_genlist_item_append(genlist,
+       data->it = elm_genlist_item_append(genlist_,
                        &alarm_itc,
                        data,
                        NULL,
                        ELM_GENLIST_ITEM_NONE,
                        NULL, NULL);
 
-       return elm_genlist_item_index_get(data->it);
+       return (uintptr_t)data->it;
 }
 
 void AlarmView::ItemUpdate(int idx, Time time, const char *name,
                const WeekFlags flags, bool active)
 {
-       Elm_Object_Item *it = elm_genlist_nth_item_get(genlist, idx);
+       Elm_Object_Item *it = (Elm_Object_Item*)idx;
        if (!it) return;
 
        ItemData *data = static_cast<ItemData*>(elm_object_item_data_get(it));
@@ -207,32 +218,62 @@ void AlarmView::ItemUpdate(int idx, Time time, const char *name,
 
 void AlarmView::RemoveItem(int idx)
 {
-       //Elm_Object_Item *it = elm_genlist_item_nth_get(idx);
-       //if (it) elm_object_item_del(it);
+       Elm_Object_Item *it = (Elm_Object_Item*)idx;
+       if (it) elm_object_item_del(it);
 }
 
 void AlarmView::SetItemToggleCallback(ToggleCallback func)
 {
-       onToggled = std::move(func);
+       onToggled_ = std::move(func);
 }
 
 void AlarmView::SetItemSelectCallback(SelectCallback func)
 {
-       onSelected = std::move(func);
+       onSelected_ = std::move(func);
 }
 
 void AlarmView::SetButtonClickedCallback(ButtonClickedCallback func)
 {
-       onClicked = std::move(func);
+       onClicked_ = std::move(func);
 }
 
 Evas_Object *AlarmView::GetEvasObject()
 {
-       return content;
+       return content_;
 }
 
 void AlarmView::ButtonClicked(void *data, Evas_Object *obj, void *event_info)
 {
        AlarmView *view = static_cast<AlarmView*>(data);
-       if (view->onClicked) view->onClicked();
+       if (view->onClicked_) view->onClicked_();
+}
+
+void AlarmView::DismissPopupCallback(void *data, Evas_Object *obj, void *event_info)
+{
+       Evas_Object *popup = static_cast<Evas_Object*>(data);
+       evas_object_del(popup);
+}
+
+void AlarmView::PopupDeleteItemCallback(void *data, Evas_Object *obj, void *event_info)
+{
+       AlarmView *view = static_cast<AlarmView*>(data);
+       if (view->onDeleteClicked_) view->onDeleteClicked_();
+       evas_object_del(view->popup_);
+}
+
+void AlarmView::ShowDeletePopup()
+{
+       popup_ = elm_popup_add(elm_object_top_widget_get(content_));
+       elm_popup_align_set(popup_, ELM_NOTIFY_ALIGN_FILL, 1.0);
+       evas_object_size_hint_weight_set(popup_, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+       evas_object_smart_callback_add(popup_, "block,clicked", AlarmView::DismissPopupCallback, popup_);
+       eext_object_event_callback_add(popup_, EEXT_CALLBACK_BACK, AlarmView::DismissPopupCallback, popup_);
+
+       Evas_Object *list = elm_list_add(popup_);
+       elm_list_mode_set(list, ELM_LIST_EXPAND);
+       evas_object_show(list);
+
+       elm_list_item_append(list, "Delete", NULL, NULL, AlarmView::PopupDeleteItemCallback, this);
+       elm_object_content_set(popup_, list);
+       evas_object_show(popup_);
 }
diff --git a/clock/src/View/DeleteAlarmView.cpp b/clock/src/View/DeleteAlarmView.cpp
new file mode 100644 (file)
index 0000000..964db0c
--- /dev/null
@@ -0,0 +1,282 @@
+#include "View/DeleteAlarmView.h"
+#include "log.h"
+
+#include <sstream>
+
+using namespace model;
+using namespace utils;
+
+namespace view {
+
+struct ItemData {
+       DeleteAlarmView *instance;
+       char *name;
+       bool active;
+       bool selected;
+       WeekFlags flags;
+       Time time;
+       Elm_Object_Item *it;
+       Evas_Object *check;
+};
+
+static char *WeekFlag2FormattedString(WeekFlags flags)
+{
+       std::stringstream weekflags;
+
+       weekflags << (flags.IsOn(WeekDay::MONDAY) ? "M" : "<off>M</off>");
+       weekflags << (flags.IsOn(WeekDay::TUESDAY) ? "T" : "<off>T</off>");
+       weekflags << (flags.IsOn(WeekDay::WEDNESDAY) ? "W" : "<off>W</off>");
+       weekflags << (flags.IsOn(WeekDay::THURSDAY) ? "T" : "<off>T</off>");
+       weekflags << (flags.IsOn(WeekDay::FRIDAY) ? "F" : "<off>F</off>");
+       weekflags << (flags.IsOn(WeekDay::SATURDAY) ? "S" : "<off>S</off>");
+       weekflags << (flags.IsOn(WeekDay::SUNDAY) ? "S" : "<off>S</off>");
+
+       return strdup(weekflags.str().c_str());
+}
+
+static char *Time2FormattedString(const Time &time)
+{
+       std::stringstream formatted_time;
+
+       formatted_time << time.Format(FORMAT_12H);
+       formatted_time << " <meridiem>";
+       formatted_time << time.Meridiem();
+       formatted_time << "</meridiem>";
+
+       return strdup(formatted_time.str().c_str());
+}
+
+DeleteAlarmView::DeleteAlarmView()
+       : all_selected_(false)
+{
+       PushPage();
+}
+
+void DeleteAlarmView::ItemSelectToggle(void *data, Evas_Object *obj, void *event)
+{
+       ItemData *id = static_cast<ItemData*>(data);
+       id->selected = !id->selected;
+       if (!id->selected) {
+               id->instance->all_selected_ = false;
+               elm_check_state_set(id->instance->all_selected_check_, id->instance->all_selected_);
+       }
+       id->instance->UpdateTitle();
+}
+
+void DeleteAlarmView::ItemSelected(void *data, Evas_Object *obj, void *event)
+{
+       ItemData *id = static_cast<ItemData*>(data);
+       id->selected = !id->selected;
+       if (id->check) {
+               elm_check_state_set(id->check, id->selected);
+       }
+       if (!id->selected) {
+               id->instance->all_selected_ = false;
+               elm_check_state_set(id->instance->all_selected_check_, id->instance->all_selected_);
+       }
+       id->instance->UpdateTitle();
+       elm_genlist_item_selected_set(id->it, EINA_FALSE);
+}
+
+void DeleteAlarmView::CreateContent()
+{
+       elm_object_item_style_set(navi_item_, "basic");
+
+       // left toolbar button
+       left_btn_ = elm_button_add(GetNaviframe());
+       elm_object_text_set(left_btn_, "CANCEL");
+       elm_object_style_set(left_btn_, "naviframe/title_left");
+       evas_object_smart_callback_add(left_btn_, "clicked", OnCancelButtonClickedCb, this);
+       evas_object_show(left_btn_);
+
+       // right toolbar button
+       right_btn_ = elm_button_add(GetNaviframe());
+       elm_object_style_set(right_btn_, "naviframe/title_right");
+       elm_object_text_set(right_btn_, "DELETE");
+       evas_object_smart_callback_add(right_btn_, "clicked", OnDeleteButtonClickedCb, this);
+       evas_object_show(right_btn_);
+
+       // main scrollable content
+       content_ = elm_genlist_add(GetNaviframe());
+       evas_object_size_hint_expand_set(content_, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+       evas_object_size_hint_align_set(content_, EVAS_HINT_FILL, EVAS_HINT_FILL);
+       elm_genlist_mode_set(content_, ELM_LIST_COMPRESS);
+       elm_genlist_homogeneous_set(content_, EINA_TRUE);
+       evas_object_smart_callback_add(content_, "realized", DeleteAlarmView::ItemRealized, this);
+       evas_object_show(content_);
+
+       // fill created parts in object item
+       elm_object_item_part_text_set(navi_item_, "elm.text.title", "0 selected");
+       elm_object_item_part_content_set(navi_item_, "title_left_btn", left_btn_);
+       elm_object_item_part_content_set(navi_item_, "title_right_btn", right_btn_);
+       elm_object_item_content_set(navi_item_, content_);
+
+       CreateSelectAllItem();
+}
+
+void DeleteAlarmView::ItemSelectAllClicked(void *data, Evas_Object *obj, void *event)
+{
+       Elm_Object_Item *it = static_cast<Elm_Object_Item*>(event);
+       DeleteAlarmView *view = static_cast<DeleteAlarmView*>(data);
+
+       view->all_selected_ = !view->all_selected_;
+
+       view->SelectAllStateSet(view->all_selected_);
+       if (view->all_selected_check_)
+               elm_check_state_set(view->all_selected_check_, view->all_selected_);
+
+       view->UpdateTitle();
+       elm_genlist_item_selected_set(it, EINA_FALSE);
+}
+
+void DeleteAlarmView::CreateSelectAllItem()
+{
+       Elm_Genlist_Item_Class *itc = elm_genlist_item_class_new();
+       Elm_Genlist_Item *it;
+
+       itc->item_style = "select_all";
+       itc->func.text_get = [](void *data, Evas_Object *obj, const char *part) -> char* {
+               if (!strcmp(part, "elm.text")) {
+                       return strdup("Select all");
+               }
+               return nullptr;
+       };
+       itc->func.content_get = [](void *data, Evas_Object *obj, const char *part) -> Evas_Object* {
+               DeleteAlarmView *view = static_cast<DeleteAlarmView*>(data);
+               if (!strcmp(part, "sw.check")) {
+                       view->all_selected_check_ = elm_check_add(obj);
+                       elm_check_state_set(view->all_selected_check_, view->all_selected_);
+                       evas_object_show(view->all_selected_check_);
+                       return view->all_selected_check_;
+               }
+               return nullptr;
+       };
+       it = elm_genlist_item_append(content_, itc, this, NULL, ELM_GENLIST_ITEM_NONE,
+                       DeleteAlarmView::ItemSelectAllClicked, this);
+       elm_genlist_item_select_mode_set(it, ELM_OBJECT_SELECT_MODE_ALWAYS);
+
+       elm_genlist_item_class_unref(itc);
+}
+
+void DeleteAlarmView::ItemRealized(void *data, Evas_Object *obj, void *info)
+{
+       Elm_Object_Item *it = static_cast<Elm_Object_Item*>(info);
+       ItemData *id = static_cast<ItemData*>(elm_object_item_data_get(it));
+
+       // return if select all item
+       if (!id) return;
+
+       if (id->active)
+               elm_object_item_signal_emit(id->it, "alarm,state,enabled", "clock");
+       else
+               elm_object_item_signal_emit(id->it, "alarm,state,disabled", "clock");
+}
+
+void DeleteAlarmView::DestroyContent()
+{
+       evas_object_del(content_);
+       evas_object_del(left_btn_);
+       evas_object_del(right_btn_);
+}
+
+void DeleteAlarmView::OnCancelButtonClickedCb(void *data, Evas_Object *obj, void *event)
+{
+       DeleteAlarmView *view = static_cast<DeleteAlarmView*>(data);
+       if (view->onCancelButtonClicked_) view->onCancelButtonClicked_();
+}
+
+void DeleteAlarmView::OnDeleteButtonClickedCb(void *data, Evas_Object *obj, void *event)
+{
+       DeleteAlarmView *view = static_cast<DeleteAlarmView*>(data);
+       if (view->onDeleteButtonClicked_) view->onDeleteButtonClicked_();
+}
+
+int DeleteAlarmView::ItemAppend(utils::Time time, const char *name,
+       const model::WeekFlags flags, bool active)
+{
+       ItemData *data = new ItemData;
+       Elm_Genlist_Item_Class *itc;
+
+       data->instance = this;
+       data->name = name ? strdup(name) : nullptr;
+       data->flags = flags;
+       data->active = active;
+       data->time = time;
+       data->selected = false;
+
+       itc = elm_genlist_item_class_new();
+       itc->item_style = "alarm";
+       itc->func.content_get = [](void *data, Evas_Object *obj, const char *part) -> Evas_Object* {
+               ItemData *id = static_cast<ItemData*>(data);
+               if (!strcmp(part, "onoff")) {
+                       id->check = elm_check_add(obj);
+                       evas_object_propagate_events_set(id->check, EINA_FALSE);
+                       elm_check_state_set(id->check, id->selected ? EINA_TRUE : EINA_FALSE);
+                       evas_object_smart_callback_add(id->check, "changed", DeleteAlarmView::ItemSelectToggle, id);
+                       evas_object_show(id->check);
+                       return id->check;
+               }
+               return nullptr;
+       };
+       itc->func.text_get = [](void *data, Evas_Object *obj, const char *part) -> char* {
+               ItemData *id = static_cast<ItemData*>(data);
+               if (!strcmp(part, "name"))
+                       return strdup(id->name);
+               if (!strcmp(part, "time"))
+                       return Time2FormattedString(id->time);
+               if (!strcmp(part, "weekflags"))
+                       return WeekFlag2FormattedString(id->flags);
+               return NULL;
+       };
+       itc->func.del = [](void *data, Evas_Object *obj) {
+               ItemData *id = static_cast<ItemData*>(data);
+               delete id->name;
+               delete id;
+       };
+
+       data->it = elm_genlist_item_append(content_,
+                       itc,
+                       data,
+                       NULL,
+                       ELM_GENLIST_ITEM_NONE,
+                       DeleteAlarmView::ItemSelected, data);
+       elm_genlist_item_class_unref(itc);
+
+       return (uintptr_t)data->it;
+}
+
+std::vector<int> DeleteAlarmView::GetSelectedItems() const
+{
+       std::vector<int> selected_ids;
+       Elm_Object_Item *it = elm_genlist_nth_item_get(content_, 1);
+
+       while (it) {
+               ItemData *data = static_cast<ItemData*>(elm_object_item_data_get(it));
+               if (data->selected)
+                       selected_ids.push_back((uintptr_t)it);
+               it = elm_genlist_item_next_get(it);
+       }
+       return selected_ids;
+}
+
+void DeleteAlarmView::SelectAllStateSet(bool state)
+{
+       Elm_Object_Item *it = elm_genlist_nth_item_get(content_, 1);
+
+       while (it) {
+               ItemData *data = static_cast<ItemData*>(elm_object_item_data_get(it));
+               data->selected = state;
+               if (data->check) elm_check_state_set(data->check, data->selected);
+               it = elm_genlist_item_next_get(it);
+       }
+}
+
+void DeleteAlarmView::UpdateTitle()
+{
+       char buf[64];
+       std::vector<int> ids = GetSelectedItems();
+       snprintf(buf, sizeof(buf), "%d selected", ids.size());
+       elm_object_item_part_text_set(navi_item_, "elm.text.title", buf);
+}
+
+}