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