Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Gui question: creating Lists with multiple columns in Allegro.

This thread is locked; no one can reply to it. rss feed Print
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.

____________________________________________________________________________________________
[Wii: 7692-0472-6469-4203]
"c is much better than c++ if you don't need OOP simply because it's smaller and requires less load time." - alethiophile
OMG my sides are hurting from laughing so hard... :D

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.

--
"Either help out or stop whining" - Evert

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).

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This thread is obviously about nothing so heres a bunny with a pancake on its head. -kazzmir

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 click and drag for the header is blocking, so any form that uses the widget, can't be double buffered. It also flickers as the widget itself isn't double buffered, but its not a hard change to fix that.

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...
@Wind Scar: If you need help sticking this in your program let me know.

Anyway, on to the code:

#SelectExpand
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()

____________________________________________________________________________________________
[Wii: 7692-0472-6469-4203]
"c is much better than c++ if you don't need OOP simply because it's smaller and requires less load time." - alethiophile
OMG my sides are hurting from laughing so hard... :D

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
avatar

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. :D

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 :P

I'm actually impressed by Timorg's code, in my experience the Allegro GUI never did what I wanted it to.

--
"Either help out or stop whining" - Evert

Evert
Member #794
November 2000
avatar

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).

Go to: