IFSCompose and bugzilla question
This discussion is connected to the gimp-developer-list.gnome.org mailing list which is provided by the GIMP developers and not related to gimpusers.com.
This is a read-only list on gimpusers.com so this discussion thread is read-only, too.
IFSCompose and bugzilla question | David Necas (Yeti) | 02 Feb 01:01 |
IFSCompose and bugzilla question | Sven Neumann | 02 Feb 01:55 |
IFSCompose and bugzilla question | Sven Neumann | 02 Feb 02:25 |
IFSCompose and bugzilla question | David Necas (Yeti) | 02 Feb 13:21 |
IFSCompose and bugzilla question | Sven Neumann | 02 Feb 19:42 |
IFSCompose and bugzilla question
Hello,
I fixed and improved a few thing in the IFS Compose plugin. I know I should use bugzilla. The reasons I write here are: The existing bugreports are 1.2, while I fixed it in 1.3 (except #82472 fix, which I also backported to 1.2), I'm not sure how to handle this. Some issues were just side effects of an underlying real problem (#82466, #82473). Bug #82470 I fixed as a side effect of a larger change. The other things are not in bugzilla at all (like Save/Load), I don't have separate patches for them, and don't like the perspective of creating a dozen of individual reports and separating the patches only for the sake of bugzillization of the whole thing.
Please critize/check/apply the attached patch (against 1.3.11) and tell me what to do with:
nor #82472 Flip button doesn't act on all selected objects (I attached the backport to this one) min #82466 Toggling between Simple/Full in IfsCompose changes preview min #82473 IfsCompose disable Undo/Redo button when nothing to be undo enh #82470 IfsCompose filter: location of 'New' and 'Delete' button not...
and what to do generally in situations like this.
IFS Compose changes:
* implemented Save and Load
* made Flip to act on all selected transformations, fixes #82472
* moved New/Delete from action area below other buttons, fixes #82470
* fixed Delete to be insensitive when num of transforms == 2
* Undo/Redo made insensitive when there's nothing to update, and avoided
creation of bogus undo levels during color updates, fixes #82466, #82473,
and other queer undo/redo behaviour
* set alpha of all colors to 1.0 -- ifscompose ignores alpha anyway, and
default value (122???) makes the color selection dialog pretty confusing
* made Undo, Redo, Select All, Recompute Center menu items visible as buttons,
so people who don't try right clicking in the design area know about them
* changed confusing numeric frame title to "Transformation n"
* changed the button layout to two centered groups (it looked approximately
this way before too, but probably only incidentally)
Thanks in advance,
Yeti
--- gimp-1.3.11.orig/plug-ins/ifscompose/ifscompose.c 2002-12-03 20:42:41.000000000 +0100
+++ gimp-1.3.11/plug-ins/ifscompose/ifscompose.c 2003-02-01 23:25:34.000000000 +0100
@@ -169,6 +169,12 @@
GtkWidget *stretch_button;
gint stretch_handler;
+ GtkWidget *undo_button;
+ GtkWidget *undo_menu_item;
+ GtkWidget *redo_button;
+ GtkWidget *redo_menu_item;
+ GtkWidget *delete_button;
+
GtkWidget *preview;
guchar *preview_data;
gint preview_iterations;
@@ -278,6 +284,10 @@
gpointer data);
static void ifs_compose_delete_callback (GtkWidget *widget,
gpointer data);
+static void ifs_compose_load_callback (GtkWidget *widget,
+ gpointer data);
+static void ifs_compose_save_callback (GtkWidget *widget,
+ gpointer data);
static void ifs_compose_ok_callback (GtkWidget *widget,
GtkWidget *window);
@@ -300,6 +310,8 @@
static gint undo_num = 0;
static gint undo_start = 0;
+static gchar ifsfile_path[PATH_MAX] = { '\0' };
+
/* num_elements = 0, signals not inited */
static IfsComposeVals ifsvals =
{
@@ -387,8 +399,6 @@
INIT_I18N_UI();
- /* kill (getpid(), 19); */
-
/* Get the active drawable */
active_drawable = gimp_drawable_get (param[2].data.d_drawable);
@@ -786,10 +796,10 @@
GIMP_STOCK_RESET, ifs_compose_defaults_callback,
NULL, NULL, NULL, FALSE, FALSE,
- GTK_STOCK_DELETE, ifs_compose_delete_callback,
+ GTK_STOCK_OPEN, ifs_compose_load_callback,
NULL, NULL, NULL, FALSE, FALSE,
- GTK_STOCK_NEW, ifs_compose_new_callback,
+ GTK_STOCK_SAVE, ifs_compose_save_callback,
NULL, NULL, NULL, FALSE, FALSE,
GTK_STOCK_CANCEL, gtk_widget_destroy,
@@ -850,10 +860,10 @@
/* Iterations and preview options */
- hbox = gtk_hbox_new (FALSE, 4);
+ hbox = gtk_hbox_new (TRUE, 4);
gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, FALSE, 0);
- alignment = gtk_alignment_new (1.0, 0.5, 0.5, 0.0);
+ alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
gtk_box_pack_start (GTK_BOX (hbox), alignment, TRUE, TRUE, 0);
util_hbox = gtk_hbox_new (FALSE, 4);
@@ -891,7 +901,7 @@
gtk_widget_show (alignment);
gtk_widget_show (util_hbox);
- alignment = gtk_alignment_new (1.0, 0.5, 0.5, 0.0);
+ alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
gtk_box_pack_start (GTK_BOX (hbox), alignment, TRUE, TRUE, 0);
util_hbox = gtk_hbox_new (FALSE, 4);
@@ -924,6 +934,70 @@
gtk_widget_show (alignment);
gtk_widget_show (hbox);
+ /* second util row */
+ hbox = gtk_hbox_new (TRUE, 4);
+ gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, FALSE, 0);
+
+ alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
+ gtk_box_pack_start (GTK_BOX (hbox), alignment, TRUE, TRUE, 0);
+
+ util_hbox = gtk_hbox_new (FALSE, 4);
+ gtk_container_add (GTK_CONTAINER (alignment), util_hbox);
+
+ ifsD->undo_button = gtk_button_new_with_label(_("Undo"));
+ gtk_box_pack_start(GTK_BOX(util_hbox), ifsD->undo_button,
+ TRUE, TRUE, 0);
+ g_signal_connect(G_OBJECT(ifsD->undo_button), "clicked",
+ G_CALLBACK(undo), NULL);
+ gtk_widget_set_sensitive(ifsD->undo_button, FALSE);
+ gtk_widget_show(ifsD->undo_button);
+
+ ifsD->redo_button = gtk_button_new_with_label (_("Redo"));
+ gtk_box_pack_start (GTK_BOX (util_hbox), ifsD->redo_button,
+ TRUE, TRUE, 0);
+ g_signal_connect(G_OBJECT(ifsD->redo_button), "clicked",
+ G_CALLBACK(redo), NULL);
+ gtk_widget_set_sensitive(ifsD->redo_button, FALSE);
+ gtk_widget_show(ifsD->redo_button);
+
+ button = gtk_button_new_with_label (_("Select All"));
+ gtk_box_pack_start (GTK_BOX (util_hbox), button,
+ TRUE, TRUE, 0);
+ g_signal_connect(G_OBJECT(button), "clicked",
+ G_CALLBACK(design_area_select_all_callback), NULL);
+ gtk_widget_show (button);
+
+ gtk_widget_show (alignment);
+ gtk_widget_show (util_hbox);
+
+ alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
+ gtk_box_pack_start (GTK_BOX (hbox), alignment, TRUE, TRUE, 0);
+
+ util_hbox = gtk_hbox_new (FALSE, 4);
+ gtk_container_add (GTK_CONTAINER (alignment), util_hbox);
+
+ ifsD->delete_button = gtk_button_new_with_label (_("Delete"));
+ g_signal_connect(G_OBJECT(ifsD->delete_button), "clicked",
+ G_CALLBACK(ifs_compose_delete_callback), NULL);
+ gtk_box_pack_start(GTK_BOX(util_hbox), ifsD->delete_button, TRUE, TRUE, 0);
+ gtk_widget_show(ifsD->delete_button);
+
+ button = gtk_button_new_with_label(_("New"));
+ g_signal_connect(G_OBJECT(button), "clicked",
+ G_CALLBACK(ifs_compose_new_callback), NULL);
+ gtk_box_pack_start (GTK_BOX (util_hbox), button, TRUE, TRUE, 0);
+ gtk_widget_show (button);
+
+ button = gtk_button_new_with_label (_("Recompute center"));
+ gtk_box_pack_start (GTK_BOX (util_hbox), button, TRUE, TRUE, 0);
+ g_signal_connect(G_OBJECT(button), "clicked",
+ G_CALLBACK(recompute_center_cb), NULL);
+ gtk_widget_show (button);
+
+ gtk_widget_show (util_hbox);
+ gtk_widget_show (alignment);
+ gtk_widget_show (hbox);
+
/* The current transformation frame */
ifsD->current_frame = gtk_frame_new (NULL);
@@ -1190,25 +1264,29 @@
'R', GDK_MOD1_MASK,
GTK_ACCEL_VISIBLE | GTK_ACCEL_LOCKED);
- menu_item = gtk_menu_item_new_with_label (_("Undo"));
- gtk_menu_shell_append (GTK_MENU_SHELL (ifsDesign->op_menu), menu_item);
- gtk_widget_show (menu_item);
- g_signal_connect (G_OBJECT (menu_item), "activate",
- G_CALLBACK (undo),
- NULL);
- gtk_widget_add_accelerator (menu_item,
+ ifsD->undo_menu_item = gtk_menu_item_new_with_label(_("Undo"));
+ gtk_menu_shell_append(GTK_MENU_SHELL(ifsDesign->op_menu),
+ ifsD->undo_menu_item);
+ gtk_widget_set_sensitive(ifsD->undo_menu_item, FALSE);
+ gtk_widget_show(ifsD->undo_menu_item);
+ g_signal_connect(G_OBJECT(ifsD->undo_menu_item), "activate",
+ G_CALLBACK(undo),
+ NULL);
+ gtk_widget_add_accelerator(ifsD->undo_menu_item,
"activate",
accel_group,
'Z', GDK_CONTROL_MASK,
GTK_ACCEL_VISIBLE | GTK_ACCEL_LOCKED);
- menu_item = gtk_menu_item_new_with_label(_("Redo"));
- gtk_menu_shell_append (GTK_MENU_SHELL (ifsDesign->op_menu), menu_item);
- gtk_widget_show(menu_item);
- g_signal_connect (G_OBJECT (menu_item), "activate",
+ ifsD->redo_menu_item = gtk_menu_item_new_with_label(_("Redo"));
+ gtk_menu_shell_append (GTK_MENU_SHELL (ifsDesign->op_menu),
+ ifsD->redo_menu_item);
+ gtk_widget_set_sensitive(ifsD->redo_menu_item, FALSE);
+ gtk_widget_show(ifsD->redo_menu_item);
+ g_signal_connect (G_OBJECT (ifsD->redo_menu_item), "activate",
G_CALLBACK (redo),
NULL);
- gtk_widget_add_accelerator(menu_item,
+ gtk_widget_add_accelerator(ifsD->redo_menu_item,
"activate",
accel_group,
'R', GDK_CONTROL_MASK,
@@ -1415,7 +1493,7 @@
gint btot=0;
gint gtot=0;
gint mtot=0;
- for (jj=0;jj< ifsvals.subdivide; jj++)
{
ptr = data + 3 *
(((j-band_y)*ifsvals.subdivide+jj)*ifsvals.subdivide*width +
@@ -1424,7 +1502,7 @@
maskptr = mask +
((j-band_y)*ifsvals.subdivide+jj)*ifsvals.subdivide*width +
i*ifsvals.subdivide;
- for (ii=0;ii< ifsvals.subdivide; ii++)
{
maskval = *maskptr++;
mtot += maskval;
@@ -1524,9 +1602,13 @@
static void
set_current_element (gint index)
{
+ gchar *frame_name = g_strdup_printf(_("Transformation %s"),
+ elements[index]->name);
+
ifsD->current_element = index;
- gtk_frame_set_label(GTK_FRAME(ifsD->current_frame),elements[index]->name);
+ gtk_frame_set_label(GTK_FRAME(ifsD->current_frame),frame_name);
+ g_free(frame_name);
update_values();
}
@@ -1564,7 +1646,7 @@
widget->style->fg_gc[widget->state],
cx, cy - 10, cx, cy + 10);
- for (i=0;i< ifsvals.num_elements; i++)
{
aff_element_draw(elements[i], element_selected[i],
widget->allocation.width,
@@ -1593,10 +1675,10 @@
gdouble width = widget->allocation.width;
gdouble height = widget->allocation.height;
- for (i=0;i< ifsvals.num_elements; i++)
aff_element_compute_trans(elements[i],width,height,
ifsvals.center_x, ifsvals.center_y);
- for (i=0;i< ifsvals.num_elements; i++)
aff_element_compute_boundary(elements[i],width,height,
elements, ifsvals.num_elements);
@@ -1634,7 +1716,7 @@
ifsD->current_element = -1;
/* Find out where the button press was */
- for (i=0;i< ifsvals.num_elements; i++)
{
if ( ipolygon_contains(elements[i]->click_boundary,event->x,event->y) )
{
@@ -1652,7 +1734,7 @@
&& ( (ifsD->current_elementcurrent_element] ))
{
- for (i=0;i< ifsvals.num_elements; i++)
element_selected[i] = 0;
}
@@ -1665,7 +1747,7 @@
ifsDesign->num_selected = 0;
ifsDesign->op_xcenter = 0.0;
ifsDesign->op_ycenter = 0.0;
- for (i=0;i< ifsvals.num_elements; i++)
{
if (element_selected[i])
{
@@ -1772,7 +1854,7 @@
}
}
- for (i=0;i< ifsvals.num_elements; i++)
if (element_selected[i])
{
if (ifsDesign->num_selected == ifsvals.num_elements)
@@ -1784,7 +1866,7 @@
cx = ifsDesign->op_center_x * width;
cy = ifsDesign->op_center_y * width;
- aff2_apply(&trans,cx,cy,&cx,&cy);
+ aff2_apply(&trans, cx, cy, &cx, &cy);
ifsvals.center_x = cx / width;
ifsvals.center_y = cy / width;
}
@@ -1843,9 +1925,9 @@
new_index = (undo_start+undo_cur)%UNDO_LEVELS;
/* remove any redo elements or the oldest element if necessary */
- for (j=new_index;to_delete>0;j=(j+1)%UNDO_LEVELS,to_delete--)
+ for (j = new_index; to_delete > 0; j = (j+1)%UNDO_LEVELS, to_delete--)
{
- for (i=0;i< undo_ring[j].ifsvals.num_elements; i++)
if (undo_ring[j].elements[i])
aff_element_free(undo_ring[j].elements[i]);
g_free(undo_ring[j].elements);
@@ -1857,11 +1939,16 @@
undo_ring[new_index].element_selected = g_new(gint,ifsvals.num_elements);
undo_ring[new_index].current_element = ifsD->current_element;
- for (i=0;i< ifsvals.num_elements; i++)
{
undo_ring[new_index].elements[i] = NULL;
undo_ring[new_index].element_selected[i] = element_selected[i];
}
+
+ gtk_widget_set_sensitive(ifsD->undo_button, undo_cur >= 0);
+ gtk_widget_set_sensitive(ifsD->undo_menu_item, undo_cur >= 0);
+ gtk_widget_set_sensitive(ifsD->redo_button, undo_cur != undo_num-1);
+ gtk_widget_set_sensitive(ifsD->redo_menu_item, undo_cur != undo_num-1);
}
static void
@@ -1910,7 +1997,7 @@
undo_ring[el].current_element = tcurrent;
/* now swap back any unchanged elements */
- for (i=0;i< ifsvals.num_elements; i++)
if (!elements[i])
{
elements[i] = undo_ring[el].elements[i];
@@ -1936,6 +2023,11 @@
undo_exchange((undo_start+undo_cur)%UNDO_LEVELS);
undo_cur--;
}
+
+ gtk_widget_set_sensitive(ifsD->undo_button, undo_cur >= 0);
+ gtk_widget_set_sensitive(ifsD->undo_menu_item, undo_cur >= 0);
+ gtk_widget_set_sensitive(ifsD->redo_button, undo_cur != undo_num-1);
+ gtk_widget_set_sensitive(ifsD->redo_menu_item, undo_cur != undo_num-1);
}
static void
@@ -1946,6 +2038,11 @@
undo_cur++;
undo_exchange((undo_start+undo_cur)%UNDO_LEVELS);
}
+
+ gtk_widget_set_sensitive(ifsD->undo_button, undo_cur >= 0);
+ gtk_widget_set_sensitive(ifsD->undo_menu_item, undo_cur >= 0);
+ gtk_widget_set_sensitive(ifsD->redo_button, undo_cur != undo_num-1);
+ gtk_widget_set_sensitive(ifsD->redo_menu_item, undo_cur != undo_num-1);
}
static void
@@ -1954,7 +2051,7 @@
{
gint i;
- for (i=0;i< ifsvals.num_elements; i++)
element_selected[i] = TRUE;
design_area_redraw();
@@ -2002,6 +2099,7 @@
ColorMap *color_map = g_new (ColorMap,1);
+ gimp_rgb_set_alpha(data, 1.0);
color_map->color = data;
color_map->fixed_point = fixed_point;
color_map->hbox = gtk_hbox_new (FALSE,2);
@@ -2048,6 +2146,9 @@
color_map_color_changed_cb (GtkWidget *widget,
ColorMap *color_map)
{
+ if (ifsD->in_update)
+ return;
+
undo_begin ();
undo_update (ifsD->current_element);
@@ -2065,11 +2166,11 @@
color_map_update (ColorMap *color_map)
{
gimp_color_button_set_color (GIMP_COLOR_BUTTON (color_map->button),
- color_map->color);
+ color_map->color);
if (color_map->fixed_point)
gimp_color_area_set_color (GIMP_COLOR_AREA (color_map->orig_preview),
- color_map->color);
+ color_map->color);
}
static void
@@ -2097,10 +2198,9 @@
cur->v.simple_color = GTK_TOGGLE_BUTTON(widget)->active;
ifsD->current_vals.simple_color = cur->v.simple_color;
if (cur->v.simple_color)
- {
- aff_element_compute_color_trans(cur);
- val_changed_update();
- }
+ aff_element_compute_color_trans(cur);
+
+ val_changed_update();
simple_color_set_sensitive();
}
@@ -2364,7 +2464,7 @@
if (save_undo)
undo_begin();
- for (i=0;i< ifsvals.num_elements; i++)
{
if (save_undo)
undo_update(i);
@@ -2378,7 +2478,7 @@
ifsvals.center_x = center_x/ifsvals.num_elements;
ifsvals.center_y = center_y/ifsvals.num_elements;
- for (i=0;i< ifsvals.num_elements; i++)
{
aff_element_decompose_trans(elements[i],&elements[i]->trans,
1,ifsvals.aspect_ratio,
@@ -2387,7 +2487,7 @@
if (width > 1 && height > 1)
{
- for (i=0;i< ifsvals.num_elements; i++)
aff_element_compute_trans(elements[i],width,height,
ifsvals.center_x, ifsvals.center_y);
design_area_redraw();
@@ -2414,8 +2514,29 @@
flip_check_button_callback (GtkWidget *widget,
gpointer data)
{
- ifsD->current_vals.flip = GTK_TOGGLE_BUTTON(widget)->active;
- val_changed_update ();
+ guint i;
+ gdouble width = ifsDesign->area->allocation.width;
+ gdouble height = ifsDesign->area->allocation.height;
+ gint active = GTK_TOGGLE_BUTTON(widget)->active;
+
+ if (ifsD->in_update)
+ return;
+
+ undo_begin();
+ for (i = 0; i < ifsvals.num_elements; i++) {
+ if (element_selected[i]) {
+ undo_update(i);
+ elements[i]->v.flip = active;
+ aff_element_compute_trans(elements[i], width, height,
+ ifsvals.center_x, ifsvals.center_y);
+ }
+ }
+
+ update_values();
+ design_area_redraw();
+
+ if (ifsD->auto_preview)
+ ifs_compose_preview();
}
static void
@@ -2428,7 +2549,7 @@
ifsvals.aspect_ratio = (gdouble)ifsD->drawable_height/ifsD->drawable_width;
- for (i=0;i< ifsvals.num_elements; i++)
aff_element_free(elements[i]);
count_for_naming = 0;
@@ -2497,6 +2618,191 @@
design_area_redraw ();
}
+/* show a modal dialog */
+void
+yeti_message_dialog(GtkMessageType type, GtkWindow *parent,
+ gchar *title, gchar *message)
+{
+ GtkWidget *dlg;
+
+ dlg = gtk_message_dialog_new(parent, GTK_DIALOG_MODAL,
+ type, GTK_BUTTONS_OK, message);
+ if (title)
+ gtk_window_set_title(GTK_WINDOW(dlg), title);
+ gtk_window_set_wmclass(GTK_WINDOW(dlg), "message", "Gimp");
+ gtk_dialog_run(GTK_DIALOG(dlg));
+ gtk_widget_destroy(dlg);
+}
+
+/* save an ifs file */
+static void
+ifsfile_save(GtkWidget *widget, GtkWidget *file_select)
+{
+ gchar *str = ifsvals_stringify(&ifsvals, elements);
+ FILE *fh;
+ char *warning = NULL;
+
+ strcpy(ifsfile_path,
+ gtk_file_selection_get_filename(GTK_FILE_SELECTION(file_select)));
+ fh = fopen(ifsfile_path, "w");
+ if (fh) {
+ fputs(str, fh);
+ fclose(fh);
+ }
+ else
+ warning = g_strdup_printf(_("Cannot save into file `%s'.\n"
+ "Check the path and permissions.\n"),
+ ifsfile_path);
+
+ free(str);
+ if (warning) {
+ yeti_message_dialog(GTK_MESSAGE_ERROR, GTK_WINDOW(file_select),
+ "Save failed", warning);
+ g_free(warning);
+ }
+ gtk_widget_destroy(file_select);
+}
+
+/* replace ifsvals and elements with specified new values
+ * recompute and update everything necessary */
+static void
+ifsfile_replace_ifsvals(IfsComposeVals *new_ifsvals,
+ AffElement **new_elements)
+{
+ gdouble width = ifsDesign->area->allocation.width;
+ gdouble height = ifsDesign->area->allocation.height;
+ guint i;
+
+ for (i = 0; i < ifsvals.num_elements; i++)
+ aff_element_free(elements[i]);
+ free(elements);
+
+ ifsvals = *new_ifsvals;
+ elements = new_elements;
+ for (i = 0; i < ifsvals.num_elements; i++) {
+ aff_element_compute_trans(elements[i], width, height,
+ ifsvals.center_x, ifsvals.center_y);
+ aff_element_compute_color_trans(elements[i]);
+ }
+
+ element_selected = g_realloc(element_selected,
+ ifsvals.num_elements * sizeof(gint));
+ for (i = 0; i < ifsvals.num_elements; i++)
+ element_selected[i] = FALSE;
+
+ if (ifsOptD) {
+ value_pair_update(ifsOptD->iterations_pair);
+ value_pair_update(ifsOptD->subdivide_pair);
+ value_pair_update(ifsOptD->radius_pair);
+ value_pair_update(ifsOptD->memory_pair);
+ }
+
+ set_current_element(0);
+ element_selected[0] = TRUE;
+ recompute_center(FALSE);
+
+ if (ifsD->selected_orig)
+ g_free(ifsD->selected_orig);
+
+ ifsD->selected_orig = g_new(AffElement, ifsvals.num_elements);
+}
+
+/* load an ifs file */
+static void
+ifsfile_load(GtkWidget *widget, GtkWidget *file_select)
+{
+ FILE *fh;
+ guint size = 4096;
+ guint len, pos;
+ guchar *buffer;
+ AffElement **new_elements;
+ IfsComposeVals new_ifsvals;
+ gchar *warning = NULL;
+
+ buffer = g_new(guchar, size);
+ strcpy(ifsfile_path,
+ gtk_file_selection_get_filename(GTK_FILE_SELECTION(file_select)));
+ fh = fopen(ifsfile_path, "r");
+ if (fh) {
+ pos = 0;
+ while ((len = fread(buffer + pos, 1, size - pos, fh)) == size-pos) {
+ pos = size;
+ size *= 2;
+ buffer = g_realloc(buffer, size);
+ }
+ fclose(fh);
+
+ pos += len;
+ buffer[pos] = '\0';
+ if (ifsvals_parse_string(buffer, &new_ifsvals, &new_elements)) {
+ guint i;
+
+ undo_begin ();
+ for (i = 0; i < ifsvals.num_elements; i++)
+ undo_update(i);
+
+ ifsfile_replace_ifsvals(&new_ifsvals, new_elements);
+
+ if (ifsD->auto_preview)
+ ifs_compose_preview();
+
+ design_area_redraw();
+ }
+ else
+ warning = g_strdup_printf(_("File `%s' doesn't seem to be "
+ "an IFS Compose file.\n"), ifsfile_path);
+ g_free(buffer);
+ }
+ else
+ warning = g_strdup_printf(_("Cannot open file `%s'.\n"
+ "Check the path and permissions.\n"),
+ ifsfile_path);
+
+ if (warning) {
+ yeti_message_dialog(GTK_MESSAGE_ERROR, GTK_WINDOW(file_select),
+ _("Load failed"), warning);
+ g_free(warning);
+ }
+
+ gtk_widget_destroy(file_select);
+}
+
+static void
+ifs_compose_save_callback(GtkWidget *widget, gpointer data)
+{
+ GtkWidget *file_select;
+
+ file_select = gtk_file_selection_new(_("Save as IFS file"));
+ gimp_help_connect(file_select, gimp_standard_help_func,
+ "filters/ifscompose.html");
+ gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_select),
+ ifsfile_path);
+ g_signal_connect (G_OBJECT(GTK_FILE_SELECTION(file_select)->ok_button),
+ "clicked", G_CALLBACK(ifsfile_save), file_select);
+ g_signal_connect_swapped(G_OBJECT(GTK_FILE_SELECTION(file_select)->cancel_button),
+ "clicked", G_CALLBACK(gtk_widget_destroy),
+ file_select);
+ gtk_widget_show(file_select);
+}
+
+static void
+ifs_compose_load_callback(GtkWidget *widget, gpointer data)
+{
+ GtkWidget *file_select;
+
+ file_select = gtk_file_selection_new(_("Load IFS file"));
+ gimp_help_connect(file_select, gimp_standard_help_func,
+ "filters/ifscompose.html");
+ gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_select),
+ ifsfile_path);
+ g_signal_connect (G_OBJECT(GTK_FILE_SELECTION(file_select)->ok_button),
+ "clicked", G_CALLBACK(ifsfile_load), file_select);
+ g_signal_connect_swapped(G_OBJECT(GTK_FILE_SELECTION(file_select)->cancel_button),
+ "clicked", G_CALLBACK(gtk_widget_destroy),
+ file_select);
+ gtk_widget_show(file_select);
+}
+
static void
ifs_compose_new_callback (GtkWidget *widget,
gpointer data)
@@ -2519,7 +2825,7 @@
element_selected = g_realloc (element_selected,
ifsvals.num_elements * sizeof (gint));
- for (i=0;i< ifsvals.num_elements-1; i++)
element_selected[i] = FALSE;
element_selected[ifsvals.num_elements-1] = TRUE;
@@ -2535,6 +2841,9 @@
if (ifsD->auto_preview)
ifs_compose_preview ();
+
+ if (ifsvals.num_elements > 2)
+ gtk_widget_set_sensitive(ifsD->delete_button, TRUE);
}
static void
@@ -2543,8 +2852,6 @@
{
gint i;
gint new_current;
- if (ifsvals.num_elements current_element);
@@ -2562,7 +2869,7 @@
ifsvals.num_elements--;
- for (i=0;i< ifsvals.num_elements; i++)
if (element_selected[i])
{
new_current = i;
@@ -2576,6 +2883,9 @@
if (ifsD->auto_preview)
ifs_compose_preview ();
+
+ if (ifsvals.num_elements == 2)
+ gtk_widget_set_sensitive(ifsD->delete_button, FALSE);
}
static gint
@@ -2589,7 +2899,7 @@
if (iterations > ifsD->preview_iterations)
iterations = ifsD->preview_iterations;
- for (i=0;i< ifsvals.num_elements; i++)
aff_element_compute_trans(elements[i], width, height,
ifsvals.center_x, ifsvals.center_y);
@@ -2597,7 +2907,7 @@
iterations,&ifsvals,0,height,
ifsD->preview_data,NULL,NULL,TRUE);
- for (i=0;i< ifsvals.num_elements; i++)
aff_element_compute_trans(elements[i],
ifsDesign->area->allocation.width,
ifsDesign->area->allocation.height,
@@ -2632,7 +2942,7 @@
gimp_rgb_get_uchar (&color, &rc, &gc, &bc);
ptr = ifsD->preview_data;
- for (i=0; i < width * height; i++)
+ for (i = 0; i < width * height; i++)
{
*ptr++ = rc;
*ptr++ = gc;
--- gimp-1.3.11.orig/plug-ins/ifscompose/ifscompose_storage.c 2002-05-14 01:30:03.000000000 +0200
+++ gimp-1.3.11/plug-ins/ifscompose/ifscompose_storage.c 2003-01-30 21:48:53.000000000 +0100
@@ -129,6 +129,8 @@
if (token != G_TOKEN_RIGHT_CURLY)
return G_TOKEN_RIGHT_CURLY;
+ gimp_rgb_set_alpha(result, 1.0);
+
return G_TOKEN_NONE;
}
IFSCompose and bugzilla question
Hi,
"David Necas (Yeti)" writes:
I fixed and improved a few thing in the IFS Compose plugin. I know I should use bugzilla. The reasons I write here are: The existing bugreports are 1.2, while I fixed it in 1.3 (except #82472 fix, which I also backported to 1.2), I'm not sure how to handle this. Some issues were just side effects of an underlying real problem (#82466, #82473). Bug #82470 I fixed as a side effect of a larger change. The other things are not in bugzilla at all (like Save/Load), I don't have separate patches for them, and don't like the perspective of creating a dozen of individual reports and separating the patches only for the sake of bugzillization of the whole thing.
Please critize/check/apply the attached patch (against 1.3.11) and tell me what to do with:
nor #82472 Flip button doesn't act on all selected objects (I attached the backport to this one) min #82466 Toggling between Simple/Full in IfsCompose changes preview min #82473 IfsCompose disable Undo/Redo button when nothing to be undo enh #82470 IfsCompose filter: location of 'New' and 'Delete' button not...
and what to do generally in situations like this.
I think it's fine to fix these in 1.3 only. Only severe bugs should be fixed in 1.2. An exception can be made if the fix is trivial and thus certainly doesn't break things.
* set alpha of all colors to 1.0 -- ifscompose ignores alpha anyway, and default value (122???) makes the color selection dialog pretty confusing
The color selection dialog shouldn't show the alpha value. If it does, the color buttons are set up incorrectly. Make sure they are created with a type of GIMP_COLOR_AREA_FLAT.
I had a quick look at your patch and I have a few comments:
+ g_signal_connect(G_OBJECT(ifsD->redo_button), "clicked", + G_CALLBACK(redo), NULL); + gtk_widget_set_sensitive(ifsD->redo_button, FALSE); + gtk_widget_show(ifsD->redo_button);
I'd appreciate if you could try to follow the GIMP coding style which asks for a space before the opening bracket of a function call.
+void
+yeti_message_dialog(GtkMessageType type, GtkWindow *parent, + gchar *title, gchar *message) +{
+ GtkWidget *dlg;
+
+ dlg = gtk_message_dialog_new(parent, GTK_DIALOG_MODAL, + type, GTK_BUTTONS_OK, message); + if (title)
+ gtk_window_set_title(GTK_WINDOW(dlg), title); + gtk_window_set_wmclass(GTK_WINDOW(dlg), "message", "Gimp"); + gtk_dialog_run(GTK_DIALOG(dlg));
+ gtk_widget_destroy(dlg);
+}
yeti_message_dialog() is a rather unintuitive name for a function that is supposed to create a modal dialog.
+static void
+ifsfile_save(GtkWidget *widget, GtkWidget *file_select) +{
+ gchar *str = ifsvals_stringify(&ifsvals, elements); + FILE *fh;
+ char *warning = NULL;
+
+ strcpy(ifsfile_path,
+ gtk_file_selection_get_filename(GTK_FILE_SELECTION(file_select))); + fh = fopen(ifsfile_path, "w");
+ if (fh) {
+ fputs(str, fh);
+ fclose(fh);
+ }
+ else
+ warning = g_strdup_printf(_("Cannot save into file `%s'.\n" + "Check the path and permissions.\n"), + ifsfile_path); +
+ free(str);
+ if (warning) {
+ yeti_message_dialog(GTK_MESSAGE_ERROR, GTK_WINDOW(file_select), + "Save failed", warning);
Why do you use a modal dialog here? We usually don't use modal dialogs in gimp. You should rather make the message dialog transient for the file selection dialog and set destroy_with_parent on it.
+/* load an ifs file */
+static void
+ifsfile_load(GtkWidget *widget, GtkWidget *file_select) +{
+ FILE *fh;
+ guint size = 4096;
+ guint len, pos;
+ guchar *buffer;
+ AffElement **new_elements;
+ IfsComposeVals new_ifsvals;
+ gchar *warning = NULL;
+
+ buffer = g_new(guchar, size);
+ strcpy(ifsfile_path,
+ gtk_file_selection_get_filename(GTK_FILE_SELECTION(file_select)));
Please, don't ever use strcpy(). It's dangerous and should never be used.
+ fh = fopen(ifsfile_path, "r"); + if (fh) {
+ pos = 0;
+ while ((len = fread(buffer + pos, 1, size - pos, fh)) == size-pos) { + pos = size;
+ size *= 2;
+ buffer = g_realloc(buffer, size); + }
+ fclose(fh);
This code looks like a reimplementation of g_file_get_contents(). You might want to use the latter instead.
Salut, Sven
IFSCompose and bugzilla question
Hi,
myself wrote:
The color selection dialog shouldn't show the alpha value. If it does, the color buttons are set up incorrectly. Make sure they are created with a type of GIMP_COLOR_AREA_FLAT.
actually the bug was in GimpColorButton itself. It used to enable opacity control in the GTK+ color selection dialog unconditonally. This is now fixed in CVS.
Salut, Sven
IFSCompose and bugzilla question
On Sun, Feb 02, 2003 at 01:55:37AM +0100, Sven Neumann wrote:
* set alpha of all colors to 1.0 -- ifscompose ignores alpha anyway, and default value (122???) makes the color selection dialog pretty confusing
The color selection dialog shouldn't show the alpha value. If it does, the color buttons are set up incorrectly. Make sure they are created with a type of GIMP_COLOR_AREA_FLAT.
...(later) actually the bug was in GimpColorButton itself. It used to enable opacity control in the GTK+ color selection dialog unconditonally. This is now fixed in CVS.
So I removed the alpha=1.0 settings.
I'd appreciate if you could try to follow the GIMP coding style which asks for a space before the opening bracket of a function call.
Well, OK. I'll restrain commenting this particular coding style requirement, because I'd have to be vulgar. I'll never learn to type them when coding, so I always have to add them later. So I added them with search and replace, and there were maybe more places in the original code lacking the spaces than in my (the original often didn't even have spaces after commas, I fixed some before and the remaining now). But, well, OK.
yeti_message_dialog() is a rather unintuitive name for a function that is supposed to create a modal dialog.
Why do you use a modal dialog here? We usually don't use modal dialogs in gimp. You should rather make the message dialog transient for the file selection dialog and set destroy_with_parent on it.
It was just copied from some other code. I changed yeti_ to ifscompose_, fixed problems when filename contained %, removed the modality and also parent destruction. After all, it makes more sense to try another file name when one fails.
Please, don't ever use strcpy(). It's dangerous and should never be used.
It's funny, the strcpy () got there from the Qbist plugin. I looked there for simple file save/load code. So Qbist should be probably fixed too.
This code looks like a reimplementation of g_file_get_contents(). You might want to use the latter instead.
Unfortunately, I wasn't aware of g_file_get_contents (). It uses it now.
With all the space-after-something stuff the patch has grown over 45k, so I'm not posting it by email. It's here:
http://physics.muni.cz/~yeti/download/tmp/ifscompose-1.3.11.patch
There's a one more issue I'd like to raise: the design area is still too tiny. While I'd prefer DESIGN_AREA_MAX_SIZE about 400 (now it's 256), I understand it wouldn't fit onto 800x600 screen. But even increasing the size to 320 or 300 would help considerably.
Thanks for the comments.
Regards,
Yeti
IFSCompose and bugzilla question
Hi,
I've applied your changes to the HEAD branch. I had to resolve some merge conflicts but I'm confident that I got everything right. I've then fixed some minor issues (mainly coding style) with the new load and save routines and did a second commit.
It's funny, the strcpy () got there from the Qbist plugin. I looked there for simple file save/load code. So Qbist should be probably fixed too.
yes indeed.
There's a one more issue I'd like to raise: the design area is still too tiny. While I'd prefer DESIGN_AREA_MAX_SIZE about 400 (now it's 256), I understand it wouldn't fit onto 800x600 screen. But even increasing the size to 320 or 300 would help considerably.
IMO bug #82470 is also still open. See my comments in Bugzilla.
Salut, Sven