ui/gtk/toolbar.c

changeset 0
2483f517c562
child 29
3fc287f06305
equal deleted inserted replaced
-1:000000000000 0:2483f517c562
1 /*
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3 *
4 * Copyright 2017 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 <string.h>
32
33 #include "toolbar.h"
34 #include "button.h"
35 #include "image.h"
36 #include "tree.h"
37 #include <cx/basic_mempool.h>
38 #include <cx/hash_map.h>
39 #include <cx/linked_list.h>
40 #include <cx/array_list.h>
41 #include "../common/context.h"
42
43 static CxMap *toolbar_items;
44 static CxList *defaults;
45
46 void ui_toolbar_init() {
47 toolbar_items = cxHashMapCreate(cxDefaultAllocator, CX_STORE_POINTERS, 16);
48 defaults = cxLinkedListCreateSimple(CX_STORE_POINTERS);
49 }
50
51 void ui_toolitem(char *name, char *label, ui_callback f, void *udata) {
52 ui_toolitem_img(name, label, NULL, f, udata);
53 }
54
55 void ui_toolitem_st(char *name, char *stockid, ui_callback f, void *userdata) {
56 ui_toolitem_stgr(name, stockid, f, userdata, -1);
57 }
58
59 void ui_toolitem_sti(char *name, char *stockid, ui_callback f, void *userdata) {
60 ui_toolitem_stgri(name, stockid, f, userdata, -1);
61 }
62
63 void ui_toolitem_stgr(char *name, char *stockid, ui_callback f, void *userdata, ...) {
64 va_list ap;
65 va_start(ap, userdata);
66 ui_toolitem_vstgr(name, stockid, 0, f, userdata, ap);
67 va_end(ap);
68 }
69
70 void ui_toolitem_stgri(char *name, char *stockid, ui_callback f, void *userdata, ...) {
71 va_list ap;
72 va_start(ap, userdata);
73 ui_toolitem_vstgr(name, stockid, 1, f, userdata, ap);
74 va_end(ap);
75 }
76
77 void ui_toolitem_img(char *name, char *label, char *img, ui_callback f, void *udata) {
78 UiToolItem *item = malloc(sizeof(UiToolItem));
79 item->item.add_to = (ui_toolbar_add_f)add_toolitem_widget;
80 item->label = label;
81 item->image = img;
82 item->callback = f;
83 item->userdata = udata;
84 item->isimportant = 0;
85 item->groups = NULL;
86
87 cxMapPut(toolbar_items, name, item);
88 }
89
90 void ui_toolitem_vstgr(
91 char *name,
92 char *stockid,
93 int isimportant,
94 ui_callback f,
95 void *userdata,
96 va_list ap)
97 {
98 UiStToolItem *item = malloc(sizeof(UiStToolItem));
99 item->item.add_to = (ui_toolbar_add_f)add_toolitem_st_widget;
100 item->stockid = stockid;
101 item->callback = f;
102 item->userdata = userdata;
103 item->groups = NULL;
104 item->isimportant = isimportant;
105
106 // add groups
107 int group;
108 while((group = va_arg(ap, int)) != -1) {
109 if(!item->groups) {
110 item->groups = cxArrayListCreateSimple(sizeof(int), 16);
111 }
112 cxListAdd(item->groups, &group);
113 }
114
115 cxMapPut(toolbar_items, name, item);
116 }
117
118 void ui_toolitem_toggle(const char *name, const char *label, const char *img, UiInteger *i) {
119 UiToggleToolItem *item = malloc(sizeof(UiToggleToolItem));
120 item->item.add_to = (ui_toolbar_add_f)add_toolitem_toggle_widget;
121 item->label = label;
122 item->image = img;
123 item->stockid = NULL;
124 item->groups = NULL;
125 item->isimportant = 0;
126 item->value = i;
127 item->var = NULL;
128
129 cxMapPut(toolbar_items, name, item);
130 }
131
132 void ui_toolitem_toggle_st(const char *name, const char *stockid, UiInteger *i) {
133 UiToggleToolItem *item = malloc(sizeof(UiToggleToolItem));
134 item->item.add_to = (ui_toolbar_add_f)add_toolitem_toggle_widget;
135 item->label = NULL;
136 item->image = NULL;
137 item->stockid = stockid;
138 item->groups = NULL;
139 item->isimportant = 0;
140 item->value = i;
141 item->var = NULL;
142
143 cxMapPut(toolbar_items, name, item);
144 }
145
146 void ui_toolitem_toggle_nv(const char *name, const char *label, const char *img, const char *intvar) {
147 UiToggleToolItem *item = malloc(sizeof(UiToggleToolItem));
148 item->item.add_to = (ui_toolbar_add_f)add_toolitem_toggle_widget;
149 item->label = label;
150 item->image = img;
151 item->stockid = NULL;
152 item->groups = NULL;
153 item->isimportant = 0;
154 item->value = NULL;
155 item->var = intvar;
156
157 cxMapPut(toolbar_items, name, item);
158 }
159
160 void ui_toolitem_toggle_stnv(const char *name, const char *stockid, const char *intvar) {
161 UiToggleToolItem *item = malloc(sizeof(UiToggleToolItem));
162 item->item.add_to = (ui_toolbar_add_f)add_toolitem_toggle_widget;
163 item->label = NULL;
164 item->image = NULL;
165 item->stockid = stockid;
166 item->groups = NULL;
167 item->isimportant = 0;
168 item->value = NULL;
169 item->var = intvar;
170
171 cxMapPut(toolbar_items, name, item);
172 }
173
174
175 void ui_toolbar_combobox(
176 char *name,
177 UiList *list,
178 ui_getvaluefunc getvalue,
179 ui_callback f,
180 void *udata)
181 {
182 UiToolbarComboBox *cb = malloc(sizeof(UiToolbarComboBox));
183 cb->item.add_to = (ui_toolbar_add_f)add_toolbar_combobox;
184 UiVar *var = malloc(sizeof(UiVar));
185 var->value = list;
186 var->type = UI_VAR_SPECIAL;
187 var->from = NULL;
188 var->from_ctx = NULL;
189 cb->var = var;
190 cb->getvalue = getvalue;
191 cb->callback = f;
192 cb->userdata = udata;
193
194 cxMapPut(toolbar_items, name, cb);
195 }
196
197 void ui_toolbar_combobox_str(
198 char *name,
199 UiList *list,
200 ui_callback f,
201 void *udata)
202 {
203 ui_toolbar_combobox(name, list, ui_strmodel_getvalue, f, udata);
204 }
205
206 void ui_toolbar_combobox_nv(
207 char *name,
208 char *listname,
209 ui_getvaluefunc getvalue,
210 ui_callback f,
211 void *udata)
212 {
213 UiToolbarComboBoxNV *cb = malloc(sizeof(UiToolbarComboBoxNV));
214 cb->item.add_to = (ui_toolbar_add_f)add_toolbar_combobox_nv;
215 cb->listname = listname;
216 cb->getvalue = getvalue;
217 cb->callback = f;
218 cb->userdata = udata;
219
220 cxMapPut(toolbar_items, name, cb);
221 }
222
223
224 void ui_toolbar_add_default(char *name) {
225 char *s = strdup(name);
226 cxListAdd(defaults, s);
227 }
228
229 GtkWidget* ui_create_toolbar(UiObject *obj) {
230 if(!defaults) {
231 return NULL;
232 }
233
234 GtkWidget *toolbar = gtk_toolbar_new();
235 #ifdef UI_GTK3
236 gtk_style_context_add_class(
237 gtk_widget_get_style_context(toolbar),
238 GTK_STYLE_CLASS_PRIMARY_TOOLBAR);
239 #endif
240
241 GtkToolbar *tb = GTK_TOOLBAR(toolbar);
242 CxIterator i = cxListIterator(defaults);
243 cx_foreach(char *, def, i) {
244 UiToolItemI *item = cxMapGet(toolbar_items, def);
245 if(item) {
246 item->add_to(tb, item, obj);
247 } else if(!strcmp(def, "@separator")) {
248 gtk_toolbar_insert(tb, gtk_separator_tool_item_new(), -1);
249 } else {
250 fprintf(stderr, "UI Error: Unknown toolbar item: %s\n", def);
251 }
252 }
253
254 return toolbar;
255 }
256
257 void add_toolitem_widget(GtkToolbar *tb, UiToolItem *item, UiObject *obj) {
258 GtkToolItem *button = gtk_tool_button_new(NULL, item->label);
259 gtk_tool_item_set_homogeneous(button, FALSE);
260 if(item->image) {
261 GdkPixbuf *pixbuf = ui_get_image(item->image);
262 GtkWidget *image = gtk_image_new_from_pixbuf(pixbuf);
263 gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(button), image);
264 } else {
265 gtk_tool_item_set_is_important(button, TRUE);
266 }
267
268 if(item->callback) {
269 UiEventData *event = cxMalloc(
270 obj->ctx->allocator,
271 sizeof(UiEventData));
272 event->obj = obj;
273 event->userdata = item->userdata;
274 event->callback = item->callback;
275
276 g_signal_connect(
277 button,
278 "clicked",
279 G_CALLBACK(ui_button_clicked),
280 event);
281 }
282
283 gtk_toolbar_insert(tb, button, -1);
284
285 if(item->groups) {
286 uic_add_group_widget(obj->ctx, button, (ui_enablefunc)ui_set_enabled, item->groups);
287 }
288 }
289
290 void add_toolitem_st_widget(GtkToolbar *tb, UiStToolItem *item, UiObject *obj) {
291 GtkToolItem *button = gtk_tool_button_new_from_stock(item->stockid);
292 gtk_tool_item_set_homogeneous(button, FALSE);
293 if(item->isimportant) {
294 gtk_tool_item_set_is_important(button, TRUE);
295 }
296
297 if(item->callback) {
298 UiEventData *event = cxMalloc(
299 obj->ctx->allocator,
300 sizeof(UiEventData));
301 event->obj = obj;
302 event->userdata = item->userdata;
303 event->callback = item->callback;
304
305 g_signal_connect(
306 button,
307 "clicked",
308 G_CALLBACK(ui_button_clicked),
309 event);
310 }
311
312 gtk_toolbar_insert(tb, button, -1);
313
314 if(item->groups) {
315 uic_add_group_widget(obj->ctx, button, (ui_enablefunc)ui_set_enabled, item->groups);
316 }
317 }
318
319 void add_toolitem_toggle_widget(GtkToolbar *tb, UiToggleToolItem *item, UiObject *obj) {
320 GtkToolItem *button;
321 if(item->stockid) {
322 button = gtk_toggle_tool_button_new_from_stock(item->stockid);
323 } else {
324 button = gtk_toggle_tool_button_new();
325 gtk_tool_item_set_homogeneous(button, FALSE);
326 if(item->label) {
327 gtk_tool_button_set_label(GTK_TOOL_BUTTON(button), item->label);
328 }
329 if(item->image) {
330 GdkPixbuf *pixbuf = ui_get_image(item->image);
331 GtkWidget *image = gtk_image_new_from_pixbuf(pixbuf);
332 gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(button), image);
333 }
334 }
335
336 UiVar *var;
337 if(item->value) {
338 var = malloc(sizeof(UiVar));
339 var->value = item->value;
340 var->type = UI_VAR_SPECIAL;
341 var->from = NULL;
342 var->from_ctx = NULL;
343 } else {
344 var = uic_create_var(obj->ctx, item->var, UI_VAR_INTEGER);
345 }
346
347 if(var->value) {
348 UiInteger *i = var->value;
349 i->get = ui_tool_toggle_button_get;
350 i->set = ui_tool_toggle_button_set;
351 i->obj = button;
352
353 if(i->value != 0) {
354 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(button), TRUE);
355 }
356 }
357
358 // register event
359 // the event func will call the UiInteger observer callbacks
360 UiEventData *event = cxMalloc(
361 obj->ctx->allocator,
362 sizeof(UiEventData));
363 event->obj = obj;
364 event->userdata = var;
365 event->callback = NULL;
366
367 g_signal_connect(
368 button,
369 "toggled",
370 G_CALLBACK(ui_tool_button_toggled),
371 event);
372
373 // add item to toolbar
374 gtk_toolbar_insert(tb, button, -1);
375
376 if(item->groups) {
377 uic_add_group_widget(obj->ctx, button, (ui_enablefunc)ui_set_enabled, item->groups);
378 }
379 }
380
381 void ui_tool_button_toggled(GtkToggleToolButton *widget, UiEventData *event) {
382 UiEvent e;
383 e.obj = event->obj;
384 e.window = event->obj->window;
385 e.document = event->obj->ctx->document;
386 e.eventdata = NULL;
387 e.intval = gtk_toggle_tool_button_get_active(widget);
388
389 UiVar *var = event->userdata;
390 UiInteger *i = var->value;
391
392 ui_notify_evt(i->observers, &e);
393 }
394
395 int64_t ui_tool_toggle_button_get(UiInteger *integer) {
396 integer->value = gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(integer->obj));
397 return integer->value;
398 }
399
400 void ui_tool_toggle_button_set(UiInteger *integer, int64_t value) {
401 gboolean s = value != 0 ? TRUE : FALSE;
402 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(integer->obj), s);
403 integer->value = s;
404 }
405
406 void add_toolbar_combobox(GtkToolbar *tb, UiToolbarComboBox *cb, UiObject *obj) {
407 UiModel *modelinfo = ui_model(obj->ctx, UI_STRING, "", -1);
408 modelinfo->getvalue = cb->getvalue;
409 UiListModel *model = ui_list_model_new(obj, cb->var, modelinfo);
410
411 GtkWidget *combobox = ui_create_combobox(obj, model, cb->callback, cb->userdata);
412 GtkToolItem *item = gtk_tool_item_new();
413 gtk_container_add(GTK_CONTAINER(item), combobox);
414 gtk_toolbar_insert(tb, item, -1);
415 }
416
417 void add_toolbar_combobox_nv(GtkToolbar *tb, UiToolbarComboBoxNV *cb, UiObject *obj) {
418 UiVar *var = uic_create_var(obj->ctx, cb->listname, UI_VAR_LIST);
419 if(var) {
420 UiModel *modelinfo = ui_model(obj->ctx, UI_STRING, "", -1);
421 modelinfo->getvalue = cb->getvalue;
422 UiListModel *model = ui_list_model_new(obj, var, modelinfo);
423
424 GtkWidget *combobox = ui_create_combobox(obj, model, cb->callback, cb->userdata);
425 GtkToolItem *item = gtk_tool_item_new();
426 gtk_container_add(GTK_CONTAINER(item), combobox);
427 gtk_toolbar_insert(tb, item, -1);
428 }
429 }
430

mercurial