menu: reduce indirection

This commit is contained in:
Andrzej Rybczak
2015-05-08 21:42:09 +02:00
parent 173d23dde6
commit 4d552bef58
2 changed files with 15 additions and 40 deletions

View File

@@ -37,8 +37,6 @@ namespace NC {
/// holding any std::vector compatible values. /// holding any std::vector compatible values.
template <typename ItemT> class Menu : public Window template <typename ItemT> class Menu : public Window
{ {
struct ItemProxy;
public: public:
struct Item struct Item
{ {
@@ -82,16 +80,8 @@ public:
bool m_is_separator; bool m_is_separator;
}; };
typedef boost::indirect_iterator< typedef typename std::vector<Item>::iterator Iterator;
typename std::vector<ItemProxy>::iterator, typedef typename std::vector<Item>::const_iterator ConstIterator;
Item,
boost::random_access_traversal_tag
> Iterator;
typedef boost::indirect_iterator<
typename std::vector<ItemProxy>::const_iterator,
const Item,
boost::random_access_traversal_tag
> 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;
@@ -226,20 +216,20 @@ public:
/// @param pos requested position /// @param pos requested position
/// @return reference to item at given position /// @return reference to item at given position
/// @throw std::out_of_range if given position is out of range /// @throw std::out_of_range if given position is out of range
Menu<ItemT>::Item &at(size_t pos) { return *m_items.at(pos); } Menu<ItemT>::Item &at(size_t pos) { return m_items.at(pos); }
/// @param pos requested position /// @param pos requested position
/// @return const reference to item at given position /// @return const reference to item at given position
/// @throw std::out_of_range if given position is out of range /// @throw std::out_of_range if given position is out of range
const Menu<ItemT>::Item &at(size_t pos) const { return *m_items.at(pos); } const Menu<ItemT>::Item &at(size_t pos) const { return m_items.at(pos); }
/// @param pos requested position /// @param pos requested position
/// @return const reference to item at given position /// @return const reference to item at given position
const Menu<ItemT>::Item &operator[](size_t pos) const { return *m_items[pos]; } const Menu<ItemT>::Item &operator[](size_t pos) const { return m_items[pos]; }
/// @param pos requested position /// @param pos requested position
/// @return const reference to item at given position /// @return const reference to item at given position
Menu<ItemT>::Item &operator[](size_t pos) { return *m_items[pos]; } Menu<ItemT>::Item &operator[](size_t pos) { return m_items[pos]; }
Iterator current() { return Iterator(m_items.begin() + m_highlight); } Iterator current() { return Iterator(m_items.begin() + m_highlight); }
ConstIterator current() const { return ConstIterator(m_items.begin() + m_highlight); } ConstIterator current() const { return ConstIterator(m_items.begin() + m_highlight); }
@@ -272,31 +262,16 @@ public:
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>(std::move(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_items[pos]->isSeparator() return !m_items[pos].isSeparator()
&& !m_items[pos]->isInactive(); && !m_items[pos].isInactive();
} }
ItemDisplayer m_item_displayer; ItemDisplayer m_item_displayer;
std::vector<ItemProxy> m_items; std::vector<Item> m_items;
size_t m_beginning; size_t m_beginning;
size_t m_highlight; size_t m_highlight;

View File

@@ -191,12 +191,12 @@ void Menu<ItemT>::refresh()
mvwhline(m_window, line, 0, KEY_SPACE, m_width); mvwhline(m_window, line, 0, KEY_SPACE, m_width);
break; break;
} }
if (m_items[i]->isSeparator()) if (m_items[i].isSeparator())
{ {
mvwhline(m_window, line, 0, 0, m_width); mvwhline(m_window, line, 0, 0, m_width);
continue; continue;
} }
if (m_items[i]->isBold()) if (m_items[i].isBold())
*this << Format::Bold; *this << Format::Bold;
if (m_highlight_enabled && i == m_highlight) if (m_highlight_enabled && i == m_highlight)
{ {
@@ -204,18 +204,18 @@ void Menu<ItemT>::refresh()
*this << m_highlight_color; *this << m_highlight_color;
} }
mvwhline(m_window, line, 0, KEY_SPACE, m_width); mvwhline(m_window, line, 0, KEY_SPACE, m_width);
if (m_items[i]->isSelected()) if (m_items[i].isSelected())
*this << m_selected_prefix; *this << m_selected_prefix;
if (m_item_displayer) if (m_item_displayer)
m_item_displayer(*this); m_item_displayer(*this);
if (m_items[i]->isSelected()) if (m_items[i].isSelected())
*this << m_selected_suffix; *this << m_selected_suffix;
if (m_highlight_enabled && i == m_highlight) if (m_highlight_enabled && i == m_highlight)
{ {
*this << Color::End; *this << Color::End;
*this << Format::NoReverse; *this << Format::NoReverse;
} }
if (m_items[i]->isBold()) if (m_items[i].isBold())
*this << Format::NoBold; *this << Format::NoBold;
} }
Window::refresh(); Window::refresh();