2 * Copyright (C) Volition, Inc. 1999. All rights reserved.
4 * All source code herein is the property of Volition, Inc. You may not sell
5 * or otherwise commercially exploit the source or things you created based on
10 * $Logfile: /Freespace2/code/UI/LISTBOX.cpp $
15 * Code to implement a listbox gadget.
18 * Revision 1.5 2004/09/20 01:31:45 theoddone33
21 * Revision 1.4 2004/07/04 11:39:06 taylor
22 * fix missing debrief text, crash on exit, path separator's, warning fixes, no GR_SOFT
24 * Revision 1.3 2002/06/09 04:41:29 relnev
25 * added copyright header
27 * Revision 1.2 2002/05/07 03:16:53 theoddone33
28 * The Great Newline Fix
30 * Revision 1.1.1.1 2002/05/03 03:28:11 root
34 * 4 12/02/98 5:47p Dave
35 * Put in interface xstr code. Converted barracks screen to new format.
37 * 3 10/13/98 9:29a Dave
38 * Started neatening up freespace.h. Many variables renamed and
39 * reorganized. Added AlphaColors.[h,cpp]
41 * 2 10/07/98 10:54a Dave
44 * 1 10/07/98 10:51a Dave
46 * 20 3/23/98 5:48p Hoffoss
47 * Improved listbox handling. Most notibly the scrollbar arrows work now.
49 * 19 2/03/98 4:21p Hoffoss
50 * Made UI controls draw white text when disabled.
52 * 18 1/20/98 10:36a Hoffoss
53 * Fixed optimized warnings.
55 * 17 1/14/98 6:43p Hoffoss
56 * Massive changes to UI code. A lot cleaner and better now. Did all
57 * this to get the new UI_DOT_SLIDER to work properly, which the old code
58 * wasn't flexible enough to handle.
60 * 16 9/18/97 10:31p Lawrance
61 * allow listbox to change text
63 * 15 9/09/97 4:32p Dave
64 * Added sel_changed() function to UI_LISTBOX to check is the selection
67 * 14 9/09/97 3:39p Sandeep
68 * warning level 4 bugs
70 * 13 8/19/97 1:27p Dave
71 * Made it possible to create an empty list box and summarily add items.
73 * 12 8/14/97 5:23p Dave
74 * Added clear_all_items() to the UI_LISTBOX
76 * 11 6/26/97 5:53p Lawrance
77 * change code slightly, so current_item is not forced to 0 when was -1
79 * 10 6/12/97 12:39p John
80 * made ui use freespace colors
82 * 9 6/11/97 1:13p John
83 * Started fixing all the text colors in the game.
85 * 8 5/26/97 10:26a Lawrance
86 * get slider control working 100%
88 * 7 4/22/97 10:11a John
89 * Added checkbox lists to listboxes
91 * 6 4/15/97 3:47p Allender
92 * moved type selection of list box items into actual UI code. Made it
93 * behave more like windows listboxes do
95 * 5 12/23/96 2:42p Lawrance
96 * allowing keys to select list box items in the mission load screen
98 * 4 12/02/96 2:17p John
99 * Made right button drag UI gadgets around and
100 * Ctrl+Shift+Alt+F12 dumps out where they are.
102 * 3 12/01/96 3:48a Lawrance
103 * added function set_current to UI_LISTBOX
105 * 2 11/15/96 11:43a John
107 * 1 11/14/96 6:55p John
116 #include "alphacolors.h"
118 #define KEY_BUFFER_TIMEOUT 1000 // time to clear buffer in milliseconds
120 #define DEFAULT_LISTBOX_ITEM_LENGTH 40
122 // --------------------------------------------------------------------
123 // UI_LISTBOX::link_hotspot
126 void UI_LISTBOX::link_hotspot(int up_button_num, int down_button_num)
128 scrollbar.link_hotspot(up_button_num,down_button_num);
131 // --------------------------------------------------------------------
132 // UI_LISTBOX::set_bmaps
134 // Call the UI_SCROLLBAR::set_bmaps() function for the scroll bar gadget.
136 // returns: -1 ==> error
139 int UI_LISTBOX::set_bmaps(char *lbox_fname, char *b_up_fname, char *b_down_fname, char *sb_fname)
142 scrollbar.set_bmaps(b_up_fname, b_down_fname, sb_fname);
145 // set the bitmaps for the list box rectangle
146 UI_GADGET::set_bmaps(lbox_fname);
151 void UI_LISTBOX::create(UI_WINDOW *wnd, int _x, int _y, int _w, int _h, int _numitems, char **_list, char *_check_list, int _max_items)
156 gr_set_font(wnd->f_id);
157 gr_get_string_size(&tw, &th, "*");
162 base_create( wnd, UI_KIND_LISTBOX, _x, _y, _w, real_h );
164 max_items = _max_items;
166 num_items = _numitems;
167 check_list = _check_list;
168 num_items_displayed = nrows;
177 key_buffer_count = 0;
178 last_typed = timer_get_milliseconds();
180 if (_numitems > nrows) {
181 scrollbar.create( wnd, _x+_w+3, _y, real_h, 0, _numitems-nrows, 0, nrows );
182 scrollbar.set_parent(this);
190 void UI_LISTBOX::draw()
196 gr_set_font(my_wnd->f_id);
200 if ( bmap_ids[LBOX_DISABLED] >= 0 ) {
201 gr_set_bitmap(bmap_ids[LBOX_DISABLED], GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
206 if ( bmap_ids[LBOX_NORMAL] >= 0 ) {
207 gr_set_bitmap(bmap_ids[LBOX_NORMAL], GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
213 gr_set_color_fast(&CBLACK);
214 gr_set_clip( x, y, w, h );
215 ui_rect( 0, 0, w-1, h-1 );
218 ui_draw_sunken_border( x-2, y-2, x+w+scrollbar.w+4, y+h+1 );
221 ui_draw_sunken_border( x-2, y-2, x+w+4, y+h+1 );
225 stop = first_item+num_items_displayed;
226 if (stop>num_items) stop = num_items;
229 gr_set_clip( x, y, w, h );
231 for ( i=first_item; i<stop; i++ ) {
232 gr_get_string_size( &w1, &h1,list[i] );
237 if (i !=current_item) {
239 if ((current_item == -1) && (my_wnd->selected_gadget == this ) && (i == first_item) ) {
241 gr_set_color_fast( &CBLACK );
242 gr_rect( x1, y1, w1+2, h1 );
244 current_item = first_item;
245 gr_set_color_fast( &CBRIGHT_GREEN );
248 gr_set_color_fast( &CBLACK );
249 gr_rect( x1, y1, w1+2, h1 );
251 gr_set_color_fast( &CWHITE );
255 gr_set_color_fast( &CBLACK );
256 gr_rect( x1, y1, w1+2, h1 );
259 gr_set_color_fast(&CWHITE);
262 if (my_wnd->selected_gadget == this) {
263 gr_set_color_fast( &CGRAY );
264 gr_rect( x1, y1, w1+2, h1 );
265 gr_set_color_fast( &CBRIGHT_GREEN );
268 gr_set_color_fast( &CGRAY );
269 gr_rect( x1, y1, w1+2, h1 );
270 gr_set_color_fast( &CBLACK );
275 if ( check_list[i] ) {
276 gr_string( x1+2, y1, "X" );
279 gr_string( x1+16, y1, list[i] );
282 gr_string( x1+2, y1, list[i] );
285 gr_set_color_fast( &CGRAY );
287 gr_set_color_fast( &CBLACK );
290 ui_rect( x1+w1+2, y1, w-1, y1+h1-1 );
291 ui_rect( x1, y1, x1+1, y1+h1-1 );
297 if (stop < num_items_displayed-1 && !uses_bmaps) {
298 gr_set_color_fast(&CBLACK);
299 ui_rect( x1, y1, w-1, h-1 );
303 void UI_LISTBOX::process(int focus)
305 int OnMe, mitem, oldbarpos, kf = 0;
314 if (my_wnd->selected_gadget == this)
318 scrollbar.process(0);
319 if (my_wnd->selected_gadget == &scrollbar) {
328 old_current_item = current_item;
329 old_first_item = first_item;
331 // if (my_wnd->selected_gadget == this) {
332 // my_wnd->selected_gadget == get_next();
338 old_current_item = current_item;
339 old_first_item = first_item;
341 OnMe = is_mouse_on();
344 if (scrollbar.moved) {
345 first_item = scrollbar.position;
346 Assert(first_item >= 0);
348 if (current_item<first_item)
349 current_item = first_item;
351 if (current_item > first_item + num_items_displayed - 1)
352 current_item = first_item + num_items_displayed - 1;
359 if (B1_PRESSED && OnMe) {
364 if ( key_buffer_count && (timer_get_milliseconds() > last_typed + KEY_BUFFER_TIMEOUT) )
365 key_buffer_count = 0;
368 if (my_wnd->keypress) {
371 switch (my_wnd->keypress) {
373 selected_item = current_item;
377 toggled_item = current_item;
396 current_item=num_items - 1;
401 current_item -= num_items_displayed;
406 current_item += num_items_displayed;
410 default: // enter the key in the key buffer
411 if (my_wnd->keypress == KEY_BACKSP) {
412 key_buffer_count = 0;
414 } else if (key_buffer_count < MAX_KEY_BUFFER) {
415 key_buffer[key_buffer_count++] = (char) my_wnd->keypress;
416 last_typed = timer_get_milliseconds();
419 if (!key_buffer_count)
422 for (i=0; i<num_items; i++) {
425 current_text = get_string(i);
426 for (j=0; j<key_buffer_count; j++)
427 if ( (current_text[j] != ascii_table[(int)key_buffer[j]]) && (current_text[j] != shifted_ascii_table[(int)key_buffer[j]]) )
430 if (j == key_buffer_count) {
431 set_first_item(i - num_items_displayed / 2);
440 if (current_item < 0)
443 if (current_item >= num_items)
444 current_item = num_items - 1;
446 if (current_item < first_item)
447 first_item = current_item;
449 if (current_item >= first_item + num_items_displayed)
450 first_item = current_item - num_items_displayed + 1;
452 if (num_items <= num_items_displayed ) {
457 oldbarpos = scrollbar.position;
458 scrollbar.position = first_item;
460 scrollbar.bar_position = scrollbar.position - scrollbar.start;
461 scrollbar.bar_position *= scrollbar.h - scrollbar.bar_size;
462 scrollbar.bar_position /= scrollbar.stop - scrollbar.start;
464 if (scrollbar.bar_position < 0) {
465 scrollbar.bar_position = 0;
468 if (scrollbar.bar_position > scrollbar.h - scrollbar.bar_size) {
469 scrollbar.bar_position = scrollbar.h - scrollbar.bar_size;
478 if (B1_PRESSED && dragging) {
482 mitem = (ui_mouse.y - y)/textheight;
484 if ( (mitem < 0) && (timer_get_milliseconds() > last_scrolled + 1000 / 18) ) {
486 last_scrolled = timer_get_milliseconds();
489 if ( (mitem >= num_items_displayed) && (timer_get_milliseconds() > last_scrolled + 1000 / 18) ) {
491 last_scrolled = timer_get_milliseconds();
494 if ((mitem >= 0) && (mitem<num_items_displayed)) {
495 current_item = mitem + first_item;
498 if (current_item < 0)
501 if (current_item >= num_items)
502 current_item = num_items - 1;
504 if (current_item < first_item)
505 first_item = current_item;
507 if (current_item >= first_item + num_items_displayed)
508 first_item = current_item - num_items_displayed + 1;
510 if (num_items <= num_items_displayed) {
513 } else if (has_scrollbar) {
514 oldbarpos = scrollbar.position;
515 scrollbar.position = first_item;
517 scrollbar.bar_position = scrollbar.position - scrollbar.start;
518 scrollbar.bar_position *= scrollbar.h - scrollbar.bar_size;
519 scrollbar.bar_position /= scrollbar.stop - scrollbar.start;
521 if (scrollbar.bar_position < 0) {
522 scrollbar.bar_position = 0;
525 if (scrollbar.bar_position > scrollbar.h - scrollbar.bar_size) {
526 scrollbar.bar_position = scrollbar.h - scrollbar.bar_size;
532 if (B1_JUST_RELEASED)
533 toggled_item = current_item;
536 if (B1_DOUBLE_CLICKED) {
537 selected_item = current_item;
542 int UI_LISTBOX::toggled()
551 int UI_LISTBOX::selected()
556 return selected_item;
560 int UI_LISTBOX::current()
565 void UI_LISTBOX::set_current(int _index)
567 current_item = _index;
570 void UI_LISTBOX::set_first_item(int _index)
574 else if (_index > num_items)
580 char *UI_LISTBOX::get_string(int _index)
585 void UI_LISTBOX::clear_all_items()
589 for ( idx=0; idx<num_items; idx++ )
596 void UI_LISTBOX::set_new_list(int _numitems, char **_list)
598 num_items = _numitems;
603 int UI_LISTBOX::add_string(char *str)
605 if (max_items < 0) // only if we created an "empty" listbox can we add items
609 if ( (num_items == max_items - 1) || (strlen(str) > DEFAULT_LISTBOX_ITEM_LENGTH) )
610 return 0; // we've reached our limit
613 list[num_items] = strdup(str);
620 int UI_LISTBOX::sel_changed()
622 return old_current_item == current_item ? 0 : 1;