Created common signature for panel event handling functions.
[xuni.git] / src / editor / editor.c
blobd5c76307c9fc15d8b8b14b36de03cc51accb0891
1 /*! \file editor.c
3 */
5 #include <string.h>
7 #include "editor.h"
9 #include "xuni.h"
10 #include "error.h"
11 #include "graphics.h"
12 #include "loadso.h"
13 #include "loop.h"
14 #include "resource/resource.h"
15 #include "memory.h"
16 #include "utility.h"
17 #include "version.h"
19 #include "widget/dump.h"
20 #include "widget/widgets.h"
22 static void load_resource(struct resource_t *settings);
23 static void save_resource(struct resource_t *resource);
25 static void init_loop_data(struct gui_t *gui);
27 #ifdef VERSION_WIN32
28 #include <windows.h>
29 int STDCALL WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpCmd, int nShow) {
30 #else
31 int main(int argc, char *argv[]) {
32 #endif
33 struct resource_t settings;
34 struct xuni_t *xuni = allocate_xuni();
36 xuni_error_initialize();
37 xuni_error_add_stream(0, stderr);
38 xuni_error_add_stream("editor.log", 0);
40 load_resource(&settings);
42 init_xuni(xuni, &settings,
43 lookup_resource_string(&settings, 0, "xuni-resource", "icon", 0));
45 init_loop_data(xuni->gui);
47 call_init_funcs(xuni, xuni->gui->widget, &settings);
48 main_loop(xuni, 0, PANEL_EDITOR);
50 xuni_memory_keep_freed_blocks(1);
52 save_resource(&settings);
53 free_resource(&settings);
54 free_xuni(xuni);
56 quit_sdl_libraries();
57 xuni_error_quit();
58 xuni_memory_free_all();
60 return 0;
63 static void load_resource(struct resource_t *settings) {
64 init_resource(settings);
66 if(parse_resource(settings->data, SETTINGS_FILE)) {
67 log_message(ERROR_TYPE_FATAL, 0, __FILE__, __LINE__,
68 "Failed to load resource \"%s\"", SETTINGS_FILE);
72 static void save_resource(struct resource_t *resource) {
73 /*write_resource(resource, SETTINGS_FILE ".generated");*/
76 static int editor_init(struct xuni_t *xuni, struct panel_data_t *data);
77 static int editor_start(struct xuni_t *xuni, struct panel_data_t *data);
78 static int editor_event(struct xuni_t *xuni, struct panel_data_t *data);
79 static int editor_click(struct xuni_t *xuni, struct panel_data_t *data);
80 static int editor_deactivate(struct xuni_t *xuni, struct panel_data_t *data);
81 static int editor_paint(struct xuni_t *xuni, struct panel_data_t *data);
82 static int editor_free(struct xuni_t *xuni, struct panel_data_t *data);
84 static void handle_cancel_action(struct xuni_t *xuni,
85 struct editor_data_t *data);
86 static void set_editor_mode(struct xuni_t *xuni, struct editor_data_t *data,
87 enum editor_mode_t mode);
89 enum wid_t {
90 WID_QUIT,
91 WID_MODE_LABEL,
92 WID_POSITION_LABEL,
93 WID_MODE_TEST,
94 WID_CANCEL_ACTION,
95 WID_MODE_DELETE_WIDGET,
96 WID_MODE_ADD_BUTTON,
97 WID_AREA,
98 WID_AREA_BOX,
99 WID_AREA_CURSOR_BOX,
100 WIDS
103 static void init_loop_data(struct gui_t *gui) {
104 void *data;
106 init_wid(gui->widget, gui->widget, PANEL_EDITOR, "editor");
108 data = xuni_memory_allocate(sizeof(struct editor_data_t));
109 set_panel_callbacks(widget_nameid_access(gui->widget, PANEL_EDITOR),
110 data, 0, editor_init, editor_start, editor_event,
111 default_panel_sel, editor_click, editor_deactivate,
112 editor_paint, editor_free);
115 static const char *get_mode_name(enum editor_mode_t mode) {
116 static const char *name[] = {
117 "test",
118 "delete",
119 "button"
122 if((size_t)mode < sizeof(name)/sizeof(*name)) {
123 return name[mode];
125 else return "ERROR";
128 static int editor_init(struct xuni_t *xuni, struct panel_data_t *data) {
129 struct editor_data_t *edata = data->data;
130 struct widget_t *panel = data->event[PANEL_EVENT_INIT].p.init.panel;
132 init_wid(panel, panel, WID_QUIT, "quit");
133 init_wid(panel, panel, WID_MODE_LABEL, "mode label");
134 init_wid(panel, panel, WID_POSITION_LABEL, "position label");
135 init_wid(panel, panel, WID_MODE_TEST, "resource tab/test");
136 init_wid(panel, panel, WID_CANCEL_ACTION,
137 "resource tab/cancel action");
138 init_wid(panel, panel, WID_MODE_DELETE_WIDGET,
139 "resource tab/delete widget");
140 init_wid(panel, panel, WID_MODE_ADD_BUTTON,
141 "resource tab/add button");
142 init_wid(panel, panel, WID_AREA, "area");
143 init_wid(panel, panel, WID_AREA_BOX, "area/box");
144 init_wid(panel, panel, WID_AREA_CURSOR_BOX, "area/cursor box");
146 add_widget_accelerator(xuni, panel, panel, SDLK_SPACE, KMOD_NONE);
147 add_widget_accelerator(xuni, panel, widget_nameid_access(panel,
148 WID_CANCEL_ACTION), SDLK_ESCAPE, KMOD_NONE);
150 edata->mode = EDITOR_MODE_TEST;
152 return 0;
155 static int editor_start(struct xuni_t *xuni, struct panel_data_t *data) {
156 set_caption("xuni editor");
158 return 0;
161 static int editor_event(struct xuni_t *xuni, struct panel_data_t *data) {
162 /*static int editor_event(void *vdata, struct xuni_t *xuni, panel_type_t *mode,
163 SDL_Event *event) {*/
165 struct editor_data_t *edata = data->data;
166 struct widget_t *cbox;
167 int repaint = 0;
168 panel_type_t *mode = data->event[PANEL_EVENT_EVENT].p.event.mode;
169 SDL_Event *event = data->event[PANEL_EVENT_EVENT].p.event.event;
171 switch(event->type) {
172 case SDL_QUIT:
173 *mode = (size_t)-1;
174 break;
175 case SDL_KEYDOWN:
176 switch(event->key.keysym.sym) {
177 case SDLK_F4:
178 dump_widget_tree(xuni, widget_nameid_follow(xuni->gui->widget,
179 PANEL_EDITOR, WID_AREA, (size_t)-1));
180 break;
181 case SDLK_F3:
182 dump_widget_tree_xml(xuni, widget_nameid_follow(xuni->gui->widget,
183 PANEL_EDITOR, WID_AREA, (size_t)-1), "editor-dump.xml");
184 break;
185 default:
186 break;
189 break;
190 case SDL_MOUSEMOTION:
191 if(widget_nameid_follow(xuni->gui->widget,
192 PANEL_EDITOR, WID_AREA_BOX, (size_t)-1)->sel) {
194 char buffer[BUFSIZ], **bdata;
195 struct widget_t *label;
196 struct widget_t *box = widget_nameid_follow(xuni->gui->widget,
197 PANEL_EDITOR, WID_AREA, (size_t)-1);
199 label = widget_nameid_follow(xuni->gui->widget,
200 PANEL_EDITOR, WID_POSITION_LABEL, (size_t)-1);
201 bdata = (char **)&label->p.label->text;
203 sprintf(buffer, "(%.2f,%.2f)",
204 (event->motion.x - box->pos->real.x)
205 / (xuni->smode->width * (box->pos->scale.w / 100.0))
206 * 100.0,
207 (event->motion.y - box->pos->real.y)
208 / (xuni->smode->height * (box->pos->scale.h / 100.0))
209 * 100.0);
211 xuni_memory_free(*bdata);
212 *bdata = xuni_memory_duplicate_string(buffer);
214 widget_event(xuni, label, WIDGET_EVENT_RESCALE);
216 repaint = 1;
219 if(edata->mode == EDITOR_MODE_ADD_BUTTON) {
220 cbox = widget_nameid_follow(xuni->gui->widget,
221 PANEL_EDITOR, WID_AREA_CURSOR_BOX, (size_t)-1);
222 if(cbox->visibility & WIDGET_VISIBILITY_VISIBLE) {
223 /* !!! this really needs to be simplified */
224 cbox->pos->scale.w = (event->motion.x - cbox->pos->real.x)
225 / ((xuni->smode->width / 100.0)
226 * (cbox->base->pos->scale.w / 100.0));
227 cbox->pos->scale.h = (event->motion.y - cbox->pos->real.y)
228 / ((xuni->smode->height / 100.0)
229 * (cbox->base->pos->scale.h / 100.0));
230 if(cbox->pos->scale.w < 0) cbox->pos->scale.w = 0;
231 if(cbox->pos->scale.h < 0) cbox->pos->scale.h = 0;
233 widget_event(xuni, cbox->base, WIDGET_EVENT_RESCALE);
235 repaint = 1;
239 break;
240 default:
241 break;
244 return repaint;
247 #if !1
248 static int set_editor_widget_sel(panel_type_t mode, int xp, int yp, int click,
249 void *vdata, struct xuni_t *xuni) {
251 struct editor_data_t *data = vdata;
252 struct widget_t *widget;
254 switch(data->mode) {
255 case EDITOR_MODE_ADD_BUTTON:
256 widget = widget_nameid_follow(xuni->gui->widget,
257 PANEL_EDITOR, WID_AREA_BOX, (size_t)-1);
259 clear_widget_sel(xuni->gui->widget);
261 if(pos_in_rect(xp, yp, widget->pos)) {
262 widget->sel = 1;
263 /*return 1;*/
266 break;
267 default:
268 break;
271 return set_widget_sel_repaint(&xuni->gui->sel, xp, yp, click,
272 widget_nameid_access(xuni->gui->widget, mode));
274 #endif
276 static void handle_cancel_action(struct xuni_t *xuni,
277 struct editor_data_t *data) {
279 if(data->mode == EDITOR_MODE_ADD_BUTTON) {
280 struct widget_t *panel = widget_nameid_follow(xuni->gui->widget,
281 PANEL_EDITOR, WID_AREA_CURSOR_BOX, (size_t)-1);
283 panel->visibility &= ~WIDGET_VISIBILITY_VISIBLE;
284 panel->visibility &= ~WIDGET_VISIBILITY_SELABLE;
288 static void set_editor_mode(struct xuni_t *xuni, struct editor_data_t *data,
289 enum editor_mode_t mode) {
291 struct widget_t *modelabel;
292 const char *text;
294 if(mode == data->mode) return;
296 data->mode = mode;
298 handle_cancel_action(xuni, data);
300 modelabel = widget_nameid_follow(xuni->gui->widget,
301 PANEL_EDITOR, WID_MODE_LABEL, (size_t)-1);
303 xuni_memory_free((void *)modelabel->p.label->text);
304 text = get_mode_name(data->mode);
305 text = xuni_memory_duplicate_string(text);
306 modelabel->p.label->text = text;
307 widget_event(xuni, modelabel, WIDGET_EVENT_RESCALE);
310 static void set_all_widget_visibilities(struct widget_t *widget,
311 enum widget_visibility_t visibility) {
313 size_t x;
315 widget->visibility &= ~visibility;
317 if(widget->compose) {
318 for(x = 0; x < widget->compose->widgets; x ++) {
319 set_all_widget_visibilities(widget->compose->widget[x],
320 visibility);
325 static int editor_click(struct xuni_t *xuni, struct panel_data_t *data) {
326 struct editor_data_t *edata = data->data;
327 panel_type_t *mode = data->event[PANEL_EVENT_CLICK].p.click.mode;
328 struct widget_t *widget = data->event[PANEL_EVENT_CLICK].p.click.widget;
329 struct widget_t *cbox;
330 int repaint = 0;
331 int xp, yp;
333 switch(widget->id) {
334 case WID_QUIT:
335 *mode = (size_t)-1;
336 break;
337 case WID_MODE_TEST:
338 widget_nameid_follow(xuni->gui->widget, PANEL_EDITOR, WID_AREA_BOX,
339 (size_t)-1)->visibility &= ~WIDGET_VISIBILITY_CLICKABLE;
341 set_editor_mode(xuni, edata, EDITOR_MODE_TEST);
343 break;
344 case WID_CANCEL_ACTION:
345 handle_cancel_action(xuni, edata);
347 repaint = 1;
348 break;
349 case WID_MODE_DELETE_WIDGET:
350 widget_nameid_follow(xuni->gui->widget, PANEL_EDITOR, WID_AREA_BOX,
351 (size_t)-1)->visibility &= ~WIDGET_VISIBILITY_CLICKABLE;
353 set_editor_mode(xuni, edata, EDITOR_MODE_DELETE_WIDGET);
355 break;
356 case WID_MODE_ADD_BUTTON:
357 widget_nameid_follow(xuni->gui->widget, PANEL_EDITOR, WID_AREA_BOX,
358 (size_t)-1)->visibility |= WIDGET_VISIBILITY_CLICKABLE;
360 /*set_all_widget_visibilities(widget_nameid_follow(xuni->gui->widget,
361 PANEL_EDITOR, WID_AREA_BOX, (size_t)-1),
362 WIDGET_VISIBILITY_SELABLE);*/
364 set_editor_mode(xuni, edata, EDITOR_MODE_ADD_BUTTON);
366 break;
367 case WID_AREA_BOX:
368 if(edata->mode == EDITOR_MODE_ADD_BUTTON) {
369 cbox = widget_nameid_access(widget->base->base,
370 WID_AREA_CURSOR_BOX);
372 if(cbox->visibility & WIDGET_VISIBILITY_VISIBLE) {
373 cbox->visibility &= ~WIDGET_VISIBILITY_VISIBLE;
375 /* Only add the button if its width and height are nonzero. */
376 if(cbox->pos->scale.w && cbox->pos->scale.h) {
377 add_allocate_widget_compose(widget->base, "button");
379 init_widget_pos(last_compose_widget(widget->base),
380 cbox->pos->scale.x, cbox->pos->scale.y,
381 cbox->pos->scale.w, cbox->pos->scale.h,
382 POS_PACK_NONE);
383 init_button(last_compose_widget(widget->base), 0);
385 widget_event(xuni, last_compose_widget(widget->base),
386 WIDGET_EVENT_RESCALE);
389 else {
390 cbox->visibility |= WIDGET_VISIBILITY_VISIBLE;
392 SDL_GetMouseState(&xp, &yp);
393 xp -= cbox->base->pos->real.x;
394 yp -= cbox->base->pos->real.y;
395 cbox->pos->scale.x = (double)xp / cbox->base->pos->real.w
396 * 100.0;
397 cbox->pos->scale.y = (double)yp / cbox->base->pos->real.h
398 * 100.0;
399 cbox->pos->scale.w = 0;
400 cbox->pos->scale.h = 0;
402 widget_event(xuni, cbox, WIDGET_EVENT_RESCALE);
406 repaint = 1;
407 break;
408 default:
409 if(widget_is_parent(widget_nameid_follow(xuni->gui->widget,
410 PANEL_EDITOR, WID_AREA, (size_t)-1), widget)) {
412 if(edata->mode == EDITOR_MODE_DELETE_WIDGET) {
413 delete_widget_pointer(xuni, widget);
417 break;
420 return repaint;
423 static int editor_deactivate(struct xuni_t *xuni, struct panel_data_t *data) {
424 return 0;
427 static int editor_paint(struct xuni_t *xuni, struct panel_data_t *data) {
428 /*struct widget_t *area = widget_nameid_follow(xuni->gui->widget,
429 PANEL_EDITOR, WID_AREA, (size_t)-1);*/
431 clear_screen(xuni->smode->screen);
433 widget_event(xuni, widget_nameid_access(xuni->gui->widget, PANEL_EDITOR),
434 WIDGET_EVENT_PAINT);
437 int x, y;
438 SDL_GetMouseState(&x, &y);
439 lineRGBA(xuni->smode->screen, area->pos->real.x, area->pos->real.y,
440 x, y, 255, 255, 255, 255);
443 update_screen(xuni);
445 return 0;
448 static int editor_free(struct xuni_t *xuni, struct panel_data_t *data) {
449 return 0;
452 #ifdef LOADSO_STATIC_VERSION
453 func_point_t xuni_loadso_load_function(loadso_t object, const char *func) {
454 struct string_function_t data[] = {
455 {0, (func_point_t)0}
457 func_point_t funcp
458 = string_to_function(data, sizeof(data) / sizeof(*data), func);
460 if(!funcp) {
461 log_message(ERROR_TYPE_RESOURCE, 0, __FILE__, __LINE__,
462 "Unknown function: \"%s\"", func);
465 return funcp;
467 #endif