- "presentation" folder split into "presenters" and "view".
Change-Id: Ife435970d2a7dc4c5164e92644ba01089c2d6b3c
+++ /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_I_IMAGE_GRID_LISTENER_H__
-#define __GALLERY_PRESENTATION_I_IMAGE_GRID_LISTENER_H__
-
-#include "types.h"
-
-namespace gallery {
-
- class IImageGridListener : public ucl::Polymorphic {
- public:
- virtual void onItemRealized(int itemIndex) = 0;
- virtual void onItemUnrealized(int itemIndex) = 0;
- virtual void onItemEvent(int itemIndex, int event, int x, int y) = 0;
- };
-}
-
-#endif // __GALLERY_PRESENTATION_I_IMAGE_GRID_LISTENER_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_IMAGE_GRID_H__
-#define __GALLERY_PRESENTATION_IMAGE_GRID_H__
-
-#include <deque>
-
-#include "ucl/gui/StyledWidget.h"
-
-#include "types.h"
-
-namespace gallery {
-
- class ImageGrid : public ucl::Widget {
- public:
- enum class Type {
- HCOMB_3X3,
- LINEAR
- };
-
- enum ItemEvent {
- ITEM_EVENT_CLICK,
- ITEM_EVENT_DOUBLE_TAP
- };
-
- class Builder {
- public:
- Builder();
- Builder &setType(Type value);
- Builder &setListener(IImageGridListener *value);
- ImageGridSRef build(Widget &parent) const;
- private:
- Type m_type;
- IImageGridListener *m_listener;
- };
-
- enum {
- UF_LOSE_IMAGE = 1,
- UF_LOSE_BG = 2,
- UF_BLOCK_CLICKS = 4
- };
-
- struct ItemParams {
- int flags;
- int aspectX;
- int aspectY;
- std::string imagePath;
- std::string bgImagePath;
- };
-
- class Unrealizer : ucl::NonCopyable {
- public:
- Unrealizer(ImageGrid &imageGrid);
- ~Unrealizer();
- private:
- ImageGrid &m_imageGrid;
- };
-
- public:
- void setListener(IImageGridListener *listener);
-
- void setItemCount(int count);
-
- void update();
-
- ucl::Result updateItem(int itemIndex, const ItemParams ¶ms);
-
- ucl::Result isItemRealized(int itemIndex) const;
-
- ucl::Result scrollToItem(int itemIndex);
- ucl::Result bringInItem(int itemIndex);
-
- void activateRotary();
- void deactivateRotary();
-
- private:
- class Slot;
- using SlotUPtr = std::unique_ptr<Slot>;
-
- struct Info;
- struct HcombInfo;
- struct LinearInfo;
-
- 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) const;
- template <class FUNC>
- ucl::Result doWithCell(int itemIndex, FUNC &&func) const;
-
- template <class SHOW_FUNC>
- ucl::Result showItem(int itemIndex, SHOW_FUNC &&showFunc);
-
- void addUnrealizeLock();
- void removeUnrealizeLock();
-
- void handleItemEvent(int itemIndex, int event, int x, int y) const;
-
- // Initialization
- void prepare();
- void createCircleScroller();
-
- // 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::StyledWidgetWRef m_scroller;
- ucl::ElmWidget m_box;
- ucl::Widget m_rect1;
- ucl::Widget m_rect2;
- Evas_Object *m_circleScroller;
-
- IImageGridListener *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;
-
- int m_unrealizeLock;
- int m_eventsLock;
- };
-}
-
-#endif // __GALLERY_PRESENTATION_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_IMAGE_VIEWER_H__
-#define __GALLERY_PRESENTATION_IMAGE_VIEWER_H__
-
-#include "ucl/gui/StyledWidget.h"
-#include "ucl/gui/Layout.h"
-
-#include "types.h"
-
-namespace gallery {
-
- constexpr ucl::SmartEvent IMAGE_VIEWER_ZOOM_END {"gallery,zoom,end"};
-
- class ImageViewer final : public ucl::Widget {
- public:
- class Builder {
- public:
- Builder();
- Builder &setImageSize(int w, int h);
- ImageViewerSRef build(ucl::Widget &parent) const;
- private:
- int m_imageW;
- int m_imageH;
- };
-
- public:
- void setLowResImagePath(const std::string &path);
- void setHighResImagePath(const std::string &path);
-
- bool zoomIn(int originX, int originY);
- bool zoomOut();
-
- bool isZooming() const;
- bool isZoomedIn() const;
- bool isZoomedOut() const;
-
- private:
- friend class ucl::RefCountObj<ImageViewer>;
- ImageViewer(ucl::RefCountObjBase &rc, int imageW,
- int imageH, Evas_Object *scroller);
- virtual ~ImageViewer();
-
- void prepare();
-
- void onImagePreloaded(ucl::Widget &widget, void *eventInfo);
- void onScrollerResize(ucl::Widget &widget, void *eventInfo);
-
- bool updateScrollerSize();
- void updateScales();
- void updateGridSize();
- void updateScrollOffset();
-
- void calcZoomInFactors(int originX, int originY);
- void calcZoomOutFactors();
- void startAnimation();
-
- Eina_Bool onAnimationStartTimer();
- Eina_Bool onAnimationFrame(double pos);
-
- private:
- enum class State {
- ZOOMED_OUT,
- ZOOMED_IN,
- ZOOMING_OUT,
- ZOOMING_IN
- };
-
- private:
- const int m_imageW;
- const int m_imageH;
-
- ucl::StyledWidgetWRef m_scroller;
- ucl::Layout m_layout;
- ucl::Widget m_grid;
- ucl::Widget m_lowResImage;
- ucl::Widget m_highResImage;
-
- int m_scrollerW;
- int m_scrollerH;
- int m_gridW;
- int m_gridH;
- double m_scale0;
- double m_scale1;
-
- double m_xf1;
- double m_yf1;
- double m_xf2;
- double m_yf2;
- double m_zoom;
-
- Ecore_Timer *m_animationStartTimer;
- Ecore_Animator *m_animator;
- State m_state;
- };
-}
-
-#endif // __GALLERY_PRESENTATION_IMAGE_VIEWER_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_INSTANCE_H__
-#define __GALLERY_PRESENTATION_INSTANCE_H__
-
-#include "types.h"
-
-#include "ucl/appfw/IInstance.h"
-#include "ucl/appfw/IInstanceAppControlExt.h"
-
-#include "ucl/gui/Theme.h"
-#include "ucl/gui/Naviframe.h"
-
-#include "types.h"
-#include "model/types.h"
-
-namespace gallery {
-
- class Instance final :
- public ucl::IInstance,
- public ucl::IInstanceAppControlExt {
- public:
- Instance(ucl::SysEventProvider &sysEventProvider);
- virtual ~Instance();
-
- // IInstance //
-
- virtual ucl::Result onCreate(
- ucl::IInstanceContext *context) final override;
- virtual void onPause() final override;
- virtual void onResume() final override;
-
- // IInstanceAppControlExt //
-
- virtual void onAppControl(app_control_h appControl) final override;
-
- private:
- ucl::Result setupTheme();
-
- void rescanMediaContent();
- void stopMediaContentScan();
- void startMediaContentScan();
- void onScanComplete(media_content_error_e error);
-
- void createNoContentPage();
- void createThumbnailPage();
-
- void onPageExitRequest(Page &page);
-
- void onSysEvent(const ucl::SysEvent sysEvent);
-
- private:
- ucl::SysEventProvider &m_sysEventProvider;
- ucl::IInstanceContext *m_context;
-
- GallerySRef m_gallery;
- bool m_isScanInProgress;
-
- ucl::WindowSRef m_win;
- ucl::Theme m_theme;
- ucl::NaviframeSRef m_navi;
-
- PageWRef m_page;
- };
-}
-
-#endif // __GALLERY_PRESENTATION_INSTANCE_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_INSTANCE_MANAGER_H__
-#define __GALLERY_PRESENTATION_INSTANCE_MANAGER_H__
-
-#include "types.h"
-
-#include "ucl/appfw/InstanceManagerBase.h"
-
-namespace gallery {
-
- class InstanceManager : public ucl::InstanceManagerBase {
- public:
- InstanceManager();
-
- // ucl::InstanceManagerBase //
-
- virtual ucl::IInstanceSRef newInstance() const final override;
- };
-}
-
-#endif // __GALLERY_PRESENTATION_INSTANCE_MANAGER_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_NO_CONTENT_PAGE_H__
-#define __GALLERY_PRESENTATION_NO_CONTENT_PAGE_H__
-
-#include "Page.h"
-
-namespace gallery {
-
- class NoContentPage final : public Page {
- public:
- class Builder {
- public:
- Builder();
- ~Builder();
- Builder &setNaviframe(const ucl::NaviframeSRef &navi);
- NoContentPageSRef build(ExitRequestHandler onExitRequest) const;
- private:
- ucl::NaviframeSRef m_navi;
- };
-
- private:
- friend class ucl::RefCountObj<NoContentPage>;
- NoContentPage(ucl::RefCountObjBase &rc, const ucl::NaviframeSRef &navi,
- ExitRequestHandler onExitRequest);
- virtual ~NoContentPage();
-
- ucl::Result prepare();
- };
-}
-
-#endif // __GALLERY_PRESENTATION_NO_CONTENT_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.
- */
-
-#ifndef __GALLERY_PRESENTATION_PAGE_H__
-#define __GALLERY_PRESENTATION_PAGE_H__
-
-#include "ucl/gui/Naviframe.h"
-
-#include "types.h"
-
-namespace gallery {
-
- 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 {
-
- template <class ITEM_FACTORY>
- inline ucl::Result Page::prepare(ITEM_FACTORY &&makeItem)
- {
- m_item = makeItem();
- if (isNotValid(m_item)) {
- UCL_LOG_RETURN(ucl::RES_FAIL, "m_item is NULL");
- }
- return preparePart2();
- }
-
- template <class ...ARGS>
- inline ucl::NaviItem Page::insertAfter(ARGS &&...args)
- {
- return m_navi->insertAfter(m_item, std::forward<ARGS>(args)...);
- }
-
- template <class ...ARGS>
- inline ucl::NaviItem Page::insertBefore(ARGS &&...args)
- {
- return m_navi->insertBefore(m_item, std::forward<ARGS>(args)...);
- }
-
- inline ucl::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_PRESENTATION_PREVIEW_PAGE_H__
-#define __GALLERY_PRESENTATION_PREVIEW_PAGE_H__
-
-#include "Page.h"
-
-#include "IImageGridListener.h"
-
-#include "model/types.h"
-
-namespace gallery {
-
- class PreviewPage final : public Page,
- private IImageGridListener {
- public:
- class Builder {
- public:
- Builder();
- ~Builder();
- Builder &setNaviframe(const ucl::NaviframeSRef &navi);
- Builder &setAlbum(const IMediaAlbumSRef &album);
- Builder &setStartItemIndex(int index);
- PreviewPageSRef build(ExitRequestHandler onExitRequest) const;
- private:
- ucl::NaviframeSRef m_navi;
- IMediaAlbumSRef m_album;
- int m_startItemIndex;
- };
-
- public:
- void reload();
-
- private:
- friend class ucl::RefCountObj<PreviewPage>;
- PreviewPage(ucl::RefCountObjBase &rc, const ucl::NaviframeSRef &navi,
- ExitRequestHandler onExitRequest, const IMediaAlbumSRef &album);
- virtual ~PreviewPage();
-
- ucl::Result prepare();
- void showItem(int itemIndex);
-
- bool onEachMedia(MediaItemSRef &&media);
-
- void onPageExitRequest(Page &page);
-
- // Page //
-
- virtual void onActivate() final override;
- virtual void onDeactivate() final override;
-
- // IImageGridListener //
-
- virtual void onItemRealized(int itemIndex) final override;
- virtual void onItemUnrealized(int itemIndex) final override;
- virtual void onItemEvent(int itemIndex,
- int event, int x, int y) final override;
-
- private:
- class Item;
- using ItemUPtr = std::unique_ptr<Item>;
-
- private:
- const IMediaAlbumSRef m_album;
- ImageGridSRef m_imageGrid;
- std::vector<ItemUPtr> m_items;
- PageWRef m_page;
- };
-}
-
-#endif // __GALLERY_PRESENTATION_PREVIEW_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.
- */
-
-#ifndef __GALLERY_PRESENTATION_THUMBNAIL_PAGE_H__
-#define __GALLERY_PRESENTATION_THUMBNAIL_PAGE_H__
-
-#include "Page.h"
-
-#include "IImageGridListener.h"
-
-#include "model/types.h"
-
-namespace gallery {
-
- class ThumbnailPage final : public Page,
- private IImageGridListener {
- public:
- class Builder {
- public:
- Builder();
- ~Builder();
- Builder &setNaviframe(const ucl::NaviframeSRef &navi);
- Builder &setAlbum(const IMediaAlbumSRef &album);
- ThumbnailPageSRef build(ExitRequestHandler onExitRequest) const;
- private:
- ucl::NaviframeSRef m_navi;
- IMediaAlbumSRef m_album;
- };
-
- public:
- void reload();
-
- private:
- friend class ucl::RefCountObj<ThumbnailPage>;
- ThumbnailPage(ucl::RefCountObjBase &rc, const ucl::NaviframeSRef &navi,
- ExitRequestHandler onExitRequest, const IMediaAlbumSRef &album);
- virtual ~ThumbnailPage();
-
- ucl::Result prepare();
-
- bool onEachMedia(MediaItemSRef &&media);
-
- void onPageExitRequest(Page &page);
-
- // Page //
-
- virtual void onActivate() final override;
- virtual void onDeactivate() final override;
-
- // IImageGridListener //
-
- virtual void onItemRealized(int itemIndex) final override;
- virtual void onItemUnrealized(int itemIndex) final override;
- virtual void onItemEvent(int itemIndex,
- int event, int x, int y) final override;
-
- private:
- class RealizedItem;
- using RealizedItemUPtr = std::unique_ptr<RealizedItem>;
-
- private:
- const IMediaAlbumSRef m_album;
- std::vector<MediaItemSRef> m_mediaItems;
-
- std::vector<RealizedItemUPtr> m_realizedItems;
-
- ImageGridSRef m_imageGrid;
-
- PageWRef m_page;
- };
-}
-
-#endif // __GALLERY_PRESENTATION_THUMBNAIL_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.
- */
-
-#ifndef __GALLERY_PRESENTATION_TOUCH_PARSER_H__
-#define __GALLERY_PRESENTATION_TOUCH_PARSER_H__
-
-#include "ucl/gui/Widget.h"
-
-#include "types.h"
-
-namespace gallery {
-
- class TouchParser final : public ucl::RefCountAware {
- public:
- using TapHandler = ucl::Delegate<void(int x, int y)>;
-
- private:
- friend class ucl::RefCountObj<TouchParser>;
- TouchParser(ucl::RefCountObjBase &rc, ucl::Widget &eventSource);
- virtual ~TouchParser();
-
- public:
- void setTapHandler(TapHandler handler);
- void setDoubleTapHandler(TapHandler handler);
-
- private:
- void onMouseDown(ucl::Widget &widget, void *eventInfo);
- void onMouseUp(ucl::Widget &widget, void *eventInfo);
- void onMouseMove(ucl::Widget &widget, void *eventInfo);
-
- void updateIsTapPossible(int flags, int curX, int curY);
-
- bool isFastTap(ucl::UInt curTime, int curX, int curY) const;
- double calcDownDistance(int curX, int curY) const;
-
- private:
- TapHandler m_tapHandler;
- TapHandler m_doubleTapHandler;
- ucl::UInt m_downTime;
- int m_downX;
- int m_downY;
- int m_tapCounter;
- bool m_isMouseDown;
- bool m_isTapPossible;
- };
-}
-
-#endif // __GALLERY_PRESENTATION_TOUCH_PARSER_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_VIEWER_PAGE_H__
-#define __GALLERY_PRESENTATION_VIEWER_PAGE_H__
-
-#include "Page.h"
-
-#include "model/types.h"
-
-namespace gallery {
-
- class ViewerPage final : public Page {
- public:
- class Builder {
- public:
- Builder();
- ~Builder();
- Builder &setNaviframe(const ucl::NaviframeSRef &navi);
- Builder &setMedia(const MediaItemSRef &media);
- Builder &setZoomIn(int x, int y);
- Builder &setExitOnZoomOut(bool value);
- ViewerPageSRef build(ExitRequestHandler onExitRequest) const;
- private:
- ucl::NaviframeSRef m_navi;
- MediaItemSRef m_media;
- int m_zoomInX;
- int m_zoomInY;
- bool m_exitOnZoomOut;
- };
-
- public:
- const std::string &getMediaId() const;
-
- private:
- friend class ucl::RefCountObj<ViewerPage>;
- ViewerPage(ucl::RefCountObjBase &rc, const ucl::NaviframeSRef &navi,
- ExitRequestHandler onExitRequest, const MediaItemSRef &media,
- bool exitOnZoomOut);
- virtual ~ViewerPage();
-
- ucl::Result prepare();
-
- void zoomIn(int originX, int originY);
-
- void onThumbnail(ucl::Result result, const std::string &path);
- void onZoomEnd(ucl::Widget &widget, void *eventInfo);
- void onDoubleTap(int x, int y);
-
- // Page //
-
- virtual void onBackKey() final override;
-
- private:
- const MediaItemSRef m_media;
- const bool m_exitOnZoomOut;
- ImageViewerSRef m_imageViewer;
- TouchParserSRef m_touchParser;
- };
-}
-
-#endif // __GALLERY_PRESENTATION_VIEWER_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.
- */
-
-#ifndef __GALLERY_PRESENTATION_TYPES_H__
-#define __GALLERY_PRESENTATION_TYPES_H__
-
-#include <efl_extension.h>
-
-#include "../types.h"
-
-namespace gallery {
-
- class IImageGridListener;
-
- UCL_DECLARE_REF_ALIASES(TouchParser);
-
- UCL_DECLARE_REF_ALIASES(ImageGrid);
- UCL_DECLARE_REF_ALIASES(ImageViewer);
-
- UCL_DECLARE_REF_ALIASES(Page);
-
- UCL_DECLARE_REF_ALIASES(NoContentPage);
- UCL_DECLARE_REF_ALIASES(ThumbnailPage);
- UCL_DECLARE_REF_ALIASES(PreviewPage);
- UCL_DECLARE_REF_ALIASES(ViewerPage);
-}
-
-#endif // __GALLERY_PRESENTATION_TYPES_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_PRESENTERS_INSTANCE_H__
+#define __GALLERY_PRESENTERS_INSTANCE_H__
+
+#include "ucl/appfw/IInstance.h"
+#include "ucl/appfw/IInstanceAppControlExt.h"
+
+#include "ucl/gui/Theme.h"
+#include "ucl/gui/Naviframe.h"
+
+#include "types.h"
+
+namespace gallery {
+
+ class Instance final :
+ public ucl::IInstance,
+ public ucl::IInstanceAppControlExt {
+ public:
+ Instance(ucl::SysEventProvider &sysEventProvider);
+ virtual ~Instance();
+
+ // IInstance //
+
+ virtual ucl::Result onCreate(
+ ucl::IInstanceContext *context) final override;
+ virtual void onPause() final override;
+ virtual void onResume() final override;
+
+ // IInstanceAppControlExt //
+
+ virtual void onAppControl(app_control_h appControl) final override;
+
+ private:
+ ucl::Result setupTheme();
+
+ void rescanMediaContent();
+ void stopMediaContentScan();
+ void startMediaContentScan();
+ void onScanComplete(media_content_error_e error);
+
+ void createNoContentPage();
+ void createThumbnailPage();
+
+ void onPageExitRequest(Page &page);
+
+ void onSysEvent(const ucl::SysEvent sysEvent);
+
+ private:
+ ucl::SysEventProvider &m_sysEventProvider;
+ ucl::IInstanceContext *m_context;
+
+ GallerySRef m_gallery;
+ bool m_isScanInProgress;
+
+ ucl::WindowSRef m_win;
+ ucl::Theme m_theme;
+ ucl::NaviframeSRef m_navi;
+
+ PageWRef m_page;
+ };
+}
+
+#endif // __GALLERY_PRESENTERS_INSTANCE_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_PRESENTERS_INSTANCE_MANAGER_H__
+#define __GALLERY_PRESENTERS_INSTANCE_MANAGER_H__
+
+#include "ucl/appfw/InstanceManagerBase.h"
+
+#include "types.h"
+
+namespace gallery {
+
+ class InstanceManager : public ucl::InstanceManagerBase {
+ public:
+ InstanceManager();
+
+ // ucl::InstanceManagerBase //
+
+ virtual ucl::IInstanceSRef newInstance() const final override;
+ };
+}
+
+#endif // __GALLERY_PRESENTERS_INSTANCE_MANAGER_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_PRESENTERS_NO_CONTENT_PAGE_H__
+#define __GALLERY_PRESENTERS_NO_CONTENT_PAGE_H__
+
+#include "Page.h"
+
+namespace gallery {
+
+ class NoContentPage final : public Page {
+ public:
+ class Builder {
+ public:
+ Builder();
+ ~Builder();
+ Builder &setNaviframe(const ucl::NaviframeSRef &navi);
+ NoContentPageSRef build(ExitRequestHandler onExitRequest) const;
+ private:
+ ucl::NaviframeSRef m_navi;
+ };
+
+ private:
+ friend class ucl::RefCountObj<NoContentPage>;
+ NoContentPage(ucl::RefCountObjBase &rc, const ucl::NaviframeSRef &navi,
+ ExitRequestHandler onExitRequest);
+ virtual ~NoContentPage();
+
+ ucl::Result prepare();
+ };
+}
+
+#endif // __GALLERY_PRESENTERS_NO_CONTENT_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.
+ */
+
+#ifndef __GALLERY_PRESENTERS_PAGE_H__
+#define __GALLERY_PRESENTERS_PAGE_H__
+
+#include "ucl/gui/Naviframe.h"
+
+#include "types.h"
+
+namespace gallery {
+
+ 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_PRESENTERS_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 {
+
+ template <class ITEM_FACTORY>
+ inline ucl::Result Page::prepare(ITEM_FACTORY &&makeItem)
+ {
+ m_item = makeItem();
+ if (isNotValid(m_item)) {
+ UCL_LOG_RETURN(ucl::RES_FAIL, "m_item is NULL");
+ }
+ return preparePart2();
+ }
+
+ template <class ...ARGS>
+ inline ucl::NaviItem Page::insertAfter(ARGS &&...args)
+ {
+ return m_navi->insertAfter(m_item, std::forward<ARGS>(args)...);
+ }
+
+ template <class ...ARGS>
+ inline ucl::NaviItem Page::insertBefore(ARGS &&...args)
+ {
+ return m_navi->insertBefore(m_item, std::forward<ARGS>(args)...);
+ }
+
+ inline ucl::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_PRESENTERS_PREVIEW_PAGE_H__
+#define __GALLERY_PRESENTERS_PREVIEW_PAGE_H__
+
+#include "Page.h"
+
+#include "view/IImageGridListener.h"
+
+namespace gallery {
+
+ class PreviewPage final : public Page,
+ private IImageGridListener {
+ public:
+ class Builder {
+ public:
+ Builder();
+ ~Builder();
+ Builder &setNaviframe(const ucl::NaviframeSRef &navi);
+ Builder &setAlbum(const IMediaAlbumSRef &album);
+ Builder &setStartItemIndex(int index);
+ PreviewPageSRef build(ExitRequestHandler onExitRequest) const;
+ private:
+ ucl::NaviframeSRef m_navi;
+ IMediaAlbumSRef m_album;
+ int m_startItemIndex;
+ };
+
+ public:
+ void reload();
+
+ private:
+ friend class ucl::RefCountObj<PreviewPage>;
+ PreviewPage(ucl::RefCountObjBase &rc, const ucl::NaviframeSRef &navi,
+ ExitRequestHandler onExitRequest, const IMediaAlbumSRef &album);
+ virtual ~PreviewPage();
+
+ ucl::Result prepare();
+ void showItem(int itemIndex);
+
+ bool onEachMedia(MediaItemSRef &&media);
+
+ void onPageExitRequest(Page &page);
+
+ // Page //
+
+ virtual void onActivate() final override;
+ virtual void onDeactivate() final override;
+
+ // IImageGridListener //
+
+ virtual void onItemRealized(int itemIndex) final override;
+ virtual void onItemUnrealized(int itemIndex) final override;
+ virtual void onItemEvent(int itemIndex,
+ int event, int x, int y) final override;
+
+ private:
+ class Item;
+ using ItemUPtr = std::unique_ptr<Item>;
+
+ private:
+ const IMediaAlbumSRef m_album;
+ ImageGridSRef m_imageGrid;
+ std::vector<ItemUPtr> m_items;
+ PageWRef m_page;
+ };
+}
+
+#endif // __GALLERY_PRESENTERS_PREVIEW_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.
+ */
+
+#ifndef __GALLERY_PRESENTERS_THUMBNAIL_PAGE_H__
+#define __GALLERY_PRESENTERS_THUMBNAIL_PAGE_H__
+
+#include "Page.h"
+
+#include "view/IImageGridListener.h"
+
+namespace gallery {
+
+ class ThumbnailPage final : public Page,
+ private IImageGridListener {
+ public:
+ class Builder {
+ public:
+ Builder();
+ ~Builder();
+ Builder &setNaviframe(const ucl::NaviframeSRef &navi);
+ Builder &setAlbum(const IMediaAlbumSRef &album);
+ ThumbnailPageSRef build(ExitRequestHandler onExitRequest) const;
+ private:
+ ucl::NaviframeSRef m_navi;
+ IMediaAlbumSRef m_album;
+ };
+
+ public:
+ void reload();
+
+ private:
+ friend class ucl::RefCountObj<ThumbnailPage>;
+ ThumbnailPage(ucl::RefCountObjBase &rc, const ucl::NaviframeSRef &navi,
+ ExitRequestHandler onExitRequest, const IMediaAlbumSRef &album);
+ virtual ~ThumbnailPage();
+
+ ucl::Result prepare();
+
+ bool onEachMedia(MediaItemSRef &&media);
+
+ void onPageExitRequest(Page &page);
+
+ // Page //
+
+ virtual void onActivate() final override;
+ virtual void onDeactivate() final override;
+
+ // IImageGridListener //
+
+ virtual void onItemRealized(int itemIndex) final override;
+ virtual void onItemUnrealized(int itemIndex) final override;
+ virtual void onItemEvent(int itemIndex,
+ int event, int x, int y) final override;
+
+ private:
+ class RealizedItem;
+ using RealizedItemUPtr = std::unique_ptr<RealizedItem>;
+
+ private:
+ const IMediaAlbumSRef m_album;
+ std::vector<MediaItemSRef> m_mediaItems;
+
+ std::vector<RealizedItemUPtr> m_realizedItems;
+
+ ImageGridSRef m_imageGrid;
+
+ PageWRef m_page;
+ };
+}
+
+#endif // __GALLERY_PRESENTERS_THUMBNAIL_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.
+ */
+
+#ifndef __GALLERY_PRESENTERS_VIEWER_PAGE_H__
+#define __GALLERY_PRESENTERS_VIEWER_PAGE_H__
+
+#include "Page.h"
+
+namespace gallery {
+
+ class ViewerPage final : public Page {
+ public:
+ class Builder {
+ public:
+ Builder();
+ ~Builder();
+ Builder &setNaviframe(const ucl::NaviframeSRef &navi);
+ Builder &setMedia(const MediaItemSRef &media);
+ Builder &setZoomIn(int x, int y);
+ Builder &setExitOnZoomOut(bool value);
+ ViewerPageSRef build(ExitRequestHandler onExitRequest) const;
+ private:
+ ucl::NaviframeSRef m_navi;
+ MediaItemSRef m_media;
+ int m_zoomInX;
+ int m_zoomInY;
+ bool m_exitOnZoomOut;
+ };
+
+ public:
+ const std::string &getMediaId() const;
+
+ private:
+ friend class ucl::RefCountObj<ViewerPage>;
+ ViewerPage(ucl::RefCountObjBase &rc, const ucl::NaviframeSRef &navi,
+ ExitRequestHandler onExitRequest, const MediaItemSRef &media,
+ bool exitOnZoomOut);
+ virtual ~ViewerPage();
+
+ ucl::Result prepare();
+
+ void zoomIn(int originX, int originY);
+
+ void onThumbnail(ucl::Result result, const std::string &path);
+ void onZoomEnd(ucl::Widget &widget, void *eventInfo);
+ void onDoubleTap(int x, int y);
+
+ // Page //
+
+ virtual void onBackKey() final override;
+
+ private:
+ const MediaItemSRef m_media;
+ const bool m_exitOnZoomOut;
+ ImageViewerSRef m_imageViewer;
+ TouchParserSRef m_touchParser;
+ };
+}
+
+#endif // __GALLERY_PRESENTERS_VIEWER_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.
+ */
+
+#ifndef __GALLERY_PRESENTERS_TYPES_H__
+#define __GALLERY_PRESENTERS_TYPES_H__
+
+#include "../types.h"
+#include "view/types.h"
+#include "model/types.h"
+
+namespace gallery {
+
+ UCL_DECLARE_REF_ALIASES(Page);
+
+ UCL_DECLARE_REF_ALIASES(NoContentPage);
+ UCL_DECLARE_REF_ALIASES(ThumbnailPage);
+ UCL_DECLARE_REF_ALIASES(PreviewPage);
+ UCL_DECLARE_REF_ALIASES(ViewerPage);
+}
+
+#endif // __GALLERY_PRESENTERS_TYPES_H__
#ifndef __GALLERY_RESOURCES_H__
#define __GALLERY_RESOURCES_H__
-#include "config.h"
-
#include "ucl/misc/TString.h"
+#include "config.h"
+
namespace gallery {
constexpr auto THEME_EDJE_PATH = "edje/theme.edj";
--- /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_I_IMAGE_GRID_LISTENER_H__
+#define __GALLERY_VIEW_I_IMAGE_GRID_LISTENER_H__
+
+#include "types.h"
+
+namespace gallery {
+
+ class IImageGridListener : public ucl::Polymorphic {
+ public:
+ virtual void onItemRealized(int itemIndex) = 0;
+ virtual void onItemUnrealized(int itemIndex) = 0;
+ virtual void onItemEvent(int itemIndex, int event, int x, int y) = 0;
+ };
+}
+
+#endif // __GALLERY_VIEW_I_IMAGE_GRID_LISTENER_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_VIEW_IMAGE_GRID_H__
+#define __GALLERY_VIEW_IMAGE_GRID_H__
+
+#include <deque>
+
+#include "ucl/gui/StyledWidget.h"
+
+#include "types.h"
+
+namespace gallery {
+
+ class ImageGrid : public ucl::Widget {
+ public:
+ enum class Type {
+ HCOMB_3X3,
+ LINEAR
+ };
+
+ enum ItemEvent {
+ ITEM_EVENT_CLICK,
+ ITEM_EVENT_DOUBLE_TAP
+ };
+
+ class Builder {
+ public:
+ Builder();
+ Builder &setType(Type value);
+ Builder &setListener(IImageGridListener *value);
+ ImageGridSRef build(Widget &parent) const;
+ private:
+ Type m_type;
+ IImageGridListener *m_listener;
+ };
+
+ enum {
+ UF_LOSE_IMAGE = 1,
+ UF_LOSE_BG = 2,
+ UF_BLOCK_CLICKS = 4
+ };
+
+ struct ItemParams {
+ int flags;
+ int aspectX;
+ int aspectY;
+ std::string imagePath;
+ std::string bgImagePath;
+ };
+
+ class Unrealizer : ucl::NonCopyable {
+ public:
+ Unrealizer(ImageGrid &imageGrid);
+ ~Unrealizer();
+ private:
+ ImageGrid &m_imageGrid;
+ };
+
+ public:
+ void setListener(IImageGridListener *listener);
+
+ void setItemCount(int count);
+
+ void update();
+
+ ucl::Result updateItem(int itemIndex, const ItemParams ¶ms);
+
+ ucl::Result isItemRealized(int itemIndex) const;
+
+ ucl::Result scrollToItem(int itemIndex);
+ ucl::Result bringInItem(int itemIndex);
+
+ void activateRotary();
+ void deactivateRotary();
+
+ private:
+ class Slot;
+ using SlotUPtr = std::unique_ptr<Slot>;
+
+ struct Info;
+ struct HcombInfo;
+ struct LinearInfo;
+
+ 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) const;
+ template <class FUNC>
+ ucl::Result doWithCell(int itemIndex, FUNC &&func) const;
+
+ template <class SHOW_FUNC>
+ ucl::Result showItem(int itemIndex, SHOW_FUNC &&showFunc);
+
+ void addUnrealizeLock();
+ void removeUnrealizeLock();
+
+ void handleItemEvent(int itemIndex, int event, int x, int y) const;
+
+ // Initialization
+ void prepare();
+ void createCircleScroller();
+
+ // 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::StyledWidgetWRef m_scroller;
+ ucl::ElmWidget m_box;
+ ucl::Widget m_rect1;
+ ucl::Widget m_rect2;
+ Evas_Object *m_circleScroller;
+
+ IImageGridListener *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;
+
+ int m_unrealizeLock;
+ int m_eventsLock;
+ };
+}
+
+#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_VIEW_IMAGE_VIEWER_H__
+#define __GALLERY_VIEW_IMAGE_VIEWER_H__
+
+#include "ucl/gui/StyledWidget.h"
+#include "ucl/gui/Layout.h"
+
+#include "types.h"
+
+namespace gallery {
+
+ constexpr ucl::SmartEvent IMAGE_VIEWER_ZOOM_END {"gallery,zoom,end"};
+
+ class ImageViewer final : public ucl::Widget {
+ public:
+ class Builder {
+ public:
+ Builder();
+ Builder &setImageSize(int w, int h);
+ ImageViewerSRef build(ucl::Widget &parent) const;
+ private:
+ int m_imageW;
+ int m_imageH;
+ };
+
+ public:
+ void setLowResImagePath(const std::string &path);
+ void setHighResImagePath(const std::string &path);
+
+ bool zoomIn(int originX, int originY);
+ bool zoomOut();
+
+ bool isZooming() const;
+ bool isZoomedIn() const;
+ bool isZoomedOut() const;
+
+ private:
+ friend class ucl::RefCountObj<ImageViewer>;
+ ImageViewer(ucl::RefCountObjBase &rc, int imageW,
+ int imageH, Evas_Object *scroller);
+ virtual ~ImageViewer();
+
+ void prepare();
+
+ void onImagePreloaded(ucl::Widget &widget, void *eventInfo);
+ void onScrollerResize(ucl::Widget &widget, void *eventInfo);
+
+ bool updateScrollerSize();
+ void updateScales();
+ void updateGridSize();
+ void updateScrollOffset();
+
+ void calcZoomInFactors(int originX, int originY);
+ void calcZoomOutFactors();
+ void startAnimation();
+
+ Eina_Bool onAnimationStartTimer();
+ Eina_Bool onAnimationFrame(double pos);
+
+ private:
+ enum class State {
+ ZOOMED_OUT,
+ ZOOMED_IN,
+ ZOOMING_OUT,
+ ZOOMING_IN
+ };
+
+ private:
+ const int m_imageW;
+ const int m_imageH;
+
+ ucl::StyledWidgetWRef m_scroller;
+ ucl::Layout m_layout;
+ ucl::Widget m_grid;
+ ucl::Widget m_lowResImage;
+ ucl::Widget m_highResImage;
+
+ int m_scrollerW;
+ int m_scrollerH;
+ int m_gridW;
+ int m_gridH;
+ double m_scale0;
+ double m_scale1;
+
+ double m_xf1;
+ double m_yf1;
+ double m_xf2;
+ double m_yf2;
+ double m_zoom;
+
+ Ecore_Timer *m_animationStartTimer;
+ Ecore_Animator *m_animator;
+ State m_state;
+ };
+}
+
+#endif // __GALLERY_VIEW_IMAGE_VIEWER_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_VIEW_TOUCH_PARSER_H__
+#define __GALLERY_VIEW_TOUCH_PARSER_H__
+
+#include "ucl/gui/Widget.h"
+
+#include "types.h"
+
+namespace gallery {
+
+ class TouchParser final : public ucl::RefCountAware {
+ public:
+ using TapHandler = ucl::Delegate<void(int x, int y)>;
+
+ private:
+ friend class ucl::RefCountObj<TouchParser>;
+ TouchParser(ucl::RefCountObjBase &rc, ucl::Widget &eventSource);
+ virtual ~TouchParser();
+
+ public:
+ void setTapHandler(TapHandler handler);
+ void setDoubleTapHandler(TapHandler handler);
+
+ private:
+ void onMouseDown(ucl::Widget &widget, void *eventInfo);
+ void onMouseUp(ucl::Widget &widget, void *eventInfo);
+ void onMouseMove(ucl::Widget &widget, void *eventInfo);
+
+ void updateIsTapPossible(int flags, int curX, int curY);
+
+ bool isFastTap(ucl::UInt curTime, int curX, int curY) const;
+ double calcDownDistance(int curX, int curY) const;
+
+ private:
+ TapHandler m_tapHandler;
+ TapHandler m_doubleTapHandler;
+ ucl::UInt m_downTime;
+ int m_downX;
+ int m_downY;
+ int m_tapCounter;
+ bool m_isMouseDown;
+ bool m_isTapPossible;
+ };
+}
+
+#endif // __GALLERY_VIEW_TOUCH_PARSER_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_VIEW_HELPERS_H__
+#define __GALLERY_VIEW_HELPERS_H__
+
+#include <efl_extension.h>
+
+#include "types.h"
+
+namespace ucl {
+
+ class ElmWidget;
+ class Naviframe;
+}
+
+namespace gallery {
+
+ ucl::Result createCircleSurface(ucl::Naviframe &navi);
+
+ Eext_Circle_Surface *getCircleSurface(const ucl::ElmWidget &widget);
+}
+
+#endif // __GALLERY_VIEW_HELPERS_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_VIEW_TYPES_H__
+#define __GALLERY_VIEW_TYPES_H__
+
+#include "../types.h"
+
+namespace gallery {
+
+ class IImageGridListener;
+
+ UCL_DECLARE_REF_ALIASES(TouchParser);
+
+ UCL_DECLARE_REF_ALIASES(ImageGrid);
+ UCL_DECLARE_REF_ALIASES(ImageViewer);
+}
+
+#endif // __GALLERY_VIEW_TYPES_H__
#include <algorithm>
-#include <Ecore.h>
-
#include "ucl/util/helpers.h"
#include "ucl/util/logging.h"
#include "ucl/util/shortLogs.h"
-#include "ucl/gui/stdTheme.h"
-#include "ucl/gui/helpers.h"
-
-#include "resources.h"
-
#undef UCL_LOG_TAG
-#define UCL_LOG_TAG "GALLERY"
+#define UCL_LOG_TAG GALLERY_LOG_TAG
#endif // __GALLERY_COMMON_H__
#include "ucl/appfw/UIApp.h"
-#include "presentation/InstanceManager.h"
+#include "presenters/InstanceManager.h"
#include "common.h"
#include "GalleryAlbum.h"
+#include "ucl/misc/TString.h"
+
#include "model/MediaItem.h"
#include "common.h"
using namespace ucl;
- const auto CONDITION = TString("%s=%d OR %s=%d").format(
- MEDIA_TYPE, MEDIA_CONTENT_TYPE_IMAGE,
- MEDIA_TYPE, MEDIA_CONTENT_TYPE_VIDEO);
+ const auto CONDITION = TString("%s=%d").format(
+ MEDIA_TYPE, MEDIA_CONTENT_TYPE_IMAGE);
}}}
namespace gallery {
#include "model/MediaItem.h"
+#include <Ecore_File.h>
+
#include "common.h"
namespace gallery {
#ifndef __GALLERY_MODEL_COMMON_H__
#define __GALLERY_MODEL_COMMON_H__
-#include "../common.h"
-
#include "helpers.h"
+#include "../common.h"
+
#endif // __GALLERY_MODEL_COMMON_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 "presentation/ImageGrid.h"
-
-#include <array>
-#include <vector>
-
-#include "ucl/gui/Layout.h"
-
-#include "presentation/IImageGridListener.h"
-#include "presentation/TouchParser.h"
-
-#include "common.h"
-
-namespace gallery { namespace { namespace impl {
-
- using namespace ucl;
-
- // Related to ImageGrid //
- const TString SLOT_PART_FMT {"swallow.cell_%d"};
-
- // Related to Button //
- constexpr ElmStyle ITEM_BTN_STYLE {"gallery_image"};
- constexpr EdjePart PART_BTN_BG {"swallow.bg"};
- constexpr SmartEvent BTN_CLICKED {"clicked"};
- constexpr EdjeSignal BTN_BLOCK_CLICKS {"gallery,block,clicks"};
- constexpr EdjeSignal BTN_UNBLOCK_CLICKS {"gallery,unblock,clicks"};
-
- // Other //
- constexpr auto HCOMB_SCROLL_LIMIT = 1000;
-}}}
-
-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(
- IImageGridListener *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 int slotsPerPage;
- 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;
-
- virtual int calcExtraPaddingSize(const int slotSize,
- const int itemCount) const
- {
- return 0;
- }
-
- Info(const std::array<LayoutTheme, 2> &slotThemes,
- const std::array<int, 2> &slotLens,
- const int scrollLimit, const int slotsPerPage,
- const bool isHorizontal) :
- slotThemes(slotThemes),
- slotLens(slotLens),
- scrollLimit(scrollLimit),
- slotsPerPage(slotsPerPage),
- 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);
- }
-
- virtual int calcExtraPaddingSize(const int slotSize,
- const int itemCount) const final override
- {
- return slotSize;
- }
-
- HcombInfo(const int totalLength,
- const std::array<LayoutTheme, 2> &slotThemes) :
- Info(slotThemes, {{(totalLength / 2), ceilDiv<2>(totalLength)}},
- impl::HCOMB_SCROLL_LIMIT, (totalLength - 1), true),
- totalLength(totalLength)
- {
- }
- };
-
- // ImageGrid::LinearInfo //
-
- struct ImageGrid::LinearInfo : Info {
- virtual int calcItemIndexFromCell(
- const int slotIndex, const int itemOffset) const final override
- {
- return (slotIndex / 2);
- }
-
- virtual void calcCellFromItemIndex(const int itemIndex,
- int &slotIndex, int &itemOffset) const final override
- {
- slotIndex = (itemIndex * 2);
- itemOffset = 0;
- }
-
- virtual int calcMaxSlotCount(const int itemCount) const final override
- {
- return (itemCount * 2);
- }
-
- LinearInfo(const LayoutTheme &slotTheme, const bool isHorizontal) :
- Info({{slotTheme}}, {{1, 0}}, 1, 1, isHorizontal)
- {
- }
- };
-
- // ImageGrid::Slot //
-
- class ImageGrid::Slot {
- private:
- class Item : public RefCountAware {
- public:
- friend class RefCountObj<Item>;
- Item(RefCountObjBase &rc,
- const ImageGrid &imageGrid, Widget &parent) :
- RefCountAware(&rc),
- m_imageGrid(imageGrid),
- m_btn(elm_button_add(parent)),
- m_image(elm_image_add(m_btn)),
- m_realizeIndex(-1),
- m_imageLoadSize(0),
- m_wasUpdated(false),
- m_isClicksBlocked(false)
- {
- m_btn.setFocusAlowed(false);
- m_btn.setStyle(impl::ITEM_BTN_STYLE);
- show(m_btn);
-
- elm_image_preload_disabled_set(m_image, EINA_FALSE);
- elm_image_aspect_fixed_set(m_image, EINA_TRUE);
- elm_image_fill_outside_set(m_image, EINA_TRUE);
- m_btn.setContent(m_image);
- show(m_image);
-
- m_btn.addEventHandler(impl::BTN_CLICKED, WEAK_DELEGATE(
- Item::onClicked, asWeak(*this)));
-
- m_touchParser = makeShared<TouchParser>(m_btn);
- m_touchParser->setDoubleTapHandler(
- DELEGATE(Item::onDoubleTap, this));
- }
-
- Widget &getWidget()
- {
- return m_btn;
- }
-
- void setImageLoadSize(const int value)
- {
- m_imageLoadSize = value;
- elm_image_prescale_set(m_image, m_imageLoadSize);
- }
-
- 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_btn);
- }
- }
-
- 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;
- }
-
- updateClicksBlock(params);
- updateImage(params);
- updateBgImage(params);
-
- makeWhite(m_btn);
-
- m_wasUpdated = true;
-
- return true;
- }
-
- private:
- void updateClicksBlock(const ItemParams ¶ms)
- {
- if (params.flags & UF_BLOCK_CLICKS) {
- if (!m_isClicksBlocked) {
- m_isClicksBlocked = true;
- m_btn.emitSignal(impl::BTN_BLOCK_CLICKS);
- }
- } else if (m_isClicksBlocked) {
- m_isClicksBlocked = false;
- m_btn.emitSignal(impl::BTN_UNBLOCK_CLICKS);
- }
- }
-
- void updateImage(const ItemParams ¶ms)
- {
- if (isEmpty(params.imagePath)) {
- if (!m_wasUpdated || (params.flags & UF_LOSE_IMAGE)) {
- makeTransparent(m_image);
- }
- return;
- }
-
- elm_image_file_set(m_image, params.imagePath.c_str(), NULL);
-
- makeWhite(m_image);
- }
-
- void updateBgImage(const ItemParams ¶ms)
- {
- if (isEmpty(params.bgImagePath)) {
- if (m_bgImage && (!m_wasUpdated ||
- (params.flags & UF_LOSE_BG))) {
- makeTransparent(*m_bgImage);
- }
- return;
- }
-
- if (!m_bgImage) {
- m_bgImage = makeShared<Widget>(
- evas_object_image_filled_add(m_btn.getEvas()));
- evas_object_image_load_size_set(*m_bgImage,
- m_imageLoadSize, m_imageLoadSize);
- m_btn.setContent(impl::PART_BTN_BG, *m_bgImage);
- show(*m_bgImage);
- }
-
- evas_object_image_file_set(*m_bgImage,
- params.bgImagePath.c_str(), NULL);
-
- int w = params.aspectX;
- int h = params.aspectY;
- if ((w == 0) || (h == 0)) {
- evas_object_image_size_get(*m_bgImage, &w, &h);
- }
- m_bgImage->setARHint(WidgetARHint::NEITHER, w, h);
-
- makeWhite(*m_bgImage);
- }
-
- void onClicked(Widget &wifget, void *eventInfo)
- {
- if (isRealized()) {
- 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);
- }
- }
-
- private:
- const ImageGrid &m_imageGrid;
- StyledWidget m_btn;
- StyledWidget m_image;
- WidgetSRef m_bgImage;
- TouchParserSRef m_touchParser;
- int m_realizeIndex;
- int m_imageLoadSize;
- bool m_wasUpdated;
- bool m_isClicksBlocked;
- };
-
- 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 (isValid(m_info.slotThemes[isOdd]) &&
- !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(makeShared<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<SharedRef<Item>> m_items;
- Layout m_layout;
- bool m_isRealized;
- };
-
- // ImageGrid::Unrealizer //
-
- ImageGrid::Unrealizer::Unrealizer(ImageGrid &imageGrid) :
- m_imageGrid(imageGrid)
- {
- m_imageGrid.addUnrealizeLock();
- }
-
- ImageGrid::Unrealizer::~Unrealizer()
- {
- m_imageGrid.removeUnrealizeLock();
- }
-
- // ImageGrid //
-
- ImageGrid::ImageGrid(RefCountObjBase *const rc, const Type type,
- Evas_Object *const scroller) :
- Widget(rc, scroller, true),
- m_info(getInfo(type)),
-
- m_scroller(makeShared<StyledWidget>(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_circleScroller(nullptr),
-
- 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),
-
- m_unrealizeLock(0),
- m_eventsLock(0)
- {
- prepare();
-
- ++m_eventsLock;
-
- updateSlotCount();
-
- updatePadSizes();
- updateScrollBias();
- updateRectMins();
-
- --m_eventsLock;
- }
-
- const ImageGrid::Info &ImageGrid::getInfo(const Type type)
- {
- switch (type) {
- case Type::HCOMB_3X3: {
- static HcombInfo info{3, {{
- {"layout", "gallery_image_grid", "hcomb_3x3_even"},
- {"layout", "gallery_image_grid", "hcomb_3x3_odd"}}}};
- return info;
- }
- case Type::LINEAR:
- default: {
- static LinearInfo info{
- {"layout", "gallery_image_grid", "linear"}, true};
- 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);
-
- m_scroller->setStyle(SCROLLER_STYLE);
- expandAndFill(*m_scroller);
- if (m_info.isHorizontal) {
- elm_scroller_page_scroll_limit_set(
- *m_scroller, m_info.scrollLimit, 0);
- elm_scroller_bounce_set(*m_scroller, EINA_TRUE, EINA_FALSE);
- } else {
- elm_scroller_page_scroll_limit_set(
- *m_scroller, 0, m_info.scrollLimit);
- elm_scroller_bounce_set(*m_scroller, EINA_FALSE, EINA_TRUE);
- }
- show(*m_scroller);
-
- createCircleScroller();
-
- 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::createCircleScroller()
- {
- const auto sfc = getCircleSurface(*m_scroller);
- if (!sfc) {
- LOG_RETURN_VOID(RES_FAIL, "getCircleSurface() failed!");
- }
-
- m_circleScroller = eext_circle_object_scroller_add(*m_scroller, sfc);
- if (!m_circleScroller) {
- LOG_RETURN_VOID(RES_FAIL,
- "eext_circle_object_scroller_add() failed!");
- }
-
- if (m_info.isHorizontal) {
- eext_circle_object_scroller_policy_set(m_circleScroller,
- ELM_SCROLLER_POLICY_AUTO, ELM_SCROLLER_POLICY_OFF);
- } else {
- eext_circle_object_scroller_policy_set(m_circleScroller,
- ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_AUTO);
- }
- }
-
- void ImageGrid::setListener(IImageGridListener *const listener)
- {
- m_listener = listener;
- }
-
- void ImageGrid::setItemCount(const int count)
- {
- if (m_itemCount == count) {
- return;
- }
-
- ++m_eventsLock;
-
- unrealizeSlots(0, m_slotCount);
-
- m_itemCount = count;
-
- if (updateMaxSlotCount()) {
- updateSlotCount();
- if (updateMaxBeginSlotIndex()) {
- updateBeginSlotIndex();
- }
- }
-
- realizeSlots();
- updateRectMins();
-
- --m_eventsLock;
- }
-
- void ImageGrid::update()
- {
- Unrealizer(*this);
- }
-
- 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) const
- {
- 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) const
- {
- return doWithCell(itemIndex,
- [this, &func](const int slotIndex, const int itemOffset)
- {
- const int slotOffset = (slotIndex - m_beginSlotIndex);
- if ((slotOffset < 0) || (slotOffset >= m_slotCount)) {
- return RES_FALSE;
- }
- return func(*m_slots[slotOffset], itemOffset);
- });
- }
-
- template <class FUNC>
- Result ImageGrid::doWithCell(const int itemIndex, FUNC &&func) const
- {
- 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);
-
- return func(slotIndex, itemOffset);
- }
-
- Result ImageGrid::scrollToItem(const int itemIndex)
- {
- return showItem(itemIndex, elm_scroller_region_show);
- }
-
- Result ImageGrid::bringInItem(int itemIndex)
- {
- return showItem(itemIndex, elm_scroller_region_bring_in);
- }
-
- template <class SHOW_FUNC>
- Result ImageGrid::showItem(const int itemIndex, SHOW_FUNC &&showFunc)
- {
- return doWithCell(itemIndex,
- [this, &showFunc](const int slotIndex, const int itemOffset)
- {
- const int scrollOffset = ((slotIndex / 2) * m_slotSize);
- if (m_info.isHorizontal) {
- showFunc(*m_scroller, scrollOffset, 0, m_scrollerSize, 1);
- } else {
- showFunc(*m_scroller, 0, scrollOffset, 1, m_scrollerSize);
- }
- return RES_OK;
- });
- }
-
- void ImageGrid::activateRotary()
- {
- eext_rotary_object_event_activated_set(m_circleScroller, EINA_TRUE);
- }
-
- void ImageGrid::deactivateRotary()
- {
- eext_rotary_object_event_activated_set(m_circleScroller, EINA_FALSE);
- }
-
- void ImageGrid::addUnrealizeLock()
- {
- unrealizeSlots(0, m_slotCount);
- ++m_unrealizeLock;
- }
-
- void ImageGrid::removeUnrealizeLock()
- {
- if (m_unrealizeLock > 0) {
- --m_unrealizeLock;
- realizeSlots();
- } else {
- WLOG("m_unrealizeLock = 0!");
- }
- }
-
- void ImageGrid::handleItemEvent(const int itemIndex, const int event,
- const int x, const int y) const
- {
- if (m_listener) {
- m_listener->onItemEvent(itemIndex, event, x, y);
- }
- }
-
- 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);
- 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->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 / m_slotSize) + 3) * 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 -
- (std::max((m_scrollerSize / m_slotSize), 1) * m_slotSize));
-
- m_padSize1 = (spaceSize / 2);
- m_padSize2 = (spaceSize - m_padSize1 +
- m_info.calcExtraPaddingSize(m_slotSize, m_itemCount));
- }
-
- 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()
- {
- if (m_unrealizeLock == 0) {
- for (int i = 0; i < m_slotCount; ++i) {
- m_slots[i]->realize(m_beginSlotIndex + i);
- }
- }
- }
-
- void ImageGrid::unrealizeSlots(
- const int beginSlotOffset, const int endSlotOffset)
- {
- if (m_unrealizeLock == 0) {
- for (int i = beginSlotOffset; i < endSlotOffset; ++i) {
- m_slots[i]->unrealize();
- }
- }
- }
-
- void ImageGrid::handleScrolling()
- {
- if (m_eventsLock > 0) {
- WLOG("Event handling was blocked!");
- return;
- }
- ++m_eventsLock;
-
- if (updateScrollOffset() && updateBeginSlotIndex()) {
- realizeSlots();
- updateRectMins();
- }
-
- --m_eventsLock;
- }
-
- void ImageGrid::handleResize()
- {
- if (m_eventsLock > 0) {
- WLOG("Event handling was blocked!");
- return;
- }
- ++m_eventsLock;
-
- if (updateScrollerSize()) {
- bool needRealize = false;
-
- updatePadSizes();
-
- if (updateOptimalSlotCount() && updateSlotCount()) {
- updateMaxBeginSlotIndex();
- needRealize = true;
- }
-
- updateScrollBias();
-
- if (updateBeginSlotIndex()) {
- needRealize = true;
- }
-
- if (needRealize) {
- realizeSlots();
- }
- updateRectMins();
- }
-
- --m_eventsLock;
- }
-
- 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/ImageViewer.h"
-
-#include "common.h"
-
-namespace gallery { namespace { namespace impl {
-
- constexpr auto ANIMATION_START_TIMEOUT_SEC = (1.0 / 30.0);
- constexpr auto ANIMATION_RUNTIME_SEC = (300.0 / 1000.0);
- constexpr auto ANIMATION_STOP_POS = 0.999999;
-}}}
-
-namespace gallery {
-
- using namespace ucl;
-
- // ImageViewer::Builder //
-
- ImageViewer::Builder::Builder() :
- m_imageW(0),
- m_imageH(0)
- {
- }
-
- ImageViewer::Builder &ImageViewer::Builder::setImageSize(
- const int w, const int h)
- {
- m_imageW = w;
- m_imageH = h;
- return *this;
- }
-
- ImageViewerSRef ImageViewer::Builder::build(Widget &parent) const
- {
- if ((m_imageW <= 0) || (m_imageH <= 0)) {
- LOG_RETURN_VALUE(RES_INVALID_ARGUMENTS, {}, "Image size is invalid");
- }
-
- auto scroller = elm_scroller_add(parent);
- if (!scroller) {
- LOG_RETURN_VALUE(RES_FAIL, {}, "elm_scroller_add() failed!");
- }
-
- return makeShared<ImageViewer>(m_imageW, m_imageH, scroller);
- }
-
- // ImageViewer //
-
- ImageViewer::ImageViewer(RefCountObjBase &rc,
- const int imageW, const int imageH,
- Evas_Object *const scroller) :
- Widget(&rc, scroller, true),
- m_imageW(imageW),
- m_imageH(imageH),
-
- m_scroller(makeShared<StyledWidget>(scroller)),
- m_layout(elm_layout_add(*m_scroller)),
- m_grid(evas_object_grid_add(m_layout.getEvas())),
- m_lowResImage(evas_object_image_filled_add(m_grid.getEvas())),
- m_highResImage(evas_object_image_filled_add(m_grid.getEvas())),
-
- m_scrollerW(0),
- m_scrollerH(0),
- m_gridW(0),
- m_gridH(0),
- m_scale0(0),
- m_scale1(0),
-
- m_xf1(0.5),
- m_yf1(0.5),
- m_xf2(0.5),
- m_yf2(0.5),
- m_zoom(0.0),
-
- m_animationStartTimer(nullptr),
- m_animator(nullptr),
- m_state(State::ZOOMED_OUT)
- {
- prepare();
- }
-
- ImageViewer::~ImageViewer()
- {
- if (m_animationStartTimer) {
- ecore_timer_del(m_animationStartTimer);
- }
- if (m_animator) {
- ecore_animator_del(m_animator);
- }
- }
-
- void ImageViewer::prepare()
- {
- expandAndFill(*m_scroller);
- m_scroller->setStyle(SCROLLER_STYLE);
- elm_scroller_bounce_set(*m_scroller, EINA_TRUE, EINA_TRUE);
- elm_scroller_policy_set(*m_scroller,
- ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_OFF);
- elm_scroller_single_direction_set(*m_scroller,
- ELM_SCROLLER_SINGLE_DIRECTION_NONE);
- elm_object_scroll_freeze_push(*m_scroller);
- show(*m_scroller);
-
- expandAndFill(m_layout);
- m_layout.setTheme(LAYOUT_DEFAULT);
- m_scroller->setContent(m_layout);
- show(m_layout);
-
- evas_object_grid_size_set(m_grid, 1, 1);
- m_layout.setContent(m_grid);
- show(m_grid);
-
- evas_object_grid_pack(m_grid, m_lowResImage, 0, 0, 1, 1);
- show(m_lowResImage);
- evas_object_grid_pack(m_grid, m_highResImage, 0, 0, 1, 1);
- show(m_highResImage);
-
- m_scroller->addEventHandler(WidgetEvent::RESIZE,
- WEAK_DELEGATE(ImageViewer::onScrollerResize, asWeak(*this)));
-
- m_highResImage.addEventHandler(WidgetEvent::IMAGE_PRELOADED,
- WEAK_DELEGATE(ImageViewer::onImagePreloaded, asWeak(*this)));
- }
-
- void ImageViewer::onScrollerResize(Widget &widget, void *eventInfo)
- {
- if (updateScrollerSize()) {
- updateScales();
- updateGridSize();
- updateScrollOffset();
- }
- }
-
- bool ImageViewer::updateScrollerSize()
- {
- int scrollerW = 0;
- int scrollerH = 0;
- getSize(*m_scroller, &scrollerW, &scrollerH);
-
- if ((scrollerW == 0) || (scrollerH == 0)) {
- DLOG("Scroller has 0 size. Skip.");
- return false;
- }
-
- if ((scrollerW != m_scrollerW) || (scrollerH != m_scrollerH)) {
- m_scrollerW = scrollerW;
- m_scrollerH = scrollerH;
- return true;
- }
-
- return false;
- }
-
- void ImageViewer::updateScales()
- {
- const double sx = (1.0 * m_scrollerW / m_imageW);
- const double sy = (1.0 * m_scrollerH / m_imageH);
-
- m_scale0 = ((sx > sy) ? sx : sy);
- m_scale1 = 1.0;
- }
-
- void ImageViewer::updateGridSize()
- {
- const double scale = (m_scale0 + m_zoom * (m_scale1 - m_scale0));
-
- m_gridW = std::lround(scale * m_imageW);
- m_gridH = std::lround(scale * m_imageH);
-
- m_grid.setMin(m_gridW, m_gridH);
- m_grid.setMax(m_gridW, m_gridH);
-
- evas_object_smart_calculate(m_layout);
- }
-
- void ImageViewer::updateScrollOffset()
- {
- const double xf2 = (m_xf2 + m_zoom * (0.5 - m_xf2));
- const double yf2 = (m_yf2 + m_zoom * (0.5 - m_yf2));
-
- const int sx = std::lround((m_xf1 * m_gridW) - (xf2 * m_scrollerW));
- const int sy = std::lround((m_yf1 * m_gridH) - (yf2 * m_scrollerH));
-
- elm_scroller_region_show(*m_scroller, sx, sy, m_scrollerW, m_scrollerH);
- }
-
- void ImageViewer::setLowResImagePath(const std::string &path)
- {
- evas_object_image_file_set(m_lowResImage, path.c_str(), nullptr);
- }
-
- void ImageViewer::setHighResImagePath(const std::string &path)
- {
- hide(m_highResImage);
- evas_object_image_file_set(m_highResImage, path.c_str(), nullptr);
- evas_object_image_preload(m_highResImage, EINA_FALSE);
- }
-
- void ImageViewer::onImagePreloaded(Widget &widget, void *eventInfo)
- {
- show(widget);
- }
-
- bool ImageViewer::zoomIn(const int originX, const int originY)
- {
- if (m_state != State::ZOOMED_OUT) {
- WLOG("Can't zoom in!");
- return false;
- }
-
- m_state = State::ZOOMING_IN;
-
- calcZoomInFactors(originX, originY);
- startAnimation();
-
- return true;
- }
-
- bool ImageViewer::zoomOut()
- {
- if (m_state != State::ZOOMED_IN) {
- WLOG("Can't zoom out!");
- return false;
- }
-
- m_state = State::ZOOMING_OUT;
-
- calcZoomOutFactors();
- startAnimation();
-
- return true;
- }
-
- bool ImageViewer::isZooming() const
- {
- return ((m_state == State::ZOOMING_IN) ||
- (m_state == State::ZOOMING_OUT));
- }
-
- bool ImageViewer::isZoomedIn() const
- {
- return (m_state == State::ZOOMED_IN);
- }
-
- bool ImageViewer::isZoomedOut() const
- {
- return (m_state == State::ZOOMED_OUT);
- }
-
- void ImageViewer::calcZoomInFactors(const int originX, const int originY)
- {
- if (m_scale0 > m_scale1) {
- m_xf1 = 0.5;
- m_yf1 = 0.5;
- m_xf2 = 0.5;
- m_yf2 = 0.5;
- return;
- }
-
- int x = 0;
- int y = 0;
- getPosition(*m_scroller, &x, &y);
-
- const int newOriginX = (originX - x);
- const int newOriginY = (originY - x);
-
- int sx = 0;
- int sy = 0;
- elm_scroller_region_get(*m_scroller, &sx, &sy, nullptr, nullptr);
-
- m_xf1 = (1.0 * (sx + newOriginX) / m_gridW);
- m_yf1 = (1.0 * (sy + newOriginY) / m_gridH);
- m_xf2 = (1.0 * newOriginX / m_scrollerW);
- m_yf2 = (1.0 * newOriginY / m_scrollerH);
- }
-
- void ImageViewer::calcZoomOutFactors()
- {
- int sx = 0;
- int sy = 0;
- elm_scroller_region_get(*m_scroller, &sx, &sy, nullptr, nullptr);
-
- if (m_gridW < m_scrollerW) {
- sx = (0.5 * (m_gridW - m_scrollerW));
- }
- if (m_gridH < m_scrollerH) {
- sy = (0.5 * (m_gridH - m_scrollerH));
- }
-
- m_xf1 = ((sx + 0.5 * m_scrollerW) / m_gridW);
- m_yf1 = ((sy + 0.5 * m_scrollerH) / m_gridH);
- m_xf2 = (m_scale0 * m_imageW * (m_xf1 - 0.5) / m_scrollerW + 0.5);
- m_yf2 = (m_scale0 * m_imageH * (m_yf1 - 0.5) / m_scrollerH + 0.5);
- }
-
- void ImageViewer::startAnimation()
- {
- if (m_animationStartTimer) {
- WLOG("Timer is running!");
- ecore_timer_del(m_animationStartTimer);
- }
-
- m_animationStartTimer = ecore_timer_add(
- impl::ANIMATION_START_TIMEOUT_SEC,
- CALLBACK_A(ImageViewer::onAnimationStartTimer), this);
- }
-
- Eina_Bool ImageViewer::onAnimationStartTimer()
- {
- m_animationStartTimer = nullptr;
-
- if (m_animator) {
- WLOG("Animator is running!");
- ecore_animator_del(m_animator);
- }
- m_animator = ecore_animator_timeline_add(
- impl::ANIMATION_RUNTIME_SEC,
- CALLBACK_A(ImageViewer::onAnimationFrame), this);
-
- return ECORE_CALLBACK_CANCEL;
- }
-
- Eina_Bool ImageViewer::onAnimationFrame(const double pos)
- {
- const double t = ecore_animator_pos_map(
- pos, ECORE_POS_MAP_DECELERATE, 0.0, 0.0);
-
- m_zoom = ((m_state == State::ZOOMING_IN) ? t : (1.0 - t));
-
- updateGridSize();
- updateScrollOffset();
-
- if (pos >= impl::ANIMATION_STOP_POS) {
- m_animator = nullptr;
- if (m_state == State::ZOOMING_IN) {
- m_state = State::ZOOMED_IN;
- elm_object_scroll_freeze_pop(*m_scroller);
- } else {
- m_state = State::ZOOMED_OUT;
- elm_object_scroll_freeze_push(*m_scroller);
- }
- callSmartEvent(IMAGE_VIEWER_ZOOM_END, nullptr);
- return ECORE_CALLBACK_CANCEL;
- }
-
- return ECORE_CALLBACK_RENEW;
- }
-}
+++ /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/Instance.h"
-
-#include <system_settings.h>
-
-#include "ucl/appfw/SysEventProvider.h"
-#include "ucl/appfw/helpers.h"
-
-#include "model/Gallery.h"
-#include "model/IMediaAlbum.h"
-
-#include "presentation/NoContentPage.h"
-#include "presentation/ThumbnailPage.h"
-
-#include "common.h"
-
-namespace gallery { namespace { namespace impl {
-
- // TODO Since feature is temporary using hard-coded path
- constexpr auto MEDIA_FOLDER = "/opt/usr/home/owner/media";
-}}}
-
-namespace gallery {
-
- using namespace ucl;
-
- Instance::Instance(SysEventProvider &sysEventProvider) :
- m_sysEventProvider(sysEventProvider),
- m_isScanInProgress(false)
- {
- }
-
- Instance::~Instance()
- {
- stopMediaContentScan();
- }
-
- Result Instance::onCreate(IInstanceContext *const context)
- {
- m_context = context;
-
- m_gallery = Gallery::newInstance();
- if (!m_gallery) {
- LOG_RETURN(RES_FAIL, "Gallery::newInstance() failed!");
- }
-
- m_win = m_context->getWindow();
-
- FAIL_RETURN(setupTheme(), "setupTheme() failed!");
-
- m_navi = Naviframe::Builder().
- build(m_win->getConformant());
- if (!m_navi) {
- LOG_RETURN(RES_FAIL, "Naviframe::build() failed!");
- }
-
- m_win->getConformant().setContent(*m_navi);
-
- FAIL_RETURN(createCircleSurface(*m_navi),
- "createCircleSurface() failed!");
-
- m_sysEventProvider.addEventHandler(
- DELEGATE(Instance::onSysEvent, this));
-
- return RES_OK;
- }
-
- Result Instance::setupTheme()
- {
- m_theme = Theme::create();
- if (isNotValid(m_theme)) {
- LOG_RETURN(RES_FAIL, "Theme::create() failed!");
- }
-
- m_theme.addExtension(getResPath(THEME_EDJE_PATH));
-
- m_win->setTheme(m_theme);
-
- return RES_OK;
- }
-
- void Instance::onPause()
- {
- DLOG("PAUSE");
- }
-
- void Instance::onResume()
- {
- DLOG("RESUME");
-
- if (SCAN_MEDIA_ON_RESUME) {
- rescanMediaContent();
- }
-
- ecore_animator_frametime_set(1.0 / 60.0);
- }
-
- void Instance::rescanMediaContent()
- {
- stopMediaContentScan();
- startMediaContentScan();
- }
-
- void Instance::stopMediaContentScan()
- {
- if (m_isScanInProgress) {
- m_isScanInProgress = false;
- DLOG("Scan is in progress. Terminating...");
- const int ret = media_content_cancel_scan_folder(
- impl::MEDIA_FOLDER);
- if (ret != 0) {
- WLOG("media_content_cancel_scan_folder() failed: %d", ret);
- }
- }
- }
-
- void Instance::startMediaContentScan()
- {
- DLOG("Starting media scan...");
-
- int ret = media_content_scan_folder(impl::MEDIA_FOLDER, true,
- CALLBACK_B(Instance::onScanComplete), this);
- if (ret != 0) {
- ELOG("media_content_scan_folder() failed: %d", ret);
- return;
- }
-
- m_isScanInProgress = true;
- }
-
- void Instance::onScanComplete(media_content_error_e error)
- {
- DLOG("Media scan complete. error: %d", error);
-
- m_isScanInProgress = false;
-
- const auto thumbPage = dynamicRefCast<ThumbnailPage>(m_page);
-
- if (isNotEmpty(m_gallery->getAlbum())) {
- if (thumbPage) {
- DLOG("Reloading the ThumbnailPage...");
- thumbPage->reload();
- } else {
- if (m_page) {
- m_page->exitNoTransition();
- }
- createThumbnailPage();
- }
- } else if (thumbPage) {
- DLOG("Exit from ThumbnailPage witout transition...");
- thumbPage->exitNoTransition();
- createNoContentPage();
- }
- }
-
- void Instance::onAppControl(app_control_h appControl)
- {
- DLOG("APP CONTROL");
-
- if (!m_page) {
- if (isEmpty(m_gallery->getAlbum())) {
- createNoContentPage();
- } else {
- createThumbnailPage();
- }
- }
-
- if (!m_win->isVisible()) {
- DLOG("Show the window.");
- show(*m_win);
- }
- }
-
- void Instance::createNoContentPage()
- {
- DLOG("Creating NoContentPage.");
- m_page = NoContentPage::Builder().setNaviframe(m_navi).
- build(DELEGATE(Instance::onPageExitRequest, this));
- }
-
- void Instance::createThumbnailPage()
- {
- DLOG("Creating ThumbnailPage.");
- m_page = ThumbnailPage::Builder().setNaviframe(m_navi).
- setAlbum(m_gallery->getAlbum()).
- build(DELEGATE(Instance::onPageExitRequest, this));
- }
-
- void Instance::onPageExitRequest(Page &page)
- {
- if (page.isAtBottom()) {
- DLOG("Bottom page. Lowering the window.");
- m_win->lower();
- } else {
- DLOG("Exit page.");
- page.exit();
- }
- }
-
- void Instance::onSysEvent(const SysEvent sysEvent)
- {
- switch(sysEvent) {
- case SysEvent::LANGUAGE_CHANGED:
- DLOG("SysEvent::LANGUAGE_CHANGED");
- {
- char *locale = NULL;
- system_settings_get_value_string(
- SYSTEM_SETTINGS_KEY_LOCALE_LANGUAGE, &locale);
- elm_language_set(locale);
- free(locale);
- }
- break;
- default:
- DLOG("sysEvent: %d", sysEvent);
- break;
- }
- }
-}
+++ /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/InstanceManager.h"
-
-#include "presentation/Instance.h"
-
-namespace gallery {
-
- using namespace ucl;
-
- InstanceManager::InstanceManager() :
- InstanceManagerBase(AppParams().
- set(AppParam::WINDOW_NAME, WINDOW_NAME).
- set(AppParam::BASE_SCALE, BASE_SCALE))
- {
- }
-
- IInstanceSRef InstanceManager::newInstance() const
- {
- return makeShared<Instance>(getSysEventProvider());
- }
-}
+++ /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/NoContentPage.h"
-
-#include "ucl/gui/Layout.h"
-
-#include "common.h"
-
-namespace gallery {namespace { namespace impl {
-
- using namespace ucl;
-
- constexpr LayoutTheme ICON_THEME
- {"layout", "gallery_image", "gallery_icon_no_photos.png"};
-}}}
-
-namespace gallery {
-
- using namespace ucl;
-
- // NoContentPage::Builder //
-
- NoContentPage::Builder::Builder()
- {
- }
-
- NoContentPage::Builder::~Builder()
- {
- }
-
- NoContentPage::Builder &NoContentPage::Builder::setNaviframe(
- const NaviframeSRef &navi)
- {
- m_navi = navi;
- return *this;
- }
-
- NoContentPageSRef NoContentPage::Builder::build(
- const ExitRequestHandler onExitRequest) const
- {
- if (!onExitRequest) {
- LOG_RETURN_VALUE(RES_INVALID_ARGUMENTS, {},
- "onExitRequest is NULL");
- }
- if (!m_navi) {
- LOG_RETURN_VALUE(RES_INVALID_ARGUMENTS, {}, "m_navi is NULL");
- }
-
- auto result = makeShared<NoContentPage>(m_navi, onExitRequest);
-
- FAIL_RETURN_VALUE(result->prepare(), {}, "result->prepare() failed!");
-
- return result;
- }
-
- // NoContentPage //
-
- NoContentPage::NoContentPage(RefCountObjBase &rc,
- const NaviframeSRef &navi,
- const ExitRequestHandler onExitRequest) :
- Page(rc, navi, onExitRequest)
- {
- }
-
- NoContentPage::~NoContentPage()
- {
- }
-
- Result NoContentPage::prepare()
- {
- const auto layout = Layout::Builder().
- setIsOwner(true).
- setTheme(LAYOUT_NO_CONTENTS).
- build(getNaviframe());
- if (!layout) {
- LOG_RETURN(RES_FAIL, "Layout::build() failed!");
- }
-
- const auto icon = Layout::Builder().
- setTheme(impl::ICON_THEME).
- build(*layout);
- if (!layout) {
- LOG_RETURN(RES_FAIL, "Layout::build() failed!");
- }
-
- layout->setContent(*icon);
- layout->setText(PART_TITLE, STR_APP_NAME);
- layout->setText(STR_NO_PHOTOS);
-
- FAIL_RETURN(Page::prepare(
- [this, &layout]()
- {
- return getNaviframe().push(*layout, NAVIFRAME_EMPTY);
- }),
- "Page::prepare() failed!");
-
- layout->setIsOwner(false);
-
- return RES_OK;
- }
-}
+++ /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 "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,
- const 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() && isAtTop()) {
- 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 (isAtTop()) {
- m_item.del();
- dispatchTopPageChanged();
- } else if (isValid(m_item)) {
- m_item.del();
- }
- }
-
- 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 "presentation/PreviewPage.h"
-
-#include "model/IMediaAlbum.h"
-#include "model/MediaItem.h"
-
-#include "presentation/ImageGrid.h"
-#include "presentation/ViewerPage.h"
-
-#include "common.h"
-
-namespace gallery {
-
- using namespace ucl;
-
- // PreviewPage::Builder //
-
- PreviewPage::Builder::Builder() :
- m_startItemIndex(0)
- {
- }
-
- PreviewPage::Builder::~Builder()
- {
- }
-
- PreviewPage::Builder &PreviewPage::Builder::setNaviframe(
- const NaviframeSRef &navi)
- {
- m_navi = navi;
- return *this;
- }
-
- PreviewPage::Builder &PreviewPage::Builder::setAlbum(
- const IMediaAlbumSRef &album)
- {
- m_album = album;
- return *this;
- }
-
- PreviewPage::Builder &PreviewPage::Builder::setStartItemIndex(
- const int index)
- {
- m_startItemIndex = index;
- return *this;
- }
-
- PreviewPageSRef PreviewPage::Builder::build(
- const ExitRequestHandler onExitRequest) const
- {
- if (!onExitRequest) {
- LOG_RETURN_VALUE(RES_INVALID_ARGUMENTS, {},
- "onExitRequest is NULL");
- }
- if (!m_navi) {
- LOG_RETURN_VALUE(RES_INVALID_ARGUMENTS, {}, "m_navi is NULL");
- }
- if (!m_album) {
- LOG_RETURN_VALUE(RES_INVALID_ARGUMENTS, {}, "m_album is NULL");
- }
-
- auto result = makeShared<PreviewPage>(
- m_navi, onExitRequest, m_album);
-
- FAIL_RETURN_VALUE(result->prepare(), {}, "result->prepare() failed!");
-
- if (m_startItemIndex > 0) {
- result->showItem(m_startItemIndex);
- }
-
- return result;
- }
-
- // PreviewPage::Item //
-
- class PreviewPage::Item : public NonCopyable {
- public:
- Item(MediaItemSRef &&media, ImageGrid &imageGrid, const int itemIndex) :
- m_media(std::move(media)),
- m_imageGrid(imageGrid),
- m_index(itemIndex)
- {
- }
-
- void realize()
- {
- FAIL_LOG(m_media->getThumbnailPath(
- DELEGATE(Item::onThumbnail, this)),
- "getThumbnailPath() failed!");
- }
-
- void unrealize()
- {
- m_media->cancelThumbnailPathGet();
- }
-
- MediaItemSRef getMedia()
- {
- return m_media;
- }
-
- private:
- void onThumbnail(const Result result, const std::string &path)
- {
- FAIL_LOG(result, "Failed to get thumbnail!");
-
- ImageGrid::ItemParams params = {};
- m_media->getResolution(params.aspectX, params.aspectY);
- params.imagePath = m_media->getFilePath();
- params.bgImagePath = path;
- params.flags = ImageGrid::UF_BLOCK_CLICKS;
-
- m_imageGrid.updateItem(m_index, params);
- }
-
- private:
- const MediaItemSRef m_media;
- ImageGrid &m_imageGrid;
- const int m_index;
- };
-
- // PreviewPage //
-
- PreviewPage::PreviewPage(RefCountObjBase &rc,
- const NaviframeSRef &navi,
- const ExitRequestHandler onExitRequest,
- const IMediaAlbumSRef &album) :
- Page(rc, navi, onExitRequest),
- m_album(album)
- {
- }
-
- PreviewPage::~PreviewPage()
- {
- if (m_page) {
- m_page->exitNoTransition();
- }
- m_imageGrid->setListener(nullptr);
- }
-
- void PreviewPage::reload()
- {
- ImageGrid::Unrealizer u(*m_imageGrid);
-
- m_items.clear();
-
- FAIL_LOG(m_album->forEachMedia(
- DELEGATE(PreviewPage::onEachMedia, this)),
- "m_album->forEachMedia() failed!");
-
- m_imageGrid->setItemCount(m_items.size());
-
- const auto viewerPage = dynamicRefCast<ViewerPage>(m_page);
- if (viewerPage) {
- const auto mediaId = viewerPage->getMediaId();
- const auto it = std::find_if(m_items.begin(), m_items.end(),
- [&mediaId](const ItemUPtr &item)
- {
- return (item->getMedia()->getId() == mediaId);
- });
- if (it == m_items.end()) {
- DLOG("Viewed media item was removed.");
- deleteTo();
- } else {
- m_imageGrid->scrollToItem(it - m_items.begin());
- }
- }
- }
-
- Result PreviewPage::prepare()
- {
- m_imageGrid = ImageGrid::Builder().
- setListener(this).
- setType(ImageGrid::Type::LINEAR).
- build(getNaviframe());
- if (!m_imageGrid) {
- LOG_RETURN(RES_FAIL, "ImageGrid::build() failed!");
- }
-
- FAIL_RETURN(m_album->forEachMedia(
- DELEGATE(PreviewPage::onEachMedia, this)),
- "m_album->forEachMedia() failed!");
-
- FAIL_RETURN(Page::prepare(
- [this]()
- {
- return getNaviframe().push(*m_imageGrid, NAVIFRAME_EMPTY);
- }),
- "Page::prepare() failed!");
-
- m_imageGrid->setItemCount(m_items.size());
-
- return RES_OK;
- }
-
- void PreviewPage::showItem(const int itemIndex)
- {
- m_imageGrid->scrollToItem(itemIndex);
- }
-
- bool PreviewPage::onEachMedia(MediaItemSRef &&media)
- {
- m_items.emplace_back(
- new Item(std::move(media), *m_imageGrid, m_items.size()));
- return true;
- }
-
- void PreviewPage::onActivate()
- {
- m_imageGrid->activateRotary();
- }
-
- void PreviewPage::onDeactivate()
- {
- m_imageGrid->deactivateRotary();
- }
-
- void PreviewPage::onItemRealized(const int itemIndex)
- {
- m_items[itemIndex]->realize();
- }
-
- void PreviewPage::onItemUnrealized(const int itemIndex)
- {
- m_items[itemIndex]->unrealize();
- }
-
- void PreviewPage::onItemEvent(const int itemIndex,
- const int event, const int x, const int y)
- {
- if (!isActive() || (event != ImageGrid::ITEM_EVENT_DOUBLE_TAP)) {
- return;
- }
-
- m_page = ViewerPage::Builder().
- setNaviframe(asShared(getNaviframe())).
- setZoomIn(x, y).
- setMedia(m_items[itemIndex]->getMedia()).
- build(DELEGATE(PreviewPage::onPageExitRequest, this));
- }
-
- void PreviewPage::onPageExitRequest(Page &page)
- {
- deleteTo();
- }
-}
+++ /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/ThumbnailPage.h"
-
-#include "model/IMediaAlbum.h"
-#include "model/MediaItem.h"
-
-#include "presentation/ImageGrid.h"
-#include "presentation/PreviewPage.h"
-
-#include "common.h"
-
-namespace gallery {
-
- using namespace ucl;
-
- // ThumbnailPage::Builder //
-
- ThumbnailPage::Builder::Builder()
- {
- }
-
- ThumbnailPage::Builder::~Builder()
- {
- }
-
- ThumbnailPage::Builder &ThumbnailPage::Builder::setNaviframe(
- const NaviframeSRef &navi)
- {
- m_navi = navi;
- return *this;
- }
-
- ThumbnailPage::Builder &ThumbnailPage::Builder::setAlbum(
- const IMediaAlbumSRef &album)
- {
- m_album = album;
- return *this;
- }
-
- ThumbnailPageSRef ThumbnailPage::Builder::build(
- const ExitRequestHandler onExitRequest) const
- {
- if (!onExitRequest) {
- LOG_RETURN_VALUE(RES_INVALID_ARGUMENTS, {},
- "onExitRequest is NULL");
- }
- if (!m_navi) {
- LOG_RETURN_VALUE(RES_INVALID_ARGUMENTS, {}, "m_navi is NULL");
- }
- if (!m_album) {
- LOG_RETURN_VALUE(RES_INVALID_ARGUMENTS, {}, "m_album is NULL");
- }
-
- auto result = makeShared<ThumbnailPage>(
- m_navi, onExitRequest, m_album);
-
- FAIL_RETURN_VALUE(result->prepare(), {}, "result->prepare() failed!");
-
- return result;
- }
-
- // ThumbnailPage::RealizedItem //
-
- class ThumbnailPage::RealizedItem : public NonCopyable {
- public:
- RealizedItem(ThumbnailPage &parent, const int index) :
- m_parent(parent),
- m_index(index)
- {
- FAIL_LOG(m_parent.m_mediaItems[m_index]->getThumbnailPath(
- DELEGATE(RealizedItem::onThumbnail, this)),
- "getThumbnailPath() failed!");
- }
-
- ~RealizedItem()
- {
- m_parent.m_mediaItems[m_index]->cancelThumbnailPathGet();
- }
-
- int getIndex() const
- {
- return m_index;
- }
-
- private:
- void onThumbnail(const Result result, const std::string &path)
- {
- FAIL_RETURN_VOID(result, "Failed to get thumbnail!");
-
- ImageGrid::ItemParams params = {};
- params.imagePath = path;
-
- m_parent.m_imageGrid->updateItem(m_index, params);
- }
-
- private:
- ThumbnailPage &m_parent;
- int m_index;
- };
-
- // ThumbnailPage //
-
- ThumbnailPage::ThumbnailPage(RefCountObjBase &rc,
- const NaviframeSRef &navi,
- const ExitRequestHandler onExitRequest,
- const IMediaAlbumSRef &album) :
- Page(rc, navi, onExitRequest),
- m_album(album)
- {
- }
-
- ThumbnailPage::~ThumbnailPage()
- {
- if (m_page) {
- m_page->exitNoTransition();
- }
- m_imageGrid->setListener(nullptr);
- }
-
- void ThumbnailPage::reload()
- {
- ImageGrid::Unrealizer u(*m_imageGrid);
-
- m_mediaItems.clear();
-
- FAIL_LOG(m_album->forEachMedia(
- DELEGATE(ThumbnailPage::onEachMedia, this)),
- "m_album->forEachMedia() failed!");
-
- m_imageGrid->setItemCount(m_mediaItems.size());
-
- if (const auto vp = dynamic_cast<PreviewPage *>(m_page.get())) {
- vp->reload();
- }
- }
-
- Result ThumbnailPage::prepare()
- {
- FAIL_RETURN(m_album->forEachMedia(
- DELEGATE(ThumbnailPage::onEachMedia, this)),
- "m_album->forEachMedia() failed!");
-
- m_imageGrid = ImageGrid::Builder().
- setListener(this).
- setType(ImageGrid::Type::HCOMB_3X3).
- build(getNaviframe());
- if (!m_imageGrid) {
- LOG_RETURN(RES_FAIL, "ImageGrid::build() failed!");
- }
-
- FAIL_RETURN(Page::prepare(
- [this]()
- {
- return getNaviframe().push(*m_imageGrid, NAVIFRAME_EMPTY);
- }),
- "Page::prepare() failed!");
-
- m_imageGrid->setItemCount(m_mediaItems.size());
-
- return RES_OK;
- }
-
- bool ThumbnailPage::onEachMedia(MediaItemSRef &&media)
- {
- m_mediaItems.emplace_back(std::move(media));
- return true;
- }
-
- void ThumbnailPage::onActivate()
- {
- m_imageGrid->activateRotary();
- }
-
- void ThumbnailPage::onDeactivate()
- {
- m_imageGrid->deactivateRotary();
- }
-
- void ThumbnailPage::onItemRealized(const int itemIndex)
- {
- m_realizedItems.emplace_back(new RealizedItem(*this, itemIndex));
- }
-
- void ThumbnailPage::onItemUnrealized(const int itemIndex)
- {
- const auto it = std::find_if(
- m_realizedItems.begin(), m_realizedItems.end(),
- [itemIndex](const RealizedItemUPtr &item)
- {
- return (item->getIndex() == itemIndex);
- });
- if (it != m_realizedItems.end()) {
- m_realizedItems.erase(it);
- } else {
- WLOG("Item is not found in realized list!");
- }
- }
-
- void ThumbnailPage::onItemEvent(const int itemIndex,
- const int event, const int x, const int y)
- {
- if (!isActive() || (event != ImageGrid::ITEM_EVENT_CLICK)) {
- return;
- }
-
- m_page = PreviewPage::Builder().
- setNaviframe(asShared(getNaviframe())).
- setAlbum(m_album).
- setStartItemIndex(itemIndex).
- build(DELEGATE(ThumbnailPage::onPageExitRequest, this));
- }
-
- void ThumbnailPage::onPageExitRequest(Page &page)
- {
- popTo();
- }
-}
+++ /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/TouchParser.h"
-
-#include "common.h"
-
-namespace gallery { namespace { namespace impl {
-
- constexpr auto TAP_MOVE_THRESHOLD = 30;
- constexpr auto FAST_TAP_DISTANCE = 60;
- constexpr auto FAST_TAP_DELAY_MS = 300;
-}}}
-
-namespace gallery {
-
- using namespace ucl;
-
- TouchParser::TouchParser(RefCountObjBase &rc, Widget &eventSource) :
- RefCountAware(&rc),
- m_downTime(0),
- m_downX(0),
- m_downY(0),
- m_tapCounter(0),
- m_isMouseDown(false),
- m_isTapPossible(false)
- {
- eventSource.addEventHandler(WidgetEvent::MOUSE_DOWN,
- WEAK_DELEGATE(TouchParser::onMouseDown, asWeak(*this)));
-
- eventSource.addEventHandler(WidgetEvent::MOUSE_UP,
- WEAK_DELEGATE(TouchParser::onMouseUp, asWeak(*this)));
-
- eventSource.addEventHandler(WidgetEvent::MOUSE_MOVE,
- WEAK_DELEGATE(TouchParser::onMouseMove, asWeak(*this)));
- }
-
- TouchParser::~TouchParser()
- {
- }
-
- void TouchParser::setTapHandler(TapHandler handler)
- {
- m_tapHandler = handler;
- }
-
- void TouchParser::setDoubleTapHandler(TapHandler handler)
- {
- m_doubleTapHandler = handler;
- }
-
- void TouchParser::onMouseDown(Widget &widget, void *eventInfo)
- {
- if (m_isMouseDown) {
- return;
- }
- m_isMouseDown = true;
-
- const auto e = static_cast<Evas_Event_Mouse_Down *>(eventInfo);
-
- if (!isFastTap(e->timestamp, e->canvas.x, e->canvas.y)) {
- m_tapCounter = 0;
- } else if (m_doubleTapHandler && (m_tapCounter == 1)) {
- m_doubleTapHandler(m_downX, m_downY);
- }
-
- m_downTime = e->timestamp;
- m_downX = e->canvas.x;
- m_downY = e->canvas.y;
- m_isTapPossible = true;
- }
-
- void TouchParser::onMouseUp(Widget &widget, void *eventInfo)
- {
- if (!m_isMouseDown) {
- return;
- }
- m_isMouseDown = false;
-
- const auto e = static_cast<Evas_Event_Mouse_Up *>(eventInfo);
-
- updateIsTapPossible(e->event_flags, e->canvas.x, e->canvas.y);
-
- if (!m_isTapPossible) {
- m_tapCounter = 0;
- return;
- }
-
- ++m_tapCounter;
-
- if (m_tapHandler) {
- m_tapHandler(e->canvas.x, e->canvas.y);
- }
- }
-
- void TouchParser::onMouseMove(Widget &widget, void *eventInfo)
- {
- if (!m_isMouseDown || !m_isTapPossible) {
- return;
- }
-
- const auto e = static_cast<Evas_Event_Mouse_Move *>(eventInfo);
-
- updateIsTapPossible(e->event_flags, e->cur.canvas.x, e->cur.canvas.y);
- }
-
- void TouchParser::updateIsTapPossible(const int flags,
- const int curX, const int curY)
- {
- if (!m_isTapPossible) {
- return;
- }
- if ((flags & EVAS_EVENT_FLAG_ON_HOLD) || (calcDownDistance(curX, curY) >
- ELM_SCALE_SIZE(impl::TAP_MOVE_THRESHOLD))) {
- m_isTapPossible = false;
- }
- }
-
- bool TouchParser::isFastTap(const UInt curTime,
- const int curX, const int curY) const
- {
- return (((curTime - m_downTime) <= impl::FAST_TAP_DELAY_MS) &&
- (calcDownDistance(curX, curY) <=
- ELM_SCALE_SIZE(impl::FAST_TAP_DISTANCE)));
- }
-
- double TouchParser::calcDownDistance(int curX, int curY) const
- {
- const auto dx = (curX - m_downX);
- const auto dy = (curY - m_downY);
-
- return sqrt(1.0 * dx * dx + 1.0 * dy * dy);
- }
-}
+++ /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/ViewerPage.h"
-
-#include "model/MediaItem.h"
-
-#include "presentation/ImageViewer.h"
-#include "presentation/TouchParser.h"
-
-#include "common.h"
-
-namespace gallery {
-
- using namespace ucl;
-
- // ViewerPage::Builder //
-
- ViewerPage::Builder::Builder() :
- m_zoomInX(-1),
- m_zoomInY(-1),
- m_exitOnZoomOut(true)
- {
- }
-
- ViewerPage::Builder::~Builder()
- {
- }
-
- ViewerPage::Builder &ViewerPage::Builder::setNaviframe(
- const NaviframeSRef &navi)
- {
- m_navi = navi;
- return *this;
- }
-
- ViewerPage::Builder &ViewerPage::Builder::setMedia(
- const MediaItemSRef &media)
- {
- m_media = media;
- return *this;
- }
-
- ViewerPage::Builder &ViewerPage::Builder::setZoomIn(
- const int x, const int y)
- {
- m_zoomInX = x;
- m_zoomInY = y;
- return *this;
- }
-
- ViewerPage::Builder &ViewerPage::Builder::setExitOnZoomOut(const bool value)
- {
- m_exitOnZoomOut = value;
- return *this;
- }
-
- ViewerPageSRef ViewerPage::Builder::build(
- const ExitRequestHandler onExitRequest) const
- {
- if (!onExitRequest) {
- LOG_RETURN_VALUE(RES_INVALID_ARGUMENTS, {},
- "onExitRequest is NULL");
- }
- if (!m_navi) {
- LOG_RETURN_VALUE(RES_INVALID_ARGUMENTS, {}, "m_navi is NULL");
- }
- if (!m_media) {
- LOG_RETURN_VALUE(RES_INVALID_ARGUMENTS, {}, "m_media is NULL");
- }
-
- auto result = makeShared<ViewerPage>(
- m_navi, onExitRequest, m_media, m_exitOnZoomOut);
-
- FAIL_RETURN_VALUE(result->prepare(), {}, "result->prepare() failed!");
-
- if ((m_zoomInX >= 0) && (m_zoomInY >= 0)) {
- result->zoomIn(m_zoomInX, m_zoomInY);
- }
-
- return result;
- }
-
- // ViewerPage //
-
- ViewerPage::ViewerPage(RefCountObjBase &rc,
- const NaviframeSRef &navi,
- const ExitRequestHandler onExitRequest,
- const MediaItemSRef &media,
- const bool exitOnZoomOut) :
- Page(rc, navi, onExitRequest),
- m_media(media),
- m_exitOnZoomOut(exitOnZoomOut)
- {
- }
-
- ViewerPage::~ViewerPage()
- {
- }
-
- Result ViewerPage::prepare()
- {
- int mediaW = 0;
- int mediaH = 0;
- m_media->getResolution(mediaW, mediaH);
-
- m_imageViewer = ImageViewer::Builder().
- setImageSize(mediaW, mediaH).
- build(getNaviframe());
- if (!m_imageViewer) {
- LOG_RETURN(RES_FAIL, "ImageViewer::build() failed!");
- }
-
- FAIL_RETURN(m_media->getThumbnailPath(DELEGATE(
- ViewerPage::onThumbnail, this)),
- "m_media->getThumbnailPath() failed!");
-
- m_imageViewer->setHighResImagePath(m_media->getFilePath());
-
- m_imageViewer->addEventHandler(IMAGE_VIEWER_ZOOM_END,
- WEAK_DELEGATE(ViewerPage::onZoomEnd, asWeak(*this)));
-
- FAIL_RETURN(Page::prepare(
- [this]()
- {
- const auto topItem = getNaviframe().getTopItem();
- if (topItem) {
- return getNaviframe().insertAfter(topItem,
- *m_imageViewer, NAVIFRAME_EMPTY);
- }
- return getNaviframe().push(*m_imageViewer, NAVIFRAME_EMPTY);
- }),
- "Page::prepare() failed!");
-
- m_touchParser = makeShared<TouchParser>(*m_imageViewer);
- m_touchParser->setDoubleTapHandler(
- DELEGATE(ViewerPage::onDoubleTap, this));
-
- return RES_OK;
- }
-
- void ViewerPage::zoomIn(const int originX, const int originY)
- {
- m_imageViewer->zoomIn(originX, originY);
- }
-
- const std::string &ViewerPage::getMediaId() const
- {
- return m_media->getId();
- }
-
- void ViewerPage::onThumbnail(const Result result, const std::string &path)
- {
- FAIL_RETURN_VOID(result, "Failed to get thumbnail!");
-
- m_imageViewer->setLowResImagePath(path);
- }
-
- void ViewerPage::onZoomEnd(ucl::Widget &widget, void *eventInfo)
- {
- if (m_exitOnZoomOut && m_imageViewer->isZoomedOut()) {
- requestExit();
- }
- }
-
- void ViewerPage::onDoubleTap(int x, int y)
- {
- if (!isActive()) {
- return;
- }
- if (m_imageViewer->isZoomedOut()) {
- m_imageViewer->zoomIn(x, y);
- } else if (m_imageViewer->isZoomedIn()) {
- m_imageViewer->zoomOut();
- }
- }
-
- void ViewerPage::onBackKey()
- {
- if (m_imageViewer->isZoomedOut()) {
- requestExit();
- } else if (m_imageViewer->isZoomedIn()) {
- m_imageViewer->zoomOut();
- }
- }
-}
+++ /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_COMMON_H__
-#define __GALLERY_PRESENTATION_COMMON_H__
-
-#include "helpers.h"
-
-#include "../common.h"
-
-namespace gallery {
-
- constexpr ucl::ElmStyle SCROLLER_STYLE {"effect"};
-}
-
-#endif // __GALLERY_PRESENTATION_COMMON_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 "helpers.h"
-
-#include "ucl/gui/Window.h"
-#include "ucl/gui/Naviframe.h"
-
-#include "common.h"
-
-namespace gallery { namespace { namespace impl {
-
- using namespace ucl;
-
- constexpr EoDataKey CIRCLE_SURFACE {"gallery,eext,circle,surface"};
-}}}
-
-namespace gallery {
-
- using namespace ucl;
-
- Result createCircleSurface(Naviframe &navi)
- {
- const auto win = navi.getWindow();
- if (!win) {
- LOG_RETURN(RES_FAIL, "Failed to get Window from Naviframe!");
- }
-
- if (win->getData(impl::CIRCLE_SURFACE)) {
- LOG_RETURN(RES_ILLEGAL_STATE, "Circle Surface data already set!");
- }
-
- const auto sfc = eext_circle_surface_naviframe_add(navi);
- if (!sfc) {
- LOG_RETURN(RES_FAIL,
- "eext_circle_surface_conformant_add() failed!");
- }
-
- win->setData(impl::CIRCLE_SURFACE, sfc);
-
- return RES_OK;
- }
-
- Eext_Circle_Surface *getCircleSurface(const ElmWidget &widget)
- {
- const auto win = widget.getWindow();
- if (!win) {
- LOG_RETURN_VALUE(RES_FAIL, nullptr,
- "Failed to get Window from widget!");
- }
-
- const auto sfc = static_cast<Eext_Circle_Surface *>(
- win->getData(impl::CIRCLE_SURFACE));
- if (!sfc) {
- LOG_RETURN_VALUE(RES_FAIL, nullptr,
- "Failed to get Eext_Circle_Surface from window!");
- }
-
- return sfc;
- }
-}
-
+++ /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_HELPERS_H__
-#define __GALLERY_PRESENTATION_HELPERS_H__
-
-#include "presentation/types.h"
-
-namespace ucl {
-
- class ElmWidget;
- class Naviframe;
-}
-
-namespace gallery {
-
- ucl::Result createCircleSurface(ucl::Naviframe &navi);
-
- Eext_Circle_Surface *getCircleSurface(const ucl::ElmWidget &widget);
-}
-
-#endif // __GALLERY_PRESENTATION_HELPERS_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 "presenters/Instance.h"
+
+#include <system_settings.h>
+
+#include "ucl/appfw/SysEventProvider.h"
+#include "ucl/appfw/helpers.h"
+
+#include "model/Gallery.h"
+#include "model/IMediaAlbum.h"
+
+#include "presenters/NoContentPage.h"
+#include "presenters/ThumbnailPage.h"
+
+#include "resources.h"
+#include "common.h"
+
+namespace gallery { namespace { namespace impl {
+
+ // TODO Since feature is temporary using hard-coded path
+ constexpr auto MEDIA_FOLDER = "/opt/usr/home/owner/media";
+}}}
+
+namespace gallery {
+
+ using namespace ucl;
+
+ Instance::Instance(SysEventProvider &sysEventProvider) :
+ m_sysEventProvider(sysEventProvider),
+ m_isScanInProgress(false)
+ {
+ }
+
+ Instance::~Instance()
+ {
+ stopMediaContentScan();
+ }
+
+ Result Instance::onCreate(IInstanceContext *const context)
+ {
+ m_context = context;
+
+ m_gallery = Gallery::newInstance();
+ if (!m_gallery) {
+ LOG_RETURN(RES_FAIL, "Gallery::newInstance() failed!");
+ }
+
+ m_win = m_context->getWindow();
+
+ FAIL_RETURN(setupTheme(), "setupTheme() failed!");
+
+ m_navi = Naviframe::Builder().
+ build(m_win->getConformant());
+ if (!m_navi) {
+ LOG_RETURN(RES_FAIL, "Naviframe::build() failed!");
+ }
+
+ m_win->getConformant().setContent(*m_navi);
+
+ FAIL_RETURN(createCircleSurface(*m_navi),
+ "createCircleSurface() failed!");
+
+ m_sysEventProvider.addEventHandler(
+ DELEGATE(Instance::onSysEvent, this));
+
+ return RES_OK;
+ }
+
+ Result Instance::setupTheme()
+ {
+ m_theme = Theme::create();
+ if (isNotValid(m_theme)) {
+ LOG_RETURN(RES_FAIL, "Theme::create() failed!");
+ }
+
+ m_theme.addExtension(getResPath(THEME_EDJE_PATH));
+
+ m_win->setTheme(m_theme);
+
+ return RES_OK;
+ }
+
+ void Instance::onPause()
+ {
+ DLOG("PAUSE");
+ }
+
+ void Instance::onResume()
+ {
+ DLOG("RESUME");
+
+ if (SCAN_MEDIA_ON_RESUME) {
+ rescanMediaContent();
+ }
+
+ ecore_animator_frametime_set(1.0 / 60.0);
+ }
+
+ void Instance::rescanMediaContent()
+ {
+ stopMediaContentScan();
+ startMediaContentScan();
+ }
+
+ void Instance::stopMediaContentScan()
+ {
+ if (m_isScanInProgress) {
+ m_isScanInProgress = false;
+ DLOG("Scan is in progress. Terminating...");
+ const int ret = media_content_cancel_scan_folder(
+ impl::MEDIA_FOLDER);
+ if (ret != 0) {
+ WLOG("media_content_cancel_scan_folder() failed: %d", ret);
+ }
+ }
+ }
+
+ void Instance::startMediaContentScan()
+ {
+ DLOG("Starting media scan...");
+
+ int ret = media_content_scan_folder(impl::MEDIA_FOLDER, true,
+ CALLBACK_B(Instance::onScanComplete), this);
+ if (ret != 0) {
+ ELOG("media_content_scan_folder() failed: %d", ret);
+ return;
+ }
+
+ m_isScanInProgress = true;
+ }
+
+ void Instance::onScanComplete(media_content_error_e error)
+ {
+ DLOG("Media scan complete. error: %d", error);
+
+ m_isScanInProgress = false;
+
+ const auto thumbPage = dynamicRefCast<ThumbnailPage>(m_page);
+
+ if (isNotEmpty(m_gallery->getAlbum())) {
+ if (thumbPage) {
+ DLOG("Reloading the ThumbnailPage...");
+ thumbPage->reload();
+ } else {
+ if (m_page) {
+ m_page->exitNoTransition();
+ }
+ createThumbnailPage();
+ }
+ } else if (thumbPage) {
+ DLOG("Exit from ThumbnailPage witout transition...");
+ thumbPage->exitNoTransition();
+ createNoContentPage();
+ }
+ }
+
+ void Instance::onAppControl(app_control_h appControl)
+ {
+ DLOG("APP CONTROL");
+
+ if (!m_page) {
+ if (isEmpty(m_gallery->getAlbum())) {
+ createNoContentPage();
+ } else {
+ createThumbnailPage();
+ }
+ }
+
+ if (!m_win->isVisible()) {
+ DLOG("Show the window.");
+ show(*m_win);
+ }
+ }
+
+ void Instance::createNoContentPage()
+ {
+ DLOG("Creating NoContentPage.");
+ m_page = NoContentPage::Builder().setNaviframe(m_navi).
+ build(DELEGATE(Instance::onPageExitRequest, this));
+ }
+
+ void Instance::createThumbnailPage()
+ {
+ DLOG("Creating ThumbnailPage.");
+ m_page = ThumbnailPage::Builder().setNaviframe(m_navi).
+ setAlbum(m_gallery->getAlbum()).
+ build(DELEGATE(Instance::onPageExitRequest, this));
+ }
+
+ void Instance::onPageExitRequest(Page &page)
+ {
+ if (page.isAtBottom()) {
+ DLOG("Bottom page. Lowering the window.");
+ m_win->lower();
+ } else {
+ DLOG("Exit page.");
+ page.exit();
+ }
+ }
+
+ void Instance::onSysEvent(const SysEvent sysEvent)
+ {
+ switch(sysEvent) {
+ case SysEvent::LANGUAGE_CHANGED:
+ DLOG("SysEvent::LANGUAGE_CHANGED");
+ {
+ char *locale = NULL;
+ system_settings_get_value_string(
+ SYSTEM_SETTINGS_KEY_LOCALE_LANGUAGE, &locale);
+ elm_language_set(locale);
+ free(locale);
+ }
+ break;
+ default:
+ DLOG("sysEvent: %d", sysEvent);
+ break;
+ }
+ }
+}
--- /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 "presenters/InstanceManager.h"
+
+#include "presenters/Instance.h"
+
+namespace gallery {
+
+ using namespace ucl;
+
+ InstanceManager::InstanceManager() :
+ InstanceManagerBase(AppParams().
+ set(AppParam::WINDOW_NAME, WINDOW_NAME).
+ set(AppParam::BASE_SCALE, BASE_SCALE))
+ {
+ }
+
+ IInstanceSRef InstanceManager::newInstance() const
+ {
+ return makeShared<Instance>(getSysEventProvider());
+ }
+}
--- /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 "presenters/NoContentPage.h"
+
+#include "ucl/gui/Layout.h"
+
+#include "resources.h"
+#include "common.h"
+
+namespace gallery {namespace { namespace impl {
+
+ using namespace ucl;
+
+ constexpr LayoutTheme ICON_THEME
+ {"layout", "gallery_image", "gallery_icon_no_photos.png"};
+}}}
+
+namespace gallery {
+
+ using namespace ucl;
+
+ // NoContentPage::Builder //
+
+ NoContentPage::Builder::Builder()
+ {
+ }
+
+ NoContentPage::Builder::~Builder()
+ {
+ }
+
+ NoContentPage::Builder &NoContentPage::Builder::setNaviframe(
+ const NaviframeSRef &navi)
+ {
+ m_navi = navi;
+ return *this;
+ }
+
+ NoContentPageSRef NoContentPage::Builder::build(
+ const ExitRequestHandler onExitRequest) const
+ {
+ if (!onExitRequest) {
+ LOG_RETURN_VALUE(RES_INVALID_ARGUMENTS, {},
+ "onExitRequest is NULL");
+ }
+ if (!m_navi) {
+ LOG_RETURN_VALUE(RES_INVALID_ARGUMENTS, {}, "m_navi is NULL");
+ }
+
+ auto result = makeShared<NoContentPage>(m_navi, onExitRequest);
+
+ FAIL_RETURN_VALUE(result->prepare(), {}, "result->prepare() failed!");
+
+ return result;
+ }
+
+ // NoContentPage //
+
+ NoContentPage::NoContentPage(RefCountObjBase &rc,
+ const NaviframeSRef &navi,
+ const ExitRequestHandler onExitRequest) :
+ Page(rc, navi, onExitRequest)
+ {
+ }
+
+ NoContentPage::~NoContentPage()
+ {
+ }
+
+ Result NoContentPage::prepare()
+ {
+ const auto layout = Layout::Builder().
+ setIsOwner(true).
+ setTheme(LAYOUT_NO_CONTENTS).
+ build(getNaviframe());
+ if (!layout) {
+ LOG_RETURN(RES_FAIL, "Layout::build() failed!");
+ }
+
+ const auto icon = Layout::Builder().
+ setTheme(impl::ICON_THEME).
+ build(*layout);
+ if (!layout) {
+ LOG_RETURN(RES_FAIL, "Layout::build() failed!");
+ }
+
+ layout->setContent(*icon);
+ layout->setText(PART_TITLE, STR_APP_NAME);
+ layout->setText(STR_NO_PHOTOS);
+
+ FAIL_RETURN(Page::prepare(
+ [this, &layout]()
+ {
+ return getNaviframe().push(*layout, NAVIFRAME_EMPTY);
+ }),
+ "Page::prepare() failed!");
+
+ layout->setIsOwner(false);
+
+ return RES_OK;
+ }
+}
--- /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 "presenters/Page.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,
+ const 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() && isAtTop()) {
+ 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 (isAtTop()) {
+ m_item.del();
+ dispatchTopPageChanged();
+ } else if (isValid(m_item)) {
+ m_item.del();
+ }
+ }
+
+ 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 "presenters/PreviewPage.h"
+
+#include "model/IMediaAlbum.h"
+#include "model/MediaItem.h"
+
+#include "view/ImageGrid.h"
+
+#include "presenters/ViewerPage.h"
+
+#include "common.h"
+
+namespace gallery {
+
+ using namespace ucl;
+
+ // PreviewPage::Builder //
+
+ PreviewPage::Builder::Builder() :
+ m_startItemIndex(0)
+ {
+ }
+
+ PreviewPage::Builder::~Builder()
+ {
+ }
+
+ PreviewPage::Builder &PreviewPage::Builder::setNaviframe(
+ const NaviframeSRef &navi)
+ {
+ m_navi = navi;
+ return *this;
+ }
+
+ PreviewPage::Builder &PreviewPage::Builder::setAlbum(
+ const IMediaAlbumSRef &album)
+ {
+ m_album = album;
+ return *this;
+ }
+
+ PreviewPage::Builder &PreviewPage::Builder::setStartItemIndex(
+ const int index)
+ {
+ m_startItemIndex = index;
+ return *this;
+ }
+
+ PreviewPageSRef PreviewPage::Builder::build(
+ const ExitRequestHandler onExitRequest) const
+ {
+ if (!onExitRequest) {
+ LOG_RETURN_VALUE(RES_INVALID_ARGUMENTS, {},
+ "onExitRequest is NULL");
+ }
+ if (!m_navi) {
+ LOG_RETURN_VALUE(RES_INVALID_ARGUMENTS, {}, "m_navi is NULL");
+ }
+ if (!m_album) {
+ LOG_RETURN_VALUE(RES_INVALID_ARGUMENTS, {}, "m_album is NULL");
+ }
+
+ auto result = makeShared<PreviewPage>(
+ m_navi, onExitRequest, m_album);
+
+ FAIL_RETURN_VALUE(result->prepare(), {}, "result->prepare() failed!");
+
+ if (m_startItemIndex > 0) {
+ result->showItem(m_startItemIndex);
+ }
+
+ return result;
+ }
+
+ // PreviewPage::Item //
+
+ class PreviewPage::Item : public NonCopyable {
+ public:
+ Item(MediaItemSRef &&media, ImageGrid &imageGrid, const int itemIndex) :
+ m_media(std::move(media)),
+ m_imageGrid(imageGrid),
+ m_index(itemIndex)
+ {
+ }
+
+ void realize()
+ {
+ FAIL_LOG(m_media->getThumbnailPath(
+ DELEGATE(Item::onThumbnail, this)),
+ "getThumbnailPath() failed!");
+ }
+
+ void unrealize()
+ {
+ m_media->cancelThumbnailPathGet();
+ }
+
+ MediaItemSRef getMedia()
+ {
+ return m_media;
+ }
+
+ private:
+ void onThumbnail(const Result result, const std::string &path)
+ {
+ FAIL_LOG(result, "Failed to get thumbnail!");
+
+ ImageGrid::ItemParams params = {};
+ m_media->getResolution(params.aspectX, params.aspectY);
+ params.imagePath = m_media->getFilePath();
+ params.bgImagePath = path;
+ params.flags = ImageGrid::UF_BLOCK_CLICKS;
+
+ m_imageGrid.updateItem(m_index, params);
+ }
+
+ private:
+ const MediaItemSRef m_media;
+ ImageGrid &m_imageGrid;
+ const int m_index;
+ };
+
+ // PreviewPage //
+
+ PreviewPage::PreviewPage(RefCountObjBase &rc,
+ const NaviframeSRef &navi,
+ const ExitRequestHandler onExitRequest,
+ const IMediaAlbumSRef &album) :
+ Page(rc, navi, onExitRequest),
+ m_album(album)
+ {
+ }
+
+ PreviewPage::~PreviewPage()
+ {
+ if (m_page) {
+ m_page->exitNoTransition();
+ }
+ m_imageGrid->setListener(nullptr);
+ }
+
+ void PreviewPage::reload()
+ {
+ ImageGrid::Unrealizer u(*m_imageGrid);
+
+ m_items.clear();
+
+ FAIL_LOG(m_album->forEachMedia(
+ DELEGATE(PreviewPage::onEachMedia, this)),
+ "m_album->forEachMedia() failed!");
+
+ m_imageGrid->setItemCount(m_items.size());
+
+ const auto viewerPage = dynamicRefCast<ViewerPage>(m_page);
+ if (viewerPage) {
+ const auto mediaId = viewerPage->getMediaId();
+ const auto it = std::find_if(m_items.begin(), m_items.end(),
+ [&mediaId](const ItemUPtr &item)
+ {
+ return (item->getMedia()->getId() == mediaId);
+ });
+ if (it == m_items.end()) {
+ DLOG("Viewed media item was removed.");
+ deleteTo();
+ } else {
+ m_imageGrid->scrollToItem(it - m_items.begin());
+ }
+ }
+ }
+
+ Result PreviewPage::prepare()
+ {
+ m_imageGrid = ImageGrid::Builder().
+ setListener(this).
+ setType(ImageGrid::Type::LINEAR).
+ build(getNaviframe());
+ if (!m_imageGrid) {
+ LOG_RETURN(RES_FAIL, "ImageGrid::build() failed!");
+ }
+
+ FAIL_RETURN(m_album->forEachMedia(
+ DELEGATE(PreviewPage::onEachMedia, this)),
+ "m_album->forEachMedia() failed!");
+
+ FAIL_RETURN(Page::prepare(
+ [this]()
+ {
+ return getNaviframe().push(*m_imageGrid, NAVIFRAME_EMPTY);
+ }),
+ "Page::prepare() failed!");
+
+ m_imageGrid->setItemCount(m_items.size());
+
+ return RES_OK;
+ }
+
+ void PreviewPage::showItem(const int itemIndex)
+ {
+ m_imageGrid->scrollToItem(itemIndex);
+ }
+
+ bool PreviewPage::onEachMedia(MediaItemSRef &&media)
+ {
+ m_items.emplace_back(
+ new Item(std::move(media), *m_imageGrid, m_items.size()));
+ return true;
+ }
+
+ void PreviewPage::onActivate()
+ {
+ m_imageGrid->activateRotary();
+ }
+
+ void PreviewPage::onDeactivate()
+ {
+ m_imageGrid->deactivateRotary();
+ }
+
+ void PreviewPage::onItemRealized(const int itemIndex)
+ {
+ m_items[itemIndex]->realize();
+ }
+
+ void PreviewPage::onItemUnrealized(const int itemIndex)
+ {
+ m_items[itemIndex]->unrealize();
+ }
+
+ void PreviewPage::onItemEvent(const int itemIndex,
+ const int event, const int x, const int y)
+ {
+ if (!isActive() || (event != ImageGrid::ITEM_EVENT_DOUBLE_TAP)) {
+ return;
+ }
+
+ m_page = ViewerPage::Builder().
+ setNaviframe(asShared(getNaviframe())).
+ setZoomIn(x, y).
+ setMedia(m_items[itemIndex]->getMedia()).
+ build(DELEGATE(PreviewPage::onPageExitRequest, this));
+ }
+
+ void PreviewPage::onPageExitRequest(Page &page)
+ {
+ deleteTo();
+ }
+}
--- /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 "presenters/ThumbnailPage.h"
+
+#include "model/IMediaAlbum.h"
+#include "model/MediaItem.h"
+
+#include "view/ImageGrid.h"
+
+#include "presenters/PreviewPage.h"
+
+#include "common.h"
+
+namespace gallery {
+
+ using namespace ucl;
+
+ // ThumbnailPage::Builder //
+
+ ThumbnailPage::Builder::Builder()
+ {
+ }
+
+ ThumbnailPage::Builder::~Builder()
+ {
+ }
+
+ ThumbnailPage::Builder &ThumbnailPage::Builder::setNaviframe(
+ const NaviframeSRef &navi)
+ {
+ m_navi = navi;
+ return *this;
+ }
+
+ ThumbnailPage::Builder &ThumbnailPage::Builder::setAlbum(
+ const IMediaAlbumSRef &album)
+ {
+ m_album = album;
+ return *this;
+ }
+
+ ThumbnailPageSRef ThumbnailPage::Builder::build(
+ const ExitRequestHandler onExitRequest) const
+ {
+ if (!onExitRequest) {
+ LOG_RETURN_VALUE(RES_INVALID_ARGUMENTS, {},
+ "onExitRequest is NULL");
+ }
+ if (!m_navi) {
+ LOG_RETURN_VALUE(RES_INVALID_ARGUMENTS, {}, "m_navi is NULL");
+ }
+ if (!m_album) {
+ LOG_RETURN_VALUE(RES_INVALID_ARGUMENTS, {}, "m_album is NULL");
+ }
+
+ auto result = makeShared<ThumbnailPage>(
+ m_navi, onExitRequest, m_album);
+
+ FAIL_RETURN_VALUE(result->prepare(), {}, "result->prepare() failed!");
+
+ return result;
+ }
+
+ // ThumbnailPage::RealizedItem //
+
+ class ThumbnailPage::RealizedItem : public NonCopyable {
+ public:
+ RealizedItem(ThumbnailPage &parent, const int index) :
+ m_parent(parent),
+ m_index(index)
+ {
+ FAIL_LOG(m_parent.m_mediaItems[m_index]->getThumbnailPath(
+ DELEGATE(RealizedItem::onThumbnail, this)),
+ "getThumbnailPath() failed!");
+ }
+
+ ~RealizedItem()
+ {
+ m_parent.m_mediaItems[m_index]->cancelThumbnailPathGet();
+ }
+
+ int getIndex() const
+ {
+ return m_index;
+ }
+
+ private:
+ void onThumbnail(const Result result, const std::string &path)
+ {
+ FAIL_RETURN_VOID(result, "Failed to get thumbnail!");
+
+ ImageGrid::ItemParams params = {};
+ params.imagePath = path;
+
+ m_parent.m_imageGrid->updateItem(m_index, params);
+ }
+
+ private:
+ ThumbnailPage &m_parent;
+ int m_index;
+ };
+
+ // ThumbnailPage //
+
+ ThumbnailPage::ThumbnailPage(RefCountObjBase &rc,
+ const NaviframeSRef &navi,
+ const ExitRequestHandler onExitRequest,
+ const IMediaAlbumSRef &album) :
+ Page(rc, navi, onExitRequest),
+ m_album(album)
+ {
+ }
+
+ ThumbnailPage::~ThumbnailPage()
+ {
+ if (m_page) {
+ m_page->exitNoTransition();
+ }
+ m_imageGrid->setListener(nullptr);
+ }
+
+ void ThumbnailPage::reload()
+ {
+ ImageGrid::Unrealizer u(*m_imageGrid);
+
+ m_mediaItems.clear();
+
+ FAIL_LOG(m_album->forEachMedia(
+ DELEGATE(ThumbnailPage::onEachMedia, this)),
+ "m_album->forEachMedia() failed!");
+
+ m_imageGrid->setItemCount(m_mediaItems.size());
+
+ if (const auto vp = dynamic_cast<PreviewPage *>(m_page.get())) {
+ vp->reload();
+ }
+ }
+
+ Result ThumbnailPage::prepare()
+ {
+ FAIL_RETURN(m_album->forEachMedia(
+ DELEGATE(ThumbnailPage::onEachMedia, this)),
+ "m_album->forEachMedia() failed!");
+
+ m_imageGrid = ImageGrid::Builder().
+ setListener(this).
+ setType(ImageGrid::Type::HCOMB_3X3).
+ build(getNaviframe());
+ if (!m_imageGrid) {
+ LOG_RETURN(RES_FAIL, "ImageGrid::build() failed!");
+ }
+
+ FAIL_RETURN(Page::prepare(
+ [this]()
+ {
+ return getNaviframe().push(*m_imageGrid, NAVIFRAME_EMPTY);
+ }),
+ "Page::prepare() failed!");
+
+ m_imageGrid->setItemCount(m_mediaItems.size());
+
+ return RES_OK;
+ }
+
+ bool ThumbnailPage::onEachMedia(MediaItemSRef &&media)
+ {
+ m_mediaItems.emplace_back(std::move(media));
+ return true;
+ }
+
+ void ThumbnailPage::onActivate()
+ {
+ m_imageGrid->activateRotary();
+ }
+
+ void ThumbnailPage::onDeactivate()
+ {
+ m_imageGrid->deactivateRotary();
+ }
+
+ void ThumbnailPage::onItemRealized(const int itemIndex)
+ {
+ m_realizedItems.emplace_back(new RealizedItem(*this, itemIndex));
+ }
+
+ void ThumbnailPage::onItemUnrealized(const int itemIndex)
+ {
+ const auto it = std::find_if(
+ m_realizedItems.begin(), m_realizedItems.end(),
+ [itemIndex](const RealizedItemUPtr &item)
+ {
+ return (item->getIndex() == itemIndex);
+ });
+ if (it != m_realizedItems.end()) {
+ m_realizedItems.erase(it);
+ } else {
+ WLOG("Item is not found in realized list!");
+ }
+ }
+
+ void ThumbnailPage::onItemEvent(const int itemIndex,
+ const int event, const int x, const int y)
+ {
+ if (!isActive() || (event != ImageGrid::ITEM_EVENT_CLICK)) {
+ return;
+ }
+
+ m_page = PreviewPage::Builder().
+ setNaviframe(asShared(getNaviframe())).
+ setAlbum(m_album).
+ setStartItemIndex(itemIndex).
+ build(DELEGATE(ThumbnailPage::onPageExitRequest, this));
+ }
+
+ void ThumbnailPage::onPageExitRequest(Page &page)
+ {
+ popTo();
+ }
+}
--- /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 "presenters/ViewerPage.h"
+
+#include "model/MediaItem.h"
+
+#include "view/ImageViewer.h"
+#include "view/TouchParser.h"
+
+#include "common.h"
+
+namespace gallery {
+
+ using namespace ucl;
+
+ // ViewerPage::Builder //
+
+ ViewerPage::Builder::Builder() :
+ m_zoomInX(-1),
+ m_zoomInY(-1),
+ m_exitOnZoomOut(true)
+ {
+ }
+
+ ViewerPage::Builder::~Builder()
+ {
+ }
+
+ ViewerPage::Builder &ViewerPage::Builder::setNaviframe(
+ const NaviframeSRef &navi)
+ {
+ m_navi = navi;
+ return *this;
+ }
+
+ ViewerPage::Builder &ViewerPage::Builder::setMedia(
+ const MediaItemSRef &media)
+ {
+ m_media = media;
+ return *this;
+ }
+
+ ViewerPage::Builder &ViewerPage::Builder::setZoomIn(
+ const int x, const int y)
+ {
+ m_zoomInX = x;
+ m_zoomInY = y;
+ return *this;
+ }
+
+ ViewerPage::Builder &ViewerPage::Builder::setExitOnZoomOut(const bool value)
+ {
+ m_exitOnZoomOut = value;
+ return *this;
+ }
+
+ ViewerPageSRef ViewerPage::Builder::build(
+ const ExitRequestHandler onExitRequest) const
+ {
+ if (!onExitRequest) {
+ LOG_RETURN_VALUE(RES_INVALID_ARGUMENTS, {},
+ "onExitRequest is NULL");
+ }
+ if (!m_navi) {
+ LOG_RETURN_VALUE(RES_INVALID_ARGUMENTS, {}, "m_navi is NULL");
+ }
+ if (!m_media) {
+ LOG_RETURN_VALUE(RES_INVALID_ARGUMENTS, {}, "m_media is NULL");
+ }
+
+ auto result = makeShared<ViewerPage>(
+ m_navi, onExitRequest, m_media, m_exitOnZoomOut);
+
+ FAIL_RETURN_VALUE(result->prepare(), {}, "result->prepare() failed!");
+
+ if ((m_zoomInX >= 0) && (m_zoomInY >= 0)) {
+ result->zoomIn(m_zoomInX, m_zoomInY);
+ }
+
+ return result;
+ }
+
+ // ViewerPage //
+
+ ViewerPage::ViewerPage(RefCountObjBase &rc,
+ const NaviframeSRef &navi,
+ const ExitRequestHandler onExitRequest,
+ const MediaItemSRef &media,
+ const bool exitOnZoomOut) :
+ Page(rc, navi, onExitRequest),
+ m_media(media),
+ m_exitOnZoomOut(exitOnZoomOut)
+ {
+ }
+
+ ViewerPage::~ViewerPage()
+ {
+ }
+
+ Result ViewerPage::prepare()
+ {
+ int mediaW = 0;
+ int mediaH = 0;
+ m_media->getResolution(mediaW, mediaH);
+
+ m_imageViewer = ImageViewer::Builder().
+ setImageSize(mediaW, mediaH).
+ build(getNaviframe());
+ if (!m_imageViewer) {
+ LOG_RETURN(RES_FAIL, "ImageViewer::build() failed!");
+ }
+
+ FAIL_RETURN(m_media->getThumbnailPath(DELEGATE(
+ ViewerPage::onThumbnail, this)),
+ "m_media->getThumbnailPath() failed!");
+
+ m_imageViewer->setHighResImagePath(m_media->getFilePath());
+
+ m_imageViewer->addEventHandler(IMAGE_VIEWER_ZOOM_END,
+ WEAK_DELEGATE(ViewerPage::onZoomEnd, asWeak(*this)));
+
+ FAIL_RETURN(Page::prepare(
+ [this]()
+ {
+ const auto topItem = getNaviframe().getTopItem();
+ if (topItem) {
+ return getNaviframe().insertAfter(topItem,
+ *m_imageViewer, NAVIFRAME_EMPTY);
+ }
+ return getNaviframe().push(*m_imageViewer, NAVIFRAME_EMPTY);
+ }),
+ "Page::prepare() failed!");
+
+ m_touchParser = makeShared<TouchParser>(*m_imageViewer);
+ m_touchParser->setDoubleTapHandler(
+ DELEGATE(ViewerPage::onDoubleTap, this));
+
+ return RES_OK;
+ }
+
+ void ViewerPage::zoomIn(const int originX, const int originY)
+ {
+ m_imageViewer->zoomIn(originX, originY);
+ }
+
+ const std::string &ViewerPage::getMediaId() const
+ {
+ return m_media->getId();
+ }
+
+ void ViewerPage::onThumbnail(const Result result, const std::string &path)
+ {
+ FAIL_RETURN_VOID(result, "Failed to get thumbnail!");
+
+ m_imageViewer->setLowResImagePath(path);
+ }
+
+ void ViewerPage::onZoomEnd(ucl::Widget &widget, void *eventInfo)
+ {
+ if (m_exitOnZoomOut && m_imageViewer->isZoomedOut()) {
+ requestExit();
+ }
+ }
+
+ void ViewerPage::onDoubleTap(int x, int y)
+ {
+ if (!isActive()) {
+ return;
+ }
+ if (m_imageViewer->isZoomedOut()) {
+ m_imageViewer->zoomIn(x, y);
+ } else if (m_imageViewer->isZoomedIn()) {
+ m_imageViewer->zoomOut();
+ }
+ }
+
+ void ViewerPage::onBackKey()
+ {
+ if (m_imageViewer->isZoomedOut()) {
+ requestExit();
+ } else if (m_imageViewer->isZoomedIn()) {
+ m_imageViewer->zoomOut();
+ }
+ }
+}
--- /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_PRESENTERS_COMMON_H__
+#define __GALLERY_PRESENTERS_COMMON_H__
+
+#include "ucl/gui/stdTheme.h"
+
+#include "view/helpers.h"
+
+#include "../common.h"
+
+#endif // __GALLERY_PRESENTERS_COMMON_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 "view/ImageGrid.h"
+
+#include <array>
+#include <vector>
+
+#include "ucl/gui/Layout.h"
+
+#include "view/IImageGridListener.h"
+#include "view/TouchParser.h"
+
+#include "common.h"
+
+namespace gallery { namespace { namespace impl {
+
+ using namespace ucl;
+
+ // Related to ImageGrid //
+ const TString SLOT_PART_FMT {"swallow.cell_%d"};
+
+ // Related to Button //
+ constexpr ElmStyle ITEM_BTN_STYLE {"gallery_image"};
+ constexpr EdjePart PART_BTN_BG {"swallow.bg"};
+ constexpr SmartEvent BTN_CLICKED {"clicked"};
+ constexpr EdjeSignal BTN_BLOCK_CLICKS {"gallery,block,clicks"};
+ constexpr EdjeSignal BTN_UNBLOCK_CLICKS {"gallery,unblock,clicks"};
+
+ // Other //
+ constexpr auto HCOMB_SCROLL_LIMIT = 1000;
+}}}
+
+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(
+ IImageGridListener *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 int slotsPerPage;
+ 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;
+
+ virtual int calcExtraPaddingSize(const int slotSize,
+ const int itemCount) const
+ {
+ return 0;
+ }
+
+ Info(const std::array<LayoutTheme, 2> &slotThemes,
+ const std::array<int, 2> &slotLens,
+ const int scrollLimit, const int slotsPerPage,
+ const bool isHorizontal) :
+ slotThemes(slotThemes),
+ slotLens(slotLens),
+ scrollLimit(scrollLimit),
+ slotsPerPage(slotsPerPage),
+ 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);
+ }
+
+ virtual int calcExtraPaddingSize(const int slotSize,
+ const int itemCount) const final override
+ {
+ return slotSize;
+ }
+
+ HcombInfo(const int totalLength,
+ const std::array<LayoutTheme, 2> &slotThemes) :
+ Info(slotThemes, {{(totalLength / 2), ceilDiv<2>(totalLength)}},
+ impl::HCOMB_SCROLL_LIMIT, (totalLength - 1), true),
+ totalLength(totalLength)
+ {
+ }
+ };
+
+ // ImageGrid::LinearInfo //
+
+ struct ImageGrid::LinearInfo : Info {
+ virtual int calcItemIndexFromCell(
+ const int slotIndex, const int itemOffset) const final override
+ {
+ return (slotIndex / 2);
+ }
+
+ virtual void calcCellFromItemIndex(const int itemIndex,
+ int &slotIndex, int &itemOffset) const final override
+ {
+ slotIndex = (itemIndex * 2);
+ itemOffset = 0;
+ }
+
+ virtual int calcMaxSlotCount(const int itemCount) const final override
+ {
+ return (itemCount * 2);
+ }
+
+ LinearInfo(const LayoutTheme &slotTheme, const bool isHorizontal) :
+ Info({{slotTheme}}, {{1, 0}}, 1, 1, isHorizontal)
+ {
+ }
+ };
+
+ // ImageGrid::Slot //
+
+ class ImageGrid::Slot {
+ private:
+ class Item : public RefCountAware {
+ public:
+ friend class RefCountObj<Item>;
+ Item(RefCountObjBase &rc,
+ const ImageGrid &imageGrid, Widget &parent) :
+ RefCountAware(&rc),
+ m_imageGrid(imageGrid),
+ m_btn(elm_button_add(parent)),
+ m_image(elm_image_add(m_btn)),
+ m_realizeIndex(-1),
+ m_imageLoadSize(0),
+ m_wasUpdated(false),
+ m_isClicksBlocked(false)
+ {
+ m_btn.setFocusAlowed(false);
+ m_btn.setStyle(impl::ITEM_BTN_STYLE);
+ show(m_btn);
+
+ elm_image_preload_disabled_set(m_image, EINA_FALSE);
+ elm_image_aspect_fixed_set(m_image, EINA_TRUE);
+ elm_image_fill_outside_set(m_image, EINA_TRUE);
+ m_btn.setContent(m_image);
+ show(m_image);
+
+ m_btn.addEventHandler(impl::BTN_CLICKED, WEAK_DELEGATE(
+ Item::onClicked, asWeak(*this)));
+
+ m_touchParser = makeShared<TouchParser>(m_btn);
+ m_touchParser->setDoubleTapHandler(
+ DELEGATE(Item::onDoubleTap, this));
+ }
+
+ Widget &getWidget()
+ {
+ return m_btn;
+ }
+
+ void setImageLoadSize(const int value)
+ {
+ m_imageLoadSize = value;
+ elm_image_prescale_set(m_image, m_imageLoadSize);
+ }
+
+ 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_btn);
+ }
+ }
+
+ 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;
+ }
+
+ updateClicksBlock(params);
+ updateImage(params);
+ updateBgImage(params);
+
+ makeWhite(m_btn);
+
+ m_wasUpdated = true;
+
+ return true;
+ }
+
+ private:
+ void updateClicksBlock(const ItemParams ¶ms)
+ {
+ if (params.flags & UF_BLOCK_CLICKS) {
+ if (!m_isClicksBlocked) {
+ m_isClicksBlocked = true;
+ m_btn.emitSignal(impl::BTN_BLOCK_CLICKS);
+ }
+ } else if (m_isClicksBlocked) {
+ m_isClicksBlocked = false;
+ m_btn.emitSignal(impl::BTN_UNBLOCK_CLICKS);
+ }
+ }
+
+ void updateImage(const ItemParams ¶ms)
+ {
+ if (isEmpty(params.imagePath)) {
+ if (!m_wasUpdated || (params.flags & UF_LOSE_IMAGE)) {
+ makeTransparent(m_image);
+ }
+ return;
+ }
+
+ elm_image_file_set(m_image, params.imagePath.c_str(), NULL);
+
+ makeWhite(m_image);
+ }
+
+ void updateBgImage(const ItemParams ¶ms)
+ {
+ if (isEmpty(params.bgImagePath)) {
+ if (m_bgImage && (!m_wasUpdated ||
+ (params.flags & UF_LOSE_BG))) {
+ makeTransparent(*m_bgImage);
+ }
+ return;
+ }
+
+ if (!m_bgImage) {
+ m_bgImage = makeShared<Widget>(
+ evas_object_image_filled_add(m_btn.getEvas()));
+ evas_object_image_load_size_set(*m_bgImage,
+ m_imageLoadSize, m_imageLoadSize);
+ m_btn.setContent(impl::PART_BTN_BG, *m_bgImage);
+ show(*m_bgImage);
+ }
+
+ evas_object_image_file_set(*m_bgImage,
+ params.bgImagePath.c_str(), NULL);
+
+ int w = params.aspectX;
+ int h = params.aspectY;
+ if ((w == 0) || (h == 0)) {
+ evas_object_image_size_get(*m_bgImage, &w, &h);
+ }
+ m_bgImage->setARHint(WidgetARHint::NEITHER, w, h);
+
+ makeWhite(*m_bgImage);
+ }
+
+ void onClicked(Widget &wifget, void *eventInfo)
+ {
+ if (isRealized()) {
+ 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);
+ }
+ }
+
+ private:
+ const ImageGrid &m_imageGrid;
+ StyledWidget m_btn;
+ StyledWidget m_image;
+ WidgetSRef m_bgImage;
+ TouchParserSRef m_touchParser;
+ int m_realizeIndex;
+ int m_imageLoadSize;
+ bool m_wasUpdated;
+ bool m_isClicksBlocked;
+ };
+
+ 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 (isValid(m_info.slotThemes[isOdd]) &&
+ !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(makeShared<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<SharedRef<Item>> m_items;
+ Layout m_layout;
+ bool m_isRealized;
+ };
+
+ // ImageGrid::Unrealizer //
+
+ ImageGrid::Unrealizer::Unrealizer(ImageGrid &imageGrid) :
+ m_imageGrid(imageGrid)
+ {
+ m_imageGrid.addUnrealizeLock();
+ }
+
+ ImageGrid::Unrealizer::~Unrealizer()
+ {
+ m_imageGrid.removeUnrealizeLock();
+ }
+
+ // ImageGrid //
+
+ ImageGrid::ImageGrid(RefCountObjBase *const rc, const Type type,
+ Evas_Object *const scroller) :
+ Widget(rc, scroller, true),
+ m_info(getInfo(type)),
+
+ m_scroller(makeShared<StyledWidget>(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_circleScroller(nullptr),
+
+ 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),
+
+ m_unrealizeLock(0),
+ m_eventsLock(0)
+ {
+ prepare();
+
+ ++m_eventsLock;
+
+ updateSlotCount();
+
+ updatePadSizes();
+ updateScrollBias();
+ updateRectMins();
+
+ --m_eventsLock;
+ }
+
+ const ImageGrid::Info &ImageGrid::getInfo(const Type type)
+ {
+ switch (type) {
+ case Type::HCOMB_3X3: {
+ static HcombInfo info{3, {{
+ {"layout", "gallery_image_grid", "hcomb_3x3_even"},
+ {"layout", "gallery_image_grid", "hcomb_3x3_odd"}}}};
+ return info;
+ }
+ case Type::LINEAR:
+ default: {
+ static LinearInfo info{
+ {"layout", "gallery_image_grid", "linear"}, true};
+ 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);
+
+ m_scroller->setStyle(SCROLLER_STYLE);
+ expandAndFill(*m_scroller);
+ if (m_info.isHorizontal) {
+ elm_scroller_page_scroll_limit_set(
+ *m_scroller, m_info.scrollLimit, 0);
+ elm_scroller_bounce_set(*m_scroller, EINA_TRUE, EINA_FALSE);
+ } else {
+ elm_scroller_page_scroll_limit_set(
+ *m_scroller, 0, m_info.scrollLimit);
+ elm_scroller_bounce_set(*m_scroller, EINA_FALSE, EINA_TRUE);
+ }
+ show(*m_scroller);
+
+ createCircleScroller();
+
+ 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::createCircleScroller()
+ {
+ const auto sfc = getCircleSurface(*m_scroller);
+ if (!sfc) {
+ LOG_RETURN_VOID(RES_FAIL, "getCircleSurface() failed!");
+ }
+
+ m_circleScroller = eext_circle_object_scroller_add(*m_scroller, sfc);
+ if (!m_circleScroller) {
+ LOG_RETURN_VOID(RES_FAIL,
+ "eext_circle_object_scroller_add() failed!");
+ }
+
+ if (m_info.isHorizontal) {
+ eext_circle_object_scroller_policy_set(m_circleScroller,
+ ELM_SCROLLER_POLICY_AUTO, ELM_SCROLLER_POLICY_OFF);
+ } else {
+ eext_circle_object_scroller_policy_set(m_circleScroller,
+ ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_AUTO);
+ }
+ }
+
+ void ImageGrid::setListener(IImageGridListener *const listener)
+ {
+ m_listener = listener;
+ }
+
+ void ImageGrid::setItemCount(const int count)
+ {
+ if (m_itemCount == count) {
+ return;
+ }
+
+ ++m_eventsLock;
+
+ unrealizeSlots(0, m_slotCount);
+
+ m_itemCount = count;
+
+ if (updateMaxSlotCount()) {
+ updateSlotCount();
+ if (updateMaxBeginSlotIndex()) {
+ updateBeginSlotIndex();
+ }
+ }
+
+ realizeSlots();
+ updateRectMins();
+
+ --m_eventsLock;
+ }
+
+ void ImageGrid::update()
+ {
+ Unrealizer(*this);
+ }
+
+ 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) const
+ {
+ 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) const
+ {
+ return doWithCell(itemIndex,
+ [this, &func](const int slotIndex, const int itemOffset)
+ {
+ const int slotOffset = (slotIndex - m_beginSlotIndex);
+ if ((slotOffset < 0) || (slotOffset >= m_slotCount)) {
+ return RES_FALSE;
+ }
+ return func(*m_slots[slotOffset], itemOffset);
+ });
+ }
+
+ template <class FUNC>
+ Result ImageGrid::doWithCell(const int itemIndex, FUNC &&func) const
+ {
+ 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);
+
+ return func(slotIndex, itemOffset);
+ }
+
+ Result ImageGrid::scrollToItem(const int itemIndex)
+ {
+ return showItem(itemIndex, elm_scroller_region_show);
+ }
+
+ Result ImageGrid::bringInItem(int itemIndex)
+ {
+ return showItem(itemIndex, elm_scroller_region_bring_in);
+ }
+
+ template <class SHOW_FUNC>
+ Result ImageGrid::showItem(const int itemIndex, SHOW_FUNC &&showFunc)
+ {
+ return doWithCell(itemIndex,
+ [this, &showFunc](const int slotIndex, const int itemOffset)
+ {
+ const int scrollOffset = ((slotIndex / 2) * m_slotSize);
+ if (m_info.isHorizontal) {
+ showFunc(*m_scroller, scrollOffset, 0, m_scrollerSize, 1);
+ } else {
+ showFunc(*m_scroller, 0, scrollOffset, 1, m_scrollerSize);
+ }
+ return RES_OK;
+ });
+ }
+
+ void ImageGrid::activateRotary()
+ {
+ eext_rotary_object_event_activated_set(m_circleScroller, EINA_TRUE);
+ }
+
+ void ImageGrid::deactivateRotary()
+ {
+ eext_rotary_object_event_activated_set(m_circleScroller, EINA_FALSE);
+ }
+
+ void ImageGrid::addUnrealizeLock()
+ {
+ unrealizeSlots(0, m_slotCount);
+ ++m_unrealizeLock;
+ }
+
+ void ImageGrid::removeUnrealizeLock()
+ {
+ if (m_unrealizeLock > 0) {
+ --m_unrealizeLock;
+ realizeSlots();
+ } else {
+ WLOG("m_unrealizeLock = 0!");
+ }
+ }
+
+ void ImageGrid::handleItemEvent(const int itemIndex, const int event,
+ const int x, const int y) const
+ {
+ if (m_listener) {
+ m_listener->onItemEvent(itemIndex, event, x, y);
+ }
+ }
+
+ 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);
+ 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->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 / m_slotSize) + 3) * 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 -
+ (std::max((m_scrollerSize / m_slotSize), 1) * m_slotSize));
+
+ m_padSize1 = (spaceSize / 2);
+ m_padSize2 = (spaceSize - m_padSize1 +
+ m_info.calcExtraPaddingSize(m_slotSize, m_itemCount));
+ }
+
+ 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()
+ {
+ if (m_unrealizeLock == 0) {
+ for (int i = 0; i < m_slotCount; ++i) {
+ m_slots[i]->realize(m_beginSlotIndex + i);
+ }
+ }
+ }
+
+ void ImageGrid::unrealizeSlots(
+ const int beginSlotOffset, const int endSlotOffset)
+ {
+ if (m_unrealizeLock == 0) {
+ for (int i = beginSlotOffset; i < endSlotOffset; ++i) {
+ m_slots[i]->unrealize();
+ }
+ }
+ }
+
+ void ImageGrid::handleScrolling()
+ {
+ if (m_eventsLock > 0) {
+ WLOG("Event handling was blocked!");
+ return;
+ }
+ ++m_eventsLock;
+
+ if (updateScrollOffset() && updateBeginSlotIndex()) {
+ realizeSlots();
+ updateRectMins();
+ }
+
+ --m_eventsLock;
+ }
+
+ void ImageGrid::handleResize()
+ {
+ if (m_eventsLock > 0) {
+ WLOG("Event handling was blocked!");
+ return;
+ }
+ ++m_eventsLock;
+
+ if (updateScrollerSize()) {
+ bool needRealize = false;
+
+ updatePadSizes();
+
+ if (updateOptimalSlotCount() && updateSlotCount()) {
+ updateMaxBeginSlotIndex();
+ needRealize = true;
+ }
+
+ updateScrollBias();
+
+ if (updateBeginSlotIndex()) {
+ needRealize = true;
+ }
+
+ if (needRealize) {
+ realizeSlots();
+ }
+ updateRectMins();
+ }
+
+ --m_eventsLock;
+ }
+
+ 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 "view/ImageViewer.h"
+
+#include "common.h"
+
+namespace gallery { namespace { namespace impl {
+
+ constexpr auto ANIMATION_START_TIMEOUT_SEC = (1.0 / 30.0);
+ constexpr auto ANIMATION_RUNTIME_SEC = (300.0 / 1000.0);
+ constexpr auto ANIMATION_STOP_POS = 0.999999;
+}}}
+
+namespace gallery {
+
+ using namespace ucl;
+
+ // ImageViewer::Builder //
+
+ ImageViewer::Builder::Builder() :
+ m_imageW(0),
+ m_imageH(0)
+ {
+ }
+
+ ImageViewer::Builder &ImageViewer::Builder::setImageSize(
+ const int w, const int h)
+ {
+ m_imageW = w;
+ m_imageH = h;
+ return *this;
+ }
+
+ ImageViewerSRef ImageViewer::Builder::build(Widget &parent) const
+ {
+ if ((m_imageW <= 0) || (m_imageH <= 0)) {
+ LOG_RETURN_VALUE(RES_INVALID_ARGUMENTS, {}, "Image size is invalid");
+ }
+
+ auto scroller = elm_scroller_add(parent);
+ if (!scroller) {
+ LOG_RETURN_VALUE(RES_FAIL, {}, "elm_scroller_add() failed!");
+ }
+
+ return makeShared<ImageViewer>(m_imageW, m_imageH, scroller);
+ }
+
+ // ImageViewer //
+
+ ImageViewer::ImageViewer(RefCountObjBase &rc,
+ const int imageW, const int imageH,
+ Evas_Object *const scroller) :
+ Widget(&rc, scroller, true),
+ m_imageW(imageW),
+ m_imageH(imageH),
+
+ m_scroller(makeShared<StyledWidget>(scroller)),
+ m_layout(elm_layout_add(*m_scroller)),
+ m_grid(evas_object_grid_add(m_layout.getEvas())),
+ m_lowResImage(evas_object_image_filled_add(m_grid.getEvas())),
+ m_highResImage(evas_object_image_filled_add(m_grid.getEvas())),
+
+ m_scrollerW(0),
+ m_scrollerH(0),
+ m_gridW(0),
+ m_gridH(0),
+ m_scale0(0),
+ m_scale1(0),
+
+ m_xf1(0.5),
+ m_yf1(0.5),
+ m_xf2(0.5),
+ m_yf2(0.5),
+ m_zoom(0.0),
+
+ m_animationStartTimer(nullptr),
+ m_animator(nullptr),
+ m_state(State::ZOOMED_OUT)
+ {
+ prepare();
+ }
+
+ ImageViewer::~ImageViewer()
+ {
+ if (m_animationStartTimer) {
+ ecore_timer_del(m_animationStartTimer);
+ }
+ if (m_animator) {
+ ecore_animator_del(m_animator);
+ }
+ }
+
+ void ImageViewer::prepare()
+ {
+ expandAndFill(*m_scroller);
+ m_scroller->setStyle(SCROLLER_STYLE);
+ elm_scroller_bounce_set(*m_scroller, EINA_TRUE, EINA_TRUE);
+ elm_scroller_policy_set(*m_scroller,
+ ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_OFF);
+ elm_scroller_single_direction_set(*m_scroller,
+ ELM_SCROLLER_SINGLE_DIRECTION_NONE);
+ elm_object_scroll_freeze_push(*m_scroller);
+ show(*m_scroller);
+
+ expandAndFill(m_layout);
+ m_layout.setTheme(LAYOUT_DEFAULT);
+ m_scroller->setContent(m_layout);
+ show(m_layout);
+
+ evas_object_grid_size_set(m_grid, 1, 1);
+ m_layout.setContent(m_grid);
+ show(m_grid);
+
+ evas_object_grid_pack(m_grid, m_lowResImage, 0, 0, 1, 1);
+ show(m_lowResImage);
+ evas_object_grid_pack(m_grid, m_highResImage, 0, 0, 1, 1);
+ show(m_highResImage);
+
+ m_scroller->addEventHandler(WidgetEvent::RESIZE,
+ WEAK_DELEGATE(ImageViewer::onScrollerResize, asWeak(*this)));
+
+ m_highResImage.addEventHandler(WidgetEvent::IMAGE_PRELOADED,
+ WEAK_DELEGATE(ImageViewer::onImagePreloaded, asWeak(*this)));
+ }
+
+ void ImageViewer::onScrollerResize(Widget &widget, void *eventInfo)
+ {
+ if (updateScrollerSize()) {
+ updateScales();
+ updateGridSize();
+ updateScrollOffset();
+ }
+ }
+
+ bool ImageViewer::updateScrollerSize()
+ {
+ int scrollerW = 0;
+ int scrollerH = 0;
+ getSize(*m_scroller, &scrollerW, &scrollerH);
+
+ if ((scrollerW == 0) || (scrollerH == 0)) {
+ DLOG("Scroller has 0 size. Skip.");
+ return false;
+ }
+
+ if ((scrollerW != m_scrollerW) || (scrollerH != m_scrollerH)) {
+ m_scrollerW = scrollerW;
+ m_scrollerH = scrollerH;
+ return true;
+ }
+
+ return false;
+ }
+
+ void ImageViewer::updateScales()
+ {
+ const double sx = (1.0 * m_scrollerW / m_imageW);
+ const double sy = (1.0 * m_scrollerH / m_imageH);
+
+ m_scale0 = ((sx > sy) ? sx : sy);
+ m_scale1 = 1.0;
+ }
+
+ void ImageViewer::updateGridSize()
+ {
+ const double scale = (m_scale0 + m_zoom * (m_scale1 - m_scale0));
+
+ m_gridW = std::lround(scale * m_imageW);
+ m_gridH = std::lround(scale * m_imageH);
+
+ m_grid.setMin(m_gridW, m_gridH);
+ m_grid.setMax(m_gridW, m_gridH);
+
+ evas_object_smart_calculate(m_layout);
+ }
+
+ void ImageViewer::updateScrollOffset()
+ {
+ const double xf2 = (m_xf2 + m_zoom * (0.5 - m_xf2));
+ const double yf2 = (m_yf2 + m_zoom * (0.5 - m_yf2));
+
+ const int sx = std::lround((m_xf1 * m_gridW) - (xf2 * m_scrollerW));
+ const int sy = std::lround((m_yf1 * m_gridH) - (yf2 * m_scrollerH));
+
+ elm_scroller_region_show(*m_scroller, sx, sy, m_scrollerW, m_scrollerH);
+ }
+
+ void ImageViewer::setLowResImagePath(const std::string &path)
+ {
+ evas_object_image_file_set(m_lowResImage, path.c_str(), nullptr);
+ }
+
+ void ImageViewer::setHighResImagePath(const std::string &path)
+ {
+ hide(m_highResImage);
+ evas_object_image_file_set(m_highResImage, path.c_str(), nullptr);
+ evas_object_image_preload(m_highResImage, EINA_FALSE);
+ }
+
+ void ImageViewer::onImagePreloaded(Widget &widget, void *eventInfo)
+ {
+ show(widget);
+ }
+
+ bool ImageViewer::zoomIn(const int originX, const int originY)
+ {
+ if (m_state != State::ZOOMED_OUT) {
+ WLOG("Can't zoom in!");
+ return false;
+ }
+
+ m_state = State::ZOOMING_IN;
+
+ calcZoomInFactors(originX, originY);
+ startAnimation();
+
+ return true;
+ }
+
+ bool ImageViewer::zoomOut()
+ {
+ if (m_state != State::ZOOMED_IN) {
+ WLOG("Can't zoom out!");
+ return false;
+ }
+
+ m_state = State::ZOOMING_OUT;
+
+ calcZoomOutFactors();
+ startAnimation();
+
+ return true;
+ }
+
+ bool ImageViewer::isZooming() const
+ {
+ return ((m_state == State::ZOOMING_IN) ||
+ (m_state == State::ZOOMING_OUT));
+ }
+
+ bool ImageViewer::isZoomedIn() const
+ {
+ return (m_state == State::ZOOMED_IN);
+ }
+
+ bool ImageViewer::isZoomedOut() const
+ {
+ return (m_state == State::ZOOMED_OUT);
+ }
+
+ void ImageViewer::calcZoomInFactors(const int originX, const int originY)
+ {
+ if (m_scale0 > m_scale1) {
+ m_xf1 = 0.5;
+ m_yf1 = 0.5;
+ m_xf2 = 0.5;
+ m_yf2 = 0.5;
+ return;
+ }
+
+ int x = 0;
+ int y = 0;
+ getPosition(*m_scroller, &x, &y);
+
+ const int newOriginX = (originX - x);
+ const int newOriginY = (originY - x);
+
+ int sx = 0;
+ int sy = 0;
+ elm_scroller_region_get(*m_scroller, &sx, &sy, nullptr, nullptr);
+
+ m_xf1 = (1.0 * (sx + newOriginX) / m_gridW);
+ m_yf1 = (1.0 * (sy + newOriginY) / m_gridH);
+ m_xf2 = (1.0 * newOriginX / m_scrollerW);
+ m_yf2 = (1.0 * newOriginY / m_scrollerH);
+ }
+
+ void ImageViewer::calcZoomOutFactors()
+ {
+ int sx = 0;
+ int sy = 0;
+ elm_scroller_region_get(*m_scroller, &sx, &sy, nullptr, nullptr);
+
+ if (m_gridW < m_scrollerW) {
+ sx = (0.5 * (m_gridW - m_scrollerW));
+ }
+ if (m_gridH < m_scrollerH) {
+ sy = (0.5 * (m_gridH - m_scrollerH));
+ }
+
+ m_xf1 = ((sx + 0.5 * m_scrollerW) / m_gridW);
+ m_yf1 = ((sy + 0.5 * m_scrollerH) / m_gridH);
+ m_xf2 = (m_scale0 * m_imageW * (m_xf1 - 0.5) / m_scrollerW + 0.5);
+ m_yf2 = (m_scale0 * m_imageH * (m_yf1 - 0.5) / m_scrollerH + 0.5);
+ }
+
+ void ImageViewer::startAnimation()
+ {
+ if (m_animationStartTimer) {
+ WLOG("Timer is running!");
+ ecore_timer_del(m_animationStartTimer);
+ }
+
+ m_animationStartTimer = ecore_timer_add(
+ impl::ANIMATION_START_TIMEOUT_SEC,
+ CALLBACK_A(ImageViewer::onAnimationStartTimer), this);
+ }
+
+ Eina_Bool ImageViewer::onAnimationStartTimer()
+ {
+ m_animationStartTimer = nullptr;
+
+ if (m_animator) {
+ WLOG("Animator is running!");
+ ecore_animator_del(m_animator);
+ }
+ m_animator = ecore_animator_timeline_add(
+ impl::ANIMATION_RUNTIME_SEC,
+ CALLBACK_A(ImageViewer::onAnimationFrame), this);
+
+ return ECORE_CALLBACK_CANCEL;
+ }
+
+ Eina_Bool ImageViewer::onAnimationFrame(const double pos)
+ {
+ const double t = ecore_animator_pos_map(
+ pos, ECORE_POS_MAP_DECELERATE, 0.0, 0.0);
+
+ m_zoom = ((m_state == State::ZOOMING_IN) ? t : (1.0 - t));
+
+ updateGridSize();
+ updateScrollOffset();
+
+ if (pos >= impl::ANIMATION_STOP_POS) {
+ m_animator = nullptr;
+ if (m_state == State::ZOOMING_IN) {
+ m_state = State::ZOOMED_IN;
+ elm_object_scroll_freeze_pop(*m_scroller);
+ } else {
+ m_state = State::ZOOMED_OUT;
+ elm_object_scroll_freeze_push(*m_scroller);
+ }
+ callSmartEvent(IMAGE_VIEWER_ZOOM_END, nullptr);
+ return ECORE_CALLBACK_CANCEL;
+ }
+
+ return ECORE_CALLBACK_RENEW;
+ }
+}
--- /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/TouchParser.h"
+
+#include "common.h"
+
+namespace gallery { namespace { namespace impl {
+
+ constexpr auto TAP_MOVE_THRESHOLD = 30;
+ constexpr auto FAST_TAP_DISTANCE = 60;
+ constexpr auto FAST_TAP_DELAY_MS = 300;
+}}}
+
+namespace gallery {
+
+ using namespace ucl;
+
+ TouchParser::TouchParser(RefCountObjBase &rc, Widget &eventSource) :
+ RefCountAware(&rc),
+ m_downTime(0),
+ m_downX(0),
+ m_downY(0),
+ m_tapCounter(0),
+ m_isMouseDown(false),
+ m_isTapPossible(false)
+ {
+ eventSource.addEventHandler(WidgetEvent::MOUSE_DOWN,
+ WEAK_DELEGATE(TouchParser::onMouseDown, asWeak(*this)));
+
+ eventSource.addEventHandler(WidgetEvent::MOUSE_UP,
+ WEAK_DELEGATE(TouchParser::onMouseUp, asWeak(*this)));
+
+ eventSource.addEventHandler(WidgetEvent::MOUSE_MOVE,
+ WEAK_DELEGATE(TouchParser::onMouseMove, asWeak(*this)));
+ }
+
+ TouchParser::~TouchParser()
+ {
+ }
+
+ void TouchParser::setTapHandler(TapHandler handler)
+ {
+ m_tapHandler = handler;
+ }
+
+ void TouchParser::setDoubleTapHandler(TapHandler handler)
+ {
+ m_doubleTapHandler = handler;
+ }
+
+ void TouchParser::onMouseDown(Widget &widget, void *eventInfo)
+ {
+ if (m_isMouseDown) {
+ return;
+ }
+ m_isMouseDown = true;
+
+ const auto e = static_cast<Evas_Event_Mouse_Down *>(eventInfo);
+
+ if (!isFastTap(e->timestamp, e->canvas.x, e->canvas.y)) {
+ m_tapCounter = 0;
+ } else if (m_doubleTapHandler && (m_tapCounter == 1)) {
+ m_doubleTapHandler(m_downX, m_downY);
+ }
+
+ m_downTime = e->timestamp;
+ m_downX = e->canvas.x;
+ m_downY = e->canvas.y;
+ m_isTapPossible = true;
+ }
+
+ void TouchParser::onMouseUp(Widget &widget, void *eventInfo)
+ {
+ if (!m_isMouseDown) {
+ return;
+ }
+ m_isMouseDown = false;
+
+ const auto e = static_cast<Evas_Event_Mouse_Up *>(eventInfo);
+
+ updateIsTapPossible(e->event_flags, e->canvas.x, e->canvas.y);
+
+ if (!m_isTapPossible) {
+ m_tapCounter = 0;
+ return;
+ }
+
+ ++m_tapCounter;
+
+ if (m_tapHandler) {
+ m_tapHandler(e->canvas.x, e->canvas.y);
+ }
+ }
+
+ void TouchParser::onMouseMove(Widget &widget, void *eventInfo)
+ {
+ if (!m_isMouseDown || !m_isTapPossible) {
+ return;
+ }
+
+ const auto e = static_cast<Evas_Event_Mouse_Move *>(eventInfo);
+
+ updateIsTapPossible(e->event_flags, e->cur.canvas.x, e->cur.canvas.y);
+ }
+
+ void TouchParser::updateIsTapPossible(const int flags,
+ const int curX, const int curY)
+ {
+ if (!m_isTapPossible) {
+ return;
+ }
+ if ((flags & EVAS_EVENT_FLAG_ON_HOLD) || (calcDownDistance(curX, curY) >
+ ELM_SCALE_SIZE(impl::TAP_MOVE_THRESHOLD))) {
+ m_isTapPossible = false;
+ }
+ }
+
+ bool TouchParser::isFastTap(const UInt curTime,
+ const int curX, const int curY) const
+ {
+ return (((curTime - m_downTime) <= impl::FAST_TAP_DELAY_MS) &&
+ (calcDownDistance(curX, curY) <=
+ ELM_SCALE_SIZE(impl::FAST_TAP_DISTANCE)));
+ }
+
+ double TouchParser::calcDownDistance(int curX, int curY) const
+ {
+ const auto dx = (curX - m_downX);
+ const auto dy = (curY - m_downY);
+
+ return sqrt(1.0 * dx * dx + 1.0 * dy * dy);
+ }
+}
--- /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_COMMON_H__
+#define __GALLERY_VIEW_COMMON_H__
+
+#include "ucl/gui/stdTheme.h"
+#include "ucl/gui/helpers.h"
+
+#include "view/helpers.h"
+
+#include "../common.h"
+
+namespace gallery {
+
+ constexpr ucl::ElmStyle SCROLLER_STYLE {"effect"};
+}
+
+#endif // __GALLERY_VIEW_COMMON_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 "view/helpers.h"
+
+#include "ucl/gui/Window.h"
+#include "ucl/gui/Naviframe.h"
+
+#include "common.h"
+
+namespace gallery { namespace { namespace impl {
+
+ using namespace ucl;
+
+ constexpr EoDataKey CIRCLE_SURFACE {"gallery,eext,circle,surface"};
+}}}
+
+namespace gallery {
+
+ using namespace ucl;
+
+ Result createCircleSurface(Naviframe &navi)
+ {
+ const auto win = navi.getWindow();
+ if (!win) {
+ LOG_RETURN(RES_FAIL, "Failed to get Window from Naviframe!");
+ }
+
+ if (win->getData(impl::CIRCLE_SURFACE)) {
+ LOG_RETURN(RES_ILLEGAL_STATE, "Circle Surface data already set!");
+ }
+
+ const auto sfc = eext_circle_surface_naviframe_add(navi);
+ if (!sfc) {
+ LOG_RETURN(RES_FAIL,
+ "eext_circle_surface_conformant_add() failed!");
+ }
+
+ win->setData(impl::CIRCLE_SURFACE, sfc);
+
+ return RES_OK;
+ }
+
+ Eext_Circle_Surface *getCircleSurface(const ElmWidget &widget)
+ {
+ const auto win = widget.getWindow();
+ if (!win) {
+ LOG_RETURN_VALUE(RES_FAIL, nullptr,
+ "Failed to get Window from widget!");
+ }
+
+ const auto sfc = static_cast<Eext_Circle_Surface *>(
+ win->getData(impl::CIRCLE_SURFACE));
+ if (!sfc) {
+ LOG_RETURN_VALUE(RES_FAIL, nullptr,
+ "Failed to get Eext_Circle_Surface from window!");
+ }
+
+ return sfc;
+ }
+}
+