missing NULL terminator in set_config_x
[geda-gaf.git] / gschem / src / gschem_accel_label.c
blob0b3c782f1c2b39e013e37f092dc9b17dd5b48594
1 /* gEDA - GPL Electronic Design Automation
2 * gschem - gEDA Schematic Capture
3 * Copyright (C) 1998-2020 gEDA Contributors (see ChangeLog for details)
5 * Code based on GTK 2.14.5 gtk/gtkaccellabel.c (LGPL)
7 * GTK - The GIMP Toolkit
8 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
10 * GschemAccelLabel: GtkLabel with accelerator monitoring facilities.
11 * Copyright (C) 1998 Tim Janik
13 * Modified by the GTK+ Team and others 1997-2001. See the AUTHORS
14 * file for a list of people on the GTK+ Team. See the ChangeLog
15 * files for a list of changes. These files are distributed with
16 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
18 * Adapted for gEDA by Peter Clifton <pcjc2@cam.ac.uk>
20 * THIS FILE IS LGPL LICENSED, gEDA AS A WHOLE IS GPL LICENSED
22 * This library is free software; you can redistribute it and/or
23 * modify it under the terms of the GNU Lesser General Public
24 * License as published by the Free Software Foundation; either
25 * version 2 of the License, or (at your option) any later version.
27 * This library is distributed in the hope that it will be useful,
28 * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
30 * Lesser General Public License for more details.
32 * You should have received a copy of the GNU Library General Public
33 * License along with this library; if not, write to the
34 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
35 * Boston, MA 02110-1301 USA
38 #include "config.h"
40 #include "gschem.h"
42 #define P_(x) (x)
44 enum {
45 PROP_0,
46 PROP_ACCEL_CLOSURE,
47 PROP_ACCEL_WIDGET,
48 PROP_ACCEL_STRING,
51 G_DEFINE_TYPE (GschemAccelLabel, gschem_accel_label, GTK_TYPE_ACCEL_LABEL)
54 gboolean
55 gschem_accel_label_refetch (GschemAccelLabel *accel_label)
57 gboolean enable_accels;
59 g_return_val_if_fail (GSCHEM_IS_ACCEL_LABEL (accel_label), FALSE);
61 g_object_get (gtk_widget_get_settings (GTK_WIDGET (accel_label)),
62 "gtk-enable-accels", &enable_accels,
63 NULL);
65 if (!enable_accels || accel_label->accel_string == NULL) {
66 if (accel_label->accel_string != NULL)
67 g_free (accel_label->accel_string);
69 accel_label->accel_string = g_strdup ("");
72 gtk_widget_queue_resize (GTK_WIDGET (accel_label));
74 return FALSE;
78 static const gchar *
79 gschem_accel_label_get_string (GschemAccelLabel *accel_label)
81 if (!accel_label->accel_string)
82 gschem_accel_label_refetch (accel_label);
84 return accel_label->accel_string;
88 static void
89 gschem_accel_label_set_property (GObject *object,
90 guint prop_id,
91 const GValue *value,
92 GParamSpec *pspec)
94 GschemAccelLabel *accel_label;
96 accel_label = GSCHEM_ACCEL_LABEL (object);
98 switch (prop_id) {
99 /* Dummy properties from GtkAccelLabel */
100 case PROP_ACCEL_CLOSURE:
101 case PROP_ACCEL_WIDGET:
102 break;
104 case PROP_ACCEL_STRING:
105 gschem_accel_label_set_accel_string (accel_label, g_value_get_string (value));
106 break;
107 default:
108 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
109 break;
113 static void
114 gschem_accel_label_get_property (GObject *object,
115 guint prop_id,
116 GValue *value,
117 GParamSpec *pspec)
119 GschemAccelLabel *accel_label;
121 accel_label = GSCHEM_ACCEL_LABEL (object);
123 switch (prop_id) {
124 /* Dummy property from GtkAccelLabel */
125 case PROP_ACCEL_CLOSURE:
126 g_value_set_boxed (value, NULL);
127 break;
129 /* Dummy property from GtkAccelLabel */
130 case PROP_ACCEL_WIDGET:
131 g_value_set_object (value, NULL);
132 break;
134 case PROP_ACCEL_STRING:
135 g_value_set_string (value, accel_label->accel_string);
136 break;
138 default:
139 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
140 break;
144 static void
145 gschem_accel_label_init (GschemAccelLabel *accel_label)
147 accel_label->accel_padding = 3;
148 accel_label->accel_string = NULL;
151 static void
152 gschem_accel_label_finalize (GObject *object)
154 GschemAccelLabel *accel_label = GSCHEM_ACCEL_LABEL (object);
156 g_free (accel_label->accel_string);
158 G_OBJECT_CLASS (gschem_accel_label_parent_class)->finalize (object);
161 guint
162 gschem_accel_label_get_accel_width (GschemAccelLabel *accel_label)
164 g_return_val_if_fail (GSCHEM_IS_ACCEL_LABEL (accel_label), 0);
166 return (accel_label->accel_string_width +
167 (accel_label->accel_string_width ? accel_label->accel_padding : 0));
170 static void
171 gschem_accel_label_size_request (GtkWidget *widget,
172 GtkRequisition *requisition)
174 GschemAccelLabel *accel_label = GSCHEM_ACCEL_LABEL (widget);
175 GtkAccelLabel *gtk_accel_label = GTK_ACCEL_LABEL (widget);
176 PangoLayout *layout;
177 gint width;
179 GTK_WIDGET_CLASS (gschem_accel_label_parent_class)->size_request (widget, requisition);
181 layout = gtk_widget_create_pango_layout (widget, gschem_accel_label_get_string (accel_label));
182 pango_layout_get_pixel_size (layout, &width, NULL);
183 accel_label->accel_string_width = width;
184 gtk_accel_label->accel_string_width = width; /* HACK: This field is private to GtkAccelLabel */
185 g_object_unref (layout);
188 static gint
189 get_first_baseline (PangoLayout *layout)
191 PangoLayoutIter *iter;
192 gint result;
194 iter = pango_layout_get_iter (layout);
195 result = pango_layout_iter_get_baseline (iter);
196 pango_layout_iter_free (iter);
198 return PANGO_PIXELS (result);
201 static gboolean
202 gschem_accel_label_expose_event (GtkWidget *widget,
203 GdkEventExpose *event)
205 GschemAccelLabel *accel_label = GSCHEM_ACCEL_LABEL (widget);
206 GtkMisc *misc = GTK_MISC (accel_label);
207 GtkTextDirection direction;
209 direction = gtk_widget_get_direction (widget);
211 if (gtk_widget_is_drawable (GTK_WIDGET (accel_label)))
213 guint ac_width;
215 ac_width = gschem_accel_label_get_accel_width (accel_label);
217 if (widget->allocation.width >= widget->requisition.width + ac_width)
219 PangoLayout *label_layout;
220 PangoLayout *accel_layout;
221 GtkLabel *label = GTK_LABEL (widget);
223 gint x;
224 gint y;
226 label_layout = gtk_label_get_layout (GTK_LABEL (accel_label));
228 if (direction == GTK_TEXT_DIR_RTL)
229 widget->allocation.x += ac_width;
230 widget->allocation.width -= ac_width;
231 if (gtk_label_get_ellipsize (label))
232 pango_layout_set_width (label_layout,
233 pango_layout_get_width (label_layout)
234 - ac_width * PANGO_SCALE);
236 if (GTK_WIDGET_CLASS (gschem_accel_label_parent_class)->expose_event)
237 GTK_WIDGET_CLASS (gschem_accel_label_parent_class)->expose_event (widget, event);
238 if (direction == GTK_TEXT_DIR_RTL)
239 widget->allocation.x -= ac_width;
240 widget->allocation.width += ac_width;
241 if (gtk_label_get_ellipsize (label))
242 pango_layout_set_width (label_layout,
243 pango_layout_get_width (label_layout)
244 + ac_width * PANGO_SCALE);
246 if (direction == GTK_TEXT_DIR_RTL)
247 x = widget->allocation.x + misc->xpad;
248 else
249 x = widget->allocation.x + widget->allocation.width - misc->xpad - ac_width;
251 gtk_label_get_layout_offsets (GTK_LABEL (accel_label), NULL, &y);
253 accel_layout = gtk_widget_create_pango_layout (widget, gschem_accel_label_get_string (accel_label));
255 y += get_first_baseline (label_layout) - get_first_baseline (accel_layout);
257 gtk_paint_layout (widget->style,
258 widget->window,
259 gtk_widget_get_state (widget),
260 FALSE,
261 &event->area,
262 widget,
263 "accellabel",
264 x, y,
265 accel_layout);
267 g_object_unref (accel_layout);
269 else
271 if (GTK_WIDGET_CLASS (gschem_accel_label_parent_class)->expose_event)
272 GTK_WIDGET_CLASS (gschem_accel_label_parent_class)->expose_event (widget, event);
276 return FALSE;
279 /* Underscores in key names are better displayed as spaces
280 * E.g., Page_Up should be "Page Up"
282 static void
283 substitute_underscores (char *str)
285 char *p;
287 for (p = str; *p; p++)
288 if (*p == '_')
289 *p = ' ';
294 * gschem_accel_label_set_accel_string:
295 * \param accel_label a #GschemAccelLabel
296 * \param accel_string the accelerator string.
298 * Sets the accelerator string for this accelerator label.
300 void
301 gschem_accel_label_set_accel_string (GschemAccelLabel *accel_label,
302 const gchar *accel_string)
304 g_return_if_fail (GSCHEM_IS_ACCEL_LABEL (accel_label));
306 if (accel_label->accel_string)
307 g_free (accel_label->accel_string);
309 if (accel_string) {
310 accel_label->accel_string = g_strdup (accel_string);
311 substitute_underscores (accel_label->accel_string);
312 } else {
313 accel_label->accel_string = NULL;
316 g_object_notify (G_OBJECT (accel_label), "accel-string");
319 static void
320 gschem_accel_label_class_init (GschemAccelLabelClass *class)
322 GObjectClass *gobject_class = G_OBJECT_CLASS (class);
323 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
325 gobject_class->finalize = gschem_accel_label_finalize;
326 gobject_class->set_property = gschem_accel_label_set_property;
327 gobject_class->get_property = gschem_accel_label_get_property;
329 widget_class->size_request = gschem_accel_label_size_request;
330 widget_class->expose_event = gschem_accel_label_expose_event;
332 g_object_class_install_property (gobject_class,
333 PROP_ACCEL_CLOSURE,
334 g_param_spec_boxed ("accel-closure",
335 P_("Accelerator Closure"),
336 P_("The closure to be monitored for accelerator changes"),
337 G_TYPE_CLOSURE,
338 G_PARAM_READWRITE));
339 g_object_class_install_property (gobject_class,
340 PROP_ACCEL_WIDGET,
341 g_param_spec_object ("accel-widget",
342 P_("Accelerator Widget"),
343 P_("The widget to be monitored for accelerator changes"),
344 GTK_TYPE_WIDGET,
345 G_PARAM_READWRITE));
346 g_object_class_install_property (gobject_class,
347 PROP_ACCEL_STRING,
348 g_param_spec_string ("accel-string",
349 P_("Accelerator String"),
350 P_("The accelerator string to be displayed"),
351 NULL,
352 G_PARAM_READWRITE));