[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 12/17] pspp-sheet-view: Optimize by making column header widgets
From: |
Ben Pfaff |
Subject: |
[PATCH 12/17] pspp-sheet-view: Optimize by making column header widgets lazy. |
Date: |
Sun, 22 Apr 2012 11:12:30 -0700 |
This is a major speedup when there are hundreds of columns.
---
src/ui/gui/pspp-sheet-private.h | 5 +-
src/ui/gui/pspp-sheet-view-column.c | 115 +++++++++++++----
src/ui/gui/pspp-sheet-view-column.h | 10 ++
src/ui/gui/pspp-sheet-view.c | 251 +++++++++++++++++++++--------------
4 files changed, 256 insertions(+), 125 deletions(-)
diff --git a/src/ui/gui/pspp-sheet-private.h b/src/ui/gui/pspp-sheet-private.h
index c964c52..3993b8c 100644
--- a/src/ui/gui/pspp-sheet-private.h
+++ b/src/ui/gui/pspp-sheet-private.h
@@ -1,5 +1,5 @@
/* PSPPIRE - a graphical user interface for PSPP.
- Copyright (C) 2011 Free Software Foundation, Inc.
+ Copyright (C) 2011, 2012 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
@@ -250,6 +250,9 @@ struct _PsppSheetViewPrivate
/* Tooltip support */
gint tooltip_column;
+ /* Cached style for button facades in columns. */
+ GtkStyle *button_style;
+
/* Here comes the bitfield */
guint scroll_to_use_align : 1;
diff --git a/src/ui/gui/pspp-sheet-view-column.c
b/src/ui/gui/pspp-sheet-view-column.c
index 996a85a..0b78643 100644
--- a/src/ui/gui/pspp-sheet-view-column.c
+++ b/src/ui/gui/pspp-sheet-view-column.c
@@ -1,5 +1,5 @@
/* PSPPIRE - a graphical user interface for PSPP.
- Copyright (C) 2011 Free Software Foundation, Inc.
+ Copyright (C) 2011, 2012 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
@@ -44,6 +44,7 @@
#include "ui/gui/psppire-marshal.h"
#include "ui/gui/pspp-sheet-selection.h"
+#include "ui/gui/pspp-widget-facade.h"
#define I_(STRING) STRING
#define P_(STRING) STRING
@@ -140,7 +141,7 @@ static GList *pspp_sheet_view_column_cell_layout_get_cells
(GtkCellLayout
/* Button handling code */
static void pspp_sheet_view_column_create_button
(PsppSheetViewColumn *tree_column);
-static void pspp_sheet_view_column_update_button
(PsppSheetViewColumn *tree_column);
+void pspp_sheet_view_column_update_button (PsppSheetViewColumn
*tree_column);
/* Button signal handlers */
static gint pspp_sheet_view_column_button_event (GtkWidget
*widget,
@@ -480,6 +481,7 @@ pspp_sheet_view_column_init (PsppSheetViewColumn
*tree_column)
tree_column->use_resized_width = FALSE;
tree_column->title = g_strdup ("");
tree_column->quick_edit = TRUE;
+ tree_column->need_button = FALSE;
}
static void
@@ -1036,7 +1038,7 @@ pspp_sheet_view_column_create_button (PsppSheetViewColumn
*tree_column)
pspp_sheet_view_column_update_button (tree_column);
}
-static void
+void
pspp_sheet_view_column_update_button (PsppSheetViewColumn *tree_column)
{
gint sort_column_id = -1;
@@ -1046,6 +1048,7 @@ pspp_sheet_view_column_update_button (PsppSheetViewColumn
*tree_column)
GtkWidget *current_child;
GtkArrowType arrow_type = GTK_ARROW_NONE;
GtkTreeModel *model;
+ gboolean can_focus;
if (tree_column->tree_view)
model = pspp_sheet_view_get_model (PSPP_SHEET_VIEW
(tree_column->tree_view));
@@ -1053,7 +1056,8 @@ pspp_sheet_view_column_update_button (PsppSheetViewColumn
*tree_column)
model = NULL;
/* Create a button if necessary */
- if (tree_column->visible &&
+ if (tree_column->need_button &&
+ tree_column->visible &&
tree_column->button == NULL &&
tree_column->tree_view &&
gtk_widget_get_realized (tree_column->tree_view))
@@ -1188,23 +1192,18 @@ pspp_sheet_view_column_update_button
(PsppSheetViewColumn *tree_column)
gdk_window_hide (tree_column->window);
}
}
-
- if (tree_column->reorderable || tree_column->clickable)
- {
- gtk_widget_set_can_focus (tree_column->button, TRUE);
- }
- else
+
+ can_focus = pspp_sheet_view_column_can_focus (tree_column);
+ gtk_widget_set_can_focus (tree_column->button, can_focus);
+ if (!can_focus && gtk_widget_has_focus (tree_column->button))
{
- gtk_widget_set_can_focus (tree_column->button, FALSE);
- if (gtk_widget_has_focus (tree_column->button))
- {
- GtkWidget *toplevel = gtk_widget_get_toplevel
(tree_column->tree_view);
- if (gtk_widget_is_toplevel (toplevel))
- {
- gtk_window_set_focus (GTK_WINDOW (toplevel), NULL);
- }
- }
+ GtkWidget *toplevel = gtk_widget_get_toplevel (tree_column->tree_view);
+ if (gtk_widget_is_toplevel (toplevel))
+ {
+ gtk_window_set_focus (GTK_WINDOW (toplevel), NULL);
+ }
}
+
/* Queue a resize on the assumption that we always want to catch all changes
* and columns don't change all that often.
*/
@@ -1540,6 +1539,9 @@ _pspp_sheet_view_column_realize_button
(PsppSheetViewColumn *column)
g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
g_return_if_fail (gtk_widget_get_realized (GTK_WIDGET (tree_view)));
g_return_if_fail (tree_view->priv->header_window != NULL);
+ if (!column->need_button || !column->button)
+ return;
+
g_return_if_fail (column->button != NULL);
gtk_widget_set_parent_window (column->button,
tree_view->priv->header_window);
@@ -1578,11 +1580,12 @@ void
_pspp_sheet_view_column_unrealize_button (PsppSheetViewColumn *column)
{
g_return_if_fail (column != NULL);
- g_return_if_fail (column->window != NULL);
-
- gdk_window_set_user_data (column->window, NULL);
- gdk_window_destroy (column->window);
- column->window = NULL;
+ if (column->window != NULL)
+ {
+ gdk_window_set_user_data (column->window, NULL);
+ gdk_window_destroy (column->window);
+ column->window = NULL;
+ }
}
void
@@ -1605,7 +1608,8 @@ _pspp_sheet_view_column_set_tree_view
(PsppSheetViewColumn *column,
g_assert (column->tree_view == NULL);
column->tree_view = GTK_WIDGET (tree_view);
- pspp_sheet_view_column_create_button (column);
+ if (column->need_button)
+ pspp_sheet_view_column_create_button (column);
column->property_changed_signal =
g_signal_connect_swapped (tree_view,
@@ -4263,3 +4267,64 @@ _gtk_cell_layout_buildable_add_child (GtkBuildable
*buildable,
g_return_if_fail (iface->pack_start != NULL);
iface->pack_start (GTK_CELL_LAYOUT (buildable), GTK_CELL_RENDERER (child),
FALSE);
}
+
+void
+pspp_sheet_view_column_size_request (PsppSheetViewColumn *tree_column,
+ GtkRequisition *request)
+{
+ GtkWidget *base = GTK_WIDGET (tree_column->tree_view);
+ GtkRequisition label_req;
+ GtkRequisition align_req;
+ GtkRequisition arrow_req;
+ GtkRequisition hbox_req;
+ GtkStyle **button_style;
+
+ if (tree_column->button)
+ {
+ gtk_widget_size_request (tree_column->button, request);
+ return;
+ }
+
+ facade_label_get_size_request (0, 0, base, tree_column->title, &label_req);
+ facade_alignment_get_size_request (0, 0, 0, 0, 0, &label_req, &align_req);
+ facade_arrow_get_size_request (0, 0, &arrow_req);
+
+ facade_hbox_get_base_size_request (0, 2, 2, &hbox_req);
+ facade_hbox_add_child_size_request (0, &arrow_req, 0, &hbox_req);
+ facade_hbox_add_child_size_request (0, &align_req, 0, &hbox_req);
+
+ button_style = &PSPP_SHEET_VIEW (tree_column->tree_view)->priv->button_style;
+ if (*button_style == NULL)
+ {
+ *button_style = facade_get_style (base, GTK_TYPE_BUTTON, 0);
+ g_object_ref (*button_style);
+ }
+ facade_button_get_size_request (0, base, *button_style, &hbox_req, request);
+}
+
+void
+pspp_sheet_view_column_size_allocate (PsppSheetViewColumn *tree_column,
+ GtkAllocation *allocation)
+{
+ tree_column->allocation = *allocation;
+ if (tree_column->button)
+ gtk_widget_size_allocate (tree_column->button, allocation);
+}
+
+gboolean
+pspp_sheet_view_column_can_focus (PsppSheetViewColumn *tree_column)
+{
+ return tree_column->reorderable || tree_column->clickable;
+}
+
+void
+pspp_sheet_view_column_set_need_button (PsppSheetViewColumn *tree_column,
+ gboolean need_button)
+{
+ if (tree_column->need_button != need_button)
+ {
+ tree_column->need_button = need_button;
+ pspp_sheet_view_column_update_button (tree_column);
+ _pspp_sheet_view_column_realize_button (tree_column);
+ }
+}
diff --git a/src/ui/gui/pspp-sheet-view-column.h
b/src/ui/gui/pspp-sheet-view-column.h
index 8e4df86..743440f 100644
--- a/src/ui/gui/pspp-sheet-view-column.h
+++ b/src/ui/gui/pspp-sheet-view-column.h
@@ -71,6 +71,7 @@ struct _PsppSheetViewColumn
gfloat GSEAL (xalign);
guint GSEAL (property_changed_signal);
gint GSEAL (spacing);
+ GtkAllocation GSEAL (allocation);
/* Sizing fields */
/* see gtk+/doc/tree-column-sizing.txt for more information on them */
@@ -109,6 +110,7 @@ struct _PsppSheetViewColumn
guint GSEAL (selected) : 1;
guint GSEAL (selectable) : 1;
guint GSEAL (row_head) : 1;
+ guint GSEAL (need_button) : 1;
};
struct _PsppSheetViewColumnClass
@@ -250,6 +252,14 @@ gboolean
pspp_sheet_view_column_cell_get_position (PsppSheetVie
void pspp_sheet_view_column_queue_resize
(PsppSheetViewColumn *tree_column);
GtkWidget *pspp_sheet_view_column_get_tree_view
(PsppSheetViewColumn *tree_column);
+void pspp_sheet_view_column_size_request
(PsppSheetViewColumn *tree_column,
+
GtkRequisition *requisition);
+
+void pspp_sheet_view_column_size_allocate
(PsppSheetViewColumn *tree_column,
+
GtkAllocation *allocation);
+gboolean pspp_sheet_view_column_can_focus
(PsppSheetViewColumn *tree_column);
+void pspp_sheet_view_column_set_need_button
(PsppSheetViewColumn *tree_column,
+ gboolean
need_button);
G_END_DECLS
diff --git a/src/ui/gui/pspp-sheet-view.c b/src/ui/gui/pspp-sheet-view.c
index b965b64..fbe1fd9 100644
--- a/src/ui/gui/pspp-sheet-view.c
+++ b/src/ui/gui/pspp-sheet-view.c
@@ -1031,6 +1031,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;
}
@@ -1290,6 +1292,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);
}
@@ -1313,14 +1321,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)
{
@@ -1539,12 +1548,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);
}
@@ -1708,6 +1712,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,
@@ -1724,7 +1737,7 @@ pspp_sheet_view_size_allocate_columns (GtkWidget *widget,
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);
@@ -1817,8 +1830,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;
}
@@ -1855,7 +1868,8 @@ pspp_sheet_view_size_allocate_columns (GtkWidget *widget,
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;
@@ -1863,7 +1877,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,
@@ -2470,7 +2490,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);
@@ -2497,6 +2517,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);
@@ -2844,9 +2866,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;
@@ -2875,8 +2897,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;
@@ -2912,13 +2934,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;
@@ -2991,9 +3013,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;
@@ -3195,7 +3217,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 */
@@ -4280,7 +4302,7 @@ done:
static gboolean
pspp_sheet_view_expose (GtkWidget *widget,
- GdkEventExpose *event)
+ GdkEventExpose *event)
{
PsppSheetView *tree_view = PSPP_SHEET_VIEW (widget);
@@ -4315,13 +4337,14 @@ pspp_sheet_view_expose (GtkWidget *widget,
{
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);
}
}
else if (event->window == tree_view->priv->drag_window)
@@ -4580,7 +4603,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;
}
@@ -4609,7 +4632,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,
@@ -6464,6 +6487,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
*/
@@ -6473,7 +6517,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;
@@ -6486,10 +6530,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;
}
@@ -6502,10 +6545,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;
}
@@ -6522,12 +6564,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;
@@ -6536,20 +6579,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. */
@@ -6561,7 +6609,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)
@@ -6581,39 +6629,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
@@ -6737,6 +6767,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);
}
@@ -7221,8 +7258,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)
{
@@ -7432,9 +7469,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
{
@@ -7458,6 +7495,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);
@@ -7471,10 +7509,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;
@@ -7524,8 +7562,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);
@@ -8316,7 +8354,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;
@@ -8392,19 +8430,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;
}
@@ -8481,6 +8517,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,
@@ -8488,6 +8527,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,
@@ -8535,8 +8575,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);
+ }
+ }
}
}
@@ -8880,7 +8932,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);
}
--
1.7.2.5
- [PATCH 09/17] pspp-sheet-view: Start editing upon button release, not press., (continued)
- [PATCH 09/17] pspp-sheet-view: Start editing upon button release, not press., Ben Pfaff, 2012/04/22
- [PATCH 10/17] pspp-sheet-view: Add "special-cells" property to speed drawing many columns., Ben Pfaff, 2012/04/22
- [PATCH 13/17] pspp-sheet-view: Improve look of sheet when there are few columns., Ben Pfaff, 2012/04/22
- [PATCH 11/17] pspp-widget-facade: New code to measure and render some GTK+ widgets., Ben Pfaff, 2012/04/22
- [PATCH 14/17] pspp-sheet-view: Make pspp_sheet_view_stop_editing() public., Ben Pfaff, 2012/04/22
- [PATCH 08/17] pspp-sheet-view: Support rectangular selection, column popup menus., Ben Pfaff, 2012/04/22
- [PATCH 12/17] pspp-sheet-view: Optimize by making column header widgets lazy.,
Ben Pfaff <=
- [PATCH 15/17] pspp-sheet-view: Add "fixed-height" and "fixed-height-set" properties., Ben Pfaff, 2012/04/22
- [PATCH 17/17] psppire-cell-renderer-button: Add "slash" property., Ben Pfaff, 2012/04/22
- [PATCH 16/17] psppire-cell-renderer-button: New cell renderer for GtkButton., Ben Pfaff, 2012/04/22
- [PATCH 02/17] pspp-sheet-view: Reduce time and memory cost to O(1) in number of rows., Ben Pfaff, 2012/04/22
- [PATCH 01/17] Import GtkTreeView from GTK+ 2.0-2.20.1 renamed as PsppSheetView., Ben Pfaff, 2012/04/22
- Re: [PATCH 00/17] Implement PsppSheetView, Ben Pfaff, 2012/04/24