/* PSPPIRE - a graphical user interface for PSPP.
- Copyright (C) 2011, 2012 Free Software Foundation, Inc.
+ Copyright (C) 2011, 2012, 2013 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
static void
pspp_sheet_selection_init (PsppSheetSelection *selection)
{
- selection->type = GTK_SELECTION_SINGLE;
+ selection->type = PSPP_SHEET_SELECTION_SINGLE;
}
static void
* @type: The selection mode
*
* Sets the selection mode of the @selection. If the previous type was
- * #GTK_SELECTION_MULTIPLE, then the anchor is kept selected, if it was
- * previously selected.
+ * #PSPP_SHEET_SELECTION_MULTIPLE or #PSPP_SHEET_SELECTION_RECTANGLE, then the
+ * anchor is kept selected, if it was previously selected.
**/
void
pspp_sheet_selection_set_mode (PsppSheetSelection *selection,
- GtkSelectionMode type)
+ PsppSheetSelectionMode type)
{
g_return_if_fail (PSPP_IS_SHEET_SELECTION (selection));
if (selection->type == type)
return;
-
- if (type == GTK_SELECTION_NONE)
+ if (type == PSPP_SHEET_SELECTION_NONE)
{
pspp_sheet_selection_unselect_all (selection);
gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
selection->tree_view->priv->anchor = NULL;
}
- else if (type == GTK_SELECTION_SINGLE ||
- type == GTK_SELECTION_BROWSE)
+ else if (type == PSPP_SHEET_SELECTION_SINGLE ||
+ type == PSPP_SHEET_SELECTION_BROWSE)
{
int node = -1;
gint selected = FALSE;
gtk_tree_path_free (anchor_path);
}
+ /* XXX unselect all columns when switching to/from rectangular selection? */
+
selection->type = type;
}
*
* Return value: the current selection mode
**/
-GtkSelectionMode
+PsppSheetSelectionMode
pspp_sheet_selection_get_mode (PsppSheetSelection *selection)
{
- g_return_val_if_fail (PSPP_IS_SHEET_SELECTION (selection), GTK_SELECTION_SINGLE);
+ g_return_val_if_fail (PSPP_IS_SHEET_SELECTION (selection), PSPP_SHEET_SELECTION_SINGLE);
return selection->type;
}
/**
* pspp_sheet_selection_get_tree_view:
* @selection: A #PsppSheetSelection
- *
+ *
* Returns the tree view associated with @selection.
- *
+ *
* Return value: A #PsppSheetView
**/
PsppSheetView *
* @iter: (allow-none): The #GtkTreeIter, or NULL.
*
* Sets @iter to the currently selected node if @selection is set to
- * #GTK_SELECTION_SINGLE or #GTK_SELECTION_BROWSE. @iter may be NULL if you
- * just want to test if @selection has any selected nodes. @model is filled
- * with the current model as a convenience. This function will not work if you
- * use @selection is #GTK_SELECTION_MULTIPLE.
+ * #PSPP_SHEET_SELECTION_SINGLE or #PSPP_SHEET_SELECTION_BROWSE. @iter may be
+ * NULL if you just want to test if @selection has any selected nodes. @model
+ * is filled with the current model as a convenience. This function will not
+ * work if @selection's mode is #PSPP_SHEET_SELECTION_MULTIPLE or
+ * #PSPP_SHEET_SELECTION_RECTANGLE.
*
* Return value: TRUE, if there is a selected node.
**/
gboolean retval;
g_return_val_if_fail (PSPP_IS_SHEET_SELECTION (selection), FALSE);
- g_return_val_if_fail (selection->type != GTK_SELECTION_MULTIPLE, FALSE);
+ g_return_val_if_fail (selection->type != PSPP_SHEET_SELECTION_MULTIPLE &&
+ selection->type != PSPP_SHEET_SELECTION_RECTANGLE,
+ FALSE);
g_return_val_if_fail (selection->tree_view != NULL, FALSE);
/* Clear the iter */
if (selection->tree_view->priv->row_count == 0)
return NULL;
- if (selection->type == GTK_SELECTION_NONE)
+ if (selection->type == PSPP_SHEET_SELECTION_NONE)
return NULL;
- else if (selection->type != GTK_SELECTION_MULTIPLE)
+ else if (selection->type != PSPP_SHEET_SELECTION_MULTIPLE &&
+ selection->type != PSPP_SHEET_SELECTION_RECTANGLE)
{
GtkTreeIter iter;
* Returns the number of rows that have been selected in @tree.
*
* Return value: The number of rows selected.
- *
+ *
* Since: 2.2
**/
gint
if (selection->tree_view->priv->row_count == 0)
return 0;
- if (selection->type == GTK_SELECTION_SINGLE ||
- selection->type == GTK_SELECTION_BROWSE)
+ if (selection->type == PSPP_SHEET_SELECTION_SINGLE ||
+ selection->type == PSPP_SHEET_SELECTION_BROWSE)
{
if (pspp_sheet_selection_get_selected (selection, NULL, NULL))
return 1;
selection->tree_view->priv->row_count == 0)
return;
- if (selection->type == GTK_SELECTION_SINGLE ||
- selection->type == GTK_SELECTION_BROWSE)
+ if (selection->type == PSPP_SHEET_SELECTION_SINGLE ||
+ selection->type == PSPP_SHEET_SELECTION_BROWSE)
{
if (gtk_tree_row_reference_valid (selection->tree_view->priv->anchor))
{
G_CALLBACK (model_changed),
&stop);
changed_id = g_signal_connect_swapped (selection->tree_view, "notify::model",
- G_CALLBACK (model_changed),
+ G_CALLBACK (model_changed),
&stop);
RANGE_TOWER_FOR_EACH (node, start, selection->tree_view->priv->selected)
GtkTreePath *path)
{
int node;
- GtkTreeSelectMode mode = 0;
+ PsppSheetSelectMode mode = 0;
g_return_if_fail (PSPP_IS_SHEET_SELECTION (selection));
g_return_if_fail (selection->tree_view != NULL);
path,
&node);
- if (node < 0 || pspp_sheet_view_node_is_selected (selection->tree_view, node))
+ if (node < 0 || pspp_sheet_view_node_is_selected (selection->tree_view, node))
return;
- if (selection->type == GTK_SELECTION_MULTIPLE)
- mode = GTK_TREE_SELECT_MODE_TOGGLE;
+ if (selection->type == PSPP_SHEET_SELECTION_MULTIPLE ||
+ selection->type == PSPP_SHEET_SELECTION_RECTANGLE)
+ mode = PSPP_SHEET_SELECT_MODE_TOGGLE;
_pspp_sheet_selection_internal_select_node (selection,
node,
path,
&node);
- if (node < 0 || !pspp_sheet_view_node_is_selected (selection->tree_view, node))
+ if (node < 0 || !pspp_sheet_view_node_is_selected (selection->tree_view, node))
return;
_pspp_sheet_selection_internal_select_node (selection,
node,
path,
- GTK_TREE_SELECT_MODE_TOGGLE,
+ PSPP_SHEET_SELECT_MODE_TOGGLE,
TRUE);
}
* pspp_sheet_selection_path_is_selected:
* @selection: A #PsppSheetSelection.
* @path: A #GtkTreePath to check selection on.
- *
+ *
* Returns %TRUE if the row pointed to by @path is currently selected. If @path
* does not point to a valid location, %FALSE is returned
- *
+ *
* Return value: %TRUE if @path is selected.
**/
gboolean
path,
&node);
- if (node < 0 || !pspp_sheet_view_node_is_selected (selection->tree_view, node))
+ if (node < 0 || !pspp_sheet_view_node_is_selected (selection->tree_view, node))
return FALSE;
return TRUE;
* pspp_sheet_selection_iter_is_selected:
* @selection: A #PsppSheetSelection
* @iter: A valid #GtkTreeIter
- *
+ *
* Returns %TRUE if the row at @iter is currently selected.
- *
+ *
* Return value: %TRUE, if @iter is selected
**/
gboolean
return FALSE;
range_tower_set1 (selection->tree_view->priv->selected, 0, row_count);
+ pspp_sheet_selection_select_all_columns (selection);
/* XXX we could invalidate individual visible rows instead */
gdk_window_invalidate_rect (selection->tree_view->priv->bin_window, NULL, TRUE);
* pspp_sheet_selection_select_all:
* @selection: A #PsppSheetSelection.
*
- * Selects all the nodes. @selection must be set to #GTK_SELECTION_MULTIPLE
- * mode.
+ * Selects all the nodes and column. @selection must be set to
+ * #PSPP_SHEET_SELECTION_MULTIPLE or #PSPP_SHEET_SELECTION_RECTANGLE mode.
**/
void
pspp_sheet_selection_select_all (PsppSheetSelection *selection)
if (selection->tree_view->priv->row_count == 0 || selection->tree_view->priv->model == NULL)
return;
- g_return_if_fail (selection->type == GTK_SELECTION_MULTIPLE);
+ g_return_if_fail (selection->type == PSPP_SHEET_SELECTION_MULTIPLE ||
+ selection->type == PSPP_SHEET_SELECTION_RECTANGLE);
if (pspp_sheet_selection_real_select_all (selection))
g_signal_emit (selection, tree_selection_signals[CHANGED], 0);
static gint
pspp_sheet_selection_real_unselect_all (PsppSheetSelection *selection)
{
- if (selection->type == GTK_SELECTION_SINGLE ||
- selection->type == GTK_SELECTION_BROWSE)
+ if (selection->type == PSPP_SHEET_SELECTION_SINGLE ||
+ selection->type == PSPP_SHEET_SELECTION_BROWSE)
{
int node = -1;
GtkTreePath *anchor_path;
else
{
range_tower_set0 (selection->tree_view->priv->selected, 0, ULONG_MAX);
+ pspp_sheet_selection_unselect_all_columns (selection);
/* XXX we could invalidate individual visible rows instead */
gdk_window_invalidate_rect (selection->tree_view->priv->bin_window, NULL, TRUE);
* pspp_sheet_selection_unselect_all:
* @selection: A #PsppSheetSelection.
*
- * Unselects all the nodes.
+ * Unselects all the nodes and columns.
**/
void
pspp_sheet_selection_unselect_all (PsppSheetSelection *selection)
if (selection->tree_view->priv->row_count == 0 || selection->tree_view->priv->model == NULL)
return;
-
+
if (pspp_sheet_selection_real_unselect_all (selection))
g_signal_emit (selection, tree_selection_signals[CHANGED], 0);
}
* @end_path: The final node of the range.
*
* Selects a range of nodes, determined by @start_path and @end_path inclusive.
- * @selection must be set to #GTK_SELECTION_MULTIPLE mode.
+ * @selection must be set to #PSPP_SHEET_SELECTION_MULTIPLE or
+ * #PSPP_SHEET_SELECTION_RECTANGLE mode.
**/
void
pspp_sheet_selection_select_range (PsppSheetSelection *selection,
{
g_return_if_fail (PSPP_IS_SHEET_SELECTION (selection));
g_return_if_fail (selection->tree_view != NULL);
- g_return_if_fail (selection->type == GTK_SELECTION_MULTIPLE);
+ g_return_if_fail (selection->type == PSPP_SHEET_SELECTION_MULTIPLE ||
+ selection->type == PSPP_SHEET_SELECTION_RECTANGLE);
g_return_if_fail (selection->tree_view->priv->model != NULL);
if (pspp_sheet_selection_real_modify_range (selection, RANGE_SELECT, start_path, end_path))
_pspp_sheet_selection_internal_select_node (PsppSheetSelection *selection,
int node,
GtkTreePath *path,
- GtkTreeSelectMode mode,
+ PsppSheetSelectMode mode,
gboolean override_browse_mode)
{
gint dirty = FALSE;
GtkTreePath *anchor_path = NULL;
- if (selection->type == GTK_SELECTION_NONE)
+ if (selection->type == PSPP_SHEET_SELECTION_NONE)
return;
if (selection->tree_view->priv->anchor)
anchor_path = gtk_tree_row_reference_get_path (selection->tree_view->priv->anchor);
- if (selection->type == GTK_SELECTION_SINGLE ||
- selection->type == GTK_SELECTION_BROWSE)
+ if (selection->type == PSPP_SHEET_SELECTION_SINGLE ||
+ selection->type == PSPP_SHEET_SELECTION_BROWSE)
{
/* just unselect */
- if (selection->type == GTK_SELECTION_BROWSE && override_browse_mode)
+ if (selection->type == PSPP_SHEET_SELECTION_BROWSE && override_browse_mode)
{
dirty = pspp_sheet_selection_real_unselect_all (selection);
}
/* Did we try to select the same node again? */
- else if (selection->type == GTK_SELECTION_SINGLE &&
+ else if (selection->type == PSPP_SHEET_SELECTION_SINGLE &&
anchor_path && gtk_tree_path_compare (path, anchor_path) == 0)
{
- if ((mode & GTK_TREE_SELECT_MODE_TOGGLE) == GTK_TREE_SELECT_MODE_TOGGLE)
+ if ((mode & PSPP_SHEET_SELECT_MODE_TOGGLE) == PSPP_SHEET_SELECT_MODE_TOGGLE)
{
dirty = pspp_sheet_selection_real_unselect_all (selection);
}
}
}
}
- else if (selection->type == GTK_SELECTION_MULTIPLE)
+ else if (selection->type == PSPP_SHEET_SELECTION_MULTIPLE ||
+ selection->type == PSPP_SHEET_SELECTION_RECTANGLE)
{
- if ((mode & GTK_TREE_SELECT_MODE_EXTEND) == GTK_TREE_SELECT_MODE_EXTEND
+ if ((mode & PSPP_SHEET_SELECT_MODE_EXTEND) == PSPP_SHEET_SELECT_MODE_EXTEND
&& (anchor_path == NULL))
{
if (selection->tree_view->priv->anchor)
gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view), selection->tree_view->priv->model, path);
dirty = pspp_sheet_selection_real_select_node (selection, node, TRUE);
}
- else if ((mode & (GTK_TREE_SELECT_MODE_EXTEND | GTK_TREE_SELECT_MODE_TOGGLE)) == (GTK_TREE_SELECT_MODE_EXTEND | GTK_TREE_SELECT_MODE_TOGGLE))
+ else if ((mode & (PSPP_SHEET_SELECT_MODE_EXTEND | PSPP_SHEET_SELECT_MODE_TOGGLE)) == (PSPP_SHEET_SELECT_MODE_EXTEND | PSPP_SHEET_SELECT_MODE_TOGGLE))
{
pspp_sheet_selection_select_range (selection,
anchor_path,
path);
}
- else if ((mode & GTK_TREE_SELECT_MODE_TOGGLE) == GTK_TREE_SELECT_MODE_TOGGLE)
+ else if ((mode & PSPP_SHEET_SELECT_MODE_TOGGLE) == PSPP_SHEET_SELECT_MODE_TOGGLE)
{
bool selected = pspp_sheet_view_node_is_selected (selection->tree_view, node);
if (selection->tree_view->priv->anchor)
else
dirty |= pspp_sheet_selection_real_select_node (selection, node, TRUE);
}
- else if ((mode & GTK_TREE_SELECT_MODE_EXTEND) == GTK_TREE_SELECT_MODE_EXTEND)
+ else if ((mode & PSPP_SHEET_SELECT_MODE_EXTEND) == PSPP_SHEET_SELECT_MODE_EXTEND)
{
dirty = pspp_sheet_selection_real_unselect_all (selection);
dirty |= pspp_sheet_selection_real_modify_range (selection,
gtk_tree_path_free (anchor_path);
if (dirty)
- g_signal_emit (selection, tree_selection_signals[CHANGED], 0);
+ g_signal_emit (selection, tree_selection_signals[CHANGED], 0);
}
-void
+void
_pspp_sheet_selection_emit_changed (PsppSheetSelection *selection)
{
- g_signal_emit (selection, tree_selection_signals[CHANGED], 0);
+ g_signal_emit (selection, tree_selection_signals[CHANGED], 0);
}
/* NOTE: Any {un,}selection ever done _MUST_ be done through this function!
pspp_sheet_view_node_unselect (selection->tree_view, node);
_pspp_sheet_view_queue_draw_node (selection->tree_view, node, NULL);
-
+
return TRUE;
}
return FALSE;
}
+
+void
+pspp_sheet_selection_unselect_all_columns (PsppSheetSelection *selection)
+{
+ PsppSheetView *sheet_view = selection->tree_view;
+ gboolean changed;
+ GList *list;
+
+ changed = FALSE;
+ for (list = sheet_view->priv->columns; list; list = list->next)
+ {
+ PsppSheetViewColumn *column = list->data;
+ if (column->selected)
+ {
+ column->selected = FALSE;
+ changed = TRUE;
+ }
+ }
+ if (changed && selection->type == PSPP_SHEET_SELECTION_RECTANGLE)
+ {
+ gtk_widget_queue_draw (GTK_WIDGET (selection->tree_view));
+ _pspp_sheet_selection_emit_changed (selection);
+ }
+}
+
+GList *
+pspp_sheet_selection_get_selected_columns (PsppSheetSelection *selection)
+{
+ PsppSheetView *sheet_view = selection->tree_view;
+ GList *selected_columns = NULL;
+ GList *iter;
+
+ g_return_val_if_fail (PSPP_IS_SHEET_SELECTION (selection), NULL);
+ g_return_val_if_fail (selection->tree_view != NULL, NULL);
+
+ if (selection->type != PSPP_SHEET_SELECTION_RECTANGLE)
+ return NULL;
+
+ for (iter = sheet_view->priv->columns; iter; iter = iter->next)
+ {
+ PsppSheetViewColumn *column = iter->data;
+ if (column->selected)
+ selected_columns = g_list_prepend (selected_columns, column);
+ }
+ return g_list_reverse (selected_columns);
+}
+
+gint
+pspp_sheet_selection_count_selected_columns (PsppSheetSelection *selection)
+{
+ PsppSheetView *sheet_view = selection->tree_view;
+ GList *list;
+ gint n;
+
+ n = 0;
+ for (list = sheet_view->priv->columns; list; list = list->next)
+ {
+ PsppSheetViewColumn *column = list->data;
+ if (column->selected)
+ n++;
+ }
+ return n;
+}
+
+void
+pspp_sheet_selection_select_all_columns (PsppSheetSelection *selection)
+{
+ PsppSheetView *sheet_view = selection->tree_view;
+ gboolean changed;
+ GList *list;
+
+ changed = FALSE;
+ for (list = sheet_view->priv->columns; list; list = list->next)
+ {
+ PsppSheetViewColumn *column = list->data;
+ if (!column->selected && column->selectable)
+ {
+ /* XXX should use pspp_sheet_view_column_set_selected() here (and
+ elsewhere) but we want to call
+ _pspp_sheet_selection_emit_changed() only once for all the
+ columns. */
+ column->selected = TRUE;
+ changed = TRUE;
+ }
+ }
+ if (changed && selection->type == PSPP_SHEET_SELECTION_RECTANGLE)
+ {
+ _pspp_sheet_selection_emit_changed (selection);
+ gtk_widget_queue_draw (GTK_WIDGET (selection->tree_view));
+ }
+}
+
+void
+pspp_sheet_selection_select_column (PsppSheetSelection *selection,
+ PsppSheetViewColumn *column)
+{
+ if (!column->selected && column->selectable)
+ {
+ column->selected = TRUE;
+ if (selection->type == PSPP_SHEET_SELECTION_RECTANGLE)
+ {
+ _pspp_sheet_selection_emit_changed (selection);
+ gtk_widget_queue_draw (GTK_WIDGET (selection->tree_view));
+ }
+ }
+}
+
+void
+pspp_sheet_selection_select_column_range (PsppSheetSelection *selection,
+ PsppSheetViewColumn *first,
+ PsppSheetViewColumn *last)
+{
+ PsppSheetView *sheet_view = selection->tree_view;
+ gboolean in_range;
+ gboolean changed;
+ GList *list;
+
+ in_range = FALSE;
+ changed = FALSE;
+ for (list = sheet_view->priv->columns; list; list = list->next)
+ {
+ PsppSheetViewColumn *column = list->data;
+ gboolean c0 = column == first;
+ gboolean c1 = column == last;
+
+ if (in_range || c0 || c1)
+ {
+ if (!column->selected && column->selectable)
+ {
+ column->selected = TRUE;
+ changed = TRUE;
+ }
+ }
+
+ in_range = in_range ^ c0 ^ c1;
+ }
+ if (changed && selection->type == PSPP_SHEET_SELECTION_RECTANGLE)
+ {
+ _pspp_sheet_selection_emit_changed (selection);
+ gtk_widget_queue_draw (GTK_WIDGET (selection->tree_view));
+ }
+}