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 /// Checks if list is empty
445 /// @return true if list is empty, false otherwise
447 virtual bool Empty() const { return itsOptionsPtr
->empty(); }
449 /// @return size of the list
451 virtual size_t Size() const;
453 /// @return position of currently drawed item. The result is
454 /// defined only within drawing function that is called by Refresh()
457 size_t CurrentlyDrawedPosition() const { return itsCurrentlyDrawedPosition
; }
459 /// @return reference to last item on the list
460 /// @throw List::InvalidItem if requested item is separator
464 /// @return const reference to last item on the list
465 /// @throw List::InvalidItem if requested item is separator
467 const T
&Back() const;
469 /// @return reference to curently highlighted object
470 /// @throw List::InvalidItem if requested item is separator
474 /// @return const reference to curently highlighted object
475 /// @throw List::InvalidItem if requested item is separator
477 const T
&Current() const;
479 /// @param pos requested position
480 /// @return reference to item at given position
481 /// @throw std::out_of_range if given position is out of range
482 /// @throw List::InvalidItem if requested item is separator
486 /// @param pos requested position
487 /// @return const reference to item at given position
488 /// @throw std::out_of_range if given position is out of range
489 /// @throw List::InvalidItem if requested item is separator
491 const T
&at(size_t pos
) const;
493 /// @param pos requested position
494 /// @return const reference to item at given position
495 /// @throw List::InvalidItem if requested item is separator
497 const T
&operator[](size_t pos
) const;
499 /// @param pos requested position
500 /// @return const reference to item at given position
501 /// @throw List::InvalidItem if requested item is separator
503 T
&operator[](size_t pos
);
506 /// Clears filter, filtered data etc.
508 void ClearFiltered();
510 ItemDisplayer itsItemDisplayer
;
511 void *itsItemDisplayerUserdata
;
512 GetStringFunction itsGetStringFunction
;
513 void *itsGetStringFunctionUserData
;
515 std::string itsFilter
;
516 std::string itsSearchConstraint
;
518 std::vector
<Option
*> *itsOptionsPtr
;
519 std::vector
<Option
*> itsOptions
;
520 std::vector
<Option
*> itsFilteredOptions
;
521 std::vector
<size_t> itsFilteredRealPositions
;
522 std::set
<size_t> itsFound
;
527 Color itsHighlightColor
;
528 bool highlightEnabled
;
529 bool useCyclicScrolling
;
531 size_t itsCurrentlyDrawedPosition
;
533 Buffer
*itsSelectedPrefix
;
534 Buffer
*itsSelectedSuffix
;
537 /// Specialization of Menu<T>::GetOption for T = std::string, it's obvious
538 /// that if strings are stored, we don't need extra function to convert
539 /// them to strings by default
540 template <> std::string Menu
<std::string
>::GetOption(size_t pos
);
543 template <typename T
> NCurses::Menu
<T
>::Menu(size_t startx
,
547 const std::string
&title
,
550 : Window(startx
, starty
, width
, height
, title
, color
, border
),
552 itsItemDisplayerUserdata(0),
553 itsGetStringFunction(0),
554 itsGetStringFunctionUserData(0),
555 itsOptionsPtr(&itsOptions
),
558 itsHighlightColor(itsBaseColor
),
560 useCyclicScrolling(0),
561 itsSelectedPrefix(0),
566 template <typename T
> NCurses::Menu
<T
>::Menu(const Menu
&m
) : Window(m
),
567 itsItemDisplayer(m
.itsItemDisplayer
),
568 itsItemDisplayerUserdata(m
.itsItemDisplayerUserdata
),
569 itsGetStringFunction(m
.itsGetStringFunction
),
570 itsGetStringFunctionUserData(m
.itsGetStringFunctionUserData
),
571 itsOptionsPtr(m
.itsOptionsPtr
),
572 itsBeginning(m
.itsBeginning
),
573 itsHighlight(m
.itsHighlight
),
574 itsHighlightColor(m
.itsHighlightColor
),
575 highlightEnabled(m
.highlightEnabled
),
576 itsSelectedPrefix(m
.itsSelectedPrefix
),
577 itsSelectedSuffix(m
.itsSelectedSuffix
)
579 itsOptions
.reserve(m
.itsOptions
.size());
580 for (option_const_iterator it
= m
.itsOptions
.begin(); it
!= m
.itsOptions
.end(); ++it
)
581 itsOptions
.push_back(new Option(**it
));
584 template <typename T
> NCurses::Menu
<T
>::~Menu()
586 for (option_iterator it
= itsOptions
.begin(); it
!= itsOptions
.end(); ++it
)
590 template <typename T
> void NCurses::Menu
<T
>::Reserve(size_t size
)
592 itsOptions
.reserve(size
);
595 template <typename T
> void NCurses::Menu
<T
>::ResizeList(size_t size
)
597 if (size
> itsOptions
.size())
599 itsOptions
.resize(size
);
600 for (size_t i
= 0; i
< size
; ++i
)
602 itsOptions
[i
] = new Option();
604 else if (size
< itsOptions
.size())
606 for (size_t i
= size
; i
< itsOptions
.size(); ++i
)
607 delete itsOptions
[i
];
608 itsOptions
.resize(size
);
612 template <typename T
> void NCurses::Menu
<T
>::AddOption(const T
&item
, bool is_bold
, bool is_static
)
614 itsOptions
.push_back(new Option(item
, is_bold
, is_static
));
617 template <typename T
> void NCurses::Menu
<T
>::AddSeparator()
619 itsOptions
.push_back(static_cast<Option
*>(0));
622 template <typename T
> void NCurses::Menu
<T
>::InsertOption(size_t pos
, const T
&item
, bool is_bold
, bool is_static
)
624 itsOptions
.insert(itsOptions
.begin()+pos
, new Option(item
, is_bold
, is_static
));
627 template <typename T
> void NCurses::Menu
<T
>::InsertSeparator(size_t pos
)
629 itsOptions
.insert(itsOptions
.begin()+pos
, 0);
632 template <typename T
> void NCurses::Menu
<T
>::DeleteOption(size_t pos
)
634 if (itsOptionsPtr
->empty())
636 if (itsOptionsPtr
== &itsFilteredOptions
)
638 delete itsOptions
.at(itsFilteredRealPositions
[pos
]);
639 itsOptions
.erase(itsOptions
.begin()+itsFilteredRealPositions
[pos
]);
640 itsFilteredOptions
.erase(itsFilteredOptions
.begin()+pos
);
641 itsFilteredRealPositions
.erase(itsFilteredRealPositions
.begin()+pos
);
642 for (size_t i
= pos
; i
< itsFilteredRealPositions
.size(); ++i
)
643 itsFilteredRealPositions
[i
]--;
647 delete itsOptions
.at(pos
);
648 itsOptions
.erase(itsOptions
.begin()+pos
);
651 if (itsOptionsPtr
->empty())
655 template <typename T
> void NCurses::Menu
<T
>::IntoSeparator(size_t pos
)
657 delete itsOptionsPtr
->at(pos
);
658 (*itsOptionsPtr
)[pos
] = 0;
661 template <typename T
> void NCurses::Menu
<T
>::Bold(int pos
, bool state
)
663 if (!itsOptionsPtr
->at(pos
))
665 (*itsOptionsPtr
)[pos
]->isBold
= state
;
668 template <typename T
> void NCurses::Menu
<T
>::Swap(size_t one
, size_t two
)
670 std::swap(itsOptions
.at(one
), itsOptions
.at(two
));
673 template <typename T
> void NCurses::Menu
<T
>::Move(size_t from
, size_t to
)
678 for (size_t i
= from
; i
> to
; --i
)
679 std::swap(itsOptions
.at(i
), itsOptions
.at(i
-1));
683 for (size_t i
= from
; i
< to
; ++i
)
684 std::swap(itsOptions
.at(i
), itsOptions
.at(i
+1));
688 template <typename T
> bool NCurses::Menu
<T
>::Goto(size_t y
)
690 if (!itsOptionsPtr
->at(itsBeginning
+y
) || itsOptionsPtr
->at(itsBeginning
+y
)->isStatic
)
692 itsHighlight
= itsBeginning
+y
;
696 template <typename T
> void NCurses::Menu
<T
>::Refresh()
698 if (itsOptionsPtr
->empty())
703 int MaxBeginning
= itsOptionsPtr
->size() < itsHeight
? 0 : itsOptionsPtr
->size()-itsHeight
;
705 if (itsBeginning
< itsHighlight
-int(itsHeight
)+1) // highlighted position is off the screen
706 itsBeginning
= itsHighlight
-itsHeight
+1;
708 if (itsBeginning
< 0)
710 else if (itsBeginning
> MaxBeginning
)
711 itsBeginning
= MaxBeginning
;
713 if (!itsOptionsPtr
->empty() && itsHighlight
> int(itsOptionsPtr
->size())-1)
714 itsHighlight
= itsOptionsPtr
->size()-1;
716 if (!(*itsOptionsPtr
)[itsHighlight
] || (*itsOptionsPtr
)[itsHighlight
]->isStatic
) // it shouldn't be here
719 if (!(*itsOptionsPtr
)[itsHighlight
] || (*itsOptionsPtr
)[itsHighlight
]->isStatic
)
724 for (size_t &i
= (itsCurrentlyDrawedPosition
= itsBeginning
); i
< itsBeginning
+itsHeight
; ++i
)
727 if (i
>= itsOptionsPtr
->size())
729 for (; line
< itsHeight
; ++line
)
730 mvwhline(itsWindow
, line
, 0, 32, itsWidth
);
733 if (!(*itsOptionsPtr
)[i
]) // separator
735 mvwhline(itsWindow
, line
++, 0, 0, itsWidth
);
738 if ((*itsOptionsPtr
)[i
]->isBold
)
740 if (highlightEnabled
&& int(i
) == itsHighlight
)
743 *this << itsHighlightColor
;
745 mvwhline(itsWindow
, line
, 0, 32, itsWidth
);
746 if ((*itsOptionsPtr
)[i
]->isSelected
&& itsSelectedPrefix
)
747 *this << *itsSelectedPrefix
;
748 if (itsItemDisplayer
)
749 itsItemDisplayer((*itsOptionsPtr
)[i
]->Item
, itsItemDisplayerUserdata
, this);
750 if ((*itsOptionsPtr
)[i
]->isSelected
&& itsSelectedSuffix
)
751 *this << *itsSelectedSuffix
;
752 if (highlightEnabled
&& int(i
) == itsHighlight
)
755 *this << fmtReverseEnd
;
757 if ((*itsOptionsPtr
)[i
]->isBold
)
764 template <typename T
> void NCurses::Menu
<T
>::Scroll(Where where
)
766 if (itsOptionsPtr
->empty())
768 int MaxHighlight
= itsOptionsPtr
->size()-1;
769 int MaxBeginning
= itsOptionsPtr
->size() < itsHeight
? 0 : itsOptionsPtr
->size()-itsHeight
;
770 int MaxCurrentHighlight
= itsBeginning
+itsHeight
-1;
775 if (itsHighlight
<= itsBeginning
&& itsHighlight
> 0)
779 if (itsHighlight
== 0)
781 if (useCyclicScrolling
)
789 if (!(*itsOptionsPtr
)[itsHighlight
] || (*itsOptionsPtr
)[itsHighlight
]->isStatic
)
791 Scroll(itsHighlight
== 0 && !useCyclicScrolling
? wDown
: wUp
);
797 if (itsHighlight
>= MaxCurrentHighlight
&& itsHighlight
< MaxHighlight
)
801 if (itsHighlight
== MaxHighlight
)
803 if (useCyclicScrolling
)
804 return Scroll(wHome
);
811 if (!(*itsOptionsPtr
)[itsHighlight
] || (*itsOptionsPtr
)[itsHighlight
]->isStatic
)
813 Scroll(itsHighlight
== MaxHighlight
&& !useCyclicScrolling
? wUp
: wDown
);
819 if (useCyclicScrolling
&& itsHighlight
== 0)
821 itsHighlight
-= itsHeight
;
822 itsBeginning
-= itsHeight
;
823 if (itsBeginning
< 0)
826 if (itsHighlight
< 0)
829 if (!(*itsOptionsPtr
)[itsHighlight
] || (*itsOptionsPtr
)[itsHighlight
]->isStatic
)
831 Scroll(itsHighlight
== 0 && !useCyclicScrolling
? wDown
: wUp
);
837 if (useCyclicScrolling
&& itsHighlight
== MaxHighlight
)
838 return Scroll(wHome
);
839 itsHighlight
+= itsHeight
;
840 itsBeginning
+= itsHeight
;
841 if (itsBeginning
> MaxBeginning
)
843 itsBeginning
= MaxBeginning
;
844 if (itsHighlight
> MaxHighlight
)
845 itsHighlight
= MaxHighlight
;
847 if (!(*itsOptionsPtr
)[itsHighlight
] || (*itsOptionsPtr
)[itsHighlight
]->isStatic
)
849 Scroll(itsHighlight
== MaxHighlight
&& !useCyclicScrolling
? wUp
: wDown
);
857 if (!(*itsOptionsPtr
)[itsHighlight
] || (*itsOptionsPtr
)[itsHighlight
]->isStatic
)
859 Scroll(itsHighlight
== 0 ? wDown
: wUp
);
865 itsHighlight
= MaxHighlight
;
866 itsBeginning
= MaxBeginning
;
867 if (!(*itsOptionsPtr
)[itsHighlight
] || (*itsOptionsPtr
)[itsHighlight
]->isStatic
)
869 Scroll(itsHighlight
== MaxHighlight
? wUp
: wDown
);
876 template <typename T
> void NCurses::Menu
<T
>::Reset()
882 template <typename T
> void NCurses::Menu
<T
>::ClearFiltered()
884 itsFilteredOptions
.clear();
885 itsFilteredRealPositions
.clear();
886 itsOptionsPtr
= &itsOptions
;
889 template <typename T
> void NCurses::Menu
<T
>::Clear()
891 for (option_iterator it
= itsOptions
.begin(); it
!= itsOptions
.end(); ++it
)
897 itsOptionsPtr
= &itsOptions
;
901 template <typename T
> bool NCurses::Menu
<T
>::isBold(int pos
)
903 pos
= pos
== -1 ? itsHighlight
: pos
;
904 if (!itsOptionsPtr
->at(pos
))
906 return (*itsOptionsPtr
)[pos
]->isBold
;
909 template <typename T
> void NCurses::Menu
<T
>::Select(int pos
, bool state
)
911 if (!itsOptionsPtr
->at(pos
))
913 (*itsOptionsPtr
)[pos
]->isSelected
= state
;
916 template <typename T
> void NCurses::Menu
<T
>::Static(int pos
, bool state
)
918 if (!itsOptionsPtr
->at(pos
))
920 (*itsOptionsPtr
)[pos
]->isStatic
= state
;
923 template <typename T
> bool NCurses::Menu
<T
>::isSelected(int pos
) const
925 pos
= pos
== -1 ? itsHighlight
: pos
;
926 if (!itsOptionsPtr
->at(pos
))
928 return (*itsOptionsPtr
)[pos
]->isSelected
;
931 template <typename T
> bool NCurses::Menu
<T
>::isStatic(int pos
) const
933 pos
= pos
== -1 ? itsHighlight
: pos
;
934 if (!itsOptionsPtr
->at(pos
))
936 return (*itsOptionsPtr
)[pos
]->isStatic
;
939 template <typename T
> bool NCurses::Menu
<T
>::hasSelected() const
941 for (option_const_iterator it
= itsOptionsPtr
->begin(); it
!= itsOptionsPtr
->end(); ++it
)
942 if (*it
&& (*it
)->isSelected
)
947 template <typename T
> void NCurses::Menu
<T
>::GetSelected(std::vector
<size_t> &v
) const
949 for (size_t i
= 0; i
< itsOptionsPtr
->size(); ++i
)
950 if ((*itsOptionsPtr
)[i
] && (*itsOptionsPtr
)[i
]->isSelected
)
954 template <typename T
> void NCurses::Menu
<T
>::Highlight(size_t pos
)
957 itsBeginning
= pos
-itsHeight
/2;
960 template <typename T
> size_t NCurses::Menu
<T
>::Size() const
962 return itsOptionsPtr
->size();
965 template <typename T
> size_t NCurses::Menu
<T
>::Choice() const
970 template <typename T
> size_t NCurses::Menu
<T
>::RealChoice() const
973 for (option_const_iterator it
= itsOptionsPtr
->begin(); it
!= itsOptionsPtr
->begin()+itsHighlight
; ++it
)
974 if (*it
&& !(*it
)->isStatic
)
979 template <typename T
> void NCurses::Menu
<T
>::ReverseSelection(size_t beginning
)
981 option_iterator it
= itsOptionsPtr
->begin()+beginning
;
982 for (size_t i
= beginning
; i
< Size(); ++i
, ++it
)
983 (*it
)->isSelected
= !(*it
)->isSelected
&& !(*it
)->isStatic
;
986 template <typename T
> bool NCurses::Menu
<T
>::Search(const std::string
&constraint
, size_t beginning
, int flags
)
989 itsSearchConstraint
.clear();
990 if (constraint
.empty())
992 itsSearchConstraint
= constraint
;
994 if (regcomp(&rx
, itsSearchConstraint
.c_str(), flags
) == 0)
996 for (size_t i
= beginning
; i
< itsOptionsPtr
->size(); ++i
)
998 if (regexec(&rx
, GetOption(i
).c_str(), 0, 0, 0) == 0)
1003 return !itsFound
.empty();
1006 template <typename T
> void NCurses::Menu
<T
>::NextFound(bool wrap
)
1008 if (itsFound
.empty())
1010 std::set
<size_t>::iterator next
= itsFound
.upper_bound(itsHighlight
);
1011 if (next
!= itsFound
.end())
1014 Highlight(*itsFound
.begin());
1017 template <typename T
> void NCurses::Menu
<T
>::PrevFound(bool wrap
)
1019 if (itsFound
.empty())
1021 std::set
<size_t>::iterator prev
= itsFound
.lower_bound(itsHighlight
);
1022 if (prev
!= itsFound
.begin())
1025 Highlight(*itsFound
.rbegin());
1028 template <typename T
> void NCurses::Menu
<T
>::ApplyFilter(const std::string
&filter
, size_t beginning
, int flags
)
1033 if (itsFilter
.empty())
1035 for (size_t i
= 0; i
< beginning
; ++i
)
1037 itsFilteredRealPositions
.push_back(i
);
1038 itsFilteredOptions
.push_back(itsOptions
[i
]);
1041 if (regcomp(&rx
, itsFilter
.c_str(), flags
) == 0)
1043 for (size_t i
= beginning
; i
< itsOptions
.size(); ++i
)
1045 if (regexec(&rx
, GetOption(i
).c_str(), 0, 0, 0) == 0)
1047 itsFilteredRealPositions
.push_back(i
);
1048 itsFilteredOptions
.push_back(itsOptions
[i
]);
1053 itsOptionsPtr
= &itsFilteredOptions
;
1054 if (itsOptionsPtr
->empty()) // oops, we didn't find anything
1058 template <typename T
> const std::string
&NCurses::Menu
<T
>::GetFilter()
1063 template <typename T
> std::string
NCurses::Menu
<T
>::GetOption(size_t pos
)
1065 if (itsOptionsPtr
->at(pos
) && itsGetStringFunction
)
1066 return itsGetStringFunction((*itsOptionsPtr
)[pos
]->Item
, itsGetStringFunctionUserData
);
1071 template <typename T
> T
&NCurses::Menu
<T
>::Back()
1073 if (!itsOptionsPtr
->back())
1074 FatalError("Menu::Back() has requested separator!");
1075 return itsOptionsPtr
->back()->Item
;
1078 template <typename T
> const T
&NCurses::Menu
<T
>::Back() const
1080 if (!itsOptionsPtr
->back())
1081 FatalError("Menu::Back() has requested separator!");
1082 return itsOptionsPtr
->back()->Item
;
1085 template <typename T
> T
&NCurses::Menu
<T
>::Current()
1087 if (!itsOptionsPtr
->at(itsHighlight
))
1088 FatalError("Menu::Current() has requested separator!");
1089 return (*itsOptionsPtr
)[itsHighlight
]->Item
;
1092 template <typename T
> const T
&NCurses::Menu
<T
>::Current() const
1094 if (!itsOptionsPtr
->at(itsHighlight
))
1095 FatalError("Menu::Current() const has requested separator!");
1096 return (*itsOptionsPtr
)[itsHighlight
]->Item
;
1099 template <typename T
> T
&NCurses::Menu
<T
>::at(size_t pos
)
1101 if (!itsOptionsPtr
->at(pos
))
1102 FatalError("Menu::at() has requested separator!");
1103 return (*itsOptionsPtr
)[pos
]->Item
;
1106 template <typename T
> const T
&NCurses::Menu
<T
>::at(size_t pos
) const
1108 if (!itsOptions
->at(pos
))
1109 FatalError("Menu::at() const has requested separator!");
1110 return (*itsOptionsPtr
)[pos
]->Item
;
1113 template <typename T
> const T
&NCurses::Menu
<T
>::operator[](size_t pos
) const
1115 if (!(*itsOptionsPtr
)[pos
])
1116 FatalError("Menu::operator[] const has requested separator!");
1117 return (*itsOptionsPtr
)[pos
]->Item
;
1120 template <typename T
> T
&NCurses::Menu
<T
>::operator[](size_t pos
)
1122 if (!(*itsOptionsPtr
)[pos
])
1123 FatalError("Menu::operator[] has requested separator!");
1124 return (*itsOptionsPtr
)[pos
]->Item
;