1 /*
2  * (SLIK) SimpLIstic sKin functions
3  * (C) 2005 John Ellis
4  *
5  * Author: 5ohn Ellis
6  *
7  * This software is released under the GNU General Public License (GNU GPL).
8  * Please read the included file COPYING for more information.
9  * This software comes with no warranty of any kind, use at your own risk!
10  */
11 
12 #include "ui2_includes.h"
13 #include "ui2_typedefs.h"
14 #include "ui2_main.h"
15 
16 #include "ui2_button.h"
17 #include "ui2_decal.h"
18 #include "ui2_display.h"
19 #include "ui2_parse.h"
20 #include "ui2_skin.h"
21 #include "ui2_util.h"
22 #include "ui2_widget.h"
23 #include "ui_fileops.h"
24 #include "ui_misc.h"
25 #include "ui_utildlg.h"
26 
27 #include "ui2_logo.h"
28 
29 /* these two includes are _only_ used in ui_iconify() */
30 #include <gdk/gdkx.h>
31 #include <X11/Xlib.h>
32 
33 
34 /*
35  *-------------
36  * yes, these are globals
37  *-------------
38  */
39 
40 gint slik_smart_placement = TRUE;
41 gint slik_remember_position = FALSE;
42 
43 gint slik_focus_enable = TRUE;
44 
45 gint slik_double_size = FALSE;
46 
47 gint slik_scale = FALSE;
48 gfloat slik_scale_value = 1.0;
49 gint slik_allow_shapes = TRUE;
50 
51 gint slik_colorshift_r = 128;
52 gint slik_colorshift_g = 128;
53 gint slik_colorshift_b = 128;
54 gint slik_colorshift_a = 128;
55 gint slik_colorshift_on = FALSE;
56 
57 gint slik_transparency_force = FALSE;
58 gint slik_transparency_force_a = 192;
59 
60 gint debug_mode = FALSE;
61 gint debug_skin = FALSE;
62 
63 /* list of all windows created with ui_new() */
64 static GList *slik_ui_list = NULL;
65 
66 
67 /*
68  *-------------
69  * misc
70  *-------------
71  */
72 
window_set_icon(GtkWidget * window,const char ** icon,const gchar * file,GdkPixbuf * pixbuf)73 void window_set_icon(GtkWidget *window, const char **icon, const gchar *file, GdkPixbuf *pixbuf)
74 {
75 	GdkPixbuf *pb;
76 
77 	if (icon)
78 		{
79 		pb = gdk_pixbuf_new_from_xpm_data(icon);
80 		}
81 	else if (file)
82 		{
83 		pb = util_pixbuf_new_from_file(file);
84 		}
85 	else
86 		{
87 		pb = pixbuf;
88 		if (pb)
89 			{
90 			gdk_pixbuf_ref(pb);
91 			}
92 		else
93 			{
94 			pb = ui_slik_logo();
95 			}
96 		}
97 
98 	if (!pb) return;
99 	gtk_window_set_icon(GTK_WINDOW(window), pb);
100 	gdk_pixbuf_unref(pb);
101 }
102 
ui_set_icon(UIData * ui,const char ** icon,const gchar * file,GdkPixbuf * pixbuf)103 void ui_set_icon(UIData *ui, const char **icon, const gchar *file, GdkPixbuf *pixbuf)
104 {
105 	if (!ui || !ui->window) return;
106 
107 	window_set_icon(ui->window, icon, file, pixbuf);
108 }
109 
ui_iconify(UIData * ui)110 void ui_iconify(UIData *ui)
111 {
112         Window xwindow;
113 
114         if (!ui || !ui->window->window) return;
115 
116         xwindow = GDK_WINDOW_XWINDOW(ui->window->window);
117         XIconifyWindow (GDK_DISPLAY (), xwindow, DefaultScreen (GDK_DISPLAY ()));
118 }
119 
ui_mode_unique(UIData * ui,const gchar * mode_key)120 static gint ui_mode_unique(UIData *ui, const gchar *mode_key)
121 {
122 	GList *work;
123 
124 	if (!mode_key) return FALSE;
125 
126 	if (ui->parent) ui = ui->parent;
127 
128 	if (strcmp(mode_key, "skindata") == 0) return FALSE;
129 	if (ui->skin_mode_key && strcmp(ui->skin_mode_key, mode_key) == 0) return FALSE;
130 	if (ui->key && strcmp(ui->key, mode_key) == 0) return FALSE;
131 
132 	work = ui->children;
133 	while (work)
134 		{
135 		UIData *child;
136 
137 		child = work->data;
138 		work = work->next;
139 
140 		if (child->key && strcmp(child->key, mode_key) == 0) return FALSE;
141 		}
142 
143 	return TRUE;
144 }
145 
146 /*
147  *-------------
148  * these are the reserved widgets for window resizing and skin mode toggles.
149  *-------------
150  */
151 
ui_skin_toggle_click_cb(ButtonData * button,const gchar * key,gpointer data)152 static void ui_skin_toggle_click_cb(ButtonData *button, const gchar *key, gpointer data)
153 {
154 	UIData *ui = data;
155 	const gchar *mode_key;
156 
157 	/* luckily, the editor disables this button, no need to handle ui->edit */
158 
159 	mode_key = ui_widget_get_data_by_widget(ui, button);
160 
161 	if (debug_mode) printf("Setting skin mode key = \"%s\"\n", mode_key);
162 
163 	ui_skin_mode_set(ui, mode_key);
164 }
165 
ui_skin_expand_status_cb(ButtonData * button,const gchar * key,gpointer data)166 static gint ui_skin_expand_status_cb(ButtonData *button, const gchar *key, gpointer data)
167 {
168 	UIData *ui = data;
169 	SkinData *skin;
170 
171 	skin = ui->skin;
172 
173 	return (skin->width != skin->width_def || skin->height != skin->height_def);
174 }
175 
ui_skin_expand_click_cb(ButtonData * button,const gchar * key,gpointer data)176 static void ui_skin_expand_click_cb(ButtonData *button, const gchar *key, gpointer data)
177 {
178 	UIData *ui = data;
179 	const gchar *text;
180 	gint w, h;
181 
182 	text = ui_widget_get_data_by_widget(ui, button);
183 
184 	/* we must support the editor */
185 	if (!text && ui->edit && skin_widget_get_by_widget(ui->skin, button) == NULL)
186 		{
187 		text = ui_widget_get_data_by_widget(ui->edit, button);
188 		ui = ui->edit;
189 		}
190 
191 	if (debug_mode) printf("Skin expand data = \"%s\"\n", text);
192 
193 	if (text && sscanf(text, "%i %i", &w, &h) == 2)
194 		{
195 		SkinData *skin = ui->skin;
196 		gint state;
197 
198 		if (skin->width == skin->width_def && skin->height == skin->height_def)
199 			{
200 			util_size(&w);
201 			util_size(&h);
202 
203 			/* do the expand (can be negative too) */
204 			skin_resize(ui, skin->width + w, skin->height + h);
205 			state = TRUE;
206 			}
207 		else
208 			{
209 			/* assume expanded, snap back to default */
210 			skin_resize(ui, skin->width_def, skin->height_def);
211 			state = FALSE;
212 			}
213 		button_state_set("skin_expand", ui, state);
214 		}
215 }
216 
ui_spawn_child(UIData * parent,const gchar * key,const gchar * title,const gchar * mode_key)217 UIData *ui_spawn_child(UIData *parent, const gchar *key, const gchar *title, const gchar *mode_key)
218 {
219 	UIData *child;
220 	SkinData *skin;
221 
222 	if (!key) return NULL;
223 
224 	if (parent->parent) parent = parent->parent;
225 
226 	if (debug_mode) printf("ui2_main.c: opening skin \"%s\"for addition as \"%s\"\n", (mode_key) ? mode_key : "default", key);
227 
228 	if (parent->skin_path)
229 		{
230 		gchar *datafile;
231 
232 		datafile = g_strconcat(parent->skin_path, "/", (mode_key) ? mode_key : "skindata", NULL);
233 		skin = skin_parse(parent->skin_path, datafile, FALSE);
234 		g_free(datafile);
235 		}
236 	else
237 		{
238 		if (parent->skin_func)
239 			{
240 			skin = parent->skin_func(parent, mode_key, parent->skin_data);
241 			}
242 		else
243 			{
244 			skin = NULL;
245 			}
246 		}
247 
248 	if (!skin)
249 		{
250 		printf("ui2_main.c: failed to open skin \"%s\"for spawned window\n", mode_key);
251 		return NULL;
252 		}
253 
254 	child = ui_new(parent->class, key, parent->decorations, parent->class);
255 	ui_title_set(child, title);
256 	child->allow_move = parent->allow_move;
257 
258 	/* copy a few things from parent, it is up to the application to determine if
259 	 * the UI in the callback(s) is the parent.
260 	 */
261 	child->click_func = parent->click_func;
262 	child->click_data = parent->click_data;
263 
264 	child->skin_func = parent->skin_func;
265 	child->skin_data = parent->skin_data;
266 
267 	child->back_func = parent->back_func;
268 	child->back_data = parent->back_data;
269 
270 	child->new_window_func = parent->new_window_func;
271 	child->new_window_data = parent->new_window_data;
272 
273 	child->new_skin_func = parent->new_skin_func;
274 	child->new_skin_data = parent->new_skin_data;
275 
276 	ui_group_set_child(parent, child);
277 
278 	ui_skin_set(child, skin, parent->skin_path, mode_key);
279 
280 	if (parent->new_window_func)
281 		{
282 		parent->new_window_func(child, child->key, parent->new_window_data);
283 		}
284 
285 	return child;
286 }
287 
ui_skin_open_click_cb(ButtonData * button,const gchar * key,gpointer data)288 static void ui_skin_open_click_cb(ButtonData *button, const gchar *key, gpointer data)
289 {
290 	UIData *ui = data;
291 	UIData *child;
292 	const gchar *mode_key;
293 
294 	mode_key = ui_widget_get_data_by_widget(ui, button);
295 
296 	if (!mode_key || strlen(mode_key) == 0)
297 		{
298 		printf("ui2_main.c: skin_open requires valid mode key\n");
299 		return;
300 		}
301 
302 	if (!ui_mode_unique(ui, mode_key)) return;
303 
304 	if (debug_mode) printf("ui2_main.c: opening skin \"%s\"for addition\n", mode_key);
305 
306 	child = ui_spawn_child(ui, mode_key, NULL, mode_key);
307 	if (child)
308 		{
309 		gtk_widget_show(child->window);
310 		}
311 }
312 
ui_skin_close_click_cb(ButtonData * button,const gchar * key,gpointer data)313 static void ui_skin_close_click_cb(ButtonData *button, const gchar *key, gpointer data)
314 {
315 	UIData *ui = data;
316 
317 	if (!ui->parent) return;
318 
319 	if (debug_mode) printf("ui2_main.c: closing skin \"%s\"\n", ui->skin_mode_key);
320 
321 	ui_close(ui);
322 }
323 
ui_skin_iconify_click_cb(ButtonData * button,const gchar * key,gpointer data)324 static void ui_skin_iconify_click_cb(ButtonData *button, const gchar *key, gpointer data)
325 {
326 	UIData *ui = data;
327 
328 	if (ui->allow_move) ui_iconify(ui);
329 }
330 
ui_skin_sticky_update_cb(WidgetData * wd,gpointer data,UIData * ui)331 static void ui_skin_sticky_update_cb(WidgetData *wd, gpointer data, UIData *ui)
332 {
333 	ui_widget_draw(ui, wd, TRUE, FALSE);
334 }
335 
ui_skin_sticky_update(UIData * ui)336 static void ui_skin_sticky_update(UIData *ui)
337 {
338 	ui_widget_for_each_key_one(ui, "skin_sticky", button_type_id(),
339 				   ui_skin_sticky_update_cb, NULL);
340 }
341 
ui_skin_sticky_status_cb(ButtonData * button,const gchar * key,gpointer data)342 static gint ui_skin_sticky_status_cb(ButtonData *button, const gchar *key, gpointer data)
343 {
344 	UIData *ui = data;
345 
346 	return ui->sticky;
347 }
348 
ui_skin_sticky_click_cb(ButtonData * button,const gchar * key,gpointer data)349 static void ui_skin_sticky_click_cb(ButtonData *button, const gchar *key, gpointer data)
350 {
351 	UIData *ui = data;
352 
353 	if (!ui->window) return;
354 
355 	if (debug_mode) printf("setting sticky state to %d\n", !ui->sticky);
356 
357 	if (ui->sticky)
358 		{
359 		gtk_window_unstick(GTK_WINDOW(ui->window));
360 		ui->sticky = FALSE;
361 		}
362 	else
363 		{
364 		gtk_window_stick(GTK_WINDOW(ui->window));
365 		ui->sticky = TRUE;
366 		}
367 
368 	ui_skin_sticky_update(ui);
369 }
370 
ui_window_state_cb(GtkWidget * widget,GdkEventWindowState * event,gpointer data)371 static gboolean ui_window_state_cb(GtkWidget *widget, GdkEventWindowState *event, gpointer data)
372 {
373 	UIData *ui = data;
374 
375 	if (event->changed_mask & GDK_WINDOW_STATE_STICKY)
376 		{
377 		ui->sticky = (event->new_window_state & GDK_WINDOW_STATE_STICKY);
378 		ui_skin_sticky_update(ui);
379 
380 		if (debug_mode) printf("sticky changed: %d\n", ui->sticky);
381 		}
382 
383 	return FALSE;
384 }
385 
ui_add_reserved(UIData * ui)386 static void ui_add_reserved(UIData *ui)
387 {
388 	/* ensure decals can be recognized */
389         decal_type_init();
390 
391 	if (!ui_registered_key_exists(ui, "skin_toggle", button_type_id()))
392 		{
393 		button_register_key("skin_toggle", ui,
394 				     NULL, NULL,
395 				     ui_skin_toggle_click_cb, ui,
396 				     NULL, NULL,
397 				     NULL, NULL);
398 		}
399 	if (!ui_registered_key_exists(ui, "skin_size", button_type_id()))
400 		{
401 		/* this is really a dummy register, but it makes the key show in the editor */
402 		button_register_key("skin_size", ui,
403 				     NULL, NULL,
404 				     NULL, NULL,
405 				     NULL, NULL,
406 				     NULL, NULL);
407 		}
408 	if (!ui_registered_key_exists(ui, "skin_expand", button_type_id()))
409 		{
410 		button_register_key("skin_expand", ui,
411 				     ui_skin_expand_status_cb, ui,
412 				     ui_skin_expand_click_cb, ui,
413 				     NULL, NULL,
414 				     NULL, NULL);
415 		}
416 
417 	if (!ui_registered_key_exists(ui, "skin_open", button_type_id()))
418 		{
419 		button_register_key("skin_open", ui,
420 				     NULL, NULL,
421 				     ui_skin_open_click_cb, ui,
422 				     NULL, NULL,
423 				     NULL, NULL);
424 		}
425 	if (!ui_registered_key_exists(ui, "skin_close", button_type_id()))
426 		{
427 		button_register_key("skin_close", ui,
428 				     NULL, NULL,
429 				     ui_skin_close_click_cb, ui,
430 				     NULL, NULL,
431 				     NULL, NULL);
432 		}
433 	if (!ui_registered_key_exists(ui, "skin_iconify", button_type_id()))
434 		{
435 		button_register_key("skin_iconify", ui,
436 				     NULL, NULL,
437 				     ui_skin_iconify_click_cb, ui,
438 				     NULL, NULL,
439 				     NULL, NULL);
440 		}
441 	if (!ui_registered_key_exists(ui, "skin_sticky", button_type_id()))
442 		{
443 		button_register_key("skin_sticky", ui,
444 				     ui_skin_sticky_status_cb, ui,
445 				     ui_skin_sticky_click_cb, ui,
446 				     NULL, NULL,
447 				     NULL, NULL);
448 		}
449 }
450 
451 /*
452  *-------------
453  * ui
454  *-------------
455  */
456 
ui_free(UIData * ui)457 void ui_free(UIData *ui)
458 {
459 	if (!ui) return;
460 
461 	if (!ui->destroyed)
462 		{
463 		printf("warning: free called for ui \"%s\" not marked as destroyed\n", ui->key);
464 		}
465 
466 	/* close children */
467 	while (ui->children)
468 		{
469 		UIData *child = ui->children->data;
470 		ui_close(child);
471 		}
472 
473 	/* if child, break from parent */
474 	ui_group_unset_child(ui);
475 
476 	slik_ui_list = g_list_remove(slik_ui_list, ui);
477 
478 	if (ui->root_win_idle != -1) g_source_remove(ui->root_win_idle);
479 	ui_register_free_all(ui);
480 	skin_free(ui->skin);
481 	g_free(ui->skin_path);
482 	g_free(ui->skin_mode_key);
483 	g_free(ui->class);
484 	g_free(ui->key);
485 	g_free(ui);
486 }
487 
ui_hide_cb(GtkWidget * widget,gpointer data)488 static void ui_hide_cb(GtkWidget *widget, gpointer data)
489 {
490 	UIData *ui = data;
491 	gint x, y, w, h;
492 
493 	if (ui_geometry_get(ui, &x, &y, &w, &h))
494 		{
495 		if (debug_mode) printf("hidden \"%s\"\n", ui->key);
496 		ui_state_set(filename_from_path(ui->skin_path), ui->skin_mode_key, x, y, w, h);
497 		}
498 }
499 
ui_destroy_cb(GtkWidget * widget,gpointer data)500 static void ui_destroy_cb(GtkWidget *widget, gpointer data)
501 {
502 	UIData *ui = data;
503 
504 	if (debug_mode) printf("UI destroyed \"%s\"\n", ui->key);
505 
506 	ui->destroyed = TRUE;
507 	ui_free(ui);
508 }
509 
ui_real_new(const gchar * class,const gchar * key,gint decorations,const gchar * title,GtkWindowType type)510 static UIData *ui_real_new(const gchar *class, const gchar *key,
511 			   gint decorations, const gchar *title, GtkWindowType type)
512 {
513 	UIData *ui;
514 
515 	ui = g_new0(UIData, 1);
516 
517 	ui->decorations = decorations;
518 	ui->root_win_idle = -1;
519 	ui->edit = NULL;
520 	ui->skin = NULL;
521 	ui->class = g_strdup((class) ? class : "SLIK");
522 	ui->key = g_strdup(key);
523 	ui->allow_move = TRUE;
524 	ui->focus_enable = FALSE;
525 	ui->tooltips_enable = FALSE;
526 
527 	ui->parent = NULL;
528 	ui->children = NULL;
529 
530 	ui->window = gtk_window_new(type);
531 	gtk_window_set_resizable(GTK_WINDOW(ui->window), FALSE);
532 	gtk_container_set_border_width(GTK_CONTAINER(ui->window), 0);
533 	gtk_window_set_wmclass(GTK_WINDOW(ui->window), ui->key, ui->class);
534 	gtk_window_set_title(GTK_WINDOW(ui->window), title);
535 
536 	g_signal_connect(G_OBJECT(ui->window), "hide",
537 			 G_CALLBACK(ui_hide_cb), ui);
538 	g_signal_connect(G_OBJECT(ui->window), "destroy",
539 			 G_CALLBACK(ui_destroy_cb), ui);
540 	g_signal_connect(G_OBJECT(ui->window), "window_state_event",
541 			 G_CALLBACK(ui_window_state_cb), ui);
542 
543 	ui->display = gtk_drawing_area_new();
544 	ui_display_events_init(ui);
545 	gtk_container_add(GTK_CONTAINER(ui->window), ui->display);
546 	gtk_widget_show(ui->display);
547 
548 	if (GTK_WIDGET_CAN_FOCUS(ui->display)) gtk_widget_grab_focus(ui->display);
549 
550 	if (type != GTK_WINDOW_POPUP && !ui->decorations)
551 		{
552 		gtk_window_set_decorated(GTK_WINDOW(ui->window), 0);
553 		}
554 
555 	/* add the default reserved keys */
556 	ui_add_reserved(ui);
557 
558 	slik_ui_list = g_list_append(slik_ui_list, ui);
559 
560 	return ui;
561 }
562 
ui_new(const gchar * class,const gchar * subclass,gint decorations,const gchar * title)563 UIData *ui_new(const gchar *class, const gchar *subclass, gint decorations, const gchar *title)
564 {
565 	return ui_real_new(class, subclass, decorations, title, GTK_WINDOW_TOPLEVEL);
566 }
567 
ui_new_dialog(const gchar * class,const gchar * subclass,gint decorations,const gchar * title)568 UIData *ui_new_dialog(const gchar *class, const gchar *subclass, gint decorations, const gchar *title)
569 {
570 	UIData *ui;
571 
572 	ui = ui_real_new(class, subclass, decorations, title, GTK_WINDOW_TOPLEVEL);
573 	gtk_window_set_type_hint(GTK_WINDOW(ui->window), GDK_WINDOW_TYPE_HINT_DIALOG);
574 
575 	return ui;
576 }
577 
ui_new_into_container(const gchar * class,const gchar * key,GtkWidget * widget)578 UIData *ui_new_into_container(const gchar *class, const gchar *key, GtkWidget *widget)
579 {
580 	UIData *ui;
581 
582 	ui = g_new0(UIData, 1);
583 
584 	ui->decorations = FALSE;
585 	ui->root_win_idle = -1;
586 	ui->edit = NULL;
587 	ui->skin = NULL;
588 	ui->class = g_strdup((class) ? class : "SLIK");
589 	ui->key = g_strdup(key);
590 	ui->allow_move = FALSE;
591 	ui->focus_enable = FALSE;
592 	ui->tooltips_enable = FALSE;
593 
594 	ui->parent = NULL;
595 	ui->children = NULL;
596 
597 	ui->window = NULL;
598 
599 	ui->display = gtk_drawing_area_new();
600 	g_signal_connect(G_OBJECT(ui->display), "destroy",
601 			 G_CALLBACK(ui_destroy_cb), ui);
602 
603 	ui_display_events_init(ui);
604 	if (widget)
605 		{
606 		gtk_container_add(GTK_CONTAINER(widget), ui->display);
607 		}
608 
609 	gtk_widget_show(ui->display);
610 
611 	/* add the default reserved keys */
612 	ui_add_reserved(ui);
613 
614 	slik_ui_list = g_list_append(slik_ui_list, ui);
615 
616 	return ui;
617 }
618 
ui_close_cb(gpointer data)619 static gint ui_close_cb(gpointer data)
620 {
621 	UIData *ui = data;
622 
623 	if (ui->window)
624 		{
625 		gtk_widget_destroy(ui->window);
626 		}
627 	else
628 		{
629 		gtk_widget_destroy(ui->display);
630 		}
631 
632 	return FALSE;
633 }
634 
ui_close(UIData * ui)635 void ui_close(UIData *ui)
636 {
637 	if (!ui || ui->destroyed) return;
638 
639 	/* This may be called in the middle of a widget event (like a button press handler),
640 	 * and bad things may happen if the ui vanishes from under the handler, so hide the window
641 	 * then clean up in an idle function.
642 	 */
643 
644 	ui->destroyed = TRUE;
645 	if (ui->window && GTK_WIDGET_VISIBLE(ui->window)) gtk_widget_hide(ui->window);
646 
647 	/* close children.
648 	 * this may be duplicating effort in ui free,
649 	 * but has the benefit immediately hiding the windows.
650 	 */
651 	while (ui->children)
652 		{
653 		UIData *child = ui->children->data;
654 		ui_close(child);
655 		}
656 
657 	/* if a child, break from parent */
658 	ui_group_unset_child(ui);
659 
660 	g_idle_add(ui_close_cb, ui);
661 }
662 
ui_set_mouse_callback(UIData * ui,void (* func)(UIData * ui,gint button,guint32 time,gpointer data),gpointer data)663 void ui_set_mouse_callback(UIData *ui, void (*func)(UIData *ui, gint button, guint32 time, gpointer data), gpointer data)
664 {
665 	ui->click_func = func;
666 	ui->click_data = data;
667 }
668 
ui_set_skin_callback(UIData * ui,SkinData * (* func)(UIData * ui,const gchar * key,gpointer data),gpointer data)669 void ui_set_skin_callback(UIData *ui, SkinData *(*func)(UIData *ui, const gchar *key, gpointer data), gpointer data)
670 {
671 	ui->skin_func = func;
672 	ui->skin_data = data;
673 }
674 
ui_set_back_callback(UIData * ui,gint (* func)(UIData * ui,GdkPixbuf * pixbuf,gpointer data),gpointer data)675 void ui_set_back_callback(UIData *ui, gint (*func)(UIData *ui, GdkPixbuf *pixbuf, gpointer data), gpointer data)
676 {
677 	ui->back_func = func;
678 	ui->back_data = data;
679 }
680 
ui_set_new_window_callback(UIData * ui,void (* func)(UIData * ui,const gchar * key,gpointer data),gpointer data)681 void ui_set_new_window_callback(UIData *ui, void (*func)(UIData *ui, const gchar *key, gpointer data), gpointer data)
682 {
683 	ui->new_window_func = func;
684 	ui->new_window_data = data;
685 }
686 
ui_set_new_skin_callback(UIData * ui,void (* func)(UIData * ui,SkinData * skin,gint initialized,gpointer data),gpointer data)687 void ui_set_new_skin_callback(UIData *ui, void (*func)(UIData *ui, SkinData *skin, gint initialized, gpointer data),
688 			      gpointer data)
689 {
690 	ui->new_skin_func = func;
691 	ui->new_skin_data = data;
692 }
693 
694 
695 /*
696  *-------------
697  * app side keys
698  *-------------
699  */
700 
ui_register_key(UIData * ui,const gchar * key,WidgetType type,gpointer callbacks,guint length)701 RegisterData *ui_register_key(UIData *ui, const gchar *key, WidgetType type, gpointer callbacks, guint length)
702 {
703 	RegisterData *rd;
704 
705 	rd = g_new0(RegisterData, 1);
706 	rd->type = type;
707 	rd->key = g_strdup(key);
708 	rd->tooltip = NULL;
709 	rd->callbacks = callbacks;
710 	rd->callbacks_l = length;
711 	rd->private = FALSE;
712 	rd->private_widget = NULL;
713 
714 	ui->register_list = g_list_prepend(ui->register_list, rd);
715 
716 	return rd;
717 }
718 
ui_register_key_private(UIData * ui,const gchar * key,WidgetType type,gpointer callbacks,guint length,gpointer widget)719 RegisterData *ui_register_key_private(UIData *ui, const gchar *key, WidgetType type,
720 				      gpointer callbacks, guint length, gpointer widget)
721 {
722 	RegisterData *rd;
723 
724 	rd = ui_register_key(ui, key, type, callbacks, length);
725 	rd->private = TRUE;
726 	rd->private_widget = widget;
727 	return rd;
728 }
729 
ui_register_free(RegisterData * rd)730 static void ui_register_free(RegisterData *rd)
731 {
732 	g_free(rd->callbacks);
733 	g_free(rd->key);
734 	g_free(rd->tooltip);
735 	g_free(rd);
736 }
737 
ui_register_free_all(UIData * ui)738 void ui_register_free_all(UIData *ui)
739 {
740 	while(ui->register_list)
741 		{
742 		RegisterData *rd = ui->register_list->data;
743 		ui->register_list = g_list_remove(ui->register_list, rd);
744 		ui_register_free(rd);
745 		}
746 }
747 
ui_register_free_private(UIData * ui)748 void ui_register_free_private(UIData *ui)
749 {
750 	GList *work = ui->register_list;
751 
752 	while(work)
753 		{
754 		RegisterData *rd = work->data;
755 		work = work->next;
756 
757 		if (rd->private)
758 			{
759 			ui->register_list = g_list_remove(ui->register_list, rd);
760 			ui_register_free(rd);
761 			}
762 		}
763 }
764 
765 /* this will remove all keys with private_widget that match the widget,
766  * needed only when removing a widget
767  */
ui_unregister_key_private_for_widget(UIData * ui,gpointer widget)768 void ui_unregister_key_private_for_widget(UIData *ui, gpointer widget)
769 {
770 	GList *work;
771 
772 	if (!widget) return;
773 
774 	work = ui->register_list;
775 	while (work)
776 		{
777 		RegisterData *rd = work->data;
778 		work = work->next;
779 
780 		if (rd->private && rd->private_widget == widget)
781 			{
782 			ui->register_list = g_list_remove(ui->register_list, rd);
783 			ui_register_free(rd);
784 			}
785 		}
786 }
787 
ui_registered_by_key(UIData * ui,const gchar * key,WidgetType type)788 static RegisterData *ui_registered_by_key(UIData *ui, const gchar *key, WidgetType type)
789 {
790 	GList *work;
791 
792 	work = ui->register_list;
793 	while (work)
794 		{
795 		RegisterData *rd = work->data;
796 		if (rd->type == type && strcmp(rd->key, key) == 0) return rd;
797 		work = work->next;
798 		}
799 	return NULL;
800 }
801 
ui_get_registered_callbacks(UIData * ui,const gchar * key,WidgetType type)802 gpointer ui_get_registered_callbacks(UIData *ui, const gchar *key, WidgetType type)
803 {
804 	RegisterData *rd;
805 
806 	rd = ui_registered_by_key(ui, key, type);
807 	if (rd) return rd->callbacks;
808 
809 	if (ui->parent)
810 		{
811 		return ui_get_registered_callbacks(ui->parent, key, type);
812 		}
813 
814 	return NULL;
815 }
816 
ui_registered_key_exists(UIData * ui,const gchar * key,WidgetType type)817 gint ui_registered_key_exists(UIData *ui, const gchar *key, WidgetType type)
818 {
819 	return (ui_registered_by_key(ui, key, type) != NULL);
820 }
821 
ui_widget_exists(UIData * ui,const gchar * key,WidgetType type)822 gint ui_widget_exists(UIData *ui, const gchar *key, WidgetType type)
823 {
824 	if (!ui->skin) return FALSE;
825 
826 	return (skin_widget_get_by_key(ui->skin, key, type) != NULL);
827 }
828 
ui_registered_key_is_private(UIData * ui,const gchar * key,WidgetType type)829 gint ui_registered_key_is_private(UIData *ui, const gchar *key, WidgetType type)
830 {
831 	GList *work;
832 
833 	/* walk the loop ourselves, for speed only strcmp if private and type match */
834 
835 	work = ui->register_list;
836 	while (work)
837 		{
838 		RegisterData *rd = work->data;
839 		if (rd->private && rd->type == type && strcmp(rd->key, key) == 0) return TRUE;
840 		work = work->next;
841 		}
842 	return FALSE;
843 }
844 
ui_tooltip_set(UIData * ui,const gchar * key,WidgetType type,const gchar * message)845 void ui_tooltip_set(UIData *ui, const gchar *key, WidgetType type, const gchar *message)
846 {
847 	RegisterData *rd;
848 
849 	rd = ui_registered_by_key(ui, key, type);
850 	if (!rd) return;
851 
852 	g_free(rd->tooltip);
853 	rd->tooltip = g_strdup(message);
854 }
855 
ui_tooltip_get(UIData * ui,const gchar * key,WidgetType type)856 const gchar *ui_tooltip_get(UIData *ui, const gchar *key, WidgetType type)
857 {
858 	RegisterData *rd;
859 
860 	rd = ui_registered_by_key(ui, key, type);
861 	if (rd) return rd->tooltip;
862 
863 	if (ui->parent)
864 		{
865 		return ui_tooltip_get(ui->parent, key, type);
866 		}
867 
868 	return NULL;
869 }
870 
871 
ui_debug_print_register_list(UIData * ui)872 static void ui_debug_print_register_list(UIData *ui)
873 {
874 	GList *work;
875 
876 	printf("-------------------------\n");
877 	printf("UI registered keys (%3d):\n", g_list_length(ui->register_list));
878 	printf("-[key]------------------------[type]-----\n");
879 
880 	work = ui->register_list;
881 	while (work)
882 		{
883 		RegisterData *rd = work->data;
884 		work = work->next;
885 
886 		printf("%-30s %-10s %s\n", rd->key, ui_widget_type_to_text(rd->type), rd->private ? "(widget)" : "");
887 		}
888 }
889 
ui_debug_print_registered_keys(UIData * ui)890 void ui_debug_print_registered_keys(UIData *ui)
891 {
892 	if (!ui) return;
893 
894 	if (ui->parent)
895 		{
896 		printf("=========================\n");
897 		printf("UI is \"%s\" is a child of \"%s\"\n", ui->key, ui->parent->key);
898 		printf("printing out keys starting at the parent\n");
899 		printf("-------------------------\n");
900 		ui_debug_print_registered_keys(ui->parent);
901 		return;
902 		}
903 
904 	printf("=========================\n");
905 	printf("UI is \"%s\"\n", ui->key);
906 	printf("-------------------------\n");
907 	printf("    skin: \"%s\"\n", ui->skin_path);
908 	printf("mode key: \"%s\"\n", ui->skin_mode_key);
909 
910 	ui_debug_print_register_list(ui);
911 
912 	if (ui->children)
913 		{
914 		GList *work;
915 
916 		printf("-------------------------\n");
917 		printf("children: %d\n", g_list_length(ui->children));
918 
919 		work = ui->children;
920 		while (work)
921 			{
922 			UIData *child;
923 
924 			child = work->data;
925 			work = work->next;
926 
927 			printf("=========================\n");
928 			printf("   child: \"%s\"\n", child->key);
929 			printf("mode key: \"%s\"\n", child->skin_mode_key);
930 
931 			ui_debug_print_register_list(child);
932 			}
933 		}
934 
935 	printf("=========================\n");
936 }
937 
ui_debug_print_all_keys(UIData * ui)938 void ui_debug_print_all_keys(UIData *ui)
939 {
940 	GList *work;
941 
942 	ui_debug_print_registered_keys(ui);
943 
944 	if (ui->parent) ui = ui->parent;
945 
946 	skin_debug_print_registered_keys(ui->skin);
947 
948 	work = ui->children;
949 	while (work)
950 		{
951 		UIData *child;
952 
953 		child = work->data;
954 		work = work->next;
955 
956 		printf("=========================\n");
957 		printf("child: \"%s\"\n", child->key);
958 		printf("-------------------------\n");
959 
960 		skin_debug_print_registered_keys(child->skin);
961 		}
962 
963 	printf("=========================\n");
964 }
965 
966 /*
967  *-------------
968  * ui_misc
969  *-------------
970  */
971 
ui_update(UIData * ui)972 void ui_update(UIData *ui)
973 {
974 	GList *work;
975 
976 	if (!ui) return;
977 
978 	ui_display_draw_all(ui, TRUE, FALSE);
979 
980 	work = ui->children;
981 	while (work)
982 		{
983 		UIData *child = work->data;
984 		work = work->next;
985 
986 		ui_display_draw_all(child, TRUE, FALSE);
987 		}
988 }
989 
ui_geometry_get(UIData * ui,gint * x,gint * y,gint * w,gint * h)990 gint ui_geometry_get(UIData *ui, gint *x, gint *y, gint *w, gint *h)
991 {
992 	gint rx, ry, rw, rh;
993 
994 	if (!ui || !ui->skin ||
995 	    !ui->window || !ui->window->window ||
996 	    !GTK_WIDGET_REALIZED(ui->window)) return FALSE;
997 
998 	gdk_window_get_position(ui->window->window, &rx, &ry);
999 	gtk_window_get_size(GTK_WINDOW(ui->window), &rw, &rh);
1000 
1001 	if (x) *x = rx;
1002 	if (y) *y = ry;
1003 	if (w) *w = rw;
1004 	if (h) *h = rh;
1005 
1006 	ui_state_set(filename_from_path(ui->skin_path), ui->skin_mode_key, rx, ry, rw, rh);
1007 
1008 	return TRUE;
1009 }
1010 
ui_title_set(UIData * ui,const gchar * text)1011 void ui_title_set(UIData *ui, const gchar *text)
1012 {
1013 	gtk_window_set_title(GTK_WINDOW(ui->window), text);
1014 }
1015 
ui_moveable_set(UIData * ui,gint moveable)1016 void ui_moveable_set(UIData *ui, gint moveable)
1017 {
1018 	ui->allow_move = moveable;
1019 }
1020 
ui_focus_set(UIData * ui,gint enable)1021 void ui_focus_set(UIData *ui, gint enable)
1022 {
1023 	ui->focus_enable = enable;
1024 }
1025 
ui_tooltips_enable(UIData * ui,gint enable)1026 void ui_tooltips_enable(UIData *ui, gint enable)
1027 {
1028 	ui->tooltips_enable = enable;
1029 }
1030 
ui_skin_set(UIData * ui,SkinData * skin,const gchar * path,const gchar * mode_key)1031 void ui_skin_set(UIData *ui, SkinData *skin, const gchar *path, const gchar *mode_key)
1032 {
1033 	gchar *tmp;
1034 
1035 	if (!skin) return;
1036 
1037 	/* handle children, closing any that were opened
1038 	 * with the skin_open button, these are identified by
1039 	 * having the same key and skin_mode_key.
1040 	 */
1041 	if (( (path == NULL) != (ui->skin_path == NULL) ) ||
1042 	    (path && strcmp(path, ui->skin_path) != 0) )
1043 		{
1044 		GList *work;
1045 
1046 		work = ui->children;
1047 		while (work)
1048 			{
1049 			UIData *child;
1050 
1051 			child = work->data;
1052 			work = work->next;
1053 
1054 			if (child->key && child->skin_mode_key &&
1055 			    strcmp(child->key, child->skin_mode_key) == 0)
1056 				{
1057 				ui_close(child);
1058 				}
1059 			}
1060 		}
1061 
1062 	/* save current state of old skin */
1063 	ui_geometry_get(ui, NULL, NULL, NULL, NULL);
1064 
1065 	/* remove old internal widget signals */
1066 	ui_register_free_private(ui);
1067 
1068 	/* notify app of new skin */
1069 	if (ui->new_skin_func)
1070 		{
1071 		ui->new_skin_func(ui, skin, FALSE, ui->new_skin_data);
1072 		}
1073 
1074 	skin_free(ui->skin);
1075 	ui->skin = skin;
1076 	skin->ui = ui;
1077 
1078 	ui->active_widget = NULL;
1079 	ui->focus_widget = NULL;
1080 
1081 	/* use tmp, may be src = dest */
1082 
1083 	tmp = g_strdup(path);
1084 	g_free(ui->skin_path);
1085 	ui->skin_path = tmp;
1086 
1087 	tmp = g_strdup(mode_key);
1088 	g_free(ui->skin_mode_key);
1089 	ui->skin_mode_key = tmp;
1090 
1091 	/* set up new internal widget signals */
1092 	skin_widgets_init(skin, ui);
1093 
1094 	/* notify app new skin is about to be drawn */
1095 	if (ui->new_skin_func)
1096 		{
1097 		ui->new_skin_func(ui, skin, TRUE, ui->new_skin_data);
1098 		}
1099 
1100 	/* restore skin states */
1101 	if (slik_remember_position)
1102 		{
1103 		gint x;
1104 		gint y;
1105 		gint w;
1106 		gint h;
1107 
1108 		if (ui_state_get(filename_from_path(ui->skin_path), ui->skin_mode_key, &x, &y, &w, &h))
1109 			{
1110 			/* if not visible, this is the first skin, set position */
1111 			if (ui->window && !GTK_WIDGET_VISIBLE(ui->window) && ui->allow_move)
1112 				{
1113 				/* ensure that window is at least visible */
1114 				if (x < 0 - skin->width) x = 0;
1115 				if (x > gdk_screen_width()) x = gdk_screen_width() - skin->width;
1116 				if (y < 0 - skin->height) y = 0;
1117 				if (y > gdk_screen_height()) y = gdk_screen_height() - skin->height;
1118 
1119 				if (debug_mode) printf("setting window position %d, %d\n", x, y);
1120 
1121 				gtk_window_move(GTK_WINDOW(ui->window), x, y);
1122 				}
1123 
1124 			/* only do this if the skin is actually sizeable in some way */
1125 			if ((skin->sizeable && ui_widget_exists(ui, "skin_size", button_type_id())) ||
1126 			    ui_widget_exists(ui, "skin_expand", button_type_id()) )
1127 				{
1128 				w = CLAMP(w, skin->width_min, skin->width_max);
1129 				h = CLAMP(h, skin->height_min, skin->height_max);
1130 				skin_resize(ui, w, h);
1131 				}
1132 			}
1133 		}
1134 
1135 	ui_display_sync_all(ui);
1136 }
1137 
ui_skin_load_default(UIData * ui,const gchar * key)1138 SkinData *ui_skin_load_default(UIData *ui, const gchar *key)
1139 {
1140 	SkinData *skin = NULL;
1141 
1142 	if (ui->skin_func)
1143 		{
1144 		skin = ui->skin_func(ui, key, ui->skin_data);
1145 		}
1146 	if (!skin)
1147 		{
1148 		/* well, return something! */
1149 		skin = skin_new();
1150 
1151 		skin->real_overlay = ui_slik_logo();
1152 		skin->width = gdk_pixbuf_get_width(skin->real_overlay);
1153 		skin->height = gdk_pixbuf_get_height(skin->real_overlay);
1154 
1155 		/* add some widgets (a text message maybe? ) */
1156 
1157 		skin->width_def = skin->width_min = skin->width_max = skin->width;
1158 		skin->height_def = skin->height_min = skin->height_max = skin->height;
1159 		}
1160 
1161 	return skin;
1162 }
1163 
ui_skin_load(UIData * ui,const gchar * path,const gchar * mode_key)1164 gint ui_skin_load(UIData *ui, const gchar *path, const gchar *mode_key)
1165 {
1166 	SkinData *skin;
1167 	gint success = FALSE;
1168 	gchar *cpath;
1169 	gchar *ckey;
1170 
1171 	if (!mode_key) mode_key = "skindata";
1172 
1173 	/* copy, since loading a new skin may free the source ? */
1174 	cpath = g_strdup(path);
1175 	ckey = g_strdup(mode_key);
1176 
1177 	if (cpath)
1178 		{
1179 		if (!isdir(cpath) && isfile(cpath))
1180 			{
1181 			gchar *dirbuf = remove_level_from_path(path);
1182 
1183 			g_free(ckey);
1184 			ckey = g_strdup(filename_from_path(path));
1185 
1186 			skin = skin_parse(dirbuf, cpath, FALSE);
1187 
1188 			g_free(cpath);
1189 			cpath = dirbuf;
1190 			}
1191 		else
1192 			{
1193 			gchar *datafile;
1194 
1195 			datafile = g_strconcat(cpath, "/", ckey, NULL);
1196 			skin = skin_parse(cpath, datafile, FALSE);
1197 			g_free(datafile);
1198 			}
1199 
1200 		}
1201 	else
1202 		{
1203 		skin = ui_skin_load_default(ui, ckey);
1204 		}
1205 
1206 	if (skin)
1207 		{
1208 		ui_skin_set(ui, skin, cpath, ckey);
1209 		success = TRUE;
1210 		}
1211 
1212 	g_free(cpath);
1213 	g_free(ckey);
1214 
1215 	return success;
1216 }
1217 
ui_skin_mode_set(UIData * ui,const gchar * mode_key)1218 gint ui_skin_mode_set(UIData *ui, const gchar *mode_key)
1219 {
1220 	gint success;
1221 	gint ox, oy, ow, oh;
1222 
1223 	if (ui->window)
1224 		{
1225 		gdk_window_get_position(ui->window->window, &ox, &oy);
1226 		}
1227 	else
1228 		{
1229 		ox = oy = 0;
1230 		}
1231 	ow = ui->skin->width;
1232 	oh = ui->skin->height;
1233 
1234 	success = ui_skin_load(ui, ui->skin_path, mode_key);
1235 
1236 	if (slik_smart_placement && success && ui->window)
1237 		{
1238 		gint x, y;
1239 		gint move = FALSE;
1240 
1241 		x = y = 0;
1242 
1243 		if (oy + (oh / 2) > gdk_screen_height() / 2)
1244 			{
1245 			move = TRUE;
1246 			if (oh > ui->skin->height)
1247 				{
1248 				x = ox;
1249 				y = oy + oh - ui->skin->height;
1250 				if (y > gdk_screen_height() - ui->skin->height)
1251 					{
1252 					y = gdk_screen_height() - ui->skin->height;
1253 					}
1254 				}
1255 			else
1256 				{
1257 				x = ox;
1258 				y = oy + oh - ui->skin->height;
1259 				}
1260 			}
1261 		else if (oy < 0)
1262 			{
1263 			move = TRUE;
1264 			x = ox;
1265 			y = 0;
1266 			}
1267 		if (move) gdk_window_move(ui->window->window, x, y);
1268 		}
1269 
1270 	return success;
1271 }
1272 
ui_set_underlay(UIData * ui,GdkPixbuf * pb)1273 void ui_set_underlay(UIData *ui, GdkPixbuf *pb)
1274 {
1275 	if (!ui || !ui->skin) return;
1276 
1277 	skin_set_underlay(ui->skin, ui, pb);
1278 	ui_display_sync(ui, FALSE);
1279 }
1280 
ui_sync_states(void)1281 void ui_sync_states(void)
1282 {
1283 	GList *work;
1284 
1285 	work = slik_ui_list;
1286 	while (work)
1287 		{
1288 		UIData *ui = work->data;
1289 		gint x, y, w, h;
1290 
1291 		if (ui_geometry_get(ui, &x, &y, &w, &h))
1292 			{
1293 			ui_state_set(filename_from_path(ui->skin_path), ui->skin_mode_key, x, y, w, h);
1294 			}
1295 
1296 		work = work->next;
1297 		}
1298 }
1299 
1300 /*
1301  *-------------
1302  * ui_misc text based utils
1303  *-------------
1304  */
1305 
ui_find_by_key(const gchar * key)1306 UIData *ui_find_by_key(const gchar *key)
1307 {
1308 	GList *work;
1309 
1310 	if (!key) return NULL;
1311 
1312 	work = slik_ui_list;
1313 	while(work)
1314 		{
1315 		UIData *ui = work->data;
1316 
1317 		if (ui->key && strcmp(ui->key, key) == 0) return ui;
1318 
1319 		work = work->next;
1320 		}
1321 	return NULL;
1322 }
1323 
1324 /*
1325  *-------------
1326  * grouping (children) support
1327  *-------------
1328  */
1329 
ui_group_set_child(UIData * parent,UIData * child)1330 void ui_group_set_child(UIData *parent, UIData *child)
1331 {
1332 	if (!parent || !child) return;
1333 
1334 	if (child->parent) return;
1335 
1336 	/* children are linear,
1337 	 * that is one parent and the rest are children of that parent (no complex trees!)
1338 	 */
1339 	if (parent->parent) parent = parent->parent;
1340 
1341 	child->parent = parent;
1342 	parent->children = g_list_append(parent->children, child);
1343 
1344 	if (debug_mode) printf("setting %s as a child of %s\n", child->skin_mode_key, parent->skin_mode_key);
1345 }
1346 
ui_group_unset_child(UIData * child)1347 void ui_group_unset_child(UIData *child)
1348 {
1349 	UIData *parent;
1350 
1351 	if (!child || !child->parent) return;
1352 
1353 	parent = child->parent;
1354 	parent->children = g_list_remove(parent->children, child);
1355 	child->parent = NULL;
1356 
1357 	if (debug_mode) printf("removed %s as a child of %s\n", child->skin_mode_key, parent->skin_mode_key);
1358 }
1359 
ui_group_get_parent(UIData * ui)1360 UIData *ui_group_get_parent(UIData *ui)
1361 {
1362 	if (!ui) return NULL;
1363 
1364 	return ui->parent;
1365 }
1366 
ui_group_get_child(UIData * ui,const gchar * key)1367 UIData *ui_group_get_child(UIData *ui, const gchar *key)
1368 {
1369 	GList *work;
1370 
1371 	if (!ui || !key) return NULL;
1372 
1373 	work = ui->children;
1374 	while (work)
1375 		{
1376 		UIData *child = work->data;
1377 		work = work->next;
1378 
1379 		if (child->key && strcmp(child->key, key) == 0) return child;
1380 		}
1381 
1382 	return NULL;
1383 }
1384 
1385 /*
1386  *-------------
1387  * SLIK credits / about / logo
1388  *-------------
1389  */
1390 
ui_slik_logo(void)1391 GdkPixbuf *ui_slik_logo(void)
1392 {
1393 	return gdk_pixbuf_new_from_inline(-1, icon_slik_logo, FALSE, NULL);
1394 }
1395 
1396 static GenericDialog *slik_about = NULL;
1397 
ui_slik_about_destroy_cb(GtkWidget * widget,gpointer data)1398 static void ui_slik_about_destroy_cb(GtkWidget *widget, gpointer data)
1399 {
1400 	slik_about = NULL;
1401 }
1402 
slik_about_toggle_cb(GtkWidget * button,gpointer data)1403 static void slik_about_toggle_cb(GtkWidget *button, gpointer data)
1404 {
1405 	gint *val = data;
1406 	*val = GTK_TOGGLE_BUTTON(button)->active;
1407 
1408 	if (val == &debug_mode)
1409 		{
1410 		printf("Debug set: %d\n", debug_mode);
1411 		}
1412 	else if (val == &debug_skin)
1413 		{
1414 		printf("Skin coordinates set: %d\n", debug_skin);
1415 		}
1416 }
1417 
ui_slik_about(void)1418 static void ui_slik_about(void)
1419 {
1420 	GtkWidget *hbox;
1421 	GtkWidget *label;
1422 	GtkWidget *button;
1423 	GtkWidget *image;
1424 	GdkPixbuf *pixbuf;
1425 	gchar *buf;
1426 
1427 	if (slik_about)
1428 		{
1429 		gtk_window_present(GTK_WINDOW(slik_about->dialog));
1430 		return;
1431 		}
1432 
1433 	slik_about = generic_dialog_new(_("About - SLIK"),
1434 					"SLIK", "about",
1435 					NULL, TRUE, NULL, NULL);
1436 	g_signal_connect(G_OBJECT(slik_about->dialog), "destroy",
1437 			 G_CALLBACK(ui_slik_about_destroy_cb), NULL);
1438 	generic_dialog_add_button(slik_about, GTK_STOCK_CLOSE, NULL, NULL, TRUE);
1439 
1440 	pixbuf = ui_slik_logo();
1441 	image = gtk_image_new_from_pixbuf(pixbuf);
1442 	gdk_pixbuf_unref(pixbuf);
1443 
1444 	gtk_box_pack_start(GTK_BOX(slik_about->vbox), image, FALSE, FALSE, 0);
1445 	gtk_widget_show(image);
1446 
1447 	buf = g_strdup_printf(_("SLIK\nSimpLIstic sKin interface\n%s\nCopyright (c) %s John Ellis\nwebsite: %s\nemail: %s\n\nReleased under the GNU General Public License"),
1448 			      SLIK_VERSION,
1449 			      "2005",
1450 			      "gqmpeg.sourceforge.net",
1451 			      "gqview@users.sourceforge.net");
1452 	label = pref_label_new(slik_about->vbox, buf);
1453 	g_free(buf);
1454 	gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_CENTER);
1455 
1456 	hbox = pref_box_new(slik_about->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, 0);
1457 
1458 	button = gtk_toggle_button_new();
1459 	gtk_widget_set_size_request(button, 8, 8);
1460 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), debug_mode);
1461 	g_signal_connect(G_OBJECT(button), "toggled",
1462 			 G_CALLBACK(slik_about_toggle_cb), &debug_mode);
1463 	gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 4);
1464 	gtk_widget_show(button);
1465 
1466 	button = gtk_toggle_button_new();
1467 	gtk_widget_set_size_request(button, 8, 8);
1468 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), debug_skin);
1469 	g_signal_connect(G_OBJECT(button), "toggled",
1470 			 G_CALLBACK(slik_about_toggle_cb), &debug_skin);
1471 	gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 4);
1472 	gtk_widget_show(button);
1473 
1474 	window_set_icon(slik_about->dialog, NULL, NULL, NULL);
1475 
1476 	gtk_widget_show(slik_about->dialog);
1477 }
1478 
ui_slik_credit(void)1479 GtkWidget *ui_slik_credit(void)
1480 {
1481 	GtkWidget *frame;
1482 	GtkWidget *hbox;
1483 	GtkWidget *label;
1484 	GtkWidget *image;
1485 	GdkPixbuf *pb;
1486 	gchar *buf;
1487 
1488 	frame = gtk_button_new();
1489 	gtk_button_set_relief(GTK_BUTTON(frame), GTK_RELIEF_NONE);
1490 	gtk_container_set_border_width(GTK_CONTAINER(frame), 10);
1491 	g_signal_connect(G_OBJECT(frame), "clicked",
1492 			 G_CALLBACK(ui_slik_about), NULL);
1493 
1494 	hbox = gtk_hbox_new(FALSE, 5);
1495 	gtk_container_add(GTK_CONTAINER(frame), hbox);
1496 	gtk_widget_show(hbox);
1497 
1498 	pb = ui_slik_logo();
1499 	image = gtk_image_new_from_pixbuf(pb);
1500 	gdk_pixbuf_unref(pb);
1501 
1502 	gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 0);
1503 	gtk_widget_show(image);
1504 
1505 	buf = g_strdup_printf(_("utilizes SLIK %s\nSimpLIstic sKin interface"), SLIK_VERSION);
1506 	label = gtk_label_new(buf);
1507 	g_free(buf);
1508 	gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT);
1509 
1510 	gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
1511 	gtk_widget_show(label);
1512 
1513 	return frame;
1514 }
1515 
1516 
1517