Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1 | pmbaty | 1 | /* |
2 | * Portions of this file are copyright Rebirth contributors and licensed as |
||
3 | * described in COPYING.txt. |
||
4 | * Portions of this file are copyright Parallax Software and licensed |
||
5 | * according to the Parallax license below. |
||
6 | * See COPYING.txt for license details. |
||
7 | |||
8 | THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX |
||
9 | SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO |
||
10 | END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A |
||
11 | ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS |
||
12 | IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS |
||
13 | SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE |
||
14 | FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE |
||
15 | CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS |
||
16 | AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. |
||
17 | COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. |
||
18 | */ |
||
19 | |||
20 | |||
21 | #include <stdlib.h> |
||
22 | |||
23 | #include "maths.h" |
||
24 | #include "pstypes.h" |
||
25 | #include "event.h" |
||
26 | #include "gr.h" |
||
27 | #include "ui.h" |
||
28 | #include "mouse.h" |
||
29 | #include "key.h" |
||
30 | #include "timer.h" |
||
31 | |||
32 | namespace dcx { |
||
33 | |||
34 | static void gr_draw_sunken_border( short x1, short y1, short x2, short y2 ); |
||
35 | |||
36 | void ui_draw_listbox( UI_DIALOG *dlg, UI_GADGET_LISTBOX * listbox ) |
||
37 | { |
||
38 | int i, x, y, stop; |
||
39 | int w, h; |
||
40 | |||
41 | //if (listbox->current_item<0) |
||
42 | // listbox->current_item=0; |
||
43 | //if (listbox->current_item>=listbox->num_items) |
||
44 | // listbox->current_item = listbox->num_items-1; |
||
45 | //if (listbox->first_item<0) |
||
46 | // listbox->first_item=0; |
||
47 | //if (listbox->first_item>(listbox->num_items-listbox->num_items_displayed)) |
||
48 | // listbox->first_item=(listbox->num_items-listbox->num_items_displayed); |
||
49 | |||
50 | #if 0 //ndef OGL |
||
51 | if ((listbox->status!=1) && !listbox->moved ) |
||
52 | return; |
||
53 | #endif |
||
54 | |||
55 | gr_set_current_canvas( listbox->canvas ); |
||
56 | auto &canvas = *grd_curcanv; |
||
57 | |||
58 | w = listbox->width; |
||
59 | h = listbox->height; |
||
60 | |||
61 | gr_rect(canvas, 0, 0, w-1, h-1, CBLACK); |
||
62 | |||
63 | gr_draw_sunken_border( -2, -2, w+listbox->scrollbar->width+4, h+1); |
||
64 | |||
65 | stop = listbox->first_item+listbox->num_items_displayed; |
||
66 | if (stop>listbox->num_items) stop = listbox->num_items; |
||
67 | |||
68 | listbox->status = 0; |
||
69 | |||
70 | x = y = 0; |
||
71 | |||
72 | for (i= listbox->first_item; i< stop; i++ ) |
||
73 | { |
||
74 | const auto color = (i == listbox->current_item) |
||
75 | ? CGREY |
||
76 | : CBLACK; |
||
77 | gr_rect(canvas, x, y, listbox->width - 1, y + h - 1, color); |
||
78 | |||
79 | if (i !=listbox->current_item) |
||
80 | { |
||
81 | if ((listbox->current_item == -1) && (dlg->keyboard_focus_gadget == listbox) && (i == listbox->first_item) ) |
||
82 | gr_set_fontcolor(canvas, CRED, -1); |
||
83 | else |
||
84 | gr_set_fontcolor(canvas, CWHITE, -1); |
||
85 | } |
||
86 | else |
||
87 | { |
||
88 | if (dlg->keyboard_focus_gadget == listbox) |
||
89 | gr_set_fontcolor(canvas, CRED, -1); |
||
90 | else |
||
91 | gr_set_fontcolor(canvas, CBLACK, -1); |
||
92 | } |
||
93 | gr_get_string_size(*canvas.cv_font, listbox->list[i], &w, &h, nullptr); |
||
94 | gr_string(canvas, *canvas.cv_font, x + 2, y, listbox->list[i], w, h); |
||
95 | y += h; |
||
96 | } |
||
97 | |||
98 | if (stop < listbox->num_items_displayed-1 ) |
||
99 | { |
||
100 | gr_rect(canvas, x, y, listbox->width-1, listbox->height-1, CBLACK); |
||
101 | } |
||
102 | |||
103 | //gr_ubox( -1, -1, listbox->width, listbox->height); |
||
104 | } |
||
105 | |||
106 | |||
107 | static void gr_draw_sunken_border( short x1, short y1, short x2, short y2 ) |
||
108 | { |
||
109 | const uint8_t cgrey = CGREY; |
||
110 | const uint8_t cbright = CBRIGHT; |
||
111 | Hline(*grd_curcanv, x1 - 1, x2 + 1, y1 - 1, cgrey); |
||
112 | Vline(*grd_curcanv, y1 - 1, y2 + 1, x1 - 1, cgrey); |
||
113 | |||
114 | Hline(*grd_curcanv, x1 - 1, x2 + 1, y2 + 1, cbright); |
||
115 | Vline(*grd_curcanv, y1, y2 + 1, x2 + 1, cbright); |
||
116 | } |
||
117 | |||
118 | |||
119 | std::unique_ptr<UI_GADGET_LISTBOX> ui_add_gadget_listbox(UI_DIALOG *dlg, short x, short y, short w, short h, short numitems, char **list) |
||
120 | { |
||
121 | int th, i; |
||
122 | gr_get_string_size(*grd_curcanv->cv_font, "*", nullptr, &th, nullptr); |
||
123 | |||
124 | i = h / th; |
||
125 | h = i * th; |
||
126 | |||
127 | std::unique_ptr<UI_GADGET_LISTBOX> listbox{ui_gadget_add<UI_GADGET_LISTBOX>( dlg, x, y, x+w-1, y+h-1 )}; |
||
128 | listbox->list = list; |
||
129 | listbox->width = w; |
||
130 | listbox->height = h; |
||
131 | listbox->num_items = numitems; |
||
132 | listbox->num_items_displayed = i; |
||
133 | listbox->first_item = 0; |
||
134 | listbox->current_item = -1; |
||
135 | listbox->last_scrolled = 0; |
||
136 | listbox->textheight = th; |
||
137 | listbox->dragging = 0; |
||
138 | listbox->selected_item = -1; |
||
139 | listbox->moved = 1; |
||
140 | listbox->scrollbar = ui_add_gadget_scrollbar( dlg, x+w+3, y, 0, h, 0, numitems-i, 0, i ); |
||
141 | listbox->scrollbar->parent = listbox.get(); |
||
142 | return listbox; |
||
143 | } |
||
144 | |||
145 | window_event_result ui_listbox_do( UI_DIALOG *dlg, UI_GADGET_LISTBOX * listbox,const d_event &event ) |
||
146 | { |
||
147 | int mitem, oldfakepos, kf; |
||
148 | int keypress = 0; |
||
149 | if (event.type == EVENT_WINDOW_DRAW) |
||
150 | { |
||
151 | ui_draw_listbox( dlg, listbox ); |
||
152 | return window_event_result::ignored; |
||
153 | } |
||
154 | |||
155 | if (event.type == EVENT_KEY_COMMAND) |
||
156 | keypress = event_key_get(event); |
||
157 | |||
158 | listbox->selected_item = -1; |
||
159 | |||
160 | listbox->moved = 0; |
||
161 | |||
162 | if (listbox->num_items < 1 ) { |
||
163 | listbox->current_item = -1; |
||
164 | listbox->first_item = 0; |
||
165 | listbox->old_current_item = listbox->current_item; |
||
166 | listbox->old_first_item = listbox->first_item; |
||
167 | //ui_draw_listbox( dlg, listbox ); |
||
168 | |||
169 | if (dlg->keyboard_focus_gadget == listbox) |
||
170 | { |
||
171 | dlg->keyboard_focus_gadget = ui_gadget_get_next(listbox); |
||
172 | } |
||
173 | |||
174 | return window_event_result::ignored; |
||
175 | } |
||
176 | |||
177 | listbox->old_current_item = listbox->current_item; |
||
178 | listbox->old_first_item = listbox->first_item; |
||
179 | |||
180 | |||
181 | if (GADGET_PRESSED(listbox->scrollbar.get())) |
||
182 | { |
||
183 | listbox->moved = 1; |
||
184 | |||
185 | listbox->first_item = listbox->scrollbar->position; |
||
186 | |||
187 | if (listbox->current_item<listbox->first_item) |
||
188 | listbox->current_item = listbox->first_item; |
||
189 | |||
190 | if (listbox->current_item>(listbox->first_item+listbox->num_items_displayed-1)) |
||
191 | listbox->current_item = listbox->first_item + listbox->num_items_displayed-1; |
||
192 | |||
193 | } |
||
194 | |||
195 | if (B1_JUST_RELEASED) |
||
196 | listbox->dragging = 0; |
||
197 | |||
198 | window_event_result rval = window_event_result::ignored; |
||
199 | if (B1_JUST_PRESSED && ui_mouse_on_gadget( listbox )) |
||
200 | { |
||
201 | listbox->dragging = 1; |
||
202 | rval = window_event_result::handled; |
||
203 | } |
||
204 | |||
205 | if ( dlg->keyboard_focus_gadget==listbox ) |
||
206 | { |
||
207 | if (keypress==KEY_ENTER) { |
||
208 | listbox->selected_item = listbox->current_item; |
||
209 | rval = window_event_result::handled; |
||
210 | } |
||
211 | |||
212 | kf = 0; |
||
213 | |||
214 | switch(keypress) |
||
215 | { |
||
216 | case (KEY_UP): |
||
217 | listbox->current_item--; |
||
218 | kf = 1; |
||
219 | break; |
||
220 | case (KEY_DOWN): |
||
221 | listbox->current_item++; |
||
222 | kf = 1; |
||
223 | break; |
||
224 | case (KEY_HOME): |
||
225 | listbox->current_item=0; |
||
226 | kf = 1; |
||
227 | break; |
||
228 | case (KEY_END): |
||
229 | listbox->current_item=listbox->num_items-1; |
||
230 | kf = 1; |
||
231 | break; |
||
232 | case (KEY_PAGEUP): |
||
233 | listbox->current_item -= listbox->num_items_displayed; |
||
234 | kf = 1; |
||
235 | break; |
||
236 | case (KEY_PAGEDOWN): |
||
237 | listbox->current_item += listbox->num_items_displayed; |
||
238 | kf = 1; |
||
239 | break; |
||
240 | } |
||
241 | |||
242 | if (kf==1) |
||
243 | { |
||
244 | listbox->moved = 1; |
||
245 | rval = window_event_result::handled; |
||
246 | |||
247 | if (listbox->current_item<0) |
||
248 | listbox->current_item=0; |
||
249 | |||
250 | if (listbox->current_item>=listbox->num_items) |
||
251 | listbox->current_item = listbox->num_items-1; |
||
252 | |||
253 | if (listbox->current_item<listbox->first_item) |
||
254 | listbox->first_item = listbox->current_item; |
||
255 | |||
256 | if (listbox->current_item>=(listbox->first_item+listbox->num_items_displayed)) |
||
257 | listbox->first_item = listbox->current_item-listbox->num_items_displayed+1; |
||
258 | |||
259 | if (listbox->num_items <= listbox->num_items_displayed ) |
||
260 | listbox->first_item = 0; |
||
261 | else |
||
262 | { |
||
263 | oldfakepos = listbox->scrollbar->position; |
||
264 | listbox->scrollbar->position = listbox->first_item; |
||
265 | |||
266 | listbox->scrollbar->fake_position = listbox->scrollbar->position-listbox->scrollbar->start; |
||
267 | listbox->scrollbar->fake_position *= listbox->scrollbar->height-listbox->scrollbar->fake_size; |
||
268 | listbox->scrollbar->fake_position /= (listbox->scrollbar->stop-listbox->scrollbar->start); |
||
269 | |||
270 | if (listbox->scrollbar->fake_position<0) |
||
271 | { |
||
272 | listbox->scrollbar->fake_position = 0; |
||
273 | } |
||
274 | if (listbox->scrollbar->fake_position > (listbox->scrollbar->height-listbox->scrollbar->fake_size)) |
||
275 | { |
||
276 | listbox->scrollbar->fake_position = (listbox->scrollbar->height-listbox->scrollbar->fake_size); |
||
277 | } |
||
278 | |||
279 | if (oldfakepos != listbox->scrollbar->position ) |
||
280 | listbox->scrollbar->status = 1; |
||
281 | } |
||
282 | } |
||
283 | } |
||
284 | |||
285 | |||
286 | if (selected_gadget==listbox) |
||
287 | { |
||
288 | if (listbox->dragging) |
||
289 | { |
||
290 | int x, y, z; |
||
291 | |||
292 | mouse_get_pos(&x, &y, &z); |
||
293 | if (y < listbox->y1) |
||
294 | mitem = -1; |
||
295 | else |
||
296 | mitem = (y - listbox->y1)/listbox->textheight; |
||
297 | |||
298 | if ((mitem < 0) && (timer_query() > listbox->last_scrolled + 1)) |
||
299 | { |
||
300 | listbox->current_item--; |
||
301 | listbox->last_scrolled = timer_query(); |
||
302 | listbox->moved = 1; |
||
303 | } |
||
304 | |||
305 | if ((mitem >= listbox->num_items_displayed) && |
||
306 | (timer_query() > listbox->last_scrolled + 1)) |
||
307 | { |
||
308 | listbox->current_item++; |
||
309 | listbox->last_scrolled = timer_query(); |
||
310 | listbox->moved = 1; |
||
311 | } |
||
312 | |||
313 | if ((mitem>=0) && (mitem<listbox->num_items_displayed)) |
||
314 | { |
||
315 | listbox->current_item = mitem+listbox->first_item; |
||
316 | listbox->moved=1; |
||
317 | } |
||
318 | |||
319 | if (listbox->current_item <0 ) |
||
320 | listbox->current_item = 0; |
||
321 | |||
322 | if (listbox->current_item >= listbox->num_items ) |
||
323 | listbox->current_item = listbox->num_items-1; |
||
324 | |||
325 | if (listbox->current_item<listbox->first_item) |
||
326 | listbox->first_item = listbox->current_item; |
||
327 | |||
328 | if (listbox->current_item>=(listbox->first_item+listbox->num_items_displayed)) |
||
329 | listbox->first_item = listbox->current_item-listbox->num_items_displayed+1; |
||
330 | |||
331 | if (listbox->num_items <= listbox->num_items_displayed ) |
||
332 | listbox->first_item = 0; |
||
333 | else |
||
334 | { |
||
335 | oldfakepos = listbox->scrollbar->position; |
||
336 | listbox->scrollbar->position = listbox->first_item; |
||
337 | |||
338 | listbox->scrollbar->fake_position = listbox->scrollbar->position-listbox->scrollbar->start; |
||
339 | listbox->scrollbar->fake_position *= listbox->scrollbar->height-listbox->scrollbar->fake_size; |
||
340 | listbox->scrollbar->fake_position /= (listbox->scrollbar->stop-listbox->scrollbar->start); |
||
341 | |||
342 | if (listbox->scrollbar->fake_position<0) |
||
343 | { |
||
344 | listbox->scrollbar->fake_position = 0; |
||
345 | } |
||
346 | if (listbox->scrollbar->fake_position > (listbox->scrollbar->height-listbox->scrollbar->fake_size)) |
||
347 | { |
||
348 | listbox->scrollbar->fake_position = (listbox->scrollbar->height-listbox->scrollbar->fake_size); |
||
349 | } |
||
350 | |||
351 | if (oldfakepos != listbox->scrollbar->position ) |
||
352 | listbox->scrollbar->status = 1; |
||
353 | } |
||
354 | |||
355 | } |
||
356 | |||
357 | if (B1_DOUBLE_CLICKED ) |
||
358 | { |
||
359 | listbox->selected_item = listbox->current_item; |
||
360 | rval = window_event_result::handled; |
||
361 | } |
||
362 | |||
363 | } |
||
364 | |||
365 | if (listbox->moved || (listbox->selected_item > 0)) |
||
366 | { |
||
367 | rval = ui_gadget_send_event(dlg, (listbox->selected_item > 0) ? EVENT_UI_LISTBOX_SELECTED : EVENT_UI_LISTBOX_MOVED, listbox); |
||
368 | if (rval == window_event_result::ignored) |
||
369 | rval = window_event_result::handled; |
||
370 | } |
||
371 | |||
372 | return rval; |
||
373 | } |
||
374 | |||
375 | void ui_listbox_change(UI_DIALOG *, UI_GADGET_LISTBOX *listbox, uint_fast32_t numitems, const char *const *list) |
||
376 | { |
||
377 | int stop, start; |
||
378 | UI_GADGET_SCROLLBAR * scrollbar; |
||
379 | |||
380 | listbox->list = list; |
||
381 | listbox->num_items = numitems; |
||
382 | listbox->first_item = 0; |
||
383 | listbox->current_item = -1; |
||
384 | listbox->last_scrolled = timer_query(); |
||
385 | listbox->dragging = 0; |
||
386 | listbox->selected_item = -1; |
||
387 | listbox->status = 1; |
||
388 | listbox->first_item = 0; |
||
389 | listbox->current_item = listbox->old_current_item = 0; |
||
390 | listbox->moved = 0; |
||
391 | |||
392 | scrollbar = listbox->scrollbar.get(); |
||
393 | |||
394 | start=0; |
||
395 | stop= numitems - listbox->num_items_displayed; |
||
396 | |||
397 | if (stop < start) stop = start; |
||
398 | |||
399 | scrollbar->horz = 0; |
||
400 | scrollbar->start = start; |
||
401 | scrollbar->stop = stop; |
||
402 | scrollbar->fake_length = scrollbar->height; |
||
403 | scrollbar->fake_position = 0; |
||
404 | if (stop!=start) |
||
405 | scrollbar->fake_size = (listbox->num_items_displayed * scrollbar->height)/(stop-start+1+listbox->num_items_displayed); |
||
406 | else |
||
407 | scrollbar->fake_size = scrollbar->height; |
||
408 | |||
409 | if (scrollbar->fake_size < 7) scrollbar->fake_size = 7; |
||
410 | scrollbar->dragging = 0; |
||
411 | scrollbar->moved=0; |
||
412 | scrollbar->status=1; |
||
413 | |||
414 | |||
415 | } |
||
416 | |||
417 | } |