[gimp] Add GimpToolOverlay which displays tool dialogs directly on the canvas
- From: Michael Natterer <mitch src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gimp] Add GimpToolOverlay which displays tool dialogs directly on the canvas
- Date: Sun, 18 Oct 2009 20:35:11 +0000 (UTC)
commit 81786482ec1e7ba301f6c29f0189c63f8e1ce157
Author: Michael Natterer <mitch gimp org>
Date: Sun Oct 18 22:33:23 2009 +0200
Add GimpToolOverlay which displays tool dialogs directly on the canvas
The new widget has a GtkDialog-like API so tools which use either an
overlay or a real dialog are as obvious as possible.
app/widgets/Makefile.am | 2 +
app/widgets/gimptooloverlay.c | 432 +++++++++++++++++++++++++++++++++++++++++
app/widgets/gimptooloverlay.h | 69 +++++++
3 files changed, 503 insertions(+), 0 deletions(-)
---
diff --git a/app/widgets/Makefile.am b/app/widgets/Makefile.am
index b1926e2..8fc196a 100644
--- a/app/widgets/Makefile.am
+++ b/app/widgets/Makefile.am
@@ -310,6 +310,8 @@ libappwidgets_a_sources = \
gimptooleditor.h \
gimptooloptionseditor.c \
gimptooloptionseditor.h \
+ gimptooloverlay.c \
+ gimptooloverlay.h \
gimpuimanager.c \
gimpuimanager.h \
gimpundoeditor.c \
diff --git a/app/widgets/gimptooloverlay.c b/app/widgets/gimptooloverlay.c
new file mode 100644
index 0000000..1bf2e81
--- /dev/null
+++ b/app/widgets/gimptooloverlay.c
@@ -0,0 +1,432 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * gimptooloverlay.c
+ * Copyright (C) 2009 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 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "widgets-types.h"
+
+#include "core/gimpmarshal.h"
+#include "core/gimptoolinfo.h"
+
+#include "gimptooloverlay.h"
+
+
+enum
+{
+ RESPONSE,
+ CLOSE,
+ LAST_SIGNAL
+};
+
+
+typedef struct _ResponseData ResponseData;
+
+struct _ResponseData
+{
+ gint response_id;
+};
+
+
+static void gimp_tool_overlay_destroy (GtkObject *object);
+
+static void gimp_tool_overlay_size_request (GtkWidget *widget,
+ GtkRequisition *requisition);
+static void gimp_tool_overlay_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation);
+static gboolean gimp_tool_overlay_expose (GtkWidget *widget,
+ GdkEventExpose *eevent);
+
+static void gimp_tool_overlay_forall (GtkContainer *container,
+ gboolean include_internals,
+ GtkCallback callback,
+ gpointer callback_data);
+
+static ResponseData * get_response_data (GtkWidget *widget,
+ gboolean create);
+
+
+G_DEFINE_TYPE (GimpToolOverlay, gimp_tool_overlay, GTK_TYPE_BIN)
+
+static guint signals[LAST_SIGNAL] = { 0, };
+
+#define parent_class gimp_tool_overlay_parent_class
+
+
+static void
+gimp_tool_overlay_class_init (GimpToolOverlayClass *klass)
+{
+ GtkObjectClass *gtk_object_class = GTK_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
+
+ gtk_object_class->destroy = gimp_tool_overlay_destroy;
+
+ widget_class->size_request = gimp_tool_overlay_size_request;
+ widget_class->size_allocate = gimp_tool_overlay_size_allocate;
+ widget_class->expose_event = gimp_tool_overlay_expose;
+
+ container_class->forall = gimp_tool_overlay_forall;
+
+ signals[RESPONSE] =
+ g_signal_new ("response",
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GimpToolOverlayClass, response),
+ NULL, NULL,
+ gimp_marshal_VOID__INT,
+ G_TYPE_NONE, 1,
+ G_TYPE_INT);
+
+ signals[CLOSE] =
+ g_signal_new ("close",
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (GimpToolOverlayClass, close),
+ NULL, NULL,
+ gimp_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+}
+
+static void
+gimp_tool_overlay_init (GimpToolOverlay *overlay)
+{
+ GtkWidget *widget = GTK_WIDGET (overlay);
+#if 0
+ GdkScreen *screen = gtk_widget_get_screen (widget);
+ GdkColormap *rgba = gdk_screen_get_rgba_colormap (screen);
+
+ g_assert (gdk_screen_get_rgba_visual (screen) != NULL);
+
+ gtk_widget_set_colormap (widget, rgba);
+#endif
+ gtk_widget_set_app_paintable (widget, TRUE);
+
+ overlay->action_area = gtk_hbutton_box_new ();
+ gtk_button_box_set_layout (GTK_BUTTON_BOX (overlay->action_area),
+ GTK_BUTTONBOX_END);
+ gtk_widget_set_parent (overlay->action_area, widget);
+ gtk_widget_show (overlay->action_area);
+}
+
+static void
+gimp_tool_overlay_destroy (GtkObject *object)
+{
+ GimpToolOverlay *overlay = GIMP_TOOL_OVERLAY (object);
+
+ if (overlay->action_area)
+ {
+ gtk_widget_unparent (overlay->action_area);
+ overlay->action_area = NULL;
+ }
+
+ GTK_OBJECT_CLASS (parent_class)->destroy (object);
+}
+
+static void
+gimp_tool_overlay_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ GtkContainer *container = GTK_CONTAINER (widget);
+ GimpToolOverlay *overlay = GIMP_TOOL_OVERLAY (widget);
+ GtkWidget *child = gtk_bin_get_child (GTK_BIN (widget));
+ GtkRequisition child_requisition;
+ GtkRequisition action_requisition;
+ gint border_width;
+
+ border_width = gtk_container_get_border_width (container);
+
+ requisition->width = border_width * 2;
+ requisition->height = border_width * 2;
+
+ if (child && gtk_widget_get_visible (child))
+ {
+ gtk_widget_size_request (child, &child_requisition);
+ }
+ else
+ {
+ child_requisition.width = 0;
+ child_requisition.height = 0;
+ }
+
+ gtk_widget_size_request (overlay->action_area, &action_requisition);
+
+ requisition->width += MAX (child_requisition.width,
+ action_requisition.width);
+ requisition->height += (child_requisition.height +
+ border_width +
+ action_requisition.height);
+}
+
+static void
+gimp_tool_overlay_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ GtkContainer *container = GTK_CONTAINER (widget);
+ GimpToolOverlay *overlay = GIMP_TOOL_OVERLAY (widget);
+ GtkWidget *child = gtk_bin_get_child (GTK_BIN (widget));
+ GtkRequisition action_requisition;
+ GtkAllocation child_allocation;
+ GtkAllocation action_allocation;
+ gint border_width;
+
+ gtk_widget_set_allocation (widget, allocation);
+
+ border_width = gtk_container_get_border_width (container);
+
+ gtk_widget_size_request (overlay->action_area, &action_requisition);
+
+ if (child && gtk_widget_get_visible (child))
+ {
+ child_allocation.x = allocation->x + border_width;
+ child_allocation.y = allocation->y + border_width;
+ child_allocation.width = MAX (allocation->width - 2 * border_width, 0);
+ child_allocation.height = MAX (allocation->height -
+ 3 * border_width -
+ action_requisition.height, 0);
+
+ gtk_widget_size_allocate (child, &child_allocation);
+ }
+
+ action_allocation.x = allocation->x + border_width;
+ action_allocation.y = (child_allocation.y + child_allocation.height +
+ border_width);
+ action_allocation.width = MAX (allocation->width - 2 * border_width, 0);
+ action_allocation.height = MAX (action_requisition.height, 0);
+
+ gtk_widget_size_allocate (overlay->action_area, &action_allocation);
+}
+
+static gboolean
+gimp_tool_overlay_expose (GtkWidget *widget,
+ GdkEventExpose *eevent)
+{
+ cairo_t *cr = gdk_cairo_create (gtk_widget_get_window (widget));
+ GtkStyle *style;
+ GtkAllocation allocation;
+ gint border_width;
+ gint inner_width;
+ gint inner_height;
+
+ style = gtk_widget_get_style (widget);
+ gtk_widget_get_allocation (widget, &allocation);
+
+ border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
+
+ inner_width = allocation.width - border_width / 2;
+ inner_height = allocation.height - border_width / 2;
+
+ cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
+ gdk_cairo_region (cr, eevent->region);
+ cairo_clip_preserve (cr);
+ cairo_fill (cr);
+
+ cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
+ gdk_cairo_set_source_color (cr, &style->bg[GTK_STATE_NORMAL]);
+
+#define TO_RAD(deg) (deg * (G_PI / 180.0))
+
+ cairo_arc (cr,
+ border_width,
+ border_width,
+ border_width,
+ TO_RAD (180),
+ TO_RAD (270));
+ cairo_line_to (cr,
+ allocation.width - border_width,
+ 0);
+
+ cairo_arc (cr,
+ allocation.width - border_width,
+ border_width,
+ border_width,
+ TO_RAD (270),
+ TO_RAD (0));
+ cairo_line_to (cr,
+ allocation.width,
+ allocation.height - border_width);
+
+ cairo_arc (cr,
+ allocation.width - border_width,
+ allocation.height - border_width,
+ border_width,
+ TO_RAD (0),
+ TO_RAD (90));
+ cairo_line_to (cr,
+ border_width,
+ allocation.height);
+
+ cairo_arc (cr,
+ border_width,
+ allocation.height - border_width,
+ border_width,
+ TO_RAD (90),
+ TO_RAD (180));
+ cairo_close_path (cr);
+
+ cairo_fill (cr);
+
+ cairo_destroy (cr);
+
+ return GTK_WIDGET_CLASS (parent_class)->expose_event (widget, eevent);
+}
+
+static void
+gimp_tool_overlay_forall (GtkContainer *container,
+ gboolean include_internals,
+ GtkCallback callback,
+ gpointer callback_data)
+{
+ GTK_CONTAINER_CLASS (parent_class)->forall (container, include_internals,
+ callback, callback_data);
+
+ if (include_internals)
+ {
+ GimpToolOverlay *overlay = GIMP_TOOL_OVERLAY (container);
+
+ if (overlay->action_area)
+ (* callback) (overlay->action_area, callback_data);
+ }
+}
+
+GtkWidget *
+gimp_tool_overlay_new (GimpToolInfo *tool_info,
+ const gchar *desc,
+ ...)
+{
+ GtkWidget *overlay;
+ const gchar *stock_id;
+ va_list args;
+
+ g_return_val_if_fail (GIMP_IS_TOOL_INFO (tool_info), NULL);
+
+ stock_id = gimp_viewable_get_stock_id (GIMP_VIEWABLE (tool_info));
+
+ overlay = g_object_new (GIMP_TYPE_TOOL_OVERLAY, NULL);
+
+ va_start (args, desc);
+ gimp_tool_overlay_add_buttons_valist (GIMP_TOOL_OVERLAY (overlay), args);
+ va_end (args);
+
+ return overlay;
+}
+
+void
+gimp_tool_overlay_response (GimpToolOverlay *overlay,
+ gint response_id)
+{
+ g_return_if_fail (GIMP_IS_TOOL_OVERLAY (overlay));
+
+ g_signal_emit (overlay, signals[RESPONSE], 0,
+ response_id);
+}
+
+void
+gimp_tool_overlay_add_buttons_valist (GimpToolOverlay *overlay,
+ va_list args)
+{
+ const gchar *button_text;
+ gint response_id;
+
+ g_return_if_fail (GIMP_IS_TOOL_OVERLAY (overlay));
+
+ while ((button_text = va_arg (args, const gchar *)))
+ {
+ response_id = va_arg (args, gint);
+
+ gimp_tool_overlay_add_button (overlay, button_text, response_id);
+ }
+}
+
+static void
+action_widget_activated (GtkWidget *widget,
+ GimpToolOverlay *overlay)
+{
+ ResponseData *ad = get_response_data (widget, FALSE);
+
+ gimp_tool_overlay_response (overlay, ad->response_id);
+}
+
+GtkWidget *
+gimp_tool_overlay_add_button (GimpToolOverlay *overlay,
+ const gchar *button_text,
+ gint response_id)
+{
+ GtkWidget *button;
+ ResponseData *ad;
+ guint signal_id;
+ GClosure *closure;
+
+ g_return_val_if_fail (GIMP_IS_TOOL_OVERLAY (overlay), NULL);
+ g_return_val_if_fail (button_text != NULL, NULL);
+
+ button = gtk_button_new_from_stock (button_text);
+
+ gtk_widget_set_can_default (button, TRUE);
+
+ gtk_widget_show (button);
+
+ ad = get_response_data (button, TRUE);
+
+ ad->response_id = response_id;
+
+ signal_id = g_signal_lookup ("clicked", GTK_TYPE_BUTTON);
+
+ closure = g_cclosure_new_object (G_CALLBACK (action_widget_activated),
+ G_OBJECT (overlay));
+ g_signal_connect_closure_by_id (button, signal_id, 0,
+ closure, FALSE);
+
+ gtk_box_pack_end (GTK_BOX (overlay->action_area), button, FALSE, TRUE, 0);
+
+ if (response_id == GTK_RESPONSE_HELP)
+ gtk_button_box_set_child_secondary (GTK_BUTTON_BOX (overlay->action_area),
+ button, TRUE);
+
+ return button;
+}
+
+static void
+response_data_free (gpointer data)
+{
+ g_slice_free (ResponseData, data);
+}
+
+static ResponseData *
+get_response_data (GtkWidget *widget,
+ gboolean create)
+{
+ ResponseData *ad = g_object_get_data (G_OBJECT (widget),
+ "gimp-tool-overlay-response-data");
+
+ if (! ad && create)
+ {
+ ad = g_slice_new (ResponseData);
+
+ g_object_set_data_full (G_OBJECT (widget),
+ "gimp-tool-overlay-response-data",
+ ad, response_data_free);
+ }
+
+ return ad;
+}
diff --git a/app/widgets/gimptooloverlay.h b/app/widgets/gimptooloverlay.h
new file mode 100644
index 0000000..8c9d481
--- /dev/null
+++ b/app/widgets/gimptooloverlay.h
@@ -0,0 +1,69 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * gimptooloverlay.h
+ * Copyright (C) 2009 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 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GIMP_TOOL_OVERLAY_H__
+#define __GIMP_TOOL_OVERLAY_H__
+
+
+#define GIMP_TYPE_TOOL_OVERLAY (gimp_tool_overlay_get_type ())
+#define GIMP_TOOL_OVERLAY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_TOOL_OVERLAY, GimpToolOverlay))
+#define GIMP_TOOL_OVERLAY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_TOOL_OVERLAY, GimpToolOverlayClass))
+#define GIMP_IS_TOOL_OVERLAY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_TOOL_OVERLAY))
+#define GIMP_IS_TOOL_OVERLAY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_TOOL_OVERLAY))
+#define GIMP_TOOL_OVERLAY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_TOOL_OVERLAY, GimpToolOverlayClass))
+
+
+typedef struct _GimpToolOverlay GimpToolOverlay;
+typedef struct _GimpToolOverlayClass GimpToolOverlayClass;
+
+struct _GimpToolOverlay
+{
+ GtkBin parent_instance;
+
+ GtkWidget *action_area;
+};
+
+struct _GimpToolOverlayClass
+{
+ GtkBinClass parent_class;
+
+ void (* response) (GimpToolOverlay *overlay,
+ gint response_id);
+
+ void (* close) (GimpToolOverlay *overlay);
+};
+
+
+GType gimp_tool_overlay_get_type (void) G_GNUC_CONST;
+
+GtkWidget * gimp_tool_overlay_new (GimpToolInfo *tool_info,
+ const gchar *desc,
+ ...) G_GNUC_NULL_TERMINATED;
+
+void gimp_tool_overlay_response (GimpToolOverlay *overlay,
+ gint response_id);
+void gimp_tool_overlay_add_buttons_valist (GimpToolOverlay *overlay,
+ va_list args);
+GtkWidget * gimp_tool_overlay_add_button (GimpToolOverlay *overlay,
+ const gchar *button_text,
+ gint response_id);
+
+
+#endif /* __GIMP_TOOL_OVERLAY_H__ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]