1 /*
2   LibRCC UI - GTK library
3 
4   Copyright (C) 2005-2008 Suren A. Chilingaryan <csa@dside.dyndns.org>
5 
6   This library is free software; you can redistribute it and/or modify it
7   under the terms of the GNU Lesser General Public License version 2.1 or later
8   as published by the Free Software Foundation.
9 
10   This library is distributed in the hope that it will be useful, but WITHOUT
11   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
13   for more details.
14 
15   You should have received a copy of the GNU Lesser General Public License
16   along with this program; if not, write to the Free Software Foundation, Inc.,
17   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19 
20 #include <stdio.h>
21 #include <gtk/gtk.h>
22 
23 #include <librcc.h>
24 
25 #include "internal.h"
26 #include "rccnames.h"
27 
28 #define TITLE_WIDTH 224
29 #define TITLE_HEIGHT 10
30 #define BOX_SPACING 1
31 #define BOX_BORDER 0
32 #define FRAME_SPACING 1
33 #define FRAME_BORDER 0
34 #define PAGE_SPACING 1
35 
36 #if GTK_MAJOR_VERSION > 2
37 # define gtk_container_border_width gtk_container_set_border_width
38 # define gtk_widget_set_usize gtk_widget_set_size_request
39 # define gtk_container_children gtk_container_get_children
40 #endif /*  GTK_MAJOR_VERSION */
41 
42 
rccUiCreateInternal(rcc_ui_context ctx)43 rcc_ui_internal rccUiCreateInternal(rcc_ui_context ctx) {
44     return NULL;
45 }
46 
rccUiFreeInternal(rcc_ui_context ctx)47 void rccUiFreeInternal(rcc_ui_context ctx) {
48 }
49 
rccUiMenuCreateWidget(rcc_ui_menu_context ctx)50 rcc_ui_widget rccUiMenuCreateWidget(rcc_ui_menu_context ctx) {
51     return NULL;
52 }
53 
rccUiMenuFreeWidget(rcc_ui_menu_context ctx)54 void rccUiMenuFreeWidget(rcc_ui_menu_context ctx) {
55 }
56 
rccUiMenuGet(rcc_ui_menu_context ctx)57 rcc_ui_id rccUiMenuGet(rcc_ui_menu_context ctx) {
58 #if GTK_MAJOR_VERSION < 3
59     GtkWidget *menu;
60 #endif /* GTK_MAJOR_VERSION */
61 
62     if (!ctx) return (rcc_ui_id)-1;
63 
64     if (ctx->type == RCC_UI_MENU_OPTION) {
65 	switch (rccUiMenuGetRangeType(ctx)) {
66 
67 	    case RCC_OPTION_RANGE_TYPE_BOOLEAN:
68 		return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ctx->widget));
69 	    case RCC_OPTION_RANGE_TYPE_MENU:
70 		break;
71 	    case RCC_OPTION_RANGE_TYPE_RANGE:
72 	        return gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(ctx->widget));
73 	    default:
74 		return (rcc_ui_id)-1;
75 	}
76     }
77 
78 #if GTK_MAJOR_VERSION > 2
79     return gtk_combo_box_get_active(GTK_COMBO_BOX(ctx->widget));
80 #else /* GTK_MAJOR_VERSION < 3 */
81     menu = gtk_option_menu_get_menu(ctx->widget);
82     return g_list_index(GTK_MENU_SHELL(menu)->children, gtk_menu_get_active(GTK_MENU(menu)));
83 #endif /* GTK_MAJOR_VERSION */
84 }
85 
rccUiMenuSet(rcc_ui_menu_context ctx,rcc_ui_id id)86 int rccUiMenuSet(rcc_ui_menu_context ctx, rcc_ui_id id) {
87     if (!ctx) return -1;
88 
89     switch (ctx->type) {
90 	case RCC_UI_MENU_OPTION:
91 	    switch (rccUiMenuGetRangeType(ctx)) {
92 		case RCC_OPTION_RANGE_TYPE_BOOLEAN:
93 		    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ctx->widget),id);
94 		break;
95 		case RCC_OPTION_RANGE_TYPE_MENU:
96 #if GTK_MAJOR_VERSION > 2
97                     gtk_combo_box_set_active(GTK_COMBO_BOX(ctx->widget), id);
98 #else /* GTK_MAJOR_VERSION < 3 */
99 		    gtk_option_menu_set_history(ctx->widget, id);
100 #endif /* GTK_MAJOR_VERSION */
101 		break;
102 		case RCC_OPTION_RANGE_TYPE_RANGE:
103 		    gtk_spin_button_set_value(GTK_SPIN_BUTTON(ctx->widget), id);
104 		default:
105 		    return -1;
106 	    }
107 	break;
108 	default:
109 #if GTK_MAJOR_VERSION > 2
110             gtk_combo_box_set_active(GTK_COMBO_BOX(ctx->widget), id);
111 #else /* GTK_MAJOR_VERSION < 3 */
112 	    gtk_option_menu_set_history(ctx->widget, id);
113 #endif /* GTK_MAJOR_VERSION */
114     }
115 
116     return 0;
117 }
118 
119 
rccGtkMenuLanguageCB(GtkWidget * w,gpointer item)120 static void rccGtkMenuLanguageCB(GtkWidget * w, gpointer item) {
121     rccUiRestoreLanguage(((rcc_ui_menu_context)item)->uictx);
122 }
123 
rccUiMenuConfigureWidget(rcc_ui_menu_context ctx)124 int rccUiMenuConfigureWidget(rcc_ui_menu_context ctx) {
125     unsigned int i;
126     unsigned long num;
127 
128     rcc_context rccctx;
129     rcc_ui_context uictx;
130 
131     rcc_language_config config;
132     rcc_language_id language_id;
133 
134     rcc_class_id class_id;
135     rcc_charset_id charset_id;
136     rcc_engine_id engine_id;
137     gint value_id = 0;
138 
139     const char *language;
140     const char *charset;
141     const char *engine;
142 
143     rcc_option_range *range;
144     rcc_option_name *option_name;
145     rcc_option_value_names optnames;
146 
147     GtkWidget *menu = NULL;
148     GtkWidget *item;
149 #if GTK_MAJOR_VERSION > 2
150     GtkCellRenderer *cell = NULL;
151     GtkTreeStore *store = NULL;
152     GtkTreeIter iter;
153     GtkAdjustment *adjustment;
154 #else /* GTK_MAJOR_VERSION < 3 */
155     GtkWidget *list = NULL;
156     GtkObject *adjustment;
157 #endif /* GTK_MAJOR_VERSION */
158 
159     if (!ctx) return -1;
160 
161     uictx = ctx->uictx;
162     rccctx = uictx->rccctx;
163 
164     switch (ctx->type) {
165 	case RCC_UI_MENU_LANGUAGE:
166 #if GTK_MAJOR_VERSION < 3
167 	case RCC_UI_MENU_CHARSET:
168 #endif /* GTK_MAJOR_VERSION */
169 	case RCC_UI_MENU_ENGINE:
170             if (ctx->widget) menu = ctx->widget;
171             else
172 #if GTK_MAJOR_VERSION > 2
173                 menu = gtk_combo_box_text_new();
174 	    gtk_combo_box_text_remove_all(GTK_COMBO_BOX_TEXT(menu));
175 #else /* GTK_MAJOR_VERSION < 3 */
176                 menu = gtk_option_menu_new();
177 	    gtk_option_menu_remove_menu(GTK_OPTION_MENU(menu));
178 	    list = gtk_menu_new();
179 #endif /* GTK_MAJOR_VERSION */
180 
181             ctx->widget = menu;
182         break;
183         default:
184             ;
185     }
186 
187 #if GTK_MAJOR_VERSION > 2
188     switch (ctx->type) {
189 	case RCC_UI_MENU_CHARSET:
190             if (ctx->widget) {
191                 menu = ctx->widget;
192                 store = GTK_TREE_STORE(gtk_combo_box_get_model(GTK_COMBO_BOX(menu)));
193                 gtk_tree_store_clear(store);
194             } else {
195                 store = gtk_tree_store_new(2, G_TYPE_STRING, G_TYPE_BOOLEAN);
196                 menu = gtk_combo_box_new_with_model(GTK_TREE_MODEL(store));
197                 g_object_unref (store);
198 
199                 cell = gtk_cell_renderer_text_new();
200                 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(menu), cell, TRUE);
201                 gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT(menu), cell, "text", 0, "sensitive", 1, NULL);
202 
203                 ctx->widget = menu;
204             }
205         break;
206         default:
207             ;
208     }
209 #endif /* GTK_MAJOR_VERSION */
210 
211     switch (ctx->type) {
212 	case RCC_UI_MENU_LANGUAGE:
213 	    num = rccGetLanguageNumber(rccctx);
214 
215 	    for (i=0; i<(num?num:1); i++) {
216 		language = rccUiGetLanguageName(uictx, (rcc_language_id)i);
217 		if (!language) continue;
218 
219 #if GTK_MAJOR_VERSION > 2
220                 gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(menu), NULL, language);
221 #else /* GTK_MAJOR_VERSION < 3 */
222 		item = gtk_menu_item_new_with_label(language);
223 		gtk_widget_show(item);
224                 gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(rccGtkMenuLanguageCB), ctx);
225 		gtk_menu_append(GTK_MENU(list), item);
226 #endif /* GTK_MAJOR_VERSION */
227 	    }
228 
229 	    language_id = rccGetSelectedLanguage(rccctx);
230 	    if (language_id == (rcc_language_id)-1) language_id = 0;
231 
232 	    value_id = language_id;
233 	break;
234 	case RCC_UI_MENU_CHARSET:
235 	    language_id = (rcc_language_id)rccUiMenuGet(uictx->language);
236 	    class_id = rccUiMenuGetClassId(ctx);
237 	    config = rccGetConfig(rccctx, language_id);
238 	    num = rccConfigGetClassCharsetNumber(config, class_id);
239 
240 	    for (i=0;i<(num?num:1);i++) {
241 		charset = rccUiGetCharsetName(uictx, language_id, class_id, (rcc_charset_id)i);
242 		if (!charset) continue;
243 
244 #if GTK_MAJOR_VERSION > 2
245                 gtk_tree_store_append(store, &iter, NULL);
246                 gtk_tree_store_set(store, &iter, 0, charset, 1, !rccIsDisabledCharsetName(rccctx, class_id, charset), -1);
247 #else /* GTK_MAJOR_VERSION < 3 */
248 		item = gtk_menu_item_new_with_label(charset);
249 		if (rccIsDisabledCharsetName(rccctx, class_id, charset))
250 		    gtk_widget_set_sensitive(item, 0);
251 		else
252 		    gtk_widget_show(item);
253     		gtk_menu_append(GTK_MENU(list), item);
254 #endif /* GTK_MAJOR_VERSION */
255 	    }
256 
257 
258 	    charset_id = rccConfigGetSelectedCharset(config, class_id);
259 	    if (charset_id == (rcc_charset_id)-1) charset_id = 0;
260 	    value_id = charset_id;
261 	break;
262 	case RCC_UI_MENU_ENGINE:
263 	    language_id = (rcc_language_id)rccUiMenuGet(uictx->language);
264 	    config = rccGetConfig(rccctx, language_id);
265 	    num = rccConfigGetEngineNumber(config);
266 
267 	    for (i=0;i<(num?num:1);i++) {
268 		engine = rccUiGetEngineName(uictx, language_id, (rcc_engine_id)i);
269 		if (!engine) continue;
270 
271 #if GTK_MAJOR_VERSION > 2
272                 gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(menu), NULL, engine);
273 #else /* GTK_MAJOR_VERSION < 3 */
274 		item = gtk_menu_item_new_with_label(engine);
275 		gtk_widget_show(item);
276     		gtk_menu_append(GTK_MENU(list), item);
277 #endif /* GTK_MAJOR_VERSION */
278 	    }
279 
280 	    engine_id = rccConfigGetCurrentEngine(config);
281 	    if (engine_id == (rcc_engine_id)-1) engine_id = 0;
282 	    value_id = engine_id;
283 	break;
284 	case RCC_UI_MENU_OPTION:
285 	    switch (rccUiMenuGetRangeType(ctx)) {
286 		case RCC_OPTION_RANGE_TYPE_BOOLEAN:
287 		    if (!ctx->widget) {
288 		        item = gtk_check_button_new_with_label(rccUiGetOptionName(uictx, rccUiMenuGetOption(ctx)));
289 			ctx->widget = item;
290 		    }
291     		    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ctx->widget), rccGetOption(rccctx, rccUiMenuGetOption(ctx)));
292 		break;
293 		case RCC_OPTION_RANGE_TYPE_MENU:
294 		    if (!ctx->widget) {
295 			option_name = rccUiGetOptionRccName(uictx, rccUiMenuGetOption(ctx));
296 			if (!option_name) return -1;
297 			optnames = option_name->value_names;
298 			if (!optnames) return -1;
299 
300 #if GTK_MAJOR_VERSION > 2
301 	                menu = gtk_combo_box_text_new();
302 			for (i=0;optnames[i];i++) {
303                             gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(menu), NULL, optnames[i]);
304 			}
305 #else /* GTK_MAJOR_VERSION < 3 */
306 			list = gtk_menu_new();
307 			for (i=0;optnames[i];i++) {
308 			    item = gtk_menu_item_new_with_label(optnames[i]);
309 			    gtk_widget_show(item);
310     			    gtk_menu_append(GTK_MENU(list), item);
311 			}
312 
313 			menu = gtk_option_menu_new();
314 
315 			gtk_option_menu_remove_menu(GTK_OPTION_MENU(menu));
316 			gtk_option_menu_set_menu(GTK_OPTION_MENU(menu), list);
317 #endif /* GTK_MAJOR_VERSION */
318 
319 			ctx->widget = menu;
320 		    }
321 #if GTK_MAJOR_VERSION > 2
322                     gtk_combo_box_set_active(GTK_COMBO_BOX(ctx->widget), rccGetOption(rccctx, rccUiMenuGetOption(ctx)));
323 #else /* GTK_MAJOR_VERSION < 3 */
324 		    gtk_option_menu_set_history(GTK_OPTION_MENU(ctx->widget), rccGetOption(rccctx, rccUiMenuGetOption(ctx)));
325 #endif /* GTK_MAJOR_VERSION */
326 		break;
327 		case RCC_OPTION_RANGE_TYPE_RANGE:
328 		    range = rccUiMenuGetRange(ctx);
329 		    adjustment = gtk_adjustment_new(rccGetOption(rccctx, rccUiMenuGetOption(ctx)), range->min, range->max, range->step, 0, 0);
330 /*		    item = gtk_hscale_new(GTK_ADJUSTMENT(adjustment));
331 		    gtk_scale_set_digits(GTK_SCALE(item), 0);*/
332 		    item = gtk_spin_button_new(GTK_ADJUSTMENT(adjustment), range->step, 0);
333 		    ctx->widget = item;
334 		break;
335 		default:
336 		    return -1;
337 	    }
338 	break;
339 	default:
340 	    return -1;
341     }
342 
343 
344     switch (ctx->type) {
345 	case RCC_UI_MENU_LANGUAGE:
346 #if GTK_MAJOR_VERSION > 2
347             g_signal_connect(G_OBJECT(menu), "changed", G_CALLBACK(rccGtkMenuLanguageCB), ctx);
348 #endif /* GTK_MAJOR_VERSION */
349 
350 	case RCC_UI_MENU_CHARSET:
351 	case RCC_UI_MENU_ENGINE:
352 #if GTK_MAJOR_VERSION > 2
353             gtk_combo_box_set_active(GTK_COMBO_BOX(menu), value_id);
354 #else /* GTK_MAJOR_VERSION < 3 */
355 	    gtk_option_menu_set_menu(GTK_OPTION_MENU(menu), list);
356 	    gtk_option_menu_set_history(GTK_OPTION_MENU(menu), value_id);
357 #endif /* GTK_MAJOR_VERSION */
358 
359         break;
360         default:
361             ;
362     }
363 
364     return 0;
365 }
366 
rccUiBoxCreate(rcc_ui_menu_context ctx,const char * title)367 rcc_ui_box rccUiBoxCreate(rcc_ui_menu_context ctx, const char *title) {
368     GtkWidget *hbox, *label;
369 #if GTK_MAJOR_VERSION > 2
370     hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, BOX_SPACING);
371 #else /* GTK_MAJOR_VERSION < 3 */
372     hbox = gtk_hbox_new(FALSE, BOX_SPACING);
373 #endif /* GTK_MAJOR_VERSION */
374 
375 
376     gtk_container_border_width(GTK_CONTAINER(hbox), BOX_BORDER);
377     if ((ctx->type != RCC_UI_MENU_OPTION)||(rccUiMenuGetRangeType(ctx) != RCC_OPTION_RANGE_TYPE_BOOLEAN)) {
378 	label = gtk_label_new(title);
379 	gtk_widget_show(label);
380 	gtk_widget_set_usize(label, TITLE_WIDTH, TITLE_HEIGHT);
381 	gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
382     }
383     gtk_widget_show((GtkWidget*)ctx->widget);
384     gtk_box_pack_start(GTK_BOX(hbox), (GtkWidget*)ctx->widget, TRUE, TRUE, 0);
385     return (rcc_ui_box)hbox;
386 }
387 
rccUiFrameCreate(rcc_ui_frame_context ctx,const char * title)388 rcc_ui_frame rccUiFrameCreate(rcc_ui_frame_context ctx, const char *title) {
389     GtkWidget *frame, *box;
390 
391     if (!ctx) return NULL;
392 
393     frame = gtk_frame_new(title?title:"");
394     gtk_container_border_width(GTK_CONTAINER(frame), FRAME_BORDER);
395 
396 #if GTK_MAJOR_VERSION > 2
397     box = gtk_box_new(GTK_ORIENTATION_VERTICAL, FRAME_SPACING);
398 #else /* GTK_MAJOR_VERSION < 3 */
399     box = gtk_vbox_new(FALSE, FRAME_SPACING);
400 #endif /* GTK_MAJOR_VERSION */
401     gtk_widget_show(box);
402     gtk_container_add(GTK_CONTAINER(frame), box);
403 
404     return (rcc_ui_frame)frame;
405 }
406 
rccUiFrameFree(rcc_ui_frame_context ctx)407 void rccUiFrameFree(rcc_ui_frame_context ctx) {
408 }
409 
410 
rccUiFrameAdd(rcc_ui_frame_context ctx,rcc_ui_box box)411 int rccUiFrameAdd(rcc_ui_frame_context ctx, rcc_ui_box box) {
412     GtkWidget *vbox;
413 
414     if ((!ctx)||(!box)) return -1;
415 
416     vbox = gtk_container_children(GTK_CONTAINER(ctx->frame))->data;
417     gtk_widget_show(GTK_WIDGET(box));
418     gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(box), FALSE, FALSE, 0);
419     return 0;
420 }
421 
rccUiPageCreate(rcc_ui_context ctx,const char * title)422 rcc_ui_page rccUiPageCreate(rcc_ui_context ctx, const char *title) {
423     GtkWidget *vbox;
424 #if GTK_MAJOR_VERSION > 2
425     vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, PAGE_SPACING);
426 #else /* GTK_MAJOR_VERSION < 3 */
427     vbox = gtk_vbox_new(FALSE, PAGE_SPACING);
428 #endif /* GTK_MAJOR_VERSION */
429     return (rcc_ui_page)vbox;
430 }
431 
rccUiPageAdd(rcc_ui_page page,rcc_ui_frame frame)432 int rccUiPageAdd(rcc_ui_page page, rcc_ui_frame frame) {
433     if ((!page)||(!frame)) return -1;
434     gtk_widget_show(frame);
435     gtk_box_pack_start(GTK_BOX(page), GTK_WIDGET(frame), FALSE, FALSE, 0);
436     return 0;
437 }
438