gtk3 - adapted draw routine to gtk_cairo_should_draw_window. gtk-criticals with undef...
[pspp] / src / ui / gui / pspp-sheet-view.c
index 7f9a12258466dff3677f24bafdc8c219787aabbd..d13d995efd3547c5a2825120894a9a630a691dfc 100644 (file)
@@ -135,6 +135,8 @@ enum {
   PROP_MODEL,
   PROP_HADJUSTMENT,
   PROP_VADJUSTMENT,
+  PROP_HSCROLL_POLICY,
+  PROP_VSCROLL_POLICY,
   PROP_HEADERS_VISIBLE,
   PROP_HEADERS_CLICKABLE,
   PROP_REORDERABLE,
@@ -295,6 +297,12 @@ static void     pspp_sheet_view_top_row_to_dy (PsppSheetView *tree_view);
 static void     invalidate_empty_focus      (PsppSheetView *tree_view);
 
 /* Internal functions */
+static GtkAdjustment *pspp_sheet_view_do_get_hadjustment (PsppSheetView *);
+static GtkAdjustment *pspp_sheet_view_do_get_vadjustment (PsppSheetView *);
+static void pspp_sheet_view_do_set_hadjustment (PsppSheetView   *tree_view,
+                                              GtkAdjustment *adjustment);
+static void pspp_sheet_view_do_set_vadjustment (PsppSheetView   *tree_view,
+                                              GtkAdjustment *adjustment);
 static void     pspp_sheet_view_add_move_binding               (GtkBindingSet      *binding_set,
                                                              guint               keyval,
                                                              guint               modmask,
@@ -451,7 +459,8 @@ static GtkBindingSet *edit_bindings;
 
 G_DEFINE_TYPE_WITH_CODE (PsppSheetView, pspp_sheet_view, GTK_TYPE_CONTAINER,
                         G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
-                                               pspp_sheet_view_buildable_init))
+                                               pspp_sheet_view_buildable_init)
+                         G_IMPLEMENT_INTERFACE (GTK_TYPE_SCROLLABLE, NULL))
 
 static void
 pspp_sheet_view_get_preferred_width (GtkWidget *widget,
@@ -556,21 +565,10 @@ pspp_sheet_view_class_init (PsppSheetViewClass *class)
                                                        GTK_TYPE_TREE_MODEL,
                                                        GTK_PARAM_READWRITE));
 
-  g_object_class_install_property (o_class,
-                                   PROP_HADJUSTMENT,
-                                   g_param_spec_object ("hadjustment",
-                                                       P_("Horizontal Adjustment"),
-                                                        P_("Horizontal Adjustment for the widget"),
-                                                        GTK_TYPE_ADJUSTMENT,
-                                                        GTK_PARAM_READWRITE));
-
-  g_object_class_install_property (o_class,
-                                   PROP_VADJUSTMENT,
-                                   g_param_spec_object ("vadjustment",
-                                                       P_("Vertical Adjustment"),
-                                                        P_("Vertical Adjustment for the widget"),
-                                                        GTK_TYPE_ADJUSTMENT,
-                                                        GTK_PARAM_READWRITE));
+  g_object_class_override_property (o_class, PROP_HADJUSTMENT,    "hadjustment");
+  g_object_class_override_property (o_class, PROP_VADJUSTMENT,    "vadjustment");
+  g_object_class_override_property (o_class, PROP_HSCROLL_POLICY, "hscroll-policy");
+  g_object_class_override_property (o_class, PROP_VSCROLL_POLICY, "vscroll-policy");
 
   g_object_class_install_property (o_class,
                                    PROP_HEADERS_VISIBLE,
@@ -1121,6 +1119,9 @@ pspp_sheet_view_init (PsppSheetView *tree_view)
   tree_view->priv->button_style = NULL;
 
   tree_view->dispose_has_run = FALSE;
+
+  pspp_sheet_view_do_set_vadjustment (tree_view, NULL);
+  pspp_sheet_view_do_set_hadjustment (tree_view, NULL);
 }
 
 \f
@@ -1144,12 +1145,20 @@ pspp_sheet_view_set_property (GObject         *object,
       pspp_sheet_view_set_model (tree_view, g_value_get_object (value));
       break;
     case PROP_HADJUSTMENT:
-      pspp_sheet_view_set_hadjustment (tree_view, g_value_get_object (value));
+      pspp_sheet_view_do_set_hadjustment (tree_view, g_value_get_object (value));
       break;
     case PROP_VADJUSTMENT:
-      pspp_sheet_view_set_vadjustment (tree_view, g_value_get_object (value));
+      pspp_sheet_view_do_set_vadjustment (tree_view, g_value_get_object (value));
       break;
-    case PROP_HEADERS_VISIBLE:
+    case PROP_HSCROLL_POLICY:
+      tree_view->priv->hscroll_policy = g_value_get_enum (value);
+      gtk_widget_queue_resize (GTK_WIDGET (tree_view));
+      break;
+    case PROP_VSCROLL_POLICY:
+      tree_view->priv->vscroll_policy = g_value_get_enum (value);
+      gtk_widget_queue_resize (GTK_WIDGET (tree_view));
+      break;
+     case PROP_HEADERS_VISIBLE:
       pspp_sheet_view_set_headers_visible (tree_view, g_value_get_boolean (value));
       break;
     case PROP_HEADERS_CLICKABLE:
@@ -1232,6 +1241,12 @@ pspp_sheet_view_get_property (GObject    *object,
     case PROP_VADJUSTMENT:
       g_value_set_object (value, tree_view->priv->vadjustment);
       break;
+    case PROP_HSCROLL_POLICY:
+      g_value_set_enum (value, tree_view->priv->hscroll_policy);
+      break;
+    case PROP_VSCROLL_POLICY:
+      g_value_set_enum (value, tree_view->priv->vscroll_policy);
+      break;
     case PROP_HEADERS_VISIBLE:
       g_value_set_boolean (value, pspp_sheet_view_get_headers_visible (tree_view));
       break;
@@ -1964,12 +1979,6 @@ pspp_sheet_view_size_allocate_columns (GtkWidget *widget,
 
       pspp_sheet_view_column_size_allocate (column, &col_allocation);
 
-      if (span_intersects (col_allocation.x, col_allocation.width,
-                           gtk_adjustment_get_value (tree_view->priv->hadjustment),
-                           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,
                                 col_allocation.x + (rtl ? 0 : col_allocation.width) - TREE_VIEW_DRAG_WIDTH/2,
@@ -3819,21 +3828,24 @@ pspp_sheet_view_draw_vertical_grid_lines (PsppSheetView    *tree_view,
   for (list = tree_view->priv->columns; list; list = list->next, i++)
     {
       PsppSheetViewColumn *column = list->data;
-
-      /* We don't want a line for the last column */
-      if (i == n_visible_columns - 1)
-       break;
+      gint x;
 
       if (! column->visible)
        continue;
 
       current_x += column->width;
 
+      /* Generally the grid lines should fit within the column, but for the
+         last visible column we put it just past the end of the column.
+         (Otherwise horizontal grid lines sometimes stick out by one pixel.) */
+      x = current_x;
+      if (i != n_visible_columns - 1)
+        x--;
+
       cairo_set_line_width (cr, 1.0);
       cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE);
-      cairo_move_to (cr, current_x - 0.5, min_y);
-      cairo_line_to (cr, current_x - 0.5 , max_y - min_y);
-      
+      cairo_move_to (cr, x + 0.5, min_y);
+      cairo_line_to (cr, x + 0.5, max_y - min_y);
       cairo_stroke (cr);
     }
 }
@@ -3844,9 +3856,9 @@ pspp_sheet_view_draw_vertical_grid_lines (PsppSheetView    *tree_view,
  * KEEP IN SYNC WITH pspp_sheet_view_create_row_drag_icon()!
  * FIXME: It's not...
  */
-static gboolean
-pspp_sheet_view_bin_expose (GtkWidget      *widget,
-                           cairo_t *cr)
+static void
+pspp_sheet_view_draw_bin (GtkWidget      *widget,
+                         cairo_t *cr)
 {
   PsppSheetView *tree_view = PSPP_SHEET_VIEW (widget);
   GtkTreePath *path;
@@ -3882,6 +3894,9 @@ pspp_sheet_view_bin_expose (GtkWidget      *widget,
   GtkAllocation allocation;
   gtk_widget_get_allocation (widget, &allocation);
 
+  GdkRectangle exposed_rect;
+  gdk_cairo_get_clip_rectangle (cr, &exposed_rect);
+  
   Zarea.x =      0;
   Zarea.y =      0;
   Zarea.height = allocation.height;
@@ -3899,13 +3914,13 @@ pspp_sheet_view_bin_expose (GtkWidget      *widget,
   if (tree_view->priv->row_count == 0)
     {
       draw_empty_focus (tree_view);
-      return TRUE;
+      return;
     }
 
 #if GTK3_TRANSITION
   /* clip event->area to the visible area */
   if (Zarea.height < 0.5)
-    return TRUE;
+    return;
 #endif
 
   validate_visible_area (tree_view);
@@ -3936,7 +3951,7 @@ pspp_sheet_view_bin_expose (GtkWidget      *widget,
     }
 
   if (node < 0)
-    return TRUE;
+    return;
 
   /* find the path for the node */
   path = _pspp_sheet_view_find_path ((PsppSheetView *)widget, node);
@@ -4119,11 +4134,14 @@ pspp_sheet_view_bin_expose (GtkWidget      *widget,
 
 #if GTK3_TRANSITION
          if (gdk_region_rect_in (event->region, &background_area) == GDK_OVERLAP_RECTANGLE_OUT)
+#else
+         if (!gdk_rectangle_intersect (&background_area, &exposed_rect, NULL))
+#endif
            {
              cell_offset += column->width;
              continue;
            }
-#endif
+
 
          pspp_sheet_view_column_cell_set_cell_data (column,
                                                      tree_view->priv->model,
@@ -4244,7 +4262,7 @@ pspp_sheet_view_bin_expose (GtkWidget      *widget,
 #endif
                }
 
-             if (y_offset + max_height >= Zarea.height - 0.5)
+             if (y_offset + max_height <= Zarea.height - 0.5)
                {
 #if GTK3_TRANSITION
                  gdk_draw_line (event->window,
@@ -4423,7 +4441,7 @@ pspp_sheet_view_bin_expose (GtkWidget      *widget,
               done = TRUE;
 
               /* Sanity Check! */
-              TREE_VIEW_INTERNAL_ASSERT (has_next, FALSE);
+              TREE_VIEW_INTERNAL_ASSERT_VOID (has_next);
             }
           else
             goto done;
@@ -4459,7 +4477,7 @@ done:
   if (drag_dest_path)
     gtk_tree_path_free (drag_dest_path);
 
-  return FALSE;
+  return;
 }
 
 
@@ -4468,17 +4486,14 @@ pspp_sheet_view_draw (GtkWidget      *widget,
                      cairo_t *cr)
 {
   PsppSheetView *tree_view = PSPP_SHEET_VIEW (widget);
-  GtkAllocation allocation;
-  gtk_widget_get_allocation (widget, &allocation);
   
   if (gtk_cairo_should_draw_window (cr, tree_view->priv->bin_window))
     {
-      gboolean retval;
       GList *tmp_list;
 
       cairo_save (cr);
-      cairo_translate (cr, 0, gdk_window_get_height (tree_view->priv->header_window));
-      retval = pspp_sheet_view_bin_expose (widget, cr);
+      gtk_cairo_transform_to_window(cr,widget,tree_view->priv->bin_window);
+      pspp_sheet_view_draw_bin (widget, cr);
       cairo_restore (cr);
 
       /* We can't just chain up to Container::expose as it will try to send the
@@ -4493,26 +4508,12 @@ pspp_sheet_view_draw (GtkWidget      *widget,
 
          gtk_container_propagate_draw (GTK_CONTAINER (tree_view), child->widget, cr);
        }
-
-      return retval;
     }
-  else if (gtk_cairo_should_draw_window (cr, tree_view->priv->header_window))
+  if (gtk_cairo_should_draw_window (cr, tree_view->priv->header_window))
     {
       gint n_visible_columns;
       GList *list;
 
-      gtk_paint_flat_box (gtk_widget_get_style (widget),
-                          cr,
-                          GTK_STATE_NORMAL,
-                          GTK_SHADOW_NONE,
-                          widget,
-                          "cell_odd",
-                         allocation.x,
-                         allocation.y,
-                         allocation.width,
-                         allocation.height
-                         );
-
       for (list = tree_view->priv->columns; list != NULL; list = list->next)
        {
          PsppSheetViewColumn *column = list->data;
@@ -4521,7 +4522,8 @@ pspp_sheet_view_draw (GtkWidget      *widget,
            continue;
 
           if (span_intersects (column->allocation.x, column->allocation.width,
-                              allocation.x, allocation.width)
+                               (int) gtk_adjustment_get_value (tree_view->priv->hadjustment),
+                               (int) gtk_widget_get_allocated_width (widget))
               && column->button != NULL)
             gtk_container_propagate_draw (GTK_CONTAINER (tree_view),
                                          column->button, cr);
@@ -4534,21 +4536,21 @@ pspp_sheet_view_draw (GtkWidget      *widget,
             continue;
           n_visible_columns ++;
         }
+      cairo_save (cr);
+      gtk_cairo_transform_to_window(cr,widget,tree_view->priv->header_window);
       pspp_sheet_view_draw_vertical_grid_lines (tree_view,
                                                cr,
                                                n_visible_columns,
-                                               allocation.y,
-                                               allocation.height);
-
-      return TRUE;
+                                               0,
+                                               TREE_VIEW_HEADER_HEIGHT (tree_view));
+      cairo_restore (cr);
     }
-  else if (gtk_cairo_should_draw_window (cr, tree_view->priv->drag_window))
+  if (tree_view->priv->drag_window &&
+      gtk_cairo_should_draw_window (cr, tree_view->priv->drag_window))
     {
       gtk_container_propagate_draw (GTK_CONTAINER (tree_view),
                                    tree_view->priv->drag_column->button,
                                    cr);
-     
-      return TRUE;
     }
 
   return FALSE;
@@ -6705,13 +6707,6 @@ pspp_sheet_view_focus_column (PsppSheetView *tree_view,
   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 (focus_column->button == NULL)
-       return;
-    }
 
   if (gtk_container_get_focus_child (GTK_CONTAINER (tree_view)) != focus_column->button)
     gtk_widget_grab_focus (focus_column->button);
@@ -6842,7 +6837,6 @@ pspp_sheet_view_header_focus (PsppSheetView      *tree_view,
           if (column->visible &&
              pspp_sheet_view_column_can_focus (column))
             {
-              pspp_sheet_view_column_set_need_button (column, TRUE);
               if (column->button)
                 {
                   pspp_sheet_view_focus_column (tree_view, column,
@@ -8985,23 +8979,6 @@ pspp_sheet_view_adjustment_changed (GtkAdjustment *adjustment,
           if (!tree_view->priv->in_top_row_to_dy)
             pspp_sheet_view_dy_to_top_row (tree_view);
        }
-
-      for (list = tree_view->priv->columns; list; list = list->next)
-        {
-          PsppSheetViewColumn *column = list->data;
-          GtkAllocation *col_allocation = &column->allocation;
-         GtkAllocation widget_allocation;
-         gtk_widget_get_allocation (GTK_WIDGET (tree_view), &widget_allocation);
-
-          if (span_intersects (col_allocation->x, col_allocation->width,
-                               gtk_adjustment_get_value (tree_view->priv->hadjustment),
-                               widget_allocation.width))
-            {
-              pspp_sheet_view_column_set_need_button (column, TRUE);
-              if (!column->button)
-                pspp_sheet_view_column_update_button (column);
-            }
-        }
     }
 }
 
@@ -9214,9 +9191,12 @@ pspp_sheet_view_get_hadjustment (PsppSheetView *tree_view)
 {
   g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), NULL);
 
-  if (tree_view->priv->hadjustment == NULL)
-    pspp_sheet_view_set_hadjustment (tree_view, NULL);
+  return pspp_sheet_view_do_get_hadjustment (tree_view);
+}
 
+static GtkAdjustment *
+pspp_sheet_view_do_get_hadjustment (PsppSheetView *tree_view)
+{
   return tree_view->priv->hadjustment;
 }
 
@@ -9240,23 +9220,60 @@ pspp_sheet_view_set_hadjustment (PsppSheetView   *tree_view,
   g_object_notify (G_OBJECT (tree_view), "hadjustment");
 }
 
+static void
+pspp_sheet_view_do_set_hadjustment (PsppSheetView   *tree_view,
+                                  GtkAdjustment *adjustment)
+{
+  PsppSheetViewPrivate *priv = tree_view->priv;
+
+  if (adjustment && priv->hadjustment == adjustment)
+    return;
+
+  if (priv->hadjustment != NULL)
+    {
+      g_signal_handlers_disconnect_by_func (priv->hadjustment,
+                                            pspp_sheet_view_adjustment_changed,
+                                            tree_view);
+      g_object_unref (priv->hadjustment);
+    }
+
+  if (adjustment == NULL)
+    adjustment = gtk_adjustment_new (0.0, 0.0, 0.0,
+                                     0.0, 0.0, 0.0);
+
+  g_signal_connect (adjustment, "value-changed",
+                    G_CALLBACK (pspp_sheet_view_adjustment_changed), tree_view);
+  priv->hadjustment = g_object_ref_sink (adjustment);
+  /* FIXME: Adjustment should probably be populated here with fresh values, but
+   * internal details are too complicated for me to decipher right now.
+   */
+  pspp_sheet_view_adjustment_changed (NULL, tree_view);
+
+  g_object_notify (G_OBJECT (tree_view), "hadjustment");
+}
+
 /**
  * pspp_sheet_view_get_vadjustment:
  * @tree_view: A #PsppSheetView
  *
  * Gets the #GtkAdjustment currently being used for the vertical aspect.
  *
- * Return value: A #GtkAdjustment object, or %NULL if none is currently being
- * used.
+ * Return value: (transfer none): A #GtkAdjustment object, or %NULL
+ *     if none is currently being used.
+ *
+ * Deprecated: 3.0: Use gtk_scrollable_get_vadjustment()
  **/
 GtkAdjustment *
 pspp_sheet_view_get_vadjustment (PsppSheetView *tree_view)
 {
   g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), NULL);
 
-  if (tree_view->priv->vadjustment == NULL)
-    pspp_sheet_view_set_vadjustment (tree_view, NULL);
+  return pspp_sheet_view_do_get_vadjustment (tree_view);
+}
 
+static GtkAdjustment *
+pspp_sheet_view_do_get_vadjustment (PsppSheetView *tree_view)
+{
   return tree_view->priv->vadjustment;
 }
 
@@ -9266,17 +9283,47 @@ pspp_sheet_view_get_vadjustment (PsppSheetView *tree_view)
  * @adjustment: (allow-none): The #GtkAdjustment to set, or %NULL
  *
  * Sets the #GtkAdjustment for the current vertical aspect.
+ *
+ * Deprecated: 3.0: Use gtk_scrollable_set_vadjustment()
  **/
 void
 pspp_sheet_view_set_vadjustment (PsppSheetView   *tree_view,
-                              GtkAdjustment *adjustment)
+                               GtkAdjustment *adjustment)
 {
   g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
+  g_return_if_fail (adjustment == NULL || GTK_IS_ADJUSTMENT (adjustment));
 
-  pspp_sheet_view_set_adjustments (tree_view,
-                                tree_view->priv->hadjustment,
-                                adjustment);
+  pspp_sheet_view_do_set_vadjustment (tree_view, adjustment);
+}
 
+static void
+pspp_sheet_view_do_set_vadjustment (PsppSheetView   *tree_view,
+                                  GtkAdjustment *adjustment)
+{
+  PsppSheetViewPrivate *priv = tree_view->priv;
+
+  if (adjustment && priv->vadjustment == adjustment)
+    return;
+
+  if (priv->vadjustment != NULL)
+    {
+      g_signal_handlers_disconnect_by_func (priv->vadjustment,
+                                            pspp_sheet_view_adjustment_changed,
+                                            tree_view);
+      g_object_unref (priv->vadjustment);
+    }
+
+  if (adjustment == NULL)
+    adjustment = gtk_adjustment_new (0.0, 0.0, 0.0,
+                                     0.0, 0.0, 0.0);
+
+  g_signal_connect (adjustment, "value-changed",
+                    G_CALLBACK (pspp_sheet_view_adjustment_changed), tree_view);
+  priv->vadjustment = g_object_ref_sink (adjustment);
+  /* FIXME: Adjustment should probably be populated here with fresh values, but
+   * internal details are too complicated for me to decipher right now.
+   */
+  pspp_sheet_view_adjustment_changed (NULL, tree_view);
   g_object_notify (G_OBJECT (tree_view), "vadjustment");
 }