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