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 the
6  * source.
7  *
8 */
9 
10 
11 
12 #include "ui/uidefs.h"
13 #include "ui/ui.h"
14 #include "freespace2/freespace.h"
15 #include "bmpman/bmpman.h"
16 #include "io/timer.h"
17 
18 
19 
20 // captureCallback is called when an item is "selected" by mouse release. That is, the user has clicked, dragged and _released_.
21 // the callback is called when the scrollbar has been released
create(UI_WINDOW * wnd,int _x,int _y,int _w,int _h,int _numberItems,char * _bitmapSliderControl,void (* _upCallback)(),void (* _downCallback)(),void (* _captureCallback)())22 void UI_SLIDER2::create(UI_WINDOW *wnd, int _x, int _y, int _w, int _h, int _numberItems, char *_bitmapSliderControl, void (* _upCallback)(), void (*_downCallback)(),
23 				void (* _captureCallback)()) {
24 
25 	int buttonHeight, buttonWidth;
26 
27 	base_create( wnd, UI_KIND_SLIDER2, _x, _y, _w, _h );
28 
29 	Assert(_upCallback != NULL);
30 	Assert(_downCallback != NULL);
31 
32 	upCallback = _upCallback;
33 	downCallback = _downCallback;
34 
35 	captureCallback = _captureCallback;
36 
37 	Assert(_bitmapSliderControl > 0);
38 
39 	last_scrolled = 0;
40 
41 	// set bitmap
42 	set_bmaps(_bitmapSliderControl, 3, 0);
43 
44 	// determine possible positions
45 	bm_get_info(bmap_ids[S2_NORMAL],&buttonWidth, &buttonHeight, NULL, NULL, NULL);
46 	slider_w = buttonWidth;
47 	slider_h = buttonHeight;
48 	Assert(buttonHeight > 5);
49 	slider_half_h = (int)(buttonHeight / 2);
50 	numberPositions = _h - buttonHeight;
51 
52 	Assert(numberPositions >= 0);
53 	currentItem = 0;
54 	currentPosition = 0;
55 
56 	numberItems = _numberItems;
57 	if (numberItems <= 0) {
58 		disabled_flag = 1;
59 	}
60 
61 	slider_mode = S2M_DEFAULT;
62 }
63 
draw()64 void UI_SLIDER2::draw() {
65 	Assert((currentPosition >= 0) && (currentPosition <= numberPositions));
66 	if (uses_bmaps && !disabled_flag) {
67 		gr_reset_clip();
68 		switch (slider_mode) {
69 		case S2M_ON_ME:
70 			gr_set_bitmap(bmap_ids[S2_HIGHLIGHT]);  // draw slider level
71 			break;
72 		case S2M_MOVING:
73 			gr_set_bitmap(bmap_ids[S2_PRESSED]);
74 			break;
75 		case S2M_DEFAULT:
76 		default:
77 			gr_set_bitmap(bmap_ids[S2_NORMAL]);  // draw slider level
78 			break;
79 		}
80 		gr_bitmap(x, y+currentPosition, GR_RESIZE_MENU);
81 	}
82 }
83 
process(int focus)84 void UI_SLIDER2::process(int focus)
85 {
86 	int OnMe, mouse_lock_move;
87 
88 	if (disabled_flag) {
89 		return;
90 	}
91 
92 	OnMe = is_mouse_on();
93 	if ( OnMe ) {
94 		// are we on the button?
95 		if ( (ui_mouse.y >= (y+currentPosition)) && (ui_mouse.y <= (y+currentPosition+slider_h)) ) {
96 			slider_mode = S2M_ON_ME;
97 			if ( B1_PRESSED ) {
98 				mouse_locked = 1;
99 			}
100 		}
101 	} else
102 		slider_mode = S2M_DEFAULT;
103 
104 	if ( !B1_PRESSED) {
105 		if (mouse_locked == 1)
106 			if (captureCallback != NULL) {
107 				captureCallback();
108 				mprintf(("Called captureCallback()!\n"));
109 			}
110 		mouse_locked = 0;
111 	}
112 
113 	if (!OnMe && !mouse_locked)
114 		return;
115 
116 	// could we possibly be moving up?
117 	if ((OnMe && B1_PRESSED && ui_mouse.y < (currentPosition+y+slider_half_h-1)) || (mouse_locked && (ui_mouse.y < (currentPosition+y+slider_half_h-1))) ) {
118 		// make sure we wait at least 50 ms between events unless mouse locked
119 		if ( (timer_get_milliseconds() > last_scrolled+50) || B1_JUST_PRESSED || mouse_locked ) {
120 			last_scrolled = timer_get_milliseconds();
121 			if (!mouse_locked) {
122 				if (currentItem > 0) {
123 					currentItem--;
124 					if (upCallback != NULL) {
125 						upCallback();
126 						if (captureCallback != NULL)
127 							captureCallback();
128 					}
129 				}
130 				currentPosition = fl2i((((float)currentItem/(float)numberItems) * (float)numberPositions)-.49);
131 			} else {
132 				mouse_lock_move = fl2i( ((((float)ui_mouse.y - (float)y - (float)slider_half_h)/(float)numberPositions) * (float)numberItems) -.49);
133 				mouse_lock_move = currentItem - mouse_lock_move;
134 				if (mouse_lock_move > 0) {
135 					while (mouse_lock_move >  0) {
136 						if (currentItem > 0) {
137 							currentItem--;
138 							if (upCallback != NULL)
139 								upCallback();
140 						}
141 						mouse_lock_move--;
142 					}
143 				}
144 				// currentPosition = ui_mouse.y - y - slider_half_h;
145 				currentPosition = fl2i((((float)currentItem/(float)numberItems) * (float)numberPositions)-.49);
146 			}
147 			if (currentPosition < 0)
148 				currentPosition = 0;
149 			if (currentPosition > numberPositions)
150 			currentPosition = numberPositions;
151 			slider_mode = S2M_MOVING;
152 		}
153 	}
154 
155 	if ( ( OnMe && B1_PRESSED && ui_mouse.y > (currentPosition+y+slider_half_h+1)) || (mouse_locked && (ui_mouse.y > (currentPosition+y+slider_half_h+1)))  ) {
156 		// make sure we wait at least 50 ms between events unless mouse locked
157 		if ( (timer_get_milliseconds() > last_scrolled+50) || B1_JUST_PRESSED || mouse_locked ) {
158 			last_scrolled = timer_get_milliseconds();
159 			if (!mouse_locked) {
160 				if (currentItem < numberItems) {
161 					currentItem++;
162 					if (downCallback != NULL) {
163 						downCallback();
164 						if (captureCallback != NULL)
165 							captureCallback();
166 					}
167 				}
168 				currentPosition = fl2i((((float)currentItem/(float)numberItems) * (float)numberPositions)-.49);
169 			} else {
170 				mouse_lock_move = fl2i( ((((float)ui_mouse.y - (float)y - (float)slider_half_h)/(float)numberPositions) * (float)numberItems) -.49);
171 				mouse_lock_move -= currentItem;
172 				if (mouse_lock_move > 0) {
173 					while (mouse_lock_move > 0) {
174 						if  (currentItem < numberItems) {
175 							currentItem++;
176 							if (downCallback != NULL)
177 								downCallback();
178 						}
179 						mouse_lock_move--;
180 					}
181 				}
182 				// currentPosition = ui_mouse.y - y - slider_half_h;
183 				currentPosition = fl2i((((float)currentItem/(float)numberItems) * (float)numberPositions)-.49);
184 			}
185 			if (currentPosition < 0){
186 				currentPosition = 0;
187 			}
188 			if (currentPosition > numberPositions){
189 				currentPosition = numberPositions;
190 			}
191 			slider_mode = S2M_MOVING;
192 		}
193 	}
194 
195 	// if we are centerd on the bitmap and still in mouse lock mode, we need to make sure the MOVING bitmap is still shown
196 	// or if mouse is on us and we are pressing the mouse button
197 	if (mouse_locked || (OnMe && B1_PRESSED)){
198 		slider_mode = S2M_MOVING;
199 	}
200 }
201 
hide()202 void UI_SLIDER2::hide()
203 {
204 	hidden = 1;
205 }
206 
unhide()207 void UI_SLIDER2::unhide()
208 {
209 	hidden = 0;
210 }
211 
get_hidden()212 int UI_SLIDER2::get_hidden()
213 {
214 	return hidden;
215 }
216 
217 
218 // return number of itmes
get_numberItems()219 int UI_SLIDER2::get_numberItems() {
220 	return numberItems;
221 }
222 
223 // return current position
get_currentPosition()224 int UI_SLIDER2::get_currentPosition() {
225 	return currentPosition;
226 }
227 
228 // return current item
get_currentItem()229 int UI_SLIDER2::get_currentItem() {
230 	return currentItem;
231 }
232 
233 // change range. reset back to position 0
set_numberItems(int _numberItems,int _reset)234 void UI_SLIDER2::set_numberItems(int _numberItems, int _reset) {
235 	numberItems = _numberItems;
236 
237 	if (_reset) {
238 		currentItem = 0;
239 		currentPosition = 0;
240 	} else {
241 		// recalcluate current position
242 		currentPosition = fl2i((((float)currentItem/(float)numberItems) * (float)numberPositions)-.49);
243 		if (currentPosition < 0){
244 			currentPosition = 0;
245 		}
246 		if (currentPosition > numberPositions){
247 			currentPosition = numberPositions;
248 		}
249 	}
250 	if (numberItems <= 0){
251 		disabled_flag = 1;
252 	} else {
253 		disabled_flag = 0;
254 	}
255 }
256 
257 // force slider to new position manually
set_currentItem(int _currentItem)258 void UI_SLIDER2::set_currentItem(int _currentItem) {
259 	if (_currentItem > numberItems)
260 		goto cpSafety;
261 
262 	if (_currentItem == currentItem)
263 		goto cpSafety;
264 
265 	if (_currentItem < 0)
266 		goto cpSafety;
267 
268 	if (_currentItem > currentItem) {
269 		while (currentItem != _currentItem) {
270 			currentItem++;
271 			if (downCallback != NULL)
272 				downCallback();
273 		}
274 	} else if (_currentItem < currentItem) {
275 		while (currentItem != _currentItem) {
276 			currentItem--;
277 			if (upCallback != NULL)
278 				upCallback();
279 		}
280 	}
281 
282 	currentPosition = fl2i(((float)currentItem/(float)numberItems) * (float)numberPositions);
283 
284 cpSafety: // helps fix math problem on x86_64
285 	if (currentPosition > numberItems)
286 		currentPosition = numberItems;
287 
288 	if (currentPosition < 0)
289 		currentPosition = 0;
290 }
291 
force_currentItem(int _currentItem)292 void UI_SLIDER2::force_currentItem(int _currentItem) {
293 	if (_currentItem > numberItems)
294 		goto cpSafety;
295 
296 	if (_currentItem == currentItem)
297 		goto cpSafety;
298 
299 	currentItem = _currentItem;
300 
301 	if(currentItem < 0){
302 		currentItem = 0;
303 	};
304 
305 	currentPosition = fl2i(((float)currentItem/(float)numberItems) * (float)numberPositions);
306 
307 cpSafety: // helps fix math problem on x86_64
308 	if (currentPosition > numberItems)
309 		currentPosition = numberItems;
310 
311 	if (currentPosition < 0)
312 		currentPosition = 0;
313 }
314 
forceDown()315 void UI_SLIDER2::forceDown() {
316 	if (currentItem < numberItems) {
317 		currentItem++;
318 		currentPosition = fl2i(((float)currentItem/(float)numberItems) * (float)numberPositions);
319 	}
320 }
321 
forceUp()322 void UI_SLIDER2::forceUp() {
323 	if (currentItem > 0) {
324 		currentItem--;
325 		currentPosition = fl2i(((float)currentItem/(float)numberItems) * (float)numberPositions);
326 
327 		if (currentPosition < 0)
328 			currentPosition = 0;
329 	}
330 }
331