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