]> git.vomp.tv Git - vompclient.git/blob - wselectlist.cc
Fix subs running during pause - after a jump then quick pause
[vompclient.git] / wselectlist.cc
1 /*
2     Copyright 2004-2020 Chris Tallon
3
4     This file is part of VOMP.
5
6     VOMP is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     VOMP is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with VOMP.  If not, see <https://www.gnu.org/licenses/>.
18 */
19
20 #include <math.h>
21 #include <string.h>
22
23 #include "colour.h"
24
25 #include "wselectlist.h"
26
27 WSelectList::WSelectList():
28 backgroundColour(DrawStyle::VIEWBACKGROUND)
29 {
30 }
31
32 WSelectList::~WSelectList()
33 {
34   clear();
35 }
36
37 void WSelectList::clear()
38 {
39   options.clear();
40
41   selectedOption = 0;
42   topOption = 0;
43   numOptionsDisplayable = 0;
44   numColumns = 0;
45 }
46
47 void WSelectList::setNoLoop()
48 {
49   noLoop = 1;
50 }
51
52 void WSelectList::setBackgroundColour(const DrawStyle& colour)
53 {
54   backgroundColour = colour;
55 }
56
57 void WSelectList::hintSetCurrent(int idx)
58 {
59   selectedOption = idx;
60   if (selectedOption >= static_cast<int>(options.size())) selectedOption = options.size() - 1;
61 }
62
63 void WSelectList::hintSetTop(int idx)
64 {
65   topOption = idx;
66 }
67
68 int WSelectList::addOption(const char* text, void* data, int selected)
69 {
70   int thisNewOption = options.size();
71
72   wsloption wslo;
73   wslo.text = text;
74   wslo.data = data;
75   options.push_back(wslo);
76   if (selected) selectedOption = thisNewOption;
77   return thisNewOption;
78 }
79
80 int WSelectList::addOption(const std::string& text, void* data, int selected)
81 {
82   int thisNewOption = options.size();
83
84   wsloption wslo;
85   wslo.text = text;
86   wslo.data = data;
87   options.push_back(wslo);
88   if (selected) selectedOption = thisNewOption;
89   return thisNewOption;
90 }
91
92 int WSelectList::addOption(const char* text, void* data, int selected, Image& icon)
93 {
94   int thisNewOption = options.size();
95
96   wsloption wslo;
97   wslo.text = text;
98   wslo.data = data;
99   wslo.image = icon;
100   options.push_back(wslo);
101   if (selected) selectedOption = thisNewOption;
102   return thisNewOption;
103 }
104
105 int WSelectList::addOption(const std::string& text, void* data, int selected, Image& icon)
106 {
107   int thisNewOption = options.size();
108
109   wsloption wslo;
110   wslo.text = text;
111   wslo.data = data;
112   wslo.image = icon;
113   options.push_back(wslo);
114   if (selected) selectedOption = thisNewOption;
115   return thisNewOption;
116 }
117
118 void WSelectList::draw()
119 {
120   int fontHeight = getFontHeight();
121   int ySeparation = static_cast<int>(static_cast<float>(fontHeight) * linesPerOption) + gap;
122
123   numOptionsDisplayable = (area.h - 5) / ySeparation;
124
125   if (selectedOption == (topOption + numOptionsDisplayable)) topOption++;
126   if (selectedOption == (topOption - 1)) topOption--;
127   // if still not visible...
128   if ((selectedOption < topOption) || (selectedOption > (topOption + numOptionsDisplayable)))
129   {
130     topOption = selectedOption - (numOptionsDisplayable / 2);
131   }
132
133   if (topOption < 0) topOption = 0;
134
135   fillColour(backgroundColour);
136
137   UINT ypos = 5;
138   for (int i = topOption; i < (topOption + numOptionsDisplayable); i++)
139   {
140     if (i == static_cast<int>(options.size())) return;
141     if ((ypos + ySeparation) > area.h) break;
142
143     if (i == selectedOption && showseloption)
144     {
145       rectangle(0, ypos, area.w, static_cast<UINT>(static_cast<float>(fontHeight) * linesPerOption) - 1, darkseloption ? DrawStyle::SELECTDARKHIGHLIGHT : DrawStyle::SELECTHIGHLIGHT);
146       drawOptionLine(options[i].text, 5, ypos, area.w - 5, DrawStyle::DARKTEXT, options[i].image);
147     }
148     else
149     {
150       rectangle(0, ypos, area.w, static_cast<UINT>(static_cast<float>(fontHeight) * linesPerOption) - 1, DrawStyle::SELECTBACKGROUND);
151       drawOptionLine(options[i].text, 5, ypos, area.w - 5, DrawStyle::LIGHTTEXT, options[i].image);
152     }
153     ypos += ySeparation;
154   }
155 }
156
157 void WSelectList::addColumn(int x)
158 {
159   if (numColumns == 10) return;
160   columns[numColumns++] = x;
161 }
162
163 int WSelectList::getColumn(int x)
164 {
165   if (x >= numColumns) return 0;
166   return columns[x];
167 }
168
169 void WSelectList::drawOptionLine(const std::string& text, int xpos, int ypos, int width, const DrawStyle& colour, Image& image)
170 {
171   UINT curline = 0;
172   UINT taboffset = 0;
173   int fontHeight = getFontHeight();
174   float ypos_mod = static_cast<float>(ypos) + (linesPerOption - floor(linesPerOption)) * static_cast<float>(fontHeight) * 0.5f;
175
176   int imagewidth = 0;
177   int xposmod = xpos;
178   if (numColumns > 1) imagewidth = columns[1] - columns[0];
179   if (image)
180   {
181     drawImage(image, static_cast<float>(xpos), static_cast<float>(ypos), static_cast<float>(imagewidth),
182               static_cast<float>(fontHeight) * linesPerOption, TopLeftLimited);
183     taboffset++;
184     xposmod += xpos;
185   }
186
187   if (!numColumns && linesPerOption == 1)
188   {
189     drawText(text.c_str(), xpos, ypos, width, colour);
190   }
191   else
192   {
193     const char* ctext = text.c_str();
194     char buffer[200];
195     strncpy(buffer, ctext, 199);
196     int currentColumn = taboffset;
197     char* pointer;
198     char* savepointer;
199
200     pointer = STRTOKR(buffer, "\t\n", &savepointer);
201     while(pointer)
202     {
203       drawText(pointer, xposmod + columns[currentColumn], (fontHeight * curline) + static_cast<int>(ypos_mod), width - columns[currentColumn], colour);
204
205       pointer = STRTOKR(NULL, "\t\n", &savepointer);
206       if (pointer)
207       {
208         char delimiter = ctext[pointer - buffer - 1];
209         if (delimiter == '\t') currentColumn++;
210         else if (delimiter == '\n')
211         {
212           currentColumn = taboffset;
213           curline++;
214         }
215       }
216       if (static_cast<float>(curline) >= linesPerOption) return;
217
218       if (currentColumn == 10) return;
219     }
220   }
221 }
222
223 void WSelectList::up()
224 {
225   if (selectedOption > 0)
226   {
227     selectedOption--;
228   }
229   else
230   {
231     if (!noLoop) selectedOption = options.size() - 1;
232   }
233 }
234
235 void WSelectList::down()
236 {
237   if (selectedOption < (static_cast<int>(options.size()) - 1))
238   {
239     selectedOption++;
240   }
241   else
242   {
243     if (!noLoop) selectedOption = 0;
244   }
245 }
246
247 void WSelectList::pageUp()
248 {
249   topOption -= numOptionsDisplayable;
250   if (topOption < 0) topOption = 0;
251
252   selectedOption = topOption;
253 }
254
255 void WSelectList::pageDown()
256 {
257   if ((topOption + numOptionsDisplayable) >= static_cast<int>(options.size()))
258   {
259     selectedOption = options.size() - 1;
260   }
261   else
262   {
263     topOption += numOptionsDisplayable;
264     selectedOption = topOption;
265   }
266 }
267
268 int WSelectList::getTopOption()
269 {
270   return topOption;
271 }
272
273 int WSelectList::getNumOptions()
274 {
275   return options.size();
276 }
277
278 int WSelectList::getBottomOption()
279 {
280   UINT retval = topOption + numOptionsDisplayable;
281   if (retval > options.size()) return options.size();
282   else return retval;
283 }
284
285 int WSelectList::getCurrentOption()
286 {
287   return selectedOption;
288 }
289
290 void* WSelectList::getCurrentOptionData()
291 {
292   if (!options.size()) return 0;
293   return options[selectedOption].data;
294 }
295
296 int WSelectList::getNumOptionsDisplayable()
297 {
298   return numOptionsDisplayable;
299 }
300
301 bool WSelectList::mouseAndroidScroll(int /* x */, int /* y */, int /* sx */, int /* sy */)
302 {
303 /*
304  *  int fontHeight = getFontHeight();
305  *  int movelines= sy/fontHeight;
306  *
307  *  int seloption=selectedOption+movelines;
308  *  if (seloption<0) seloption=0;
309  *  else if (seloption>options.size()-1) seloption=options.size()-1;
310  *  selectedOption=seloption;
311 */
312   return false;
313 }
314
315 bool WSelectList::mouseMove(int x, int y)
316 {
317   int ml = getMouseLine(x - getRootBoxOffsetX(), y - getRootBoxOffsetY());
318   if (ml >= 0 && ml != selectedOption)
319   {
320     selectedOption = ml;
321     return true;
322   }
323   return false;
324 }
325
326 bool WSelectList::mouseLBDOWN(int x, int y)
327 {
328   int ml = getMouseLine(x - getRootBoxOffsetX(), y - getRootBoxOffsetY());
329   if (ml == selectedOption)
330   {
331     /* caller should generate a OK message*/
332     return true;
333   }
334   return false;
335 }
336
337 int WSelectList::getMouseLine(int x, int y)
338 {
339   int fontHeight = getFontHeight();
340   int ySeparation = static_cast<int>(static_cast<float>(fontHeight) * linesPerOption) + gap;
341
342   if (y < 0) return -1;
343   if (x < 0 || x > static_cast<int>(area.w)) return -1;
344   if (y > (10 + numOptionsDisplayable * ySeparation)) return -1;
345
346   int cy = y - 5;
347
348   int selected = cy / ySeparation;
349   if (y < 5) selected = -1;
350   if (selected > numOptionsDisplayable) return -1;
351   /* Important: should be the same algorithm used in draw! */
352   if (selectedOption == (topOption + numOptionsDisplayable)) topOption++;
353   if (selectedOption == (topOption - 1)) topOption--;
354   // if still not visible...
355   if ((selectedOption < topOption) || (selectedOption > (topOption + numOptionsDisplayable)))
356   {
357     topOption = selectedOption - (numOptionsDisplayable / 2);
358   }
359
360   if (topOption < 0) topOption = 0;
361   if ((selected + topOption >= static_cast<int>(options.size())) || (selected + topOption < 0)) return -1;
362   return selected + topOption;
363 }