1 /*
2 PLIB - A Suite of Portable Game Libraries
3 Copyright (C) 1998,2002 Steve Baker
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19 For further information visit http://plib.sourceforge.net
20
21 $Id: puAuxComboBox.cxx 2050 2005-11-10 20:07:08Z fayjf $
22 */
23
24
25 #include "puAuxLocal.h"
26
UL_RTTI_DEF1(puaComboBox,puGroup)27 UL_RTTI_DEF1(puaComboBox,puGroup)
28
29
30 void puaComboBox::input_cb ( puObject *inp )
31 {
32 puaComboBox *cbox = (puaComboBox *) inp -> getUserData () ;
33
34 if ( strcmp ( inp->getStringValue (), cbox->getStringValue () ) )
35 {
36 cbox->update_current_item () ;
37 cbox->setCallbackSource ( PUACOMBOBOX_CALLBACK_INPUT ) ;
38 cbox -> invokeCallback () ;
39 }
40 }
41
input_active_cb(puObject * inp)42 void puaComboBox::input_active_cb ( puObject *inp )
43 {
44 puaComboBox *cbox = (puaComboBox *) inp -> getUserData () ;
45
46 cbox->update_current_item () ;
47 cbox->setCallbackSource ( PUACOMBOBOX_CALLBACK_INPUT ) ;
48 cbox -> invokeActiveCallback () ;
49 }
50
input_down_cb(puObject * inp)51 void puaComboBox::input_down_cb ( puObject *inp )
52 {
53 puaComboBox *cbox = (puaComboBox *) inp -> getUserData () ;
54
55 cbox->update_current_item () ;
56 cbox->setCallbackSource ( PUACOMBOBOX_CALLBACK_INPUT ) ;
57 cbox -> invokeCallback () ;
58 }
59
handle_arrow(puObject * arrow)60 void puaComboBox::handle_arrow ( puObject *arrow )
61 {
62 puaComboBox *cbox = (puaComboBox *) arrow -> getUserData () ;
63
64 if ( ! cbox -> __getPopupMenu () -> isVisible () )
65 cbox -> __getPopupMenu () -> reveal () ;
66 else
67 cbox -> __getPopupMenu () -> hide () ;
68
69 /* arrow -> setStyle ( - arrow -> getStyle () ) ; */
70 }
71
handle_popup(puObject * popupm)72 void puaComboBox::handle_popup ( puObject *popupm )
73 {
74 puaComboBox *cbox = (puaComboBox *) popupm -> getUserData () ;
75
76 cbox -> setCurrentItem ( popupm -> getLegend () ) ;
77 }
78
79
update_widgets(void)80 void puaComboBox::update_widgets ( void )
81 {
82 if ( curr_item >= 0 )
83 /* There are some items */
84 {
85 setValue ( list[curr_item] ) ;
86
87 arrow_btn -> activate () ;
88 }
89 else
90 /* There aren't any items */
91 {
92 setValue ( "" ) ;
93
94 arrow_btn -> greyOut () ;
95 }
96
97 input->setValue ( getStringValue () ) ;
98 }
99
100
update_current_item(void)101 void puaComboBox::update_current_item ( void )
102 {
103 if ( strcmp ( getStringValue (), input->getStringValue () ) )
104 {
105 /* User has typed in an arbitrary string; see if it is in the list */
106 int i ;
107 for ( i = 0 ; i < num_items ; i++ )
108 {
109 if ( !strcmp ( list[i], input->getStringValue () ) )
110 {
111 /* ... yes, it is ! */
112 curr_item = i ;
113 break ;
114 }
115 }
116
117 if ( ( i == num_items ) || ( num_items == 0 ) )
118 {
119 /* Didn't find it in the list--or the list is empty */
120 char **old_list = list ;
121 list = new char * [ num_items + 2 ] ;
122 for ( i = 0; i < num_items; i++ ) /* Copy over the old list */
123 list[i] = old_list[i] ;
124
125 delete old_list ;
126
127 num_items++ ;
128 int len = strlen ( input->getStringValue () ) + 1 ;
129 curr_item = num_items - 1 ;
130 list[curr_item] = new char [ len ] ;
131 memcpy ( list[curr_item], input->getStringValue (), len ) ;
132 list[num_items] = NULL ;
133 newList ( list ) ;
134 update_widgets () ;
135 }
136
137 setValue ( input->getStringValue () ) ;
138 }
139 }
140
141
newList(char ** _list)142 void puaComboBox::newList ( char ** _list )
143 {
144 // Delete the existing list--if it has not been passed in as the argument
145 int i ;
146 if ( list && ( list != _list ) )
147 {
148 for ( i = 0; i < num_items; i++ )
149 delete list[i] ;
150
151 delete list ;
152 list = NULL ;
153 }
154
155 popup_menu -> empty () ;
156
157 if ( _list == NULL )
158 num_items = 0 ;
159 else
160 {
161 for ( num_items = 0 ; _list[num_items] != NULL ; num_items++ )
162 /* Count number of items */ ;
163
164 if ( num_items > 0 )
165 {
166 if ( list != _list )
167 {
168 list = new char * [ num_items + 1 ] ; /* '+ 1' to capture the trailing NULL */
169 for ( i = 0; i < num_items; i++ )
170 {
171 int len = strlen ( _list[i] ) + 1 ; /* "+ 1" to capture the \0 */
172 list[i] = new char [ len ] ;
173 memcpy ( list[i], _list[i], len * sizeof(char) ) ;
174 }
175
176 list[num_items] = NULL ;
177 }
178
179 int dummy, h ;
180 int old_height = abox.max[1] - abox.min[1] ;
181
182 puPushGroup ( popup_menu ) ;
183
184 for ( i = (num_items - 1) ; i >= 0 ; i-- )
185 {
186 puObject *menu_item = popup_menu -> add_item ( list[i], handle_popup ) ;
187
188 menu_item -> setUserData ( this ) ;
189 menu_item -> getSize ( &dummy, &h ) ;
190 menu_item -> setSize ( abox.max[0] - abox.min[0], h ) ;
191 }
192
193 popup_menu -> close() ;
194
195 /* Position popup menu correctly */
196
197 popup_menu -> getSize ( &dummy, &h ) ;
198
199 if ( (abox.min[1] - h) >= 0 )
200 {
201 popup_menu -> setPosition ( 0, 0 - h ) ;
202
203 arrow_btn -> setArrowType ( PUARROW_DOWN ) ;
204 }
205 else
206 {
207 popup_menu -> setPosition ( 0, old_height ) ;
208
209 arrow_btn -> setArrowType ( PUARROW_UP ) ;
210 }
211 }
212 }
213
214 if ( ( curr_item >= num_items ) || ( curr_item < 0 ) )
215 {
216 curr_item = ( num_items > 0 ? 0 : - 1 ) ;
217 update_widgets () ;
218 }
219 }
220
getCurrentItem(void)221 int puaComboBox::getCurrentItem ( void )
222 {
223 update_current_item () ;
224
225 return curr_item ;
226 }
227
setCurrentItem(const char * item_ptr)228 void puaComboBox::setCurrentItem ( const char *item_ptr )
229 {
230 int i ;
231
232 for ( i = 0 ; i < num_items ; i++ )
233 {
234 if ( list[i] == item_ptr )
235 {
236 setCurrentItem ( i ) ;
237
238 break ;
239 }
240 }
241 }
242
243
draw(int dx,int dy)244 void puaComboBox::draw ( int dx, int dy )
245 {
246 if ( !visible || ( window != puGetWindow () ) ) return ;
247
248 draw_label ( dx, dy ) ;
249
250 puGroup::draw ( dx, dy ) ;
251 }
252
checkHit(int button,int updown,int x,int y)253 int puaComboBox::checkHit ( int button, int updown, int x, int y )
254 {
255 if ( input -> checkHit ( button, updown, x-abox.min[0], y-abox.min[1] ) )
256 {
257 popup_menu -> hide () ;
258 puSetActiveWidget ( this, x, y ) ;
259
260 return TRUE ;
261 }
262 else
263 return puGroup::checkHit ( button, updown, x, y ) ;
264 }
265
checkKey(int key,int updown)266 int puaComboBox::checkKey ( int key, int updown )
267 {
268 if ( updown == PU_UP || ! input -> isAcceptingInput () ||
269 ! isVisible () || ! isActive () || ( window != puGetWindow () ) )
270 return FALSE ;
271
272 switch ( key )
273 {
274 case PU_KEY_HOME :
275 setCurrentItem ( 0 ) ;
276 break ;
277
278 case PU_KEY_END :
279 setCurrentItem ( num_items - 1 ) ;
280 break ;
281
282 case PU_KEY_UP :
283 setCurrentItem ( getCurrentItem () + 1 ) ;
284 break ;
285
286 case PU_KEY_DOWN :
287 setCurrentItem ( getCurrentItem () - 1 ) ;
288 break ;
289
290 case PU_KEY_PAGE_UP :
291 case PU_KEY_PAGE_DOWN :
292 if ( ! popup_menu -> isVisible () )
293 popup_menu -> reveal () ;
294 else
295 popup_menu -> hide () ;
296
297 break ;
298
299 default :
300 return input -> checkKey ( key, updown ) ;
301 break ;
302 }
303
304 return TRUE ;
305 }
306
setColourScheme(float r,float g,float b,float a)307 void puaComboBox::setColourScheme ( float r, float g, float b, float a )
308 {
309 puObject::setColourScheme ( r, g, b, a ) ;
310 setChildColourScheme( PUCLASS_INPUT,
311 colour [ PUCOL_EDITFIELD ][0],
312 colour [ PUCOL_EDITFIELD ][1],
313 colour [ PUCOL_EDITFIELD ][2],
314 colour [ PUCOL_EDITFIELD ][3] ) ;
315 }
316
setColour(int which,float r,float g,float b,float a)317 void puaComboBox::setColour ( int which, float r, float g, float b, float a )
318 {
319 if (which == PUCOL_EDITFIELD)
320 input->setColourScheme ( r, g, b, a ) ;
321 else
322 puObject::setColour ( which, r, g, b, a ) ;
323 }
324
325
puaComboBox(int minx,int miny,int maxx,int maxy,char ** entries,int editable)326 puaComboBox::puaComboBox ( int minx, int miny, int maxx, int maxy,
327 char **entries, int editable ) :
328 puGroup( minx, miny )
329 {
330 type |= PUCLASS_COMBOBOX ;
331
332 char *stringval ;
333 int arrow_width = (int) ( (maxy-miny) / 1.5f ) ;
334
335 input = new puInput ( 0, 0, maxx-minx - arrow_width, maxy-miny ) ;
336 input -> setUserData ( this ) ;
337 input -> setCallback ( input_cb ) ;
338 input -> setActiveCallback ( input_active_cb ) ;
339 input -> setDownCallback ( input_down_cb ) ;
340
341 input -> setStyle ( PUSTYLE_SMALL_SHADED ) ;
342
343 if ( ! editable )
344 input -> disableInput () ;
345
346 /* Share 'string' value with input box */
347 input -> getValue ( &stringval ) ;
348 // setValuator ( stringval ) ;
349
350 arrow_btn = new puArrowButton ( maxx-minx - arrow_width, 0,
351 maxx-minx, maxy-miny,
352 PUARROW_DOWN ) ;
353 arrow_btn -> setStyle ( PUSTYLE_SMALL_SHADED ) ;
354 arrow_btn -> setUserData ( this ) ;
355 arrow_btn -> setCallback ( handle_arrow ) ;
356
357 popup_menu = new puPopupMenu ( 0, 0 ) ;
358 popup_menu -> close () ;
359
360 close () ;
361
362 list = NULL ;
363 curr_item = 0 ;
364 num_items = 0 ;
365 callback_source = PUACOMBOBOX_CALLBACK_NONE ;
366 newList ( entries ) ;
367 update_widgets () ;
368 }
369
setSize(int w,int h)370 void puaComboBox::setSize ( int w, int h )
371 {
372 int arrow_width = (int) ( float(h) / 1.5f ) ;
373 input->setSize ( w - arrow_width, h ) ;
374 arrow_btn->setPosition ( w - arrow_width, 0 ) ;
375 arrow_btn->setSize ( arrow_width, h ) ;
376 }
377
378