2 * This file is a part of hildon
4 * Copyright (C) 2006 Nokia Corporation, all rights reserved.
6 * Contact: Michael Dominic Kostrzewa <michael.kostrzewa@nokia.com>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; version 2.1 of
13 * This library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
26 * SECTION:hildon-code-dialog
27 * @short_description: A keypad-like widget used to enter pincodes.
29 * #HildonCodeDialog displays a keypad that can be used to enter
30 * numerical pin codes or lock codes. It emits a 'input' signal each time
31 * an input action is performed on the dialog.
35 /* FIXME We need property access in this widget */
41 #include "hildon-code-dialog.h"
42 #include "hildon-defines.h"
43 #include "hildon-banner.h"
45 #include <gdk/gdkkeysyms.h>
46 #include <gtk/gtkbutton.h>
47 #include <gtk/gtkentry.h>
48 #include <gtk/gtkicontheme.h>
49 #include <gtk/gtktable.h>
50 #include <gtk/gtkvbox.h>
51 #include <gtk/gtkbbox.h>
52 #include <gtk/gtklabel.h>
53 #include <gtk/gtkalignment.h>
55 #include "hildon-code-dialog-private.h"
57 #define HEIGHT (38-HILDON_MARGIN_DEFAULT)
59 #define WIDTH (60-HILDON_MARGIN_DEFAULT)
61 #define BACKSPACE_ICON "qgn_calculator_backspace"
64 dgettext("hildon-libs", String)
67 dgettext("hildon-common-strings", String)
69 #define DEVICELOCK_OK _("secu_enter_lock_code_dialog_ok")
71 #define DEVICELOCK_CANCEL _("secu_enter_lock_code_dialog_cancel")
73 #define DEVICELOCK_TITLE _("secu_application_title")
75 #define DEVICELOCK_MAX_CHAR_REACHED c_("ckdg_ib_maximum_characters_reached")
77 #define MAX_PINCODE_LEN (10)
80 hildon_code_dialog_class_init (HildonCodeDialogClass *cd_class);
83 hildon_code_dialog_init (HildonCodeDialog *self);
86 hildon_code_dialog_button_clicked (GtkButton *buttonm,
90 hildon_code_dialog_insert_text (GtkEditable *editable,
97 hildon_code_dialog_key_press_event (GtkWidget *widget,
102 hildon_code_dialog_real_input (HildonCodeDialog *dialog);
105 hildon_code_dialog_input (HildonCodeDialog *dialog);
107 static GtkDialogClass* parent_class = NULL;
109 static guint input_signal;
112 * hildon_code_dialog_get_type:
114 * Initializes and returns the type of a hildon code dialog.
116 * @Returns: GType of #HildonCodeDialog
119 hildon_code_dialog_get_type (void)
121 static GType type = 0;
125 static const GTypeInfo info =
127 sizeof (HildonCodeDialogClass),
128 NULL, /* base_init */
129 NULL, /* base_finalize */
130 (GClassInitFunc) hildon_code_dialog_class_init,
131 NULL, /* class_finalize */
132 NULL, /* class_data */
133 sizeof (HildonCodeDialog),
135 (GInstanceInitFunc) hildon_code_dialog_init
137 type = g_type_register_static (GTK_TYPE_DIALOG,
138 "HildonCodeDialog", &info, 0);
144 hildon_code_dialog_class_init (HildonCodeDialogClass *cd_class)
146 parent_class = GTK_DIALOG_CLASS (g_type_class_peek_parent (cd_class));
147 g_type_class_add_private (cd_class, sizeof (HildonCodeDialogPrivate));
149 cd_class->input = hildon_code_dialog_real_input;
151 /* FIXME Document this signal! */
152 input_signal = g_signal_new("input",
153 HILDON_TYPE_CODE_DIALOG,
155 G_STRUCT_OFFSET (HildonCodeDialogClass, input),
157 g_cclosure_marshal_VOID__VOID,
163 hildon_code_dialog_init (HildonCodeDialog *dialog)
165 HildonCodeDialogPrivate *priv;
167 GtkWidget *dialog_vbox1 = NULL;
168 GtkWidget *table = NULL;
169 GtkWidget *alignment = NULL;
170 GtkWidget *vbox1 = NULL;
171 GtkWidget *image1 = NULL;
172 GtkWidget *dialog_action_area1 = NULL;
175 GtkWidget *cancelButton;
177 priv = HILDON_CODE_DIALOG_GET_PRIVATE (dialog);
180 const gchar* numstrs[10] = {
181 "0","1","2","3","4","5","6","7","8","9"
184 GdkPixbuf* pixbuf = NULL;
185 GtkIconTheme* icon_theme = NULL;
186 GtkIconInfo *icon_info = NULL;
189 /* Set default title */
190 gtk_window_set_title (GTK_WINDOW (dialog), DEVICELOCK_TITLE);
192 gtk_window_set_type_hint (GTK_WINDOW (dialog), GDK_WINDOW_TYPE_HINT_DIALOG);
194 hints.min_width = -1;
195 hints.min_height = -1;
196 hints.max_width = -1;
197 hints.max_height = -1;
199 gtk_window_set_geometry_hints (GTK_WINDOW (dialog), GTK_WIDGET (dialog), &hints,
200 GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE);
202 table = gtk_table_new (4, 3, FALSE);
203 gtk_table_set_row_spacings (GTK_TABLE (table), HILDON_MARGIN_DEFAULT );
204 gtk_table_set_col_spacings (GTK_TABLE (table), HILDON_MARGIN_DEFAULT );
206 dialog_vbox1 = GTK_DIALOG (dialog)->vbox;
207 vbox1 = gtk_vbox_new (FALSE, 0);
208 gtk_box_set_spacing (GTK_BOX (vbox1), HILDON_MARGIN_DOUBLE);
210 priv->help_text = gtk_label_new ("");
211 alignment = gtk_alignment_new (0.5,0,1,1);
212 gtk_container_add (GTK_CONTAINER (alignment), priv->help_text);
214 priv->entry = gtk_entry_new ();
216 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->entry), GTK_CAN_FOCUS);
217 gtk_entry_set_invisible_char (GTK_ENTRY (priv->entry), g_utf8_get_char ("*"));
218 gtk_entry_set_alignment (GTK_ENTRY (priv->entry), 1.0);
220 gtk_editable_set_editable (GTK_EDITABLE (priv->entry),FALSE);
221 gtk_entry_set_visibility (GTK_ENTRY (priv->entry), FALSE);
223 gtk_box_pack_start (GTK_BOX (vbox1), alignment, TRUE,FALSE,0);
224 gtk_box_pack_start (GTK_BOX (vbox1), priv->entry, TRUE,FALSE,0);
225 gtk_box_pack_start (GTK_BOX (vbox1), table, FALSE,TRUE,0);
227 gtk_box_pack_start (GTK_BOX (dialog_vbox1), vbox1, FALSE,TRUE,0);
229 for(i = 1;i <= 3; i++) {
230 priv->buttons[0][i-1] = gtk_button_new_with_mnemonic (numstrs[i]);
231 gtk_widget_set_size_request (priv->buttons[0][i-1], WIDTH, HEIGHT);
232 gtk_table_attach_defaults (GTK_TABLE (table), priv->buttons[0][i-1],
236 for(i = 4;i <= 6;i++) {
237 priv->buttons[1][i-4] = gtk_button_new_with_mnemonic (numstrs[i]);
238 gtk_widget_set_size_request (priv->buttons[1][i-4], WIDTH, HEIGHT);
239 gtk_table_attach_defaults (GTK_TABLE (table), priv->buttons[1][i-4],
244 priv->buttons[2][i-7] = gtk_button_new_with_mnemonic (numstrs[i]);
245 gtk_widget_set_size_request (priv->buttons[2][i-7], WIDTH, HEIGHT);
246 gtk_table_attach_defaults (GTK_TABLE (table), priv->buttons[2][i-7],
250 priv->buttons[3][0] = priv->buttons[3][1] =
251 gtk_button_new_with_mnemonic (numstrs[0]);
252 gtk_widget_set_size_request (priv->buttons[3][0], WIDTH, HEIGHT);
253 gtk_table_attach (GTK_TABLE (table), priv->buttons[3][0],
254 0,2,3,4, (GtkAttachOptions) (GTK_FILL),
255 (GtkAttachOptions) (0), 0, 0);
257 priv->buttons[3][2] = gtk_button_new ();
258 gtk_widget_set_size_request (priv->buttons[3][2], WIDTH, HEIGHT);
259 gtk_table_attach_defaults (GTK_TABLE (table), priv->buttons[3][2],
262 icon_theme = gtk_icon_theme_get_default ();
264 icon_info = gtk_icon_theme_lookup_icon (icon_theme, BACKSPACE_ICON, 1,
265 GTK_ICON_LOOKUP_NO_SVG);
266 base_size = gtk_icon_info_get_base_size (icon_info);
267 gtk_icon_info_free (icon_info);
269 pixbuf = gtk_icon_theme_load_icon (icon_theme,
270 BACKSPACE_ICON, base_size,
271 GTK_ICON_LOOKUP_NO_SVG,
274 image1 = gtk_image_new_from_pixbuf (pixbuf);
275 g_object_unref (G_OBJECT(pixbuf));
276 gtk_container_add (GTK_CONTAINER (priv->buttons[3][2]), image1);
277 dialog_action_area1 = GTK_DIALOG (dialog)->action_area;
278 gtk_button_box_set_layout (GTK_BUTTON_BOX (dialog_action_area1),
281 okButton = gtk_dialog_add_button (GTK_DIALOG (dialog) ,DEVICELOCK_OK,
284 gtk_dialog_add_button (GTK_DIALOG (dialog), DEVICELOCK_CANCEL,
285 GTK_RESPONSE_CANCEL);
287 gtk_widget_set_sensitive (okButton, FALSE);
289 priv->buttons[4][0] = priv->buttons[4][1] = okButton;
290 priv->buttons[4][2] = cancelButton;
295 g_signal_connect (G_OBJECT (priv->entry), "insert_text",
296 G_CALLBACK (hildon_code_dialog_insert_text), dialog);
298 gtk_entry_set_max_length (GTK_ENTRY (priv->entry), MAX_PINCODE_LEN);
300 for (x = 0; x < 3; x++)
302 for (y = 0; y < 3; y++)
304 g_signal_connect (G_OBJECT (priv->buttons[x][y]), "clicked",
305 G_CALLBACK (hildon_code_dialog_button_clicked), dialog);
306 g_signal_connect (G_OBJECT (priv->buttons[x][y]), "key-press-event",
307 G_CALLBACK (hildon_code_dialog_key_press_event), dialog);
311 g_signal_connect (G_OBJECT (priv->buttons[3][0]), "clicked",
312 G_CALLBACK (hildon_code_dialog_button_clicked), dialog);
313 g_signal_connect (G_OBJECT (priv->buttons[3][0]), "key-press-event",
314 G_CALLBACK (hildon_code_dialog_key_press_event), dialog);
316 g_signal_connect (G_OBJECT (priv->buttons[3][2]), "clicked",
317 G_CALLBACK (hildon_code_dialog_button_clicked), dialog);
318 g_signal_connect (G_OBJECT (priv->buttons[3][2]), "key-press-event",
319 G_CALLBACK (hildon_code_dialog_key_press_event), dialog);
321 g_signal_connect (G_OBJECT (okButton), "key-press-event",
322 G_CALLBACK(hildon_code_dialog_key_press_event), dialog);
324 g_signal_connect (G_OBJECT (cancelButton), "key-press-event",
325 G_CALLBACK (hildon_code_dialog_key_press_event), dialog);
327 gtk_widget_show_all (GTK_WIDGET (GTK_DIALOG (dialog)->vbox));
331 hildon_code_dialog_button_clicked (GtkButton *button,
334 HildonCodeDialog *dialog = HILDON_CODE_DIALOG (user_data);
335 HildonCodeDialogPrivate *priv = HILDON_CODE_DIALOG_GET_PRIVATE (dialog);
338 const char *number = gtk_button_get_label (button);
340 if (number && *number )
342 gtk_entry_append_text (GTK_ENTRY (priv->entry), number);
347 gchar *text = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->entry)));
357 pos = g_utf8_find_prev_char (text, pos);
364 gtk_entry_set_text (GTK_ENTRY (priv->entry), text);
368 gtk_widget_set_sensitive (priv->buttons[4][0], FALSE);
376 hildon_code_dialog_insert_text (GtkEditable *editable,
378 gint new_text_length,
382 HildonCodeDialog *dialog = HILDON_CODE_DIALOG (user_data);
383 HildonCodeDialogPrivate *priv = HILDON_CODE_DIALOG_GET_PRIVATE (dialog);
384 gchar *text = g_strdup(gtk_entry_get_text (GTK_ENTRY (priv->entry)));
385 glong length = g_utf8_strlen (text, -1);
389 if (length == MAX_PINCODE_LEN)
391 hildon_banner_show_information (GTK_WIDGET (dialog),
393 DEVICELOCK_MAX_CHAR_REACHED);
398 /* make the Ok button sensitive */
399 gtk_widget_set_sensitive (priv->buttons[4][0], TRUE);
402 hildon_code_dialog_input (dialog);
406 hildon_code_dialog_key_press_event (GtkWidget *widget,
410 HildonCodeDialog *dialog = HILDON_CODE_DIALOG (user_data);
411 HildonCodeDialogPrivate *priv = HILDON_CODE_DIALOG_GET_PRIVATE (dialog);
412 GtkWidget *new_widget = widget;
417 for (x = 0; x < 5; x++)
419 for (y = 0; y < 3; y++)
421 if (priv->buttons[x][y] == widget)
429 while (new_widget == widget)
431 switch (event->keyval)
453 new_widget = priv->buttons[x][y];
456 gtk_widget_grab_focus (new_widget);
462 * hildon_code_dialog_new:
464 * Use this function to create a new HildonCodeDialog.
466 * Return value: A @HildonCodeDialog.
469 hildon_code_dialog_new (void)
471 HildonCodeDialog *dialog = g_object_new (HILDON_TYPE_CODE_DIALOG, NULL);
473 return GTK_WIDGET (dialog);
477 * hildon_code_dialog_get_code:
478 * @dialog: The #HildonCodeDialog from which to get the entered code
480 * Use this function to access the code entered by the user.
482 * Return value: The entered code.
485 hildon_code_dialog_get_code (HildonCodeDialog *dialog)
487 g_return_val_if_fail (HILDON_IS_CODE_DIALOG (dialog), NULL);
489 HildonCodeDialogPrivate *priv = HILDON_CODE_DIALOG_GET_PRIVATE (dialog);
492 return gtk_entry_get_text (GTK_ENTRY (priv->entry));
496 * hildon_code_dialog_clear_clode:
497 * @dialog: The #HildonCodeDialog whose entry should be cleared:
499 * Use this function to clear the user entered code.
502 hildon_code_dialog_clear_code (HildonCodeDialog *dialog)
504 g_return_if_fail (HILDON_IS_CODE_DIALOG (dialog));
506 HildonCodeDialogPrivate *priv = HILDON_CODE_DIALOG_GET_PRIVATE (dialog);
509 gtk_entry_set_text (GTK_ENTRY (priv->entry), "");
510 gtk_widget_set_sensitive (priv->buttons[4][0], FALSE);
514 * hildon_code_dialog_set_help_text:
515 * @dialog: The #HildonCodeDialog whose entry should be cleared:
516 * @text: The text to use in the help label.
518 * Use this function to set the text that will be displayd in the
522 hildon_code_dialog_set_help_text (HildonCodeDialog *dialog,
525 g_return_if_fail (HILDON_IS_CODE_DIALOG (dialog));
527 HildonCodeDialogPrivate *priv = HILDON_CODE_DIALOG_GET_PRIVATE (dialog);
530 gtk_label_set_text (GTK_LABEL (priv->help_text), text);
534 hildon_code_dialog_real_input (HildonCodeDialog *dialog)
539 hildon_code_dialog_input (HildonCodeDialog *dialog)
541 /* Emit the signal */
542 g_signal_emit (dialog, input_signal, 0);