* Boston, MA 02111-1307, USA.
*/
-#include <config.h>
+#include "config.h"
#include <string.h>
#include <atk/atk.h>
#include "gtkbindings.h"
#include "gtkdnd.h"
#include "gtkmain.h"
-#include "gtksignal.h"
#include "gtkintl.h"
#include "gtkaccessible.h"
#include "gtkwindow.h"
gint pixbuf_cell;
gint text_cell;
+ gint tooltip_column;
+
/* Drag-and-drop. */
GdkModifierType start_button_mask;
gint pressed_button;
PROP_ROW_SPACING,
PROP_COLUMN_SPACING,
PROP_MARGIN,
- PROP_REORDERABLE
+ PROP_REORDERABLE,
+ PROP_TOOLTIP_COLUMN
};
/* GObject vfuncs */
GtkIconViewItem *item,
GtkIconViewCellInfo *cell_info,
GdkEvent *event);
+static void gtk_icon_view_item_selected_changed (GtkIconView *icon_view,
+ GtkIconViewItem *item);
static void gtk_icon_view_put (GtkIconView *icon_view,
GtkWidget *widget,
GtkIconViewItem *item,
FALSE,
G_PARAM_READWRITE));
+ g_object_class_install_property (gobject_class,
+ PROP_TOOLTIP_COLUMN,
+ g_param_spec_int ("tooltip-column",
+ P_("Tooltip Column"),
+ P_("The column in the model containing the tooltip texts for the items"),
+ -1,
+ G_MAXINT,
+ -1,
+ GTK_PARAM_READWRITE));
+
+
+
/* Style properties */
gtk_widget_class_install_style_property (widget_class,
g_param_spec_boxed ("selection-box-color",
"unselect_all", 0);
gtk_binding_entry_add_signal (binding_set, GDK_space, GDK_CONTROL_MASK,
"toggle_cursor_item", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KP_Space, GDK_CONTROL_MASK,
+ "toggle_cursor_item", 0);
gtk_binding_entry_add_signal (binding_set, GDK_space, 0,
"activate_cursor_item", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KP_Space, 0,
+ "activate_cursor_item", 0);
gtk_binding_entry_add_signal (binding_set, GDK_Return, 0,
"activate_cursor_item", 0);
gtk_binding_entry_add_signal (binding_set, GDK_ISO_Enter, 0,
icon_view->priv->pixbuf_column = -1;
icon_view->priv->text_cell = -1;
icon_view->priv->pixbuf_cell = -1;
+ icon_view->priv->tooltip_column = -1;
GTK_WIDGET_SET_FLAGS (icon_view, GTK_CAN_FOCUS);
gtk_icon_view_set_reorderable (icon_view, g_value_get_boolean (value));
break;
+ case PROP_TOOLTIP_COLUMN:
+ gtk_icon_view_set_tooltip_column (icon_view, g_value_get_int (value));
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
case PROP_REORDERABLE:
g_value_set_boolean (value, icon_view->priv->reorderable);
break;
+ case PROP_TOOLTIP_COLUMN:
+ g_value_set_int (value, icon_view->priv->tooltip_column);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
gtk_icon_view_style_set (GtkWidget *widget,
GtkStyle *previous_style)
{
- GtkIconView *icon_view;
-
- g_return_if_fail (GTK_IS_ICON_VIEW (widget));
-
- icon_view = GTK_ICON_VIEW (widget);
+ GtkIconView *icon_view = GTK_ICON_VIEW (widget);
if (GTK_WIDGET_REALIZED (widget))
{
gtk_icon_view_size_request (GtkWidget *widget,
GtkRequisition *requisition)
{
- GtkIconView *icon_view;
+ GtkIconView *icon_view = GTK_ICON_VIEW (widget);
GList *tmp_list;
- icon_view = GTK_ICON_VIEW (widget);
-
requisition->width = icon_view->priv->width;
requisition->height = icon_view->priv->height;
}
}
+static void
+gtk_icon_view_item_selected_changed (GtkIconView *icon_view,
+ GtkIconViewItem *item)
+{
+ AtkObject *obj;
+ AtkObject *item_obj;
+
+ obj = gtk_widget_get_accessible (GTK_WIDGET (icon_view));
+ if (obj != NULL)
+ {
+ item_obj = atk_object_ref_accessible_child (obj, item->index);
+ if (item_obj != NULL)
+ {
+ atk_object_notify_state_change (item_obj, ATK_STATE_SELECTED, item->selected);
+ g_object_unref (item_obj);
+ }
+ }
+}
+
static void
gtk_icon_view_put (GtkIconView *icon_view,
GtkWidget *widget,
GList *l;
GdkRectangle box;
+ if (MIN (x + width, item->x + item->width) - MAX (x, item->x) <= 0 ||
+ MIN (y + height, item->y + item->height) - MAX (y, item->y) <= 0)
+ return FALSE;
+
for (l = icon_view->priv->cell_list; l; l = l->next)
{
GtkIconViewCellInfo *info = (GtkIconViewCellInfo *)l->data;
item->selected = FALSE;
dirty = TRUE;
gtk_icon_view_queue_draw_item (icon_view, item);
+ gtk_icon_view_item_selected_changed (icon_view, item);
}
}
icon_view->priv->cursor_item->selected = !icon_view->priv->cursor_item->selected;
g_signal_emit (icon_view, icon_view_signals[SELECTION_CHANGED], 0);
+ gtk_icon_view_item_selected_changed (icon_view, icon_view->priv->cursor_item);
gtk_icon_view_queue_draw_item (icon_view, icon_view->priv->cursor_item);
break;
}
GtkIconViewCellInfo *info,
GdkRectangle *cell_area)
{
+ g_return_if_fail (info->position < item->n_cells);
+
if (icon_view->priv->orientation == GTK_ORIENTATION_HORIZONTAL)
{
cell_area->x = item->box[info->position].x - item->before[info->position];
GtkIconViewCellInfo *info,
GdkRectangle *box)
{
+ g_return_if_fail (info->position < item->n_cells);
+
*box = item->box[info->position];
}
gint y,
gboolean draw_focus)
{
- gint focus_width, focus_pad;
+ gint focus_width;
gint padding;
GdkRectangle cell_area, box;
GList *l;
gtk_widget_style_get (GTK_WIDGET (icon_view),
"focus-line-width", &focus_width,
- "focus-padding", &focus_pad,
NULL);
padding = focus_width;
{
AtkObject *obj;
AtkObject *item_obj;
+ AtkObject *cursor_item_obj;
if (icon_view->priv->cursor_item == item &&
(cursor_cell < 0 || cursor_cell == icon_view->priv->cursor_cell))
return;
+ obj = gtk_widget_get_accessible (GTK_WIDGET (icon_view));
if (icon_view->priv->cursor_item != NULL)
- gtk_icon_view_queue_draw_item (icon_view, icon_view->priv->cursor_item);
-
+ {
+ gtk_icon_view_queue_draw_item (icon_view, icon_view->priv->cursor_item);
+ if (obj != NULL)
+ {
+ cursor_item_obj = atk_object_ref_accessible_child (obj, icon_view->priv->cursor_item->index);
+ if (cursor_item_obj != NULL)
+ atk_object_notify_state_change (cursor_item_obj, ATK_STATE_FOCUSED, FALSE);
+ }
+ }
icon_view->priv->cursor_item = item;
if (cursor_cell >= 0)
icon_view->priv->cursor_cell = cursor_cell;
gtk_icon_view_queue_draw_item (icon_view, item);
/* Notify that accessible focus object has changed */
- obj = gtk_widget_get_accessible (GTK_WIDGET (icon_view));
item_obj = atk_object_ref_accessible_child (obj, item->index);
if (item_obj != NULL)
{
atk_focus_tracker_notify (item_obj);
+ atk_object_notify_state_change (item_obj, ATK_STATE_FOCUSED, TRUE);
g_object_unref (item_obj);
}
}
item->selected = TRUE;
- gtk_icon_view_queue_draw_item (icon_view, item);
-
+ gtk_icon_view_item_selected_changed (icon_view, item);
g_signal_emit (icon_view, icon_view_signals[SELECTION_CHANGED], 0);
+
+ gtk_icon_view_queue_draw_item (icon_view, item);
}
item->selected = FALSE;
+ gtk_icon_view_item_selected_changed (icon_view, item);
g_signal_emit (icon_view, icon_view_signals[SELECTION_CHANGED], 0);
gtk_icon_view_queue_draw_item (icon_view, item);
col1 <= item->col && item->col <= col2)
{
if (!item->selected)
- dirty = TRUE;
-
- item->selected = TRUE;
-
+ {
+ dirty = TRUE;
+ item->selected = TRUE;
+ gtk_icon_view_item_selected_changed (icon_view, item);
+ }
gtk_icon_view_queue_draw_item (icon_view, item);
}
}
g_return_if_fail (link != NULL);
- icon_view->priv->cell_list = g_list_remove_link (icon_view->priv->cell_list,
- link);
+ icon_view->priv->cell_list = g_list_delete_link (icon_view->priv->cell_list,
+ link);
icon_view->priv->cell_list = g_list_insert (icon_view->priv->cell_list,
info, position);
{
GtkIconViewItem *item;
GtkTreePath *path;
- gint px, py;
g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), NULL);
return (item != NULL);
}
+/**
+ * gtk_icon_view_set_tooltip_item:
+ * @icon_view: a #GtkIconView
+ * @tooltip: a #GtkTooltip
+ * @path: a #GtkTreePath
+ *
+ * Sets the tip area of @tooltip to be the area covered by the item at @path.
+ * See also gtk_tooltip_set_tip_area().
+ *
+ * Since: 2.12
+ */
+void
+gtk_icon_view_set_tooltip_item (GtkIconView *icon_view,
+ GtkTooltip *tooltip,
+ GtkTreePath *path)
+{
+ g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
+ g_return_if_fail (GTK_IS_TOOLTIP (tooltip));
+
+ gtk_icon_view_set_tooltip_cell (icon_view, tooltip, path, NULL);
+}
+
+/**
+ * gtk_icon_view_set_tooltip_cell:
+ * @icon_view: a #GtkIconView
+ * @tooltip: a #GtkTooltip
+ * @path: a #GtkTreePath
+ * @cell: a #GtkCellRenderer or %NULL
+ *
+ * Sets the tip area of @tooltip to the area which @cell occupies in
+ * the item pointed to by @path. See also gtk_tooltip_set_tip_area().
+ *
+ * Since: 2.12
+ */
+void
+gtk_icon_view_set_tooltip_cell (GtkIconView *icon_view,
+ GtkTooltip *tooltip,
+ GtkTreePath *path,
+ GtkCellRenderer *cell)
+{
+ GdkRectangle rect;
+ GtkIconViewItem *item = NULL;
+ GtkIconViewCellInfo *info = NULL;
+ gint x, y;
+
+ g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
+ g_return_if_fail (GTK_IS_TOOLTIP (tooltip));
+ g_return_if_fail (cell == NULL || GTK_IS_CELL_RENDERER (cell));
+
+ if (gtk_tree_path_get_depth (path) > 0)
+ item = g_list_nth_data (icon_view->priv->items,
+ gtk_tree_path_get_indices(path)[0]);
+
+ if (!item)
+ return;
+
+ if (cell)
+ {
+ info = gtk_icon_view_get_cell_info (icon_view, cell);
+ gtk_icon_view_get_cell_area (icon_view, item, info, &rect);
+ }
+ else
+ {
+ rect.x = item->x;
+ rect.y = item->y;
+ rect.width = item->width;
+ rect.height = item->height;
+ }
+
+ if (icon_view->priv->bin_window)
+ {
+ gdk_window_get_position (icon_view->priv->bin_window, &x, &y);
+ rect.x += x;
+ rect.y += y;
+ }
+
+ gtk_tooltip_set_tip_area (tooltip, &rect);
+}
+
+
+/**
+ * gtk_icon_view_get_tooltip_context:
+ * @icon_view: an #GtkIconView
+ * @x: the x coordinate (relative to widget coordinates)
+ * @y: the y coordinate (relative to widget coordinates)
+ * @keyboard_tip: whether this is a keyboard tooltip or not
+ * @model: a pointer to receive a #GtkTreeModel or %NULL
+ * @path: a pointer to receive a #GtkTreePath or %NULL
+ * @iter: a pointer to receive a #GtkTreeIter or %NULL
+ *
+ * This function is supposed to be used in a #GtkWidget::query-tooltip
+ * signal handler for #GtkIconView. The @x, @y and @keyboard_tip values
+ * which are received in the signal handler, should be passed to this
+ * function without modification.
+ *
+ * The return value indicates whether there is an icon view item at the given
+ * coordinates (%TRUE) or not (%FALSE) for mouse tooltips. For keyboard
+ * tooltips the item returned will be the cursor item. When %TRUE, then any of
+ * @model, @path and @iter which have been provided will be set to point to
+ * that row and the corresponding model. @x and @y will always be converted
+ * to be relative to @icon_view's bin_window if @keyboard_tooltip is %FALSE.
+ *
+ * Return value: whether or not the given tooltip context points to a item
+ *
+ * Since: 2.12
+ */
+gboolean
+gtk_icon_view_get_tooltip_context (GtkIconView *icon_view,
+ gint *x,
+ gint *y,
+ gboolean keyboard_tip,
+ GtkTreeModel **model,
+ GtkTreePath **path,
+ GtkTreeIter *iter)
+{
+ GtkTreePath *tmppath = NULL;
+
+ g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), FALSE);
+ g_return_val_if_fail (x != NULL, FALSE);
+ g_return_val_if_fail (y != NULL, FALSE);
+
+ if (keyboard_tip)
+ {
+ gtk_icon_view_get_cursor (icon_view, &tmppath, NULL);
+
+ if (!tmppath)
+ return FALSE;
+ }
+ else
+ {
+ gtk_icon_view_convert_widget_to_bin_window_coords (icon_view, *x, *y,
+ x, y);
+
+ if (!gtk_icon_view_get_item_at_pos (icon_view, *x, *y, &tmppath, NULL))
+ return FALSE;
+ }
+
+ if (model)
+ *model = gtk_icon_view_get_model (icon_view);
+
+ if (iter)
+ gtk_tree_model_get_iter (gtk_icon_view_get_model (icon_view),
+ iter, tmppath);
+
+ if (path)
+ *path = tmppath;
+ else
+ gtk_tree_path_free (tmppath);
+
+ return TRUE;
+}
+
+static gboolean
+gtk_icon_view_set_tooltip_query_cb (GtkWidget *widget,
+ gint x,
+ gint y,
+ gboolean keyboard_tip,
+ GtkTooltip *tooltip,
+ gpointer data)
+{
+ gchar *str;
+ GtkTreeIter iter;
+ GtkTreePath *path;
+ GtkTreeModel *model;
+ GtkIconView *icon_view = GTK_ICON_VIEW (widget);
+
+ if (!gtk_icon_view_get_tooltip_context (GTK_ICON_VIEW (widget),
+ &x, &y,
+ keyboard_tip,
+ &model, &path, &iter))
+ return FALSE;
+
+ gtk_tree_model_get (model, &iter, icon_view->priv->tooltip_column, &str, -1);
+
+ if (!str)
+ {
+ gtk_tree_path_free (path);
+ return FALSE;
+ }
+
+ gtk_tooltip_set_markup (tooltip, str);
+ gtk_icon_view_set_tooltip_item (icon_view, tooltip, path);
+
+ gtk_tree_path_free (path);
+ g_free (str);
+
+ return TRUE;
+}
+
+
+/**
+ * gtk_icon_view_set_tooltip_column:
+ * @icon_view: a #GtkIconView
+ *
+ * @column: an integer, which is a valid column number for @icon_view's model
+ *
+ * If you only plan to have simple (text-only) tooltips on full items, you
+ * can use this function to have #GtkIconView handle these automatically
+ * for you. @column should be set to the column in @icon_view's model
+ * containing the tooltip texts, or -1 to disable this feature.
+ *
+ * When enabled, #GtkWidget::has-tooltip will be set to %TRUE and
+ * @icon_view will connect a #GtkWidget::query-tooltip signal handler.
+ *
+ * Since: 2.12
+ */
+void
+gtk_icon_view_set_tooltip_column (GtkIconView *icon_view,
+ gint column)
+{
+ g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
+
+ if (column == icon_view->priv->tooltip_column)
+ return;
+
+ if (column == -1)
+ {
+ g_signal_handlers_disconnect_by_func (icon_view,
+ gtk_icon_view_set_tooltip_query_cb,
+ NULL);
+ gtk_widget_set_has_tooltip (GTK_WIDGET (icon_view), FALSE);
+ }
+ else
+ {
+ if (icon_view->priv->tooltip_column == -1)
+ {
+ g_signal_connect (icon_view, "query-tooltip",
+ G_CALLBACK (gtk_icon_view_set_tooltip_query_cb), NULL);
+ gtk_widget_set_has_tooltip (GTK_WIDGET (icon_view), TRUE);
+ }
+ }
+
+ icon_view->priv->tooltip_column = column;
+ g_object_notify (G_OBJECT (icon_view), "tooltip-column");
+}
+
+/**
+ * gtk_icon_view_get_tooltip_column:
+ * @icon_view: a #GtkIconView
+ *
+ * Returns the column of @icon_view's model which is being used for
+ * displaying tooltips on @icon_view's rows.
+ *
+ * Return value: the index of the tooltip column that is currently being
+ * used, or -1 if this is disabled.
+ *
+ * Since: 2.12
+ */
+gint
+gtk_icon_view_get_tooltip_column (GtkIconView *icon_view)
+{
+ g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), 0);
+
+ return icon_view->priv->tooltip_column;
+}
/**
* gtk_icon_view_get_visible_range:
* To do this, you can use gtk_tree_row_reference_new().
*
* To free the return value, use:
- * <informalexample><programlisting>
+ * |[
* g_list_foreach (list, gtk_tree_path_free, NULL);
* g_list_free (list);
- * </programlisting></informalexample>
+ * ]|
*
* Return value: A #GList containing a #GtkTreePath for each selected row.
*
atk_state_set_add_state (item->state_set, ATK_STATE_FOCUSED);
else
atk_state_set_remove_state (item->state_set, ATK_STATE_FOCUSED);
+ if (item->item->selected)
+ atk_state_set_add_state (item->state_set, ATK_STATE_SELECTED);
+ else
+ atk_state_set_remove_state (item->state_set, ATK_STATE_SELECTED);
return g_object_ref (item->state_set);
}