diff --git a/src/menu.cpp b/src/menu.cpp index c50ada64..37f3aec7 100644 --- a/src/menu.cpp +++ b/src/menu.cpp @@ -20,7 +20,7 @@ #include "menu.h" -using namespace NCurses; +namespace NCurses { template <> std::string Menu::GetItem(size_t pos) { @@ -34,3 +34,5 @@ template <> std::string Menu::GetItem(size_t pos) } return result; } + +} diff --git a/src/menu.h b/src/menu.h index e3776160..8e6bdf1e 100644 --- a/src/menu.h +++ b/src/menu.h @@ -30,583 +30,581 @@ #include "window.h" #include "strbuffer.h" -namespace NCurses -{ - /// List class is an interface for Menu class - /// - class List - { - public: - /// @see Menu::Select() - /// - virtual void Select(int pos, bool state) = 0; - - /// @see Menu::isSelected() - /// - virtual bool isSelected(int pos = -1) const = 0; - - /// @see Menu::hasSelected() - /// - virtual bool hasSelected() const = 0; - - /// @see Menu::GetSelected() - /// - virtual void GetSelected(std::vector &v) const = 0; - - /// Highlights given position - /// @param pos position to be highlighted - /// - virtual void Highlight(size_t pos) = 0; - - /// @return currently highlighted position - /// - virtual size_t Choice() const = 0; - - /// @see Menu::Empty() - /// - virtual bool Empty() const = 0; - - /// @see Menu::Size() - /// - virtual size_t Size() const = 0; - - /// @see Menu::Search() - /// - virtual bool Search(const std::string &constraint, size_t beginning = 0, int flags = 0) = 0; - - /// @see Menu::GetSearchConstraint() - /// - virtual const std::string &GetSearchConstraint() = 0; - - /// @see Menu::NextFound() - /// - virtual void NextFound(bool wrap) = 0; - - /// @see Menu::PrevFound() - /// - virtual void PrevFound(bool wrap) = 0; - - /// @see Menu::ApplyFilter() - /// - virtual void ApplyFilter(const std::string &filter, size_t beginning = 0, int flags = 0) = 0; - - /// @see Menu::GetFilter() - /// - virtual const std::string &GetFilter() = 0; - - /// @see Menu::isFiltered() - /// - virtual bool isFiltered() = 0; - }; - - /// This template class is generic menu capable of - /// holding any std::vector compatible values. - /// - template struct Menu : public Window, public List - { - /// 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 &, const T &)> ItemDisplayer; - - /// Function helper prototype used for converting items to strings. - /// If not set by SetItemStringifier(), searching and filtering - /// won't work (note that Menu doesn't need this) - /// @see SetItemStringifier() - /// - typedef std::function ItemStringifier; - - /// Struct that holds each item in the list and its attributes - /// - struct Item - { - Item() : isBold(0), isSelected(0), isStatic(0) { } - Item(const T &t, bool is_bold, bool is_static) : - Value(t), isBold(is_bold), isSelected(0), isStatic(is_static) { } - - T Value; - bool isBold; - bool isSelected; - bool isStatic; - }; - - template class ItemIterator - : public std::iterator - { - friend class Menu; - - BaseIterator m_it; - explicit ItemIterator(BaseIterator it) : m_it(it) { } - - static const bool referenceValue = !std::is_same< - ValueT, typename std::remove_pointer< - typename BaseIterator::value_type - >::type - >::value; - template struct getObject { }; - template struct getObject { - static Result &apply(BaseIterator it) { return (*it)->Value; } - }; - template struct getObject { - static Result &apply(BaseIterator it) { return **it; } - }; - - public: - ItemIterator() { } - - ValueT &operator*() const { return getObject::apply(m_it); } - typename BaseIterator::value_type operator->() { return *m_it; } - - ItemIterator &operator++() { ++m_it; return *this; } - ItemIterator operator++(int) { return ItemIterator(m_it++); } - - ItemIterator &operator--() { --m_it; return *this; } - ItemIterator operator--(int) { return ItemIterator(m_it--); } - - ValueT &operator[](ptrdiff_t n) const { - return getObject::apply(&m_it[n]); - } - - ItemIterator &operator+=(ptrdiff_t n) { m_it += n; return *this; } - ItemIterator operator+(ptrdiff_t n) const { return ItemIterator(m_it + n); } - - ItemIterator &operator-=(ptrdiff_t n) { m_it -= n; return *this; } - ItemIterator operator-(ptrdiff_t n) const { return ItemIterator(m_it - n); } - - ptrdiff_t operator-(const ItemIterator &rhs) const { return m_it - rhs.m_it; } - - template - bool operator==(const Iterator &rhs) const { return m_it == rhs.m_it; } - template - bool operator!=(const Iterator &rhs) const { return m_it != rhs.m_it; } - template - bool operator<(const Iterator &rhs) const { return m_it < rhs.m_it; } - template - bool operator<=(const Iterator &rhs) const { return m_it <= rhs.m_it; } - template - bool operator>(const Iterator &rhs) const { return m_it > rhs.m_it; } - template - bool operator>=(const Iterator &rhs) const { return m_it >= rhs.m_it; } - - /// non-const to const conversion - template operator ItemIterator< - typename std::add_const::type, Iterator - >() { return ItemIterator(m_it); } - - const BaseIterator &base() { return m_it; } - }; - - typedef ItemIterator< - T, typename std::vector::iterator - > Iterator; - - typedef ItemIterator< - typename std::add_const::type, typename std::vector::const_iterator - > ConstIterator; - - typedef std::reverse_iterator ReverseIterator; - typedef std::reverse_iterator ConstReverseIterator; - - /// Constructs an empty menu with given parameters - /// @param startx X position of left upper corner of constructed menu - /// @param starty Y position of left upper corner of constructed menu - /// @param width width of constructed menu - /// @param height height of constructed menu - /// @param title title of constructed menu - /// @param color base color of constructed menu - /// @param border border of constructed menu - /// - Menu(size_t startx, size_t starty, size_t width, size_t height, - const std::string &title, Color color, Border border); - - /// Copies the menu - /// @param m copied menu - /// - Menu(const Menu &m); - - /// Destroys the object and frees memory - /// - virtual ~Menu(); - - /// Sets helper function that is responsible for displaying items - /// @param ptr function pointer that matches the ItemDisplayer prototype - /// - void setItemDisplayer(ItemDisplayer ptr) { m_item_displayer = ptr; } - - /// Sets helper function that is responsible for converting items to strings - /// @param f function pointer that matches the ItemStringifier prototype - /// - void SetItemStringifier(ItemStringifier f) { m_get_string_helper = f; } - - /// Reserves the size for internal container (this just calls std::vector::reserve()) - /// @param size requested size - /// - void Reserve(size_t size); - - /// Resizes the list to given size (adequate to std::vector::resize()) - /// @param size requested size - /// - void ResizeList(size_t size); - - /// Adds new option to list - /// @param item object that has to be added - /// @param is_bold defines the initial state of bold attribute - /// @param is_static defines the initial state of static attribute - /// - void AddItem(const T &item, bool is_bold = 0, bool is_static = 0); - - /// Adds separator to list - /// - void AddSeparator(); - - /// Inserts new option to list at given position - /// @param pos initial position of inserted item - /// @param item object that has to be inserted - /// @param is_bold defines the initial state of bold attribute - /// @param is_static defines the initial state of static attribute - /// - void InsertItem(size_t pos, const T &Item, bool is_bold = 0, bool is_static = 0); - - /// Inserts separator to list at given position - /// @param pos initial position of inserted separator - /// - void InsertSeparator(size_t pos); - - /// Deletes item from given position - /// @param pos given position of item to be deleted - /// - void DeleteItem(size_t pos); - - /// Converts the option into separator - /// @param pos position of item to be converted - /// - void IntoSeparator(size_t pos); - - /// Swaps the content of two items - /// @param one position of first item - /// @param two position of second item - /// - void Swap(size_t one, size_t two); - - /// Moves requested item from one position to another - /// @param from the position of item that has to be moved - /// @param to the position that indicates where the object has to be moved - /// - void Move(size_t from, size_t to); - - /// Moves the highlighted position to the given line of window - /// @param y Y position of menu window to be highlighted - /// @return true if the position is reachable, false otherwise - /// - bool Goto(size_t y); - - /// Checks if the given position has bold attribute set. - /// @param pos position to be checked. -1 = currently highlighted position - /// @return true if the bold is set, false otherwise - /// - bool isBold(int pos = -1); - - /// Sets bols attribute for given position - /// @param pos position of item to be bolded/unbolded - /// @param state state of bold attribute - /// - void Bold(int pos, bool state); - - /// Makes given position static/active. - /// Static positions cannot be highlighted. - /// @param pos position in list - /// @param state state of activity - /// - void Static(int pos, bool state); - - /// Checks whether given position is static or active - /// @param pos position to be checked, -1 checks currently highlighted position - /// @return true if position is static, false otherwise - /// - bool isStatic(int pos = -1) const; - - /// Checks whether given position is separator - /// @param pos position to be checked, -1 checks currently highlighted position - /// @return true if position is separator, false otherwise - /// - bool isSeparator(int pos = -1) const; - - /// Selects/deselects given position - /// @param pos position in list - /// @param state state of selection - /// - virtual void Select(int pos, bool state); - - /// Checks if given position is selected - /// @param pos position to be checked, -1 checks currently highlighted position - /// @return true if position is selected, false otherwise - /// - virtual bool isSelected(int pos = -1) const; - - /// Checks whether list contains selected positions - /// @return true if it contains them, false otherwise - /// - virtual bool hasSelected() const; - - /// Gets positions of items that are selected - /// @param v vector to be filled with selected positions numbers - /// - virtual void GetSelected(std::vector &v) const; - - /// Reverses selection of all items in list - /// @param beginning beginning of range that has to be reversed - /// - void ReverseSelection(size_t beginning = 0); - - /// Highlights given position - /// @param pos position to be highlighted - /// - void Highlight(size_t pos); - - /// @return currently highlighted position - /// - size_t Choice() const; - - /// @return real current positions, i.e it doesn't - /// count positions that are static or separators - /// - size_t RealChoice() const; - - /// Searches the list for a given contraint. It uses ItemStringifier to convert stored items - /// into strings and then performs pattern matching. Note that this supports regular expressions. - /// @param constraint a search constraint to be used - /// @param beginning beginning of range that has to be searched through - /// @param flags regex flags (REG_EXTENDED, REG_ICASE, REG_NOSUB, REG_NEWLINE) - /// @return true if at least one item matched the given pattern, false otherwise - /// - virtual bool Search(const std::string &constraint, size_t beginning = 0, int flags = 0); - - /// @return const reference to currently used search constraint - /// - virtual const std::string &GetSearchConstraint() { return m_search_constraint; } - - /// Moves current position in the list to the next found one - /// @param wrap if true, this function will go to the first - /// found pos after the last one, otherwise it'll do nothing. - /// - virtual void NextFound(bool wrap); - - /// Moves current position in the list to the previous found one - /// @param wrap if true, this function will go to the last - /// found pos after the first one, otherwise it'll do nothing. - /// - virtual void PrevFound(bool wrap); - - /// Filters the list, showing only the items that matches the pattern. It uses - /// ItemStringifier to convert stored items into strings and then performs - /// pattern matching. Note that this supports regular expressions. - /// @param filter a pattern to be used in pattern matching - /// @param beginning beginning of range that has to be filtered - /// @param flags regex flags (REG_EXTENDED, REG_ICASE, REG_NOSUB, REG_NEWLINE) - /// - virtual void ApplyFilter(const std::string &filter, size_t beginning = 0, int flags = 0); - - /// @return const reference to currently used filter - /// - virtual const std::string &GetFilter(); - - /// @return true if list is currently filtered, false otherwise - /// - virtual bool isFiltered() { return m_options_ptr == &m_filtered_options; } - - /// Turns off filtering - /// - void ShowAll() { m_options_ptr = &m_options; } - - /// Turns on filtering - /// - void ShowFiltered() { m_options_ptr = &m_filtered_options; } - - /// Converts given position in list to string using ItemStringifier - /// if specified and an empty string otherwise - /// @param pos position to be converted - /// @return item converted to string - /// @see setItemDisplayer() - /// - std::string GetItem(size_t pos); - - /// Refreshes the menu window - /// @see Window::Refresh() - /// - virtual void Refresh(); - - /// Scrolls by given amount of lines - /// @param where indicated where exactly one wants to go - /// @see Window::Scroll() - /// - virtual void Scroll(Where where); - - /// Cleares all options, used filters etc. It doesn't reset highlighted position though. - /// @see Reset() - /// - virtual void Clear(); - - /// Sets the highlighted position to 0 - /// - void Reset(); - - /// Sets prefix, that is put before each selected item to indicate its selection - /// Note that the passed variable is not deleted along with menu object. - /// @param b pointer to buffer that contains the prefix - /// - void SetSelectPrefix(Buffer *b) { m_selected_prefix = b; } - - /// Sets suffix, that is put after each selected item to indicate its selection - /// Note that the passed variable is not deleted along with menu object. - /// @param b pointer to buffer that contains the suffix - /// - void SetSelectSuffix(Buffer *b) { m_selected_suffix = b; } - - /// Sets custom color of highlighted position - /// @param col custom color - /// - void HighlightColor(Color color) { m_highlight_color = color; } - - /// @return state of highlighting - /// - bool isHighlighted() { return m_highlight_enabled; } - - /// Turns on/off highlighting - /// @param state state of hihglighting - /// - void Highlighting(bool state) { m_highlight_enabled = state; } - - /// Turns on/off cyclic scrolling - /// @param state state of cyclic scrolling - /// - void CyclicScrolling(bool state) { m_cyclic_scroll_enabled = state; } - - /// Turns on/off centered cursor - /// @param state state of centered cursor - /// - void CenteredCursor(bool state) { m_autocenter_cursor = state; } - - /// Checks if list is empty - /// @return true if list is empty, false otherwise - /// @see ReallyEmpty() - /// - virtual bool Empty() const { return m_options_ptr->empty(); } - - /// Checks if list is really empty since Empty() may not - /// be accurate if filter is set) - /// @return true if list is empty, false otherwise - /// @see Empty() - /// - virtual bool ReallyEmpty() const { return m_options.empty(); } - - /// @return size of the list - /// - virtual size_t Size() const; - - /// @return position of currently drawed item. The result is - /// defined only within drawing function that is called by Refresh() - /// @see Refresh() - /// - size_t CurrentlyDrawedPosition() const { return m_drawn_position; } - - /// @return reference to last item on the list - /// @throw List::InvalidItem if requested item is separator - /// - T &Back(); - - /// @return const reference to last item on the list - /// @throw List::InvalidItem if requested item is separator - /// - const T &Back() const; - - /// @return reference to curently highlighted object - /// @throw List::InvalidItem if requested item is separator - /// - T &Current(); - - /// @return const reference to curently highlighted object - /// @throw List::InvalidItem if requested item is separator - /// - const T &Current() const; - - /// @param pos requested position - /// @return reference to item at given position - /// @throw std::out_of_range if given position is out of range - /// @throw List::InvalidItem if requested item is separator - /// - T &at(size_t pos); - - /// @param pos requested position - /// @return const reference to item at given position - /// @throw std::out_of_range if given position is out of range - /// @throw List::InvalidItem if requested item is separator - /// - const T &at(size_t pos) const; - - /// @param pos requested position - /// @return const reference to item at given position - /// @throw List::InvalidItem if requested item is separator - /// - const T &operator[](size_t pos) const; - - /// @param pos requested position - /// @return const reference to item at given position - /// @throw List::InvalidItem if requested item is separator - /// - T &operator[](size_t pos); - - Iterator Begin() { return Iterator(m_options_ptr->begin()); } - ConstIterator Begin() const { return ConstIterator(m_options_ptr->begin()); } - - Iterator End() { return Iterator(m_options_ptr->end()); } - ConstIterator End() const { return ConstIterator(m_options_ptr->end()); } - - ReverseIterator Rbegin() { return ReverseIterator(End()); } - ConstReverseIterator Rbegin() const { return ConstReverseIterator(End()); } - - ReverseIterator Rend() { return ReverseIterator(Begin()); } - ConstReverseIterator Rend() const { return ConstReverseIterator(Begin()); } - - protected: - /// Clears filter, filtered data etc. - /// - void ClearFiltered(); - - ItemDisplayer m_item_displayer; - ItemStringifier m_get_string_helper; - - std::string m_filter; - std::string m_search_constraint; - - std::vector *m_options_ptr; - std::vector m_options; - std::vector m_filtered_options; - std::vector m_filtered_positions; - std::set m_found_positions; - - int itsBeginning; - int itsHighlight; - - Color m_highlight_color; - bool m_highlight_enabled; - bool m_cyclic_scroll_enabled; - - bool m_autocenter_cursor; - - size_t m_drawn_position; - - Buffer *m_selected_prefix; - Buffer *m_selected_suffix; - }; - - /// Specialization of Menu::GetItem for T = std::string, it's obvious - /// that if strings are stored, we don't need extra function to convert - /// them to strings by default - template <> std::string Menu::GetItem(size_t pos); -} +namespace NCurses { -template NCurses::Menu::Menu(size_t startx, +/// List class is an interface for Menu class +/// +struct List +{ + /// @see Menu::Select() + /// + virtual void Select(int pos, bool state) = 0; + + /// @see Menu::isSelected() + /// + virtual bool isSelected(int pos = -1) const = 0; + + /// @see Menu::hasSelected() + /// + virtual bool hasSelected() const = 0; + + /// @see Menu::GetSelected() + /// + virtual void GetSelected(std::vector &v) const = 0; + + /// Highlights given position + /// @param pos position to be highlighted + /// + virtual void Highlight(size_t pos) = 0; + + /// @return currently highlighted position + /// + virtual size_t Choice() const = 0; + + /// @see Menu::Empty() + /// + virtual bool Empty() const = 0; + + /// @see Menu::Size() + /// + virtual size_t Size() const = 0; + + /// @see Menu::Search() + /// + virtual bool Search(const std::string &constraint, size_t beginning = 0, int flags = 0) = 0; + + /// @see Menu::GetSearchConstraint() + /// + virtual const std::string &GetSearchConstraint() = 0; + + /// @see Menu::NextFound() + /// + virtual void NextFound(bool wrap) = 0; + + /// @see Menu::PrevFound() + /// + virtual void PrevFound(bool wrap) = 0; + + /// @see Menu::ApplyFilter() + /// + virtual void ApplyFilter(const std::string &filter, size_t beginning = 0, int flags = 0) = 0; + + /// @see Menu::GetFilter() + /// + virtual const std::string &GetFilter() = 0; + + /// @see Menu::isFiltered() + /// + virtual bool isFiltered() = 0; +}; + +/// This template class is generic menu capable of +/// holding any std::vector compatible values. +/// +template struct Menu : public Window, public List +{ + /// 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 &, const T &)> ItemDisplayer; + + /// Function helper prototype used for converting items to strings. + /// If not set by SetItemStringifier(), searching and filtering + /// won't work (note that Menu doesn't need this) + /// @see SetItemStringifier() + /// + typedef std::function ItemStringifier; + + /// Struct that holds each item in the list and its attributes + /// + struct Item + { + Item() : isBold(0), isSelected(0), isStatic(0) { } + Item(const T &t, bool is_bold, bool is_static) : + Value(t), isBold(is_bold), isSelected(0), isStatic(is_static) { } + + T Value; + bool isBold; + bool isSelected; + bool isStatic; + }; + + template class ItemIterator + : public std::iterator + { + friend class Menu; + + BaseIterator m_it; + explicit ItemIterator(BaseIterator it) : m_it(it) { } + + static const bool referenceValue = !std::is_same< + ValueT, typename std::remove_pointer< + typename BaseIterator::value_type + >::type + >::value; + template struct getObject { }; + template struct getObject { + static Result &apply(BaseIterator it) { return (*it)->Value; } + }; + template struct getObject { + static Result &apply(BaseIterator it) { return **it; } + }; + + public: + ItemIterator() { } + + ValueT &operator*() const { return getObject::apply(m_it); } + typename BaseIterator::value_type operator->() { return *m_it; } + + ItemIterator &operator++() { ++m_it; return *this; } + ItemIterator operator++(int) { return ItemIterator(m_it++); } + + ItemIterator &operator--() { --m_it; return *this; } + ItemIterator operator--(int) { return ItemIterator(m_it--); } + + ValueT &operator[](ptrdiff_t n) const { + return getObject::apply(&m_it[n]); + } + + ItemIterator &operator+=(ptrdiff_t n) { m_it += n; return *this; } + ItemIterator operator+(ptrdiff_t n) const { return ItemIterator(m_it + n); } + + ItemIterator &operator-=(ptrdiff_t n) { m_it -= n; return *this; } + ItemIterator operator-(ptrdiff_t n) const { return ItemIterator(m_it - n); } + + ptrdiff_t operator-(const ItemIterator &rhs) const { return m_it - rhs.m_it; } + + template + bool operator==(const Iterator &rhs) const { return m_it == rhs.m_it; } + template + bool operator!=(const Iterator &rhs) const { return m_it != rhs.m_it; } + template + bool operator<(const Iterator &rhs) const { return m_it < rhs.m_it; } + template + bool operator<=(const Iterator &rhs) const { return m_it <= rhs.m_it; } + template + bool operator>(const Iterator &rhs) const { return m_it > rhs.m_it; } + template + bool operator>=(const Iterator &rhs) const { return m_it >= rhs.m_it; } + + /// non-const to const conversion + template operator ItemIterator< + typename std::add_const::type, Iterator + >() { return ItemIterator(m_it); } + + const BaseIterator &base() { return m_it; } + }; + + typedef ItemIterator< + T, typename std::vector::iterator + > Iterator; + + typedef ItemIterator< + typename std::add_const::type, typename std::vector::const_iterator + > ConstIterator; + + typedef std::reverse_iterator ReverseIterator; + typedef std::reverse_iterator ConstReverseIterator; + + /// Constructs an empty menu with given parameters + /// @param startx X position of left upper corner of constructed menu + /// @param starty Y position of left upper corner of constructed menu + /// @param width width of constructed menu + /// @param height height of constructed menu + /// @param title title of constructed menu + /// @param color base color of constructed menu + /// @param border border of constructed menu + /// + Menu(size_t startx, size_t starty, size_t width, size_t height, + const std::string &title, Color color, Border border); + + /// Copies the menu + /// @param m copied menu + /// + Menu(const Menu &m); + + /// Destroys the object and frees memory + /// + virtual ~Menu(); + + /// Sets helper function that is responsible for displaying items + /// @param ptr function pointer that matches the ItemDisplayer prototype + /// + void setItemDisplayer(ItemDisplayer ptr) { m_item_displayer = ptr; } + + /// Sets helper function that is responsible for converting items to strings + /// @param f function pointer that matches the ItemStringifier prototype + /// + void SetItemStringifier(ItemStringifier f) { m_get_string_helper = f; } + + /// Reserves the size for internal container (this just calls std::vector::reserve()) + /// @param size requested size + /// + void Reserve(size_t size); + + /// Resizes the list to given size (adequate to std::vector::resize()) + /// @param size requested size + /// + void ResizeList(size_t size); + + /// Adds new option to list + /// @param item object that has to be added + /// @param is_bold defines the initial state of bold attribute + /// @param is_static defines the initial state of static attribute + /// + void AddItem(const T &item, bool is_bold = 0, bool is_static = 0); + + /// Adds separator to list + /// + void AddSeparator(); + + /// Inserts new option to list at given position + /// @param pos initial position of inserted item + /// @param item object that has to be inserted + /// @param is_bold defines the initial state of bold attribute + /// @param is_static defines the initial state of static attribute + /// + void InsertItem(size_t pos, const T &Item, bool is_bold = 0, bool is_static = 0); + + /// Inserts separator to list at given position + /// @param pos initial position of inserted separator + /// + void InsertSeparator(size_t pos); + + /// Deletes item from given position + /// @param pos given position of item to be deleted + /// + void DeleteItem(size_t pos); + + /// Converts the option into separator + /// @param pos position of item to be converted + /// + void IntoSeparator(size_t pos); + + /// Swaps the content of two items + /// @param one position of first item + /// @param two position of second item + /// + void Swap(size_t one, size_t two); + + /// Moves requested item from one position to another + /// @param from the position of item that has to be moved + /// @param to the position that indicates where the object has to be moved + /// + void Move(size_t from, size_t to); + + /// Moves the highlighted position to the given line of window + /// @param y Y position of menu window to be highlighted + /// @return true if the position is reachable, false otherwise + /// + bool Goto(size_t y); + + /// Checks if the given position has bold attribute set. + /// @param pos position to be checked. -1 = currently highlighted position + /// @return true if the bold is set, false otherwise + /// + bool isBold(int pos = -1); + + /// Sets bols attribute for given position + /// @param pos position of item to be bolded/unbolded + /// @param state state of bold attribute + /// + void Bold(int pos, bool state); + + /// Makes given position static/active. + /// Static positions cannot be highlighted. + /// @param pos position in list + /// @param state state of activity + /// + void Static(int pos, bool state); + + /// Checks whether given position is static or active + /// @param pos position to be checked, -1 checks currently highlighted position + /// @return true if position is static, false otherwise + /// + bool isStatic(int pos = -1) const; + + /// Checks whether given position is separator + /// @param pos position to be checked, -1 checks currently highlighted position + /// @return true if position is separator, false otherwise + /// + bool isSeparator(int pos = -1) const; + + /// Selects/deselects given position + /// @param pos position in list + /// @param state state of selection + /// + virtual void Select(int pos, bool state); + + /// Checks if given position is selected + /// @param pos position to be checked, -1 checks currently highlighted position + /// @return true if position is selected, false otherwise + /// + virtual bool isSelected(int pos = -1) const; + + /// Checks whether list contains selected positions + /// @return true if it contains them, false otherwise + /// + virtual bool hasSelected() const; + + /// Gets positions of items that are selected + /// @param v vector to be filled with selected positions numbers + /// + virtual void GetSelected(std::vector &v) const; + + /// Reverses selection of all items in list + /// @param beginning beginning of range that has to be reversed + /// + void ReverseSelection(size_t beginning = 0); + + /// Highlights given position + /// @param pos position to be highlighted + /// + void Highlight(size_t pos); + + /// @return currently highlighted position + /// + size_t Choice() const; + + /// @return real current positions, i.e it doesn't + /// count positions that are static or separators + /// + size_t RealChoice() const; + + /// Searches the list for a given contraint. It uses ItemStringifier to convert stored items + /// into strings and then performs pattern matching. Note that this supports regular expressions. + /// @param constraint a search constraint to be used + /// @param beginning beginning of range that has to be searched through + /// @param flags regex flags (REG_EXTENDED, REG_ICASE, REG_NOSUB, REG_NEWLINE) + /// @return true if at least one item matched the given pattern, false otherwise + /// + virtual bool Search(const std::string &constraint, size_t beginning = 0, int flags = 0); + + /// @return const reference to currently used search constraint + /// + virtual const std::string &GetSearchConstraint() { return m_search_constraint; } + + /// Moves current position in the list to the next found one + /// @param wrap if true, this function will go to the first + /// found pos after the last one, otherwise it'll do nothing. + /// + virtual void NextFound(bool wrap); + + /// Moves current position in the list to the previous found one + /// @param wrap if true, this function will go to the last + /// found pos after the first one, otherwise it'll do nothing. + /// + virtual void PrevFound(bool wrap); + + /// Filters the list, showing only the items that matches the pattern. It uses + /// ItemStringifier to convert stored items into strings and then performs + /// pattern matching. Note that this supports regular expressions. + /// @param filter a pattern to be used in pattern matching + /// @param beginning beginning of range that has to be filtered + /// @param flags regex flags (REG_EXTENDED, REG_ICASE, REG_NOSUB, REG_NEWLINE) + /// + virtual void ApplyFilter(const std::string &filter, size_t beginning = 0, int flags = 0); + + /// @return const reference to currently used filter + /// + virtual const std::string &GetFilter(); + + /// @return true if list is currently filtered, false otherwise + /// + virtual bool isFiltered() { return m_options_ptr == &m_filtered_options; } + + /// Turns off filtering + /// + void ShowAll() { m_options_ptr = &m_options; } + + /// Turns on filtering + /// + void ShowFiltered() { m_options_ptr = &m_filtered_options; } + + /// Converts given position in list to string using ItemStringifier + /// if specified and an empty string otherwise + /// @param pos position to be converted + /// @return item converted to string + /// @see setItemDisplayer() + /// + std::string GetItem(size_t pos); + + /// Refreshes the menu window + /// @see Window::Refresh() + /// + virtual void Refresh(); + + /// Scrolls by given amount of lines + /// @param where indicated where exactly one wants to go + /// @see Window::Scroll() + /// + virtual void Scroll(Where where); + + /// Cleares all options, used filters etc. It doesn't reset highlighted position though. + /// @see Reset() + /// + virtual void Clear(); + + /// Sets the highlighted position to 0 + /// + void Reset(); + + /// Sets prefix, that is put before each selected item to indicate its selection + /// Note that the passed variable is not deleted along with menu object. + /// @param b pointer to buffer that contains the prefix + /// + void SetSelectPrefix(Buffer *b) { m_selected_prefix = b; } + + /// Sets suffix, that is put after each selected item to indicate its selection + /// Note that the passed variable is not deleted along with menu object. + /// @param b pointer to buffer that contains the suffix + /// + void SetSelectSuffix(Buffer *b) { m_selected_suffix = b; } + + /// Sets custom color of highlighted position + /// @param col custom color + /// + void HighlightColor(Color color) { m_highlight_color = color; } + + /// @return state of highlighting + /// + bool isHighlighted() { return m_highlight_enabled; } + + /// Turns on/off highlighting + /// @param state state of hihglighting + /// + void Highlighting(bool state) { m_highlight_enabled = state; } + + /// Turns on/off cyclic scrolling + /// @param state state of cyclic scrolling + /// + void CyclicScrolling(bool state) { m_cyclic_scroll_enabled = state; } + + /// Turns on/off centered cursor + /// @param state state of centered cursor + /// + void CenteredCursor(bool state) { m_autocenter_cursor = state; } + + /// Checks if list is empty + /// @return true if list is empty, false otherwise + /// @see ReallyEmpty() + /// + virtual bool Empty() const { return m_options_ptr->empty(); } + + /// Checks if list is really empty since Empty() may not + /// be accurate if filter is set) + /// @return true if list is empty, false otherwise + /// @see Empty() + /// + virtual bool ReallyEmpty() const { return m_options.empty(); } + + /// @return size of the list + /// + virtual size_t Size() const; + + /// @return position of currently drawed item. The result is + /// defined only within drawing function that is called by Refresh() + /// @see Refresh() + /// + size_t CurrentlyDrawedPosition() const { return m_drawn_position; } + + /// @return reference to last item on the list + /// @throw List::InvalidItem if requested item is separator + /// + T &Back(); + + /// @return const reference to last item on the list + /// @throw List::InvalidItem if requested item is separator + /// + const T &Back() const; + + /// @return reference to curently highlighted object + /// @throw List::InvalidItem if requested item is separator + /// + T &Current(); + + /// @return const reference to curently highlighted object + /// @throw List::InvalidItem if requested item is separator + /// + const T &Current() const; + + /// @param pos requested position + /// @return reference to item at given position + /// @throw std::out_of_range if given position is out of range + /// @throw List::InvalidItem if requested item is separator + /// + T &at(size_t pos); + + /// @param pos requested position + /// @return const reference to item at given position + /// @throw std::out_of_range if given position is out of range + /// @throw List::InvalidItem if requested item is separator + /// + const T &at(size_t pos) const; + + /// @param pos requested position + /// @return const reference to item at given position + /// @throw List::InvalidItem if requested item is separator + /// + const T &operator[](size_t pos) const; + + /// @param pos requested position + /// @return const reference to item at given position + /// @throw List::InvalidItem if requested item is separator + /// + T &operator[](size_t pos); + + Iterator Begin() { return Iterator(m_options_ptr->begin()); } + ConstIterator Begin() const { return ConstIterator(m_options_ptr->begin()); } + + Iterator End() { return Iterator(m_options_ptr->end()); } + ConstIterator End() const { return ConstIterator(m_options_ptr->end()); } + + ReverseIterator Rbegin() { return ReverseIterator(End()); } + ConstReverseIterator Rbegin() const { return ConstReverseIterator(End()); } + + ReverseIterator Rend() { return ReverseIterator(Begin()); } + ConstReverseIterator Rend() const { return ConstReverseIterator(Begin()); } + +protected: + /// Clears filter, filtered data etc. + /// + void ClearFiltered(); + + ItemDisplayer m_item_displayer; + ItemStringifier m_get_string_helper; + + std::string m_filter; + std::string m_search_constraint; + + std::vector *m_options_ptr; + std::vector m_options; + std::vector m_filtered_options; + std::vector m_filtered_positions; + std::set m_found_positions; + + int itsBeginning; + int itsHighlight; + + Color m_highlight_color; + bool m_highlight_enabled; + bool m_cyclic_scroll_enabled; + + bool m_autocenter_cursor; + + size_t m_drawn_position; + + Buffer *m_selected_prefix; + Buffer *m_selected_suffix; +}; + +/// Specialization of Menu::GetItem for T = std::string, it's obvious +/// that if strings are stored, we don't need extra function to convert +/// them to strings by default +template <> std::string Menu::GetItem(size_t pos); + +template Menu::Menu(size_t startx, size_t starty, size_t width, size_t height, @@ -628,7 +626,7 @@ template NCurses::Menu::Menu(size_t startx, { } -template NCurses::Menu::Menu(const Menu &m) : Window(m), +template Menu::Menu(const Menu &m) : Window(m), m_item_displayer(m.m_item_displayer), m_get_string_helper(m.m_get_string_helper), m_options_ptr(m.m_options_ptr), @@ -646,18 +644,18 @@ template NCurses::Menu::Menu(const Menu &m) : Window(m), m_options.push_back(new Item(**it)); } -template NCurses::Menu::~Menu() +template Menu::~Menu() { for (auto it = m_options.begin(); it != m_options.end(); ++it) delete *it; } -template void NCurses::Menu::Reserve(size_t size) +template void Menu::Reserve(size_t size) { m_options.reserve(size); } -template void NCurses::Menu::ResizeList(size_t size) +template void Menu::ResizeList(size_t size) { if (size > m_options.size()) { @@ -674,27 +672,27 @@ template void NCurses::Menu::ResizeList(size_t size) } } -template void NCurses::Menu::AddItem(const T &item, bool is_bold, bool is_static) +template void Menu::AddItem(const T &item, bool is_bold, bool is_static) { m_options.push_back(new Item(item, is_bold, is_static)); } -template void NCurses::Menu::AddSeparator() +template void Menu::AddSeparator() { m_options.push_back(static_cast(0)); } -template void NCurses::Menu::InsertItem(size_t pos, const T &item, bool is_bold, bool is_static) +template void Menu::InsertItem(size_t pos, const T &item, bool is_bold, bool is_static) { m_options.insert(m_options.begin()+pos, new Item(item, is_bold, is_static)); } -template void NCurses::Menu::InsertSeparator(size_t pos) +template void Menu::InsertSeparator(size_t pos) { m_options.insert(m_options.begin()+pos, 0); } -template void NCurses::Menu::DeleteItem(size_t pos) +template void Menu::DeleteItem(size_t pos) { if (m_options_ptr->empty()) return; @@ -717,25 +715,25 @@ template void NCurses::Menu::DeleteItem(size_t pos) Window::Clear(); } -template void NCurses::Menu::IntoSeparator(size_t pos) +template void Menu::IntoSeparator(size_t pos) { delete m_options_ptr->at(pos); (*m_options_ptr)[pos] = 0; } -template void NCurses::Menu::Bold(int pos, bool state) +template void Menu::Bold(int pos, bool state) { if (!m_options_ptr->at(pos)) return; (*m_options_ptr)[pos]->isBold = state; } -template void NCurses::Menu::Swap(size_t one, size_t two) +template void Menu::Swap(size_t one, size_t two) { std::swap(m_options.at(one), m_options.at(two)); } -template void NCurses::Menu::Move(size_t from, size_t to) +template void Menu::Move(size_t from, size_t to) { int diff = from-to; if (diff > 0) @@ -750,7 +748,7 @@ template void NCurses::Menu::Move(size_t from, size_t to) } } -template bool NCurses::Menu::Goto(size_t y) +template bool Menu::Goto(size_t y) { if (!m_options_ptr->at(itsBeginning+y) || m_options_ptr->at(itsBeginning+y)->isStatic) return false; @@ -758,7 +756,7 @@ template bool NCurses::Menu::Goto(size_t y) return true; } -template void NCurses::Menu::Refresh() +template void Menu::Refresh() { if (m_options_ptr->empty()) { @@ -826,7 +824,7 @@ template void NCurses::Menu::Refresh() Window::Refresh(); } -template void NCurses::Menu::Scroll(Where where) +template void Menu::Scroll(Where where) { if (m_options_ptr->empty()) return; @@ -940,20 +938,20 @@ template void NCurses::Menu::Scroll(Where where) Highlight(itsHighlight); } -template void NCurses::Menu::Reset() +template void Menu::Reset() { itsHighlight = 0; itsBeginning = 0; } -template void NCurses::Menu::ClearFiltered() +template void Menu::ClearFiltered() { m_filtered_options.clear(); m_filtered_positions.clear(); m_options_ptr = &m_options; } -template void NCurses::Menu::Clear() +template void Menu::Clear() { for (auto it = m_options.begin(); it != m_options.end(); ++it) delete *it; @@ -965,7 +963,7 @@ template void NCurses::Menu::Clear() Window::Clear(); } -template bool NCurses::Menu::isBold(int pos) +template bool Menu::isBold(int pos) { pos = pos == -1 ? itsHighlight : pos; if (!m_options_ptr->at(pos)) @@ -973,21 +971,21 @@ template bool NCurses::Menu::isBold(int pos) return (*m_options_ptr)[pos]->isBold; } -template void NCurses::Menu::Select(int pos, bool state) +template void Menu::Select(int pos, bool state) { if (!m_options_ptr->at(pos)) return; (*m_options_ptr)[pos]->isSelected = state; } -template void NCurses::Menu::Static(int pos, bool state) +template void Menu::Static(int pos, bool state) { if (!m_options_ptr->at(pos)) return; (*m_options_ptr)[pos]->isStatic = state; } -template bool NCurses::Menu::isSelected(int pos) const +template bool Menu::isSelected(int pos) const { pos = pos == -1 ? itsHighlight : pos; if (!m_options_ptr->at(pos)) @@ -995,7 +993,7 @@ template bool NCurses::Menu::isSelected(int pos) const return (*m_options_ptr)[pos]->isSelected; } -template bool NCurses::Menu::isStatic(int pos) const +template bool Menu::isStatic(int pos) const { pos = pos == -1 ? itsHighlight : pos; if (!m_options_ptr->at(pos)) @@ -1003,13 +1001,13 @@ template bool NCurses::Menu::isStatic(int pos) const return (*m_options_ptr)[pos]->isStatic; } -template bool NCurses::Menu::isSeparator(int pos) const +template bool Menu::isSeparator(int pos) const { pos = pos == -1 ? itsHighlight : pos; return !m_options_ptr->at(pos); } -template bool NCurses::Menu::hasSelected() const +template bool Menu::hasSelected() const { for (auto it = m_options_ptr->begin(); it != m_options_ptr->end(); ++it) if (*it && (*it)->isSelected) @@ -1017,30 +1015,30 @@ template bool NCurses::Menu::hasSelected() const return false; } -template void NCurses::Menu::GetSelected(std::vector &v) const +template void Menu::GetSelected(std::vector &v) const { for (size_t i = 0; i < m_options_ptr->size(); ++i) if ((*m_options_ptr)[i] && (*m_options_ptr)[i]->isSelected) v.push_back(i); } -template void NCurses::Menu::Highlight(size_t pos) +template void Menu::Highlight(size_t pos) { itsHighlight = pos; itsBeginning = pos-itsHeight/2; } -template size_t NCurses::Menu::Size() const +template size_t Menu::Size() const { return m_options_ptr->size(); } -template size_t NCurses::Menu::Choice() const +template size_t Menu::Choice() const { return itsHighlight; } -template size_t NCurses::Menu::RealChoice() const +template size_t Menu::RealChoice() const { size_t result = 0; for (auto it = m_options_ptr->begin(); it != m_options_ptr->begin()+itsHighlight; ++it) @@ -1049,7 +1047,7 @@ template size_t NCurses::Menu::RealChoice() const return result; } -template void NCurses::Menu::ReverseSelection(size_t beginning) +template void Menu::ReverseSelection(size_t beginning) { auto it = m_options_ptr->begin()+beginning; for (size_t i = beginning; i < Size(); ++i, ++it) @@ -1057,7 +1055,7 @@ template void NCurses::Menu::ReverseSelection(size_t beginning) (*it)->isSelected = !(*it)->isSelected && !(*it)->isStatic; } -template bool NCurses::Menu::Search(const std::string &constraint, size_t beginning, int flags) +template bool Menu::Search(const std::string &constraint, size_t beginning, int flags) { m_found_positions.clear(); m_search_constraint.clear(); @@ -1077,7 +1075,7 @@ template bool NCurses::Menu::Search(const std::string &constrain return !m_found_positions.empty(); } -template void NCurses::Menu::NextFound(bool wrap) +template void Menu::NextFound(bool wrap) { if (m_found_positions.empty()) return; @@ -1088,7 +1086,7 @@ template void NCurses::Menu::NextFound(bool wrap) Highlight(*m_found_positions.begin()); } -template void NCurses::Menu::PrevFound(bool wrap) +template void Menu::PrevFound(bool wrap) { if (m_found_positions.empty()) return; @@ -1099,7 +1097,7 @@ template void NCurses::Menu::PrevFound(bool wrap) Highlight(*m_found_positions.rbegin()); } -template void NCurses::Menu::ApplyFilter(const std::string &filter, size_t beginning, int flags) +template void Menu::ApplyFilter(const std::string &filter, size_t beginning, int flags) { m_found_positions.clear(); ClearFiltered(); @@ -1129,12 +1127,12 @@ template void NCurses::Menu::ApplyFilter(const std::string &filt Window::Clear(); } -template const std::string &NCurses::Menu::GetFilter() +template const std::string &Menu::GetFilter() { return m_filter; } -template std::string NCurses::Menu::GetItem(size_t pos) +template std::string Menu::GetItem(size_t pos) { if (m_options_ptr->at(pos) && m_get_string_helper) return m_get_string_helper((*m_options_ptr)[pos]->Value); @@ -1142,61 +1140,63 @@ template std::string NCurses::Menu::GetItem(size_t pos) return ""; } -template T &NCurses::Menu::Back() +template T &Menu::Back() { if (!m_options_ptr->back()) FatalError("Menu::Back() has requested separator!"); return m_options_ptr->back()->Value; } -template const T &NCurses::Menu::Back() const +template const T &Menu::Back() const { if (!m_options_ptr->back()) FatalError("Menu::Back() has requested separator!"); return m_options_ptr->back()->Value; } -template T &NCurses::Menu::Current() +template T &Menu::Current() { if (!m_options_ptr->at(itsHighlight)) FatalError("Menu::Current() has requested separator!"); return (*m_options_ptr)[itsHighlight]->Value; } -template const T &NCurses::Menu::Current() const +template const T &Menu::Current() const { if (!m_options_ptr->at(itsHighlight)) FatalError("Menu::Current() const has requested separator!"); return (*m_options_ptr)[itsHighlight]->Value; } -template T &NCurses::Menu::at(size_t pos) +template T &Menu::at(size_t pos) { if (!m_options_ptr->at(pos)) FatalError("Menu::at() has requested separator!"); return (*m_options_ptr)[pos]->Value; } -template const T &NCurses::Menu::at(size_t pos) const +template const T &Menu::at(size_t pos) const { if (!m_options->at(pos)) FatalError("Menu::at() const has requested separator!"); return (*m_options_ptr)[pos]->Value; } -template const T &NCurses::Menu::operator[](size_t pos) const +template const T &Menu::operator[](size_t pos) const { if (!(*m_options_ptr)[pos]) FatalError("Menu::operator[] const has requested separator!"); return (*m_options_ptr)[pos]->Value; } -template T &NCurses::Menu::operator[](size_t pos) +template T &Menu::operator[](size_t pos) { if (!(*m_options_ptr)[pos]) FatalError("Menu::operator[] has requested separator!"); return (*m_options_ptr)[pos]->Value; } +} + #endif