* Boston, MA 02111-1307, USA.
*/
-#include <config.h>
+#include "config.h"
#include "gtkcombobox.h"
#include "gtkarrow.h"
gint wrap_width;
GtkShadowType shadow_type;
+ gint active; /* Only temporary */
GtkTreeRowReference *active_row;
GtkWidget *tree_view;
guint editing_canceled : 1;
guint auto_scroll : 1;
guint focus_on_click : 1;
+ guint button_sensitivity : 2;
GtkTreeViewRowSeparatorFunc row_separator_func;
gpointer row_separator_data;
PROP_TEAROFF_TITLE,
PROP_HAS_FRAME,
PROP_FOCUS_ON_CLICK,
- PROP_POPUP_SHOWN
+ PROP_POPUP_SHOWN,
+ PROP_BUTTON_SENSITIVITY,
+ PROP_EDITING_CANCELED
};
static guint combo_box_signals[LAST_SIGNAL] = {0,};
gpointer user_data);
static void gtk_combo_box_menu_item_activate (GtkWidget *item,
gpointer user_data);
+
+static void gtk_combo_box_update_sensitivity (GtkComboBox *combo_box);
static void gtk_combo_box_menu_row_inserted (GtkTreeModel *model,
GtkTreePath *path,
GtkTreeIter *iter,
* Since: 2.12
*/
combo_box_signals[MOVE_ACTIVE] =
- _gtk_binding_signal_new (I_("move-active"),
- G_OBJECT_CLASS_TYPE (klass),
- G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
- G_CALLBACK (gtk_combo_box_real_move_active),
- NULL, NULL,
- g_cclosure_marshal_VOID__ENUM,
- G_TYPE_NONE, 1,
- GTK_TYPE_SCROLL_TYPE);
+ g_signal_new_class_handler (I_("move-active"),
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_CALLBACK (gtk_combo_box_real_move_active),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__ENUM,
+ G_TYPE_NONE, 1,
+ GTK_TYPE_SCROLL_TYPE);
/**
* GtkComboBox::popup:
* Since: 2.12
*/
combo_box_signals[POPUP] =
- _gtk_binding_signal_new (I_("popup"),
- G_OBJECT_CLASS_TYPE (klass),
- G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
- G_CALLBACK (gtk_combo_box_real_popup),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
+ g_signal_new_class_handler (I_("popup"),
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_CALLBACK (gtk_combo_box_real_popup),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
/**
* GtkComboBox::popdown:
* @button: the object which received the signal
* Since: 2.12
*/
combo_box_signals[POPDOWN] =
- _gtk_binding_signal_new (I_("popdown"),
- G_OBJECT_CLASS_TYPE (klass),
- G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
- G_CALLBACK (gtk_combo_box_real_popdown),
- NULL, NULL,
- _gtk_marshal_BOOLEAN__VOID,
- G_TYPE_BOOLEAN, 0);
+ g_signal_new_class_handler (I_("popdown"),
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_CALLBACK (gtk_combo_box_real_popdown),
+ NULL, NULL,
+ _gtk_marshal_BOOLEAN__VOID,
+ G_TYPE_BOOLEAN, 0);
/* key bindings */
binding_set = gtk_binding_set_by_class (widget_class);
GTK_TYPE_SCROLL_TYPE, GTK_SCROLL_END);
/* properties */
+ g_object_class_override_property (object_class,
+ PROP_EDITING_CANCELED,
+ "editing-canceled");
+
/**
* GtkComboBox:model:
*
FALSE,
GTK_PARAM_READABLE));
+
+ /**
+ * GtkComboBox:button-sensitivity:
+ *
+ * Whether the dropdown button is sensitive when
+ * the model is empty.
+ *
+ * Since: 2.14
+ */
+ g_object_class_install_property (object_class,
+ PROP_BUTTON_SENSITIVITY,
+ g_param_spec_enum ("button-sensitivity",
+ P_("Button Sensitivity"),
+ P_("Whether the dropdown button is sensitive when the model is empty"),
+ GTK_TYPE_SENSITIVITY_TYPE,
+ GTK_SENSITIVITY_AUTO,
+ GTK_PARAM_READWRITE));
+
gtk_widget_class_install_style_property (widget_class,
g_param_spec_boolean ("appears-as-list",
P_("Appears as list"),
priv->height = 0;
priv->wrap_width = 0;
+ priv->active = -1;
priv->active_row = NULL;
priv->col_column = -1;
priv->row_column = -1;
priv->editing_canceled = FALSE;
priv->auto_scroll = FALSE;
priv->focus_on_click = TRUE;
+ priv->button_sensitivity = GTK_SENSITIVITY_AUTO;
combo_box->priv = priv;
switch (prop_id)
{
- case PROP_MODEL:
- gtk_combo_box_set_model (combo_box, g_value_get_object (value));
- break;
+ case PROP_MODEL:
+ gtk_combo_box_set_model (combo_box, g_value_get_object (value));
+ break;
- case PROP_WRAP_WIDTH:
- gtk_combo_box_set_wrap_width (combo_box, g_value_get_int (value));
- break;
+ case PROP_WRAP_WIDTH:
+ gtk_combo_box_set_wrap_width (combo_box, g_value_get_int (value));
+ break;
- case PROP_ROW_SPAN_COLUMN:
- gtk_combo_box_set_row_span_column (combo_box, g_value_get_int (value));
- break;
+ case PROP_ROW_SPAN_COLUMN:
+ gtk_combo_box_set_row_span_column (combo_box, g_value_get_int (value));
+ break;
- case PROP_COLUMN_SPAN_COLUMN:
- gtk_combo_box_set_column_span_column (combo_box, g_value_get_int (value));
- break;
+ case PROP_COLUMN_SPAN_COLUMN:
+ gtk_combo_box_set_column_span_column (combo_box, g_value_get_int (value));
+ break;
- case PROP_ACTIVE:
- gtk_combo_box_set_active (combo_box, g_value_get_int (value));
- break;
+ case PROP_ACTIVE:
+ gtk_combo_box_set_active (combo_box, g_value_get_int (value));
+ break;
- case PROP_ADD_TEAROFFS:
- gtk_combo_box_set_add_tearoffs (combo_box, g_value_get_boolean (value));
- break;
+ case PROP_ADD_TEAROFFS:
+ gtk_combo_box_set_add_tearoffs (combo_box, g_value_get_boolean (value));
+ break;
- case PROP_HAS_FRAME:
- combo_box->priv->has_frame = g_value_get_boolean (value);
- break;
+ case PROP_HAS_FRAME:
+ combo_box->priv->has_frame = g_value_get_boolean (value);
+ break;
- case PROP_FOCUS_ON_CLICK:
- gtk_combo_box_set_focus_on_click (combo_box,
- g_value_get_boolean (value));
- break;
+ case PROP_FOCUS_ON_CLICK:
+ gtk_combo_box_set_focus_on_click (combo_box,
+ g_value_get_boolean (value));
+ break;
- case PROP_TEAROFF_TITLE:
- gtk_combo_box_set_title (combo_box, g_value_get_string (value));
- break;
+ case PROP_TEAROFF_TITLE:
+ gtk_combo_box_set_title (combo_box, g_value_get_string (value));
+ break;
- case PROP_POPUP_SHOWN:
- if (g_value_get_boolean (value))
- gtk_combo_box_popup (combo_box);
- else
- gtk_combo_box_popdown (combo_box);
- break;
+ case PROP_POPUP_SHOWN:
+ if (g_value_get_boolean (value))
+ gtk_combo_box_popup (combo_box);
+ else
+ gtk_combo_box_popdown (combo_box);
+ break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
+ case PROP_BUTTON_SENSITIVITY:
+ gtk_combo_box_set_button_sensitivity (combo_box,
+ g_value_get_enum (value));
+ break;
+
+ case PROP_EDITING_CANCELED:
+ combo_box->priv->editing_canceled = g_value_get_boolean (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
}
}
GParamSpec *pspec)
{
GtkComboBox *combo_box = GTK_COMBO_BOX (object);
+ GtkComboBoxPrivate *priv = GTK_COMBO_BOX_GET_PRIVATE (combo_box);
switch (prop_id)
{
g_value_set_boolean (value, combo_box->priv->popup_shown);
break;
+ case PROP_BUTTON_SENSITIVITY:
+ g_value_set_enum (value, combo_box->priv->button_sensitivity);
+ break;
+
+ case PROP_EDITING_CANCELED:
+ g_value_set_boolean (value, priv->editing_canceled);
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
{
if ((GTK_WIDGET_STATE (widget) == GTK_STATE_INSENSITIVE) !=
(GTK_WIDGET_STATE (priv->cell_view) == GTK_STATE_INSENSITIVE))
- gtk_widget_set_sensitive (priv->cell_view, GTK_WIDGET_SENSITIVE (widget));
+ gtk_widget_set_sensitive (priv->cell_view, gtk_widget_get_sensitive (widget));
gtk_widget_set_state (priv->cell_view,
GTK_WIDGET_STATE (widget));
/* FIXME: is using the size request here broken? */
child = GTK_BIN (combo_box)->child;
-
- gdk_window_get_origin (child->window, &sx, &sy);
-
- if (GTK_WIDGET_NO_WINDOW (child))
+
+ sx = sy = 0;
+
+ if (!gtk_widget_get_has_window (child))
{
sx += child->allocation.x;
sy += child->allocation.y;
}
+ gdk_window_get_root_coords (child->window, sx, sy, &sx, &sy);
+
if (GTK_SHADOW_NONE != combo_box->priv->shadow_type)
sx -= GTK_WIDGET (combo_box)->style->xthickness;
menu_width = requisition.width;
active = gtk_menu_get_active (GTK_MENU (combo_box->priv->popup_widget));
- gdk_window_get_origin (widget->window, &menu_xpos, &menu_ypos);
- menu_xpos += widget->allocation.x;
- menu_ypos += widget->allocation.y + widget->allocation.height / 2 - 2;
+ menu_xpos = widget->allocation.x;
+ menu_ypos = widget->allocation.y + widget->allocation.height / 2 - 2;
if (active != NULL)
{
if (active == child)
break;
- if (GTK_WIDGET_VISIBLE (child))
+ if (gtk_widget_get_visible (child))
{
gtk_widget_get_child_requisition (child, &requisition);
menu_ypos -= requisition.height;
if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
menu_xpos = menu_xpos + widget->allocation.width - menu_width;
+ gdk_window_get_root_coords (widget->window, menu_xpos, menu_ypos,
+ &menu_xpos, &menu_ypos);
+
/* Clamp the position on screen */
screen_width = gdk_screen_get_width (gtk_widget_get_screen (widget));
gtk_combo_box_menu_position_over (menu, x, y, push_in, user_data);
}
- gtk_window_set_type_hint (GTK_WINDOW (GTK_MENU (priv->popup_widget)->toplevel),
- GDK_WINDOW_TYPE_HINT_COMBO);
+ if (!gtk_widget_get_visible (GTK_MENU (priv->popup_widget)->toplevel))
+ gtk_window_set_type_hint (GTK_WINDOW (GTK_MENU (priv->popup_widget)->toplevel),
+ GDK_WINDOW_TYPE_HINT_COMBO);
}
static void
see bug #340204 */
GtkWidget *sample = GTK_WIDGET (combo_box);
- gdk_window_get_origin (sample->window, x, y);
+ *x = *y = 0;
- if (GTK_WIDGET_NO_WINDOW (sample))
+ if (!gtk_widget_get_has_window (sample))
{
*x += sample->allocation.x;
*y += sample->allocation.y;
}
+ gdk_window_get_root_coords (sample->window, *x, *y, x, y);
+
*width = sample->allocation.width;
hpolicy = vpolicy = GTK_POLICY_NEVER;
GList *cells, *list;
gboolean sensitive;
- cells = gtk_cell_view_get_cell_renderers (cell_view);
+ cells = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (cell_view));
sensitive = FALSE;
for (list = cells; list; list = list->next)
if (priv->row_separator_func)
{
- if ((*priv->row_separator_func) (priv->model, iter,
- priv->row_separator_data))
+ if (priv->row_separator_func (priv->model, iter,
+ priv->row_separator_data))
return FALSE;
}
priv->model,
iter, FALSE, FALSE);
- cells = gtk_tree_view_column_get_cell_renderers (priv->column);
+ cells = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (priv->column));
sensitive = FALSE;
for (list = cells; list; list = list->next)
if (!GTK_WIDGET_REALIZED (combo_box))
return;
- if (GTK_WIDGET_MAPPED (priv->popup_widget))
+ if (gtk_widget_get_mapped (priv->popup_widget))
return;
if (GTK_IS_MENU (priv->popup_widget))
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->button),
TRUE);
- if (!GTK_WIDGET_HAS_FOCUS (priv->tree_view))
+ if (!gtk_widget_has_focus (priv->tree_view))
gtk_widget_grab_focus (priv->tree_view);
if (!popup_grab_on_window (priv->popup_window->window,
child.width -= child.x;
}
+ if (gtk_widget_get_visible (priv->popup_widget))
+ {
+ gint width;
+ GtkRequisition requisition;
+
+ /* Warning here, without the check in the position func */
+ gtk_menu_reposition (GTK_MENU (priv->popup_widget));
+ if (priv->wrap_width == 0)
+ {
+ width = GTK_WIDGET (combo_box)->allocation.width;
+ gtk_widget_set_size_request (priv->popup_widget, -1, -1);
+ gtk_widget_size_request (priv->popup_widget, &requisition);
+ gtk_widget_set_size_request (priv->popup_widget,
+ MAX (width, requisition.width), -1);
+ }
+ }
+
child.width = MAX (1, child.width);
child.height = MAX (1, child.height);
gtk_widget_size_allocate (GTK_BIN (widget)->child, &child);
child.width -= delta_x * 2;
child.height -= delta_y * 2;
}
+
+ if (gtk_widget_get_visible (priv->popup_window))
+ {
+ gint x, y, width, height;
+ gtk_combo_box_list_position (combo_box, &x, &y, &width, &height);
+ gtk_window_move (GTK_WINDOW (priv->popup_window), x, y);
+ gtk_widget_set_size_request (priv->popup_window, width, height);
+ }
+
child.width = MAX (1, child.width);
child.height = MAX (1, child.height);
GtkComboBox *combo_box = GTK_COMBO_BOX (widget);
GtkComboBoxPrivate *priv = combo_box->priv;
- if (GTK_WIDGET_DRAWABLE (widget) &&
+ if (gtk_widget_is_drawable (widget) &&
GTK_SHADOW_NONE != priv->shadow_type)
{
gtk_paint_shadow (widget->style, widget->window,
gtk_widget_show_all (priv->button);
}
- g_signal_connect (priv->button, "button_press_event",
+ g_signal_connect (priv->button, "button-press-event",
G_CALLBACK (gtk_combo_box_menu_button_press),
combo_box);
- g_signal_connect (priv->button, "state_changed",
+ g_signal_connect (priv->button, "state-changed",
G_CALLBACK (gtk_combo_box_button_state_changed),
combo_box);
/* create our funky menu */
menu = gtk_menu_new ();
gtk_widget_set_name (menu, "gtk-combobox-popup-menu");
+ gtk_menu_set_reserve_toggle_size (GTK_MENU (menu), FALSE);
- g_signal_connect (menu, "key_press_event",
+ g_signal_connect (menu, "key-press-event",
G_CALLBACK (gtk_combo_box_menu_key_press), combo_box);
gtk_combo_box_set_popup_widget (combo_box, menu);
gtk_combo_box_sync_cells (combo_box, GTK_CELL_LAYOUT (priv->column));
gtk_combo_box_update_title (combo_box);
+ gtk_combo_box_update_sensitivity (combo_box);
}
static void
gtk_tree_model_iter_nth_child (model, &iter, parent, i);
if (priv->row_separator_func)
- is_separator = (*priv->row_separator_func) (priv->model, &iter,
- priv->row_separator_data);
+ is_separator = priv->row_separator_func (priv->model, &iter,
+ priv->row_separator_data);
else
is_separator = FALSE;
if (gtk_tree_model_iter_has_child (model, &iter))
{
submenu = gtk_menu_new ();
+ gtk_menu_set_reserve_toggle_size (GTK_MENU (submenu), FALSE);
gtk_widget_show (submenu);
gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), submenu);
event->type == GDK_BUTTON_PRESS && event->button == 1)
{
if (priv->focus_on_click &&
- !GTK_WIDGET_HAS_FOCUS (priv->button))
+ !gtk_widget_has_focus (priv->button))
gtk_widget_grab_focus (priv->button);
gtk_combo_box_menu_popup (combo_box, event->button, event->time);
gtk_tree_path_free (path);
- combo_box->priv->editing_canceled = FALSE;
+ g_object_set (combo_box,
+ "editing-canceled", FALSE,
+ NULL);
+}
+
+static void
+gtk_combo_box_update_sensitivity (GtkComboBox *combo_box)
+{
+ GtkTreeIter iter;
+ gboolean sensitive = TRUE; /* fool code checkers */
+
+ if (!combo_box->priv->button)
+ return;
+
+ switch (combo_box->priv->button_sensitivity)
+ {
+ case GTK_SENSITIVITY_ON:
+ sensitive = TRUE;
+ break;
+ case GTK_SENSITIVITY_OFF:
+ sensitive = FALSE;
+ break;
+ case GTK_SENSITIVITY_AUTO:
+ sensitive = combo_box->priv->model &&
+ gtk_tree_model_get_iter_first (combo_box->priv->model, &iter);
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ gtk_widget_set_sensitive (combo_box->priv->button, sensitive);
+
+ /* In list-mode, we also need to update sensitivity of the event box */
+ if (GTK_IS_TREE_VIEW (combo_box->priv->tree_view)
+ && combo_box->priv->cell_view)
+ gtk_widget_set_sensitive (combo_box->priv->box, sensitive);
}
static void
gtk_combo_box_list_popup_resize (combo_box);
else
gtk_combo_box_menu_row_inserted (model, path, iter, user_data);
+
+ gtk_combo_box_update_sensitivity (combo_box);
}
static void
gtk_combo_box_list_popup_resize (combo_box);
else
gtk_combo_box_menu_row_deleted (model, path, user_data);
+
+ gtk_combo_box_update_sensitivity (combo_box);
}
static void
GtkComboBoxPrivate *priv = combo_box->priv;
gint x, y, width, height;
- if (priv->tree_view && GTK_WIDGET_MAPPED (priv->popup_window))
+ if (priv->tree_view && gtk_widget_get_mapped (priv->popup_window))
{
gtk_combo_box_list_position (combo_box, &x, &y, &width, &height);
if (!menu)
{
menu = gtk_menu_new ();
+ gtk_menu_set_reserve_toggle_size (GTK_MENU (menu), FALSE);
gtk_widget_show (menu);
gtk_menu_item_set_submenu (GTK_MENU_ITEM (parent), menu);
}
if (priv->row_separator_func)
- is_separator = (*priv->row_separator_func) (model, iter,
- priv->row_separator_data);
+ is_separator = priv->row_separator_func (model, iter,
+ priv->row_separator_data);
else
is_separator = FALSE;
item = find_menu_by_path (priv->popup_widget, path, FALSE);
if (priv->row_separator_func)
- is_separator = (*priv->row_separator_func) (model, iter,
- priv->row_separator_data);
+ is_separator = priv->row_separator_func (model, iter,
+ priv->row_separator_data);
else
is_separator = FALSE;
priv->button = gtk_toggle_button_new ();
gtk_widget_set_parent (priv->button,
GTK_BIN (combo_box)->child->parent);
- g_signal_connect (priv->button, "button_press_event",
+ g_signal_connect (priv->button, "button-press-event",
G_CALLBACK (gtk_combo_box_list_button_pressed), combo_box);
g_signal_connect (priv->button, "toggled",
G_CALLBACK (gtk_combo_box_button_toggled), combo_box);
gtk_container_add (GTK_CONTAINER (priv->cell_view_frame), priv->box);
gtk_widget_show_all (priv->cell_view_frame);
- g_signal_connect (priv->box, "button_press_event",
+ g_signal_connect (priv->box, "button-press-event",
G_CALLBACK (gtk_combo_box_list_button_pressed),
combo_box);
}
/* set sample/popup widgets */
gtk_combo_box_set_popup_widget (combo_box, priv->tree_view);
- g_signal_connect (priv->tree_view, "key_press_event",
+ g_signal_connect (priv->tree_view, "key-press-event",
G_CALLBACK (gtk_combo_box_list_key_press),
combo_box);
- g_signal_connect (priv->tree_view, "enter_notify_event",
+ g_signal_connect (priv->tree_view, "enter-notify-event",
G_CALLBACK (gtk_combo_box_list_enter_notify),
combo_box);
- g_signal_connect (priv->tree_view, "row_expanded",
+ g_signal_connect (priv->tree_view, "row-expanded",
G_CALLBACK (gtk_combo_box_model_row_expanded),
combo_box);
- g_signal_connect (priv->tree_view, "row_collapsed",
+ g_signal_connect (priv->tree_view, "row-collapsed",
G_CALLBACK (gtk_combo_box_model_row_expanded),
combo_box);
- g_signal_connect (priv->popup_window, "button_press_event",
+ g_signal_connect (priv->popup_window, "button-press-event",
G_CALLBACK (gtk_combo_box_list_button_pressed),
combo_box);
- g_signal_connect (priv->popup_window, "button_release_event",
+ g_signal_connect (priv->popup_window, "button-release-event",
G_CALLBACK (gtk_combo_box_list_button_released),
combo_box);
gtk_widget_show (priv->tree_view);
+
+ gtk_combo_box_update_sensitivity (combo_box);
}
static void
return FALSE;
if (priv->focus_on_click &&
- !GTK_WIDGET_HAS_FOCUS (priv->button))
+ !gtk_widget_has_focus (priv->button))
gtk_widget_grab_focus (priv->button);
gtk_combo_box_popup (combo_box);
gtk_tree_view_column_cell_set_cell_data (column, model, &iter,
FALSE, FALSE);
- cell = cells = gtk_tree_view_column_get_cell_renderers (column);
+ cell = cells = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (column));
while (cell)
{
g_object_get (cell->data,
g_object_ref_sink (cell);
- info = g_new0 (ComboCellInfo, 1);
+ info = g_slice_new0 (ComboCellInfo);
info->cell = cell;
info->expand = expand;
info->pack = GTK_PACK_START;
g_object_ref_sink (cell);
- info = g_new0 (ComboCellInfo, 1);
+ info = g_slice_new0 (ComboCellInfo);
info->cell = cell;
info->expand = expand;
info->pack = GTK_PACK_END;
for (i = priv->cells; i; i = i->next)
{
- ComboCellInfo *info = (ComboCellInfo *)i->data;
+ ComboCellInfo *info = (ComboCellInfo *)i->data;
gtk_combo_box_cell_layout_clear_attributes (layout, info->cell);
g_object_unref (info->cell);
- g_free (info);
+ g_slice_free (ComboCellInfo, info);
i->data = NULL;
}
g_slist_free (priv->cells);
if (!info->func)
return;
- (*info->func) (cell_layout, cell, tree_model, iter, info->func_data);
-
+ info->func (cell_layout, cell, tree_model, iter, info->func_data);
+
if (GTK_IS_WIDGET (cell_layout))
parent = gtk_widget_get_parent (GTK_WIDGET (cell_layout));
g_return_if_fail (GTK_IS_COMBO_BOX (combo_box));
g_return_if_fail (index_ >= -1);
+ if (combo_box->priv->model == NULL)
+ {
+ /* Save index, in case the model is set after the index */
+ combo_box->priv->active = index_;
+ if (index_ != -1)
+ return;
+ }
+
if (index_ != -1)
path = gtk_tree_path_new_from_indices (index_, -1);
GtkTreePath *active_path;
gint path_cmp;
- if (path && gtk_tree_row_reference_valid (priv->active_row))
+ /* Remember whether the initially active row is valid. */
+ gboolean is_valid_row_reference = gtk_tree_row_reference_valid (priv->active_row);
+
+ if (path && is_valid_row_reference)
{
active_path = gtk_tree_row_reference_get_path (priv->active_row);
path_cmp = gtk_tree_path_compare (path, active_path);
if (priv->cell_view)
gtk_cell_view_set_displayed_row (GTK_CELL_VIEW (priv->cell_view), NULL);
+
+ /*
+ * Do not emit a "changed" signal when an already invalid selection was
+ * now set to invalid.
+ */
+ if (!is_valid_row_reference)
+ return;
}
else
{
/**
* gtk_combo_box_set_active_iter:
* @combo_box: A #GtkComboBox
- * @iter: The #GtkTreeIter
+ * @iter: (allow-none): The #GtkTreeIter, or %NULL
*
- * Sets the current active item to be the one referenced by @iter.
- * @iter must correspond to a path of depth one.
+ * Sets the current active item to be the one referenced by @iter, or
+ * unsets the active item if @iter is %NULL.
+ *
+ * @iter must correspond to a path of depth one, or be %NULL.
*
* Since: 2.4
*/
gtk_combo_box_set_active_iter (GtkComboBox *combo_box,
GtkTreeIter *iter)
{
- GtkTreePath *path;
+ GtkTreePath *path = NULL;
g_return_if_fail (GTK_IS_COMBO_BOX (combo_box));
- path = gtk_tree_model_get_path (gtk_combo_box_get_model (combo_box), iter);
+ if (iter)
+ path = gtk_tree_model_get_path (gtk_combo_box_get_model (combo_box), iter);
+
gtk_combo_box_set_active_internal (combo_box, path);
gtk_tree_path_free (path);
}
/**
* gtk_combo_box_set_model:
* @combo_box: A #GtkComboBox
- * @model: A #GtkTreeModel
+ * @model: (allow-none): A #GtkTreeModel
*
- * Sets the model used by @combo_box to be @model. Will unset a previously set
+ * Sets the model used by @combo_box to be @model. Will unset a previously set
* model (if applicable). If model is %NULL, then it will unset the model.
*
* Note that this function does not clear the cell renderers, you have to
g_object_ref (combo_box->priv->model);
combo_box->priv->inserted_id =
- g_signal_connect (combo_box->priv->model, "row_inserted",
+ g_signal_connect (combo_box->priv->model, "row-inserted",
G_CALLBACK (gtk_combo_box_model_row_inserted),
combo_box);
combo_box->priv->deleted_id =
- g_signal_connect (combo_box->priv->model, "row_deleted",
+ g_signal_connect (combo_box->priv->model, "row-deleted",
G_CALLBACK (gtk_combo_box_model_row_deleted),
combo_box);
combo_box->priv->reordered_id =
- g_signal_connect (combo_box->priv->model, "rows_reordered",
+ g_signal_connect (combo_box->priv->model, "rows-reordered",
G_CALLBACK (gtk_combo_box_model_rows_reordered),
combo_box);
combo_box->priv->changed_id =
- g_signal_connect (combo_box->priv->model, "row_changed",
+ g_signal_connect (combo_box->priv->model, "row-changed",
G_CALLBACK (gtk_combo_box_model_row_changed),
combo_box);
gtk_cell_view_set_model (GTK_CELL_VIEW (combo_box->priv->cell_view),
combo_box->priv->model);
+ if (combo_box->priv->active != -1)
+ {
+ /* If an index was set in advance, apply it now */
+ gtk_combo_box_set_active (combo_box, combo_box->priv->active);
+ combo_box->priv->active = -1;
+ }
+
out:
+ gtk_combo_box_update_sensitivity (combo_box);
+
g_object_notify (G_OBJECT (combo_box), "model");
}
*
* Returns the #GtkTreeModel which is acting as data source for @combo_box.
*
- * Return value: A #GtkTreeModel which was passed during construction.
+ * Return value: (transfer none): A #GtkTreeModel which was passed during construction.
*
* Since: 2.4
*/
* gtk_combo_box_insert_text(), gtk_combo_box_prepend_text() and
* gtk_combo_box_remove_text().
*
- * Return value: A new text combo box.
+ * Return value: (transfer none): A new text combo box.
*
* Since: 2.4
*/
*
* Returns the currently active string in @combo_box or %NULL if none
* is selected. Note that you can only use this function with combo
- * boxes constructed with gtk_combo_box_new_text() and with
+ * boxes constructed with gtk_combo_box_new_text() and with
* #GtkComboBoxEntry<!-- -->s.
*
* Returns: a newly allocated string containing the currently active text.
+ * Must be freed with g_free().
*
* Since: 2.6
*/
class = GTK_COMBO_BOX_GET_CLASS (combo_box);
if (class->get_active_text)
- return (* class->get_active_text) (combo_box);
+ return class->get_active_text (combo_box);
return NULL;
}
gtk_combo_box_popdown (combo_box);
if (combo_box->priv->row_separator_destroy)
- (* combo_box->priv->row_separator_destroy) (combo_box->priv->row_separator_data);
+ combo_box->priv->row_separator_destroy (combo_box->priv->row_separator_data);
combo_box->priv->row_separator_func = NULL;
combo_box->priv->row_separator_data = NULL;
g_slist_free (info->attributes);
g_object_unref (info->cell);
- g_free (info);
+ g_slice_free (ComboCellInfo, info);
}
g_slist_free (combo_box->priv->cells);
if (event->keyval == GDK_Escape)
{
- combo_box->priv->editing_canceled = TRUE;
-
+ g_object_set (combo_box,
+ "editing-canceled", TRUE,
+ NULL);
gtk_cell_editable_editing_done (GTK_CELL_EDITABLE (combo_box));
gtk_cell_editable_remove_widget (GTK_CELL_EDITABLE (combo_box));
combo_box, 0);
/* we unset this if a menu item is activated */
- combo_box->priv->editing_canceled = TRUE;
+ g_object_set (combo_box,
+ "editing-canceled", TRUE,
+ NULL);
gtk_combo_box_popup (combo_box);
combo_box->priv->popup_idle_id = 0;
if (combo_box->priv->cell_view)
{
- g_signal_connect_object (combo_box->priv->button, "key_press_event",
+ g_signal_connect_object (combo_box->priv->button, "key-press-event",
G_CALLBACK (gtk_cell_editable_key_press),
cell_editable, 0);
}
else
{
- g_signal_connect_object (GTK_BIN (combo_box)->child, "key_press_event",
+ g_signal_connect_object (GTK_BIN (combo_box)->child, "key-press-event",
G_CALLBACK (gtk_cell_editable_key_press),
cell_editable, 0);
gtk_widget_grab_focus (GTK_WIDGET (GTK_BIN (combo_box)->child));
- GTK_WIDGET_UNSET_FLAGS (combo_box->priv->button, GTK_CAN_FOCUS);
+ gtk_widget_set_can_focus (combo_box->priv->button, FALSE);
}
/* we do the immediate popup only for the optionmenu-like
}
}
-gboolean
-_gtk_combo_box_editing_canceled (GtkComboBox *combo_box)
-{
- g_return_val_if_fail (GTK_IS_COMBO_BOX (combo_box), TRUE);
-
- return combo_box->priv->editing_canceled;
-}
-
/**
* gtk_combo_box_get_popup_accessible:
* @combo_box: a #GtkComboBox
* gtk_combo_box_set_row_separator_func:
* @combo_box: a #GtkComboBox
* @func: a #GtkTreeViewRowSeparatorFunc
- * @data: user data to pass to @func, or %NULL
- * @destroy: destroy notifier for @data, or %NULL
+ * @data: (allow-none): user data to pass to @func, or %NULL
+ * @destroy: (allow-none): destroy notifier for @data, or %NULL
*
* Sets the row separator function, which is used to determine
* whether a row should be drawn as a separator. If the row separator
g_return_if_fail (GTK_IS_COMBO_BOX (combo_box));
if (combo_box->priv->row_separator_destroy)
- (* combo_box->priv->row_separator_destroy) (combo_box->priv->row_separator_data);
+ combo_box->priv->row_separator_destroy (combo_box->priv->row_separator_data);
combo_box->priv->row_separator_func = func;
combo_box->priv->row_separator_data = data;
gtk_widget_queue_draw (GTK_WIDGET (combo_box));
}
+/**
+ * gtk_combo_box_set_button_sensitivity:
+ * @combo_box: a #GtkComboBox
+ * @sensitivity: specify the sensitivity of the dropdown button
+ *
+ * Sets whether the dropdown button of the combo box should be
+ * always sensitive (%GTK_SENSITIVITY_ON), never sensitive (%GTK_SENSITIVITY_OFF)
+ * or only if there is at least one item to display (%GTK_SENSITIVITY_AUTO).
+ *
+ * Since: 2.14
+ **/
+void
+gtk_combo_box_set_button_sensitivity (GtkComboBox *combo_box,
+ GtkSensitivityType sensitivity)
+{
+ g_return_if_fail (GTK_IS_COMBO_BOX (combo_box));
+
+ if (combo_box->priv->button_sensitivity != sensitivity)
+ {
+ combo_box->priv->button_sensitivity = sensitivity;
+ gtk_combo_box_update_sensitivity (combo_box);
+
+ g_object_notify (G_OBJECT (combo_box), "button-sensitivity");
+ }
+}
+
+/**
+ * gtk_combo_box_get_button_sensitivity:
+ * @combo_box: a #GtkComboBox
+ *
+ * Returns whether the combo box sets the dropdown button
+ * sensitive or not when there are no items in the model.
+ *
+ * Return Value: %GTK_SENSITIVITY_ON if the dropdown button
+ * is sensitive when the model is empty, %GTK_SENSITIVITY_OFF
+ * if the button is always insensitive or
+ * %GTK_SENSITIVITY_AUTO if it is only sensitive as long as
+ * the model has one item to be selected.
+ *
+ * Since: 2.14
+ **/
+GtkSensitivityType
+gtk_combo_box_get_button_sensitivity (GtkComboBox *combo_box)
+{
+ g_return_val_if_fail (GTK_IS_COMBO_BOX (combo_box), FALSE);
+
+ return combo_box->priv->button_sensitivity;
+}
+
/**
* gtk_combo_box_set_focus_on_click: