/* * File: dillocfg-gtk_option.c * * Copyright (C) 2003 Kiyo * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. */ #include #include #include #include #include #include "../config.h" #include "../src/intl.h" #include "dillocfg_option.h" #include "dillocfg_token.h" /* Private class. */ typedef struct { OptionBase base; GtkWidget *button; gboolean value; gboolean default_value; } CheckOption; typedef struct { OptionBase base; GtkWidget *hbox; GtkWidget *entry; gchar *value; gchar *default_value; gboolean allow_space; } EntryOption; typedef struct { OptionBase base; GtkWidget *hbox; GtkWidget *combo; gchar *value; gchar *default_value; } ComboOption; typedef ComboOption FontOption; typedef struct { OptionBase base; GtkWidget *hbox; GtkWidget *option_menu; gchar **items; gint value; gint default_value; } SelectOption; typedef struct { OptionBase base; GtkWidget *hbox; GtkWidget *label; GdkImage *image; GtkWidget *button_image; GtkWidget *dialog; GdkColor *value; GdkColor *default_value; } ColorOption; typedef struct { OptionBase base; GtkWidget *hbox; GtkWidget *button; double value; double default_value; gboolean is_integer; } SpinOption; typedef struct { gint x; gint y; } Geometry; typedef struct { OptionBase base; GtkWidget *hbox; GtkWidget *button; GtkWidget *button2; Geometry value; Geometry default_value; } GeometryOption; CheckOption *CheckOption_new(guint token, GtkWidget *table, gint x, gint y); void CheckOption_init(CheckOption *o, gboolean use_default); void CheckOption_set(CheckOption *o, gchar *value); gchar *CheckOption_get(CheckOption *o); void CheckOption_free(CheckOption *o); EntryOption *EntryOption_new(guint token, GtkWidget *table, gint x, gint y); void EntryOption_init(EntryOption *o, gboolean use_default); void EntryOption_set(EntryOption *o, gchar *value); gchar *EntryOption_get(EntryOption *o); void EntryOption_free(EntryOption *o); ComboOption *ComboOption_new(guint token, GtkWidget *table, gint x, gint y); void ComboOption_init(ComboOption *o, gboolean use_default); void ComboOption_set(ComboOption *o, gchar *value); gchar *ComboOption_get(ComboOption *o); void ComboOption_free(ComboOption *o); FontOption *FontOption_new(guint token, GtkWidget *table, gint x, gint y); SelectOption *SelectOption_new(guint token, GtkWidget *table, gint x, gint y); void SelectOption_init(SelectOption *o, gboolean use_default); void SelectOption_set(SelectOption *o, gchar *value); gchar *SelectOption_get(SelectOption *o); void SelectOption_free(SelectOption *o); ColorOption *ColorOption_new(guint token, GtkWidget *table, gint x, gint y); void ColorOption_init(ColorOption *o, gboolean use_default); void ColorOption_set(ColorOption *o, gchar *value); gchar *ColorOption_get(ColorOption *o); void ColorOption_free(ColorOption *o); SpinOption *SpinOption_new(guint token, GtkWidget *table, gint x, gint y); void SpinOption_init(SpinOption *o, gboolean use_default); void SpinOption_set(SpinOption *o, gchar *value); gchar *SpinOption_get(SpinOption *o); void SpinOption_free(SpinOption *o); GeometryOption *GeometryOption_new(guint token, GtkWidget *table, gint x, gint y); void GeometryOption_init(GeometryOption *o, gboolean use_default); void GeometryOption_set(GeometryOption *o, gchar *value); gchar *GeometryOption_get(GeometryOption *o); void GeometryOption_free(SpinOption *o); Option *Option_new(guint token, GList **list, GtkWidget *table, gint x, gint y) { guint type = get_token_type(token); Option *o; switch (type) { case CHECK_OPTION: o = (Option *)CheckOption_new(token, table, x, y); break; case ENTRY_OPTION: o = (Option *)EntryOption_new(token, table, x, y); break; case COMBO_OPTION: o = (Option *)ComboOption_new(token, table, x, y); break; case FONT_OPTION: o = (Option *)FontOption_new(token, table, x, y); break; case SELECT_OPTION: case COOKIE: o = (Option *)SelectOption_new(token, table, x, y); break; case COLOR_OPTION: o = (Option *)ColorOption_new(token, table, x, y); break; case SPIN_OPTION: o = (Option *)SpinOption_new (token, table, x, y); break; case GEOMETRY_OPTION: o = (Option *)GeometryOption_new(token, table, x, y); break; default: o = (Option *)NULL; } set_token_object(token, o); *list = g_list_append(*list, o); return o; } void Option_init(Option *o, gboolean use_default) { return ((o) ? o->base.init(o, use_default) : NULL); } void Option_set(Option *o, gchar *value) { return ((o) ? o->base.set(o, value) : NULL); } gchar *Option_get(Option *o, FILE *fp) { if (!o) return NULL; if (fp && o->base.get(o)) fprintf(fp, "%s\n", o->base.get(o)); return ((o) ? o->base.get(o) : NULL); } void Option_free(Option *o, GList **list) { return ((o) ? o->base.free(o) : NULL); } CheckOption *CheckOption_new(guint token, GtkWidget *table, gint x, gint y) { CheckOption *o = g_new(CheckOption, 1); o->base.token = token; o->base.init = CheckOption_init; o->base.set = CheckOption_set; o->base.get = CheckOption_get; o->base.free = CheckOption_free; o->button = gtk_check_button_new_with_label(_(get_token_label(token))); o->base.set(o, (gchar *)get_token_value(token)); o->default_value = o->value; gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(o->button), o->value); gtk_table_attach_defaults(GTK_TABLE(table), o->button, x, x + 1, y, y + 1); return o; } void CheckOption_init(CheckOption *o, gboolean use_default) { if (use_default) o->value = o->default_value; gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(o->button), o->value); } void CheckOption_set(CheckOption *o, gchar *value) { if (value) o->value = (strcmp(value, "YES") == 0); } gchar *CheckOption_get(CheckOption *o) { return g_strdup_printf("%s=%s", get_token_name(o->base.token), (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(o->button))) ? "YES" : "NO"); } void CheckOption_free(CheckOption *o) { g_free(o); } EntryOption *EntryOption_new(guint token, GtkWidget *table, gint x, gint y) { EntryOption *o = g_new(EntryOption, 1); GtkWidget *label = gtk_label_new(_(get_token_label(token))); o->base.token = token; o->base.init = EntryOption_init; o->base.set = EntryOption_set; o->base.get = EntryOption_get; o->base.free = EntryOption_free; o->hbox = gtk_hbox_new(FALSE, 0); o->entry = gtk_entry_new(); o->value = NULL; o->base.set(o, (gchar *)get_token_value(token)); o->default_value = g_strdup(o->value); o->allow_space = (gboolean)get_token_option(token); //gtk_box_set_homogeneous(GTK_BOX(o->hbox), TRUE); gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT); if (o->value) gtk_entry_set_text(GTK_ENTRY(o->entry), o->value); gtk_box_pack_start(GTK_BOX(o->hbox), label, FALSE, FALSE, 10); gtk_box_pack_end(GTK_BOX(o->hbox), o->entry, TRUE, TRUE, 5); gtk_table_attach_defaults(GTK_TABLE(table), o->hbox, x, x + 1, y, y + 1); return o; } void EntryOption_init(EntryOption *o, gboolean use_default) { if (use_default) { g_free(o->value); o->value = g_strdup(o->default_value); } if (o->value) gtk_entry_set_text(GTK_ENTRY(o->entry), o->value); } void EntryOption_set(EntryOption *o, gchar *value) { g_free(o->value); o->value = g_strdup(value); } gchar *EntryOption_get(EntryOption *o) { gchar *format; gchar *value = gtk_entry_get_text(GTK_ENTRY(o->entry)); if (!value) return NULL; if (strcmp(value, "") == 0) return NULL; if (o->allow_space) format = "%s=\"%s\""; else format = "%s=%s"; return g_strdup_printf(format, get_token_name(o->base.token), value); } void EntryOption_free(EntryOption *o) { g_free(o); } ComboOption *ComboOption_new(guint token, GtkWidget *table, gint x, gint y) { ComboOption *o = g_new(ComboOption, 1); GList *list = NULL; gchar **items = NULL; gint i; o->base.token = token; o->base.init = ComboOption_init; o->base.set = ComboOption_set; o->base.get = ComboOption_get; o->base.free = ComboOption_free; o->hbox = gtk_hbox_new(FALSE, 0); o->combo = gtk_combo_new(); items = (gchar **)get_token_option(token); for (i = 0; items[i]; i++) list = g_list_append(list, items[i]); o->value = NULL; gtk_combo_set_popdown_strings(GTK_COMBO(o->combo), list); g_free(list); o->base.set(o, (gchar *)get_token_value(token)); o->default_value = g_strdup(o->value); if (o->value) gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (o->combo)->entry), o->value); gtk_box_pack_start(GTK_BOX(o->hbox), gtk_label_new(_(get_token_label(token))), FALSE, FALSE, 5); gtk_box_pack_start(GTK_BOX(o->hbox), o->combo, TRUE, TRUE, 5); gtk_table_attach_defaults(GTK_TABLE(table), o->hbox, x, x + 1, y, y + 1); return o; } void ComboOption_init(ComboOption *o, gboolean use_default) { if (use_default) { g_free(o->value); o->value = g_strdup(o->default_value); } if (o->value) gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (o->combo)->entry), o->value); } void ComboOption_set(ComboOption *o, gchar *value) { g_free(o->value); o->value = g_strdup(value); } gchar *ComboOption_get(ComboOption *o) { gchar *value = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO (o->combo)->entry)); if (!value) return NULL; if (strcmp(value, "") == 0) return NULL; return g_strdup_printf("%s=\"%s\"", get_token_name(o->base.token), value); } void ComboOption_free(ComboOption *o) { g_free(o); } /* FontOption class extends ComboOption. */ FontOption *FontOption_new(guint token, GtkWidget *table, gint x, gint y) { FontOption *o = g_new(FontOption, 1); GList *list = NULL; #define MAX_FONT_NAME 1024 gchar buf[MAX_FONT_NAME]; //max font name FILE *fp; o->base.token = token; o->base.init = ComboOption_init; o->base.set = ComboOption_set; o->base.get = ComboOption_get; o->base.free = ComboOption_free; o->hbox = gtk_hbox_new(FALSE, 0); o->combo = gtk_combo_new(); #ifdef DISABLE_ANTI_ALIAS fp = popen("xlsfonts -fn \"-*-*\"|cut -d \"-\" -f 2-3|sort|uniq", "r"); list = g_list_append(list, "*-*"); list = g_list_append(list, "*-gothic"); #else fp = popen("fc-list|sed \"s/[:|,]/\\n#/g\"|grep -v \"^#\"|sort|uniq", "r"); list = g_list_append(list, "serif"); list = g_list_append(list, "sans-serif"); list = g_list_append(list, "monospace"); #endif while(fgets(buf, MAX_FONT_NAME, fp)) { g_strchomp(buf); list = g_list_append(list, g_strdup(buf)); } pclose(fp); o->value = NULL; if (list) gtk_combo_set_popdown_strings(GTK_COMBO(o->combo), list); g_list_free(list); o->base.set(o, (gchar *)get_token_value(token)); o->default_value = g_strdup(o->value); if (o->value) gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (o->combo)->entry), o->value); gtk_box_pack_start(GTK_BOX(o->hbox), gtk_label_new(_(get_token_label(token))), FALSE, FALSE, 5); gtk_box_pack_start(GTK_BOX(o->hbox), o->combo, TRUE, TRUE, 5); gtk_table_attach_defaults(GTK_TABLE(table), o->hbox, x, x + 1, y, y + 1); return o; } SelectOption *SelectOption_new(guint token, GtkWidget *table, gint x, gint y) { SelectOption *o = g_new(SelectOption, 1); GtkWidget *menu = gtk_menu_new (); gint i; o->base.token = token; o->base.init = SelectOption_init; o->base.set = SelectOption_set; o->base.get = SelectOption_get; o->base.free = SelectOption_free; o->hbox = gtk_hbox_new(FALSE, 0); o->option_menu = gtk_option_menu_new(); o->items = (gchar **)get_token_option(token); for (i = 0; o->items[i]; i++) gtk_menu_append(GTK_MENU(menu), gtk_menu_item_new_with_label(o->items[i])); gtk_option_menu_set_menu (GTK_OPTION_MENU(o->option_menu), menu); o->base.set(o, (gchar *)get_token_value(token)); o->default_value = o->value; gtk_option_menu_set_history(GTK_OPTION_MENU(o->option_menu), o->value); gtk_box_pack_start(GTK_BOX(o->hbox), gtk_label_new(_(get_token_label(token))), FALSE, FALSE, 5); gtk_box_pack_start(GTK_BOX(o->hbox), o->option_menu, TRUE, TRUE, 5); gtk_table_attach_defaults(GTK_TABLE(table), o->hbox, x, x + 1, y, y + 1); return o; } void SelectOption_init(SelectOption *o, gboolean use_default) { if (use_default) o->value = o->default_value; gtk_option_menu_set_history (GTK_OPTION_MENU(o->option_menu), o->value); } void SelectOption_set(SelectOption *o, gchar *value) { gint i; for (i = 0; o->items[i]; i++) if (!g_strcasecmp(value, o->items[i])) o->value = i; } gchar *SelectOption_get(SelectOption *o) { GtkWidget *menu = gtk_option_menu_get_menu(GTK_OPTION_MENU(o->option_menu)); /* always null... gchar *str = NULL; GtkWidget *item = gtk_menu_get_active(GTK_MENU(menu)); GtkWidget *label = GTK_BIN(GTK_MENU_ITEM(item))->child; if(!label) str = g_strdup(""); else gtk_label_get(GTK_LABEL(label), &str); */ gint i = g_list_index(GTK_MENU_SHELL(menu)->children, GTK_OPTION_MENU(o->option_menu)->menu_item); gchar *format = (get_token_type(o->base.token) == COOKIE) ? "%s %s" : "%s=\"%s\""; return g_strdup_printf(format, get_token_name(o->base.token), o->items[i]); } void SelectOption_free(SelectOption *o) { g_free(o); } void change_color_GdkColor(const double *color, GdkColor* o) { o->red = color[0] * 65535; o->green = color[1] * 65535; o->blue = color[2] * 65535; } void change_color_double(const GdkColor* o, double *color) { color[0] = o->red / (double)65535; color[1] = o->green / (double)65535; color[2] = o->blue / (double)65535; } void ColorDialog_ok(GtkButton *button, gpointer user_data) { ColorOption *o = (ColorOption *)user_data; double color[4]; gtk_color_selection_get_color( GTK_COLOR_SELECTION(GTK_COLOR_SELECTION_DIALOG(o->dialog)->colorsel), color); change_color_GdkColor(color, o->value); ColorOption_init(o, FALSE); gtk_widget_destroy(o->dialog); } void ColorDialog_cancel(GtkButton *button, gpointer user_data) { ColorOption *o = (ColorOption *)user_data; gtk_widget_destroy(o->dialog); } void ColorOption_clicked(GtkButton *button, gpointer user_data) { ColorOption *o = (ColorOption *)user_data; gchar *title; double color[4]; gtk_label_get(GTK_LABEL(o->label), &title); change_color_double(o->value, color); o->dialog = gtk_color_selection_dialog_new(title); gtk_color_selection_set_color( GTK_COLOR_SELECTION(GTK_COLOR_SELECTION_DIALOG(o->dialog)->colorsel), color); gtk_signal_connect( GTK_OBJECT(GTK_COLOR_SELECTION_DIALOG(o->dialog)->ok_button), "clicked", GTK_SIGNAL_FUNC(ColorDialog_ok), o); gtk_signal_connect( GTK_OBJECT(GTK_COLOR_SELECTION_DIALOG(o->dialog)->cancel_button), "clicked", GTK_SIGNAL_FUNC(ColorDialog_cancel), o); gtk_widget_hide(GTK_COLOR_SELECTION_DIALOG(o->dialog)->help_button); gtk_widget_show(o->dialog); } #define PREVIEW_SIZE 48 ColorOption *ColorOption_new(guint token, GtkWidget *table, gint x, gint y) { ColorOption *o = g_new(ColorOption, 1); GtkWidget *button = gtk_button_new(); o->base.token = token; o->base.init = ColorOption_init; o->base.set = ColorOption_set; o->base.get = ColorOption_get; o->base.free = ColorOption_free; o->hbox = gtk_hbox_new(FALSE, 0); o->label = gtk_label_new(_(get_token_label(token))); o->image = gdk_image_new(GDK_IMAGE_NORMAL, gdk_visual_get_system(), PREVIEW_SIZE, PREVIEW_SIZE); o->button_image = gtk_image_new(o->image, NULL); o->value = g_new(GdkColor, 1); o->base.set(o, (gchar *)get_token_value(token)); o->default_value = g_new(GdkColor, 1); o->default_value = gdk_color_copy(o->value); gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(ColorOption_clicked), o); gtk_container_add(GTK_CONTAINER(button), o->button_image); //gtk_box_set_homogeneous(GTK_BOX(o->hbox), TRUE); gtk_label_set_justify (GTK_LABEL(o->label), GTK_JUSTIFY_LEFT); gtk_box_pack_start(GTK_BOX(o->hbox), button, FALSE, FALSE, 10); gtk_box_pack_start(GTK_BOX(o->hbox), o->label, FALSE, FALSE, 10); gtk_table_attach_defaults(GTK_TABLE(table), o->hbox, x, x + 1, y, y + 1); return o; } guint32 change_color(GdkColor *o) { gdk_colormap_alloc_color(gdk_colormap_get_system(), o, TRUE, TRUE); return o->pixel; } void ColorOption_init(ColorOption *o, gboolean use_default) { int i, j; if (use_default) o->value = gdk_color_copy(o->default_value); for (i = 0; i < PREVIEW_SIZE; i++) for (j = 0; j < PREVIEW_SIZE; j++) gdk_image_put_pixel(o->image, i, j, change_color(o->value)); gtk_image_set(GTK_IMAGE(o->button_image), o->image, NULL); } void ColorOption_set(ColorOption *o, gchar *value) { guint32 i; if (strlen(value) != 8) return; if (value[0] != '0' || value[1] != 'x') return; sscanf(value, "0x%x", &i); o->value->red = (i&0x00FF0000) >> 8; o->value->green = (i&0x0000FF00); o->value->blue = (i&0x000000FF) << 8; } gchar *ColorOption_get(ColorOption *o) { return g_strdup_printf("%s=0x%.2x%.2x%.2x", get_token_name(o->base.token), o->value->red >> 8, o->value->green >> 8, o->value->blue >> 8); } void ColorOption_free(ColorOption *o) { gdk_image_destroy (o->image); g_free(o); } SpinOption *SpinOption_new(guint token, GtkWidget *table, gint x, gint y) { SpinOption *o = g_new(SpinOption, 1); OptionAdjustment_t *opt = (OptionAdjustment_t *)get_token_option(token); o->base.token = token; o->base.init = SpinOption_init; o->base.set = SpinOption_set; o->base.get = SpinOption_get; o->base.free = SpinOption_free; o->hbox = gtk_hbox_new(FALSE, 0); o->button = gtk_spin_button_new( (GtkAdjustment *)gtk_adjustment_new(0, opt->lower, opt->upper, opt->increment, opt->increment, opt->increment), opt->increment, opt->digits); o->base.set(o, (gchar *)get_token_value(token)); o->default_value = o->value; o->is_integer = (opt->digits == 0); gtk_box_pack_start(GTK_BOX(o->hbox), gtk_label_new(_(get_token_label(token))), FALSE, FALSE, 10); gtk_box_pack_start(GTK_BOX(o->hbox), o->button, FALSE, FALSE, 10); gtk_table_attach_defaults(GTK_TABLE(table), o->hbox, x, x + 1, y, y + 1); return o; } void SpinOption_init(SpinOption *o, gboolean use_default) { if (use_default) o->value = o->default_value; gtk_spin_button_set_value(GTK_SPIN_BUTTON(o->button), o->value); } void SpinOption_set(SpinOption *o, gchar *value) { if (o->is_integer) o->value = strtol(value, NULL, 0); else o->value = strtod(value, NULL); } gchar *SpinOption_get(SpinOption *o) { if (o->is_integer) return g_strdup_printf("%s=%d", get_token_name(o->base.token), gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(o->button))); else { gchar *float_str = g_strdup_printf("%s=%f", get_token_name(o->base.token), gtk_spin_button_get_value_as_float(GTK_SPIN_BUTTON(o->button))); if (strchr(float_str, ',')) strchr(float_str, ',')[0] = '.'; return float_str; } } void SpinOption_free(SpinOption *o) { g_free(o); } GeometryOption *GeometryOption_new(guint token, GtkWidget *table, gint x, gint y) { GeometryOption *o = g_new(GeometryOption, 1); OptionAdjustment_t *opt = (OptionAdjustment_t *)get_token_option(token); o->base.token = token; o->base.init = GeometryOption_init; o->base.set = GeometryOption_set; o->base.get = GeometryOption_get; o->base.free = GeometryOption_free; o->hbox = gtk_hbox_new(FALSE, 0); o->button = gtk_spin_button_new( (GtkAdjustment *)gtk_adjustment_new(0, opt->lower, opt->upper, opt->increment, opt->increment, opt->increment), opt->increment, 0); o->button2 = gtk_spin_button_new( (GtkAdjustment *)gtk_adjustment_new(0, opt->lower, opt->upper, opt->increment, opt->increment, opt->increment), opt->increment, 0); o->base.set(o, (gchar *)get_token_value(token)); o->default_value = o->value; gtk_box_pack_start(GTK_BOX(o->hbox), gtk_label_new(_(get_token_label(token))), FALSE, FALSE, 10); gtk_box_pack_start(GTK_BOX(o->hbox), o->button, FALSE, FALSE, 10); gtk_box_pack_start(GTK_BOX(o->hbox), gtk_label_new("X"), FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(o->hbox), o->button2, FALSE, FALSE, 10); gtk_table_attach_defaults(GTK_TABLE(table), o->hbox, x, x + 1, y, y + 1); return o; } void GeometryOption_init(GeometryOption *o, gboolean use_default) { if(use_default) o->value = o->default_value; gtk_spin_button_set_value(GTK_SPIN_BUTTON(o->button), o->value.x); gtk_spin_button_set_value(GTK_SPIN_BUTTON(o->button2), o->value.y); } void GeometryOption_set(GeometryOption *o, gchar *value) { gchar *ptr; if ((ptr = strchr(value, 'x'))) { o->value.x = atoi(value); o->value.y = atoi(++ptr); } } gchar *GeometryOption_get(GeometryOption *o) { return g_strdup_printf("%s=%dx%d", get_token_name(o->base.token), gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(o->button)), gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(o->button2))); } void GeometryOption_free(SpinOption *o) { g_free(o); } /* vim: set ts=3 sw=3 sts=3 expandtab:*/