libyui-gtk  2.44.9
ygtkfieldentry.c
1 /********************************************************************
2  * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
3  ********************************************************************/
4 
5 /* YGtkFieldEntry widget */
6 // check the header file for information about this widget
7 
8 #include <yui/Libyui_config.h>
9 #include "ygtkfieldentry.h"
10 #include <gtk/gtk.h>
11 #include <string.h>
12 
13 void ygutils_setFilter (GtkEntry *entry, const char *validChars);
14 static guint filter_entry_signal = 0;
15 
16 //** YGtkFieldEntry
17 
18 G_DEFINE_TYPE (YGtkFieldEntry, ygtk_field_entry, GTK_TYPE_BOX)
19 
20 static void ygtk_field_entry_init (YGtkFieldEntry *entry)
21 {
22  gtk_box_set_spacing (GTK_BOX (entry), 4);
23 }
24 
25 static GtkEntry *ygtk_field_entry_focus_next_entry (YGtkFieldEntry *fields,
26  GtkEntry *current_entry,
27  gint side)
28 {
29  GList *children = gtk_container_get_children (GTK_CONTAINER (fields));
30  gint pos = g_list_index (children, current_entry);
31 
32  GtkEntry *next_entry = g_list_nth_data (children, pos + (2 * side));
33  g_list_free (children);
34 
35  if (next_entry)
36  gtk_widget_grab_focus (GTK_WIDGET (next_entry));
37  return next_entry;
38 }
39 
40 // If max characters reached, jump to next field
41 static void ygtk_field_entry_insert_text (GtkEditable *editable, const gchar *new_text,
42  gint new_text_length, gint *position, YGtkFieldEntry *fields)
43 {
44  if (*position == gtk_entry_get_max_length (GTK_ENTRY (editable))) {
45  GtkEntry *next_entry = ygtk_field_entry_focus_next_entry (fields,
46  GTK_ENTRY (editable), 1);
47  if (next_entry) {
48  gint pos = 0;
49  gtk_editable_insert_text (GTK_EDITABLE (next_entry), new_text,
50  new_text_length, &pos);
51  gtk_editable_set_position (GTK_EDITABLE (next_entry), pos);
52 
53  // it would not insert the text anyway, but to avoid the beep
54  g_signal_stop_emission_by_name (editable, "insert_text");
55  }
56  }
57 }
58 
59 static void ygtk_field_entry_move_cursor (GtkEntry *entry, GtkMovementStep move,
60  gint count, gboolean selection, YGtkFieldEntry *fields)
61 {
62  if (move == GTK_MOVEMENT_VISUAL_POSITIONS) {
63  if (count > 0)
64  ygtk_field_entry_focus_next_entry (fields, GTK_ENTRY (entry), 1);
65  else
66  ygtk_field_entry_focus_next_entry (fields, GTK_ENTRY (entry), -1);
67  }
68 }
69 
70 
71 GtkWidget *ygtk_field_entry_new (void)
72 { return g_object_new (YGTK_TYPE_FIELD_ENTRY, NULL); }
73 
74 static void ygtk_field_entry_entry_changed (GtkEditable *editable, YGtkFieldEntry *fields)
75 {
76  GList *children = gtk_container_get_children (GTK_CONTAINER (fields));
77  gint nb = g_list_index (children, editable) / 2;
78  g_list_free (children);
79 
80  g_signal_emit (fields, filter_entry_signal, 0, nb);
81 }
82 
83 static guint ygtk_field_entry_length (YGtkFieldEntry *fields)
84 {
85  guint length;
86  GList *children = gtk_container_get_children (GTK_CONTAINER (fields));
87  length = g_list_length (children);
88  g_list_free (children);
89  return length;
90 }
91 
92 static inline guint child_to_index (YGtkFieldEntry *fields, guint child_i)
93 { return child_i / 2; }
94 static inline guint index_to_child (YGtkFieldEntry *fields, guint index)
95 { return index * 2; }
96 
97 GtkEntry *ygtk_field_entry_get_field_widget (YGtkFieldEntry *fields, guint index)
98 {
99  GtkEntry *entry;
100  GList *children = gtk_container_get_children (GTK_CONTAINER (fields));
101  entry = g_list_nth_data (children, index_to_child (fields, index));
102  g_list_free (children);
103  g_assert (GTK_IS_ENTRY (entry));
104  return entry;
105 }
106 guint ygtk_field_entry_add_field (YGtkFieldEntry *fields, gchar separator)
107 {
108  guint new_index = child_to_index (fields, ygtk_field_entry_length (fields)+1);
109 
110  GtkWidget *label = 0, *entry;
111  if (new_index > 0) {
112  const gchar str[2] = { separator, '\0' };
113  label = gtk_label_new (str);
114  }
115  entry = gtk_entry_new();
116  g_signal_connect (G_OBJECT (entry), "insert-text",
117  G_CALLBACK (ygtk_field_entry_insert_text), fields);
118  g_signal_connect (G_OBJECT (entry), "move-cursor",
119  G_CALLBACK (ygtk_field_entry_move_cursor), fields);
120 
121  g_signal_connect (G_OBJECT (entry), "changed",
122  G_CALLBACK (ygtk_field_entry_entry_changed), fields);
123 
124  GtkBox *box = GTK_BOX (fields);
125  if (label) {
126  gtk_box_pack_start (box, label, FALSE, TRUE, 0);
127  gtk_widget_show (label);
128  }
129  gtk_box_pack_start (box, entry, TRUE, TRUE, 0);
130  gtk_widget_show (entry);
131  return new_index;
132 }
133 
134 void ygtk_field_entry_setup_field (YGtkFieldEntry *fields, guint index,
135  gint max_length, const gchar *valid_chars)
136 {
137  GtkEntry *entry = ygtk_field_entry_get_field_widget (fields, index);
138  gboolean disable_len = (max_length <= 0);
139  gtk_entry_set_max_length (entry, disable_len ? 0 : max_length);
140  gtk_entry_set_width_chars (entry, disable_len ? -1 : max_length);
141  gtk_box_set_child_packing (GTK_BOX (fields), GTK_WIDGET (entry),
142  disable_len, TRUE, 0, GTK_PACK_START);
143  ygutils_setFilter (entry, valid_chars);
144 }
145 
146 void ygtk_field_entry_set_field_text (YGtkFieldEntry *fields, guint index, const gchar *text)
147 {
148  GtkEntry *entry = ygtk_field_entry_get_field_widget (fields, index);
149 
150  g_signal_handlers_block_by_func (entry,
151  (gpointer) ygtk_field_entry_entry_changed, fields);
152  g_signal_handlers_block_by_func (entry,
153  (gpointer) ygtk_field_entry_insert_text, fields);
154 
155  gtk_entry_set_text (entry, text);
156 
157  g_signal_handlers_unblock_by_func (entry,
158  (gpointer) ygtk_field_entry_entry_changed, fields);
159  g_signal_handlers_unblock_by_func (entry,
160  (gpointer) ygtk_field_entry_insert_text, fields);
161 }
162 
163 const gchar *ygtk_field_entry_get_field_text (YGtkFieldEntry *fields, guint index)
164 {
165  GtkEntry *entry = ygtk_field_entry_get_field_widget (fields, index);
166  return gtk_entry_get_text (entry);
167 }
168 
169 static gboolean ygtk_field_entry_mnemonic_activate (GtkWidget *widget, gboolean cycling)
170 {
171  YGtkFieldEntry *fields = YGTK_FIELD_ENTRY (widget);
172  GtkEntry *entry = ygtk_field_entry_get_field_widget (fields, 0);
173  gtk_widget_grab_focus (GTK_WIDGET (entry));
174  return TRUE;
175 }
176 
177 static void ygtk_field_entry_class_init (YGtkFieldEntryClass *klass)
178 {
179  ygtk_field_entry_parent_class = g_type_class_peek_parent (klass);
180 
181  GtkWidgetClass* widget_class = GTK_WIDGET_CLASS (klass);
182  widget_class->mnemonic_activate = ygtk_field_entry_mnemonic_activate;
183 
184  filter_entry_signal = g_signal_new ("field_entry_changed",
185  G_OBJECT_CLASS_TYPE (klass), G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
186  G_STRUCT_OFFSET (YGtkFieldEntryClass, filter_entry_changed),
187  NULL, NULL, g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
188 }
189 
190 gboolean ygtk_field_entry_set_focus (YGtkFieldEntry *fields)
191 {
192  GList *children = gtk_container_get_children (GTK_CONTAINER (fields));
193  g_return_val_if_fail (children != NULL, FALSE);
194  GtkWidget *widget = GTK_WIDGET (children->data);
195  g_list_free (children);
196 
197  gtk_editable_select_region (GTK_EDITABLE (widget), 0, -1);
198  gtk_widget_grab_focus (widget);
199  return gtk_widget_is_focus (widget);
200 }
201 
_YGtkFieldEntryClass
Definition: ygtkfieldentry.h:35
_YGtkFieldEntry
Definition: ygtkfieldentry.h:30