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>
* plug-ins/common/vpropagate.c: don't redefine RGB and GRAY here.

View File

@ -21,14 +21,12 @@
/* 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
* (eg floppy disk icon) Currently, its a "*" and it's on the
* wrong line.
*
* - scroll to keep current selection visible. Can some GTK guru
* help out?
* - work out which (if any) is the clean image, and mark it as such.
* Currently, it's on the wrong line.
*
* - undo names are less than useful. This isn't a problem with
* undo_history.c itself, more with the rather chaotic way
@ -37,7 +35,7 @@
* specifying an (enum) type, it should be a const char * ?
*
* BUGS:
* - clean star in wrong place
* - clean pixmap in wrong place
* - window title not updated on image title change
*
* Initial rev 0.01, (c) 19 Sept 1999 Austin Donnelly <austin@gimp.org>
@ -46,6 +44,7 @@
#include <gtk/gtk.h>
#include "gimpui.h"
#include "temp_buf.h"
#include "undo.h"
#include "libgimp/gimpintl.h"
@ -54,6 +53,12 @@
#include "pixmaps/lower.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
{
GImage *gimage; /* image we're tracking undo info for */
@ -64,6 +69,12 @@ typedef struct
int old_selection; /* previous selection in the clist */
} undo_history_st;
typedef struct
{
GtkCList *clist;
gint row;
GImage *gimage;
} idle_preview_args;
/*
* Theory of operation.
@ -130,6 +141,149 @@ static GdkBitmap *clean_mask = NULL;
/**************************************************************/
/* 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 */
static void
undo_history_close_callback (GtkWidget *widget,
@ -232,6 +386,8 @@ undo_history_undo_event (GtkWidget *widget,
int cur_selection;
GtkCList *clist;
gint row;
GdkPixmap *pixmap;
GdkBitmap *mask;
list = GTK_CLIST (st->clist)->selection;
g_return_if_fail (list != NULL);
@ -259,15 +415,19 @@ undo_history_undo_event (GtkWidget *widget,
row = gtk_clist_append (clist, namelist);
g_assert (clist->rows == cur_selection+2);
undo_history_set_pixmap (clist, row, st->gimage);
/* always force selection to bottom, and scroll to it */
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_moveto (clist, clist->rows - 1, 0, 1.0, 0.0);
cur_selection = clist->rows-1;
break;
case UNDO_EXPIRED:
/* 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);
break;
@ -276,6 +436,10 @@ undo_history_undo_event (GtkWidget *widget,
g_return_if_fail (cur_selection >= 1);
gtk_clist_select_row (clist, cur_selection - 1, -1);
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;
case UNDO_REDO:
@ -283,6 +447,10 @@ undo_history_undo_event (GtkWidget *widget,
g_return_if_fail (cur_selection+1 < clist->rows);
gtk_clist_select_row (clist, cur_selection+1, -1);
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;
case UNDO_FREE:
@ -386,15 +554,10 @@ undo_history_init_undo (const char *undoitemname,
namelist[2] = (char *) undoitemname;
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;
}
/* Ditto, but doesn't change selection */
/* Ditto */
static int
undo_history_init_redo (const char *undoitemname,
void *data)
@ -403,8 +566,7 @@ undo_history_init_redo (const char *undoitemname,
char *namelist[3];
gint row;
namelist[0] = NULL;
namelist[1] = NULL;
namelist[0] = NULL; namelist[1] = NULL;
namelist[2] = (char *) undoitemname;
row = gtk_clist_append (GTK_CLIST (st->clist), namelist);
@ -466,14 +628,15 @@ undo_history_new (GImage *gimage)
st);
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 */
st->clist = gtk_clist_new (3);
gtk_clist_set_selection_mode (GTK_CLIST (st->clist), GTK_SELECTION_BROWSE);
gtk_clist_set_reorderable (GTK_CLIST (st->clist), FALSE);
gtk_clist_set_column_width (GTK_CLIST (st->clist), 0, 1);
gtk_clist_set_column_width (GTK_CLIST (st->clist), 1, 16);
gtk_clist_set_row_height (GTK_CLIST (st->clist), UNDO_THUMBNAIL_SIZE + 2);
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);
/* allocate the pixmaps if not already done */
@ -503,11 +666,16 @@ undo_history_new (GImage *gimage)
/* work out the initial contents */
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_history_prepend_special (GTK_CLIST (st->clist));
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",
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);
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;
}