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