Resurrect filtering of lists (playlist only for now)

This commit is contained in:
Andrzej Rybczak
2016-11-13 00:21:25 +01:00
parent 60e66b47b6
commit 29b1813c6d
14 changed files with 360 additions and 127 deletions

View File

@@ -21,7 +21,6 @@
#ifndef NCMPCPP_MENU_H
#define NCMPCPP_MENU_H
#include <boost/iterator/indirect_iterator.hpp>
#include <boost/iterator/transform_iterator.hpp>
#include <boost/range/detail/any_iterator.hpp>
#include <cassert>
@@ -96,9 +95,6 @@ struct List
bool isInactive() const { return m_properties & Inactive; }
bool isSeparator() const { return m_properties & Separator; }
protected:
unsigned properties() const { return m_properties; }
private:
unsigned m_properties;
};
@@ -154,51 +150,93 @@ inline List::ConstIterator begin(const List &list) { return list.beginP(); }
inline List::Iterator end(List &list) { return list.endP(); }
inline List::ConstIterator end(const List &list) { return list.endP(); }
/// This template class is generic menu capable of
/// holding any std::vector compatible values.
template <typename ItemT> struct Menu : Window, List
/// Generic menu capable of holding any std::vector compatible values.
template <typename ItemT>
struct Menu: Window, List
{
struct Item : List::Properties
struct Item
{
template <bool Const>
struct PropertiesExtractor
{
typedef PropertiesExtractor type;
typedef typename std::conditional<Const, const Properties, Properties>::type Properties_;
typedef typename std::conditional<Const, const Item, Item>::type Item_;
Properties_ &operator()(Item_ &i) const {
return static_cast<Properties_ &>(i);
}
};
friend struct Menu<ItemT>;
typedef ItemT Type;
friend struct Menu<ItemT>;
Item()
: m_value(std::make_shared<ItemT>(ItemT()))
: m_impl(std::make_shared<std::tuple<ItemT, Properties>>())
{ }
template <typename ValueT>
Item(ValueT &&value_, Properties::Type properties)
: Properties(properties)
, m_value(std::make_shared<ItemT>(std::forward<ValueT>(value_)))
template <typename ValueT, typename PropertiesT>
Item(ValueT &&value_, PropertiesT properties_)
: m_impl(
std::make_shared<std::tuple<ItemT, List::Properties>>(
std::forward<ValueT>(value_),
std::forward<PropertiesT>(properties_)))
{ }
ItemT &value() { return *m_value; }
const ItemT &value() const { return *m_value; }
ItemT &operator*() { return *m_value; }
const ItemT &operator*() const { return *m_value; }
ItemT &value() { return std::get<0>(*m_impl); }
const ItemT &value() const { return std::get<0>(*m_impl); }
Properties &properties() { return std::get<1>(*m_impl); }
const Properties &properties() const { return std::get<1>(*m_impl); }
// Forward methods to List::Properties.
void setBold (bool is_bold) { properties().setBold(is_bold); }
void setSelectable(bool is_selectable) { properties().setSelectable(is_selectable); }
void setSelected (bool is_selected) { properties().setSelected(is_selected); }
void setInactive (bool is_inactive) { properties().setInactive(is_inactive); }
void setSeparator (bool is_separator) { properties().setSeparator(is_separator); }
bool isBold() const { return properties().isBold(); }
bool isSelectable() const { return properties().isSelectable(); }
bool isSelected() const { return properties().isSelected(); }
bool isInactive() const { return properties().isInactive(); }
bool isSeparator() const { return properties().isSeparator(); }
// Make a deep copy of Item.
Item copy() const {
return Item(*m_value, static_cast<Properties::Type>(properties()));
return Item(value(), properties());
}
private:
enum class Const { Yes, No };
template <Const const_>
struct ExtractProperties
{
typedef ExtractProperties type;
typedef typename std::conditional<
const_ == Const::Yes,
const Properties,
Properties>::type Properties_;
typedef typename std::conditional<
const_ == Const::Yes,
const Item,
Item>::type Item_;
Properties_ &operator()(Item_ &i) const {
return i.properties();
}
};
template <Const const_>
struct ExtractValue
{
typedef ExtractValue type;
typedef typename std::conditional<
const_ == Const::Yes,
const ItemT,
ItemT>::type Value_;
typedef typename std::conditional<
const_ == Const::Yes,
const Item,
Item>::type Item_;
Value_ &operator()(Item_ &i) const {
return i.value();
}
};
static Item mkSeparator()
{
Item item;
@@ -207,7 +245,7 @@ template <typename ItemT> struct Menu : Window, List
return item;
}
std::shared_ptr<ItemT> m_value;
std::shared_ptr<std::tuple<ItemT, Properties>> m_impl;
};
typedef typename std::vector<Item>::iterator Iterator;
@@ -215,33 +253,29 @@ template <typename ItemT> struct Menu : Window, List
typedef std::reverse_iterator<Iterator> ReverseIterator;
typedef std::reverse_iterator<ConstIterator> ConstReverseIterator;
typedef boost::indirect_iterator<
Iterator,
ItemT,
boost::random_access_traversal_tag
> ValueIterator;
typedef boost::indirect_iterator<
ConstIterator,
const ItemT,
boost::random_access_traversal_tag
> ConstValueIterator;
typedef boost::transform_iterator<
typename Item::template ExtractValue<Item::Const::No>,
Iterator> ValueIterator;
typedef boost::transform_iterator<
typename Item::template ExtractValue<Item::Const::Yes>,
ConstIterator> ConstValueIterator;
typedef std::reverse_iterator<ValueIterator> ReverseValueIterator;
typedef std::reverse_iterator<ConstValueIterator> ConstReverseValueIterator;
typedef boost::transform_iterator<
typename Item::template PropertiesExtractor<false>,
Iterator
> PropertiesIterator;
typename Item::template ExtractProperties<Item::Const::No>,
Iterator> PropertiesIterator;
typedef boost::transform_iterator<
typename Item::template PropertiesExtractor<true>,
ConstIterator
> ConstPropertiesIterator;
typename Item::template ExtractProperties<Item::Const::Yes>,
ConstIterator> ConstPropertiesIterator;
/// Function helper prototype used to display each option on the screen.
/// If not set by setItemDisplayer(), menu won't display anything.
/// @see setItemDisplayer()
typedef std::function<void(Menu<ItemT> &)> ItemDisplayer;
typedef std::function<bool(const Item &)> FilterPredicate;
Menu();
Menu(size_t startx, size_t starty, size_t width, size_t height,
@@ -253,7 +287,8 @@ template <typename ItemT> struct Menu : Window, List
/// Sets helper function that is responsible for displaying items
/// @param ptr function pointer that matches the ItemDisplayer prototype
void setItemDisplayer(const ItemDisplayer &f) { m_item_displayer = f; }
template <typename ItemDisplayerT>
void setItemDisplayer(ItemDisplayerT &&displayer);
/// Resizes the list to given size (adequate to std::vector::resize())
/// @param size requested size
@@ -309,8 +344,15 @@ template <typename ItemT> struct Menu : Window, List
/// Apply filter predicate to items in the menu and show the ones for which it
/// returned true.
template <typename FilterPredicate>
bool applyFilter(FilterPredicate &&p);
template <typename PredicateT>
void applyFilter(PredicateT &&pred);
/// Reapply previously applied filter.
void reapplyFilter();
/// Get current filter predicate.
template <typename TargetT>
const TargetT *filterPredicate() const;
/// Clear results of applyFilter and show all items.
void clearFilter();
@@ -451,9 +493,10 @@ private:
return !(*m_items)[pos].isSeparator()
&& !(*m_items)[pos].isInactive();
}
ItemDisplayer m_item_displayer;
FilterPredicate m_filter_predicate;
std::vector<Item> *m_items;
std::vector<Item> m_all_items;
std::vector<Item> m_filtered_items;