3 * The ComboBox widget allows to select one option out of a list.
4 * The ComboBoxEntry additionally allows the user to enter a value
5 * that is not in the list of options.
7 * How the options are displayed is controlled by cell renderers.
19 strip_underscore (const gchar *text)
24 result = g_strdup (text);
41 create_stock_icon_store (void)
43 gchar *stock_id[6] = {
44 GTK_STOCK_DIALOG_WARNING,
60 cellview = gtk_cell_view_new ();
62 store = gtk_list_store_new (2, GDK_TYPE_PIXBUF, G_TYPE_STRING);
64 for (i = 0; i < G_N_ELEMENTS (stock_id); i++)
68 pixbuf = gtk_widget_render_icon (cellview, stock_id[i],
69 GTK_ICON_SIZE_BUTTON, NULL);
70 gtk_stock_lookup (stock_id[i], &item);
71 label = strip_underscore (item.label);
72 gtk_list_store_append (store, &iter);
73 gtk_list_store_set (store, &iter,
77 g_object_unref (pixbuf);
82 gtk_list_store_append (store, &iter);
83 gtk_list_store_set (store, &iter,
85 TEXT_COL, "separator",
90 gtk_widget_destroy (cellview);
92 return GTK_TREE_MODEL (store);
95 /* A GtkCellLayoutDataFunc that demonstrates how one can control
96 * sensitivity of rows. This particular function does nothing
97 * useful and just makes the second row insensitive.
100 set_sensitive (GtkCellLayout *cell_layout,
101 GtkCellRenderer *cell,
102 GtkTreeModel *tree_model,
110 path = gtk_tree_model_get_path (tree_model, iter);
111 indices = gtk_tree_path_get_indices (path);
112 sensitive = indices[0] != 1;
113 gtk_tree_path_free (path);
115 g_object_set (cell, "sensitive", sensitive, NULL);
118 /* A GtkTreeViewRowSeparatorFunc that demonstrates how rows can be
119 * rendered as separators. This particular function does nothing
120 * useful and just turns the fourth row into a separator.
123 is_separator (GtkTreeModel *model,
130 path = gtk_tree_model_get_path (model, iter);
131 result = gtk_tree_path_get_indices (path)[0] == 4;
132 gtk_tree_path_free (path);
137 static GtkTreeModel *
138 create_capital_store (void)
146 { NULL, "Annapolis" },
150 { NULL, "Baton Rouge" },
151 { NULL, "Bismarck" },
155 { NULL, "Carson City" },
156 { NULL, "Charleston" },
157 { NULL, "Cheyenne" },
158 { NULL, "Columbia" },
159 { NULL, "Columbus" },
162 { NULL, "Des Moines" },
165 { NULL, "Frankfort" },
166 { NULL, "Harrisburg" },
167 { NULL, "Hartford" },
169 { NULL, "Honolulu" },
170 { NULL, "Indianapolis" },
172 { NULL, "Jefferson City" },
177 { NULL, "Little Rock" },
179 { NULL, "Montgomery" },
180 { NULL, "Montpelier" },
181 { NULL, "Nashville" },
182 { NULL, "Oklahoma City" },
187 { NULL, "Providence" },
189 { NULL, "Richmond" },
190 { NULL, "Sacramento" },
192 { NULL, "Salt Lake City" },
193 { NULL, "Santa Fe" },
194 { NULL, "Springfield" },
195 { NULL, "St. Paul" },
197 { NULL, "Tallahassee" },
203 GtkTreeIter iter, iter2;
207 store = gtk_tree_store_new (1, G_TYPE_STRING);
209 for (i = 0; capitals[i].group || capitals[i].capital; i++)
211 if (capitals[i].group)
213 gtk_tree_store_append (store, &iter, NULL);
214 gtk_tree_store_set (store, &iter, 0, capitals[i].group, -1);
216 else if (capitals[i].capital)
218 gtk_tree_store_append (store, &iter2, &iter);
219 gtk_tree_store_set (store, &iter2, 0, capitals[i].capital, -1);
223 return GTK_TREE_MODEL (store);
227 is_capital_sensitive (GtkCellLayout *cell_layout,
228 GtkCellRenderer *cell,
229 GtkTreeModel *tree_model,
235 sensitive = !gtk_tree_model_iter_has_child (tree_model, iter);
237 g_object_set (cell, "sensitive", sensitive, NULL);
241 fill_combo_entry (GtkWidget *combo)
243 gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), "One");
244 gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), "Two");
245 gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), "2\302\275");
246 gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), "Three");
250 /* A simple validating entry */
252 #define TYPE_MASK_ENTRY (mask_entry_get_type ())
253 #define MASK_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_MASK_ENTRY, MaskEntry))
254 #define MASK_ENTRY_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST ((vtable), TYPE_MASK_ENTRY, MaskEntryClass))
255 #define IS_MASK_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_MASK_ENTRY))
256 #define IS_MASK_ENTRY_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE ((vtable), TYPE_MASK_ENTRY))
257 #define MASK_ENTRY_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), TYPE_MASK_ENTRY, MaskEntryClass))
260 typedef struct _MaskEntry MaskEntry;
267 typedef struct _MaskEntryClass MaskEntryClass;
268 struct _MaskEntryClass
270 GtkEntryClass parent_class;
274 static void mask_entry_editable_init (GtkEditableInterface *iface);
276 G_DEFINE_TYPE_WITH_CODE (MaskEntry, mask_entry, GTK_TYPE_ENTRY,
277 G_IMPLEMENT_INTERFACE (GTK_TYPE_EDITABLE,
278 mask_entry_editable_init));
282 mask_entry_set_background (MaskEntry *entry)
284 static const GdkColor error_color = { 0, 65535, 60000, 60000 };
288 if (!g_regex_match_simple (entry->mask, gtk_entry_get_text (GTK_ENTRY (entry)), 0, 0))
290 gtk_widget_modify_base (GTK_WIDGET (entry), GTK_STATE_NORMAL, &error_color);
295 gtk_widget_modify_base (GTK_WIDGET (entry), GTK_STATE_NORMAL, NULL);
300 mask_entry_changed (GtkEditable *editable)
302 mask_entry_set_background (MASK_ENTRY (editable));
307 mask_entry_init (MaskEntry *entry)
314 mask_entry_class_init (MaskEntryClass *klass)
319 mask_entry_editable_init (GtkEditableInterface *iface)
321 iface->changed = mask_entry_changed;
326 do_combobox (GtkWidget *do_widget)
328 static GtkWidget *window = NULL;
329 GtkWidget *vbox, *frame, *box, *combo, *entry;
331 GtkCellRenderer *renderer;
337 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
338 gtk_window_set_screen (GTK_WINDOW (window),
339 gtk_widget_get_screen (do_widget));
340 gtk_window_set_title (GTK_WINDOW (window), "Combo boxes");
342 g_signal_connect (window, "destroy",
343 G_CALLBACK (gtk_widget_destroyed),
346 gtk_container_set_border_width (GTK_CONTAINER (window), 10);
348 vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 2);
349 gtk_container_add (GTK_CONTAINER (window), vbox);
351 /* A combobox demonstrating cell renderers, separators and
354 frame = gtk_frame_new ("Some stock icons");
355 gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
357 box = gtk_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 0);
358 gtk_container_set_border_width (GTK_CONTAINER (box), 5);
359 gtk_container_add (GTK_CONTAINER (frame), box);
361 model = create_stock_icon_store ();
362 combo = gtk_combo_box_new_with_model (model);
363 g_object_unref (model);
364 gtk_container_add (GTK_CONTAINER (box), combo);
366 renderer = gtk_cell_renderer_pixbuf_new ();
367 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), renderer, FALSE);
368 gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo), renderer,
369 "pixbuf", PIXBUF_COL,
372 gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (combo),
377 renderer = gtk_cell_renderer_text_new ();
378 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), renderer, TRUE);
379 gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo), renderer,
383 gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (combo),
388 gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (combo),
389 is_separator, NULL, NULL);
391 gtk_combo_box_set_active (GTK_COMBO_BOX (combo), 0);
393 /* A combobox demonstrating trees.
395 frame = gtk_frame_new ("Where are we ?");
396 gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
398 box = gtk_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 0);
399 gtk_container_set_border_width (GTK_CONTAINER (box), 5);
400 gtk_container_add (GTK_CONTAINER (frame), box);
402 model = create_capital_store ();
403 combo = gtk_combo_box_new_with_model (model);
404 g_object_unref (model);
405 gtk_container_add (GTK_CONTAINER (box), combo);
407 renderer = gtk_cell_renderer_text_new ();
408 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), renderer, TRUE);
409 gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo), renderer,
412 gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (combo),
414 is_capital_sensitive,
417 path = gtk_tree_path_new_from_indices (0, 8, -1);
418 gtk_tree_model_get_iter (model, &iter, path);
419 gtk_tree_path_free (path);
420 gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combo), &iter);
422 /* A GtkComboBoxEntry with validation.
424 frame = gtk_frame_new ("Editable");
425 gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
427 box = gtk_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 0);
428 gtk_container_set_border_width (GTK_CONTAINER (box), 5);
429 gtk_container_add (GTK_CONTAINER (frame), box);
431 combo = gtk_combo_box_text_new_with_entry ();
432 fill_combo_entry (combo);
433 gtk_container_add (GTK_CONTAINER (box), combo);
435 entry = g_object_new (TYPE_MASK_ENTRY, NULL);
436 MASK_ENTRY (entry)->mask = "^([0-9]*|One|Two|2\302\275|Three)$";
438 gtk_container_remove (GTK_CONTAINER (combo), gtk_bin_get_child (GTK_BIN (combo)));
439 gtk_container_add (GTK_CONTAINER (combo), entry);
443 if (!gtk_widget_get_visible (window))
445 gtk_widget_show_all (window);
449 gtk_widget_destroy (window);