|
|
| Gui question: creating Lists with multiple columns in Allegro. |
|
Wind Scar
Member #9,680
April 2008
|
Not much to say: is it possible? |
|
Timorg
Member #2,028
March 2002
|
With the allegro gui, anything is possible, just might take a bit of effort. It depends if you want movable columns. You will probably also want to have call backs to sort the data by the clicked column head. So you will have your dp field pointing to a struct of information, because d1 and d2 are probably going to be used for scrolling. ____________________________________________________________________________________________ |
|
Elias
Member #358
May 2000
|
Quote: Not much to say: is it possible? Short answer: No. Longer answer: As Timorg said, but it will be more work than writing a complete GUI from scratch. -- |
|
Johan Halmén
Member #1,550
September 2001
|
Well, there is more to say. Should this list be a part of a bigger dialog with other items (Ok, Cancel...)? Is it meant to be just info? Is it meant that the user picks one data field or a line? Should the user be able to choose several lines? The simpler it is, the more I would lean to Allegro gui (that's just me, I do everything gui related with Allegro gui). ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|
Timorg
Member #2,028
March 2002
|
It took just over an hour (aka 2 hours) [img http://www.allegro.cc/files/attachment/597080] There is two data structures, one that holds the headings and the column widths of the table, the other contains the table data and number of rows. A pointer to the headings struct goes in dp, and the data goes in dp2. For the list (d_column_proc), Scrolling up and down works with the mouse wheel and cursor keys. You can click and select rows. d1 holds the selected row, d2 holds how far the list has been scrolled down. For the header (d_header_proc), you can click and drag the dividers and when you release the mouse, the table updates to match. But there is problems... The allegro gui actually isn't that bad to use, and it was less than a couple of hours work to put this together. Learning the allegro gui is the tricky bit, but in a lot of ways it makes more sense than directly writing win32 gui app. If anyone has any thoughts or comments let me know... Anyway, on to the code: 1#include <allegro.h>
2
3typedef struct
4{
5 int cols;
6 int *widths;
7 char **headings;
8} columns;
9
10typedef struct
11{
12 int rows;
13 char **data;
14} columns_data;
15
16int sizes[] = {45, 200, 150};
17char *titles[] = {"Rank", "Name", "Score"};
18
19char *strings[] =
20{
21 "1", "maxpowermax", "5,275",
22 "2", "buckeyebob137", "3,695",
23 "3", "sherellej", "3,528",
24 "4", "flosset", "3,450",
25 "5", "chaotica_7", "2,664",
26 "6", "gilvilpa", "2,651",
27 "7", "abc520911", "2,613",
28 "8", "flaming_angel", "2,335",
29 "9", "bradley1221", "2,156",
30 "10", "11milan11", "2,091",
31 "11", "shaye2990", "2,040",
32 "12", "miss_ii", "2,008",
33 "13", "superboomerang", "1,947",
34 "14", "subway_monkey", "1,787",
35 "15", "beatriz_ry10_94", "1,757",
36 "16", "d1a9r9k0knight", "1,651",
37 "17", "aaron123456123456", "1,587",
38 "18", "debbie197033", "1,437",
39 "19", "gattoluna", "1,343",
40 "20", "aciddeath1989", "1,332",
41 "21", "jason_goh_tw", "1,328",
42 "22", "_jonathan1197_57", "1,305",
43 "23", "cloudy_33", "1,261",
44 "24", "sonic4_2_0", "1,248",
45 "25", "nebon", "1,239",
46 "26", "_i_95_saac_8", "1,235",
47 "27", "janicy520", "1,230",
48 "28", "goyoman1998", "1,229",
49 "29", "wafflehunter96", "1,203",
50 "30", "kennyk12", "1,197"
51};
52
53int d_column_proc(int msg, DIALOG *d, int c)
54{
55 columns *col = d->dp;
56 columns_data *cold = d->dp2;
57
58 int shown_rows = (d->h - 2) / text_height(font);
59 int unshown_rows = cold->rows - shown_rows;
60
61 int s = ((float)shown_rows) / cold->rows * d->h;
62
63 if (msg == MSG_WANTFOCUS)
64 return D_WANTFOCUS;
65 if (msg == MSG_DRAW)
66 {
67
68 BITMAP *buffer = gui_get_screen();
69 set_clip_rect(buffer, d->x, d->y, d->x + d->w, d->y + d->h);
70 rectfill(buffer, d->x, d->y, d->x + d->w, d->y + d->h, d->bg);
71
72 int x, y;
73 for (y = d->d2; y < cold->rows; y++)
74 {
75 if (y == d->d1)
76 {
77 if (unshown_rows > 0)
78 {
79 rectfill(buffer, d->x, d->y + (y - d->d2) * text_height(font) + 1, d->x + d->w - 11, d->y + (y - d->d2 + 1) * text_height(font) + 2, d->fg);
80 }
81 else
82 {
83 rectfill(buffer, d->x, d->y + (y - d->d2) * text_height(font) + 1, d->x + d->w, d->y + (y - d->d2 + 1) * text_height(font) + 2, d->fg);
84 }
85 }
86 int wtotal = 0;
87 for (x = 0; x < col->cols; x++)
88 {
89 char *str = cold->data[y * col->cols + x];
90 if (y != d->d1)
91 textout_ex(buffer, font, str, d->x + wtotal + 2, 2 + d->y + (y - d->d2) * text_height(font), d->fg, d->bg);
92 else
93 textout_ex(buffer, font, str, d->x + wtotal + 2, 2 + d->y + (y - d->d2) * text_height(font), d->bg, d->fg);
94 wtotal += col->widths[x];
95 }
96 }
97
98 if (unshown_rows > 0)
99 {
100 rect(buffer, d->x + d->w, d->y, d->x + d->w - 10, d->y + d->h, d->fg);
101 int p = ((float)d->d2) / cold->rows * d->h;
102 rectfill(buffer, d->x + d->w, d->y + p, d->x + d->w - 10, d->y + s + p, d->fg);
103 }
104 rect(buffer, d->x, d->y, d->x + d->w, d->y + d->h, d->fg);
105
106 set_clip_rect(buffer, 0, 0, buffer->w - 1, buffer->h - 1);
107 }
108 if (msg == MSG_CHAR)
109 {
110 int sc = 0xFF & (c >> 8);
111 if (sc == KEY_UP)
112 {
113 if (d->d2 > 0)
114 {
115 d->d2--;
116 return D_REDRAWME;
117 }
118 }
119 if (sc == KEY_DOWN)
120 {
121 if (d->d2 < unshown_rows)
122 d->d2++;
123 return D_REDRAWME;
124 }
125 }
126
127 if (msg == MSG_WHEEL)
128 {
129 if (c > 0)
130 {
131 if ((d->d2 - c) > 0)
132 {
133 d->d2 -= c;
134 }
135 else
136 {
137 d->d2 = 0;
138 }
139 }
140 else
141 {
142 if ((d->d2 - c) < unshown_rows)
143 {
144 d->d2 -= c;
145 }
146 else
147 {
148 d->d2 = unshown_rows;
149 }
150 }
151 return D_REDRAWME;
152 }
153
154 if (msg == MSG_CLICK)
155 {
156 int mx = (gui_mouse_x() - 2) - d->x;
157 int my = (gui_mouse_y() - 2)- d->y;
158 if (unshown_rows > 0)
159 {
160 if (mx > (d->w - 10))
161 {
162 if (my < (s / 2))
163 d->d2 = 0;
164 else
165 if (my > (d->h - (s / 2)))
166 d->d2 = unshown_rows;
167 else
168 {
169 d->d2 = (((float)my) / d->h) * unshown_rows;
170 }
171 return D_REDRAWME;
172 }
173 }
174 d->d1 = d->d2 + (my / text_height(font));
175 return D_REDRAWME;
176 }
177
178 return D_O_K;
179}
180
181int d_header_proc(int msg, DIALOG *d, int c)
182{
183 columns *col = d->dp;
184
185 if (msg == MSG_WANTFOCUS)
186 return D_WANTFOCUS;
187 if (msg == MSG_DRAW)
188 {
189 BITMAP *buffer = gui_get_screen();
190 set_clip_rect(buffer, d->x, d->y, d->x + d->w, d->y + d->h);
191 rectfill(buffer, d->x, d->y, d->x + d->w, d->y + d->h, d->bg);
192 int max_cols = col->cols;
193 int wtotal = 0;
194 int x;
195 for (x = 0; x < (max_cols - 0); x++)
196 {
197 char *str = col->headings[x];
198 textout_ex(buffer, font, str, d->x + wtotal + 2, d->y + 2, d->fg, d->bg);
199 wtotal += col->widths[x];
200 if (x != (max_cols - 1))
201 vline(buffer, d->x + wtotal, d->y, d->y + d->h, d->fg);
202 }
203 rect(buffer, d->x, d->y, d->x + d->w, d->y + d->h, d->fg);
204 set_clip_rect(buffer, 0, 0, buffer->w - 1, buffer->h - 1);
205 }
206 if (msg == MSG_LPRESS)
207 {
208 int mx = gui_mouse_x() - d->x;
209 int found = 0;
210 int wtotal = col->widths[0];
211 int x;
212 for (x = 1; x < col->cols; x++)
213 {
214 if (abs(mx - wtotal) < 5)
215 {
216 found = x;
217 break;
218 }
219 wtotal += col->widths[x];
220 }
221 if (found == 0)
222 return D_O_K;
223 int sx = x - 1;
224 int ow = col->widths[sx];
225 while (gui_mouse_b())
226 {
227 int wx = (gui_mouse_x() - d->x) - mx;
228 col->widths[sx] = ow + wx;
229 d_header_proc(MSG_DRAW, d, c);
230 }
231 return D_REDRAW_ALL;
232 }
233 return D_O_K;
234}
235
236DIALOG the_dialog[] =
237{
238/* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) (dp2) (dp3) */
239 {d_clear_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL},
240 {d_header_proc, 10, 10, 400, 10, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL},
241 {d_column_proc, 10, 20, 400, 200, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL},
242 {NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL}
243};
244
245int main()
246{
247 allegro_init();
248 install_keyboard();
249 install_mouse();
250
251 set_color_depth(32);
252 set_gfx_mode(GFX_AUTODETECT_WINDOWED, 640, 480, 0, 0);
253
254 columns c = {3, sizes, titles};
255 columns_data cd = {30, strings};
256
257 set_dialog_color(the_dialog, gui_fg_color, gui_bg_color);
258
259 the_dialog[1].dp = &c;
260 the_dialog[2].dp = &c;
261 the_dialog[2].dp2 = &cd;
262
263 do_dialog(the_dialog, -1);
264 return 0;
265}
266END_OF_MAIN()
____________________________________________________________________________________________ |
|
Wind Scar
Member #9,680
April 2008
|
I was away, sorry, but thank's a lot, that looks very cool. I'm going to test it. |
|
RayHawk
Member #9,652
April 2008
|
Elias said: As Timorg said, but it will be more work than writing a complete GUI from scratch.
Eh, I'd tend to disagree with that. By using the allegro GUI, all you have to do is handle events, not send them out. However, my word isn't worth much because I've not worked with any other GUI besides web based stuff, so I'm kindof a fan of the allegro GUI, despite all it's oddities. Nice code Timorg. I'll definitely come back here if I ever need something like that. Thanks for taking the time to make that! |
|
Elias
Member #358
May 2000
|
Quote: Eh, I'd tend to disagree with that.
Well, I'm not going to prove it by writing a new GUI in under two hours now I'm actually impressed by Timorg's code, in my experience the Allegro GUI never did what I wanted it to. -- |
|
Evert
Member #794
November 2000
|
Quote: I'm actually impressed by Timorg's code, in my experience the Allegro GUI never did what I wanted it to.
Goes to show how subjective the evaluation of A4's GUI is. I've made it jump through some interesting hoops myself; it's far more capable than most of its critics claim it is (and yes, the default widgets look rather plain and ugly, but we know they're easy to replace). |
|
|