ui/win32/menu.c

changeset 1060
74bed80a0503
parent 1059
226140134594
equal deleted inserted replaced
1059:226140134594 1060:74bed80a0503
52 while (menu) { 52 while (menu) {
53 ui_add_menu(hMenu, 0, &menu->item, obj); 53 ui_add_menu(hMenu, 0, &menu->item, obj);
54 UiMenuItemI *next = menu->item.next; 54 UiMenuItemI *next = menu->item.next;
55 menu = next && next->type == UI_MENU ? (UiMenu*)next : NULL; 55 menu = next && next->type == UI_MENU ? (UiMenu*)next : NULL;
56 } 56 }
57
58 57
59 return hMenu; 58 return hMenu;
60 } 59 }
61 60
62 void ui_add_menu(HMENU parent, int pos, UiMenuItemI *item, UiObject *obj) { 61 void ui_add_menu(HMENU parent, int pos, UiMenuItemI *item, UiObject *obj) {
257 menu_stateitem_update(item); 256 menu_stateitem_update(item);
258 } 257 }
259 } 258 }
260 } 259 }
261 260
261 static void menuitem_list_remove_binding(void *obj) {
262 UiActiveMenuItemList *ls = obj;
263 UiList *list = ls->var->value;
264 CxList *bindings = list->obj;
265 if(bindings) {
266 (void)cxListFindRemove(bindings, obj);
267 if(cxListSize(bindings) == 0) {
268 cxListFree(bindings);
269 list->obj = NULL;
270 list->update = NULL;
271 }
272 }
273 }
274
262 void ui_add_menu_list(HMENU parent, int pos, UiMenuItemI *item, UiObject *obj) { 275 void ui_add_menu_list(HMENU parent, int pos, UiMenuItemI *item, UiObject *obj) {
263 276 UiMenuItemList *il = (UiMenuItemList*)item;
264 } 277 const CxAllocator *a = obj->ctx->allocator;
278
279 UiVar *var = uic_create_var(ui_global_context(), il->varname, UI_VAR_LIST);
280 if (!var) {
281 return;
282 }
283
284 UiActiveMenuItemList *ls = cxMalloc(
285 a,
286 sizeof(UiActiveMenuItemList));
287 ls->object = obj;
288 ls->menu = parent;
289 ls->command_ids = cxArrayListCreate(a, sizeof(uint64_t), 16);
290 ls->index = pos;
291 ls->getvalue = il->getvalue;
292 ls->callback = il->callback;
293 ls->userdata = il->userdata;
294 ls->addseparator = il->addseparator;
295 ls->var = var;
296
297 UiList *list = ls->var->value;
298 list->update = ui_menulist_update;
299 list->getselection = NULL;
300 list->setselection = NULL;
301
302 // It is possible, that the UiVar is from a global shared context,
303 // used by multiple windows. To support this usecase, the list->obj
304 // binding object is a list of all connected UiActiveMenuItemList.
305 CxList *bindings = list->obj;
306 if(!bindings) {
307 bindings = cxLinkedListCreate(ls->var->from_ctx->mp->allocator, CX_STORE_POINTERS);
308 list->obj = bindings;
309 }
310 cxListAdd(bindings, ls);
311
312 // The destruction of the toplevel obj must remove the menulist binding
313 uic_context_add_destructor(obj->ctx, menuitem_list_remove_binding, ls);
314
315 ui_update_menuitem_list(ls);
316 }
317
318 void ui_menulist_update(UiList *list, int ignored) {
319 CxList *bindings = list->obj;
320 CxIterator i = cxListIterator(bindings);
321 cx_foreach(UiActiveMenuItemList *, ls, i) {
322 ui_update_menuitem_list(ls);
323 }
324 }
325
326 void ui_update_menuitem_list(UiActiveMenuItemList *list) {
327 UiObject *obj = list->object;
328
329 UiList *ls;
330 if(list->var && list->var->value) {
331 ls = list->var->value;
332 } else {
333 return;
334 }
335
336 CxIterator i = cxListIterator(list->command_ids);
337 cx_foreach(uint64_t *, id, i) {
338 DeleteMenu(list->menu, *id, MF_BYCOMMAND);
339 }
340 cxListClear(list->command_ids); // TODO: we could reuse some of the ids
341
342 ui_getvaluefunc getvalue = list->getvalue;
343 void* elm = ui_list_first(ls);
344
345 int pos = list->index;
346 while(elm) {
347 char *label = (char*) (getvalue ? getvalue(elm, 0) : elm);
348 if (!label) {
349 label = "";
350 }
351
352 uint64_t id = ++obj->ctx->command_id_counter;
353 InsertMenu(list->menu, pos++, MF_STRING, id, label);
354 cxListAdd(list->command_ids, &id);
355
356 elm = ui_list_next(ls);
357 }
358 }
359
265 360
266 void ui_add_menu_checklist(HMENU parent, int pos, UiMenuItemI *item, UiObject *obj) { 361 void ui_add_menu_checklist(HMENU parent, int pos, UiMenuItemI *item, UiObject *obj) {
267 362
268 } 363 }
269 364

mercurial