TizenRefApp-8535 [Gallery] Improve image load size calculation in 52/130952/2 submit/tizen/20170531.142232
authorIgor Nazarov <i.nazarov@samsung.com>
Wed, 24 May 2017 12:36:21 +0000 (15:36 +0300)
committerIgor Nazarov <i.nazarov@samsung.com>
Wed, 24 May 2017 12:58:46 +0000 (15:58 +0300)
ImageGrid

- Improved image load size calculation in ImageGrid;
- Returned "MediaItem::getResoulution()" method;
- Improved ViewrPage image quality;
- Added gray bg for not loaded images.

Change-Id: Ic1df38ac846f1df0fce549fc265c9911b505a5df

14 files changed:
edc/button.edc
edc/colors.h
edc/image-grid.edc
inc/model/MediaItem.h
inc/model/types.h
inc/presenters/ViewerPage.h
inc/view/ImageGrid.h
inc/view/ImageViewer.h
src/model/MediaItem.cpp
src/presenters/PreviewPage.cpp
src/presenters/ThumbnailPage.cpp
src/presenters/ViewerPage.cpp
src/view/ImageGrid.cpp
src/view/ImageViewer.cpp

index 49fe3904e562c846baaa1472dd41efbda0b8fde3..e6b652e918a25a2e2aedfc23335b14ba9a014a37 100644 (file)
@@ -133,9 +133,14 @@ group{ "elm/button/base/transparent";
 group{ "elm/button/base/gallery_image";
    inherit: "elm/button/base/transparent";
    parts {
+      rect { "rect.bg";
+         before: "swallow.bg";
+         desc { "default";
+            color: GALLERY_COLOR_IMG_BG;
+         }
+      }
       swallow { "swallow.bg";
          before: "elm.swallow.content";
-         scale;
          desc { "default";
          }
       }
index 8eb78bca59e9a476e69b82c99d9d3d85261d4671..09373c0694962215a3079bd98834a243e5df972c 100644 (file)
@@ -19,6 +19,7 @@
 
 #define GALLERY_COLOR_WHITE 255 255 255 255
 
+#define GALLERY_COLOR_IMG_BG 64 64 64 255
 #define GALLERY_COLOR_IMG_EF_NORMAL 0 0 0 0
 #define GALLERY_COLOR_IMG_EF_PRESSED 0 0 0 102
 #define GALLERY_COLOR_IMG_EF_DISABLED 0 0 0 77
index 7ca4b37f1bec2f8784ee0a6603464914d0210b2a..842a3cecd53946c453f1188aa370d516004ca8a4 100644 (file)
@@ -20,6 +20,7 @@ images {
    image: "gallery_thumbnail_select_ring_1x1.png" COMP;
 }
 group { "elm/layout/gallery_image_grid/hcomb_3x3_even";
+   data.item: "image_min_load_size" 116;
    parts {
       spacer { "spacer_t";
          scale;
@@ -67,6 +68,7 @@ group { "elm/layout/gallery_image_grid/hcomb_3x3_even";
    }
 }
 group { "elm/layout/gallery_image_grid/hcomb_3x3_odd";
+   data.item: "image_min_load_size" 116;
    parts {
       spacer { "spacer_t";
          scale;
@@ -149,6 +151,7 @@ group { "elm/layout/gallery_image_grid/hcomb_3x3_odd";
    }
 }
 group { "elm/layout/gallery_image_grid/linear";
+   data.item: "image_min_load_size" 360;
    parts {
       spacer { "spacer";
          scale;
index 5f62b9ece0a3d7eff5588937f36e65282a551567..16ce969a14f8b20a3abb9d2554620f7acb7a9f36 100644 (file)
@@ -48,8 +48,10 @@ namespace gallery {
                        FLAG_THUMBNAIL = 1,
                        FLAG_REMOVE = 2,
                        FLAG_SAVE = 4,
+                       FLAG_RESOLUTION = 8,
 
-                       FLAGS_FROM_MEDIA_DB = (FLAG_THUMBNAIL | FLAG_REMOVE),
+                       FLAGS_FROM_MEDIA_DB = (FLAG_THUMBNAIL | FLAG_REMOVE |
+                                       FLAG_RESOLUTION),
                        FLAGS_SIMPLE_FILE = (FLAG_SAVE)
                };
 
@@ -64,6 +66,8 @@ namespace gallery {
 
                const std::string &getId() const;
 
+               ucl::Result getResolution(int &x, int &y) const;
+
                const std::string &getFilePath() const;
 
                ucl::Result getThumbnailPath(ThumbnailPathGetCb cb) const;
@@ -77,11 +81,11 @@ namespace gallery {
                MediaItem(int flags, MediaType type);
 
                ucl::Result prepare(media_info_h media);
+               ucl::Result prepareImage(media_info_h media);
                ucl::Result prepare(std::string filePath);
 
        private:
                ucl::Result initThumbPath(media_info_h media) const;
-               void freeMediaInfo() const;
 
        private:
                // XXX This proxy is needed to deal with cases when
@@ -93,12 +97,18 @@ namespace gallery {
                        void completeCb(media_content_error_e error, const char *path);
                };
 
+       private:
+               using AutoMediaInfo = ucl::AutoHandle<
+                               media_info_h, int, media_info_destroy>;
+
        private:
                const int m_flags;
                const MediaType m_type;
                std::string m_mediaId;
                std::string m_filePath;
-               mutable media_info_h m_media;
+               int m_resolutionX;
+               int m_resolutionY;
+               mutable AutoMediaInfo m_media;
                mutable std::string m_thumbPath;
                mutable std::unique_ptr<ThumbCbProxy> m_thumbCbProxy;
                bool m_isValid;
index 0ee204045690fa1de8692d4265ce9302033d7663..181b26b6a78b05b750f37f1540aedc91b5a8f414 100644 (file)
@@ -21,6 +21,8 @@
 
 #include <media_content.h>
 
+#include "ucl/misc/AutoHandle.h"
+
 #include "../types.h"
 
 namespace gallery {
index bef8407234848d709036a028b0ff0962e4d00a9a..c685909b20e63ece0d07362e601f5575a71bbef1 100644 (file)
@@ -33,6 +33,7 @@ namespace gallery {
                        Builder &setNaviframe(const ucl::NaviframeSRef &navi);
                        Builder &setMedia(const MediaItemSRef &media);
                        Builder &setZoomIn(int x, int y);
+                       Builder &setImageLoadSize(int size, bool isFull);
                        Builder &setExitOnZoomOut(bool value);
                        ViewerPageWRef build(ExitRequestHandler onExitRequest) const;
                private:
@@ -40,6 +41,8 @@ namespace gallery {
                        MediaItemSRef m_media;
                        int m_zoomInX;
                        int m_zoomInY;
+                       int m_imageLoadSize;
+                       bool m_isImageLoadSizeFull;
                        bool m_exitOnZoomOut;
                };
 
@@ -53,7 +56,7 @@ namespace gallery {
                                bool exitOnZoomOut);
                virtual ~ViewerPage();
 
-               ucl::Result prepare();
+               ucl::Result prepare(int imageLoadSize, bool isImageLoadSizeFull);
 
                void zoomIn(int originX, int originY);
 
index 8fac6c334334f9f7703d34a8b00ad8bd109fd634..019031d44c243b12e75b6b77411df48fe246e221 100644 (file)
@@ -59,9 +59,17 @@ namespace gallery {
                };
 
                struct ItemParams {
-                       int flags;
                        std::string imagePath;
                        std::string bgImagePath;
+                       int imageWidth;
+                       int imageHeight;
+                       int flags;
+               };
+
+               struct ItemInfo {
+                       int imageLoadSize;
+                       bool isImageLoadSizeFull;
+                       bool isImageLoaded;
                };
 
                class Unrealizer : ucl::NonCopyable {
@@ -87,6 +95,8 @@ namespace gallery {
 
                ucl::Result isItemRealized(int itemIndex) const;
 
+               ucl::Result getItemInfo(int itemIndex, ItemInfo &info) const;
+
                int getScrolledToItemIndex() const;
                ucl::Result scrollToItem(int itemIndex);
                ucl::Result bringInItem(int itemIndex);
index e6126dee7d289203687ab9a4d1a77e51fbb0a6c2..73395dbfd950eec913b1e24fb2bb4375a8d00f9a 100644 (file)
@@ -32,10 +32,12 @@ namespace gallery {
                public:
                        Builder();
                        Builder &setHighResImagePath(std::string path);
+                       Builder &setLoadSize(int value);
                        Builder &setForceLoad(bool value);
                        ImageViewerSRef build(ucl::ElmWidget &parent) const;
                private:
                        std::string m_highResPath;
+                       int m_loadSize;
                        bool m_forceLoad;
                };
 
@@ -51,10 +53,11 @@ namespace gallery {
        private:
                friend class ucl::RefCountObj<ImageViewer>;
                ImageViewer(ucl::RefCountObjBase &rc, Evas_Object *scroller,
-                               const std::string &highResPath, bool forceLoad);
+                               const std::string &highResPath, int loadSize, bool forceLoad);
                virtual ~ImageViewer();
 
-               void prepare(const std::string &highResPath, bool forceLoad);
+               void prepare(const std::string &highResPath,
+                               int loadSize, bool forceLoad);
 
                void onImagePreloaded(ucl::Widget &widget, void *eventInfo);
                void onScrollerResize(ucl::Widget &widget, void *eventInfo);
index f8802b833b39dab99df9e39cb32c9f697197197f..61d3a272f2f8b5da215d570d3af1e9d2751a38ba 100644 (file)
 
 namespace gallery { namespace { namespace impl {
 
+       using namespace ucl;
+
        const std::string MIME_PREFIX_IMAGE {"image/"};
        const std::string MIME_PREFIX_VIDEO {"video/"};
 
+       using AutoImageMeta = AutoHandle<image_meta_h, int, image_meta_destroy>;
+
        MediaType getFileMediaType(const std::string &filePath)
        {
                const auto ext = util::extractFileExtension(filePath);
@@ -176,7 +180,8 @@ namespace gallery {
        MediaItem::MediaItem(const int flags, const MediaType type) :
                m_flags(flags),
                m_type(type),
-               m_media(nullptr),
+               m_resolutionX(0),
+               m_resolutionY(0),
                m_isValid(false)
        {
        }
@@ -184,17 +189,13 @@ namespace gallery {
        MediaItem::~MediaItem()
        {
                cancelThumbnailPathGet();
-               freeMediaInfo();
        }
 
        MediaItemSRef MediaItem::newInstance(const media_info_h media)
        {
                media_content_type_e contentType = MEDIA_CONTENT_TYPE_OTHERS;
-               const int ret = media_info_get_media_type(media, &contentType);
-               if (ret != 0) {
-                       LOG_RETURN_VALUE(RES_FAIL, {},
-                                       "media_info_get_media_type() failed: %d", ret);
-               }
+               FAIL_RETURN_VALUE(util::get(media_info_get_media_type, contentType,
+                               media), {}, "media_info_get_media_type() failed!");
 
                auto result = makeShared<MediaItem>(FLAGS_FROM_MEDIA_DB,
                                toMediaType(contentType));
@@ -221,28 +222,47 @@ namespace gallery {
                FAIL_RETURN(initThumbPath(media), "initThumbPath() failed!");
 
                if (isEmpty(m_thumbPath)) {
-                       const int ret = media_info_clone(&m_media, media);
-                       if (ret != 0) {
-                               m_media = nullptr;
-                               LOG_RETURN(RES_FAIL, "media_info_clone() failed: %d", ret);
-                       }
+                       media_info_h mediaClone = nullptr;
+                       FAIL_RETURN(util::call(media_info_clone, &mediaClone, media),
+                                       "media_info_clone() failed!");
+                       m_media = mediaClone;
                }
 
                FAIL_RETURN(util::getNz(media_info_get_media_id, m_mediaId, media),
-                       "media_info_get_media_id() failed!");
+                               "media_info_get_media_id() failed!");
 
                FAIL_RETURN(util::getNz(media_info_get_file_path, m_filePath, media),
-                       "media_info_get_file_path() failed!");
+                               "media_info_get_file_path() failed!");
+
+               if (m_type == MediaType::IMAGE) {
+                       prepareImage(media);
+               }
 
                m_isValid = true;
 
                return RES_OK;
        }
 
+       Result MediaItem::prepareImage(const media_info_h media)
+       {
+               impl::AutoImageMeta imageMeta;
+
+               FAIL_RETURN(util::getNz(media_info_get_image, imageMeta, media),
+                               "media_info_get_image() failed!");
+
+               FAIL_RETURN(util::getNz(image_meta_get_width, m_resolutionX,
+                               imageMeta), "image_meta_get_width() failed!");
+
+               FAIL_RETURN(util::getNz(image_meta_get_height, m_resolutionY,
+                               imageMeta), "image_meta_get_height() failed!");
+
+               return RES_OK;
+       }
+
        Result MediaItem::initThumbPath(const media_info_h media) const
        {
                FAIL_RETURN(util::get(media_info_get_thumbnail_path, m_thumbPath,
-                       media), "media_info_get_thumbnail_path() failed!");
+                               media), "media_info_get_thumbnail_path() failed!");
                return RES_OK;
        }
 
@@ -253,17 +273,6 @@ namespace gallery {
                return RES_OK;
        }
 
-       void MediaItem::freeMediaInfo() const
-       {
-               if (m_media) {
-                       const int ret = media_info_destroy(m_media);
-                       if (ret != 0) {
-                               WLOG("media_info_destroy() failed: %d", ret);
-                       }
-                       m_media = nullptr;
-               }
-       }
-
        bool MediaItem::isValid() const
        {
                return m_isValid;
@@ -284,6 +293,18 @@ namespace gallery {
                return m_mediaId;
        }
 
+       Result MediaItem::getResolution(int &x, int &y) const
+       {
+               if (!(m_flags & FLAG_RESOLUTION)) {
+                       LOG_RETURN(RES_NOT_SUPPORTED, "Operation not supported!");
+               }
+
+               x = m_resolutionX;
+               y = m_resolutionY;
+
+               return RES_OK;
+       }
+
        const std::string &MediaItem::getFilePath() const
        {
                return m_filePath;
@@ -306,7 +327,7 @@ namespace gallery {
                                LOG_RETURN(RES_FAIL, "media_info_delete_from_db() failed: %d", ret);
                        }
 
-                       freeMediaInfo();
+                       m_media = nullptr;
                        m_isValid = false;
                }
 
@@ -385,11 +406,9 @@ namespace gallery {
                {
                        MutexLock lock(getMediaMutex());
 
-                       const int ret = media_info_create_thumbnail(m_media,
-                               CALLBACK_B(ThumbCbProxy::completeCb), cbProxy.get());
-                       if (ret != 0) {
-                               LOG_RETURN(RES_FAIL, "media_info_clone() failed: %d", ret);
-                       }
+                       FAIL_RETURN(util::call(media_info_create_thumbnail, m_media,
+                                       CALLBACK_B(ThumbCbProxy::completeCb), cbProxy.get()),
+                                       "media_info_create_thumbnail() failed!");
                }
 
                m_thumbCbProxy = std::move(cbProxy);
@@ -444,7 +463,7 @@ namespace gallery {
                        result = RES_FAIL;
                } else {
                        item->m_thumbPath = path;
-                       item->freeMediaInfo();
+                       item->m_media = nullptr;
                }
 
                const auto proxy = std::move(*item->m_thumbCbProxy);
index cc923575f15d533e297fc980850dd8971351b3d3..0bdd68ca482f16ef2ad712fadb70e3ab069a13bc 100644 (file)
@@ -184,6 +184,7 @@ namespace gallery {
                        ImageGrid::ItemParams params = {};
                        params.imagePath = m_media->getFilePath();
                        params.bgImagePath = path;
+                       m_media->getResolution(params.imageWidth, params.imageHeight);
                        addFlags(params);
 
                        m_imageGrid.updateItem(m_index, params);
@@ -668,11 +669,19 @@ namespace gallery {
 
        void PreviewPage::openViewer(const int itemIndex, const int x, const int y)
        {
-               m_page = ViewerPage::Builder().
-                               setNaviframe(asShared(getNaviframe())).
-                               setZoomIn(x, y).
-                               setMedia(m_items[itemIndex]->getMedia()).
-                               build(DELEGATE(PreviewPage::onPageExitRequest, this));
+               ViewerPage::Builder builder;
+               builder.setNaviframe(asShared(getNaviframe()));
+               builder.setZoomIn(x, y);
+               builder.setMedia(m_items[itemIndex]->getMedia());
+
+               ImageGrid::ItemInfo info = {};
+               m_imageGrid->getItemInfo(itemIndex, info);
+               if (info.isImageLoaded) {
+                       builder.setImageLoadSize(info.imageLoadSize,
+                                       info.isImageLoadSizeFull);
+               }
+
+               m_page = builder.build(DELEGATE(PreviewPage::onPageExitRequest, this));
        }
 
        void PreviewPage::onPageExitRequest(Page &page)
index 2828c13bc75f7b37ce0737fb3603e69b77dd8251..0114b4c28f5332cf8c28d8139364dba49d8b8b94 100644 (file)
@@ -120,6 +120,8 @@ namespace gallery {
 
                        ImageGrid::ItemParams params = {};
                        params.imagePath = path;
+                       m_parent.m_mediaItems[m_index]->getResolution(
+                                       params.imageWidth, params.imageHeight);
 
                        m_parent.m_imageGrid->updateItem(m_index, params);
                }
index 5d4fcbc330ef98baba5e0f66650687dd1c69215b..8765444ba201805a1c69fbe74ce1b30b0267dbcd 100644 (file)
@@ -45,6 +45,8 @@ namespace gallery {
        ViewerPage::Builder::Builder() :
                m_zoomInX(-1),
                m_zoomInY(-1),
+               m_imageLoadSize(-1),
+               m_isImageLoadSizeFull(false),
                m_exitOnZoomOut(true)
        {
        }
@@ -75,6 +77,14 @@ namespace gallery {
                return *this;
        }
 
+       ViewerPage::Builder &ViewerPage::Builder::setImageLoadSize(
+                       const int size, const bool isFull)
+       {
+               m_imageLoadSize = size;
+               m_isImageLoadSizeFull = isFull;
+               return *this;
+       }
+
        ViewerPage::Builder &ViewerPage::Builder::setExitOnZoomOut(const bool value)
        {
                m_exitOnZoomOut = value;
@@ -101,7 +111,8 @@ namespace gallery {
                auto result = makeShared<ViewerPage>(
                                m_navi, onExitRequest, m_media, m_exitOnZoomOut);
 
-               FAIL_RETURN_VALUE(result->prepare(), {}, "result->prepare() failed!");
+               FAIL_RETURN_VALUE(result->prepare(m_imageLoadSize,
+                               m_isImageLoadSizeFull), {}, "result->prepare() failed!");
 
                if ((m_zoomInX >= 0) && (m_zoomInY >= 0)) {
                        result->zoomIn(m_zoomInX, m_zoomInY);
@@ -130,15 +141,19 @@ namespace gallery {
                }
        }
 
-       Result ViewerPage::prepare()
+       Result ViewerPage::prepare(const int imageLoadSize,
+                       const bool isImageLoadSizeFull)
        {
                const int mediaFlags = m_media->getFlags();
                const bool canSave = (mediaFlags & MediaItem::FLAG_SAVE);
                const bool hasThumb = (mediaFlags & MediaItem::FLAG_THUMBNAIL);
+               const bool useThumb = (hasThumb && (imageLoadSize < 0));
+               const bool forceLoad = (!useThumb && isImageLoadSizeFull);
 
                m_imageViewer = ImageViewer::Builder().
                                setHighResImagePath(m_media->getFilePath()).
-                               setForceLoad(!hasThumb).
+                               setLoadSize(imageLoadSize).
+                               setForceLoad(forceLoad).
                                build(getNaviframe());
                if (!m_imageViewer) {
                        LOG_RETURN(RES_FAIL, "ImageViewer::build() failed!");
@@ -173,10 +188,12 @@ namespace gallery {
                        m_more->setListener(asWeakThis<IMoreOptionsListener>(this));
                }
 
-               if (hasThumb) {
+               if (useThumb) {
                        FAIL_RETURN(m_media->getThumbnailPath(DELEGATE(
                                        ViewerPage::onThumbnail, this)),
                                        "m_media->getThumbnailPath() failed!");
+               } else if (!forceLoad) {
+                       m_imageViewer->setLowResImagePath(m_media->getFilePath());
                }
 
                m_imageViewer->addEventHandler(IMAGE_VIEWER_ZOOM_END,
index 864056d882153405d224de1ac79c8ed4ee9fcec5..beaa6d78190e5e9893c244ca63fe0739eea2df5c 100644 (file)
@@ -36,6 +36,8 @@ namespace gallery { namespace { namespace impl {
        const TString SIGNAL_SELECT_ITEM_FMT {"gallery,select,%d"};
        const TString SIGNAL_UNSELECT_ITEM_FMT {"gallery,unselect,%d"};
 
+       constexpr EdjeDataKey DATA_IMAGE_MIN_LOAD_SIZE {"image_min_load_size"};
+
        constexpr EdjeSignal SIGNAL_FORCE_SELECT_MODE
                        {"gallery,force,select,mode"};
        constexpr EdjeSignal SIGNAL_ENABLE_SELECT_MODE
@@ -237,13 +239,7 @@ namespace gallery {
                                RefCountAware(&rc),
                                m_imageGrid(imageGrid),
                                m_btn(elm_button_add(parent)),
-                               m_image(evas_object_image_filled_add(m_btn.getEvas())),
-                               m_realizeIndex(-1),
-                               m_imageLoadSize(0),
-                               m_wasUpdated(false),
-                               m_isImageEmpty(false),
-                               m_isClicksBlocked(false),
-                               m_isSelected(false)
+                               m_image(evas_object_image_filled_add(m_btn.getEvas()))
                        {
                                m_btn.setFocusAlowed(false);
                                m_btn.setStyle(impl::ITEM_BTN_STYLE);
@@ -270,11 +266,9 @@ namespace gallery {
                                return m_btn;
                        }
 
-                       void setImageLoadSize(const int value)
+                       void setImageMinLoadSize(const int value)
                        {
-                               m_imageLoadSize = value;
-                               evas_object_image_load_size_set(m_image,
-                                               m_imageLoadSize, m_imageLoadSize);
+                               m_imageMinLoadSize = std::max(value, 1);
                        }
 
                        bool isRealized() const
@@ -282,6 +276,20 @@ namespace gallery {
                                return (m_realizeIndex >= 0);
                        }
 
+                       void getInfo(ItemInfo &info) const
+                       {
+                               int w = m_imageWidth;
+                               int h = m_imageHeight;
+                               if (!impl::getImageSize(m_image, w, h)) {
+                                       WLOG("Invalid image size!");
+                               }
+
+                               info.imageLoadSize = m_imageLoadSize;
+                               info.isImageLoadSizeFull = (
+                                               (w == m_imageWidth) && (h == m_imageHeight));
+                               info.isImageLoaded = m_isImageLoaded;
+                       }
+
                        void realize(const int itemIndex)
                        {
                                if (isRealized()) {
@@ -366,31 +374,82 @@ namespace gallery {
                                        if (!m_wasUpdated || (params.flags & UF_LOSE_IMAGE)) {
                                                makeTransparent(m_image);
                                                m_isImageEmpty = true;
+                                               m_isImageLoaded = false;
                                        }
                                        return;
                                }
 
                                makeTransparent(m_image);
                                m_isImageEmpty = false;
+                               m_isImageLoaded = false;
+
+                               m_imageWidth = std::max(params.imageWidth, 1);
+                               m_imageHeight = std::max(params.imageHeight, 1);
 
                                evas_object_image_file_set(m_image,
                                                params.imagePath.c_str(), NULL);
 
+                               updateImageLoadSize();
+
                                evas_object_image_preload(m_image, EINA_FALSE);
                        }
 
-                       void onImagePreloaded(Widget &widget, void *eventInfo)
+                       void updateImageLoadSize()
                        {
-                               if (m_isImageEmpty) {
+                               const int newLoadSize = ((m_imageWidth > m_imageHeight) ?
+                                               (m_imageMinLoadSize * m_imageWidth / m_imageHeight) :
+                                               (m_imageMinLoadSize * m_imageHeight / m_imageWidth));
+                               if (newLoadSize == m_imageLoadSize) {
                                        return;
                                }
 
-                               int w = 1;
-                               int h = 1;
+                               int w = m_imageWidth;
+                               int h = m_imageHeight;
                                if (!impl::getImageSize(m_image, w, h)) {
                                        WLOG("Invalid image size!");
                                }
-                               m_image.setARHint(WidgetARHint::NEITHER, w, h);
+
+                               if (isCurentLoadSizeSatisfying(w, h) ||
+                                               !isImageRespectsLoadSize(w, h)) {
+                                       return;
+                               }
+
+                               m_imageLoadSize = newLoadSize;
+                               evas_object_image_load_size_set(m_image,
+                                               newLoadSize, newLoadSize);
+                       }
+
+                       bool isCurentLoadSizeSatisfying(
+                                       const int curImgW, const int curImgH) const
+                       {
+                               const int kw = ((m_imageWidth > m_imageMinLoadSize) ?
+                                               (curImgW / m_imageMinLoadSize) : 1);
+                               const int kh = ((m_imageHeight > m_imageMinLoadSize) ?
+                                               (curImgH / m_imageMinLoadSize) : 1);
+                               return (((kw == 1) && (kh >= 1)) || ((kh == 1) && (kw >= 1)));
+                       }
+
+                       bool isImageRespectsLoadSize(
+                                       const int curImgW, const int curImgH) const
+                       {
+                               return ((m_imageLoadSize <= 0) ||
+                                               (curImgW != m_imageWidth) ||
+                                               (curImgH != m_imageHeight) || (
+                                                       ((curImgW / m_imageLoadSize) <= 1) &&
+                                                       ((curImgH / m_imageLoadSize) <= 1)
+                                               ));
+                       }
+
+                       void onImagePreloaded(Widget &widget, void *eventInfo)
+                       {
+                               if (m_isImageEmpty) {
+                                       return;
+                               }
+
+                               m_isImageLoaded = true;
+
+                               m_image.setARHint(WidgetARHint::NEITHER,
+                                               m_imageWidth, m_imageHeight);
 
                                makeWhite(m_image);
                        }
@@ -408,8 +467,6 @@ namespace gallery {
                                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(*m_bgImage, impl::BTN_PART_BG);
                                        show(*m_bgImage);
                                }
@@ -417,13 +474,8 @@ namespace gallery {
                                evas_object_image_file_set(*m_bgImage,
                                                params.bgImagePath.c_str(), NULL);
 
-                               int w = 1;
-                               int h = 1;
-                               if (!impl::getImageSize(m_image, w, h) &&
-                                               !impl::getImageSize(*m_bgImage, w, h)) {
-                                       WLOG("Invalid image size!");
-                               }
-                               m_bgImage->setARHint(WidgetARHint::NEITHER, w, h);
+                               m_bgImage->setARHint(WidgetARHint::NEITHER,
+                                               m_imageWidth, m_imageHeight);
 
                                makeWhite(*m_bgImage);
                        }
@@ -458,12 +510,16 @@ namespace gallery {
                        StyledWidget m_image;
                        WidgetSRef m_bgImage;
                        TouchParserSRef m_touchParser;
-                       int m_realizeIndex;
-                       int m_imageLoadSize;
-                       bool m_wasUpdated;
-                       bool m_isImageEmpty;
-                       bool m_isClicksBlocked;
-                       bool m_isSelected;
+                       int m_realizeIndex = -1;
+                       int m_imageLoadSize = 0;
+                       int m_imageMinLoadSize = 1;
+                       int m_imageWidth = 1;
+                       int m_imageHeight = 1;
+                       bool m_wasUpdated = false;
+                       bool m_isImageEmpty = false;
+                       bool m_isImageLoaded = false;
+                       bool m_isClicksBlocked = false;
+                       bool m_isSelected = false;
                };
 
        public:
@@ -472,6 +528,8 @@ namespace gallery {
                        m_layout(elm_layout_add(imageGrid.m_box), true),
                        m_isRealized(false)
                {
+                       int imageMinLoadSize = 0;
+
                        if (isValid(m_info.slotThemes[isOdd])) {
                                if (!m_layout.setTheme(m_info.slotThemes[isOdd])) {
                                        ELOG("setTheme() failed!");
@@ -480,6 +538,8 @@ namespace gallery {
                                        edje_object_message_signal_process(
                                                        elm_layout_edje_get(m_layout));
                                }
+                               imageMinLoadSize = ELM_SCALE_SIZE(m_layout.getData(
+                                               impl::DATA_IMAGE_MIN_LOAD_SIZE).asInt());
                        }
                        fill(m_layout);
                        show(m_layout);
@@ -491,6 +551,8 @@ namespace gallery {
                                const auto partName = impl::SLOT_PART_FMT.format(i);
                                m_layout.setContent(m_items.back()->getWidget(),
                                                EdjePart(partName.c_str()));
+
+                               m_items.back()->setImageMinLoadSize(imageMinLoadSize);
                        }
                }
 
@@ -507,13 +569,6 @@ namespace gallery {
                        return std::max((m_info.isHorizontal ? w : h), 1);
                }
 
-               void setImageLoadSize(const int value)
-               {
-                       for (auto &item: m_items) {
-                               item->setImageLoadSize(value);
-                       }
-               }
-
                void unrealize()
                {
                        if (!m_isRealized) {
@@ -557,6 +612,11 @@ namespace gallery {
                        return m_items[itemOffset]->isRealized();
                }
 
+               void getItemInfo(const int itemOffset, ItemInfo &info) const
+               {
+                       m_items[itemOffset]->getInfo(info);
+               }
+
        private:
                void setSelected(const int itemOffset, const bool selected)
                {
@@ -928,6 +988,16 @@ namespace gallery {
                        });
        }
 
+       Result ImageGrid::getItemInfo(const int itemIndex, ItemInfo &info) const
+       {
+               return doWithItem(itemIndex,
+                       [&info](Slot &slot, const int itemOffset)
+                       {
+                               slot.getItemInfo(itemOffset, info);
+                               return RES_OK;
+                       });
+       }
+
        template <class FUNC>
        Result ImageGrid::doWithItem(const int itemIndex, FUNC &&func) const
        {
@@ -1087,8 +1157,6 @@ namespace gallery {
                                setSlotSize(slot->getSize());
                        }
 
-                       slot->setImageLoadSize(m_slotSize);
-
                        elm_box_pack_before(m_box, slot->getLayout(), m_rect2);
 
                        m_slots.emplace_back(std::move(slot));
index 17abcc2ea6bf2c9775413cdc7d16a3de9ca27c08..0437bfcdf41d99edf08aeb2318c9c31772def09b 100644 (file)
@@ -32,6 +32,7 @@ namespace gallery {
        // ImageViewer::Builder //
 
        ImageViewer::Builder::Builder() :
+               m_loadSize(0),
                m_forceLoad(false)
        {
        }
@@ -43,6 +44,12 @@ namespace gallery {
                return *this;
        }
 
+       ImageViewer::Builder &ImageViewer::Builder::setLoadSize(const int value)
+       {
+               m_loadSize = value;
+               return *this;
+       }
+
        ImageViewer::Builder &ImageViewer::Builder::setForceLoad(const bool value)
        {
                m_forceLoad = value;
@@ -61,13 +68,15 @@ namespace gallery {
                        LOG_RETURN_VALUE(RES_FAIL, {}, "elm_scroller_add() failed!");
                }
 
-               return makeShared<ImageViewer>(scroller, m_highResPath, m_forceLoad);
+               return makeShared<ImageViewer>(scroller, m_highResPath,
+                               m_loadSize, m_forceLoad);
        }
 
        // ImageViewer //
 
        ImageViewer::ImageViewer(RefCountObjBase &rc, Evas_Object *const scroller,
-                       const std::string &highResPath, const bool forceLoad) :
+                       const std::string &highResPath, const int loadSize,
+                       const bool forceLoad) :
                ElmWidget(&rc, scroller, true),
 
                m_scroller(makeShared<StyledWidget>(scroller)),
@@ -96,7 +105,7 @@ namespace gallery {
                m_animator(nullptr),
                m_state(State::ZOOMED_OUT)
        {
-               prepare(highResPath, forceLoad);
+               prepare(highResPath, loadSize, forceLoad);
        }
 
        ImageViewer::~ImageViewer()
@@ -110,7 +119,7 @@ namespace gallery {
        }
 
        void ImageViewer::prepare(const std::string &highResPath,
-                       const bool forceLoad)
+                       const int loadSize, const bool forceLoad)
        {
                expandAndFill(*m_scroller);
                m_scroller->setStyle(SCROLLER_STYLE);
@@ -131,11 +140,18 @@ namespace gallery {
                show(m_grid);
 
                evas_object_grid_pack(m_grid, m_lowResImage, 0, 0, 1, 1);
+               if (loadSize > 0) {
+                       evas_object_image_load_size_set(m_lowResImage, loadSize, loadSize);
+               }
                show(m_lowResImage);
                makeTransparent(m_lowResImage);
 
                evas_object_grid_pack(m_grid, m_highResImage, 0, 0, 1, 1);
                if (forceLoad) {
+                       if (loadSize > 0) {
+                               evas_object_image_load_size_set(m_highResImage,
+                                               loadSize, loadSize);
+                       }
                        evas_object_image_file_set(m_highResImage,
                                        highResPath.c_str(), nullptr);
                        show(m_highResImage);