From a4ed5c6e3876f58239350fa8439326676e1fdfe1 Mon Sep 17 00:00:00 2001 From: o9000 Date: Sat, 4 Mar 2017 14:06:41 +0100 Subject: [PATCH] Tint2conf: gradientcolor stops --- src/tint2conf/gradient_gui.c | 263 +++++++++++++++++++++++++++++++++-- src/tint2conf/gradient_gui.h | 7 + src/tint2conf/properties.h | 12 +- 3 files changed, 265 insertions(+), 17 deletions(-) diff --git a/src/tint2conf/gradient_gui.c b/src/tint2conf/gradient_gui.c index 5be1632..0ceaa52 100644 --- a/src/tint2conf/gradient_gui.c +++ b/src/tint2conf/gradient_gui.c @@ -2,9 +2,10 @@ #include -GtkListStore *gradient_ids; +GtkListStore *gradient_ids, *gradient_stop_ids; GList *gradients; -GtkWidget *current_gradient, *gradient_combo_type, *gradient_start_color, *gradient_end_color, *gradient_color_stops; +GtkWidget *current_gradient, *gradient_combo_type, *gradient_start_color, *gradient_end_color, *current_gradient_stop, +*gradient_stop_color, *gradient_stop_offset; int gradient_index_safe(int index) { @@ -34,6 +35,8 @@ void create_gradient(GtkWidget *parent) gradient_ids = gtk_list_store_new(grNumCols, GDK_TYPE_PIXBUF, GTK_TYPE_INT, GTK_TYPE_STRING); gradients = NULL; + gradient_stop_ids = gtk_list_store_new(grStopNumCols, GDK_TYPE_PIXBUF); + GtkWidget *table, *label, *button; int row, col; // GtkTooltips *tooltips = gtk_tooltips_new(); @@ -119,32 +122,77 @@ void create_gradient(GtkWidget *parent) change_paragraph(parent); -#if 0 - label = gtk_label_new(_("Color stops")); - gtk_misc_set_alignment(GTK_MISC(label), 0, 0); - gtk_label_set_use_markup(GTK_LABEL(label), TRUE); - gtk_widget_show(label); - gtk_box_pack_start(GTK_BOX(parent), label, FALSE, FALSE, 0); - table = gtk_table_new(1, 4, FALSE); gtk_widget_show(table); gtk_box_pack_start(GTK_BOX(parent), table, FALSE, FALSE, 0); gtk_table_set_row_spacings(GTK_TABLE(table), ROW_SPACING); gtk_table_set_col_spacings(GTK_TABLE(table), COL_SPACING); + row = 0, col = 0; + label = gtk_label_new(_("Color stop")); + gtk_misc_set_alignment(GTK_MISC(label), 0, 0); + gtk_label_set_use_markup(GTK_LABEL(label), TRUE); + gtk_widget_show(label); + gtk_table_attach(GTK_TABLE(table), label, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0); + col++; + + current_gradient_stop = create_gradient_stop_combo(NULL); + gtk_widget_show(current_gradient_stop); + gtk_table_attach(GTK_TABLE(table), current_gradient_stop, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0); + col++; + + button = gtk_button_new_from_stock("gtk-add"); + gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(gradient_stop_duplicate), NULL); + gtk_widget_show(button); + gtk_table_attach(GTK_TABLE(table), button, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0); + col++; + + button = gtk_button_new_from_stock("gtk-remove"); + gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(gradient_stop_delete), NULL); + gtk_widget_show(button); + gtk_table_attach(GTK_TABLE(table), button, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0); + col++; + + table = gtk_table_new(3, 4, FALSE); + gtk_widget_show(table); + gtk_box_pack_start(GTK_BOX(parent), table, FALSE, FALSE, 0); + gtk_table_set_row_spacings(GTK_TABLE(table), ROW_SPACING); + gtk_table_set_col_spacings(GTK_TABLE(table), COL_SPACING); + row = 0, col = 2; - label = gtk_label_new(_("--")); + label = gtk_label_new(_("Color")); + gtk_misc_set_alignment(GTK_MISC(label), 0, 0); + gtk_widget_show(label); + gtk_table_attach(GTK_TABLE(table), label, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0); + col++; + + gradient_stop_color = gtk_color_button_new(); + gtk_color_button_set_use_alpha(GTK_COLOR_BUTTON(gradient_stop_color), TRUE); + gtk_widget_show(gradient_stop_color); + gtk_table_attach(GTK_TABLE(table), gradient_stop_color, col, col + 1, row, row + 1, GTK_FILL, 0, 0, 0); + col++; + + row++, col = 2; + label = gtk_label_new(_("Position")); gtk_misc_set_alignment(GTK_MISC(label), 0, 0); gtk_widget_show(label); gtk_table_attach(GTK_TABLE(table), label, col, col+1, row, row+1, GTK_FILL, 0, 0, 0); col++; -#endif + + gradient_stop_offset = gtk_spin_button_new_with_range(0, 100, 1); + gtk_widget_show(gradient_stop_offset); + gtk_table_attach(GTK_TABLE(table), gradient_stop_offset, col, col+1, row, row+1, GTK_FILL, 0, 0, 0); + col++; g_signal_connect(G_OBJECT(current_gradient), "changed", G_CALLBACK(current_gradient_changed), NULL); g_signal_connect(G_OBJECT(gradient_combo_type), "changed", G_CALLBACK(gradient_update), NULL); g_signal_connect(G_OBJECT(gradient_start_color), "color-set", G_CALLBACK(gradient_update), NULL); g_signal_connect(G_OBJECT(gradient_end_color), "color-set", G_CALLBACK(gradient_update), NULL); + g_signal_connect(G_OBJECT(current_gradient_stop), "changed", G_CALLBACK(current_gradient_stop_changed), NULL); + g_signal_connect(G_OBJECT(gradient_stop_color), "color-set", G_CALLBACK(gradient_stop_update), NULL); + g_signal_connect(G_OBJECT(gradient_stop_offset), "value-changed", G_CALLBACK(gradient_stop_update), NULL); + change_paragraph(parent); } @@ -356,15 +404,200 @@ void current_gradient_changed(GtkWidget *widget, gpointer data) int opacity; cairoColor2GdkColor(g->start_color.color.rgb[0], g->start_color.color.rgb[1], g->start_color.color.rgb[2], &color); - opacity = (g->start_color.color.alpha * 65535) / 100; + opacity = g->start_color.color.alpha * 65535; gtk_color_button_set_color(GTK_COLOR_BUTTON(gradient_start_color), &color); - gtk_color_button_set_alpha(GTK_COLOR_BUTTON(background_fill_color_over), opacity); + gtk_color_button_set_alpha(GTK_COLOR_BUTTON(gradient_start_color), opacity); cairoColor2GdkColor(g->end_color.color.rgb[0], g->end_color.color.rgb[1], g->end_color.color.rgb[2], &color); - opacity = (g->end_color.color.alpha * 65535) / 100; + opacity = g->end_color.color.alpha * 65535; gtk_color_button_set_color(GTK_COLOR_BUTTON(gradient_end_color), &color); - gtk_color_button_set_alpha(GTK_COLOR_BUTTON(background_fill_color_over), opacity); + gtk_color_button_set_alpha(GTK_COLOR_BUTTON(gradient_end_color), opacity); + + int old_stop_index = gtk_combo_box_get_active(GTK_COMBO_BOX(current_gradient_stop)); + gtk_list_store_clear(gradient_stop_ids); + int stop_index = 0; + for (GList *l = g->extra_color_stops; l; l = l->next, stop_index++) { + GtkTreeIter iter; + gtk_list_store_append(gradient_stop_ids, &iter); + gtk_list_store_set(gradient_stop_ids, &iter, + grStopColPixbuf, NULL, + -1); + gradient_stop_update_image(stop_index); + } + if (old_stop_index >= 0 && old_stop_index < stop_index) + gtk_combo_box_set_active(GTK_COMBO_BOX(current_gradient_stop), old_stop_index); + else + gtk_combo_box_set_active(GTK_COMBO_BOX(current_gradient_stop), stop_index - 1); gradient_updates_disabled = FALSE; gradient_update_image(index); } + +//////// Gradient stops + +GtkWidget *create_gradient_stop_combo() +{ + GtkWidget *combo = gtk_combo_box_new_with_model(GTK_TREE_MODEL(gradient_stop_ids)); + GtkCellRenderer *renderer = gtk_cell_renderer_pixbuf_new(); + gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combo), renderer, FALSE); + gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combo), renderer, "pixbuf", grStopColPixbuf, NULL); + return combo; +} + +void gradient_stop_create_new() +{ + int g_index = gtk_combo_box_get_active(GTK_COMBO_BOX(current_gradient)); + if (g_index < 0) + return; + + GradientConfig *g = (GradientConfig *)g_list_nth(gradients, (guint)g_index)->data; + GradientConfigColorStop *stop = (GradientConfigColorStop *)calloc(1, sizeof(GradientConfigColorStop)); + if (g->extra_color_stops) + memcpy(stop, g_list_last(g->extra_color_stops)->data, sizeof(GradientConfigColorStop)); + else + memcpy(stop, &g->start_color, sizeof(GradientConfigColorStop)); + g->extra_color_stops = g_list_append(g->extra_color_stops, stop); + GtkTreeIter iter; + gtk_list_store_append(gradient_stop_ids, &iter); + gtk_list_store_set(gradient_stop_ids, &iter, + grStopColPixbuf, NULL, + -1); + + int stop_index = g_list_length(g->extra_color_stops) - 1; + gradient_stop_update_image(stop_index); + gtk_combo_box_set_active(GTK_COMBO_BOX(current_gradient_stop), stop_index); + current_gradient_stop_changed(0, 0); + gradient_update_image(g_index); + background_update_for_gradient(g_index); +} + +void gradient_stop_duplicate(GtkWidget *widget, gpointer data) +{ + gradient_stop_create_new(); +} + +void gradient_stop_delete(GtkWidget *widget, gpointer data) +{ + int g_index = gtk_combo_box_get_active(GTK_COMBO_BOX(current_gradient)); + if (g_index < 0) + return; + + GradientConfig *g = (GradientConfig *)g_list_nth(gradients, (guint)g_index)->data; + if (!g->extra_color_stops) + return; + + int index = gtk_combo_box_get_active(GTK_COMBO_BOX(current_gradient_stop)); + if (index < 0) + return; + + GtkTreePath *path; + GtkTreeIter iter; + + path = gtk_tree_path_new_from_indices(index, -1); + gtk_tree_model_get_iter(GTK_TREE_MODEL(gradient_stop_ids), &iter, path); + gtk_tree_path_free(path); + + g->extra_color_stops = g_list_remove(g->extra_color_stops, g_list_nth(g->extra_color_stops, (guint)index)->data); + gtk_list_store_remove(gradient_stop_ids, &iter); + + if (index >= get_model_length(GTK_TREE_MODEL(gradient_stop_ids))) + index--; + gtk_combo_box_set_active(GTK_COMBO_BOX(current_gradient_stop), index); + + gradient_update_image(g_index); + background_update_for_gradient(g_index); +} + +void gradient_stop_update_image(int index) +{ + int g_index = gtk_combo_box_get_active(GTK_COMBO_BOX(current_gradient)); + if (g_index < 0) + return; + GradientConfig *g = (GradientConfig *)g_list_nth(gradients, (guint)g_index)->data; + GradientConfigColorStop *stop = (GradientConfigColorStop *)g_list_nth(g->extra_color_stops, (guint)index)->data; + + int w = 70; + int h = 30; + GdkPixmap *pixmap = gdk_pixmap_new(NULL, w, h, 24); + + cairo_t *cr = gdk_cairo_create(pixmap); + cairo_set_source_rgba(cr, stop->color.rgb[0], stop->color.rgb[1], stop->color.rgb[2], stop->color.alpha); + cairo_rectangle(cr, 0, 0, w, h); + cairo_fill(cr); + + GdkPixbuf *pixbuf = gdk_pixbuf_get_from_drawable(NULL, pixmap, gdk_colormap_get_system(), 0, 0, 0, 0, w, h); + if (pixmap) + g_object_unref(pixmap); + + GtkTreePath *path; + GtkTreeIter iter; + + path = gtk_tree_path_new_from_indices(index, -1); + gtk_tree_model_get_iter(GTK_TREE_MODEL(gradient_stop_ids), &iter, path); + gtk_tree_path_free(path); + + gtk_list_store_set(gradient_stop_ids, &iter, + grStopColPixbuf, pixbuf, + -1); + if (pixbuf) + g_object_unref(pixbuf); +} + +void current_gradient_stop_changed(GtkWidget *widget, gpointer data) +{ + int g_index = gtk_combo_box_get_active(GTK_COMBO_BOX(current_gradient)); + if (g_index < 0) + return; + GradientConfig *g = (GradientConfig *)g_list_nth(gradients, (guint)g_index)->data; + + int index = gtk_combo_box_get_active(GTK_COMBO_BOX(current_gradient_stop)); + if (index < 0) + return; + + GradientConfigColorStop *stop = (GradientConfigColorStop *)g_list_nth(g->extra_color_stops, (guint)index)->data; + + gradient_updates_disabled = TRUE; + + GdkColor color; + int opacity; + + cairoColor2GdkColor(stop->color.rgb[0], stop->color.rgb[1], stop->color.rgb[2], &color); + opacity = stop->color.alpha * 65535; + gtk_color_button_set_color(GTK_COLOR_BUTTON(gradient_stop_color), &color); + gtk_color_button_set_alpha(GTK_COLOR_BUTTON(gradient_stop_color), opacity); + + gtk_spin_button_set_value(GTK_SPIN_BUTTON(gradient_stop_offset), stop->offset * 100); + + gradient_updates_disabled = FALSE; +} + +void gradient_stop_update(GtkWidget *widget, gpointer data) +{ + if (gradient_updates_disabled) + return; + + int g_index = gtk_combo_box_get_active(GTK_COMBO_BOX(current_gradient)); + if (g_index < 0) + return; + GradientConfig *g = (GradientConfig *)g_list_nth(gradients, (guint)g_index)->data; + + int index = gtk_combo_box_get_active(GTK_COMBO_BOX(current_gradient_stop)); + if (index < 0) + return; + + GradientConfigColorStop *stop = (GradientConfigColorStop *)g_list_nth(g->extra_color_stops, (guint)index)->data; + + GdkColor color; + int opacity; + + gtk_color_button_get_color(GTK_COLOR_BUTTON(gradient_stop_color), &color); + opacity = MIN(100, 0.5 + gtk_color_button_get_alpha(GTK_COLOR_BUTTON(gradient_stop_color)) * 100.0 / 0xffff); + gdkColor2CairoColor(color, &stop->color.rgb[0], &stop->color.rgb[1], &stop->color.rgb[2]); + stop->color.alpha = opacity / 100.0; + + stop->offset = gtk_spin_button_get_value(GTK_SPIN_BUTTON(gradient_stop_offset)) / 100.; + + gradient_stop_update_image(index); + gradient_update_image(g_index); + background_update_for_gradient(g_index); +} diff --git a/src/tint2conf/gradient_gui.h b/src/tint2conf/gradient_gui.h index 891b609..2cc3485 100644 --- a/src/tint2conf/gradient_gui.h +++ b/src/tint2conf/gradient_gui.h @@ -14,6 +14,13 @@ void gradient_force_update(); void current_gradient_changed(GtkWidget *widget, gpointer data); void background_update_for_gradient(int gradient_id); +GtkWidget *create_gradient_stop_combo(); +void gradient_stop_duplicate(GtkWidget *widget, gpointer data); +void gradient_stop_delete(GtkWidget *widget, gpointer data); +void gradient_stop_update(GtkWidget *widget, gpointer data); +void gradient_stop_update_image(int index); +void current_gradient_stop_changed(GtkWidget *widget, gpointer data); + typedef enum GradientConfigType { GRADIENT_CONFIG_VERTICAL = 0, GRADIENT_CONFIG_HORIZONTAL, diff --git a/src/tint2conf/properties.h b/src/tint2conf/properties.h index bc9bf36..2274b30 100644 --- a/src/tint2conf/properties.h +++ b/src/tint2conf/properties.h @@ -231,14 +231,22 @@ enum { grColText, grNumCols }; -extern GtkListStore *gradient_ids; + +// gradient color stops +enum { + grStopColPixbuf = 0, + grStopNumCols +}; +extern GtkListStore *gradient_ids, *gradient_stop_ids; extern GList *gradients; extern GtkWidget *current_gradient, *gradient_combo_type, *gradient_start_color, *gradient_end_color, - *gradient_color_stops; + *current_gradient_stop, + *gradient_stop_color, + *gradient_stop_offset; void background_create_new(); void background_force_update();