7925e43062bf08d4e1c94cbf7ff89378a728f22f
[hildon] / src / hildon-entry.c
1 /*
2  * This file is a part of hildon
3  *
4  * Copyright (C) 2008 Nokia Corporation, all rights reserved.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser Public License as published by
8  * the Free Software Foundation; version 2 of the license.
9  *
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 Lesser Public License for more details.
14  *
15  */
16
17 /**
18  * SECTION:hildon-entry
19  * @short_description: Widget representing a text entry in the Hildon framework.
20  *
21  * The #HildonEntry is a GTK widget which represents a text entry. It
22  * is derived from the #GtkEntry widget and provides additional
23  * commodities specific to the Hildon framework.
24  *
25  * Besides all the features inherited from #GtkEntry, a #HildonEntry
26  * can also have a placeholder text. This text will be shown if the
27  * entry is empty and doesn't have the input focus, but it's otherwise
28  * ignored. Thus, calls to hildon_entry_get_text() will never return
29  * the placeholder text, not even when it's being displayed.
30  *
31  * Although #HildonEntry is derived from #GtkEntry,
32  * gtk_entry_get_text() and gtk_entry_set_text() must never be used to
33  * get/set the text in this widget. hildon_entry_get_text() and
34  * hildon_entry_set_text() must be used instead.
35  */
36
37 #include                                        "hildon-entry.h"
38
39 G_DEFINE_TYPE                                   (HildonEntry, hildon_entry, GTK_TYPE_ENTRY);
40
41 #define                                         HILDON_ENTRY_GET_PRIVATE(obj) \
42                                                 (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
43                                                 HILDON_TYPE_ENTRY, HildonEntryPrivate));
44
45 typedef struct                                  _HildonEntryPrivate HildonEntryPrivate;
46
47 struct                                          _HildonEntryPrivate
48 {
49     gchar *placeholder;
50 };
51
52 static const gchar *placeholder_widget_name     = "hildon-entry-placeholder";
53
54 /* Function used to decide whether to show the placeholder or not */
55 static void
56 hildon_entry_refresh_contents                   (GtkWidget *entry)
57 {
58     HildonEntryPrivate *priv = HILDON_ENTRY_GET_PRIVATE (entry);
59     gboolean showing_placeholder, entry_has_focus;
60
61     showing_placeholder = g_str_equal (gtk_widget_get_name (entry), placeholder_widget_name);
62     entry_has_focus = GTK_WIDGET_HAS_FOCUS (entry);
63
64     if (showing_placeholder) {
65         if (entry_has_focus) {
66             /* Remove the placeholder when the widget obtains focus */
67             gtk_widget_set_name (entry, NULL);
68             gtk_entry_set_text (GTK_ENTRY (entry), "");
69         } else {
70             /* Update the placeholder (it may have been changed) */
71             gtk_entry_set_text (GTK_ENTRY (entry), priv->placeholder);
72         }
73     } else {
74         /* Show the placeholder when the widget is empty and has no focus */
75         const gchar *text = gtk_entry_get_text (GTK_ENTRY (entry));
76         if (text[0] == '\0' && !entry_has_focus) {
77             if (priv->placeholder) {
78                 gtk_widget_set_name (entry, placeholder_widget_name);
79                 gtk_entry_set_text (GTK_ENTRY (entry), priv->placeholder);
80             }
81         }
82     }
83 }
84
85 /**
86  * hildon_entry_set_text:
87  * @entry: a #HildonEntry
88  * @text: the new text
89  *
90  * Sets the text in @entry to @text, replacing its current contents.
91  *
92  * Note that you must never use gtk_entry_set_text() to set the text
93  * of a #HildonEntry.
94  */
95 void
96 hildon_entry_set_text                           (HildonEntry *entry,
97                                                  const gchar *text)
98 {
99     g_return_if_fail (HILDON_IS_ENTRY (entry) && text != NULL);
100
101     gtk_widget_set_name (GTK_WIDGET (entry), NULL);
102     gtk_entry_set_text (GTK_ENTRY (entry), text);
103
104     /* If the entry is cleared show the placeholder */
105     if (text[0] == '\0')
106         hildon_entry_refresh_contents (GTK_WIDGET (entry));
107 }
108
109 /**
110  * hildon_entry_get_text:
111  * @entry: a #HildonEntry
112  *
113  * Gets the current text in @entry.
114  *
115  * Note that you must never use gtk_entry_get_text() to get the text
116  * from a #HildonEntry.
117  *
118  * Also note that placeholder text (set using
119  * hildon_entry_set_placeholder()) is never returned. Only text set by
120  * hildon_entry_set_text() or typed by the user is considered.
121  *
122  * Returns: the text in @entry. This text must not be modified or
123  * freed.
124  */
125 const gchar *
126 hildon_entry_get_text                           (HildonEntry *entry)
127 {
128     g_return_val_if_fail (HILDON_IS_ENTRY (entry), NULL);
129
130     if (g_str_equal (gtk_widget_get_name (GTK_WIDGET (entry)), placeholder_widget_name)) {
131         return "";
132     }
133
134     return gtk_entry_get_text (GTK_ENTRY (entry));
135 }
136
137 /**
138  * hildon_entry_set_placeholder:
139  * @entry: a #HildonEntry
140  * @text: the new text
141  *
142  * Sets the placeholder text in @entry to @text.
143  */
144 void
145 hildon_entry_set_placeholder                    (HildonEntry *entry,
146                                                  const gchar *text)
147 {
148     HildonEntryPrivate *priv;
149
150     g_return_if_fail (HILDON_IS_ENTRY (entry) && text != NULL);
151
152     priv = HILDON_ENTRY_GET_PRIVATE (entry);
153
154     g_free (priv->placeholder);
155     priv->placeholder = g_strdup (text);
156     hildon_entry_refresh_contents (GTK_WIDGET (entry));
157 }
158
159 /**
160  * hildon_entry_new:
161  * @size: The size of the entry
162  *
163  * Creates a new entry.
164  *
165  * Returns: a new #HildonEntry
166  */
167 GtkWidget *
168 hildon_entry_new                                (HildonSizeType size)
169 {
170     GtkWidget *entry = g_object_new (HILDON_TYPE_ENTRY, NULL);
171
172     hildon_gtk_widget_set_theme_size (entry, size);
173
174     return entry;
175 }
176
177 static gboolean
178 hildon_entry_focus_in_event                     (GtkWidget     *widget,
179                                                  GdkEventFocus *event)
180 {
181     hildon_entry_refresh_contents (widget);
182
183     if (GTK_WIDGET_CLASS (hildon_entry_parent_class)->focus_in_event) {
184         return GTK_WIDGET_CLASS (hildon_entry_parent_class)->focus_in_event (widget, event);
185     } else {
186         return FALSE;
187     }
188 }
189
190 static gboolean
191 hildon_entry_focus_out_event                    (GtkWidget     *widget,
192                                                  GdkEventFocus *event)
193 {
194     hildon_entry_refresh_contents (widget);
195
196     if (GTK_WIDGET_CLASS (hildon_entry_parent_class)->focus_out_event) {
197         return GTK_WIDGET_CLASS (hildon_entry_parent_class)->focus_out_event (widget, event);
198     } else {
199         return FALSE;
200     }
201 }
202
203 static void
204 hildon_entry_finalize                           (GObject *object)
205 {
206     HildonEntryPrivate *priv = HILDON_ENTRY_GET_PRIVATE (object);
207
208     g_free (priv->placeholder);
209
210     if (G_OBJECT_CLASS (hildon_entry_parent_class)->finalize)
211         G_OBJECT_CLASS (hildon_entry_parent_class)->finalize (object);
212 }
213
214 static void
215 hildon_entry_class_init                         (HildonEntryClass *klass)
216 {
217     GObjectClass *gobject_class = (GObjectClass *)klass;
218     GtkWidgetClass *widget_class = (GtkWidgetClass *)klass;
219
220     gobject_class->finalize = hildon_entry_finalize;
221     widget_class->focus_in_event = hildon_entry_focus_in_event;
222     widget_class->focus_out_event = hildon_entry_focus_out_event;
223
224     g_type_class_add_private (klass, sizeof (HildonEntryPrivate));
225 }
226
227 static void
228 hildon_entry_init                               (HildonEntry *self)
229 {
230     HildonEntryPrivate *priv = HILDON_ENTRY_GET_PRIVATE (self);
231
232     priv->placeholder = NULL;
233 }