X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fui%2Fgui%2Fpspp-sheet-view.c;h=0219411a4688909d0782498fd1e93902d12e8329;hb=0fe886a656b0ee57b4d542b7c16b3c56288b6fc6;hp=40ea94c4767e0dce69bdd19afc6c6530a4be3732;hpb=45861388123559f96d05eb8d4f9356ad00ced281;p=pspp diff --git a/src/ui/gui/pspp-sheet-view.c b/src/ui/gui/pspp-sheet-view.c index 40ea94c476..0219411a46 100644 --- a/src/ui/gui/pspp-sheet-view.c +++ b/src/ui/gui/pspp-sheet-view.c @@ -144,7 +144,9 @@ enum { PROP_RUBBER_BANDING, PROP_ENABLE_GRID_LINES, PROP_TOOLTIP_COLUMN, - PROP_SPECIAL_CELLS + PROP_SPECIAL_CELLS, + PROP_FIXED_HEIGHT, + PROP_FIXED_HEIGHT_SET }; /* object signals */ @@ -397,8 +399,6 @@ static void pspp_sheet_view_real_start_editing (PsppSheetView *tree_view, GdkRectangle *cell_area, GdkEvent *event, guint flags); -static void pspp_sheet_view_stop_editing (PsppSheetView *tree_view, - gboolean cancel_editing); static gboolean pspp_sheet_view_real_start_interactive_search (PsppSheetView *tree_view, gboolean keybinding); static gboolean pspp_sheet_view_start_interactive_search (PsppSheetView *tree_view); @@ -429,6 +429,8 @@ static void remove_scroll_timeout (PsppSheetView *tree_view); static guint tree_view_signals [LAST_SIGNAL] = { 0 }; +static GtkBindingSet *edit_bindings; + /* GType Methods @@ -445,9 +447,13 @@ pspp_sheet_view_class_init (PsppSheetViewClass *class) GtkObjectClass *object_class; GtkWidgetClass *widget_class; GtkContainerClass *container_class; - GtkBindingSet *binding_set; + GtkBindingSet *binding_set[2]; + int i; + + binding_set[0] = gtk_binding_set_by_class (class); - binding_set = gtk_binding_set_by_class (class); + binding_set[1] = gtk_binding_set_new ("PsppSheetViewEditing"); + edit_bindings = binding_set[1]; o_class = (GObjectClass *) class; object_class = (GtkObjectClass *) class; @@ -639,6 +645,24 @@ pspp_sheet_view_class_init (PsppSheetViewClass *class) PSPP_SHEET_VIEW_SPECIAL_CELLS_DETECT, GTK_PARAM_READWRITE)); + g_object_class_install_property (o_class, + PROP_FIXED_HEIGHT, + g_param_spec_int ("fixed-height", + P_("Fixed Height"), + P_("Height of a single row. Normally the height of a row is determined automatically. Writing this property sets fixed-height-set to true, preventing this property's value from changing."), + -1, + G_MAXINT, + -1, + GTK_PARAM_READWRITE)); + + g_object_class_install_property (o_class, + PROP_FIXED_HEIGHT_SET, + g_param_spec_boolean ("fixed-height-set", + P_("Fixed Height Set"), + P_("Whether fixed-height was set externally."), + FALSE, + GTK_PARAM_READWRITE)); + /* Style properties */ #define _TREE_VIEW_EXPANDER_SIZE 12 #define _TREE_VIEW_VERTICAL_SEPARATOR 2 @@ -855,110 +879,113 @@ pspp_sheet_view_class_init (PsppSheetViewClass *class) G_TYPE_BOOLEAN, 0); /* Key bindings */ - pspp_sheet_view_add_move_binding (binding_set, GDK_Up, 0, TRUE, - GTK_MOVEMENT_DISPLAY_LINES, -1); - pspp_sheet_view_add_move_binding (binding_set, GDK_KP_Up, 0, TRUE, - GTK_MOVEMENT_DISPLAY_LINES, -1); + for (i = 0; i < 2; i++) + { + pspp_sheet_view_add_move_binding (binding_set[i], GDK_Up, 0, TRUE, + GTK_MOVEMENT_DISPLAY_LINES, -1); + pspp_sheet_view_add_move_binding (binding_set[i], GDK_KP_Up, 0, TRUE, + GTK_MOVEMENT_DISPLAY_LINES, -1); - pspp_sheet_view_add_move_binding (binding_set, GDK_Down, 0, TRUE, - GTK_MOVEMENT_DISPLAY_LINES, 1); - pspp_sheet_view_add_move_binding (binding_set, GDK_KP_Down, 0, TRUE, - GTK_MOVEMENT_DISPLAY_LINES, 1); + pspp_sheet_view_add_move_binding (binding_set[i], GDK_Down, 0, TRUE, + GTK_MOVEMENT_DISPLAY_LINES, 1); + pspp_sheet_view_add_move_binding (binding_set[i], GDK_KP_Down, 0, TRUE, + GTK_MOVEMENT_DISPLAY_LINES, 1); - pspp_sheet_view_add_move_binding (binding_set, GDK_p, GDK_CONTROL_MASK, FALSE, - GTK_MOVEMENT_DISPLAY_LINES, -1); + pspp_sheet_view_add_move_binding (binding_set[i], GDK_p, GDK_CONTROL_MASK, FALSE, + GTK_MOVEMENT_DISPLAY_LINES, -1); - pspp_sheet_view_add_move_binding (binding_set, GDK_n, GDK_CONTROL_MASK, FALSE, - GTK_MOVEMENT_DISPLAY_LINES, 1); + pspp_sheet_view_add_move_binding (binding_set[i], GDK_n, GDK_CONTROL_MASK, FALSE, + GTK_MOVEMENT_DISPLAY_LINES, 1); - pspp_sheet_view_add_move_binding (binding_set, GDK_Home, 0, TRUE, - GTK_MOVEMENT_BUFFER_ENDS, -1); - pspp_sheet_view_add_move_binding (binding_set, GDK_KP_Home, 0, TRUE, - GTK_MOVEMENT_BUFFER_ENDS, -1); + pspp_sheet_view_add_move_binding (binding_set[i], GDK_Home, 0, TRUE, + GTK_MOVEMENT_BUFFER_ENDS, -1); + pspp_sheet_view_add_move_binding (binding_set[i], GDK_KP_Home, 0, TRUE, + GTK_MOVEMENT_BUFFER_ENDS, -1); - pspp_sheet_view_add_move_binding (binding_set, GDK_End, 0, TRUE, - GTK_MOVEMENT_BUFFER_ENDS, 1); - pspp_sheet_view_add_move_binding (binding_set, GDK_KP_End, 0, TRUE, - GTK_MOVEMENT_BUFFER_ENDS, 1); + pspp_sheet_view_add_move_binding (binding_set[i], GDK_End, 0, TRUE, + GTK_MOVEMENT_BUFFER_ENDS, 1); + pspp_sheet_view_add_move_binding (binding_set[i], GDK_KP_End, 0, TRUE, + GTK_MOVEMENT_BUFFER_ENDS, 1); - pspp_sheet_view_add_move_binding (binding_set, GDK_Page_Up, 0, TRUE, - GTK_MOVEMENT_PAGES, -1); - pspp_sheet_view_add_move_binding (binding_set, GDK_KP_Page_Up, 0, TRUE, - GTK_MOVEMENT_PAGES, -1); + pspp_sheet_view_add_move_binding (binding_set[i], GDK_Page_Up, 0, TRUE, + GTK_MOVEMENT_PAGES, -1); + pspp_sheet_view_add_move_binding (binding_set[i], GDK_KP_Page_Up, 0, TRUE, + GTK_MOVEMENT_PAGES, -1); - pspp_sheet_view_add_move_binding (binding_set, GDK_Page_Down, 0, TRUE, - GTK_MOVEMENT_PAGES, 1); - pspp_sheet_view_add_move_binding (binding_set, GDK_KP_Page_Down, 0, TRUE, - GTK_MOVEMENT_PAGES, 1); + pspp_sheet_view_add_move_binding (binding_set[i], GDK_Page_Down, 0, TRUE, + GTK_MOVEMENT_PAGES, 1); + pspp_sheet_view_add_move_binding (binding_set[i], GDK_KP_Page_Down, 0, TRUE, + GTK_MOVEMENT_PAGES, 1); - gtk_binding_entry_add_signal (binding_set, GDK_Right, 0, "move-cursor", 2, - G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS, - G_TYPE_INT, 1); + gtk_binding_entry_add_signal (binding_set[i], GDK_Right, 0, "move-cursor", 2, + G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS, + G_TYPE_INT, 1); - gtk_binding_entry_add_signal (binding_set, GDK_Left, 0, "move-cursor", 2, - G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS, - G_TYPE_INT, -1); + gtk_binding_entry_add_signal (binding_set[i], GDK_Left, 0, "move-cursor", 2, + G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS, + G_TYPE_INT, -1); - gtk_binding_entry_add_signal (binding_set, GDK_KP_Right, 0, "move-cursor", 2, - G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS, - G_TYPE_INT, 1); + gtk_binding_entry_add_signal (binding_set[i], GDK_KP_Right, 0, "move-cursor", 2, + G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS, + G_TYPE_INT, 1); - gtk_binding_entry_add_signal (binding_set, GDK_KP_Left, 0, "move-cursor", 2, - G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS, - G_TYPE_INT, -1); + gtk_binding_entry_add_signal (binding_set[i], GDK_KP_Left, 0, "move-cursor", 2, + G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS, + G_TYPE_INT, -1); - gtk_binding_entry_add_signal (binding_set, GDK_Right, GDK_CONTROL_MASK, - "move-cursor", 2, - G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS, - G_TYPE_INT, 1); + gtk_binding_entry_add_signal (binding_set[i], GDK_Right, GDK_CONTROL_MASK, + "move-cursor", 2, + G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS, + G_TYPE_INT, 1); - gtk_binding_entry_add_signal (binding_set, GDK_Left, GDK_CONTROL_MASK, - "move-cursor", 2, - G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS, - G_TYPE_INT, -1); + gtk_binding_entry_add_signal (binding_set[i], GDK_Left, GDK_CONTROL_MASK, + "move-cursor", 2, + G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS, + G_TYPE_INT, -1); - gtk_binding_entry_add_signal (binding_set, GDK_KP_Right, GDK_CONTROL_MASK, - "move-cursor", 2, - G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS, - G_TYPE_INT, 1); + gtk_binding_entry_add_signal (binding_set[i], GDK_KP_Right, GDK_CONTROL_MASK, + "move-cursor", 2, + G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS, + G_TYPE_INT, 1); - gtk_binding_entry_add_signal (binding_set, GDK_KP_Left, GDK_CONTROL_MASK, - "move-cursor", 2, - G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS, - G_TYPE_INT, -1); + gtk_binding_entry_add_signal (binding_set[i], GDK_KP_Left, GDK_CONTROL_MASK, + "move-cursor", 2, + G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS, + G_TYPE_INT, -1); + + gtk_binding_entry_add_signal (binding_set[i], GDK_f, GDK_CONTROL_MASK, "start-interactive-search", 0); - gtk_binding_entry_add_signal (binding_set, GDK_space, GDK_CONTROL_MASK, "toggle-cursor-row", 0); - gtk_binding_entry_add_signal (binding_set, GDK_KP_Space, GDK_CONTROL_MASK, "toggle-cursor-row", 0); + gtk_binding_entry_add_signal (binding_set[i], GDK_F, GDK_CONTROL_MASK, "start-interactive-search", 0); + } - gtk_binding_entry_add_signal (binding_set, GDK_a, GDK_CONTROL_MASK, "select-all", 0); - gtk_binding_entry_add_signal (binding_set, GDK_slash, GDK_CONTROL_MASK, "select-all", 0); + gtk_binding_entry_add_signal (binding_set[0], GDK_space, GDK_CONTROL_MASK, "toggle-cursor-row", 0); + gtk_binding_entry_add_signal (binding_set[0], GDK_KP_Space, GDK_CONTROL_MASK, "toggle-cursor-row", 0); - gtk_binding_entry_add_signal (binding_set, GDK_A, GDK_CONTROL_MASK | GDK_SHIFT_MASK, "unselect-all", 0); - gtk_binding_entry_add_signal (binding_set, GDK_backslash, GDK_CONTROL_MASK, "unselect-all", 0); + gtk_binding_entry_add_signal (binding_set[0], GDK_a, GDK_CONTROL_MASK, "select-all", 0); + gtk_binding_entry_add_signal (binding_set[0], GDK_slash, GDK_CONTROL_MASK, "select-all", 0); - gtk_binding_entry_add_signal (binding_set, GDK_space, GDK_SHIFT_MASK, "select-cursor-row", 1, + gtk_binding_entry_add_signal (binding_set[0], GDK_A, GDK_CONTROL_MASK | GDK_SHIFT_MASK, "unselect-all", 0); + gtk_binding_entry_add_signal (binding_set[0], GDK_backslash, GDK_CONTROL_MASK, "unselect-all", 0); + + gtk_binding_entry_add_signal (binding_set[0], GDK_space, GDK_SHIFT_MASK, "select-cursor-row", 1, G_TYPE_BOOLEAN, TRUE); - gtk_binding_entry_add_signal (binding_set, GDK_KP_Space, GDK_SHIFT_MASK, "select-cursor-row", 1, + gtk_binding_entry_add_signal (binding_set[0], GDK_KP_Space, GDK_SHIFT_MASK, "select-cursor-row", 1, G_TYPE_BOOLEAN, TRUE); - gtk_binding_entry_add_signal (binding_set, GDK_space, 0, "select-cursor-row", 1, + gtk_binding_entry_add_signal (binding_set[0], GDK_space, 0, "select-cursor-row", 1, G_TYPE_BOOLEAN, TRUE); - gtk_binding_entry_add_signal (binding_set, GDK_KP_Space, 0, "select-cursor-row", 1, + gtk_binding_entry_add_signal (binding_set[0], GDK_KP_Space, 0, "select-cursor-row", 1, G_TYPE_BOOLEAN, TRUE); - gtk_binding_entry_add_signal (binding_set, GDK_Return, 0, "select-cursor-row", 1, + gtk_binding_entry_add_signal (binding_set[0], GDK_Return, 0, "select-cursor-row", 1, G_TYPE_BOOLEAN, TRUE); - gtk_binding_entry_add_signal (binding_set, GDK_ISO_Enter, 0, "select-cursor-row", 1, + gtk_binding_entry_add_signal (binding_set[0], GDK_ISO_Enter, 0, "select-cursor-row", 1, G_TYPE_BOOLEAN, TRUE); - gtk_binding_entry_add_signal (binding_set, GDK_KP_Enter, 0, "select-cursor-row", 1, + gtk_binding_entry_add_signal (binding_set[0], GDK_KP_Enter, 0, "select-cursor-row", 1, G_TYPE_BOOLEAN, TRUE); - gtk_binding_entry_add_signal (binding_set, GDK_BackSpace, 0, "select-cursor-parent", 0); - gtk_binding_entry_add_signal (binding_set, GDK_BackSpace, GDK_CONTROL_MASK, "select-cursor-parent", 0); - - gtk_binding_entry_add_signal (binding_set, GDK_f, GDK_CONTROL_MASK, "start-interactive-search", 0); - - gtk_binding_entry_add_signal (binding_set, GDK_F, GDK_CONTROL_MASK, "start-interactive-search", 0); + gtk_binding_entry_add_signal (binding_set[0], GDK_BackSpace, 0, "select-cursor-parent", 0); + gtk_binding_entry_add_signal (binding_set[0], GDK_BackSpace, GDK_CONTROL_MASK, "select-cursor-parent", 0); g_type_class_add_private (o_class, sizeof (PsppSheetViewPrivate)); } @@ -996,6 +1023,7 @@ pspp_sheet_view_init (PsppSheetView *tree_view) tree_view->priv->presize_handler_timer = 0; tree_view->priv->scroll_sync_timer = 0; tree_view->priv->fixed_height = -1; + tree_view->priv->fixed_height_set = FALSE; pspp_sheet_view_set_adjustments (tree_view, NULL, NULL); tree_view->priv->selection = _pspp_sheet_selection_new_with_tree_view (tree_view); tree_view->priv->enable_search = TRUE; @@ -1093,6 +1121,29 @@ pspp_sheet_view_set_property (GObject *object, case PROP_SPECIAL_CELLS: pspp_sheet_view_set_special_cells (tree_view, g_value_get_enum (value)); break; + case PROP_FIXED_HEIGHT: + pspp_sheet_view_set_fixed_height (tree_view, g_value_get_int (value)); + break; + case PROP_FIXED_HEIGHT_SET: + if (g_value_get_boolean (value)) + { + if (!tree_view->priv->fixed_height_set + && tree_view->priv->fixed_height >= 0) + { + tree_view->priv->fixed_height_set = true; + g_object_notify (G_OBJECT (tree_view), "fixed-height-set"); + } + } + else + { + if (tree_view->priv->fixed_height_set) + { + tree_view->priv->fixed_height_set = false; + g_object_notify (G_OBJECT (tree_view), "fixed-height-set"); + install_presize_handler (tree_view); + } + } + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1153,6 +1204,12 @@ pspp_sheet_view_get_property (GObject *object, case PROP_SPECIAL_CELLS: g_value_set_enum (value, tree_view->priv->special_cells); break; + case PROP_FIXED_HEIGHT: + g_value_set_int (value, pspp_sheet_view_get_fixed_height (tree_view)); + break; + case PROP_FIXED_HEIGHT_SET: + g_value_set_boolean (value, tree_view->priv->fixed_height_set); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1730,12 +1787,11 @@ pspp_sheet_view_size_allocate_columns (GtkWidget *widget, PsppSheetViewColumn *column; GtkAllocation allocation; gint width = 0; - gint extra, extra_per_column, extra_for_last; + gint extra, extra_per_column; gint full_requested_width = 0; gint number_of_expand_columns = 0; gboolean column_changed = FALSE; gboolean rtl; - gboolean update_expand; tree_view = PSPP_SHEET_VIEW (widget); @@ -1770,42 +1826,12 @@ pspp_sheet_view_size_allocate_columns (GtkWidget *widget, number_of_expand_columns++; } - /* Only update the expand value if the width of the widget has changed, - * or the number of expand columns has changed, or if there are no expand - * columns, or if we didn't have an size-allocation yet after the - * last validated node. - */ - update_expand = (width_changed && *width_changed == TRUE) - || number_of_expand_columns != tree_view->priv->last_number_of_expand_columns - || number_of_expand_columns == 0 - || tree_view->priv->post_validation_flag == TRUE; - - tree_view->priv->post_validation_flag = FALSE; - - if (!update_expand) - { - extra = tree_view->priv->last_extra_space; - extra_for_last = MAX (widget->allocation.width - full_requested_width - extra, 0); - } - else - { - extra = MAX (widget->allocation.width - full_requested_width, 0); - extra_for_last = 0; - - tree_view->priv->last_extra_space = extra; - } - + extra = MAX (widget->allocation.width - full_requested_width, 0); if (number_of_expand_columns > 0) extra_per_column = extra/number_of_expand_columns; else extra_per_column = 0; - if (update_expand) - { - tree_view->priv->last_extra_space_per_column = extra_per_column; - tree_view->priv->last_number_of_expand_columns = number_of_expand_columns; - } - for (list = (rtl ? last_column : first_column); list != (rtl ? first_column->prev : last_column->next); list = (rtl ? list->prev : list->next)) @@ -1855,17 +1881,6 @@ pspp_sheet_view_size_allocate_columns (GtkWidget *widget, number_of_expand_columns --; } } - else if (number_of_expand_columns == 0 && - list == last_column) - { - column->width += extra; - } - - /* In addition to expand, the last column can get even more - * extra space so all available space is filled up. - */ - if (extra_for_last > 0 && list == last_column) - column->width += extra_for_last; if (column->width != old_width) g_object_notify (G_OBJECT (column), "width"); @@ -2478,7 +2493,7 @@ pspp_sheet_view_button_press (GtkWidget *widget, gtk_grab_add (widget); PSPP_SHEET_VIEW_SET_FLAG (tree_view, PSPP_SHEET_VIEW_IN_COLUMN_RESIZE); - column->resized_width = column->width - tree_view->priv->last_extra_space_per_column; + column->resized_width = column->width; /* block attached dnd signal handler */ drag_data = g_object_get_data (G_OBJECT (widget), "gtk-site-data"); @@ -3111,8 +3126,10 @@ pspp_sheet_view_motion_resize_column (GtkWidget *widget, { column->use_resized_width = TRUE; column->resized_width = new_width; +#if 0 if (column->expand) column->resized_width -= tree_view->priv->last_extra_space_per_column; +#endif gtk_widget_queue_resize (widget); } @@ -3687,7 +3704,9 @@ draw_empty_focus (PsppSheetView *tree_view, GdkRectangle *clip_area) static void pspp_sheet_view_draw_grid_lines (PsppSheetView *tree_view, GdkEventExpose *event, - gint n_visible_columns) + gint n_visible_columns, + gint min_y, + gint max_y) { GList *list = tree_view->priv->columns; gint i = 0; @@ -3718,8 +3737,8 @@ pspp_sheet_view_draw_grid_lines (PsppSheetView *tree_view, && current_x - 1 < event->area.x + event->area.width) gdk_draw_line (event->window, tree_view->priv->grid_line_gc, - current_x - 1, 0, - current_x - 1, height); + current_x - 1, min_y, + current_x - 1, max_y - min_y); } } @@ -3762,6 +3781,7 @@ pspp_sheet_view_bin_expose (GtkWidget *widget, gint grid_line_width; gboolean row_ending_details; gboolean draw_vgrid_lines, draw_hgrid_lines; + gint min_y, max_y; rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL); @@ -3869,6 +3889,7 @@ pspp_sheet_view_bin_expose (GtkWidget *widget, * order, drawing each successive node. */ + min_y = y_offset; do { gboolean parity; @@ -3883,6 +3904,7 @@ pspp_sheet_view_bin_expose (GtkWidget *widget, background_area.y = y_offset + event->area.y; background_area.height = max_height; + max_y = background_area.y + max_height; flags = 0; @@ -4134,6 +4156,21 @@ pspp_sheet_view_bin_expose (GtkWidget *widget, cell_offset += column->width; } + if (cell_offset < event->area.x) + { + gtk_paint_flat_box (widget->style, + event->window, + GTK_STATE_NORMAL, + GTK_SHADOW_NONE, + &event->area, + widget, + "base", + cell_offset, + background_area.y, + event->area.x - cell_offset, + background_area.height); + } + if (node == drag_highlight) { /* Draw indicator for the drop @@ -4273,7 +4310,8 @@ pspp_sheet_view_bin_expose (GtkWidget *widget, while (y_offset < event->area.height); done: - pspp_sheet_view_draw_grid_lines (tree_view, event, n_visible_columns); + pspp_sheet_view_draw_grid_lines (tree_view, event, n_visible_columns, + min_y, max_y); if (tree_view->priv->rubber_band_status == RUBBER_BAND_ACTIVE) { @@ -4330,8 +4368,21 @@ pspp_sheet_view_expose (GtkWidget *widget, else if (event->window == tree_view->priv->header_window) { + gint n_visible_columns; GList *list; - + + gtk_paint_flat_box (widget->style, + event->window, + GTK_STATE_NORMAL, + GTK_SHADOW_NONE, + &event->area, + widget, + "cell_odd", + event->area.x, + event->area.y, + event->area.width, + event->area.height); + for (list = tree_view->priv->columns; list != NULL; list = list->next) { PsppSheetViewColumn *column = list->data; @@ -4345,6 +4396,19 @@ pspp_sheet_view_expose (GtkWidget *widget, gtk_container_propagate_expose (GTK_CONTAINER (tree_view), column->button, event); } + + n_visible_columns = 0; + for (list = tree_view->priv->columns; list; list = list->next) + { + if (! PSPP_SHEET_VIEW_COLUMN (list->data)->visible) + continue; + n_visible_columns ++; + } + pspp_sheet_view_draw_grid_lines (tree_view, + event, + n_visible_columns, + event->area.y, + event->area.height); } else if (event->window == tree_view->priv->drag_window) { @@ -5239,6 +5303,9 @@ initialize_fixed_height_mode (PsppSheetView *tree_view) if (!tree_view->priv->row_count) return; + if (tree_view->priv->fixed_height_set) + return; + if (tree_view->priv->fixed_height < 0) { GtkTreeIter iter; @@ -5252,6 +5319,8 @@ initialize_fixed_height_mode (PsppSheetView *tree_view) tree_view->priv->fixed_height = validate_row (tree_view, node, &iter, path); gtk_tree_path_free (path); + + g_object_notify (G_OBJECT (tree_view), "fixed-height"); } } @@ -7966,7 +8035,7 @@ pspp_sheet_view_move_cursor_left_right (PsppSheetView *tree_view, gboolean left, right; column = list->data; - if (column->visible == FALSE) + if (column->visible == FALSE || column->row_head) goto loop_end; pspp_sheet_view_column_cell_set_cell_data (column, @@ -12000,6 +12069,154 @@ pspp_sheet_view_editable_clicked (GtkButton *button, sheet_view); } +static gboolean +is_all_selected (GtkWidget *widget) +{ + GtkEntryBuffer *buffer; + gint start_pos, end_pos; + + if (!GTK_IS_ENTRY (widget)) + return FALSE; + + buffer = gtk_entry_get_buffer (GTK_ENTRY (widget)); + return (gtk_editable_get_selection_bounds (GTK_EDITABLE (widget), + &start_pos, &end_pos) + && start_pos == 0 + && end_pos == gtk_entry_buffer_get_length (buffer)); +} + +static gboolean +is_at_left (GtkWidget *widget) +{ + return (GTK_IS_ENTRY (widget) + && gtk_editable_get_position (GTK_EDITABLE (widget)) == 0); +} + +static gboolean +is_at_right (GtkWidget *widget) +{ + GtkEntryBuffer *buffer; + gint length; + + if (!GTK_IS_ENTRY (widget)) + return FALSE; + + buffer = gtk_entry_get_buffer (GTK_ENTRY (widget)); + length = gtk_entry_buffer_get_length (buffer); + return gtk_editable_get_position (GTK_EDITABLE (widget)) == length; +} + +static gboolean +pspp_sheet_view_event (GtkWidget *widget, + GdkEventKey *event, + PsppSheetView *tree_view) +{ + PsppSheetViewColumn *column; + GtkTreePath *path; + gboolean handled; + gboolean cancel; + guint keyval; + guint state; + gint row; + + /* Intercept only key press events. + It would make sense to use "key-press-event" instead of "event", but + GtkEntry attaches its own signal handler to "key-press-event" that runs + before ours and overrides our desired behavior for GDK_Up and GDK_Down. + */ + if (event->type != GDK_KEY_PRESS) + return FALSE; + + if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK | GDK_MOD1_MASK)) + { + /* Pass through most keys that include modifiers. */ + if ((event->keyval == GDK_Tab || event->keyval == GDK_ISO_Left_Tab) + && !(event->state & (GDK_CONTROL_MASK | GDK_MOD1_MASK))) + { + /* Special case for Shift-Tab. */ + } + else + return FALSE; + } + + keyval = event->keyval; + state = event->state & ~(GDK_CONTROL_MASK | GDK_SHIFT_MASK | GDK_MOD1_MASK); + cancel = FALSE; + switch (event->keyval) + { + case GDK_Left: case GDK_KP_Left: + if (!is_all_selected (widget) && !is_at_left (widget)) + return FALSE; + break; + + case GDK_Right: case GDK_KP_Right: + if (!is_all_selected (widget) && !is_at_right (widget)) + return FALSE; + break; + + case GDK_Up: case GDK_KP_Up: + case GDK_Down: case GDK_KP_Down: + break; + + case GDK_Page_Up: case GDK_KP_Page_Up: + case GDK_Page_Down: case GDK_KP_Page_Down: + break; + + case GDK_Escape: + cancel = TRUE; + break; + + case GDK_Return: + keyval = GDK_Down; + break; + + case GDK_Tab: + case GDK_ISO_Left_Tab: + keyval = event->state & GDK_SHIFT_MASK ? GDK_Left : GDK_Right; + break; + + default: + return FALSE; + } + + row = tree_view->priv->edited_row; + column = tree_view->priv->edited_column; + path = gtk_tree_path_new_from_indices (row, -1); + + pspp_sheet_view_stop_editing (tree_view, cancel); + gtk_widget_grab_focus (GTK_WIDGET (tree_view)); + + pspp_sheet_view_set_cursor (tree_view, path, column, FALSE); + gtk_tree_path_free (path); + + handled = gtk_binding_set_activate (edit_bindings, keyval, state, + GTK_OBJECT (tree_view)); + if (handled) + g_signal_stop_emission_by_name (widget, "event"); + + pspp_sheet_view_get_cursor (tree_view, &path, NULL); + pspp_sheet_view_start_editing (tree_view, path); + gtk_tree_path_free (path); + + return handled; +} + +static void +pspp_sheet_view_override_cell_keypresses (GtkWidget *widget, + gpointer data) +{ + PsppSheetView *sheet_view = data; + + g_signal_connect (widget, "event", + G_CALLBACK (pspp_sheet_view_event), + sheet_view); + + if (GTK_IS_CONTAINER (widget)) + gtk_container_foreach (GTK_CONTAINER (widget), + pspp_sheet_view_override_cell_keypresses, + data); +} + static void pspp_sheet_view_real_start_editing (PsppSheetView *tree_view, PsppSheetViewColumn *column, @@ -12012,10 +12229,15 @@ pspp_sheet_view_real_start_editing (PsppSheetView *tree_view, PsppSheetSelectionMode mode = pspp_sheet_selection_get_mode (tree_view->priv->selection); gint pre_val = tree_view->priv->vadjustment->value; GtkRequisition requisition; + gint row; + + g_return_if_fail (gtk_tree_path_get_depth (path) == 1); tree_view->priv->edited_column = column; _pspp_sheet_view_column_start_editing (column, GTK_CELL_EDITABLE (cell_editable)); + row = gtk_tree_path_get_indices (path)[0]; + tree_view->priv->edited_row = row; pspp_sheet_view_real_set_cursor (tree_view, path, FALSE, TRUE); cell_area->y += pre_val - (int)tree_view->priv->vadjustment->value; @@ -12056,16 +12278,19 @@ pspp_sheet_view_real_start_editing (PsppSheetView *tree_view, G_CALLBACK (pspp_sheet_view_editable_button_press_event), tree_view); g_object_set_data (G_OBJECT (cell_editable), "pspp-sheet-view-node", - GINT_TO_POINTER (gtk_tree_path_get_indices (path)[0])); + GINT_TO_POINTER (row)); g_signal_connect (cell_editable, "clicked", G_CALLBACK (pspp_sheet_view_editable_clicked), tree_view); } + + pspp_sheet_view_override_cell_keypresses (GTK_WIDGET (cell_editable), + tree_view); } -static void +void pspp_sheet_view_stop_editing (PsppSheetView *tree_view, - gboolean cancel_editing) + gboolean cancel_editing) { PsppSheetViewColumn *column; GtkCellRenderer *cell; @@ -12362,6 +12587,31 @@ pspp_sheet_view_set_special_cells (PsppSheetView *tree_view, } } +int +pspp_sheet_view_get_fixed_height (const PsppSheetView *tree_view) +{ + /* XXX (re)calculate fixed_height if necessary */ + return tree_view->priv->fixed_height; +} + +void +pspp_sheet_view_set_fixed_height (PsppSheetView *tree_view, + int fixed_height) +{ + g_return_if_fail (fixed_height > 0); + + if (tree_view->priv->fixed_height != fixed_height) + { + tree_view->priv->fixed_height = fixed_height; + g_object_notify (G_OBJECT (tree_view), "fixed-height"); + } + if (!tree_view->priv->fixed_height_set) + { + tree_view->priv->fixed_height_set = TRUE; + g_object_notify (G_OBJECT (tree_view), "fixed-height-set"); + } +} + /** * pspp_sheet_view_set_tooltip_row: * @tree_view: a #PsppSheetView