diff options
| author | Mattias Andrée <m@maandree.se> | 2026-10-13 23:00:56 +0200 |
|---|---|---|
| committer | Mattias Andrée <m@maandree.se> | 2026-10-13 23:00:56 +0200 |
| commit | 0476071164c36b41de5b19e3e8a768feb422f27f (patch) | |
| tree | 09d16e177042b14020a48030176d99e9024bea66 /preferences.c | |
| parent | Third commit (diff) | |
| download | gbild-0476071164c36b41de5b19e3e8a768feb422f27f.tar.gz gbild-0476071164c36b41de5b19e3e8a768feb422f27f.tar.bz2 gbild-0476071164c36b41de5b19e3e8a768feb422f27f.tar.xz | |
Fourth commit
Signed-off-by: Mattias Andrée <m@maandree.se>
Diffstat (limited to 'preferences.c')
| -rw-r--r-- | preferences.c | 223 |
1 files changed, 223 insertions, 0 deletions
diff --git a/preferences.c b/preferences.c new file mode 100644 index 0000000..e4d73e2 --- /dev/null +++ b/preferences.c @@ -0,0 +1,223 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + +#define LIST_SCALING_FILTERS(X, ...)\ + X(0, CAIRO_FILTER_NEAREST, "Nearest") __VA_ARGS__\ + X(1, CAIRO_FILTER_BILINEAR, "Bilinear") __VA_ARGS__\ + X(2, CAIRO_FILTER_GAUSSIAN, "Gaussian") + +cairo_filter_t scaling_filter = CAIRO_FILTER_BILINEAR; +GdkColor chequer_colours[2] = { + {0u, 0xD3D3u, 0xD3D3u, 0xD3D3u}, + {0u, 0xFFFFu, 0xFFFFu, 0xFFFFu} +}; +uint16_t chequer_alphas[2] = {0xFFFFu, 0xFFFFu}; +int chequered_background = 0; +int chequer_size = 16; + +static GtkWidget *preferences_window; +static GtkWidget *transparency_controls; + +static void +preferences_response(GtkDialog *dialog, int response, void *user) +{ + (void) response; + (void) user; + gtk_widget_destroy(GTK_WIDGET(dialog)); +} + +static void +preferences_destroyed(GtkWidget *widget, void *user) +{ + (void) widget; + (void) user; + preferences_window = NULL; +} + +static void +scaling_filter_changed(GtkComboBox *box, void *user) +{ + (void) user; + switch (gtk_combo_box_get_active(box)) { +#define X(I, V, T) case I: scaling_filter = V; break + LIST_SCALING_FILTERS(X, ;); +#undef X + default: + abort(); + } + gtk_widget_queue_draw(display_area); +} + +static void +chequered_background_changed(GtkToggleButton *button, void *user) +{ + (void) user; + chequered_background = gtk_toggle_button_get_active(button); + gtk_widget_set_sensitive(transparency_controls, chequered_background); + gtk_widget_queue_draw(display_area); +} + +static void +transparency_colour_changed(GtkColorButton *button, void *user) +{ + GdkColor *colour = user; + size_t index = (size_t)(colour - chequer_colours); + gtk_color_button_get_color(button, colour); + chequer_alphas[index] = gtk_color_button_get_alpha(button); + gtk_widget_queue_draw(display_area); +} + +static void +chequer_size_changed(GtkSpinButton *button, void *user) +{ + (void) user; + chequer_size = gtk_spin_button_get_value_as_int(button); + gtk_widget_queue_draw(display_area); +} + +static GtkWidget * +new_section(const char *title) +{ + GtkWidget *frame = gtk_frame_new(title); + GtkWidget *box = gtk_vbox_new(0, 6); + gtk_container_set_border_width(GTK_CONTAINER(box), 6u); + gtk_container_add(GTK_CONTAINER(frame), box); + return frame; +} + +static GtkWidget * +new_scaling_section(void) +{ + GtkWidget *section = new_section("Scaling"); + GtkWidget *box = gtk_bin_get_child(GTK_BIN(section)); + GtkWidget *row = gtk_hbox_new(0, 6); + GtkWidget *label = gtk_label_new_with_mnemonic("_Algorithm:"); + GtkWidget *filters = gtk_combo_box_new_text(); + +#define X(I, V, T) gtk_combo_box_append_text(GTK_COMBO_BOX(filters), T) + LIST_SCALING_FILTERS(X, ;); +#undef X + + switch (scaling_filter) { +#define X(I, V, T) case V: gtk_combo_box_set_active(GTK_COMBO_BOX(filters), I); break + LIST_SCALING_FILTERS(X, ;); +#undef X + case CAIRO_FILTER_FAST: + case CAIRO_FILTER_GOOD: + case CAIRO_FILTER_BEST: + default: + abort(); + } + + gtk_label_set_mnemonic_widget(GTK_LABEL(label), filters); + gtk_box_pack_start(GTK_BOX(row), label, 0, 0, 0u); + gtk_box_pack_start(GTK_BOX(row), filters, 0, 0, 0u); + gtk_box_pack_start(GTK_BOX(box), row, 0, 0, 0u); + g_signal_connect(filters, "changed", G_CALLBACK(&scaling_filter_changed), NULL); + return section; +} + +#ifdef TODO +static GtkWidget * +new_unimplemented_section(void) +{ + GtkWidget *section = new_section("Image handling"); + GtkWidget *box = gtk_bin_get_child(GTK_BIN(section)); + GtkWidget *orientation; + GtkWidget *physical_size; + + orientation = gtk_check_button_new_with_mnemonic("Apply embedded _orientation"); + physical_size = gtk_check_button_new_with_mnemonic("Normal size is _physical size"); + gtk_box_pack_start(GTK_BOX(box), orientation, 0, 0, 0u); + gtk_box_pack_start(GTK_BOX(box), physical_size, 0, 0, 0u); + return section; +} +#endif + +static GtkWidget * +new_transparency_section(void) +{ + GtkWidget *section = new_section("Transparent images"); + GtkWidget *box = gtk_bin_get_child(GTK_BIN(section)); + GtkWidget *enabled; + GtkWidget *first; + GtkWidget *second; + GtkWidget *size; + GtkWidget *label; + GtkWidget *units; + + enabled = gtk_check_button_new_with_mnemonic("Use che_quered background"); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(enabled), chequered_background); + gtk_box_pack_start(GTK_BOX(box), enabled, 0, 0, 0u); + transparency_controls = gtk_table_new(3u, 3u, 0); + gtk_table_set_row_spacings(GTK_TABLE(transparency_controls), 3u); + gtk_table_set_col_spacings(GTK_TABLE(transparency_controls), 6u); + gtk_box_pack_start(GTK_BOX(box), transparency_controls, 0, 0, 0u); + + label = gtk_label_new_with_mnemonic("_First colour:"); + gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); + first = gtk_color_button_new_with_color(&chequer_colours[0]); + gtk_color_button_set_use_alpha(GTK_COLOR_BUTTON(first), 1); + gtk_color_button_set_alpha(GTK_COLOR_BUTTON(first), chequer_alphas[0]); + gtk_label_set_mnemonic_widget(GTK_LABEL(label), first); + gtk_table_attach(GTK_TABLE(transparency_controls), label, 0u, 1u, 0u, 1u, GTK_FILL, GTK_FILL, 0u, 0u); + gtk_table_attach(GTK_TABLE(transparency_controls), first, 1u, 2u, 0u, 1u, GTK_FILL, GTK_FILL, 0u, 0u); + + label = gtk_label_new_with_mnemonic("_Second colour:"); + gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); + second = gtk_color_button_new_with_color(&chequer_colours[1]); + gtk_color_button_set_use_alpha(GTK_COLOR_BUTTON(second), 1); + gtk_color_button_set_alpha(GTK_COLOR_BUTTON(second), chequer_alphas[1]); + gtk_label_set_mnemonic_widget(GTK_LABEL(label), second); + gtk_table_attach(GTK_TABLE(transparency_controls), label, 0u, 1u, 1u, 2u, GTK_FILL, GTK_FILL, 0u, 0u); + gtk_table_attach(GTK_TABLE(transparency_controls), second, 1u, 2u, 1u, 2u, GTK_FILL, GTK_FILL, 0u, 0u); + + label = gtk_label_new_with_mnemonic("Chequer si_ze:"); + gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); + size = gtk_spin_button_new_with_range(1.0, 256.0, 1.0); + units = gtk_label_new("pixels"); + gtk_misc_set_alignment(GTK_MISC(units), 0.0, 0.5); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(size), (double)chequer_size); + gtk_label_set_mnemonic_widget(GTK_LABEL(label), size); + gtk_table_attach(GTK_TABLE(transparency_controls), label, 0u, 1u, 2u, 3u, GTK_FILL, GTK_FILL, 0u, 0u); + gtk_table_attach(GTK_TABLE(transparency_controls), size, 1u, 2u, 2u, 3u, GTK_FILL, GTK_FILL, 0u, 0u); + gtk_table_attach(GTK_TABLE(transparency_controls), units, 2u, 3u, 2u, 3u, GTK_FILL, GTK_FILL, 0u, 0u); + + gtk_widget_set_sensitive(transparency_controls, chequered_background); + g_signal_connect(enabled, "toggled", G_CALLBACK(&chequered_background_changed), NULL); + g_signal_connect(first, "color-set", G_CALLBACK(&transparency_colour_changed), &chequer_colours[0]); + g_signal_connect(second, "color-set", G_CALLBACK(&transparency_colour_changed), &chequer_colours[1]); + g_signal_connect(size, "value-changed", G_CALLBACK(&chequer_size_changed), NULL); + return section; +} + +void +open_preferences(void) +{ + GtkWidget *alignment, *box; + + if (preferences_window) { + gtk_window_present(GTK_WINDOW(preferences_window)); + return; + } + + preferences_window = gtk_dialog_new_with_buttons("Preferences", GTK_WINDOW(window), GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, NULL); + + alignment = gtk_alignment_new(0.0, 0.0, 1.0, 1.0); + gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 6u, 6u, 6u, 6u); + gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(preferences_window))), alignment, 1, 1, 0u); + box = gtk_vbox_new(0, 6); + gtk_container_add(GTK_CONTAINER(alignment), box); + + gtk_box_pack_start(GTK_BOX(box), new_scaling_section(), 0, 0, 0u); +#ifdef TODO + gtk_box_pack_start(GTK_BOX(box), new_unimplemented_section(), 0, 0, 0u); +#endif + gtk_box_pack_start(GTK_BOX(box), new_transparency_section(), 0, 0, 0u); + + g_signal_connect(preferences_window, "response", G_CALLBACK(&preferences_response), NULL); + g_signal_connect(preferences_window, "destroy", G_CALLBACK(&preferences_destroyed), NULL); + + gtk_widget_show_all(preferences_window); +} |
