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
51 G_DEFINE_TYPE (GschemAccelLabel
, gschem_accel_label
, GTK_TYPE_ACCEL_LABEL
)
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
,
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
));
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
;
89 gschem_accel_label_set_property (GObject
*object
,
94 GschemAccelLabel
*accel_label
;
96 accel_label
= GSCHEM_ACCEL_LABEL (object
);
99 /* Dummy properties from GtkAccelLabel */
100 case PROP_ACCEL_CLOSURE
:
101 case PROP_ACCEL_WIDGET
:
104 case PROP_ACCEL_STRING
:
105 gschem_accel_label_set_accel_string (accel_label
, g_value_get_string (value
));
108 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
114 gschem_accel_label_get_property (GObject
*object
,
119 GschemAccelLabel
*accel_label
;
121 accel_label
= GSCHEM_ACCEL_LABEL (object
);
124 /* Dummy property from GtkAccelLabel */
125 case PROP_ACCEL_CLOSURE
:
126 g_value_set_boxed (value
, NULL
);
129 /* Dummy property from GtkAccelLabel */
130 case PROP_ACCEL_WIDGET
:
131 g_value_set_object (value
, NULL
);
134 case PROP_ACCEL_STRING
:
135 g_value_set_string (value
, accel_label
->accel_string
);
139 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
145 gschem_accel_label_init (GschemAccelLabel
*accel_label
)
147 accel_label
->accel_padding
= 3;
148 accel_label
->accel_string
= NULL
;
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
);
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));
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
);
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
);
189 get_first_baseline (PangoLayout
*layout
)
191 PangoLayoutIter
*iter
;
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
);
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
)))
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
);
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
;
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
,
259 gtk_widget_get_state (widget
),
267 g_object_unref (accel_layout
);
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
);
279 /* Underscores in key names are better displayed as spaces
280 * E.g., Page_Up should be "Page Up"
283 substitute_underscores (char *str
)
287 for (p
= str
; *p
; 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.
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
);
310 accel_label
->accel_string
= g_strdup (accel_string
);
311 substitute_underscores (accel_label
->accel_string
);
313 accel_label
->accel_string
= NULL
;
316 g_object_notify (G_OBJECT (accel_label
), "accel-string");
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
,
334 g_param_spec_boxed ("accel-closure",
335 P_("Accelerator Closure"),
336 P_("The closure to be monitored for accelerator changes"),
339 g_object_class_install_property (gobject_class
,
341 g_param_spec_object ("accel-widget",
342 P_("Accelerator Widget"),
343 P_("The widget to be monitored for accelerator changes"),
346 g_object_class_install_property (gobject_class
,
348 g_param_spec_string ("accel-string",
349 P_("Accelerator String"),
350 P_("The accelerator string to be displayed"),