mirror of https://github.com/GNOME/gimp.git
577 lines
13 KiB
C
577 lines
13 KiB
C
/* The GIMP -- an image manipulation program
|
|
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
|
*
|
|
* 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 <gtk/gtk.h>
|
|
|
|
#include "gimpcontext.h"
|
|
#include "gimpsignal.h"
|
|
|
|
#define context_return_if_fail(context) \
|
|
g_return_if_fail ((context) != NULL); \
|
|
g_return_if_fail (GIMP_IS_CONTEXT (context));
|
|
|
|
#define context_return_val_if_fail(context,val) \
|
|
g_return_val_if_fail ((context) != NULL, (val)); \
|
|
g_return_val_if_fail (GIMP_IS_CONTEXT (context), (val));
|
|
|
|
#define context_check_current(context) \
|
|
((context) = (context) ? (context) : current_context)
|
|
|
|
#define context_find_defined(context,field_defined) \
|
|
while (!((context)->field_defined) && (context)->parent) \
|
|
(context) = (context)->parent
|
|
|
|
enum {
|
|
ARG_0,
|
|
ARG_OPACITY,
|
|
ARG_PAINT_MODE,
|
|
ARG_IMAGE,
|
|
ARG_DISPLAY
|
|
};
|
|
|
|
enum {
|
|
OPACITY_CHANGED,
|
|
PAINT_MODE_CHANGED,
|
|
IMAGE_CHANGED,
|
|
DISPLAY_CHANGED,
|
|
LAST_SIGNAL
|
|
};
|
|
|
|
static guint gimp_context_signals[LAST_SIGNAL] = { 0 };
|
|
|
|
static GimpObjectClass * parent_class = NULL;
|
|
|
|
/* the currently active context */
|
|
static GimpContext * current_context = NULL;
|
|
|
|
/* the context user by the interface */
|
|
static GimpContext * user_context = NULL;
|
|
|
|
/* the default context which is initialized from gimprc */
|
|
static GimpContext * default_context = NULL;
|
|
|
|
/* the hardcoded standard context */
|
|
static GimpContext * standard_context = NULL;
|
|
|
|
|
|
/* private functions ******************************************************/
|
|
|
|
static void
|
|
gimp_context_set_arg (GtkObject *object,
|
|
GtkArg *arg,
|
|
guint arg_id)
|
|
{
|
|
GimpContext *context;
|
|
|
|
context = GIMP_CONTEXT (object);
|
|
|
|
switch (arg_id)
|
|
{
|
|
case ARG_OPACITY:
|
|
gimp_context_set_opacity (context, GTK_VALUE_DOUBLE (*arg));
|
|
break;
|
|
case ARG_PAINT_MODE:
|
|
gimp_context_set_paint_mode (context, GTK_VALUE_INT (*arg));
|
|
break;
|
|
case ARG_IMAGE:
|
|
gimp_context_set_image (context, GTK_VALUE_POINTER (*arg));
|
|
break;
|
|
case ARG_DISPLAY:
|
|
gimp_context_set_display (context, GTK_VALUE_POINTER (*arg));
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
gimp_context_get_arg (GtkObject *object,
|
|
GtkArg *arg,
|
|
guint arg_id)
|
|
{
|
|
GimpContext *context;
|
|
|
|
context = GIMP_CONTEXT (object);
|
|
|
|
switch (arg_id)
|
|
{
|
|
case ARG_OPACITY:
|
|
GTK_VALUE_DOUBLE (*arg) = gimp_context_get_opacity (context);
|
|
break;
|
|
case ARG_PAINT_MODE:
|
|
GTK_VALUE_INT (*arg) = gimp_context_get_paint_mode (context);
|
|
break;
|
|
case ARG_IMAGE:
|
|
GTK_VALUE_POINTER (*arg) = gimp_context_get_image (context);
|
|
break;
|
|
case ARG_DISPLAY:
|
|
GTK_VALUE_POINTER (*arg) = gimp_context_get_display (context);
|
|
break;
|
|
default:
|
|
arg->type = GTK_TYPE_INVALID;
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
gimp_context_destroy (GtkObject *object)
|
|
{
|
|
GimpContext *context;
|
|
|
|
context_return_if_fail (object);
|
|
|
|
context = GIMP_CONTEXT (object);
|
|
|
|
if (context->name)
|
|
g_free (context->name);
|
|
|
|
if (GTK_OBJECT_CLASS (parent_class)->destroy)
|
|
(* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
|
|
}
|
|
|
|
static void
|
|
gimp_context_class_init (GimpContextClass *klass)
|
|
{
|
|
GtkObjectClass *object_class;
|
|
|
|
object_class = GTK_OBJECT_CLASS (klass);
|
|
|
|
gtk_object_add_arg_type ("GimpContext::opacity",
|
|
GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_OPACITY);
|
|
gtk_object_add_arg_type ("GimpContext::paint_mode",
|
|
GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_PAINT_MODE);
|
|
gtk_object_add_arg_type ("GimpContext::image",
|
|
GTK_TYPE_POINTER, GTK_ARG_READWRITE, ARG_IMAGE);
|
|
gtk_object_add_arg_type ("GimpContext::display",
|
|
GTK_TYPE_POINTER, GTK_ARG_READWRITE, ARG_DISPLAY);
|
|
|
|
parent_class = gtk_type_class (gimp_object_get_type ());
|
|
|
|
gimp_context_signals[OPACITY_CHANGED] =
|
|
gimp_signal_new ("opacity_changed",
|
|
GTK_RUN_FIRST,
|
|
object_class->type,
|
|
GTK_SIGNAL_OFFSET (GimpContextClass,
|
|
opacity_changed),
|
|
gimp_sigtype_double);
|
|
|
|
gimp_context_signals[PAINT_MODE_CHANGED] =
|
|
gimp_signal_new ("paint_mode_changed",
|
|
GTK_RUN_FIRST,
|
|
object_class->type,
|
|
GTK_SIGNAL_OFFSET (GimpContextClass,
|
|
paint_mode_changed),
|
|
gimp_sigtype_int);
|
|
|
|
gimp_context_signals[IMAGE_CHANGED] =
|
|
gimp_signal_new ("image_changed",
|
|
GTK_RUN_FIRST,
|
|
object_class->type,
|
|
GTK_SIGNAL_OFFSET (GimpContextClass,
|
|
image_changed),
|
|
gimp_sigtype_pointer);
|
|
|
|
gimp_context_signals[DISPLAY_CHANGED] =
|
|
gimp_signal_new ("display_changed",
|
|
GTK_RUN_FIRST,
|
|
object_class->type,
|
|
GTK_SIGNAL_OFFSET (GimpContextClass,
|
|
display_changed),
|
|
gimp_sigtype_pointer);
|
|
|
|
gtk_object_class_add_signals (object_class, gimp_context_signals,
|
|
LAST_SIGNAL);
|
|
|
|
object_class->set_arg = gimp_context_set_arg;
|
|
object_class->get_arg = gimp_context_get_arg;
|
|
object_class->destroy = gimp_context_destroy;
|
|
|
|
klass->opacity_changed = NULL;
|
|
klass->paint_mode_changed = NULL;
|
|
klass->image_changed = NULL;
|
|
klass->display_changed = NULL;
|
|
}
|
|
|
|
static void
|
|
gimp_context_init (GimpContext *context)
|
|
{
|
|
context->name = NULL;
|
|
context->parent = NULL;
|
|
|
|
/* Values defined by default */
|
|
|
|
context->opacity_defined = TRUE;
|
|
context->opacity = 1.0;
|
|
|
|
context->paint_mode_defined = TRUE;
|
|
context->paint_mode = 0;
|
|
|
|
/* Values to be taken from the parent context by default */
|
|
|
|
context->image_defined = FALSE;
|
|
context->image = NULL;
|
|
|
|
context->display_defined = FALSE;
|
|
context->display = NULL;
|
|
}
|
|
|
|
/* public functions *******************************************************/
|
|
|
|
GtkType
|
|
gimp_context_get_type (void)
|
|
{
|
|
static GtkType context_type = 0;
|
|
|
|
if(! context_type)
|
|
{
|
|
GtkTypeInfo context_info =
|
|
{
|
|
"GimpContext",
|
|
sizeof (GimpContext),
|
|
sizeof (GimpContextClass),
|
|
(GtkClassInitFunc) gimp_context_class_init,
|
|
(GtkObjectInitFunc) gimp_context_init,
|
|
/* reserved_1 */ NULL,
|
|
/* reserved_2 */ NULL,
|
|
(GtkClassInitFunc) NULL
|
|
};
|
|
|
|
context_type = gtk_type_unique (gimp_object_get_type (), &context_info);
|
|
}
|
|
|
|
return context_type;
|
|
}
|
|
|
|
GimpContext *
|
|
gimp_context_new (gchar *name,
|
|
GimpContext *template,
|
|
GimpContext *parent)
|
|
{
|
|
GimpContext *context;
|
|
|
|
g_return_val_if_fail (!template || GIMP_IS_CONTEXT (template), NULL);
|
|
g_return_val_if_fail (!parent || GIMP_IS_CONTEXT (parent), NULL);
|
|
|
|
context = gtk_type_new (gimp_context_get_type ());
|
|
|
|
/* FIXME: need unique (translated??) names here
|
|
*/
|
|
context->name = g_strdup (name ? name : "Unnamed");
|
|
context->parent = parent;
|
|
|
|
if (template)
|
|
{
|
|
context->opacity = gimp_context_get_opacity (template);
|
|
context->paint_mode = gimp_context_get_paint_mode (template);
|
|
context->image = gimp_context_get_image (template);
|
|
context->display = gimp_context_get_display (template);
|
|
|
|
context->opacity_defined = template->opacity_defined;
|
|
context->paint_mode_defined = template->paint_mode_defined;
|
|
context->image_defined = template->image_defined;
|
|
context->display_defined = template->display_defined;
|
|
}
|
|
|
|
return context;
|
|
}
|
|
|
|
/* getting/setting the special contexts ***********************************/
|
|
|
|
GimpContext *
|
|
gimp_context_get_current (void)
|
|
{
|
|
return current_context;
|
|
}
|
|
|
|
void
|
|
gimp_context_set_current (GimpContext *context)
|
|
{
|
|
current_context = context;
|
|
}
|
|
|
|
GimpContext *
|
|
gimp_context_get_user (void)
|
|
{
|
|
return user_context;
|
|
}
|
|
|
|
void
|
|
gimp_context_set_user (GimpContext *context)
|
|
{
|
|
user_context = context;
|
|
}
|
|
|
|
GimpContext *
|
|
gimp_context_get_default (void)
|
|
{
|
|
return default_context;
|
|
}
|
|
|
|
void
|
|
gimp_context_set_default (GimpContext *context)
|
|
{
|
|
default_context = context;
|
|
}
|
|
|
|
GimpContext *
|
|
gimp_context_get_standard (void)
|
|
{
|
|
if (! standard_context)
|
|
{
|
|
standard_context = gimp_context_new ("Standard", NULL, NULL);
|
|
|
|
gtk_quit_add_destroy (TRUE, GTK_OBJECT (standard_context));
|
|
}
|
|
|
|
return standard_context;
|
|
}
|
|
|
|
/* functions manipulating a single context ********************************/
|
|
|
|
gchar *
|
|
gimp_context_get_name (GimpContext *context)
|
|
{
|
|
context_check_current (context);
|
|
context_return_val_if_fail (context, NULL);
|
|
|
|
return context->name;
|
|
}
|
|
|
|
GimpContext *
|
|
gimp_context_get_parent (GimpContext *context)
|
|
{
|
|
context_return_val_if_fail (context, NULL);
|
|
|
|
return context->parent;
|
|
}
|
|
|
|
void
|
|
gimp_context_set_parent (GimpContext *context,
|
|
GimpContext *parent)
|
|
{
|
|
context_return_if_fail (context);
|
|
g_return_if_fail (!parent || GIMP_IS_CONTEXT (parent));
|
|
|
|
context->parent = parent;
|
|
}
|
|
|
|
|
|
/* attribute access functions */
|
|
|
|
/* FIXME: - this is UGLY code duplication
|
|
* - gimp_context_*_defined and _define_* sounds very ugly, too
|
|
* TODO: - implement a generic way or alternatively
|
|
* - write some macros which will fold one of the following
|
|
* functions into a single macro call
|
|
*/
|
|
|
|
/* opacity */
|
|
|
|
gdouble
|
|
gimp_context_get_opacity (GimpContext *context)
|
|
{
|
|
context_check_current (context);
|
|
context_return_val_if_fail (context, 1.0);
|
|
context_find_defined (context, opacity_defined);
|
|
|
|
return context->opacity;
|
|
}
|
|
|
|
void
|
|
gimp_context_set_opacity (GimpContext *context,
|
|
gdouble opacity)
|
|
{
|
|
context_check_current (context);
|
|
context_return_if_fail (context);
|
|
context_find_defined (context, opacity_defined);
|
|
|
|
context->opacity = opacity;
|
|
gtk_signal_emit (GTK_OBJECT (context),
|
|
gimp_context_signals[OPACITY_CHANGED],
|
|
opacity);
|
|
}
|
|
|
|
gboolean
|
|
gimp_context_opacity_defined (GimpContext *context)
|
|
{
|
|
context_return_val_if_fail (context, FALSE);
|
|
|
|
return context->opacity_defined;
|
|
}
|
|
|
|
void
|
|
gimp_context_define_opacity (GimpContext *context,
|
|
gboolean defined)
|
|
{
|
|
context_return_if_fail (context);
|
|
|
|
if (defined)
|
|
context->opacity = gimp_context_get_opacity (context);
|
|
|
|
context->opacity_defined = defined;
|
|
}
|
|
|
|
/* paint mode */
|
|
|
|
LayerModeEffects
|
|
gimp_context_get_paint_mode (GimpContext *context)
|
|
{
|
|
context_check_current (context);
|
|
context_return_val_if_fail (context, 0);
|
|
context_find_defined (context, paint_mode_defined);
|
|
|
|
return context->paint_mode;
|
|
}
|
|
|
|
void
|
|
gimp_context_set_paint_mode (GimpContext *context,
|
|
LayerModeEffects paint_mode)
|
|
{
|
|
context_check_current (context);
|
|
context_return_if_fail (context);
|
|
context_find_defined (context, paint_mode_defined);
|
|
|
|
context->paint_mode = paint_mode;
|
|
gtk_signal_emit (GTK_OBJECT(context),
|
|
gimp_context_signals[PAINT_MODE_CHANGED],
|
|
paint_mode);
|
|
}
|
|
|
|
gboolean
|
|
gimp_context_paint_mode_defined (GimpContext *context)
|
|
{
|
|
context_return_val_if_fail (context, FALSE);
|
|
|
|
return context->paint_mode_defined;
|
|
}
|
|
|
|
void
|
|
gimp_context_define_paint_mode (GimpContext *context,
|
|
gboolean defined)
|
|
{
|
|
context_return_if_fail (context);
|
|
|
|
if (defined)
|
|
context->paint_mode = gimp_context_get_paint_mode (context);
|
|
|
|
context->paint_mode_defined = defined;
|
|
}
|
|
|
|
/* image */
|
|
|
|
GimpImage *
|
|
gimp_context_get_image (GimpContext *context)
|
|
{
|
|
context_check_current (context);
|
|
context_return_val_if_fail (context, NULL);
|
|
context_find_defined (context, image_defined);
|
|
|
|
return context->image;
|
|
}
|
|
|
|
void
|
|
gimp_context_set_image (GimpContext *context,
|
|
GimpImage *image)
|
|
{
|
|
context_check_current (context);
|
|
context_return_if_fail (context);
|
|
context_find_defined (context, image_defined);
|
|
|
|
if (context->image == image) return;
|
|
|
|
context->image = image;
|
|
gtk_signal_emit (GTK_OBJECT (context),
|
|
gimp_context_signals[IMAGE_CHANGED],
|
|
image);
|
|
}
|
|
|
|
gboolean
|
|
gimp_context_image_defined (GimpContext *context)
|
|
{
|
|
context_return_val_if_fail (context, FALSE);
|
|
|
|
return context->image_defined;
|
|
}
|
|
|
|
void
|
|
gimp_context_define_image (GimpContext *context,
|
|
gboolean defined)
|
|
{
|
|
context_return_if_fail (context);
|
|
|
|
if (defined)
|
|
context->image = gimp_context_get_image (context);
|
|
|
|
context->image_defined = defined;
|
|
}
|
|
|
|
/* display */
|
|
|
|
GDisplay *
|
|
gimp_context_get_display (GimpContext *context)
|
|
{
|
|
context_check_current (context);
|
|
context_return_val_if_fail (context, NULL);
|
|
context_find_defined (context, display_defined);
|
|
|
|
return context->display;
|
|
}
|
|
|
|
void
|
|
gimp_context_set_display (GimpContext *context,
|
|
GDisplay *display)
|
|
{
|
|
GimpContext *orig = context;
|
|
|
|
context_check_current (context);
|
|
context_return_if_fail (context);
|
|
context_find_defined (context, display_defined);
|
|
|
|
if (context->display == display) return;
|
|
|
|
context->display = display;
|
|
|
|
/* set the image _before_ emitting the display_changed signal */
|
|
if (display)
|
|
gimp_context_set_image (orig, display->gimage);
|
|
|
|
gtk_signal_emit (GTK_OBJECT (context),
|
|
gimp_context_signals[DISPLAY_CHANGED],
|
|
display);
|
|
}
|
|
|
|
gboolean
|
|
gimp_context_display_defined (GimpContext *context)
|
|
{
|
|
context_return_val_if_fail (context, FALSE);
|
|
|
|
return context->display_defined;
|
|
}
|
|
|
|
void
|
|
gimp_context_define_display (GimpContext *context,
|
|
gboolean defined)
|
|
{
|
|
context_return_if_fail (context);
|
|
|
|
if (defined)
|
|
context->display = gimp_context_get_display (context);
|
|
|
|
context->display_defined = defined;
|
|
}
|