listbase: Redo rubberbanding
Make it so that the selection is only updated in the end.
This commit is contained in:
@@ -34,13 +34,13 @@
|
|||||||
#include "gtksnapshot.h"
|
#include "gtksnapshot.h"
|
||||||
#include "gtkmultiselection.h"
|
#include "gtkmultiselection.h"
|
||||||
#include "gtkgizmoprivate.h"
|
#include "gtkgizmoprivate.h"
|
||||||
|
#include "gtkset.h"
|
||||||
|
|
||||||
typedef struct _RubberbandData RubberbandData;
|
typedef struct _RubberbandData RubberbandData;
|
||||||
|
|
||||||
struct _RubberbandData
|
struct _RubberbandData
|
||||||
{
|
{
|
||||||
GtkWidget *widget;
|
GtkWidget *widget;
|
||||||
GtkSelectionModel *selection;
|
|
||||||
double x1, y1;
|
double x1, y1;
|
||||||
double x2, y2;
|
double x2, y2;
|
||||||
gboolean modify;
|
gboolean modify;
|
||||||
@@ -53,7 +53,6 @@ rubberband_data_free (gpointer data)
|
|||||||
RubberbandData *rdata = data;
|
RubberbandData *rdata = data;
|
||||||
|
|
||||||
g_clear_pointer (&rdata->widget, gtk_widget_unparent);
|
g_clear_pointer (&rdata->widget, gtk_widget_unparent);
|
||||||
g_clear_object (&rdata->selection);
|
|
||||||
g_free (rdata);
|
g_free (rdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1324,7 +1323,6 @@ gtk_list_base_start_rubberband (GtkListBase *self,
|
|||||||
{
|
{
|
||||||
GtkListBasePrivate *priv = gtk_list_base_get_instance_private (self);
|
GtkListBasePrivate *priv = gtk_list_base_get_instance_private (self);
|
||||||
double value_x, value_y;
|
double value_x, value_y;
|
||||||
GtkSelectionModel *selection;
|
|
||||||
|
|
||||||
if (priv->rubberband)
|
if (priv->rubberband)
|
||||||
return;
|
return;
|
||||||
@@ -1343,24 +1341,66 @@ gtk_list_base_start_rubberband (GtkListBase *self,
|
|||||||
priv->rubberband->widget = gtk_gizmo_new ("rubberband",
|
priv->rubberband->widget = gtk_gizmo_new ("rubberband",
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL);
|
NULL, NULL, NULL, NULL, NULL, NULL);
|
||||||
gtk_widget_set_parent (priv->rubberband->widget, GTK_WIDGET (self));
|
gtk_widget_set_parent (priv->rubberband->widget, GTK_WIDGET (self));
|
||||||
|
}
|
||||||
|
|
||||||
selection = gtk_list_item_manager_get_model (priv->item_manager);
|
static void
|
||||||
if ((modify || extend) &&
|
range_cb (guint position,
|
||||||
GTK_IS_MULTI_SELECTION (selection))
|
guint *start,
|
||||||
priv->rubberband->selection = GTK_SELECTION_MODEL (gtk_multi_selection_copy (selection));
|
guint *n_items,
|
||||||
|
gboolean *selected,
|
||||||
|
gpointer data)
|
||||||
|
{
|
||||||
|
GtkSet *set = data;
|
||||||
|
|
||||||
if (!modify && !extend)
|
gtk_set_find_range (set, position, gtk_set_get_max (set), start, n_items, selected);
|
||||||
gtk_selection_model_unselect_all (selection);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gtk_list_base_stop_rubberband (GtkListBase *self)
|
gtk_list_base_stop_rubberband (GtkListBase *self)
|
||||||
{
|
{
|
||||||
GtkListBasePrivate *priv = gtk_list_base_get_instance_private (self);
|
GtkListBasePrivate *priv = gtk_list_base_get_instance_private (self);
|
||||||
|
GtkListItemManagerItem *item;
|
||||||
|
GtkSelectionModel *model;
|
||||||
|
GtkSet *active;
|
||||||
|
|
||||||
if (!priv->rubberband)
|
if (!priv->rubberband)
|
||||||
return;
|
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);
|
g_clear_pointer (&priv->rubberband, rubberband_data_free);
|
||||||
remove_autoscroll (self);
|
remove_autoscroll (self);
|
||||||
|
|
||||||
@@ -1423,55 +1463,24 @@ gtk_list_base_update_rubberband_selection (GtkListBase *self)
|
|||||||
GtkListBasePrivate *priv = gtk_list_base_get_instance_private (self);
|
GtkListBasePrivate *priv = gtk_list_base_get_instance_private (self);
|
||||||
GdkRectangle rect;
|
GdkRectangle rect;
|
||||||
GdkRectangle alloc;
|
GdkRectangle alloc;
|
||||||
GtkSelectionModel *model;
|
|
||||||
GtkListItemManagerItem *item;
|
GtkListItemManagerItem *item;
|
||||||
|
|
||||||
gtk_list_base_allocate_rubberband (self);
|
gtk_list_base_allocate_rubberband (self);
|
||||||
gtk_widget_get_allocation (priv->rubberband->widget, &rect);
|
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);
|
for (item = gtk_list_item_manager_get_first (priv->item_manager);
|
||||||
item != NULL;
|
item != NULL;
|
||||||
item = gtk_rb_tree_node_get_next (item))
|
item = gtk_rb_tree_node_get_next (item))
|
||||||
{
|
{
|
||||||
guint pos;
|
|
||||||
gboolean selected;
|
|
||||||
gboolean was_selected;
|
|
||||||
|
|
||||||
if (!item->widget)
|
if (!item->widget)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
pos = gtk_list_item_manager_get_item_position (priv->item_manager, item);
|
|
||||||
|
|
||||||
gtk_widget_get_allocation (item->widget, &alloc);
|
gtk_widget_get_allocation (item->widget, &alloc);
|
||||||
|
|
||||||
if (priv->rubberband->selection)
|
if (gdk_rectangle_intersect (&rect, &alloc, &alloc))
|
||||||
was_selected = gtk_selection_model_is_selected (priv->rubberband->selection, pos);
|
gtk_widget_set_state_flags (item->widget, GTK_STATE_FLAG_ACTIVE, FALSE);
|
||||||
else
|
else
|
||||||
was_selected = FALSE;
|
gtk_widget_unset_state_flags (item->widget, GTK_STATE_FLAG_ACTIVE);
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user