TizenRefApp-5295 Pages addition and deletion 60/55560/2
authorDenis Dolzhenko <d.dolzhenko@samsung.com>
Thu, 24 Dec 2015 14:26:45 +0000 (16:26 +0200)
committerDenis Dolzhenko <d.dolzhenko@samsung.com>
Thu, 24 Dec 2015 14:34:13 +0000 (16:34 +0200)
Change-Id: I665222a1d7f18c4ecbab4e85b58cb9a2bdb98e65
Signed-off-by: Denis Dolzhenko <d.dolzhenko@samsung.com>
20 files changed:
inc/Resource.h
res/images/cat.jpeg [new file with mode: 0755]
src/Common/View/inc/View.h
src/Common/View/inc/ViewItem.h
src/Common/View/src/View.cpp
src/Conversation/Body/Controller/inc/Body.h
src/Conversation/Body/Controller/src/Body.cpp
src/Conversation/Body/View/inc/BodyView.h
src/Conversation/Body/View/inc/ImagePageViewItem.h
src/Conversation/Body/View/inc/MediaPageViewItem.h
src/Conversation/Body/View/inc/PageView.h
src/Conversation/Body/View/inc/PageViewItem.h
src/Conversation/Body/View/inc/TextPageViewItem.h
src/Conversation/Body/View/src/BodyView.cpp
src/Conversation/Body/View/src/ImagePageViewItem.cpp
src/Conversation/Body/View/src/MediaPageViewItem.cpp
src/Conversation/Body/View/src/PageView.cpp
src/Conversation/Body/View/src/PageViewItem.cpp
src/Conversation/Body/View/src/TextPageViewItem.cpp
src/Conversation/Main/Controller/src/Conversation.cpp

index ba926f9..56af9e4 100644 (file)
@@ -40,7 +40,7 @@
 #define THUMBNAIL_EDJ_PATH               EDJ_PATH"/msg_thumbnail.edj"
 #define MSG_TITLE_EDJ_PATH               EDJ_PATH"/msg_title.edj"
 
-// Images:
+// Images(res):
 #define THUMB_CONTACT_IMG_PATH           IMAGE_PATH"/list_ic_contacts.png"
 #define THUMB_GROUP_IMG_PATH             IMAGE_PATH"/list_ic_group.png"
 #define THUMB_CB_IMG_PATH                IMAGE_PATH"/list_ic_cb_message.png"
@@ -48,6 +48,7 @@
 #define THUMB_OTA_IMG_PATH               IMAGE_PATH"/list_ic_OTA_message.png"
 #define THUMB_USER_MASK_74x74_IMG_PATH   IMAGE_PATH"/list_ic_user_thumb_masking.png"
 #define MSG_THREAD_FLOATING_BTN_ICON     IMAGE_PATH"/message_floating_button_icon.png"
+#define TEST_IMG_PATH                    IMAGE_PATH"/cat.jpeg"
 
 // Colors:
 #define BUTTON_COLOR                     2, 61, 132, 255
diff --git a/res/images/cat.jpeg b/res/images/cat.jpeg
new file mode 100755 (executable)
index 0000000..13055f6
Binary files /dev/null and b/res/images/cat.jpeg differ
index 5da4429..94609e9 100644 (file)
@@ -31,9 +31,8 @@ namespace Msg
     {
         public:
             View();
-            virtual ~View();
-            virtual void destroy();
 
+            inline void destroy();
             inline operator Evas_Object *() const;
             inline Evas_Object *getEo() const;
             inline void show();
@@ -55,10 +54,13 @@ namespace Msg
             inline void emitSignal(const char *emission, const char *source);
             inline void setData(const char *key, const void *data);
             inline void *getData(const char *key) const;
-            inline void setSmartData(const void *data);
-            inline static void setSmartData(Evas_Object *obj, const void *data);
-            inline void *getSmartData() const;
-            inline static void *getSmartData(Evas_Object *obj);
+
+            template<typename T>
+            inline static T staticCast(Evas_Object *obj);
+            template<typename T>
+            inline static T reinterpretCast(void *obj);
+            template<typename T>
+            inline static T dynamicCast(Evas_Object *obj);
 
             inline std::string getText(const char *part = nullptr) const;
             inline const char *getTextCStr(const char *part = nullptr) const;
@@ -68,6 +70,7 @@ namespace Msg
             inline static void setText(Evas_Object *obj, const TText &text, const char *part = nullptr);
 
         protected:
+            virtual ~View();
             virtual void onBeforeDelete(View &view) {};
 
             void setEventCb(Evas_Callback_Type type);
@@ -78,6 +81,10 @@ namespace Msg
             View(View&) = delete;
             View& operator=(View&) = delete;
             Evas_Object_Event_Cb getCb(Evas_Callback_Type);
+            inline void *getSmartData() const;
+            inline static void *getSmartData(Evas_Object *obj);
+            inline void setSmartData(const void *data);
+            inline static void setSmartData(Evas_Object *obj, const void *data);
 
         private:
             static void on_free_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
@@ -97,6 +104,11 @@ namespace Msg
         return m_pEo;
     }
 
+    inline void View::destroy()
+    {
+        evas_object_del(m_pEo);
+    }
+
     inline void View::show()
     {
         evas_object_show(m_pEo);
@@ -227,6 +239,24 @@ namespace Msg
     {
         return evas_object_smart_data_get(obj);
     }
+
+    template<typename T>
+    inline T View::staticCast(Evas_Object *obj)
+    {
+        return static_cast<T>(getSmartData(obj));
+    }
+
+    template<typename T>
+    inline T View::reinterpretCast(void *obj)
+    {
+        return reinterpret_cast<T>(getSmartData((Evas_Object*)obj));
+    }
+
+    template<typename T>
+    inline T View::dynamicCast(Evas_Object *obj)
+    {
+        return dynamic_cast<T>(staticCast<T>(obj));
+    }
 }
 
 #endif /* View_h_ */
index 442987c..3183a33 100644 (file)
@@ -33,7 +33,6 @@ namespace Msg
             ViewItem();
             ViewItem(ViewItem&) = delete;
             ViewItem& operator=(const ViewItem&) = delete;
-            virtual ~ViewItem();
 
             inline operator Elm_Object_Item *() const;
             virtual void destroy();
@@ -56,6 +55,7 @@ namespace Msg
             inline static void setText(Elm_Object_Item *it, const TText &text, const char *part = nullptr);
 
         protected:
+            virtual ~ViewItem();
             virtual void onAttached(ViewItem &item) {};
             void setElmObjItem(Elm_Object_Item *item);
 
index f1a16f7..40e2a21 100644 (file)
@@ -45,11 +45,6 @@ Evas_Object_Event_Cb View::getCb(Evas_Callback_Type type)
     return it != cbMap.end() ? it->second : nullptr;
 }
 
-void View::destroy()
-{
-    evas_object_del(m_pEo);
-}
-
 void View::setEventCb(Evas_Callback_Type type)
 {
     Evas_Object_Event_Cb cb = getCb(type);
@@ -74,8 +69,12 @@ void View::setEo(Evas_Object *eo)
     }
 
     m_pEo = eo;
-    setEventCb(EVAS_CALLBACK_FREE);
-    setEventCb(EVAS_CALLBACK_DEL);
+    if(eo)
+    {
+        setSmartData(this);
+        setEventCb(EVAS_CALLBACK_FREE);
+        setEventCb(EVAS_CALLBACK_DEL);
+    }
 }
 
 void View::unsetEventCb(Evas_Callback_Type type)
index 428d9e3..0a3b0b0 100644 (file)
 #include "MessageSMS.h"
 #include "MessageMms.h"
 #include "WorkingDir.h"
-#include "MediaPageViewItem.h"
-#include "TextPageViewItem.h"
+
+#include <list>
+#include <Ecore.h>
 
 namespace Msg
 {
     class IBodyListener;
     class MsgEngine;
-    class TextPageViewItem;
-    class ImagePageViewItem;
-    class AudioPageViewItem;
 
     struct BodySmsSize
     {
@@ -41,17 +39,14 @@ namespace Msg
 
     class Body
         : public BodyView
-        , private ITextPageViewItemListener
-        , private IMediaPageViewItemListener
     {
         public:
             Body(Evas_Object *parent, MsgEngine &msgEngine);
             virtual ~Body();
 
-            void setFocus(bool focus);
             void setListener(IBodyListener *listener);
-            void clear();
-            bool isEmpty() const;
+
+            bool addMedia(const std::list<std::string> &fileList);
             bool addMedia(const std::string &filePath);
 
             bool isMms() const;
@@ -65,34 +60,16 @@ namespace Msg
             void read(MessageMms &msg);
             void write(const MessageSMS &msg);
             void write(const MessageMms &msg);
-
-            PageView *addPage();
             bool isMms(const PageView &page) const;
 
-            // ITextPageViewItemListener:
-            virtual void onChanged(TextPageViewItem &item);
-            virtual void onCursorChanged(TextPageViewItem &item) {};
-            virtual void onFocused(TextPageViewItem &item) {};
-            virtual void onUnfocused(TextPageViewItem &item) {};
-            virtual void onPreeditChanged(TextPageViewItem &item) {};
-            virtual void onPress(TextPageViewItem &item) {};
-            virtual void onClicked(TextPageViewItem &item) {};
-            virtual void onMaxLengthReached(TextPageViewItem &item) {};
-            virtual void onKeyDown(TextPageViewItem &item) {};
-            virtual void onKeyUp(TextPageViewItem &item) {};
-
-            // IMediaPageViewItemListener:
-            virtual void onClicked(MediaPageViewItem &item) {};
-            virtual void onPressed(MediaPageViewItem &item) {};
-            virtual void onUnpressed(MediaPageViewItem &item) {};
-            virtual void onFocused(MediaPageViewItem &item) {};
-            virtual void onUnfocused(MediaPageViewItem &item) {};
+            // BodyView:
+            virtual void onContentChanged();
 
         private:
             IBodyListener *m_pListener;
-            PageView *m_pDefaultPage;
             MsgEngine &m_MsgEngine;
             WorkingDir m_WorkingDir;
+            Ecore_Idler *m_pOnChangedIdler;
     };
 
     class IBodyListener
@@ -101,8 +78,6 @@ namespace Msg
             virtual ~IBodyListener() {}
 
             virtual void onChanged(Body &body) {};
-            virtual void onFoucused(Body &body) {};
-            virtual void onUnfoucused(Body &body) {};
     };
 }
 
index 17c4531..c293bb9 100644 (file)
 
 #include "Body.h"
 #include "PageView.h"
-#include "MsgEngine.h"
 #include "FileUtils.h"
 #include "TextPageViewItem.h"
 #include "ImagePageViewItem.h"
 #include "BodyMediaType.h"
+#include "MsgEngine.h"
+#include "Logger.h"
 
 #include <assert.h>
+#include <string.h>
 
 using namespace Msg;
 
 namespace
 {
-
-    const std::string maxPageSepLabel = "3"; // TODO: check
-    TextPageViewItem *getTextItem(PageView *page)
+    inline TextPageViewItem *getTextItem(const PageView &page)
     {
-        return page ? static_cast<TextPageViewItem*>(page->getItem(PageViewItem::TextType)) : nullptr;
+        return page ? static_cast<TextPageViewItem*>(page.getItem(PageViewItem::TextType)) : nullptr;
     }
 }
 
@@ -41,86 +41,66 @@ Body::Body(Evas_Object *parent, MsgEngine &msgEngine)
     : BodyView(parent)
     , m_pListener(nullptr)
     , m_MsgEngine(msgEngine)
+    , m_pOnChangedIdler(nullptr)
 {
-    BodyView::setMaxPageLabel(maxPageSepLabel);
-    m_pDefaultPage = addPage();
 }
 
 Body::~Body()
 {
+    if(m_pOnChangedIdler)
+    {
+        ecore_idler_del(m_pOnChangedIdler);
+        m_pOnChangedIdler = nullptr;
+    }
 }
 
-PageView *Body::addPage()
-{
-    PageView *page = new PageView(*this);
-    TextPageViewItem *text = new TextPageViewItem(*page);
-    text->setListener(this);
-    text->setGuideText(msgt("IDS_MSG_TMBODY_TEXT_MESSAGES"));
-    page->addItem(*text);
-    BodyView::addPage(*page);
-    return page;
-}
-
-
 void Body::setListener(IBodyListener *listener)
 {
     m_pListener = listener;
 }
 
-void Body::setFocus(bool focus)
+bool Body::addMedia(const std::list<std::string> &fileList)
 {
-    PageViewCollection pages = getPages();
-    if(!pages.empty())
-    {
-        auto itEnd = pages.end();
-        PageView *lastPage = *(--itEnd);
-        lastPage->setFocus(true);
-    }
+    bool res = true;
+    for(auto &file : fileList)
+        res &= addMedia(file);
+    return res;
 }
 
-void Body::clear()
+bool Body::addMedia(const std::string &filePath)
 {
-    auto pages = getPages();
-    for(PageView *page : pages)
+    MSG_LOG("Try add resource:", filePath);
+
+    // TODO:
+    // If path is web uri then set path as body text:
+    // Check file path:
+    // Use working dir:
+
+    if(!FileUtils::isExists(filePath) || FileUtils::isDir(filePath))
     {
-        if(page == m_pDefaultPage)
-        {
-            auto pageItems = page->getItems();
-            for(PageViewItem *pageItem : pageItems)
-            {
-                PageViewItem::Type itemType = pageItem->getType();
-                if(itemType != PageViewItem::TextType)
-                {
-                    page->removeItem(itemType);
-                }
-            }
-        }
-        else
-        {
-            page->destroy();
-        }
+        MSG_LOG_ERROR("File not exists:", filePath);
+        return false;
     }
+
+    bool res = BodyView::addMedia(filePath);
+
+    if(m_pListener)
+        m_pListener->onChanged(*this);
+
+    return res;
 }
 
 bool Body::isMms() const
 {
-    int pageCount = 0;
-    auto bodyItems = BodyView::getAllItems();
-    for(BodyViewItem *bodyItem : bodyItems)
+    auto pages = getPages();
+
+    if(pages.size() > 1)
+        return true;
+
+    for(PageView *page : pages)
     {
-        BodyViewItem::Type type = bodyItem->getType();
-        if(type == BodyViewItem::PageType)
-        {
-            ++pageCount;
-            if(pageCount > 1 || isMms(static_cast<PageView&>(*bodyItem)))
-            {
-                return true;
-            }
-        }
-        else if(type == BodyViewItem::AttachmentType)
-        {
+        if(isMms(*page))
             return true;
-        }
     }
     return false;
 }
@@ -132,9 +112,7 @@ bool Body::isMms(const PageView &page) const
     {
         PageViewItem::Type itemType = pageItem->getType();
         if(itemType != PageViewItem::TextType)
-        {
             return true;
-        }
     }
     return false;
 }
@@ -142,7 +120,7 @@ bool Body::isMms(const PageView &page) const
 BodySmsSize Body::getSmsSize() const
 {
     BodySmsSize size = {};
-    TextPageViewItem *textItem = getTextItem(m_pDefaultPage);
+    TextPageViewItem *textItem = getTextItem(getDefaultPage());
 
     if(textItem)
     {
@@ -164,102 +142,20 @@ long long Body::getMmsSize() const
     return 0;
 }
 
-bool Body::isEmpty() const
-{
-    const auto pages = getPages();
-    for(PageView *page : pages)
-    {
-        if(!page->isEmpty())
-        {
-            return false;
-        }
-    }
-    return true;
-}
-
-bool Body::addMedia(const std::string &filePath)
-{
-    // If path is web uri then set path as body text:
-    // TODO:
-
-    // Check file path:
-    if(!FileUtils::isExists(filePath) || FileUtils::isDir(filePath))
-    {
-        return false;
-    }
-
-    PageViewItem::Type itemType = getMediaType(filePath).type;
-    if(itemType != PageViewItem::UnknownType)
-    {
-        PageViewItem *pageItem = nullptr;
-        PageView *page = addPage();
-
-        switch(itemType)
-        {
-            case PageViewItem::TextType:
-            {
-                break;
-            }
-
-            case PageViewItem::ImageType:
-            {
-                pageItem = new ImagePageViewItem(*page, filePath);
-                break;
-            }
-
-            case PageViewItem::AudioType:
-            {
-                break;
-            }
-
-            case PageViewItem::VideoType:
-            {
-                break;
-            }
-
-            default:
-                assert(false);
-                break;
-        }
-
-        if(pageItem)
-        {
-            page->addItem(*pageItem);
-        }
-    }
-    else
-    {
-        // TODO:
-    }
-
-    if(m_pListener)
-        m_pListener->onChanged(*this);
-
-    return true;
-}
-
 void Body::read(Message &msg)
 {
     if(MessageSMS *sms = dynamic_cast<MessageSMS*>(&msg))
-    {
         read(*sms);
-    }
     else if(MessageMms *mms = dynamic_cast<MessageMms*>(&msg))
-    {
         read(*mms);
-    }
 }
 
 void Body::write(const Message &msg)
 {
     if(const MessageSMS *sms = dynamic_cast<const MessageSMS*>(&msg))
-    {
         write(*sms);
-    }
     else if(const MessageMms *mms = dynamic_cast<const MessageMms*>(&msg))
-    {
         write(*mms);
-    }
 }
 
 void Body::write(const MessageSMS &msg)
@@ -274,7 +170,7 @@ void Body::write(const MessageMms &msg)
 
 void Body::read(MessageSMS &msg)
 {
-    TextPageViewItem *textItem = getTextItem(m_pDefaultPage);
+    TextPageViewItem *textItem = getTextItem(getDefaultPage());
     assert(textItem);
     if(textItem)
     {
@@ -287,7 +183,7 @@ void Body::read(MessageMms &msg)
     auto pages = getPages();
     for(PageView *page : pages)
     {
-        TextPageViewItem *textItem = getTextItem(page);
+        TextPageViewItem *textItem = getTextItem(*page);
         if(textItem)
         {
             std::string textFile = m_WorkingDir.addTextFile(textItem->getPlainUtf8Text());
@@ -301,8 +197,21 @@ void Body::read(MessageMms &msg)
     }
 }
 
-void Body::onChanged(TextPageViewItem &item)
+void Body::onContentChanged()
 {
-    if(m_pListener)
-        m_pListener->onChanged(*this);
+    if(!m_pOnChangedIdler)
+    {
+        m_pOnChangedIdler = ecore_idler_add
+        (
+            [](void *data)->Eina_Bool
+            {
+                Body *self =(Body*)data;
+                if(self->m_pListener)
+                    self->m_pListener->onChanged(*self);
+                self->m_pOnChangedIdler = nullptr;
+                return false; // Delete idler
+            },
+            this
+        );
+    }
 }
index de88083..0837c4b 100644 (file)
@@ -20,6 +20,9 @@
 
 #include "View.h"
 #include "BodyViewItem.h"
+#include "MediaPageViewItem.h"
+#include "TextPageViewItem.h"
+#include "ImagePageViewItem.h"
 
 #include <vector>
 
@@ -27,6 +30,7 @@ namespace Msg
 {
     class PageView;
     class BodyAttachmentView;
+    class PageSeparator;
 
     typedef std::vector<PageView*> PageViewCollection;
     typedef std::vector<BodyAttachmentView*> BodyAttachmentCollection;
@@ -34,6 +38,8 @@ namespace Msg
 
     class BodyView
         : public View
+        , private ITextPageViewItemListener
+        , private IMediaPageViewItemListener
     {
         friend class PageView;
 
@@ -41,30 +47,82 @@ namespace Msg
             BodyView(Evas_Object *parent);
             virtual ~BodyView();
 
-            void setMaxPageLabel(const std::string &max);
-            void addPage(PageView &page);
-            void removePage(PageView &page);
+            bool isEmpty() const;
+            void clear();
+            void setFocus(bool focus);
+
+        protected:
+            bool addMedia(const std::string &filePath);
+            const PageView &getDefaultPage() const;
             PageViewCollection getPages() const;
+            int getPageCount() const;
+            PageView *getNextPage(PageView &page) const;
+            PageView *getPrevPage(PageView &page) const;
+            PageView *addPage();
+
+        private:
+            /*====Input signals====*/
+
+            // ITextPageViewItemListener:
+            virtual void onDelete(TextPageViewItem &item);
+            virtual void onCursorChanged(TextPageViewItem &item);
+            virtual void onFocused(TextPageViewItem &item);
+            virtual void onUnfocused(TextPageViewItem &item);
+            virtual void onPreeditChanged(TextPageViewItem &item);
+            virtual void onPress(TextPageViewItem &item);
+            virtual void onClicked(TextPageViewItem &item);
+            virtual void onMaxLengthReached(TextPageViewItem &item);
+            virtual void onKeyDown(TextPageViewItem &obj, Evas_Event_Key_Down &event);
+            virtual void onKeyUp(TextPageViewItem &obj, Evas_Event_Key_Up &event);
+            virtual void onChanged(TextPageViewItem &item);
+
+            // IMediaPageViewItemListener:
+            virtual void onDelete(MediaPageViewItem &item);
+            virtual void onClicked(MediaPageViewItem &item);
+            virtual void onPressed(MediaPageViewItem &item);
+            virtual void onUnpressed(MediaPageViewItem &item);
+            virtual void onFocused(MediaPageViewItem &item);
+            virtual void onUnfocused(MediaPageViewItem &item);
+            virtual void onKeyDown(MediaPageViewItem &item, Evas_Event_Key_Down &event);
+            virtual void onKeyUp(MediaPageViewItem &item, Evas_Event_Key_Up &event);
+
+            /*====Output signals====*/
+            virtual void onContentChanged() {};
+            virtual void onMediaRemoved(const std::string &resourcePath) {};
+
+        private:
+            void setMaxPageLabel(const std::string &max);
             BodyAttachmentCollection getAttachments() const;
             template<typename T>
             std::vector<T*> getItems() const;
             BodyViewItemCollection getAllItems() const;
-            PageView *getFocusedPage() const;
-            bool getFocus() const;
             int getItemCount(BodyViewItem::Type type) const;
+            void setFocus(PageView &page, bool focus);
+            void showInputPanel(PageView &page, bool show);
+            void showInputPanel(PageViewItem &pageItem, bool show);
+            void removePage(PageView &page, bool setNextFocus);
+            TextPageViewItem *addText(PageView &page);
+            ImagePageViewItem *addImage(PageView &page, const std::string &filePath);
+            void updateLastFocusedPage(PageViewItem &pageItem);
+            PageView *getPageForMedia(PageViewItem::Type type);
+            void backKeyHandler(MediaPageViewItem &item);
+            void backKeyHandler(TextPageViewItem &item);
 
-        private:
             void create(Evas_Object *parent);
             void prepare(BodyViewItem &item);
             void insertAfter(BodyViewItem &item, BodyViewItem &after);
             void insertBefore(BodyViewItem &item, BodyViewItem &before);
             void append(BodyViewItem &item);
-            void prepend(BodyViewItem &item);
             void remove(BodyViewItem &item);
+            void rebuildPageSeparators();
+            PageSeparator *createSep(int number);
 
         private:
             BodyViewItemCollection m_Items;
             std::string m_MaxPageLabel;
+            PageView *m_pDefaultPage;
+            int m_LastTextCursorPos;
+            PageView *m_pLastFocusedPage;
     };
 }
 
index 461a45e..9f79896 100644 (file)
@@ -33,11 +33,15 @@ namespace Msg
 
             virtual Type getType() const;
             virtual bool isEmpty() const;
+            virtual void highlight(bool value);
 
         private:
             Evas_Object *createImageLayout(Evas_Object *parent);
             Evas_Object *createRect(Evas_Object *parent);
             Evas_Object *createImageIconAndSetOrient(Evas_Object *parent);
+
+        private:
+            Evas_Object *m_pImageLayout;
     };
 }
 
index e9dd5f9..00343cb 100644 (file)
@@ -36,6 +36,8 @@ namespace Msg
             void setListener(IMediaPageViewItemListener *l);
             const std::string &getResourcePath() const;
 
+            virtual void highlight(bool value) = 0;
+
         protected:
             Evas_Object *getMediaLayout() const;
             Evas_Object *getButtonLayout() const;
@@ -43,13 +45,15 @@ namespace Msg
             void setRect(Evas_Object *layout);
 
         private:
-            typedef void (IMediaPageViewItemListener::*ListenerMethod)(MediaPageViewItem &);
+            virtual void onBeforeDelete(View &view);
 
             Evas_Object *createMainLayout(Evas_Object *parent);
             Evas_Object *createButton(Evas_Object *parent);
             Evas_Object *createRect(Evas_Object *parent);
             Evas_Object *createGestureLayer(Evas_Object *parent);
-            static void notifyListener(void *data, ListenerMethod method);
+
+            template<class...Args>
+            static void notifyListener(void *data, void (IMediaPageViewItemListener::*method)(MediaPageViewItem &, Args...args), Args&&...args);
 
         private:
             IMediaPageViewItemListener *m_pListener;
@@ -62,11 +66,14 @@ namespace Msg
         public:
             virtual ~IMediaPageViewItemListener() {}
 
+            virtual void onDelete(MediaPageViewItem &item) {};
             virtual void onClicked(MediaPageViewItem &item) {};
             virtual void onPressed(MediaPageViewItem &item) {};
             virtual void onUnpressed(MediaPageViewItem &item) {};
             virtual void onFocused(MediaPageViewItem &item) {};
             virtual void onUnfocused(MediaPageViewItem &item) {};
+            virtual void onKeyDown(MediaPageViewItem &item, Evas_Event_Key_Down &event) {};
+            virtual void onKeyUp(MediaPageViewItem &item, Evas_Event_Key_Up &event) {};
     };
 }
 
index d355959..237b466 100644 (file)
@@ -27,7 +27,6 @@
 namespace Msg
 {
     class BodyView;
-
     class PageView
         : public BodyViewItem
     {
@@ -40,7 +39,7 @@ namespace Msg
 
             ItemList getItems() const;
             void addItem(PageViewItem &item);
-            void removeItem(PageViewItem::Type type);
+            void removeItem(PageViewItem &item);
             PageViewItem *getItem(PageViewItem::Type type) const;
             bool isEmpty() const;
             Evas_Object *getItemParent() const;
index a4e3267..297545d 100644 (file)
@@ -46,6 +46,7 @@ namespace Msg
 
             const PageView &getParentPage() const;
             PageView &getParentPage();
+            void destroy();
 
         protected:
             const std::string &getEdjPath() const;
index 66bb55b..1fe6997 100644 (file)
@@ -35,17 +35,24 @@ namespace Msg
             virtual Type getType() const;
             virtual bool isEmpty() const;
 
+            void showInputPanel(bool show);
+            int getCursorPos() const;
+            void setCursorPos(int pos);
+            void setEndCursorPos();
+            void setBeginCursorPos();
             void setListener(ITextPageViewItemListener *l);
             void setGuideText(const TText &text);
-            void clearText();
+            void clear();
             std::string getText() const;
             std::string getPlainUtf8Text() const;
 
         private:
-            typedef void (ITextPageViewItemListener::*ListenerMethod)(TextPageViewItem &);
+            virtual void onBeforeDelete(View &view);
 
             Evas_Object *createEntry(Evas_Object *parent);
-            static void notifyListener(void *data, ListenerMethod method);
+
+            template<class...Args>
+            static void notifyListener(void *data, void (ITextPageViewItemListener::*method)(TextPageViewItem &, Args...args), Args&&...args);
 
         private:
             Evas_Object *m_pEntry;
@@ -56,6 +63,7 @@ namespace Msg
     {
         public:
             virtual ~ITextPageViewItemListener() {}
+            virtual void onDelete(TextPageViewItem &item) {};
             virtual void onCursorChanged(TextPageViewItem &obj) {};
             virtual void onFocused(TextPageViewItem &obj) {};
             virtual void onUnfocused(TextPageViewItem &obj) {};
@@ -64,8 +72,8 @@ namespace Msg
             virtual void onPress(TextPageViewItem &obj) {};
             virtual void onClicked(TextPageViewItem &obj) {};
             virtual void onMaxLengthReached(TextPageViewItem &obj) {};
-            virtual void onKeyDown(TextPageViewItem &obj) {};
-            virtual void onKeyUp(TextPageViewItem &obj) {};
+            virtual void onKeyDown(TextPageViewItem &obj, Evas_Event_Key_Down &event) {};
+            virtual void onKeyUp(TextPageViewItem &obj, Evas_Event_Key_Up &event) {};
     };
 }
 
index 586425a..309b783 100644 (file)
 #include "PageView.h"
 #include "BodyAttachmentView.h"
 #include "PageSeparator.h"
+#include "Logger.h"
+#include "BodyMediaType.h"
 
 #include <assert.h>
+#include <algorithm>
 
 using namespace Msg;
 
 namespace
 {
-    const char *objKey = "obj";
+    const std::string maxPageSepLabel = "3"; // TODO: check
+
+    inline bool isBackKey(const char *name)
+    {
+        return name ? strcmp("BackSpace", name) == 0 : false;
+    }
 }
 
 BodyView::BodyView(Evas_Object *parent)
+    : m_pDefaultPage(nullptr)
+    , m_LastTextCursorPos(0)
+    , m_pLastFocusedPage(nullptr)
 {
     create(parent);
 }
@@ -39,21 +50,56 @@ BodyView::~BodyView()
 
 }
 
-void BodyView::addPage(PageView &page)
+void BodyView::create(Evas_Object *parent)
 {
-    int pageCount = getItemCount(BodyViewItem::PageType);
-    if(pageCount > 0)
+    setEo(elm_box_add(parent));
+    expand();
+
+    setMaxPageLabel(maxPageSepLabel);
+    m_pDefaultPage = addPage();
+}
+
+const PageView &BodyView::getDefaultPage() const
+{
+    assert(m_pDefaultPage);
+    return *m_pDefaultPage;
+}
+
+bool BodyView::isEmpty() const
+{
+    const auto pages = getPages();
+    for(PageView *page : pages)
     {
-        PageSeparator *sep = new PageSeparator(*this);
-        sep->setText(std::to_string(pageCount) + '/' + m_MaxPageLabel);
-        append(*sep);
+        if(!page->isEmpty())
+            return false;
     }
-    append(page);
+    return true;
 }
 
-void BodyView::removePage(PageView &page)
+PageView *BodyView::getNextPage(PageView &page) const
 {
-    // TODO: impl
+    auto pages = getPages();
+    auto itEnd = pages.end();
+    auto it = std::find(pages.begin(), pages.end(), &page);
+
+    if(it != itEnd)
+        ++it;
+
+    return it != itEnd ? *it : nullptr;
+}
+
+PageView *BodyView::getPrevPage(PageView &page) const
+{
+    auto pages = getPages();
+
+    auto itBegin = pages.begin();
+    auto itEnd = pages.end();
+    auto it = std::find(pages.begin(), pages.end(), &page);
+
+    if(it != itEnd && it != itBegin)
+        --it;
+
+    return it != itEnd ? *it : nullptr;
 }
 
 void BodyView::setMaxPageLabel(const std::string &max)
@@ -68,35 +114,49 @@ int BodyView::getItemCount(BodyViewItem::Type type) const
     for(BodyViewItem *item : list)
     {
         if(item->getType() == type)
-        {
             ++count;
-        }
     }
     return count;
 }
 
-void BodyView::create(Evas_Object *parent)
+PageSeparator *BodyView::createSep(int number)
 {
-    setEo(elm_box_add(parent));
-    expand();
+    PageSeparator *sep = new PageSeparator(*this);
+    sep->setText(std::to_string(number) + '/' + m_MaxPageLabel);
+    return sep;
 }
 
-void BodyView::prepare(BodyViewItem &item)
+void BodyView::rebuildPageSeparators()
 {
-    item.setData(objKey, &item);
+    auto separators = getItems<PageSeparator>();
+    for(PageSeparator *sep : separators)
+        remove(*sep);
+
+    auto pages = getPages();
+    PageView *prevPage = nullptr;
+    int number = 0;
+
+    for(PageView *page : pages)
+    {
+        if(prevPage)
+        {
+            ++number;
+            PageSeparator *sep = createSep(number);
+            insertAfter(*sep, *prevPage);
+        }
+        prevPage = page;
+    }
 }
 
-void BodyView::append(BodyViewItem &item)
+void BodyView::prepare(BodyViewItem &item)
 {
-    prepare(item);
-    elm_box_pack_end(getEo(), item);
     item.show();
 }
 
-void BodyView::prepend(BodyViewItem &item)
+void BodyView::append(BodyViewItem &item)
 {
     prepare(item);
-    elm_box_pack_start(getEo(), item);
+    elm_box_pack_end(getEo(), item);
     item.show();
 }
 
@@ -118,6 +178,11 @@ void BodyView::remove(BodyViewItem &item)
     item.destroy();
 }
 
+int BodyView::getPageCount() const
+{
+    return getPages().size();
+}
+
 PageViewCollection BodyView::getPages() const
 {
     return getItems<PageView>();
@@ -136,11 +201,8 @@ std::vector<T*> BodyView::getItems() const
     for(BodyViewItem *item : all)
     {
         if(T *itemT = dynamic_cast<T*>(item))
-        {
             res.push_back(itemT);
-        }
     }
-
     return res;
 }
 
@@ -155,8 +217,7 @@ BodyViewItemCollection BodyView::getAllItems() const
 
         EINA_LIST_FOREACH(list, l, obj)
         {
-            BodyViewItem *item = static_cast<BodyViewItem*>(evas_object_data_get((Evas_Object*)obj, objKey));
-            assert(item);
+            BodyViewItem *item = reinterpretCast<BodyViewItem*>(obj);
             if(item)
                 res.push_back(item);
         }
@@ -166,25 +227,315 @@ BodyViewItemCollection BodyView::getAllItems() const
     return res;
 }
 
-PageView *BodyView::getFocusedPage() const
+PageView *BodyView::addPage()
 {
-    PageView *focusedPage = nullptr;
-    PageViewCollection pages = getPages();
+    PageView *page = new PageView(*this);
+
+    int pageCount = getItemCount(BodyViewItem::PageType);
+    if(pageCount > 0)
+        append(*createSep(pageCount));
+
+    append(*page);
+    addText(*page);
+
+    return page;
+}
 
+void BodyView::setFocus(PageView &page, bool focus)
+{
+    TextPageViewItem *textItem = static_cast<TextPageViewItem*>(page.getItem(PageViewItem::TextType));
+    if(textItem)
+    {
+        textItem->setFocus(focus);
+        textItem->setEndCursorPos();
+    }
+}
+
+void BodyView::setFocus(bool focus)
+{
+    setFocus(*m_pDefaultPage, focus);
+}
+
+void BodyView::clear()
+{
+    auto pages = getPages();
     for(PageView *page : pages)
     {
-        if(page->getFocus())
+        if(page == m_pDefaultPage)
+        {
+            auto pageItems = page->getItems();
+            for(PageViewItem *pageItem : pageItems)
+            {
+                if(pageItem->getType() == PageViewItem::TextType)
+                    static_cast<TextPageViewItem*>(pageItem)->clear();
+                else
+                    page->removeItem(*pageItem);
+            }
+        }
+        else
+        {
+            removePage(*page, false);
+        }
+    }
+}
+
+void BodyView::showInputPanel(PageView &page, bool show)
+{
+    TextPageViewItem *item = static_cast<TextPageViewItem*>(page.getItem(PageViewItem::TextType));
+    if(item)
+        item->showInputPanel(show);
+}
+
+void BodyView::showInputPanel(PageViewItem &pageItem, bool show)
+{
+    if(pageItem.getType() == PageViewItem::TextType)
+        static_cast<TextPageViewItem&>(pageItem).showInputPanel(show);
+    else
+        showInputPanel(pageItem.getParentPage(), show);
+}
+
+ImagePageViewItem *BodyView::addImage(PageView &page, const std::string &filePath)
+{
+    ImagePageViewItem *item = new ImagePageViewItem(page, filePath);
+    item->setListener(this);
+    item->show();
+    page.addItem(*item);
+    return item;
+}
+
+TextPageViewItem *BodyView::addText(PageView &page)
+{
+    TextPageViewItem *item = new TextPageViewItem(page);
+    item->setListener(this);
+    item->show();
+    item->setGuideText(msgt("IDS_MSG_TMBODY_TEXT_MESSAGES"));
+    page.addItem(*item);
+    return item;
+}
+
+void BodyView::updateLastFocusedPage(PageViewItem &pageItem)
+{
+    m_pLastFocusedPage = &pageItem.getParentPage();
+}
+
+PageView *BodyView::getPageForMedia(PageViewItem::Type type)
+{
+    PageView *page = m_pLastFocusedPage;
+
+    if(page && !page->getItem(type))
+        return page;
+
+    page = nullptr;
+    auto pages = getPages();
+
+    for(PageView *p : pages)
+    {
+        if(!p->getItem(type))
         {
-            focusedPage = page;
+            page = p;
             break;
         }
     }
-    return focusedPage;
+    if(!page)
+        page = addPage();
+
+    return page;
+}
+
+void BodyView::removePage(PageView &page, bool setNextFocus)
+{
+    if(m_pDefaultPage != &page && getPageCount() > 1)
+    {
+        if(setNextFocus)
+        {
+            PageView *prevPage = getPrevPage(page);
+            if(prevPage)
+                setFocus(*prevPage, true);
+        }
+
+        page.View::destroy();
+        rebuildPageSeparators();
+
+        if(m_pLastFocusedPage == &page)
+            m_pLastFocusedPage = nullptr;
+    }
+}
+
+bool BodyView::addMedia(const std::string &filePath)
+{
+    bool res = false;
+
+    PageViewItem::Type type = getMediaType(filePath).type;
+    if(type != PageViewItem::UnknownType)
+    {
+        PageView *page = getPageForMedia(type);
+        if(!page)
+            return false;
+
+        switch(type)
+        {
+            case PageViewItem::ImageType:
+            {
+                MSG_LOG("");
+                res = addImage(*page, filePath);
+                break;
+            }
+
+            case PageViewItem::AudioType:
+            {
+                break;
+            }
+
+            case PageViewItem::VideoType:
+            {
+                break;
+            }
+
+            default:
+                assert(false);
+                return false;
+                break;
+        }
+
+
+        if(res)
+            onContentChanged();
+        setFocus(*page, true); // TODO: check for multi insertion
+    }
+    else
+    {
+        // TODO:
+    }
+
+    return res;
+}
+
+void BodyView::backKeyHandler(MediaPageViewItem &item)
+{
+    item.destroy();
+}
+
+void BodyView::backKeyHandler(TextPageViewItem &item)
+{
+    if(m_LastTextCursorPos == 0)
+    {
+        MSG_LOG("Last text cursor position");
+        PageView &page = item.getParentPage();
+        if(PageViewItem *image = page.getItem(PageViewItem::ImageType))
+            image->setFocus(true);
+        else
+            removePage(page, true);
+    }
+}
+
+void BodyView::onDelete(TextPageViewItem &item)
+{
+    MSG_LOG("");
+    onContentChanged();
+}
+
+void BodyView::onCursorChanged(TextPageViewItem &item)
+{
+    m_LastTextCursorPos = item.getCursorPos();
+    MSG_LOG("Cursor pos: ", item.getCursorPos());
+}
+
+void BodyView::onFocused(TextPageViewItem &item)
+{
+    MSG_LOG("");
+    updateLastFocusedPage(item);
+    item.showInputPanel(true);
+}
+
+void BodyView::onUnfocused(TextPageViewItem &item)
+{
+    MSG_LOG("");
+    item.showInputPanel(false);
+}
+
+void BodyView::onPreeditChanged(TextPageViewItem &item)
+{
+    MSG_LOG("");
 }
 
-bool BodyView::getFocus() const
+void BodyView::onPress(TextPageViewItem &item)
 {
-    return getFocusedPage() != nullptr;
+    MSG_LOG("");
 }
 
+void BodyView::onClicked(TextPageViewItem &item)
+{
+    MSG_LOG("");
+    showInputPanel(item, true);
+}
 
+void BodyView::onMaxLengthReached(TextPageViewItem &item)
+{
+    MSG_LOG("");
+}
+
+void BodyView::onKeyDown(TextPageViewItem &item, Evas_Event_Key_Down &event)
+{
+    MSG_LOG("");
+    if(isBackKey(event.keyname))
+        backKeyHandler(item);
+}
+
+void BodyView::onKeyUp(TextPageViewItem &item, Evas_Event_Key_Up &event)
+{
+    MSG_LOG("");
+}
+
+void BodyView::onChanged(TextPageViewItem &item)
+{
+    MSG_LOG("");
+    onContentChanged();
+}
+
+void BodyView::onClicked(MediaPageViewItem &item)
+{
+    MSG_LOG("");
+}
+
+void BodyView::onPressed(MediaPageViewItem &item)
+{
+    MSG_LOG("");
+}
+
+void BodyView::onUnpressed(MediaPageViewItem &item)
+{
+    MSG_LOG("");
+}
+
+void BodyView::onFocused(MediaPageViewItem &item)
+{
+    MSG_LOG("");
+    updateLastFocusedPage(item);
+    item.highlight(true);
+    showInputPanel(item, true);
+}
+
+void BodyView::onUnfocused(MediaPageViewItem &item)
+{
+    MSG_LOG("");
+    item.highlight(false);
+    showInputPanel(item, false);
+}
+
+void BodyView::onKeyDown(MediaPageViewItem &item, Evas_Event_Key_Down &event)
+{
+    MSG_LOG("");
+    if(isBackKey(event.keyname))
+        backKeyHandler(item);
+}
+
+void BodyView::onKeyUp(MediaPageViewItem &item, Evas_Event_Key_Up &event)
+{
+    MSG_LOG("");
+}
+
+void BodyView::onDelete(MediaPageViewItem &item)
+{
+    onMediaRemoved(item.getResourcePath());
+    onContentChanged();
+}
index 0fb648a..08e9a26 100644 (file)
@@ -29,6 +29,7 @@ namespace
     const char *mediaImageLandscapeSig = "media.image.landscape";
     const char *mediaImageEqualSig = "media.image.equal";
     const char *imageLayout = "conv/body/media_image";
+    const char *imageContentPart = "swl.thumbnail";
 
     const int thumbOriginHeight = 75;
     const int thumbLandscapeWidth = 128;
@@ -40,12 +41,15 @@ namespace
 
 ImagePageViewItem::ImagePageViewItem(PageView &parent, const std::string &reourcePath)
     : MediaPageViewItem(parent, reourcePath)
+    , m_pImageLayout(nullptr)
 {
+    Evas_Object *imageLayout = createImageLayout(getMediaLayout());
     Evas_Object *rect = createRect(getMediaLayout());
-    Evas_Object *icon = createImageIconAndSetOrient(getButtonLayout());
+    Evas_Object *icon = createImageIconAndSetOrient(m_pImageLayout);
 
+    elm_object_part_content_set(m_pImageLayout, imageContentPart, icon);
     setRect(rect);
-    setButtonContent(icon);
+    setButtonContent(imageLayout);
 }
 
 ImagePageViewItem::~ImagePageViewItem()
@@ -63,12 +67,18 @@ bool ImagePageViewItem::isEmpty() const
     return getResourcePath().empty();
 }
 
+void ImagePageViewItem::highlight(bool value)
+{
+    const char *sig = value ? "focused" : "unfocused";
+    elm_object_signal_emit(m_pImageLayout, sig, "*");
+}
+
 Evas_Object *ImagePageViewItem::createImageLayout(Evas_Object *parent)
 {
-    Evas_Object *layout = elm_layout_add(parent);
-    elm_layout_file_set(layout, getEdjPath().c_str(), imageLayout);
-    evas_object_show(layout);
-    return layout;
+    m_pImageLayout = elm_layout_add(parent);
+    elm_layout_file_set(m_pImageLayout, getEdjPath().c_str(), imageLayout);
+    evas_object_show(m_pImageLayout);
+    return m_pImageLayout;
 }
 
 Evas_Object *ImagePageViewItem::createRect(Evas_Object *parent)
index 48bc638..99e7953 100644 (file)
@@ -48,13 +48,12 @@ MediaPageViewItem::~MediaPageViewItem()
 
 }
 
-void MediaPageViewItem::notifyListener(void *data, ListenerMethod method)
+template<class...Args>
+void MediaPageViewItem::notifyListener(void *data, void (IMediaPageViewItemListener::*method)(MediaPageViewItem &, Args...args), Args&&...args)
 {
     MediaPageViewItem *self = static_cast<MediaPageViewItem*>(data);
     if(self && self->m_pListener)
-    {
-        (self->m_pListener->*method)(*self);
-    }
+        (self->m_pListener->*method)(*self, args...);
 }
 
 Evas_Object *MediaPageViewItem::getMediaLayout() const
@@ -127,5 +126,22 @@ Evas_Object *MediaPageViewItem::createButton(Evas_Object *parent)
     {
         notifyListener(data, &IMediaPageViewItemListener::onUnpressed);
     }, this);
+
+    evas_object_event_callback_add(button, EVAS_CALLBACK_KEY_DOWN, [](void *data, Evas *e, Evas_Object *obj, void *event_info)
+    {
+        notifyListener(data, &IMediaPageViewItemListener::onKeyDown, *(Evas_Event_Key_Down*)event_info);
+    }, this);
+
+    evas_object_event_callback_add(button, EVAS_CALLBACK_KEY_UP, [](void *data, Evas *e, Evas_Object *obj, void *event_info)
+    {
+        notifyListener(data, &IMediaPageViewItemListener::onKeyUp, *(Evas_Event_Key_Up*)event_info);
+    }, this);
+
     return button;
 }
+
+void MediaPageViewItem::onBeforeDelete(View &view)
+{
+    if(m_pListener)
+        m_pListener->onDelete(*this);
+}
index 78baf03..a495b0f 100644 (file)
 #include "BodyView.h"
 #include "TextPageViewItem.h"
 #include "ImagePageViewItem.h"
+#include "Logger.h"
 
 #include <efl_extension.h>
+#include <assert.h>
 
 using namespace Msg;
 
@@ -68,29 +70,64 @@ void PageView::addItem(PageViewItem &item)
     if(it != m_PageItemMap.end())
     {
         if(it->second == &item)
-        {
             return;
-        }
         else
+            removeItem(*it->second);
+    }
+
+    /* Page items order:
+     * Image
+     * Text
+     * Audio
+     */
+    switch(item.getType())
+    {
+        case PageViewItem::TextType:
+        {
+            // Middle:
+            auto itEnd = m_PageItemMap.end();
+            auto it = m_PageItemMap.find(PageViewItem::ImageType);
+            if(it != itEnd)
+                elm_box_pack_after(m_pBox, item, *it->second);
+            else if((it = m_PageItemMap.find(PageViewItem::AudioType)) != itEnd)
+                elm_box_pack_before(m_pBox, item, *it->second);
+            else
+                elm_box_pack_start(m_pBox, item);
+            break;
+        }
+
+        case PageViewItem::ImageType:
+        {
+            // Top:
+            elm_box_pack_start(m_pBox, item);
+            break;
+        }
+
+        case PageViewItem::AudioType:
         {
-            removeItem(item.getType());
+            // Bottom:
+            elm_box_pack_end(m_pBox, item);
+            break;
         }
+
+        default:
+            assert(false);
+            return;
+            break;
     }
 
     item.expand();
     item.show();
-    elm_box_pack_end(m_pBox, item);
+
     m_PageItemMap[item.getType()] = &item;
 }
 
-void PageView::removeItem(PageViewItem::Type type)
+void PageView::removeItem(PageViewItem &item)
 {
-    auto it = m_PageItemMap.find(type);
+    auto it = m_PageItemMap.find(item.getType());
     if(it != m_PageItemMap.end())
-    {
-        it->second->destroy();
         m_PageItemMap.erase(it);
-    }
+    item.View::destroy();
 }
 
 PageViewItem *PageView::getItem(PageViewItem::Type type) const
@@ -102,20 +139,17 @@ PageViewItem *PageView::getItem(PageViewItem::Type type) const
 PageView::ItemList PageView::getItems() const
 {
     ItemList res;
-    Eina_List *list = elm_box_children_get(m_Body);
+    Eina_List *list = elm_box_children_get(m_pBox);
     Eina_List *l = nullptr;
     void *data = nullptr;
 
     EINA_LIST_FOREACH(list, l, data)
     {
-        PageViewItem *item = static_cast<PageViewItem*>(getSmartData((Evas_Object*)data));
-        if(item)
-        {
-            res.push_back(item);
-        }
+        PageViewItem *item = reinterpretCast<PageViewItem*>(data);
+        res.push_back(item);
     }
-
     eina_list_free(list);
+
     return res;
 }
 
@@ -131,6 +165,7 @@ Evas_Object *PageView::createLayout(Evas_Object *parent)
 Evas_Object *PageView::createBox(Evas_Object *parent)
 {
     m_pBox = elm_box_add(parent);
+    elm_box_homogeneous_set(m_pBox, false);
     evas_object_show(m_pBox);
     return m_pBox;
 }
index 0f7f880..87441e8 100644 (file)
@@ -17,6 +17,7 @@
 
 #include "PageViewItem.h"
 #include "Resource.h"
+#include "PageView.h"
 
 using namespace Msg;
 
@@ -31,6 +32,11 @@ PageViewItem::~PageViewItem()
 
 }
 
+void PageViewItem::destroy()
+{
+    m_Parent.removeItem(*this);
+}
+
 const std::string &PageViewItem::getEdjPath() const
 {
     static std::string path = ResourceUtils::getResourcePath(MSG_BODY_EDJ_PATH);
index df44ab5..137f800 100644 (file)
@@ -36,6 +36,14 @@ TextPageViewItem::~TextPageViewItem()
 
 }
 
+template<class...Args>
+void TextPageViewItem::notifyListener(void *data, void (ITextPageViewItemListener::*method)(TextPageViewItem &, Args...args), Args&&...args)
+{
+    TextPageViewItem *self = static_cast<TextPageViewItem*>(data);
+    if(self && self->m_pListener)
+        (self->m_pListener->*method)(*self, args...);
+}
+
 TextPageViewItem::Type TextPageViewItem::getType() const
 {
     return TextType;
@@ -52,13 +60,33 @@ void TextPageViewItem::setListener(ITextPageViewItemListener *l)
     m_pListener = l;
 }
 
-void TextPageViewItem::notifyListener(void *data, ListenerMethod method)
+int TextPageViewItem::getCursorPos() const
 {
-    TextPageViewItem *self = static_cast<TextPageViewItem*>(data);
-    if(self && self->m_pListener)
-    {
-        (self->m_pListener->*method)(*self);
-    }
+    return elm_entry_cursor_pos_get(getEo());
+}
+
+void TextPageViewItem::showInputPanel(bool show)
+{
+    if(show)
+        elm_entry_input_panel_show(m_pEntry);
+    else
+        elm_entry_input_panel_hide(m_pEntry);
+}
+
+void TextPageViewItem::setCursorPos(int pos)
+{
+
+    elm_entry_cursor_pos_set(getEo(), pos);
+}
+
+void TextPageViewItem::setEndCursorPos()
+{
+    elm_entry_cursor_end_set(getEo());
+}
+
+void TextPageViewItem::setBeginCursorPos()
+{
+    elm_entry_cursor_begin_set(getEo());
 }
 
 void TextPageViewItem::setGuideText(const TText &text)
@@ -66,12 +94,10 @@ void TextPageViewItem::setGuideText(const TText &text)
     setText(m_pEntry, text, "elm.guide");
     int cur = elm_entry_cursor_pos_get(m_pEntry);
     if(!cur)
-    {
         elm_entry_cursor_line_end_set(m_pEntry);
-    }
 }
 
-void TextPageViewItem::clearText()
+void TextPageViewItem::clear()
 {
     elm_object_text_set(m_pEntry, "");
 }
@@ -105,9 +131,10 @@ Evas_Object *TextPageViewItem::createEntry(Evas_Object *parent)
     elm_entry_autocapital_type_set(m_pEntry, ELM_AUTOCAPITAL_TYPE_SENTENCE);
     elm_entry_input_panel_return_key_type_set(m_pEntry, ELM_INPUT_PANEL_RETURN_KEY_TYPE_DEFAULT);
     elm_object_focus_allow_set(m_pEntry, true);
-    evas_object_show(m_pEntry);
+    elm_entry_input_panel_enabled_set(m_pEntry, EINA_FALSE);  // Keypad is manually controlled
     eext_entry_selection_back_event_allow_set(m_pEntry, EINA_TRUE);
     expand(m_pEntry);
+    evas_object_show(m_pEntry);
 
     evas_object_smart_callback_add(m_pEntry, "changed", [](void *data, Evas_Object *obj, void *event_info)
     {
@@ -129,11 +156,6 @@ Evas_Object *TextPageViewItem::createEntry(Evas_Object *parent)
         notifyListener(data, &ITextPageViewItemListener::onUnfocused);
     }, this);
 
-    evas_object_smart_callback_add(m_pEntry, "changed", [](void *data, Evas_Object *obj, void *event_info)
-    {
-        notifyListener(data, &ITextPageViewItemListener::onChanged);
-    }, this);
-
     evas_object_smart_callback_add(m_pEntry, "preedit,changed", [](void *data, Evas_Object *obj, void *event_info)
     {
         notifyListener(data, &ITextPageViewItemListener::onPreeditChanged);
@@ -156,13 +178,19 @@ Evas_Object *TextPageViewItem::createEntry(Evas_Object *parent)
 
     evas_object_event_callback_add(m_pEntry, EVAS_CALLBACK_KEY_DOWN, [](void *data, Evas *e, Evas_Object *obj, void *event_info)
     {
-        notifyListener(data, &ITextPageViewItemListener::onKeyDown);
+        notifyListener(data, &ITextPageViewItemListener::onKeyDown, *(Evas_Event_Key_Down*)event_info);
     }, this);
 
     evas_object_event_callback_add(m_pEntry, EVAS_CALLBACK_KEY_UP, [](void *data, Evas *e, Evas_Object *obj, void *event_info)
     {
-        notifyListener(data, &ITextPageViewItemListener::onKeyUp);
+        notifyListener(data, &ITextPageViewItemListener::onKeyUp, *(Evas_Event_Key_Up*)event_info);
     }, this);
 
     return m_pEntry;
 }
+
+void TextPageViewItem::onBeforeDelete(View &view)
+{
+    if(m_pListener)
+        m_pListener->onDelete(*this);
+}
index 0010d25..cd03b82 100644 (file)
@@ -25,6 +25,7 @@
 #include "Logger.h"
 #include "Box.h"
 #include "RecipientItem.h"
+#include "ResourceUtils.h"
 
 #include <Elementary.h>
 #include <sstream>
@@ -55,8 +56,6 @@ Conversation::Conversation(NaviFrameController &parent,ThreadId threadId)
 
 Conversation::~Conversation()
 {
-    saveDraftMsg();
-    getMsgEngine().getStorage().removeListener(*this);
 }
 
 void Conversation::create(Mode mode)
@@ -298,6 +297,8 @@ void Conversation::onButtonClicked(MessageInputPanel &obj, MessageInputPanel::Bu
     switch(id)
     {
         case MessageInputPanel::AddButtonId:
+            // TODO: Only for test, will be removed
+            m_pBody->addMedia(ResourceUtils::getResourcePath(TEST_IMG_PATH));
             break;
         case MessageInputPanel::SendButtonId:
             sendMessage();
@@ -354,6 +355,8 @@ void Conversation::onHwBackButtonClicked()
 {
     MSG_LOG("");
     getParent().pop();
+    getMsgEngine().getStorage().removeListener(*this);
+    saveDraftMsg();
 }
 
 void Conversation::onHwMoreButtonClicked()