bool isInserted() const;
/**
+ * @return Whether the item is visible.
+ */
+ bool isVisible() const;
+
+ /**
* @return Whether the item is a group item.
*/
virtual bool isGroupItem() const { return false; }
* @brief Set item destruction callback.
* @param[in] callback Callback to be called before item is destroyed
*/
- void setDestroyCallback(SelectCallback callback);
+ void setDestroyCallback(DestroyCallback callback);
/**
* @brief Scroll to the item.
/**
* @brief Called whenever any item's state part needs to be updated
- * @details Genlist will emit signal "elm,state,x,active" or
- * "elm,state,x,passive" with part's name instead of 'x'.
+ * @details Genlist will emit signal "elm,state,x,active" or "elm,state,x,passive"
+ * with part's name instead of 'x'.
* @param[in] parent Parent genlist
* @param[in] part Name of the part
* @return EINA_TRUE for active, EINA_FALSE for passive
/**
* @brief Called when genlist filter is set using elm_genlist_filter_set().
- * @param[in] parent Parent genlist
* @param[in] filter Filter to compare with
* @return Whether the item satisfies the filter.
*/
- virtual Eina_Bool compare(Evas_Object *parent, void *filter) { return EINA_TRUE; }
+ virtual bool compare(void *filter) { return true; }
/**
* @brief Called after item was inserted into genlist.
virtual void onPop() { }
/**
+ * @brief Called when item visibility changes via pop() or compare() or
+ * insertion into container.
+ */
+ virtual void onVisibilityChanged(bool isVisible) { }
+
+ /**
* @brief Called when item is selected.
*/
virtual void onSelected() { }
virtual bool onLongpressed() { return false; }
/**
- * @brief Called when item is realized (became visible).
+ * @brief Called when item is realized (its content is created).
*/
virtual void onRealized() { }
/**
- * @brief Called when item is unrealized (became invisible)
- * and its text and content is deleted until it is realized again.
+ * @brief Called when item is unrealized and its text and content are
+ * deleted until it is realized again.
*/
virtual void onUnrealized() { }
virtual void onFocused() { }
private:
+ void updateVisibility();
+
friend class GenContainer;
void onInserted(Elm_Object_Item *item);
+ Eina_Bool onFiltered(Evas_Object *parent, void *filter);
void onDestroy(Evas_Object *genlist);
void onSelected(Elm_Object_Item *item);
Elm_Object_Item *m_Item;
bool m_Preserve;
+ bool m_IsMatching;
bool m_IsRealized;
+ bool m_IsVisible;
bool m_IsFocusPending;
bool m_IsLongpressed;
/**
* @brief Called when item's "checked" state changed in #SelectMulti mode.
- * @param[in] item Changed item
- * @param[in] isChecked Whether item is checked
- * @param[in] isSelectAll Whether item is being checked via "Select All"
+ * @param[in] item Changed item
+ * @param[in] isChecked Whether item is checked
+ * @param[in] isMultiChecked Whether item is being checked via "Select All"
* @return Whether item's state should be changed.
*/
- typedef std::function<bool(SelectItem *item, bool isChecked, bool isSelectAll)> CheckCallback;
+ typedef std::function<bool(SelectItem *item, bool isChecked, bool isMultiChecked)> CheckCallback;
/**
* @brief Called when selection limit is reached.
};
size_t getSelectMax() const;
+ bool isLimitReached() const;
bool isMaxSelected() const;
void updatePageTitle();
void updateDoneButtonState();
void updateSelectAllState();
- void updateSelectCount(CountChange change, SelectItem *item);
- void updateItemCount(CountChange change, SelectItem *item);
+ void updateTotalCount(CountChange change, SelectItem *item);
+ void updateTotalSelectCount(CountChange change, SelectItem *item);
+
+ void updateVisibleCount(CountChange change, SelectItem *item);
+ void updateVisibleSelectCount(CountChange change, SelectItem *item);
void createPageButtons(Ui::NavigatorPage *page);
void destroyPageButtons();
void onItemExcluded(SelectItem *item, bool isExcluded);
+ void onItemVisibilityChanged(SelectItem *item, bool isVisible);
void onItemSelected(SelectItem *item);
bool onItemChecked(SelectItem *item, bool isChecked);
bool onSelectAllChecked(bool isChecked);
Evas_Object *m_DoneButton;
Evas_Object *m_CancelButton;
- bool m_IsChecking;
+ bool m_IsMultiChecking;
size_t m_TotalCount;
- size_t m_SelectCount;
+ size_t m_TotalSelectCount;
+ size_t m_VisibleCount;
+ size_t m_VisibleSelectCount;
size_t m_SelectLimit;
bool m_IsEmptyResultAllowed;
using namespace std::placeholders;
SelectView::SelectView()
- : m_DoneButton(nullptr), m_CancelButton(nullptr), m_IsChecking(false),
- m_TotalCount(0), m_SelectCount(0), m_SelectLimit(0), m_IsEmptyResultAllowed(false),
- m_SelectMode(SelectNone), m_Strings{ nullptr }
+ : m_DoneButton(nullptr), m_CancelButton(nullptr), m_IsMultiChecking(false),
+ m_TotalCount(0), m_TotalSelectCount(0),
+ m_VisibleCount(0), m_VisibleSelectCount(0),
+ m_SelectLimit(0), m_IsEmptyResultAllowed(false), m_SelectMode(SelectNone),
+ m_Strings{ nullptr }
{
}
size_t SelectView::getSelectCount() const
{
- return m_SelectCount;
+ return m_TotalSelectCount;
}
const SelectView::SelectItems &SelectView::getSelectItems() const
m_SelectLimit = selectLimit;
if (m_SelectLimit) {
- m_IsChecking = true;
- for (size_t i = m_Items.size() - 1; m_SelectCount > m_SelectLimit; --i) {
+ m_IsMultiChecking = true;
+ for (size_t i = m_Items.size() - 1; m_TotalSelectCount > m_SelectLimit; --i) {
if (!m_Items[i]->isExcluded()) {
m_Items[i]->setChecked(false);
}
}
- m_IsChecking = false;
+ m_IsMultiChecking = false;
}
updateSelectAllState();
m_Items.push_back(item);
if (!item->isExcluded()) {
- updateItemCount(CountIncrement, item);
+ updateTotalCount(CountIncrement, item);
}
}
m_Items.erase(it);
if (!item->isExcluded()) {
- updateItemCount(CountDecrement, item);
+ updateTotalCount(CountDecrement, item);
}
item->m_SelectView = nullptr;
}
size_t SelectView::getSelectMax() const
{
- if (m_SelectLimit && m_SelectLimit < m_TotalCount) {
+ if (m_SelectLimit && m_SelectLimit < m_VisibleCount) {
return m_SelectLimit;
}
- return m_TotalCount;
+ return m_VisibleCount;
+}
+
+bool SelectView::isLimitReached() const
+{
+ return m_SelectLimit && m_TotalSelectCount == m_SelectLimit;
}
bool SelectView::isMaxSelected() const
{
- return m_SelectCount == getSelectMax();
+ return m_VisibleSelectCount == getSelectMax();
}
void SelectView::updatePageTitle()
break;
case SelectMulti:
if (m_SelectLimit) {
- snprintf(buffer, sizeof(buffer), _(m_Strings.titleWithLimit), m_SelectCount, m_SelectLimit);
+ snprintf(buffer, sizeof(buffer), _(m_Strings.titleWithLimit), m_TotalSelectCount, m_SelectLimit);
title = buffer;
- } else if (m_SelectCount) {
- snprintf(buffer, sizeof(buffer), _(m_Strings.titleWithCount), m_SelectCount);
+ } else if (m_TotalSelectCount) {
+ snprintf(buffer, sizeof(buffer), _(m_Strings.titleWithCount), m_TotalSelectCount);
title = buffer;
} else {
title = m_Strings.titleMulti;
void SelectView::updateSelectAllItem()
{
- if (m_SelectMode == SelectMulti && m_TotalCount) {
+ if (m_SelectMode == SelectMulti && m_VisibleCount) {
if (m_SelectAllItem.expired()) {
SelectAllItem *item = new SelectAllItem(m_Strings.selectAll);
item->setCheckCallback(std::bind(&SelectView::onSelectAllChecked, this, _1));
void SelectView::updateDoneButtonState()
{
elm_object_disabled_set(m_DoneButton,
- m_IsEmptyResultAllowed ? m_TotalCount == 0 : m_SelectCount == 0);
+ m_IsEmptyResultAllowed ? m_TotalCount == 0 : m_TotalSelectCount == 0);
}
void SelectView::updateSelectAllState()
}
}
-void SelectView::updateSelectCount(CountChange change, SelectItem *item)
+void SelectView::updateTotalCount(CountChange change, SelectItem *item)
{
- /* CURRENT count if incremented, PREVIOUS count otherwise */
- size_t checkCount = (change == CountIncrement) ? ++m_SelectCount : m_SelectCount--;
- onSelectCountChanged(m_SelectCount);
+ (change == CountIncrement) ? ++m_TotalCount : --m_TotalCount;
- if (m_SelectLimit && m_SelectCount > m_SelectLimit) {
- item->setChecked(false);
- return;
+ if (item->isChecked()) {
+ updateTotalSelectCount(change, item);
}
+ if (item->isVisible()) {
+ updateVisibleCount(change, item);
+ }
+}
- /* Prevent updating if multiple checking is in progress */
- if (m_IsChecking) {
+void SelectView::updateTotalSelectCount(CountChange change, SelectItem *item)
+{
+ (change == CountIncrement) ? ++m_TotalSelectCount : --m_TotalSelectCount;
+ onSelectCountChanged(m_TotalSelectCount);
+
+ if (m_SelectLimit && m_TotalSelectCount > m_SelectLimit) {
+ item->setChecked(false);
return;
}
- /* m_SelectCount: (all - 1) -> all or all -> (all - 1) */
- if (checkCount == getSelectMax()) {
- updateSelectAllState();
- }
- /* m_SelectCount: 0 -> 1 or 1 -> 0 */
- if (checkCount == 1) {
- updateDoneButtonState();
+ updateDoneButtonState();
+ /* Prevent updating if multiple checking is in progress (performance optimization) */
+ if (!m_IsMultiChecking) {
+ updatePageTitle();
}
-
- updatePageTitle();
}
-void SelectView::updateItemCount(CountChange change, SelectItem *item)
+void SelectView::updateVisibleCount(CountChange change, SelectItem *item)
{
- /* PREVIOUS count if incremented, CURRENT count otherwise */
- size_t checkCount = (change == CountIncrement) ? m_TotalCount++ : --m_TotalCount;
+ (change == CountIncrement) ? ++m_VisibleCount : --m_VisibleCount;
if (item->isChecked()) {
- updateSelectCount(change, item);
+ updateVisibleSelectCount(change, item);
}
- /* (all checked -> unchecked inserted) or (one unchecked -> unchecked removed) */
- if (checkCount == m_SelectCount) {
- updateSelectAllState();
- }
- /* m_TotalCount: 0 -> 1 or 1 -> 0 */
- if (checkCount == 0) {
- updateDoneButtonState();
- updateSelectAllItem();
- }
+ updateSelectAllItem();
+}
+
+void SelectView::updateVisibleSelectCount(CountChange change, SelectItem *item)
+{
+ (change == CountIncrement) ? ++m_VisibleSelectCount : --m_VisibleSelectCount;
+ updateSelectAllState();
}
void SelectView::createPageButtons(Ui::NavigatorPage *page)
void SelectView::onItemExcluded(SelectItem *item, bool isExcluded)
{
- updateItemCount(isExcluded ? CountDecrement : CountIncrement, item);
+ updateTotalCount(isExcluded ? CountDecrement : CountIncrement, item);
+}
+
+void SelectView::onItemVisibilityChanged(SelectItem *item, bool isVisible)
+{
+ updateVisibleCount(isVisible ? CountIncrement : CountDecrement, item);
}
void SelectView::onItemSelected(SelectItem *item)
bool SelectView::onItemChecked(SelectItem *item, bool isChecked)
{
- if (isChecked && isMaxSelected()) {
+ if (isChecked && isLimitReached()) {
onLimitReached();
return false;
}
- if (m_OnChecked && !m_OnChecked(item, isChecked, m_IsChecking)) {
+ if (m_OnChecked && !m_OnChecked(item, isChecked, m_IsMultiChecking)) {
return false;
}
- updateSelectCount(isChecked ? CountIncrement : CountDecrement, item);
+ CountChange change = isChecked ? CountIncrement : CountDecrement;
+ updateTotalSelectCount(change, item);
+ if (item->isVisible()) {
+ updateVisibleSelectCount(change, item);
+ }
return true;
}
return true;
}
- m_IsChecking = true;
+ m_IsMultiChecking = true;
for (auto &&item : m_Items) {
- if (!item->isExcluded()) {
+ if (!item->isExcluded() && item->isVisible()) {
if (!item->setChecked(isChecked)) {
break;
}
}
}
- m_IsChecking = false;
+ m_IsMultiChecking = false;
updatePageTitle();
- updateDoneButtonState();
return isChecked == isMaxSelected();
}