X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=instimg;a=blobdiff_plain;f=src%2Fwidgets.c;h=2d37973c7101c5a2480b74affb7e93a94e51e108;hp=7796cba3e957ed6debc17da3ea1acb50d92df7f6;hb=5890e34dc52247c2ed4b9ae2f6cd5e534e3d369f;hpb=4f312c9361b1f4c63d7697e58503cd0fb8b05fff diff --git a/src/widgets.c b/src/widgets.c index 7796cba..2d37973 100644 --- a/src/widgets.c +++ b/src/widgets.c @@ -24,6 +24,8 @@ struct wgt_widget { char **itemlist; int num_items; + int disabled; + wgt_callback cb_click; wgt_callback cb_modify; }; @@ -59,7 +61,7 @@ struct wgt_window *wgt_window(const char *title, int width, int height) memset(&wc, 0, sizeof wc); wc.hInstance = hinst; - wc.hbrBackground = (HBRUSH)GetStockObject(LTGRAY_BRUSH); + wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE); wc.hCursor = LoadCursor(0, IDC_ARROW); wc.hIcon = LoadIcon(0, IDI_APPLICATION); wc.lpszClassName = win->cname; @@ -79,7 +81,7 @@ struct wgt_window *wgt_window(const char *title, int width, int height) win->dc = GetDC(win->handle); SetLastError(0); if(!SetWindowLong(win->handle, GWL_USERDATA, (long)win) && (err = GetLastError())) { - fprintf(stderr, "wgt_create_window: failed to store window user data (err: %d)\n", err); + fprintf(stderr, "wgt_create_window: failed to store window user data (err: %d)\n", (int)err); UnregisterClass(title, hinst); DestroyWindow(win->handle); return 0; @@ -118,6 +120,23 @@ void wgt_destroy_widget(struct wgt_widget *w) free(w->itemlist); } +void wgt_enable_widget(struct wgt_widget *w) +{ + w->disabled = 0; + EnableWindow(w->handle, 1); +} + +void wgt_disable_widget(struct wgt_widget *w) +{ + w->disabled = 1; + EnableWindow(w->handle, 0); +} + +int wgt_widget_enabled(struct wgt_widget *w) +{ + return !w->disabled; +} + struct wgt_window *wgt_widget_window(struct wgt_widget *w) { return w->win; @@ -232,6 +251,7 @@ struct wgt_widget *wgt_checkbox(struct wgt_window *win, const char *text, int on { struct wgt_widget *w; struct wgt_rect textsz; + int check_width; if(!(w = calloc(1, sizeof *w))) { fprintf(stderr, "wgt_checkbox: failed to allocate widget structure\n"); @@ -239,9 +259,11 @@ struct wgt_widget *wgt_checkbox(struct wgt_window *win, const char *text, int on } w->win = win; + check_width = GetSystemMetrics(SM_CXMENUCHECK); + if(width < 0 || height < 0) { wgt_string_size(win, text, &textsz); - if(width < 0) width = textsz.width + 32; /* XXX */ + if(width < 0) width = textsz.width + check_width + 10; if(height < 0) height = textsz.height; } @@ -257,18 +279,52 @@ struct wgt_widget *wgt_checkbox(struct wgt_window *win, const char *text, int on w->rect.width = width; w->rect.height = height; - w->cb_modify = modfunc; + w->cb_click = modfunc; /* BN_CLICKED is sent for checkbox state changes */ w->next = win->wlist; win->wlist = w; return w; } +static void combosize(struct wgt_window *win, HWND cbwnd, const char **items, int num_items, + int width, int height, struct wgt_rect *sz) +{ + int i, max_width, sum_height; + struct wgt_rect textsz; + + wgt_string_size(win, "00", &textsz); + max_width = width < 0 && width != WGT_AUTO ? -width : textsz.width; + + /* first get the height of the editbox */ + sum_height = SendMessage(cbwnd, CB_GETITEMHEIGHT, -1, 0); + sz->y = sum_height; + /* then add the height of the dropdown list items */ + /* XXX I can't figure out why, but it's not sufficient to show all items + * without some more height, so let's double it... + */ + sum_height *= 2; + sum_height += SendMessage(cbwnd, CB_GETITEMHEIGHT, 0, 0) * num_items; + sum_height += GetSystemMetrics(SM_CYEDGE) * 2; + + if(width < 0) { + int sbar_width; + for(i=0; i max_width) max_width = textsz.width; + } + sbar_width = GetSystemMetrics(SM_CXVSCROLL); + width = max_width + sbar_width + GetSystemMetrics(SM_CXEDGE) * 2; + } + if(height < 0) height = sum_height; + + sz->width = width; + sz->height = height; +} + struct wgt_widget *wgt_combo(struct wgt_window *win, const char **items, int num_items, int sel, int x, int y, int width, int height, wgt_callback modfunc) { - int i, max_width, max_height, sum_height, res; struct wgt_widget *w; - struct wgt_rect textsz; + struct wgt_rect rect; if(!(w = calloc(1, sizeof *w))) { fprintf(stderr, "wgt_combo: failed to allocate widget structure\n"); @@ -276,60 +332,89 @@ struct wgt_widget *wgt_combo(struct wgt_window *win, const char **items, int num } w->win = win; - if(!(w->itemlist = malloc(num_items * sizeof *w->itemlist))) { - fprintf(stderr, "wgt_combo: failed to allocate item list\n"); + if(!(w->handle = CreateWindow("COMBOBOX", items[0] ? items[0] : "", + WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | CBS_HASSTRINGS, + x, y, 16, 16, win->handle, 0, GetModuleHandle(0), 0))) { + fprintf(stderr, "wgt_combo: failed to create window\n"); free(w); return 0; } - max_width = max_height = sum_height = 0; + combosize(win, w->handle, items, num_items, width, height, &rect); + w->rect.x = x; + w->rect.y = y; + w->rect.width = rect.width; + w->rect.height = rect.y; /* single line height for layout purposes */ + MoveWindow(w->handle, x, y, rect.width, rect.height, FALSE); - for(i=0; i max_width) max_width = textsz.width; - if(textsz.height > max_height) max_height = textsz.height; - sum_height += textsz.height; + wgt_combo_setitems(w, items, num_items); + + if(sel < 0) sel = 0; + if(sel >= num_items) sel = num_items - 1; + if(sel >= 0) { + SendMessage(w->handle, CB_SETCURSEL, sel, 0); } - if(width < 0) width = max_width * 3 / 2; - if(height < 0) height = sum_height * 2; + w->cb_modify = modfunc; + w->next = win->wlist; + win->wlist = w; + return w; +} - if(!(w->handle = CreateWindow("COMBOBOX", items[0], - WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | CBS_HASSTRINGS, - x, y, width, height, win->handle, 0, GetModuleHandle(0), 0))) { - fprintf(stderr, "wgt_combo: failed to create window\n"); - free(w); - return 0; - } +void wgt_checkbox_check(struct wgt_widget *w) +{ + SendMessage(w->handle, BM_SETCHECK, BST_CHECKED, 0); +} + +void wgt_checkbox_uncheck(struct wgt_widget *w) +{ + SendMessage(w->handle, BM_SETCHECK, BST_UNCHECKED, 0); +} +int wgt_checkbox_checked(struct wgt_widget *w) +{ + return SendMessage(w->handle, BM_GETCHECK, 0, 0) == BST_CHECKED; +} + +int wgt_combo_setitems(struct wgt_widget *w, const char **items, int num_items) +{ + int i; + char **newit; + struct wgt_rect size; + + if(!(newit = malloc(num_items * sizeof *newit))) { + fprintf(stderr, "wgt_combo_setitems: failed to allocate item list\n"); + return -1; + } for(i=0; iitemlist[i] = strdup(items[i]))) { - fprintf(stderr, "wgt_combo: failed to allocate item\n"); - while(--i >= 0) free(w->itemlist[i]); - DestroyWindow(w->handle); - free(w->itemlist); - free(w); - return 0; - } - if((res = SendMessage(w->handle, CB_ADDSTRING, 0, (long)items[i])) != i) { - fprintf(stderr, "wgt_combo: failed to add item\n"); + if(!(newit[i] = strdup(items[i]))) { + fprintf(stderr, "wgt_combo_setitems: failed to allocate item\n"); + while(--i >= 0) { + free(newit[i]); + } + free(newit); + return -1; } } + + for(i=0; inum_items; i++) { + free(w->itemlist[i]); + } + free(w->itemlist); + SendMessage(w->handle, CB_RESETCONTENT, 0, 0); + + w->itemlist = newit; w->num_items = num_items; - if(sel < 0) sel = 0; - if(sel >= num_items) sel = num_items - 1; - SendMessage(w->handle, CB_SETCURSEL, sel, 0); + for(i=0; ihandle, CB_ADDSTRING, 0, (long)w->itemlist[i]); + } - w->rect.x = x; - w->rect.y = y; - w->rect.width = width; - w->rect.height = max_height; + combosize(w->win, w->handle, items, num_items, w->rect.width, WGT_AUTO, &size); + MoveWindow(w->handle, w->rect.x, w->rect.y, w->rect.width, size.height, TRUE); - w->cb_modify = modfunc; - w->next = win->wlist; - win->wlist = w; - return w; + SendMessage(w->handle, CB_SETCURSEL, 0, 0); + return 0; } int wgt_combo_selected(struct wgt_widget *w) @@ -383,7 +468,7 @@ static LRESULT WINAPI event_handler(HWND wnd, unsigned int msg, WPARAM wparam, L default: break; } - + default: return DefWindowProc(wnd, msg, wparam, lparam); } @@ -400,4 +485,4 @@ static struct wgt_widget *find_widget(struct wgt_window *win, HWND handle) w = w->next; } return 0; -} \ No newline at end of file +}