TizenRefApp-8316 [Gallery] Implement Select mode animation in ImageGrid 06/124206/2
authorIgor Nazarov <i.nazarov@samsung.com>
Mon, 10 Apr 2017 13:35:08 +0000 (16:35 +0300)
committerIgor Nazarov <i.nazarov@samsung.com>
Tue, 11 Apr 2017 11:06:56 +0000 (14:06 +0300)
- Implemented selection mode login in ImageGrid widget.

Change-Id: I02948e227cad2cae25031c685a7045ca813f85d3

inc/view/IImageGridListener.h
inc/view/ImageGrid.h
src/view/ImageGrid.cpp

index 1f2992fdbba96b9ed2d314d35a468be0840c91bb..07227856858802677feaf9c68b8c8af0f71f54a0 100644 (file)
@@ -26,6 +26,7 @@ namespace gallery {
                virtual void onItemRealized(int itemIndex) = 0;
                virtual void onItemUnrealized(int itemIndex) = 0;
                virtual void onItemEvent(int itemIndex, int event, int x, int y) = 0;
+               virtual void onTransitionFinished() {}
        };
 }
 
index 3016f09cffbfa680694ca0df00c5d8539b92520e..712f827e462f6d275239924e1100dc9bb4822776 100644 (file)
@@ -73,7 +73,11 @@ namespace gallery {
        public:
                void setListener(IImageGridListener *listener);
 
-               void setItemCount(int count);
+               ucl::Result setItemCount(int count);
+
+               ucl::Result setSelectModeEnabled(bool enabled);
+               bool isInSelectMode() const;
+               bool isInTransition() const;
 
                void update();
 
@@ -98,6 +102,7 @@ namespace gallery {
        private:
                friend class ucl::RefCountObj<ImageGrid>;
                ImageGrid(ucl::RefCountObjBase *rc, Type type, Evas_Object *scroller);
+               virtual ~ImageGrid();
 
                static const Info &getInfo(Type type);
 
@@ -114,6 +119,14 @@ namespace gallery {
 
                void handleItemEvent(int itemIndex, int event, int x, int y) const;
 
+               // Selection mode hanling
+               void evalSlotSizes();
+               void finalizeTransition();
+               Eina_Bool onAnimationFrame();
+               void onBoxResize(Evas *e, Evas_Object *obj, void *eventInfo);
+               void onTransitonFinished(Evas_Object *obj, const char *emission,
+                               const char *source);
+
                // Initialization
                void prepare();
                void createCircleScroller();
@@ -145,6 +158,10 @@ namespace gallery {
                void updateScrollBias();
                void updateRectMins();
 
+               // Slot size
+               bool updateSlotSize();
+               void setSlotSize(int newSlotSize);
+
                // Scroller size
                bool updateScrollerSize();
                int calcScrollerSize();
@@ -201,6 +218,10 @@ namespace gallery {
 
                int m_unrealizeLock;
                int m_eventsLock;
+
+               Ecore_Animator *m_animator;
+               bool m_isInSelectMode;
+               bool m_isRotaryActive;
        };
 }
 
index 5d1a247e5aa8cdb4a2f00a4c1e164e5cc4955b77..0ef62161b86164029f3ad488e1f01b7108f3ffcc 100644 (file)
@@ -33,6 +33,13 @@ namespace gallery { namespace { namespace impl {
        // Related to ImageGrid //
        const TString SLOT_PART_FMT {"swallow.cell_%d"};
 
+       constexpr EdjeSignal SIGNAL_ENABLE_SELECT_MODE
+                       {"gallery,enable,select,mode"};
+       constexpr EdjeSignal SIGNAL_DISABLE_SELECT_MODE
+                       {"gallery,disable,select,mode"};
+       constexpr EdjeSignal SIGNAL_TRANSITION_FINISHED
+                       {"gallery,transition,finished"};
+
        // Related to Button //
        constexpr ElmStyle ITEM_BTN_STYLE {"gallery_image"};
        constexpr EdjePart PART_BTN_BG {"swallow.bg"};
@@ -403,18 +410,17 @@ namespace gallery {
                        }
                }
 
-               Widget &getWidget()
+               Layout &getLayout()
                {
                        return m_layout;
                }
 
-               int calcSize()
+               int getSize()
                {
                        int w = 0;
                        int h = 0;
-                       m_layout.calculate();
                        m_layout.getMin(&w, &h);
-                       return (m_info.isHorizontal ? w : h);
+                       return std::max((m_info.isHorizontal ? w : h), 1);
                }
 
                void setImageLoadSize(const int value)
@@ -511,7 +517,11 @@ namespace gallery {
                m_scrollOffset(0),
 
                m_unrealizeLock(0),
-               m_eventsLock(0)
+               m_eventsLock(0),
+
+               m_animator(nullptr),
+               m_isInSelectMode(false),
+               m_isRotaryActive(false)
        {
                prepare();
 
@@ -526,6 +536,13 @@ namespace gallery {
                --m_eventsLock;
        }
 
+       ImageGrid::~ImageGrid()
+       {
+               if (m_animator) {
+                       finalizeTransition();
+               }
+       }
+
        const ImageGrid::Info &ImageGrid::getInfo(const Type type)
        {
                switch (type) {
@@ -613,10 +630,14 @@ namespace gallery {
                m_listener = listener;
        }
 
-       void ImageGrid::setItemCount(const int count)
+       Result ImageGrid::setItemCount(const int count)
        {
+               if (m_animator) {
+                       LOG_RETURN(RES_ILLEGAL_STATE, "Transition is in progress.");
+               }
+
                if (m_itemCount == count) {
-                       return;
+                       return RES_FALSE;
                }
 
                ++m_eventsLock;
@@ -636,6 +657,129 @@ namespace gallery {
                updateRectMins();
 
                --m_eventsLock;
+
+               return RES_OK;
+       }
+
+       Result ImageGrid::setSelectModeEnabled(const bool enabled)
+       {
+               if (m_animator) {
+                       LOG_RETURN(RES_ILLEGAL_STATE, "Transition is in progress.");
+               }
+
+               if (enabled == m_isInSelectMode) {
+                       return RES_FALSE;
+               }
+
+               if ((m_scrollOffset % m_slotSize) > 0) {
+                       DLOG("Can't handle it right now!");
+                       return RES_FAIL;
+               }
+
+               m_isInSelectMode = enabled;
+
+               elm_object_scroll_freeze_push(*m_scroller);
+               evas_object_freeze_events_set(*m_scroller, EINA_TRUE);
+               eext_rotary_object_event_activated_set(m_circleScroller, EINA_FALSE);
+
+               const auto aSignal = (enabled ?
+                               impl::SIGNAL_ENABLE_SELECT_MODE :
+                               impl::SIGNAL_DISABLE_SELECT_MODE);
+               for (auto &slot: m_slots) {
+                       slot->getLayout().emitSignal(aSignal);
+               }
+
+               m_animator = ecore_animator_add(
+                               CALLBACK_A(ImageGrid::onAnimationFrame), this);
+
+               evas_object_event_callback_priority_add(m_box,
+                                       EVAS_CALLBACK_RESIZE, EO_CALLBACK_PRIORITY_AFTER,
+                                       CALLBACK_A(ImageGrid::onBoxResize), this);
+
+               elm_object_signal_callback_add(
+                               m_slots[m_beginSlotIndex & 1]->getLayout(),
+                               impl::SIGNAL_TRANSITION_FINISHED.name, "",
+                               CALLBACK_A(ImageGrid::onTransitonFinished), this);
+
+               return RES_OK;
+       }
+
+       bool ImageGrid::isInSelectMode() const
+       {
+               return m_isInSelectMode;
+       }
+
+       bool ImageGrid::isInTransition() const
+       {
+               return !!m_animator;
+       }
+
+       void ImageGrid::onTransitonFinished(Evas_Object *obj,
+                       const char *emission, const char *source)
+       {
+               evalSlotSizes();
+
+               finalizeTransition();
+
+               elm_object_scroll_freeze_pop(*m_scroller);
+               evas_object_freeze_events_set(*m_scroller, EINA_FALSE);
+               if (m_isRotaryActive) {
+                       eext_rotary_object_event_activated_set(m_circleScroller, EINA_TRUE);
+               }
+
+               if (m_listener) {
+                       m_listener->onTransitionFinished();
+               }
+       }
+
+       void ImageGrid::finalizeTransition()
+       {
+               if (m_animator) {
+                       ecore_animator_del(m_animator);
+                       m_animator = nullptr;
+               }
+
+               evas_object_event_callback_del_full(m_box, EVAS_CALLBACK_RESIZE,
+                               CALLBACK_A(ImageGrid::onBoxResize), this);
+
+               elm_object_signal_callback_del(
+                               m_slots[m_beginSlotIndex & 1]->getLayout(),
+                               "gallery,transition,finished", "",
+                               CALLBACK_A(ImageGrid::onTransitonFinished));
+       }
+
+       Eina_Bool ImageGrid::onAnimationFrame()
+       {
+               evalSlotSizes();
+               return ECORE_CALLBACK_RENEW;
+       }
+
+       void ImageGrid::evalSlotSizes()
+       {
+               for (auto &slot: m_slots) {
+                       elm_layout_sizing_eval(slot->getLayout());
+               }
+       }
+
+       void ImageGrid::onBoxResize(Evas *e, Evas_Object *obj, void *eventInfo)
+       {
+               const int scrollLockIndex = (m_scrollOffset / m_slotSize);
+
+               if (updateSlotSize()) {
+
+                       m_scrollOffset = (scrollLockIndex * m_slotSize);
+                       if (m_info.isHorizontal) {
+                               elm_scroller_region_show(*m_scroller,
+                                               m_scrollOffset, 0, m_scrollerSize, 1);
+                       } else {
+                               elm_scroller_region_show(*m_scroller,
+                                               0, m_scrollOffset, 1, m_scrollerSize);
+                       }
+
+                       updatePadSizes();
+                       updateScrollBias();
+                       updateRectMins();
+               }
        }
 
        void ImageGrid::update()
@@ -693,11 +837,17 @@ namespace gallery {
 
        Result ImageGrid::scrollToItem(const int itemIndex)
        {
+               if (m_animator) {
+                       LOG_RETURN(RES_ILLEGAL_STATE, "Transition is in progress.");
+               }
                return showItem(itemIndex, elm_scroller_region_show);
        }
 
        Result ImageGrid::bringInItem(int itemIndex)
        {
+               if (m_animator) {
+                       LOG_RETURN(RES_ILLEGAL_STATE, "Transition is in progress.");
+               }
                return showItem(itemIndex, elm_scroller_region_bring_in);
        }
 
@@ -719,17 +869,25 @@ namespace gallery {
 
        void ImageGrid::activateRotary()
        {
-               eext_rotary_object_event_activated_set(m_circleScroller, EINA_TRUE);
+               m_isRotaryActive = true;
+               if (!m_animator) {
+                       eext_rotary_object_event_activated_set(m_circleScroller, EINA_TRUE);
+               }
        }
 
        void ImageGrid::deactivateRotary()
        {
+               m_isRotaryActive = false;
                eext_rotary_object_event_activated_set(m_circleScroller, EINA_FALSE);
        }
 
        void ImageGrid::addUnrealizeLock()
        {
-               unrealizeSlots(0, m_slotCount);
+               if (m_animator) {
+                       ELOG("Transition is in progress.");
+               } else {
+                       unrealizeSlots(0, m_slotCount);
+               }
                ++m_unrealizeLock;
        }
 
@@ -737,7 +895,11 @@ namespace gallery {
        {
                if (m_unrealizeLock > 0) {
                        --m_unrealizeLock;
-                       realizeSlots();
+                       if (m_animator) {
+                               ELOG("Transition is in progress.");
+                       } else {
+                               realizeSlots();
+                       }
                } else {
                        WLOG("m_unrealizeLock = 0!");
                }
@@ -779,18 +941,13 @@ namespace gallery {
 
                        if (m_slotSize == 0) {
                                UCL_ASSERT(!isOdd, "Must be even!");
-                               m_slotSize = std::max(slot->calcSize(), 1);
-                               const int pageSize = (m_slotSize * m_info.slotsPerPage);
-                               if (m_info.isHorizontal) {
-                                       elm_scroller_page_size_set(*m_scroller, pageSize, 0);
-                               } else {
-                                       elm_scroller_page_size_set(*m_scroller, 0, pageSize);
-                               }
+                               slot->getLayout().calculate();
+                               setSlotSize(slot->getSize());
                        }
 
                        slot->setImageLoadSize(m_slotSize);
 
-                       elm_box_pack_before(m_box, slot->getWidget(), m_rect2);
+                       elm_box_pack_before(m_box, slot->getLayout(), m_rect2);
 
                        m_slots.emplace_back(std::move(slot));
                }
@@ -939,7 +1096,7 @@ namespace gallery {
                const int spaceSize = (m_scrollerSize -
                                (std::max((m_scrollerSize / m_slotSize), 1) * m_slotSize));
 
-               m_padSize1 = (spaceSize / 2);
+               m_padSize1 = std::lround(spaceSize / 2.0);
                m_padSize2 = (spaceSize - m_padSize1 +
                                m_info.calcExtraPaddingSize(m_slotSize, m_itemCount));
        }
@@ -968,6 +1125,31 @@ namespace gallery {
                }
        }
 
+       bool ImageGrid::updateSlotSize()
+       {
+               const int newSlotSize = m_slots[m_beginSlotIndex & 1]->getSize();
+
+               if (newSlotSize != m_slotSize) {
+                       DLOG("newSlotSize: %d; m_slotSize: %d;",
+                                       newSlotSize, m_slotSize);
+                       setSlotSize(newSlotSize);
+                       return true;
+               }
+
+               return false;
+       }
+
+       void ImageGrid::setSlotSize(const int newSlotSize)
+       {
+               m_slotSize = newSlotSize;
+               const int pageSize = (m_slotSize * m_info.slotsPerPage);
+               if (m_info.isHorizontal) {
+                       elm_scroller_page_size_set(*m_scroller, pageSize, 0);
+               } else {
+                       elm_scroller_page_size_set(*m_scroller, 0, pageSize);
+               }
+       }
+
        int ImageGrid::calcScrollerSize()
        {
                int scrollerW = 0;
@@ -1030,8 +1212,8 @@ namespace gallery {
                for (int i = 0; i < count; ++i) {
                        SlotUPtr slot = std::move(m_slots.back());
                        m_slots.pop_back();
-                       elm_box_unpack(m_box, slot->getWidget());
-                       elm_box_pack_after(m_box, slot->getWidget(), m_rect1);
+                       elm_box_unpack(m_box, slot->getLayout());
+                       elm_box_pack_after(m_box, slot->getLayout(), m_rect1);
                        m_slots.emplace_front(std::move(slot));
                }
        }
@@ -1042,8 +1224,8 @@ namespace gallery {
                for (int i = 0; i < count; ++i) {
                        SlotUPtr slot = std::move(m_slots.front());
                        m_slots.pop_front();
-                       elm_box_unpack(m_box, slot->getWidget());
-                       elm_box_pack_before(m_box, slot->getWidget(), m_rect2);
+                       elm_box_unpack(m_box, slot->getLayout());
+                       elm_box_pack_before(m_box, slot->getLayout(), m_rect2);
                        m_slots.emplace_back(std::move(slot));
                }
        }
@@ -1069,6 +1251,10 @@ namespace gallery {
 
        void ImageGrid::handleScrolling()
        {
+               if (m_animator) {
+                       return;
+               }
+
                if (m_eventsLock > 0) {
                        WLOG("Event handling was blocked!");
                        return;
@@ -1085,6 +1271,10 @@ namespace gallery {
 
        void ImageGrid::handleResize()
        {
+               if (m_animator) {
+                       return;
+               }
+
                if (m_eventsLock > 0) {
                        WLOG("Event handling was blocked!");
                        return;