]> git.vomp.tv Git - vompclient.git/blob - wselectlist.cc
Remove deprecated max() function
[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   int vsize = options.size();
40   for (int i = 0; i < vsize; i++)
41   {
42     if (options[i].pict) delete options[i].pict;
43   }
44   options.clear();
45
46   selectedOption = 0;
47   topOption = 0;
48   numOptionsDisplayable = 0;
49   numColumns = 0;
50 }
51
52 void WSelectList::setNoLoop()
53 {
54   noLoop = 1;
55 }
56
57 void WSelectList::setBackgroundColour(const DrawStyle& colour)
58 {
59   backgroundColour = colour;
60 }
61
62 void WSelectList::hintSetCurrent(int idx)
63 {
64   selectedOption = idx;
65   if (selectedOption >= static_cast<int>(options.size())) selectedOption = options.size() - 1;
66 }
67
68 void WSelectList::hintSetTop(int idx)
69 {
70   topOption = idx;
71 }
72
73 int WSelectList::addOption(const char* text, void* data, int selected, TVMediaInfo* pict)
74 {
75   int thisNewOption = options.size();
76
77   wsloption wslo;
78   wslo.text = text;
79   wslo.data = data;
80   wslo.pict = pict;
81   options.push_back(wslo);
82   if (selected) selectedOption = thisNewOption;
83   return thisNewOption;
84 }
85
86 int WSelectList::addOption(const std::string& text, void* data, int selected, TVMediaInfo* pict)
87 {
88   int thisNewOption = options.size();
89
90   wsloption wslo;
91   wslo.text = text;
92   wslo.data = data;
93   wslo.pict = pict;
94   options.push_back(wslo);
95   if (selected) selectedOption = thisNewOption;
96   return thisNewOption;
97 }
98
99 void WSelectList::draw()
100 {
101   int fontHeight = getFontHeight();
102   int ySeparation = static_cast<int>(static_cast<float>(fontHeight) * linesPerOption) + gap;
103
104   numOptionsDisplayable = (area.h - 5) / ySeparation;
105
106   if (selectedOption == (topOption + numOptionsDisplayable)) topOption++;
107   if (selectedOption == (topOption - 1)) topOption--;
108   // if still not visible...
109   if ((selectedOption < topOption) || (selectedOption > (topOption + numOptionsDisplayable)))
110   {
111     topOption = selectedOption - (numOptionsDisplayable / 2);
112   }
113
114   if (topOption < 0) topOption = 0;
115
116   fillColour(backgroundColour);
117
118   UINT ypos = 5;
119   for (int i = topOption; i < (topOption + numOptionsDisplayable); i++)
120   {
121     if (i == static_cast<int>(options.size())) return;
122     if ((ypos + ySeparation) > area.h) break;
123
124     if (i == selectedOption && showseloption)
125     {
126       rectangle(0, ypos, area.w, static_cast<UINT>(static_cast<float>(fontHeight) * linesPerOption) - 1, darkseloption ? DrawStyle::SELECTDARKHIGHLIGHT : DrawStyle::SELECTHIGHLIGHT);
127       drawOptionLine(options[i].text, 5, ypos, area.w - 5, DrawStyle::DARKTEXT, options[i].pict);
128     }
129     else
130     {
131       rectangle(0, ypos, area.w, static_cast<UINT>(static_cast<float>(fontHeight) * linesPerOption) - 1, DrawStyle::SELECTBACKGROUND);
132       drawOptionLine(options[i].text, 5, ypos, area.w - 5, DrawStyle::LIGHTTEXT, options[i].pict);
133     }
134     ypos += ySeparation;
135   }
136 }
137
138 void WSelectList::addColumn(int x)
139 {
140   if (numColumns == 10) return;
141   columns[numColumns++] = x;
142 }
143
144 int WSelectList::getColumn(int x)
145 {
146   if (x >= numColumns) return 0;
147   return columns[x];
148 }
149
150 void WSelectList::drawOptionLine(const std::string& text, int xpos, int ypos, int width, const DrawStyle& colour, TVMediaInfo* pict)
151 {
152   UINT curline = 0;
153   UINT taboffset = 0;
154   int fontHeight = getFontHeight();
155   float ypos_mod = static_cast<float>(ypos) + (linesPerOption - floor(linesPerOption)) * static_cast<float>(fontHeight) * 0.5f;
156
157   int imagewidth = 0;
158   int xposmod = xpos;
159   if (numColumns > 1) imagewidth = columns[1] - columns[0];
160   if (pict)
161   {
162     drawTVMedia(*pict, static_cast<float>(xpos), static_cast<float>(ypos), static_cast<float>(imagewidth),
163                 static_cast<float>(fontHeight) * linesPerOption, TopLeftLimited);
164     taboffset++;
165     xposmod += xpos;
166   }
167
168   if (!numColumns && linesPerOption == 1)
169   {
170     drawText(text.c_str(), xpos, ypos, width, colour);
171   }
172   else
173   {
174     const char* ctext = text.c_str();
175     char buffer[200];
176     strncpy(buffer, ctext, 199);
177     int currentColumn = taboffset;
178     char* pointer;
179     char* savepointer;
180
181     pointer = STRTOKR(buffer, "\t\n", &savepointer);
182     while(pointer)
183     {
184       drawText(pointer, xposmod + columns[currentColumn], (fontHeight * curline) + static_cast<int>(ypos_mod), width - columns[currentColumn], colour);
185
186       pointer = STRTOKR(NULL, "\t\n", &savepointer);
187       if (pointer)
188       {
189         char delimiter = ctext[pointer - buffer - 1];
190         if (delimiter == '\t') currentColumn++;
191         else if (delimiter == '\n')
192         {
193           currentColumn = taboffset;
194           curline++;
195         }
196       }
197       if (static_cast<float>(curline) >= linesPerOption) return;
198
199       if (currentColumn == 10) return;
200     }
201   }
202 }
203
204 void WSelectList::up()
205 {
206   if (selectedOption > 0)
207   {
208     selectedOption--;
209   }
210   else
211   {
212     if (!noLoop) selectedOption = options.size() - 1;
213   }
214 }
215
216 void WSelectList::down()
217 {
218   if (selectedOption < (static_cast<int>(options.size()) - 1))
219   {
220     selectedOption++;
221   }
222   else
223   {
224     if (!noLoop) selectedOption = 0;
225   }
226 }
227
228 void WSelectList::pageUp()
229 {
230   topOption -= numOptionsDisplayable;
231   if (topOption < 0) topOption = 0;
232
233   selectedOption = topOption;
234 }
235
236 void WSelectList::pageDown()
237 {
238   if ((topOption + numOptionsDisplayable) >= static_cast<int>(options.size()))
239   {
240     selectedOption = options.size() - 1;
241   }
242   else
243   {
244     topOption += numOptionsDisplayable;
245     selectedOption = topOption;
246   }
247 }
248
249 int WSelectList::getTopOption()
250 {
251   return topOption;
252 }
253
254 int WSelectList::getNumOptions()
255 {
256   return options.size();
257 }
258
259 int WSelectList::getBottomOption()
260 {
261   UINT retval = topOption + numOptionsDisplayable;
262   if (retval > options.size()) return options.size();
263   else return retval;
264 }
265
266 int WSelectList::getCurrentOption()
267 {
268   return selectedOption;
269 }
270
271 void* WSelectList::getCurrentOptionData()
272 {
273   if (!options.size()) return 0;
274   return options[selectedOption].data;
275 }
276
277 int WSelectList::getNumOptionsDisplayable()
278 {
279   return numOptionsDisplayable;
280 }
281
282 bool WSelectList::mouseAndroidScroll(int /* x */, int /* y */, int /* sx */, int /* sy */)
283 {
284 /*
285  *  int fontHeight = getFontHeight();
286  *  int movelines= sy/fontHeight;
287  *
288  *  int seloption=selectedOption+movelines;
289  *  if (seloption<0) seloption=0;
290  *  else if (seloption>options.size()-1) seloption=options.size()-1;
291  *  selectedOption=seloption;
292 */
293   return false;
294 }
295
296 bool WSelectList::mouseMove(int x, int y)
297 {
298   int ml = getMouseLine(x - getRootBoxOffsetX(), y - getRootBoxOffsetY());
299   if (ml >= 0 && ml != selectedOption)
300   {
301     selectedOption = ml;
302     return true;
303   }
304   return false;
305 }
306
307 bool WSelectList::mouseLBDOWN(int x, int y)
308 {
309   int ml = getMouseLine(x - getRootBoxOffsetX(), y - getRootBoxOffsetY());
310   if (ml == selectedOption)
311   {
312     /* caller should generate a OK message*/
313     return true;
314   }
315   return false;
316 }
317
318 int WSelectList::getMouseLine(int x, int y)
319 {
320   int fontHeight = getFontHeight();
321   int ySeparation = static_cast<int>(static_cast<float>(fontHeight) * linesPerOption) + gap;
322
323   if (y < 0) return -1;
324   if (x < 0 || x > static_cast<int>(area.w)) return -1;
325   if (y > (10 + numOptionsDisplayable * ySeparation)) return -1;
326
327   int cy = y - 5;
328
329   int selected = cy / ySeparation;
330   if (y < 5) selected = -1;
331   if (selected > numOptionsDisplayable) return -1;
332   /* Important: should be the same algorithm used in draw! */
333   if (selectedOption == (topOption + numOptionsDisplayable)) topOption++;
334   if (selectedOption == (topOption - 1)) topOption--;
335   // if still not visible...
336   if ((selectedOption < topOption) || (selectedOption > (topOption + numOptionsDisplayable)))
337   {
338     topOption = selectedOption - (numOptionsDisplayable / 2);
339   }
340
341   if (topOption < 0) topOption = 0;
342   if ((selected + topOption >= static_cast<int>(options.size())) || (selected + topOption < 0)) return -1;
343   return selected + topOption;
344 }