[gtk+] list box: Implement multiple selection
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+] list box: Implement multiple selection
- Date: Sun, 6 Apr 2014 05:46:13 +0000 (UTC)
commit f652120347f6348dc895ba48f4c7b77bbab27114
Author: Matthias Clasen <mclasen redhat com>
Date: Fri Mar 28 21:34:39 2014 -0400
list box: Implement multiple selection
This largely copies the flox box implementation, including the
same key bindings.
gtk/gtklistbox.c | 535 +++++++++++++++++++++++++++++++++++++++---------------
1 files changed, 391 insertions(+), 144 deletions(-)
---
diff --git a/gtk/gtklistbox.c b/gtk/gtklistbox.c
index d032fbb..4841afc 100644
--- a/gtk/gtklistbox.c
+++ b/gtk/gtklistbox.c
@@ -99,6 +99,7 @@ typedef struct
gint y;
gint height;
gboolean visible;
+ gboolean selected;
} GtkListBoxRowPrivate;
enum {
@@ -125,11 +126,12 @@ enum {
LAST_PROPERTY
};
+#define BOX_PRIV(box) ((GtkListBoxPrivate*)gtk_list_box_get_instance_private ((GtkListBox*)(box)))
+#define ROW_PRIV(row) ((GtkListBoxRowPrivate*)gtk_list_box_row_get_instance_private ((GtkListBoxRow*)(row)))
+
G_DEFINE_TYPE_WITH_PRIVATE (GtkListBox, gtk_list_box, GTK_TYPE_CONTAINER)
G_DEFINE_TYPE_WITH_PRIVATE (GtkListBoxRow, gtk_list_box_row, GTK_TYPE_BIN)
-static void gtk_list_box_update_selected (GtkListBox *list_box,
- GtkListBoxRow *row);
static void gtk_list_box_apply_filter_all (GtkListBox *list_box);
static void gtk_list_box_update_header (GtkListBox *list_box,
GSequenceIter *iter);
@@ -212,6 +214,17 @@ static void gtk_list_box_get_preferred_width_for_height (GtkWidg
gint *minimum_width,
gint *natural_width);
+static void gtk_list_box_select_row_internal (GtkListBox *box,
+ GtkListBoxRow *row);
+static void gtk_list_box_unselect_row_internal (GtkListBox *box,
+ GtkListBoxRow *row);
+static void gtk_list_box_select_all_between (GtkListBox *box,
+ GtkListBoxRow *row1,
+ GtkListBoxRow *row2,
+ gboolean modify);
+static gboolean gtk_list_box_unselect_all_internal (GtkListBox *box);
+static void gtk_list_box_selected_rows_changed (GtkListBox *list_box);
+
static GParamSpec *properties[LAST_PROPERTY] = { NULL, };
static guint signals[LAST_SIGNAL] = { 0 };
static guint row_signals[ROW__LAST_SIGNAL] = { 0 };
@@ -354,6 +367,9 @@ gtk_list_box_class_init (GtkListBoxClass *klass)
klass->activate_cursor_row = gtk_list_box_activate_cursor_row;
klass->toggle_cursor_row = gtk_list_box_toggle_cursor_row;
klass->move_cursor = gtk_list_box_move_cursor;
+ klass->select_all = gtk_list_box_select_all;
+ klass->unselect_all = gtk_list_box_unselect_all;
+ klass->selected_rows_changed = gtk_list_box_selected_rows_changed;
properties[PROP_SELECTION_MODE] =
g_param_spec_enum ("selection-mode",
@@ -507,13 +523,13 @@ gtk_list_box_class_init (GtkListBoxClass *klass)
GTK_MOVEMENT_BUFFER_ENDS, 1);
gtk_list_box_add_move_binding (binding_set, GDK_KEY_KP_End, 0,
GTK_MOVEMENT_BUFFER_ENDS, 1);
- gtk_list_box_add_move_binding (binding_set, GDK_KEY_Up, GDK_CONTROL_MASK,
+ gtk_list_box_add_move_binding (binding_set, GDK_KEY_Up, 0,
GTK_MOVEMENT_DISPLAY_LINES, -1);
- gtk_list_box_add_move_binding (binding_set, GDK_KEY_KP_Up, GDK_CONTROL_MASK,
+ gtk_list_box_add_move_binding (binding_set, GDK_KEY_KP_Up, 0,
GTK_MOVEMENT_DISPLAY_LINES, -1);
- gtk_list_box_add_move_binding (binding_set, GDK_KEY_Down, GDK_CONTROL_MASK,
+ gtk_list_box_add_move_binding (binding_set, GDK_KEY_Down, 0,
GTK_MOVEMENT_DISPLAY_LINES, 1);
- gtk_list_box_add_move_binding (binding_set, GDK_KEY_KP_Down, GDK_CONTROL_MASK,
+ gtk_list_box_add_move_binding (binding_set, GDK_KEY_KP_Down, 0,
GTK_MOVEMENT_DISPLAY_LINES, 1);
gtk_list_box_add_move_binding (binding_set, GDK_KEY_Page_Up, 0,
GTK_MOVEMENT_PAGES, -1);
@@ -523,8 +539,16 @@ gtk_list_box_class_init (GtkListBoxClass *klass)
GTK_MOVEMENT_PAGES, 1);
gtk_list_box_add_move_binding (binding_set, GDK_KEY_KP_Page_Down, 0,
GTK_MOVEMENT_PAGES, 1);
+
gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, GDK_CONTROL_MASK,
"toggle-cursor-row", 0, NULL);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, GDK_CONTROL_MASK,
+ "toggle-cursor-row", 0, NULL);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_a, GDK_CONTROL_MASK,
+ "select-all", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_a, GDK_CONTROL_MASK | GDK_SHIFT_MASK,
+ "unselect-all", 0);
}
/**
@@ -640,7 +664,10 @@ gtk_list_box_select_row (GtkListBox *list_box,
g_return_if_fail (GTK_IS_LIST_BOX (list_box));
g_return_if_fail (row == NULL || GTK_IS_LIST_BOX_ROW (row));
- gtk_list_box_update_selected (list_box, row);
+ if (row)
+ gtk_list_box_select_row_internal (list_box, row);
+ else
+ gtk_list_box_unselect_all_internal (list_box);
}
/**
@@ -660,7 +687,7 @@ gtk_list_box_unselect_row (GtkListBox *list_box,
g_return_if_fail (GTK_IS_LIST_BOX (list_box));
g_return_if_fail (GTK_IS_LIST_BOX_ROW (row));
- gtk_list_box_update_selected (list_box, NULL);
+ gtk_list_box_unselect_row_internal (list_box, row);
}
/**
@@ -676,6 +703,15 @@ void
gtk_list_box_select_all (GtkListBox *list_box)
{
g_return_if_fail (GTK_IS_LIST_BOX (list_box));
+
+ if (BOX_PRIV (list_box)->selection_mode != GTK_SELECTION_MULTIPLE)
+ return;
+
+ if (g_sequence_get_length (BOX_PRIV (list_box)->children) > 0)
+ {
+ gtk_list_box_select_all_between (list_box, NULL, NULL, FALSE);
+ g_signal_emit (list_box, signals[SELECTED_ROWS_CHANGED], 0);
+ }
}
/**
@@ -690,9 +726,23 @@ gtk_list_box_select_all (GtkListBox *list_box)
void
gtk_list_box_unselect_all (GtkListBox *list_box)
{
+ gboolean dirty = FALSE;
+
g_return_if_fail (GTK_IS_LIST_BOX (list_box));
- gtk_list_box_update_selected (list_box, NULL);
+ if (BOX_PRIV (list_box)->selection_mode == GTK_SELECTION_BROWSE)
+ return;
+
+ dirty = gtk_list_box_unselect_all_internal (list_box);
+
+ if (dirty)
+ g_signal_emit (list_box, signals[SELECTED_ROWS_CHANGED], 0);
+}
+
+static void
+gtk_list_box_selected_rows_changed (GtkListBox *list_box)
+{
+ _gtk_list_box_accessible_selection_changed (list_box);
}
/**
@@ -899,26 +949,27 @@ void
gtk_list_box_set_selection_mode (GtkListBox *list_box,
GtkSelectionMode mode)
{
- GtkListBoxPrivate *priv;
+ GtkListBoxPrivate *priv = BOX_PRIV (list_box);
+ gboolean dirty = FALSE;
g_return_if_fail (GTK_IS_LIST_BOX (list_box));
- priv = gtk_list_box_get_instance_private (list_box);
+ if (priv->selection_mode == mode)
+ return;
- if (mode == GTK_SELECTION_MULTIPLE)
+ if (mode == GTK_SELECTION_NONE ||
+ priv->selection_mode == GTK_SELECTION_MULTIPLE)
{
- g_warning ("Multiple selections not supported");
- return;
+ dirty = gtk_list_box_unselect_all_internal (list_box);
+ priv->selected_row = NULL;
}
- if (priv->selection_mode == mode)
- return;
-
priv->selection_mode = mode;
- if (mode == GTK_SELECTION_NONE)
- gtk_list_box_update_selected (list_box, NULL);
g_object_notify_by_pspec (G_OBJECT (list_box), properties[PROP_SELECTION_MODE]);
+
+ if (dirty)
+ g_signal_emit (list_box, signals[SELECTED_ROWS_CHANGED], 0);
}
/**
@@ -1254,14 +1305,39 @@ gtk_list_box_add_move_binding (GtkBindingSet *binding_set,
GtkMovementStep step,
gint count)
{
- gtk_binding_entry_add_signal (binding_set, keyval, modmask,
- "move-cursor", (guint) 2, GTK_TYPE_MOVEMENT_STEP, step, G_TYPE_INT, count,
NULL);
+ GdkDisplay *display;
+ GdkModifierType extend_mod_mask = GDK_SHIFT_MASK;
+ GdkModifierType modify_mod_mask = GDK_CONTROL_MASK;
- if ((modmask & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
- return;
+ display = gdk_display_get_default ();
+ if (display)
+ {
+ extend_mod_mask = gdk_keymap_get_modifier_mask (gdk_keymap_get_for_display (display),
+ GDK_MODIFIER_INTENT_EXTEND_SELECTION);
+ modify_mod_mask = gdk_keymap_get_modifier_mask (gdk_keymap_get_for_display (display),
+ GDK_MODIFIER_INTENT_MODIFY_SELECTION);
+ }
- gtk_binding_entry_add_signal (binding_set, keyval, GDK_CONTROL_MASK,
- "move-cursor", (guint) 2, GTK_TYPE_MOVEMENT_STEP, step, G_TYPE_INT, count,
NULL);
+ gtk_binding_entry_add_signal (binding_set, keyval, modmask,
+ "move-cursor", 2,
+ GTK_TYPE_MOVEMENT_STEP, step,
+ G_TYPE_INT, count,
+ NULL);
+ gtk_binding_entry_add_signal (binding_set, keyval, modmask | extend_mod_mask,
+ "move-cursor", 2,
+ GTK_TYPE_MOVEMENT_STEP, step,
+ G_TYPE_INT, count,
+ NULL);
+ gtk_binding_entry_add_signal (binding_set, keyval, modmask | modify_mod_mask,
+ "move-cursor", 2,
+ GTK_TYPE_MOVEMENT_STEP, step,
+ G_TYPE_INT, count,
+ NULL);
+ gtk_binding_entry_add_signal (binding_set, keyval, modmask | extend_mod_mask | modify_mod_mask,
+ "move-cursor", 2,
+ GTK_TYPE_MOVEMENT_STEP, step,
+ G_TYPE_INT, count,
+ NULL);
}
static void
@@ -1276,42 +1352,224 @@ gtk_list_box_update_cursor (GtkListBox *list_box,
_gtk_list_box_accessible_update_cursor (list_box, row);
}
-static void
-gtk_list_box_update_selected (GtkListBox *list_box,
- GtkListBoxRow *row)
+static GtkListBox *
+gtk_list_box_row_get_box (GtkListBoxRow *row)
{
- GtkListBoxPrivate *priv = gtk_list_box_get_instance_private (list_box);
+ GtkWidget *parent;
+
+ parent = gtk_widget_get_parent (GTK_WIDGET (row));
+ if (parent && GTK_IS_LIST_BOX (parent))
+ return GTK_LIST_BOX (parent);
+
+ return NULL;
+}
+
+static gboolean
+row_is_visible (GtkListBoxRow *row)
+{
+ return ROW_PRIV (row)->visible;
+}
- if (row != priv->selected_row &&
- (row == NULL || priv->selection_mode != GTK_SELECTION_NONE))
+static gboolean
+gtk_list_box_row_set_selected (GtkListBoxRow *row,
+ gboolean selected)
+{
+ GtkListBox *box;
+ GtkListBoxRowPrivate *priv;
+
+ priv = gtk_list_box_row_get_instance_private (row);
+
+ if (priv->selected != selected)
{
- if (priv->selected_row)
- gtk_widget_unset_state_flags (GTK_WIDGET (priv->selected_row),
+ priv->selected = selected;
+ if (selected)
+ gtk_widget_set_state_flags (GTK_WIDGET (row),
+ GTK_STATE_FLAG_SELECTED, FALSE);
+ else
+ gtk_widget_unset_state_flags (GTK_WIDGET (row),
GTK_STATE_FLAG_SELECTED);
- priv->selected_row = row;
- if (priv->selected_row)
- gtk_widget_set_state_flags (GTK_WIDGET (priv->selected_row),
- GTK_STATE_FLAG_SELECTED,
- FALSE);
- g_signal_emit (list_box, signals[ROW_SELECTED], 0, priv->selected_row);
- g_signal_emit (list_box, signals[SELECTED_ROWS_CHANGED], 0);
+ box = gtk_list_box_row_get_box (row);
+ _gtk_list_box_accessible_selection_changed (box);
- gtk_widget_queue_draw (GTK_WIDGET (list_box));
+ gtk_widget_queue_draw (GTK_WIDGET (row));
+
+ return TRUE;
}
- _gtk_list_box_accessible_selection_changed (list_box);
- if (row != NULL)
- gtk_list_box_update_cursor (list_box, row);
+
+ return FALSE;
+}
+
+static gboolean
+gtk_list_box_unselect_all_internal (GtkListBox *box)
+{
+ GtkListBoxRow *row;
+ GSequenceIter *iter;
+ gboolean dirty = FALSE;
+
+ if (BOX_PRIV (box)->selection_mode == GTK_SELECTION_NONE)
+ return FALSE;
+
+ for (iter = g_sequence_get_begin_iter (BOX_PRIV (box)->children);
+ !g_sequence_iter_is_end (iter);
+ iter = g_sequence_iter_next (iter))
+ {
+ row = g_sequence_get (iter);
+ dirty |= gtk_list_box_row_set_selected (row, FALSE);
+ }
+
+ return dirty;
+}
+
+static void
+gtk_list_box_unselect_row_internal (GtkListBox *box,
+ GtkListBoxRow *row)
+{
+ if (!ROW_PRIV (row)->selected)
+ return;
+
+ if (BOX_PRIV (box)->selection_mode == GTK_SELECTION_NONE)
+ return;
+ else if (BOX_PRIV (box)->selection_mode != GTK_SELECTION_MULTIPLE)
+ gtk_list_box_unselect_all_internal (box);
+ else
+ gtk_list_box_row_set_selected (row, FALSE);
+
+ g_signal_emit (box, signals[SELECTED_ROWS_CHANGED], 0);
}
static void
-gtk_list_box_select_and_activate (GtkListBox *list_box,
+gtk_list_box_select_row_internal (GtkListBox *box,
GtkListBoxRow *row)
{
- gtk_list_box_update_selected (list_box, row);
+ if (ROW_PRIV (row)->selected)
+ return;
+
+ if (BOX_PRIV (box)->selection_mode == GTK_SELECTION_NONE)
+ return;
+ if (BOX_PRIV (box)->selection_mode != GTK_SELECTION_MULTIPLE)
+ gtk_list_box_unselect_all_internal (box);
+
+ gtk_list_box_row_set_selected (row, TRUE);
+ BOX_PRIV (box)->selected_row = row;
+
+ g_signal_emit (box, signals[SELECTED_ROWS_CHANGED], 0);
+}
+
+static void
+gtk_list_box_select_all_between (GtkListBox *box,
+ GtkListBoxRow *row1,
+ GtkListBoxRow *row2,
+ gboolean modify)
+{
+ GSequenceIter *iter, *iter1, *iter2;
+
+ if (row1)
+ iter1 = ROW_PRIV (row1)->iter;
+ else
+ iter1 = g_sequence_get_begin_iter (BOX_PRIV (box)->children);
+
+ if (row2)
+ iter2 = ROW_PRIV (row2)->iter;
+ else
+ iter2 = g_sequence_get_end_iter (BOX_PRIV (box)->children);
+
+ if (g_sequence_iter_compare (iter2, iter1) < 0)
+ {
+ iter = iter1;
+ iter1 = iter2;
+ iter2 = iter;
+ }
+ for (iter = iter1;
+ !g_sequence_iter_is_end (iter);
+ iter = g_sequence_iter_next (iter))
+ {
+ GtkListBoxRow *row;
+
+ row = GTK_LIST_BOX_ROW (g_sequence_get (iter));
+ if (row_is_visible (row))
+ {
+ if (modify)
+ gtk_list_box_row_set_selected (row, !ROW_PRIV (row)->selected);
+ else
+ gtk_list_box_row_set_selected (row, TRUE);
+ }
+
+ if (g_sequence_iter_compare (iter, iter2) == 0)
+ break;
+ }
+}
+
+static void
+gtk_list_box_update_selection (GtkListBox *box,
+ GtkListBoxRow *row,
+ gboolean modify,
+ gboolean extend)
+{
+ GtkListBoxPrivate *priv = BOX_PRIV (box);
+
+ gtk_list_box_update_cursor (box, row);
+
+ if (priv->selection_mode == GTK_SELECTION_NONE)
+ return;
+
+ if (priv->selection_mode == GTK_SELECTION_BROWSE)
+ {
+ gtk_list_box_unselect_all_internal (box);
+ gtk_list_box_row_set_selected (row, TRUE);
+ priv->selected_row = row;
+ }
+ else if (priv->selection_mode == GTK_SELECTION_SINGLE)
+ {
+ gboolean was_selected;
+
+ was_selected = ROW_PRIV (row)->selected;
+ gtk_list_box_unselect_all_internal (box);
+ gtk_list_box_row_set_selected (row, modify ? !was_selected : TRUE);
+ priv->selected_row = ROW_PRIV (row)->selected ? row : NULL;
+ }
+ else /* GTK_SELECTION_MULTIPLE */
+ {
+ if (extend)
+ {
+ gtk_list_box_unselect_all_internal (box);
+ if (priv->selected_row == NULL)
+ {
+ gtk_list_box_row_set_selected (row, TRUE);
+ priv->selected_row = row;
+ }
+ else
+ gtk_list_box_select_all_between (box, priv->selected_row, row, FALSE);
+ }
+ else
+ {
+ if (modify)
+ {
+ gtk_list_box_row_set_selected (row, !ROW_PRIV (row)->selected);
+ }
+ else
+ {
+ gtk_list_box_unselect_all_internal (box);
+ gtk_list_box_row_set_selected (row, !ROW_PRIV (row)->selected);
+ priv->selected_row = row;
+ }
+ }
+ }
+
+ g_signal_emit (box, signals[SELECTED_ROWS_CHANGED], 0);
+}
+
+static void
+gtk_list_box_select_and_activate (GtkListBox *box,
+ GtkListBoxRow *row)
+{
if (row != NULL)
- g_signal_emit (list_box, signals[ROW_ACTIVATED], 0, row);
+ {
+ gtk_list_box_select_row_internal (box, row);
+ gtk_list_box_update_cursor (box, row);
+ g_signal_emit (box, signals[ROW_ACTIVATED], 0, row);
+ }
}
static void
@@ -1449,7 +1707,6 @@ gtk_list_box_button_press_event (GtkWidget *widget,
GtkListBox *list_box = GTK_LIST_BOX (widget);
GtkListBoxPrivate *priv = gtk_list_box_get_instance_private (list_box);
gboolean retval = GDK_EVENT_PROPAGATE;
- gboolean ctrl_pressed;
GdkWindow *window;
double x, y;
@@ -1457,8 +1714,6 @@ gtk_list_box_button_press_event (GtkWidget *widget,
{
GtkListBoxRow *row;
- ctrl_pressed = (event->state & GDK_CONTROL_MASK) != 0;
-
priv->active_row = NULL;
window = event->window;
@@ -1474,40 +1729,46 @@ gtk_list_box_button_press_event (GtkWidget *widget,
row = gtk_list_box_get_row_at_y (list_box, y);
if (row != NULL && gtk_widget_is_sensitive (GTK_WIDGET (row)))
{
- if (event->type == GDK_2BUTTON_PRESS)
- {
- if (!priv->activate_single_click)
- g_signal_emit (list_box, signals[ROW_ACTIVATED], 0,
- row);
- }
- else if (ctrl_pressed)
- {
- if (priv->selection_mode == GTK_SELECTION_SINGLE &&
- priv->selected_row == row)
- gtk_list_box_update_selected (list_box, NULL);
- else
- gtk_list_box_update_selected (list_box, row);
- }
- else
+ priv->active_row = row;
+ priv->active_row_active = TRUE;
+ gtk_widget_set_state_flags (GTK_WIDGET (priv->active_row),
+ GTK_STATE_FLAG_ACTIVE,
+ FALSE);
+ gtk_widget_queue_draw (GTK_WIDGET (list_box));
+ if (event->type == GDK_2BUTTON_PRESS &&
+ !priv->activate_single_click)
{
- priv->active_row = row;
- priv->active_row_active = TRUE;
- gtk_widget_set_state_flags (GTK_WIDGET (priv->active_row),
- GTK_STATE_FLAG_ACTIVE,
- FALSE);
- gtk_widget_queue_draw (GTK_WIDGET (list_box));
+ g_signal_emit (list_box, signals[ROW_ACTIVATED], 0, row);
+ retval = GDK_EVENT_STOP;
}
-
- retval = GDK_EVENT_STOP;
}
- /* TODO:
- Should mark as active while down,
- and handle grab breaks */
}
return retval;
}
+static void
+get_current_selection_modifiers (GtkWidget *widget,
+ gboolean *modify,
+ gboolean *extend)
+{
+ GdkModifierType state = 0;
+ GdkModifierType mask;
+
+ *modify = FALSE;
+ *extend = FALSE;
+
+ if (gtk_get_current_event_state (&state))
+ {
+ mask = gtk_widget_get_modifier_mask (widget, GDK_MODIFIER_INTENT_MODIFY_SELECTION);
+ if ((state & mask) == mask)
+ *modify = TRUE;
+ mask = gtk_widget_get_modifier_mask (widget, GDK_MODIFIER_INTENT_EXTEND_SELECTION);
+ if ((state & mask) == mask)
+ *extend = TRUE;
+ }
+}
+
static gboolean
gtk_list_box_button_release_event (GtkWidget *widget,
GdkEventButton *event)
@@ -1516,13 +1777,14 @@ gtk_list_box_button_release_event (GtkWidget *widget,
GtkListBoxPrivate *priv = gtk_list_box_get_instance_private (list_box);
gboolean retval = GDK_EVENT_PROPAGATE;
- /* Take a ref to protect against reentrancy (i.e. the activation may destroy the widget) */
+ /* Take a ref to protect against reentrancy
+ * (the activation may destroy the widget)
+ */
g_object_ref (list_box);
if (event->button == GDK_BUTTON_PRIMARY)
{
- if (priv->active_row != NULL &&
- priv->active_row_active)
+ if (priv->active_row != NULL && priv->active_row_active)
{
gtk_widget_unset_state_flags (GTK_WIDGET (priv->active_row),
GTK_STATE_FLAG_ACTIVE);
@@ -1530,10 +1792,27 @@ gtk_list_box_button_release_event (GtkWidget *widget,
if (priv->activate_single_click)
gtk_list_box_select_and_activate (list_box, priv->active_row);
else
- gtk_list_box_update_selected (list_box, priv->active_row);
+ {
+ gboolean modify;
+ gboolean extend;
+ GdkDevice *device;
+
+ get_current_selection_modifiers (widget, &modify, &extend);
+
+ /* With touch, we default to modifying the selection.
+ * You can still clear the selection and start over
+ * by holding Ctrl.
+ */
+ device = gdk_event_get_source_device ((GdkEvent *)event);
+ if (gdk_device_get_source (device) == GDK_SOURCE_TOUCHSCREEN)
+ modify = !modify;
+
+ gtk_list_box_update_selection (list_box, priv->active_row, modify, extend);
+ }
retval = GDK_EVENT_STOP;
}
+
priv->active_row = NULL;
priv->active_row_active = FALSE;
gtk_widget_queue_draw (GTK_WIDGET (list_box));
@@ -1554,8 +1833,6 @@ gtk_list_box_show (GtkWidget *widget)
GTK_WIDGET_CLASS (gtk_list_box_parent_class)->show (widget);
}
-#define ROW_PRIV(_row) ((GtkListBoxRowPrivate *)gtk_list_box_row_get_instance_private (_row))
-
static gboolean
gtk_list_box_focus (GtkWidget *widget,
GtkDirectionType direction)
@@ -1722,12 +1999,6 @@ update_row_is_visible (GtkListBox *list_box,
list_box_add_visible_rows (list_box, 1);
}
-static gboolean
-row_is_visible (GtkListBoxRow *row)
-{
- return ROW_PRIV (row)->visible;
-}
-
static void
gtk_list_box_apply_filter (GtkListBox *list_box,
GtkListBoxRow *row)
@@ -1939,6 +2210,7 @@ gtk_list_box_remove (GtkContainer *container,
GtkListBox *list_box = GTK_LIST_BOX (container);
GtkListBoxPrivate *priv = gtk_list_box_get_instance_private (list_box);
gboolean was_visible;
+ gboolean was_selected;
GtkListBoxRow *row;
GSequenceIter *next;
@@ -1969,6 +2241,8 @@ gtk_list_box_remove (GtkContainer *container,
return;
}
+ was_selected = ROW_PRIV (row)->selected;
+
if (ROW_PRIV (row)->visible)
list_box_add_visible_rows (list_box, -1);
@@ -1980,20 +2254,19 @@ gtk_list_box_remove (GtkContainer *container,
}
if (row == priv->selected_row)
- gtk_list_box_update_selected (list_box, NULL);
- if (row == priv->prelight_row) {
- gtk_widget_unset_state_flags (GTK_WIDGET (priv->prelight_row),
- GTK_STATE_FLAG_PRELIGHT);
- priv->prelight_row = NULL;
- }
+ priv->selected_row =NULL;
+ if (row == priv->prelight_row)
+ {
+ gtk_widget_unset_state_flags (GTK_WIDGET (row), GTK_STATE_FLAG_PRELIGHT);
+ priv->prelight_row = NULL;
+ }
if (row == priv->cursor_row)
priv->cursor_row = NULL;
- if (row == priv->active_row) {
- if (priv->active_row_active)
- gtk_widget_unset_state_flags (GTK_WIDGET (priv->active_row),
- GTK_STATE_FLAG_ACTIVE);
- priv->active_row = NULL;
- }
+ if (row == priv->active_row)
+ {
+ gtk_widget_unset_state_flags (GTK_WIDGET (row), GTK_STATE_FLAG_ACTIVE);
+ priv->active_row = NULL;
+ }
if (row == priv->drag_highlighted_row)
gtk_list_box_drag_unhighlight_row (list_box);
@@ -2006,6 +2279,9 @@ gtk_list_box_remove (GtkContainer *container,
if (was_visible && gtk_widget_get_visible (GTK_WIDGET (list_box)))
gtk_widget_queue_resize (GTK_WIDGET (list_box));
+
+ if (was_selected)
+ g_signal_emit (box, signals[SELECTED_ROWS_CHANGED], 0);
}
static void
@@ -2431,9 +2707,10 @@ gtk_list_box_toggle_cursor_row (GtkListBox *list_box)
if (priv->cursor_row == NULL)
return;
- if (priv->selection_mode == GTK_SELECTION_SINGLE &&
- priv->selected_row == priv->cursor_row)
- gtk_list_box_update_selected (list_box, NULL);
+ if ((priv->selection_mode == GTK_SELECTION_SINGLE ||
+ priv->selection_mode == GTK_SELECTION_MULTIPLE) &&
+ ROW_PRIV (priv->cursor_row)->selected)
+ gtk_list_box_unselect_row_internal (list_box, priv->cursor_row);
else
gtk_list_box_select_and_activate (list_box, priv->cursor_row);
}
@@ -2444,10 +2721,9 @@ gtk_list_box_move_cursor (GtkListBox *list_box,
gint count)
{
GtkListBoxPrivate *priv = gtk_list_box_get_instance_private (list_box);
- GdkModifierType state;
- gboolean modify_selection_pressed;
+ gboolean modify;
+ gboolean extend;
GtkListBoxRow *row;
- GdkModifierType modify_mod_mask;
GtkListBoxRow *prev;
GtkListBoxRow *next;
gint page_size;
@@ -2455,16 +2731,6 @@ gtk_list_box_move_cursor (GtkListBox *list_box,
gint start_y;
gint end_y;
- modify_selection_pressed = FALSE;
-
- if (gtk_get_current_event_state (&state))
- {
- modify_mod_mask = gtk_widget_get_modifier_mask (GTK_WIDGET (list_box),
- GDK_MODIFIER_INTENT_MODIFY_SELECTION);
- if ((state & modify_mod_mask) == modify_mod_mask)
- modify_selection_pressed = TRUE;
- }
-
row = NULL;
switch (step)
{
@@ -2569,9 +2835,11 @@ gtk_list_box_move_cursor (GtkListBox *list_box,
return;
}
+ get_current_selection_modifiers (GTK_WIDGET (list_box), &modify, &extend);
+
gtk_list_box_update_cursor (list_box, row);
- if (!modify_selection_pressed)
- gtk_list_box_update_selected (list_box, row);
+ if (!modify)
+ gtk_list_box_update_selection (list_box, row, FALSE, extend);
}
@@ -2602,43 +2870,22 @@ gtk_list_box_row_init (GtkListBoxRow *row)
gtk_style_context_add_class (context, GTK_STYLE_CLASS_LIST_ROW);
}
-static GtkListBox *
-gtk_list_box_row_get_box (GtkListBoxRow *row)
-{
- GtkWidget *parent;
-
- parent = gtk_widget_get_parent (GTK_WIDGET (row));
- if (parent && GTK_IS_LIST_BOX (parent))
- return GTK_LIST_BOX (parent);
-
- return NULL;
-}
-
static void
gtk_list_box_row_set_focus (GtkListBoxRow *row)
{
GtkListBox *list_box = gtk_list_box_row_get_box (row);
- GdkModifierType state = 0;
- gboolean modify_selection_pressed;
+ gboolean modify;
+ gboolean extend;
if (!list_box)
return;
- modify_selection_pressed = FALSE;
- if (gtk_get_current_event_state (&state))
- {
- GdkModifierType modify_mod_mask;
- modify_mod_mask =
- gtk_widget_get_modifier_mask (GTK_WIDGET (list_box),
- GDK_MODIFIER_INTENT_MODIFY_SELECTION);
- if ((state & modify_mod_mask) == modify_mod_mask)
- modify_selection_pressed = TRUE;
- }
+ get_current_selection_modifiers (GTK_WIDGET (row), &modify, &extend);
- if (modify_selection_pressed)
+ if (modify)
gtk_list_box_update_cursor (list_box, row);
else
- gtk_list_box_update_selected (list_box, row);
+ gtk_list_box_update_selection (list_box, row, FALSE, FALSE);
}
static gboolean
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]