TizenRefApp-5491 Implement MMS content viewer for bubble 74/58374/1
authorDmytro Dragan <dm.dragan@samsung.com>
Fri, 29 Jan 2016 21:04:07 +0000 (23:04 +0200)
committerDmytro Dragan <dm.dragan@samsung.com>
Fri, 29 Jan 2016 21:08:21 +0000 (23:08 +0200)
Change-Id: If388bbeff3e8f89f0310baa3c8d97daa36131339
Signed-off-by: Dmytro Dragan <dm.dragan@samsung.com>
res/edje/bubble_theme.edc
src/Common/Utils/inc/FileUtils.h
src/Common/Utils/src/FileUtils.cpp
src/Common/View/src/PopupManager.cpp
src/Conversation/ConvList/Controller/inc/ConvListItem.h
src/Conversation/ConvList/Controller/src/ConvListItem.cpp
src/Conversation/ConvList/View/inc/BubbleView.h
src/Conversation/ConvList/View/inc/ConvListViewItem.h
src/Conversation/ConvList/View/src/BubbleView.cpp
src/Conversation/ConvList/View/src/ConvListViewItem.cpp
src/Conversation/Main/Controller/src/Conversation.cpp

index d2d1ead..e0d13b9 100755 (executable)
@@ -181,7 +181,6 @@ group { name: "elm/genlist/item/sentbubble/default";
                 min: 0 BUBBLE_INFO_TEXT_HEIGHT;
                 max: -1 BUBBLE_INFO_TEXT_HEIGHT;
                 rel1.to_y: "info.status";
-                rel1.to_x: "info.pad";
                 rel1.relative: 0.0 1.0;
                 rel2.to_x: "info.thumb.pad";
                 rel2.relative: 0.0 1.0;
@@ -481,7 +480,7 @@ group { name: "elm/genlist/item/receivebubble/default";
                 align: 0.0 0.0;
                 rel1.to_x: "info.thumb.pad";
                 rel1.relative: 1.0 1.0;
-                rel2.to_x: "info.pad";
+                rel2.to_x: "";
                 rel2.relative: 1.0 0.0;
                 text.style: "entry_bubble_receive_textblock_style";
             }
index 91cffeb..b33e0d3 100755 (executable)
@@ -92,6 +92,13 @@ namespace Msg
              * @retval Returns true if all sucess, false otherwise
              */
             static bool remove(const std::string &path, bool removeCurrentDir = true);
+
+            /**
+             * @brief Read text file
+             * @param[in] file path name
+             * @retval Returns text content
+             */
+            static std::string readTextFile(const std::string &path);
     };
 }
 
index 48c522b..19cc4b6 100755 (executable)
@@ -25,6 +25,7 @@
 #include <dirent.h>
 #include <string.h>
 #include <ctype.h>
+#include <fstream>
 
 using namespace Msg;
 
@@ -183,3 +184,12 @@ bool FileUtils::remove(const std::string &path, bool removeCurrentDir)
 
     return res;
 }
+
+std::string FileUtils::readTextFile(const std::string &path)
+{
+    std::string text;
+    std::ifstream fs(path, std::ifstream::in | std::ifstream::binary);
+    if(fs.is_open())
+        fs >> text;
+    return text;
+}
index 9839802..32172e5 100644 (file)
@@ -83,12 +83,9 @@ void PopupManager::resetPopup()
 
 ContextPopup &PopupManager::getCtxPopup()
 {
-    if(!m_pCtxPopup)
-    {
-        m_pCtxPopup = new ContextPopup(*this);
-        eext_object_event_callback_add(*m_pCtxPopup, EEXT_CALLBACK_BACK, SMART_CALLBACK(PopupManager, onHwBackButtonCtxPopupClicked), this);
-    }
-
+    reset();
+    m_pCtxPopup = new ContextPopup(*this);
+    eext_object_event_callback_add(*m_pCtxPopup, EEXT_CALLBACK_BACK, SMART_CALLBACK(PopupManager, onHwBackButtonCtxPopupClicked), this);
     return *m_pCtxPopup;
 }
 
index 46f5353..e219b22 100644 (file)
@@ -47,7 +47,7 @@ namespace Msg
             void showPopup();
 
         protected:
-            virtual Evas_Object *getBubble();
+            virtual Evas_Object *getBubbleContent();
             virtual Evas_Object *getThumbnail();
             virtual std::string getText();
             virtual std::string getTime();
@@ -57,6 +57,7 @@ namespace Msg
 
         private:
             ConvListViewItem::ConvItemType getConvItemType(MsgConversationItem &item);
+            void prepareBubble(MsgConversationItem &item);
 
             // Create Popup when message is clicked
             void showMainCtxPopup();
@@ -77,8 +78,6 @@ namespace Msg
             void onFailedResendButtonClicked(Popup &popup, int buttonId);
             void onPopupDel(Evas_Object *popup, void *eventInfo);
 
-            void onBubbleResized(Evas_Object *obj, void *data);
-
         private:
             App &m_App;
             MsgId m_MsgId;
@@ -86,10 +85,7 @@ namespace Msg
             bool m_IsDraft;
             Message::Status m_Status;
             Message::Type m_Type;
-
-            //Fixme: temporary fix caused by genlist resize issue
-            Evas_Coord m_Width;
-            Evas_Coord m_Height;
+            BubbleEntity m_BubbleEntity;
     };
 }
 
index 9e53377..1d26d1c 100644 (file)
@@ -17,7 +17,6 @@
 
 #include "ConvListItem.h"
 #include "MsgConversationItem.h"
-#include "BubbleView.h"
 #include "ListView.h"
 #include "CallbackAssist.h"
 #include "ThumbnailMaker.h"
@@ -32,9 +31,9 @@ ConvListItem::ConvListItem(MsgConversationItem &item, App &app)
     , m_IsDraft(item.isDraft())
     , m_Status(item.getStatus())
     , m_Type(item.getType())
-    , m_Width(0)
-    , m_Height(0)
+    , m_BubbleEntity()
 {
+    prepareBubble(item);
 }
 
 ConvListItem::~ConvListItem()
@@ -58,50 +57,34 @@ ConvListViewItem::ConvItemType ConvListItem::getConvItemType(MsgConversationItem
     return type;
 }
 
-void ConvListItem::onBubbleResized(Evas_Object *obj, void *data)
+void ConvListItem::prepareBubble(MsgConversationItem &item)
 {
-    MSG_LOG("");
-    Evas_Coord w,h;
-    evas_object_geometry_get(obj, nullptr, nullptr, &w, &h);
-    if(m_Height < h || m_Width < w)
+    if(m_Type == Message::MT_SMS)
+    {
+        m_BubbleEntity.addPart(BubbleEntity::TextPart, item.getText());
+    }
+    else
     {
-        m_Width = w;
-        m_Height = h;
-        MSG_LOG("sizes: ", m_Height, " ",m_Width);
-        elm_genlist_item_update(this->getElmObjItem());
+        const MsgConvMediaList &list = item.getMediaList();
+        for(int i = 0; i < list.getLength(); i++)
+        {
+            std::string mime = list.at(i).getMime();
+            if(!list.at(i).getThumbPath().empty())
+                //msg service corrupts thumbnail's metadata, so it lost rotation. Use getPath instead getThumbPath until fix
+                m_BubbleEntity.addPart(BubbleEntity::ThumbnailPart, list.at(i).getPath());
+            else if(mime == "text/plain")
+                m_BubbleEntity.addPart(BubbleEntity::TextFilePart, list.at(i).getPath());
+            else if(mime != "application/smil")
+                m_BubbleEntity.addPart(BubbleEntity::TextPart, list.at(i).getName());
+        }
     }
 }
 
-Evas_Object *ConvListItem::getBubble()
+Evas_Object *ConvListItem::getBubbleContent()
 {
-    //TODO: implement getting of multimedia instead dummy content. Split to separate class (or update BubbleView)
-    //Only for demo
-    Evas_Object *box = elm_box_add(*getOwner());
-    evas_object_event_callback_add(box, EVAS_CALLBACK_RESIZE, EVAS_EVENT_CALLBACK(ConvListItem, onBubbleResized), this);
-    View::expand(box);
-
-    Evas_Object *label = elm_label_add(box);
-    elm_label_line_wrap_set(label, ELM_WRAP_MIXED);
-    elm_object_part_text_set(label, nullptr, m_MessageText.c_str());
-    View::expand(label);
-    evas_object_show(label);
-    elm_box_pack_end(box, label);
-
-    //Dummy image
-    Evas_Object *image = elm_image_add(box);
-    elm_image_file_set(image, PathUtils::getResourcePath(TEST_IMG_PATH).c_str(), nullptr);
-    evas_object_size_hint_min_set(image, 0, 150);
-    View::expand(image);
-    evas_object_show(image);
-    elm_box_pack_end(box, image);
-
-    MSG_LOG("sizes: ", m_Height, " ",m_Width);
-    if(m_Height > 0 && m_Width > 0)
-    {
-        evas_object_size_hint_min_set(box, m_Width, m_Height);
-        evas_object_size_hint_max_set(box, m_Width, m_Height);
-    }
-    return box;
+    BubbleView *bubble = new BubbleView(*getOwner());
+    bubble->fill(m_BubbleEntity);
+    return *bubble;
 }
 
 Evas_Object *ConvListItem::getThumbnail()
index be2ac27..b4256c6 100644 (file)
 #define BubbleView_h_
 
 #include "View.h"
+#include "MsgTypes.h"
 
 #include <string>
+#include <list>
 
 namespace Msg
 {
-    class BubbleView
-        : public View
+    class BubbleView;
+
+    class BubbleEntity
     {
+        friend class BubbleView;
+
         public:
-            enum Style
+            BubbleEntity();
+            ~BubbleEntity();
+            enum PartType
+            {
+                TextPart,   //raw text
+                TextFilePart,   //path to text file
+                ThumbnailPart   //path to thumbnail image
+            };
+
+            /**
+             * @brief Add new part to bubble entity
+             * @param[in] type Set which type is @value
+             * @param[in] value Resource path or raw text to display
+             */
+            void addPart(PartType type, const std::string &value);
+
+        private:
+            BubbleEntity(BubbleEntity&) = delete;
+            BubbleEntity &operator=(BubbleEntity&) = delete;
+
+            struct BubblePart
             {
-                Sent,
-                Received
+                PartType type;
+                std::string value;
             };
 
+        private:
+            std::list<BubblePart> m_Parts;
+    };
+
+    class BubbleView
+        : public View
+    {
         public:
-            //TODO: remove BubbleView from project and use Body's viewer instead
-            BubbleView(Evas_Object *parent, Style style);
+            BubbleView(Evas_Object *parent);
             virtual ~BubbleView();
 
-            void setText(const std::string &text);
-            void setTime(const std::string &time);
+            /**
+             * @brief Draw content from @entity
+             * @param[in] entity Filled list of contents
+             */
+            void fill(const BubbleEntity &entity);
 
         private:
             void create(Evas_Object *parent);
-            const char *getStyle() const;
-
-        private:
-            Style m_Style;
+            Evas_Object *createTextView(const std::string &text);
+            Evas_Object *createTextFileView(const std::string &path);
+            Evas_Object *createThumbView(const std::string &path);
     };
 }
 
index ac53d80..a91bc79 100644 (file)
@@ -38,7 +38,7 @@ namespace Msg
             virtual ~ConvListViewItem();
 
         protected:
-            virtual Evas_Object *getBubble() = 0;
+            virtual Evas_Object *getBubbleContent() = 0;
             virtual Evas_Object *getThumbnail() = 0;
             virtual std::string getText() = 0;
             virtual std::string getTime() = 0;
@@ -47,10 +47,16 @@ namespace Msg
             virtual void onFailedButtonClicked(Evas_Object *obj, void *event_info) = 0;
 
         private:
+            void onBubbleResized(Evas_Object *obj, void *data);
             Evas_Object *getButton(bool isEnabled, ConvItemType type);
             virtual std::string getText(ListItem &item, const char *part);
             virtual Evas_Object *getContent(ListItem &item, const char *part);
             virtual const char *getCheckPart(ListItem &item);
+
+        private:
+            //Fixme: temporary fix caused by genlist resize issue
+            Evas_Coord m_BubbleWidth;
+            Evas_Coord m_BubbleHeight;
     };
 }
 
index a222262..bf16b0b 100644 (file)
  */
 
 #include "BubbleView.h"
+#include "FileUtils.h"
 
 #include <Elementary.h>
 
 using namespace Msg;
 
-const char *bubbleSentStyle = "sentmessage/custom/sent_style_01";
-const char *bubbleRecvStyle = "readmessage/custom/recv_style_01";
+namespace
+{
+    const int verticalBoxPads = 10;
+    const int horizontalBoxPads = 0;
+    const int maxWidth = 220; //Fixme: set to 340 when apply base_scale: 2.6
+    const char *textStyle = "DEFAULT='font=Tizen:style=Regular font_size=30 wrap=mixed text_class=label'";
+}
 
-BubbleView::BubbleView(Evas_Object *parent, Style style)
-    : m_Style(style)
+BubbleView::BubbleView(Evas_Object *parent)
 {
     create(parent);
 }
@@ -35,61 +40,98 @@ BubbleView::~BubbleView()
 
 }
 
-const char *BubbleView::getStyle() const
+void BubbleView::create(Evas_Object *parent)
 {
-    switch(m_Style)
-    {
-        case Sent:
-            return bubbleSentStyle;
-            break;
+    Evas_Object *box = elm_box_add(parent);
+    View::expand(box);
+    elm_box_padding_set(box, (int)ELM_SCALE_SIZE(horizontalBoxPads), (int)ELM_SCALE_SIZE(verticalBoxPads));
 
-        case Received:
-            return bubbleRecvStyle;
-            break;
+    setEo(box);
+}
 
-        default:
-            break;
+void BubbleView::fill(const BubbleEntity &entity)
+{
+    for(const BubbleEntity::BubblePart &part : entity.m_Parts)
+    {
+        switch (part.type)
+        {
+            case BubbleEntity::TextPart:
+                elm_box_pack_end(*this, createTextView(part.value));
+                break;
+            case BubbleEntity::TextFilePart:
+                elm_box_pack_end(*this, createTextFileView(part.value));
+                break;
+            case BubbleEntity::ThumbnailPart:
+                elm_box_pack_end(*this, createThumbView(part.value));
+                break;
+            default:
+                break;
+        }
     }
-
-    return nullptr;
 }
 
-void BubbleView::create(Evas_Object *parent)
+Evas_Object *BubbleView::createTextView(const std::string &text)
 {
-    Evas_Object *label = elm_label_add(parent);
-    setEo(label);
-    evas_object_show(label);
-    elm_label_line_wrap_set(label, ELM_WRAP_MIXED);
-    elm_object_focus_allow_set(label, true);
-    elm_object_tree_focus_allow_set(label, true);
-    elm_object_style_set(label, getStyle());
-    evas_object_color_set(label, rand() % 230, rand() % 230, rand() % 230, 190);
+    //TODO: apply to label the same text style as to textblock (figure out how-to)
+    Evas_Coord ww, hh;
+    Evas_Object *label = elm_label_add(*this);
+    Evas_Object *textBlock = evas_object_textblock_add(evas_object_evas_get(label));
+    Evas_Textblock_Style *ts = evas_textblock_style_new();
 
-   // edje_object_signal_emit(elm_layout_edje_get(label), "elm,state,text,status,enabled", "");
-   // edje_object_signal_emit(elm_layout_edje_get(label), "elm,state,effect,show", "");
-   // edje_object_signal_emit(elm_layout_edje_get(label), "elm,state,contents,enabled", "");
+    evas_textblock_style_set(ts, textStyle);
+    evas_object_textblock_style_set(textBlock, ts);
+    evas_object_textblock_text_markup_set(textBlock, text.c_str());
+    evas_object_textblock_size_native_get(textBlock, &ww, &hh);
 
-    evas_object_size_hint_weight_set(label, EVAS_HINT_EXPAND, 0);
-    evas_object_size_hint_align_set(label, EVAS_HINT_FILL, EVAS_HINT_FILL);
+    evas_textblock_style_free(ts);
+    evas_object_del(textBlock);
 
-    // Demo Colors
-    if(m_Style == Received)
-    {
-        evas_object_color_set(label, rand() % 230, rand() % 230, 255, 190);
-    }
+    int wrapWidth = ww > maxWidth ? (int)ELM_SCALE_SIZE(maxWidth) : (int)ELM_SCALE_SIZE(ww);
+    elm_label_line_wrap_set(label, ELM_WRAP_MIXED);
+    elm_label_wrap_width_set(label, wrapWidth);
+    elm_object_part_text_set(label, nullptr, text.c_str());
+    evas_object_show(label);
+    evas_object_size_hint_align_set(label, 0.0, EVAS_HINT_FILL);
+    return label;
+}
+
+Evas_Object *BubbleView::createTextFileView(const std::string &path)
+{
+    std::string text = FileUtils::readTextFile(path);
+    if(text.empty())
+        return nullptr;
     else
+        return createTextView(text);
+}
+
+Evas_Object *BubbleView::createThumbView(const std::string &path)
+{
+    Evas_Object *image = elm_image_add(*this);
+    elm_image_aspect_fixed_set(image, false);
+    elm_image_file_set(image, path.c_str(), nullptr);
+    int imageWidth = 0;
+    int imageHeight = 0;
+    elm_image_object_size_get(image, &imageWidth, &imageHeight);
+    if(imageWidth > maxWidth)
     {
-        evas_object_color_set(label, 255, rand() % 230, rand() % 230, 190);
+        double scale = maxWidth/(double)imageWidth;
+        imageWidth *= scale;
+        imageHeight *= scale;
     }
-    //Demo colors
+    evas_object_size_hint_min_set(image, imageWidth, imageHeight);
+    evas_object_show(image);
+    return image;
+}
+
+BubbleEntity::BubbleEntity()
+{
 }
 
-void BubbleView::setText(const std::string &text)
+BubbleEntity::~BubbleEntity()
 {
-    elm_object_text_set(getEo(), text.c_str());
 }
 
-void BubbleView::setTime(const std::string &time)
+void BubbleEntity::addPart(PartType type, const std::string &value)
 {
-    elm_object_part_text_set(getEo(), "elm.text.time", time.c_str());
+    m_Parts.push_back(BubblePart{type, value});
 }
index 1d337b3..8043974 100644 (file)
@@ -42,6 +42,8 @@ namespace
 
 ConvListViewItem::ConvListViewItem(ConvItemType type)
     : ListItem()
+    , m_BubbleWidth(0)
+    , m_BubbleHeight(0)
 {
     switch (type)
     {
@@ -80,15 +82,32 @@ std::string ConvListViewItem::getText(ListItem &item, const char *part)
 Evas_Object *ConvListViewItem::getContent(ListItem &item, const char *part)
 {
     if(!strcmp(part, bubbleContentPart))
-        return getBubble();
+    {
+        Evas_Object *bubble = getBubbleContent();
+        evas_object_event_callback_add(bubble, EVAS_CALLBACK_RESIZE, EVAS_EVENT_CALLBACK(ConvListViewItem, onBubbleResized), this);
+        if(m_BubbleHeight > 0 && m_BubbleWidth > 0)
+        {
+            evas_object_size_hint_min_set(bubble, m_BubbleWidth, m_BubbleHeight);
+            evas_object_size_hint_max_set(bubble, m_BubbleWidth, m_BubbleHeight);
+        }
+        return bubble;
+    }
     else if(!strcmp(part, thumbContentPart))
+    {
         return getThumbnail();
+    }
     else if(!strcmp(part, draftButtonPart))
+    {
         return getButton(!getOwner()->getCheckMode(), Draft);
+    }
     else if(!strcmp(part, failedButtonPart))
+    {
         return getButton(!getOwner()->getCheckMode(), Failed);
+    }
     else
+    {
         return nullptr;
+    }
 }
 
 const char *ConvListViewItem::getCheckPart(ListItem &item)
@@ -121,3 +140,16 @@ Evas_Object *ConvListViewItem::getButton(bool isEnabled, ConvItemType type)
     }
     return button;
 }
+
+void ConvListViewItem::onBubbleResized(Evas_Object *obj, void *data)
+{
+    MSG_LOG("");
+    Evas_Coord w,h;
+    evas_object_geometry_get(obj, nullptr, nullptr, &w, &h);
+    if(m_BubbleHeight < h || m_BubbleWidth < w)
+    {
+        m_BubbleWidth = w;
+        m_BubbleHeight = h;
+        elm_genlist_item_update(this->getElmObjItem());
+    }
+}
index b01a09e..421ecba 100644 (file)
@@ -358,7 +358,7 @@ void Conversation::sendMessage()
         return;
     }
 
-    auto msg = getMsgEngine().getComposer().createSms();
+    auto msg = getMsgEngine().getComposer().createMessage(m_IsMms ? Message::MT_MMS : Message::MT_SMS);
     fillMessage(*msg);
     MSG_LOG("m_ThreadId = ", m_ThreadId);
     MsgTransport::SendResult sendRes = getMsgEngine().getTransport().sendMessage(*msg, &m_ThreadId);