pspp-dev
[Top][All Lists]
Advanced

[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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]