1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
3
* Copyright 2009-2010 Red Hat, Inc,
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 3 of the License, or
8
* (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
* Written by: Matthias Clasen <mclasen@redhat.com>
22
#include <gdk/gdkkeysyms.h>
23
#include "um-editable-entry.h"
25
#define EMPTY_TEXT "\xe2\x80\x94"
27
struct _UmEditableEntryPrivate {
28
GtkNotebook *notebook;
41
#define UM_EDITABLE_ENTRY_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), UM_TYPE_EDITABLE_ENTRY, UmEditableEntryPrivate))
58
static guint signals [LAST_SIGNAL] = { 0, };
60
G_DEFINE_TYPE (UmEditableEntry, um_editable_entry, GTK_TYPE_ALIGNMENT);
63
um_editable_entry_set_text (UmEditableEntry *e,
66
UmEditableEntryPrivate *priv;
72
tmp = g_strdup (text);
76
gtk_entry_set_text (priv->entry, tmp);
78
if (tmp == NULL || tmp[0] == '\0')
81
gtk_label_set_text (priv->label, tmp);
82
label = gtk_bin_get_child (GTK_BIN (priv->button));
83
gtk_label_set_text (GTK_LABEL (label), tmp);
85
g_object_notify (G_OBJECT (e), "text");
89
um_editable_entry_get_text (UmEditableEntry *e)
95
um_editable_entry_set_editable (UmEditableEntry *e,
98
UmEditableEntryPrivate *priv;
102
if (priv->editable != editable) {
103
priv->editable = editable;
105
gtk_notebook_set_current_page (priv->notebook, editable ? 1 : 0);
107
g_object_notify (G_OBJECT (e), "editable");
112
um_editable_entry_get_editable (UmEditableEntry *e)
114
return e->priv->editable;
118
update_entry_font (GtkWidget *widget,
121
UmEditableEntryPrivate *priv = e->priv;
122
PangoFontDescription *desc;
123
GtkStyleContext *style;
126
if (!priv->weight_set && !priv->scale_set)
129
g_signal_handlers_block_by_func (widget, update_entry_font, e);
131
gtk_widget_override_font (widget, NULL);
133
style = gtk_widget_get_style_context (widget);
134
desc = pango_font_description_copy
135
(gtk_style_context_get_font (style, gtk_widget_get_state_flags (widget)));
137
if (priv->weight_set)
138
pango_font_description_set_weight (desc, priv->weight);
139
if (priv->scale_set) {
140
size = pango_font_description_get_size (desc);
141
pango_font_description_set_size (desc, priv->scale * size);
143
gtk_widget_override_font (widget, desc);
145
pango_font_description_free (desc);
147
g_signal_handlers_unblock_by_func (widget, update_entry_font, e);
151
update_fonts (UmEditableEntry *e)
153
PangoAttrList *attrs;
154
PangoAttribute *attr;
157
UmEditableEntryPrivate *priv = e->priv;
159
attrs = pango_attr_list_new ();
160
if (priv->scale_set) {
161
attr = pango_attr_scale_new (priv->scale);
162
pango_attr_list_insert (attrs, attr);
164
if (priv->weight_set) {
165
attr = pango_attr_weight_new (priv->weight);
166
pango_attr_list_insert (attrs, attr);
169
gtk_label_set_attributes (priv->label, attrs);
171
label = gtk_bin_get_child (GTK_BIN (priv->button));
172
gtk_label_set_attributes (GTK_LABEL (label), attrs);
174
pango_attr_list_unref (attrs);
176
update_entry_font ((GtkWidget *)priv->entry, e);
180
um_editable_entry_set_weight (UmEditableEntry *e,
183
UmEditableEntryPrivate *priv = e->priv;
185
if (priv->weight == weight && priv->weight_set)
188
priv->weight = weight;
189
priv->weight_set = TRUE;
193
g_object_notify (G_OBJECT (e), "weight");
194
g_object_notify (G_OBJECT (e), "weight-set");
198
um_editable_entry_get_weight (UmEditableEntry *e)
200
return e->priv->weight;
204
um_editable_entry_set_scale (UmEditableEntry *e,
207
UmEditableEntryPrivate *priv = e->priv;
209
if (priv->scale == scale && priv->scale_set)
213
priv->scale_set = TRUE;
217
g_object_notify (G_OBJECT (e), "scale");
218
g_object_notify (G_OBJECT (e), "scale-set");
222
um_editable_entry_get_scale (UmEditableEntry *e)
224
return e->priv->scale;
228
um_editable_entry_set_property (GObject *object,
233
UmEditableEntry *e = UM_EDITABLE_ENTRY (object);
237
um_editable_entry_set_text (e, g_value_get_string (value));
240
um_editable_entry_set_editable (e, g_value_get_boolean (value));
243
um_editable_entry_set_weight (e, g_value_get_int (value));
245
case PROP_WEIGHT_SET:
246
e->priv->weight_set = g_value_get_boolean (value);
249
um_editable_entry_set_scale (e, g_value_get_double (value));
252
e->priv->scale_set = g_value_get_boolean (value);
255
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
261
um_editable_entry_get_property (GObject *object,
266
UmEditableEntry *e = UM_EDITABLE_ENTRY (object);
270
g_value_set_string (value,
271
um_editable_entry_get_text (e));
274
g_value_set_boolean (value,
275
um_editable_entry_get_editable (e));
278
g_value_set_int (value,
279
um_editable_entry_get_weight (e));
281
case PROP_WEIGHT_SET:
282
g_value_set_boolean (value, e->priv->weight_set);
285
g_value_set_double (value,
286
um_editable_entry_get_scale (e));
289
g_value_set_boolean (value, e->priv->scale_set);
292
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
298
um_editable_entry_finalize (GObject *object)
300
UmEditableEntry *e = (UmEditableEntry*)object;
302
g_free (e->priv->text);
304
G_OBJECT_CLASS (um_editable_entry_parent_class)->finalize (object);
308
um_editable_entry_class_init (UmEditableEntryClass *class)
310
GObjectClass *object_class;
312
object_class = G_OBJECT_CLASS (class);
314
object_class->set_property = um_editable_entry_set_property;
315
object_class->get_property = um_editable_entry_get_property;
316
object_class->finalize = um_editable_entry_finalize;
318
signals[EDITING_DONE] =
319
g_signal_new ("editing-done",
320
G_TYPE_FROM_CLASS (class),
322
G_STRUCT_OFFSET (UmEditableEntryClass, editing_done),
324
g_cclosure_marshal_VOID__VOID,
327
g_object_class_install_property (object_class, PROP_TEXT,
328
g_param_spec_string ("text",
329
"Text", "The text of the button",
333
g_object_class_install_property (object_class, PROP_EDITABLE,
334
g_param_spec_boolean ("editable",
335
"Editable", "Whether the text can be edited",
339
g_object_class_install_property (object_class, PROP_WEIGHT,
340
g_param_spec_int ("weight",
341
"Font Weight", "The font weight to use",
342
0, G_MAXINT, PANGO_WEIGHT_NORMAL,
345
g_object_class_install_property (object_class, PROP_WEIGHT_SET,
346
g_param_spec_boolean ("weight-set",
347
"Font Weight Set", "Whether a font weight is set",
351
g_object_class_install_property (object_class, PROP_SCALE,
352
g_param_spec_double ("scale",
353
"Font Scale", "The font scale to use",
354
0.0, G_MAXDOUBLE, 1.0,
357
g_object_class_install_property (object_class, PROP_SCALE_SET,
358
g_param_spec_boolean ("scale-set",
359
"Font Scale Set", "Whether a font scale is set",
363
g_type_class_add_private (class, sizeof (UmEditableEntryPrivate));
367
start_editing (UmEditableEntry *e)
369
gtk_notebook_set_current_page (e->priv->notebook, 2);
373
stop_editing (UmEditableEntry *e)
375
um_editable_entry_set_text (e, gtk_entry_get_text (e->priv->entry));
376
gtk_notebook_set_current_page (e->priv->notebook, 1);
377
g_signal_emit (e, signals[EDITING_DONE], 0);
381
cancel_editing (UmEditableEntry *e)
383
gtk_entry_set_text (e->priv->entry, um_editable_entry_get_text (e));
384
gtk_notebook_set_current_page (e->priv->notebook, 1);
388
button_clicked (GtkWidget *widget,
395
entry_activated (GtkWidget *widget,
402
entry_focus_out (GtkWidget *widget,
403
GdkEventFocus *event,
411
entry_key_press (GtkWidget *widget,
415
if (event->keyval == GDK_KEY_Escape) {
422
update_button_padding (GtkWidget *widget,
423
GtkAllocation *allocation,
426
UmEditableEntryPrivate *priv = e->priv;
431
gtk_widget_get_allocation (gtk_widget_get_parent (widget), &alloc);
433
offset = allocation->x - alloc.x;
435
gtk_misc_get_padding (GTK_MISC (priv->label), &pad, NULL);
437
gtk_misc_set_padding (GTK_MISC (priv->label), offset, 0);
441
um_editable_entry_init (UmEditableEntry *e)
443
UmEditableEntryPrivate *priv;
445
priv = e->priv = UM_EDITABLE_ENTRY_GET_PRIVATE (e);
447
priv->weight = PANGO_WEIGHT_NORMAL;
448
priv->weight_set = FALSE;
450
priv->scale_set = FALSE;
452
priv->notebook = (GtkNotebook*)gtk_notebook_new ();
453
gtk_notebook_set_show_tabs (priv->notebook, FALSE);
454
gtk_notebook_set_show_border (priv->notebook, FALSE);
456
priv->label = (GtkLabel*)gtk_label_new (EMPTY_TEXT);
457
gtk_misc_set_alignment (GTK_MISC (priv->label), 0.0, 0.5);
458
gtk_notebook_append_page (priv->notebook, (GtkWidget*)priv->label, NULL);
460
priv->button = (GtkButton*)gtk_button_new_with_label (EMPTY_TEXT);
461
gtk_widget_set_receives_default ((GtkWidget*)priv->button, TRUE);
462
gtk_button_set_relief (priv->button, GTK_RELIEF_NONE);
463
gtk_button_set_alignment (priv->button, 0.0, 0.5);
464
gtk_notebook_append_page (priv->notebook, (GtkWidget*)priv->button, NULL);
465
g_signal_connect (priv->button, "clicked", G_CALLBACK (button_clicked), e);
467
priv->entry = (GtkEntry*)gtk_entry_new ();
468
gtk_notebook_append_page (priv->notebook, (GtkWidget*)priv->entry, NULL);
470
g_signal_connect (priv->entry, "activate", G_CALLBACK (entry_activated), e);
471
g_signal_connect (priv->entry, "focus-out-event", G_CALLBACK (entry_focus_out), e);
472
g_signal_connect (priv->entry, "key-press-event", G_CALLBACK (entry_key_press), e);
473
g_signal_connect (priv->entry, "style-updated", G_CALLBACK (update_entry_font), e);
474
g_signal_connect (gtk_bin_get_child (GTK_BIN (priv->button)), "size-allocate", G_CALLBACK (update_button_padding), e);
476
gtk_container_add (GTK_CONTAINER (e), (GtkWidget*)priv->notebook);
478
gtk_widget_show ((GtkWidget*)priv->notebook);
479
gtk_widget_show ((GtkWidget*)priv->label);
480
gtk_widget_show ((GtkWidget*)priv->button);
481
gtk_widget_show ((GtkWidget*)priv->entry);
483
gtk_notebook_set_current_page (priv->notebook, 0);
487
um_editable_entry_new (void)
489
return (GtkWidget *) g_object_new (UM_TYPE_EDITABLE_ENTRY, NULL);