]> git.vomp.tv Git - vompclient.git/blob - wselectlist.cc
Fix for possible crash when removing bar
[vompclient.git] / wselectlist.cc
1 /*
2     Copyright 2004-2005 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, write to the Free Software
18     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 */
20
21 #include "wselectlist.h"
22
23 WSelectList::WSelectList()
24 {
25   selectedOption = 0;
26   topOption = 0;
27   numOptionsDisplayable = 0;
28   numColumns = 0;
29   noLoop = 0;
30   gap = 1;
31   showseloption = true;
32 }
33
34 WSelectList::~WSelectList()
35 {
36   clear();
37 }
38
39 void WSelectList::clear()
40 {
41   int vsize = options.size();
42   for (int i = 0; i < vsize; i++)
43   {
44     delete[] options[i].text;
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::hintSetCurrent(int idx)
60 {
61   selectedOption = idx;
62   if (selectedOption >= options.size()) selectedOption = options.size() - 1;
63 }
64
65 void WSelectList::hintSetTop(int idx)
66 {
67   topOption = idx;
68 }
69
70 int WSelectList::addOption(char* text, ULONG data, int selected)
71 {
72   int thisNewOption = options.size();
73
74   wsloption wslo;
75   wslo.text = new char[strlen(text) + 1];
76   strcpy(wslo.text, text);
77   wslo.data = data;
78   options.push_back(wslo);
79   if (selected) selectedOption = thisNewOption;
80   return thisNewOption;
81 }
82
83 void WSelectList::draw()
84 {
85   int fontHeight = surface->getFontHeight();
86   int ySeperation = fontHeight + gap;
87
88   numOptionsDisplayable = (area.h - 5) / ySeperation;
89
90   if (selectedOption == (topOption + numOptionsDisplayable)) topOption++;
91   if (selectedOption == ((UINT)topOption - 1)) topOption--;
92   // if still not visible...
93   if ((selectedOption < (UINT)topOption) || (selectedOption > (topOption + numOptionsDisplayable)))
94   {
95     topOption = selectedOption - (numOptionsDisplayable / 2);
96   }
97
98   if (topOption < 0) topOption = 0;
99
100
101   fillColour(backgroundColour);
102
103   UINT ypos = 5;
104   for (UINT i = topOption; i < (topOption + numOptionsDisplayable); i++)
105   {
106     if (i == options.size()) return;
107     if ((ypos + ySeperation) > area.h) break;
108
109     if (i == selectedOption && showseloption)
110     {
111       rectangle(0, ypos, area.w, fontHeight, Colour::SELECTHIGHLIGHT);
112       drawOptionLine(options[i].text, 5, ypos, Colour::DARKTEXT);
113     }
114     else
115     {
116       drawOptionLine(options[i].text, 5, ypos, Colour::LIGHTTEXT);
117     }
118     ypos += ySeperation;
119   }
120 }
121
122 void WSelectList::addColumn(int x)
123 {
124   if (numColumns == 10) return;
125   columns[numColumns++] = x;
126 }
127
128 void WSelectList::drawOptionLine(char* text, int xpos, int ypos, Colour& colour)
129 {
130   if (!numColumns)
131   {
132     drawText(text, xpos, ypos, colour);
133   }
134   else
135   {
136     char buffer[200];
137     strncpy(buffer, text, 199);
138     int currentColumn = 0;
139     char* pointer;
140
141     pointer = strtok(buffer, "\t");
142     while(pointer)
143     {
144       drawText(pointer, xpos + columns[currentColumn], ypos, colour);
145       currentColumn++;
146       if (currentColumn == 10) return;
147       pointer = strtok(NULL, "\t");
148     }
149   }
150 }
151
152 void WSelectList::up()
153 {
154   if (selectedOption > 0)
155   {
156     selectedOption--;
157   }
158   else
159   {
160     if (!noLoop) selectedOption = options.size() - 1;
161   }
162 }
163
164 void WSelectList::down()
165 {
166   if (selectedOption < options.size() - 1)
167   {
168     selectedOption++;
169   }
170   else
171   {
172     if (!noLoop) selectedOption = 0;
173   }
174 }
175
176 void WSelectList::pageUp()
177 {
178   topOption -= numOptionsDisplayable;
179   if (topOption < 0) topOption = 0;
180
181   selectedOption = topOption;
182 }
183
184 void WSelectList::pageDown()
185 {
186   if ((topOption + numOptionsDisplayable) >= options.size())
187   {
188     selectedOption = options.size() - 1;
189   }
190   else
191   {
192     topOption += numOptionsDisplayable;
193     selectedOption = topOption;
194   }
195 }
196
197 int WSelectList::getTopOption()
198 {
199   return topOption;
200 }
201
202 int WSelectList::getNumOptions()
203 {
204   return options.size();
205 }
206
207 int WSelectList::getBottomOption()
208 {
209   UINT retval = topOption + numOptionsDisplayable;
210   if (retval > options.size()) return options.size();
211   else return retval;
212 }
213
214 int WSelectList::getCurrentOption()
215 {
216   return selectedOption;
217 }
218
219 ULONG WSelectList::getCurrentOptionData()
220 {
221   if (!options.size()) return 0;
222   return options[selectedOption].data;
223 }
224
225 bool WSelectList::mouseMove(int x, int y)
226 {
227   int ml = getMouseLine(x-offsetX,y-offsetY);
228   if (ml>=0 && ml!=(int)selectedOption)
229   {
230     selectedOption = ml;
231     return true;
232   }
233   return false;
234 }
235
236 bool WSelectList::mouseLBDOWN(int x, int y)
237 {
238   int ml = getMouseLine(x-offsetX, y-offsetY);
239   if (ml == (int)selectedOption)
240   {
241     /* caller should generate a OK message*/
242     return true;
243   }
244   return false;
245 }
246
247 int WSelectList::getMouseLine(int x,int y)
248 {
249   int fontHeight = surface->getFontHeight();
250   int ySeperation = fontHeight + gap;
251
252   if (y<0) return -1;
253   if (x<0 || x>(int)area.w) return -1;
254   if (y>(int)(10+numOptionsDisplayable*ySeperation)) return -1;
255
256   int cy = y - 5;
257
258   int selected=cy/ySeperation;
259   if (y<5) selected=-1;
260   if (selected> ((int)numOptionsDisplayable)) return -1;
261   /* Important: should be the same algorithm used in draw! */
262   if (selectedOption == (topOption + numOptionsDisplayable)) topOption++;
263   if (selectedOption == ((UINT)topOption - 1)) topOption--;
264   // if still not visible...
265   if ((selectedOption < (UINT)topOption) || (selectedOption > (topOption + numOptionsDisplayable)))
266   {
267     topOption = selectedOption - (numOptionsDisplayable / 2);
268   }
269
270   if (topOption < 0) topOption = 0;
271
272   if ((selected+topOption >= (int) options.size()) ||
273       (selected + topOption < 0)) return -1;
274
275   return selected + topOption;
276 }