2 Copyright 2004-2020 Chris Tallon
4 This file is part of VOMP.
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.
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.
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/>.
25 #include "wselectlist.h"
27 WSelectList::WSelectList():
28 backgroundColour(DrawStyle::VIEWBACKGROUND)
32 WSelectList::~WSelectList()
37 void WSelectList::clear()
43 numOptionsDisplayable = 0;
47 void WSelectList::setNoLoop()
52 void WSelectList::setBackgroundColour(const DrawStyle& colour)
54 backgroundColour = colour;
57 void WSelectList::hintSetCurrent(int idx)
60 if (selectedOption >= toi4(options.size())) selectedOption = options.size() - 1;
63 void WSelectList::hintSetTop(int idx)
68 int WSelectList::addOption(const char* text, void* data, int selected)
70 int thisNewOption = options.size();
75 options.push_back(wslo);
76 if (selected) selectedOption = thisNewOption;
80 int WSelectList::addOption(const std::string& text, void* data, int selected)
82 int thisNewOption = options.size();
87 options.push_back(wslo);
88 if (selected) selectedOption = thisNewOption;
92 int WSelectList::addOption(const char* text, void* data, int selected, Image& icon)
94 int thisNewOption = options.size();
100 options.push_back(wslo);
101 if (selected) selectedOption = thisNewOption;
102 return thisNewOption;
105 int WSelectList::addOption(const std::string& text, void* data, int selected, Image& icon)
107 int thisNewOption = options.size();
113 options.push_back(wslo);
114 if (selected) selectedOption = thisNewOption;
115 return thisNewOption;
118 void WSelectList::draw()
120 int fontHeight = getFontHeight();
121 int ySeparation = toi4(static_cast<float>(fontHeight) * linesPerOption) + gap;
123 numOptionsDisplayable = (area.h - 5) / ySeparation;
125 if (selectedOption == (topOption + numOptionsDisplayable)) topOption++;
126 if (selectedOption == (topOption - 1)) topOption--;
127 // if still not visible...
128 if ((selectedOption < topOption) || (selectedOption > (topOption + numOptionsDisplayable)))
130 topOption = selectedOption - (numOptionsDisplayable / 2);
133 if (topOption < 0) topOption = 0;
135 fillColour(backgroundColour);
138 for (int i = topOption; i < (topOption + numOptionsDisplayable); i++)
140 if (i == toi4(options.size())) return;
141 if ((ypos + ySeparation) > area.h) break;
143 if (i == selectedOption && showseloption)
145 rectangle(0, ypos, area.w, static_cast<u4>(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);
150 rectangle(0, ypos, area.w, static_cast<u4>(static_cast<float>(fontHeight) * linesPerOption) - 1, DrawStyle::SELECTBACKGROUND);
151 drawOptionLine(options[i].text, 5, ypos, area.w - 5, DrawStyle::LIGHTTEXT, options[i].image);
157 void WSelectList::addColumn(int x)
159 if (numColumns == 10) return;
160 columns[numColumns++] = x;
163 int WSelectList::getColumn(int x)
165 if (x >= numColumns) return 0;
169 void WSelectList::drawOptionLine(const std::string& text, int xpos, int ypos, int width, const DrawStyle& colour, Image& image)
173 int fontHeight = getFontHeight();
174 float ypos_mod = static_cast<float>(ypos) + (linesPerOption - floor(linesPerOption)) * static_cast<float>(fontHeight) * 0.5f;
178 if (numColumns > 1) imagewidth = columns[1] - columns[0];
181 drawImage(image, static_cast<float>(xpos), static_cast<float>(ypos), static_cast<float>(imagewidth),
182 static_cast<float>(fontHeight) * linesPerOption, TopLeftLimited);
187 if (!numColumns && linesPerOption == 1)
189 drawText(text.c_str(), xpos, ypos, width, colour);
193 const char* ctext = text.c_str();
195 strncpy(buffer, ctext, 199);
196 int currentColumn = taboffset;
200 pointer = STRTOKR(buffer, "\t\n", &savepointer);
203 drawText(pointer, xposmod + columns[currentColumn], (fontHeight * curline) + toi4(ypos_mod), width - columns[currentColumn], colour);
205 pointer = STRTOKR(NULL, "\t\n", &savepointer);
208 char delimiter = ctext[pointer - buffer - 1];
209 if (delimiter == '\t') currentColumn++;
210 else if (delimiter == '\n')
212 currentColumn = taboffset;
216 if (static_cast<float>(curline) >= linesPerOption) return;
218 if (currentColumn == 10) return;
223 void WSelectList::up()
225 if (selectedOption > 0)
231 if (!noLoop) selectedOption = options.size() - 1;
235 void WSelectList::down()
237 if (selectedOption < (toi4(options.size()) - 1))
243 if (!noLoop) selectedOption = 0;
247 void WSelectList::pageUp()
249 topOption -= numOptionsDisplayable;
250 if (topOption < 0) topOption = 0;
252 selectedOption = topOption;
255 void WSelectList::pageDown()
257 if ((topOption + numOptionsDisplayable) >= toi4(options.size()))
259 selectedOption = options.size() - 1;
263 topOption += numOptionsDisplayable;
264 selectedOption = topOption;
268 int WSelectList::getTopOption()
273 int WSelectList::getNumOptions()
275 return options.size();
278 int WSelectList::getBottomOption()
280 u4 retval = topOption + numOptionsDisplayable;
281 if (retval > options.size()) return options.size();
285 int WSelectList::getCurrentOption()
287 return selectedOption;
290 void* WSelectList::getCurrentOptionData()
292 if (!options.size()) return 0;
293 return options[selectedOption].data;
296 int WSelectList::getNumOptionsDisplayable()
298 return numOptionsDisplayable;
301 bool WSelectList::mouseAndroidScroll(int /* x */, int /* y */, int /* sx */, int /* sy */)
304 * int fontHeight = getFontHeight();
305 * int movelines= sy/fontHeight;
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;
315 bool WSelectList::mouseMove(int x, int y)
317 int ml = getMouseLine(x - getRootBoxOffsetX(), y - getRootBoxOffsetY());
318 if (ml >= 0 && ml != selectedOption)
326 bool WSelectList::mouseLBDOWN(int x, int y)
328 int ml = getMouseLine(x - getRootBoxOffsetX(), y - getRootBoxOffsetY());
329 if (ml == selectedOption)
331 /* caller should generate a OK message*/
337 int WSelectList::getMouseLine(int x, int y)
339 int fontHeight = getFontHeight();
340 int ySeparation = toi4(static_cast<float>(fontHeight) * linesPerOption) + gap;
342 if (y < 0) return -1;
343 if (x < 0 || x > toi4(area.w)) return -1;
344 if (y > (10 + numOptionsDisplayable * ySeparation)) return -1;
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)))
357 topOption = selectedOption - (numOptionsDisplayable / 2);
360 if (topOption < 0) topOption = 0;
361 if ((selected + topOption >= toi4(options.size())) || (selected + topOption < 0)) return -1;
362 return selected + topOption;