2 * $Logfile: /Freespace2/code/Ui/slider.cpp $
7 * C++ file for controlling and displaying a horizontal slider
10 * Revision 1.2 2002/05/07 03:16:53 theoddone33
11 * The Great Newline Fix
13 * Revision 1.1.1.1 2002/05/03 03:28:11 root
17 * 8 8/10/99 6:54p Dave
18 * Mad optimizations. Added paging to the nebula effect.
20 * 7 8/02/99 6:04p Jefff
21 * use_hack_to_get_around_stupid_problem_flag extended to sliders
23 * 6 5/03/99 8:33p Dave
24 * New version of multi host options screen.
26 * 5 2/11/99 3:08p Dave
27 * PXO refresh button. Very preliminary squad war support.
29 * 4 12/02/98 5:47p Dave
30 * Put in interface xstr code. Converted barracks screen to new format.
32 * 3 10/13/98 9:29a Dave
33 * Started neatening up freespace.h. Many variables renamed and
34 * reorganized. Added AlphaColors.[h,cpp]
36 * 2 10/07/98 10:54a Dave
39 * 1 10/07/98 10:51a Dave
41 * 12 4/17/98 10:34a Hoffoss
42 * Fixed dot slider positionings.
44 * 11 3/22/98 10:50p Lawrance
45 * Allow sliders to not have end-buttons.
47 * 10 2/03/98 4:21p Hoffoss
48 * Made UI controls draw white text when disabled.
50 * 9 1/30/98 11:59a Hoffoss
51 * changed offset of slider child button.
53 * 8 1/27/98 7:02p Lawrance
54 * Don't play the "mouse over" sound for the volume circles.
56 * 7 1/15/98 12:00p Hoffoss
57 * Embelished file with nifty comments.
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.
64 * 5 8/24/97 5:25p Lawrance
65 * improve drawing of buttons
67 * 4 6/12/97 12:39p John
68 * made ui use freespace colors
70 * 3 6/11/97 1:13p John
71 * Started fixing all the text colors in the game.
73 * 2 5/26/97 10:26a Lawrance
74 * get slider control working 100%
84 #include "missionscreencommon.h"
87 #include "alphacolors.h"
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,
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)){
105 // now we know we have end buttons
111 base_create(wnd, UI_KIND_DOT_SLIDER_NEW, _x, _y, 0, 20);
113 dot_width = _dot_width;
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);
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);
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);
140 void UI_DOT_SLIDER_NEW::draw()
143 if ( has_end_buttons ) {
148 // draw the proper dot
149 Assert((pos >= 0) && (pos <= num_pos));
151 // for position -1, we don't draw (no dots)
154 button.draw_forced(pos);
159 void UI_DOT_SLIDER_NEW::process(int focus)
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);
170 if ( (hotkey >= 0) && (my_wnd->keypress == hotkey) ){
171 gamesnd_play_iface(SND_GENERAL_FAIL);
178 // check focus and derived focus with one variable
179 if (my_wnd->selected_gadget == this){
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
188 pos = (ui_mouse.x - x) / dot_width;
194 // if we have 10 positions, 0 - 9 are valid
195 if ( pos >= num_pos ) {
202 if ( has_end_buttons ) {
203 up_button.process(focus);
204 if (up_button.pressed()) {
205 if (pos < num_pos-1){
208 gamesnd_play_iface(SND_GENERAL_FAIL);
212 down_button.process(focus);
213 if (down_button.pressed()) {
217 gamesnd_play_iface(SND_GENERAL_FAIL);
224 // OLD DOT SLIDER - TO BE PHASED OUT. IF YOU NEED TO USE A UI_DOT_SLIDER, use a UI_DOT_SLIDER_NEW -------------------
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)
230 char filename[MAX_PATH_LEN];
231 int bx, by, bw, hotspot;
233 has_end_buttons = end_buttons;
235 if ( has_end_buttons ) {
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);
258 base_create(wnd, UI_KIND_DOT_SLIDER, bx, by, bw, 20);
261 // A DOT_SLIDER has up to 3 child buttons..
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);
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);
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);
290 void UI_DOT_SLIDER::destroy()
294 // release ani frames for the dots.
295 for (i=0; i<total_frames; i++){
296 bm_release(first_frame + i);
299 UI_GADGET::destroy();
302 void UI_DOT_SLIDER::draw()
304 if ( has_end_buttons ) {
308 Assert((pos >= 0) && (pos <= num_pos));
309 gr_set_bitmap(first_frame + pos); // draw the dot level
313 void UI_DOT_SLIDER::process(int focus)
318 // check focus and derived focus with one variable
319 if (my_wnd->selected_gadget == this)
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
327 if ( has_end_buttons ) {
328 pos = (ui_mouse.x - x + 17) / 19;
330 pos = (ui_mouse.x - x) / 19;
337 if ( pos > num_pos ){
344 if ( has_end_buttons ) {
345 up_button.process(focus);
346 if (up_button.pressed()) {
350 gamesnd_play_iface(SND_GENERAL_FAIL);
354 down_button.process(focus);
355 if (down_button.pressed()) {
359 gamesnd_play_iface(SND_GENERAL_FAIL);
366 // --------------------------------------------------------------------
367 // UI_SLIDER::link_hotspot
370 void UI_SLIDER::link_hotspot(int left_button_num, int right_button_num)
372 left_button.link_hotspot(left_button_num);
373 right_button.link_hotspot(right_button_num);
376 // --------------------------------------------------------------------
377 // UI_SLIDER::set_bmaps
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
383 // We also need to get the dimensions of the bitmap button so we can update
384 // the dimensions of the scrollbar.
386 // returns: -1 ==> error
389 int UI_SLIDER::set_bmaps(char *left_button_fname, char *right_button_fname, char *bar_fname, char *marker_fname)
393 left_button.set_bmaps(left_button_fname);
394 right_button.set_bmaps(right_button_fname);
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
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;
405 pixel_range = w-marker_w;
406 increment = pixel_range / n_positions;
408 right_button.update_dimensions(x+w, y, -1, -1);
415 void UI_SLIDER::hide()
422 void UI_SLIDER::unhide()
425 left_button.unhide();
426 right_button.unhide();
429 int UI_SLIDER::get_hidden()
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 )
440 real_w = _n_positions*bw;
441 base_create( wnd, UI_KIND_SLIDER, _x, _y, real_w, _h);
443 left_button.create( wnd, up, _x-bw, _y, _h, _h );
444 left_button.set_parent(this);
446 right_button.create( wnd, down, _x+real_w, _y, bh, bh );
447 right_button.set_parent(this);
454 Assert( _current >= _start );
455 Assert( _current <= _stop );
458 n_positions = _n_positions;
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);
474 void UI_SLIDER::draw()
478 if ( disabled_flag ) {
479 if ( bmap_ids[SLIDER_BAR_DISABLED] != -1 ) {
480 gr_set_bitmap(bmap_ids[SLIDER_BAR_DISABLED]);
484 if ( bmap_ids[SLIDER_MARKER_DISABLED] != -1 ) {
485 gr_set_bitmap(bmap_ids[SLIDER_MARKER_DISABLED]);
486 gr_bitmap(marker_x,marker_y);
491 if ( bmap_ids[SLIDER_BAR_NORMAL] != -1 ) {
492 gr_set_bitmap(bmap_ids[SLIDER_BAR_NORMAL]);
496 if ( bmap_ids[SLIDER_MARKER_NORMAL] != -1 ) {
497 gr_set_bitmap(bmap_ids[SLIDER_MARKER_NORMAL]);
498 gr_bitmap(marker_x,marker_y);
503 gr_set_font(my_wnd->f_id);
504 gr_set_clip( x, y, w, h );
506 if (my_wnd->selected_gadget == this)
507 gr_set_color_fast( &CBRIGHT_GREEN );
509 gr_set_color_fast( &CGRAY );
511 ui_rect( 0, 0, w-1, h-1 );
513 gr_set_clip( marker_x, marker_y, w, h );
514 ui_draw_box_out(0, 0, marker_w, marker_h);
518 void UI_SLIDER::process(int focus)
520 int OnMe, OnMarker, keyfocus;
529 if (my_wnd->selected_gadget == this)
532 left_button.process(focus);
533 right_button.process(focus);
544 oldpos = fake_position;
547 OnMe = is_mouse_on();
549 if ( ui_mouse.x >= (marker_x ) && ui_mouse.x <= (marker_x+marker_w) ) {
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;
565 last_scrolled = timer_get_milliseconds();
566 marker_x -= increment;
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;
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;
584 percent = i2fl(marker_x - x)/i2fl(pixel_range);
585 current = percent * (stop - start);
588 int UI_SLIDER::getpos()
593 float UI_SLIDER::getcurrent()
598 int UI_SLIDER::changed()