pcb 4.1.1
An interactive printed circuit board layout editor.

ghid-cell-renderer-visibility.c

Go to the documentation of this file.
00001 
00011 #include <glib.h>
00012 #include <glib-object.h>
00013 #include <gtk/gtk.h>
00014 
00015 #include "gtkhid.h"
00016 #include "gui.h"
00017 
00018 #include "ghid-cell-renderer-visibility.h"
00019 
00020 enum {
00021   TOGGLED,
00022   LAST_SIGNAL
00023 };
00024 static guint toggle_cell_signals[LAST_SIGNAL] = { 0 };
00025 
00026 enum {
00027   PROP_ACTIVE = 1,
00028   PROP_COLOR
00029 };
00030 
00031 struct _GHidCellRendererVisibility
00032 {
00033   GtkCellRenderer parent;
00034 
00035   gboolean active;
00036   gchar *color;
00037 };
00038 
00039 struct _GHidCellRendererVisibilityClass
00040 {
00041   GtkCellRendererClass parent_class;
00042 
00043   void (* toggled) (GHidCellRendererVisibility *cell, const gchar *path);
00044 };
00045 
00046 /* RENDERER FUNCTIONS */
00047 
00051 static void
00052 ghid_cell_renderer_visibility_get_size (GtkCellRenderer *cell,
00053                                         GtkWidget       *widget,
00054                                         GdkRectangle    *cell_area,
00055                                         gint            *x_offset,
00056                                         gint            *y_offset,
00057                                         gint            *width,
00058                                         gint            *height)
00059 {
00060   GtkStyle *style = gtk_widget_get_style (widget);
00061   gint w, h;
00062   gint xpad, ypad;
00063   gfloat xalign, yalign;
00064 
00065   gtk_cell_renderer_get_padding (cell, &xpad, &ypad);
00066   gtk_cell_renderer_get_alignment (cell, &xalign, &yalign);
00067 
00068   w = VISIBILITY_TOGGLE_SIZE + 2 * (xpad + style->xthickness);
00069   h = VISIBILITY_TOGGLE_SIZE + 2 * (ypad + style->ythickness);
00070 
00071   if (width)
00072     *width = w;
00073   if (height)
00074     *height = h;
00075 
00076   if (cell_area)
00077     {
00078       if (x_offset)
00079         {
00080           if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
00081             xalign = 1. - xalign;
00082           *x_offset = MAX (0, xalign * (cell_area->width - w));
00083         }
00084       if (y_offset)
00085         *y_offset = MAX(0, yalign * (cell_area->height - h));
00086     }
00087 }
00088 
00092 static void
00093 ghid_cell_renderer_visibility_render (GtkCellRenderer      *cell,
00094                                       GdkWindow            *window,
00095                                       GtkWidget            *widget,
00096                                       GdkRectangle         *background_area,
00097                                       GdkRectangle         *cell_area,
00098                                       GdkRectangle         *expose_area,
00099                                       GtkCellRendererState  flags)
00100 {
00101   GHidCellRendererVisibility *pcb_cell;
00102   GdkRectangle toggle_rect;
00103   GdkRectangle draw_rect;
00104   gint xpad, ypad;
00105 
00106   pcb_cell = GHID_CELL_RENDERER_VISIBILITY (cell);
00107   ghid_cell_renderer_visibility_get_size (cell, widget, cell_area,
00108                                           &toggle_rect.x,
00109                                           &toggle_rect.y,
00110                                           &toggle_rect.width,
00111                                           &toggle_rect.height);
00112   gtk_cell_renderer_get_padding (cell, &xpad, &ypad);
00113 
00114   toggle_rect.x      += cell_area->x + xpad;
00115   toggle_rect.y      += cell_area->y + ypad;
00116   toggle_rect.width  -= xpad * 2;
00117   toggle_rect.height -= ypad * 2;
00118 
00119   if (toggle_rect.width <= 0 || toggle_rect.height <= 0)
00120     return;
00121 
00122   if (gdk_rectangle_intersect (expose_area, cell_area, &draw_rect))
00123     {
00124       GdkColor color;
00125       cairo_t *cr = gdk_cairo_create (window);
00126       cairo_pattern_t *pattern;
00127 
00128       if (expose_area)
00129         {
00130           gdk_cairo_rectangle (cr, expose_area);
00131           cairo_clip (cr);
00132         }
00133       cairo_set_line_width (cr, 1);
00134 
00135       cairo_rectangle (cr, toggle_rect.x + 0.5, toggle_rect.y + 0.5,
00136                            toggle_rect.width - 1, toggle_rect.height - 1);
00137       cairo_set_source_rgb (cr, 1, 1, 1);
00138       cairo_fill_preserve (cr);
00139       cairo_set_source_rgb (cr, 0, 0, 0);
00140       cairo_stroke (cr);
00141 
00142       gdk_color_parse (pcb_cell->color, &color);
00143       if (flags & GTK_CELL_RENDERER_PRELIT)
00144         {
00145           color.red = (4*color.red + 65535) / 5;
00146           color.green = (4*color.green + 65535) / 5;
00147           color.blue = (4*color.blue + 65535) / 5;
00148         }
00149 
00150       pattern = cairo_pattern_create_radial ((toggle_rect.width  - 1.) * 0.75 + toggle_rect.x + 0.5,
00151                                              (toggle_rect.height - 1.) * 0.75 + toggle_rect.y + 0.5,
00152                                              0.,
00153                                              (toggle_rect.width  - 1.) * 0.50 + toggle_rect.x + 0.5,
00154                                              (toggle_rect.height - 1.) * 0.50 + toggle_rect.y + 0.5,
00155                                              (toggle_rect.width  - 1.) * 0.71);
00156 
00157       cairo_pattern_add_color_stop_rgb (pattern, 0.0,
00158                                         (color.red   / 65535. * 4. + 1.) / 5.,
00159                                         (color.green / 65535. * 4. + 1.) / 5.,
00160                                         (color.blue  / 65535. * 4. + 1.) / 5.);
00161       cairo_pattern_add_color_stop_rgb (pattern, 1.0,
00162                                         (color.red   / 65535. * 5. + 0.) / 5.,
00163                                         (color.green / 65535. * 5. + 0.) / 5.,
00164                                         (color.blue  / 65535. * 5. + 0.) / 5.);
00165       cairo_set_source (cr, pattern);
00166       cairo_pattern_destroy (pattern);
00167 
00168       if (pcb_cell->active)
00169         cairo_rectangle (cr, toggle_rect.x + 0.5, toggle_rect.y + 0.5,
00170                              toggle_rect.width - 1, toggle_rect.height - 1);
00171       else
00172         {
00173           cairo_move_to (cr, toggle_rect.x + 1, toggle_rect.y + 1);
00174           cairo_rel_line_to (cr, toggle_rect.width / 2, 0);
00175           cairo_rel_line_to (cr, -toggle_rect.width / 2, toggle_rect.width / 2);
00176           cairo_close_path (cr);
00177         }
00178       cairo_fill (cr);
00179 
00180       cairo_destroy (cr);
00181     }
00182 }
00183 
00187 static gint
00188 ghid_cell_renderer_visibility_activate (GtkCellRenderer      *cell,
00189                                         GdkEvent             *event,
00190                                         GtkWidget            *widget,
00191                                         const gchar          *path,
00192                                         GdkRectangle         *background_area,
00193                                         GdkRectangle         *cell_area,
00194                                         GtkCellRendererState  flags)
00195 {
00196   g_signal_emit (cell, toggle_cell_signals[TOGGLED], 0, path);
00197   return TRUE;
00198 }
00199 
00200 /* Setter/Getter */
00201 static void
00202 ghid_cell_renderer_visibility_get_property (GObject     *object,
00203                                             guint        param_id,
00204                                             GValue      *value,
00205                                             GParamSpec  *pspec)
00206 {
00207   GHidCellRendererVisibility *pcb_cell =
00208     GHID_CELL_RENDERER_VISIBILITY (object);
00209 
00210   switch (param_id)
00211     {
00212     case PROP_ACTIVE:
00213       g_value_set_boolean (value, pcb_cell->active);
00214       break;
00215     case PROP_COLOR:
00216       g_value_set_string (value, pcb_cell->color);
00217       break;
00218     }
00219 }
00220 
00221 static void
00222 ghid_cell_renderer_visibility_set_property (GObject      *object,
00223                                                guint         param_id,
00224                                                const GValue *value,
00225                                                GParamSpec   *pspec)
00226 {
00227   GHidCellRendererVisibility *pcb_cell =
00228     GHID_CELL_RENDERER_VISIBILITY (object);
00229 
00230   switch (param_id)
00231     {
00232     case PROP_ACTIVE:
00233       pcb_cell->active = g_value_get_boolean (value);
00234       break;
00235     case PROP_COLOR:
00236       g_free (pcb_cell->color);
00237       pcb_cell->color = g_value_dup_string (value);
00238       break;
00239     }
00240 }
00241 
00242 
00243 /* CONSTRUCTOR */
00244 static void
00245 ghid_cell_renderer_visibility_init (GHidCellRendererVisibility *ls)
00246 {
00247   g_object_set (ls, "mode", GTK_CELL_RENDERER_MODE_ACTIVATABLE, NULL);
00248 }
00249 
00250 static void
00251 ghid_cell_renderer_visibility_class_init (GHidCellRendererVisibilityClass *klass)
00252 {
00253   GObjectClass *object_class = G_OBJECT_CLASS (klass);
00254   GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (klass);
00255 
00256   object_class->get_property = ghid_cell_renderer_visibility_get_property;
00257   object_class->set_property = ghid_cell_renderer_visibility_set_property;
00258 
00259   cell_class->get_size = ghid_cell_renderer_visibility_get_size;
00260   cell_class->render   = ghid_cell_renderer_visibility_render;
00261   cell_class->activate = ghid_cell_renderer_visibility_activate;
00262 
00263   g_object_class_install_property (object_class, PROP_ACTIVE,
00264                                    g_param_spec_boolean ("active",
00265                                                          _("Visibility state"),
00266                                                          _("Visibility of the layer"),
00267                                                          FALSE,
00268                                                          G_PARAM_READWRITE));
00269   g_object_class_install_property (object_class, PROP_COLOR,
00270                                    g_param_spec_string ("color",
00271                                                          _("Layer color"),
00272                                                          _("Layer color"),
00273                                                          FALSE,
00274                                                          G_PARAM_READWRITE));
00275 
00276 
00285   toggle_cell_signals[TOGGLED] =
00286     g_signal_new ("toggled",
00287                   G_OBJECT_CLASS_TYPE (object_class),
00288                   G_SIGNAL_RUN_LAST,
00289                   G_STRUCT_OFFSET (GHidCellRendererVisibilityClass, toggled),
00290                   NULL, NULL,
00291                   g_cclosure_marshal_VOID__STRING,
00292                   G_TYPE_NONE, 1,
00293                   G_TYPE_STRING);
00294 }
00295 
00296 /* PUBLIC FUNCTIONS */
00297 GType
00298 ghid_cell_renderer_visibility_get_type (void)
00299 {
00300   static GType ls_type = 0;
00301 
00302   if (!ls_type)
00303     {
00304       const GTypeInfo ls_info =
00305       {
00306         sizeof (GHidCellRendererVisibilityClass),
00307         NULL, /* base_init */
00308         NULL, /* base_finalize */
00309         (GClassInitFunc) ghid_cell_renderer_visibility_class_init,
00310         NULL, /* class_finalize */
00311         NULL, /* class_data */
00312         sizeof (GHidCellRendererVisibility),
00313         0,    /* n_preallocs */
00314         (GInstanceInitFunc) ghid_cell_renderer_visibility_init,
00315       };
00316 
00317       ls_type = g_type_register_static (GTK_TYPE_CELL_RENDERER,
00318                                         "GHidCellRendererVisibility",
00319                                         &ls_info,
00320                                         0);
00321     }
00322 
00323   return ls_type;
00324 }
00325 
00326 GtkCellRenderer *
00327 ghid_cell_renderer_visibility_new (void)
00328 {
00329   GHidCellRendererVisibility *rv =
00330     g_object_new (GHID_CELL_RENDERER_VISIBILITY_TYPE, NULL);
00331 
00332   rv->active = FALSE;
00333 
00334   return GTK_CELL_RENDERER (rv);
00335 }
00336