menu: use shared pointers internally

This commit is contained in:
Andrzej Rybczak
2012-09-09 16:25:20 +02:00
parent 96315cfdba
commit 3ba94edca7

View File

@@ -24,6 +24,7 @@
#include <cassert> #include <cassert>
#include <functional> #include <functional>
#include <iterator> #include <iterator>
#include <memory>
#include <set> #include <set>
#include "error.h" #include "error.h"
@@ -35,11 +36,14 @@ namespace NC {
/// This template class is generic menu capable of /// This template class is generic menu capable of
/// holding any std::vector compatible values. /// holding any std::vector compatible values.
template <typename T> struct Menu : public Window template <typename T> class Menu : public Window
{ {
struct ItemProxy;
public:
struct Item struct Item
{ {
friend struct Menu<T>; friend class Menu<T>;
Item() Item()
: m_is_bold(false), m_is_selected(false), m_is_inactive(false), m_is_separator(false) { } : m_is_bold(false), m_is_selected(false), m_is_inactive(false), m_is_separator(false) { }
@@ -60,11 +64,11 @@ template <typename T> struct Menu : public Window
bool isSeparator() const { return m_is_separator; } bool isSeparator() const { return m_is_separator; }
private: private:
static Item *mkSeparator() static Item mkSeparator()
{ {
Item *i = new Item; Item item;
i->m_is_separator = true; item.m_is_separator = true;
return i; return item;
} }
T m_value; T m_value;
@@ -77,7 +81,7 @@ template <typename T> struct Menu : public Window
template <typename ValueT, typename BaseIterator> class ItemIterator template <typename ValueT, typename BaseIterator> class ItemIterator
: public std::iterator<std::random_access_iterator_tag, ValueT> : public std::iterator<std::random_access_iterator_tag, ValueT>
{ {
friend struct Menu<T>; friend class Menu<T>;
BaseIterator m_it; BaseIterator m_it;
explicit ItemIterator(BaseIterator it) : m_it(it) { } explicit ItemIterator(BaseIterator it) : m_it(it) { }
@@ -87,7 +91,7 @@ template <typename T> struct Menu : public Window
// version to be instantiated. // version to be instantiated.
static const bool referenceValue = !std::is_same< static const bool referenceValue = !std::is_same<
typename std::remove_const<ValueT>::type, typename std::remove_const<ValueT>::type,
typename std::remove_pointer<typename BaseIterator::value_type>::type typename BaseIterator::value_type::element_type
>::value; >::value;
template <typename Result, bool referenceValue> struct getObject { }; template <typename Result, bool referenceValue> struct getObject { };
template <typename Result> struct getObject<Result, true> { template <typename Result> struct getObject<Result, true> {
@@ -144,20 +148,20 @@ template <typename T> struct Menu : public Window
}; };
typedef ItemIterator< typedef ItemIterator<
Item, typename std::vector<Item *>::iterator Item, typename std::vector<ItemProxy>::iterator
> Iterator; > Iterator;
typedef ItemIterator< typedef ItemIterator<
const Item, typename std::vector<Item *>::const_iterator const Item, typename std::vector<ItemProxy>::const_iterator
> ConstIterator; > ConstIterator;
typedef std::reverse_iterator<Iterator> ReverseIterator; typedef std::reverse_iterator<Iterator> ReverseIterator;
typedef std::reverse_iterator<ConstIterator> ConstReverseIterator; typedef std::reverse_iterator<ConstIterator> ConstReverseIterator;
typedef ItemIterator< typedef ItemIterator<
T, typename std::vector<Item *>::iterator T, typename std::vector<ItemProxy>::iterator
> ValueIterator; > ValueIterator;
typedef ItemIterator< typedef ItemIterator<
typename std::add_const<T>::type, typename std::vector<Item *>::const_iterator typename std::add_const<T>::type, typename std::vector<ItemProxy>::const_iterator
> ConstValueIterator; > ConstValueIterator;
typedef std::reverse_iterator<ValueIterator> ReverseValueIterator; typedef std::reverse_iterator<ValueIterator> ReverseValueIterator;
@@ -181,8 +185,8 @@ template <typename T> struct Menu : public Window
Menu(size_t startx, size_t starty, size_t width, size_t height, Menu(size_t startx, size_t starty, size_t width, size_t height,
const std::string &title, Color color, Border border); const std::string &title, Color color, Border border);
/// Destroys the object and frees memory Menu(const Menu &) = delete;
virtual ~Menu(); Menu &operator=(const Menu &) = delete;
/// Sets helper function that is responsible for displaying items /// Sets helper function that is responsible for displaying items
/// @param ptr function pointer that matches the ItemDisplayer prototype /// @param ptr function pointer that matches the ItemDisplayer prototype
@@ -399,6 +403,22 @@ template <typename T> struct Menu : public Window
ConstReverseValueIterator rendV() const { return ConstReverseValueIterator(beginV()); } ConstReverseValueIterator rendV() const { return ConstReverseValueIterator(beginV()); }
private: private:
struct ItemProxy
{
typedef Item element_type;
ItemProxy() { }
ItemProxy(Item &&item) : m_ptr(std::make_shared<Item>(item)) { }
Item &operator*() const { return *m_ptr; }
Item *operator->() const { return m_ptr.get(); }
bool operator==(const ItemProxy &rhs) const { return m_ptr == rhs.m_ptr; }
private:
std::shared_ptr<Item> m_ptr;
};
bool isHighlightable(size_t pos) bool isHighlightable(size_t pos)
{ {
return !(*m_options_ptr)[pos]->isSeparator() && !(*m_options_ptr)[pos]->isInactive(); return !(*m_options_ptr)[pos]->isSeparator() && !(*m_options_ptr)[pos]->isInactive();
@@ -409,9 +429,9 @@ private:
FilterFunction m_filter; FilterFunction m_filter;
FilterFunction m_searcher; FilterFunction m_searcher;
std::vector<Item *> *m_options_ptr; std::vector<ItemProxy> *m_options_ptr;
std::vector<Item *> m_options; std::vector<ItemProxy> m_options;
std::vector<Item *> m_filtered_options; std::vector<ItemProxy> m_filtered_options;
std::set<size_t> m_found_positions; std::set<size_t> m_found_positions;
size_t m_beginning; size_t m_beginning;
@@ -448,12 +468,6 @@ template <typename T> Menu<T>::Menu(size_t startx,
{ {
} }
template <typename T> Menu<T>::~Menu()
{
for (auto it = m_options.begin(); it != m_options.end(); ++it)
delete *it;
}
template <typename T> void Menu<T>::reserve(size_t size_) template <typename T> void Menu<T>::reserve(size_t size_)
{ {
m_options.reserve(size_); m_options.reserve(size_);
@@ -463,22 +477,18 @@ template <typename T> void Menu<T>::resizeList(size_t new_size)
{ {
if (new_size > m_options.size()) if (new_size > m_options.size())
{ {
size_t old_size = m_options.size();
m_options.resize(new_size); m_options.resize(new_size);
for (size_t i = 0; i < new_size; ++i) for (size_t i = old_size; i < new_size; ++i)
if (!m_options[i]) m_options[i] = Item();
m_options[i] = new Item();
} }
else if (new_size < m_options.size()) else
{
for (size_t i = new_size; i < m_options.size(); ++i)
delete m_options[i];
m_options.resize(new_size); m_options.resize(new_size);
} }
}
template <typename T> void Menu<T>::addItem(const T &item, bool is_bold, bool is_inactive) template <typename T> void Menu<T>::addItem(const T &item, bool is_bold, bool is_inactive)
{ {
m_options.push_back(new Item(item, is_bold, is_inactive)); m_options.push_back(Item(item, is_bold, is_inactive));
} }
template <typename T> void Menu<T>::addSeparator() template <typename T> void Menu<T>::addSeparator()
@@ -488,7 +498,7 @@ template <typename T> void Menu<T>::addSeparator()
template <typename T> void Menu<T>::insertItem(size_t pos, const T &item, bool is_bold, bool is_inactive) template <typename T> void Menu<T>::insertItem(size_t pos, const T &item, bool is_bold, bool is_inactive)
{ {
m_options.insert(m_options.begin()+pos, new Item(item, is_bold, is_inactive)); m_options.insert(m_options.begin()+pos, Item(item, is_bold, is_inactive));
} }
template <typename T> void Menu<T>::insertSeparator(size_t pos) template <typename T> void Menu<T>::insertSeparator(size_t pos)
@@ -680,8 +690,6 @@ template <typename T> void Menu<T>::reset()
template <typename T> void Menu<T>::clear() template <typename T> void Menu<T>::clear()
{ {
for (auto it = m_options.begin(); it != m_options.end(); ++it)
delete *it;
clearFilterResults(); clearFilterResults();
m_options.clear(); m_options.clear();
m_found_positions.clear(); m_found_positions.clear();