LCOV - code coverage report
Current view: top level - gnucash/register/register-gnome - gnucash-header.c (source / functions) Hit Total Coverage
Test: gnucash.info Lines: 0 319 0.0 %
Date: 2024-10-31 11:06:40 Functions: 0 21 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : /********************************************************************\
       2                 :            :  * This program is free software; you can redistribute it and/or    *
       3                 :            :  * modify it under the terms of the GNU General Public License as   *
       4                 :            :  * published by the Free Software Foundation; either version 2 of   *
       5                 :            :  * the License, or (at your option) any later version.              *
       6                 :            :  *                                                                  *
       7                 :            :  * This program is distributed in the hope that it will be useful,  *
       8                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
       9                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
      10                 :            :  * GNU General Public License for more details.                     *
      11                 :            :  *                                                                  *
      12                 :            :  * You should have received a copy of the GNU General Public License*
      13                 :            :  * along with this program; if not, contact:                        *
      14                 :            :  *                                                                  *
      15                 :            :  * Free Software Foundation           Voice:  +1-617-542-5942       *
      16                 :            :  * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
      17                 :            :  * Boston, MA  02110-1301,  USA       gnu@gnu.org                   *
      18                 :            :  *                                                                  *
      19                 :            : \********************************************************************/
      20                 :            : 
      21                 :            : /*
      22                 :            :  * The Gnucash Header Canvas
      23                 :            :  *
      24                 :            :  * Authors:
      25                 :            :  *     Heath Martin <martinh@pegasus.cc.ucf.edu>
      26                 :            :  *     Dave Peticolas <dave@krondo.com>
      27                 :            :  */
      28                 :            : 
      29                 :            : #include <config.h>
      30                 :            : 
      31                 :            : #include <string.h>
      32                 :            : 
      33                 :            : #include "gnucash-sheet.h"
      34                 :            : #include "gnucash-sheetP.h"
      35                 :            : #include "gnucash-color.h"
      36                 :            : #include "gnucash-style.h"
      37                 :            : #include "gnucash-cursor.h"
      38                 :            : #include "gnucash-item-edit.h"
      39                 :            : #include "gnc-gtk-utils.h"
      40                 :            : 
      41                 :            : #include "gnucash-header.h"
      42                 :            : 
      43                 :            : enum
      44                 :            : {
      45                 :            :     PROP_0,
      46                 :            :     PROP_SHEET,       /*  the sheet this header is associated with */
      47                 :            :     PROP_CURSOR_NAME, /* the name of the current cursor */
      48                 :            : };
      49                 :            : 
      50                 :          0 : G_DEFINE_TYPE (GncHeader, gnc_header, GTK_TYPE_LAYOUT)
      51                 :            : 
      52                 :            : static void
      53                 :          0 : gnc_header_draw_offscreen (GncHeader *header)
      54                 :            : {
      55                 :          0 :     SheetBlockStyle *style = header->style;
      56                 :          0 :     GncItemEdit *item_edit = GNC_ITEM_EDIT(header->sheet->item_editor);
      57                 :          0 :     Table *table = header->sheet->table;
      58                 :            :     VirtualLocation virt_loc;
      59                 :            :     VirtualCell *vcell;
      60                 :            :     guint32 color_type;
      61                 :          0 :     GtkStyleContext *stylectxt = gtk_widget_get_style_context (GTK_WIDGET(header));
      62                 :            :     GdkRGBA color;
      63                 :            :     int row_offset;
      64                 :            :     CellBlock *cb;
      65                 :            :     int i;
      66                 :            :     cairo_t *cr;
      67                 :            : 
      68                 :          0 :     virt_loc.vcell_loc.virt_row = 0;
      69                 :          0 :     virt_loc.vcell_loc.virt_col = 0;
      70                 :          0 :     virt_loc.phys_row_offset = 0;
      71                 :          0 :     virt_loc.phys_col_offset = 0;
      72                 :            : 
      73                 :          0 :     gtk_style_context_save (stylectxt);
      74                 :            : 
      75                 :            :     // Get the color type and apply the css class
      76                 :          0 :     color_type = gnc_table_get_color (table, virt_loc, NULL);
      77                 :          0 :     gnucash_get_style_classes (header->sheet, stylectxt, color_type, FALSE);
      78                 :            : 
      79                 :          0 :     if (header->surface)
      80                 :          0 :         cairo_surface_destroy (header->surface);
      81                 :          0 :     header->surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
      82                 :            :                                                   header->width,
      83                 :            :                                                   header->height);
      84                 :            : 
      85                 :          0 :     cr = cairo_create (header->surface);
      86                 :            : 
      87                 :            :     // Fill background color of header
      88                 :          0 :     gtk_render_background (stylectxt, cr, 0, 0, header->width, header->height);
      89                 :            : 
      90                 :          0 :     gdk_rgba_parse (&color, "black");
      91                 :          0 :     cairo_set_source_rgb (cr, color.red, color.green, color.blue);
      92                 :          0 :     cairo_rectangle (cr, 0.5, 0.5, header->width - 1.0, header->height - 1.0);
      93                 :          0 :     cairo_set_line_width (cr, 1.0);
      94                 :          0 :     cairo_stroke (cr);
      95                 :            : 
      96                 :            :     // Draw bottom horizontal line, makes bottom line thicker
      97                 :          0 :     cairo_move_to (cr, 0.5, header->height - 1.5);
      98                 :          0 :     cairo_line_to (cr, header->width - 1.0, header->height - 1.5);
      99                 :          0 :     cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE);
     100                 :          0 :     cairo_set_line_width (cr, 1.0);
     101                 :          0 :     cairo_stroke (cr);
     102                 :            : 
     103                 :            :     /*font = gnucash_register_font;*/
     104                 :            : 
     105                 :          0 :     vcell = gnc_table_get_virtual_cell
     106                 :            :             (table, table->current_cursor_loc.vcell_loc);
     107                 :          0 :     cb = vcell ? vcell->cellblock : NULL;
     108                 :          0 :     row_offset = 0;
     109                 :            : 
     110                 :          0 :     for (i = 0; i < style->nrows; i++)
     111                 :            :     {
     112                 :          0 :         int col_offset = 0;
     113                 :          0 :         int height = 0, j;
     114                 :          0 :         virt_loc.phys_row_offset = i;
     115                 :            : 
     116                 :            :         /* TODO: This routine is duplicated in several places.
     117                 :            :            Can we abstract at least the cell drawing routine?
     118                 :            :            That way we'll be sure everything is drawn
     119                 :            :            consistently, and cut down on maintenance issues. */
     120                 :            : 
     121                 :          0 :         for (j = 0; j < style->ncols; j++)
     122                 :            :         {
     123                 :            :             CellDimensions *cd;
     124                 :            :             BasicCell *cell;
     125                 :            :             const char *text;
     126                 :            :             int width;
     127                 :            :             PangoLayout *layout;
     128                 :            :             PangoRectangle logical_rect;
     129                 :            :             GdkRectangle rect;
     130                 :            :             int x_offset;
     131                 :            : 
     132                 :          0 :             virt_loc.phys_col_offset = j;
     133                 :            : 
     134                 :          0 :             cd = gnucash_style_get_cell_dimensions (style, i, j);
     135                 :          0 :             if (!cd) continue;
     136                 :            : 
     137                 :          0 :             height = cd->pixel_height;
     138                 :          0 :             if (header->in_resize && (j == header->resize_col))
     139                 :          0 :                 width = header->resize_col_width;
     140                 :            :             else
     141                 :          0 :                 width = cd->pixel_width;
     142                 :            : 
     143                 :          0 :             cell = gnc_cellblock_get_cell (cb, i, j);
     144                 :          0 :             if (!cell || !cell->cell_name)
     145                 :            :             {
     146                 :          0 :                 col_offset += width;
     147                 :          0 :                 continue;
     148                 :            :             }
     149                 :            : 
     150                 :          0 :             cairo_rectangle (cr, col_offset - 0.5, row_offset + 0.5, width, height);
     151                 :          0 :             cairo_set_line_width (cr, 1.0);
     152                 :          0 :             cairo_stroke (cr);
     153                 :            : 
     154                 :          0 :             virt_loc.vcell_loc =
     155                 :            :                 table->current_cursor_loc.vcell_loc;
     156                 :          0 :             text = gnc_table_get_label (table, virt_loc);
     157                 :          0 :             if (!text)
     158                 :          0 :                 text = "";
     159                 :            : 
     160                 :          0 :             layout = gtk_widget_create_pango_layout (GTK_WIDGET(header->sheet), text);
     161                 :            : 
     162                 :          0 :             pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
     163                 :            : 
     164                 :          0 :             gnucash_sheet_set_text_bounds (header->sheet, &rect,
     165                 :            :                                            col_offset, row_offset, width, height);
     166                 :            : 
     167                 :          0 :             cairo_save (cr);
     168                 :          0 :             cairo_rectangle (cr, rect.x, rect.y, rect.width, rect.height);
     169                 :          0 :             cairo_clip (cr);
     170                 :            : 
     171                 :          0 :             x_offset = gnucash_sheet_get_text_offset (header->sheet, virt_loc,
     172                 :            :                                                       rect.width, logical_rect.width);
     173                 :            : 
     174                 :          0 :             gtk_render_layout (stylectxt, cr, rect.x + x_offset,
     175                 :          0 :                                rect.y + gnc_item_edit_get_padding_border (item_edit, top), layout);
     176                 :            : 
     177                 :          0 :             cairo_restore (cr);
     178                 :          0 :             g_object_unref (layout);
     179                 :            : 
     180                 :          0 :             col_offset += width;
     181                 :            :         }
     182                 :          0 :         row_offset += height;
     183                 :            :     }
     184                 :          0 :     gtk_style_context_restore (stylectxt);
     185                 :            : 
     186                 :          0 :     cairo_destroy (cr);
     187                 :          0 : }
     188                 :            : 
     189                 :            : 
     190                 :            : gint
     191                 :          0 : gnc_header_get_cell_offset (GncHeader *header, gint col, gint *cell_width)
     192                 :            : {
     193                 :          0 :     SheetBlockStyle *style = header->style;
     194                 :            :     gint j;
     195                 :          0 :     gint offset = 0;
     196                 :            : 
     197                 :          0 :     for (j = 0; j < style->ncols; j++)
     198                 :            :     {
     199                 :            :         CellDimensions *cd;
     200                 :            : 
     201                 :          0 :         cd = gnucash_style_get_cell_dimensions (style, 0, j);
     202                 :          0 :         if (!cd) continue;
     203                 :            : 
     204                 :          0 :         if (j == col)
     205                 :            :         {
     206                 :          0 :             *cell_width = cd->pixel_width;
     207                 :          0 :             break;
     208                 :            :         }
     209                 :          0 :         offset = offset + cd->pixel_width;
     210                 :            :     }
     211                 :          0 :     return offset;
     212                 :            : }
     213                 :            : 
     214                 :            : 
     215                 :            : static gboolean
     216                 :          0 : gnc_header_draw (GtkWidget *header, cairo_t *cr)
     217                 :            : {
     218                 :          0 :     GnucashSheet *sheet = GNC_HEADER(header)->sheet;
     219                 :          0 :     GdkWindow *sheet_layout_win = gtk_layout_get_bin_window (GTK_LAYOUT(sheet));
     220                 :            :     gint x, y;
     221                 :            : 
     222                 :            :     // use this to get the scroll x value to align the header
     223                 :          0 :     gdk_window_get_position (sheet_layout_win, &x, &y);
     224                 :            : 
     225                 :            :     // if the register page is moved to another window, the surface is
     226                 :            :     // not created so test for a surface and create one if null
     227                 :          0 :     if (GNC_HEADER(header)->surface == NULL)
     228                 :          0 :         gnc_header_draw_offscreen (GNC_HEADER(header));
     229                 :            : 
     230                 :          0 :     cairo_set_source_surface (cr, GNC_HEADER(header)->surface, x, 0);
     231                 :          0 :     cairo_paint (cr);
     232                 :            : 
     233                 :          0 :     return TRUE;
     234                 :            : }
     235                 :            : 
     236                 :            : 
     237                 :            : void
     238                 :          0 : gnc_header_request_redraw (GncHeader *header)
     239                 :            : {
     240                 :          0 :     if (!header->style)
     241                 :          0 :         return;
     242                 :            : 
     243                 :          0 :     gnc_header_draw_offscreen (header);
     244                 :          0 :     gtk_widget_queue_draw (GTK_WIDGET(header));
     245                 :            : }
     246                 :            : 
     247                 :            : 
     248                 :            : static void
     249                 :          0 : gnc_header_unrealize (GtkWidget *widget)
     250                 :            : {
     251                 :          0 :     GncHeader *header = GNC_HEADER(widget);
     252                 :          0 :     if (header->surface)
     253                 :          0 :         cairo_surface_destroy (header->surface);
     254                 :          0 :     header->surface = NULL;
     255                 :            : 
     256                 :          0 :     if (header->resize_cursor)
     257                 :          0 :         g_object_unref (header->resize_cursor);
     258                 :          0 :     header->resize_cursor = NULL;
     259                 :            : 
     260                 :          0 :     if (header->normal_cursor)
     261                 :          0 :         g_object_unref (header->normal_cursor);
     262                 :          0 :     header->normal_cursor = NULL;
     263                 :            : 
     264                 :          0 :     if (GTK_WIDGET_CLASS(gnc_header_parent_class)->unrealize)
     265                 :          0 :         GTK_WIDGET_CLASS(gnc_header_parent_class)->unrealize (GTK_WIDGET(header));
     266                 :          0 : }
     267                 :            : 
     268                 :            : 
     269                 :            : static void
     270                 :          0 : gnc_header_finalize (GObject *object)
     271                 :            : {
     272                 :            :     GncHeader *header;
     273                 :            : 
     274                 :          0 :     header = GNC_HEADER(object);
     275                 :            : 
     276                 :          0 :     g_free (header->cursor_name);
     277                 :          0 :     header->cursor_name = NULL;
     278                 :            : 
     279                 :          0 :     G_OBJECT_CLASS(gnc_header_parent_class)->finalize (object);
     280                 :          0 : }
     281                 :            : 
     282                 :            : 
     283                 :            : void
     284                 :          0 : gnc_header_reconfigure (GncHeader *header)
     285                 :            : {
     286                 :            :     GnucashSheet *sheet;
     287                 :            :     SheetBlockStyle *old_style;
     288                 :            :     int w, h;
     289                 :            : 
     290                 :          0 :     g_return_if_fail (header != NULL);
     291                 :          0 :     g_return_if_fail (GNC_IS_HEADER(header));
     292                 :            : 
     293                 :          0 :     sheet = GNUCASH_SHEET(header->sheet);
     294                 :          0 :     old_style = header->style;
     295                 :            : 
     296                 :          0 :     header->style = gnucash_sheet_get_style_from_cursor
     297                 :          0 :                     (sheet, header->cursor_name);
     298                 :            : 
     299                 :          0 :     if (header->style == NULL)
     300                 :          0 :         return;
     301                 :            : 
     302                 :          0 :     sheet->width = header->style->dimensions->width;
     303                 :            : 
     304                 :          0 :     w = header->style->dimensions->width;
     305                 :          0 :     h = header->style->dimensions->height;
     306                 :          0 :     h *= header->num_phys_rows;
     307                 :          0 :     h /= header->style->nrows;
     308                 :          0 :     h += 2;
     309                 :            : 
     310                 :          0 :     if (header->height != h ||
     311                 :          0 :             header->width != w  ||
     312                 :          0 :             header->style != old_style)
     313                 :            :     {
     314                 :          0 :         header->height = h;
     315                 :          0 :         header->width = w;
     316                 :          0 :         gtk_layout_set_size (GTK_LAYOUT(header), w, h);
     317                 :          0 :         gtk_widget_set_size_request (GTK_WIDGET(header), -1, h);
     318                 :          0 :         gnc_header_request_redraw (header);
     319                 :            :     }
     320                 :            : }
     321                 :            : 
     322                 :            : void
     323                 :          0 : gnc_header_set_header_rows (GncHeader *header,
     324                 :            :                             int num_phys_rows)
     325                 :            : {
     326                 :          0 :     g_return_if_fail (header != NULL);
     327                 :          0 :     g_return_if_fail (GNC_IS_HEADER(header));
     328                 :            : 
     329                 :          0 :     header->num_phys_rows = num_phys_rows;
     330                 :            : }
     331                 :            : 
     332                 :            : /*
     333                 :            :  *  Returns FALSE if pointer not on a resize line, else returns
     334                 :            :  *  TRUE. Returns the index of the column to the left in the col
     335                 :            :  *  argument.
     336                 :            :  */
     337                 :            : static gboolean
     338                 :          0 : pointer_on_resize_line (GncHeader *header, int x, G_GNUC_UNUSED int y, int *col)
     339                 :            : {
     340                 :          0 :     SheetBlockStyle *style = header->style;
     341                 :          0 :     gboolean on_the_line = FALSE;
     342                 :            :     CellDimensions *cd;
     343                 :          0 :     int pixels = 0;
     344                 :            :     int j;
     345                 :            : 
     346                 :          0 :     for (j = 0; j < style->ncols; j++)
     347                 :            :     {
     348                 :          0 :         cd = gnucash_style_get_cell_dimensions (style, 0, j);
     349                 :          0 :         if (!cd) continue;
     350                 :            : 
     351                 :          0 :         pixels += cd->pixel_width;
     352                 :          0 :         if (x >= pixels - 1 && x <= pixels + 1)
     353                 :          0 :             on_the_line = TRUE;
     354                 :          0 :         if (x <= pixels + 1)
     355                 :          0 :             break;
     356                 :            :     }
     357                 :            : 
     358                 :          0 :     if (col != NULL)
     359                 :          0 :         *col = j;
     360                 :            : 
     361                 :          0 :     return on_the_line;
     362                 :            : }
     363                 :            : 
     364                 :            : static int
     365                 :          0 : find_resize_col (GncHeader *header, int col)
     366                 :            : {
     367                 :          0 :     SheetBlockStyle *style = header->style;
     368                 :            :     CellDimensions *cd;
     369                 :          0 :     int start = col;
     370                 :            : 
     371                 :          0 :     if (col < 0 || col >= style->ncols)
     372                 :          0 :         return -1;
     373                 :            : 
     374                 :            :     /* skip to the right over zero-width columns */
     375                 :          0 :     while ((col + 1 < style->ncols) &&
     376                 :          0 :             (cd = gnucash_style_get_cell_dimensions (style, 0, col + 1)) &&
     377                 :          0 :             cd && (cd->pixel_width == 0))
     378                 :          0 :         ++col;
     379                 :            : 
     380                 :            :     /* now go back left till we have a resizable column */
     381                 :          0 :     while (col >= start)
     382                 :            :     {
     383                 :          0 :         if (gnucash_style_col_is_resizable (style, col))
     384                 :          0 :             return col;
     385                 :            :         else
     386                 :          0 :             col--;
     387                 :            :     }
     388                 :            : 
     389                 :            :     /* didn't find a resizable column to the right of col */
     390                 :          0 :     return -1;
     391                 :            : }
     392                 :            : 
     393                 :            : static void
     394                 :          0 : gnc_header_resize_column (GncHeader *header, gint col, gint width)
     395                 :            : {
     396                 :          0 :     GnucashSheet *sheet = header->sheet;
     397                 :            : 
     398                 :          0 :     gnucash_sheet_set_col_width (sheet, col, width);
     399                 :            : 
     400                 :          0 :     gnucash_cursor_configure (GNUCASH_CURSOR(sheet->cursor));
     401                 :          0 :     gnc_item_edit_configure (gnucash_sheet_get_item_edit (sheet));
     402                 :            : 
     403                 :          0 :     gnc_header_reconfigure (header);
     404                 :            : 
     405                 :          0 :     gnucash_sheet_set_scroll_region (sheet);
     406                 :          0 :     gnucash_sheet_update_adjustments (sheet);
     407                 :            : 
     408                 :          0 :     gnc_header_request_redraw (header);
     409                 :          0 :     gnucash_sheet_redraw_all (sheet);
     410                 :          0 : }
     411                 :            : 
     412                 :            : static void
     413                 :          0 : gnc_header_auto_resize_column (GncHeader *header, gint col)
     414                 :            : {
     415                 :            :     int width;
     416                 :            : 
     417                 :          0 :     width = gnucash_sheet_col_max_width (header->sheet, 0, col);
     418                 :            : 
     419                 :          0 :     gnc_header_resize_column (header, col, width);
     420                 :          0 : }
     421                 :            : 
     422                 :            : static gint
     423                 :          0 : gnc_header_event (GtkWidget *widget, GdkEvent *event)
     424                 :            : {
     425                 :          0 :     GncHeader *header = GNC_HEADER(widget);
     426                 :          0 :     GdkWindow *window = gtk_widget_get_window (widget);
     427                 :            :     int x, y;
     428                 :            :     int col;
     429                 :            : 
     430                 :          0 :     if (!header->resize_cursor)
     431                 :          0 :         header->resize_cursor = gdk_cursor_new_for_display (gdk_window_get_display (window),
     432                 :            :                                                             GDK_SB_H_DOUBLE_ARROW);
     433                 :            : 
     434                 :          0 :     switch (event->type)
     435                 :            :     {
     436                 :          0 :     case GDK_MOTION_NOTIFY:
     437                 :          0 :         x = event->motion.x;
     438                 :          0 :         y = event->motion.y;
     439                 :            : 
     440                 :          0 :         if (header->in_resize)
     441                 :            :         {
     442                 :          0 :             int change = x - header->resize_x;
     443                 :          0 :             int new_width = header->resize_col_width + change;
     444                 :            : 
     445                 :          0 :             if (new_width >= 0)
     446                 :            :             {
     447                 :          0 :                 header->resize_x = x;
     448                 :          0 :                 header->resize_col_width = new_width;
     449                 :          0 :                 gnc_header_request_redraw (header);
     450                 :            :             }
     451                 :            : 
     452                 :          0 :             break;
     453                 :            :         }
     454                 :            : 
     455                 :          0 :         if (pointer_on_resize_line (header, x, y, &col) &&
     456                 :          0 :                 gnucash_style_col_is_resizable (header->style, col))
     457                 :          0 :             gdk_window_set_cursor (window, header->resize_cursor);
     458                 :            :         else
     459                 :          0 :             gdk_window_set_cursor (window, header->normal_cursor);
     460                 :          0 :         break;
     461                 :            : 
     462                 :          0 :     case GDK_BUTTON_PRESS:
     463                 :            :     {
     464                 :            :         int col;
     465                 :            : 
     466                 :          0 :         if (event->button.button != 1)
     467                 :          0 :             break;
     468                 :            : 
     469                 :          0 :         x = event->button.x;
     470                 :          0 :         y = event->button.y;
     471                 :            : 
     472                 :          0 :         if (pointer_on_resize_line (header, x, y, &col))
     473                 :          0 :             col = find_resize_col (header, col);
     474                 :            :         else
     475                 :          0 :             col = -1;
     476                 :            : 
     477                 :          0 :         if (col > -1)
     478                 :            :         {
     479                 :            :             CellDimensions *cd;
     480                 :            : 
     481                 :          0 :             cd = gnucash_style_get_cell_dimensions
     482                 :            :                  (header->style, 0, col);
     483                 :          0 :             if (!cd) break;
     484                 :            : 
     485                 :          0 :             header->in_resize = TRUE;
     486                 :          0 :             header->resize_col = col;
     487                 :          0 :             header->resize_col_width = cd->pixel_width;
     488                 :          0 :             header->resize_x = x;
     489                 :            :         }
     490                 :          0 :         break;
     491                 :            :     }
     492                 :          0 :     case GDK_BUTTON_RELEASE:
     493                 :            :     {
     494                 :          0 :         if (event->button.button != 1)
     495                 :          0 :             break;
     496                 :            : 
     497                 :          0 :         if (header->in_resize)
     498                 :            :         {
     499                 :          0 :             if (header->resize_col_width == 0)
     500                 :          0 :                 header->resize_col_width = 1;
     501                 :            : 
     502                 :          0 :             gnc_header_resize_column
     503                 :            :                 (header,
     504                 :            :                  header->resize_col,
     505                 :            :                  header->resize_col_width);
     506                 :          0 :             header->in_resize = FALSE;
     507                 :          0 :             header->resize_col = -1;
     508                 :          0 :             gnc_header_request_redraw (header);
     509                 :            :         }
     510                 :          0 :         break;
     511                 :            :     }
     512                 :            : 
     513                 :          0 :     case GDK_2BUTTON_PRESS:
     514                 :            :     {
     515                 :            :         gboolean on_line;
     516                 :            :         int ptr_col;
     517                 :            :         int resize_col;
     518                 :            : 
     519                 :          0 :         if (event->button.button != 1)
     520                 :          0 :             break;
     521                 :            : 
     522                 :          0 :         x = event->button.x;
     523                 :          0 :         y = event->button.y;
     524                 :            : 
     525                 :          0 :         on_line = pointer_on_resize_line (header, x, y, &ptr_col);
     526                 :            : 
     527                 :            :         /* If we're on a resize line and the column to the right is zero
     528                 :            :            width, resize that one. */
     529                 :          0 :         if (on_line)
     530                 :          0 :             resize_col = find_resize_col (header, ptr_col);
     531                 :            :         else
     532                 :          0 :             resize_col = ptr_col;
     533                 :            : 
     534                 :          0 :         if (resize_col > -1)
     535                 :            :         {
     536                 :          0 :             header->in_resize = FALSE;
     537                 :          0 :             header->resize_col = -1;
     538                 :          0 :             gnc_header_auto_resize_column (header, resize_col);
     539                 :            :         }
     540                 :            :     }
     541                 :          0 :     break;
     542                 :            : 
     543                 :          0 :     default:
     544                 :          0 :         break;
     545                 :            :     }
     546                 :          0 :     return FALSE;
     547                 :            : }
     548                 :            : 
     549                 :            : 
     550                 :            : /* Note that g_value_set_object() refs the object, as does
     551                 :            :  * g_object_get(). But g_object_get() only unrefs once when it disgorges
     552                 :            :  * the object, leaving an unbalanced ref, which leaks. So instead of
     553                 :            :  * using g_value_set_object(), use g_value_take_object() which doesn't
     554                 :            :  * ref the object when used in get_property().
     555                 :            :  */
     556                 :            : static void
     557                 :          0 : gnc_header_get_property (GObject *object,
     558                 :            :                          guint param_id,
     559                 :            :                          GValue *value,
     560                 :            :                          GParamSpec *pspec)
     561                 :            : {
     562                 :          0 :     GncHeader *header = GNC_HEADER(object);
     563                 :            : 
     564                 :          0 :     switch (param_id)
     565                 :            :     {
     566                 :          0 :     case PROP_SHEET:
     567                 :          0 :         g_value_take_object (value, header->sheet);
     568                 :          0 :         break;
     569                 :          0 :     case PROP_CURSOR_NAME:
     570                 :          0 :         g_value_set_string (value, header->cursor_name);
     571                 :          0 :         break;
     572                 :          0 :     default:
     573                 :          0 :         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec);
     574                 :          0 :         break;
     575                 :            :     }
     576                 :          0 : }
     577                 :            : 
     578                 :            : static void
     579                 :          0 : gnc_header_set_property (GObject *object,
     580                 :            :                          guint param_id,
     581                 :            :                          const GValue *value,
     582                 :            :                          GParamSpec *pspec)
     583                 :            : {
     584                 :          0 :     GncHeader *header = GNC_HEADER(object);
     585                 :          0 :     GtkLayout *layout = GTK_LAYOUT(header);
     586                 :          0 :     gboolean needs_update = FALSE;
     587                 :            :     gchar *old_name;
     588                 :            : 
     589                 :          0 :     switch (param_id)
     590                 :            :     {
     591                 :          0 :     case PROP_SHEET:
     592                 :          0 :         header->sheet = GNUCASH_SHEET(g_value_get_object (value));
     593                 :          0 :         gtk_scrollable_set_hadjustment (GTK_SCROLLABLE(layout), header->sheet->hadj);
     594                 :          0 :         needs_update = TRUE;
     595                 :          0 :         break;
     596                 :          0 :     case PROP_CURSOR_NAME:
     597                 :          0 :         old_name = header->cursor_name;
     598                 :            : 
     599                 :          0 :         header->cursor_name = g_value_dup_string (value);
     600                 :          0 :         needs_update = !old_name || !header->cursor_name ||
     601                 :          0 :                        strcmp (old_name, header->cursor_name) != 0;
     602                 :          0 :         g_free (old_name);
     603                 :          0 :         break;
     604                 :          0 :     default:
     605                 :          0 :         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec);
     606                 :          0 :         break;
     607                 :            :     }
     608                 :            : 
     609                 :          0 :     if ((header->sheet != NULL) && needs_update)
     610                 :          0 :         gnc_header_reconfigure (header);
     611                 :          0 : }
     612                 :            : 
     613                 :            : 
     614                 :            : static void
     615                 :          0 : gnc_header_init (GncHeader *header)
     616                 :            : {
     617                 :          0 :     header->sheet = NULL;
     618                 :          0 :     header->cursor_name = NULL;
     619                 :          0 :     header->in_resize = FALSE;
     620                 :          0 :     header->resize_col = -1;
     621                 :          0 :     header->resize_cursor = NULL;
     622                 :          0 :     header->normal_cursor = NULL;
     623                 :          0 :     header->height = 20;
     624                 :          0 :     header->width = 400;
     625                 :          0 :     header->style = NULL;
     626                 :            : 
     627                 :          0 :     gtk_widget_add_events (GTK_WIDGET(header),
     628                 :            :                           (GDK_EXPOSURE_MASK
     629                 :            :                           | GDK_BUTTON_PRESS_MASK
     630                 :            :                           | GDK_BUTTON_RELEASE_MASK
     631                 :            :                           | GDK_POINTER_MOTION_MASK
     632                 :            :                           | GDK_POINTER_MOTION_HINT_MASK));
     633                 :            : 
     634                 :          0 :     g_signal_connect (G_OBJECT(header), "configure_event",
     635                 :            :                       G_CALLBACK(gnc_header_reconfigure), NULL);
     636                 :          0 :     gtk_widget_show_all (GTK_WIDGET(header));
     637                 :          0 : }
     638                 :            : 
     639                 :            : 
     640                 :            : static void
     641                 :          0 : gnc_header_class_init (GncHeaderClass *header_class)
     642                 :            : {
     643                 :          0 :     GObjectClass  *object_class = G_OBJECT_CLASS(header_class);
     644                 :          0 :     GtkWidgetClass *item_class = GTK_WIDGET_CLASS(header_class);
     645                 :            : 
     646                 :          0 :     gtk_widget_class_set_css_name (GTK_WIDGET_CLASS(header_class), "gnc-id-header");
     647                 :            : 
     648                 :          0 :     object_class->finalize = gnc_header_finalize;
     649                 :          0 :     object_class->get_property = gnc_header_get_property;
     650                 :          0 :     object_class->set_property = gnc_header_set_property;
     651                 :            : 
     652                 :          0 :     g_object_class_install_property (object_class,
     653                 :            :                                      PROP_SHEET,
     654                 :            :                                      g_param_spec_object ("sheet",
     655                 :            :                                              "Sheet Value",
     656                 :            :                                              "Sheet Value",
     657                 :            :                                              GNUCASH_TYPE_SHEET,
     658                 :            :                                              G_PARAM_READWRITE));
     659                 :          0 :     g_object_class_install_property (object_class,
     660                 :            :                                      PROP_CURSOR_NAME,
     661                 :            :                                      g_param_spec_string ("cursor_name",
     662                 :            :                                              "Cursor Name",
     663                 :            :                                              "Cursor Name",
     664                 :            :                                              CURSOR_HEADER,
     665                 :            :                                              G_PARAM_READWRITE));
     666                 :            : 
     667                 :            : 
     668                 :          0 :     item_class->unrealize = gnc_header_unrealize;
     669                 :          0 :     item_class->draw      = gnc_header_draw;
     670                 :          0 :     item_class->event     = gnc_header_event;
     671                 :          0 : }
     672                 :            : 
     673                 :            : GtkWidget *
     674                 :          0 : gnc_header_new (GnucashSheet *sheet)
     675                 :            : {
     676                 :            :     GtkWidget *layout;
     677                 :            : 
     678                 :          0 :     layout = g_object_new (GNC_TYPE_HEADER,
     679                 :            :                            "sheet", sheet,
     680                 :            :                            "cursor_name", CURSOR_HEADER,
     681                 :            :                            NULL);
     682                 :            : 
     683                 :          0 :     sheet->header_item = layout;
     684                 :          0 :     return layout;
     685                 :            : }
     686                 :            : 
     687                 :            : 

Generated by: LCOV version 1.14