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