1 /* GtkCellRendererCombo
2 * Copyright (C) 2004 Lorenzo Gil Sanchez
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
26 #include "gtkcelllayout.h"
27 #include "gtkcellrenderercombo.h"
28 #include "gtkcellrenderertext.h"
29 #include "gtkcombobox.h"
30 #include "gtkcomboboxentry.h"
33 static void gtk_cell_renderer_combo_class_init (GtkCellRendererComboClass *klass);
34 static void gtk_cell_renderer_combo_init (GtkCellRendererCombo *self);
35 static void gtk_cell_renderer_combo_finalize (GObject *object);
36 static void gtk_cell_renderer_combo_get_property (GObject *object,
41 static void gtk_cell_renderer_combo_set_property (GObject *object,
46 static GtkCellEditable *gtk_cell_renderer_combo_start_editing (GtkCellRenderer *cell,
50 GdkRectangle *background_area,
51 GdkRectangle *cell_area,
52 GtkCellRendererState flags);
61 #define GTK_CELL_RENDERER_COMBO_PATH "gtk-cell-renderer-combo-path"
63 G_DEFINE_TYPE (GtkCellRendererCombo, gtk_cell_renderer_combo, GTK_TYPE_CELL_RENDERER_TEXT);
66 gtk_cell_renderer_combo_class_init (GtkCellRendererComboClass *klass)
68 GObjectClass *object_class = G_OBJECT_CLASS (klass);
69 GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (klass);
71 object_class->finalize = gtk_cell_renderer_combo_finalize;
72 object_class->get_property = gtk_cell_renderer_combo_get_property;
73 object_class->set_property = gtk_cell_renderer_combo_set_property;
75 cell_class->start_editing = gtk_cell_renderer_combo_start_editing;
78 * GtkCellRendererCombo:model:
80 * Holds a tree model containing the possible values for the combo box.
81 * Use the text_column property to specify the column holding the values.
85 g_object_class_install_property (object_class,
87 g_param_spec_object ("model",
89 P_("The model containing the possible values for the combo box"),
94 * GtkCellRendererCombo:text-column:
96 * Specifies the model column which holds the possible values for the combo box.
97 * Note that this refers to the model specified in the model property,
98 * <emphasis>not</emphasis> the model backing the tree view to which this cell
99 * renderer is attached.
101 * #GtkCellRendererCombo automatically adds a text cell renderer for this column
106 g_object_class_install_property (object_class,
108 g_param_spec_int ("text-column",
110 P_("A column in the data source model to get the strings from"),
117 * GtkCellRendererCombo:has-entry:
119 * If %TRUE, the cell renderer will include an entry and allow to enter values
120 * other than the ones in the popup list.
124 g_object_class_install_property (object_class,
126 g_param_spec_boolean ("has-entry",
128 P_("If FALSE, don't allow to enter strings other than the chosen ones"),
135 gtk_cell_renderer_combo_init (GtkCellRendererCombo *self)
138 self->text_column = -1;
139 self->has_entry = TRUE;
140 self->focus_out_id = 0;
144 * gtk_cell_renderer_combo_new:
146 * Creates a new #GtkCellRendererCombo.
147 * Adjust how text is drawn using object properties.
148 * Object properties can be set globally (with g_object_set()).
149 * Also, with #GtkTreeViewColumn, you can bind a property to a value
150 * in a #GtkTreeModel. For example, you can bind the "text" property
151 * on the cell renderer to a string value in the model, thus rendering
152 * a different string in each row of the #GtkTreeView.
154 * Returns: the new cell renderer
159 gtk_cell_renderer_combo_new (void)
161 return g_object_new (GTK_TYPE_CELL_RENDERER_COMBO, NULL);
165 gtk_cell_renderer_combo_finalize (GObject *object)
167 GtkCellRendererCombo *cell = GTK_CELL_RENDERER_COMBO (object);
171 g_object_unref (cell->model);
175 G_OBJECT_CLASS (gtk_cell_renderer_combo_parent_class)->finalize (object);
179 gtk_cell_renderer_combo_get_property (GObject *object,
184 GtkCellRendererCombo *cell;
186 g_return_if_fail (GTK_IS_CELL_RENDERER_COMBO (object));
188 cell = GTK_CELL_RENDERER_COMBO (object);
193 g_value_set_object (value, cell->model);
195 case PROP_TEXT_COLUMN:
196 g_value_set_int (value, cell->text_column);
199 g_value_set_boolean (value, cell->has_entry);
202 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
207 gtk_cell_renderer_combo_set_property (GObject *object,
212 GtkCellRendererCombo *cell;
214 g_return_if_fail (GTK_IS_CELL_RENDERER_COMBO (object));
216 cell = GTK_CELL_RENDERER_COMBO (object);
224 object = g_value_get_object (value);
225 g_return_if_fail (GTK_IS_TREE_MODEL (object));
226 g_object_ref (object);
230 g_object_unref (cell->model);
233 cell->model = GTK_TREE_MODEL (object);
236 case PROP_TEXT_COLUMN:
237 cell->text_column = g_value_get_int (value);
240 cell->has_entry = g_value_get_boolean (value);
243 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
248 gtk_cell_renderer_combo_editing_done (GtkCellEditable *combo,
252 gchar *new_text = NULL;
255 GtkCellRendererCombo *cell;
259 cell = GTK_CELL_RENDERER_COMBO (data);
261 if (cell->focus_out_id > 0)
263 g_signal_handler_disconnect (combo, cell->focus_out_id);
264 cell->focus_out_id = 0;
267 canceled = _gtk_combo_box_editing_canceled (GTK_COMBO_BOX (combo));
268 gtk_cell_renderer_stop_editing (GTK_CELL_RENDERER (data), canceled);
272 if (GTK_IS_COMBO_BOX_ENTRY (combo))
274 entry = GTK_ENTRY (gtk_bin_get_child (GTK_BIN (combo)));
275 new_text = g_strdup (gtk_entry_get_text (entry));
279 model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo));
280 if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combo), &iter))
281 gtk_tree_model_get (model, &iter, cell->text_column, &new_text, -1);
284 path = g_object_get_data (G_OBJECT (combo), GTK_CELL_RENDERER_COMBO_PATH);
285 g_signal_emit_by_name (cell, "edited", path, new_text);
291 gtk_cell_renderer_combo_focus_out_event (GtkWidget *widget,
296 gtk_cell_renderer_combo_editing_done (GTK_CELL_EDITABLE (widget), data);
303 GtkCellRendererCombo *cell;
309 find_text (GtkTreeModel *model,
314 SearchData *search_data = (SearchData *)data;
317 gtk_tree_model_get (model, iter, search_data->cell->text_column, &text, -1);
318 if (text && GTK_CELL_RENDERER_TEXT (search_data->cell)->text &&
319 strcmp (text, GTK_CELL_RENDERER_TEXT (search_data->cell)->text) == 0)
321 search_data->iter = *iter;
322 search_data->found = TRUE;
327 return search_data->found;
330 static GtkCellEditable *
331 gtk_cell_renderer_combo_start_editing (GtkCellRenderer *cell,
335 GdkRectangle *background_area,
336 GdkRectangle *cell_area,
337 GtkCellRendererState flags)
339 GtkCellRendererCombo *cell_combo;
340 GtkCellRendererText *cell_text;
342 SearchData search_data;
344 cell_text = GTK_CELL_RENDERER_TEXT (cell);
345 if (cell_text->editable == FALSE)
348 cell_combo = GTK_CELL_RENDERER_COMBO (cell);
349 if (cell_combo->model == NULL || cell_combo->text_column < 0)
352 if (cell_combo->has_entry)
354 combo = gtk_combo_box_entry_new_with_model (cell_combo->model, cell_combo->text_column);
357 gtk_entry_set_text (GTK_ENTRY (GTK_BIN (combo)->child),
362 cell = gtk_cell_renderer_text_new ();
363 combo = gtk_combo_box_new_with_model (cell_combo->model);
364 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), cell, TRUE);
365 gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo),
366 cell, "text", cell_combo->text_column,
369 /* determine the current value */
370 search_data.cell = cell_combo;
371 search_data.found = FALSE;
372 gtk_tree_model_foreach (cell_combo->model, find_text, &search_data);
373 if (search_data.found)
374 gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combo),
375 &(search_data.iter));
378 g_object_set (combo, "has_frame", FALSE, NULL);
379 g_object_set_data_full (G_OBJECT (combo),
380 GTK_CELL_RENDERER_COMBO_PATH,
381 g_strdup (path), g_free);
383 gtk_widget_show (combo);
385 g_signal_connect (GTK_CELL_EDITABLE (combo), "editing_done",
386 G_CALLBACK (gtk_cell_renderer_combo_editing_done),
388 cell_combo->focus_out_id =
389 g_signal_connect (combo, "focus_out_event",
390 G_CALLBACK (gtk_cell_renderer_combo_focus_out_event),
393 return GTK_CELL_EDITABLE (combo);
396 #define __GTK_CELL_RENDERER_COMBO_C__
397 #include "gtkaliasdef.c"