1 /*
2 * CRRCsim - the Charles River Radio Control Club Flight Simulator Project
3 *
4 * Copyright (C) 2005, 2006, 2007 Jan Reucker (original author)
5 * Copyright (C) 2008 Jens Wilhelm Wulf
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2
9 * as published by the Free Software Foundation.
10 *
11 * This program 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 this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330,
19 * Boston, MA 02111-1307, USA.
20 *
21 */
22
23
24 // puaScrListBox.cpp - implementation of a scrolling list box.
25 // Filename in FG sources: puList.cxx
26
27 #include "puaScrListBox.h"
28
29 /**
30 * Create a puaCRRCListBox
31 *
32 * The constructor only prepares the color values for the highlighted entry.
33 * By adjusting "high" and "label", these two color values can be mixed.
34 * Right now it's set to 100% highlight color, 0% label color.
35 */
puaCRRCListBox(int x,int y,int w,int h,char ** contents)36 puaCRRCListBox::puaCRRCListBox (int x, int y, int w, int h, char ** contents)
37 : puListBox(x, y, w, h, contents)
38 {
39 /*TODO
40 The visibility of the selected element is even less good with textured fonts.
41 It would be necessary to invert the color of the background of this element.
42 Temporarily, I force the color in red. ( J.L).*/
43 #if 0
44 float high = 1.0f;
45 float label = 0.0f;
46 float frac = high + label;
47
48 selectioncol[0] = (high * colour [ PUCOL_HIGHLIGHT ][0] + label * colour [ PUCOL_LABEL ][0]) / frac;
49 selectioncol[1] = (high * colour [ PUCOL_HIGHLIGHT ][1] + label * colour [ PUCOL_LABEL ][1]) / frac;
50 selectioncol[2] = (high * colour [ PUCOL_HIGHLIGHT ][2] + label * colour [ PUCOL_LABEL ][2]) / frac;
51 selectioncol[3] = (high * colour [ PUCOL_HIGHLIGHT ][3] + label * colour [ PUCOL_LABEL ][3]) / frac;
52 #else
53 //HIGHLIGHT red !!
54 selectioncol[0] = 1;
55 selectioncol[1] = 0;
56 selectioncol[2] = 0;
57 selectioncol[3] = 1;
58 #endif
59 }
60
61
62 /**
63 * Draw the widget.
64 *
65 * This method mainly contains the original code from the base class,
66 * but when drawing a highlighted list entry, the special selectcol[]
67 * is used.
68 */
draw(int dx,int dy)69 void puaCRRCListBox::draw ( int dx, int dy )
70 {
71 if ( !visible || ( window != puGetWindow () ) || list == NULL ) return ;
72
73 abox.draw ( dx, dy, style, colour, isReturnDefault(), border_thickness ) ;
74
75 /* If greyed out then halve the opacity when drawing the text */
76
77 if ( active )
78 glColor4fv ( colour [ PUCOL_LEGEND ] ) ;
79 else
80 glColor4f ( colour [ PUCOL_LEGEND ][0],
81 colour [ PUCOL_LEGEND ][1],
82 colour [ PUCOL_LEGEND ][2],
83 colour [ PUCOL_LEGEND ][3] / 2.0f ) ; /* 50% more transparent */
84
85 int xsize = abox.max[0] - abox.min[0] + 1 ;
86
87 if ( r_cb )
88 r_cb ( this, dx, dy, render_data ) ;
89 else
90 {
91 int yinc = legendFont.getStringHeight () + PUSTR_BGAP ;
92 int num_vis = getNumVisible () ;
93
94 int selected ;
95 getValue ( &selected ) ;
96
97 for ( int i = top ; i < num && i < top + num_vis ; i++ )
98 {
99 if ( i == selected )
100 glColor4f ( selectioncol[0],
101 selectioncol[1],
102 selectioncol[2],
103 selectioncol[3] );
104 else
105 glColor4f ( colour [ PUCOL_LABEL ][0],
106 colour [ PUCOL_LABEL ][1],
107 colour [ PUCOL_LABEL ][2],
108 colour [ PUCOL_LABEL ][3] ) ;
109
110 int x = PUSTR_LGAP ;
111 int y = yinc * ((i-top)+1) ;
112
113 int xx = dx + abox.min[0] + x ;
114 int yy = dy + abox.max[1] - y ;
115
116 int width ;
117 char str [ PUSTRING_MAX ] ;
118 strcpy ( str, list [ i ] ) ;
119
120 /*
121 Does the string fit into the box?
122
123 If not, chop it down one character at a time until
124 it does fit.
125 */
126
127 while ( 1 )
128 {
129 width = legendFont.getStringWidth ( (char *)str ) + PUSTR_LGAP ;
130
131 if ( width < xsize )
132 break ;
133
134 /*
135 Nibble off one character and try again
136 (Do that sneakily by replacing the last 4 characters with 3 dots)
137 */
138
139 strcpy ( & str [ strlen(str) - 4 ], "..." ) ;
140 }
141
142 legendFont.drawString ( (char*)str, xx, yy ) ;
143 }
144 }
145
146 draw_label ( dx, dy ) ;
147 }
148
149
150
151
152 /**
153 * Static function: handle slider movements.
154 */
155 static void
handle_slider(puObject * slider)156 handle_slider (puObject * slider)
157 {
158 puListBox * box = (puListBox *)slider->getUserData();
159 int index = int(box->getNumItems() * (1.0 - slider->getFloatValue()));
160 if (index >= box->getNumItems())
161 index = box->getNumItems() - 1;
162 box->setTopItem(index);
163 }
164
165
166 /**
167 * Static function: handle list entry selection.
168 */
169 static void
handle_list_entry(puObject * listbox)170 handle_list_entry (puObject * listbox)
171 {
172 puaScrListBox * box = (puaScrListBox *)listbox->getUserData();
173 box->invokeCallback();
174 }
175
176
177 /**
178 * Static function: handle arrow clicks.
179 */
180 static void
handle_arrow(puObject * arrow)181 handle_arrow (puObject * arrow)
182 {
183 puSlider * slider = (puSlider *)arrow->getUserData();
184 puListBox * list_box = (puListBox *)slider->getUserData();
185
186 int step;
187 switch (((puArrowButton *)arrow)->getArrowType())
188 {
189 case PUARROW_DOWN:
190 step = 1;
191 break;
192 case PUARROW_UP:
193 step = -1;
194 break;
195 default:
196 step = 0;
197 break;
198 }
199
200 int index = list_box->getTopItem();
201 index += step;
202 if (index < 0)
203 index = 0;
204 else if (index >= list_box->getNumItems())
205 index = list_box->getNumItems() - 1;
206 list_box->setTopItem(index);
207
208 slider->setValue(1.0f - float(index)/list_box->getNumItems());
209 }
210
211 /** \brief Create an empty list box.
212 *
213 * \param x X-coordinate of lower left corner.
214 * \param y Y-coordinate of lower left corner.
215 * \param w Widget width
216 * \param h Widget height
217 */
puaScrListBox(int x,int y,int w,int h)218 puaScrListBox::puaScrListBox (int x, int y, int w, int h)
219 : puGroup(x, y)
220 {
221 init(w, h);
222 }
223
224
225 /** \brief Create a filled list box.
226 *
227 * \param x X-coordinate of lower left corner.
228 * \param y Y-coordinate of lower left corner.
229 * \param w Widget width
230 * \param h Widget height
231 * \param contents Pointer to an array of pointers to the string items.
232 */
puaScrListBox(int x,int y,int w,int h,char ** contents)233 puaScrListBox::puaScrListBox (int x, int y, int w, int h, char ** contents)
234 : puGroup(x, y)
235 {
236 init(w, h);
237 newList(contents);
238 }
239
240
241 /**
242 * Destroy the ScrListBox
243 */
~puaScrListBox()244 puaScrListBox::~puaScrListBox ()
245 {
246 puDeleteObject(_list_box);
247 puDeleteObject(_slider);
248 puDeleteObject(_up_arrow);
249 puDeleteObject(_down_arrow);
250 }
251
252 /**
253 * Fill the list box with the strings from the given
254 * array of character pointers.
255 */
256 void
newList(char ** contents)257 puaScrListBox::newList (char ** contents)
258 {
259 _list_box->newList(contents);
260 _contents = contents;
261 }
262
263 /**
264 * Return a pointer to a character string with the
265 * contents of the selected entry.
266 * \return Pointer to highlighted entry or NULL if none is selected.
267 */
268 char *
getStringValue()269 puaScrListBox::getStringValue ()
270 {
271 int currElem = _list_box->getIntegerValue();
272 if (currElem < 0)
273 {
274 return NULL;
275 }
276 else
277 {
278 return _contents[currElem];
279 }
280 }
281
282 /**
283 * Set a pointer to a character string with the
284 * contents of the selected entry
285 */
286 void
getValue(char ** ps)287 puaScrListBox::getValue(char **ps)
288 {
289 int currElem = _list_box->getIntegerValue();
290 if (currElem < 0)
291 {
292 *ps = NULL;
293 }
294 else
295 {
296 *ps = _contents[currElem];
297 }
298 }
299
300
301 /**
302 * Set the integer pointed to by <code>i</code> to
303 * the index of the currently selected entry.
304 */
305 void
getValue(int * i)306 puaScrListBox::getValue(int *i)
307 {
308 *i = _list_box->getIntegerValue();
309 }
310
311 /**
312 * Return the index of the currently selected entry.
313 */
314 int
getIntegerValue()315 puaScrListBox::getIntegerValue()
316 {
317 return _list_box->getIntegerValue();
318 }
319
320 /**
321 * Setup the widget.
322 */
323 void
init(int w,int h)324 puaScrListBox::init (int w, int h)
325 {
326 //~ _frame = new puFrame(0, 0, w, h);
327
328 _list_box = new puaCRRCListBox(0, 0, w-17, h);
329
330 //~ _list_box->setColour (PUCOL_BACKGROUND,1,0,0,1);//for better visibility of selected item on Plib-1.8.5
331 //_list_box->setColour (PUCOL_FOREGROUND,.75,.75,.75,1);//darker for better visibility of selected item on Plib-1.8.4
332 // _list_box->setStyle(-PUSTYLE_SMALL_SHADED);
333 //~_list_box->setStyle(PUSTYLE_BOXED);//for not use PUCOL_BACKGROUND on outline
334 _list_box->setUserData(this);
335 _list_box->setCallback(handle_list_entry);
336 _list_box->setValue(0);
337
338 _slider = new puSlider(w-18, 18, h-34, true, 18);
339 _slider->setValue(1.0f);
340 _slider->setUserData(_list_box);
341 _slider->setCallback(handle_slider);
342 _slider->setCBMode(PUSLIDER_ALWAYS);
343
344 _down_arrow = new puArrowButton(w-18, 0, w, 18, PUARROW_DOWN) ;
345 _down_arrow->setUserData(_slider);
346 _down_arrow->setCallback(handle_arrow);
347
348 _up_arrow = new puArrowButton(w-18, h-18, w, h, PUARROW_UP);
349 _up_arrow->setUserData(_slider);
350 _up_arrow->setCallback(handle_arrow);
351
352 close();
353 }
354 //~ void
355 //~ puaScrListBox::init (int w, int h)
356 //~ {
357 //~ _frame = new puFrame(0, 0, w, h);
358
359 //~ _list_box = new puListBox(0, 0, w-30, h);
360 //~ _list_box->setStyle(-PUSTYLE_SMALL_SHADED);
361 //~ _list_box->setUserData(this);
362 //~ _list_box->setValue(0);
363
364 //~ _slider = new puSlider(w-30, 30, h-60, true);
365 //~ _slider->setValue(1.0f);
366 //~ _slider->setUserData(_list_box);
367 //~ _slider->setCallback(handle_slider);
368 //~ _slider->setCBMode(PUSLIDER_ALWAYS);
369
370 //~ _down_arrow = new puArrowButton(w-30, 0, w, 30, PUARROW_DOWN) ;
371 //~ _down_arrow->setUserData(_slider);
372 //~ _down_arrow->setCallback(handle_arrow);
373
374 //~ _up_arrow = new puArrowButton(w-30, h-30, w, h, PUARROW_UP);
375 //~ _up_arrow->setUserData(_slider);
376 //~ _up_arrow->setCallback(handle_arrow);
377
378 //~ close();
379 //~ }
380
381 /**
382 * Set the widget's style.
383 * \param style A style as defined in pu.h (PUSTYLE_xxxx)
384 */
385 void
setStyle(int style)386 puaScrListBox::setStyle(int style)
387 {
388 _list_box->setStyle(style);
389 _slider->setStyle(style);
390 _down_arrow->setStyle(style);
391 _up_arrow->setStyle(style);
392 _style = style;
393 }
394
395
396 /**
397 * Return the number of items in the list
398 */
399 int
getNumItems() const400 puaScrListBox::getNumItems() const
401 {
402 return _list_box->getNumItems();
403 }
404
405 /**
406 * Return the index of the top item that is displayed in the list
407 */
408 int
getTopItem() const409 puaScrListBox::getTopItem() const
410 {
411 return _list_box->getTopItem();
412 }
413
414 /**
415 * Set the index of the top item to be displayed
416 */
417 void
setTopItem(int item_index)418 puaScrListBox::setTopItem(int item_index)
419 {
420 _list_box->setTopItem(item_index);
421 float new_val = 1.0f - (float)item_index/_list_box->getNumItems();
422 _slider->setValue(new_val);
423 }
424
425 /**
426 * Set the item to be selected
427 */
428 void
setValue(int i)429 puaScrListBox::setValue(int i)
430 {
431 _list_box->setValue(i);
432 }
433
434 // end of puaScrListBox.cpp
435
436