add existing code (build system, libs, initial mizucp code)
[mizunara.git] / ui / gtk / button.c
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
32 #include "button.h"
33 #include "container.h"
34 #include <ucx/mempool.h>
35 #include "../common/context.h"
36 #include "../common/object.h"
37
38 UIWIDGET ui_button(UiObject *obj, char *label, ui_callback f, void *data) {
39     GtkWidget *button = gtk_button_new_with_label(label);
40     
41     if(f) {
42         UiEventData *event = malloc(sizeof(UiEventData));
43         event->obj = obj;
44         event->userdata = data;
45         event->callback = f;
46         event->value = 0;
47
48         g_signal_connect(
49                 button,
50                 "clicked",
51                 G_CALLBACK(ui_button_clicked),
52                 event);
53         g_signal_connect(
54                 button,
55                 "destroy",
56                 G_CALLBACK(ui_destroy_userdata),
57                 event);
58     }
59     
60     UiContainer *ct = uic_get_current_container(obj);
61     ct->add(ct, button, FALSE);
62     
63     return button;
64 }
65
66
67 void ui_button_clicked(GtkWidget *widget, UiEventData *event) {
68     UiEvent e;
69     e.obj = event->obj;
70     e.window = event->obj->window;
71     e.document = event->obj->ctx->document;
72     e.eventdata = NULL;
73     e.intval = event->value;
74     event->callback(&e, event->userdata);
75 }
76
77 int64_t ui_toggle_button_get(UiInteger *integer) {
78     GtkToggleButton *button = integer->obj;
79     integer->value = (int)gtk_toggle_button_get_active(button);
80     return integer->value;
81 }
82
83 void ui_toggle_button_set(UiInteger *integer, int64_t value) {
84     GtkToggleButton *button = integer->obj;
85     integer->value = value;
86     gtk_toggle_button_set_active(button, value != 0 ? TRUE : FALSE);
87 }
88
89 void ui_toggled_obs(GtkToggleToolButton *widget, UiVarEventData *event) {
90     UiEvent e;
91     e.obj = event->obj;
92     e.window = event->obj->window;
93     e.document = event->obj->ctx->document;
94     e.eventdata = event->var->value;
95     e.intval = gtk_toggle_tool_button_get_active(widget);
96     
97     UiInteger *i = event->var->value;
98     ui_notify_evt(i->observers, &e);
99 }
100
101 UIWIDGET ui_checkbox_var(UiObject *obj, char *label, UiVar *var) {
102     GtkWidget *button = gtk_check_button_new_with_label(label);
103     
104     // bind value
105     if(var) {
106         UiInteger *value = var->value;
107         value->obj = GTK_TOGGLE_BUTTON(button);
108         value->get = ui_toggle_button_get;
109         value->set = ui_toggle_button_set;
110         gtk_toggle_button_set_active(value->obj, value->value);
111         
112         UiVarEventData *event = malloc(sizeof(UiVarEventData));
113         event->obj = obj;
114         event->var = var;
115         event->observers = NULL;
116
117         g_signal_connect(
118                 button,
119                 "clicked",
120                 G_CALLBACK(ui_toggled_obs),
121                 event);
122         g_signal_connect(
123                 button,
124                 "destroy",
125                 G_CALLBACK(ui_destroy_vardata),
126                 event);
127     }
128     
129     UiContainer *ct = uic_get_current_container(obj);
130     ct->add(ct, button, FALSE);
131     
132     return button;
133 }
134
135 UIWIDGET ui_checkbox(UiObject *obj, char *label, UiInteger *value) {
136     UiVar *var = NULL;
137     if(value) {
138         var = malloc(sizeof(UiVar));
139         var->value = value;
140         var->type = UI_VAR_SPECIAL;
141     }
142     return ui_checkbox_var(obj, label, var);
143 }
144
145 UIWIDGET ui_checkbox_nv(UiObject *obj, char *label, char *varname) {
146     UiVar *var = uic_create_var(obj->ctx, varname, UI_VAR_INTEGER);
147     return ui_checkbox_var(obj, label, var);
148 }
149
150
151 UIWIDGET ui_radiobutton_var(UiObject *obj, char *label, UiVar *var) {
152     GSList *rg = NULL;
153     UiInteger *rgroup;
154     
155     if(var) {
156         rgroup = var->value;
157         rg = rgroup->obj;
158     }
159     
160     GtkWidget *rbutton = gtk_radio_button_new_with_label(rg, label);
161     rg = gtk_radio_button_get_group(GTK_RADIO_BUTTON(rbutton));
162     
163     if(rgroup) {
164         rgroup->obj = rg;
165         rgroup->get = ui_radiobutton_get;
166         rgroup->set = ui_radiobutton_set;
167         
168         ui_radiobutton_set(rgroup, rgroup->value);
169         
170         UiVarEventData *event = malloc(sizeof(UiVarEventData));
171         event->obj = obj;
172         event->var = var;
173         event->observers = NULL;
174         
175         g_signal_connect(
176                 rbutton,
177                 "clicked",
178                 G_CALLBACK(ui_radio_obs),
179                 event);
180         g_signal_connect(
181                 rbutton,
182                 "destroy",
183                 G_CALLBACK(ui_destroy_vardata),
184                 event);
185     }
186     
187     UiContainer *ct = uic_get_current_container(obj);
188     ct->add(ct, rbutton, FALSE);
189     
190     return rbutton;
191 }
192
193 UIWIDGET ui_radiobutton(UiObject *obj, char *label, UiInteger *rgroup) {
194     UiVar *var = NULL;
195     if(rgroup) {
196         var = malloc(sizeof(UiVar));
197         var->value = rgroup;
198         var->type = UI_VAR_SPECIAL;
199     }
200     return ui_radiobutton_var(obj, label, var);
201 }
202
203 UIWIDGET ui_radiobutton_nv(UiObject *obj, char *label, char *varname) {
204     UiVar *var = uic_create_var(obj->ctx, varname, UI_VAR_INTEGER);
205     return ui_radiobutton_var(obj, label, var);
206 }
207
208 void ui_radio_obs(GtkToggleToolButton *widget, UiVarEventData *event) {
209     UiInteger *i = event->var->value;
210     
211     UiEvent e;
212     e.obj = event->obj;
213     e.window = event->obj->window;
214     e.document = event->obj->ctx->document;
215     e.eventdata = NULL;
216     e.intval = i->get(i);
217     
218     ui_notify_evt(i->observers, &e);
219 }
220
221 int64_t ui_radiobutton_get(UiInteger *value) {
222     int selection = 0;
223     GSList *ls = value->obj;
224     int i = 0;
225     guint len = g_slist_length(ls);
226     while(ls) {
227         if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ls->data))) {
228             selection = len - i - 1;
229             break;
230         }
231         ls = ls->next;
232         i++;
233     }
234     
235     value->value = selection;
236     return selection;
237 }
238
239 void ui_radiobutton_set(UiInteger *value, int64_t i) {
240     GSList *ls = value->obj;
241     int s = g_slist_length(ls) - 1 - i;
242     int j = 0;
243     while(ls) {
244         if(j == s) {
245             gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ls->data), TRUE);
246             break;
247         }
248         ls = ls->next;
249         j++;
250     }
251     
252     value->value = i;
253 }
254