TizenRefApp-8607 [Gallery] Implement autohighlighting feature while 78/132378/2
authorIgor Nazarov <i.nazarov@samsung.com>
Fri, 2 Jun 2017 17:44:03 +0000 (20:44 +0300)
committerIgor Nazarov <i.nazarov@samsung.com>
Tue, 6 Jun 2017 09:23:42 +0000 (12:23 +0300)
scrolling in ScreenReader mode

- Implemented autohighlighting in ImageGrid while scrolling;
- UCL: added Timeout class;
- UCL: smartDelegateion moved from "misc" to "util".

Change-Id: Ib97b1bcc663b2f125e4d8a6cd0eb5f6b7eaed043

20 files changed:
edc/layouts.edc
inc/types.h
inc/view/ImageGrid.h
src/view/ImageGrid.cpp
src/view/common.h
ucl/inc/ucl/gui/types.h
ucl/inc/ucl/misc/Timeout.h [new file with mode: 0644]
ucl/inc/ucl/misc/smartDelegation.h [deleted file]
ucl/inc/ucl/misc/smartDelegation/WeakDelegate.h [deleted file]
ucl/inc/ucl/misc/smartDelegation/WeakDelegate.hpp [deleted file]
ucl/inc/ucl/misc/smartDelegation/macro.h [deleted file]
ucl/inc/ucl/misc/smartDelegation/shortMacro.h [deleted file]
ucl/inc/ucl/util/smartDelegation.h [new file with mode: 0644]
ucl/inc/ucl/util/smartDelegation/WeakDelegate.h [new file with mode: 0644]
ucl/inc/ucl/util/smartDelegation/WeakDelegate.hpp [new file with mode: 0644]
ucl/inc/ucl/util/smartDelegation/macro.h [new file with mode: 0644]
ucl/inc/ucl/util/smartDelegation/shortMacro.h [new file with mode: 0644]
ucl/inc/ucl/util/types/classTypes.h
ucl/src/common.h
ucl/src/misc/Timeout.cpp [new file with mode: 0644]

index 20dc42c5b7bf280897a2557d3c25c19cd6fca4aa..65211b84afb9a549e0487b40d80158165b1bef6c 100644 (file)
  * limitations under the License.
  */
 
+group { "elm/layout/gallery/fake_access_object";
+   data.item: "access_highlight" "on";
+}
+
 group { "elm/layout/gallery/more_options";
    parts {
       swallow { "elm.swallow.content";
index 898385508f91cb354ccf3bd945f7688ff478997e..9a1476e6583c19d4ac453022a14481449bf460fd 100644 (file)
@@ -22,8 +22,7 @@
 #include "ucl/util/types.h"
 #include "ucl/util/memory.h"
 #include "ucl/util/delegation.h"
-
-#include "ucl/misc/smartDelegation.h"
+#include "ucl/util/smartDelegation.h"
 
 namespace gallery {
 
index 399201b15e0ae7304e994c8e87978e2dd7a3a087..540cafa8e819b0839d2cb8c49c8864f3767d9fea 100644 (file)
 
 #include <deque>
 
+#include "ucl/gui/Layout.h"
 #include "ucl/gui/StyledWidget.h"
 
+#include "ucl/misc/Timeout.h"
+
 #include "types.h"
 
 namespace gallery {
@@ -129,12 +132,28 @@ namespace gallery {
                template <class SHOW_FUNC>
                ucl::Result showItem(int itemIndex, SHOW_FUNC &&showFunc);
 
+               bool isItemFullyVisible(int itemIndex);
+               bool isItemFullyVisible(int itemIndex,
+                               int &minVisibleOffset, int &maxVisibleOffset) const;
+               bool isItemFullyVisible(int slotIndex, int itemOffset,
+                               int &minVisibleOffset, int &maxVisibleOffset) const;
+
                void forceBoxSizeCalculate();
 
                void addUnrealizeLock();
                void removeUnrealizeLock();
 
                void handleItemEvent(int itemIndex, int event, int x, int y) const;
+
+               // Accessibility
+
+               void onItemHighlighted(int itemIndex);
+               void onItemUnhighlighted(int itemIndex);
+               void onKeeperUnhighlighted(Widget &sender, void *eventInfo);
+
+               void updateHighlightTimeout();
+               void onHighlightTimeout(ucl::Timeout *sender);
+
                Elm_Interface_Atspi_Accessible *requestAtspi(int itemIndex);
                Elm_Interface_Atspi_Accessible *getItemAtspi(int itemIndex);
 
@@ -150,6 +169,7 @@ namespace gallery {
                // Initialization
                void prepare();
                void createCircleScroller();
+               void createHighlighKeeper();
 
                // Actual slots count
                bool updateSlotCount();
@@ -243,6 +263,11 @@ namespace gallery {
                int m_scrollLockIndex;
                bool m_isInSelectMode;
                bool m_isRotaryActive;
+
+               ucl::LayoutSRef m_highlighKeeper;
+               ucl::TimeoutSRef m_highlightTimeout;
+               int m_highlightID;
+               bool m_isHighlightLocked;
        };
 }
 
index 6c8e14cf2ba7def927660f3e48971c577c77d307..278a745926e1ed9e49249e79693d5999f8db07a1 100644 (file)
@@ -20,6 +20,7 @@
 #include <vector>
 
 #include "ucl/gui/Layout.h"
+#include "ucl/gui/Window.h"
 
 #include "view/IImageGridListener.h"
 #include "view/TouchParser.h"
@@ -53,7 +54,11 @@ namespace gallery { namespace { namespace impl {
        constexpr EdjeSignal BTN_UNBLOCK_CLICKS {"gallery,unblock,clicks"};
 
        // Other //
+       constexpr LayoutTheme LAYOUT_FAKE_ACCESS_OBJECT
+                       {"layout", "gallery", "fake_access_object"};
+
        constexpr auto HCOMB_SCROLL_LIMIT = 1000;
+       constexpr auto SCROLL_HIGHLIGHT_TIMEOUT_SEC = 0.1;
 
        bool getImageSize(const Widget &image, int &w, int &h)
        {
@@ -145,6 +150,11 @@ namespace gallery {
                        return 0;
                }
 
+               virtual int getHighlightScanRange() const
+               {
+                       return 1;
+               }
+
                Info(const std::array<LayoutTheme, 2> &slotThemes,
                                const std::array<int, 2> &slotLens,
                                const ElmStyle btnStyle,
@@ -158,6 +168,8 @@ namespace gallery {
                        isHorizontal(isHorizontal)
                {
                }
+
+               virtual ~Info() = default;
        };
 
        // ImageGrid::HcombInfo //
@@ -192,6 +204,11 @@ namespace gallery {
                        return slotSize;
                }
 
+               virtual int getHighlightScanRange() const final override
+               {
+                       return totalLength;
+               }
+
                HcombInfo(const int totalLength,
                                const std::array<LayoutTheme, 2> &slotThemes,
                                const ElmStyle btnStyle) :
@@ -257,6 +274,10 @@ namespace gallery {
 
                                m_btn.addEventHandler(BTN_CLICKED, WEAK_DELEGATE(
                                                Item::onClicked, asWeak(*this)));
+                               m_btn.addEventHandler(ATSPI_HIGHLIGHTED, WEAK_DELEGATE(
+                                               Item::onHighlighted, asWeak(*this)));
+                               m_btn.addEventHandler(ATSPI_UNHIGHLIGHTED, WEAK_DELEGATE(
+                                               Item::onUnhighlighted, asWeak(*this)));
 
                                elm_atspi_accessible_gesture_cb_set(m_btn,
                                                CALLBACK_A(Item::onAtspiGesture), this);
@@ -329,6 +350,11 @@ namespace gallery {
                                        return;
                                }
 
+                               if (m_isHighlighted && m_imageGrid.m_highlightTimeout) {
+                                       m_imageGrid.m_isHighlightLocked = true;
+                                       elm_atspi_component_highlight_clear(m_btn);
+                               }
+
                                const int itemIndex = m_realizeIndex;
                                m_realizeIndex = -1;
 
@@ -496,32 +522,59 @@ namespace gallery {
 
                        void onClicked(Widget &widget, void *eventInfo)
                        {
-                               if (isRealized()) {
-                                       m_imageGrid.handleItemEvent(m_realizeIndex,
-                                                       ITEM_EVENT_CLICK, -1, -1);
+                               if (!isRealized()) {
+                                       LOG_RETURN_VOID(RES_ILLEGAL_STATE, "Item is not realized!");
                                }
+                               m_imageGrid.handleItemEvent(m_realizeIndex,
+                                               ITEM_EVENT_CLICK, -1, -1);
                        }
 
                        void onDoubleTap(const int x, const int y)
                        {
-                               if (isRealized()) {
-                                       m_imageGrid.handleItemEvent(m_realizeIndex,
-                                                       ITEM_EVENT_DOUBLE_TAP, x, y);
+                               if (!isRealized()) {
+                                       LOG_RETURN_VOID(RES_ILLEGAL_STATE, "Item is not realized!");
                                }
+                               m_imageGrid.handleItemEvent(m_realizeIndex,
+                                               ITEM_EVENT_DOUBLE_TAP, x, y);
                        }
 
                        void onTapAndHold(const int x, const int y)
                        {
-                               if (isRealized()) {
-                                       m_imageGrid.handleItemEvent(m_realizeIndex,
-                                                       ITEM_EVENT_TAP_AND_HOLD, x, y);
+                               if (!isRealized()) {
+                                       LOG_RETURN_VOID(RES_ILLEGAL_STATE, "Item is not realized!");
+                               }
+                               m_imageGrid.handleItemEvent(m_realizeIndex,
+                                               ITEM_EVENT_TAP_AND_HOLD, x, y);
+                       }
+
+                       void onHighlighted(Widget &widget, void *eventInfo)
+                       {
+                               if (m_isHighlighted) {
+                                       return;
+                               }
+                               m_isHighlighted = true;
+                               if (!isRealized()) {
+                                       LOG_RETURN_VOID(RES_ILLEGAL_STATE, "Item is not realized!");
+                               }
+                               m_imageGrid.onItemHighlighted(m_realizeIndex);
+                       }
+
+                       void onUnhighlighted(Widget &widget, void *eventInfo)
+                       {
+                               if (!m_isHighlighted) {
+                                       return;
+                               }
+                               m_isHighlighted = false;
+                               if (!isRealized()) {
+                                       LOG_RETURN_VOID(RES_ILLEGAL_STATE, "Item is not realized!");
                                }
+                               m_imageGrid.onItemUnhighlighted(m_realizeIndex);
                        }
 
                        Eina_Bool onAtspiGesture(Elm_Atspi_Gesture_Info gestureInfo,
                                        Evas_Object *obj)
                        {
-                               if (m_realizeIndex == -1) {
+                               if (!isRealized()) {
                                        LOG_RETURN_VALUE(RES_ILLEGAL_STATE, EINA_FALSE,
                                                        "Item is not realized!");
                                }
@@ -565,6 +618,7 @@ namespace gallery {
                        bool m_isImageLoaded = false;
                        bool m_isClicksBlocked = false;
                        bool m_isSelected = false;
+                       bool m_isHighlighted = false;
                };
 
        public:
@@ -736,7 +790,10 @@ namespace gallery {
                m_animator(nullptr),
                m_scrollLockIndex(0),
                m_isInSelectMode(selectModeStartup),
-               m_isRotaryActive(false)
+               m_isRotaryActive(false),
+
+               m_highlightID(-1),
+               m_isHighlightLocked(false)
        {
                prepare();
 
@@ -809,6 +866,8 @@ namespace gallery {
 
                createCircleScroller();
 
+               createHighlighKeeper();
+
                m_scroller->addEventHandler(WidgetEvent::RESIZE,
                                WEAK_DELEGATE(ImageGrid::onScrollerResize, asWeak(*this)));
 
@@ -841,6 +900,30 @@ namespace gallery {
                }
        }
 
+       void ImageGrid::createHighlighKeeper()
+       {
+               m_highlighKeeper = Layout::Builder().
+                               setTheme(impl::LAYOUT_FAKE_ACCESS_OBJECT).
+                               setIsOwner(true).
+                               build(*m_box.getWindow());
+               UCL_ASSERT(m_highlighKeeper, "m_highlighKeeper is NULL");
+
+               m_highlighKeeper->setGeometry(0, 0, 1, 1);
+               show(*m_highlighKeeper);
+
+               elm_atspi_accessible_reading_info_type_set(*m_highlighKeeper, 0);
+
+               elm_atspi_accessible_gesture_cb_set(*m_highlighKeeper,
+                       [](void *, Elm_Atspi_Gesture_Info, Evas_Object *) -> Eina_Bool
+                       {
+                               return EINA_TRUE;
+                       },
+                       nullptr);
+
+               m_highlighKeeper->addEventHandler(ATSPI_UNHIGHLIGHTED,
+                               WEAK_DELEGATE(ImageGrid::onKeeperUnhighlighted, asWeak(*this)));
+       }
+
        void ImageGrid::setListener(IImageGridListener *const listener)
        {
                m_listener = listener;
@@ -1117,19 +1200,15 @@ namespace gallery {
                return doWithCell(itemIndex,
                        [this, &showFunc](const int slotIndex, const int itemOffset)
                        {
-                               const int extraPadding = ((slotIndex & 1) ?
-                                               m_info.calcExtraPaddingSize(m_slotSize) : 0);
-
-                               const int maxOffest = ((slotIndex / 2) * m_slotSize);
-                               const int minOffset = (maxOffest + extraPadding -
-                                               ((m_scrollerSize / m_slotSize) - 1) * m_slotSize);
-                               if ((m_scrollOffset >= minOffset) &&
-                                               (m_scrollOffset <= maxOffest)) {
+                               int minVisibleOffset = 0;
+                               int maxVisibleOffset = 0;
+                               if (isItemFullyVisible(slotIndex, itemOffset,
+                                               minVisibleOffset, maxVisibleOffset)) {
                                        return RES_OK;
                                }
 
-                               const int scrollOffset = ((m_scrollOffset > maxOffest) ?
-                                               maxOffest : minOffset);
+                               const int scrollOffset = ((m_scrollOffset > maxVisibleOffset) ?
+                                               maxVisibleOffset : minVisibleOffset);
                                if (m_info.isHorizontal) {
                                        showFunc(*m_scroller, scrollOffset, 0, m_scrollerSize, 1);
                                } else {
@@ -1140,6 +1219,47 @@ namespace gallery {
                        });
        }
 
+       bool ImageGrid::isItemFullyVisible(int itemIndex)
+       {
+               int minVisibleOffset = 0;
+               int maxVisibleOffset = 0;
+               return isItemFullyVisible(itemIndex,
+                               minVisibleOffset, maxVisibleOffset);
+       }
+
+       bool ImageGrid::isItemFullyVisible(const int itemIndex,
+                       int &minVisibleOffset, int &maxVisibleOffset) const
+       {
+               return (doWithCell(itemIndex,
+                               [this, &minVisibleOffset, &maxVisibleOffset](
+                                               const int slotIndex, const int itemOffset)
+                               {
+                                       return (isItemFullyVisible(slotIndex, itemOffset,
+                                                       minVisibleOffset, maxVisibleOffset) ?
+                                                               RES_OK : RES_FALSE);
+                               }
+                       ) == RES_OK);
+       }
+
+       bool ImageGrid::isItemFullyVisible(
+                       const int slotIndex, const int itemOffset,
+                       int &minVisibleOffset, int &maxVisibleOffset) const
+       {
+               const int extraPadding = ((slotIndex & 1) ?
+                               m_info.calcExtraPaddingSize(m_slotSize) : 0);
+
+               maxVisibleOffset = ((slotIndex / 2) * m_slotSize);
+               minVisibleOffset = (maxVisibleOffset + extraPadding -
+                               ((m_scrollerSize / m_slotSize) - 1) * m_slotSize);
+
+               if ((m_scrollOffset >= minVisibleOffset) &&
+                               (m_scrollOffset <= maxVisibleOffset)) {
+                       return true;
+               }
+
+               return false;
+       }
+
        void ImageGrid::forceBoxSizeCalculate()
        {
                for (int i = 0; i < m_slotCount; ++i) {
@@ -1196,6 +1316,83 @@ namespace gallery {
                }
        }
 
+       void ImageGrid::onItemHighlighted(const int itemIndex)
+       {
+               m_highlightID = itemIndex;
+               m_highlightTimeout.reset();
+       }
+
+       void ImageGrid::onItemUnhighlighted(const int itemIndex)
+       {
+               if (m_highlightID == itemIndex) {
+                       m_highlightID = (-1 - itemIndex);
+                       if (m_isHighlightLocked) {
+                               elm_atspi_component_highlight_grab(*m_highlighKeeper);
+                       } else {
+                               m_highlightTimeout.reset();
+                       }
+               } else {
+                       WLOG("Item was not highlighted: %d.", itemIndex);
+               }
+       }
+
+       void ImageGrid::onKeeperUnhighlighted(Widget &sender, void *eventInfo)
+       {
+               m_isHighlightLocked = false;
+               m_highlightTimeout.reset();
+       }
+
+       void ImageGrid::updateHighlightTimeout()
+       {
+               if (m_highlightID >= 0) {
+                       if (isItemFullyVisible(m_highlightID)) {
+                               m_highlightTimeout.reset();
+                               return;
+                       }
+               } else if (!m_isHighlightLocked) {
+                       return;
+               }
+
+               m_highlightTimeout = Timeout::create(
+                               impl::SCROLL_HIGHLIGHT_TIMEOUT_SEC, WEAK_DELEGATE(
+                                       ImageGrid::onHighlightTimeout, asWeak(*this)));
+       }
+
+       void ImageGrid::onHighlightTimeout(Timeout *sender)
+       {
+               m_highlightTimeout.reset();
+
+               int itemIndex = ((m_highlightID >= 0) ?
+                               m_highlightID : (-1 - m_highlightID));
+               bool found = false;
+
+               for (int i = m_info.getHighlightScanRange(); ((i >= 0) &&
+                               (itemIndex >= 0) && (itemIndex < m_itemCount)); --i) {
+                       int minVisibleOffset = 0;
+                       int maxVisibleOffset = 0;
+                       if (isItemFullyVisible(itemIndex,
+                                       minVisibleOffset, maxVisibleOffset)) {
+                               found = true;
+                       } else if (m_scrollOffset > maxVisibleOffset) {
+                               ++itemIndex;
+                       } else {
+                               --itemIndex;
+                       }
+               }
+
+               if (!found) {
+                       itemIndex = getScrolledToItemIndex();
+               }
+
+               FAIL_RETURN_VOID(doWithItem(itemIndex,
+                       [](Slot &slot, const int itemOffset)
+                       {
+                               elm_atspi_component_highlight_grab(
+                                               slot.getItemAtspi(itemOffset));
+                               return RES_OK;
+                       }), "Failed to get item Atspi!");
+       }
+
        Elm_Interface_Atspi_Accessible *ImageGrid::requestAtspi(const int itemIndex)
        {
                if ((itemIndex < 0) || (itemIndex >= m_itemCount)) {
@@ -1563,9 +1760,12 @@ namespace gallery {
                }
                ++m_eventsLock;
 
-               if (updateScrollOffset() && updateBeginSlotIndex()) {
-                       realizeSlots();
-                       updateRectMins();
+               if (updateScrollOffset()) {
+                       if (updateBeginSlotIndex()) {
+                               realizeSlots();
+                               updateRectMins();
+                       }
+                       updateHighlightTimeout();
                }
 
                --m_eventsLock;
index e1d87b0267cdb09266011fd0ba91e19741595306..b6bcb12961ba6532672a0e166ad15f57beac99a9 100644 (file)
@@ -29,6 +29,9 @@ namespace gallery {
        constexpr ucl::SmartEvent BTN_CLICKED {"clicked"};
        constexpr ucl::SmartEvent POPUP_DISMISSED {"dismissed"};
 
+       constexpr ucl::SmartEvent ATSPI_HIGHLIGHTED {"atspi,highlighted"};
+       constexpr ucl::SmartEvent ATSPI_UNHIGHLIGHTED {"atspi,unhighlighted"};
+
        constexpr ucl::ElmStyle SCROLLER_STYLE {"effect"};
 
        constexpr ucl::ElmStyle NAVIFRAME_NO_CLIP {"gallery_no_clip"};
index f4deb132e40ff8f3a2d79aae22ce79857ed3077d..3ed1afa2c38386efb14d91cb8946c94905cc066d 100644 (file)
@@ -22,8 +22,8 @@
 #include "ucl/util/types.h"
 #include "ucl/util/memory.h"
 #include "ucl/util/delegation.h"
+#include "ucl/util/smartDelegation.h"
 
-#include "ucl/misc/smartDelegation.h"
 #include "ucl/misc/Aspect.h"
 #include "ucl/misc/TString.h"
 #include "ucl/misc/Variant.h"
diff --git a/ucl/inc/ucl/misc/Timeout.h b/ucl/inc/ucl/misc/Timeout.h
new file mode 100644 (file)
index 0000000..707c25c
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2017 Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.1 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://floralicense.org/license/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __UCL_MISC_TIMEOUT_H__
+#define __UCL_MISC_TIMEOUT_H__
+
+#include <Ecore.h>
+
+#include "ucl/util/types.h"
+#include "ucl/util/smartDelegation.h"
+
+namespace ucl {
+
+       UCL_DECLARE_REF_ALIASES(Timeout);
+
+       class Timeout final : public NonCopyable {
+       public:
+               using TimeoutHandler = WeakDelegate<void(Timeout *sender)>;
+
+       public:
+               static TimeoutSRef create(double timeoutSec,
+                               const TimeoutHandler &handler);
+
+               bool isExpired() const;
+
+       private:
+               friend class RefCountObj<Timeout>;
+               Timeout(const TimeoutHandler &handler);
+               ~Timeout();
+
+               Result prepare(double timeoutSec);
+
+               Eina_Bool onTimer();
+
+       private:
+               Ecore_Timer *m_timer;
+               TimeoutHandler m_handler;
+       };
+}
+
+#endif // __UCL_MISC_TIMEOUT_H__
diff --git a/ucl/inc/ucl/misc/smartDelegation.h b/ucl/inc/ucl/misc/smartDelegation.h
deleted file mode 100644 (file)
index f921743..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright 2017 Samsung Electronics Co., Ltd
- *
- * Licensed under the Flora License, Version 1.1 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://floralicense.org/license/
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef __UCL_MISC_SMART_DELEGATION_H__
-#define __UCL_MISC_SMART_DELEGATION_H__
-
-#include "smartDelegation/WeakDelegate.h"
-
-#include "smartDelegation/macro.h"
-
-#if (UCL_INCLUDE_SMART_DELEGATION_SHORT_MACRO_H)
-#include "smartDelegation/shortMacro.h"
-#endif
-
-#endif // __UCL_MISC_SMART_DELEGATION_H__
diff --git a/ucl/inc/ucl/misc/smartDelegation/WeakDelegate.h b/ucl/inc/ucl/misc/smartDelegation/WeakDelegate.h
deleted file mode 100644 (file)
index 0a5e976..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright 2017 Samsung Electronics Co., Ltd
- *
- * Licensed under the Flora License, Version 1.1 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://floralicense.org/license/
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef __UCL_MISC_SMART_DELEGATION_WEAK_DELEGATE_H__
-#define __UCL_MISC_SMART_DELEGATION_WEAK_DELEGATE_H__
-
-#include "ucl/util/delegation.h"
-#include "ucl/util/memory.h"
-
-namespace ucl {
-
-       template <class FUNC_SIG>
-       class WeakDelegate;
-
-       template <class R, class ...ARGS>
-       class WeakDelegate<R(ARGS...)> :
-                       public BaseDelegate<R(ARGS...), WeakRef<void>> {
-       public:
-               using BaseDelegate<R(ARGS...), WeakRef<void>>::BaseDelegate;
-
-               template <class CLASS, R(CLASS::*METHOD)(ARGS...)>
-               static WeakDelegate make(const WeakRef<CLASS> &data) noexcept;
-
-               template <class CLASS, R(CLASS::*METHOD)(ARGS...) const>
-               static WeakDelegate make(const WeakRef<const CLASS> &data) noexcept;
-       };
-}
-
-#include "WeakDelegate.hpp"
-
-#endif // __UCL_MISC_SMART_DELEGATION_WEAK_DELEGATE_H__
diff --git a/ucl/inc/ucl/misc/smartDelegation/WeakDelegate.hpp b/ucl/inc/ucl/misc/smartDelegation/WeakDelegate.hpp
deleted file mode 100644 (file)
index e4b4b5d..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2017 Samsung Electronics Co., Ltd
- *
- * Licensed under the Flora License, Version 1.1 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://floralicense.org/license/
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-namespace ucl {
-
-       template <class R, class ...ARGS>
-       template <class CLASS, R(CLASS::*METHOD)(ARGS...)>
-       inline WeakDelegate<R(ARGS...)> WeakDelegate<R(ARGS...)>::make(
-                       const WeakRef<CLASS> &data) noexcept
-       {
-               return {data, WeakDelegate::Cb::template stubA<CLASS, METHOD>};
-       }
-
-       template <class R, class ...ARGS>
-       template <class CLASS, R(CLASS::*METHOD)(ARGS...) const>
-       inline WeakDelegate<R(ARGS...)> WeakDelegate<R(ARGS...)>::make(
-                       const WeakRef<const CLASS> &data) noexcept
-       {
-               return {constRefCast<CLASS>(data),
-                               WeakDelegate::Cb::template stubA<CLASS, METHOD>};
-       }
-}
diff --git a/ucl/inc/ucl/misc/smartDelegation/macro.h b/ucl/inc/ucl/misc/smartDelegation/macro.h
deleted file mode 100644 (file)
index 5368eda..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright 2017 Samsung Electronics Co., Ltd
- *
- * Licensed under the Flora License, Version 1.1 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://floralicense.org/license/
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef __UCL_MISC_SMART_DELEGATION_MACRO_H__
-#define __UCL_MISC_SMART_DELEGATION_MACRO_H__
-
-#define UCL_WEAK_DELEGATE(FUNC, DATA) \
-               _UCL_DELEGATE(::ucl::WeakDelegate, FUNC, DATA)
-
-#endif // __UCL_MISC_SMART_DELEGATION_MACRO_H__
diff --git a/ucl/inc/ucl/misc/smartDelegation/shortMacro.h b/ucl/inc/ucl/misc/smartDelegation/shortMacro.h
deleted file mode 100644 (file)
index 43c1ec3..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright 2017 Samsung Electronics Co., Ltd
- *
- * Licensed under the Flora License, Version 1.1 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://floralicense.org/license/
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef __UCL_MISC_SMART_DELEGATION_SHORT_MACRO_H__
-#define __UCL_MISC_SMART_DELEGATION_SHORT_MACRO_H__
-
-#define WEAK_DELEGATE(FUNC, DATA) UCL_WEAK_DELEGATE(FUNC, DATA)
-
-#endif // __UCL_MISC_SMART_DELEGATION_SHORT_MACRO_H__
diff --git a/ucl/inc/ucl/util/smartDelegation.h b/ucl/inc/ucl/util/smartDelegation.h
new file mode 100644 (file)
index 0000000..6714411
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2017 Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.1 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://floralicense.org/license/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __UCL_UTIL_SMART_DELEGATION_H__
+#define __UCL_UTIL_SMART_DELEGATION_H__
+
+#include "smartDelegation/WeakDelegate.h"
+
+#include "smartDelegation/macro.h"
+
+#if (UCL_INCLUDE_SMART_DELEGATION_SHORT_MACRO_H)
+#include "smartDelegation/shortMacro.h"
+#endif
+
+#endif // __UCL_UTIL_SMART_DELEGATION_H__
diff --git a/ucl/inc/ucl/util/smartDelegation/WeakDelegate.h b/ucl/inc/ucl/util/smartDelegation/WeakDelegate.h
new file mode 100644 (file)
index 0000000..0d29f0f
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2017 Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.1 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://floralicense.org/license/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __UCL_UTIL_SMART_DELEGATION_WEAK_DELEGATE_H__
+#define __UCL_UTIL_SMART_DELEGATION_WEAK_DELEGATE_H__
+
+#include "ucl/util/delegation.h"
+#include "ucl/util/memory.h"
+
+namespace ucl {
+
+       template <class FUNC_SIG>
+       class WeakDelegate;
+
+       template <class R, class ...ARGS>
+       class WeakDelegate<R(ARGS...)> :
+                       public BaseDelegate<R(ARGS...), WeakRef<void>> {
+       public:
+               using BaseDelegate<R(ARGS...), WeakRef<void>>::BaseDelegate;
+
+               template <class CLASS, R(CLASS::*METHOD)(ARGS...)>
+               static WeakDelegate make(const WeakRef<CLASS> &data) noexcept;
+
+               template <class CLASS, R(CLASS::*METHOD)(ARGS...) const>
+               static WeakDelegate make(const WeakRef<const CLASS> &data) noexcept;
+       };
+}
+
+#include "WeakDelegate.hpp"
+
+#endif // __UCL_UTIL_SMART_DELEGATION_WEAK_DELEGATE_H__
diff --git a/ucl/inc/ucl/util/smartDelegation/WeakDelegate.hpp b/ucl/inc/ucl/util/smartDelegation/WeakDelegate.hpp
new file mode 100644 (file)
index 0000000..e4b4b5d
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2017 Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.1 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://floralicense.org/license/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace ucl {
+
+       template <class R, class ...ARGS>
+       template <class CLASS, R(CLASS::*METHOD)(ARGS...)>
+       inline WeakDelegate<R(ARGS...)> WeakDelegate<R(ARGS...)>::make(
+                       const WeakRef<CLASS> &data) noexcept
+       {
+               return {data, WeakDelegate::Cb::template stubA<CLASS, METHOD>};
+       }
+
+       template <class R, class ...ARGS>
+       template <class CLASS, R(CLASS::*METHOD)(ARGS...) const>
+       inline WeakDelegate<R(ARGS...)> WeakDelegate<R(ARGS...)>::make(
+                       const WeakRef<const CLASS> &data) noexcept
+       {
+               return {constRefCast<CLASS>(data),
+                               WeakDelegate::Cb::template stubA<CLASS, METHOD>};
+       }
+}
diff --git a/ucl/inc/ucl/util/smartDelegation/macro.h b/ucl/inc/ucl/util/smartDelegation/macro.h
new file mode 100644 (file)
index 0000000..b117820
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2017 Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.1 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://floralicense.org/license/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __UCL_UTIL_SMART_DELEGATION_MACRO_H__
+#define __UCL_UTIL_SMART_DELEGATION_MACRO_H__
+
+#define UCL_WEAK_DELEGATE(FUNC, DATA) \
+               _UCL_DELEGATE(::ucl::WeakDelegate, FUNC, DATA)
+
+#endif // __UCL_UTIL_SMART_DELEGATION_MACRO_H__
diff --git a/ucl/inc/ucl/util/smartDelegation/shortMacro.h b/ucl/inc/ucl/util/smartDelegation/shortMacro.h
new file mode 100644 (file)
index 0000000..ddf5e35
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2017 Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.1 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://floralicense.org/license/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __UCL_UTIL_SMART_DELEGATION_SHORT_MACRO_H__
+#define __UCL_UTIL_SMART_DELEGATION_SHORT_MACRO_H__
+
+#define WEAK_DELEGATE(FUNC, DATA) UCL_WEAK_DELEGATE(FUNC, DATA)
+
+#endif // __UCL_UTIL_SMART_DELEGATION_SHORT_MACRO_H__
index 89d33dd41bb6cf9f15aa3c9bed6182f24edb3f23..1b1402da4b33a842f83d62104780e8ef6d14cf71 100644 (file)
@@ -51,7 +51,7 @@ namespace ucl {
        public:
                virtual IPRODUCT *newInstance() const = 0;
        protected:
-               ~IFactory() = default;
+               virtual ~IFactory() = default;
        };
 
        template <class PRODUCT, class IPRODUCT>
index f03d1947ba2ffc3cdf2b92e5ba3cd18c60f71127..f358669773cd78e85fe2f79913f45ccf3ab19c94 100644 (file)
@@ -30,6 +30,6 @@
 #include "ucl/util/shortLogs.h"
 
 #include "ucl/util/delegation/shortMacro.h"
-#include "ucl/misc/smartDelegation/shortMacro.h"
+#include "ucl/util/smartDelegation/shortMacro.h"
 
 #endif // __UCL_COMMON_H__
diff --git a/ucl/src/misc/Timeout.cpp b/ucl/src/misc/Timeout.cpp
new file mode 100644 (file)
index 0000000..41a3d3f
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2017 Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.1 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://floralicense.org/license/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ucl/misc/Timeout.h"
+
+#include "common.h"
+
+namespace ucl {
+
+       TimeoutSRef Timeout::create(double timeoutSec,
+                       const TimeoutHandler &handler)
+       {
+               auto result = makeShared<Timeout>(handler);
+
+               FAIL_RETURN_VALUE(result->prepare(timeoutSec), {},
+                               "result->prepare() failed!");
+
+               return result;
+       }
+
+       Timeout::Timeout(const TimeoutHandler &handler) :
+               m_timer(nullptr),
+               m_handler(handler)
+       {
+       }
+
+       Timeout::~Timeout()
+       {
+               if (m_timer) {
+                       ecore_timer_del(m_timer);
+               }
+       }
+
+       Result Timeout::prepare(const double timeoutSec)
+       {
+               m_timer = ecore_timer_add(timeoutSec,
+                       [](void *data) -> Eina_Bool
+                       {
+                               const auto self = static_cast<Timeout *>(data);
+                               self->m_timer = nullptr;
+                               if (self->m_handler) {
+                                       self->m_handler(self);
+                               }
+                               return ECORE_CALLBACK_CANCEL;
+                       },
+                       this);
+
+               if (!m_timer) {
+                       FAIL_RETURN(RES_FAIL, "ecore_timer_add() failed!");
+               }
+
+               return RES_OK;
+       }
+
+       bool Timeout::isExpired() const
+       {
+               return !m_timer;
+       }
+}