#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"
#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
{
public:
View();
- virtual ~View();
- virtual void destroy();
+ inline void destroy();
inline operator Evas_Object *() const;
inline Evas_Object *getEo() const;
inline void show();
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;
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);
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);
return m_pEo;
}
+ inline void View::destroy()
+ {
+ evas_object_del(m_pEo);
+ }
+
inline void View::show()
{
evas_object_show(m_pEo);
{
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_ */
ViewItem();
ViewItem(ViewItem&) = delete;
ViewItem& operator=(const ViewItem&) = delete;
- virtual ~ViewItem();
inline operator Elm_Object_Item *() const;
virtual void destroy();
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);
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);
}
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)
#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
{
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;
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
virtual ~IBodyListener() {}
virtual void onChanged(Body &body) {};
- virtual void onFoucused(Body &body) {};
- virtual void onUnfoucused(Body &body) {};
};
}
#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;
}
}
: 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;
}
{
PageViewItem::Type itemType = pageItem->getType();
if(itemType != PageViewItem::TextType)
- {
return true;
- }
}
return false;
}
BodySmsSize Body::getSmsSize() const
{
BodySmsSize size = {};
- TextPageViewItem *textItem = getTextItem(m_pDefaultPage);
+ TextPageViewItem *textItem = getTextItem(getDefaultPage());
if(textItem)
{
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)
void Body::read(MessageSMS &msg)
{
- TextPageViewItem *textItem = getTextItem(m_pDefaultPage);
+ TextPageViewItem *textItem = getTextItem(getDefaultPage());
assert(textItem);
if(textItem)
{
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());
}
}
-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
+ );
+ }
}
#include "View.h"
#include "BodyViewItem.h"
+#include "MediaPageViewItem.h"
+#include "TextPageViewItem.h"
+#include "ImagePageViewItem.h"
#include <vector>
{
class PageView;
class BodyAttachmentView;
+ class PageSeparator;
typedef std::vector<PageView*> PageViewCollection;
typedef std::vector<BodyAttachmentView*> BodyAttachmentCollection;
class BodyView
: public View
+ , private ITextPageViewItemListener
+ , private IMediaPageViewItemListener
{
friend class PageView;
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;
};
}
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;
};
}
void setListener(IMediaPageViewItemListener *l);
const std::string &getResourcePath() const;
+ virtual void highlight(bool value) = 0;
+
protected:
Evas_Object *getMediaLayout() const;
Evas_Object *getButtonLayout() const;
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;
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) {};
};
}
namespace Msg
{
class BodyView;
-
class PageView
: public BodyViewItem
{
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;
const PageView &getParentPage() const;
PageView &getParentPage();
+ void destroy();
protected:
const std::string &getEdjPath() const;
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;
{
public:
virtual ~ITextPageViewItemListener() {}
+ virtual void onDelete(TextPageViewItem &item) {};
virtual void onCursorChanged(TextPageViewItem &obj) {};
virtual void onFocused(TextPageViewItem &obj) {};
virtual void onUnfocused(TextPageViewItem &obj) {};
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) {};
};
}
#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);
}
}
-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)
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();
}
item.destroy();
}
+int BodyView::getPageCount() const
+{
+ return getPages().size();
+}
+
PageViewCollection BodyView::getPages() const
{
return getItems<PageView>();
for(BodyViewItem *item : all)
{
if(T *itemT = dynamic_cast<T*>(item))
- {
res.push_back(itemT);
- }
}
-
return res;
}
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);
}
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();
+}
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;
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()
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)
}
-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
{
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);
+}
#include "BodyView.h"
#include "TextPageViewItem.h"
#include "ImagePageViewItem.h"
+#include "Logger.h"
#include <efl_extension.h>
+#include <assert.h>
using namespace Msg;
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
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;
}
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;
}
#include "PageViewItem.h"
#include "Resource.h"
+#include "PageView.h"
using namespace Msg;
}
+void PageViewItem::destroy()
+{
+ m_Parent.removeItem(*this);
+}
+
const std::string &PageViewItem::getEdjPath() const
{
static std::string path = ResourceUtils::getResourcePath(MSG_BODY_EDJ_PATH);
}
+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;
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)
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, "");
}
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)
{
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);
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);
+}
#include "Logger.h"
#include "Box.h"
#include "RecipientItem.h"
+#include "ResourceUtils.h"
#include <Elementary.h>
#include <sstream>
Conversation::~Conversation()
{
- saveDraftMsg();
- getMsgEngine().getStorage().removeListener(*this);
}
void Conversation::create(Mode mode)
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();
{
MSG_LOG("");
getParent().pop();
+ getMsgEngine().getStorage().removeListener(*this);
+ saveDraftMsg();
}
void Conversation::onHwMoreButtonClicked()