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