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