ui/win32/menu.c

changeset 118
6d0da97105d8
parent 115
e57ca2747782
equal deleted inserted replaced
117:b174e721663e 118:6d0da97105d8
26 * POSSIBILITY OF SUCH DAMAGE. 26 * POSSIBILITY OF SUCH DAMAGE.
27 */ 27 */
28 28
29 #include "menu.h" 29 #include "menu.h"
30 30
31 #include <cx/array_list.h>
32
31 static ui_menu_add_f createMenuItem[] = { 33 static ui_menu_add_f createMenuItem[] = {
32 /* UI_MENU */ ui_add_menu, 34 /* UI_MENU */ ui_add_menu,
33 /* UI_MENU_ITEM */ ui_add_menu_item, 35 /* UI_MENU_ITEM */ ui_add_menu_item,
34 /* UI_MENU_CHECK_ITEM */ ui_add_menu_checkitem, 36 /* UI_MENU_CHECK_ITEM */ ui_add_menu_checkitem,
35 /* UI_MENU_RADIO_ITEM */ ui_add_menu_radioitem, 37 /* UI_MENU_RADIO_ITEM */ ui_add_menu_radioitem,
56 58
57 void ui_add_menu(HMENU parent, int pos, UiMenuItemI *item, UiObject *obj) { 59 void ui_add_menu(HMENU parent, int pos, UiMenuItemI *item, UiObject *obj) {
58 UiMenu *menu = (UiMenu*)item; 60 UiMenu *menu = (UiMenu*)item;
59 HMENU hMenu = CreatePopupMenu(); 61 HMENU hMenu = CreatePopupMenu();
60 AppendMenu(parent, MF_POPUP, (UINT_PTR)hMenu, menu->label); 62 AppendMenu(parent, MF_POPUP, (UINT_PTR)hMenu, menu->label);
61
62 int i = 0; 63 int i = 0;
63 UiMenuItemI *child = menu->items_begin; 64 UiMenuItemI *child = menu->items_begin;
64 while (child) { 65 while (child) {
65 createMenuItem[child->type](hMenu, i++, child, obj); 66 createMenuItem[child->type](hMenu, i++, child, obj);
66 child = child->next; 67 child = child->next;
67 } 68 }
68 } 69 }
69 70
71 static void menu_item_clicked(UiObject *obj, uint64_t id, UiMenuItem *item) {
72 UiEvent event;
73 event.obj = obj;
74 event.window = obj->window;
75 event.document = obj->ctx->document;
76 event.eventdata = NULL;
77 event.eventdatatype = 0;
78 event.intval = 0;
79 event.set = 0;
80 if (item->callback) {
81 item->callback(&event, item->userdata);
82 }
83 }
84
70 void ui_add_menu_item(HMENU parent, int pos, UiMenuItemI *item, UiObject *obj) { 85 void ui_add_menu_item(HMENU parent, int pos, UiMenuItemI *item, UiObject *obj) {
86 uint64_t id = ++obj->ctx->command_id_counter;
87
71 UiMenuItem *i = (UiMenuItem*)item; 88 UiMenuItem *i = (UiMenuItem*)item;
72 AppendMenu(parent, MF_STRING, 0, i->label); 89 AppendMenu(parent, MF_STRING, id, i->label);
90
91 UiCommand cmd;
92 cmd.callback = (ui_command_func)menu_item_clicked;
93 cmd.userdata = i;
94 cxMapPut(obj->ctx->command_map, id, &cmd);
95 }
96
97 static void menu_stateitem_update(UiStateMenuItem *item) {
98 MENUITEMINFO mi = { 0 };
99 mi.cbSize = sizeof(mi);
100 mi.fMask = MIIM_STATE;
101 mi.fState = item->state ? MFS_CHECKED : MFS_UNCHECKED;
102 SetMenuItemInfo(item->menu, item->id, FALSE, &mi);
103 }
104
105 static void menu_checkitem_clicked(UiObject *obj, uint64_t id, UiStateMenuItem *item) {
106 item->state = !item->state;
107 menu_stateitem_update(item);
108
109 UiEvent event;
110 event.obj = obj;
111 event.window = obj->window;
112 event.document = obj->ctx->document;
113 event.eventdata = NULL;
114 event.eventdatatype = 0;
115 event.intval = 0;
116 event.set = 0;
117 if (item->onchange) {
118 item->onchange(&event, item->userdata);
119 }
120
121 if (item->var) {
122 UiInteger *i = item->var->value;
123 ui_notify_evt(i->observers, &event);
124 }
73 } 125 }
74 126
75 void ui_add_menu_checkitem(HMENU parent, int pos, UiMenuItemI *item, UiObject *obj) { 127 void ui_add_menu_checkitem(HMENU parent, int pos, UiMenuItemI *item, UiObject *obj) {
76 128 uint64_t id = ++obj->ctx->command_id_counter;
129
130 UiMenuCheckItem *i = (UiMenuCheckItem*)item;
131 AppendMenu(parent, MF_STRING, id, i->label);
132
133 // create an UiStateMenuItem with the same lifetime as the UiObject
134 UiStateMenuItem *sitem = ui_malloc(obj->ctx, sizeof(UiStateMenuItem));
135 memset(sitem, 0, sizeof(UiStateMenuItem));
136 sitem->obj = obj;
137 sitem->menu = parent;
138 sitem->id = id;
139 sitem->onchange = i->callback;
140 sitem->userdata = i->userdata;
141 sitem->var = uic_widget_var(obj->ctx, obj->ctx, NULL, i->varname, UI_VAR_INTEGER);
142 // bind to var
143 if (sitem->var) {
144 UiInteger *v = sitem->var->value;
145 sitem->state = v->value != 0;
146 v->obj = sitem;
147 v->get = ui_checkitem_get;
148 v->set = ui_checkitem_set;
149 }
150
151 // register command id
152 UiCommand cmd;
153 cmd.callback = (ui_command_func)menu_checkitem_clicked;
154 cmd.userdata = sitem;
155 cxMapPut(obj->ctx->command_map, id, &cmd);
156
157 menu_stateitem_update(sitem);
158 }
159
160 int64_t ui_checkitem_get(UiInteger *i) {
161 return i->value;
162 }
163
164 void ui_checkitem_set(UiInteger *i, int64_t value) {
165 i->value = value;
166 menu_stateitem_update(i->obj);
167 }
168
169 static void menu_radioitem_clicked(UiObject *obj, uint64_t id, UiStateMenuItem *item) {
170 UiInteger *i = item->var->value; // UiVar is always not NULL for radio items
171 ui_set(i, item->index+1);
172
173 UiEvent event;
174 event.obj = obj;
175 event.window = obj->window;
176 event.document = obj->ctx->document;
177 event.eventdata = i;
178 event.eventdatatype = UI_EVENT_DATA_INTEGER_VALUE;
179 event.intval = item->state;
180 event.set = ui_get_setop();
181
182 if (item->onchange) {
183 item->onchange(&event, item->userdata);
184 }
185
186 event.intval = (int)ui_get(i);
187 ui_notify_evt(i->observers, &event);
77 } 188 }
78 189
79 void ui_add_menu_radioitem(HMENU parent, int pos, UiMenuItemI *item, UiObject *obj) { 190 void ui_add_menu_radioitem(HMENU parent, int pos, UiMenuItemI *item, UiObject *obj) {
80 191 uint64_t id = ++obj->ctx->command_id_counter;
192
193 UiMenuRadioItem *i = (UiMenuRadioItem*)item;
194 AppendMenu(parent, MF_STRING, id, i->label);
195
196 UiVar *var = uic_widget_var(obj->ctx, obj->ctx, NULL, i->varname, UI_VAR_INTEGER);
197 if (!var) {
198 return; // radio item without var is useless
199 }
200
201 UiInteger *v = var->value;
202 CxList *group = v->obj;
203 if (!group) {
204 // first radio button in this group
205 group = cxArrayListCreate(obj->ctx->allocator, sizeof(UiStateMenuItem), 4);
206 v->obj = group;
207 v->get = ui_radioitem_get;
208 v->set = ui_radioitem_set;
209 }
210
211 UiStateMenuItem sitem = { 0 };
212 sitem.obj = obj;
213 sitem.menu = parent;
214 sitem.id = id;
215 sitem.onchange = i->callback;
216 sitem.userdata = i->userdata;
217 sitem.var = var;
218 sitem.index = (int)cxListSize(group);
219 cxListAdd(group, &sitem);
220
221 if (v->value == sitem.index+1) {
222 sitem.state = 1;
223 menu_stateitem_update(&sitem);
224 }
225
226
227 UiStateMenuItem *sitem_ptr = cxListAt(group, sitem.index);
228 // register command id
229 UiCommand cmd;
230 cmd.callback = (ui_command_func)menu_radioitem_clicked;
231 cmd.userdata = sitem_ptr;
232 cxMapPut(obj->ctx->command_map, id, &cmd);
233 }
234
235 int64_t ui_radioitem_get(UiInteger *i) {
236 return i->value;
237 }
238
239 void ui_radioitem_set(UiInteger *i, int64_t value) {
240 CxList *group = i->obj;
241 // de-select all items
242 CxIterator it = cxListIterator(group);
243 cx_foreach(UiStateMenuItem *, item, it) {
244 if (item->state) {
245 item->state = FALSE;
246 menu_stateitem_update(item);
247 }
248 }
249
250 if (value > 0) {
251 UiStateMenuItem *item = cxListAt(group, value-1);
252 if (item) {
253 item->state = TRUE;
254 menu_stateitem_update(item);
255 }
256 }
81 } 257 }
82 258
83 void ui_add_menu_list(HMENU parent, int pos, UiMenuItemI *item, UiObject *obj) { 259 void ui_add_menu_list(HMENU parent, int pos, UiMenuItemI *item, UiObject *obj) {
84 260
85 } 261 }

mercurial