aboutsummaryrefslogtreecommitdiffstats
path: root/preferences.c
diff options
context:
space:
mode:
authorMattias Andrée <m@maandree.se>2026-10-13 23:00:56 +0200
committerMattias Andrée <m@maandree.se>2026-10-13 23:00:56 +0200
commit0476071164c36b41de5b19e3e8a768feb422f27f (patch)
tree09d16e177042b14020a48030176d99e9024bea66 /preferences.c
parentThird commit (diff)
downloadgbild-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.c223
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);
+}