gschem
|
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 }