gschem

gschem_accel_label.c

Go to the documentation of this file.
00001 /* gEDA - GPL Electronic Design Automation
00002  * gschem - gEDA Schematic Capture
00003  * Copyright (C) 1998-2010 gEDA Contributors (see ChangeLog for details)
00004  *
00005  * Code based on GTK 2.14.5 gtk/gtkaccellabel.c (LGPL)
00006  *
00007  * GTK - The GIMP Toolkit
00008  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
00009  *
00010  * GschemAccelLabel: GtkLabel with accelerator monitoring facilities.
00011  * Copyright (C) 1998 Tim Janik
00012  *
00013  * Modified by the GTK+ Team and others 1997-2001.  See the AUTHORS
00014  * file for a list of people on the GTK+ Team.  See the ChangeLog
00015  * files for a list of changes.  These files are distributed with
00016  * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
00017  *
00018  *  Adapted for gEDA by Peter Clifton <pcjc2@cam.ac.uk>
00019  *
00020  *  THIS FILE IS LGPL LICENSED, gEDA AS A WHOLE IS GPL LICENSED
00021  *
00022  * This library is free software; you can redistribute it and/or
00023  * modify it under the terms of the GNU Lesser General Public
00024  * License as published by the Free Software Foundation; either
00025  * version 2 of the License, or (at your option) any later version.
00026  *
00027  * This library is distributed in the hope that it will be useful,
00028  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00029  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00030  * Lesser General Public License for more details.
00031  *
00032  * You should have received a copy of the GNU Library General Public
00033  * License along with this library; if not, write to the
00034  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00035  * Boston, MA 02110-1301 USA
00036  */
00037 
00038 #include "config.h"
00039 
00040 #include "gschem.h"
00041 
00042 #define P_(x) (x)
00043 
00044 enum {
00045   PROP_0,
00046   PROP_ACCEL_CLOSURE,
00047   PROP_ACCEL_WIDGET,
00048   PROP_ACCEL_STRING,
00049 };
00050 
00051 G_DEFINE_TYPE (GschemAccelLabel, gschem_accel_label, GTK_TYPE_ACCEL_LABEL)
00052 
00053 
00054 gboolean
00055 gschem_accel_label_refetch (GschemAccelLabel *accel_label)
00056 {
00057   gboolean enable_accels;
00058 
00059   g_return_val_if_fail (GSCHEM_IS_ACCEL_LABEL (accel_label), FALSE);
00060 
00061   g_object_get (gtk_widget_get_settings (GTK_WIDGET (accel_label)),
00062                 "gtk-enable-accels", &enable_accels,
00063                 NULL);
00064 
00065   if (!enable_accels || accel_label->accel_string == NULL) {
00066     if (accel_label->accel_string != NULL)
00067       g_free (accel_label->accel_string);
00068 
00069     accel_label->accel_string = g_strdup ("");
00070   }
00071 
00072   gtk_widget_queue_resize (GTK_WIDGET (accel_label));
00073 
00074   return FALSE;
00075 }
00076 
00077 
00078 static const gchar *
00079 gschem_accel_label_get_string (GschemAccelLabel *accel_label)
00080 {
00081   if (!accel_label->accel_string)
00082     gschem_accel_label_refetch (accel_label);
00083 
00084   return accel_label->accel_string;
00085 }
00086 
00087 
00088 static void
00089 gschem_accel_label_set_property (GObject      *object,
00090                                  guint         prop_id,
00091                                  const GValue *value,
00092                                  GParamSpec   *pspec)
00093 {
00094   GschemAccelLabel  *accel_label;
00095 
00096   accel_label = GSCHEM_ACCEL_LABEL (object);
00097 
00098   switch (prop_id) {
00099     /* Dummy properties from GtkAccelLabel */
00100     case PROP_ACCEL_CLOSURE:
00101     case PROP_ACCEL_WIDGET:
00102       break;
00103 
00104     case PROP_ACCEL_STRING:
00105       gschem_accel_label_set_accel_string (accel_label, g_value_get_string (value));
00106       break;
00107     default:
00108       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
00109       break;
00110   }
00111 }
00112 
00113 static void
00114 gschem_accel_label_get_property (GObject    *object,
00115                               guint       prop_id,
00116                               GValue     *value,
00117                               GParamSpec *pspec)
00118 {
00119   GschemAccelLabel  *accel_label;
00120 
00121   accel_label = GSCHEM_ACCEL_LABEL (object);
00122 
00123   switch (prop_id) {
00124     /* Dummy property from GtkAccelLabel */
00125     case PROP_ACCEL_CLOSURE:
00126       g_value_set_boxed (value, NULL);
00127       break;
00128 
00129       /* Dummy property from GtkAccelLabel */
00130     case PROP_ACCEL_WIDGET:
00131       g_value_set_object (value, NULL);
00132       break;
00133 
00134     case PROP_ACCEL_STRING:
00135       g_value_set_string (value, accel_label->accel_string);
00136       break;
00137 
00138     default:
00139       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
00140       break;
00141     }
00142 }
00143 
00144 static void
00145 gschem_accel_label_init (GschemAccelLabel *accel_label)
00146 {
00147   accel_label->accel_padding = 3;
00148   accel_label->accel_string = NULL;
00149 }
00150 
00151 static void
00152 gschem_accel_label_finalize (GObject *object)
00153 {
00154   GschemAccelLabel *accel_label = GSCHEM_ACCEL_LABEL (object);
00155 
00156   g_free (accel_label->accel_string);
00157 
00158   G_OBJECT_CLASS (gschem_accel_label_parent_class)->finalize (object);
00159 }
00160 
00161 guint
00162 gschem_accel_label_get_accel_width (GschemAccelLabel *accel_label)
00163 {
00164   g_return_val_if_fail (GSCHEM_IS_ACCEL_LABEL (accel_label), 0);
00165 
00166   return (accel_label->accel_string_width +
00167           (accel_label->accel_string_width ? accel_label->accel_padding : 0));
00168 }
00169 
00170 static void
00171 gschem_accel_label_size_request (GtkWidget      *widget,
00172                                  GtkRequisition *requisition)
00173 {
00174   GschemAccelLabel *accel_label = GSCHEM_ACCEL_LABEL (widget);
00175   GtkAccelLabel *gtk_accel_label = GTK_ACCEL_LABEL (widget);
00176   PangoLayout *layout;
00177   gint width;
00178 
00179   GTK_WIDGET_CLASS (gschem_accel_label_parent_class)->size_request (widget, requisition);
00180 
00181   layout = gtk_widget_create_pango_layout (widget, gschem_accel_label_get_string (accel_label));
00182   pango_layout_get_pixel_size (layout, &width, NULL);
00183   accel_label->accel_string_width = width;
00184   gtk_accel_label->accel_string_width = width; /* HACK: This field is private to GtkAccelLabel */
00185   g_object_unref (layout);
00186 }
00187 
00188 static gint
00189 get_first_baseline (PangoLayout *layout)
00190 {
00191   PangoLayoutIter *iter;
00192   gint result;
00193 
00194   iter = pango_layout_get_iter (layout);
00195   result = pango_layout_iter_get_baseline (iter);
00196   pango_layout_iter_free (iter);
00197 
00198   return PANGO_PIXELS (result);
00199 }
00200 
00201 static gboolean
00202 gschem_accel_label_expose_event (GtkWidget      *widget,
00203                                  GdkEventExpose *event)
00204 {
00205   GschemAccelLabel *accel_label = GSCHEM_ACCEL_LABEL (widget);
00206   GtkMisc *misc = GTK_MISC (accel_label);
00207   GtkTextDirection direction;
00208 
00209   direction = gtk_widget_get_direction (widget);
00210 
00211   if (GTK_WIDGET_DRAWABLE (accel_label))
00212     {
00213       guint ac_width;
00214 
00215       ac_width = gschem_accel_label_get_accel_width (accel_label);
00216 
00217       if (widget->allocation.width >= widget->requisition.width + ac_width)
00218         {
00219           PangoLayout *label_layout;
00220           PangoLayout *accel_layout;
00221           GtkLabel *label = GTK_LABEL (widget);
00222 
00223           gint x;
00224           gint y;
00225 
00226           label_layout = gtk_label_get_layout (GTK_LABEL (accel_label));
00227 
00228           if (direction == GTK_TEXT_DIR_RTL)
00229             widget->allocation.x += ac_width;
00230           widget->allocation.width -= ac_width;
00231           if (gtk_label_get_ellipsize (label))
00232             pango_layout_set_width (label_layout,
00233                                     pango_layout_get_width (label_layout)
00234                                     - ac_width * PANGO_SCALE);
00235 
00236           if (GTK_WIDGET_CLASS (gschem_accel_label_parent_class)->expose_event)
00237             GTK_WIDGET_CLASS (gschem_accel_label_parent_class)->expose_event (widget, event);
00238           if (direction == GTK_TEXT_DIR_RTL)
00239             widget->allocation.x -= ac_width;
00240           widget->allocation.width += ac_width;
00241           if (gtk_label_get_ellipsize (label))
00242             pango_layout_set_width (label_layout,
00243                                     pango_layout_get_width (label_layout)
00244                                     + ac_width * PANGO_SCALE);
00245 
00246           if (direction == GTK_TEXT_DIR_RTL)
00247             x = widget->allocation.x + misc->xpad;
00248           else
00249             x = widget->allocation.x + widget->allocation.width - misc->xpad - ac_width;
00250 
00251           gtk_label_get_layout_offsets (GTK_LABEL (accel_label), NULL, &y);
00252 
00253           accel_layout = gtk_widget_create_pango_layout (widget, gschem_accel_label_get_string (accel_label));
00254 
00255           y += get_first_baseline (label_layout) - get_first_baseline (accel_layout);
00256 
00257           gtk_paint_layout (widget->style,
00258                             widget->window,
00259                             GTK_WIDGET_STATE (widget),
00260                             FALSE,
00261                             &event->area,
00262                             widget,
00263                             "accellabel",
00264                             x, y,
00265                             accel_layout);
00266 
00267           g_object_unref (accel_layout);
00268         }
00269       else
00270         {
00271           if (GTK_WIDGET_CLASS (gschem_accel_label_parent_class)->expose_event)
00272             GTK_WIDGET_CLASS (gschem_accel_label_parent_class)->expose_event (widget, event);
00273         }
00274     }
00275 
00276   return FALSE;
00277 }
00278 
00279 /* Underscores in key names are better displayed as spaces
00280  * E.g., Page_Up should be "Page Up"
00281  */
00282 static void
00283 substitute_underscores (char *str)
00284 {
00285   char *p;
00286 
00287   for (p = str; *p; p++)
00288     if (*p == '_')
00289       *p = ' ';
00290 }
00291 
00292 
00300 void
00301 gschem_accel_label_set_accel_string (GschemAccelLabel *accel_label,
00302                                      const gchar      *accel_string)
00303 {
00304   g_return_if_fail (GSCHEM_IS_ACCEL_LABEL (accel_label));
00305 
00306   if (accel_label->accel_string)
00307     g_free (accel_label->accel_string);
00308 
00309   if (accel_string) {
00310     accel_label->accel_string = g_strdup (accel_string);
00311     substitute_underscores (accel_label->accel_string);
00312   } else {
00313     accel_label->accel_string = NULL;
00314   }
00315 
00316   g_object_notify (G_OBJECT (accel_label), "accel-string");
00317 }
00318 
00319 static void
00320 gschem_accel_label_class_init (GschemAccelLabelClass *class)
00321 {
00322   GObjectClass *gobject_class = G_OBJECT_CLASS (class);
00323   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
00324 
00325   gobject_class->finalize = gschem_accel_label_finalize;
00326   gobject_class->set_property = gschem_accel_label_set_property;
00327   gobject_class->get_property = gschem_accel_label_get_property;
00328 
00329   widget_class->size_request = gschem_accel_label_size_request;
00330   widget_class->expose_event = gschem_accel_label_expose_event;
00331 
00332   g_object_class_install_property (gobject_class,
00333                                    PROP_ACCEL_CLOSURE,
00334                                    g_param_spec_boxed ("accel-closure",
00335                                                        P_("Accelerator Closure"),
00336                                                        P_("The closure to be monitored for accelerator changes"),
00337                                                        G_TYPE_CLOSURE,
00338                                                        G_PARAM_READWRITE));
00339   g_object_class_install_property (gobject_class,
00340                                    PROP_ACCEL_WIDGET,
00341                                    g_param_spec_object ("accel-widget",
00342                                                         P_("Accelerator Widget"),
00343                                                         P_("The widget to be monitored for accelerator changes"),
00344                                                         GTK_TYPE_WIDGET,
00345                                                         G_PARAM_READWRITE));
00346   g_object_class_install_property (gobject_class,
00347                                    PROP_ACCEL_STRING,
00348                                    g_param_spec_string ("accel-string",
00349                                                         P_("Accelerator String"),
00350                                                         P_("The accelerator string to be displayed"),
00351                                                         NULL,
00352                                                         G_PARAM_READWRITE));
00353 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines