Sheet Grid Lines: Correct positioning.
[pspp] / src / ui / gui / pspp-sheet-view.c
index 3ae3c18c381ade07f01bc57d3db1c42aacfbfd13..709adea3918cce671c5ea330f307be89acbda23c 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPPIRE - a graphical user interface for PSPP.
-   Copyright (C) 2011, 2012, 2013 Free Software Foundation, Inc.
+   Copyright (C) 2011, 2012, 2013, 2015 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
@@ -93,10 +93,8 @@ typedef struct _PsppSheetViewChild PsppSheetViewChild;
 struct _PsppSheetViewChild
 {
   GtkWidget *widget;
-  gint x;
-  gint y;
-  gint width;
-  gint height;
+  PsppSheetViewColumn *column;
+  int node;
 };
 
 
@@ -402,10 +400,8 @@ static void     pspp_sheet_view_search_init               (GtkWidget        *ent
                                                         PsppSheetView      *tree_view);
 static void     pspp_sheet_view_put                       (PsppSheetView      *tree_view,
                                                         GtkWidget        *child_widget,
-                                                        gint              x,
-                                                        gint              y,
-                                                        gint              width,
-                                                        gint              height);
+                                                        GtkTreePath *path,
+                                                        PsppSheetViewColumn *column);
 static gboolean pspp_sheet_view_start_editing             (PsppSheetView      *tree_view,
                                                         GtkTreePath      *cursor_path);
 static gboolean pspp_sheet_view_editable_button_press_event (GtkWidget *,
@@ -1526,6 +1522,7 @@ pspp_sheet_view_realize (GtkWidget *widget)
   window = gdk_window_new (gtk_widget_get_parent_window (widget),
                            &attributes, attributes_mask);
   gtk_widget_set_window (widget, window);
+
   gtk_widget_register_window (widget, window);
   gtk_widget_get_allocation (widget, &allocation);
 
@@ -1773,7 +1770,9 @@ pspp_sheet_view_size_request (GtkWidget      *widget,
       tmp_list = tmp_list->next;
 
       if (gtk_widget_get_visible (child->widget))
-        gtk_widget_size_request (child->widget, &child_requisition);
+       {
+         gtk_widget_get_preferred_size (child->widget, NULL, &child_requisition);
+       }
     }
 }
 
@@ -2002,6 +2001,24 @@ pspp_sheet_view_size_allocate_columns (GtkWidget *widget,
     gtk_widget_queue_draw (GTK_WIDGET (tree_view));
 }
 
+static void
+update_childrens_allocation (PsppSheetView *tree_view)
+{
+  GList *tmp_list;
+  for (tmp_list = tree_view->priv->children; tmp_list; tmp_list = tmp_list->next)
+    {
+      PsppSheetViewChild *child = tmp_list->data;
+      GtkAllocation allocation;
+      GtkTreePath *path;
+
+      /* totally ignore our child's requisition */
+      path = _pspp_sheet_view_find_path (tree_view, child->node);
+      pspp_sheet_view_get_cell_area (tree_view, path, child->column, &allocation);
+      gtk_tree_path_free (path);
+      gtk_widget_size_allocate (child->widget, &allocation);
+    }
+}
+
 static void
 pspp_sheet_view_size_allocate (GtkWidget     *widget,
                             GtkAllocation *allocation)
@@ -2015,26 +2032,11 @@ pspp_sheet_view_size_allocate (GtkWidget     *widget,
   if (allocation->width != old_allocation.width)
     width_changed = TRUE;
 
+  if (gtk_widget_get_direction(widget) == GTK_TEXT_DIR_RTL)   
+    allocation->x += allocation->width - tree_view->priv->width ;
 
   gtk_widget_set_allocation (widget, allocation);
 
-  tmp_list = tree_view->priv->children;
-
-  while (tmp_list)
-    {
-      GtkAllocation allocation;
-
-      PsppSheetViewChild *child = tmp_list->data;
-      tmp_list = tmp_list->next;
-
-      /* totally ignore our child's requisition */
-      allocation.x = child->x;
-      allocation.y = child->y;
-      allocation.width = child->width;
-      allocation.height = child->height;
-      gtk_widget_size_allocate (child->widget, &allocation);
-    }
-
   /* We size-allocate the columns first because the width of the
    * tree view (used in updating the adjustments below) might change.
    */
@@ -2134,6 +2136,7 @@ pspp_sheet_view_size_allocate (GtkWidget     *widget,
          else
            gtk_widget_queue_draw (widget);
        }
+      update_childrens_allocation(tree_view);
     }
 }
 
@@ -2566,11 +2569,14 @@ pspp_sheet_view_button_press (GtkWidget      *widget,
        {
          gpointer drag_data;
 
-         if (gdk_pointer_grab (column->window, FALSE,
-                               GDK_POINTER_MOTION_HINT_MASK |
-                               GDK_BUTTON1_MOTION_MASK |
-                               GDK_BUTTON_RELEASE_MASK,
-                               NULL, NULL, event->time))
+         if (GDK_GRAB_SUCCESS != gdk_device_grab (event->device,
+                                                  column->window,
+                                                  GDK_OWNERSHIP_NONE,
+                                                  FALSE,
+                                                  GDK_POINTER_MOTION_HINT_MASK |
+                                                  GDK_BUTTON1_MOTION_MASK |
+                                                  GDK_BUTTON_RELEASE_MASK,
+                                                  NULL, event->time))
            return FALSE;
 
          gtk_grab_add (widget);
@@ -2686,8 +2692,8 @@ pspp_sheet_view_button_release_column_resize (GtkWidget      *widget,
 
   PSPP_SHEET_VIEW_UNSET_FLAG (tree_view, PSPP_SHEET_VIEW_IN_COLUMN_RESIZE);
   gtk_grab_remove (widget);
-  gdk_display_pointer_ungrab (gdk_window_get_display (event->window),
-                             event->time);
+  gdk_device_ungrab (event->device, event->time);
+
   return TRUE;
 }
 
@@ -3822,35 +3828,30 @@ pspp_sheet_view_draw_vertical_grid_lines (PsppSheetView    *tree_view,
                                          gint max_y)
 {
   GList *list = tree_view->priv->columns;
-  gint i = 0;
-  gint current_x = 0;
+  gint x = 0;
 
   if (tree_view->priv->grid_lines != PSPP_SHEET_VIEW_GRID_LINES_VERTICAL
       && tree_view->priv->grid_lines != PSPP_SHEET_VIEW_GRID_LINES_BOTH)
     return;
 
   /* Only draw the lines for visible rows and columns */
-  for (list = tree_view->priv->columns; list; list = list->next, i++)
+  gboolean rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
+
+  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;
-      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--;
+      x += column->width;
 
       cairo_set_line_width (cr, 1.0);
       cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE);
       cairo_move_to (cr, x + 0.5, min_y);
-      cairo_line_to (cr, x + 0.5, max_y - min_y);
+      cairo_line_to (cr, x + 0.5, max_y - min_y - 0.5);
       cairo_stroke (cr);
     }
 }
@@ -3887,7 +3888,6 @@ pspp_sheet_view_draw_bin (GtkWidget      *widget,
   gint horizontal_separator;
   gint focus_line_width;
   gboolean allow_rules;
-  gboolean has_special_cell;
   gboolean rtl;
   gint n_visible_columns;
   gint grid_line_width;
@@ -4044,27 +4044,6 @@ pspp_sheet_view_draw_bin (GtkWidget      *widget,
 
       parity = node % 2;
 
-      if (tree_view->priv->special_cells == PSPP_SHEET_VIEW_SPECIAL_CELLS_DETECT)
-        {
-          /* 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);
-        }
-      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;
           list = (rtl ? list->prev : list->next))
@@ -4260,37 +4239,11 @@ pspp_sheet_view_draw_bin (GtkWidget      *widget,
                                                &cell_area,
                                                flags);
 
-          if (node == cursor && has_special_cell &&
-             ((column == tree_view->priv->focus_column &&
-               PSPP_SHEET_VIEW_FLAG_SET (tree_view, PSPP_SHEET_VIEW_DRAW_KEYFOCUS) &&
-               gtk_widget_has_focus (widget)) ||
-              (column == tree_view->priv->edited_column)))
-           {
-             _pspp_sheet_view_column_cell_draw_focus (column,
-                                                      cr,
-                                                    &background_area,
-                                                    &cell_area,
-                                                    flags);
-           }
 
          cell_offset += column->width;
          gtk_style_context_restore (context);
        }
 
-      if (cell_offset < Zarea.x)
-        {
-          gtk_paint_flat_box (gtk_widget_get_style (widget),
-                              cr,
-                              GTK_STATE_NORMAL,
-                              GTK_SHADOW_NONE,
-                              widget,
-                              "base",
-                              cell_offset,
-                              background_area.y,
-                              Zarea.x - cell_offset,
-                              background_area.height);
-        }
-
       if (node == drag_highlight)
         {
           /* Draw indicator for the drop
@@ -4357,54 +4310,6 @@ pspp_sheet_view_draw_bin (GtkWidget      *widget,
 #endif
         }
 
-      /* draw the big row-spanning focus rectangle, if needed */
-      if (!has_special_cell && node == cursor &&
-         PSPP_SHEET_VIEW_FLAG_SET (tree_view, PSPP_SHEET_VIEW_DRAW_KEYFOCUS) &&
-         gtk_widget_has_focus (widget))
-        {
-         gint tmp_y, tmp_height;
-         gint width;
-         GtkStateType focus_rect_state;
-
-         focus_rect_state =
-           flags & GTK_CELL_RENDERER_SELECTED ? GTK_STATE_SELECTED :
-           (flags & GTK_CELL_RENDERER_PRELIT ? GTK_STATE_PRELIGHT :
-            (flags & GTK_CELL_RENDERER_INSENSITIVE ? GTK_STATE_INSENSITIVE :
-             GTK_STATE_NORMAL));
-
-         width = gdk_window_get_width (tree_view->priv->bin_window);
-         
-         if (draw_hgrid_lines)
-           {
-             tmp_y = BACKGROUND_FIRST_PIXEL (tree_view, node) + grid_line_width / 2;
-             tmp_height = ROW_HEIGHT (tree_view) - grid_line_width;
-           }
-         else
-           {
-             tmp_y = BACKGROUND_FIRST_PIXEL (tree_view, node);
-             tmp_height = ROW_HEIGHT (tree_view);
-           }
-
-         if (row_ending_details)
-           gtk_paint_focus (gtk_widget_get_style (widget),
-                            cr,
-                            focus_rect_state,
-                            widget,
-                            (is_first
-                             ? (is_last ? "treeview" : "treeview-left" )
-                             : (is_last ? "treeview-right" : "treeview-middle" )),
-                            0, tmp_y,
-                            width, tmp_height);
-         else
-           gtk_paint_focus (gtk_widget_get_style (widget),
-                            cr,
-                            focus_rect_state,
-                            widget,
-                            "treeview",
-                            0, tmp_y,
-                            width, tmp_height);
-       }
-
       y_offset += max_height;
 
       do
@@ -4485,7 +4390,7 @@ pspp_sheet_view_draw (GtkWidget      *widget,
          tmp_list = tmp_list->next;
 
          gtk_container_propagate_draw (GTK_CONTAINER (tree_view), child->widget, cr);
-       }
+        }
     }
   else
     {
@@ -5220,7 +5125,6 @@ validate_visible_area (PsppSheetView *tree_view)
   GtkTreePath *above_path = NULL;
   GtkTreeIter iter;
   int node = -1;
-  gboolean size_changed = FALSE;
   gint total_height;
   gint area_above = 0;
   gint area_below = 0;
@@ -5394,23 +5298,6 @@ validate_visible_area (PsppSheetView *tree_view)
   pspp_sheet_view_set_top_row (tree_view, above_path, -area_above);
   pspp_sheet_view_top_row_to_dy (tree_view);
 
-  /* update width/height and queue a resize */
-  if (size_changed)
-    {
-      GtkRequisition requisition;
-
-      /* We temporarily guess a size, under the assumption that it will be the
-       * same when we get our next size_allocate.  If we don't do this, we'll be
-       * in an inconsistent state if we call top_row_to_dy. */
-
-      gtk_widget_size_request (GTK_WIDGET (tree_view), &requisition);
-      gtk_adjustment_set_upper (tree_view->priv->hadjustment, MAX (gtk_adjustment_get_upper (tree_view->priv->hadjustment), (gfloat)requisition.width));
-      gtk_adjustment_set_upper (tree_view->priv->vadjustment, MAX (gtk_adjustment_get_upper (tree_view->priv->vadjustment), (gfloat)requisition.height));
-      gtk_adjustment_changed (tree_view->priv->hadjustment);
-      gtk_adjustment_changed (tree_view->priv->vadjustment);
-      gtk_widget_queue_resize (GTK_WIDGET (tree_view));
-    }
-
   gtk_tree_row_reference_free (tree_view->priv->scroll_to_path);
   tree_view->priv->scroll_to_path = NULL;
 
@@ -5481,7 +5368,7 @@ do_presize_handler (PsppSheetView *tree_view)
   if (! gtk_widget_get_realized (GTK_WIDGET (tree_view)))
     return FALSE;
 
-  gtk_widget_size_request (GTK_WIDGET (tree_view), &requisition);
+  gtk_widget_get_preferred_size (GTK_WIDGET (tree_view), NULL, &requisition);
 
   gtk_adjustment_set_upper (tree_view->priv->hadjustment, MAX (gtk_adjustment_get_upper (tree_view->priv->hadjustment), (gfloat)requisition.width));
   gtk_adjustment_set_upper (tree_view->priv->vadjustment, MAX (gtk_adjustment_get_upper (tree_view->priv->vadjustment), (gfloat)requisition.height));
@@ -7122,12 +7009,9 @@ pspp_sheet_view_real_move_cursor (PsppSheetView       *tree_view,
 
 static void
 pspp_sheet_view_put (PsppSheetView *tree_view,
-                  GtkWidget   *child_widget,
-                  /* in bin_window coordinates */
-                  gint         x,
-                  gint         y,
-                  gint         width,
-                  gint         height)
+                    GtkWidget   *child_widget,
+                    GtkTreePath *path,
+                    PsppSheetViewColumn *column)
 {
   PsppSheetViewChild *child;
   
@@ -7137,10 +7021,12 @@ pspp_sheet_view_put (PsppSheetView *tree_view,
   child = g_slice_new (PsppSheetViewChild);
 
   child->widget = child_widget;
-  child->x = x;
-  child->y = y;
-  child->width = width;
-  child->height = height;
+  _pspp_sheet_view_find_node (tree_view, path, &child->node);
+  if (child->node < 0)
+    {
+      g_assert_not_reached ();
+    }
+  child->column = column;
 
   tree_view->priv->children = g_list_append (tree_view->priv->children, child);
 
@@ -7150,43 +7036,6 @@ pspp_sheet_view_put (PsppSheetView *tree_view,
   gtk_widget_set_parent (child_widget, GTK_WIDGET (tree_view));
 }
 
-void
-_pspp_sheet_view_child_move_resize (PsppSheetView *tree_view,
-                                 GtkWidget   *widget,
-                                 /* in tree coordinates */
-                                 gint         x,
-                                 gint         y,
-                                 gint         width,
-                                 gint         height)
-{
-  PsppSheetViewChild *child = NULL;
-  GList *list;
-  GdkRectangle allocation;
-
-  g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
-  g_return_if_fail (GTK_IS_WIDGET (widget));
-
-  for (list = tree_view->priv->children; list; list = list->next)
-    {
-      if (((PsppSheetViewChild *)list->data)->widget == widget)
-       {
-         child = list->data;
-         break;
-       }
-    }
-  if (child == NULL)
-    return;
-
-  allocation.x = child->x = x;
-  allocation.y = child->y = y;
-  allocation.width = child->width = width;
-  allocation.height = child->height = height;
-
-  if (gtk_widget_get_realized (widget))
-    gtk_widget_size_allocate (widget, &allocation);
-}
-
-
 /* TreeModel Callbacks
  */
 
@@ -8690,7 +8539,7 @@ pspp_sheet_view_ensure_interactive_directory (PsppSheetView *tree_view)
   gtk_widget_show (frame);
   gtk_container_add (GTK_CONTAINER (tree_view->priv->search_window), frame);
 
-  vbox = gtk_vbox_new (FALSE, 0);
+  vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
   gtk_widget_show (vbox);
   gtk_container_add (GTK_CONTAINER (frame), vbox);
   gtk_container_set_border_width (GTK_CONTAINER (vbox), 3);
@@ -8842,79 +8691,6 @@ pspp_sheet_view_new_column_width (PsppSheetView *tree_view,
   return width;
 }
 
-
-/* FIXME this adjust_allocation is a big cut-and-paste from
- * GtkCList, needs to be some "official" way to do this
- * factored out.
- */
-typedef struct
-{
-  GdkWindow *window;
-  int dx;
-  int dy;
-} ScrollData;
-
-/* The window to which gtk_widget_get_window (widget) is relative */
-#define ALLOCATION_WINDOW(widget)              \
-   (!gtk_widget_get_has_window (widget) ?              \
-    gtk_widget_get_window (widget) :                          \
-    gdk_window_get_parent (gtk_widget_get_window (widget)))
-
-static void
-adjust_allocation_recurse (GtkWidget *widget,
-                          gpointer   data)
-{
-  ScrollData *scroll_data = data;
-  GtkAllocation allocation;
-  gtk_widget_get_allocation (widget, &allocation);
-  /* Need to really size allocate instead of just poking
-   * into widget->allocation if the widget is not realized.
-   * FIXME someone figure out why this was.
-   */
-  if (!gtk_widget_get_realized (widget))
-    {
-      if (gtk_widget_get_visible (widget))
-       {
-         GdkRectangle tmp_rectangle = allocation;
-         tmp_rectangle.x += scroll_data->dx;
-          tmp_rectangle.y += scroll_data->dy;
-          
-         gtk_widget_size_allocate (widget, &tmp_rectangle);
-       }
-    }
-  else
-    {
-      if (ALLOCATION_WINDOW (widget) == scroll_data->window)
-       {
-         allocation.x += scroll_data->dx;
-          allocation.y += scroll_data->dy;
-          
-         if (GTK_IS_CONTAINER (widget))
-           gtk_container_forall (GTK_CONTAINER (widget),
-                                 adjust_allocation_recurse,
-                                 data);
-       }
-    }
-}
-
-static void
-adjust_allocation (GtkWidget *widget,
-                  int        dx,
-                   int        dy)
-{
-  ScrollData scroll_data;
-
-  if (gtk_widget_get_realized (widget))
-    scroll_data.window = ALLOCATION_WINDOW (widget);
-  else
-    scroll_data.window = NULL;
-    
-  scroll_data.dx = dx;
-  scroll_data.dy = dy;
-  
-  adjust_allocation_recurse (widget, &scroll_data);
-}
-
 void 
 pspp_sheet_view_column_update_button (PsppSheetViewColumn *tree_column);
 
@@ -8925,9 +8701,8 @@ 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,
                       - gtk_adjustment_get_value (tree_view->priv->hadjustment),
                       TREE_VIEW_HEADER_HEIGHT (tree_view));
@@ -8935,48 +8710,26 @@ pspp_sheet_view_adjustment_changed (GtkAdjustment *adjustment,
                       - gtk_adjustment_get_value (tree_view->priv->hadjustment),
                       0);
       dy = tree_view->priv->dy - (int) gtk_adjustment_get_value (tree_view->priv->vadjustment);
-      if (dy)
-       {
-          update_prelight (tree_view,
-                           tree_view->priv->event_last_x,
-                           tree_view->priv->event_last_y - dy);
-
-         if (tree_view->priv->edited_column &&
-              GTK_IS_WIDGET (tree_view->priv->edited_column->editable_widget))
-           {
-             GList *list;
-             GtkWidget *widget;
-             PsppSheetViewChild *child = NULL;
 
-             widget = GTK_WIDGET (tree_view->priv->edited_column->editable_widget);
-             adjust_allocation (widget, 0, dy); 
-             
-             for (list = tree_view->priv->children; list; list = list->next)
-               {
-                 child = (PsppSheetViewChild *)list->data;
-                 if (child->widget == widget)
-                   {
-                     child->y += dy;
-                     break;
-                   }
-               }
-           }
-       }
       gdk_window_scroll (tree_view->priv->bin_window, 0, dy);
 
-      if (tree_view->priv->dy != (int) gtk_adjustment_get_value (tree_view->priv->vadjustment))
+      if (dy != 0)
         {
           /* update our dy and top_row */
           tree_view->priv->dy = (int) gtk_adjustment_get_value (tree_view->priv->vadjustment);
 
+         update_prelight (tree_view,
+                           tree_view->priv->event_last_x,
+                           tree_view->priv->event_last_y);
+
           if (!tree_view->priv->in_top_row_to_dy)
             pspp_sheet_view_dy_to_top_row (tree_view);
        }
+
+      update_childrens_allocation(tree_view);
     }
 }
 
-\f
-
 /* Public methods
  */
 
@@ -12642,7 +12395,6 @@ pspp_sheet_view_real_start_editing (PsppSheetView       *tree_view,
 {
   PsppSheetSelectionMode mode = pspp_sheet_selection_get_mode (tree_view->priv->selection);
   gint pre_val = gtk_adjustment_get_value (tree_view->priv->vadjustment);
-  GtkRequisition requisition;
   gint row;
 
   g_return_if_fail (gtk_tree_path_get_depth (path) == 1);
@@ -12659,25 +12411,12 @@ pspp_sheet_view_real_start_editing (PsppSheetView       *tree_view,
   pspp_sheet_selection_select_column (tree_view->priv->selection, column);
   tree_view->priv->anchor_column = column;
 
-  gtk_widget_size_request (GTK_WIDGET (cell_editable), &requisition);
-
   PSPP_SHEET_VIEW_SET_FLAG (tree_view, PSPP_SHEET_VIEW_DRAW_KEYFOCUS);
 
-  if (requisition.height < cell_area->height)
-    {
-      gint diff = cell_area->height - requisition.height;
-      pspp_sheet_view_put (tree_view,
-                        GTK_WIDGET (cell_editable),
-                        cell_area->x, cell_area->y + diff/2,
-                        cell_area->width, requisition.height);
-    }
-  else
-    {
-      pspp_sheet_view_put (tree_view,
-                        GTK_WIDGET (cell_editable),
-                        cell_area->x, cell_area->y,
-                        cell_area->width, cell_area->height);
-    }
+  pspp_sheet_view_put (tree_view,
+                      GTK_WIDGET (cell_editable),
+                      path,
+                      column);
 
   gtk_cell_editable_start_editing (GTK_CELL_EDITABLE (cell_editable),
                                   (GdkEvent *)event);