#ifndef UI_SCROLL_NAVIGATOR_H
#define UI_SCROLL_NAVIGATOR_H
-#include "Ui/Navigator.h"
+#include "Ui/TabNavigator.h"
#include "Ui/ScrollPage.h"
#include <vector>
/**
* @brief Scrollable page navigator.
*/
- class EXPORT_API ScrollNavigator : public Navigator
+ class EXPORT_API ScrollNavigator : public TabNavigator
{
public:
- ScrollNavigator();
+ /**
+ * @see TabNavigator::TabNavigator()
+ */
+ explicit ScrollNavigator(Selector *selector = nullptr);
/**
* @brief Set whether navigation is allowed either by user or by calling navigateTo().
protected:
virtual Evas_Object *onCreate(Evas_Object *parent) override;
- virtual void onPageAttached(NavigatorPage *page) override;
-
virtual ScrollPage *addPage(View *view) override;
- virtual bool removePage(NavigatorPage *page) override;
- virtual void navigateToPage(NavigatorPage *page) override;
+ virtual ScrollPage *createPage(View *view, Elm_Object_Item *item) override;
+ virtual void changePage(TabPage *page) override;
private:
- void onTabSelected(Evas_Object *obj, Elm_Object_Item *selectedItem);
+ size_t getPageIndex(TabPage *page) const;
+ TabPage *getPageByIndex(size_t index) const;
+
void onPageChanged(Evas_Object *obj, void *eventInfo);
void onResize(Evas *e, Evas_Object *obj, void *eventInfo);
- Evas_Object *m_Tabbar;
Evas_Object *m_Scroller;
Evas_Object *m_Box;
Evas_Coord m_Width;
Evas_Coord m_Height;
- bool m_IsNavigating;
bool m_IsNavigationEnabled;
- std::vector<ScrollPage *> m_Pages;
};
}
#include "Ui/ScrollNavigator.h"
#include "Ui/ScrollPage.h"
+#include "Ui/Selector.h"
#include "Utils/Callback.h"
-#include "Utils/Logger.h"
using namespace Ui;
-ScrollNavigator::ScrollNavigator()
- : Navigator(TypeTabNavigator),
- m_Tabbar(nullptr), m_Scroller(nullptr), m_Box(nullptr),
+ScrollNavigator::ScrollNavigator(Selector *selector)
+ : TabNavigator(selector),
+ m_Scroller(nullptr), m_Box(nullptr),
m_Width(0), m_Height(0),
- m_IsNavigating(false), m_IsNavigationEnabled(true)
+ m_IsNavigationEnabled(true)
{
}
void ScrollNavigator::setNavigationEnabled(bool isEnabled)
{
m_IsNavigationEnabled = isEnabled;
- if (isEnabled) {
- elm_toolbar_select_mode_set(m_Tabbar, ELM_OBJECT_SELECT_MODE_ALWAYS);
- elm_scroller_movement_block_set(getEvasObject(), ELM_SCROLLER_MOVEMENT_NO_BLOCK);
- } else {
- elm_toolbar_select_mode_set(m_Tabbar, ELM_OBJECT_SELECT_MODE_NONE);
- elm_scroller_movement_block_set(getEvasObject(), ELM_SCROLLER_MOVEMENT_BLOCK_HORIZONTAL);
- }
+ getSelector()->setSelectEnabled(isEnabled);
+ elm_scroller_movement_block_set(getEvasObject(),
+ isEnabled ? ELM_SCROLLER_MOVEMENT_NO_BLOCK : ELM_SCROLLER_MOVEMENT_BLOCK_HORIZONTAL);
}
Evas_Object *ScrollNavigator::onCreate(Evas_Object *parent)
return m_Scroller;
}
-void ScrollNavigator::onPageAttached(NavigatorPage *page)
-{
- m_Tabbar = elm_toolbar_add(getEvasObject());
- elm_toolbar_shrink_mode_set(m_Tabbar, ELM_TOOLBAR_SHRINK_EXPAND);
- elm_toolbar_select_mode_set(m_Tabbar, ELM_OBJECT_SELECT_MODE_ALWAYS);
- elm_toolbar_transverse_expanded_set(m_Tabbar, EINA_TRUE);
- evas_object_smart_callback_add(m_Tabbar, "selected",
- (Evas_Smart_Cb) makeCallback(&ScrollNavigator::onTabSelected), this);
-
- page->setStyle("tabbar/notitle");
- page->setContent("tabbar", m_Tabbar);
-}
-
ScrollPage *ScrollNavigator::addPage(View *view)
{
- Elm_Object_Item *item = elm_toolbar_item_append(m_Tabbar, nullptr, nullptr, nullptr, nullptr);
- ScrollPage *page = new ScrollPage(item, m_Pages.size());
- m_Pages.push_back(page);
-
- Evas_Object *layout = page->create(getEvasObject());
- page->setContent("elm.swallow.content", view->create(layout));
+ auto page = static_cast<ScrollPage *>(TabNavigator::addPage(view));
evas_object_size_hint_min_set(page->m_Sizer, m_Width, m_Height);
- elm_box_pack_end(m_Box, layout);
- evas_object_show(layout);
-
+ elm_box_pack_end(m_Box, page->getEvasObject());
+ evas_object_show(page->getEvasObject());
return page;
}
-bool ScrollNavigator::removePage(NavigatorPage *page)
+ScrollPage *ScrollNavigator::createPage(View *view, Elm_Object_Item *item)
{
- if (m_Pages.size() == 1) {
- return false;
- }
-
- size_t index = static_cast<ScrollPage *>(page)->m_Index;
- m_Pages.erase(m_Pages.begin() + index);
-
- for (; index < m_Pages.size(); ++index) {
- --(m_Pages[index]->m_Index);
- }
-
- delete page;
- return true;
+ return new ScrollPage(item);
}
-void ScrollNavigator::navigateToPage(NavigatorPage *page)
+void ScrollNavigator::changePage(TabPage *page)
{
- if (!m_IsNavigationEnabled) {
- return;
- }
-
- m_IsNavigating = true;
-
+ size_t pageIndex = getPageIndex(page);
size_t currentIndex = 0;
elm_scroller_current_page_get(m_Scroller, (int *) ¤tIndex, nullptr);
- ScrollPage *tabPage = static_cast<ScrollPage *>(page);
- if (currentIndex != tabPage->m_Index) {
- elm_scroller_page_show(m_Scroller, tabPage->m_Index, 0);
- }
- if (!elm_toolbar_item_selected_get(tabPage->getTabItem())) {
- elm_toolbar_item_selected_set(tabPage->getTabItem(), EINA_TRUE);
+ if (currentIndex != pageIndex) {
+ elm_scroller_page_show(m_Scroller, pageIndex, 0);
}
- setCurrentPage(tabPage);
+}
- m_IsNavigating = false;
+size_t ScrollNavigator::getPageIndex(TabPage *page) const
+{
+ Eina_List *list = elm_box_children_get(m_Box);
+ size_t index = eina_list_data_idx(list, page->getEvasObject());
+ eina_list_free(list);
+ return index;
}
-void ScrollNavigator::onTabSelected(Evas_Object *obj, Elm_Object_Item *selectedItem)
+TabPage *ScrollNavigator::getPageByIndex(size_t index) const
{
- if (!m_IsNavigating) {
- ScrollPage *page = (ScrollPage *) elm_object_item_data_get(selectedItem);
- if (page) {
- navigateTo(page->getView());
- }
- }
+ Eina_List *list = elm_box_children_get(m_Box);
+ Evas_Object *obj = (Evas_Object *) eina_list_nth(list, index);
+ eina_list_free(list);
+ return static_cast<TabPage *>(Control::getControl(obj));
}
void ScrollNavigator::onPageChanged(Evas_Object *obj, void *eventInfo)
{
- if (!m_IsNavigating) {
- int index = 0;
- elm_scroller_current_page_get(m_Scroller, &index, nullptr);
- navigateTo(m_Pages[index]->getView());
+ /* Page count might be invalid until scroller is properly resized,
+ so we cannot reliably use page index at that point */
+ size_t count = 0;
+ elm_scroller_last_page_get(m_Scroller, (int *) &count, nullptr);
+ if (count + 1 != getPages().size()) {
+ return;
+ }
+
+ size_t index = 0;
+ elm_scroller_current_page_get(m_Scroller, (int *) &index, nullptr);
+ if (auto page = getPageByIndex(index)) {
+ navigateTo(page->getView());
}
}
void ScrollNavigator::onResize(Evas *e, Evas_Object *obj, void *eventInfo)
{
evas_object_geometry_get(obj, nullptr, nullptr, &m_Width, &m_Height);
- for (auto &&page : m_Pages) {
- evas_object_size_hint_min_set(page->m_Sizer, m_Width, m_Height);
+ for (auto &&page : getPages()) {
+ auto scrollPage = static_cast<ScrollPage *>(page);
+ evas_object_size_hint_min_set(scrollPage->m_Sizer, m_Width, m_Height);
}
if (auto page = static_cast<ScrollPage *>(getCurrentPage())) {
- m_IsNavigating = true;
- elm_scroller_page_show(m_Scroller, page->m_Index, 0);
- m_IsNavigating = false;
+ elm_scroller_page_show(m_Scroller, getPageIndex(page), 0);
}
}