[gimp] app: add initial version of GimpDial, a widget to select a range of angles



commit b2ac41b961d3c28425f3656f5cf03da7c14782a5
Author: Michael Natterer <mitch gimp org>
Date:   Sun May 25 03:03:51 2014 +0200

    app: add initial version of GimpDial, a widget to select a range of angles
    
    Ported from the color-rotate plug-in.

 app/widgets/Makefile.am     |    2 +
 app/widgets/gimpdial.c      |  662 +++++++++++++++++++++++++++++++++++++++++++
 app/widgets/gimpdial.h      |   78 +++++
 app/widgets/widgets-types.h |    1 +
 4 files changed, 743 insertions(+), 0 deletions(-)
---
diff --git a/app/widgets/Makefile.am b/app/widgets/Makefile.am
index ecf5d13..83af774 100644
--- a/app/widgets/Makefile.am
+++ b/app/widgets/Makefile.am
@@ -133,6 +133,8 @@ libappwidgets_a_sources = \
        gimpdevices.h                   \
        gimpdevicestatus.c              \
        gimpdevicestatus.h              \
+       gimpdial.c                      \
+       gimpdial.h                      \
        gimpdialogfactory.c             \
        gimpdialogfactory.h             \
        gimpdnd.c                       \
diff --git a/app/widgets/gimpdial.c b/app/widgets/gimpdial.c
new file mode 100644
index 0000000..f91d362
--- /dev/null
+++ b/app/widgets/gimpdial.c
@@ -0,0 +1,662 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * gimpdial.c
+ * Copyright (C) 2014 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 <string.h>
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpmath/gimpmath.h"
+#include "libgimpcolor/gimpcolor.h"
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "widgets-types.h"
+
+#include "gimpdial.h"
+
+
+#define REL  0.8
+#define DEL  0.1
+#define TICK 10
+#define EACH_OR_BOTH  0.3
+
+
+enum
+{
+  PROP_0,
+  PROP_ALPHA,
+  PROP_BETA
+};
+
+enum
+{
+  FOO,
+  LAST_SIGNAL
+};
+
+
+static void        gimp_dial_dispose              (GObject          *object);
+static void        gimp_dial_set_property         (GObject          *object,
+                                                   guint             property_id,
+                                                   const GValue     *value,
+                                                   GParamSpec       *pspec);
+static void        gimp_dial_get_property         (GObject          *object,
+                                                   guint             property_id,
+                                                   GValue           *value,
+                                                   GParamSpec       *pspec);
+
+static void        gimp_dial_realize              (GtkWidget        *widget);
+static void        gimp_dial_unrealize            (GtkWidget        *widget);
+static void        gimp_dial_map                  (GtkWidget        *widget);
+static void        gimp_dial_unmap                (GtkWidget        *widget);
+static void        gimp_dial_size_request         (GtkWidget        *widget,
+                                                   GtkRequisition   *requisition);
+static void        gimp_dial_size_allocate        (GtkWidget        *widget,
+                                                   GtkAllocation    *allocation);
+static gboolean    gimp_dial_expose_event         (GtkWidget        *widget,
+                                                   GdkEventExpose   *event);
+static gboolean    gimp_dial_button_press_event   (GtkWidget        *widget,
+                                                   GdkEventButton   *bevent);
+static gboolean    gimp_dial_button_release_event (GtkWidget        *widget,
+                                                   GdkEventButton   *bevent);
+static gboolean    gimp_dial_motion_notify_event  (GtkWidget        *widget,
+                                                   GdkEventMotion   *mevent);
+
+static void        gimp_dial_draw_background      (cairo_t          *cr,
+                                                   gint              size);
+static void        gimp_dial_draw_arrows          (cairo_t          *cr,
+                                                   gint              size,
+                                                   gdouble           alpha,
+                                                   gdouble           beta,
+                                                   DialDirection     direction);
+
+
+G_DEFINE_TYPE (GimpDial, gimp_dial, GTK_TYPE_WIDGET)
+
+#define parent_class gimp_dial_parent_class
+
+static guint dial_signals[LAST_SIGNAL] = { 0 };
+
+
+static void
+gimp_dial_class_init (GimpDialClass *klass)
+{
+  GObjectClass   *object_class = G_OBJECT_CLASS (klass);
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+  object_class->dispose              = gimp_dial_dispose;
+  object_class->get_property         = gimp_dial_get_property;
+  object_class->set_property         = gimp_dial_set_property;
+
+  widget_class->realize              = gimp_dial_realize;
+  widget_class->unrealize            = gimp_dial_unrealize;
+  widget_class->map                  = gimp_dial_map;
+  widget_class->unmap                = gimp_dial_unmap;
+  widget_class->size_request         = gimp_dial_size_request;
+  widget_class->size_allocate        = gimp_dial_size_allocate;
+  widget_class->expose_event         = gimp_dial_expose_event;
+  widget_class->button_press_event   = gimp_dial_button_press_event;
+  widget_class->button_release_event = gimp_dial_button_release_event;
+  widget_class->motion_notify_event  = gimp_dial_motion_notify_event;
+
+  g_object_class_install_property (object_class, PROP_ALPHA,
+                                   g_param_spec_double ("alpha",
+                                                        NULL, NULL,
+                                                        0.0, 2 * G_PI, 0.0,
+                                                        GIMP_PARAM_READWRITE |
+                                                        G_PARAM_CONSTRUCT));
+
+  g_object_class_install_property (object_class, PROP_BETA,
+                                   g_param_spec_double ("beta",
+                                                        NULL, NULL,
+                                                        0.0, 2 * G_PI, G_PI,
+                                                        GIMP_PARAM_READWRITE |
+                                                        G_PARAM_CONSTRUCT));
+}
+
+static void
+gimp_dial_init (GimpDial *dial)
+{
+  gtk_widget_set_has_window (GTK_WIDGET (dial), FALSE);
+  gtk_widget_add_events (GTK_WIDGET (dial),
+                         GDK_BUTTON_PRESS_MASK   |
+                         GDK_BUTTON_RELEASE_MASK |
+                         GDK_BUTTON1_MOTION_MASK);
+
+  dial->border_width = 4;
+  dial->direction    = DIAL_DIRECTION_CW;
+}
+
+static void
+gimp_dial_dispose (GObject *object)
+{
+  G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+gimp_dial_set_property (GObject      *object,
+                        guint         property_id,
+                        const GValue *value,
+                        GParamSpec   *pspec)
+{
+  GimpDial *dial = GIMP_DIAL (object);
+
+  switch (property_id)
+    {
+    case PROP_ALPHA:
+      dial->alpha = g_value_get_double (value);
+      gtk_widget_queue_draw (GTK_WIDGET (dial));
+      break;
+
+    case PROP_BETA:
+      dial->beta = g_value_get_double (value);
+      gtk_widget_queue_draw (GTK_WIDGET (dial));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+    }
+}
+
+static void
+gimp_dial_get_property (GObject    *object,
+                        guint       property_id,
+                        GValue     *value,
+                        GParamSpec *pspec)
+{
+  GimpDial *dial = GIMP_DIAL (object);
+
+  switch (property_id)
+    {
+    case PROP_ALPHA:
+      g_value_set_double (value, dial->alpha);
+      break;
+
+    case PROP_BETA:
+      g_value_set_double (value, dial->beta);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+    }
+}
+
+static void
+gimp_dial_realize (GtkWidget *widget)
+{
+  GimpDial      *dial = GIMP_DIAL (widget);
+  GtkAllocation  allocation;
+  GdkWindowAttr  attributes;
+  gint           attributes_mask;
+
+  GTK_WIDGET_CLASS (parent_class)->realize (widget);
+
+  gtk_widget_get_allocation (widget, &allocation);
+
+  attributes.window_type = GDK_WINDOW_CHILD;
+  attributes.x           = allocation.x;
+  attributes.y           = allocation.y;
+  attributes.width       = allocation.width;
+  attributes.height      = allocation.height;
+  attributes.wclass      = GDK_INPUT_ONLY;
+  attributes.event_mask  = gtk_widget_get_events (widget);
+
+  attributes_mask = GDK_WA_X | GDK_WA_Y;
+
+  dial->event_window = gdk_window_new (gtk_widget_get_window (widget),
+                                       &attributes, attributes_mask);
+  gdk_window_set_user_data (dial->event_window, dial);
+}
+
+static void
+gimp_dial_unrealize (GtkWidget *widget)
+{
+  GimpDial *dial = GIMP_DIAL (widget);
+
+  if (dial->event_window)
+    {
+      gdk_window_set_user_data (dial->event_window, NULL);
+      gdk_window_destroy (dial->event_window);
+      dial->event_window = NULL;
+    }
+
+  GTK_WIDGET_CLASS (parent_class)->unrealize (widget);
+}
+
+static void
+gimp_dial_map (GtkWidget *widget)
+{
+  GimpDial *dial = GIMP_DIAL (widget);
+
+  GTK_WIDGET_CLASS (parent_class)->map (widget);
+
+  if (dial->event_window)
+    gdk_window_show (dial->event_window);
+}
+
+static void
+gimp_dial_unmap (GtkWidget *widget)
+{
+  GimpDial *dial = GIMP_DIAL (widget);
+
+  if (dial->has_grab)
+    {
+      gtk_grab_remove (widget);
+      dial->has_grab = FALSE;
+    }
+
+  if (dial->event_window)
+    gdk_window_hide (dial->event_window);
+
+  GTK_WIDGET_CLASS (parent_class)->unmap (widget);
+}
+
+static void
+gimp_dial_size_request (GtkWidget      *widget,
+                        GtkRequisition *requisition)
+{
+  GimpDial *dial = GIMP_DIAL (widget);
+
+  requisition->width  = 2 * dial->border_width + 128;
+  requisition->height = 2 * dial->border_width + 128;
+}
+
+static void
+gimp_dial_size_allocate (GtkWidget     *widget,
+                         GtkAllocation *allocation)
+{
+  GimpDial *dial = GIMP_DIAL (widget);
+
+  gtk_widget_set_allocation (widget, allocation);
+
+  if (gtk_widget_get_realized (widget))
+    gdk_window_move_resize (dial->event_window,
+                            allocation->x,
+                            allocation->y,
+                            allocation->width,
+                            allocation->height);
+}
+
+static gboolean
+gimp_dial_expose_event (GtkWidget      *widget,
+                        GdkEventExpose *event)
+{
+  GimpDial *dial = GIMP_DIAL (widget);
+
+  if (gtk_widget_is_drawable (widget))
+    {
+      GtkAllocation  allocation;
+      cairo_t       *cr;
+      gint           size;
+      gint           x, y;
+
+      gtk_widget_get_allocation (widget, &allocation);
+
+      cr = gdk_cairo_create (event->window);
+      gdk_cairo_region (cr, event->region);
+      cairo_clip (cr);
+
+      size = MIN (allocation.width, allocation.height) - 2 * dial->border_width;
+
+      x = (allocation.width  - 2 * dial->border_width - size) / 2;
+      y = (allocation.height - 2 * dial->border_width - size) / 2;
+
+      cairo_translate (cr,
+                       allocation.x + dial->border_width + x,
+                       allocation.y + dial->border_width + y);
+
+      gimp_dial_draw_background (cr, size);
+      gimp_dial_draw_arrows (cr, size, dial->alpha, dial->beta, dial->direction);
+
+      cairo_destroy (cr);
+    }
+
+  return FALSE;
+}
+
+static gdouble
+angle_mod_2PI (gdouble angle)
+{
+  if (angle < 0)
+    return angle + 2 * G_PI;
+  else if (angle > 2 * G_PI)
+    return angle - 2 * G_PI;
+  else
+    return angle;
+}
+
+static gdouble
+arctg (gdouble y,
+       gdouble x)
+{
+  gdouble temp = atan2 (y, x);
+
+  return (temp < 0) ? (temp + 2 * G_PI) : temp;
+}
+
+static gdouble
+min_prox (gdouble alpha,
+         gdouble beta,
+         gdouble angle)
+{
+  gdouble temp1 = MIN (angle_mod_2PI (alpha - angle),
+                       2 * G_PI - angle_mod_2PI (alpha - angle));
+  gdouble temp2 = MIN (angle_mod_2PI (beta - angle),
+                       2 * G_PI - angle_mod_2PI (beta - angle));
+
+  return MIN (temp1, temp2);
+}
+
+static DialTarget
+closest (gdouble alpha,
+        gdouble beta,
+        gdouble angle)
+{
+  gdouble temp_alpha = MIN (angle_mod_2PI (alpha - angle),
+                            2 * G_PI - angle_mod_2PI (alpha - angle));
+
+  gdouble temp_beta  = MIN (angle_mod_2PI (beta - angle),
+                            2 * G_PI - angle_mod_2PI (beta - angle));
+
+  if (temp_alpha - temp_beta < 0)
+    return DIAL_TARGET_ALPHA;
+  else
+    return DIAL_TARGET_BETA;
+}
+
+static gboolean
+gimp_dial_button_press_event (GtkWidget      *widget,
+                              GdkEventButton *bevent)
+{
+  GimpDial *dial = GIMP_DIAL (widget);
+
+  if (bevent->type == GDK_BUTTON_PRESS)
+    {
+      if (gdk_event_triggers_context_menu ((GdkEvent *) bevent))
+        {
+          dial->press_state = 0;
+
+          //g_signal_emit (widget, dial_signals[CONTEXT], 0);
+        }
+      else if (bevent->button == 1)
+        {
+          GtkAllocation allocation;
+          gint          size;
+          gdouble       center_x;
+          gdouble       center_y;
+          gdouble       press_angle;
+
+          gtk_widget_get_allocation (widget, &allocation);
+
+          size = MIN (allocation.width, allocation.height) - 2 * dial->border_width;
+
+          center_x = allocation.width  / 2.0;
+          center_y = allocation.height / 2.0;
+
+          gtk_grab_add (widget);
+
+          dial->has_grab    = TRUE;
+          dial->press_state = bevent->state;
+
+          press_angle = angle_mod_2PI (arctg (center_y - bevent->y,
+                                              bevent->x - center_x));
+          dial->press_angle = press_angle;
+
+          if ((sqrt (SQR (bevent->y - center_y) +
+                     SQR (bevent->x - center_x)) > size / 2.0 * EACH_OR_BOTH) &&
+              (min_prox (dial->alpha, dial->beta, press_angle) < G_PI / 12))
+            {
+              dial->target = closest (dial->alpha, dial->beta, press_angle);
+
+              if (dial->target == DIAL_TARGET_ALPHA)
+                g_object_set (dial, "alpha", press_angle, NULL);
+              else
+                g_object_set (dial, "beta", press_angle, NULL);
+            }
+          else
+            {
+              dial->target = DIAL_TARGET_BOTH;
+            }
+        }
+    }
+
+  return FALSE;
+}
+
+static gboolean
+gimp_dial_button_release_event (GtkWidget      *widget,
+                                GdkEventButton *bevent)
+{
+  GimpDial *dial = GIMP_DIAL (widget);
+
+  if (bevent->button == 1)
+    {
+      gtk_grab_remove (widget);
+      dial->has_grab = FALSE;
+    }
+
+  return FALSE;
+}
+
+static gboolean
+gimp_dial_motion_notify_event (GtkWidget      *widget,
+                               GdkEventMotion *mevent)
+{
+  GimpDial      *dial = GIMP_DIAL (widget);
+  GtkAllocation  allocation;
+  gdouble        center_x;
+  gdouble        center_y;
+  gfloat         motion_angle, delta;
+
+  gtk_widget_get_allocation (widget, &allocation);
+
+  center_x = allocation.width  / 2.0;
+  center_y = allocation.height / 2.0;
+
+  motion_angle = angle_mod_2PI (arctg (center_y - mevent->y,
+                                       mevent->x - center_x));
+
+  delta = motion_angle - dial->press_angle;
+  dial->press_angle = motion_angle;
+
+  if (delta)
+    {
+      if (dial->target == DIAL_TARGET_ALPHA)
+        {
+          g_object_set (dial, "alpha", motion_angle, NULL);
+        }
+      else if (dial->target == DIAL_TARGET_BETA)
+        {
+          g_object_set (dial, "beta", motion_angle, NULL);
+        }
+      else
+        {
+          g_object_set (dial,
+                        "alpha", angle_mod_2PI (dial->alpha + delta),
+                        "beta",  angle_mod_2PI (dial->beta  + delta),
+                        NULL);
+        }
+    }
+
+  return FALSE;
+}
+
+
+/*  public functions  */
+
+GtkWidget *
+gimp_dial_new (void)
+{
+  return g_object_new (GIMP_TYPE_DIAL, NULL);
+}
+
+
+/*  private functions  */
+
+static void
+gimp_dial_draw_background (cairo_t *cr,
+                           gint     size)
+{
+  cairo_surface_t *surface;
+  guchar          *data;
+  gint             stride;
+  gint             i, j;
+
+  surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, size, size);
+
+  data   = cairo_image_surface_get_data (surface);
+  stride = cairo_image_surface_get_stride (surface);
+
+  for (j = 0; j < size; j++)
+    {
+      for (i = 0; i < size; i++)
+        {
+          gdouble h, s, v;
+          guchar  rgb[3];
+
+          s = sqrt ((SQR (i - size  / 2.0) +
+                     SQR (j - size / 2.0)) / (gdouble) SQR (size / 2.0));
+
+          h = arctg (size / 2.0 - j, i - size / 2.0) / (2 * G_PI);
+          v = 1 - sqrt (s) / 4;
+
+          gimp_hsv_to_rgb4 (rgb, h, MIN (1.0, s), v);
+
+          GIMP_CAIRO_ARGB32_SET_PIXEL (data + j * stride + i * 4,
+                                       rgb[0], rgb[1], rgb[2], 255);
+        }
+    }
+
+  cairo_surface_mark_dirty (surface);
+
+  cairo_save (cr);
+
+  cairo_set_source_surface (cr, surface, 0.0, 0.0);
+
+  cairo_arc (cr, size / 2.0, size / 2.0, size / 2.0, 0.0, 2 * G_PI);
+  cairo_clip (cr);
+
+  cairo_paint (cr);
+
+  cairo_restore (cr);
+
+  cairo_surface_destroy (surface);
+}
+
+static void
+gimp_dial_draw_arrows (cairo_t      *cr,
+                       gint          size,
+                       gdouble       alpha,
+                       gdouble       beta,
+                       DialDirection direction)
+{
+  gint     radius = size / 2.0;
+  gint     dist;
+  gdouble  delta;
+
+  delta = angle_mod_2PI (beta - alpha);
+
+  if (direction == DIAL_DIRECTION_CCW)
+    delta = delta - 2 * G_PI;
+
+  cairo_move_to (cr, radius, radius);
+  cairo_line_to (cr,
+                 ROUND (radius + radius * cos (alpha)),
+                 ROUND (radius - radius * sin (alpha)));
+
+  cairo_move_to (cr,
+                 radius + radius * cos (alpha),
+                 radius - radius * sin (alpha));
+  cairo_line_to (cr,
+                 ROUND (radius + radius * REL * cos (alpha - DEL)),
+                 ROUND (radius - radius * REL * sin (alpha - DEL)));
+
+  cairo_move_to (cr,
+                 radius + radius * cos (alpha),
+                 radius - radius * sin (alpha));
+  cairo_line_to (cr,
+                 ROUND (radius + radius * REL * cos (alpha + DEL)),
+                 ROUND (radius - radius * REL * sin (alpha + DEL)));
+
+  cairo_move_to (cr,
+                 radius,
+                 radius);
+  cairo_line_to (cr,
+                 ROUND (radius + radius * cos (beta)),
+                 ROUND (radius - radius * sin (beta)));
+
+  cairo_move_to (cr,
+                 radius + radius * cos (beta),
+                 radius - radius * sin (beta));
+  cairo_line_to (cr,
+                 ROUND (radius + radius * REL * cos (beta - DEL)),
+                 ROUND (radius - radius * REL * sin (beta - DEL)));
+
+  cairo_move_to (cr,
+                 radius + radius * cos (beta),
+                 radius - radius * sin (beta));
+  cairo_line_to (cr,
+                 ROUND (radius + radius * REL * cos (beta + DEL)),
+                 ROUND (radius - radius * REL * sin (beta + DEL)));
+
+  dist = radius * EACH_OR_BOTH;
+
+  cairo_move_to (cr,
+                 radius + dist * cos (beta),
+                 radius - dist * sin (beta));
+  cairo_line_to (cr,
+                 ROUND (radius + dist * cos(beta) +
+                        direction * TICK * sin (beta)),
+                 ROUND (radius - dist * sin(beta) +
+                        direction * TICK * cos (beta)));
+
+  cairo_new_sub_path (cr);
+
+  if (direction == DIAL_DIRECTION_CW)
+    {
+      cairo_arc_negative (cr,
+                          radius,
+                          radius,
+                          dist,
+                          -alpha,
+                          -beta);
+    }
+  else
+    {
+      cairo_arc (cr,
+                 radius,
+                 radius,
+                 dist,
+                 -alpha,
+                 -beta);
+    }
+
+  cairo_set_line_width (cr, 3.0);
+  cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.6);
+  cairo_stroke_preserve (cr);
+
+  cairo_set_line_width (cr, 1.0);
+  cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.8);
+  cairo_stroke (cr);
+}
diff --git a/app/widgets/gimpdial.h b/app/widgets/gimpdial.h
new file mode 100644
index 0000000..b534588
--- /dev/null
+++ b/app/widgets/gimpdial.h
@@ -0,0 +1,78 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * gimpdial.h
+ * Copyright (C) 2014 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_DIAL_H__
+#define __GIMP_DIAL_H__
+
+
+typedef enum
+{
+  DIAL_DIRECTION_CW  = 1,
+  DIAL_DIRECTION_CCW = -1
+} DialDirection;
+
+typedef enum
+{
+  DIAL_TARGET_ALPHA,
+  DIAL_TARGET_BETA,
+  DIAL_TARGET_BOTH
+} DialTarget;
+
+
+#define GIMP_TYPE_DIAL            (gimp_dial_get_type ())
+#define GIMP_DIAL(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_DIAL, GimpDial))
+#define GIMP_DIAL_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_DIAL, GimpDialClass))
+#define GIMP_IS_DIAL(obj)         (G_TYPE_CHECK_INSTANCE_TYPE (obj, GIMP_TYPE_DIAL))
+#define GIMP_IS_DIAL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_DIAL))
+#define GIMP_DIAL_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_DIAL, GimpDialClass))
+
+
+typedef struct _GimpDialClass  GimpDialClass;
+
+struct _GimpDial
+{
+  GtkWidget         parent_instance;
+
+  gdouble           alpha;
+  gdouble           beta;
+  DialDirection     direction;
+
+  GdkWindow        *event_window;
+
+  DialTarget        target;
+  gdouble           press_angle;
+
+  gint              border_width;
+  guint             has_grab : 1;
+  GdkModifierType   press_state;
+};
+
+struct _GimpDialClass
+{
+  GtkWidgetClass  parent_class;
+};
+
+
+GType          gimp_dial_get_type          (void) G_GNUC_CONST;
+
+GtkWidget    * gimp_dial_new               (void);
+
+
+#endif /* __GIMP_DIAL_H__ */
diff --git a/app/widgets/widgets-types.h b/app/widgets/widgets-types.h
index eda8634..42f1f72 100644
--- a/app/widgets/widgets-types.h
+++ b/app/widgets/widgets-types.h
@@ -167,6 +167,7 @@ typedef struct _GimpCurveView                GimpCurveView;
 typedef struct _GimpDashEditor               GimpDashEditor;
 typedef struct _GimpDeviceEditor             GimpDeviceEditor;
 typedef struct _GimpDeviceInfoEditor         GimpDeviceInfoEditor;
+typedef struct _GimpDial                     GimpDial;
 typedef struct _GimpDynamicsOutputEditor     GimpDynamicsOutputEditor;
 typedef struct _GimpFgBgEditor               GimpFgBgEditor;
 typedef struct _GimpFgBgView                 GimpFgBgView;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]