X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fui%2Fgui%2Fpspp-sheet-view.c;h=c4eec5637c9e2664d4b3cee3c39840f20b9e59b0;hb=933ad79a28fbde607ec062b42d248169a2d16353;hp=312b55e57b12177b8fc3fec0350340462ab2e9b9;hpb=5a2caf22268ce4211830147389ba299d52b7dbad;p=pspp diff --git a/src/ui/gui/pspp-sheet-view.c b/src/ui/gui/pspp-sheet-view.c index 312b55e57b..c4eec5637c 100644 --- a/src/ui/gui/pspp-sheet-view.c +++ b/src/ui/gui/pspp-sheet-view.c @@ -143,7 +143,10 @@ enum { PROP_HOVER_SELECTION, PROP_RUBBER_BANDING, PROP_ENABLE_GRID_LINES, - PROP_TOOLTIP_COLUMN + PROP_TOOLTIP_COLUMN, + PROP_SPECIAL_CELLS, + PROP_FIXED_HEIGHT, + PROP_FIXED_HEIGHT_SET }; /* object signals */ @@ -396,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); @@ -629,6 +630,33 @@ pspp_sheet_view_class_init (PsppSheetViewClass *class) -1, GTK_PARAM_READWRITE)); + g_object_class_install_property (o_class, + PROP_SPECIAL_CELLS, + g_param_spec_enum ("special-cells", + P_("Special Cells"), + P_("Whether rows have special cells."), + PSPP_TYPE_SHEET_VIEW_SPECIAL_CELLS, + 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 @@ -986,6 +1014,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; @@ -1005,6 +1034,8 @@ pspp_sheet_view_init (PsppSheetView *tree_view) tree_view->priv->tooltip_column = -1; + tree_view->priv->special_cells = PSPP_SHEET_VIEW_SPECIAL_CELLS_DETECT; + tree_view->priv->post_validation_flag = FALSE; tree_view->priv->last_button_x = -1; @@ -1018,6 +1049,8 @@ pspp_sheet_view_init (PsppSheetView *tree_view) tree_view->priv->rubber_band_end_node = -1; tree_view->priv->anchor_column = NULL; + + tree_view->priv->button_style = NULL; } @@ -1076,6 +1109,32 @@ pspp_sheet_view_set_property (GObject *object, case PROP_TOOLTIP_COLUMN: pspp_sheet_view_set_tooltip_column (tree_view, g_value_get_int (value)); break; + 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; @@ -1133,6 +1192,15 @@ pspp_sheet_view_get_property (GObject *object, case PROP_TOOLTIP_COLUMN: g_value_set_int (value, tree_view->priv->tooltip_column); break; + 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; @@ -1271,6 +1339,12 @@ pspp_sheet_view_destroy (GtkObject *object) tree_view->priv->vadjustment = NULL; } + if (tree_view->priv->button_style) + { + g_object_unref (tree_view->priv->button_style); + tree_view->priv->button_style = NULL; + } + GTK_OBJECT_CLASS (pspp_sheet_view_parent_class)->destroy (object); } @@ -1294,14 +1368,15 @@ pspp_sheet_view_map_buttons (PsppSheetView *tree_view) for (list = tree_view->priv->columns; list; list = list->next) { column = list->data; - if (gtk_widget_get_visible (column->button) && + if (column->button != NULL && + gtk_widget_get_visible (column->button) && !gtk_widget_get_mapped (column->button)) gtk_widget_map (column->button); } for (list = tree_view->priv->columns; list; list = list->next) { column = list->data; - if (column->visible == FALSE) + if (column->visible == FALSE || column->window == NULL) continue; if (column->resizable) { @@ -1520,12 +1595,7 @@ pspp_sheet_view_size_request_columns (PsppSheetView *tree_view) GtkRequisition requisition; PsppSheetViewColumn *column = list->data; - if (column->button == NULL) - continue; - - column = list->data; - - gtk_widget_size_request (column->button, &requisition); + pspp_sheet_view_column_size_request (column, &requisition); column->button_request = requisition.width; tree_view->priv->header_height = MAX (tree_view->priv->header_height, requisition.height); } @@ -1689,6 +1759,15 @@ pspp_sheet_view_get_real_requested_width_from_column (PsppSheetView *tree_ return real_requested_width; } +static gboolean +span_intersects (int a0, int a_width, + int b0, int b_width) +{ + int a1 = a0 + a_width; + int b1 = b0 + b_width; + return (a0 >= b0 && a0 < b1) || (b0 >= a0 && b0 < a1); +} + /* GtkWidget::size_allocate helper */ static void pspp_sheet_view_size_allocate_columns (GtkWidget *widget, @@ -1699,13 +1778,12 @@ 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); for (last_column = g_list_last (tree_view->priv->columns); @@ -1739,42 +1817,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)) @@ -1798,8 +1846,8 @@ pspp_sheet_view_size_allocate_columns (GtkWidget *widget, &(drag_allocation.height)); drag_allocation.x = 0; drag_allocation.y = 0; - gtk_widget_size_allocate (tree_view->priv->drag_column->button, - &drag_allocation); + pspp_sheet_view_column_size_allocate (tree_view->priv->drag_column, + &drag_allocation); width += drag_allocation.width; continue; } @@ -1824,19 +1872,9 @@ 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; - - g_object_notify (G_OBJECT (column), "width"); + if (column->width != old_width) + g_object_notify (G_OBJECT (column), "width"); allocation.width = column->width; width += column->width; @@ -1844,7 +1882,13 @@ pspp_sheet_view_size_allocate_columns (GtkWidget *widget, if (column->width > old_width) column_changed = TRUE; - gtk_widget_size_allocate (column->button, &allocation); + pspp_sheet_view_column_size_allocate (column, &allocation); + + if (span_intersects (allocation.x, allocation.width, + tree_view->priv->hadjustment->value, + widget->allocation.width) + && gtk_widget_get_realized (widget)) + pspp_sheet_view_column_set_need_button (column, TRUE); if (column->window) gdk_window_move_resize (column->window, @@ -2259,7 +2303,6 @@ pspp_sheet_view_button_press (GtkWidget *widget, PsppSheetViewColumn *column = NULL; GtkCellRenderer *focus_cell = NULL; gboolean row_double_click = FALSE; - gboolean node_selected; /* Empty tree? */ if (tree_view->priv->row_count == 0) @@ -2281,7 +2324,6 @@ pspp_sheet_view_button_press (GtkWidget *widget, return TRUE; /* select */ - node_selected = pspp_sheet_view_node_is_selected (tree_view, node); pre_val = tree_view->priv->vadjustment->value; path = _pspp_sheet_view_find_path (tree_view, node); @@ -2347,7 +2389,6 @@ pspp_sheet_view_button_press (GtkWidget *widget, tree_view->priv->press_start_node = node; if (tree_view->priv->rubber_banding_enable - //&& !node_selected && (tree_view->priv->selection->type == PSPP_SHEET_SELECTION_MULTIPLE || tree_view->priv->selection->type == PSPP_SHEET_SELECTION_RECTANGLE)) { @@ -2440,7 +2481,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"); @@ -2451,7 +2492,7 @@ pspp_sheet_view_button_press (GtkWidget *widget, drag_data); tree_view->priv->drag_pos = i; - tree_view->priv->x_drag = column->button->allocation.x + (rtl ? 0 : column->button->allocation.width); + tree_view->priv->x_drag = column->allocation.x + (rtl ? 0 : column->allocation.width); if (!gtk_widget_has_focus (widget)) gtk_widget_grab_focus (widget); @@ -2478,6 +2519,8 @@ pspp_sheet_view_button_release_drag_column (GtkWidget *widget, gdk_display_keyboard_ungrab (gtk_widget_get_display (widget), GDK_CURRENT_TIME); /* Move the button back */ + g_return_val_if_fail (tree_view->priv->drag_column->button, FALSE); + g_object_ref (tree_view->priv->drag_column->button); gtk_container_remove (GTK_CONTAINER (tree_view), tree_view->priv->drag_column->button); gtk_widget_set_parent_window (tree_view->priv->drag_column->button, tree_view->priv->header_window); @@ -2825,9 +2868,9 @@ pspp_sheet_view_motion_draw_column_motion_arrow (PsppSheetView *tree_view) GdkRectangle visible_rect; pspp_sheet_view_get_visible_rect (tree_view, &visible_rect); if (reorder->left_column) - x = reorder->left_column->button->allocation.x + reorder->left_column->button->allocation.width; + x = reorder->left_column->allocation.x + reorder->left_column->allocation.width; else - x = reorder->right_column->button->allocation.x; + x = reorder->right_column->allocation.x; if (x < visible_rect.x) arrow_type = DRAG_COLUMN_WINDOW_STATE_ARROW_LEFT; @@ -2856,8 +2899,8 @@ pspp_sheet_view_motion_draw_column_motion_arrow (PsppSheetView *tree_view) attributes.wclass = GDK_INPUT_OUTPUT; attributes.x = tree_view->priv->drag_column_x; attributes.y = 0; - width = attributes.width = tree_view->priv->drag_column->button->allocation.width; - height = attributes.height = tree_view->priv->drag_column->button->allocation.height; + width = attributes.width = tree_view->priv->drag_column->allocation.width; + height = attributes.height = tree_view->priv->drag_column->allocation.height; attributes.visual = gtk_widget_get_visual (GTK_WIDGET (tree_view)); attributes.colormap = gtk_widget_get_colormap (GTK_WIDGET (tree_view)); attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK | GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK; @@ -2893,13 +2936,13 @@ pspp_sheet_view_motion_draw_column_motion_arrow (PsppSheetView *tree_view) gdk_window_get_origin (tree_view->priv->header_window, &x, &y); if (reorder->left_column) { - x += reorder->left_column->button->allocation.x + reorder->left_column->button->allocation.width - width/2; - height = reorder->left_column->button->allocation.height; + x += reorder->left_column->allocation.x + reorder->left_column->allocation.width - width/2; + height = reorder->left_column->allocation.height; } else { - x += reorder->right_column->button->allocation.x - width/2; - height = reorder->right_column->button->allocation.height; + x += reorder->right_column->allocation.x - width/2; + height = reorder->right_column->allocation.height; } y -= tree_view->priv->expander_size/2; /* The arrow takes up only half the space */ height += tree_view->priv->expander_size; @@ -2972,9 +3015,9 @@ pspp_sheet_view_motion_draw_column_motion_arrow (PsppSheetView *tree_view) x += widget->allocation.width - width; if (reorder->left_column) - height = reorder->left_column->button->allocation.height; + height = reorder->left_column->allocation.height; else - height = reorder->right_column->button->allocation.height; + height = reorder->right_column->allocation.height; y -= tree_view->priv->expander_size; height += 2*tree_view->priv->expander_size; @@ -3071,8 +3114,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); } @@ -3176,7 +3221,7 @@ pspp_sheet_view_motion_drag_column (GtkWidget *widget, /* Handle moving the header */ gdk_window_get_position (tree_view->priv->drag_window, &x, &y); x = CLAMP (x + (gint)event->x - column->drag_x, 0, - MAX (tree_view->priv->width, GTK_WIDGET (tree_view)->allocation.width) - column->button->allocation.width); + MAX (tree_view->priv->width, GTK_WIDGET (tree_view)->allocation.width) - column->allocation.width); gdk_window_move (tree_view->priv->drag_window, x, y); /* autoscroll, if needed */ @@ -3647,7 +3692,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; @@ -3678,8 +3725,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); } } @@ -3703,7 +3750,6 @@ pspp_sheet_view_bin_expose (GtkWidget *widget, gint new_y; gint y_offset, cell_offset; gint max_height; - gint depth; GdkRectangle background_area; GdkRectangle cell_area; guint flags; @@ -3722,6 +3768,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); @@ -3775,7 +3822,6 @@ pspp_sheet_view_bin_expose (GtkWidget *widget, gtk_tree_model_get_iter (tree_view->priv->model, &iter, path); - depth = gtk_tree_path_get_depth (path); gtk_tree_path_free (path); cursor_path = NULL; @@ -3829,6 +3875,7 @@ pspp_sheet_view_bin_expose (GtkWidget *widget, * order, drawing each successive node. */ + min_y = y_offset; do { gboolean parity; @@ -3843,6 +3890,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; @@ -3853,21 +3901,26 @@ pspp_sheet_view_bin_expose (GtkWidget *widget, parity = node % 2; - /* we *need* to set cell data on all cells before the call - * to _has_special_cell, else _has_special_cell() does not - * return a correct value. - */ - for (list = (rtl ? g_list_last (tree_view->priv->columns) : g_list_first (tree_view->priv->columns)); - list; - list = (rtl ? list->prev : list->next)) + if (tree_view->priv->special_cells == PSPP_SHEET_VIEW_SPECIAL_CELLS_DETECT) { - PsppSheetViewColumn *column = list->data; - pspp_sheet_view_column_cell_set_cell_data (column, - tree_view->priv->model, - &iter); - } + /* we *need* to set cell data on all cells before the call + * to _has_special_cell, else _has_special_cell() does not + * return a correct value. + */ + for (list = (rtl ? g_list_last (tree_view->priv->columns) : g_list_first (tree_view->priv->columns)); + list; + list = (rtl ? list->prev : list->next)) + { + PsppSheetViewColumn *column = list->data; + pspp_sheet_view_column_cell_set_cell_data (column, + tree_view->priv->model, + &iter); + } - has_special_cell = pspp_sheet_view_has_special_cell (tree_view); + has_special_cell = pspp_sheet_view_has_special_cell (tree_view); + } + else + has_special_cell = tree_view->priv->special_cells == PSPP_SHEET_VIEW_SPECIAL_CELLS_YES; for (list = (rtl ? g_list_last (tree_view->priv->columns) : g_list_first (tree_view->priv->columns)); list; @@ -4089,6 +4142,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 @@ -4228,7 +4296,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) { @@ -4256,7 +4325,7 @@ done: static gboolean pspp_sheet_view_expose (GtkWidget *widget, - GdkEventExpose *event) + GdkEventExpose *event) { PsppSheetView *tree_view = PSPP_SHEET_VIEW (widget); @@ -4285,20 +4354,47 @@ 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; - if (column == tree_view->priv->drag_column) + if (column == tree_view->priv->drag_column || !column->visible) continue; - if (column->visible) - gtk_container_propagate_expose (GTK_CONTAINER (tree_view), - column->button, - event); + if (span_intersects (column->allocation.x, column->allocation.width, + event->area.x, event->area.width) + && column->button != NULL) + 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) { @@ -4556,7 +4652,7 @@ pspp_sheet_view_key_press (GtkWidget *widget, { PsppSheetViewColumn *column = PSPP_SHEET_VIEW_COLUMN (focus_column->data); - if (gtk_widget_has_focus (column->button)) + if (column->button && gtk_widget_has_focus (column->button)) break; } @@ -4585,7 +4681,7 @@ pspp_sheet_view_key_press (GtkWidget *widget, column->resized_width = 0; if (column->min_width == -1) - column->resized_width = MAX (column->button->requisition.width, + column->resized_width = MAX (column->button_request, column->resized_width); else column->resized_width = MAX (column->min_width, @@ -4902,7 +4998,6 @@ validate_row (PsppSheetView *tree_view, gint horizontal_separator; gint vertical_separator; gint focus_line_width; - gboolean retval = FALSE; gboolean draw_vgrid_lines, draw_hgrid_lines; gint focus_pad; gint grid_line_width; @@ -4965,10 +5060,7 @@ validate_row (PsppSheetView *tree_view, } if (tmp_width > column->requested_width) - { - retval = TRUE; - column->requested_width = tmp_width; - } + column->requested_width = tmp_width; } if (draw_hgrid_lines) @@ -5193,6 +5285,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; @@ -5206,6 +5301,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"); } } @@ -6426,6 +6523,9 @@ pspp_sheet_view_has_special_cell (PsppSheetView *tree_view) { GList *list; + if (tree_view->priv->special_cells != PSPP_SHEET_VIEW_SPECIAL_CELLS_DETECT) + return tree_view->priv->special_cells = PSPP_SHEET_VIEW_SPECIAL_CELLS_YES; + for (list = tree_view->priv->columns; list; list = list->next) { if (!((PsppSheetViewColumn *)list->data)->visible) @@ -6437,6 +6537,27 @@ pspp_sheet_view_has_special_cell (PsppSheetView *tree_view) return FALSE; } +static void +pspp_sheet_view_focus_column (PsppSheetView *tree_view, + PsppSheetViewColumn *focus_column, + gboolean clamp_column_visible) +{ + g_return_if_fail (focus_column != NULL); + + tree_view->priv->focus_column = focus_column; + if (!focus_column->button) + { + pspp_sheet_view_column_set_need_button (focus_column, TRUE); + g_return_if_fail (focus_column->button != NULL); + } + + if (GTK_CONTAINER (tree_view)->focus_child != focus_column->button) + gtk_widget_grab_focus (focus_column->button); + + if (clamp_column_visible) + pspp_sheet_view_clamp_column_visible (tree_view, focus_column, FALSE); +} + /* Returns TRUE if the focus is within the headers, after the focus operation is * done */ @@ -6446,7 +6567,7 @@ pspp_sheet_view_header_focus (PsppSheetView *tree_view, gboolean clamp_column_visible) { GtkWidget *focus_child; - + PsppSheetViewColumn *focus_column; GList *last_column, *first_column; GList *tmp_list; gboolean rtl; @@ -6459,10 +6580,9 @@ pspp_sheet_view_header_focus (PsppSheetView *tree_view, first_column = tree_view->priv->columns; while (first_column) { - if (gtk_widget_get_can_focus (PSPP_SHEET_VIEW_COLUMN (first_column->data)->button) && - PSPP_SHEET_VIEW_COLUMN (first_column->data)->visible && - (PSPP_SHEET_VIEW_COLUMN (first_column->data)->clickable || - PSPP_SHEET_VIEW_COLUMN (first_column->data)->reorderable)) + PsppSheetViewColumn *c = PSPP_SHEET_VIEW_COLUMN (first_column->data); + + if (pspp_sheet_view_column_can_focus (c) && c->visible) break; first_column = first_column->next; } @@ -6475,10 +6595,9 @@ pspp_sheet_view_header_focus (PsppSheetView *tree_view, last_column = g_list_last (tree_view->priv->columns); while (last_column) { - if (gtk_widget_get_can_focus (PSPP_SHEET_VIEW_COLUMN (last_column->data)->button) && - PSPP_SHEET_VIEW_COLUMN (last_column->data)->visible && - (PSPP_SHEET_VIEW_COLUMN (last_column->data)->clickable || - PSPP_SHEET_VIEW_COLUMN (last_column->data)->reorderable)) + PsppSheetViewColumn *c = PSPP_SHEET_VIEW_COLUMN (last_column->data); + + if (pspp_sheet_view_column_can_focus (c) && c->visible) break; last_column = last_column->prev; } @@ -6495,12 +6614,13 @@ pspp_sheet_view_header_focus (PsppSheetView *tree_view, if (focus_child == NULL) { if (tree_view->priv->focus_column != NULL && - gtk_widget_get_can_focus (tree_view->priv->focus_column->button)) - focus_child = tree_view->priv->focus_column->button; + pspp_sheet_view_column_can_focus (tree_view->priv->focus_column)) + focus_column = tree_view->priv->focus_column; else - focus_child = PSPP_SHEET_VIEW_COLUMN (first_column->data)->button; - gtk_widget_grab_focus (focus_child); - break; + focus_column = first_column->data; + pspp_sheet_view_focus_column (tree_view, focus_column, + clamp_column_visible); + return TRUE; } return FALSE; @@ -6509,20 +6629,25 @@ pspp_sheet_view_header_focus (PsppSheetView *tree_view, if (focus_child == NULL) { if (tree_view->priv->focus_column != NULL) - focus_child = tree_view->priv->focus_column->button; + focus_column = tree_view->priv->focus_column; else if (dir == GTK_DIR_LEFT) - focus_child = PSPP_SHEET_VIEW_COLUMN (last_column->data)->button; + focus_column = last_column->data; else - focus_child = PSPP_SHEET_VIEW_COLUMN (first_column->data)->button; - gtk_widget_grab_focus (focus_child); - break; + focus_column = first_column->data; + pspp_sheet_view_focus_column (tree_view, focus_column, + clamp_column_visible); + return TRUE; } if (gtk_widget_child_focus (focus_child, dir)) { /* The focus moves inside the button. */ /* This is probably a great example of bad UI */ - break; + if (clamp_column_visible) + pspp_sheet_view_clamp_column_visible (tree_view, + tree_view->priv->focus_column, + FALSE); + return TRUE; } /* We need to move the focus among the row of buttons. */ @@ -6534,7 +6659,7 @@ pspp_sheet_view_header_focus (PsppSheetView *tree_view, || (tmp_list == last_column && dir == (rtl ? GTK_DIR_LEFT : GTK_DIR_RIGHT))) { gtk_widget_error_bell (GTK_WIDGET (tree_view)); - break; + return TRUE; } while (tmp_list) @@ -6554,39 +6679,21 @@ pspp_sheet_view_header_focus (PsppSheetView *tree_view, column = tmp_list->data; if (column->button && column->visible && - gtk_widget_get_can_focus (column->button)) + pspp_sheet_view_column_can_focus (column)) { - focus_child = column->button; - gtk_widget_grab_focus (column->button); - break; + pspp_sheet_view_focus_column (tree_view, column, + clamp_column_visible); + return TRUE; } } - break; + return FALSE; + default: g_assert_not_reached (); break; } - /* if focus child is non-null, we assume it's been set to the current focus child - */ - if (focus_child) - { - for (tmp_list = tree_view->priv->columns; tmp_list; tmp_list = tmp_list->next) - if (PSPP_SHEET_VIEW_COLUMN (tmp_list->data)->button == focus_child) - { - tree_view->priv->focus_column = PSPP_SHEET_VIEW_COLUMN (tmp_list->data); - break; - } - - if (clamp_column_visible) - { - pspp_sheet_view_clamp_column_visible (tree_view, - tree_view->priv->focus_column, - FALSE); - } - } - - return (focus_child != NULL); + return FALSE; } /* This function returns in 'path' the first focusable path, if the given path @@ -6710,6 +6817,13 @@ pspp_sheet_view_style_set (GtkWidget *widget, tree_view->priv->fixed_height = -1; + /* Invalidate cached button style. */ + if (tree_view->priv->button_style) + { + g_object_unref (tree_view->priv->button_style); + tree_view->priv->button_style = NULL; + } + gtk_widget_queue_resize (widget); } @@ -7194,8 +7308,8 @@ pspp_sheet_view_clamp_column_visible (PsppSheetView *tree_view, if (column == NULL) return; - x = column->button->allocation.x; - width = column->button->allocation.width; + x = column->allocation.x; + width = column->allocation.width; if (width > tree_view->priv->hadjustment->page_size) { @@ -7405,9 +7519,9 @@ pspp_sheet_view_set_column_drag_info (PsppSheetView *tree_view, if (tmp_list->next != NULL) { g_assert (tmp_list->next->data); - left = reorder->right_align = (reorder->right_column->button->allocation.x + - reorder->right_column->button->allocation.width + - ((PsppSheetViewColumnReorder *)tmp_list->next->data)->left_column->button->allocation.x)/2; + left = reorder->right_align = (reorder->right_column->allocation.x + + reorder->right_column->allocation.width + + ((PsppSheetViewColumnReorder *)tmp_list->next->data)->left_column->allocation.x)/2; } else { @@ -7431,6 +7545,7 @@ _pspp_sheet_view_column_start_drag (PsppSheetView *tree_view, g_return_if_fail (tree_view->priv->column_drag_info == NULL); g_return_if_fail (tree_view->priv->cur_reorder == NULL); + g_return_if_fail (column->button); pspp_sheet_view_set_column_drag_info (tree_view, column); @@ -7444,10 +7559,10 @@ _pspp_sheet_view_column_start_drag (PsppSheetView *tree_view, attributes.window_type = GDK_WINDOW_CHILD; attributes.wclass = GDK_INPUT_OUTPUT; - attributes.x = column->button->allocation.x; + attributes.x = column->allocation.x; attributes.y = 0; - attributes.width = column->button->allocation.width; - attributes.height = column->button->allocation.height; + attributes.width = column->allocation.width; + attributes.height = column->allocation.height; attributes.visual = gtk_widget_get_visual (GTK_WIDGET (tree_view)); attributes.colormap = gtk_widget_get_colormap (GTK_WIDGET (tree_view)); attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK | GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK; @@ -7497,8 +7612,8 @@ _pspp_sheet_view_column_start_drag (PsppSheetView *tree_view, gtk_widget_set_parent (column->button, GTK_WIDGET (tree_view)); g_object_unref (column->button); - tree_view->priv->drag_column_x = column->button->allocation.x; - allocation = column->button->allocation; + tree_view->priv->drag_column_x = column->allocation.x; + allocation = column->allocation; allocation.x = 0; gtk_widget_size_allocate (column->button, &allocation); gtk_widget_set_parent_window (column->button, tree_view->priv->drag_window); @@ -8289,7 +8404,7 @@ pspp_sheet_view_real_start_interactive_search (PsppSheetView *tree_view, if (! column->visible) continue; - if (gtk_widget_has_focus (column->button)) + if (column->button && gtk_widget_has_focus (column->button)) { found_focus = TRUE; break; @@ -8365,19 +8480,17 @@ pspp_sheet_view_new_column_width (PsppSheetView *tree_view, */ rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL); column = g_list_nth (tree_view->priv->columns, i)->data; - width = rtl ? (column->button->allocation.x + column->button->allocation.width - *x) : (*x - column->button->allocation.x); + width = rtl ? (column->allocation.x + column->allocation.width - *x) : (*x - column->allocation.x); /* Clamp down the value */ if (column->min_width == -1) - width = MAX (column->button->requisition.width, - width); + width = MAX (column->button_request, width); else - width = MAX (column->min_width, - width); + width = MAX (column->min_width, width); if (column->max_width != -1) width = MIN (width, column->max_width); - *x = rtl ? (column->button->allocation.x + column->button->allocation.width - width) : (column->button->allocation.x + width); + *x = rtl ? (column->allocation.x + column->allocation.width - width) : (column->allocation.x + width); return width; } @@ -8454,6 +8567,9 @@ adjust_allocation (GtkWidget *widget, adjust_allocation_recurse (widget, &scroll_data); } +void +pspp_sheet_view_column_update_button (PsppSheetViewColumn *tree_column); + /* Callbacks */ static void pspp_sheet_view_adjustment_changed (GtkAdjustment *adjustment, @@ -8461,6 +8577,7 @@ pspp_sheet_view_adjustment_changed (GtkAdjustment *adjustment, { if (gtk_widget_get_realized (GTK_WIDGET (tree_view))) { + GList *list; gint dy; gdk_window_move (tree_view->priv->bin_window, @@ -8508,8 +8625,20 @@ pspp_sheet_view_adjustment_changed (GtkAdjustment *adjustment, pspp_sheet_view_dy_to_top_row (tree_view); } - gdk_window_process_updates (tree_view->priv->header_window, TRUE); - gdk_window_process_updates (tree_view->priv->bin_window, TRUE); + for (list = tree_view->priv->columns; list; list = list->next) + { + PsppSheetViewColumn *column = list->data; + GtkAllocation *allocation = &column->allocation; + + if (span_intersects (allocation->x, allocation->width, + tree_view->priv->hadjustment->value, + GTK_WIDGET (tree_view)->allocation.width)) + { + pspp_sheet_view_column_set_need_button (column, TRUE); + if (!column->button) + pspp_sheet_view_column_update_button (column); + } + } } } @@ -8644,7 +8773,6 @@ pspp_sheet_view_set_model (PsppSheetView *tree_view, if (tree_view->priv->model) { gint i; - GtkTreeModelFlags flags; if (tree_view->priv->search_column == -1) { @@ -8678,8 +8806,6 @@ pspp_sheet_view_set_model (PsppSheetView *tree_view, G_CALLBACK (pspp_sheet_view_rows_reordered), tree_view); - flags = gtk_tree_model_get_flags (tree_view->priv->model); - tree_view->priv->row_count = gtk_tree_model_iter_n_children (tree_view->priv->model, NULL); /* FIXME: do I need to do this? pspp_sheet_view_create_buttons (tree_view); */ @@ -8853,7 +8979,8 @@ pspp_sheet_view_set_headers_visible (PsppSheetView *tree_view, for (list = tree_view->priv->columns; list; list = list->next) { column = list->data; - gtk_widget_unmap (column->button); + if (column->button) + gtk_widget_unmap (column->button); } gdk_window_hide (tree_view->priv->header_window); } @@ -10882,7 +11009,6 @@ pspp_sheet_view_create_row_drag_icon (PsppSheetView *tree_view, GdkRectangle background_area; GdkRectangle expose_area; GtkWidget *widget; - gint depth; /* start drawing inside the black outline */ gint x = 1, y = 1; GdkDrawable *drawable; @@ -10897,8 +11023,6 @@ pspp_sheet_view_create_row_drag_icon (PsppSheetView *tree_view, if (!gtk_widget_get_realized (widget)) return NULL; - depth = gtk_tree_path_get_depth (path); - _pspp_sheet_view_find_node (tree_view, path, &node); @@ -11984,9 +12108,9 @@ pspp_sheet_view_real_start_editing (PsppSheetView *tree_view, } } -static void +void pspp_sheet_view_stop_editing (PsppSheetView *tree_view, - gboolean cancel_editing) + gboolean cancel_editing) { PsppSheetViewColumn *column; GtkCellRenderer *cell; @@ -12237,6 +12361,75 @@ pspp_sheet_view_set_grid_lines (PsppSheetView *tree_view, } } +/** + * pspp_sheet_view_get_special_cells: + * @tree_view: a #PsppSheetView + * + * Returns which grid lines are enabled in @tree_view. + * + * Return value: a #PsppSheetViewSpecialCells value indicating whether rows in + * the sheet view contain special cells. + */ +PsppSheetViewSpecialCells +pspp_sheet_view_get_special_cells (PsppSheetView *tree_view) +{ + g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), 0); + + return tree_view->priv->special_cells; +} + +/** + * pspp_sheet_view_set_special_cells: + * @tree_view: a #PsppSheetView + * @special_cells: a #PsppSheetViewSpecialCells value indicating whether rows in + * the sheet view contain special cells. + * + * Sets whether rows in the sheet view contain special cells, controlling the + * rendering of row selections. + */ +void +pspp_sheet_view_set_special_cells (PsppSheetView *tree_view, + PsppSheetViewSpecialCells special_cells) +{ + PsppSheetViewPrivate *priv; + + g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view)); + + priv = tree_view->priv; + + if (priv->special_cells != special_cells) + { + priv->special_cells = special_cells; + gtk_widget_queue_draw (GTK_WIDGET (tree_view)); + g_object_notify (G_OBJECT (tree_view), "special-cells"); + } +} + +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 @@ -12567,3 +12760,19 @@ pspp_sheet_view_grid_lines_get_type (void) } return etype; } + +GType +pspp_sheet_view_special_cells_get_type (void) +{ + static GType etype = 0; + if (G_UNLIKELY(etype == 0)) { + static const GEnumValue values[] = { + { PSPP_SHEET_VIEW_SPECIAL_CELLS_DETECT, "PSPP_SHEET_VIEW_SPECIAL_CELLS_DETECT", "detect" }, + { PSPP_SHEET_VIEW_SPECIAL_CELLS_YES, "PSPP_SHEET_VIEW_SPECIAL_CELLS_YES", "yes" }, + { PSPP_SHEET_VIEW_SPECIAL_CELLS_NO, "PSPP_SHEET_VIEW_SPECIAL_CELLS_NO", "no" }, + { 0, NULL, NULL } + }; + etype = g_enum_register_static (g_intern_static_string ("PsppSheetViewSpecialCells"), values); + } + return etype; +}