* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
+
#include "gtkcombobox.h"
+
+#include "gtkadjustment.h"
#include "gtkcellareabox.h"
#include "gtktreemenu.h"
#include "gtkarrow.h"
#include "gtkcellview.h"
#include "gtkeventbox.h"
#include "gtkframe.h"
-#include "gtkhbox.h"
+#include "gtkbox.h"
#include "gtkliststore.h"
#include "gtkmain.h"
#include "gtkmenuprivate.h"
#include "gtkmenushellprivate.h"
#include "gtkscrolledwindow.h"
#include "gtkseparatormenuitem.h"
-#include "gtktearoffmenuitem.h"
+#include "deprecated/gtktearoffmenuitem.h"
#include "gtktogglebutton.h"
#include "gtktreeselection.h"
-#include "gtkvseparator.h"
+#include "gtkseparator.h"
+#include "gtkwidgetpath.h"
+#include "gtkwidgetprivate.h"
#include "gtkwindow.h"
+#include "gtktypebuiltins.h"
#include "gtkprivate.h"
-#include <gdk/gdkkeysyms.h>
-
#include <gobject/gvaluecollector.h>
#include <string.h>
#include "gtkentryprivate.h"
#include "gtktreeprivate.h"
+#include "a11y/gtkcomboboxaccessible.h"
/**
GtkTreeRowReference *active_row;
GtkWidget *tree_view;
- GtkTreeViewColumn *column;
GtkWidget *cell_view;
GtkWidget *cell_view_frame;
guint resize_idle_id;
/* For "has-entry" specific behavior we track
- * an automated cell renderer and text column */
+ * an automated cell renderer and text column
+ */
gint text_column;
GtkCellRenderer *text_renderer;
MOVE_ACTIVE,
POPUP,
POPDOWN,
+ FORMAT_ENTRY_TEXT,
LAST_SIGNAL
};
static guint combo_box_signals[LAST_SIGNAL] = {0,};
-#define BONUS_PADDING 4
#define SCROLL_TIME 100
/* common */
GValue *value,
GParamSpec *spec);
-static void gtk_combo_box_state_changed (GtkWidget *widget,
- GtkStateType previous);
+static void gtk_combo_box_state_flags_changed (GtkWidget *widget,
+ GtkStateFlags previous);
static void gtk_combo_box_grab_focus (GtkWidget *widget);
static void gtk_combo_box_style_updated (GtkWidget *widget);
static void gtk_combo_box_button_toggled (GtkWidget *widget,
guint32 activate_time);
/* cell layout */
-GtkCellArea *gtk_combo_box_cell_layout_get_area (GtkCellLayout *cell_layout);
+static GtkCellArea *gtk_combo_box_cell_layout_get_area (GtkCellLayout *cell_layout);
static gboolean gtk_combo_box_mnemonic_activate (GtkWidget *widget,
gboolean group_cycling);
gpointer user_data);
static void gtk_combo_box_entry_active_changed (GtkComboBox *combo_box,
gpointer user_data);
-
+static gchar *gtk_combo_box_format_entry_text (GtkComboBox *combo_box,
+ const gchar *path);
/* GtkBuildable method implementation */
static GtkBuildableIface *parent_buildable_iface;
gint avail_size,
gint *minimum_size,
gint *natural_size);
-
+static GtkWidgetPath *gtk_combo_box_get_path_for_child (GtkContainer *container,
+ GtkWidget *child);
+static void gtk_combo_box_direction_changed (GtkWidget *widget,
+ GtkTextDirection previous_direction);
G_DEFINE_TYPE_WITH_CODE (GtkComboBox, gtk_combo_box, GTK_TYPE_BIN,
G_IMPLEMENT_INTERFACE (GTK_TYPE_CELL_LAYOUT,
container_class->forall = gtk_combo_box_forall;
container_class->add = gtk_combo_box_add;
container_class->remove = gtk_combo_box_remove;
+ container_class->get_path_for_child = gtk_combo_box_get_path_for_child;
+
+ gtk_container_class_handle_border_width (container_class);
widget_class = (GtkWidgetClass *)klass;
widget_class->size_allocate = gtk_combo_box_size_allocate;
widget_class->mnemonic_activate = gtk_combo_box_mnemonic_activate;
widget_class->grab_focus = gtk_combo_box_grab_focus;
widget_class->style_updated = gtk_combo_box_style_updated;
- widget_class->state_changed = gtk_combo_box_state_changed;
+ widget_class->state_flags_changed = gtk_combo_box_state_flags_changed;
widget_class->get_preferred_width = gtk_combo_box_get_preferred_width;
widget_class->get_preferred_height = gtk_combo_box_get_preferred_height;
widget_class->get_preferred_height_for_width = gtk_combo_box_get_preferred_height_for_width;
widget_class->get_preferred_width_for_height = gtk_combo_box_get_preferred_width_for_height;
widget_class->destroy = gtk_combo_box_destroy;
+ widget_class->direction_changed = gtk_combo_box_direction_changed;
object_class = (GObjectClass *)klass;
object_class->constructor = gtk_combo_box_constructor;
object_class->set_property = gtk_combo_box_set_property;
object_class->get_property = gtk_combo_box_get_property;
+ klass->format_entry_text = gtk_combo_box_format_entry_text;
+
/* signals */
/**
* GtkComboBox::changed:
_gtk_marshal_BOOLEAN__VOID,
G_TYPE_BOOLEAN, 0);
+ /**
+ * GtkComboBox::format-entry-text:
+ * @combo: the object which received the signal
+ * @path: the GtkTreePath string from the combo box's current model to format text for
+ *
+ * For combo boxes that are created with an entry (See GtkComboBox:has-entry).
+ *
+ * A signal which allows you to change how the text displayed in a combo box's
+ * entry is displayed.
+ *
+ * Connect a signal handler which returns an allocated string representing
+ * @path. That string will then be used to set the text in the combo box's entry.
+ * The default signal handler uses the text from the GtkComboBox::entry-text-column
+ * model column.
+ *
+ * Here's an example signal handler which fetches data from the model and
+ * displays it in the entry.
+ * |[
+ * static gchar*
+ * format_entry_text_callback (GtkComboBox *combo,
+ * const gchar *path,
+ * gpointer user_data)
+ * {
+ * GtkTreeIter iter;
+ * GtkTreeModel model;
+ * gdouble value;
+ *
+ * model = gtk_combo_box_get_model (combo);
+ *
+ * gtk_tree_model_get_iter_from_string (model, &iter, path);
+ * gtk_tree_model_get (model, &iter,
+ * THE_DOUBLE_VALUE_COLUMN, &value,
+ * -1);
+ *
+ * return g_strdup_printf ("%g", value);
+ * }
+ * ]|
+ *
+ * Return value: (transfer full): a newly allocated string representing @path
+ * for the current GtkComboBox model.
+ *
+ * Since: 3.4
+ */
+ combo_box_signals[FORMAT_ENTRY_TEXT] =
+ g_signal_new (I_("format-entry-text"),
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GtkComboBoxClass, format_entry_text),
+ _gtk_single_string_accumulator, NULL,
+ _gtk_marshal_STRING__STRING,
+ G_TYPE_STRING, 1, G_TYPE_STRING);
+
/* key bindings */
binding_set = gtk_binding_set_by_class (widget_class);
*
* The #GtkCellArea used to layout cell renderers for this combo box.
*
+ * If no area is specified when creating the combo box with gtk_combo_box_new_with_area()
+ * a horizontally oriented #GtkCellAreaBox will be used.
+ *
* Since: 3.0
*/
g_object_class_install_property (object_class,
15,
GTK_PARAM_READABLE));
+ /**
+ * GtkComboBox:arrow-scaling:
+ *
+ * Sets the amount of space used up by the combobox arrow,
+ * proportional to the font size.
+ *
+ * Since: 3.2
+ */
+ gtk_widget_class_install_style_property (widget_class,
+ g_param_spec_float ("arrow-scaling",
+ P_("Arrow Scaling"),
+ P_("The amount of space used by the arrow"),
+ 0,
+ 2.0,
+ 1.0,
+ GTK_PARAM_READABLE));
+
/**
* GtkComboBox:shadow-type:
*
GTK_PARAM_READABLE));
g_type_class_add_private (object_class, sizeof (GtkComboBoxPrivate));
+
+ gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_COMBO_BOX_ACCESSIBLE);
}
static void
GParamSpec *pspec)
{
GtkComboBox *combo_box = GTK_COMBO_BOX (object);
+ GtkComboBoxPrivate *priv = combo_box->priv;
GtkCellArea *area;
switch (prop_id)
break;
case PROP_HAS_FRAME:
- combo_box->priv->has_frame = g_value_get_boolean (value);
+ priv->has_frame = g_value_get_boolean (value);
- if (combo_box->priv->has_entry)
+ if (priv->has_entry)
{
GtkWidget *child;
child = gtk_bin_get_child (GTK_BIN (combo_box));
- gtk_entry_set_has_frame (GTK_ENTRY (child),
- combo_box->priv->has_frame);
+ gtk_entry_set_has_frame (GTK_ENTRY (child), priv->has_frame);
}
break;
break;
case PROP_EDITING_CANCELED:
- combo_box->priv->editing_canceled = g_value_get_boolean (value);
+ priv->editing_canceled = g_value_get_boolean (value);
break;
case PROP_HAS_ENTRY:
- combo_box->priv->has_entry = g_value_get_boolean (value);
+ priv->has_entry = g_value_get_boolean (value);
break;
case PROP_ENTRY_TEXT_COLUMN:
case PROP_CELL_AREA:
/* Construct-only, can only be assigned once */
area = g_value_get_object (value);
-
if (area)
- combo_box->priv->area = g_object_ref_sink (area);
+ {
+ if (priv->area != NULL)
+ {
+ g_warning ("cell-area has already been set, ignoring construct property");
+ g_object_ref_sink (area);
+ g_object_unref (area);
+ }
+ else
+ priv->area = g_object_ref_sink (area);
+ }
break;
default:
}
static void
-gtk_combo_box_state_changed (GtkWidget *widget,
- GtkStateType previous)
+gtk_combo_box_state_flags_changed (GtkWidget *widget,
+ GtkStateFlags previous)
{
GtkComboBox *combo_box = GTK_COMBO_BOX (widget);
GtkComboBoxPrivate *priv = combo_box->priv;
{
GtkStyleContext *context;
GtkStateFlags state;
- GdkRGBA *color;
+ GdkRGBA color;
context = gtk_widget_get_style_context (widget);
state = gtk_widget_get_state_flags (widget);
+ gtk_style_context_get_background_color (context, state, &color);
- gtk_style_context_get (context, state,
- "background-color", &color,
- NULL);
-
- gtk_cell_view_set_background_rgba (GTK_CELL_VIEW (priv->cell_view), color);
- gdk_rgba_free (color);
+ gtk_cell_view_set_background_rgba (GTK_CELL_VIEW (priv->cell_view), &color);
}
}
gtk_widget_queue_draw (widget);
}
+static void
+gtk_combo_box_invalidate_order_foreach (GtkWidget *widget)
+{
+ _gtk_widget_invalidate_style_context (widget, GTK_CSS_CHANGE_POSITION | GTK_CSS_CHANGE_SIBLING_POSITION);
+}
+
+static void
+gtk_combo_box_invalidate_order (GtkComboBox *combo_box)
+{
+ gtk_container_forall (GTK_CONTAINER (combo_box),
+ (GtkCallback) gtk_combo_box_invalidate_order_foreach,
+ NULL);
+}
+
+static void
+gtk_combo_box_direction_changed (GtkWidget *widget,
+ GtkTextDirection previous_direction)
+{
+ gtk_combo_box_invalidate_order (GTK_COMBO_BOX (widget));
+}
+
+static GtkWidgetPath *
+gtk_combo_box_get_path_for_child (GtkContainer *container,
+ GtkWidget *child)
+{
+ GtkComboBoxPrivate *priv = GTK_COMBO_BOX (container)->priv;
+ GtkWidgetPath *path;
+ GtkWidget *widget;
+ gboolean found = FALSE;
+ GList *visible_children, *l;
+ GtkWidgetPath *sibling_path;
+ int pos;
+
+ path = _gtk_widget_create_path (GTK_WIDGET (container));
+
+ if (gtk_widget_get_visible (child))
+ {
+ visible_children = NULL;
+
+ if (priv->button && gtk_widget_get_visible (priv->button))
+ visible_children = g_list_prepend (visible_children, priv->button);
+
+ if (priv->cell_view_frame && gtk_widget_get_visible (priv->cell_view_frame))
+ visible_children = g_list_prepend (visible_children, priv->cell_view_frame);
+
+ widget = gtk_bin_get_child (GTK_BIN (container));
+ if (widget && gtk_widget_get_visible (widget))
+ visible_children = g_list_prepend (visible_children, widget);
+
+ if (gtk_widget_get_direction (GTK_WIDGET (container)) == GTK_TEXT_DIR_RTL)
+ visible_children = g_list_reverse (visible_children);
+
+ pos = 0;
+
+ for (l = visible_children; l; l = l->next)
+ {
+ widget = l->data;
+
+ if (widget == child)
+ {
+ found = TRUE;
+ break;
+ }
+
+ pos++;
+ }
+ }
+
+ if (found)
+ {
+ sibling_path = gtk_widget_path_new ();
+
+ for (l = visible_children; l; l = l->next)
+ gtk_widget_path_append_for_widget (sibling_path, l->data);
+
+ gtk_widget_path_append_with_siblings (path, sibling_path, pos);
+
+ g_list_free (visible_children);
+ gtk_widget_path_unref (sibling_path);
+ }
+ else
+ {
+ gtk_widget_path_append_for_widget (path, child);
+ }
+
+ return path;
+}
+
static void
gtk_combo_box_check_appearance (GtkComboBox *combo_box)
{
GtkComboBoxPrivate *priv = combo_box->priv;
GtkWidget *child;
+ GTK_WIDGET_CLASS (gtk_combo_box_parent_class)->style_updated (widget);
+
gtk_combo_box_check_appearance (combo_box);
if (priv->tree_view && priv->cell_view)
{
GtkStyleContext *context;
- GdkRGBA *color;
-
- context = gtk_widget_get_style_context (widget);
- gtk_style_context_get (context, 0,
- "background-color", &color,
- NULL);
+ GtkStateFlags state;
+ GdkRGBA color;
- gtk_cell_view_set_background_rgba (GTK_CELL_VIEW (priv->cell_view),
- color);
+ context = gtk_widget_get_style_context (widget);
+ state = gtk_widget_get_state_flags (widget);
+ gtk_style_context_get_background_color (context, state, &color);
- gdk_rgba_free (color);
+ gtk_cell_view_set_background_rgba (GTK_CELL_VIEW (priv->cell_view), &color);
}
child = gtk_bin_get_child (GTK_BIN (combo_box));
}
static void
-get_widget_border (GtkWidget *widget,
- GtkBorder *border)
+get_widget_padding_and_border (GtkWidget *widget,
+ GtkBorder *padding)
{
GtkStyleContext *context;
- GtkBorder *border_width;
+ GtkStateFlags state;
+ GtkBorder tmp;
context = gtk_widget_get_style_context (widget);
+ state = gtk_style_context_get_state (context);
- gtk_style_context_get (context,
- gtk_widget_get_state_flags (widget),
- "border-width", &border_width,
- NULL);
+ gtk_style_context_get_padding (context, state, padding);
+ gtk_style_context_get_border (context, state, &tmp);
- *border = *border_width;
- gtk_border_free (border_width);
+ padding->top += tmp.top;
+ padding->right += tmp.right;
+ padding->bottom += tmp.bottom;
+ padding->left += tmp.left;
}
static void
GdkScreen *screen;
gint monitor_num;
GdkRectangle monitor;
- GtkBorder border;
+ GtkBorder padding;
/* FIXME: is using the size request here broken? */
child = gtk_bin_get_child (GTK_BIN (combo_box));
gdk_window_get_root_coords (gtk_widget_get_window (child),
sx, sy, &sx, &sy);
- get_widget_border (GTK_WIDGET (combo_box), &border);
- sx -= border.left;
+ get_widget_padding_and_border (GTK_WIDGET (combo_box), &padding);
+
+ if (gtk_widget_get_direction (GTK_WIDGET (combo_box)) == GTK_TEXT_DIR_RTL)
+ sx += padding.left;
+ else
+ sx -= padding.left;
if (combo_box->priv->popup_fixed_width)
gtk_widget_get_preferred_size (GTK_WIDGET (menu), &req, NULL);
screen = gtk_widget_get_screen (GTK_WIDGET (combo_box));
monitor_num = gdk_screen_get_monitor_at_window (screen,
gtk_widget_get_window (GTK_WIDGET (combo_box)));
- gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
+ gdk_screen_get_monitor_workarea (screen, monitor_num, &monitor);
if (*x < monitor.x)
*x = monitor.x;
screen = gtk_widget_get_screen (GTK_WIDGET (combo_box));
monitor_num = gdk_screen_get_monitor_at_window (screen, window);
- gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
+ gdk_screen_get_monitor_workarea (screen, monitor_num, &monitor);
if (gtk_widget_get_direction (GTK_WIDGET (combo_box)) == GTK_TEXT_DIR_RTL)
*x = *x + allocation.width - *width;
}
static gboolean
-cell_view_is_sensitive (GtkCellView *cell_view)
+cell_layout_is_sensitive (GtkCellLayout *layout)
{
GList *cells, *list;
gboolean sensitive;
- cells = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (cell_view));
+ cells = gtk_cell_layout_get_cells (layout);
sensitive = FALSE;
for (list = cells; list; list = list->next)
return sensitive;
}
+static gboolean
+cell_is_sensitive (GtkCellRenderer *cell,
+ gpointer data)
+{
+ gboolean *sensitive = data;
+
+ g_object_get (cell, "sensitive", sensitive, NULL);
+
+ return *sensitive;
+}
+
static gboolean
tree_column_row_is_sensitive (GtkComboBox *combo_box,
GtkTreeIter *iter)
{
GtkComboBoxPrivate *priv = combo_box->priv;
- GList *cells, *list;
- gboolean sensitive;
-
- if (!priv->column)
- return TRUE;
if (priv->row_separator_func)
{
return FALSE;
}
- gtk_tree_view_column_cell_set_cell_data (priv->column,
- priv->model,
- iter, FALSE, FALSE);
+ if (priv->area)
+ {
+ gboolean sensitive;
- cells = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (priv->column));
+ gtk_cell_area_apply_attributes (priv->area, priv->model, iter, FALSE, FALSE);
- sensitive = FALSE;
- for (list = cells; list; list = list->next)
- {
- g_object_get (list->data, "sensitive", &sensitive, NULL);
+ sensitive = FALSE;
- if (sensitive)
- break;
+ gtk_cell_area_foreach (priv->area, cell_is_sensitive, &sensitive);
+
+ return sensitive;
}
- g_list_free (cells);
- return sensitive;
+ return TRUE;
}
static void
}
else
{
- sensitive = cell_view_is_sensitive (GTK_CELL_VIEW (cell_view));
+ sensitive = cell_layout_is_sensitive (GTK_CELL_LAYOUT (cell_view));
if (menu != priv->popup_widget && child == children)
{
priv->grab_keyboard = NULL;
}
-#define GTK_COMBO_BOX_SIZE_ALLOCATE_BUTTON \
- gtk_widget_get_preferred_size (combo_box->priv->button, \
- &req, NULL); \
- \
- if (is_rtl) \
- child.x = allocation->x + border.right; \
- else \
- child.x = allocation->x + allocation->width - req.width - border.left; \
- \
- child.y = allocation->y + border.top; \
- child.width = req.width; \
- child.height = allocation->height - (border.top + border.bottom); \
- child.width = MAX (1, child.width); \
- child.height = MAX (1, child.height); \
- \
- gtk_widget_size_allocate (combo_box->priv->button, &child);
+#define GTK_COMBO_BOX_SIZE_ALLOCATE_BUTTON \
+ GtkAllocation button_allocation; \
+ gtk_widget_get_preferred_size (combo_box->priv->button, \
+ &req, NULL); \
+ \
+ if (is_rtl) \
+ button_allocation.x = allocation->x; \
+ else \
+ button_allocation.x = allocation->x + allocation->width \
+ - req.width; \
+ \
+ button_allocation.y = allocation->y; \
+ button_allocation.width = MAX (1, req.width); \
+ button_allocation.height = allocation->height; \
+ button_allocation.height = MAX (1, button_allocation.height); \
+ \
+ gtk_widget_size_allocate (combo_box->priv->button, \
+ &button_allocation);
static void
GtkComboBox *combo_box = GTK_COMBO_BOX (widget);
GtkComboBoxPrivate *priv = combo_box->priv;
GtkWidget *child_widget;
- gint focus_width, focus_pad;
GtkAllocation child;
GtkRequisition req;
gboolean is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
- GtkBorder border;
+ GtkBorder padding;
gtk_widget_set_allocation (widget, allocation);
child_widget = gtk_bin_get_child (GTK_BIN (widget));
- get_widget_border (widget, &border);
+ get_widget_padding_and_border (widget, &padding);
- gtk_widget_style_get (widget,
- "focus-line-width", &focus_width,
- "focus-padding", &focus_pad,
- NULL);
+ allocation->x += padding.left;
+ allocation->y += padding.top;
+ allocation->width -= padding.left + padding.right;
+ allocation->height -= padding.top + padding.bottom;
if (!priv->tree_view)
{
if (priv->cell_view)
{
- GtkBorder button_border;
+ GtkBorder button_padding;
gint width;
guint border_width;
- /* menu mode */
- allocation->x += border.left;
- allocation->y += border.top;
- allocation->width -= border.left + border.right;
- allocation->height -= border.top + border.bottom;
+ border_width = gtk_container_get_border_width (GTK_CONTAINER (priv->button));
+ get_widget_padding_and_border (priv->button, &button_padding);
+ /* menu mode; child_widget is priv->cell_view.
+ * Allocate the button to the full combobox allocation (minus the
+ * padding).
+ */
gtk_widget_size_allocate (priv->button, allocation);
- /* set some things ready */
- border_width = gtk_container_get_border_width (GTK_CONTAINER (priv->button));
- get_widget_border (priv->button, &button_border);
-
child.x = allocation->x;
child.y = allocation->y;
width = allocation->width;
if (!priv->is_cell_renderer)
{
- child.x += border_width + button_border.left + focus_width + focus_pad;
- child.y += border_width + button_border.top + focus_width + focus_pad;
- width -= (2 * (border_width + focus_width + focus_pad)) +
- button_border.left + button_border.right;
- child.height -= (2 * (border_width + focus_width + focus_pad)) +
- button_border.top + button_border.bottom;
+ /* restrict allocation of the child into the button box
+ * if we're not in cell renderer mode.
+ */
+ child.x += border_width + button_padding.left;
+ child.y += border_width + button_padding.top;
+ width -= 2 * border_width +
+ button_padding.left + button_padding.right;
+ child.height -= 2 * border_width +
+ button_padding.top + button_padding.bottom;
}
- /* handle the children */
- gtk_widget_get_preferred_size (priv->arrow, &req, NULL);
+ /* allocate the box containing the separator and the arrow */
+ gtk_widget_get_preferred_size (priv->box, &req, NULL);
child.width = req.width;
if (!is_rtl)
child.x += width - req.width;
child.width = MAX (1, child.width);
child.height = MAX (1, child.height);
- gtk_widget_size_allocate (priv->arrow, &child);
- if (is_rtl)
- child.x += req.width;
- gtk_widget_get_preferred_size (priv->separator, &req, NULL);
- child.width = req.width;
- if (!is_rtl)
- child.x -= req.width;
- child.width = MAX (1, child.width);
- child.height = MAX (1, child.height);
- gtk_widget_size_allocate (priv->separator, &child);
+ gtk_widget_size_allocate (priv->box, &child);
if (is_rtl)
{
child.x += req.width;
child.width = allocation->x + allocation->width
- - (border_width + button_border.right + focus_width + focus_pad)
- - child.x;
+ - border_width - child.x - button_padding.right;
}
else
{
child.width = child.x;
child.x = allocation->x
- + border_width + button_border.left + focus_width + focus_pad;
+ + border_width + button_padding.left;
child.width -= child.x;
}
}
else
{
+ /* menu mode; child_widget has been set with gtk_container_add().
+ * E.g. it might be a GtkEntry if priv->has_entry is TRUE.
+ * Allocate the button at the far end, according to the direction
+ * of the widget.
+ */
GTK_COMBO_BOX_SIZE_ALLOCATE_BUTTON
+ /* After the macro, button_allocation has the button allocation rect */
+
if (is_rtl)
- child.x = allocation->x + req.width + border.right;
+ child.x = button_allocation.x + button_allocation.width;
else
- child.x = allocation->x + border.left;
- child.y = allocation->y + border.top;
- child.width = allocation->width - req.width - (border.left + border.right);
+ child.x = allocation->x;
+
+ child.y = allocation->y;
+ child.width = allocation->width - button_allocation.width;
+ child.height = button_allocation.height;
+
child.width = MAX (1, child.width);
- child.height = MAX (1, child.height);
+
gtk_widget_size_allocate (child_widget, &child);
}
}
else
{
- /* list mode */
- guint border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
+ /* list mode; child_widget might be either priv->cell_view or a child
+ * added with gtk_container_add().
+ */
- /* button */
+ /* After the macro, button_allocation has the button allocation rect */
GTK_COMBO_BOX_SIZE_ALLOCATE_BUTTON
- /* frame */
if (is_rtl)
- child.x = allocation->x + req.width;
+ child.x = button_allocation.x + button_allocation.width;
else
child.x = allocation->x;
child.y = allocation->y;
- child.width = allocation->width - req.width;
- child.height = allocation->height;
+ child.width = allocation->width - button_allocation.width;
+ child.height = button_allocation.height;
if (priv->cell_view_frame)
{
- child.x += border.left + border_width;
- child.y += border.top + border_width;
- child.width = MAX (1, child.width - (2 * border_width) - (border.left + border.right));
- child.height = MAX (1, child.height - (2 * border_width) - (border.top + border.bottom));
gtk_widget_size_allocate (priv->cell_view_frame, &child);
- /* the sample */
+ /* restrict allocation of the child into the frame box if it's present */
if (priv->has_frame)
{
- GtkBorder frame_border;
+ GtkBorder frame_padding;
+ guint border_width;
border_width = gtk_container_get_border_width (GTK_CONTAINER (priv->cell_view_frame));
- get_widget_border (priv->cell_view_frame, &frame_border);
+ get_widget_padding_and_border (priv->cell_view_frame, &frame_padding);
- child.x += border_width + frame_border.left;
- child.y += border_width + frame_border.right;
- child.width -= (2 * border_width) + frame_border.left + frame_border.right;
- child.height -= (2 * border_width) + frame_border.top + frame_border.bottom;
+ child.x += border_width + frame_padding.left;
+ child.y += border_width + frame_padding.right;
+ child.width -= (2 * border_width) + frame_padding.left + frame_padding.right;
+ child.height -= (2 * border_width) + frame_padding.top + frame_padding.bottom;
}
}
- else
- {
- child.x += border.left + border_width;
- child.y += border.top + border_width;
- child.width -= (2 * border_width) - (border.left + border.right);
- child.height -= (2 * border_width) - (border.top + border.bottom);
- }
if (gtk_widget_get_visible (priv->popup_window))
{
gtk_widget_set_size_request (priv->popup_window, width, height);
}
+ /* allocate the child */
child.width = MAX (1, child.width);
child.height = MAX (1, child.height);
gtk_widget_size_allocate (child_widget, &child);
if (priv->shadow_type != GTK_SHADOW_NONE)
{
GtkStyleContext *context;
- GtkStateFlags state;
context = gtk_widget_get_style_context (widget);
- state = gtk_widget_get_state_flags (widget);
- gtk_style_context_set_state (context, state);
gtk_render_background (context, cr, 0, 0,
gtk_widget_get_allocated_width (widget),
priv->arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
gtk_container_add (GTK_CONTAINER (priv->box), priv->arrow);
+ gtk_widget_add_events (priv->button, GDK_SCROLL_MASK);
gtk_widget_show_all (priv->button);
}
priv->arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
gtk_container_add (GTK_CONTAINER (priv->button), priv->arrow);
+ gtk_widget_add_events (priv->button, GDK_SCROLL_MASK);
gtk_widget_show_all (priv->button);
}
(GtkTreeMenuHeaderFunc)gtk_combo_box_header_func,
combo_box, NULL);
- gtk_widget_set_name (menu, "gtk-combobox-popup-menu");
-
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);
priv->arrow = NULL;
priv->separator = NULL;
- priv->column = NULL;
-
/* changing the popup window will unref the menu and the children */
}
GtkComboBoxPrivate *priv = combo_box->priv;
if (GTK_IS_MENU (priv->popup_widget) &&
- event->type == GDK_BUTTON_PRESS && event->button == 1)
+ event->type == GDK_BUTTON_PRESS && event->button == GDK_BUTTON_PRIMARY)
{
if (priv->focus_on_click &&
!gtk_widget_has_focus (priv->button))
{
GtkStyleContext *context;
GtkStateFlags state;
- GdkRGBA *color;
+ GdkRGBA color;
- context = gtk_widget_get_style_context (widget);
+ context = gtk_widget_get_style_context (widget);
state = gtk_widget_get_state_flags (widget);
+ gtk_style_context_get_background_color (context, state, &color);
- gtk_style_context_get (context, state,
- "background-color", &color,
- NULL);
-
- gtk_cell_view_set_background_rgba (GTK_CELL_VIEW (priv->cell_view), color);
- gdk_rgba_free (color);
+ gtk_cell_view_set_background_rgba (GTK_CELL_VIEW (priv->cell_view), &color);
priv->box = gtk_event_box_new ();
gtk_event_box_set_visible_window (GTK_EVENT_BOX (priv->box),
if (priv->model)
gtk_tree_view_set_model (GTK_TREE_VIEW (priv->tree_view), priv->model);
- priv->column = gtk_tree_view_column_new_with_area (priv->area);
- gtk_tree_view_append_column (GTK_TREE_VIEW (priv->tree_view), priv->column);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (priv->tree_view),
+ gtk_tree_view_column_new_with_area (priv->area));
if (gtk_tree_row_reference_valid (priv->active_row))
{
gtk_widget_get_allocation (tree_view, &allocation);
adj = gtk_scrolled_window_get_hadjustment (GTK_SCROLLED_WINDOW (combo_box->priv->scrolled_window));
- if (adj && adj->upper - adj->lower > adj->page_size)
+ if (adj && gtk_adjustment_get_upper (adj) - gtk_adjustment_get_lower (adj) > gtk_adjustment_get_page_size (adj))
{
if (x <= allocation.x &&
- adj->lower < adj->value)
+ gtk_adjustment_get_lower (adj) < gtk_adjustment_get_value (adj))
{
- value = adj->value - (allocation.x - x + 1);
+ value = gtk_adjustment_get_value (adj) - (allocation.x - x + 1);
gtk_adjustment_set_value (adj, value);
}
else if (x >= allocation.x + allocation.width &&
- adj->upper - adj->page_size > adj->value)
+ gtk_adjustment_get_upper (adj) - gtk_adjustment_get_page_size (adj) > gtk_adjustment_get_value (adj))
{
- value = adj->value + (x - allocation.x - allocation.width + 1);
+ value = gtk_adjustment_get_value (adj) + (x - allocation.x - allocation.width + 1);
gtk_adjustment_set_value (adj, MAX (value, 0.0));
}
}
adj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (combo_box->priv->scrolled_window));
- if (adj && adj->upper - adj->lower > adj->page_size)
+ if (adj && gtk_adjustment_get_upper (adj) - gtk_adjustment_get_lower (adj) > gtk_adjustment_get_page_size (adj))
{
if (y <= allocation.y &&
- adj->lower < adj->value)
+ gtk_adjustment_get_lower (adj) < gtk_adjustment_get_value (adj))
{
- value = adj->value - (allocation.y - y + 1);
+ value = gtk_adjustment_get_value (adj) - (allocation.y - y + 1);
gtk_adjustment_set_value (adj, value);
}
else if (y >= allocation.height &&
- adj->upper - adj->page_size > adj->value)
+ gtk_adjustment_get_upper (adj) - gtk_adjustment_get_page_size (adj) > gtk_adjustment_get_value (adj))
{
- value = adj->value + (y - allocation.height + 1);
+ value = gtk_adjustment_get_value (adj) + (y - allocation.height + 1);
gtk_adjustment_set_value (adj, MAX (value, 0.0));
}
}
NULL);
if (cell_visible && cell_sensitive)
- break;
+ {
+ sensitive = TRUE;
+ break;
+ }
cell = cell->next;
}
- g_list_free (cells);
- sensitive = cell_sensitive;
+ g_list_free (cells);
}
g_list_free (columns);
/*
* GtkCellLayout implementation
*/
-GtkCellArea *
-gtk_combo_box_cell_layout_get_area (GtkCellLayout *cell_layout)
+static GtkCellArea *
+gtk_combo_box_cell_layout_get_area (GtkCellLayout *cell_layout)
{
- return GTK_COMBO_BOX (cell_layout)->priv->area;
+ GtkComboBox *combo = GTK_COMBO_BOX (cell_layout);
+ GtkComboBoxPrivate *priv = combo->priv;
+
+ if (G_UNLIKELY (!priv->area))
+ {
+ priv->area = gtk_cell_area_box_new ();
+ g_object_ref_sink (priv->area);
+ }
+
+ return priv->area;
}
/*
gtk_combo_box_entry_active_changed (GtkComboBox *combo_box,
gpointer user_data)
{
- GtkComboBoxPrivate *priv = combo_box->priv;
GtkTreeModel *model;
GtkTreeIter iter;
if (entry)
{
- GValue value = {0,};
+ GtkTreePath *path;
+ gchar *path_str;
+ gchar *text = NULL;
+
+ model = gtk_combo_box_get_model (combo_box);
+ path = gtk_tree_model_get_path (model, &iter);
+ path_str = gtk_tree_path_to_string (path);
g_signal_handlers_block_by_func (entry,
gtk_combo_box_entry_contents_changed,
combo_box);
- model = gtk_combo_box_get_model (combo_box);
- gtk_tree_model_get_value (model, &iter,
- priv->text_column, &value);
- g_object_set_property (G_OBJECT (entry), "text", &value);
- g_value_unset (&value);
+ g_signal_emit (combo_box, combo_box_signals[FORMAT_ENTRY_TEXT], 0,
+ path_str, &text);
+
+ gtk_entry_set_text (entry, text);
g_signal_handlers_unblock_by_func (entry,
gtk_combo_box_entry_contents_changed,
combo_box);
+
+ gtk_tree_path_free (path);
+ g_free (text);
+ g_free (path_str);
}
}
}
+static gchar *
+gtk_combo_box_format_entry_text (GtkComboBox *combo_box,
+ const gchar *path)
+{
+ GtkComboBoxPrivate *priv = combo_box->priv;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ gchar *text = NULL;
+
+ if (priv->text_column >= 0)
+ {
+ model = gtk_combo_box_get_model (combo_box);
+ gtk_tree_model_get_iter_from_string (model, &iter, path);
+
+ gtk_tree_model_get (model, &iter,
+ priv->text_column, &text,
+ -1);
+ }
+
+ return text;
+}
+
+
static GObject *
gtk_combo_box_constructor (GType type,
guint n_construct_properties,
GObject *object;
GtkComboBox *combo_box;
GtkComboBoxPrivate *priv;
- GtkStyleContext *context;
object = G_OBJECT_CLASS (gtk_combo_box_parent_class)->constructor
(type, n_construct_properties, construct_properties);
if (!priv->area)
{
- GtkCellArea *area = gtk_cell_area_box_new ();
-
- priv->area = g_object_ref_sink (area);
+ priv->area = gtk_cell_area_box_new ();
+ g_object_ref_sink (priv->area);
}
priv->cell_view = gtk_cell_view_new_with_context (priv->area, NULL);
gtk_combo_box_check_appearance (combo_box);
- context = gtk_widget_get_style_context (GTK_WIDGET (combo_box));
- gtk_style_context_add_class (context, GTK_STYLE_CLASS_BUTTON);
-
if (priv->has_entry)
{
GtkWidget *entry;
+ GtkStyleContext *context;
entry = gtk_entry_new ();
gtk_widget_show (entry);
gtk_container_add (GTK_CONTAINER (combo_box), entry);
+ context = gtk_widget_get_style_context (GTK_WIDGET (combo_box));
+ gtk_style_context_add_class (context, GTK_STYLE_CLASS_COMBOBOX_ENTRY);
+
priv->text_renderer = gtk_cell_renderer_text_new ();
gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo_box),
priv->text_renderer, TRUE);
*
* Since: 2.10
*/
-G_CONST_RETURN gchar*
+const gchar*
gtk_combo_box_get_title (GtkComboBox *combo_box)
{
g_return_val_if_fail (GTK_IS_COMBO_BOX (combo_box), NULL);
}
/**
- * gtk_combo_box_get_row_separator_func:
+ * gtk_combo_box_get_row_separator_func: (skip)
* @combo_box: a #GtkComboBox
*
* Returns the current row separator function.
{
GtkComboBox *combo_box = GTK_COMBO_BOX (widget);
GtkComboBoxPrivate *priv = combo_box->priv;
- gint focus_width, focus_pad;
gint font_size, arrow_size;
PangoContext *context;
PangoFontMetrics *metrics;
- PangoFontDescription *font_desc;
+ const PangoFontDescription *font_desc;
GtkWidget *child;
gint minimum_width = 0, natural_width = 0;
gint child_min, child_nat;
GtkStyleContext *style_context;
GtkStateFlags state;
- GtkBorder *border;
+ GtkBorder padding;
+ gfloat arrow_scaling;
child = gtk_bin_get_child (GTK_BIN (widget));
gtk_widget_get_preferred_width (child, &child_min, &child_nat);
gtk_widget_style_get (GTK_WIDGET (widget),
- "focus-line-width", &focus_width,
- "focus-padding", &focus_pad,
"arrow-size", &arrow_size,
+ "arrow-scaling", &arrow_scaling,
NULL);
style_context = gtk_widget_get_style_context (widget);
state = gtk_widget_get_state_flags (widget);
- gtk_style_context_get (style_context, state,
- "font", &font_desc,
- "border-width", &border,
- NULL);
+ get_widget_padding_and_border (widget, &padding);
+ font_desc = gtk_style_context_get_font (style_context, state);
context = gtk_widget_get_pango_context (GTK_WIDGET (widget));
metrics = pango_context_get_metrics (context, font_desc,
font_size = PANGO_PIXELS (pango_font_metrics_get_ascent (metrics) +
pango_font_metrics_get_descent (metrics));
pango_font_metrics_unref (metrics);
- pango_font_description_free (font_desc);
- arrow_size = MAX (arrow_size, font_size);
+ arrow_size = MAX (arrow_size, font_size) * arrow_scaling;
gtk_widget_set_size_request (priv->arrow, arrow_size, arrow_size);
/* menu mode */
if (priv->cell_view)
{
- gint sep_width, arrow_width;
- gint border_width, xpad;
- GtkBorder button_border;
-
- border_width = gtk_container_get_border_width (GTK_CONTAINER (combo_box));
- get_widget_border (priv->button, &button_border);
+ gint box_width, xpad;
+ GtkBorder button_padding;
- gtk_widget_get_preferred_width (priv->separator, &sep_width, NULL);
- gtk_widget_get_preferred_width (priv->arrow, &arrow_width, NULL);
+ get_widget_padding_and_border (priv->button, &button_padding);
- xpad = 2 * (border_width + focus_width + focus_pad) +
- button_border.left + button_border.right;
+ gtk_widget_get_preferred_width (priv->box, &box_width, NULL);
+ xpad = button_padding.left + button_padding.right + padding.left + padding.right;
- minimum_width = child_min + sep_width + arrow_width + xpad;
- natural_width = child_nat + sep_width + arrow_width + xpad;
+ minimum_width = child_min + box_width + xpad;
+ natural_width = child_nat + box_width + xpad;
}
else
{
minimum_width = child_min;
natural_width = child_nat;
- minimum_width += 2 * focus_width;
- natural_width += 2 * focus_width;
-
if (priv->cell_view_frame)
{
if (priv->has_frame)
{
gint border_width, xpad;
- GtkBorder frame_border;
+ GtkBorder frame_padding;
border_width = gtk_container_get_border_width (GTK_CONTAINER (priv->cell_view_frame));
- get_widget_border (priv->cell_view_frame, &frame_border);
- xpad = (2 * border_width) + frame_border.left + frame_border.right;
+ get_widget_padding_and_border (priv->cell_view_frame, &frame_padding);
+ xpad = (2 * border_width) + frame_padding.left + frame_padding.right;
minimum_width += xpad;
natural_width += xpad;
natural_width += button_nat_width;
}
- minimum_width += border->left + border->right;
- natural_width += border->left + border->right;
- gtk_border_free (border);
+ minimum_width += padding.left + padding.right;
+ natural_width += padding.left + padding.right;
if (minimum_size)
*minimum_size = minimum_width;
{
GtkComboBox *combo_box = GTK_COMBO_BOX (widget);
GtkComboBoxPrivate *priv = combo_box->priv;
- gint focus_width, focus_pad;
gint min_height = 0, nat_height = 0;
gint size;
GtkWidget *child;
- GtkBorder border;
-
- gtk_widget_style_get (GTK_WIDGET (widget),
- "focus-line-width", &focus_width,
- "focus-padding", &focus_pad,
- NULL);
+ GtkBorder padding;
child = gtk_bin_get_child (GTK_BIN (widget));
- get_widget_border (widget, &border);
- size = avail_size - border.left;
+ get_widget_padding_and_border (widget, &padding);
+ size = avail_size;
if (!priv->tree_view)
{
if (priv->cell_view)
{
/* calculate x/y padding and separator/arrow size */
- gint sep_width, arrow_width, sep_height, arrow_height;
- gint border_width, xpad, ypad;
- GtkBorder button_border;
+ gint box_width, box_height;
+ gint xpad, ypad;
+ GtkBorder button_padding;
- border_width = gtk_container_get_border_width (GTK_CONTAINER (combo_box));
- get_widget_border (priv->button, &button_border);
+ get_widget_padding_and_border (priv->button, &button_padding);
- gtk_widget_get_preferred_width (priv->separator, &sep_width, NULL);
- gtk_widget_get_preferred_width (priv->arrow, &arrow_width, NULL);
- gtk_widget_get_preferred_height_for_width (priv->separator,
- sep_width, &sep_height, NULL);
- gtk_widget_get_preferred_height_for_width (priv->arrow,
- arrow_width, &arrow_height, NULL);
+ gtk_widget_get_preferred_width (priv->box, &box_width, NULL);
+ gtk_widget_get_preferred_height_for_width (priv->box,
+ box_width, &box_height, NULL);
- xpad = 2 * (border_width + focus_width + focus_pad) +
- button_border.left + button_border.right;
- ypad = 2 * (border_width + focus_width + focus_pad) +
- button_border.top + button_border.bottom;
+ xpad = button_padding.left + button_padding.right;
+ ypad = button_padding.top + button_padding.bottom;
- size -= sep_width + arrow_width + xpad;
+ size -= box_width + xpad;
/* Get height-for-width of the child widget, usually a GtkCellArea calculating
* and fitting the whole treemodel */
gtk_widget_get_preferred_height_for_width (child, size, &min_height, &nat_height);
- arrow_height = MAX (arrow_height, sep_height);
- min_height = MAX (min_height, arrow_height);
- nat_height = MAX (nat_height, arrow_height);
+ min_height = MAX (min_height, box_height);
+ nat_height = MAX (nat_height, box_height);
min_height += ypad;
nat_height += ypad;
if (priv->cell_view_frame && priv->has_frame)
{
- GtkBorder frame_border;
+ GtkBorder frame_padding;
gint border_width;
border_width = gtk_container_get_border_width (GTK_CONTAINER (priv->cell_view_frame));
- get_widget_border (GTK_WIDGET (priv->cell_view_frame), &frame_border);
+ get_widget_padding_and_border (GTK_WIDGET (priv->cell_view_frame), &frame_padding);
- xpad = (2 * border_width) + border.left + frame_border.right;
- ypad = (2 * border_width) + border.top + frame_border.bottom;
+ xpad = (2 * border_width) + padding.left + frame_padding.right;
+ ypad = (2 * border_width) + padding.top + frame_padding.bottom;
}
size -= but_width;
- size -= 2 * focus_width;
size -= xpad;
/* Get height-for-width of the child widget, usually a GtkCellArea calculating
nat_height += ypad;
}
- min_height += border.top + border.bottom;
- nat_height += border.top + border.bottom;
+ min_height += padding.top + padding.bottom;
+ nat_height += padding.top + padding.bottom;
if (minimum_size)
*minimum_size = min_height;
* @combo_box: a #GtkComboBox
*
* Returns the ID of the active row of @combo_box. This value is taken
- * from the active row and the column specified by the 'id-column'
+ * from the active row and the column specified by the #GtkComboBox:id-column
* property of @combo_box (see gtk_combo_box_set_id_column()).
*
* The returned value is an interned string which means that you can
* compare the pointer by value to other interned strings and that you
* must not free it.
*
- * If the 'id-column' property of @combo_box is not set or if no row is
- * selected then %NULL is returned.
+ * If the #GtkComboBox:id-column property of @combo_box is not set, or if
+ * no row is active, or if the active row has a %NULL ID value, then %NULL
+ * is returned.
*
* Return value: the ID of the active row, or %NULL
*
GtkTreeIter iter;
gint column;
- g_return_val_if_fail (GTK_IS_COMBO_BOX (combo_box), 0);
+ g_return_val_if_fail (GTK_IS_COMBO_BOX (combo_box), NULL);
column = combo_box->priv->id_column;
/**
* gtk_combo_box_set_active_id:
* @combo_box: a #GtkComboBox
- * @active_id: the ID of the row to select
+ * @active_id: (allow-none): the ID of the row to select, or %NULL
+ *
+ * Changes the active row of @combo_box to the one that has an ID equal to
+ * @active_id, or unsets the active row if @active_id is %NULL. Rows having
+ * a %NULL ID string cannot be made active by this function.
*
- * Changes the active row of @combo_box to the one that has an ID equal to @id.
+ * If the #GtkComboBox:id-column property of @combo_box is unset or if no
+ * row has the given ID then the function does nothing and returns %FALSE.
*
- * If the 'id-column' property of @combo_box is unset or if no row has
- * the given ID then nothing happens.
+ * Returns: %TRUE if a row with a matching ID was found. If a %NULL
+ * @active_id was given to unset the active row, the function
+ * always returns %TRUE.
*
* Since: 3.0
**/
-void
+gboolean
gtk_combo_box_set_active_id (GtkComboBox *combo_box,
const gchar *active_id)
{
GtkTreeModel *model;
GtkTreeIter iter;
+ gboolean match = FALSE;
gint column;
- g_return_if_fail (GTK_IS_COMBO_BOX (combo_box));
+ g_return_val_if_fail (GTK_IS_COMBO_BOX (combo_box), FALSE);
+
+ if (active_id == NULL)
+ {
+ gtk_combo_box_set_active (combo_box, -1);
+ return TRUE; /* active row was successfully unset */
+ }
column = combo_box->priv->id_column;
if (column < 0)
- return;
+ return FALSE;
model = gtk_combo_box_get_model (combo_box);
- g_return_if_fail (gtk_tree_model_get_column_type (model, column) ==
- G_TYPE_STRING);
+ g_return_val_if_fail (gtk_tree_model_get_column_type (model, column) ==
+ G_TYPE_STRING, FALSE);
if (gtk_tree_model_get_iter_first (model, &iter))
do {
- gboolean match;
gchar *id;
gtk_tree_model_get (model, &iter, column, &id, -1);
- match = strcmp (id, active_id) == 0;
+ if (id != NULL)
+ match = strcmp (id, active_id) == 0;
g_free (id);
if (match)
break;
}
} while (gtk_tree_model_iter_next (model, &iter));
+
+ return match;
}