summaryrefslogtreecommitdiffstats
path: root/app/widgets/gimpfgbgview.c
diff options
context:
space:
mode:
Diffstat (limited to 'app/widgets/gimpfgbgview.c')
-rw-r--r--app/widgets/gimpfgbgview.c329
1 files changed, 329 insertions, 0 deletions
diff --git a/app/widgets/gimpfgbgview.c b/app/widgets/gimpfgbgview.c
new file mode 100644
index 0000000..2047d4d
--- /dev/null
+++ b/app/widgets/gimpfgbgview.c
@@ -0,0 +1,329 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * gimpfgbgview.c
+ * Copyright (C) 2005 Sven Neumann <sven@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 3 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, see <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpcolor/gimpcolor.h"
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "widgets-types.h"
+
+#include "config/gimpcoreconfig.h"
+
+#include "core/gimp.h"
+#include "core/gimpcontext.h"
+#include "core/gimpmarshal.h"
+
+#include "gimpdnd.h"
+#include "gimpfgbgview.h"
+
+
+enum
+{
+ PROP_0,
+ PROP_CONTEXT
+};
+
+
+static void gimp_fg_bg_view_dispose (GObject *object);
+static void gimp_fg_bg_view_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void gimp_fg_bg_view_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec);
+
+static gboolean gimp_fg_bg_view_expose (GtkWidget *widget,
+ GdkEventExpose *eevent);
+
+static void gimp_fg_bg_view_create_transform (GimpFgBgView *view);
+static void gimp_fg_bg_view_destroy_transform (GimpFgBgView *view);
+
+
+G_DEFINE_TYPE (GimpFgBgView, gimp_fg_bg_view, GTK_TYPE_WIDGET)
+
+#define parent_class gimp_fg_bg_view_parent_class
+
+
+static void
+gimp_fg_bg_view_class_init (GimpFgBgViewClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->dispose = gimp_fg_bg_view_dispose;
+ object_class->set_property = gimp_fg_bg_view_set_property;
+ object_class->get_property = gimp_fg_bg_view_get_property;
+
+ widget_class->expose_event = gimp_fg_bg_view_expose;
+
+ g_object_class_install_property (object_class, PROP_CONTEXT,
+ g_param_spec_object ("context",
+ NULL, NULL,
+ GIMP_TYPE_CONTEXT,
+ GIMP_PARAM_READWRITE));
+}
+
+static void
+gimp_fg_bg_view_init (GimpFgBgView *view)
+{
+ gtk_widget_set_has_window (GTK_WIDGET (view), FALSE);
+
+ gimp_widget_track_monitor (GTK_WIDGET (view),
+ G_CALLBACK (gimp_fg_bg_view_destroy_transform),
+ NULL);
+}
+
+static void
+gimp_fg_bg_view_dispose (GObject *object)
+{
+ GimpFgBgView *view = GIMP_FG_BG_VIEW (object);
+
+ if (view->context)
+ gimp_fg_bg_view_set_context (view, NULL);
+
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+gimp_fg_bg_view_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GimpFgBgView *view = GIMP_FG_BG_VIEW (object);
+
+ switch (property_id)
+ {
+ case PROP_CONTEXT:
+ gimp_fg_bg_view_set_context (view, g_value_get_object (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+gimp_fg_bg_view_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GimpFgBgView *view = GIMP_FG_BG_VIEW (object);
+
+ switch (property_id)
+ {
+ case PROP_CONTEXT:
+ g_value_set_object (value, view->context);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static gboolean
+gimp_fg_bg_view_expose (GtkWidget *widget,
+ GdkEventExpose *eevent)
+{
+ GimpFgBgView *view = GIMP_FG_BG_VIEW (widget);
+ GtkStyle *style = gtk_widget_get_style (widget);
+ GdkWindow *window = gtk_widget_get_window (widget);
+ cairo_t *cr;
+ GtkAllocation allocation;
+ gint rect_w, rect_h;
+ GimpRGB color;
+
+ if (! gtk_widget_is_drawable (widget))
+ return FALSE;
+
+ cr = gdk_cairo_create (eevent->window);
+
+ gdk_cairo_region (cr, eevent->region);
+ cairo_clip (cr);
+
+ gtk_widget_get_allocation (widget, &allocation);
+
+ cairo_translate (cr, allocation.x, allocation.y);
+
+ rect_w = allocation.width * 3 / 4;
+ rect_h = allocation.height * 3 / 4;
+
+ if (! view->transform)
+ gimp_fg_bg_view_create_transform (view);
+
+ /* draw the background area */
+
+ if (view->context)
+ {
+ gimp_context_get_background (view->context, &color);
+
+ if (view->transform)
+ gimp_color_transform_process_pixels (view->transform,
+ babl_format ("R'G'B'A double"),
+ &color,
+ babl_format ("R'G'B'A double"),
+ &color,
+ 1);
+
+ gimp_cairo_set_source_rgb (cr, &color);
+
+ cairo_rectangle (cr,
+ allocation.width - rect_w + 1,
+ allocation.height - rect_h + 1,
+ rect_w - 2,
+ rect_h - 2);
+ cairo_fill (cr);
+ }
+
+ gtk_paint_shadow (style, window, GTK_STATE_NORMAL,
+ GTK_SHADOW_IN,
+ NULL, widget, NULL,
+ allocation.x + allocation.width - rect_w,
+ allocation.y + allocation.height - rect_h,
+ rect_w, rect_h);
+
+ /* draw the foreground area */
+
+ if (view->context)
+ {
+ gimp_context_get_foreground (view->context, &color);
+
+ if (view->transform)
+ gimp_color_transform_process_pixels (view->transform,
+ babl_format ("R'G'B'A double"),
+ &color,
+ babl_format ("R'G'B'A double"),
+ &color,
+ 1);
+
+ gimp_cairo_set_source_rgb (cr, &color);
+
+ cairo_rectangle (cr, 1, 1, rect_w - 2, rect_h - 2);
+ cairo_fill (cr);
+ }
+
+ gtk_paint_shadow (style, window, GTK_STATE_NORMAL,
+ GTK_SHADOW_OUT,
+ NULL, widget, NULL,
+ allocation.x, allocation.y, rect_w, rect_h);
+
+ cairo_destroy (cr);
+
+ return TRUE;
+}
+
+static void
+gimp_fg_bg_view_create_transform (GimpFgBgView *view)
+{
+ if (view->color_config)
+ {
+ static GimpColorProfile *profile = NULL;
+
+ if (G_UNLIKELY (! profile))
+ profile = gimp_color_profile_new_rgb_srgb ();
+
+ view->transform =
+ gimp_widget_get_color_transform (GTK_WIDGET (view),
+ view->color_config,
+ profile,
+ babl_format ("R'G'B'A double"),
+ babl_format ("R'G'B'A double"));
+ }
+}
+
+static void
+gimp_fg_bg_view_destroy_transform (GimpFgBgView *view)
+{
+ g_clear_object (&view->transform);
+
+ gtk_widget_queue_draw (GTK_WIDGET (view));
+}
+
+
+/* public functions */
+
+GtkWidget *
+gimp_fg_bg_view_new (GimpContext *context)
+{
+ g_return_val_if_fail (context == NULL || GIMP_IS_CONTEXT (context), NULL);
+
+ return g_object_new (GIMP_TYPE_FG_BG_VIEW,
+ "context", context,
+ NULL);
+}
+
+void
+gimp_fg_bg_view_set_context (GimpFgBgView *view,
+ GimpContext *context)
+{
+ g_return_if_fail (GIMP_IS_FG_BG_VIEW (view));
+ g_return_if_fail (context == NULL || GIMP_IS_CONTEXT (context));
+
+ if (context != view->context)
+ {
+ if (view->context)
+ {
+ g_signal_handlers_disconnect_by_func (view->context,
+ gtk_widget_queue_draw,
+ view);
+ g_clear_object (&view->context);
+
+ g_signal_handlers_disconnect_by_func (view->color_config,
+ gimp_fg_bg_view_destroy_transform,
+ view);
+ g_clear_object (&view->color_config);
+ }
+
+ view->context = context;
+
+ if (context)
+ {
+ g_object_ref (context);
+
+ g_signal_connect_swapped (context, "foreground-changed",
+ G_CALLBACK (gtk_widget_queue_draw),
+ view);
+ g_signal_connect_swapped (context, "background-changed",
+ G_CALLBACK (gtk_widget_queue_draw),
+ view);
+
+ view->color_config = g_object_ref (context->gimp->config->color_management);
+
+ g_signal_connect_swapped (view->color_config, "notify",
+ G_CALLBACK (gimp_fg_bg_view_destroy_transform),
+ view);
+ }
+
+ gimp_fg_bg_view_destroy_transform (view);
+
+ g_object_notify (G_OBJECT (view), "context");
+ }
+}