--- /dev/null
+/*
+ * Copyright 2017 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 __UCL_MVP_LIST_PRESENTER_H__
+#define __UCL_MVP_LIST_PRESENTER_H__
+
+#include "ucl/gui/Genlist.h"
+
+#include "GuiPresenter.h"
+#include "ListItemPresenter.h"
+
+namespace ucl {
+
+ UCL_DECLARE_REF_ALIASES(ListPresenter);
+
+ class ListPresenter final : public GuiPresenter {
+ public:
+ enum {
+ FLAG_HOMOGENEOUS = (1 << 0),
+ FLAG_CALC_X_MIN = (1 << 1),
+ FLAG_CALC_Y_MIN = (1 << 2),
+
+ FLAG_NOTIFY_REALIZED = (1 << 8),
+ FLAG_NOTIFY_UNREALIZED = (1 << 9),
+ FLAG_NOTIFY_HIGHLIGHTED = (1 << 10),
+ FLAG_NOTIFY_UNHIGHLIGHTED = (1 << 11),
+ };
+
+ class Builder final {
+ public:
+ Builder();
+ Builder &setStyle(ElmStyle style);
+ Builder &setFlags(int flags);
+ Builder &setParentWidget(const ElmWidgetSRef &parentWidget);
+ ListPresenterSRef build(GuiPresenter &parent) const;
+ private:
+ ucl::ElmWidgetSRef m_parentWidget;
+ ElmStyle m_style;
+ int m_flags;
+ };
+
+ public:
+ Genlist &getWidget();
+
+ void clear();
+
+ Result append(ListItemPresenter &itemPresenter,
+ ListItemPresenter *parent = nullptr);
+
+ Result prepend(ListItemPresenter &itemPresenter,
+ ListItemPresenter *parent = nullptr);
+
+ Result insertAfter(const ListItemPresenter &after,
+ ListItemPresenter &itemPresenter,
+ ListItemPresenter *parent = nullptr);
+
+ Result insertBefore(const ListItemPresenter &before,
+ ListItemPresenter &itemPresenter,
+ ListItemPresenter *parent = nullptr);
+
+ private:
+ friend class ReffedObj<ListPresenter>;
+ ListPresenter(IRefCountObj &rc);
+ virtual ~ListPresenter();
+
+ Result prepare(GuiPresenter &parent, ElmWidget &parentWidget,
+ ElmStyle style, int flags);
+
+ template <class INSERT_FUNC>
+ Result insert(ListItemPresenter &itemPresenter,
+ ListItemPresenter *parent,
+ INSERT_FUNC &&insertFunc);
+
+ template <class INSERT_FUNC>
+ Result insertRelative(const ListItemPresenter &relative,
+ ListItemPresenter &itemPresenter,
+ ListItemPresenter *parent, INSERT_FUNC &&insertFunc);
+
+ void setIsActiveRef(bool value);
+
+ void onItemSelected(Widget &widget, void *eventInfo);
+
+ void onItemRealized(Widget &widget, void *eventInfo);
+ void onItemUnrealized(Widget &widget, void *eventInfo);
+ void onItemHighlighted(Widget &widget, void *eventInfo);
+ void onItemUnhighlighted(Widget &widget, void *eventInfo);
+
+ // GuiPresenter //
+
+ virtual void onActivate() final override;
+ virtual void onDeactivate() final override;
+
+ private:
+ GenlistSRef m_genlist;
+ ListItemPresenter::ItemClassCacheSRef m_itcCache;
+ SharedRef<bool> m_isActiveRef;
+ };
+}
+
+#endif // __UCL_MVP_LIST_PRESENTER_H__
--- /dev/null
+/*
+ * Copyright 2017 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 "ucl/mvp/ListPresenter.h"
+
+#include "common.h"
+
+namespace ucl { namespace { namespace impl {
+
+ constexpr SmartEvent ITEM_SELECTED {"selected"};
+
+ constexpr SmartEvent ITEM_REALIZED {"realized"};
+ constexpr SmartEvent ITEM_UNREALIZED {"unrealized"};
+ constexpr SmartEvent ITEM_HIGHLIGHTED {"highlighted"};
+ constexpr SmartEvent ITEM_UNHIGHLIGHTED {"unhighlighted"};
+
+ ListItemPresenter *toItemPresenter(void *eventInfo)
+ {
+ if (!eventInfo) {
+ LOG_RETURN_VALUE(RES_FATAL, nullptr, "eventInfo is NULL");
+ }
+
+ const GenlistItem item{static_cast<Elm_Object_Item *>(eventInfo)};
+ const auto data = item.getData();
+ if (!data) {
+ LOG_RETURN_VALUE(RES_FATAL, nullptr, "data is NULL");
+ }
+
+ return static_cast<ListItemPresenter *>(data);
+ }
+}}}
+
+namespace ucl {
+
+ // ListPresenter::Builder //
+
+ ListPresenter::Builder::Builder() :
+ m_flags(FLAG_HOMOGENEOUS)
+ {
+ }
+
+ ListPresenter::Builder &ListPresenter::Builder::setStyle(
+ const ElmStyle style)
+ {
+ m_style = style;
+ return *this;
+ }
+
+ ListPresenter::Builder &ListPresenter::Builder::setFlags(const int flags)
+ {
+ m_flags = flags;
+ return *this;
+ }
+
+ ListPresenter::Builder &ListPresenter::Builder::setParentWidget(
+ const ElmWidgetSRef &parentWidget)
+ {
+ m_parentWidget = parentWidget;
+ return *this;
+ }
+
+ ListPresenterSRef ListPresenter::Builder::build(GuiPresenter &parent) const
+ {
+ if (!m_parentWidget) {
+ LOG_RETURN_VALUE(RES_INVALID_ARGUMENTS, {},
+ "m_parentWidget is NULL!");
+ }
+
+ auto result = makeShared<ListPresenter>();
+
+ FAIL_RETURN_VALUE(result->prepare(
+ parent, *m_parentWidget, m_style, m_flags),
+ {}, "result->prepare() failed!");
+
+ return result;
+ }
+
+ // ListPresenter //
+
+ ListPresenter::ListPresenter(IRefCountObj &rc) :
+ GuiPresenter(rc)
+ {
+ }
+
+ ListPresenter::~ListPresenter()
+ {
+ }
+
+ Result ListPresenter::prepare(
+ GuiPresenter &parent, ElmWidget &parentWidget,
+ const ElmStyle style, const int flags)
+ {
+ FAIL_RETURN(GuiPresenter::prepare(parent, PF_DEACTIVATOR),
+ "GuiPresenter::prepare() failed!");
+
+ m_genlist = Genlist::Builder().
+ setStyle(style).
+ setMode(Genlist::Mode::COMPRESS).
+ setHomogeneous(flags & FLAG_HOMOGENEOUS).
+ setIsOwner(true).
+ setNeedBindToEo(true).
+ build(parentWidget);
+ if (!m_genlist) {
+ LOG_RETURN(RES_FAIL, "Genlist::build() failed!");
+ }
+
+ expandAndFill(*m_genlist);
+
+ // TODO Add Scroller widget.
+ elm_scroller_content_min_limit(*m_genlist,
+ toEina((flags & FLAG_CALC_X_MIN) != 0),
+ toEina((flags & FLAG_CALC_Y_MIN) != 0));
+
+ m_itcCache = makeShared<ListItemPresenter::ItemClassCache>();
+
+ m_isActiveRef = makeShared<bool>();
+ *m_isActiveRef = isActive();
+
+ m_genlist->addEventHandler(impl::ITEM_SELECTED, WEAK_DELEGATE(
+ ListPresenter::onItemSelected, asWeak(*this)));
+
+ if (flags & FLAG_NOTIFY_REALIZED) {
+ m_genlist->addEventHandler(impl::ITEM_REALIZED, WEAK_DELEGATE(
+ ListPresenter::onItemRealized, asWeak(*this)));
+ }
+ if (flags & FLAG_NOTIFY_UNREALIZED) {
+ m_genlist->addEventHandler(impl::ITEM_UNREALIZED, WEAK_DELEGATE(
+ ListPresenter::onItemUnrealized, asWeak(*this)));
+ }
+ if (flags & FLAG_NOTIFY_HIGHLIGHTED) {
+ m_genlist->addEventHandler(impl::ITEM_HIGHLIGHTED, WEAK_DELEGATE(
+ ListPresenter::onItemHighlighted, asWeak(*this)));
+ }
+ if (flags & FLAG_NOTIFY_UNHIGHLIGHTED) {
+ m_genlist->addEventHandler(impl::ITEM_UNHIGHLIGHTED, WEAK_DELEGATE(
+ ListPresenter::onItemUnhighlighted, asWeak(*this)));
+ }
+
+ return RES_OK;
+ }
+
+ Genlist &ListPresenter::getWidget()
+ {
+ return *m_genlist;
+ }
+
+ void ListPresenter::clear()
+ {
+ m_genlist->clear();
+ m_itcCache->purge();
+ }
+
+ Result ListPresenter::append(ListItemPresenter &itemPresenter,
+ ListItemPresenter *parent)
+ {
+ return insert(itemPresenter, parent,
+ [this](const Elm_Genlist_Item_Class *itc, const void *data,
+ GenlistItem parent, GenlistItem::Type type)
+ {
+ return m_genlist->append(itc, data, nullptr, type, parent);
+ });
+ }
+
+ Result ListPresenter::prepend(ListItemPresenter &itemPresenter,
+ ListItemPresenter *parent)
+ {
+ return insert(itemPresenter, parent,
+ [this](const Elm_Genlist_Item_Class *itc, const void *data,
+ GenlistItem parent, GenlistItem::Type type)
+ {
+ return m_genlist->prepend(itc, data, nullptr, type, parent);
+ });
+ }
+
+ Result ListPresenter::insertAfter(const ListItemPresenter &after,
+ ListItemPresenter &itemPresenter,
+ ListItemPresenter *parent)
+ {
+ return insertRelative(after, itemPresenter, parent,
+ [this](GenlistItem rel, const Elm_Genlist_Item_Class *itc,
+ const void *data, GenlistItem parent, GenlistItem::Type type)
+ {
+ return m_genlist->insertAfter(
+ rel, itc, data, nullptr, type, parent);
+ });
+ }
+
+ Result ListPresenter::insertBefore(const ListItemPresenter &before,
+ ListItemPresenter &itemPresenter,
+ ListItemPresenter *parent)
+ {
+ return insertRelative(before, itemPresenter, parent,
+ [this](GenlistItem rel, const Elm_Genlist_Item_Class *itc,
+ const void *data, GenlistItem parent, GenlistItem::Type type)
+ {
+ return m_genlist->insertBefore(
+ rel, itc, data, nullptr, type, parent);
+ });
+ }
+
+ template <class INSERT_FUNC>
+ Result ListPresenter::insert(ListItemPresenter &itemPresenter,
+ ListItemPresenter *parent, INSERT_FUNC &&insertFunc)
+ {
+ const auto params = itemPresenter.getItemInsertionParams();
+
+ const auto itc = m_itcCache->getItemClass(params.itemStyle);
+ if (!itc) {
+ LOG_RETURN(RES_FAIL, "m_itcCache.getItemClass() failed!");
+ }
+
+ GenlistItem parentItem;
+ if (parent) {
+ parentItem = parent->m_item;
+ if (!parentItem) {
+ ELOG("parentItem is NULL");
+ }
+ }
+
+ const auto item = insertFunc(itc->get(),
+ &itemPresenter, parentItem, params.itemType);
+ if (!item) {
+ LOG_RETURN(RES_FAIL, "insertFunc() failed!");
+ }
+
+ itemPresenter.attachItem(item, m_itcCache, m_isActiveRef);
+
+ return RES_OK;
+ }
+
+ template <class INSERT_FUNC>
+ Result ListPresenter::insertRelative(const ListItemPresenter &relative,
+ ListItemPresenter &itemPresenter, ListItemPresenter *parent,
+ INSERT_FUNC &&insertFunc)
+ {
+ const auto relItem = relative.m_item;
+ if (!relItem) {
+ LOG_RETURN(RES_FAIL, "relItem is NULL!");
+ }
+ if (relItem.getWidget() != m_genlist->getEo()) {
+ LOG_RETURN(RES_FAIL, "relItem has wrong genlist!");
+ }
+ return insert(itemPresenter, parent,
+ [relItem, &insertFunc](const Elm_Genlist_Item_Class *itc,
+ const void *data, GenlistItem parent, GenlistItem::Type type)
+ {
+ return insertFunc(relItem, itc, data, parent, type);
+ });
+ }
+
+ void ListPresenter::setIsActiveRef(const bool value)
+ {
+ if (!m_isActiveRef) {
+ LOG_RETURN_VOID(RES_FATAL, "m_isActiveRef is NULL");
+ }
+ *m_isActiveRef = value;
+ }
+
+ void ListPresenter::onItemSelected(Widget &widget, void *eventInfo)
+ {
+ const auto itemPresenter = impl::toItemPresenter(eventInfo);
+ if (!itemPresenter) {
+ LOG_RETURN_VOID(RES_FATAL, "itemPresenter is NULL");
+ }
+ itemPresenter->onItemSelectedHook();
+ }
+
+ void ListPresenter::onItemRealized(Widget &widget, void *eventInfo)
+ {
+ const auto itemPresenter = impl::toItemPresenter(eventInfo);
+ if (!itemPresenter) {
+ LOG_RETURN_VOID(RES_FATAL, "itemPresenter is NULL");
+ }
+ itemPresenter->onItemRealized();
+ }
+
+ void ListPresenter::onItemUnrealized(Widget &widget, void *eventInfo)
+ {
+ const auto itemPresenter = impl::toItemPresenter(eventInfo);
+ if (!itemPresenter) {
+ LOG_RETURN_VOID(RES_FATAL, "itemPresenter is NULL");
+ }
+ itemPresenter->onItemUnrealized();
+ }
+
+ void ListPresenter::onItemHighlighted(Widget &widget, void *eventInfo)
+ {
+ const auto itemPresenter = impl::toItemPresenter(eventInfo);
+ if (!itemPresenter) {
+ LOG_RETURN_VOID(RES_FATAL, "itemPresenter is NULL");
+ }
+ itemPresenter->onItemHighlighted();
+ }
+
+ void ListPresenter::onItemUnhighlighted(Widget &widget, void *eventInfo)
+ {
+ const auto itemPresenter = impl::toItemPresenter(eventInfo);
+ if (!itemPresenter) {
+ LOG_RETURN_VOID(RES_FATAL, "itemPresenter is NULL");
+ }
+ itemPresenter->onItemUnhighlighted();
+ }
+
+ void ListPresenter::onActivate()
+ {
+ setIsActiveRef(true);
+ }
+
+ void ListPresenter::onDeactivate()
+ {
+ setIsActiveRef(false);
+ }
+}