Add new Web API for updating period
authorYunchan Cho <yunchan.cho@samsung.com>
Thu, 21 Mar 2013 04:05:07 +0000 (13:05 +0900)
committerYunchan Cho <yunchan.cho@samsung.com>
Sun, 24 Mar 2013 12:45:28 +0000 (21:45 +0900)
- requested period = 0 : let the livebox's instance not be updated
- requested period > 0 : let the livebox's instance be update per requested period (MIN: 65.0)
- requested period < 0 : let the user select predefined period (1 hour, 3 hour, ..) on popup

[Issue#] N/A
[Problem] User can't change period of a livebox instance after creating it.
[Cause] There was no way for user to change its period
[Solution] Add new Web API for updating period, so that developer can provide update-period to user using it.

Change-Id: Ifca0847eac93b4ea06b197029be8736560815e2a

16 files changed:
src/Core/Box.cpp
src/Core/Box.h
src/Core/BoxManager.cpp
src/Core/BoxManager.h
src/Core/BoxSchemeHandler.cpp
src/Core/BoxSchemeHandler.h
src/Core/BoxUpdateTimer.cpp
src/Core/IBox.h
src/Core/Service/AppControl.h
src/Core/Service/CMakeLists.txt
src/Core/Service/PeriodChanger.cpp [new file with mode: 0644]
src/Core/Service/PeriodChanger.h [new file with mode: 0644]
src/Core/View/InjectedScript.h
src/Daemon/BoxDaemonImpl.cpp
src/Daemon/BoxDaemonImpl.h
src/Plugin/box_plugin_interface.h

index ad9b24c..1f62aa5 100644 (file)
@@ -207,13 +207,27 @@ bool Box::closePd()
     return true;
 }
 
-void Box::update()
+bool Box::update()
 {
     LogD("enter");
 
+    // reload box
     m_boxBuffer->startCanvasUpdate();
     RenderInfoPtr renderInfo = makeRenderInfo(renderTypeUpdate);
     m_view->showBox(renderInfo);
+
+    return true;
+}
+
+bool Box::changePeriod(float period)
+{
+    LogD("enter");
+
+    // reset period
+    m_boxInfo->period = period;
+    m_updateTimer->setPeriod(m_boxInfo->period);
+
+    return true;
 }
 
 RenderInfoPtr Box::makeRenderInfo(const std::string& renderType) const
index 9622351..83ac101 100644 (file)
@@ -49,7 +49,8 @@ class Box: public IBox, public IBoxContext {
         bool pause();
         bool openPd(int width, int height);
         bool closePd();
-        void update();
+        bool update();
+        bool changePeriod(float period);
         ~Box();
 
     private:
@@ -74,6 +75,8 @@ class Box: public IBox, public IBoxContext {
         IRenderViewPtr m_view;
         ITimerPtr m_updateTimer;
         //IBoxStatePtr m_state;
+
+        friend class BoxSchemeHandler;
 };
 
 #endif //BOX_H
index e607cc2..047ff7a 100644 (file)
@@ -70,6 +70,9 @@ bool BoxManager::doCommand(const request_cmd_type type, const BoxInfoPtr& boxInf
     case REQUEST_CMD_CLOSE_PD:
         result = requestClosePd(boxInfo->instanceId);
         break;
+    case REQUEST_CMD_CHANGE_PERIOD:
+        result = requestChangePeriod(boxInfo->instanceId, boxInfo->period);
+        break;
     default:
         LogD("not available request type");
         break;
@@ -176,6 +179,7 @@ bool BoxManager::requestPauseAll()
 
 bool BoxManager::requestOpenPd(std::string& instanceId, int width, int height)
 {
+    LogD("enter");
     IBoxPtr box = searchBoxMap(instanceId);
     if (!box) {
         return false;
@@ -186,6 +190,7 @@ bool BoxManager::requestOpenPd(std::string& instanceId, int width, int height)
 
 bool BoxManager::requestClosePd(std::string& instanceId)
 {
+    LogD("enter");
     IBoxPtr box = searchBoxMap(instanceId);
     if (!box) {
         return false;
@@ -194,6 +199,17 @@ bool BoxManager::requestClosePd(std::string& instanceId)
     return box->closePd();
 }
 
+bool BoxManager::requestChangePeriod(std::string& instanceId, float period)
+{
+    LogD("enter");
+    IBoxPtr box = searchBoxMap(instanceId);
+    if (!box) {
+        return false;
+    }
+
+    return box->changePeriod(period);
+}
+
 void BoxManager::insertBoxMap(std::string& instanceId, IBoxPtr box)
 {
     if (!searchBoxMap(instanceId)) {
index 7a1f25a..daa34b0 100644 (file)
@@ -50,6 +50,7 @@ class EXPORT_CLASS BoxManager: public IBoxManager {
         virtual bool requestPauseAll();
         virtual bool requestOpenPd(std::string& instanceId, int width, int height);
         virtual bool requestClosePd(std::string& instanceId);
+        virtual bool requestChangePeriod(std::string& instanceId, float period);
         // ewk context deleter 
         struct EwkContextDeleter {
             void operator()(Ewk_Context* ptr);
index f614c5a..56341d2 100644 (file)
@@ -21,6 +21,7 @@
 #include <string.h>
 #include "Box.h"
 #include "Service/AppControl.h"
+#include "Service/PeriodChanger.h"
 #include "Util/Log.h"
 #include "BoxSchemeHandler.h"
 
@@ -86,8 +87,18 @@ bool BoxSchemeHandler::process(std::string& instanceId, std::string& uri)
        return handleReload(instanceId);
     }
 
-    if (!uri.compare(BOX_SCHEME_CHANGE_PERIOD)) {
-       return handleChangePeriod(instanceId);
+    if (!uri.compare(
+                0,
+                BOX_SCHEME_CHANGE_PERIOD.size(),
+                BOX_SCHEME_CHANGE_PERIOD)) 
+    {
+        std::string key("period");
+        std::string period = parse(uri, key);
+        if (period.empty()) {
+            return handleChangePeriod(instanceId);
+        }
+
+        return handleChangePeriod(instanceId, std::atof(period.c_str()));
     }
 
     if (!uri.compare(
@@ -140,11 +151,22 @@ bool BoxSchemeHandler::handleReload(std::string& instanceId)
     return true;
 }
 
-bool BoxSchemeHandler::handleChangePeriod(std::string& instanceId)
+bool BoxSchemeHandler::handleChangePeriod(std::string& instanceId, float requestedPeriod)
 {
     LogD("enter");
-    // TODO show special efl window for this
-    return true;
+
+    Box* box = getBox(instanceId);
+    if (!box) {
+        LogD("no box for update period");
+        return false;
+    }
+
+    m_periodChanger =
+        Service::PeriodChanger::create(
+            box->m_boxInfo->boxId, instanceId,
+            box->m_boxInfo->period, requestedPeriod);
+
+    return m_periodChanger->change();
 }
 
 bool BoxSchemeHandler::handleLaunchBrowser(std::string& instanceId, std::string& url)
index ba96241..929abcd 100644 (file)
 
 class Box;
 
+namespace Service {
+class PeriodChanger;
+}
+
 #define EXPORT_CLASS __attribute__ ((visibility("default"))
 
 class EXPORT_CLASS BoxSchemeHandler {
@@ -38,7 +42,7 @@ class EXPORT_CLASS BoxSchemeHandler {
     private:
         Box* getBox(std::string& instanceId);
         bool handleReload(std::string& instanceId);
-        bool handleChangePeriod(std::string& instanceId);
+        bool handleChangePeriod(std::string& instanceId, float requestedPeriod = -1.0f);
         bool handleLaunchBrowser(std::string& instanceId, std::string& url);
         std::string parse(std::string& uri, std::string& key);
 
@@ -49,6 +53,8 @@ class EXPORT_CLASS BoxSchemeHandler {
         typedef std::map<std::string, Box*> BoxMap;
         typedef std::pair<std::string, Box*> BoxMapPair;
         BoxMap m_boxMap;
+        // members for service
+        std::shared_ptr<Service::PeriodChanger> m_periodChanger;
         static BoxSchemeHandler* s_instance;
 };
 
index ac69c3d..44040de 100644 (file)
@@ -64,4 +64,5 @@ void BoxUpdateTimer::restart()
 void BoxUpdateTimer::setPeriod(float period)
 {
     m_period = period;
+    restart();
 }
index c78b202..2746181 100644 (file)
@@ -32,6 +32,8 @@ class IBox {
         virtual bool pause() = 0;
         virtual bool openPd(int width, int height) = 0;
         virtual bool closePd() = 0;
+        virtual bool update() = 0;
+        virtual bool changePeriod(float period) = 0;
 
         //virtual IBox& operator=(const IBox& rhs) = 0;
         //virtual bool operator==(const IBox& rhs) const = 0;
index 1ff1afb..8b134f5 100644 (file)
@@ -14,7 +14,7 @@
  *    limitations under the License.
  */
 /**
- * @file    LaunchBrowser.h
+ * @file    AppControl.h
  * @author  Yunchan Cho (yunchan.cho@samsung.com)
  */
 
index 10df514..e1737b1 100644 (file)
@@ -20,12 +20,17 @@ SET(DEPS ${TARGET_NAME}_DEPS)
 PKG_CHECK_MODULES(${DEPS}
     dlog
     capi-appfw-application
+    livebox-service
+    evas
+    ecore-x
+    elementary
     REQUIRED
 )
 ADD_DEFINITIONS(${${DEPS}_CFLAGS})
 
 SET(SRCS
     ${CMAKE_CURRENT_SOURCE_DIR}/AppControl.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/PeriodChanger.cpp
 )
 
 SET(HEADERS
diff --git a/src/Core/Service/PeriodChanger.cpp b/src/Core/Service/PeriodChanger.cpp
new file mode 100644 (file)
index 0000000..d7119df
--- /dev/null
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 2013 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.
+ */
+/**
+ * @file    PeriodChanger.cpp
+ * @author  Yunchan Cho (yunchan.cho@samsung.com)
+ */
+
+#include <string>
+#include <Evas.h>
+#include <Ecore_X.h>
+#include <Elementary.h>
+#include <livebox-service.h>
+#include <Core/Util/Log.h>
+#include "PeriodChanger.h"
+
+#define UPDATE_PERIOD_MIN   60.0
+
+namespace Service {
+
+Evas_Object* PeriodChanger::s_window = NULL;
+
+PeriodChanger::PeriodChanger(
+        std::string& boxId, std::string& instanceId,
+        float currentPeriod, float requestedPeriod)
+    : m_boxId(boxId)
+    , m_instanceId(instanceId)
+    , m_currentPeriod(currentPeriod)
+    , m_requestedPeriod(requestedPeriod)
+    , m_1hour()
+    , m_3hour()
+    , m_6hour()
+    , m_12hour()
+    , m_noUpdate()
+{
+    LogD("enter");
+}
+
+PeriodChanger::~PeriodChanger()
+{
+    LogD("enter");
+}
+
+bool PeriodChanger::change()
+{
+    LogD("enter");
+
+    if (m_requestedPeriod < 0) {
+        showPeriodPopup();
+        return true;
+    }
+
+    float newPeriod;
+    if (m_requestedPeriod == 0) {
+        newPeriod = 0.0;
+    } else if (m_requestedPeriod > 0) {
+        if (m_requestedPeriod > UPDATE_PERIOD_MIN) {
+            newPeriod = m_requestedPeriod;
+        } else {
+            newPeriod = UPDATE_PERIOD_MIN;
+        }
+    } else {
+        LogD("negative value can't be handled here");
+        newPeriod = 0.0;
+    }
+
+    // after selecting one among period list, the following should be executed
+    return requestToPlatform(newPeriod);
+}
+
+void PeriodChanger::showPeriodPopup()
+{
+    LogD("enter");
+
+    Evas_Object* window = createWindow();
+    Evas_Object* periodList = elm_list_add(window);
+    if (!periodList) {
+        LogD("failed to add elm_list_add");
+    }
+    elm_list_mode_set(periodList, ELM_LIST_EXPAND);
+
+    setPopupListData();
+    // TODO Language ID should be used, not static string
+    elm_list_item_append(periodList, "1 hour", NULL, NULL, selectPeriodCallback, &m_1hour);
+    elm_list_item_append(periodList, "3 hour", NULL, NULL, selectPeriodCallback, &m_3hour);
+    elm_list_item_append(periodList, "6 hour", NULL, NULL, selectPeriodCallback, &m_6hour);
+    elm_list_item_append(periodList, "12 hour", NULL, NULL, selectPeriodCallback, &m_12hour);
+    elm_list_item_append(periodList, "Never", NULL, NULL, selectPeriodCallback, &m_noUpdate);
+
+    // create popup
+    Evas_Object *popup = elm_popup_add(window);
+    if (!popup) {
+        LogD("failed to add elm_popup_add");
+        return;
+    }
+    elm_object_style_set(popup, "min_menustyle");
+    evas_object_size_hint_weight_set(popup, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+    elm_object_part_text_set(popup, "title,text", "Update Period");
+    elm_object_content_set(popup, periodList);
+    evas_object_show(popup);
+    Evas_Object* cancelButton = elm_button_add(popup);
+    if (!cancelButton) {
+        LogD("failed to add elm_button_add");
+        return;
+    }
+    // TODO Language ID should be used, not static string
+    elm_object_text_set(cancelButton, "Cancel");
+    elm_object_style_set(cancelButton, "popup_button/default");
+    elm_object_part_content_set(popup, "button1", cancelButton);
+    evas_object_show(cancelButton);
+    evas_object_smart_callback_add(cancelButton, "clicked", cancelButtonCallback, this);
+}
+
+void PeriodChanger::destroyPeriodPopup(Evas_Object *obj)
+{
+    LogD("enter");
+    Evas_Object* parent = elm_object_parent_widget_get(obj);
+    Evas_Object* popup = elm_popup_add(parent);
+    while (parent) {
+        const char* type = elm_object_widget_type_get(parent);
+        if (type && !strcmp(type, elm_object_widget_type_get(popup))) {
+            evas_object_del(parent);
+            break;
+        }
+        parent = elm_object_parent_widget_get(parent);
+    }
+    evas_object_del(popup);
+    destroyWindow();
+}
+
+void PeriodChanger::setPopupListData()
+{
+    LogD("enter");
+
+    m_1hour.periodChanger = this;
+    m_1hour.newPeriod = 1.0 * 60.0 * 60.0;
+
+    m_3hour.periodChanger = this;
+    m_3hour.newPeriod = 3.0 * 60.0 * 60.0;
+
+    m_6hour.periodChanger = this;
+    m_6hour.newPeriod = 6.0 * 60.0 * 60.0;
+
+    m_12hour.periodChanger = this;
+    m_12hour.newPeriod = 12.0 * 60.0 * 60.0;
+
+    m_noUpdate.periodChanger = this;
+    m_noUpdate.newPeriod = 0.0;
+}
+
+bool PeriodChanger::requestToPlatform(float newPeriod)
+{
+    int ret = livebox_service_change_period(
+                m_boxId.c_str(), m_instanceId.c_str(), newPeriod);
+
+    if (ret < 0) {
+        LogD("during update period, error occurs");
+        return false;
+    }
+
+    LogD("Instance's period is set to %f", newPeriod);
+    return true;
+}
+
+
+Evas_Object* PeriodChanger::createWindow()
+{
+    LogD("enter");
+
+    if (s_window) {
+        evas_object_show(s_window);
+        elm_win_raise(s_window);
+        return s_window;
+    }
+
+    s_window = elm_win_add(NULL, "web-provider-popup", ELM_WIN_BASIC);
+    elm_win_alpha_set(s_window, EINA_TRUE);
+    elm_win_title_set(s_window, "change update period");
+    elm_win_borderless_set(s_window, EINA_TRUE);
+
+    int width = 0;
+    int height = 0;
+    ecore_x_window_size_get(ecore_x_window_root_first_get(), &width, &height);
+    evas_object_resize(s_window, width, height);
+    elm_win_indicator_mode_set(s_window, ELM_WIN_INDICATOR_SHOW);
+
+    evas_object_color_set(s_window, 255, 255, 255, 0);
+    evas_object_show(s_window);
+    return s_window;
+}
+
+void PeriodChanger::destroyWindow()
+{
+    LogD("enter");
+
+    if (!s_window) {
+        return;
+    }
+    evas_object_hide(s_window);
+    elm_win_lower(s_window);
+}
+
+void PeriodChanger::selectPeriodCallback(void *data, Evas_Object *obj, void *event_info)
+{
+    LogD("enter");
+    PopupListData* popupData = static_cast<PopupListData*>(data);
+
+    LogD("Update period is set to %f", popupData->newPeriod);
+    popupData->periodChanger->requestToPlatform(popupData->newPeriod);
+    popupData->periodChanger->destroyPeriodPopup(obj);
+}
+
+void PeriodChanger::cancelButtonCallback(void *data, Evas_Object *obj, void *event_info)
+{
+    LogD("enter");
+    PeriodChanger* This = static_cast<PeriodChanger*>(data);
+    This->destroyPeriodPopup(obj);
+}
+
+} // Service
diff --git a/src/Core/Service/PeriodChanger.h b/src/Core/Service/PeriodChanger.h
new file mode 100644 (file)
index 0000000..21cdd71
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2013 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.
+ */
+/**
+ * @file    PeriodChanger.h
+ * @author  Yunchan Cho (yunchan.cho@samsung.com)
+ */
+#ifndef PERIOD_CHNAGER_H
+#define PERIOD_CHNAGER_H
+
+#include <string>
+#include <memory>
+
+struct _Evas_Object;
+typedef _Evas_Object Evas_Object;
+
+namespace Service {
+class PeriodChanger;
+typedef std::shared_ptr<PeriodChanger> PeriodChangerPtr;
+
+class PeriodChanger {
+    public:
+        static PeriodChangerPtr create(
+                std::string& boxId, std::string& instanceId,
+                float currentPeriod, float requestedPeriod)
+        {
+            return PeriodChangerPtr(
+                    new PeriodChanger(boxId, instanceId, currentPeriod, requestedPeriod));
+        }
+        bool change();
+        ~PeriodChanger();
+
+    private:
+        void showPeriodPopup();
+        void destroyPeriodPopup(Evas_Object *obj);
+        void setPopupListData();
+        bool requestToPlatform(float newPeriod);
+        static Evas_Object* createWindow();
+        static void destroyWindow();
+
+        static void selectPeriodCallback(void *data, Evas_Object *obj, void *event_info);
+        static void cancelButtonCallback(void *data, Evas_Object *obj, void *event_info);
+
+        PeriodChanger(
+                std::string& boxId, std::string& instanceId,
+                float currentPeriod, float requestedPeriod);
+
+        static Evas_Object* s_window;
+        std::string m_boxId;
+        std::string m_instanceId;
+        float m_currentPeriod;
+        float m_requestedPeriod;
+
+        struct PopupListData {
+            PeriodChanger* periodChanger;
+            float newPeriod;
+        };
+
+        PopupListData m_1hour;
+        PopupListData m_3hour;
+        PopupListData m_6hour;
+        PopupListData m_12hour;
+        PopupListData m_noUpdate;
+};
+} // Service
+
+#endif // PERIOD_CHNAGER_H
index 85ff722..267e411 100644 (file)
        function reload() {                                                  \
            window.location.href=\"box://reload\";                           \
        }                                                                    \
-       function changePeriod() {                                            \
-           window.location.href=\"box://change-period\";                    \
+       function changePeriod(period) {                                      \
+           switch (arguments.length) {                                      \
+               case 0:                                                      \
+                    window.location.href=\"box://change-period\";           \
+                    break;                                                  \
+               case 1:                                                      \
+                    window.location.href=\"box://change-period?period=\" + period;                    \
+                    break;                                                  \
+                default:                                                    \
+                    window.location.href=\"box://change-period\";           \
+                    break;                                                  \
+           }                                                                \
        }                                                                    \
        function launchBrowser(url) {                                        \
            window.location.href=\"box://launch-browser?url=\" + url;        \
index 4424292..fd56cc2 100644 (file)
@@ -367,6 +367,28 @@ int BoxDaemonImpl::updateContentCallback(ProviderEventArgPtr arg, void* data)
     return 0;
 }
 
+int BoxDaemonImpl::changePeriodCallback(ProviderEventArgPtr arg, void* data)
+{
+    LogD("enter");
+    BoxDaemonImpl* This = static_cast<BoxDaemonImpl*>(data);
+    BoxInfoPtr info = This->initializeBoxInfo(arg);
+    if (!info) {
+        return -1;
+    }
+    info->period = arg->info.set_period.period;
+
+    LogD("--------------------------------------------");
+    LogD("boxId: %s", info->boxId.c_str());
+    LogD("InstanceId: %s", info->instanceId.c_str());
+    LogD("period: %f", info->period);
+    LogD("--------------------------------------------");
+
+    JobInfo* jobInfo = new JobInfo(REQUEST_CMD_CHANGE_PERIOD, info, This);
+    Ecore_Job* ret = ecore_job_add(requestBoxJobCallback, jobInfo);
+
+    return ret ? 0 : -1;
+}
+
 void BoxDaemonImpl::setProviderCallbacks(ProviderCallbacks& callbacks)
 {
     LogD("enter");
@@ -386,6 +408,7 @@ void BoxDaemonImpl::setProviderCallbacks(ProviderCallbacks& callbacks)
     callbacks.clicked = BoxDaemonImpl::clickedCallback;
     callbacks.resize = BoxDaemonImpl::resizeCallback;
     callbacks.update_content = BoxDaemonImpl::updateContentCallback;
+    callbacks.set_period = BoxDaemonImpl::changePeriodCallback;
 }
 
 const char* BoxDaemonImpl::getBoxType(const char* boxId)
index 77dbf24..bd1fe58 100644 (file)
@@ -66,6 +66,7 @@ class BoxDaemonImpl {
         static int pauseCallback(ProviderEventArgPtr arg, void* data);
         static int resumeCallback(ProviderEventArgPtr arg, void* data);
         static int updateContentCallback(ProviderEventArgPtr arg, void* data);
+        static int changePeriodCallback(ProviderEventArgPtr arg, void* data);
 
         // common private functions
         void setProviderCallbacks(ProviderCallbacks& callbacks);
index dfb6af8..20184b1 100644 (file)
@@ -43,6 +43,7 @@ typedef enum {
     REQUEST_CMD_PAUSE_BOX,
     REQUEST_CMD_RESUME_ALL,
     REQUEST_CMD_PAUSE_ALL,
+    REQUEST_CMD_CHANGE_PERIOD,
 } request_cmd_type;
 
 // definition of interface function type