Compiler.h: move to util/
[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 "ncmpc_curses.h"
25 #include "Size.hxx"
26 #include "util/Compiler.h"
27
28 enum class Command : unsigned;
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 class ListWindow {
86 public:
87         WINDOW *w;
88         Size size;
89
90         /**
91          * Number of items in this list.
92          */
93         unsigned length = 0;
94
95         unsigned start = 0;
96         unsigned selected = 0;
97
98         /**
99          * Represents the base item.
100          */
101         unsigned range_base = 0;
102
103         /**
104          * Range selection activated?
105          */
106         bool range_selection = false;
107
108         bool hide_cursor = false;
109
110         ListWindow(WINDOW *_w, Size _size)
111                 :w(_w), size(_size) {}
112
113         /** reset a list window (selected=0, start=0) */
114         void Reset();
115
116         void Resize(Size _size);
117
118         void SetLength(unsigned length);
119
120         void Paint(const ListRenderer &renderer) const;
121
122         /** perform basic list window commands (movement) */
123         bool HandleCommand(Command cmd);
124
125         /**
126          * Scroll the window.  Returns true if the command has been
127          * consumed.
128          */
129         bool HandleScrollCommand(Command cmd);
130
131 #ifdef HAVE_GETMOUSE
132         /**
133          * The mouse was clicked.  Check if the list should be scrolled
134          * Returns non-zero if the mouse event has been handled.
135          */
136         bool HandleMouse(mmask_t bstate, int y);
137 #endif
138
139         /**
140          * Centers the visible range around item n on the list.
141          */
142         void Center(unsigned n);
143
144         /**
145          * Scrolls the view to item n, as if the cursor would have been moved
146          * to the position.
147          */
148         void ScrollTo(unsigned n);
149
150         /**
151          * Sets the position of the cursor.  Disables range selection.
152          */
153         void SetCursor(unsigned i);
154
155         /**
156          * Moves the cursor.  Modifies the range if range selection is
157          * enabled.
158          */
159         void MoveCursor(unsigned n);
160
161         void MoveCursorNext();
162         void MoveCursorPrevious();
163         void MoveCursorTop();
164         void MoveCursorMiddle();
165         void MoveCursorBottom();
166         void MoveCursorFirst();
167         void MoveCursorLast();
168         void MoveCursorNextPage();
169         void MoveCursorPreviousPage();
170
171         void ScrollUp(unsigned n);
172         void ScrollDown(unsigned n);
173
174         /**
175          * Ensures that the cursor is visible on the screen, i.e. it is not
176          * outside the current scrolling range.
177          */
178         void FetchCursor();
179
180         /**
181          * Determines the lower and upper bound of the range selection.  If
182          * range selection is disabled, it returns the cursor position (range
183          * length is 1).
184          */
185         gcc_pure
186         ListWindowRange GetRange() const;
187
188         /**
189          * Find a string in a list window.
190          */
191         bool Find(const ListText &text,
192                   const char *str,
193                   bool wrap,
194                   bool bell_on_wrap);
195
196         /**
197          * Find a string in a list window (reversed).
198          */
199         bool ReverseFind(const ListText &text,
200                          const char *str,
201                          bool wrap,
202                          bool bell_on_wrap);
203
204         /**
205          * Find a string in a list window which begins with the given
206          * characters in *str.
207          */
208         bool Jump(const ListText &text, const char *str);
209
210 private:
211         gcc_pure
212         unsigned ValidateIndex(unsigned i) const;
213
214         void CheckSelected();
215
216         /**
217          * Scroll after the cursor was moved, the list was changed or
218          * the window was resized.
219          */
220         void CheckOrigin() {
221                 ScrollTo(selected);
222         }
223 };
224
225 #endif