mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2025-01-01 00:11:29 +00:00
Merge branch 'rubberband-again' into 'master'
Rubberband again See merge request GNOME/gtk!2041
This commit is contained in:
commit
60d6a0f2d5
@ -34,13 +34,13 @@
|
||||
#include "gtksnapshot.h"
|
||||
#include "gtkmultiselection.h"
|
||||
#include "gtkgizmoprivate.h"
|
||||
#include "gtkset.h"
|
||||
|
||||
typedef struct _RubberbandData RubberbandData;
|
||||
|
||||
struct _RubberbandData
|
||||
{
|
||||
GtkWidget *widget;
|
||||
GtkSelectionModel *selection;
|
||||
double x1, y1;
|
||||
double x2, y2;
|
||||
gboolean modify;
|
||||
@ -53,7 +53,6 @@ rubberband_data_free (gpointer data)
|
||||
RubberbandData *rdata = data;
|
||||
|
||||
g_clear_pointer (&rdata->widget, gtk_widget_unparent);
|
||||
g_clear_object (&rdata->selection);
|
||||
g_free (rdata);
|
||||
}
|
||||
|
||||
@ -1324,7 +1323,6 @@ gtk_list_base_start_rubberband (GtkListBase *self,
|
||||
{
|
||||
GtkListBasePrivate *priv = gtk_list_base_get_instance_private (self);
|
||||
double value_x, value_y;
|
||||
GtkSelectionModel *selection;
|
||||
|
||||
if (priv->rubberband)
|
||||
return;
|
||||
@ -1343,24 +1341,66 @@ gtk_list_base_start_rubberband (GtkListBase *self,
|
||||
priv->rubberband->widget = gtk_gizmo_new ("rubberband",
|
||||
NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
gtk_widget_set_parent (priv->rubberband->widget, GTK_WIDGET (self));
|
||||
}
|
||||
|
||||
selection = gtk_list_item_manager_get_model (priv->item_manager);
|
||||
if ((modify || extend) &&
|
||||
GTK_IS_MULTI_SELECTION (selection))
|
||||
priv->rubberband->selection = GTK_SELECTION_MODEL (gtk_multi_selection_copy (selection));
|
||||
static void
|
||||
range_cb (guint position,
|
||||
guint *start,
|
||||
guint *n_items,
|
||||
gboolean *selected,
|
||||
gpointer data)
|
||||
{
|
||||
GtkSet *set = data;
|
||||
|
||||
if (!modify && !extend)
|
||||
gtk_selection_model_unselect_all (selection);
|
||||
gtk_set_find_range (set, position, gtk_set_get_max (set), start, n_items, selected);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_list_base_stop_rubberband (GtkListBase *self)
|
||||
{
|
||||
GtkListBasePrivate *priv = gtk_list_base_get_instance_private (self);
|
||||
GtkListItemManagerItem *item;
|
||||
GtkSelectionModel *model;
|
||||
GtkSet *active;
|
||||
|
||||
if (!priv->rubberband)
|
||||
return;
|
||||
|
||||
active = gtk_set_new ();
|
||||
|
||||
for (item = gtk_list_item_manager_get_first (priv->item_manager);
|
||||
item != NULL;
|
||||
item = gtk_rb_tree_node_get_next (item))
|
||||
{
|
||||
if (!item->widget)
|
||||
continue;
|
||||
|
||||
if (gtk_widget_get_state_flags (item->widget) & GTK_STATE_FLAG_ACTIVE)
|
||||
{
|
||||
guint pos;
|
||||
|
||||
pos = gtk_list_item_manager_get_item_position (priv->item_manager, item);
|
||||
gtk_set_add_item (active, pos);
|
||||
gtk_widget_unset_state_flags (item->widget, GTK_STATE_FLAG_ACTIVE);
|
||||
}
|
||||
}
|
||||
|
||||
model = gtk_list_item_manager_get_model (priv->item_manager);
|
||||
|
||||
if (priv->rubberband->modify)
|
||||
{
|
||||
gtk_selection_model_unselect_callback (model, range_cb, active);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!priv->rubberband->extend)
|
||||
gtk_selection_model_unselect_all (model);
|
||||
|
||||
gtk_selection_model_select_callback (model, range_cb, active);
|
||||
}
|
||||
|
||||
gtk_set_free (active);
|
||||
|
||||
g_clear_pointer (&priv->rubberband, rubberband_data_free);
|
||||
remove_autoscroll (self);
|
||||
|
||||
@ -1423,55 +1463,24 @@ gtk_list_base_update_rubberband_selection (GtkListBase *self)
|
||||
GtkListBasePrivate *priv = gtk_list_base_get_instance_private (self);
|
||||
GdkRectangle rect;
|
||||
GdkRectangle alloc;
|
||||
GtkSelectionModel *model;
|
||||
GtkListItemManagerItem *item;
|
||||
|
||||
gtk_list_base_allocate_rubberband (self);
|
||||
gtk_widget_get_allocation (priv->rubberband->widget, &rect);
|
||||
|
||||
model = gtk_list_item_manager_get_model (priv->item_manager);
|
||||
|
||||
for (item = gtk_list_item_manager_get_first (priv->item_manager);
|
||||
item != NULL;
|
||||
item = gtk_rb_tree_node_get_next (item))
|
||||
{
|
||||
guint pos;
|
||||
gboolean selected;
|
||||
gboolean was_selected;
|
||||
|
||||
if (!item->widget)
|
||||
continue;
|
||||
|
||||
pos = gtk_list_item_manager_get_item_position (priv->item_manager, item);
|
||||
|
||||
gtk_widget_get_allocation (item->widget, &alloc);
|
||||
|
||||
if (priv->rubberband->selection)
|
||||
was_selected = gtk_selection_model_is_selected (priv->rubberband->selection, pos);
|
||||
if (gdk_rectangle_intersect (&rect, &alloc, &alloc))
|
||||
gtk_widget_set_state_flags (item->widget, GTK_STATE_FLAG_ACTIVE, FALSE);
|
||||
else
|
||||
was_selected = FALSE;
|
||||
|
||||
selected = gdk_rectangle_intersect (&rect, &alloc, &alloc);
|
||||
|
||||
if (priv->rubberband->modify)
|
||||
{
|
||||
if (was_selected)
|
||||
{
|
||||
if (selected)
|
||||
gtk_selection_model_unselect_item (model, pos);
|
||||
else
|
||||
gtk_selection_model_select_item (model, pos, FALSE);
|
||||
}
|
||||
else
|
||||
gtk_selection_model_unselect_item (model, pos);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (selected || was_selected)
|
||||
gtk_selection_model_select_item (model, pos, FALSE);
|
||||
else
|
||||
gtk_selection_model_unselect_item (model, pos);
|
||||
}
|
||||
gtk_widget_unset_state_flags (item->widget, GTK_STATE_FLAG_ACTIVE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -167,6 +167,61 @@ gtk_multi_selection_unselect_all (GtkSelectionModel *model)
|
||||
return gtk_multi_selection_unselect_range (model, 0, g_list_model_get_n_items (G_LIST_MODEL (model)));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_multi_selection_add_or_remove (GtkSelectionModel *model,
|
||||
gboolean add,
|
||||
GtkSelectionCallback callback,
|
||||
gpointer data)
|
||||
{
|
||||
GtkMultiSelection *self = GTK_MULTI_SELECTION (model);
|
||||
guint pos, start, n;
|
||||
gboolean in;
|
||||
guint min, max;
|
||||
|
||||
min = G_MAXUINT;
|
||||
max = 0;
|
||||
|
||||
pos = 0;
|
||||
do
|
||||
{
|
||||
callback (pos, &start, &n, &in, data);
|
||||
if (in)
|
||||
{
|
||||
if (start < min)
|
||||
min = start;
|
||||
if (start + n - 1 > max)
|
||||
max = start + n - 1;
|
||||
|
||||
if (add)
|
||||
gtk_set_add_range (self->selected, start, n);
|
||||
else
|
||||
gtk_set_remove_range (self->selected, start, n);
|
||||
}
|
||||
pos = start + n;
|
||||
}
|
||||
while (n > 0);
|
||||
|
||||
gtk_selection_model_selection_changed (model, min, max - min + 1);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_multi_selection_select_callback (GtkSelectionModel *model,
|
||||
GtkSelectionCallback callback,
|
||||
gpointer data)
|
||||
{
|
||||
return gtk_multi_selection_add_or_remove (model, TRUE, callback, data);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_multi_selection_unselect_callback (GtkSelectionModel *model,
|
||||
GtkSelectionCallback callback,
|
||||
gpointer data)
|
||||
{
|
||||
return gtk_multi_selection_add_or_remove (model, FALSE, callback, data);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_multi_selection_query_range (GtkSelectionModel *model,
|
||||
guint position,
|
||||
@ -190,6 +245,8 @@ gtk_multi_selection_selection_model_init (GtkSelectionModelInterface *iface)
|
||||
iface->unselect_range = gtk_multi_selection_unselect_range;
|
||||
iface->select_all = gtk_multi_selection_select_all;
|
||||
iface->unselect_all = gtk_multi_selection_unselect_all;
|
||||
iface->select_callback = gtk_multi_selection_select_callback;
|
||||
iface->unselect_callback = gtk_multi_selection_unselect_callback;
|
||||
iface->query_range = gtk_multi_selection_query_range;
|
||||
}
|
||||
|
||||
@ -330,51 +387,3 @@ gtk_multi_selection_new (GListModel *model)
|
||||
"model", model,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_multi_selection_copy:
|
||||
* @selection: the #GtkSelectionModel to copy
|
||||
*
|
||||
* Creates a #GtkMultiSelection that has the same underlying
|
||||
* model and the same selected items as @selection.
|
||||
*
|
||||
* Returns: (transfer full): a new #GtkMultiSelection
|
||||
*/
|
||||
GtkMultiSelection *
|
||||
gtk_multi_selection_copy (GtkSelectionModel *selection)
|
||||
{
|
||||
GtkMultiSelection *copy;
|
||||
GListModel *model;
|
||||
|
||||
g_object_get (selection, "model", &model, NULL);
|
||||
|
||||
copy = GTK_MULTI_SELECTION (gtk_multi_selection_new (model));
|
||||
|
||||
if (GTK_IS_MULTI_SELECTION (selection))
|
||||
{
|
||||
GtkMultiSelection *multi = GTK_MULTI_SELECTION (selection);
|
||||
|
||||
gtk_set_free (copy->selected);
|
||||
copy->selected = gtk_set_copy (multi->selected);
|
||||
copy->last_selected = multi->last_selected;
|
||||
}
|
||||
else
|
||||
{
|
||||
guint pos, n;
|
||||
guint start, n_items;
|
||||
gboolean selected;
|
||||
|
||||
n = g_list_model_get_n_items (model);
|
||||
n_items = 0;
|
||||
for (pos = 0; pos < n; pos += n_items)
|
||||
{
|
||||
gtk_selection_model_query_range (selection, pos, &start, &n_items, &selected);
|
||||
if (selected)
|
||||
gtk_selection_model_select_range (GTK_SELECTION_MODEL (copy), start, n_items, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
g_object_unref (model);
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
@ -33,8 +33,6 @@ G_DECLARE_FINAL_TYPE (GtkMultiSelection, gtk_multi_selection, GTK, MULTI_SELECTI
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GListModel * gtk_multi_selection_new (GListModel *model);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkMultiSelection * gtk_multi_selection_copy (GtkSelectionModel *selection);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
@ -113,6 +113,22 @@ gtk_selection_model_default_unselect_range (GtkSelectionModel *model,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_selection_model_default_select_callback (GtkSelectionModel *model,
|
||||
GtkSelectionCallback callback,
|
||||
gpointer data)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_selection_model_default_unselect_callback (GtkSelectionModel *model,
|
||||
GtkSelectionCallback callback,
|
||||
gpointer data)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_selection_model_default_select_all (GtkSelectionModel *model)
|
||||
{
|
||||
@ -142,20 +158,22 @@ gtk_selection_model_default_query_range (GtkSelectionModel *model,
|
||||
else
|
||||
{
|
||||
*n_items = 1;
|
||||
*selected = gtk_selection_model_is_selected (model, position);
|
||||
*selected = gtk_selection_model_is_selected (model, position);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_selection_model_default_init (GtkSelectionModelInterface *iface)
|
||||
{
|
||||
iface->is_selected = gtk_selection_model_default_is_selected;
|
||||
iface->select_item = gtk_selection_model_default_select_item;
|
||||
iface->unselect_item = gtk_selection_model_default_unselect_item;
|
||||
iface->select_range = gtk_selection_model_default_select_range;
|
||||
iface->unselect_range = gtk_selection_model_default_unselect_range;
|
||||
iface->select_all = gtk_selection_model_default_select_all;
|
||||
iface->unselect_all = gtk_selection_model_default_unselect_all;
|
||||
iface->is_selected = gtk_selection_model_default_is_selected;
|
||||
iface->select_item = gtk_selection_model_default_select_item;
|
||||
iface->unselect_item = gtk_selection_model_default_unselect_item;
|
||||
iface->select_range = gtk_selection_model_default_select_range;
|
||||
iface->unselect_range = gtk_selection_model_default_unselect_range;
|
||||
iface->select_all = gtk_selection_model_default_select_all;
|
||||
iface->unselect_all = gtk_selection_model_default_unselect_all;
|
||||
iface->select_callback = gtk_selection_model_default_select_callback;
|
||||
iface->unselect_callback = gtk_selection_model_default_unselect_callback;
|
||||
iface->query_range = gtk_selection_model_default_query_range;
|
||||
|
||||
/**
|
||||
@ -324,6 +342,26 @@ gtk_selection_model_unselect_all (GtkSelectionModel *model)
|
||||
return iface->unselect_all (model);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gtk_selection_model_select_callback (GtkSelectionModel *model,
|
||||
GtkSelectionCallback callback,
|
||||
gpointer data)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_SELECTION_MODEL (model), FALSE);
|
||||
|
||||
return GTK_SELECTION_MODEL_GET_IFACE (model)->select_callback (model, callback, data);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gtk_selection_model_unselect_callback (GtkSelectionModel *model,
|
||||
GtkSelectionCallback callback,
|
||||
gpointer data)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_SELECTION_MODEL (model), FALSE);
|
||||
|
||||
return GTK_SELECTION_MODEL_GET_IFACE (model)->unselect_callback (model, callback, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_selection_model_query_range:
|
||||
* @model: a #GtkSelectionModel
|
||||
|
@ -29,10 +29,17 @@
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_SELECTION_MODEL (gtk_selection_model_get_type ())
|
||||
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
G_DECLARE_INTERFACE (GtkSelectionModel, gtk_selection_model, GTK, SELECTION_MODEL, GListModel)
|
||||
|
||||
typedef void (* GtkSelectionCallback) (guint position,
|
||||
guint *start_range,
|
||||
guint *n_items,
|
||||
gboolean *selected,
|
||||
gpointer data);
|
||||
|
||||
|
||||
/**
|
||||
* GtkSelectionModelInterface:
|
||||
* @is_selected: Return if the item at the given position is selected.
|
||||
@ -79,6 +86,12 @@ struct _GtkSelectionModelInterface
|
||||
guint n_items);
|
||||
gboolean (* select_all) (GtkSelectionModel *model);
|
||||
gboolean (* unselect_all) (GtkSelectionModel *model);
|
||||
gboolean (* select_callback) (GtkSelectionModel *model,
|
||||
GtkSelectionCallback callback,
|
||||
gpointer data);
|
||||
gboolean (* unselect_callback) (GtkSelectionModel *model,
|
||||
GtkSelectionCallback callback,
|
||||
gpointer data);
|
||||
void (* query_range) (GtkSelectionModel *model,
|
||||
guint position,
|
||||
guint *start_range,
|
||||
@ -111,6 +124,14 @@ gboolean gtk_selection_model_select_all (GtkSelectionMod
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gtk_selection_model_unselect_all (GtkSelectionModel *model);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gtk_selection_model_select_callback (GtkSelectionModel *model,
|
||||
GtkSelectionCallback callback,
|
||||
gpointer data);
|
||||
gboolean gtk_selection_model_unselect_callback (GtkSelectionModel *model,
|
||||
GtkSelectionCallback callback,
|
||||
gpointer data);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_selection_model_query_range (GtkSelectionModel *model,
|
||||
guint position,
|
||||
|
32
gtk/gtkset.c
32
gtk/gtkset.c
@ -335,6 +335,38 @@ next_range:
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gtk_set_is_empty (GtkSet *set)
|
||||
{
|
||||
return set->ranges->len == 0;
|
||||
}
|
||||
|
||||
guint
|
||||
gtk_set_get_min (GtkSet *set)
|
||||
{
|
||||
Range *r;
|
||||
|
||||
if (gtk_set_is_empty (set))
|
||||
return 0;
|
||||
|
||||
r = &g_array_index (set->ranges, Range, 0);
|
||||
|
||||
return r->first;
|
||||
}
|
||||
|
||||
guint
|
||||
gtk_set_get_max (GtkSet *set)
|
||||
{
|
||||
Range *r;
|
||||
|
||||
if (gtk_set_is_empty (set))
|
||||
return 0;
|
||||
|
||||
r = &g_array_index (set->ranges, Range, set->ranges->len - 1);
|
||||
|
||||
return r->first + r->n_items;
|
||||
}
|
||||
|
||||
#if 0
|
||||
void
|
||||
gtk_set_dump (GtkSet *set)
|
||||
|
@ -67,4 +67,8 @@ void gtk_set_iter_init (GtkSetIter *iter,
|
||||
gboolean gtk_set_iter_next (GtkSetIter *iter,
|
||||
guint *item);
|
||||
|
||||
gboolean gtk_set_is_empty (GtkSet *set);
|
||||
guint gtk_set_get_min (GtkSet *set);
|
||||
guint gtk_set_get_max (GtkSet *set);
|
||||
|
||||
#endif /* __GTK_SET_H__ */
|
||||
|
Loading…
Reference in New Issue
Block a user