1 /***************************************************************************
2 * Copyright (C) 2008-2010 by Andrzej Rybczak *
3 * electricityispower@gmail.com *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
19 ***************************************************************************/
30 #include "strbuffer.h"
34 /// List class is an interface for Menu class
39 /// @see Menu::Select()
41 virtual void Select(int pos
, bool state
) = 0;
43 /// @see Menu::isSelected()
45 virtual bool isSelected(int pos
= -1) const = 0;
47 /// @see Menu::hasSelected()
49 virtual bool hasSelected() const = 0;
51 /// @see Menu::GetSelected()
53 virtual void GetSelected(std::vector
<size_t> &v
) const = 0;
55 /// Highlights given position
56 /// @param pos position to be highlighted
58 virtual void Highlight(size_t pos
) = 0;
60 /// @return currently highlighted position
62 virtual size_t Choice() const = 0;
64 /// @see Menu::Empty()
66 virtual bool Empty() const = 0;
70 virtual size_t Size() const = 0;
72 /// @see Menu::Search()
74 virtual bool Search(const std::string
&constraint
, size_t beginning
= 0, int flags
= 0) = 0;
76 /// @see Menu::GetSearchConstraint()
78 virtual const std::string
&GetSearchConstraint() = 0;
80 /// @see Menu::NextFound()
82 virtual void NextFound(bool wrap
) = 0;
84 /// @see Menu::PrevFound()
86 virtual void PrevFound(bool wrap
) = 0;
88 /// @see Menu::ApplyFilter()
90 virtual void ApplyFilter(const std::string
&filter
, size_t beginning
= 0, int flags
= 0) = 0;
92 /// @see Menu::GetFilter()
94 virtual const std::string
&GetFilter() = 0;
96 /// @see Menu::isFiltered()
98 virtual bool isFiltered() = 0;
101 /// This template class is generic menu, that has holds
102 /// any values that are std::vector compatible.
104 template <typename T
> class Menu
: public Window
, public List
106 /// Function helper prototype used to display each option on the screen.
107 /// If not set by SetItemDisplayer(), menu won't display anything.
108 /// @see SetItemDisplayer()
110 typedef void (*ItemDisplayer
)(const T
&, void *, Menu
<T
> *);
112 /// Function helper prototype used for converting items to strings.
113 /// If not set by SetGetStringFunction(), searching and filtering
114 /// won't work (note that Menu<std::string> doesn't need this)
115 /// @see SetGetStringFunction()
117 typedef std::string (*GetStringFunction
)(const T
&, void *);
119 /// Struct that holds each item in the list and its attributes
123 Option() : isBold(0), isSelected(0), isStatic(0) { }
124 Option(const T
&t
, bool is_bold
, bool is_static
) :
125 Item(t
), isBold(is_bold
), isSelected(0), isStatic(is_static
) { }
133 /// Functor that wraps around the functor passed to Sort()
134 /// to fit to internal container structure
136 template <typename Comparison
> class InternalSorting
141 bool operator()(Option
*a
, Option
*b
)
143 return cmp(a
->Item
, b
->Item
);
147 typedef typename
std::vector
<Option
*>::iterator option_iterator
;
148 typedef typename
std::vector
<Option
*>::const_iterator option_const_iterator
;
152 /// Constructs an empty menu with given parameters
153 /// @param startx X position of left upper corner of constructed menu
154 /// @param starty Y position of left upper corner of constructed menu
155 /// @param width width of constructed menu
156 /// @param height height of constructed menu
157 /// @param title title of constructed menu
158 /// @param color base color of constructed menu
159 /// @param border border of constructed menu
161 Menu(size_t startx
, size_t starty
, size_t width
, size_t height
,
162 const std::string
&title
, Color color
, Border border
);
165 /// @param m copied menu
169 /// Destroys the object and frees memory
173 /// Sets helper function that is responsible for displaying items
174 /// @param ptr function pointer that matches the ItemDisplayer prototype
176 void SetItemDisplayer(ItemDisplayer ptr
) { itsItemDisplayer
= ptr
; }
178 /// Sets optional user data, that is passed to
179 /// ItemDisplayer function each time it's invoked
180 /// @param data void pointer to userdata
182 void SetItemDisplayerUserData(void *data
) { itsItemDisplayerUserdata
= data
; }
184 /// Sets helper function that is responsible for converting items to strings
185 /// @param f function pointer that matches the GetStringFunction prototype
187 void SetGetStringFunction(GetStringFunction f
) { itsGetStringFunction
= f
; }
189 /// Sets optional user data, that is passed to
190 /// GetStringFunction function each time it's invoked
191 /// @param data void pointer to user data
193 void SetGetStringFunctionUserData(void *data
) { itsGetStringFunctionUserData
= data
; }
195 /// Reserves the size for internal container (this just calls std::vector::reserve())
196 /// @param size requested size
198 void Reserve(size_t size
);
200 /// Resizes the list to given size (adequate to std::vector::resize())
201 /// @param size requested size
203 void ResizeList(size_t size
);
205 /// Adds new option to list
206 /// @param item object that has to be added
207 /// @param is_bold defines the initial state of bold attribute
208 /// @param is_static defines the initial state of static attribute
210 void AddOption(const T
&item
, bool is_bold
= 0, bool is_static
= 0);
212 /// Adds separator to list
216 /// Inserts new option to list at given position
217 /// @param pos initial position of inserted item
218 /// @param item object that has to be inserted
219 /// @param is_bold defines the initial state of bold attribute
220 /// @param is_static defines the initial state of static attribute
222 void InsertOption(size_t pos
, const T
&Item
, bool is_bold
= 0, bool is_static
= 0);
224 /// Inserts separator to list at given position
225 /// @param pos initial position of inserted separator
227 void InsertSeparator(size_t pos
);
229 /// Deletes item from given position
230 /// @param pos given position of item to be deleted
232 void DeleteOption(size_t pos
);
234 /// Converts the option into separator
235 /// @param pos position of item to be converted
237 void IntoSeparator(size_t pos
);
239 /// Swaps the content of two items
240 /// @param one position of first item
241 /// @param two position of second item
243 void Swap(size_t one
, size_t two
);
245 /// Moves requested item from one position to another
246 /// @param from the position of item that has to be moved
247 /// @param to the position that indicates where the object has to be moved
249 void Move(size_t from
, size_t to
);
251 /// Moves the highlighted position to the given line of window
252 /// @param y Y position of menu window to be highlighted
253 /// @return true if the position is reachable, false otherwise
257 /// Checks if the given position has bold attribute set.
258 /// @param pos position to be checked. -1 = currently highlighted position
259 /// @return true if the bold is set, false otherwise
261 bool isBold(int pos
= -1);
263 /// Sets bols attribute for given position
264 /// @param pos position of item to be bolded/unbolded
265 /// @param state state of bold attribute
267 void Bold(int pos
, bool state
);
269 /// Makes given position static/active.
270 /// Static positions cannot be highlighted.
271 /// @param pos position in list
272 /// @param state state of activity
274 void Static(int pos
, bool state
);
276 /// Checks whether given position is static or active
277 /// @param pos position to be checked, -1 checks currently highlighted position
278 /// @return true if position is static, false otherwise
280 bool isStatic(int pos
= -1) const;
282 /// Selects/deselects given position
283 /// @param pos position in list
284 /// @param state state of selection
286 virtual void Select(int pos
, bool state
);
288 /// Checks if given position is selected
289 /// @param pos position to be checked, -1 checks currently highlighted position
290 /// @return true if position is selected, false otherwise
292 virtual bool isSelected(int pos
= -1) const;
294 /// Checks whether list contains selected positions
295 /// @return true if it contains them, false otherwise
297 virtual bool hasSelected() const;
299 /// Gets positions of items that are selected
300 /// @param v vector to be filled with selected positions numbers
302 virtual void GetSelected(std::vector
<size_t> &v
) const;
304 /// Reverses selection of all items in list
305 /// @param beginning beginning of range that has to be reversed
307 void ReverseSelection(size_t beginning
= 0);
309 /// Highlights given position
310 /// @param pos position to be highlighted
312 void Highlight(size_t pos
);
314 /// @return currently highlighted position
316 size_t Choice() const;
318 /// @return real current positions, i.e it doesn't
319 /// count positions that are static or separators
321 size_t RealChoice() const;
323 /// Searches the list for a given contraint. It uses GetStringFunction to convert stored items
324 /// into strings and then performs pattern matching. Note that this supports regular expressions.
325 /// @param constraint a search constraint to be used
326 /// @param beginning beginning of range that has to be searched through
327 /// @param flags regex flags (REG_EXTENDED, REG_ICASE, REG_NOSUB, REG_NEWLINE)
328 /// @return true if at least one item matched the given pattern, false otherwise
330 virtual bool Search(const std::string
&constraint
, size_t beginning
= 0, int flags
= 0);
332 /// @return const reference to currently used search constraint
334 virtual const std::string
&GetSearchConstraint() { return itsSearchConstraint
; }
336 /// Moves current position in the list to the next found one
337 /// @param wrap if true, this function will go to the first
338 /// found pos after the last one, otherwise it'll do nothing.
340 virtual void NextFound(bool wrap
);
342 /// Moves current position in the list to the previous found one
343 /// @param wrap if true, this function will go to the last
344 /// found pos after the first one, otherwise it'll do nothing.
346 virtual void PrevFound(bool wrap
);
348 /// Filters the list, showing only the items that matches the pattern. It uses
349 /// GetStringFunction to convert stored items into strings and then performs
350 /// pattern matching. Note that this supports regular expressions.
351 /// @param filter a pattern to be used in pattern matching
352 /// @param beginning beginning of range that has to be filtered
353 /// @param flags regex flags (REG_EXTENDED, REG_ICASE, REG_NOSUB, REG_NEWLINE)
355 virtual void ApplyFilter(const std::string
&filter
, size_t beginning
= 0, int flags
= 0);
357 /// @return const reference to currently used filter
359 virtual const std::string
&GetFilter();
361 /// @return true if list is currently filtered, false otherwise
363 virtual bool isFiltered() { return itsOptionsPtr
== &itsFilteredOptions
; }
365 /// Turns off filtering
367 void ShowAll() { itsOptionsPtr
= &itsOptions
; }
369 /// Turns on filtering
371 void ShowFiltered() { itsOptionsPtr
= &itsFilteredOptions
; }
373 /// Converts given position in list to string using GetStringFunction
374 /// if specified and an empty string otherwise
375 /// @param pos position to be converted
376 /// @return item converted to string
377 /// @see SetItemDisplayer()
379 std::string
GetOption(size_t pos
);
381 /// Refreshes the menu window
382 /// @see Window::Refresh()
384 virtual void Refresh();
386 /// Scrolls by given amount of lines
387 /// @param where indicated where exactly one wants to go
388 /// @see Window::Scroll()
390 virtual void Scroll(Where where
);
392 /// Cleares all options, used filters etc. It doesn't reset highlighted position though.
395 virtual void Clear();
397 /// Sets the highlighted position to 0
401 /// Sorts all items using Comparison object with defined operator()
402 /// @param beginning beginning of range that has to be sorted
404 template <typename Comparison
> void Sort(size_t beginning
= 0, size_t end
= -1)
406 if (itsOptions
.empty())
408 sort(itsOptions
.begin()+beginning
, end
== size_t(-1) ? itsOptions
.end() : itsOptions
.begin()+end
, InternalSorting
<Comparison
>());
410 ApplyFilter(itsFilter
);
413 /// Sets prefix, that is put before each selected item to indicate its selection
414 /// Note that the passed variable is not deleted along with menu object.
415 /// @param b pointer to buffer that contains the prefix
417 void SetSelectPrefix(Buffer
*b
) { itsSelectedPrefix
= b
; }
419 /// Sets suffix, that is put after each selected item to indicate its selection
420 /// Note that the passed variable is not deleted along with menu object.
421 /// @param b pointer to buffer that contains the suffix
423 void SetSelectSuffix(Buffer
*b
) { itsSelectedSuffix
= b
; }
425 /// Sets custom color of highlighted position
426 /// @param col custom color
428 void HighlightColor(Color color
) { itsHighlightColor
= color
; }
430 /// @return state of highlighting
432 bool isHighlighted() { return highlightEnabled
; }
434 /// Turns on/off highlighting
435 /// @param state state of hihglighting
437 void Highlighting(bool state
) { highlightEnabled
= state
; }
439 /// Turns on/off cyclic scrolling
440 /// @param state state of cyclic scrolling
442 void CyclicScrolling(bool state
) { useCyclicScrolling
= state
; }
444 /// Turns on/off centered cursor
445 /// @param state state of centered cursor
447 void CenteredCursor(bool state
) { useCenteredCursor
= state
; }
449 /// Checks if list is empty
450 /// @return true if list is empty, false otherwise
452 virtual bool Empty() const { return itsOptionsPtr
->empty(); }
454 /// @return size of the list
456 virtual size_t Size() const;
458 /// @return position of currently drawed item. The result is
459 /// defined only within drawing function that is called by Refresh()
462 size_t CurrentlyDrawedPosition() const { return itsCurrentlyDrawedPosition
; }
464 /// @return reference to last item on the list
465 /// @throw List::InvalidItem if requested item is separator
469 /// @return const reference to last item on the list
470 /// @throw List::InvalidItem if requested item is separator
472 const T
&Back() const;
474 /// @return reference to curently highlighted object
475 /// @throw List::InvalidItem if requested item is separator
479 /// @return const reference to curently highlighted object
480 /// @throw List::InvalidItem if requested item is separator
482 const T
&Current() const;
484 /// @param pos requested position
485 /// @return reference to item at given position
486 /// @throw std::out_of_range if given position is out of range
487 /// @throw List::InvalidItem if requested item is separator
491 /// @param pos requested position
492 /// @return const reference to item at given position
493 /// @throw std::out_of_range if given position is out of range
494 /// @throw List::InvalidItem if requested item is separator
496 const T
&at(size_t pos
) const;
498 /// @param pos requested position
499 /// @return const reference to item at given position
500 /// @throw List::InvalidItem if requested item is separator
502 const T
&operator[](size_t pos
) const;
504 /// @param pos requested position
505 /// @return const reference to item at given position
506 /// @throw List::InvalidItem if requested item is separator
508 T
&operator[](size_t pos
);
511 /// Clears filter, filtered data etc.
513 void ClearFiltered();
515 ItemDisplayer itsItemDisplayer
;
516 void *itsItemDisplayerUserdata
;
517 GetStringFunction itsGetStringFunction
;
518 void *itsGetStringFunctionUserData
;
520 std::string itsFilter
;
521 std::string itsSearchConstraint
;
523 std::vector
<Option
*> *itsOptionsPtr
;
524 std::vector
<Option
*> itsOptions
;
525 std::vector
<Option
*> itsFilteredOptions
;
526 std::vector
<size_t> itsFilteredRealPositions
;
527 std::set
<size_t> itsFound
;
532 Color itsHighlightColor
;
533 bool highlightEnabled
;
534 bool useCyclicScrolling
;
536 bool useCenteredCursor
;
538 size_t itsCurrentlyDrawedPosition
;
540 Buffer
*itsSelectedPrefix
;
541 Buffer
*itsSelectedSuffix
;
544 /// Specialization of Menu<T>::GetOption for T = std::string, it's obvious
545 /// that if strings are stored, we don't need extra function to convert
546 /// them to strings by default
547 template <> std::string Menu
<std::string
>::GetOption(size_t pos
);
550 template <typename T
> NCurses::Menu
<T
>::Menu(size_t startx
,
554 const std::string
&title
,
557 : Window(startx
, starty
, width
, height
, title
, color
, border
),
559 itsItemDisplayerUserdata(0),
560 itsGetStringFunction(0),
561 itsGetStringFunctionUserData(0),
562 itsOptionsPtr(&itsOptions
),
565 itsHighlightColor(itsBaseColor
),
567 useCyclicScrolling(0),
568 useCenteredCursor(0),
569 itsSelectedPrefix(0),
574 template <typename T
> NCurses::Menu
<T
>::Menu(const Menu
&m
) : Window(m
),
575 itsItemDisplayer(m
.itsItemDisplayer
),
576 itsItemDisplayerUserdata(m
.itsItemDisplayerUserdata
),
577 itsGetStringFunction(m
.itsGetStringFunction
),
578 itsGetStringFunctionUserData(m
.itsGetStringFunctionUserData
),
579 itsOptionsPtr(m
.itsOptionsPtr
),
580 itsBeginning(m
.itsBeginning
),
581 itsHighlight(m
.itsHighlight
),
582 itsHighlightColor(m
.itsHighlightColor
),
583 highlightEnabled(m
.highlightEnabled
),
584 useCyclicScrolling(m
.useCyclicScrolling
),
585 useCenteredCursor(m
.useCenteredCursor
),
586 itsSelectedPrefix(m
.itsSelectedPrefix
),
587 itsSelectedSuffix(m
.itsSelectedSuffix
)
589 itsOptions
.reserve(m
.itsOptions
.size());
590 for (option_const_iterator it
= m
.itsOptions
.begin(); it
!= m
.itsOptions
.end(); ++it
)
591 itsOptions
.push_back(new Option(**it
));
594 template <typename T
> NCurses::Menu
<T
>::~Menu()
596 for (option_iterator it
= itsOptions
.begin(); it
!= itsOptions
.end(); ++it
)
600 template <typename T
> void NCurses::Menu
<T
>::Reserve(size_t size
)
602 itsOptions
.reserve(size
);
605 template <typename T
> void NCurses::Menu
<T
>::ResizeList(size_t size
)
607 if (size
> itsOptions
.size())
609 itsOptions
.resize(size
);
610 for (size_t i
= 0; i
< size
; ++i
)
612 itsOptions
[i
] = new Option();
614 else if (size
< itsOptions
.size())
616 for (size_t i
= size
; i
< itsOptions
.size(); ++i
)
617 delete itsOptions
[i
];
618 itsOptions
.resize(size
);
622 template <typename T
> void NCurses::Menu
<T
>::AddOption(const T
&item
, bool is_bold
, bool is_static
)
624 itsOptions
.push_back(new Option(item
, is_bold
, is_static
));
627 template <typename T
> void NCurses::Menu
<T
>::AddSeparator()
629 itsOptions
.push_back(static_cast<Option
*>(0));
632 template <typename T
> void NCurses::Menu
<T
>::InsertOption(size_t pos
, const T
&item
, bool is_bold
, bool is_static
)
634 itsOptions
.insert(itsOptions
.begin()+pos
, new Option(item
, is_bold
, is_static
));
637 template <typename T
> void NCurses::Menu
<T
>::InsertSeparator(size_t pos
)
639 itsOptions
.insert(itsOptions
.begin()+pos
, 0);
642 template <typename T
> void NCurses::Menu
<T
>::DeleteOption(size_t pos
)
644 if (itsOptionsPtr
->empty())
646 if (itsOptionsPtr
== &itsFilteredOptions
)
648 delete itsOptions
.at(itsFilteredRealPositions
[pos
]);
649 itsOptions
.erase(itsOptions
.begin()+itsFilteredRealPositions
[pos
]);
650 itsFilteredOptions
.erase(itsFilteredOptions
.begin()+pos
);
651 itsFilteredRealPositions
.erase(itsFilteredRealPositions
.begin()+pos
);
652 for (size_t i
= pos
; i
< itsFilteredRealPositions
.size(); ++i
)
653 itsFilteredRealPositions
[i
]--;
657 delete itsOptions
.at(pos
);
658 itsOptions
.erase(itsOptions
.begin()+pos
);
661 if (itsOptionsPtr
->empty())
665 template <typename T
> void NCurses::Menu
<T
>::IntoSeparator(size_t pos
)
667 delete itsOptionsPtr
->at(pos
);
668 (*itsOptionsPtr
)[pos
] = 0;
671 template <typename T
> void NCurses::Menu
<T
>::Bold(int pos
, bool state
)
673 if (!itsOptionsPtr
->at(pos
))
675 (*itsOptionsPtr
)[pos
]->isBold
= state
;
678 template <typename T
> void NCurses::Menu
<T
>::Swap(size_t one
, size_t two
)
680 std::swap(itsOptions
.at(one
), itsOptions
.at(two
));
683 template <typename T
> void NCurses::Menu
<T
>::Move(size_t from
, size_t to
)
688 for (size_t i
= from
; i
> to
; --i
)
689 std::swap(itsOptions
.at(i
), itsOptions
.at(i
-1));
693 for (size_t i
= from
; i
< to
; ++i
)
694 std::swap(itsOptions
.at(i
), itsOptions
.at(i
+1));
698 template <typename T
> bool NCurses::Menu
<T
>::Goto(size_t y
)
700 if (!itsOptionsPtr
->at(itsBeginning
+y
) || itsOptionsPtr
->at(itsBeginning
+y
)->isStatic
)
702 itsHighlight
= itsBeginning
+y
;
706 template <typename T
> void NCurses::Menu
<T
>::Refresh()
708 if (itsOptionsPtr
->empty())
713 int MaxBeginning
= itsOptionsPtr
->size() < itsHeight
? 0 : itsOptionsPtr
->size()-itsHeight
;
715 if (itsBeginning
< itsHighlight
-int(itsHeight
)+1) // highlighted position is off the screen
716 itsBeginning
= itsHighlight
-itsHeight
+1;
718 if (itsBeginning
< 0)
720 else if (itsBeginning
> MaxBeginning
)
721 itsBeginning
= MaxBeginning
;
723 if (!itsOptionsPtr
->empty() && itsHighlight
> int(itsOptionsPtr
->size())-1)
724 itsHighlight
= itsOptionsPtr
->size()-1;
726 if (!(*itsOptionsPtr
)[itsHighlight
] || (*itsOptionsPtr
)[itsHighlight
]->isStatic
) // it shouldn't be here
729 if (!(*itsOptionsPtr
)[itsHighlight
] || (*itsOptionsPtr
)[itsHighlight
]->isStatic
)
734 for (size_t &i
= (itsCurrentlyDrawedPosition
= itsBeginning
); i
< itsBeginning
+itsHeight
; ++i
)
737 if (i
>= itsOptionsPtr
->size())
739 for (; line
< itsHeight
; ++line
)
740 mvwhline(itsWindow
, line
, 0, 32, itsWidth
);
743 if (!(*itsOptionsPtr
)[i
]) // separator
745 mvwhline(itsWindow
, line
++, 0, 0, itsWidth
);
748 if ((*itsOptionsPtr
)[i
]->isBold
)
750 if (highlightEnabled
&& int(i
) == itsHighlight
)
753 *this << itsHighlightColor
;
755 mvwhline(itsWindow
, line
, 0, 32, itsWidth
);
756 if ((*itsOptionsPtr
)[i
]->isSelected
&& itsSelectedPrefix
)
757 *this << *itsSelectedPrefix
;
758 if (itsItemDisplayer
)
759 itsItemDisplayer((*itsOptionsPtr
)[i
]->Item
, itsItemDisplayerUserdata
, this);
760 if ((*itsOptionsPtr
)[i
]->isSelected
&& itsSelectedSuffix
)
761 *this << *itsSelectedSuffix
;
762 if (highlightEnabled
&& int(i
) == itsHighlight
)
765 *this << fmtReverseEnd
;
767 if ((*itsOptionsPtr
)[i
]->isBold
)
774 template <typename T
> void NCurses::Menu
<T
>::Scroll(Where where
)
776 if (itsOptionsPtr
->empty())
778 int MaxHighlight
= itsOptionsPtr
->size()-1;
779 int MaxBeginning
= itsOptionsPtr
->size() < itsHeight
? 0 : itsOptionsPtr
->size()-itsHeight
;
780 int MaxCurrentHighlight
= itsBeginning
+itsHeight
-1;
785 if (itsHighlight
<= itsBeginning
&& itsHighlight
> 0)
789 if (itsHighlight
== 0)
791 if (useCyclicScrolling
)
799 if (!(*itsOptionsPtr
)[itsHighlight
] || (*itsOptionsPtr
)[itsHighlight
]->isStatic
)
801 Scroll(itsHighlight
== 0 && !useCyclicScrolling
? wDown
: wUp
);
807 if (itsHighlight
>= MaxCurrentHighlight
&& itsHighlight
< MaxHighlight
)
811 if (itsHighlight
== MaxHighlight
)
813 if (useCyclicScrolling
)
814 return Scroll(wHome
);
821 if (!(*itsOptionsPtr
)[itsHighlight
] || (*itsOptionsPtr
)[itsHighlight
]->isStatic
)
823 Scroll(itsHighlight
== MaxHighlight
&& !useCyclicScrolling
? wUp
: wDown
);
829 if (useCyclicScrolling
&& itsHighlight
== 0)
831 itsHighlight
-= itsHeight
;
832 itsBeginning
-= itsHeight
;
833 if (itsBeginning
< 0)
836 if (itsHighlight
< 0)
839 if (!(*itsOptionsPtr
)[itsHighlight
] || (*itsOptionsPtr
)[itsHighlight
]->isStatic
)
841 Scroll(itsHighlight
== 0 && !useCyclicScrolling
? wDown
: wUp
);
847 if (useCyclicScrolling
&& itsHighlight
== MaxHighlight
)
848 return Scroll(wHome
);
849 itsHighlight
+= itsHeight
;
850 itsBeginning
+= itsHeight
;
851 if (itsBeginning
> MaxBeginning
)
853 itsBeginning
= MaxBeginning
;
854 if (itsHighlight
> MaxHighlight
)
855 itsHighlight
= MaxHighlight
;
857 if (!(*itsOptionsPtr
)[itsHighlight
] || (*itsOptionsPtr
)[itsHighlight
]->isStatic
)
859 Scroll(itsHighlight
== MaxHighlight
&& !useCyclicScrolling
? wUp
: wDown
);
867 if (!(*itsOptionsPtr
)[itsHighlight
] || (*itsOptionsPtr
)[itsHighlight
]->isStatic
)
869 Scroll(itsHighlight
== 0 ? wDown
: wUp
);
875 itsHighlight
= MaxHighlight
;
876 itsBeginning
= MaxBeginning
;
877 if (!(*itsOptionsPtr
)[itsHighlight
] || (*itsOptionsPtr
)[itsHighlight
]->isStatic
)
879 Scroll(itsHighlight
== MaxHighlight
? wUp
: wDown
);
884 if (useCenteredCursor
)
885 Highlight(itsHighlight
);
888 template <typename T
> void NCurses::Menu
<T
>::Reset()
894 template <typename T
> void NCurses::Menu
<T
>::ClearFiltered()
896 itsFilteredOptions
.clear();
897 itsFilteredRealPositions
.clear();
898 itsOptionsPtr
= &itsOptions
;
901 template <typename T
> void NCurses::Menu
<T
>::Clear()
903 for (option_iterator it
= itsOptions
.begin(); it
!= itsOptions
.end(); ++it
)
909 itsOptionsPtr
= &itsOptions
;
913 template <typename T
> bool NCurses::Menu
<T
>::isBold(int pos
)
915 pos
= pos
== -1 ? itsHighlight
: pos
;
916 if (!itsOptionsPtr
->at(pos
))
918 return (*itsOptionsPtr
)[pos
]->isBold
;
921 template <typename T
> void NCurses::Menu
<T
>::Select(int pos
, bool state
)
923 if (!itsOptionsPtr
->at(pos
))
925 (*itsOptionsPtr
)[pos
]->isSelected
= state
;
928 template <typename T
> void NCurses::Menu
<T
>::Static(int pos
, bool state
)
930 if (!itsOptionsPtr
->at(pos
))
932 (*itsOptionsPtr
)[pos
]->isStatic
= state
;
935 template <typename T
> bool NCurses::Menu
<T
>::isSelected(int pos
) const
937 pos
= pos
== -1 ? itsHighlight
: pos
;
938 if (!itsOptionsPtr
->at(pos
))
940 return (*itsOptionsPtr
)[pos
]->isSelected
;
943 template <typename T
> bool NCurses::Menu
<T
>::isStatic(int pos
) const
945 pos
= pos
== -1 ? itsHighlight
: pos
;
946 if (!itsOptionsPtr
->at(pos
))
948 return (*itsOptionsPtr
)[pos
]->isStatic
;
951 template <typename T
> bool NCurses::Menu
<T
>::hasSelected() const
953 for (option_const_iterator it
= itsOptionsPtr
->begin(); it
!= itsOptionsPtr
->end(); ++it
)
954 if (*it
&& (*it
)->isSelected
)
959 template <typename T
> void NCurses::Menu
<T
>::GetSelected(std::vector
<size_t> &v
) const
961 for (size_t i
= 0; i
< itsOptionsPtr
->size(); ++i
)
962 if ((*itsOptionsPtr
)[i
] && (*itsOptionsPtr
)[i
]->isSelected
)
966 template <typename T
> void NCurses::Menu
<T
>::Highlight(size_t pos
)
969 itsBeginning
= pos
-itsHeight
/2;
972 template <typename T
> size_t NCurses::Menu
<T
>::Size() const
974 return itsOptionsPtr
->size();
977 template <typename T
> size_t NCurses::Menu
<T
>::Choice() const
982 template <typename T
> size_t NCurses::Menu
<T
>::RealChoice() const
985 for (option_const_iterator it
= itsOptionsPtr
->begin(); it
!= itsOptionsPtr
->begin()+itsHighlight
; ++it
)
986 if (*it
&& !(*it
)->isStatic
)
991 template <typename T
> void NCurses::Menu
<T
>::ReverseSelection(size_t beginning
)
993 option_iterator it
= itsOptionsPtr
->begin()+beginning
;
994 for (size_t i
= beginning
; i
< Size(); ++i
, ++it
)
995 (*it
)->isSelected
= !(*it
)->isSelected
&& !(*it
)->isStatic
;
998 template <typename T
> bool NCurses::Menu
<T
>::Search(const std::string
&constraint
, size_t beginning
, int flags
)
1001 itsSearchConstraint
.clear();
1002 if (constraint
.empty())
1004 itsSearchConstraint
= constraint
;
1006 if (regcomp(&rx
, itsSearchConstraint
.c_str(), flags
) == 0)
1008 for (size_t i
= beginning
; i
< itsOptionsPtr
->size(); ++i
)
1010 if (regexec(&rx
, GetOption(i
).c_str(), 0, 0, 0) == 0)
1015 return !itsFound
.empty();
1018 template <typename T
> void NCurses::Menu
<T
>::NextFound(bool wrap
)
1020 if (itsFound
.empty())
1022 std::set
<size_t>::iterator next
= itsFound
.upper_bound(itsHighlight
);
1023 if (next
!= itsFound
.end())
1026 Highlight(*itsFound
.begin());
1029 template <typename T
> void NCurses::Menu
<T
>::PrevFound(bool wrap
)
1031 if (itsFound
.empty())
1033 std::set
<size_t>::iterator prev
= itsFound
.lower_bound(itsHighlight
);
1034 if (prev
!= itsFound
.begin())
1037 Highlight(*itsFound
.rbegin());
1040 template <typename T
> void NCurses::Menu
<T
>::ApplyFilter(const std::string
&filter
, size_t beginning
, int flags
)
1045 if (itsFilter
.empty())
1047 for (size_t i
= 0; i
< beginning
; ++i
)
1049 itsFilteredRealPositions
.push_back(i
);
1050 itsFilteredOptions
.push_back(itsOptions
[i
]);
1053 if (regcomp(&rx
, itsFilter
.c_str(), flags
) == 0)
1055 for (size_t i
= beginning
; i
< itsOptions
.size(); ++i
)
1057 if (regexec(&rx
, GetOption(i
).c_str(), 0, 0, 0) == 0)
1059 itsFilteredRealPositions
.push_back(i
);
1060 itsFilteredOptions
.push_back(itsOptions
[i
]);
1065 itsOptionsPtr
= &itsFilteredOptions
;
1066 if (itsOptionsPtr
->empty()) // oops, we didn't find anything
1070 template <typename T
> const std::string
&NCurses::Menu
<T
>::GetFilter()
1075 template <typename T
> std::string
NCurses::Menu
<T
>::GetOption(size_t pos
)
1077 if (itsOptionsPtr
->at(pos
) && itsGetStringFunction
)
1078 return itsGetStringFunction((*itsOptionsPtr
)[pos
]->Item
, itsGetStringFunctionUserData
);
1083 template <typename T
> T
&NCurses::Menu
<T
>::Back()
1085 if (!itsOptionsPtr
->back())
1086 FatalError("Menu::Back() has requested separator!");
1087 return itsOptionsPtr
->back()->Item
;
1090 template <typename T
> const T
&NCurses::Menu
<T
>::Back() const
1092 if (!itsOptionsPtr
->back())
1093 FatalError("Menu::Back() has requested separator!");
1094 return itsOptionsPtr
->back()->Item
;
1097 template <typename T
> T
&NCurses::Menu
<T
>::Current()
1099 if (!itsOptionsPtr
->at(itsHighlight
))
1100 FatalError("Menu::Current() has requested separator!");
1101 return (*itsOptionsPtr
)[itsHighlight
]->Item
;
1104 template <typename T
> const T
&NCurses::Menu
<T
>::Current() const
1106 if (!itsOptionsPtr
->at(itsHighlight
))
1107 FatalError("Menu::Current() const has requested separator!");
1108 return (*itsOptionsPtr
)[itsHighlight
]->Item
;
1111 template <typename T
> T
&NCurses::Menu
<T
>::at(size_t pos
)
1113 if (!itsOptionsPtr
->at(pos
))
1114 FatalError("Menu::at() has requested separator!");
1115 return (*itsOptionsPtr
)[pos
]->Item
;
1118 template <typename T
> const T
&NCurses::Menu
<T
>::at(size_t pos
) const
1120 if (!itsOptions
->at(pos
))
1121 FatalError("Menu::at() const has requested separator!");
1122 return (*itsOptionsPtr
)[pos
]->Item
;
1125 template <typename T
> const T
&NCurses::Menu
<T
>::operator[](size_t pos
) const
1127 if (!(*itsOptionsPtr
)[pos
])
1128 FatalError("Menu::operator[] const has requested separator!");
1129 return (*itsOptionsPtr
)[pos
]->Item
;
1132 template <typename T
> T
&NCurses::Menu
<T
>::operator[](size_t pos
)
1134 if (!(*itsOptionsPtr
)[pos
])
1135 FatalError("Menu::operator[] has requested separator!");
1136 return (*itsOptionsPtr
)[pos
]->Item
;