fixed scrolling to currently selected row and added preview images.

* app/undo_history.c: fixed scrolling to currently selected row
  and added preview images.


--Sven
This commit is contained in:
Sven Neumann
1999-10-08 16:53:08 +00:00
parent 38a67ce230
commit bac4d13db2
2 changed files with 199 additions and 25 deletions

View File

@ -1,3 +1,8 @@
Fri Oct 8 18:46:43 MEST 1999 Sven Neumann <sven@gimp.org>
* app/undo_history.c: fixed scrolling to currently selected row
and added preview images.
Fri Oct 8 12:16:05 MEST 1999 Sven Neumann <sven@gimp.org> Fri Oct 8 12:16:05 MEST 1999 Sven Neumann <sven@gimp.org>
* plug-ins/common/vpropagate.c: don't redefine RGB and GRAY here. * plug-ins/common/vpropagate.c: don't redefine RGB and GRAY here.

View File

@ -21,14 +21,12 @@
/* TODO: /* TODO:
* *
* - previews of the image on each line (reuse the L&C previews?) * - reuse the L&C previews?
* Currently we use gimp_image_construct_composite_preview ()
* which makes use of the preview_cache on a per layer basis.
* *
* - work out which (if any) is the clean image, and mark it as such * - work out which (if any) is the clean image, and mark it as such.
* (eg floppy disk icon) Currently, its a "*" and it's on the * Currently, it's on the wrong line.
* wrong line.
*
* - scroll to keep current selection visible. Can some GTK guru
* help out?
* *
* - undo names are less than useful. This isn't a problem with * - undo names are less than useful. This isn't a problem with
* undo_history.c itself, more with the rather chaotic way * undo_history.c itself, more with the rather chaotic way
@ -37,7 +35,7 @@
* specifying an (enum) type, it should be a const char * ? * specifying an (enum) type, it should be a const char * ?
* *
* BUGS: * BUGS:
* - clean star in wrong place * - clean pixmap in wrong place
* - window title not updated on image title change * - window title not updated on image title change
* *
* Initial rev 0.01, (c) 19 Sept 1999 Austin Donnelly <austin@gimp.org> * Initial rev 0.01, (c) 19 Sept 1999 Austin Donnelly <austin@gimp.org>
@ -46,6 +44,7 @@
#include <gtk/gtk.h> #include <gtk/gtk.h>
#include "gimpui.h" #include "gimpui.h"
#include "temp_buf.h"
#include "undo.h" #include "undo.h"
#include "libgimp/gimpintl.h" #include "libgimp/gimpintl.h"
@ -54,6 +53,12 @@
#include "pixmaps/lower.xpm" #include "pixmaps/lower.xpm"
#include "pixmaps/yes.xpm" #include "pixmaps/yes.xpm"
#define GRAD_CHECK_SIZE_SM 4
#define GRAD_CHECK_DARK (1.0 / 3.0)
#define GRAD_CHECK_LIGHT (2.0 / 3.0)
#define UNDO_THUMBNAIL_SIZE 24
typedef struct typedef struct
{ {
GImage *gimage; /* image we're tracking undo info for */ GImage *gimage; /* image we're tracking undo info for */
@ -64,6 +69,12 @@ typedef struct
int old_selection; /* previous selection in the clist */ int old_selection; /* previous selection in the clist */
} undo_history_st; } undo_history_st;
typedef struct
{
GtkCList *clist;
gint row;
GImage *gimage;
} idle_preview_args;
/* /*
* Theory of operation. * Theory of operation.
@ -130,6 +141,149 @@ static GdkBitmap *clean_mask = NULL;
/**************************************************************/ /**************************************************************/
/* Local functions */ /* Local functions */
static gint
undo_history_set_pixmap_idle (gpointer data)
{
idle_preview_args *idle = data;
static GdkGC *gc = NULL;
TempBuf *buf;
GdkPixmap *pixmap;
guchar *src;
gdouble r, g, b, a;
gdouble c0, c1;
guchar *p0, *p1, *even, *odd;
gint width, height, bpp;
gint x, y;
if (!gc)
gc = gdk_gc_new (GTK_WIDGET (idle->clist)->window);
width = idle->gimage->width;
height = idle->gimage->height;
/* Get right aspect ratio */
if (width > height)
{
height = (UNDO_THUMBNAIL_SIZE * height) / width;
width = UNDO_THUMBNAIL_SIZE;
}
else
{
width = (UNDO_THUMBNAIL_SIZE * width) / height;
height = UNDO_THUMBNAIL_SIZE;
}
buf = gimp_image_construct_composite_preview (idle->gimage, width, height);
bpp = buf->bytes;
pixmap = gdk_pixmap_new (GTK_WIDGET (idle->clist)->window, width+2, height+2, -1);
gdk_draw_rectangle (pixmap,
GTK_WIDGET (idle->clist)->style->bg_gc[GTK_STATE_NORMAL],
TRUE,
0, 0,
width + 2, height + 2);
src = temp_buf_data (buf);
even = g_malloc (width * 3);
odd = g_malloc (width * 3);
for (y = 0; y < height; y++)
{
p0 = even;
p1 = odd;
for (x = 0; x < width; x++)
{
if (bpp == 4)
{
r = ((gdouble) src[x*4+0]) / 255.0;
g = ((gdouble) src[x*4+1]) / 255.0;
b = ((gdouble) src[x*4+2]) / 255.0;
a = ((gdouble) src[x*4+3]) / 255.0;
}
else if (bpp == 3)
{
r = ((gdouble) src[x*3+0]) / 255.0;
g = ((gdouble) src[x*3+1]) / 255.0;
b = ((gdouble) src[x*3+2]) / 255.0;
a = 1.0;
}
else
{
r = ((gdouble) src[x*bpp+0]) / 255.0;
g = b = r;
if (bpp == 2)
a = ((gdouble) src[x*bpp+1]) / 255.0;
else
a = 1.0;
}
if ((x / GRAD_CHECK_SIZE_SM) & 1)
{
c0 = GRAD_CHECK_LIGHT;
c1 = GRAD_CHECK_DARK;
}
else
{
c0 = GRAD_CHECK_DARK;
c1 = GRAD_CHECK_LIGHT;
}
*p0++ = (c0 + (r - c0) * a) * 255.0;
*p0++ = (c0 + (g - c0) * a) * 255.0;
*p0++ = (c0 + (b - c0) * a) * 255.0;
*p1++ = (c1 + (r - c1) * a) * 255.0;
*p1++ = (c1 + (g - c1) * a) * 255.0;
*p1++ = (c1 + (b - c1) * a) * 255.0;
}
if ((y / GRAD_CHECK_SIZE_SM) & 1)
{
gdk_draw_rgb_image (pixmap, gc,
1, y + 1,
width, 1,
GDK_RGB_DITHER_NORMAL,
(guchar *) odd, 3);
}
else
{
gdk_draw_rgb_image (pixmap, gc,
1, y + 1,
width, 1,
GDK_RGB_DITHER_NORMAL,
(guchar *) even, 3);
}
src += width * bpp;
}
g_free (even);
g_free (odd);
temp_buf_free (buf);
gtk_clist_set_pixmap (idle->clist, idle->row, 0, pixmap, NULL);
gdk_pixmap_unref (pixmap);
return (FALSE);
}
static void
undo_history_set_pixmap (GtkCList *clist,
gint row,
GImage *gimage)
{
static idle_preview_args idle;
idle.clist = clist;
idle.row = row;
idle.gimage = gimage;
gtk_idle_add ((GtkFunction)undo_history_set_pixmap_idle, &idle);
}
/* close button clicked */ /* close button clicked */
static void static void
undo_history_close_callback (GtkWidget *widget, undo_history_close_callback (GtkWidget *widget,
@ -232,6 +386,8 @@ undo_history_undo_event (GtkWidget *widget,
int cur_selection; int cur_selection;
GtkCList *clist; GtkCList *clist;
gint row; gint row;
GdkPixmap *pixmap;
GdkBitmap *mask;
list = GTK_CLIST (st->clist)->selection; list = GTK_CLIST (st->clist)->selection;
g_return_if_fail (list != NULL); g_return_if_fail (list != NULL);
@ -259,15 +415,19 @@ undo_history_undo_event (GtkWidget *widget,
row = gtk_clist_append (clist, namelist); row = gtk_clist_append (clist, namelist);
g_assert (clist->rows == cur_selection+2); g_assert (clist->rows == cur_selection+2);
undo_history_set_pixmap (clist, row, st->gimage);
/* always force selection to bottom, and scroll to it */ /* always force selection to bottom, and scroll to it */
gtk_clist_select_row (clist, clist->rows - 1, -1); gtk_clist_select_row (clist, clist->rows - 1, -1);
gtk_clist_moveto (clist, clist->rows-1, 0, 1.0, 0.0);
gtk_clist_thaw (clist); gtk_clist_thaw (clist);
gtk_clist_moveto (clist, clist->rows - 1, 0, 1.0, 0.0);
cur_selection = clist->rows-1; cur_selection = clist->rows-1;
break; break;
case UNDO_EXPIRED: case UNDO_EXPIRED:
/* remove earliest row, but not our special first one */ /* remove earliest row, but not our special first one */
if (gtk_clist_get_pixmap (clist, 1, 0, &pixmap, &mask))
gtk_clist_set_pixmap (clist, 0, 0, pixmap, mask);
gtk_clist_remove (clist, 1); gtk_clist_remove (clist, 1);
break; break;
@ -276,6 +436,10 @@ undo_history_undo_event (GtkWidget *widget,
g_return_if_fail (cur_selection >= 1); g_return_if_fail (cur_selection >= 1);
gtk_clist_select_row (clist, cur_selection - 1, -1); gtk_clist_select_row (clist, cur_selection - 1, -1);
cur_selection--; cur_selection--;
if (!gtk_clist_get_pixmap (clist, cur_selection, 0, &pixmap, &mask))
undo_history_set_pixmap (clist, cur_selection, st->gimage);
if ( !(gtk_clist_row_is_visible (clist, cur_selection) & GTK_VISIBILITY_FULL))
gtk_clist_moveto (clist, cur_selection, 0, 0.0, 0.0);
break; break;
case UNDO_REDO: case UNDO_REDO:
@ -283,6 +447,10 @@ undo_history_undo_event (GtkWidget *widget,
g_return_if_fail (cur_selection+1 < clist->rows); g_return_if_fail (cur_selection+1 < clist->rows);
gtk_clist_select_row (clist, cur_selection+1, -1); gtk_clist_select_row (clist, cur_selection+1, -1);
cur_selection++; cur_selection++;
if (!gtk_clist_get_pixmap (clist, cur_selection, 0, &pixmap, &mask))
undo_history_set_pixmap (clist, cur_selection, st->gimage);
if ( !(gtk_clist_row_is_visible (clist, cur_selection) & GTK_VISIBILITY_FULL))
gtk_clist_moveto (clist, cur_selection, 0, 1.0, 0.0);
break; break;
case UNDO_FREE: case UNDO_FREE:
@ -386,15 +554,10 @@ undo_history_init_undo (const char *undoitemname,
namelist[2] = (char *) undoitemname; namelist[2] = (char *) undoitemname;
row = gtk_clist_prepend (GTK_CLIST (st->clist), namelist); row = gtk_clist_prepend (GTK_CLIST (st->clist), namelist);
/* force selection to bottom */
gtk_clist_select_row (GTK_CLIST (st->clist),
GTK_CLIST (st->clist)->rows - 1, -1);
st->old_selection = GTK_CLIST (st->clist)->rows - 1;
return 0; return 0;
} }
/* Ditto, but doesn't change selection */ /* Ditto */
static int static int
undo_history_init_redo (const char *undoitemname, undo_history_init_redo (const char *undoitemname,
void *data) void *data)
@ -403,8 +566,7 @@ undo_history_init_redo (const char *undoitemname,
char *namelist[3]; char *namelist[3];
gint row; gint row;
namelist[0] = NULL; namelist[0] = NULL; namelist[1] = NULL;
namelist[1] = NULL;
namelist[2] = (char *) undoitemname; namelist[2] = (char *) undoitemname;
row = gtk_clist_append (GTK_CLIST (st->clist), namelist); row = gtk_clist_append (GTK_CLIST (st->clist), namelist);
@ -466,14 +628,15 @@ undo_history_new (GImage *gimage)
st); st);
scrolled_win = gtk_scrolled_window_new (NULL, NULL); scrolled_win = gtk_scrolled_window_new (NULL, NULL);
gtk_widget_set_usize (GTK_WIDGET (scrolled_win), 192, -1); gtk_widget_set_usize (GTK_WIDGET (scrolled_win), 192, 112);
/* clist of undo actions */ /* clist of undo actions */
st->clist = gtk_clist_new (3); st->clist = gtk_clist_new (3);
gtk_clist_set_selection_mode (GTK_CLIST (st->clist), GTK_SELECTION_BROWSE); gtk_clist_set_selection_mode (GTK_CLIST (st->clist), GTK_SELECTION_BROWSE);
gtk_clist_set_reorderable (GTK_CLIST (st->clist), FALSE); gtk_clist_set_reorderable (GTK_CLIST (st->clist), FALSE);
gtk_clist_set_column_width (GTK_CLIST (st->clist), 0, 1); gtk_clist_set_row_height (GTK_CLIST (st->clist), UNDO_THUMBNAIL_SIZE + 2);
gtk_clist_set_column_width (GTK_CLIST (st->clist), 1, 16); gtk_clist_set_column_width (GTK_CLIST (st->clist), 0, UNDO_THUMBNAIL_SIZE + 2);
gtk_clist_set_column_width (GTK_CLIST (st->clist), 1, 18);
gtk_clist_set_column_min_width (GTK_CLIST (st->clist), 2, 64); gtk_clist_set_column_min_width (GTK_CLIST (st->clist), 2, 64);
/* allocate the pixmaps if not already done */ /* allocate the pixmaps if not already done */
@ -503,11 +666,16 @@ undo_history_new (GImage *gimage)
/* work out the initial contents */ /* work out the initial contents */
undo_map_over_undo_stack (st->gimage, undo_history_init_undo, st); undo_map_over_undo_stack (st->gimage, undo_history_init_undo, st);
/* force selection to bottom */
gtk_clist_select_row (GTK_CLIST (st->clist),
GTK_CLIST (st->clist)->rows - 1, -1);
undo_map_over_redo_stack (st->gimage, undo_history_init_redo, st); undo_map_over_redo_stack (st->gimage, undo_history_init_redo, st);
undo_history_prepend_special (GTK_CLIST (st->clist)); undo_history_prepend_special (GTK_CLIST (st->clist));
st->old_selection = GPOINTER_TO_INT(GTK_CLIST(st->clist)->selection->data); st->old_selection = GPOINTER_TO_INT(GTK_CLIST(st->clist)->selection->data);
/* draw the preview of the current state */
undo_history_set_pixmap (GTK_CLIST (st->clist), st->old_selection, st->gimage);
gtk_signal_connect (GTK_OBJECT (st->clist), "select_row", gtk_signal_connect (GTK_OBJECT (st->clist), "select_row",
undo_history_select_row_callback, st); undo_history_select_row_callback, st);
@ -576,6 +744,7 @@ undo_history_new (GImage *gimage)
undo_history_set_sensitive (st, GTK_CLIST (st->clist)->rows); undo_history_set_sensitive (st, GTK_CLIST (st->clist)->rows);
gtk_widget_show (GTK_WIDGET (st->shell)); gtk_widget_show (GTK_WIDGET (st->shell));
gtk_clist_moveto (GTK_CLIST (st->clist), st->old_selection, 0, 0.5, 0.0);
return st->shell; return st->shell;
} }