ListWindow: convert list_window_callback_fn_t to an abstract class
[ncmpc-debian.git] / src / ListWindow.hxx
1 /* ncmpc (Ncurses MPD Client)
2  * (c) 2004-2018 The Music Player Daemon Project
3  * Project homepage: http://musicpd.org
4  *
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.
9  *
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.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19
20 #ifndef LIST_WINDOW_HXX
21 #define LIST_WINDOW_HXX
22
23 #include "config.h"
24 #include "command.hxx"
25 #include "colors.hxx"
26 #include "ncmpc_curses.h"
27 #include "Size.hxx"
28
29 class ListText;
30 class ListRenderer;
31
32 /**
33  * The bounds of a range selection, see list_window_get_range().
34  */
35 struct ListWindowRange {
36         /**
37          * The index of the first selected item.
38          */
39         unsigned start_index;
40
41         /**
42          * The index after the last selected item.  The selection is
43          * empty when this is the same as "start".
44          */
45         unsigned end_index;
46
47         constexpr bool empty() const {
48                 return start_index >= end_index;
49         }
50
51         constexpr bool Contains(unsigned i) const {
52                 return i >= start_index && i < end_index;
53         }
54
55         struct const_iterator {
56                 unsigned value;
57
58                 const_iterator &operator++() {
59                         ++value;
60                         return *this;
61                 }
62
63                 constexpr bool operator==(const const_iterator &other) const {
64                         return value == other.value;
65                 }
66
67                 constexpr bool operator!=(const const_iterator &other) const {
68                         return !(*this == other);
69                 }
70
71                 const unsigned &operator *() const {
72                         return value;
73                 }
74         };
75
76         constexpr const_iterator begin() const {
77                 return {start_index};
78         }
79
80         constexpr const_iterator end() const {
81                 return {end_index};
82         }
83 };
84
85 struct ListWindow {
86         WINDOW *w;
87         Size size;
88
89         /**
90          * Number of items in this list.
91          */
92         unsigned length = 0;
93
94         unsigned start = 0;
95         unsigned selected = 0;
96
97         /**
98          * Represents the base item.
99          */
100         unsigned range_base = 0;
101
102         /**
103          * Range selection activated?
104          */
105         bool range_selection = false;
106
107         bool hide_cursor = false;
108
109         ListWindow(WINDOW *_w, Size _size)
110                 :w(_w), size(_size) {}
111
112         /** reset a list window (selected=0, start=0) */
113         void Reset();
114
115         void Resize(Size _size);
116
117         void SetLength(unsigned length);
118
119         void Paint(const ListRenderer &renderer) const;
120
121         /** perform basic list window commands (movement) */
122         bool HandleCommand(command_t cmd);
123
124         /**
125          * Scroll the window.  Returns true if the command has been
126          * consumed.
127          */
128         bool HandleScrollCommand(command_t cmd);
129
130 #ifdef HAVE_GETMOUSE
131         /**
132          * The mouse was clicked.  Check if the list should be scrolled
133          * Returns non-zero if the mouse event has been handled.
134          */
135         bool HandleMouse(mmask_t bstate, int y);
136 #endif
137
138         /**
139          * Centers the visible range around item n on the list.
140          */
141         void Center(unsigned n);
142
143         /**
144          * Scrolls the view to item n, as if the cursor would have been moved
145          * to the position.
146          */
147         void ScrollTo(unsigned n);
148
149         /**
150          * Sets the position of the cursor.  Disables range selection.
151          */
152         void SetCursor(unsigned i);
153
154         /**
155          * Moves the cursor.  Modifies the range if range selection is
156          * enabled.
157          */
158         void MoveCursor(unsigned n);
159
160         void MoveCursorNext();
161         void MoveCursorPrevious();
162         void MoveCursorTop();
163         void MoveCursorMiddle();
164         void MoveCursorBottom();
165         void MoveCursorFirst();
166         void MoveCursorLast();
167         void MoveCursorNextPage();
168         void MoveCursorPreviousPage();
169
170         void ScrollUp(unsigned n);
171         void ScrollDown(unsigned n);
172
173         /**
174          * Ensures that the cursor is visible on the screen, i.e. it is not
175          * outside the current scrolling range.
176          */
177         void FetchCursor();
178
179         /**
180          * Determines the lower and upper bound of the range selection.  If
181          * range selection is disabled, it returns the cursor position (range
182          * length is 1).
183          */
184         gcc_pure
185         ListWindowRange GetRange() const;
186
187         /**
188          * Find a string in a list window.
189          */
190         bool Find(const ListText &text,
191                   const char *str,
192                   bool wrap,
193                   bool bell_on_wrap);
194
195         /**
196          * Find a string in a list window (reversed).
197          */
198         bool ReverseFind(const ListText &text,
199                          const char *str,
200                          bool wrap,
201                          bool bell_on_wrap);
202
203         /**
204          * Find a string in a list window which begins with the given
205          * characters in *str.
206          */
207         bool Jump(const ListText &text, const char *str);
208
209 private:
210         gcc_pure
211         unsigned ValidateIndex(unsigned i) const;
212
213         void CheckSelected();
214
215         /**
216          * Scroll after the cursor was moved, the list was changed or
217          * the window was resized.
218          */
219         void CheckOrigin() {
220                 ScrollTo(selected);
221         }
222 };
223
224 #endif