UNIXworkcode

1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 * 4 * Copyright 2014 Olaf Wintermann. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <stdarg.h> 32 33 #include "menu.h" 34 #include "button.h" 35 #include "toolkit.h" 36 #include "stock.h" 37 #include "container.h" 38 #include "../common/context.h" 39 #include "../common/menu.h" 40 #include "../common/types.h" 41 #include "../ui/window.h" 42 43 #include <cx/linked_list.h> 44 #include <cx/array_list.h> 45 46 47 static ui_menu_add_f createMenuItem[] = { 48 /* UI_MENU */ add_menu_widget, 49 /* UI_MENU_ITEM */ add_menuitem_widget, 50 /* UI_MENU_CHECK_ITEM */ add_checkitem_widget, 51 /* UI_MENU_RADIO_ITEM */ add_radioitem_widget, 52 /* UI_MENU_ITEM_LIST */ add_menuitem_list_widget, 53 /* UI_MENU_CHECKITEM_LIST */ add_menuitem_list_widget, 54 /* UI_MENU_RADIOITEM_LIST */ add_menuitem_list_widget, 55 /* UI_MENU_SEPARATOR */ add_menuseparator_widget 56 }; 57 58 void ui_create_menubar(UiObject *obj, Widget window) { 59 UiMenu *menus_begin = uic_get_menu_list(); 60 if(!menus_begin) { 61 return; 62 } 63 64 Widget menubar = XmCreateMenuBar(window, "menubar", NULL, 0); 65 XtManageChild(menubar); 66 67 UiMenu *ls = menus_begin; 68 while(ls) { 69 UiMenu *menu = ls; 70 add_menu_widget(menubar, 0, &menu->item, obj); 71 ls = (UiMenu*)ls->item.next; 72 } 73 } 74 75 void ui_add_menu_items(Widget parent, int i, UiMenu *menu, UiObject *obj) { 76 UiMenuItemI *it = menu->items_begin; 77 int index = 0; 78 while(it) { 79 createMenuItem[it->type](parent, index, it, obj); 80 it = it->next; 81 index++; 82 } 83 } 84 85 void add_menu_widget(Widget parent, int i, UiMenuItemI *item, UiObject *obj) { 86 UiMenu *menu = (UiMenu*)item; 87 Arg args[4]; 88 int n = 0; 89 90 XmString s = NULL; 91 if(menu->label) { 92 s = XmStringCreateLocalized((char*)menu->label); 93 XtSetArg(args[n], XmNlabelString, s); n++; 94 } 95 96 Widget submenu = XmVaCreateSimplePulldownMenu(parent, "menu_pulldown", i, NULL, NULL); 97 XtSetArg(args[n], XmNsubMenuId, submenu); n++; 98 Widget menuItem = XtCreateManagedWidget( 99 "menuitem", 100 xmCascadeButtonWidgetClass, 101 parent, 102 args, 103 n); 104 105 106 if(s) { 107 XmStringFree(s); 108 } 109 110 ui_add_menu_items(submenu, i, menu, obj); 111 } 112 113 void add_menuitem_widget(Widget parent, int i, UiMenuItemI *item, UiObject *obj) { 114 UiMenuItem *it = (UiMenuItem*)item; 115 116 XmString s = NULL; 117 Arg args[4]; 118 int n = 0; 119 if(it->label) { 120 s = XmStringCreateLocalized((char*)it->label); 121 XtSetArg(args[n], XmNlabelString, s); n++; 122 } 123 124 Widget mitem = XtCreateManagedWidget( 125 "menubutton", 126 xmPushButtonWidgetClass, 127 parent, 128 args, 129 n); 130 if(s) { 131 XmStringFree(s); 132 } 133 134 if(it->callback) { 135 UiEventData *eventdata = malloc(sizeof(UiEventData)); 136 eventdata->callback = it->callback; 137 eventdata->userdata = it->userdata; 138 eventdata->obj = obj; 139 eventdata->value = 0; 140 XtAddCallback( 141 mitem, 142 XmNactivateCallback, 143 (XtCallbackProc)ui_push_button_callback, 144 eventdata); 145 XtAddCallback( 146 mitem, 147 XmNdestroyCallback, 148 (XtCallbackProc)ui_destroy_eventdata, 149 eventdata); 150 } 151 152 ui_set_widget_groups(obj->ctx, mitem, it->groups); 153 } 154 155 void add_menuseparator_widget(Widget p, int i, UiMenuItemI *item, UiObject *obj) { 156 Widget s = XmCreateSeparatorGadget (p, "menuseparator", NULL, 0); 157 XtManageChild(s); 158 } 159 160 void add_checkitem_widget(Widget p, int i, UiMenuItemI *item, UiObject *obj) { 161 UiMenuCheckItem *it = (UiMenuCheckItem*)item; 162 163 Arg args[4]; 164 int n = 0; 165 XmString s = NULL; 166 if(it->label) { 167 s = XmStringCreateLocalized(it->label); 168 XtSetArg(args[n], XmNlabelString, s); n++; 169 } 170 171 //XtSetArg(args[n], XmNvisibleWhenOff, 0); n++; 172 Widget checkbox = XtCreateManagedWidget( 173 "menutogglebutton", 174 xmToggleButtonWidgetClass, 175 p, 176 args, 177 n); 178 if(s) { 179 XmStringFree(s); 180 } 181 182 ui_bind_togglebutton(obj, checkbox, it->varname, NULL, it->callback, it->userdata, 0); 183 184 ui_set_widget_groups(obj->ctx, checkbox, it->groups); 185 } 186 187 void add_radioitem_widget(Widget p, int index, UiMenuItemI *item, UiObject *obj) { 188 UiMenuRadioItem *it = (UiMenuRadioItem*)item; 189 190 Arg args[4]; 191 int n = 0; 192 XmString s = NULL; 193 if(it->label) { 194 s = XmStringCreateLocalized(it->label); 195 XtSetArg(args[n], XmNlabelString, s); n++; 196 } 197 XtSetArg(args[n], XmNindicatorType, XmONE_OF_MANY_ROUND); n++; 198 199 Widget button = XmCreateToggleButton(p, "menuradiobutton", args, n); 200 XtManageChild(button); 201 202 ui_bind_radiobutton(obj, button, NULL, it->varname, it->callback, it->userdata, 0); 203 } 204 205 void add_menuitem_list_widget(Widget p, int i, UiMenuItemI *item, UiObject *obj) { 206 UiMenuItemList *il = (UiMenuItemList*)item; 207 const CxAllocator *a = obj->ctx->allocator; 208 209 UiActiveMenuItemList *ls = cxMalloc( 210 a, 211 sizeof(UiActiveMenuItemList)); 212 ls->object = obj; 213 ls->menu = p; 214 ls->index = i; 215 ls->oldcount = 0; 216 ls->getvalue = il->getvalue; 217 ls->callback = il->callback; 218 ls->userdata = il->userdata; 219 ls->addseparator = il->addseparator; 220 221 ls->var = uic_create_var(ui_global_context(), il->varname, UI_VAR_LIST); //uic_widget_var(obj->ctx, obj->ctx, NULL, il->varname, UI_VAR_LIST); 222 UiList *list = ls->var->value; 223 224 UiObserver *observer = ui_observer_new((ui_callback)ui_update_menuitem_list, ls); 225 list->observers = ui_obsvlist_add(list->observers, observer); 226 uic_list_register_observer_destructor(obj->ctx, list, observer); 227 228 ui_update_menuitem_list(NULL, ls); 229 } 230 231 void ui_update_menuitem_list(UiEvent *event, UiActiveMenuItemList *list) { 232 XmString s = NULL; 233 Arg args[4]; 234 int n; 235 236 UiList *ls; 237 if(list->var && list->var->value) { 238 ls = list->var->value; 239 } else { 240 return; 241 } 242 243 if(list->oldcount > 0) { 244 Widget *children; 245 int nc; 246 247 XtVaGetValues( 248 list->menu, 249 XmNchildren, 250 &children, 251 XmNnumChildren, 252 &nc, 253 NULL); 254 255 for(int i=0;i<list->oldcount;i++) { 256 XtDestroyWidget(children[list->index + i]); 257 } 258 } 259 260 void* elm = ui_list_first(ls); 261 int i = 0; 262 if(elm && list->addseparator) { 263 XtSetArg(args[0], XmNpositionIndex, list->index); 264 Widget s = XmCreateSeparatorGadget(list->menu, "menuseparator", args, 1); 265 XtManageChild(s); 266 i++; 267 } 268 269 ui_getvaluefunc getvalue = list->getvalue; 270 int pos = list->index; 271 while(elm) { 272 n = 0; 273 char *label = (char*) (getvalue ? getvalue(elm, 0) : elm); 274 if(label) { 275 s = XmStringCreateLocalized(label); 276 XtSetArg(args[n], XmNlabelString, s); n++; 277 } 278 XtSetArg(args[n], XmNpositionIndex, pos+i); n++; 279 280 Widget mitem = XtCreateManagedWidget( 281 "menubutton", 282 xmPushButtonWidgetClass, 283 list->menu, 284 args, 285 n); 286 if(s) { 287 XmStringFree(s); 288 } 289 290 if(list->callback) { 291 UiEventData *eventdata = malloc(sizeof(UiEventData)); 292 eventdata->callback = list->callback; 293 eventdata->userdata = list->userdata; 294 eventdata->obj = list->object; 295 eventdata->value = 0; 296 XtAddCallback( 297 mitem, 298 XmNactivateCallback, 299 (XtCallbackProc)ui_push_button_callback, 300 eventdata); 301 XtAddCallback( 302 mitem, 303 XmNdestroyCallback, 304 (XtCallbackProc)ui_destroy_eventdata, 305 eventdata); 306 } 307 308 elm = ui_list_next(ls); 309 i++; 310 } 311 312 list->oldcount = i; 313 } 314