]> icculus.org git repositories - taylor/freespace2.git/blob - src/ui/slider.cpp
GCC 3.4 fixes.
[taylor/freespace2.git] / src / ui / slider.cpp
1 /*
2  * Copyright (C) Volition, Inc. 1999.  All rights reserved.
3  *
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
6  * the source.
7  */
8
9 /*
10  * $Logfile: /Freespace2/code/Ui/slider.cpp $
11  * $Revision$
12  * $Date$
13  * $Author$
14  *
15  * C++ file for controlling and displaying a horizontal slider
16  *
17  * $Log$
18  * Revision 1.5  2004/09/20 01:31:45  theoddone33
19  * GCC 3.4 fixes.
20  *
21  * Revision 1.4  2002/07/13 19:47:02  theoddone33
22  * Fix some more warnings
23  *
24  * Change demo building, edit Makefile if you want the demo.
25  *
26  * Revision 1.3  2002/06/09 04:41:29  relnev
27  * added copyright header
28  *
29  * Revision 1.2  2002/05/07 03:16:53  theoddone33
30  * The Great Newline Fix
31  *
32  * Revision 1.1.1.1  2002/05/03 03:28:11  root
33  * Initial import.
34  *
35  * 
36  * 8     8/10/99 6:54p Dave
37  * Mad optimizations. Added paging to the nebula effect.
38  * 
39  * 7     8/02/99 6:04p Jefff
40  * use_hack_to_get_around_stupid_problem_flag extended to sliders
41  * 
42  * 6     5/03/99 8:33p Dave
43  * New version of multi host options screen.
44  * 
45  * 5     2/11/99 3:08p Dave
46  * PXO refresh button. Very preliminary squad war support.
47  * 
48  * 4     12/02/98 5:47p Dave
49  * Put in interface xstr code. Converted barracks screen to new format.
50  * 
51  * 3     10/13/98 9:29a Dave
52  * Started neatening up freespace.h. Many variables renamed and
53  * reorganized. Added AlphaColors.[h,cpp]
54  * 
55  * 2     10/07/98 10:54a Dave
56  * Initial checkin.
57  * 
58  * 1     10/07/98 10:51a Dave
59  * 
60  * 12    4/17/98 10:34a Hoffoss
61  * Fixed dot slider positionings.
62  * 
63  * 11    3/22/98 10:50p Lawrance
64  * Allow sliders to not have end-buttons.
65  * 
66  * 10    2/03/98 4:21p Hoffoss
67  * Made UI controls draw white text when disabled.
68  * 
69  * 9     1/30/98 11:59a Hoffoss
70  * changed offset of slider child button.
71  * 
72  * 8     1/27/98 7:02p Lawrance
73  * Don't play the "mouse over" sound for the volume circles.
74  * 
75  * 7     1/15/98 12:00p Hoffoss
76  * Embelished file with nifty comments.
77  * 
78  * 6     1/14/98 6:44p Hoffoss
79  * Massive changes to UI code.  A lot cleaner and better now.  Did all
80  * this to get the new UI_DOT_SLIDER to work properly, which the old code
81  * wasn't flexible enough to handle.
82  * 
83  * 5     8/24/97 5:25p Lawrance
84  * improve drawing of buttons 
85  * 
86  * 4     6/12/97 12:39p John
87  * made ui use freespace colors
88  * 
89  * 3     6/11/97 1:13p John
90  * Started fixing all the text colors in the game.
91  * 
92  * 2     5/26/97 10:26a Lawrance
93  * get slider control working 100%
94  *
95  * $NoKeywords: $
96  */
97
98
99 #include "uidefs.h"
100 #include "ui.h"
101 #include "timer.h"
102
103 #include "missionscreencommon.h"
104 #include "bmpman.h"
105 #include "gamesnd.h"
106 #include "alphacolors.h"
107
108 /// DOT_SLIDER class down here
109 void UI_DOT_SLIDER_NEW::create(UI_WINDOW *wnd, int _x, int _y, int _num_pos, char *bm_slider, int slider_mask,
110                                                                                                                                                                         char *bm_left, int left_mask, int left_x, int left_y,
111                                                                                                                                                                         char *bm_right, int right_mask, int right_x, int right_y,
112                                                                                                                                                                         int _dot_width)
113 {
114         // no end buttons yet
115         has_end_buttons = 0;
116
117         // if any of the left/right arrow information is specified, make sure its _all_ specified
118         if((bm_left != NULL) || (left_mask != -1) || (bm_right != NULL) || (right_mask != -1)){
119                 Assert((bm_left != NULL) && (left_mask >= 0) && (bm_right != NULL) && (right_mask >= 0));
120                 if((bm_left == NULL) || (left_mask < 0) || (bm_right == NULL) || (right_mask < 0)){
121                         return;
122                 }
123
124                 // now we know we have end buttons
125                 has_end_buttons = 1;
126         }
127
128         // internal stuff
129         num_pos = _num_pos;
130         base_create(wnd, UI_KIND_DOT_SLIDER_NEW, _x, _y, 0, 20);
131         pos = 0;                
132         dot_width = _dot_width; 
133
134         // set bitmaps for the slider itself    
135         button.create( wnd, "", _x, _y, 0, 0, 0, 1 );
136         button.set_parent(this);
137         button.link_hotspot(slider_mask);
138         button.set_bmaps(bm_slider, num_pos, 0);        
139         button.hide();
140                 
141         // maybe setup buttons for the arrows
142         if ( has_end_buttons ) {
143                 // Second button is the up (increase) button            
144                 up_button.create( wnd, "", right_x, right_y, 0, 0, 1, 1 );
145                 up_button.set_parent(this);
146                 up_button.set_highlight_action(common_play_highlight_sound);
147                 up_button.link_hotspot(right_mask);
148                 up_button.set_bmaps(bm_right);          
149
150                 // Third button is the down (decrease) button           
151                 down_button.create( wnd, "", left_x, left_y, 0, 0, 1, 1 );
152                 down_button.set_parent(this);
153                 down_button.set_highlight_action(common_play_highlight_sound);
154                 down_button.link_hotspot(left_mask);
155                 down_button.set_bmaps(bm_left);         
156         }
157 }
158
159 void UI_DOT_SLIDER_NEW::draw()
160 {
161         // draw end buttons
162         if ( has_end_buttons ) {
163                 up_button.draw();
164                 down_button.draw();
165         }
166         
167         // draw the proper dot
168         Assert((pos >= 0) && (pos <= num_pos)); 
169         
170         // for position -1, we don't draw (no dots)     
171         if(pos >= 0){
172                 button.unhide();        
173                 button.draw_forced(pos);
174                 button.hide();          
175         }
176 }
177
178 void UI_DOT_SLIDER_NEW::process(int focus)
179 {
180         if (disabled_flag) {
181                 if (!hidden && !my_wnd->use_hack_to_get_around_stupid_problem_flag) {
182                         if (button.is_mouse_on() && B1_JUST_PRESSED) {
183                                 gamesnd_play_iface(SND_GENERAL_FAIL);
184                         } else if (has_end_buttons && (up_button.is_mouse_on() || down_button.is_mouse_on())) {
185                                 gamesnd_play_iface(SND_GENERAL_FAIL);
186                         }
187                         
188
189                         if ( (hotkey >= 0) && (my_wnd->keypress == hotkey) ){
190                                 gamesnd_play_iface(SND_GENERAL_FAIL);
191                         }
192                 }
193
194                 return;
195         }
196
197         // check focus and derived focus with one variable
198         if (my_wnd->selected_gadget == this){
199                 focus = 1;
200         }
201
202         // first check the dot area
203         button.process(focus);
204         if (button.button_down() || button.pressed() || mouse_captured()) {
205                 capture_mouse();  // while we are changing level, ignore all other buttons
206                 
207                 pos = (ui_mouse.x - x) / dot_width;             
208
209                 if (pos < 0){
210                         pos = 0;
211                 }
212
213                 // if we have 10 positions, 0 - 9 are valid
214                 if ( pos >= num_pos ) {
215                         pos = num_pos - 1;
216                 }
217
218                 return;
219         }
220
221         if ( has_end_buttons ) {
222                 up_button.process(focus);
223                 if (up_button.pressed()) {
224                         if (pos < num_pos-1){
225                                 pos++;
226                         } else {
227                                 gamesnd_play_iface(SND_GENERAL_FAIL);
228                         }
229                 }
230
231                 down_button.process(focus);
232                 if (down_button.pressed()) {
233                         if(pos){
234                                 pos--;
235                         } else {
236                                 gamesnd_play_iface(SND_GENERAL_FAIL);
237                         }
238                 }
239         }
240 }
241
242 //
243 // OLD DOT SLIDER - TO BE PHASED OUT. IF YOU NEED TO USE A UI_DOT_SLIDER, use a UI_DOT_SLIDER_NEW -------------------
244 //
245
246 /// DOT_SLIDER class down here
247 void UI_DOT_SLIDER::create(UI_WINDOW *wnd, int _x, int _y, char *bm, int id, int end_buttons, int _num_pos)
248 {
249         char    filename[MAX_PATH_LEN];
250         int     bx, by, bw, hotspot;
251
252         has_end_buttons = end_buttons;
253
254         if ( has_end_buttons ) {
255                 bx = _x + 24;
256                 by = _y + 1;
257                 bw = 190;
258                 hotspot = id + 1;
259         } else {
260                 bx = _x;
261                 by = _y;
262                 bw = 80;
263                 hotspot = id;
264         }
265
266         num_pos = _num_pos;
267
268         sprintf(filename, "%s%.2d", bm, hotspot);
269         first_frame = bm_load_animation(filename, &total_frames);
270         if (first_frame < 0) {
271                 Error(LOCATION, "Could not load %s.ani\n", filename);
272                 disable();
273                 hide();
274                 return;
275         }
276
277         base_create(wnd, UI_KIND_DOT_SLIDER, bx, by, bw, 20);
278         pos = 0;
279
280         // A DOT_SLIDER has up to 3 child buttons..
281
282         by = _y;
283
284         // First button is the region with the dots
285         button.create( wnd, "", bx, by, bw, 20, 0, 1 );
286         button.set_parent(this);
287         button.link_hotspot(hotspot);
288         button.hide();
289
290         if ( has_end_buttons ) {
291                 // Second button is the up (increase) button
292                 sprintf(filename, "%s%.2d", bm, id + 2);
293                 up_button.create( wnd, "", _x + 216, _y, 22, 24, 1, 1 );
294                 up_button.set_parent(this);
295                 up_button.set_highlight_action(common_play_highlight_sound);
296                 up_button.set_bmaps(filename);
297                 up_button.link_hotspot(id + 2);
298
299                 // Third button is the down (decrease) button
300                 sprintf(filename, "%s%.2d", bm, id);
301                 down_button.create( wnd, "", _x, _y, 22, 24, 1, 1 );
302                 down_button.set_parent(this);
303                 down_button.set_highlight_action(common_play_highlight_sound);
304                 down_button.set_bmaps(filename);
305                 down_button.link_hotspot(id);
306         }
307 }
308
309 void UI_DOT_SLIDER::destroy()
310 {
311         int i;
312
313         // release ani frames for the dots.
314         for (i=0; i<total_frames; i++){
315                 bm_release(first_frame + i);
316         }
317
318         UI_GADGET::destroy();
319 }
320
321 void UI_DOT_SLIDER::draw()
322 {
323         if ( has_end_buttons ) {
324                 up_button.draw();
325                 down_button.draw();
326         }
327         Assert((pos >= 0) && (pos <= num_pos));
328         gr_set_bitmap(first_frame + pos, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);  // draw the dot level
329         gr_bitmap(x, y);
330 }
331
332 void UI_DOT_SLIDER::process(int focus)
333 {
334         if (disabled_flag)
335                 return;
336
337         // check focus and derived focus with one variable
338         if (my_wnd->selected_gadget == this)
339                 focus = 1;
340
341         // first check the dot area
342         button.process(focus);
343         if (button.button_down() || button.pressed() || mouse_captured()) {
344                 capture_mouse();  // while we are changing level, ignore all other buttons
345
346                 if ( has_end_buttons ) {
347                         pos = (ui_mouse.x - x + 17) / 19;
348                 } else {
349                         pos = (ui_mouse.x - x) / 19;
350                 }
351
352                 if (pos < 0){
353                         pos = 0;
354                 }
355
356                 if ( pos > num_pos ){
357                         pos = num_pos;
358                 }
359
360                 return;
361         }
362
363         if ( has_end_buttons ) {
364                 up_button.process(focus);
365                 if (up_button.pressed()) {
366                         if (pos < num_pos){
367                                 pos++;
368                         } else {
369                                 gamesnd_play_iface(SND_GENERAL_FAIL);
370                         }
371                 }
372
373                 down_button.process(focus);
374                 if (down_button.pressed()) {
375                         if (pos){
376                                 pos--;
377                         } else {
378                                 gamesnd_play_iface(SND_GENERAL_FAIL);
379                         }
380                 }
381         }
382 }
383
384 /*
385 // --------------------------------------------------------------------
386 // UI_SLIDER::link_hotspot
387 //
388 //
389 void UI_SLIDER::link_hotspot(int left_button_num, int right_button_num)
390 {
391         left_button.link_hotspot(left_button_num);
392         right_button.link_hotspot(right_button_num);
393 }
394
395 // --------------------------------------------------------------------
396 // UI_SLIDER::set_bmaps
397 //
398 // Call the UI_GADGET::set_bmaps() function for the child components
399 // of a scroll bar (the up and down button).  Set up the bmaps for the
400 // line itself.
401 //
402 // We also need to get the dimensions of the bitmap button so we can update
403 // the dimensions of the scrollbar.
404 //
405 // returns:             -1 ==> error
406 //                                       0 ==> success
407 //
408 int UI_SLIDER::set_bmaps(char *left_button_fname, char *right_button_fname, char *bar_fname, char *marker_fname)
409 {
410         int m_w,m_h;
411
412         left_button.set_bmaps(left_button_fname);
413         right_button.set_bmaps(right_button_fname);
414         
415         // set the bitmaps for the rectangle that is the scrollbar itself
416         ((UI_GADGET*)this)->set_bmaps(bar_fname);
417         ((UI_GADGET*)this)->set_bmaps(marker_fname,2);  // skip the first two bitmaps 
418
419         bm_get_info( bmap_ids[SLIDER_MARKER_NORMAL], &m_w, &m_h, NULL );
420         // force the slider dimensions based on size of marker bitmap
421         w = n_positions * m_w;
422         marker_w = m_w;
423         marker_h = m_h;
424         pixel_range = w-marker_w;
425         increment = pixel_range / n_positions;
426
427         right_button.update_dimensions(x+w, y, -1, -1);
428
429         uses_bmaps = 1;
430
431         return 0;
432 }
433
434 void UI_SLIDER::hide()
435 {
436         hidden = 1;
437         left_button.hide();
438         right_button.hide();
439 }
440
441 void UI_SLIDER::unhide()
442 {
443         hidden = 0;
444         left_button.unhide();
445         right_button.unhide();
446 }
447
448 int UI_SLIDER::get_hidden()
449 {
450         return hidden;
451 }
452
453 void UI_SLIDER::create(UI_WINDOW *wnd, int _x, int _y, int _w, int _h, float _start, float _stop, float _current, int _n_positions )
454 {
455         char *up = "<";
456         char *down = ">";
457         int bw, bh, real_w;
458         bw=bh=_h;
459         real_w = _n_positions*bw;
460         base_create( wnd, UI_KIND_SLIDER, _x, _y, real_w, _h);
461
462         left_button.create( wnd, up, _x-bw, _y, _h, _h );
463         left_button.set_parent(this);
464
465         right_button.create( wnd, down, _x+real_w, _y, bh, bh );
466         right_button.set_parent(this);
467
468         horz = 0;
469         start = _start;
470         stop = _stop;
471         current = _current;
472
473         Assert( _current >= _start );
474         Assert( _current <= _stop );
475         Assert( stop >= 0 );
476
477         n_positions = _n_positions;
478
479         dragging = 0;
480         last_scrolled = 0;
481         moved = 1;
482
483         marker_w = _h;
484         marker_h = _h;
485
486         pixel_range = w-marker_w;
487         marker_x = x + fl2i( ( (current - start)/(stop-start) * pixel_range ) );
488         increment = pixel_range / n_positions;
489         Assert(increment >= 1);
490         mouse_locked = 0;
491 };
492
493 void UI_SLIDER::draw()
494 {
495         if ( uses_bmaps ) {
496                 gr_reset_clip();
497                 if ( disabled_flag ) {
498                         if ( bmap_ids[SLIDER_BAR_DISABLED] != -1 ) {
499                                 gr_set_bitmap(bmap_ids[SLIDER_BAR_DISABLED]);
500                                 gr_bitmap(x,y);
501                         }
502
503                         if ( bmap_ids[SLIDER_MARKER_DISABLED] != -1 ) {
504                                 gr_set_bitmap(bmap_ids[SLIDER_MARKER_DISABLED]);
505                                 gr_bitmap(marker_x,marker_y);
506                         }
507
508                 }
509                 else {
510                         if ( bmap_ids[SLIDER_BAR_NORMAL] != -1 ) {
511                                 gr_set_bitmap(bmap_ids[SLIDER_BAR_NORMAL]);
512                                 gr_bitmap(x,y);
513                         }
514
515                         if ( bmap_ids[SLIDER_MARKER_NORMAL] != -1 ) {
516                                 gr_set_bitmap(bmap_ids[SLIDER_MARKER_NORMAL]);
517                                 gr_bitmap(marker_x,marker_y);
518                         }
519                 }
520         }
521         else {
522                 gr_set_font(my_wnd->f_id);
523                 gr_set_clip( x, y, w, h );
524
525                 if (my_wnd->selected_gadget == this)
526                         gr_set_color_fast( &CBRIGHT_GREEN );
527                 else
528                         gr_set_color_fast( &CGRAY );
529
530                 ui_rect( 0, 0, w-1, h-1 );
531
532                 gr_set_clip( marker_x, marker_y, w, h );
533                 ui_draw_box_out(0, 0, marker_w, marker_h);
534         }
535 }
536
537 void UI_SLIDER::process(int focus)
538 {
539         int OnMe, OnMarker, keyfocus;
540         int oldpos, op;
541         float percent;
542         moved = 0;
543
544         if (disabled_flag) {
545                 return;
546         }
547
548         if (my_wnd->selected_gadget == this)
549                 keyfocus = 1;
550
551         left_button.process(focus);
552         right_button.process(focus);
553
554         marker_y = y;
555         keyfocus = 0;
556
557         if (start == stop) {
558                 marker_x = x;
559                 return;
560         }
561
562         op = marker_x;
563         oldpos = fake_position;
564
565         OnMarker = 0;
566         OnMe = is_mouse_on();
567         if ( OnMe ) {
568                 if ( ui_mouse.x >= (marker_x ) && ui_mouse.x <= (marker_x+marker_w) ) {
569                         OnMarker = 1;
570                         if ( B1_PRESSED )
571                                 mouse_locked = 1;
572                 }
573         }
574
575         if ( !B1_PRESSED) {
576                 mouse_locked = 0;
577         }
578
579         if ( (left_button.position!=0) || (keyfocus && keyd_pressed[KEY_LEFT]) || ( OnMe && B1_PRESSED && ui_mouse.x < marker_x) || (mouse_locked && ui_mouse.x < marker_x ) )  {
580                 if ( (timer_get_milliseconds() > last_scrolled+50) || left_button.just_pressed() || B1_JUST_PRESSED || mouse_locked || my_wnd->keypress == KEY_LEFT)    {
581                         if ( left_button.just_pressed() || B1_JUST_PRESSED || mouse_locked || my_wnd->keypress == KEY_LEFT )    {
582                                 last_scrolled = timer_get_milliseconds() + 300;
583                         } else
584                                 last_scrolled = timer_get_milliseconds();
585                         marker_x -= increment;
586                         if (marker_x < x )
587                                 marker_x = x;
588                 }
589         }
590
591         if ( (right_button.position!=0) || (keyfocus && keyd_pressed[KEY_RIGHT]) || ( OnMe && B1_PRESSED && ui_mouse.x > (marker_x+marker_w)) || (mouse_locked && ui_mouse.x > marker_x+marker_w) ) {
592                 if ( (timer_get_milliseconds() > last_scrolled+50) || right_button.just_pressed() || B1_JUST_PRESSED || mouse_locked || my_wnd->keypress == KEY_RIGHT)  {
593                         if ( right_button.just_pressed() || B1_JUST_PRESSED || mouse_locked || my_wnd->keypress == KEY_RIGHT)   
594                                 last_scrolled = timer_get_milliseconds() + 300;
595                         else
596                                 last_scrolled = timer_get_milliseconds();
597                         marker_x += increment;
598                         if (marker_x > (x+n_positions*increment) )
599                                 marker_x = x+n_positions*increment;
600                 }
601         }
602
603         percent = i2fl(marker_x - x)/i2fl(pixel_range);
604         current = percent * (stop - start);
605 }
606
607 int UI_SLIDER::getpos()
608 {
609         return marker_x;
610 }
611
612 float UI_SLIDER::getcurrent()
613 {
614         return current;
615 }
616
617 int UI_SLIDER::changed()
618 {
619         return moved;
620 }
621 */
622