const std::string &getFilePath() const;
- ucl::Result getThumbnailPath(const ThumbnailPathGetCb &cb) const;
+ ucl::Result getThumbnailPath(ThumbnailPathGetCb cb) const;
void cancelThumbnailPathGet() const;
ucl::Result removeFile();
--- /dev/null
+/*
+ * 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 __GALLERY_VIEW_IMAGE_GRID_H__
+#define __GALLERY_VIEW_IMAGE_GRID_H__
+
+#include <deque>
+
+#include "ucl/gui/StyledWidget.h"
+
+namespace gallery {
+
+ UCL_DECLARE_REF_ALIASES(ImageGrid);
+
+ class ImageGrid : public ucl::Widget {
+ public:
+ enum class Type {
+ HCOMB_3X3
+ };
+
+ class IListener : public ucl::Polymorphic {
+ public:
+ virtual void onItemRealized(int itemIndex) = 0;
+ virtual void onItemUnrealized(int itemIndex) = 0;
+ };
+
+ class Builder {
+ public:
+ Builder();
+ Builder &setType(Type value);
+ Builder &setListener(IListener *value);
+ ImageGridSRef build(Widget &parent) const;
+ private:
+ Type m_type;
+ IListener *m_listener;
+ };
+
+ struct ItemParams {
+ std::string imagePath;
+ };
+
+ public:
+ void setListener(IListener *listener);
+
+ void setItemCount(int count);
+
+ void update();
+
+ ucl::Result updateItem(int itemIndex, const ItemParams ¶ms);
+
+ ucl::Result isItemRealized(int itemIndex);
+
+ private:
+ class Slot;
+ using SlotUPtr = std::unique_ptr<Slot>;
+
+ struct Info;
+ struct HcombInfo;
+
+ private:
+ friend class ucl::RefCountObj<ImageGrid>;
+ ImageGrid(ucl::RefCountObjBase *rc, Type type, Evas_Object *scroller);
+
+ static const Info &getInfo(Type type);
+
+ template <class FUNC>
+ ucl::Result doWithItem(int itemIndex, FUNC &&func);
+
+ // Initialization
+ void prepare();
+
+ // Actual slots count
+ bool updateSlotCount();
+ int calcSlotCount();
+ void setSlotCount(int newSlotCount);
+
+ // Optimal slots count
+ bool updateOptimalSlotCount();
+ int calcOptimalSlotCount();
+
+ // Maximum slots count
+ bool updateMaxSlotCount();
+ int calcMaxSlotCount();
+
+ // Actual begin slot index
+ bool updateBeginSlotIndex();
+ int calcBeginSlotIndex();
+ void setBeginSlotIndex(int newBeginSlotIndex);
+
+ // Maximum begin slot index
+ bool updateMaxBeginSlotIndex();
+ int calcMaxBeginSlotIndex();
+
+ // Misc
+ void updatePadSizes();
+ void updateScrollBias();
+ void updateRectMins();
+
+ // Scroller size
+ bool updateScrollerSize();
+ int calcScrollerSize();
+
+ // Scroller scroll offset
+ bool updateScrollOffset();
+ int calcScrollOffset();
+
+ // Slots rotations
+ void rotateSlotsRight(int count);
+ void rotateSlotsLeft(int count);
+
+ // Slots realization/unrealization
+ void realizeSlots();
+ void unrealizeSlots(int beginSlotOffset, int endSlotOffset);
+
+ // Event handling
+ void handleScrolling();
+ void handleResize();
+
+ // Events
+ void onScrollerResize(Widget &sender, void *eventInfo);
+ void onScrollerMove(Widget &sender, void *eventInfo);
+ void onBoxMove(Widget &sender, void *eventInfo);
+
+ private:
+ const Info &m_info;
+
+ ucl::StyledWidget m_scroller;
+ ucl::ElmWidget m_box;
+ ucl::Widget m_rect1;
+ ucl::Widget m_rect2;
+
+ IListener *m_listener;
+ int m_itemCount;
+
+ std::deque<SlotUPtr> m_slots;
+
+ int m_slotCount;
+ int m_optimalSlotCount;
+ int m_maxSlotCount;
+
+ int m_beginSlotIndex;
+ int m_maxBeginSlotIndex;
+
+ int m_scrollBias;
+ int m_padSize1;
+ int m_padSize2;
+
+ int m_slotSize;
+ int m_scrollerSize;
+ int m_scrollOffset;
+ };
+}
+
+#endif // __GALLERY_VIEW_IMAGE_GRID_H__
--- /dev/null
+/*
+ * 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 __GALLERY_PRESENTATION_PAGE_H__
+#define __GALLERY_PRESENTATION_PAGE_H__
+
+#include "ucl/gui/Naviframe.h"
+
+#include "types.h"
+
+namespace gallery {
+
+ UCL_DECLARE_REF_ALIASES(Page);
+
+ class Page : public ucl::RefCountAware {
+ public:
+ using ExitRequestHandler = ucl::Delegate<void(Page &page)>;
+
+ public:
+ ucl::Naviframe &getNaviframe();
+
+ bool isActive() const;
+
+ bool isAtTop() const;
+ bool isAtBottom() const;
+
+ void exit();
+ void exitNoTransition();
+
+ void popTo();
+ void deleteTo();
+ void promote();
+
+ template <class ...ARGS>
+ ucl::NaviItem insertAfter(ARGS &&...args);
+
+ template <class ...ARGS>
+ ucl::NaviItem insertBefore(ARGS &&...args);
+
+ protected:
+ Page(ucl::RefCountObjBase &rc, const ucl::NaviframeSRef &navi,
+ ExitRequestHandler onExitRequest);
+ virtual ~Page();
+
+ template <class ITEM_FACTORY>
+ ucl::Result prepare(ITEM_FACTORY &&makeItem);
+
+ ucl::NaviItem getItem();
+
+ void requestExit();
+
+ virtual void onActivate();
+ virtual void onDeactivate();
+ virtual void onBackKey();
+
+ private:
+ ucl::Result preparePart2();
+
+ void dispatchTopPageChanged();
+
+ void activate();
+ void deactivate();
+ void updateActiveState();
+
+ void onTransitionStarted(ucl::Widget &widget, void *eventInfo);
+ void onTransitionFinished(ucl::Widget &widget, void *eventInfo);
+ void onTopPageChanged(ucl::Widget &widget, void *eventInfo);
+
+ void onHWBackKey(Evas_Object *obj, void *eventInfo);
+ void onItemDel(Evas_Object *obj, void *eventInfo);
+
+ private:
+ const ucl::NaviframeSRef m_navi;
+ const ExitRequestHandler m_onExitRequest;
+ ucl::NaviItem m_item;
+ bool m_isActive;
+ };
+
+ // Non-member functions //
+
+ bool isLast(const Page &page);
+}
+
+#include "Page.hpp"
+
+#endif // __GALLERY_PRESENTATION_PAGE_H__
--- /dev/null
+/*
+ * 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/util/logging.h"
+
+namespace gallery {
+
+ using namespace ucl;
+
+ template <class ITEM_FACTORY>
+ inline Result Page::prepare(ITEM_FACTORY &&makeItem)
+ {
+ m_item = makeItem();
+ if (isNotValid(m_item)) {
+ UCL_LOG_RETURN(RES_FAIL, "m_item is NULL");
+ }
+ return preparePart2();
+ }
+
+ template <class ...ARGS>
+ inline NaviItem Page::insertAfter(ARGS &&...args)
+ {
+ return m_navi->insertAfter(m_item, std::forward<ARGS>(args)...);
+ }
+
+ template <class ...ARGS>
+ inline NaviItem Page::insertBefore(ARGS &&...args)
+ {
+ return m_navi->insertBefore(m_item, std::forward<ARGS>(args)...);
+ }
+
+ inline Naviframe &Page::getNaviframe()
+ {
+ UCL_ASSERT(m_navi, "m_navi is NULL");
+ return *m_navi;
+ }
+
+ inline bool Page::isActive() const
+ {
+ return m_isActive;
+ }
+
+ inline bool Page::isAtTop() const
+ {
+ return (m_navi->getTopItem() == m_item);
+ }
+
+ inline bool Page::isAtBottom() const
+ {
+ return (m_navi->getBottomItem() == m_item);
+ }
+
+ // Non-member functions //
+
+ inline bool isLast(const Page &page)
+ {
+ return (page.isAtBottom() && page.isAtTop());
+ }
+}
+++ /dev/null
-/*
- * 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 __GALLERY_VIEW_IMAGE_GRID_H__
-#define __GALLERY_VIEW_IMAGE_GRID_H__
-
-#include <deque>
-
-#include "ucl/gui/StyledWidget.h"
-
-namespace gallery {
-
- UCL_DECLARE_REF_ALIASES(ImageGrid);
-
- class ImageGrid : public ucl::Widget {
- public:
- enum class Type {
- HCOMB_3X3
- };
-
- class IListener : public ucl::Polymorphic {
- public:
- virtual void onItemRealized(int itemIndex) = 0;
- virtual void onItemUnrealized(int itemIndex) = 0;
- };
-
- class Builder {
- public:
- Builder();
- Builder &setType(Type value);
- Builder &setListener(IListener *value);
- ImageGridSRef build(Widget &parent) const;
- private:
- Type m_type;
- IListener *m_listener;
- };
-
- struct ItemParams {
- std::string imagePath;
- };
-
- public:
- void setListener(IListener *listener);
-
- void setItemCount(int count);
-
- void update();
-
- ucl::Result updateItem(int itemIndex, const ItemParams ¶ms);
-
- ucl::Result isItemRealized(int itemIndex);
-
- private:
- class Slot;
- using SlotUPtr = std::unique_ptr<Slot>;
-
- struct Info;
- struct HcombInfo;
-
- private:
- friend class ucl::RefCountObj<ImageGrid>;
- ImageGrid(ucl::RefCountObjBase *rc, Type type, Evas_Object *scroller);
-
- static const Info &getInfo(Type type);
-
- template <class FUNC>
- ucl::Result doWithItem(int itemIndex, FUNC &&func);
-
- // Initialization
- void prepare();
-
- // Actual slots count
- bool updateSlotCount();
- int calcSlotCount();
- void setSlotCount(int newSlotCount);
-
- // Optimal slots count
- bool updateOptimalSlotCount();
- int calcOptimalSlotCount();
-
- // Maximum slots count
- bool updateMaxSlotCount();
- int calcMaxSlotCount();
-
- // Actual begin slot index
- bool updateBeginSlotIndex();
- int calcBeginSlotIndex();
- void setBeginSlotIndex(int newBeginSlotIndex);
-
- // Maximum begin slot index
- bool updateMaxBeginSlotIndex();
- int calcMaxBeginSlotIndex();
-
- // Misc
- void updatePadSizes();
- void updateScrollBias();
- void updateRectMins();
-
- // Scroller size
- bool updateScrollerSize();
- int calcScrollerSize();
-
- // Scroller scroll offset
- bool updateScrollOffset();
- int calcScrollOffset();
-
- // Slots rotations
- void rotateSlotsRight(int count);
- void rotateSlotsLeft(int count);
-
- // Slots realization/unrealization
- void realizeSlots();
- void unrealizeSlots(int beginSlotOffset, int endSlotOffset);
-
- // Event handling
- void handleScrolling();
- void handleResize();
-
- // Events
- void onScrollerResize(Widget &sender, void *eventInfo);
- void onScrollerMove(Widget &sender, void *eventInfo);
- void onBoxMove(Widget &sender, void *eventInfo);
-
- private:
- const Info &m_info;
-
- ucl::StyledWidget m_scroller;
- ucl::ElmWidget m_box;
- ucl::Widget m_rect1;
- ucl::Widget m_rect2;
-
- IListener *m_listener;
- int m_itemCount;
-
- std::deque<SlotUPtr> m_slots;
-
- int m_slotCount;
- int m_optimalSlotCount;
- int m_maxSlotCount;
-
- int m_beginSlotIndex;
- int m_maxBeginSlotIndex;
-
- int m_scrollBias;
- int m_padSize1;
- int m_padSize2;
-
- int m_slotSize;
- int m_scrollerSize;
- int m_scrollOffset;
- };
-}
-
-#endif // __GALLERY_VIEW_IMAGE_GRID_H__
return RES_OK;
}
- Result MediaItem::getThumbnailPath(const ThumbnailPathGetCb &cb) const
+ Result MediaItem::getThumbnailPath(ThumbnailPathGetCb cb) const
{
if (!cb) {
return RES_INVALID_ARGUMENTS;
--- /dev/null
+/*
+ * 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 "presentation/ImageGrid.h"
+
+#include <array>
+#include <vector>
+
+#include "ucl/gui/Layout.h"
+
+#include "../common.h"
+
+namespace gallery { namespace { namespace impl {
+
+ using namespace ucl;
+
+ const TString SLOT_PART_FMT = {"swallow.cell_%d"};
+}}}
+
+namespace gallery {
+
+ using namespace ucl;
+
+ // ImageGrid::Builder //
+
+ ImageGrid::Builder::Builder() :
+ m_type(Type::HCOMB_3X3),
+ m_listener(nullptr)
+ {
+ }
+
+ ImageGrid::Builder &ImageGrid::Builder::setType(const Type value)
+ {
+ m_type = value;
+ return *this;
+ }
+
+ ImageGrid::Builder &ImageGrid::Builder::setListener(IListener *const value)
+ {
+ m_listener = value;
+ return *this;
+ }
+
+ ImageGridSRef ImageGrid::Builder::build(Widget &parent) const
+ {
+ Evas_Object *const scrollerEo = elm_scroller_add(parent);
+ if (!scrollerEo) {
+ ELOG("elm_scroller_add() failed!");
+ return {};
+ }
+
+ auto result = makeShared<ImageGrid>(m_type, scrollerEo);
+
+ result->bindToEo();
+ result->setListener(m_listener);
+
+ return result;
+ }
+
+ // ImageGrid::Info //
+
+ struct ImageGrid::Info {
+ const std::array<LayoutTheme, 2> slotThemes;
+ const std::array<int, 2> slotLens;
+ const int scrollLimit;
+ const bool isHorizontal;
+
+ virtual int calcItemIndexFromCell(
+ const int slotIndex, const int itemOffset) const = 0;
+ virtual void calcCellFromItemIndex(const int itemIndex,
+ int &slotIndex, int &itemOffset) const = 0;
+ virtual int calcMaxSlotCount(const int itemCount) const = 0;
+
+ Info(const std::array<LayoutTheme, 2> &slotThemes,
+ const std::array<int, 2> &slotLens,
+ const int scrollLimit, const bool isHorizontal) :
+ slotThemes(slotThemes),
+ slotLens(slotLens),
+ scrollLimit(scrollLimit),
+ isHorizontal(isHorizontal)
+ {
+ }
+ };
+
+ // ImageGrid::HcombInfo //
+
+ struct ImageGrid::HcombInfo : Info {
+ const int totalLength;
+
+ virtual int calcItemIndexFromCell(
+ const int slotIndex, const int itemOffset) const final override
+ {
+ return ((slotIndex / 2 * totalLength) +
+ (itemOffset * 2) + ((slotIndex ^ 1) & 1));
+ }
+
+ virtual void calcCellFromItemIndex(const int itemIndex,
+ int &slotIndex, int &itemOffset) const final override
+ {
+ slotIndex = (itemIndex / totalLength);
+ itemOffset = (itemIndex % totalLength);
+ slotIndex += (slotIndex + ((itemOffset ^ 1) & 1));
+ itemOffset /= 2;
+ }
+
+ virtual int calcMaxSlotCount(const int itemCount) const final override
+ {
+ return ((itemCount + (totalLength - 1)) / totalLength * 2);
+ }
+
+ HcombInfo(const int totalLength,
+ const std::array<LayoutTheme, 2> &slotThemes) :
+ Info(slotThemes, {{(totalLength / 2), ceilDiv<2>(totalLength)}},
+ (totalLength - 1), true),
+ totalLength(totalLength)
+ {
+ }
+ };
+
+ // ImageGrid::Slot //
+
+ class ImageGrid::Slot {
+ private:
+ class Item {
+ public:
+ Item(const ImageGrid &imageGrid, Widget &parent) :
+ m_imageGrid(imageGrid),
+ m_image(evas_object_image_filled_add(parent.getEvas())),
+ m_realizeIndex(-1),
+ m_wasUpdated(false)
+ {
+ show(m_image);
+ }
+
+ Widget &getWidget()
+ {
+ return m_image;
+ }
+
+ void setImageLoadSize(const int value)
+ {
+ evas_object_image_load_size_set(m_image, value, value);
+ }
+
+ bool isRealized() const
+ {
+ return (m_realizeIndex >= 0);
+ }
+
+ void realize(const int itemIndex)
+ {
+ if (isRealized()) {
+ return;
+ }
+
+ m_wasUpdated = false;
+
+ if (itemIndex < m_imageGrid.m_itemCount) {
+ m_realizeIndex = itemIndex;
+
+ if (m_imageGrid.m_listener) {
+ m_imageGrid.m_listener->onItemRealized(itemIndex);
+ }
+ }
+
+ if (!m_wasUpdated) {
+ makeTransparent(m_image);
+ }
+ }
+
+ void unrealize()
+ {
+ if (!isRealized()) {
+ return;
+ }
+
+ const int itemIndex = m_realizeIndex;
+ m_realizeIndex = -1;
+
+ if (m_imageGrid.m_listener) {
+ m_imageGrid.m_listener->onItemUnrealized(itemIndex);
+ }
+ }
+
+ bool update(const ItemParams ¶ms)
+ {
+ if (!isRealized()) {
+ return false;
+ }
+
+ m_wasUpdated = true;
+
+ if (isEmpty(params.imagePath)) {
+ makeTransparent(m_image);
+ return true;
+ }
+
+ evas_object_image_file_set(m_image,
+ params.imagePath.c_str(), NULL);
+
+ int w, h;
+ getSize(m_image, &w, &h);
+ m_image.setARHint(WidgetARHint::NEITHER, w, h);
+
+ makeWhite(m_image);
+
+ return true;
+ }
+
+ private:
+ const ImageGrid &m_imageGrid;
+ Widget m_image;
+ int m_realizeIndex;
+ bool m_wasUpdated;
+ };
+
+ public:
+ Slot(ImageGrid &imageGrid, const bool isOdd) :
+ m_info(imageGrid.m_info),
+ m_layout(elm_layout_add(imageGrid.m_box), true),
+ m_isRealized(false)
+ {
+ if (!m_layout.setTheme(m_info.slotThemes[isOdd])) {
+ ELOG("setTheme() failed!");
+ }
+ fill(m_layout);
+ show(m_layout);
+
+ const int length = m_info.slotLens[isOdd];
+ for (int i = 0; i < length; ++i) {
+ m_items.emplace_back(new Item(imageGrid, m_layout));
+
+ m_layout.setContent(
+ EdjePart(impl::SLOT_PART_FMT.format(i)),
+ m_items.back()->getWidget());
+ }
+ }
+
+ Widget &getWidget()
+ {
+ return m_layout;
+ }
+
+ int calcSize()
+ {
+ int w = 0;
+ int h = 0;
+ m_layout.calculate();
+ m_layout.getMin(&w, &h);
+ return (m_info.isHorizontal ? w : h);
+ }
+
+ void setImageLoadSize(const int value)
+ {
+ for (auto &item: m_items) {
+ item->setImageLoadSize(value);
+ }
+ }
+
+ void unrealize()
+ {
+ if (!m_isRealized) {
+ return;
+ }
+ m_isRealized = false;
+
+ for (auto &item: m_items) {
+ item->unrealize();
+ }
+ }
+
+ void realize(const int slotIndex)
+ {
+ if (m_isRealized) {
+ return;
+ }
+ m_isRealized = true;
+
+ for (UInt i = 0; i < m_items.size(); ++i) {
+ m_items[i]->realize(
+ m_info.calcItemIndexFromCell(slotIndex, i));
+ }
+ }
+
+ bool updateItem(const int itemOffset, const ItemParams ¶ms)
+ {
+ return m_items[itemOffset]->update(params);
+ }
+
+ bool isItemRealized(const int itemOffset) const
+ {
+ return m_items[itemOffset]->isRealized();
+ }
+
+ private:
+ const Info &m_info;
+ std::vector<std::unique_ptr<Item>> m_items;
+ Layout m_layout;
+ bool m_isRealized;
+ };
+
+ // ImageGrid //
+
+ ImageGrid::ImageGrid(RefCountObjBase *const rc, const Type type,
+ Evas_Object *const scroller) :
+ Widget(rc, scroller, true),
+ m_info(getInfo(type)),
+
+ m_scroller(scroller),
+ m_box(elm_box_add(m_scroller)),
+ m_rect1(evas_object_rectangle_add(m_box.getEvas())),
+ m_rect2(evas_object_rectangle_add(m_box.getEvas())),
+
+ m_listener(nullptr),
+ m_itemCount(0),
+
+ m_slotCount(0), // Must be even >= 2
+ m_optimalSlotCount(2), // Must be even >= 2
+ m_maxSlotCount(2), // Must be even >= 2
+
+ m_beginSlotIndex(0),
+ m_maxBeginSlotIndex(0),
+
+ m_scrollBias(0),
+ m_padSize1(0),
+ m_padSize2(0),
+
+ m_slotSize(0), // Must not be 0
+ m_scrollerSize(1), // Must not be 0
+ m_scrollOffset(0)
+ {
+ prepare();
+
+ updateSlotCount();
+
+ updatePadSizes();
+ updateScrollBias();
+ updateRectMins();
+ }
+
+ const ImageGrid::Info &ImageGrid::getInfo(const Type type)
+ {
+ switch (type) {
+ case Type::HCOMB_3X3:
+ default: {
+ static HcombInfo info{3, {{
+ {"layout", "gallery_image_grid", "hcomb_3x3_even"},
+ {"layout", "gallery_image_grid", "hcomb_3x3_odd"}}}};
+ return info;
+ }
+ }
+ }
+
+ void ImageGrid::prepare()
+ {
+ fill(m_rect1);
+ elm_box_pack_end(m_box, m_rect1);
+ makeTransparent(m_rect1);
+ show(m_rect1);
+
+ expandAndFill(m_rect2);
+ elm_box_pack_end(m_box, m_rect2);
+ makeTransparent(m_rect2);
+ show(m_rect2);
+
+ expandAndFill(m_box);
+ m_scroller.setContent(m_box);
+ elm_box_horizontal_set(m_box, toEina(m_info.isHorizontal));
+ show(m_box);
+
+ expandAndFill(m_scroller);
+ if (m_info.isHorizontal) {
+ elm_scroller_page_scroll_limit_set(
+ m_scroller, m_info.scrollLimit, 0);
+ } else {
+ elm_scroller_page_scroll_limit_set(
+ m_scroller, 0, m_info.scrollLimit);
+ }
+ show(m_scroller);
+
+ m_scroller.addEventHandler(WidgetEvent::RESIZE,
+ WEAK_DELEGATE(ImageGrid::onScrollerResize, asWeak(this)));
+
+ m_scroller.addEventHandler(WidgetEvent::MOVE,
+ WEAK_DELEGATE(ImageGrid::onScrollerMove, asWeak(this)));
+
+ m_box.addEventHandler(WidgetEvent::MOVE,
+ WEAK_DELEGATE(ImageGrid::onBoxMove, asWeak(this)));
+ }
+
+ void ImageGrid::setListener(IListener *const listener)
+ {
+ m_listener = listener;
+ }
+
+ void ImageGrid::setItemCount(const int count)
+ {
+ if (m_itemCount == count) {
+ return;
+ }
+
+ unrealizeSlots(0, m_slotCount);
+
+ m_itemCount = count;
+
+ if (updateMaxSlotCount()) {
+ updateSlotCount();
+ if (updateMaxBeginSlotIndex()) {
+ updateBeginSlotIndex();
+ }
+ }
+
+ realizeSlots();
+ updateRectMins();
+ }
+
+ void ImageGrid::update()
+ {
+ unrealizeSlots(0, m_slotCount);
+ realizeSlots();
+ }
+
+ Result ImageGrid::updateItem(const int itemIndex, const ItemParams ¶ms)
+ {
+ return doWithItem(itemIndex,
+ [¶ms](Slot &slot, const int itemOffset)
+ {
+ return (slot.updateItem(itemOffset, params) ?
+ RES_OK : RES_FALSE);
+ });
+ }
+
+ Result ImageGrid::isItemRealized(const int itemIndex)
+ {
+ return doWithItem(itemIndex,
+ [](Slot &slot, const int itemOffset)
+ {
+ return (slot.isItemRealized(itemOffset) ? RES_OK : RES_FALSE);
+ });
+ }
+
+ template <class FUNC>
+ Result ImageGrid::doWithItem(const int itemIndex, FUNC &&func)
+ {
+ if ((itemIndex < 0) || (itemIndex >= m_itemCount)) {
+ LOG_RETURN(RES_INVALID_ARGUMENTS,
+ "Item index out of range: %d", itemIndex);
+ }
+
+ int slotIndex = 0;
+ int itemOffset = 0;
+ m_info.calcCellFromItemIndex(itemIndex, slotIndex, itemOffset);
+
+ const int slotOffset = (slotIndex - m_beginSlotIndex);
+ if ((slotOffset < 0) || (slotOffset >= m_slotCount)) {
+ return RES_FALSE;
+ }
+
+ return func(*m_slots[slotOffset], itemOffset);
+ }
+
+ bool ImageGrid::updateSlotCount()
+ {
+ const int newSlotCount = calcSlotCount();
+
+ if (newSlotCount != m_slotCount) {
+ DLOG("newSlotCount: %d; m_slotCount: %d;",
+ newSlotCount, m_slotCount);
+ setSlotCount(newSlotCount);
+ return true;
+ }
+
+ return false;
+ }
+
+ int ImageGrid::calcSlotCount()
+ {
+ return std::min(m_optimalSlotCount, m_maxSlotCount);
+ }
+
+ void ImageGrid::setSlotCount(const int newSlotCount)
+ {
+ for (int i = m_slotCount; i < newSlotCount; ++i) {
+ const bool isOdd = ((m_beginSlotIndex + i) & 1);
+
+ auto slot = util::makeUnique(new Slot(*this, isOdd));
+
+ if (m_slotSize == 0) {
+ UCL_ASSERT(!isOdd, "Must be even!");
+ m_slotSize = std::max(slot->calcSize(), 1);
+ if (m_info.isHorizontal) {
+ elm_scroller_page_size_set(m_scroller, m_slotSize, 0);
+ } else {
+ elm_scroller_page_size_set(m_scroller, 0, m_slotSize);
+ }
+ }
+
+ slot->setImageLoadSize(m_slotSize);
+
+ elm_box_pack_before(m_box, slot->getWidget(), m_rect2);
+
+ m_slots.emplace_back(std::move(slot));
+ }
+
+ unrealizeSlots(newSlotCount, m_slotCount);
+
+ m_slots.resize(newSlotCount);
+ m_slotCount = newSlotCount;
+ }
+
+ bool ImageGrid::updateOptimalSlotCount()
+ {
+ const int newOptimalSlotCount = calcOptimalSlotCount();
+
+ if (newOptimalSlotCount != m_optimalSlotCount) {
+ DLOG("newOptimalSlotCount: %d; m_optimalSlotCount: %d;",
+ newOptimalSlotCount, m_optimalSlotCount);
+ m_optimalSlotCount = newOptimalSlotCount;
+ return true;
+ }
+
+ return false;
+ }
+
+ int ImageGrid::calcOptimalSlotCount()
+ {
+ return ((((m_scrollerSize - 1) + (m_slotSize - 1)) /
+ m_slotSize + 1) * 2);
+ }
+
+ bool ImageGrid::updateMaxSlotCount()
+ {
+ const int newMaxSlotCount = calcMaxSlotCount();
+
+ if (newMaxSlotCount != m_maxSlotCount) {
+ DLOG("newMaxSlotCount: %d; m_maxSlotCount: %d;",
+ newMaxSlotCount, m_maxSlotCount);
+ m_maxSlotCount = newMaxSlotCount;
+ return true;
+ }
+
+ return false;
+ }
+
+ int ImageGrid::calcMaxSlotCount()
+ {
+ return std::max(m_info.calcMaxSlotCount(m_itemCount), 2);
+ }
+
+ bool ImageGrid::updateBeginSlotIndex()
+ {
+ const int newBeginSlotIndex = calcBeginSlotIndex();
+
+ if (newBeginSlotIndex != m_beginSlotIndex) {
+ DLOG("newBeginSlotIndex: %d; m_beginSlotIndex: %d;",
+ newBeginSlotIndex, m_beginSlotIndex);
+ setBeginSlotIndex(newBeginSlotIndex);
+ return true;
+ }
+
+ return false;
+ }
+
+ int ImageGrid::calcBeginSlotIndex()
+ {
+ const int evenScrolledSize = (m_scrollOffset - m_scrollBias);
+ const int oddScrolledSize = (evenScrolledSize - m_slotSize / 2);
+
+ const int beginEvenSlotIndex = (evenScrolledSize / m_slotSize);
+ const int beginOddSlotIndex = (oddScrolledSize / m_slotSize);
+
+ int beginSlotIndex = ((beginEvenSlotIndex <= beginOddSlotIndex) ?
+ (beginEvenSlotIndex * 2) : (beginOddSlotIndex * 2 + 1));
+
+ if (beginSlotIndex < 0) {
+ beginSlotIndex = 0;
+ } else if (beginSlotIndex > m_maxBeginSlotIndex) {
+ beginSlotIndex = m_maxBeginSlotIndex;
+ }
+
+ return beginSlotIndex;
+ }
+
+ void ImageGrid::setBeginSlotIndex(const int newBeginSlotIndex)
+ {
+ const int beginSlotIndex = m_beginSlotIndex;
+ const int endSlotIndex = (beginSlotIndex + m_slotCount);
+ const int newEndSlotIndex = (newBeginSlotIndex + m_slotCount);
+
+ if ((newEndSlotIndex <= beginSlotIndex) ||
+ (endSlotIndex <= newBeginSlotIndex)) {
+
+ unrealizeSlots(0, m_slotCount);
+
+ if ((beginSlotIndex ^ newBeginSlotIndex) & 1) {
+ rotateSlotsRight(1);
+ }
+
+ } else if (newBeginSlotIndex < beginSlotIndex) {
+ const int goodSlots = (newEndSlotIndex - beginSlotIndex);
+ const int badSlots = (m_slotCount - goodSlots);
+
+ unrealizeSlots(goodSlots, m_slotCount);
+
+ if (goodSlots > badSlots) {
+ rotateSlotsRight(badSlots);
+ } else {
+ rotateSlotsLeft(goodSlots);
+ }
+ } else {
+ const int goodSlots = (endSlotIndex - newBeginSlotIndex);
+ const int badSlots = (m_slotCount - goodSlots);
+
+ unrealizeSlots(0, badSlots);
+
+ if (goodSlots > badSlots) {
+ rotateSlotsLeft(badSlots);
+ } else {
+ rotateSlotsRight(goodSlots);
+ }
+ }
+
+ m_beginSlotIndex = newBeginSlotIndex;
+ }
+
+ bool ImageGrid::updateMaxBeginSlotIndex()
+ {
+ const int newMaxBeginSlotIndex = calcMaxBeginSlotIndex();
+
+ if (newMaxBeginSlotIndex != m_maxBeginSlotIndex) {
+ DLOG("newMaxBeginSlotIndex: %d; m_maxBeginSlotIndex: %d;",
+ newMaxBeginSlotIndex, m_maxBeginSlotIndex);
+ m_maxBeginSlotIndex = newMaxBeginSlotIndex;
+ return true;
+ }
+
+ return false;
+ }
+
+ int ImageGrid::calcMaxBeginSlotIndex()
+ {
+ return (m_maxSlotCount - m_slotCount);
+ }
+
+ void ImageGrid::updatePadSizes()
+ {
+ const int spaceSize = (m_scrollerSize -
+ ((m_scrollerSize / m_slotSize) * m_slotSize));
+
+ m_padSize1 = (spaceSize / 2);
+ m_padSize2 = (spaceSize - m_padSize1 + m_slotSize);
+ }
+
+ void ImageGrid::updateScrollBias()
+ {
+ m_scrollBias = (((m_optimalSlotCount / 2 - 1) * m_slotSize -
+ m_scrollerSize) / 2 + m_padSize1);
+ }
+
+ void ImageGrid::updateRectMins()
+ {
+ const int beginEvenCols = ((m_beginSlotIndex + 1) / 2);
+ const int sideEvenCols = ((m_maxSlotCount - m_slotCount) / 2);
+ const int endEvenCols = (sideEvenCols - beginEvenCols);
+
+ const int rectMin1 = (m_padSize1 + (beginEvenCols * m_slotSize));
+ const int rectMin2 = (m_padSize2 + (endEvenCols * m_slotSize));
+
+ if (m_info.isHorizontal) {
+ m_rect1.setMin(rectMin1, 0);
+ m_rect2.setMin(rectMin2, 0);
+ } else {
+ m_rect1.setMin(0, rectMin1);
+ m_rect2.setMin(0, rectMin2);
+ }
+ }
+
+ int ImageGrid::calcScrollerSize()
+ {
+ int scrollerW = 0;
+ int scrollerH = 0;
+ getSize(m_scroller, &scrollerW, &scrollerH);
+
+ return std::max((m_info.isHorizontal ? scrollerW : scrollerH), 1);
+ }
+
+ bool ImageGrid::updateScrollerSize()
+ {
+ const int newScrollerSize = calcScrollerSize();
+
+ if (newScrollerSize != m_scrollerSize) {
+ DLOG("newScrollerSize: %d; m_scrollerSize: %d;",
+ newScrollerSize, m_scrollerSize);
+ m_scrollerSize = newScrollerSize;
+ return true;
+ }
+
+ return false;
+ }
+
+ int ImageGrid::calcScrollOffset()
+ {
+ int scrollerX = 0;
+ int scrollerY = 0;
+ getPosition(m_scroller, &scrollerX, &scrollerY);
+
+ int boxX = 0;
+ int boxY = 0;
+ getPosition(m_box, &boxX, &boxY);
+
+ int scrollOffset = (m_info.isHorizontal ?
+ (scrollerX - boxX) : (scrollerY - boxY));
+ if (scrollOffset < 0) {
+ scrollOffset = 0;
+ }
+
+ return scrollOffset;
+ }
+
+ bool ImageGrid::updateScrollOffset()
+ {
+ const int newScrollOffset = calcScrollOffset();
+
+ if (newScrollOffset != m_scrollOffset) {
+ DLOG("newScrollOffset: %d; m_scrollOffset: %d;",
+ newScrollOffset, m_scrollOffset);
+ m_scrollOffset= newScrollOffset;
+ return true;
+ }
+
+ return false;
+ }
+
+ void ImageGrid::rotateSlotsRight(const int count)
+ {
+ DLOG("count: %d", count);
+ 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);
+ m_slots.emplace_front(std::move(slot));
+ }
+ }
+
+ void ImageGrid::rotateSlotsLeft(const int count)
+ {
+ DLOG("count: %d", count);
+ 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);
+ m_slots.emplace_back(std::move(slot));
+ }
+ }
+
+ void ImageGrid::realizeSlots()
+ {
+ for (int i = 0; i < m_slotCount; ++i) {
+ m_slots[i]->realize(m_beginSlotIndex + i);
+ }
+ }
+
+ void ImageGrid::unrealizeSlots(
+ const int beginSlotOffset, const int endSlotOffset)
+ {
+ for (int i = beginSlotOffset; i < endSlotOffset; ++i) {
+ m_slots[i]->unrealize();
+ }
+ }
+
+ void ImageGrid::handleScrolling()
+ {
+ if (updateScrollOffset() && updateBeginSlotIndex()) {
+ realizeSlots();
+ updateRectMins();
+ }
+ }
+
+ void ImageGrid::handleResize()
+ {
+ if (updateScrollerSize()) {
+ bool needRealize = false;
+
+ updatePadSizes();
+
+ if (updateOptimalSlotCount() && updateSlotCount()) {
+ updateMaxBeginSlotIndex();
+ needRealize = true;
+ }
+
+ updateScrollBias();
+
+ if (updateBeginSlotIndex()) {
+ needRealize = true;
+ }
+
+ if (needRealize) {
+ realizeSlots();
+ }
+ updateRectMins();
+ }
+ }
+
+ void ImageGrid::onScrollerResize(Widget &sender, void *eventInfo)
+ {
+ handleResize();
+ }
+
+ void ImageGrid::onScrollerMove(Widget &sender, void *eventInfo)
+ {
+ handleScrolling();
+ }
+
+ void ImageGrid::onBoxMove(Widget &sender, void *eventInfo)
+ {
+ handleScrolling();
+ }
+}
--- /dev/null
+/*
+ * 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 "presentation/Page.h"
+
+#include <efl_extension.h>
+
+#include "../common.h"
+
+namespace gallery { namespace { namespace impl {
+
+ using namespace ucl;
+
+ constexpr SmartEvent TOP_PAGE_CHANGED {"ucl,top,page,changed"};
+}}}
+
+namespace gallery {
+
+ using namespace ucl;
+
+ Page::Page(RefCountObjBase &rc, const NaviframeSRef &navi,
+ ExitRequestHandler onExitRequest) :
+ RefCountAware(&rc),
+ m_navi(navi),
+ m_onExitRequest(onExitRequest),
+ m_isActive(false)
+ {
+ UCL_ASSERT(navi, "navi is NULL!");
+ UCL_ASSERT(onExitRequest, "onExitRequest is NULL!");
+ }
+
+ Page::~Page()
+ {
+ }
+
+ Result Page::preparePart2()
+ {
+ Evas_Object *content = m_item.getContent();
+ if (!content) {
+ LOG_RETURN(RES_FAIL, "content is NULL");
+ }
+
+ m_navi->addEventHandler(NAVI_TRANSITION_STARTED,
+ WEAK_DELEGATE(Page::onTransitionStarted, asWeak(*this)));
+
+ m_navi->addEventHandler(NAVI_TRANSITION_FINISHED,
+ WEAK_DELEGATE(Page::onTransitionFinished, asWeak(*this)));
+
+ m_navi->addEventHandler(impl::TOP_PAGE_CHANGED,
+ WEAK_DELEGATE(Page::onTopPageChanged, asWeak(*this)));
+
+ eext_object_event_callback_add(content, EEXT_CALLBACK_BACK,
+ CALLBACK_A(Page::onHWBackKey), this);
+
+ m_item.setData(this);
+ m_item.setDelCallback(CALLBACK_A(Page::onItemDel));
+
+ m_rc->ref();
+
+ if (!m_navi->isInTransition()) {
+ dispatchTopPageChanged();
+ }
+
+ return RES_OK;
+ }
+
+ void Page::dispatchTopPageChanged()
+ {
+ m_navi->callSmartEvent(impl::TOP_PAGE_CHANGED, nullptr);
+ }
+
+ void Page::onItemDel(Evas_Object *obj, void *eventInfo)
+ {
+ m_item = nullptr;
+ m_rc->unref();
+ }
+
+ void Page::exit()
+ {
+ if (isAtTop() && !isAtBottom()) {
+ m_navi->pop();
+ m_item = nullptr;
+ } else {
+ exitNoTransition();
+ }
+ }
+
+ void Page::exitNoTransition()
+ {
+ if (isValid(m_item)) {
+ m_item.del();
+ dispatchTopPageChanged();
+ }
+ }
+
+ void Page::popTo()
+ {
+ if (isValid(m_item) && !isAtTop()) {
+ m_item.popTo();
+ }
+ }
+
+ void Page::deleteTo()
+ {
+ if (isValid(m_item) && !isAtTop()) {
+ while (!isAtTop()) {
+ m_navi->getTopItem().del();
+ }
+ dispatchTopPageChanged();
+ }
+ }
+
+ void Page::promote()
+ {
+ if (isValid(m_item) && !isAtTop()) {
+ m_item.promote();
+ }
+ }
+
+ NaviItem Page::getItem()
+ {
+ return m_item;
+ }
+
+ void Page::requestExit()
+ {
+ m_onExitRequest(*this);
+ }
+
+ void Page::activate()
+ {
+ if (!m_isActive) {
+ m_isActive = true;
+ onActivate();
+ }
+ }
+
+ void Page::deactivate()
+ {
+ if (m_isActive) {
+ m_isActive = false;
+ onDeactivate();
+ }
+ }
+
+ void Page::updateActiveState()
+ {
+ if (isAtTop()) {
+ activate();
+ } else {
+ deactivate();
+ }
+ }
+
+ void Page::onTransitionStarted(Widget &widget, void *eventInfo)
+ {
+ deactivate();
+ }
+
+ void Page::onTransitionFinished(Widget &widget, void *eventInfo)
+ {
+ updateActiveState();
+ }
+
+ void Page::onTopPageChanged(Widget &widget, void *eventInfo)
+ {
+ updateActiveState();
+ }
+
+ void Page::onHWBackKey(Evas_Object *obj, void *eventInfo)
+ {
+ if (m_isActive) {
+ onBackKey();
+ }
+ }
+
+ void Page::onActivate()
+ {
+ }
+
+ void Page::onDeactivate()
+ {
+ }
+
+ void Page::onBackKey()
+ {
+ requestExit();
+ }
+}
+++ /dev/null
-/*
- * 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 "view/ImageGrid.h"
-
-#include <array>
-#include <vector>
-
-#include "ucl/gui/Layout.h"
-
-#include "../common.h"
-
-namespace gallery { namespace { namespace impl {
-
- using namespace ucl;
-
- const TString SLOT_PART_FMT = {"swallow.cell_%d"};
-}}}
-
-namespace gallery {
-
- using namespace ucl;
-
- // ImageGrid::Builder //
-
- ImageGrid::Builder::Builder() :
- m_type(Type::HCOMB_3X3),
- m_listener(nullptr)
- {
- }
-
- ImageGrid::Builder &ImageGrid::Builder::setType(const Type value)
- {
- m_type = value;
- return *this;
- }
-
- ImageGrid::Builder &ImageGrid::Builder::setListener(IListener *const value)
- {
- m_listener = value;
- return *this;
- }
-
- ImageGridSRef ImageGrid::Builder::build(Widget &parent) const
- {
- Evas_Object *const scrollerEo = elm_scroller_add(parent);
- if (!scrollerEo) {
- ELOG("elm_scroller_add() failed!");
- return {};
- }
-
- auto result = makeShared<ImageGrid>(m_type, scrollerEo);
-
- result->bindToEo();
- result->setListener(m_listener);
-
- return result;
- }
-
- // ImageGrid::Info //
-
- struct ImageGrid::Info {
- const std::array<LayoutTheme, 2> slotThemes;
- const std::array<int, 2> slotLens;
- const int scrollLimit;
- const bool isHorizontal;
-
- virtual int calcItemIndexFromCell(
- const int slotIndex, const int itemOffset) const = 0;
- virtual void calcCellFromItemIndex(const int itemIndex,
- int &slotIndex, int &itemOffset) const = 0;
- virtual int calcMaxSlotCount(const int itemCount) const = 0;
-
- Info(const std::array<LayoutTheme, 2> &slotThemes,
- const std::array<int, 2> &slotLens,
- const int scrollLimit, const bool isHorizontal) :
- slotThemes(slotThemes),
- slotLens(slotLens),
- scrollLimit(scrollLimit),
- isHorizontal(isHorizontal)
- {
- }
- };
-
- // ImageGrid::HcombInfo //
-
- struct ImageGrid::HcombInfo : Info {
- const int totalLength;
-
- virtual int calcItemIndexFromCell(
- const int slotIndex, const int itemOffset) const final override
- {
- return ((slotIndex / 2 * totalLength) +
- (itemOffset * 2) + ((slotIndex ^ 1) & 1));
- }
-
- virtual void calcCellFromItemIndex(const int itemIndex,
- int &slotIndex, int &itemOffset) const final override
- {
- slotIndex = (itemIndex / totalLength);
- itemOffset = (itemIndex % totalLength);
- slotIndex += (slotIndex + ((itemOffset ^ 1) & 1));
- itemOffset /= 2;
- }
-
- virtual int calcMaxSlotCount(const int itemCount) const final override
- {
- return ((itemCount + (totalLength - 1)) / totalLength * 2);
- }
-
- HcombInfo(const int totalLength,
- const std::array<LayoutTheme, 2> &slotThemes) :
- Info(slotThemes, {{(totalLength / 2), ceilDiv<2>(totalLength)}},
- (totalLength - 1), true),
- totalLength(totalLength)
- {
- }
- };
-
- // ImageGrid::Slot //
-
- class ImageGrid::Slot {
- private:
- class Item {
- public:
- Item(const ImageGrid &imageGrid, Widget &parent) :
- m_imageGrid(imageGrid),
- m_image(evas_object_image_filled_add(parent.getEvas())),
- m_realizeIndex(-1),
- m_wasUpdated(false)
- {
- show(m_image);
- }
-
- Widget &getWidget()
- {
- return m_image;
- }
-
- void setImageLoadSize(const int value)
- {
- evas_object_image_load_size_set(m_image, value, value);
- }
-
- bool isRealized() const
- {
- return (m_realizeIndex >= 0);
- }
-
- void realize(const int itemIndex)
- {
- if (isRealized()) {
- return;
- }
-
- m_wasUpdated = false;
-
- if (itemIndex < m_imageGrid.m_itemCount) {
- m_realizeIndex = itemIndex;
-
- if (m_imageGrid.m_listener) {
- m_imageGrid.m_listener->onItemRealized(itemIndex);
- }
- }
-
- if (!m_wasUpdated) {
- makeTransparent(m_image);
- }
- }
-
- void unrealize()
- {
- if (!isRealized()) {
- return;
- }
-
- const int itemIndex = m_realizeIndex;
- m_realizeIndex = -1;
-
- if (m_imageGrid.m_listener) {
- m_imageGrid.m_listener->onItemUnrealized(itemIndex);
- }
- }
-
- bool update(const ItemParams ¶ms)
- {
- if (!isRealized()) {
- return false;
- }
-
- m_wasUpdated = true;
-
- if (isEmpty(params.imagePath)) {
- makeTransparent(m_image);
- return true;
- }
-
- evas_object_image_file_set(m_image,
- params.imagePath.c_str(), NULL);
-
- int w, h;
- getSize(m_image, &w, &h);
- m_image.setARHint(WidgetARHint::NEITHER, w, h);
-
- makeWhite(m_image);
-
- return true;
- }
-
- private:
- const ImageGrid &m_imageGrid;
- Widget m_image;
- int m_realizeIndex;
- bool m_wasUpdated;
- };
-
- public:
- Slot(ImageGrid &imageGrid, const bool isOdd) :
- m_info(imageGrid.m_info),
- m_layout(elm_layout_add(imageGrid.m_box), true),
- m_isRealized(false)
- {
- if (!m_layout.setTheme(m_info.slotThemes[isOdd])) {
- ELOG("setTheme() failed!");
- }
- fill(m_layout);
- show(m_layout);
-
- const int length = m_info.slotLens[isOdd];
- for (int i = 0; i < length; ++i) {
- m_items.emplace_back(new Item(imageGrid, m_layout));
-
- m_layout.setContent(
- EdjePart(impl::SLOT_PART_FMT.format(i)),
- m_items.back()->getWidget());
- }
- }
-
- Widget &getWidget()
- {
- return m_layout;
- }
-
- int calcSize()
- {
- int w = 0;
- int h = 0;
- m_layout.calculate();
- m_layout.getMin(&w, &h);
- return (m_info.isHorizontal ? w : h);
- }
-
- void setImageLoadSize(const int value)
- {
- for (auto &item: m_items) {
- item->setImageLoadSize(value);
- }
- }
-
- void unrealize()
- {
- if (!m_isRealized) {
- return;
- }
- m_isRealized = false;
-
- for (auto &item: m_items) {
- item->unrealize();
- }
- }
-
- void realize(const int slotIndex)
- {
- if (m_isRealized) {
- return;
- }
- m_isRealized = true;
-
- for (UInt i = 0; i < m_items.size(); ++i) {
- m_items[i]->realize(
- m_info.calcItemIndexFromCell(slotIndex, i));
- }
- }
-
- bool updateItem(const int itemOffset, const ItemParams ¶ms)
- {
- return m_items[itemOffset]->update(params);
- }
-
- bool isItemRealized(const int itemOffset) const
- {
- return m_items[itemOffset]->isRealized();
- }
-
- private:
- const Info &m_info;
- std::vector<std::unique_ptr<Item>> m_items;
- Layout m_layout;
- bool m_isRealized;
- };
-
- // ImageGrid //
-
- ImageGrid::ImageGrid(RefCountObjBase *const rc, const Type type,
- Evas_Object *const scroller) :
- Widget(rc, scroller, true),
- m_info(getInfo(type)),
-
- m_scroller(scroller),
- m_box(elm_box_add(m_scroller)),
- m_rect1(evas_object_rectangle_add(m_box.getEvas())),
- m_rect2(evas_object_rectangle_add(m_box.getEvas())),
-
- m_listener(nullptr),
- m_itemCount(0),
-
- m_slotCount(0), // Must be even >= 2
- m_optimalSlotCount(2), // Must be even >= 2
- m_maxSlotCount(2), // Must be even >= 2
-
- m_beginSlotIndex(0),
- m_maxBeginSlotIndex(0),
-
- m_scrollBias(0),
- m_padSize1(0),
- m_padSize2(0),
-
- m_slotSize(0), // Must not be 0
- m_scrollerSize(1), // Must not be 0
- m_scrollOffset(0)
- {
- prepare();
-
- updateSlotCount();
-
- updatePadSizes();
- updateScrollBias();
- updateRectMins();
- }
-
- const ImageGrid::Info &ImageGrid::getInfo(const Type type)
- {
- switch (type) {
- case Type::HCOMB_3X3:
- default: {
- static HcombInfo info{3, {{
- {"layout", "gallery_image_grid", "hcomb_3x3_even"},
- {"layout", "gallery_image_grid", "hcomb_3x3_odd"}}}};
- return info;
- }
- }
- }
-
- void ImageGrid::prepare()
- {
- fill(m_rect1);
- elm_box_pack_end(m_box, m_rect1);
- makeTransparent(m_rect1);
- show(m_rect1);
-
- expandAndFill(m_rect2);
- elm_box_pack_end(m_box, m_rect2);
- makeTransparent(m_rect2);
- show(m_rect2);
-
- expandAndFill(m_box);
- m_scroller.setContent(m_box);
- elm_box_horizontal_set(m_box, toEina(m_info.isHorizontal));
- show(m_box);
-
- expandAndFill(m_scroller);
- if (m_info.isHorizontal) {
- elm_scroller_page_scroll_limit_set(
- m_scroller, m_info.scrollLimit, 0);
- } else {
- elm_scroller_page_scroll_limit_set(
- m_scroller, 0, m_info.scrollLimit);
- }
- show(m_scroller);
-
- m_scroller.addEventHandler(WidgetEvent::RESIZE,
- WEAK_DELEGATE(ImageGrid::onScrollerResize, asWeak(this)));
-
- m_scroller.addEventHandler(WidgetEvent::MOVE,
- WEAK_DELEGATE(ImageGrid::onScrollerMove, asWeak(this)));
-
- m_box.addEventHandler(WidgetEvent::MOVE,
- WEAK_DELEGATE(ImageGrid::onBoxMove, asWeak(this)));
- }
-
- void ImageGrid::setListener(IListener *const listener)
- {
- m_listener = listener;
- }
-
- void ImageGrid::setItemCount(const int count)
- {
- if (m_itemCount == count) {
- return;
- }
-
- unrealizeSlots(0, m_slotCount);
-
- m_itemCount = count;
-
- if (updateMaxSlotCount()) {
- updateSlotCount();
- if (updateMaxBeginSlotIndex()) {
- updateBeginSlotIndex();
- }
- }
-
- realizeSlots();
- updateRectMins();
- }
-
- void ImageGrid::update()
- {
- unrealizeSlots(0, m_slotCount);
- realizeSlots();
- }
-
- Result ImageGrid::updateItem(const int itemIndex, const ItemParams ¶ms)
- {
- return doWithItem(itemIndex,
- [¶ms](Slot &slot, const int itemOffset)
- {
- return (slot.updateItem(itemOffset, params) ?
- RES_OK : RES_FALSE);
- });
- }
-
- Result ImageGrid::isItemRealized(const int itemIndex)
- {
- return doWithItem(itemIndex,
- [](Slot &slot, const int itemOffset)
- {
- return (slot.isItemRealized(itemOffset) ? RES_OK : RES_FALSE);
- });
- }
-
- template <class FUNC>
- Result ImageGrid::doWithItem(const int itemIndex, FUNC &&func)
- {
- if ((itemIndex < 0) || (itemIndex >= m_itemCount)) {
- LOG_RETURN(RES_INVALID_ARGUMENTS,
- "Item index out of range: %d", itemIndex);
- }
-
- int slotIndex = 0;
- int itemOffset = 0;
- m_info.calcCellFromItemIndex(itemIndex, slotIndex, itemOffset);
-
- const int slotOffset = (slotIndex - m_beginSlotIndex);
- if ((slotOffset < 0) || (slotOffset >= m_slotCount)) {
- return RES_FALSE;
- }
-
- return func(*m_slots[slotOffset], itemOffset);
- }
-
- bool ImageGrid::updateSlotCount()
- {
- const int newSlotCount = calcSlotCount();
-
- if (newSlotCount != m_slotCount) {
- DLOG("newSlotCount: %d; m_slotCount: %d;",
- newSlotCount, m_slotCount);
- setSlotCount(newSlotCount);
- return true;
- }
-
- return false;
- }
-
- int ImageGrid::calcSlotCount()
- {
- return std::min(m_optimalSlotCount, m_maxSlotCount);
- }
-
- void ImageGrid::setSlotCount(const int newSlotCount)
- {
- for (int i = m_slotCount; i < newSlotCount; ++i) {
- const bool isOdd = ((m_beginSlotIndex + i) & 1);
-
- auto slot = util::makeUnique(new Slot(*this, isOdd));
-
- if (m_slotSize == 0) {
- UCL_ASSERT(!isOdd, "Must be even!");
- m_slotSize = std::max(slot->calcSize(), 1);
- if (m_info.isHorizontal) {
- elm_scroller_page_size_set(m_scroller, m_slotSize, 0);
- } else {
- elm_scroller_page_size_set(m_scroller, 0, m_slotSize);
- }
- }
-
- slot->setImageLoadSize(m_slotSize);
-
- elm_box_pack_before(m_box, slot->getWidget(), m_rect2);
-
- m_slots.emplace_back(std::move(slot));
- }
-
- unrealizeSlots(newSlotCount, m_slotCount);
-
- m_slots.resize(newSlotCount);
- m_slotCount = newSlotCount;
- }
-
- bool ImageGrid::updateOptimalSlotCount()
- {
- const int newOptimalSlotCount = calcOptimalSlotCount();
-
- if (newOptimalSlotCount != m_optimalSlotCount) {
- DLOG("newOptimalSlotCount: %d; m_optimalSlotCount: %d;",
- newOptimalSlotCount, m_optimalSlotCount);
- m_optimalSlotCount = newOptimalSlotCount;
- return true;
- }
-
- return false;
- }
-
- int ImageGrid::calcOptimalSlotCount()
- {
- return ((((m_scrollerSize - 1) + (m_slotSize - 1)) /
- m_slotSize + 1) * 2);
- }
-
- bool ImageGrid::updateMaxSlotCount()
- {
- const int newMaxSlotCount = calcMaxSlotCount();
-
- if (newMaxSlotCount != m_maxSlotCount) {
- DLOG("newMaxSlotCount: %d; m_maxSlotCount: %d;",
- newMaxSlotCount, m_maxSlotCount);
- m_maxSlotCount = newMaxSlotCount;
- return true;
- }
-
- return false;
- }
-
- int ImageGrid::calcMaxSlotCount()
- {
- return std::max(m_info.calcMaxSlotCount(m_itemCount), 2);
- }
-
- bool ImageGrid::updateBeginSlotIndex()
- {
- const int newBeginSlotIndex = calcBeginSlotIndex();
-
- if (newBeginSlotIndex != m_beginSlotIndex) {
- DLOG("newBeginSlotIndex: %d; m_beginSlotIndex: %d;",
- newBeginSlotIndex, m_beginSlotIndex);
- setBeginSlotIndex(newBeginSlotIndex);
- return true;
- }
-
- return false;
- }
-
- int ImageGrid::calcBeginSlotIndex()
- {
- const int evenScrolledSize = (m_scrollOffset - m_scrollBias);
- const int oddScrolledSize = (evenScrolledSize - m_slotSize / 2);
-
- const int beginEvenSlotIndex = (evenScrolledSize / m_slotSize);
- const int beginOddSlotIndex = (oddScrolledSize / m_slotSize);
-
- int beginSlotIndex = ((beginEvenSlotIndex <= beginOddSlotIndex) ?
- (beginEvenSlotIndex * 2) : (beginOddSlotIndex * 2 + 1));
-
- if (beginSlotIndex < 0) {
- beginSlotIndex = 0;
- } else if (beginSlotIndex > m_maxBeginSlotIndex) {
- beginSlotIndex = m_maxBeginSlotIndex;
- }
-
- return beginSlotIndex;
- }
-
- void ImageGrid::setBeginSlotIndex(const int newBeginSlotIndex)
- {
- const int beginSlotIndex = m_beginSlotIndex;
- const int endSlotIndex = (beginSlotIndex + m_slotCount);
- const int newEndSlotIndex = (newBeginSlotIndex + m_slotCount);
-
- if ((newEndSlotIndex <= beginSlotIndex) ||
- (endSlotIndex <= newBeginSlotIndex)) {
-
- unrealizeSlots(0, m_slotCount);
-
- if ((beginSlotIndex ^ newBeginSlotIndex) & 1) {
- rotateSlotsRight(1);
- }
-
- } else if (newBeginSlotIndex < beginSlotIndex) {
- const int goodSlots = (newEndSlotIndex - beginSlotIndex);
- const int badSlots = (m_slotCount - goodSlots);
-
- unrealizeSlots(goodSlots, m_slotCount);
-
- if (goodSlots > badSlots) {
- rotateSlotsRight(badSlots);
- } else {
- rotateSlotsLeft(goodSlots);
- }
- } else {
- const int goodSlots = (endSlotIndex - newBeginSlotIndex);
- const int badSlots = (m_slotCount - goodSlots);
-
- unrealizeSlots(0, badSlots);
-
- if (goodSlots > badSlots) {
- rotateSlotsLeft(badSlots);
- } else {
- rotateSlotsRight(goodSlots);
- }
- }
-
- m_beginSlotIndex = newBeginSlotIndex;
- }
-
- bool ImageGrid::updateMaxBeginSlotIndex()
- {
- const int newMaxBeginSlotIndex = calcMaxBeginSlotIndex();
-
- if (newMaxBeginSlotIndex != m_maxBeginSlotIndex) {
- DLOG("newMaxBeginSlotIndex: %d; m_maxBeginSlotIndex: %d;",
- newMaxBeginSlotIndex, m_maxBeginSlotIndex);
- m_maxBeginSlotIndex = newMaxBeginSlotIndex;
- return true;
- }
-
- return false;
- }
-
- int ImageGrid::calcMaxBeginSlotIndex()
- {
- return (m_maxSlotCount - m_slotCount);
- }
-
- void ImageGrid::updatePadSizes()
- {
- const int spaceSize = (m_scrollerSize -
- ((m_scrollerSize / m_slotSize) * m_slotSize));
-
- m_padSize1 = (spaceSize / 2);
- m_padSize2 = (spaceSize - m_padSize1 + m_slotSize);
- }
-
- void ImageGrid::updateScrollBias()
- {
- m_scrollBias = (((m_optimalSlotCount / 2 - 1) * m_slotSize -
- m_scrollerSize) / 2 + m_padSize1);
- }
-
- void ImageGrid::updateRectMins()
- {
- const int beginEvenCols = ((m_beginSlotIndex + 1) / 2);
- const int sideEvenCols = ((m_maxSlotCount - m_slotCount) / 2);
- const int endEvenCols = (sideEvenCols - beginEvenCols);
-
- const int rectMin1 = (m_padSize1 + (beginEvenCols * m_slotSize));
- const int rectMin2 = (m_padSize2 + (endEvenCols * m_slotSize));
-
- if (m_info.isHorizontal) {
- m_rect1.setMin(rectMin1, 0);
- m_rect2.setMin(rectMin2, 0);
- } else {
- m_rect1.setMin(0, rectMin1);
- m_rect2.setMin(0, rectMin2);
- }
- }
-
- int ImageGrid::calcScrollerSize()
- {
- int scrollerW = 0;
- int scrollerH = 0;
- getSize(m_scroller, &scrollerW, &scrollerH);
-
- return std::max((m_info.isHorizontal ? scrollerW : scrollerH), 1);
- }
-
- bool ImageGrid::updateScrollerSize()
- {
- const int newScrollerSize = calcScrollerSize();
-
- if (newScrollerSize != m_scrollerSize) {
- DLOG("newScrollerSize: %d; m_scrollerSize: %d;",
- newScrollerSize, m_scrollerSize);
- m_scrollerSize = newScrollerSize;
- return true;
- }
-
- return false;
- }
-
- int ImageGrid::calcScrollOffset()
- {
- int scrollerX = 0;
- int scrollerY = 0;
- getPosition(m_scroller, &scrollerX, &scrollerY);
-
- int boxX = 0;
- int boxY = 0;
- getPosition(m_box, &boxX, &boxY);
-
- int scrollOffset = (m_info.isHorizontal ?
- (scrollerX - boxX) : (scrollerY - boxY));
- if (scrollOffset < 0) {
- scrollOffset = 0;
- }
-
- return scrollOffset;
- }
-
- bool ImageGrid::updateScrollOffset()
- {
- const int newScrollOffset = calcScrollOffset();
-
- if (newScrollOffset != m_scrollOffset) {
- DLOG("newScrollOffset: %d; m_scrollOffset: %d;",
- newScrollOffset, m_scrollOffset);
- m_scrollOffset= newScrollOffset;
- return true;
- }
-
- return false;
- }
-
- void ImageGrid::rotateSlotsRight(const int count)
- {
- DLOG("count: %d", count);
- 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);
- m_slots.emplace_front(std::move(slot));
- }
- }
-
- void ImageGrid::rotateSlotsLeft(const int count)
- {
- DLOG("count: %d", count);
- 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);
- m_slots.emplace_back(std::move(slot));
- }
- }
-
- void ImageGrid::realizeSlots()
- {
- for (int i = 0; i < m_slotCount; ++i) {
- m_slots[i]->realize(m_beginSlotIndex + i);
- }
- }
-
- void ImageGrid::unrealizeSlots(
- const int beginSlotOffset, const int endSlotOffset)
- {
- for (int i = beginSlotOffset; i < endSlotOffset; ++i) {
- m_slots[i]->unrealize();
- }
- }
-
- void ImageGrid::handleScrolling()
- {
- if (updateScrollOffset() && updateBeginSlotIndex()) {
- realizeSlots();
- updateRectMins();
- }
- }
-
- void ImageGrid::handleResize()
- {
- if (updateScrollerSize()) {
- bool needRealize = false;
-
- updatePadSizes();
-
- if (updateOptimalSlotCount() && updateSlotCount()) {
- updateMaxBeginSlotIndex();
- needRealize = true;
- }
-
- updateScrollBias();
-
- if (updateBeginSlotIndex()) {
- needRealize = true;
- }
-
- if (needRealize) {
- realizeSlots();
- }
- updateRectMins();
- }
- }
-
- void ImageGrid::onScrollerResize(Widget &sender, void *eventInfo)
- {
- handleResize();
- }
-
- void ImageGrid::onScrollerMove(Widget &sender, void *eventInfo)
- {
- handleScrolling();
- }
-
- void ImageGrid::onBoxMove(Widget &sender, void *eventInfo)
- {
- handleScrolling();
- }
-}
namespace ucl {
- class NaviItem : public WidgetItem {
+ class NaviItem final : public WidgetItem {
public:
using PopHandler = Delegate<Eina_Bool(Elm_Object_Item *)>;
handler.getStubA(), handler.getData());
}
- inline void NaviItem::popTo() const
- {
- elm_naviframe_item_pop_to(getIt());
- }
-
- inline void NaviItem::promote() const
- {
- elm_naviframe_item_promote(getIt());
- }
-
inline void NaviItem::setTitleEnabled(
const bool value, const bool useTransition) const
{
namespace ucl {
+ constexpr SmartEvent NAVI_TRANSITION_STARTED {"ucl,transition,started"};
+ constexpr SmartEvent NAVI_TRANSITION_FINISHED {"transition,finished"};
+
UCL_DECLARE_REF_ALIASES(Naviframe);
- class Naviframe : public StyledWidget {
+ class Naviframe final : public StyledWidget {
public:
- static constexpr SmartEvent TRANSITION_FINISHED {"transition,finished"};
-
class Builder {
public:
Builder();
friend class RefCountObj<Naviframe>;
using StyledWidget::StyledWidget;
+ bool isInTransition() const;
+
void setAutoBackBtn(bool value);
bool isAutoBackBtn() const;
NaviItem push(const TString &title, Evas_Object *content);
NaviItem push(Evas_Object *content);
- NaviItem insertAfter(const TString &title, NaviItem after,
+ NaviItem insertAfter(NaviItem after, const TString &title,
Evas_Object *backBtn, Evas_Object *moreBtn,
Evas_Object *content, ElmStyle style);
- NaviItem insertAfter(const TString &title, NaviItem after,
+ NaviItem insertAfter(NaviItem after, const TString &title,
Evas_Object *content);
NaviItem insertAfter(NaviItem after,
Evas_Object *content);
- NaviItem insertBefore(const TString &title, NaviItem before,
+ NaviItem insertBefore(NaviItem before, const TString &title,
Evas_Object *backBtn, Evas_Object *moreBtn,
Evas_Object *content, ElmStyle style);
- NaviItem insertBefore(const TString &title, NaviItem before,
+ NaviItem insertBefore(NaviItem before, const TString &title,
Evas_Object *content);
NaviItem insertBefore(NaviItem before,
Evas_Object *content);
NaviItem getTopItem()const;
NaviItem getBottomItem() const;
std::vector<NaviItem> getItems() const;
+
+ private:
+ friend class RefCountObj<Naviframe>;
+ friend class NaviItem;
+ Naviframe(RefCountObjBase &rc, Evas_Object *eo, bool isOwner = false);
+
+ void startTransition();
+
+ void onTransitionFinished(Widget &widget, void *eventInfo);
+
+ private:
+ bool m_isInTransition;
};
}
// Naviframe //
+ inline bool Naviframe::isInTransition() const
+ {
+ return m_isInTransition;
+ }
+
inline void Naviframe::setAutoBackBtn(const bool value)
{
elm_naviframe_prev_btn_auto_pushed_set(getEo(), toEina(value));
inline Evas_Object *Naviframe::pop()
{
- return elm_naviframe_item_pop(getEo());
+ auto result = elm_naviframe_item_pop(getEo());
+ if (isValid(getBottomItem())) {
+ startTransition();
+ }
+ return result;
}
inline NaviItem Naviframe::push(const TString &title,
auto result = NaviItem(elm_naviframe_item_push(getEo(),
nullptr, backBtn, moreBtn, content, style.name));
result.setTitle(title);
+ if (result != getBottomItem()) {
+ startTransition();
+ }
return result;
}
return push(nullptr, nullptr, nullptr, content, nullptr);
}
- inline NaviItem Naviframe::insertAfter(const TString &title,
- NaviItem after,
+ inline NaviItem Naviframe::insertAfter(NaviItem after,
+ const TString &title,
Evas_Object *const backBtn, Evas_Object *const moreBtn,
Evas_Object *const content, const ElmStyle style)
{
return result;
}
- inline NaviItem Naviframe::insertAfter(const TString &title,
- NaviItem after, Evas_Object *const content)
+ inline NaviItem Naviframe::insertAfter(NaviItem after,
+ const TString &title, Evas_Object *const content)
{
- return insertAfter(title, after, nullptr, nullptr, content, nullptr);
+ return insertAfter(after, title, nullptr, nullptr, content, nullptr);
}
inline NaviItem Naviframe::insertAfter(NaviItem after,
Evas_Object *const content)
{
- return insertAfter(nullptr, after, nullptr, nullptr, content, nullptr);
+ return insertAfter(after, nullptr, nullptr, nullptr, content, nullptr);
}
- inline NaviItem Naviframe::insertBefore(const TString &title,
- NaviItem before,
+ inline NaviItem Naviframe::insertBefore(NaviItem before,
+ const TString &title,
Evas_Object *const backBtn, Evas_Object *const moreBtn,
Evas_Object *const content, const ElmStyle style)
{
return result;
}
- inline NaviItem Naviframe::insertBefore(const TString &title,
- NaviItem before, Evas_Object *const content)
+ inline NaviItem Naviframe::insertBefore(NaviItem before,
+ const TString &title, Evas_Object *const content)
{
- return insertAfter(title, before, nullptr, nullptr, content, nullptr);
+ return insertAfter(before, title, nullptr, nullptr, content, nullptr);
}
inline NaviItem Naviframe::insertBefore(NaviItem before,
Evas_Object *const content)
{
- return insertAfter(nullptr, before, nullptr, nullptr, content, nullptr);
+ return insertAfter(before, nullptr, nullptr, nullptr, content, nullptr);
}
inline NaviItem Naviframe::getTopItem()const
void delEventHandler(WidgetEvent event, WidgetEventHandler handler);
void delEventHandler(SmartEvent event, WidgetEventHandler handler);
+ void callSmartEvent(SmartEvent event, void *eventInfo = nullptr);
+
void markForDeletion();
void setVisible(bool value);
return evas_object_evas_get(getEo());
}
+ inline void Widget::callSmartEvent(SmartEvent event, void *eventInfo)
+ {
+ evas_object_smart_callback_call(getEo(), event, eventInfo);
+ }
+
inline void Widget::markForDeletion()
{
evas_object_del(getEo());
operator Elm_Object_Item *() const;
+ Evas_Object *getWidget() const;
+
void setDelCallback(Evas_Smart_Cb cb) const;
void del();
void disable(WidgetItem item);
bool isValid(WidgetItem item);
+
+ bool operator==(WidgetItem lhs, WidgetItem rhs);
+ bool operator!=(WidgetItem lhs, WidgetItem rhs);
}
#include "WidgetItem.hpp"
return m_it;
}
+ inline Evas_Object *WidgetItem::getWidget() const
+ {
+ return elm_object_item_widget_get(getIt());
+ }
+
inline void WidgetItem::setDelCallback(const Evas_Smart_Cb cb) const
{
elm_object_item_del_cb_set(getIt(), cb);
// Non-member functions //
- inline void enable(WidgetItem item)
+ inline void enable(const WidgetItem item)
{
item.setEnabled(true);
}
- inline void disable(WidgetItem item)
+ inline void disable(const WidgetItem item)
{
item.setEnabled(false);
}
- inline bool isValid(WidgetItem item)
+ inline bool isValid(const WidgetItem item)
{
return !!item.getIt();
}
+
+ inline bool operator==(const WidgetItem lhs, const WidgetItem rhs)
+ {
+ return (lhs.getIt() == rhs.getIt());
+ }
+
+ inline bool operator!=(const WidgetItem lhs, const WidgetItem rhs)
+ {
+ return (lhs.getIt() != rhs.getIt());
+ }
}
namespace ucl {
+ constexpr SmartEvent WIN_ROTATION_CHANGED {"wm,rotation,changed"};
+
UCL_DECLARE_REF_ALIASES(Window);
- class Window : public ElmWidget {
+ class Window final : public ElmWidget {
public:
- static constexpr SmartEvent ROTATION_CHANGED {"wm,rotation,changed"};
-
enum class Type {
BASIC = ELM_WIN_BASIC
};
static Delegate make(const CLASS *data) noexcept;
template <class CLASS, R(*FUNC)(CLASS &, ARGS...)>
- static Delegate make(CLASS &data) noexcept;
+ static Delegate makeA(CLASS &data) noexcept;
template <class CLASS, R(*FUNC)(ARGS..., CLASS &)>
- static Delegate make(CLASS &data) noexcept;
+ static Delegate makeB(CLASS &data) noexcept;
template <class HANDLE, R(*FUNC)(HANDLE, ARGS...)>
- static Delegate make(HANDLE data) noexcept;
+ static Delegate makeA(HANDLE data) noexcept;
template <class HANDLE, R(*FUNC)(ARGS..., HANDLE)>
- static Delegate make(HANDLE data) noexcept;
+ static Delegate makeB(HANDLE data) noexcept;
template <R(*FUNC)(ARGS...)>
static Delegate make() noexcept;
template <class R, class ...ARGS>
template <class CLASS, R(*FUNC)(CLASS &, ARGS...)>
inline Delegate<R(ARGS...)>
- Delegate<R(ARGS...)>::make(CLASS &data) noexcept
+ Delegate<R(ARGS...)>::makeA(CLASS &data) noexcept
{
return {const_cast<void *>(static_cast<const void *>(&data)),
Delegate::Cb::template stubA2A<CLASS, FUNC>};
template <class R, class ...ARGS>
template <class CLASS, R(*FUNC)(ARGS..., CLASS &)>
inline Delegate<R(ARGS...)>
- Delegate<R(ARGS...)>::make(CLASS &data) noexcept
+ Delegate<R(ARGS...)>::makeB(CLASS &data) noexcept
{
return {const_cast<void *>(static_cast<const void *>(&data)),
Delegate::Cb::template stubA2B<CLASS, FUNC>};
template <class R, class ...ARGS>
template <class HANDLE, R(*FUNC)(HANDLE, ARGS...)>
inline Delegate<R(ARGS...)>
- Delegate<R(ARGS...)>::make(const HANDLE data) noexcept
+ Delegate<R(ARGS...)>::makeA(const HANDLE data) noexcept
{
return {const_cast<void *>(static_cast<const void *>(data)),
Delegate::Cb::template stubA2A<HANDLE, FUNC>};
template <class R, class ...ARGS>
template <class HANDLE, R(*FUNC)(ARGS..., HANDLE)>
inline Delegate<R(ARGS...)>
- Delegate<R(ARGS...)>::make(const HANDLE data) noexcept
+ Delegate<R(ARGS...)>::makeB(const HANDLE data) noexcept
{
return {const_cast<void *>(static_cast<const void *>(data)),
Delegate::Cb::template stubA2B<HANDLE, FUNC>};
static Delegate2 make(const CLASS *data) noexcept;
template <class CLASS, R(*FUNC)(CLASS &, ARGS...)>
- static Delegate2 make(CLASS &data) noexcept;
+ static Delegate2 makeA(CLASS &data) noexcept;
template <class CLASS, R(*FUNC)(ARGS..., CLASS &)>
- static Delegate2 make(CLASS &data) noexcept;
+ static Delegate2 makeB(CLASS &data) noexcept;
template <class HANDLE, R(*FUNC)(HANDLE, ARGS...)>
- static Delegate2 make(HANDLE data) noexcept;
+ static Delegate2 makeA(HANDLE data) noexcept;
template <class HANDLE, R(*FUNC)(ARGS..., HANDLE)>
- static Delegate2 make(HANDLE data) noexcept;
+ static Delegate2 makeB(HANDLE data) noexcept;
template <R(*FUNC)(ARGS...)>
static Delegate2 make() noexcept;
template <class R, class ...ARGS>
template <class CLASS, R(*FUNC)(CLASS &, ARGS...)>
inline Delegate2<R(ARGS...)>
- Delegate2<R(ARGS...)>::make(CLASS &data) noexcept
+ Delegate2<R(ARGS...)>::makeA(CLASS &data) noexcept
{
return {const_cast<void *>(static_cast<const void *>(&data)),
Delegate2::Cb::template stubA2A<CLASS, FUNC>,
template <class R, class ...ARGS>
template <class CLASS, R(*FUNC)(ARGS..., CLASS &)>
inline Delegate2<R(ARGS...)>
- Delegate2<R(ARGS...)>::make(CLASS &data) noexcept
+ Delegate2<R(ARGS...)>::makeB(CLASS &data) noexcept
{
return {const_cast<void *>(static_cast<const void *>(&data)),
Delegate2::Cb::template stubA2B<CLASS, FUNC>,
template <class R, class ...ARGS>
template <class HANDLE, R(*FUNC)(HANDLE, ARGS...)>
inline Delegate2<R(ARGS...)>
- Delegate2<R(ARGS...)>::make(const HANDLE data) noexcept
+ Delegate2<R(ARGS...)>::makeA(const HANDLE data) noexcept
{
return {const_cast<void *>(static_cast<const void *>(data)),
Delegate2::Cb::template stubA2A<HANDLE, FUNC>,
template <class R, class ...ARGS>
template <class HANDLE, R(*FUNC)(ARGS..., HANDLE)>
inline Delegate2<R(ARGS...)>
- Delegate2<R(ARGS...)>::make(const HANDLE data) noexcept
+ Delegate2<R(ARGS...)>::makeB(const HANDLE data) noexcept
{
return {const_cast<void *>(static_cast<const void *>(data)),
Delegate2::Cb::template stubA2B<HANDLE, FUNC>,
#define _UCL_DELEGATE(DELEGATE, FUNC, DATA) (_UCL_AFS(DELEGATE, FUNC):: \
Type::make<_UCL_AFS(DELEGATE, FUNC)::Data, &FUNC>(DATA))
+#define _UCL_DELEGATE_A(DELEGATE, FUNC, DATA) (_UCL_AFS(DELEGATE, FUNC):: \
+ Type::makeA<_UCL_AFS(DELEGATE, FUNC)::Data, &FUNC>(DATA))
+
#define _UCL_DELEGATE_V(DELEGATE, FUNC) \
(::ucl::AutoFuncSig<DELEGATE, void, decltype(&FUNC)>::\
Type::make<&FUNC>())
// Helper macro to automatically generate Delegate objects //
#define UCL_DELEGATE(FUNC, DATA) _UCL_DELEGATE(::ucl::Delegate, FUNC, DATA)
+#define UCL_DELEGATE_A(FUNC, DATA) _UCL_DELEGATE_A(::ucl::Delegate, FUNC, DATA)
#define UCL_DELEGATE_V(FUNC) _UCL_DELEGATE_V(::ucl::Delegate, FUNC)
// Helper macro to automatically generate Delegate2 objects //
#define UCL_DELEGATE2(FUNC, DATA) _UCL_DELEGATE(::ucl::Delegate2, FUNC, DATA)
+#define UCL_DELEGATE2_A(FUNC, DATA) \
+ _UCL_DELEGATE_A(::ucl::Delegate2, FUNC, DATA)
#define UCL_DELEGATE2_V(FUNC) _UCL_DELEGATE_V(::ucl::Delegate2, FUNC)
// Helper macro to automatically generate Callback stubs //
// Helper macro to automatically generate Delegate objects //
-#define DELEGATE(FUNC, DATA) UCL_DELEGATE(FUNC, DATA)
-#define DELEGATE_V(FUNC) UCL_DELEGATE_V(FUNC)
+#define DELEGATE(FUNC, DATA) UCL_DELEGATE(FUNC, DATA)
+#define DELEGATE_A(FUNC, DATA) UCL_DELEGATE_A(FUNC, DATA)
+#define DELEGATE_V(FUNC) UCL_DELEGATE_V(FUNC)
// Helper macro to automatically generate Delegate2 objects //
-#define DELEGATE2(FUNC, DATA) UCL_DELEGATE2(FUNC, DATA)
-#define DELEGATE2_V(FUNC) UCL_DELEGATE2_V(FUNC)
+#define DELEGATE2(FUNC, DATA) UCL_DELEGATE2(FUNC, DATA)
+#define DELEGATE2_A(FUNC, DATA) UCL_DELEGATE2_A(FUNC, DATA)
+#define DELEGATE2_V(FUNC) UCL_DELEGATE2_V(FUNC)
// Helper macro to automatically generate Callback stubs //
--- /dev/null
+/*
+ * 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/gui/NaviItem.h"
+
+#include "ucl/gui/Naviframe.h"
+#include "ucl/gui/helpers.h"
+
+namespace ucl {
+
+ void NaviItem::popTo() const
+ {
+ const auto navi = dynamicCast<Naviframe>(getWidget());
+ const bool needStartTransition =
+ (navi && (navi->getTopItem() != *this));
+
+ elm_naviframe_item_pop_to(getIt());
+
+ if (needStartTransition) {
+ navi->startTransition();
+ }
+ }
+
+ void NaviItem::promote() const
+ {
+ const auto navi = dynamicCast<Naviframe>(getWidget());
+ const bool needStartTransition =
+ (navi && (navi->getTopItem() != *this));
+
+ elm_naviframe_item_promote(getIt());
+
+ if (needStartTransition) {
+ navi->startTransition();
+ }
+ }
+}
return result;
}
+
+ // Naviframe //
+
+ Naviframe::Naviframe(RefCountObjBase &rc, Evas_Object *eo, bool isOwner) :
+ StyledWidget(&rc, eo, isOwner),
+ m_isInTransition(false)
+ {
+ addEventHandler(NAVI_TRANSITION_FINISHED, WEAK_DELEGATE(
+ Naviframe::onTransitionFinished, asWeak(*this)));
+ }
+
+ void Naviframe::startTransition()
+ {
+ if (!m_isInTransition) {
+ m_isInTransition = true;
+ callSmartEvent(NAVI_TRANSITION_STARTED);
+ }
+ }
+
+ void Naviframe::onTransitionFinished(Widget &widget, void *eventInfo)
+ {
+ m_isInTransition = false;
+ }
}