X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fui%2Fgui%2Fpspp-sheet-selection.c;h=13c69c0ed6ed59dbc05493cdf1b7c5299a0bbea4;hb=19cf39ef8802208ca67fc3e1cf12ce4b239aaabf;hp=ac75e27237c43c4d349233b756fc1cfe9470d8b0;hpb=7ecdf4e88e39024da846a25c98caa2887f0dac59;p=pspp diff --git a/src/ui/gui/pspp-sheet-selection.c b/src/ui/gui/pspp-sheet-selection.c index ac75e27237..13c69c0ed6 100644 --- a/src/ui/gui/pspp-sheet-selection.c +++ b/src/ui/gui/pspp-sheet-selection.c @@ -1,5 +1,5 @@ /* 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 @@ -84,7 +84,7 @@ pspp_sheet_selection_class_init (PsppSheetSelectionClass *class) static void pspp_sheet_selection_init (PsppSheetSelection *selection) { - selection->type = GTK_SELECTION_SINGLE; + selection->type = PSPP_SHEET_SELECTION_SINGLE; } static void @@ -158,28 +158,27 @@ _pspp_sheet_selection_set_tree_view (PsppSheetSelection *selection, * @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; @@ -214,6 +213,8 @@ pspp_sheet_selection_set_mode (PsppSheetSelection *selection, gtk_tree_path_free (anchor_path); } + /* XXX unselect all columns when switching to/from rectangular selection? */ + selection->type = type; } @@ -226,10 +227,10 @@ pspp_sheet_selection_set_mode (PsppSheetSelection *selection, * * 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; } @@ -257,10 +258,11 @@ pspp_sheet_selection_get_tree_view (PsppSheetSelection *selection) * @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. **/ @@ -274,7 +276,9 @@ pspp_sheet_selection_get_selected (PsppSheetSelection *selection, 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 */ @@ -359,9 +363,10 @@ pspp_sheet_selection_get_selected_rows (PsppSheetSelection *selection, 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; @@ -413,8 +418,8 @@ pspp_sheet_selection_count_selected_rows (PsppSheetSelection *selection) 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; @@ -469,8 +474,8 @@ pspp_sheet_selection_selected_foreach (PsppSheetSelection *selection, 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)) { @@ -542,7 +547,7 @@ pspp_sheet_selection_select_path (PsppSheetSelection *selection, 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); @@ -555,8 +560,9 @@ pspp_sheet_selection_select_path (PsppSheetSelection *selection, 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, @@ -592,7 +598,7 @@ pspp_sheet_selection_unselect_path (PsppSheetSelection *selection, _pspp_sheet_selection_internal_select_node (selection, node, path, - GTK_TREE_SELECT_MODE_TOGGLE, + PSPP_SHEET_SELECT_MODE_TOGGLE, TRUE); } @@ -737,6 +743,7 @@ pspp_sheet_selection_real_select_all (PsppSheetSelection *selection) 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); @@ -748,8 +755,8 @@ pspp_sheet_selection_real_select_all (PsppSheetSelection *selection) * 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) @@ -760,7 +767,8 @@ 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); @@ -769,8 +777,8 @@ pspp_sheet_selection_select_all (PsppSheetSelection *selection) 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; @@ -808,6 +816,7 @@ pspp_sheet_selection_real_unselect_all (PsppSheetSelection *selection) 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); @@ -820,7 +829,7 @@ pspp_sheet_selection_real_unselect_all (PsppSheetSelection *selection) * 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) @@ -921,7 +930,8 @@ pspp_sheet_selection_real_modify_range (PsppSheetSelection *selection, * @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, @@ -930,7 +940,8 @@ 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)) @@ -990,31 +1001,31 @@ void _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); } @@ -1056,9 +1067,10 @@ _pspp_sheet_selection_internal_select_node (PsppSheetSelection *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) @@ -1068,13 +1080,13 @@ _pspp_sheet_selection_internal_select_node (PsppSheetSelection *selection, 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) @@ -1088,7 +1100,7 @@ _pspp_sheet_selection_internal_select_node (PsppSheetSelection *selection, 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, @@ -1147,3 +1159,145 @@ pspp_sheet_selection_real_select_node (PsppSheetSelection *selection, 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)); + } +}