1 /* DreamChess
2 **
3 ** DreamChess is the legal property of its developers, whose names are too
4 ** numerous to list here. Please refer to the AUTHORS.txt file distributed
5 ** with this source distribution.
6 **
7 ** This program is free software: you can redistribute it and/or modify
8 ** it under the terms of the GNU General Public License as published by
9 ** the Free Software Foundation, either version 3 of the License, or
10 ** (at your option) any later version.
11 **
12 ** This program is distributed in the hope that it will be useful,
13 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ** GNU General Public License for more details.
16 **
17 ** You should have received a copy of the GNU General Public License
18 ** along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 /** @file
22 * @brief Widget class implementation.
23 */
24
25 #include <stdlib.h>
26
27 #include <gamegui/dialog.h>
28 #include <gamegui/system.h>
29 #include <gamegui/widget.h>
30
gg_widget_get_class_id(void)31 gg_class_id gg_widget_get_class_id(void) {
32 GG_CHILD(GG_CLASS_ID_NONE)
33 }
34
gg_widget_destroy(gg_widget_t * widget)35 void gg_widget_destroy(gg_widget_t *widget) {
36 while (!TAILQ_EMPTY(&widget->callbacks)) {
37 gg_widget_cb_list_t *cb = TAILQ_FIRST(&widget->callbacks);
38 TAILQ_REMOVE(&widget->callbacks, cb, entries);
39 free(cb);
40 }
41
42 free(widget);
43 }
44
gg_set_requested_size(gg_widget_t * widget,int width,int height)45 void gg_set_requested_size(gg_widget_t *widget, int width, int height) {
46 widget->width_f = width;
47 widget->height_f = height;
48 }
49
gg_widget_get_requested_size(gg_widget_t * widget,int * width,int * height)50 void gg_widget_get_requested_size(gg_widget_t *widget, int *width, int *height) {
51 if (width) {
52 if (widget->width_f > widget->width)
53 *width = widget->width_f;
54 else
55 *width = widget->width;
56 }
57
58 if (height) {
59 if (widget->height_f > widget->height)
60 *height = widget->height_f;
61 else
62 *height = widget->height;
63 }
64 }
65
gg_set_size(gg_widget_t * widget,int width,int height)66 void gg_set_size(gg_widget_t *widget, int width, int height) {
67 widget->width_a = width;
68 widget->height_a = height;
69 }
70
gg_get_focus_pos(gg_widget_t * widget)71 gg_rect_t gg_get_focus_pos(gg_widget_t *widget) {
72 gg_rect_t rect;
73
74 rect.x = 0;
75 rect.y = 0;
76 rect.width = widget->width_a;
77 rect.height = widget->height_a;
78
79 return rect;
80 }
81
gg_set_focus_pos(gg_widget_t * widget,int x,int y)82 int gg_set_focus_pos(gg_widget_t *widget, int x, int y) {
83 return 1;
84 }
85
gg_widget_find_dialog(gg_widget_t * widget)86 gg_dialog_t *gg_widget_find_dialog(gg_widget_t *widget) {
87 if (widget->parent == NULL)
88 return NULL;
89
90 while (widget->parent != NULL)
91 widget = widget->parent;
92
93 return GG_DIALOG(widget);
94 }
95
gg_widget_init(gg_widget_t * widget)96 void gg_widget_init(gg_widget_t *widget) {
97 widget->render = NULL;
98 widget->input = NULL;
99 widget->destroy = gg_widget_destroy;
100 widget->get_requested_size = gg_widget_get_requested_size;
101 widget->set_size = gg_set_size;
102 widget->get_focus_pos = gg_get_focus_pos;
103 widget->set_focus_pos = gg_set_focus_pos;
104 widget->id = gg_widget_get_class_id();
105 widget->enabled = 0;
106 widget->width = widget->height = 0;
107 widget->width_f = widget->height_f = -1;
108 widget->width_a = widget->height_a = 0;
109 widget->parent = NULL;
110 TAILQ_INIT(&widget->callbacks);
111 }
112
gg_widget_subscribe_signal(gg_widget_t * widget,gg_signal_t signal,gg_widget_cb_t callback,void * extra_data)113 void gg_widget_subscribe_signal(gg_widget_t *widget, gg_signal_t signal, gg_widget_cb_t callback, void *extra_data) {
114 gg_widget_cb_list_t *cb = malloc(sizeof(gg_widget_cb_list_t));
115 cb->signal = signal;
116 cb->callback = callback;
117 cb->extra_data = extra_data;
118 TAILQ_INSERT_HEAD(&widget->callbacks, cb, entries);
119 }
120
gg_widget_subscribe_signal_name(gg_widget_t * widget,gg_class_id id,char * name,gg_widget_cb_t callback,void * extra_data)121 int gg_widget_subscribe_signal_name(gg_widget_t *widget, gg_class_id id, char *name, gg_widget_cb_t callback,
122 void *extra_data) {
123 gg_signal_t signal = gg_signal_lookup(id, name);
124
125 if (signal == -1)
126 return -1;
127
128 gg_widget_subscribe_signal(widget, signal, callback, extra_data);
129 return 0;
130 }
131
gg_widget_emit_signal(gg_widget_t * widget,gg_widget_t * emitter,gg_signal_t signal,void * data)132 void gg_widget_emit_signal(gg_widget_t *widget, gg_widget_t *emitter, gg_signal_t signal, void *data) {
133 gg_widget_cb_list_t *cb_list;
134
135 TAILQ_FOREACH(cb_list, &widget->callbacks, entries) {
136 if (cb_list->signal == signal) {
137 if (cb_list->callback(widget, emitter, data, cb_list->extra_data))
138 return;
139 }
140 }
141
142 if (widget->parent)
143 gg_widget_emit_signal(widget->parent, emitter, signal, data);
144 }
145