TizenRefApp-8408 Implement contact selecter 83/125983/2
authorDenis Dolzhenko <d.dolzhenko@samsung.com>
Wed, 19 Apr 2017 13:35:55 +0000 (16:35 +0300)
committerDenis Dolzhenko <d.dolzhenko@samsung.com>
Thu, 20 Apr 2017 08:10:35 +0000 (01:10 -0700)
Change-Id: I6567fa8b413354566c70bfb17366c53775dfa3b4
Signed-off-by: Denis Dolzhenko <d.dolzhenko@samsung.com>
17 files changed:
src/Common/Controller/inc/InputFrame.h
src/Common/Controller/src/InputFrame.cpp
src/Common/Recipient/inc/Recipient.h
src/Common/Recipient/src/Recipient.cpp
src/Common/View/inc/LineListViewItem.h
src/Common/View/src/LineListViewItem.cpp
src/Common/View/src/ListView.cpp
src/Common/View/src/SearchBar.cpp
src/Composer/Controller/inc/ContactFrame.h
src/Composer/Controller/inc/ContactListItem.h [new file with mode: 0644]
src/Composer/Controller/inc/RecipInputFrame.h
src/Composer/Controller/src/ContactFrame.cpp
src/Composer/Controller/src/ContactListItem.cpp [new file with mode: 0644]
src/Composer/Controller/src/RecipInputFrame.cpp
src/Composer/View/inc/ContactListViewItem.h
src/Composer/View/src/ContactListViewItem.cpp
src/Conversation/View/src/BubbleImageViewItem.cpp

index 2d8bd3207840dc26068f3b025fe06a5a11739fe1..fb9879a99b3f35a19d406f1afdea362b51793df8 100644 (file)
@@ -35,6 +35,8 @@ namespace Msg {
             InputLayout &getLayout();
 
         protected:
+            virtual void onInputPanelHide() {};
+
             // NaviFrameItem
             void onAttached(ViewItem &item) override;
 
index 06609e941337c3bd2534f8e6cad706c19ddaba63..c7770c1a48517bdf5a7e3f6a0f50ad840ef81884 100644 (file)
@@ -15,7 +15,6 @@
  */
 
 #include "InputFrame.h"
-#include "PopupManager.h"
 
 using namespace Msg;
 
@@ -100,9 +99,7 @@ void InputFrame::onInputPanelEvent(Ecore_IMF_Context *ctx, int value)
 {
     switch (value) {
     case ECORE_IMF_INPUT_PANEL_STATE_HIDE: {
-            BasePopup *popup = App::getInst().getPopupManager().getTop();
-            if (!isPause() && !(popup && popup->isVisible()))
-                pop();
+        onInputPanelHide();
             break;
         }
     }
index 08e36708318569ff56be4e25c81bc396ae53a839..47fe9ebef8ef715e1934b000b5199e23ae920501 100644 (file)
 #include "MsgTypes.h"
 
 #include <string>
+#include <list>
 
 namespace Msg {
     class Recipient {
 
         public:
+            Recipient(std::string address, std::string dispName);
             Recipient();
             ~Recipient();
 
@@ -42,6 +44,14 @@ namespace Msg {
              */
             static Recipient searchFirstRecip(const std::string &searchWord);
 
+
+            /**
+             * @brief       Search all recipient in ContactPersonNumber and ContactPersonPhoneLog based on a given search word.
+             * @param       searchWord - search keyword
+             * @return      list of recipients
+             */
+            static std::list<Recipient> searchRecips(const std::string &searchWord);
+
             /**
              * @brief       Get recipient by ThreadId
              * @param       id valid thread id
index db27ca37bb48648ff6ca9116f60dfa92a9a9b3ee..77cd2d68060dbd872585865277642c08bcc074af 100644 (file)
@@ -27,14 +27,20 @@ using namespace Msg;
 
 namespace {
     template<typename ContactRec>
-    std::shared_ptr<ContactRec> searchContact(const std::string &searchWord)
+    bool isValid(const ContactRec &rec)
+    {
+        return rec.isValid() && MsgUtils::isValidAddress(rec.getAddress());
+    }
+
+    template<typename ContactRec>
+    std::shared_ptr<ContactRec> searchFirstContact(const std::string &searchWord)
     {
         if (!searchWord.empty()) {
             auto list = App::getInst().getContactManager().search<ContactRec>(searchWord);
             if (list) {
                 do {
                     auto &rec = list->get();
-                    if (rec.isValid() && MsgUtils::isValidAddress(rec.getAddress())) {
+                    if (isValid(rec)) {
                         return std::static_pointer_cast<ContactRec>(rec.clone());
                     } else {
                         MSG_LOG("Skip invalid contact: ", rec.getAddress());
@@ -44,12 +50,38 @@ namespace {
         }
         return {};
     }
+
+    template<typename ContactRec>
+    std::list<Recipient> searchContacts(const std::string &searchWord)
+    {
+        std::list<Recipient> results;
+        if (!searchWord.empty()) {
+            auto list = App::getInst().getContactManager().search<ContactRec>(searchWord);
+            if (list) {
+                do {
+                    auto &rec = list->get();
+                    if (isValid(rec)) {
+                        results.emplace_back(Recipient(rec.getAddress(), rec.getDispName()));
+                    } else {
+                        MSG_LOG("Skip invalid contact: ", rec.getAddress());
+                    }
+                } while (list->next());
+             }
+        }
+        return results;
+    }
 }
 
 Recipient::Recipient()
 {
 }
 
+Recipient::Recipient(std::string address, std::string dispName)
+    : m_Address(address)
+    , m_DispName(dispName)
+{
+}
+
 Recipient::~Recipient()
 {
 }
@@ -89,13 +121,13 @@ Recipient Recipient::searchFirstRecip(const std::string &searchWord)
 {
     Recipient res;
 
-    auto numberRef = searchContact<ContactPersonNumber>(searchWord);
+    auto numberRef = searchFirstContact<ContactPersonNumber>(searchWord);
 
     if (numberRef) {
         res.m_Address = numberRef->getAddress();
         res.m_DispName = numberRef->getDispName();
     } else {
-        auto phoneLogRef = searchContact<ContactPersonPhoneLog>(searchWord);
+        auto phoneLogRef = searchFirstContact<ContactPersonPhoneLog>(searchWord);
         if (phoneLogRef)
             res.m_Address = phoneLogRef->getAddress();
     }
@@ -106,6 +138,14 @@ Recipient Recipient::searchFirstRecip(const std::string &searchWord)
     return res;
 }
 
+std::list<Recipient> Recipient::searchRecips(const std::string &searchWord)
+{
+    std::list<Recipient> result;
+    result = searchContacts<ContactPersonNumber>(searchWord);
+    result.splice(result.end(), searchContacts<ContactPersonPhoneLog>(searchWord));
+    return result;
+}
+
 Recipient Recipient::getByThreadId(ThreadId id)
 {
     Recipient res;
index 3f337f75c27e7b6b292d61fa3cf4e89773d0dd87..bcc61ba80ab961035770ec2ba925a188a0f75298 100644 (file)
@@ -27,6 +27,8 @@ namespace Msg {
             LineListViewItem(std::string titleText = std::string());
             virtual ~LineListViewItem();
 
+            void setText(std::string text);
+
         protected:
             void onAttached(ViewItem &item) override;
 
index fc337e7878ac40a98fe4aaa8d24a2770a5a1d41b..58392214c7aaffe76c5d488bbd991e0e24ebf7b4 100644 (file)
@@ -33,6 +33,11 @@ void LineListViewItem::onAttached(ViewItem &item)
     setSelectable(false);
 }
 
+void LineListViewItem::setText(std::string text)
+{
+    m_TitleText = std::move(text);
+}
+
 std::string LineListViewItem::getText(ListItem &item, const char *part)
 {
     if (!strcmp(part, "elm.text"))
index 88cacb1bcf980687d2ad1ca449650ce8fcc03c86..fea6e6f6fd26f8e0521d4ccc27fc68a24a84906e 100644 (file)
@@ -66,6 +66,7 @@ void ListView::createListView(Evas_Object *parent, Eext_Circle_Surface *parentCi
 {
     setEo(elm_genlist_add(parent));
     setMode(ELM_LIST_COMPRESS);
+    setMultiSelection(false);
     addSmartCb("realized", ListView::on_realized_cb, this);
     addSmartCb("unrealized", ListView::on_unrealized_cb, this);
     addSmartCb("longpressed", ListView::on_longpressed_cb, this);
index 74cf15422dc523d696ce2def5563103e1ffacd90..9d22532e41a95fcbff383f36b494dda38204d0d9 100644 (file)
@@ -26,6 +26,7 @@ SearchBar::SearchBar(Evas_Object *parent)
     Evas_Object *button = addIconButton(getEo(), "prediction_icon", makeCbFirst(&SearchBar::onButtonClicked), this);
     setContent(button, "swl.button");
     addSignalCb("mouse,clicked,*", "elm.text", makeCbFirst(&SearchBar::onTextClicked), this);
+    elm_object_tree_focus_allow_set(getEo(), false);
 }
 
 void SearchBar::setListener(ISearchBarListener *l)
index ff4dbb6ffff1a73b24eaf6e0225664663807e483..4887e9106210c4119a7d571083b99f90096491d8 100644 (file)
 
 #include "FrameController.h"
 #include "ListView.h"
-#include "ContactAddress.h"
+#include "LineListViewItem.h"
+#include "Recipient.h"
 
 namespace Msg {
 
     class IContactFrameListener;
+    class PaddingListViewItem;
 
     class ContactFrame
         : public FrameController
         , private IListViewListener {
 
         public:
-            ContactFrame(NaviFrameController &parent);
+            ContactFrame(NaviFrameController &parent, std::list<Recipient> recips, std::string searchWord);
             virtual ~ContactFrame();
 
             void setListener(IContactFrameListener *l);
@@ -47,16 +49,22 @@ namespace Msg {
 
         private:
             void prepareList();
+            void updateList();
+            void updateCounterItem();
+            void fillList(std::list<Recipient> recips);
 
         private:
             ListView *m_pList;
             IContactFrameListener *m_pListener;
+            std::string m_SearchWord;
+            LineListViewItem *m_pInfoItem;
+            int m_ItemsCount;
     };
 
     class IContactFrameListener {
         public:
             virtual ~IContactFrameListener() {}
-            virtual void onContactSelected(ContactAddressRef &contact) {};
+            virtual void onContactSelected(ContactFrame &sender, const Recipient &recip) {};
     };
 }
 
diff --git a/src/Composer/Controller/inc/ContactListItem.h b/src/Composer/Controller/inc/ContactListItem.h
new file mode 100644 (file)
index 0000000..fd44c7b
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2016 Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.1 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ContactListItem_h_
+#define ContactListItem_h_
+
+#include "ContactListViewItem.h"
+#include "Recipient.h"
+
+namespace Msg {
+    class ContactListItem
+        : public ContactListViewItem {
+
+        public:
+            ContactListItem(Recipient recip, const std::string &searchWord);
+            virtual ~ContactListItem();
+
+            const Recipient &getRecip() const;
+
+        private:
+            std::string getSubText() override;
+            std::string getMainText() override;
+
+        private:
+            Recipient m_Recip;
+            std::string m_DispName;
+            std::string m_Address;
+    };
+}
+
+#endif // ContactListItem_h_
index b49bd1dbdccba03f25717c8fea27c7bceeb782ec..5841b2247b027c41155dfe8b2d6c9f53ad3f3c84 100644 (file)
 #include "InputFrame.h"
 #include "SearchBar.h"
 #include "Recipient.h"
+#include "ContactFrame.h"
 
 namespace Msg {
 
     class RecipInputFrame
         : public InputFrame
-        , private ISearchBarListener {
+        , private ISearchBarListener
+        , private IContactFrameListener{
 
         public:
             RecipInputFrame(NaviFrameController &parent, const Recipient &recip);
@@ -34,9 +36,10 @@ namespace Msg {
             const Recipient &getRecip() const;
 
         private:
-            // NaviFrameItem:
+            // NaviFrame:
             void onAttached(ViewItem &item) override;
-            bool onRequestPop() override;
+            void onInputPanelHide() override;
+
 
             // Entry:
             void onEntryChanged(Evas_Object *obj, void *event_info);
@@ -47,6 +50,9 @@ namespace Msg {
             void onButtonClicked(SearchBar &obj) override;
             void onTextClicked(SearchBar &obj) override;
 
+            // ISearchBarListener:
+            void onContactSelected(ContactFrame &sender, const Recipient &recip) override;
+
             // Timer:
             Eina_Bool onSearchTimerTick();
 
@@ -58,11 +64,13 @@ namespace Msg {
             void reqestSearch();
             void cancelSearch();
             void searchButtonHandler();
+            void navigateToContactFrame(std::list<Recipient> recips, std::string searchWord);
 
         private:
             SearchBar *m_pSearchBar;
             Ecore_Timer *m_pTimer;
             Recipient m_Recip;
+            bool m_IsClosed;
     };
 }
 
index ba94997050ab4e87d853355321adbd87330a4f2b..5d53ac72b5d2ee65b843b94c63748296dd96b2b0 100644 (file)
  */
 
 #include "ContactFrame.h"
+#include "PaddingListViewItem.h"
+#include "LineListViewItem.h"
+#include "ContactListItem.h"
+#include "App.h"
+#include "Window.h"
 
 using namespace Msg;
 
-ContactFrame::ContactFrame(NaviFrameController &parent)
+ContactFrame::ContactFrame(NaviFrameController &parent, std::list<Recipient> recips, std::string searchWord)
     : FrameController(parent)
     , m_pList(nullptr)
     , m_pListener(nullptr)
+    , m_SearchWord(std::move(searchWord))
+    , m_pInfoItem(nullptr)
+    , m_ItemsCount(0)
 {
     MSG_LOG("");
     prepareList();
+    fillList(std::move(recips));
 }
 
 ContactFrame::~ContactFrame()
@@ -40,14 +49,46 @@ void ContactFrame::setListener(IContactFrameListener *l)
 void ContactFrame::prepareList()
 {
     if (!m_pList) {
-        m_pList = new ListView(getParent());
+        m_pList = new ListView(getParent(), App::getInst().getWindow().getCircleSurface());
         m_pList->addHwButtonEvent(EEXT_CALLBACK_BACK, makeCbFirst(&ContactFrame::onHwBackButtonPreessed), this);
         m_pList->setHomogeneous(false);
-        m_pList->setMultiSelection(false);
         m_pList->setListener(this);
     }
 }
 
+void ContactFrame::updateList()
+{
+
+}
+
+void ContactFrame::updateCounterItem()
+{
+    if (m_pInfoItem)
+        m_pInfoItem->setText(msgArgs("WDS_PB_HEADER_PD_RESULTS_FOUND_ABB", m_ItemsCount));
+}
+
+void ContactFrame::fillList(std::list<Recipient> recips)
+{
+    m_ItemsCount = recips.size();
+
+    m_pList->clear();
+
+    // Top padding:
+    m_pList->appendItem(*new PaddingListViewItem);
+
+    m_pInfoItem = new LineListViewItem;
+    updateCounterItem();
+    m_pList->appendItem(*m_pInfoItem);
+
+    for (Recipient recip : recips) {
+        auto *item = new ContactListItem(std::move(recip), m_SearchWord);
+        m_pList->appendItem(*item);
+    }
+
+    // Bottom padding:
+    m_pList->appendItem(*new PaddingListViewItem);
+}
+
 void ContactFrame::onAttached(ViewItem &item)
 {
     MSG_LOG("");
@@ -58,8 +99,12 @@ void ContactFrame::onAttached(ViewItem &item)
 void ContactFrame::onListItemSelected(ListItem &listItem)
 {
     MSG_LOG("");
-    if (m_pListener) {
-        // TODO: impl.
+
+    auto *item = dynamic_cast<ContactListItem*>(&listItem);
+    if (item) {
+        if (m_pListener)
+            m_pListener->onContactSelected(*this, item->getRecip());
+        pop();
     }
 }
 
diff --git a/src/Composer/Controller/src/ContactListItem.cpp b/src/Composer/Controller/src/ContactListItem.cpp
new file mode 100644 (file)
index 0000000..7e36bce
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2016 Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.1 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ContactListItem.h"
+#include "TextDecorator.h"
+
+using namespace Msg;
+
+ContactListItem::ContactListItem(Recipient recip, const std::string &searchWord)
+    : m_Recip(std::move(recip))
+{
+    ListItemStyleRef style = recip.getDispName().empty() ? text1 : text2;
+    setStyle(style);
+
+    m_DispName = TextDecorator::highlightKeyword(recip.getDispName(), searchWord);
+    m_Address = TextDecorator::highlightKeyword(recip.getAddress(), searchWord);
+}
+
+ContactListItem::~ContactListItem()
+{
+}
+
+const Recipient &ContactListItem::getRecip() const
+{
+    return m_Recip;
+}
+
+std::string ContactListItem::getSubText()
+{
+    return m_Address;
+}
+
+std::string ContactListItem::getMainText()
+{
+    return m_DispName;
+}
index 270911b0b0e257e05c1d37889f32f710d0587bcc..2464ab558408b5864827bf6a40ae1b2391dedf3c 100644 (file)
@@ -20,6 +20,8 @@
 #include "TextDecorator.h"
 #include "MsgUtils.h"
 #include "ToastPopup.h"
+#include "PopupManager.h"
+#include "ContactFrame.h"
 
 #include <Eina.h>
 
@@ -54,6 +56,7 @@ RecipInputFrame::RecipInputFrame(NaviFrameController &parent, const Recipient &r
     , m_pSearchBar(nullptr)
     , m_pTimer(nullptr)
     , m_Recip(recip)
+    , m_IsClosed(false)
 {
     prepareEntry(m_Recip.getAddress());
 }
@@ -72,6 +75,7 @@ void RecipInputFrame::showSearchBar(bool show)
 {
     if (show && !m_pSearchBar) {
         m_pSearchBar = new SearchBar(getLayout());
+        m_pSearchBar->setListener(this);
         setPredictBar(*m_pSearchBar);
     }
     showPredictBar(show);
@@ -104,9 +108,12 @@ void RecipInputFrame::setRecip(std::string address, std::string dispName)
 
 void RecipInputFrame::close(std::string address, std::string dispName)
 {
-    setRecip(std::move(address), std::move(dispName));
-    cancelSearch();
-    pop();
+    if (!m_IsClosed) {
+        m_IsClosed = true;
+        setRecip(std::move(address), std::move(dispName));
+        cancelSearch();
+        pop();
+    }
 }
 
 Eina_Bool RecipInputFrame::onSearchTimerTick()
@@ -176,9 +183,9 @@ void RecipInputFrame::searchButtonHandler()
             return;
         }
 
-        Recipient recip = Recipient::searchFirstRecip(input);
-        if (recip.isValid()) {
-            // TODO: impl.
+        auto recips = Recipient::searchRecips(input);
+        if (!recips.empty()) {
+            navigateToContactFrame(std::move(recips), std::move(input));
         } else {
             if (MsgUtils::isValidNumber(input)) {
                 close();
@@ -189,17 +196,18 @@ void RecipInputFrame::searchButtonHandler()
     }
 }
 
-void RecipInputFrame::onAttached(ViewItem &item)
+void RecipInputFrame::navigateToContactFrame(std::list<Recipient> recips, std::string searchWord)
 {
-    MSG_LOG("");
-    InputFrame::onAttached(item);
+    auto *frame = new ContactFrame(getParent(), std::move(recips), std::move(searchWord));
+    frame->setListener(this);
+    addToGroup(*frame);
+    getParent().push(*frame);
 }
 
-bool RecipInputFrame::onRequestPop()
+void RecipInputFrame::onAttached(ViewItem &item)
 {
-    cancelSearch();
-    setRecip();
-    return true;
+    MSG_LOG("");
+    InputFrame::onAttached(item);
 }
 
 void RecipInputFrame::onEntryFilter(Evas_Object *obj, char **text)
@@ -212,7 +220,8 @@ void RecipInputFrame::onEntryFilter(Evas_Object *obj, char **text)
         if (isSeparatorChar(*text)) {
             free(*text);
             *text = nullptr;
-            close();
+            std::string text = getEntry().getText();
+            close(text, text);
         }
     }
 }
@@ -241,3 +250,19 @@ void RecipInputFrame::onEntryActivated(Evas_Object *obj, void *event_info)
     searchButtonHandler();
 }
 
+void RecipInputFrame::onInputPanelHide()
+{
+    MSG_LOG("");
+    BasePopup *popup = App::getInst().getPopupManager().getTop();
+    if (!isPause() && !(popup && popup->isVisible())) {
+        std::string text = getEntry().getText();
+        close(text, text);
+    }
+}
+
+void RecipInputFrame::onContactSelected(ContactFrame &sender, const Recipient &recip)
+{
+    MSG_LOG("");
+    close(recip.getAddress(), recip.getDispName());
+}
+
index d43fbed63d7b3a952123b8f2debb2965f20694a2..6210199f471c9c3fb00e7f1efdb746fc2e76d74d 100644 (file)
@@ -28,8 +28,8 @@ namespace Msg {
             virtual ~ContactListViewItem();
 
         protected:
-            static ListItemStyleRef logStyle;
-            static ListItemStyleRef nameOrEmailStyle;
+            static ListItemStyleRef text1;
+            static ListItemStyleRef text2;
 
             virtual std::string getSubText() = 0;
             virtual std::string getMainText() = 0;
index abe14da708460974958945d02e4b662b1ff8944b..dda8c5d524c18452d96c4de52bb5007d62eb82c8 100644 (file)
@@ -19,8 +19,8 @@
 
 using namespace Msg;
 
-ListItemStyleRef ContactListViewItem::logStyle = ListItemStyle::create("1text");
-ListItemStyleRef ContactListViewItem::nameOrEmailStyle = ListItemStyle::create("2text");
+ListItemStyleRef ContactListViewItem::text1 = ListItemStyle::create("1text");
+ListItemStyleRef ContactListViewItem::text2 = ListItemStyle::create("2text");
 
 namespace {
     const char *mainTextPart = "elm.text";
@@ -41,7 +41,7 @@ std::string ContactListViewItem::getText(ListItem &item, const char *part)
     if (strcmp(part, mainTextPart) == 0)
         return getMainText();
 
-    if (getStyle() == nameOrEmailStyle && strcmp(part, subTextPart) == 0)
+    if (getStyle() == text2 && strcmp(part, subTextPart) == 0)
         return getSubText();
 
     return "";
index 973c60fbc27279c2b3c20e9f705e1588ebaeac28..0783eaf29420036100400ef7d0a9ab376210d3b5 100644 (file)
@@ -38,7 +38,6 @@ Evas_Object *BubbleImageViewItem::createImage(Evas_Object *parent, const std::st
     int imageHeight = 0;
 
     Evas_Object *image = elm_image_add(parent);
-    elm_image_preload_disabled_set(image, true);
     elm_image_prescale_set(image, maxWidth);
     elm_image_aspect_fixed_set(image, true);
     elm_image_file_set(image, path.c_str(), nullptr);