122 e.intval = i->get(i); |
128 e.intval = i->get(i); |
123 |
129 |
124 ui_notify_evt(i->observers, &e); |
130 ui_notify_evt(i->observers, &e); |
125 } |
131 } |
126 |
132 |
127 static UIWIDGET togglebutton_create(UiObject *obj, GtkWidget *widget, UiToggleArgs args) { |
133 static void ui_toggled_callback(GtkToggleButton *widget, UiEventData *event) { |
|
134 UiEvent e; |
|
135 e.obj = event->obj; |
|
136 e.window = event->obj->window; |
|
137 e.document = event->obj->ctx->document; |
|
138 e.eventdata = NULL; |
|
139 e.intval = gtk_toggle_button_get_active(widget); |
|
140 event->callback(&e, event->userdata); |
|
141 } |
|
142 |
|
143 void ui_setup_togglebutton( |
|
144 UiObject *obj, |
|
145 GtkWidget *togglebutton, |
|
146 const char *label, |
|
147 const char *icon, |
|
148 const char *varname, |
|
149 UiInteger *value, |
|
150 ui_callback onchange, |
|
151 void *onchangedata) |
|
152 { |
|
153 if(label) { |
|
154 gtk_button_set_label(GTK_BUTTON(togglebutton), label); |
|
155 } |
|
156 ui_button_set_icon_name(togglebutton, icon); |
|
157 |
|
158 ui_bind_togglebutton( |
|
159 obj, |
|
160 togglebutton, |
|
161 ui_toggle_button_get, |
|
162 ui_toggle_button_set, |
|
163 varname, |
|
164 value, |
|
165 (ui_toggled_func)ui_toggled_callback, |
|
166 onchange, |
|
167 onchangedata); |
|
168 } |
|
169 |
|
170 void ui_bind_togglebutton( |
|
171 UiObject *obj, |
|
172 GtkWidget *widget, |
|
173 int64_t (*getfunc)(UiInteger*), |
|
174 void (*setfunc)(UiInteger*, int64_t), |
|
175 const char *varname, |
|
176 UiInteger *value, |
|
177 void (*toggled_callback)(void*, void*), |
|
178 ui_callback onchange, |
|
179 void *onchangedata) |
|
180 { |
128 UiObject* current = uic_current_obj(obj); |
181 UiObject* current = uic_current_obj(obj); |
129 |
182 UiVar* var = uic_widget_var(obj->ctx, current->ctx, value, varname, UI_VAR_INTEGER); |
130 if(args.label) { |
|
131 gtk_button_set_label(GTK_BUTTON(widget), args.label); |
|
132 } |
|
133 ui_button_set_icon_name(widget, args.icon); |
|
134 |
|
135 UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.value, args.varname, UI_VAR_INTEGER); |
|
136 if (var) { |
183 if (var) { |
137 UiInteger* value = (UiInteger*)var->value; |
184 UiInteger* value = (UiInteger*)var->value; |
138 value->obj = widget; |
185 value->obj = widget; |
139 value->get = ui_toggle_button_get; |
186 value->get = getfunc; |
140 value->set = ui_toggle_button_set; |
187 value->set = setfunc; |
141 |
188 |
142 UiVarEventData *event = malloc(sizeof(UiVarEventData)); |
189 UiVarEventData *event = malloc(sizeof(UiVarEventData)); |
143 event->obj = obj; |
190 event->obj = obj; |
144 event->var = var; |
191 event->var = var; |
145 event->observers = NULL; |
192 event->observers = NULL; |
146 event->callback = NULL; |
193 event->callback = NULL; |
147 event->userdata = NULL; |
194 event->userdata = NULL; |
148 |
195 |
149 g_signal_connect( |
196 g_signal_connect( |
150 widget, |
197 widget, |
151 "clicked", |
198 "toggled", |
152 G_CALLBACK(ui_toggled_obs), |
199 G_CALLBACK(ui_toggled_obs), |
153 event); |
200 event); |
154 g_signal_connect( |
201 g_signal_connect( |
155 widget, |
202 widget, |
156 "destroy", |
203 "destroy", |
157 G_CALLBACK(ui_destroy_vardata), |
204 G_CALLBACK(ui_destroy_vardata), |
158 event); |
205 event); |
159 } |
206 } |
|
207 |
|
208 if(onchange) { |
|
209 UiEventData *event = malloc(sizeof(UiEventData)); |
|
210 event->obj = obj; |
|
211 event->userdata = onchangedata; |
|
212 event->callback = onchange; |
|
213 event->value = 0; |
|
214 event->customdata = NULL; |
|
215 |
|
216 g_signal_connect( |
|
217 widget, |
|
218 "toggled", |
|
219 G_CALLBACK(toggled_callback), |
|
220 event); |
|
221 g_signal_connect( |
|
222 widget, |
|
223 "destroy", |
|
224 G_CALLBACK(ui_destroy_userdata), |
|
225 event); |
|
226 } |
|
227 } |
|
228 |
|
229 static UIWIDGET togglebutton_create(UiObject *obj, GtkWidget *widget, UiToggleArgs args) { |
|
230 UiObject* current = uic_current_obj(obj); |
|
231 |
|
232 ui_setup_togglebutton(current, widget, args.label, args.icon, args.varname, args.value, args.onchange, args.onchangedata); |
160 |
233 |
161 UI_APPLY_LAYOUT1(current, args); |
234 UI_APPLY_LAYOUT1(current, args); |
162 current->container->add(current->container, widget, FALSE); |
235 current->container->add(current->container, widget, FALSE); |
163 |
236 |
164 return widget; |
237 return widget; |
180 GtkCheckButton *button = integer->obj; |
253 GtkCheckButton *button = integer->obj; |
181 integer->value = value; |
254 integer->value = value; |
182 gtk_check_button_set_active(button, value != 0 ? TRUE : FALSE); |
255 gtk_check_button_set_active(button, value != 0 ? TRUE : FALSE); |
183 } |
256 } |
184 |
257 |
|
258 static void ui_checkbox_callback(GtkCheckButton *widget, UiEventData *event) { |
|
259 UiEvent e; |
|
260 e.obj = event->obj; |
|
261 e.window = event->obj->window; |
|
262 e.document = event->obj->ctx->document; |
|
263 e.eventdata = NULL; |
|
264 e.intval = gtk_check_button_get_active(widget); |
|
265 event->callback(&e, event->userdata); |
|
266 } |
|
267 |
185 UIWIDGET ui_checkbox_create(UiObject* obj, UiToggleArgs args) { |
268 UIWIDGET ui_checkbox_create(UiObject* obj, UiToggleArgs args) { |
186 UiObject* current = uic_current_obj(obj); |
269 UiObject* current = uic_current_obj(obj); |
187 |
270 |
188 GtkWidget *widget = gtk_check_button_new_with_label(args.label); |
271 GtkWidget *widget = gtk_check_button_new_with_label(args.label); |
|
272 ui_bind_togglebutton( |
|
273 obj, |
|
274 widget, |
|
275 ui_check_button_get, |
|
276 ui_check_button_set, |
|
277 args.varname, |
|
278 args.value, |
|
279 (ui_toggled_func)ui_checkbox_callback, |
|
280 args.onchange, |
|
281 args.onchangedata); |
|
282 |
|
283 UI_APPLY_LAYOUT1(current, args); |
|
284 current->container->add(current->container, widget, FALSE); |
|
285 |
|
286 return widget; |
|
287 } |
|
288 |
|
289 #else |
|
290 UIWIDGET ui_checkbox_create(UiObject* obj, UiToggleArgs args) { |
|
291 return togglebutton_create(obj, gtk_check_button_new(), args); |
|
292 } |
|
293 #endif |
|
294 |
|
295 UIWIDGET ui_switch_create(UiObject* obj, UiToggleArgs args) { |
|
296 #ifdef UI_GTK3 |
|
297 return NULL; // TODO |
|
298 #else |
|
299 return ui_checkbox_create(obj, args); |
|
300 #endif |
|
301 } |
|
302 |
|
303 #if GTK_MAJOR_VERSION >= 4 |
|
304 #define RADIOBUTTON_NEW(group, label) gtk_check_button_new_with_label(label) |
|
305 #define RADIOBUTTON_SET_GROUP(button, group) |
|
306 #define RADIOBUTTON_GET_GROUP(button) GTK_CHECK_BUTTON(button) |
|
307 #define RADIOBUTTON_GET_ACTIVE(button) gtk_check_button_get_active(GTK_CHECK_BUTTON(button)) |
|
308 #else |
|
309 #define RADIOBUTTON_NEW(group, label) gtk_radio_button_new_with_label(group, label) |
|
310 #define RADIOBUTTON_SET_GROUP(button, group) /* noop */ |
|
311 #define RADIOBUTTON_GET_GROUP(button) gtk_radio_button_get_group(GTK_RADIO_BUTTON(button)) |
|
312 #define RADIOBUTTON_GET_ACTIVE(button) gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)) |
|
313 #endif |
|
314 |
|
315 static void radiobutton_toggled(void *widget, UiEventData *event) { |
|
316 UiEvent e; |
|
317 e.obj = event->obj; |
|
318 e.window = event->obj->window; |
|
319 e.document = event->obj->ctx->document; |
|
320 e.eventdata = NULL; |
|
321 e.intval = RADIOBUTTON_GET_ACTIVE(widget); |
|
322 event->callback(&e, event->userdata); |
|
323 } |
|
324 |
|
325 UIWIDGET ui_radiobutton_create(UiObject *obj, UiToggleArgs args) { |
|
326 UiObject* current = uic_current_obj(obj); |
|
327 |
|
328 GSList *rg = NULL; |
|
329 UiInteger *rgroup; |
189 |
330 |
190 UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.value, args.varname, UI_VAR_INTEGER); |
331 UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.value, args.varname, UI_VAR_INTEGER); |
191 if (var) { |
332 |
192 UiInteger* value = (UiInteger*)var->value; |
333 UiBool first = FALSE; |
193 value->obj = widget; |
334 if(var) { |
194 value->get = ui_check_button_get; |
335 rgroup = var->value; |
195 value->set = ui_check_button_set; |
336 rg = rgroup->obj; |
|
337 if(!rg) { |
|
338 first = TRUE; |
|
339 } |
|
340 } |
|
341 |
|
342 GtkWidget *rbutton = RADIOBUTTON_NEW(rg, args.label); |
|
343 if(rgroup) { |
|
344 #if GTK_MAJOR_VERSION >= 4 |
|
345 if(rg) { |
|
346 gtk_check_button_set_group(GTK_CHECK_BUTTON(rbutton), rg->data); |
|
347 } |
|
348 rg = g_slist_prepend(rg, rbutton); |
|
349 #else |
|
350 gtk_radio_button_set_group(GTK_RADIO_BUTTON(rbutton), rg); |
|
351 rg = gtk_radio_button_get_group(GTK_RADIO_BUTTON(rbutton)); |
|
352 #endif |
|
353 |
|
354 rgroup->obj = rg; |
|
355 rgroup->get = ui_radiobutton_get; |
|
356 rgroup->set = ui_radiobutton_set; |
|
357 |
|
358 ui_radiobutton_set(rgroup, rgroup->value); |
196 |
359 |
197 UiVarEventData *event = malloc(sizeof(UiVarEventData)); |
360 UiVarEventData *event = malloc(sizeof(UiVarEventData)); |
198 event->obj = obj; |
361 event->obj = obj; |
199 event->var = var; |
362 event->var = var; |
200 event->observers = NULL; |
363 event->observers = NULL; |
201 event->callback = NULL; |
364 event->callback = NULL; |
202 event->userdata = NULL; |
365 event->userdata = NULL; |
203 |
|
204 g_signal_connect( |
|
205 widget, |
|
206 "toggled", |
|
207 G_CALLBACK(ui_toggled_obs), |
|
208 event); |
|
209 g_signal_connect( |
|
210 widget, |
|
211 "destroy", |
|
212 G_CALLBACK(ui_destroy_vardata), |
|
213 event); |
|
214 } |
|
215 |
|
216 UI_APPLY_LAYOUT1(current, args); |
|
217 current->container->add(current->container, widget, FALSE); |
|
218 |
|
219 return widget; |
|
220 } |
|
221 |
|
222 #else |
|
223 UIWIDGET ui_checkbox_create(UiObject* obj, UiToggleArgs args) { |
|
224 return togglebutton_create(obj, gtk_check_button_new(), args); |
|
225 } |
|
226 #endif |
|
227 |
|
228 UIWIDGET ui_switch_create(UiObject* obj, UiToggleArgs args) { |
|
229 #ifdef UI_GTK3 |
|
230 return NULL; // TODO |
|
231 #else |
|
232 return ui_checkbox_create(obj, args); |
|
233 #endif |
|
234 } |
|
235 |
|
236 #if GTK_MAJOR_VERSION >= 4 |
|
237 #define RADIOBUTTON_NEW(group, label) gtk_check_button_new_with_label(label) |
|
238 #define RADIOBUTTON_SET_GROUP(button, group) |
|
239 #define RADIOBUTTON_GET_GROUP(button) GTK_CHECK_BUTTON(button) |
|
240 #else |
|
241 #define RADIOBUTTON_NEW(group, label) gtk_radio_button_new_with_label(group, label) |
|
242 #define RADIOBUTTON_SET_GROUP(button, group) /* noop */ |
|
243 #define RADIOBUTTON_GET_GROUP(button) gtk_radio_button_get_group(GTK_RADIO_BUTTON(button)) |
|
244 #endif |
|
245 |
|
246 UIWIDGET ui_radiobutton_create(UiObject *obj, UiToggleArgs args) { |
|
247 UiObject* current = uic_current_obj(obj); |
|
248 |
|
249 GSList *rg = NULL; |
|
250 UiInteger *rgroup; |
|
251 |
|
252 UiVar* var = NULL; |
|
253 if (args.value) { |
|
254 var = uic_create_value_var(current->ctx, args.value); |
|
255 } else if (args.varname) { |
|
256 var = uic_create_var(obj->ctx, args.varname, UI_VAR_INTEGER); |
|
257 } |
|
258 |
|
259 UiBool first = FALSE; |
|
260 if(var) { |
|
261 rgroup = var->value; |
|
262 rg = rgroup->obj; |
|
263 if(!rg) { |
|
264 first = TRUE; |
|
265 } |
|
266 } |
|
267 |
|
268 GtkWidget *rbutton = RADIOBUTTON_NEW(rg, args.label); |
|
269 if(rgroup) { |
|
270 #if GTK_MAJOR_VERSION >= 4 |
|
271 if(rg) { |
|
272 gtk_check_button_set_group(GTK_CHECK_BUTTON(rbutton), rg->data); |
|
273 } |
|
274 rg = g_slist_prepend(rg, rbutton); |
|
275 #else |
|
276 gtk_radio_button_set_group(GTK_RADIO_BUTTON(rbutton), rg); |
|
277 rg = gtk_radio_button_get_group(GTK_RADIO_BUTTON(rbutton)); |
|
278 #endif |
|
279 |
|
280 rgroup->obj = rg; |
|
281 rgroup->get = ui_radiobutton_get; |
|
282 rgroup->set = ui_radiobutton_set; |
|
283 |
|
284 ui_radiobutton_set(rgroup, rgroup->value); |
|
285 |
|
286 UiVarEventData *event = malloc(sizeof(UiVarEventData)); |
|
287 event->obj = obj; |
|
288 event->var = var; |
|
289 event->observers = NULL; |
|
290 event->callback = NULL; |
|
291 event->userdata = NULL; |
|
292 |
366 |
293 g_signal_connect( |
367 g_signal_connect( |
294 rbutton, |
368 rbutton, |
295 "toggled", |
369 "toggled", |
296 G_CALLBACK(ui_radio_obs), |
370 G_CALLBACK(ui_radio_obs), |