X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=instimg;a=blobdiff_plain;f=src%2Fwidgets.c;h=9ae4c1ed6bbdcb25c6c7553f576aecdab0b7b7b9;hp=2ad99839ba307f6fd653273fc949cd3081fbb4df;hb=c81bf22901960cf05babbb157272d784f47a18f6;hpb=9f8f8c6cde6f5d9174aa8bc88f530436aecb70d9 diff --git a/src/widgets.c b/src/widgets.c index 2ad9983..9ae4c1e 100644 --- a/src/widgets.c +++ b/src/widgets.c @@ -3,8 +3,11 @@ #include #include #include +#include #include "widgets.h" +#define WIN_STYLE WS_OVERLAPPEDWINDOW & ~WS_THICKFRAME + struct wgt_window { HWND handle; struct wgt_rect rect; @@ -12,6 +15,9 @@ struct wgt_window { HDC dc; char cname[32]; struct wgt_widget *wlist; + + int close_quit; + int (*cb_close)(struct wgt_window*); }; struct wgt_widget { @@ -34,6 +40,28 @@ struct wgt_widget { static LRESULT WINAPI event_handler(HWND win, unsigned int msg, WPARAM wparam, LPARAM lparam); static struct wgt_widget *find_widget(struct wgt_window *win, HWND handle); + +void *wgt_window_handle(struct wgt_window *win) +{ + return win->handle; +} + +void *wgt_widget_handle(struct wgt_widget *w) +{ + return w->handle; +} + +unsigned int wgt_window_xid(struct wgt_window *win) +{ + return 0; +} + +unsigned int wgt_widget_xid(struct wgt_widget *w) +{ + return 0; +} + + struct wgt_window *wgt_window(const char *title, int width, int height) { struct wgt_window *win; @@ -43,11 +71,11 @@ struct wgt_window *wgt_window(const char *title, int width, int height) DWORD err; RECT rect; - if(!(win = malloc(sizeof *win))) { + if(!(win = calloc(1, sizeof *win))) { fprintf(stderr, "wgl_create_window: failed to allocate window structure\n"); return 0; } - win->wlist = 0; + win->close_quit = 1; /* by default quit when the window closes */ tlen = strlen(title); if(tlen > sizeof win->cname - 10) { @@ -72,8 +100,14 @@ struct wgt_window *wgt_window(const char *title, int width, int height) return 0; } - if(!(win->handle = CreateWindow(win->cname, title, WS_OVERLAPPEDWINDOW, - CW_USEDEFAULT, CW_USEDEFAULT, width, height, 0, 0, hinst, 0))) { + rect.left = rect.top = 0; + rect.right = width; + rect.bottom = height; + AdjustWindowRect(&rect, WIN_STYLE, FALSE); + + if(!(win->handle = CreateWindow(win->cname, title, WIN_STYLE, CW_USEDEFAULT, + CW_USEDEFAULT, rect.right - rect.left, rect.bottom - rect.top, + 0, 0, hinst, 0))) { fprintf(stderr, "wgt_create_window: failed to create window\n"); UnregisterClass(title, hinst); return 0; @@ -107,10 +141,16 @@ void wgt_destroy_window(struct wgt_window *win) free(w); } - ReleaseDC(win->handle, win->dc); - DestroyWindow(win->handle); - UnregisterClass(win->cname, GetModuleHandle(0)); + if(win->handle) { + ReleaseDC(win->handle, win->dc); + DestroyWindow(win->handle); + UnregisterClass(win->cname, GetModuleHandle(0)); + } +} +void wgt_free_window(struct wgt_window *win) +{ + wgt_destroy_window(win); free(win); } @@ -120,6 +160,34 @@ void wgt_destroy_widget(struct wgt_widget *w) free(w->itemlist); } +void wgt_resize_window(struct wgt_window *win, int width, int height) +{ + RECT rect; + + win->rect.width = width; + win->rect.height = height; + + rect.left = win->rect.x; + rect.top = win->rect.y; + rect.right = rect.left + width; + rect.bottom = rect.top + height; + if(AdjustWindowRect(&rect, WIN_STYLE, FALSE)) { + width = rect.right - rect.left; + height = rect.bottom - rect.top; + } + MoveWindow(win->handle, win->rect.x, win->rect.y, width, height, TRUE); +} + +void wgt_quit_on_close(struct wgt_window *win, int quit) +{ + win->close_quit = quit; +} + +void wgt_close_action(struct wgt_window *win, int (*func)(struct wgt_window*)) +{ + win->cb_close = func; +} + void wgt_enable_widget(struct wgt_widget *w) { w->disabled = 0; @@ -150,6 +218,20 @@ struct wgt_rect *wgt_widget_rect(struct wgt_widget *w, struct wgt_rect *rect) return &w->rect; } +void wgt_move_widget(struct wgt_widget *w, int x, int y) +{ + MoveWindow(w->handle, x, y, w->rect.width, w->rect.height, TRUE); + w->rect.x = x; + w->rect.y = y; +} + +void wgt_resize_widget(struct wgt_widget *w, int width, int height) +{ + MoveWindow(w->handle, w->rect.x, w->rect.y, width, height, TRUE); + w->rect.width = width; + w->rect.height = height; +} + int wgt_xpos_after(struct wgt_widget *w, int pad) { if(pad == WGT_AUTO) { @@ -273,6 +355,7 @@ struct wgt_widget *wgt_checkbox(struct wgt_window *win, const char *text, int on free(w); return 0; } + SendMessage(w->handle, BM_SETCHECK, on ? BST_CHECKED : BST_UNCHECKED, 0); w->rect.x = x; w->rect.y = y; @@ -285,35 +368,44 @@ struct wgt_widget *wgt_checkbox(struct wgt_window *win, const char *text, int on return w; } -static void combosize(struct wgt_window *win, const char **items, int num_items, +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, max_height, sum_height; + 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; - max_height = height < 0 && height != WGT_AUTO ? -height : textsz.height; - sum_height = num_items ? 0 : max_height; - for(i=0; i max_width) max_width = textsz.width; - if(textsz.height > max_height) max_height = textsz.height; - sum_height += textsz.height; + /* 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(width < 0) width = max_width * 3 / 2; - if(height < 0) height = sum_height * 2; + if(height < 0) height = sum_height; sz->width = width; - sz->y = max_height; 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, res; struct wgt_widget *w; struct wgt_rect rect; @@ -323,36 +415,22 @@ 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"); - free(w); - return 0; - } - - combosize(win, items, num_items, width, height, &rect); - if(!(w->handle = CreateWindow("COMBOBOX", items[0] ? items[0] : "", WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | CBS_HASSTRINGS, - x, y, rect.width, rect.height, win->handle, 0, GetModuleHandle(0), 0))) { + x, y, 16, 16, win->handle, 0, GetModuleHandle(0), 0))) { fprintf(stderr, "wgt_combo: failed to create window\n"); free(w); return 0; } - 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"); - } - } - w->num_items = num_items; + 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); + + wgt_combo_setitems(w, items, num_items); if(sel < 0) sel = 0; if(sel >= num_items) sel = num_items - 1; @@ -360,17 +438,62 @@ struct wgt_widget *wgt_combo(struct wgt_window *win, const char **items, int num SendMessage(w->handle, CB_SETCURSEL, sel, 0); } + w->cb_modify = modfunc; + w->next = win->wlist; + win->wlist = w; + return w; +} + +struct wgt_widget *wgt_progbar(struct wgt_window *win, int x, int y, int width, int height, int p) +{ + struct wgt_widget *w; + INITCOMMONCONTROLSEX commctrl; + + commctrl.dwSize = sizeof commctrl; + commctrl.dwICC = ICC_PROGRESS_CLASS; + InitCommonControlsEx(&commctrl); + + if(!(w = calloc(1, sizeof *w))) { + fprintf(stderr, "wgt_progbar: failed to allocate widget structure\n"); + return 0; + } + w->win = win; + + if(height < 0) { + height = GetSystemMetrics(SM_CYVSCROLL); + } + + if(!(w->handle = CreateWindow(PROGRESS_CLASS, 0, WS_CHILD | WS_VISIBLE, x, y, + width, height, win->handle, 0, GetModuleHandle(0), 0))) { + fprintf(stderr, "wgt_progbar: failed to create window\n"); + free(w); + return 0; + } + + /* + SendMessage(w->handle, PBM_SETRANGE, 0, MAKELPARAM(0, 100)); + SendMessage(w->handle, PBM_SETSTEP, 1, 0); + */ + SendMessage(w->handle, PBM_SETPOS, p, 0); + w->rect.x = x; w->rect.y = y; - w->rect.width = rect.width; - w->rect.height = rect.y; /* single line height for layout purposes */ + w->rect.width = width; + w->rect.height = height; - w->cb_modify = modfunc; w->next = win->wlist; win->wlist = w; return w; } +void wgt_set_text(struct wgt_widget *w, const char *text) +{ + SendMessage(w->handle, WM_SETTEXT, 0, (long)text); + + w->rect.width = wgt_string_size(w->win, text, 0); + MoveWindow(w->handle, w->rect.x, w->rect.y, w->rect.width, w->rect.height, TRUE); +} + void wgt_checkbox_check(struct wgt_widget *w) { SendMessage(w->handle, BM_SETCHECK, BST_CHECKED, 0); @@ -420,8 +543,10 @@ int wgt_combo_setitems(struct wgt_widget *w, const char **items, int num_items) SendMessage(w->handle, CB_ADDSTRING, 0, (long)w->itemlist[i]); } - combosize(w->win, items, num_items, w->rect.width, WGT_AUTO, &size); + 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); + + SendMessage(w->handle, CB_SETCURSEL, 0, 0); return 0; } @@ -440,6 +565,11 @@ const char *wgt_get_combo_item(struct wgt_widget *w, int idx) return w->itemlist[idx]; } +void wgt_set_progress(struct wgt_widget *w, int p) +{ + SendMessage(w->handle, PBM_SETPOS, p, 0); +} + static LRESULT WINAPI event_handler(HWND wnd, unsigned int msg, WPARAM wparam, LPARAM lparam) { int ncode; @@ -450,8 +580,22 @@ static LRESULT WINAPI event_handler(HWND wnd, unsigned int msg, WPARAM wparam, L switch(msg) { case WM_CLOSE: + if(!win->cb_close || win->cb_close(win)) { + if(win) { + int quit = win->close_quit; + wgt_destroy_window(win); + memset(win, 0, sizeof *win); + win->close_quit = quit; + } else { + DestroyWindow(wnd); + } + } + break; + case WM_DESTROY: - PostQuitMessage(0); + if(win && win->close_quit) { + PostQuitMessage(0); + } break; case WM_COMMAND: