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