app/widgets/Makefile.am app/widgets/widgets-types.h new widget which

2005-07-14  Michael Natterer  <mitch@gimp.org>

	* app/widgets/Makefile.am
	* app/widgets/widgets-types.h
	* app/widgets/gimppaletteview.[ch]: new widget which manages the
	selected palette entry itself and emits "selected", "activated"
	and "context" signals. Not used yet.

	* app/widgets/gimpviewrendererpalette.[ch]: reimplemented palette
	drawing: added optional grid drawing and APIs to configure the
	renderer. Should be ready for the palette editor now.
This commit is contained in:
Michael Natterer 2005-07-14 14:41:29 +00:00 committed by Michael Natterer
parent 1e568e1c58
commit c0a10c8303
7 changed files with 576 additions and 34 deletions

View File

@ -1,3 +1,15 @@
2005-07-14 Michael Natterer <mitch@gimp.org>
* app/widgets/Makefile.am
* app/widgets/widgets-types.h
* app/widgets/gimppaletteview.[ch]: new widget which manages the
selected palette entry itself and emits "selected", "activated"
and "context" signals. Not used yet.
* app/widgets/gimpviewrendererpalette.[ch]: reimplemented palette
drawing: added optional grid drawing and APIs to configure the
renderer. Should be ready for the palette editor now.
2005-07-13 Michael Natterer <mitch@gimp.org>
* app/widgets/gimpviewrendererpalette.c

View File

@ -189,6 +189,8 @@ libappwidgets_a_sources = \
gimppaletteeditor.h \
gimppaletteselect.c \
gimppaletteselect.h \
gimppaletteview.c \
gimppaletteview.h \
gimppatternfactoryview.c \
gimppatternfactoryview.h \
gimppatternselect.c \

View File

@ -0,0 +1,365 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* gimppaletteview.c
* Copyright (C) 2005 Michael Natterer <mitch@gimp.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <gtk/gtk.h>
#include "widgets-types.h"
#include "core/gimppalette.h"
#include "core/gimpmarshal.h"
#include "gimppaletteview.h"
#include "gimpviewrendererpalette.h"
enum
{
ENTRY_SELECTED,
ENTRY_ACTIVATED,
ENTRY_CONTEXT,
LAST_SIGNAL
};
static void gimp_palette_view_class_init (GimpPaletteViewClass *klass);
static void gimp_palette_view_init (GimpPaletteView *view);
static void gimp_palette_view_realize (GtkWidget *widget);
static void gimp_palette_view_unrealize (GtkWidget *widget);
static gboolean gimp_palette_view_expose (GtkWidget *widget,
GdkEventExpose *eevent);
static gboolean gimp_palette_view_button_press (GtkWidget *widget,
GdkEventButton *bevent);
static void gimp_palette_view_set_viewable (GimpView *view,
GimpViewable *old_viewable,
GimpViewable *new_viewable);
static void gimp_palette_view_expose_entry (GimpPaletteView *view,
GimpPaletteEntry *entry);
static void gimp_palette_view_draw_selected (GimpPaletteView *view,
GdkRectangle *area);
static void gimp_palette_view_invalidate (GimpPalette *palette,
GimpPaletteView *view);
static guint view_signals[LAST_SIGNAL] = { 0 };
static GimpViewClass *parent_class = NULL;
GType
gimp_palette_view_get_type (void)
{
static GType view_type = 0;
if (! view_type)
{
static const GTypeInfo view_info =
{
sizeof (GimpPaletteViewClass),
NULL, /* base_init */
NULL, /* base_finalize */
(GClassInitFunc) gimp_palette_view_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
sizeof (GimpPaletteView),
0, /* n_preallocs */
(GInstanceInitFunc) gimp_palette_view_init,
};
view_type = g_type_register_static (GIMP_TYPE_VIEW,
"GimpPaletteView",
&view_info, 0);
}
return view_type;
}
static void
gimp_palette_view_class_init (GimpPaletteViewClass *klass)
{
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
GimpViewClass *view_class = GIMP_VIEW_CLASS (klass);
parent_class = g_type_class_peek_parent (klass);
view_signals[ENTRY_SELECTED] =
g_signal_new ("entry-selected",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (GimpPaletteViewClass, entry_selected),
NULL, NULL,
gimp_marshal_VOID__POINTER,
G_TYPE_NONE, 1,
G_TYPE_POINTER);
view_signals[ENTRY_ACTIVATED] =
g_signal_new ("entry-activated",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (GimpPaletteViewClass, entry_activated),
NULL, NULL,
gimp_marshal_VOID__POINTER,
G_TYPE_NONE, 1,
G_TYPE_POINTER);
view_signals[ENTRY_CONTEXT] =
g_signal_new ("entry-context",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (GimpPaletteViewClass, entry_context),
NULL, NULL,
gimp_marshal_VOID__POINTER,
G_TYPE_NONE, 1,
G_TYPE_POINTER);
widget_class->realize = gimp_palette_view_realize;
widget_class->unrealize = gimp_palette_view_unrealize;
widget_class->expose_event = gimp_palette_view_expose;
widget_class->button_press_event = gimp_palette_view_button_press;
view_class->set_viewable = gimp_palette_view_set_viewable;
}
static void
gimp_palette_view_init (GimpPaletteView *view)
{
GTK_WIDGET_SET_FLAGS (view, GTK_CAN_FOCUS);
view->selected = NULL;
view->dnd_entry = NULL;
view->gc = NULL;
}
static void
gimp_palette_view_realize (GtkWidget *widget)
{
GimpPaletteView *view = GIMP_PALETTE_VIEW (widget);
GTK_WIDGET_CLASS (parent_class)->realize (widget);
view->gc = gdk_gc_new (widget->window);
gdk_gc_set_function (view->gc, GDK_INVERT);
gdk_gc_set_line_attributes (view->gc, 1,
GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_ROUND);
}
static void
gimp_palette_view_unrealize (GtkWidget *widget)
{
GimpPaletteView *view = GIMP_PALETTE_VIEW (widget);
if (view->gc)
{
g_object_unref (view->gc);
view->gc = NULL;
}
GTK_WIDGET_CLASS (parent_class)->unrealize (widget);
}
static gboolean
gimp_palette_view_expose (GtkWidget *widget,
GdkEventExpose *eevent)
{
if (GTK_WIDGET_DRAWABLE (widget))
{
GimpPaletteView *view = GIMP_PALETTE_VIEW (widget);
GTK_WIDGET_CLASS (parent_class)->expose_event (widget, eevent);
if (view->selected)
gimp_palette_view_draw_selected (view, &eevent->area);
}
return FALSE;
}
static gboolean
gimp_palette_view_button_press (GtkWidget *widget,
GdkEventButton *bevent)
{
GimpPaletteView *view = GIMP_PALETTE_VIEW (widget);
GimpViewRendererPalette *renderer;
GimpPaletteEntry *entry = NULL;
gint row, col;
renderer = GIMP_VIEW_RENDERER_PALETTE (GIMP_VIEW (view)->renderer);
col = bevent->x / renderer->cell_width;
row = bevent->y / renderer->cell_height;
if (col >= 0 && col < renderer->columns &&
row >= 0 && row < renderer->rows)
{
entry =
g_list_nth_data (GIMP_PALETTE (GIMP_VIEW (view)->renderer->viewable)->colors,
row * renderer->columns + col);
}
view->dnd_entry = entry;
if (! entry || bevent->button == 2)
return FALSE;
switch (bevent->button)
{
case 1:
if (bevent->type == GDK_BUTTON_PRESS)
{
gimp_palette_view_select_entry (view, entry);
}
else if (bevent->type == GDK_2BUTTON_PRESS && entry == view->selected)
{
g_signal_emit (view, view_signals[ENTRY_ACTIVATED], 0, entry);
}
break;
case 3:
if (bevent->type == GDK_BUTTON_PRESS)
{
if (entry != view->selected)
gimp_palette_view_select_entry (view, entry);
g_signal_emit (view, view_signals[ENTRY_CONTEXT], 0, entry);
}
break;
default:
break;
}
return FALSE;
}
static void
gimp_palette_view_set_viewable (GimpView *view,
GimpViewable *old_viewable,
GimpViewable *new_viewable)
{
GimpPaletteView *pal_view = GIMP_PALETTE_VIEW (view);
pal_view->dnd_entry = NULL;
pal_view->selected = NULL;
if (old_viewable)
g_signal_handlers_disconnect_by_func (old_viewable,
gimp_palette_view_invalidate,
view);
GIMP_VIEW_CLASS (parent_class)->set_viewable (view,
old_viewable, new_viewable);
if (new_viewable)
g_signal_connect (new_viewable, "invalidate-preview",
G_CALLBACK (gimp_palette_view_invalidate),
view);
}
/* public functions */
void
gimp_palette_view_select_entry (GimpPaletteView *view,
GimpPaletteEntry *entry)
{
g_return_if_fail (GIMP_IS_PALETTE_VIEW (view));
if (entry == view->selected)
return;
if (view->selected)
gimp_palette_view_expose_entry (view, view->selected);
view->selected = entry;
if (view->selected)
gimp_palette_view_expose_entry (view, view->selected);
g_signal_emit (view, view_signals[ENTRY_SELECTED], 0, view->selected);
}
/* private funcions */
static void
gimp_palette_view_expose_entry (GimpPaletteView *view,
GimpPaletteEntry *entry)
{
GimpViewRendererPalette *renderer;
gint row, col;
GtkWidget *widget = GTK_WIDGET (view);
renderer = GIMP_VIEW_RENDERER_PALETTE (GIMP_VIEW (view)->renderer);
row = entry->position / renderer->columns;
col = entry->position % renderer->columns;
gtk_widget_queue_draw_area (GTK_WIDGET (view),
widget->allocation.x + col * renderer->cell_width,
widget->allocation.y + row * renderer->cell_height,
renderer->cell_width + 1,
renderer->cell_height + 1);
}
static void
gimp_palette_view_draw_selected (GimpPaletteView *pal_view,
GdkRectangle *area)
{
GimpView *view = GIMP_VIEW (pal_view);
if (view->renderer->viewable && pal_view->selected)
{
GtkWidget *widget = GTK_WIDGET (view);
GimpViewRendererPalette *renderer;
gint row, col;
renderer = GIMP_VIEW_RENDERER_PALETTE (view->renderer);
row = pal_view->selected->position / renderer->columns;
col = pal_view->selected->position % renderer->columns;
if (area)
gdk_gc_set_clip_rectangle (pal_view->gc, area);
gdk_draw_rectangle (widget->window, pal_view->gc,
FALSE,
widget->allocation.x + col * renderer->cell_width,
widget->allocation.y + row * renderer->cell_height,
renderer->cell_width,
renderer->cell_height);
if (area)
gdk_gc_set_clip_rectangle (pal_view->gc, NULL);
}
}
static void
gimp_palette_view_invalidate (GimpPalette *palette,
GimpPaletteView *view)
{
view->dnd_entry = NULL;
if (view->selected && ! g_list_find (palette->colors, view->selected))
view->selected = NULL;
}

View File

@ -0,0 +1,66 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* gimppaletteview.h
* Copyright (C) 2005 Michael Natterer <mitch@gimp.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __GIMP_PALETTE_VIEW_H__
#define __GIMP_PALETTE_VIEW_H__
#include "gimpview.h"
#define GIMP_TYPE_PALETTE_VIEW (gimp_palette_view_get_type ())
#define GIMP_PALETTE_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_PALETTE_VIEW, GimpPaletteView))
#define GIMP_PALETTE_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_PALETTE_VIEW, GimpPaletteViewClass))
#define GIMP_IS_PALETTE_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE (obj, GIMP_TYPE_PALETTE_VIEW))
#define GIMP_IS_PALETTE_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_PALETTE_VIEW))
#define GIMP_PALETTE_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_PALETTE_VIEW, GimpPaletteViewClass))
typedef struct _GimpPaletteViewClass GimpPaletteViewClass;
struct _GimpPaletteView
{
GimpView parent_instance;
GimpPaletteEntry *selected;
GimpPaletteEntry *dnd_entry;
GdkGC *gc;
};
struct _GimpPaletteViewClass
{
GimpViewClass parent_class;
void (* entry_selected) (GimpPaletteView *view,
GimpPaletteEntry *entry);
void (* entry_activated) (GimpPaletteView *view,
GimpPaletteEntry *entry);
void (* entry_context) (GimpPaletteView *view,
GimpPaletteEntry *entry);
};
GType gimp_palette_view_get_type (void) G_GNUC_CONST;
void gimp_palette_view_select_entry (GimpPaletteView *view,
GimpPaletteEntry *entry);
#endif /* __GIMP_PALETTE_VIEW_H__ */

View File

@ -91,13 +91,13 @@ gimp_view_renderer_palette_class_init (GimpViewRendererPaletteClass *klass)
static void
gimp_view_renderer_palette_init (GimpViewRendererPalette *renderer)
{
renderer->cell_size = 4;
renderer->draw_grid = FALSE;
}
static void
gimp_view_renderer_palette_finalize (GObject *object)
{
GimpViewRendererPalette *renderer = GIMP_VIEW_RENDERER_PALETTE (object);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
@ -108,63 +108,146 @@ gimp_view_renderer_palette_render (GimpViewRenderer *renderer,
GimpViewRendererPalette *renderpal = GIMP_VIEW_RENDERER_PALETTE (renderer);
GimpPalette *palette;
guchar *row;
guchar *dest_row;
GList *list;
gint columns;
gint rows;
gint cell_size;
gint x, y;
gint y;
palette = GIMP_PALETTE (renderer->viewable);
if (! renderer->buffer)
renderer->buffer = g_new (guchar, renderer->height * renderer->rowstride);
memset (renderer->buffer, 255, renderer->height * renderer->rowstride);
if (palette->n_columns > 1)
cell_size = MAX (4, renderer->width / palette->n_columns);
if (renderpal->cell_size > 0)
{
if (palette->n_columns > 1)
renderpal->cell_width = MAX (renderpal->cell_size,
renderer->width / palette->n_columns);
else
renderpal->cell_width = renderpal->cell_size;
}
else
cell_size = 4;
{
if (palette->n_columns > 1)
renderpal->cell_width = renderer->width / palette->n_columns;
else
renderpal->cell_width = renderer->width / 16;
}
columns = renderer->width / cell_size;
rows = renderer->height / cell_size;
renderpal->cell_width = MAX (4, renderpal->cell_width);
renderpal->columns = renderer->width / renderpal->cell_width;
renderpal->rows = palette->n_colors / renderpal->columns;
if (palette->n_colors % renderpal->columns)
renderpal->rows += 1;
renderpal->cell_height = MAX (4, renderer->height / renderpal->rows);
if (! renderpal->draw_grid)
renderpal->cell_height = MIN (renderpal->cell_height, renderpal->cell_width);
list = palette->colors;
row = g_new0 (guchar, renderer->rowstride);
memset (renderer->buffer,
renderpal->draw_grid ? 0 : 255,
renderer->height * renderer->rowstride);
for (y = 0; y < rows && list; y++)
row = g_new (guchar, renderer->rowstride);
dest_row = renderer->buffer;
for (y = 0; y < renderer->height; y++)
{
gint i;
memset (row, 255, renderer->rowstride);
for (x = 0; x < columns && list; x++)
if ((y % renderpal->cell_height) == 0)
{
GimpPaletteEntry *entry = list->data;
guchar r, g, b;
gint x;
guchar *p = row;
list = g_list_next (list);
memset (row,
renderpal->draw_grid ? 0 : 255,
renderer->rowstride);
gimp_rgb_get_uchar (&entry->color,
&row[x * cell_size * 3 + 0],
&row[x * cell_size * 3 + 1],
&row[x * cell_size * 3 + 2]);
r = g = b = (renderpal->draw_grid ? 0 : 255);
for (i = 1; i < cell_size; i++)
for (x = 0; x < renderer->width; x++)
{
row[(x * cell_size + i) * 3 + 0] = row[(x * cell_size) * 3 + 0];
row[(x * cell_size + i) * 3 + 1] = row[(x * cell_size) * 3 + 1];
row[(x * cell_size + i) * 3 + 2] = row[(x * cell_size) * 3 + 2];
if ((x % renderpal->cell_width) == 0)
{
if (list && renderer->width - x >= renderpal->cell_width)
{
GimpPaletteEntry *entry = list->data;
list = g_list_next (list);
gimp_rgb_get_uchar (&entry->color, &r, &g, &b);
}
else
{
r = g = b = (renderpal->draw_grid ? 0 : 255);
}
}
if (renderpal->draw_grid && (x % renderpal->cell_width) == 0)
{
*p++ = 0;
*p++ = 0;
*p++ = 0;
}
else
{
*p++ = r;
*p++ = g;
*p++ = b;
}
}
}
for (i = 0; i < cell_size; i++)
memcpy (renderer->buffer + (y * cell_size + i) * renderer->rowstride,
row,
renderer->rowstride);
if (renderpal->draw_grid && (y % renderpal->cell_height) == 0)
{
memset (dest_row, 0,
renderpal->cell_width * renderpal->columns * 3 + 3);
}
else
{
memcpy (dest_row, row, renderer->rowstride);
}
dest_row += renderer->rowstride;
}
g_free (row);
renderer->needs_render = FALSE;
}
/* public functions */
void
gimp_view_renderer_palette_set_cell_size (GimpViewRendererPalette *renderer,
gint cell_size)
{
g_return_if_fail (GIMP_IS_VIEW_RENDERER_PALETTE (renderer));
if (cell_size != renderer->cell_size)
{
renderer->cell_size = cell_size;
gimp_view_renderer_invalidate (GIMP_VIEW_RENDERER (renderer));
}
}
void
gimp_view_renderer_palette_set_draw_grid (GimpViewRendererPalette *renderer,
gboolean draw_grid)
{
g_return_if_fail (GIMP_IS_VIEW_RENDERER_PALETTE (renderer));
if (draw_grid != renderer->draw_grid)
{
renderer->draw_grid = draw_grid ? TRUE : FALSE;
gimp_view_renderer_invalidate (GIMP_VIEW_RENDERER (renderer));
}
}

View File

@ -37,6 +37,14 @@ typedef struct _GimpViewRendererPaletteClass GimpViewRendererPaletteClass;
struct _GimpViewRendererPalette
{
GimpViewRenderer parent_instance;
gint cell_size;
gboolean draw_grid;
gint cell_width;
gint cell_height;
gint columns;
gint rows;
};
struct _GimpViewRendererPaletteClass
@ -47,5 +55,10 @@ struct _GimpViewRendererPaletteClass
GType gimp_view_renderer_palette_get_type (void) G_GNUC_CONST;
void gimp_view_renderer_palette_set_cell_size (GimpViewRendererPalette *renderer,
gint cell_size);
void gimp_view_renderer_palette_set_draw_grid (GimpViewRendererPalette *renderer,
gboolean draw_grid);
#endif /* __GIMP_VIEW_RENDERER_PALETTE_H__ */

View File

@ -174,6 +174,7 @@ typedef struct _GimpThumbBox GimpThumbBox;
/* views */
typedef struct _GimpView GimpView;
typedef struct _GimpPaletteView GimpPaletteView;
typedef struct _GimpNavigationView GimpNavigationView;