Adding UrlHistoryList class and other classes managing display of 'URL from history' 41/49541/7 accepted/tizen/tv/20151019.074357 submit/tizen_tv/20151018.232544 submit/tizen_tv/20151019.233638 tizen_3.0.m2.a1_tv_release
authorAdam Skobodzinski <a.skobodzins@partner.samsung.com>
Wed, 14 Oct 2015 09:49:17 +0000 (11:49 +0200)
committerAdam Skobodzinski <a.skobodzins@partner.samsung.com>
Fri, 16 Oct 2015 14:14:20 +0000 (16:14 +0200)
[Issue]    https://bugs.tizen.org/jira/browse/TT-161
[Problem]  'Display URL from browser history that matches to given keyword.'
[Solution] Adding necessary class and .edc files. Usage implemention in other commit.

Signed-off-by: Adam Skobodzinski <a.skobodzins@partner.samsung.com>
Change-Id: I35c8b86409e024e107498a552623840553fb3735

services/QuickAccess/CMakeLists.txt
services/QuickAccess/UrlHistoryList/GenlistManager.cpp [new file with mode: 0644]
services/QuickAccess/UrlHistoryList/GenlistManager.h [new file with mode: 0644]
services/QuickAccess/UrlHistoryList/GenlistManagerCallbacks.cpp [new file with mode: 0644]
services/QuickAccess/UrlHistoryList/GenlistManagerCallbacks.h [new file with mode: 0644]
services/QuickAccess/UrlHistoryList/UrlHistoryList.cpp [new file with mode: 0644]
services/QuickAccess/UrlHistoryList/UrlHistoryList.h [new file with mode: 0644]
services/QuickAccess/UrlHistoryList/UrlMatchesStyler.cpp [new file with mode: 0644]
services/QuickAccess/UrlHistoryList/UrlMatchesStyler.h [new file with mode: 0644]
services/QuickAccess/UrlHistoryList/WidgetListManager.h [new file with mode: 0644]
services/QuickAccess/edc/UrlHistoryList.edc [new file with mode: 0644]

index bacd28d..9d794bd 100644 (file)
@@ -3,11 +3,20 @@ project(QuickAccess)
 set(QuickAccess_SRCS
     QuickAccess.cpp
     DetailPopup.cpp
+    UrlHistoryList/UrlHistoryList.cpp
+    UrlHistoryList/GenlistManager.cpp
+    UrlHistoryList/GenlistManagerCallbacks.cpp
+    UrlHistoryList/UrlMatchesStyler.cpp
     )
 
 set(QuickAccess_HEADERS
     QuickAccess.h
     DetailPopup.h
+    UrlHistoryList/UrlHistoryList.h
+    UrlHistoryList/WidgetListManager.h
+    UrlHistoryList/GenlistManager.h
+    UrlHistoryList/GenlistManagerCallbacks.h
+    UrlHistoryList/UrlMatchesStyler.h
     )
 
 include(Coreheaders)
@@ -29,6 +38,7 @@ install(TARGETS ${PROJECT_NAME}
 set(edcFiles
     QuickAccess.edc
     DetailPopup.edc
+    UrlHistoryList.edc
     )
 
 foreach(edec ${edcFiles})
diff --git a/services/QuickAccess/UrlHistoryList/GenlistManager.cpp b/services/QuickAccess/UrlHistoryList/GenlistManager.cpp
new file mode 100644 (file)
index 0000000..c29dfc5
--- /dev/null
@@ -0,0 +1,236 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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 "GenlistManager.h"
+#include "GenlistManagerCallbacks.h"
+#include "UrlMatchesStyler.h"
+
+namespace tizen_browser {
+namespace services {
+
+GenlistManager::GenlistManager()
+{
+    m_urlMatchesStyler = make_shared<UrlMatchesStyler>();
+
+    m_historyItemClass = elm_genlist_item_class_new();
+    m_historyItemClass->item_style = "url_historylist_grid_item";
+    m_historyItemClass->func.text_get = nullptr;
+    m_historyItemClass->func.content_get = m_contentGet;
+    m_historyItemClass->func.state_get = nullptr;
+    m_historyItemClass->func.del = nullptr;
+
+    m_historyItemSpaceClass = elm_genlist_item_class_new();
+    m_historyItemSpaceClass->item_style = "url_historylist_grid_item_space";
+    m_historyItemSpaceClass->func.text_get = nullptr;
+    m_historyItemSpaceClass->func.content_get = nullptr;
+    m_historyItemSpaceClass->func.state_get = nullptr;
+    m_historyItemSpaceClass->func.del = nullptr;
+}
+
+GenlistManager::~GenlistManager()
+{
+    elm_genlist_item_class_free(m_historyItemClass);
+}
+
+void GenlistManager::clearWidget()
+{
+    elm_genlist_clear(m_genlist);
+    elm_genlist_clear(m_genlist);
+    elm_genlist_clear(m_genlist);
+    elm_genlist_clear(m_genlist);
+}
+
+void GenlistManager::onMouseFocusChange(bool mouseInsideWidget)
+{
+    this->mouseInsideWidget = mouseInsideWidget;
+}
+
+Evas_Object* GenlistManager::createWidget(Evas_Object* parentLayout)
+{
+    if (!widgetExists()) {
+        m_parentLayout = parentLayout;
+        m_genlist = elm_genlist_add(parentLayout);
+        evas_object_size_hint_weight_set(m_genlist, EVAS_HINT_EXPAND,
+        EVAS_HINT_EXPAND);
+        evas_object_size_hint_align_set(m_genlist, EVAS_HINT_FILL,
+        EVAS_HINT_FILL);
+        if (!genlistShowScrollbar) {
+            elm_scroller_policy_set(m_genlist, ELM_SCROLLER_POLICY_OFF,
+                    ELM_SCROLLER_POLICY_OFF);
+        }
+
+        evas_object_smart_callback_add(m_genlist, "scroll,anim,stop",
+                GenlistManagerCallbacks::cb_genlistAnimStop, this);
+        evas_object_smart_callback_add(m_genlist, "edge,top",
+                GenlistManagerCallbacks::cb_genlistEdgeTop, this);
+        evas_object_smart_callback_add(m_genlist, "edge,bottom",
+                GenlistManagerCallbacks::cb_genlistEdgeBottom, this);
+
+        evas_object_smart_callback_add(m_genlist, "activated",
+                GenlistManagerCallbacks::cb_genlistActivated, this);
+        evas_object_smart_callback_add(m_genlist, "pressed",
+                GenlistManagerCallbacks::cb_genlistPressed, this);
+        evas_object_smart_callback_add(m_genlist, "selected",
+                GenlistManagerCallbacks::cb_genlistSelected, this);
+
+        evas_object_event_callback_add(m_genlist, EVAS_CALLBACK_MOUSE_IN,
+                GenlistManagerCallbacks::cb_genlistMouseIn, this);
+        evas_object_event_callback_add(m_genlist, EVAS_CALLBACK_MOUSE_OUT,
+                GenlistManagerCallbacks::cb_genlistMouseOut, this);
+        evas_object_smart_callback_add(m_genlist, "unselected",
+                GenlistManagerCallbacks::cb_genlistUnselected, this);
+        evas_object_smart_callback_add(m_genlist, "focused",
+                GenlistManagerCallbacks::cb_genlistFocused, this);
+    }
+    return m_genlist;
+}
+
+Evas_Object* GenlistManager::getWidget()
+{
+    if (!widgetExists())
+        createWidget(m_parentLayout);
+    return m_genlist;
+}
+
+void GenlistManager::showWidget(const string& editedUrl,
+        shared_ptr<services::HistoryItemVector> matchedEntries)
+{
+    clearWidget();
+    prepareUrlsVector(editedUrl, matchedEntries);
+
+    m_itemUrlFirst = m_itemUrlLast = nullptr;
+    Elm_Object_Item* itemAppended;
+    for (auto it : m_readyUrls) {
+        itemAppended = elm_genlist_item_append(m_genlist, m_historyItemClass,
+                it.get(), nullptr, ELM_GENLIST_ITEM_NONE, nullptr, this);
+        if (!m_itemUrlFirst)
+            m_itemUrlFirst = itemAppended;
+    }
+    m_itemUrlLast = itemAppended;
+
+    if (widgetPreviouslyHidden) {
+        widgetPreviouslyHidden = false;
+        startScrollIn();
+    }
+}
+
+void GenlistManager::hideWidget()
+{
+    if (widgetPreviouslyHidden)
+        return;
+    startScrollOut();
+    widgetPreviouslyHidden = true;
+}
+
+bool GenlistManager::isWidgetHidden()
+{
+    return widgetPreviouslyHidden;
+}
+
+void GenlistManager::onMouseClick()
+{
+    if (!mouseInsideWidget) {
+        hideWidget();
+    }
+}
+
+void GenlistManager::startScrollIn()
+{
+    if (m_itemUrlFirst) {
+        addSpaces();
+        elm_genlist_item_show(m_itemSpaceLast, ELM_GENLIST_ITEM_SCROLLTO_TOP);
+        elm_genlist_item_bring_in(m_itemUrlFirst,
+                ELM_GENLIST_ITEM_SCROLLTO_TOP);
+    }
+}
+
+void GenlistManager::startScrollOut()
+{
+    addSpaces();
+    if (m_itemSpaceFirst) {
+        elm_genlist_item_bring_in(m_itemSpaceFirst,
+                ELM_GENLIST_ITEM_SCROLLTO_TOP);
+    }
+}
+
+void GenlistManager::setLastEdgeTop(bool edgeTop)
+{
+    lastEdgeTop = edgeTop;
+}
+
+bool GenlistManager::getLastEdgeTop()
+{
+    return lastEdgeTop;
+}
+
+void GenlistManager::addSpaces()
+{
+    if (m_itemUrlLast) {
+        m_itemSpaceFirst = m_itemSpaceLast = nullptr;
+        Elm_Object_Item* itemAppended;
+        for (auto i = 0; i < historyItemsVisibleMax; ++i) {
+            // append spaces to the last url item, so they can be easily cleared
+            itemAppended = elm_genlist_item_append(m_genlist,
+                    m_historyItemSpaceClass, nullptr, m_itemUrlLast,
+                    ELM_GENLIST_ITEM_NONE, nullptr, this);
+            if (!m_itemSpaceFirst)
+                m_itemSpaceFirst = itemAppended;
+        }
+        m_itemSpaceLast = itemAppended;
+    }
+}
+
+void GenlistManager::removeSpaces()
+{
+    if (m_itemUrlLast) {
+        elm_genlist_item_subitems_clear(m_itemUrlLast);
+    }
+    m_itemSpaceFirst = m_itemSpaceLast = nullptr;
+}
+
+Evas_Object* GenlistManager::m_contentGet(void *data, Evas_Object *obj,
+        const char *part)
+{
+    Evas_Object* label = elm_label_add(obj);
+    if (strcmp(part, "matched_url") == 0) {
+        const string * const item = reinterpret_cast<string*>(data);
+        if (item) {
+            elm_object_text_set(label, item->c_str());
+            evas_object_size_hint_weight_set(label, EVAS_HINT_EXPAND,
+            EVAS_HINT_EXPAND);
+            evas_object_size_hint_align_set(label, EVAS_HINT_FILL,
+            EVAS_HINT_FILL);
+        }
+    }
+    return label;
+}
+
+void GenlistManager::prepareUrlsVector(const string& editedUrl,
+        shared_ptr<services::HistoryItemVector> matchedEntries)
+{
+    // free previously used urls. IMPORTANT: it has to be assured that previous
+    // genlist items are not using these pointers.
+    m_readyUrls.clear();
+    for (auto it : *matchedEntries) {
+        m_readyUrls.push_back(
+                make_shared < string
+                        > (m_urlMatchesStyler->getUrlHighlightedMatches(
+                                it->getUrl(), editedUrl)));
+    }
+}
+
+} /* namespace services */
+} /* namespace tizen_browser */
diff --git a/services/QuickAccess/UrlHistoryList/GenlistManager.h b/services/QuickAccess/UrlHistoryList/GenlistManager.h
new file mode 100644 (file)
index 0000000..05d5cd3
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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 GENLISTMANAGER_H_
+#define GENLISTMANAGER_H_
+
+#include <Elementary.h>
+
+#include "BrowserLogger.h"
+#include "WidgetListManager.h"
+
+using namespace std;
+
+namespace tizen_browser {
+namespace services {
+
+class GenlistManagerCallbacks;
+class UrlMatchesStyler;
+typedef shared_ptr<UrlMatchesStyler> UrlMatchesStylerPtr;
+
+class GenlistManager: public WidgetListManager
+{
+    friend class GenlistManagerCallbacks;
+public:
+    GenlistManager();
+    virtual ~GenlistManager();
+
+    virtual Evas_Object* createWidget(Evas_Object* parentLayout);
+    virtual Evas_Object* getWidget();
+
+    virtual void showWidget(const string& editedUrl,
+            shared_ptr<services::HistoryItemVector> matchedEntries);
+    virtual void hideWidget();
+    void onMouseClick();
+
+    bool isWidgetHidden();
+
+    /**
+     * Add empty list elements to allow scroll in effect.
+     */
+    void addSpaces();
+    void removeSpaces();
+
+    void clearWidget();
+
+private:
+
+    static Evas_Object* m_contentGet(void *data, Evas_Object *obj,
+            const char *part);
+    bool widgetExists()
+    {
+        return m_genlist != nullptr;
+    }
+    void prepareUrlsVector(const string& editedUrl,
+            shared_ptr<services::HistoryItemVector> matchedEntries);
+    void startScrollIn();
+    void startScrollOut();
+    void setLastEdgeTop(bool edgeTop);
+    bool getLastEdgeTop();
+    void onMouseFocusChange(bool mouseInsideWidget);
+
+    Evas_Object* m_parentLayout = nullptr;
+    Evas_Object* m_genlist = nullptr;
+    const bool genlistShowScrollbar = false;
+
+    // don't know how to get from edc:
+    const int historyItemH = 82;
+    const int historyItemsVisibleMax = 5;
+    // don't know how to calculate:
+    const int genlistH = historyItemH * historyItemsVisibleMax;
+
+    /*
+     * Set to true, whenever hide request occurs. Set to false, whenever show
+     * request occurs. Needed to indicate when genlist should slide in.
+     */
+    bool widgetPreviouslyHidden = true;
+    /*
+     * If mouse click received and mouse is outside widget, hide it.
+     */
+    bool mouseInsideWidget = true;
+    /*
+     * needed to indicate direction of the scroll in 'anim,stop' callback
+     */
+    bool lastEdgeTop = true;
+
+    Elm_Gengrid_Item_Class * m_historyItemClass;
+    Elm_Gengrid_Item_Class * m_historyItemSpaceClass;
+    Elm_Object_Item* m_itemUrlFirst = nullptr;
+    Elm_Object_Item* m_itemUrlLast = nullptr;
+    Elm_Object_Item* m_itemSpaceFirst = nullptr;
+    Elm_Object_Item* m_itemSpaceLast = nullptr;
+
+    /*
+     * keeps shared pointers to strings, that are ready to be displayed, so they can be
+     * passed through EFL, until they're not needed. IMPORTANT: it has to be
+     * assured, that list is not cleared until all EFL items has created their
+     * labels from these pointers in m_contentGet(). in case of segfaults, delete copy of pointers
+     * manually in m_contentGet().
+     */
+    vector<shared_ptr<string>> m_readyUrls;
+    UrlMatchesStylerPtr m_urlMatchesStyler;
+
+};
+
+} /* namespace services */
+} /* namespace tizen_browser */
+
+#endif /* GENLISTMANAGER_H_ */
diff --git a/services/QuickAccess/UrlHistoryList/GenlistManagerCallbacks.cpp b/services/QuickAccess/UrlHistoryList/GenlistManagerCallbacks.cpp
new file mode 100644 (file)
index 0000000..25c3868
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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 "BrowserLogger.h"
+#include "GenlistManagerCallbacks.h"
+#include "GenlistManager.h"
+
+namespace tizen_browser
+{
+namespace services
+{
+
+GenlistManagerCallbacks::GenlistManagerCallbacks()
+{
+}
+
+GenlistManagerCallbacks::~GenlistManagerCallbacks()
+{
+}
+
+void GenlistManagerCallbacks::cb_genlistAnimStop(void *data, Evas_Object *obj,
+               void *event_info)
+{
+}
+
+void GenlistManagerCallbacks::cb_genlistEdgeTop(void *data, Evas_Object *obj,
+               void *event_info)
+{
+       BROWSER_LOGD("@@ %s", __FUNCTION__);
+       auto manager = static_cast<GenlistManager*>(data);
+       manager->setLastEdgeTop(false);
+       // spaces added for 'slide in' effect are not longer needed
+       manager->removeSpaces();
+}
+
+void GenlistManagerCallbacks::cb_genlistEdgeBottom(void *data, Evas_Object *obj,
+               void *event_info)
+{
+       auto manager = static_cast<GenlistManager*>(data);
+       manager->setLastEdgeTop(true);
+       if (manager->isWidgetHidden())
+       {
+               manager->clearWidget();
+               evas_object_hide(manager->getWidget());
+       }
+}
+
+void GenlistManagerCallbacks::cb_genlistActivated(void *data, Evas_Object *obj,
+               void *event_info)
+{
+}
+void GenlistManagerCallbacks::cb_genlistPressed(void *data, Evas_Object *obj,
+               void *event_info)
+{
+}
+void GenlistManagerCallbacks::cb_genlistSelected(void *data, Evas_Object *obj,
+               void *event_info)
+{
+}
+void GenlistManagerCallbacks::cb_genlistUnselected(void *data, Evas_Object *obj,
+               void *event_info)
+{
+}
+
+void GenlistManagerCallbacks::cb_genlistFocused(void *data, Evas_Object *obj,
+               void *event_info)
+{
+}
+
+void GenlistManagerCallbacks::cb_genlistUnfocused(void *data, Evas_Object *obj,
+               void *event_info)
+{
+}
+
+void GenlistManagerCallbacks::cb_genlistMouseIn(void *data, Evas *e,
+               Evas_Object *obj, void *event_info)
+{
+       auto manager = static_cast<GenlistManager*>(data);
+       manager->onMouseFocusChange(true);
+}
+void GenlistManagerCallbacks::cb_genlistMouseOut(void *data, Evas *e,
+               Evas_Object *obj, void *event_info)
+{
+       auto manager = static_cast<GenlistManager*>(data);
+       manager->onMouseFocusChange(false);
+}
+
+void GenlistManagerCallbacks::cb_itemFocused(void *data, Evas_Object *obj,
+               void *event_info)
+{
+}
+void GenlistManagerCallbacks::cb_itemUnfocused(void *data, Evas_Object *obj,
+               void *event_info)
+{
+}
+void GenlistManagerCallbacks::cb_itemMouseIn(void *data, Elm_Object_Item *it,
+        const char *emission, const char *source)
+{
+}
+void GenlistManagerCallbacks::cb_itemMouseOut(void *data, Evas *e,
+               Evas_Object *obj, void *event_info)
+{
+}
+
+} /* namespace services */
+} /* namespace tizen_browser */
diff --git a/services/QuickAccess/UrlHistoryList/GenlistManagerCallbacks.h b/services/QuickAccess/UrlHistoryList/GenlistManagerCallbacks.h
new file mode 100644 (file)
index 0000000..25ff418
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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 GENLISTMANAGERCALLBACKS_H_
+#define GENLISTMANAGERCALLBACKS_H_
+
+#include <Elementary.h>
+#include <Evas.h>
+
+class GenlistManager;
+
+namespace tizen_browser
+{
+namespace services
+{
+
+class GenlistManagerCallbacks
+{
+public:
+       GenlistManagerCallbacks();
+       virtual ~GenlistManagerCallbacks();
+
+       static void cb_genlistAnimStop(void *data, Evas_Object *obj,
+                       void *event_info);
+       static void cb_genlistEdgeTop(void *data, Evas_Object *obj,
+                       void *event_info);
+       static void cb_genlistEdgeBottom(void *data, Evas_Object *obj,
+                       void *event_info);
+
+       static void cb_genlistActivated(void *data, Evas_Object *obj,
+                       void *event_info);
+       static void cb_genlistPressed(void *data, Evas_Object *obj,
+                       void *event_info);
+       static void cb_genlistSelected(void *data, Evas_Object *obj,
+                       void *event_info);
+       static void cb_genlistUnselected(void *data, Evas_Object *obj,
+                       void *event_info);
+
+       static void cb_genlistFocused(void *data, Evas_Object *obj,
+                       void *event_info);
+       static void cb_genlistUnfocused(void *data, Evas_Object *obj,
+                       void *event_info);
+       static void cb_genlistMouseIn(void *data, Evas *e, Evas_Object *obj,
+                       void *event_info);
+       static void cb_genlistMouseOut(void *data, Evas *e, Evas_Object *obj,
+                       void *event_info);
+
+       static void cb_itemFocused(void *data, Evas_Object *obj, void *event_info);
+       static void cb_itemUnfocused(void *data, Evas_Object *obj,
+                       void *event_info);
+       static void cb_itemMouseIn(void *data, Elm_Object_Item *it,
+            const char *emission, const char *source);
+       static void cb_itemMouseOut(void *data, Evas *e, Evas_Object *obj,
+                       void *event_info);
+};
+
+} /* namespace services */
+} /* namespace tizen_browser */
+
+#endif /* GENLISTMANAGERCALLBACKS_H_ */
diff --git a/services/QuickAccess/UrlHistoryList/UrlHistoryList.cpp b/services/QuickAccess/UrlHistoryList/UrlHistoryList.cpp
new file mode 100644 (file)
index 0000000..fd76489
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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 <Elementary.h>
+#include "UrlHistoryList.h"
+#include "GenlistManager.h"
+
+#include "BrowserLogger.h"
+
+namespace tizen_browser
+{
+namespace base_ui
+{
+
+UrlHistoryList::UrlHistoryList() :
+               m_layout(nullptr)
+{
+       m_edjFilePath = EDJE_DIR;
+       m_edjFilePath.append("MainUI/UrlHistoryList.edj");
+       m_widgetListManager = make_shared<services::GenlistManager>();
+}
+
+UrlHistoryList::~UrlHistoryList()
+{
+}
+
+void UrlHistoryList::show()
+{
+       if (m_layout)
+       {
+               evas_object_show(m_layout);
+       }
+}
+
+Evas_Object* UrlHistoryList::getLayout()
+{
+       return m_layout;
+}
+
+void UrlHistoryList::createLayout(Evas_Object* parentLayout)
+{
+       m_layout = elm_layout_add(parentLayout);
+       elm_layout_file_set(m_layout, m_edjFilePath.c_str(), "url_history_list");
+
+       Evas_Object* widgetList = m_widgetListManager->createWidget(m_layout);
+}
+
+void UrlHistoryList::onURLEntryEdit(const string& editedUrl,
+               shared_ptr<services::HistoryItemVector> matchedEntries)
+{
+       Evas_Object* widgetList = m_widgetListManager->getWidget();
+       if (matchedEntries->size() == 0)
+       {
+               m_widgetListManager->hideWidget();
+       }
+       else
+       {
+               elm_object_part_content_set(m_layout, "list_swallow", widgetList);
+               m_widgetListManager->showWidget(editedUrl, matchedEntries);
+               evas_object_show(widgetList);
+       }
+}
+
+void UrlHistoryList::onMouseClick()
+{
+       m_widgetListManager->onMouseClick();
+}
+
+}/* namespace base_ui */
+} /* namespace tizen_browser */
diff --git a/services/QuickAccess/UrlHistoryList/UrlHistoryList.h b/services/QuickAccess/UrlHistoryList/UrlHistoryList.h
new file mode 100644 (file)
index 0000000..fa9934a
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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 URLHISTORYLIST_H_
+#define URLHISTORYLIST_H_
+
+#include <memory>
+#include <Evas.h>
+
+#include "services/HistoryService/HistoryItem.h"
+
+using namespace std;
+
+namespace tizen_browser
+{
+
+namespace services
+{
+class WidgetListManager;
+typedef shared_ptr<WidgetListManager> WidgetListManagerPtr;
+}
+
+namespace base_ui
+{
+
+/**
+ * Manages list of url matches (URL from history). Manages top layout, creates
+ * widget displaying url items.
+ */
+class UrlHistoryList
+{
+public:
+       UrlHistoryList();
+       virtual ~UrlHistoryList();
+       void show();
+       void createLayout(Evas_Object* parentLayout);
+       Evas_Object *getLayout();
+
+       /**
+        * \brief entered url is edited (edited before acceptation)
+        */
+       void onURLEntryEdit(const string& editedUrl,
+                       shared_ptr<services::HistoryItemVector> matchedEntries);
+       void onMouseClick();
+
+private:
+
+       Evas_Object* m_layout;
+       string m_edjFilePath;
+
+       services::WidgetListManagerPtr m_widgetListManager;
+
+};
+
+} /* namespace base_ui */
+} /* namespace tizen_browser */
+
+#endif /* URLHISTORYLIST_H_ */
diff --git a/services/QuickAccess/UrlHistoryList/UrlMatchesStyler.cpp b/services/QuickAccess/UrlHistoryList/UrlMatchesStyler.cpp
new file mode 100644 (file)
index 0000000..c97758b
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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 "UrlMatchesStyler.h"
+
+namespace tizen_browser {
+namespace services {
+
+UrlMatchesStyler::UrlMatchesStyler() :
+               TAG_WHOLE_URL("<align=left><color=" + FONT_COLOR_NORMAL + "><font_size="+FONT_SIZE+">"),
+               TAG_WHOLE_URL_CLOSE("</color></font></align>"),
+               TAG_HIGHLIGHT("<hilight>"),
+               TAG_HIGHLIGHT_CLOSE(closeTag(TAG_HIGHLIGHT)),
+               TAG_COLOR("<color=" + FONT_COLOR_HIGHLIGHT + ">"),
+               TAG_COLOR_CLOSE(closeTag(TAG_COLOR)),
+               TAG_COMPLETE(TAG_HIGHLIGHT + TAG_COLOR),
+               TAG_COMPLETE_CLOSE(TAG_HIGHLIGHT_CLOSE + TAG_COLOR_CLOSE),
+               TAGS_COMPLETE_LEN(TAG_COMPLETE.length() + TAG_COMPLETE_CLOSE.length()) {
+}
+
+UrlMatchesStyler::~UrlMatchesStyler() {
+}
+
+string UrlMatchesStyler::closeTag(const string& tag) const {
+       string closedTag(tag);
+       return string(closedTag.insert(1, "/"));
+}
+
+string UrlMatchesStyler::getUrlHighlightedMatches(const string& styledUrl,
+               const string& highlightingKeywords) const {
+       vector < string > keywords;
+       splitKeywordsString(highlightingKeywords, keywords);
+
+       int_pairs rangesHighlight;
+       for (auto key : keywords) {
+               fillOccuranceRanges(styledUrl, key, rangesHighlight);
+       }
+
+       int_pairs mergedRangesHighlight;
+       mergeRanges(rangesHighlight, mergedRangesHighlight);
+       return getTaggedString(styledUrl, mergedRangesHighlight);
+}
+
+void UrlMatchesStyler::splitKeywordsString(const string& keywordsString,
+               vector<string>& resultKeywords) const {
+       boost::algorithm::split(resultKeywords, keywordsString,
+                       boost::is_any_of("\t "), boost::token_compress_on);
+       // remove empty elements
+       for (auto it = resultKeywords.begin(); it != resultKeywords.end();) {
+               if ((*it).empty()) {
+                       it = resultKeywords.erase(it);
+               } else {
+                       ++it;
+               }
+       }
+}
+
+void UrlMatchesStyler::fillOccuranceRanges(const string& _checkedString,
+               const string& _searchedMatch, int_pairs& resultRanges) const {
+       if (_checkedString.empty() || _searchedMatch.empty())
+               return;
+
+       string checkedString(_checkedString);
+       string searchedMatch(_searchedMatch);
+       boost::algorithm::to_lower(checkedString);
+       boost::algorithm::to_lower(searchedMatch);
+
+       int len = searchedMatch.length();
+       vector<int> positions;
+       getMatchesPositions(checkedString, searchedMatch, positions);
+       for (auto pos : positions) {
+               resultRanges.push_back( { pos, pos + len - 1 });
+       }
+}
+
+void UrlMatchesStyler::getMatchesPositions(const string& checkedString,
+               const string& searchedMatch, vector<int>& resultPositions) const {
+       boost::regex match_regex(searchedMatch);
+       for (auto it = boost::sregex_iterator(checkedString.begin(),
+                       checkedString.end(), match_regex); it != boost::sregex_iterator();
+                       ++it) {
+               resultPositions.push_back(it->position());
+       }
+}
+
+void UrlMatchesStyler::mergeRanges(int_pairs& ranges, int_pairs& result) const {
+       if (ranges.size() == 0)
+               return;
+       sort(ranges.begin(), ranges.end());
+
+       auto current = *(ranges.begin());
+       for (auto it = ranges.begin() + 1; it != ranges.end(); ++it) {
+               if (current.second >= it->first) {
+                       current.second = max(current.second, it->second);
+               } else {
+                       result.push_back(current);
+                       current = *it;
+               }
+       }
+       result.push_back(current);
+}
+
+string UrlMatchesStyler::getTaggedString(const string& strToHighlight,
+               const int_pairs& ranges) const {
+       string strResult(strToHighlight);
+       int insertOffset = 0;
+       for (auto pair : ranges) {
+               strResult.insert(pair.second + insertOffset + 1, TAG_COMPLETE_CLOSE);
+               strResult.insert(pair.first + insertOffset, TAG_COMPLETE);
+               insertOffset += TAGS_COMPLETE_LEN;
+       }
+       strResult.insert(strResult.length(), TAG_WHOLE_URL_CLOSE);
+       strResult.insert(0, TAG_WHOLE_URL);
+       return strResult;
+}
+
+} /* namespace services */
+} /* namespace tizen_browser */
diff --git a/services/QuickAccess/UrlHistoryList/UrlMatchesStyler.h b/services/QuickAccess/UrlHistoryList/UrlMatchesStyler.h
new file mode 100644 (file)
index 0000000..d100b29
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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 URLMATCHESSTYLER_H_
+#define URLMATCHESSTYLER_H_
+
+#include <string>
+#include <vector>
+#include <boost/algorithm/string.hpp>
+#include <boost/regex.hpp>
+#include "BrowserLogger.h"
+
+using namespace std;
+
+namespace tizen_browser {
+namespace services {
+
+class UrlMatchesStyler {
+public:
+       UrlMatchesStyler();
+       virtual ~UrlMatchesStyler();
+
+       /**
+        * @brief  Get string containing EFL tags, which are highlighting given keywords.
+        * @param styledUrl url which will be styled
+        * @param highlightingKeyword keywords (entered url) indicating which
+        * fragments should be highlighted
+        * @return styledUrl enriched with EFL tags
+        */
+       string getUrlHighlightedMatches(const string& styledUrl,
+                       const string& highlightingKeywords) const;
+
+private:
+       typedef vector<pair<int, int>> int_pairs;
+       const string FONT_COLOR_HIGHLIGHT = "#4088D3";
+       const string FONT_COLOR_NORMAL = "#888888";
+       const string FONT_SIZE = "35";
+       const string TAG_WHOLE_URL;
+       const string TAG_WHOLE_URL_CLOSE;
+       const string TAG_HIGHLIGHT, TAG_HIGHLIGHT_CLOSE;
+       const string TAG_COLOR, TAG_COLOR_CLOSE;
+       const string TAG_COMPLETE, TAG_COMPLETE_CLOSE;
+       const int TAGS_COMPLETE_LEN;
+
+       /**
+        * @brief adds '/' to a tag (<a> -> </a>)
+        * @param tag tag to be closed
+        * @return closed tag
+        */
+       string closeTag(const string& tag) const;
+    /**
+     * @brief splits given string by removing spaces
+     * @param keywordsString string to split
+     * @param resultKeywords vector to which result strings are stored
+     */
+       void splitKeywordsString(const string& keywordsString,
+                       vector<string>& resultKeywords) const;
+       /**
+        * @brief Fills vector with ranges describing beginnings end ends of occurrences of one string in another.
+        * @param checkedString the subject of search
+        * @param searchedMatch match to be searched for
+        * @param resultRanges vector filled with found ranges
+        */
+       void fillOccuranceRanges(const string& checkedString,
+                       const string& searchedMatch, int_pairs& resultRanges) const;
+       /**
+        * @brief Searches the string for positions of occurrences of another string.
+        * @param checkedString the subject of search
+        * @param searchedMatch string to be searched for
+        * @param resultPositions vector filled with result positions
+        */
+       void getMatchesPositions(const string& checkedString,
+                       const string& searchedMatch, vector<int>& resultPositions) const;
+       /**
+        * @brief merges ranges
+        * @param ranges vector of ranges to merge
+        * @param result vector filled with merged ranges
+        */
+       void mergeRanges(int_pairs& ranges, int_pairs& result) const;
+       /**
+        * @brief get string enriched with opening and closing tags on given positions
+        * @param strToHighlight string to be enriched with tags
+        * @param ranges positions of opening and closing tags
+        * @param tag opening tag (for every pair.first)
+        * @param tagClose closing tag (for every pair.second)
+        * @return string with tags
+        */
+       string getTaggedString(const string& strToHighlight,
+                       const int_pairs& ranges) const;
+
+};
+
+} /* namespace services */
+} /* namespace tizen_browser */
+
+#endif /* URLMATCHESSTYLER_H_ */
diff --git a/services/QuickAccess/UrlHistoryList/WidgetListManager.h b/services/QuickAccess/UrlHistoryList/WidgetListManager.h
new file mode 100644 (file)
index 0000000..18c22b5
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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 WIDGETLISTMANAGER_H_
+#define WIDGETLISTMANAGER_H_
+
+#include <memory>
+#include <Evas.h>
+#include "services/HistoryService/HistoryItem.h"
+
+namespace tizen_browser
+{
+namespace services
+{
+
+/**
+ * Interface for classes managing list-like widgets.
+ * TODO: consider if it could be used in whole application, not only for URL
+ * list.
+ */
+class WidgetListManager
+{
+public:
+       virtual ~WidgetListManager()
+       {
+       }
+       virtual Evas_Object* createWidget(Evas_Object* parentLayout) = 0;
+       virtual Evas_Object* getWidget() = 0;
+       virtual void hideWidget() = 0;
+       virtual void showWidget(const std::string& editedUrl,
+                       std::shared_ptr<services::HistoryItemVector> matchedEntries) = 0;
+       virtual void onMouseClick() = 0;
+};
+
+} /* namespace services */
+} /* namespace tizen_browser */
+
+#endif /* WIDGETLISTMANAGER_H_ */
diff --git a/services/QuickAccess/edc/UrlHistoryList.edc b/services/QuickAccess/edc/UrlHistoryList.edc
new file mode 100644 (file)
index 0000000..9cc5fb3
--- /dev/null
@@ -0,0 +1,142 @@
+#define URI_INPUTBOX_LENGTH 1720
+#define URI_INPUTBOX_LENGTH_SMALL 1460
+#define HISTORY_ITEM_W URI_INPUTBOX_LENGTH
+#define HISTORY_ITEM_H 82
+#define HISTORY_ITEMS_VISIBLE_MAX 5
+/*
+  Right now, has to be a multiple of item's height.
+*/
+#define LIST_MAX_H HISTORY_ITEM_H*HISTORY_ITEMS_VISIBLE_MAX
+
+collections {
+    group {
+        name: "url_history_list";
+        parts
+        {
+            part {
+                name: "bg";
+                type: RECT;
+                mouse_events: 1;
+                description
+                {
+                    color: 232 122 32 150;
+                    state: "default" 0.0;
+                    visible: 0;
+                    min: URI_INPUTBOX_LENGTH LIST_MAX_H;
+                    max: -1 -1;
+                    align: 0.0 0.0;
+                    fixed: 1 1;
+                    rel1
+                    {
+                        relative: 0 0;
+                    }
+                    rel2
+                    {
+                        relative: 1.0 1.0;
+                    }
+                }
+            }
+
+            part {
+                name: "list_swallow";
+                type: SWALLOW;
+                description {
+                    color: 255 0 0 150;
+                    min: URI_INPUTBOX_LENGTH LIST_MAX_H;
+                    max: -1 -1;
+                    visible: 1;
+                    align: 0.0 0.0;
+                    rel1 {
+                        relative: 0 0;
+                        offset: 0 0;
+                    }
+                    rel2 {
+                        relative: 1.0 0.5;
+                    }
+                }
+            }
+        }
+    }
+
+    group {
+        name: "elm/genlist/item/url_historylist_grid_item/default";
+        data.item: "contents" "matched_url";
+        parts {
+            part {
+                name: "bg";
+                type: RECT;
+                mouse_events: 1;
+                description {
+                    state: "default" 0.0;
+                    min: URI_INPUTBOX_LENGTH HISTORY_ITEM_H;
+                    max: -1 -1;
+                    visible: 1;
+                    color: 255 255 255 255;
+                    align: 0.0 0.0;
+                }
+                description {
+                    state: "focused" 0.0;
+                    inherit: "default" 0.0;
+                    color: 0 119 246 255;
+                }
+            }
+            part {
+                name: "matched_url";
+                type: SWALLOW;
+                scale: 1;
+                description {
+                    state: "default" 0.0;
+                    fixed: 0 1;
+                    visible: 1;
+                    align: 0.0 0.0;
+                    rel1 {
+                        to: "bg";
+                        relative: 0.0 0.0;
+                        offset: 48 0;
+                    }
+                    rel2 {
+                        to: "bg";
+                        relative: 1.0  1.0;
+                    }
+
+                }
+            }
+        }
+        programs {
+            program {
+                name: "focused";
+                signal: "mouse,in";
+                source: "matched_url";
+                action: STATE_SET "focused" 0.0;
+                target: "bg";
+            }
+            program {
+                name: "selected";
+                signal: "mouse,out";
+                source: "matched_url";
+                action: STATE_SET "default" 0.0;
+                target: "bg";
+            }
+        }
+    }
+
+    group {
+        name: "elm/genlist/item/url_historylist_grid_item_space/default";
+        parts {
+            part {
+                name: "bg";
+                type: RECT;
+                mouse_events: 1;
+                description {
+                    state: "default" 0.0;
+                    visible: 0;
+                    min: URI_INPUTBOX_LENGTH HISTORY_ITEM_H;
+                    max: -1 -1;
+                    visible: 1;
+                    color: 255 255 255 0;
+                    align: 0.0 0.0;
+                }
+            }
+        }
+    }
+}