"Fossies" - the Fresh Open Source Software Archive

Member "gtkdatabox-1.0.0/gtk/gtkdatabox_grid.c" (31 Mar 2021, 17128 Bytes) of package /linux/privat/gtkdatabox-1.0.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 /* $Id: gtkdatabox_grid.c 4 2008-06-22 09:19:11Z rbock $ */
    2 /* GtkDatabox - An extension to the gtk+ library
    3  * Copyright (C) 1998 - 2008  Dr. Roland Bock
    4  *
    5  * This program is free software; you can redistribute it and/or
    6  * modify it under the terms of the GNU Lesser General Public License
    7  * as published by the Free Software Foundation; either version 2.1
    8  * of the License, or (at your option) any later version.
    9  *
   10  * This program is distributed in the hope that it will be useful,
   11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   13  * GNU Lesser General Public License for more details.
   14  *
   15  * You should have received a copy of the GNU General Public License
   16  * along with this program; if not, write to the Free Software
   17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   18  */
   19 
   20 #include <gtkdatabox_grid.h>
   21 #include <math.h>
   22 
   23 static void gtk_databox_grid_real_draw (GtkDataboxGraph * grid,
   24                     GtkDatabox* box);
   25 static cairo_t* gtk_databox_grid_real_create_gc (GtkDataboxGraph * graph,
   26                          GtkDatabox* box);
   27 
   28 /* IDs of properties */
   29 enum
   30 {
   31    GRID_HLINES = 1,
   32    GRID_VLINES,
   33    GRID_HLINE_VALS,
   34    GRID_VLINE_VALS,
   35    GRID_LINE_STYLE
   36 };
   37 
   38 /**
   39  * GtkDataboxGridPrivate
   40  *
   41  * A private data structure used by the #GtkDataboxGrid. It shields all internal things
   42  * from developers who are just using the object.
   43  *
   44  **/
   45 typedef struct _GtkDataboxGridPrivate GtkDataboxGridPrivate;
   46 
   47 struct _GtkDataboxGridPrivate
   48 {
   49    gint hlines;
   50    gint vlines;
   51    gfloat *hline_vals;
   52    gfloat *vline_vals;
   53    GtkDataboxGridLineStyle line_style;
   54 };
   55 
   56 G_DEFINE_TYPE_WITH_PRIVATE(GtkDataboxGrid, gtk_databox_grid,
   57     GTK_DATABOX_TYPE_GRAPH)
   58 
   59 static void
   60 gtk_databox_grid_set_property (GObject * object,
   61                    guint property_id,
   62                    const GValue * value, GParamSpec * pspec)
   63 {
   64    GtkDataboxGrid *grid = GTK_DATABOX_GRID (object);
   65 
   66    switch (property_id)
   67    {
   68    case GRID_HLINES:
   69       {
   70      gtk_databox_grid_set_hlines (grid, g_value_get_int (value));
   71       }
   72       break;
   73    case GRID_VLINES:
   74       {
   75      gtk_databox_grid_set_vlines (grid, g_value_get_int (value));
   76       }
   77       break;
   78    case GRID_HLINE_VALS:
   79       {
   80      gtk_databox_grid_set_hline_vals (grid, (gfloat *) g_value_get_pointer (value));
   81       }
   82       break;
   83    case GRID_VLINE_VALS:
   84       {
   85      gtk_databox_grid_set_vline_vals (grid, (gfloat *) g_value_get_pointer (value));
   86       }
   87       break;
   88    case GRID_LINE_STYLE:
   89       {
   90      gtk_databox_grid_set_line_style (grid, g_value_get_int (value));
   91       }
   92       break;
   93    default:
   94       /* We don't have any other property... */
   95       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
   96       break;
   97    }
   98 }
   99 
  100 static void
  101 gtk_databox_grid_get_property (GObject * object,
  102                    guint property_id,
  103                    GValue * value, GParamSpec * pspec)
  104 {
  105    GtkDataboxGrid *grid = GTK_DATABOX_GRID (object);
  106 
  107    switch (property_id)
  108    {
  109    case GRID_HLINES:
  110       {
  111      g_value_set_int (value, gtk_databox_grid_get_hlines (grid));
  112       }
  113       break;
  114    case GRID_VLINES:
  115       {
  116      g_value_set_int (value, gtk_databox_grid_get_vlines (grid));
  117       }
  118       break;
  119    case GRID_HLINE_VALS:
  120       {
  121     g_value_set_pointer (value, gtk_databox_grid_get_hline_vals (grid));
  122       }
  123       break;
  124    case GRID_VLINE_VALS:
  125       {
  126     g_value_set_pointer (value, gtk_databox_grid_get_vline_vals (grid));
  127       }
  128       break;
  129    case GRID_LINE_STYLE:
  130       {
  131      g_value_set_int (value, gtk_databox_grid_get_line_style (grid));
  132       }
  133       break;
  134    default:
  135       /* We don't have any other property... */
  136       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
  137       break;
  138    }
  139 }
  140 
  141 
  142 
  143 static cairo_t*
  144 gtk_databox_grid_real_create_gc (GtkDataboxGraph * graph,
  145                  GtkDatabox* box)
  146 {
  147    cairo_t *cr;
  148 
  149    g_return_val_if_fail (GTK_DATABOX_IS_GRID (graph), NULL);
  150 
  151    cr = GTK_DATABOX_GRAPH_CLASS (gtk_databox_grid_parent_class)->create_gc (graph, box);
  152 
  153    return cr;
  154 }
  155 
  156 static void
  157 grid_finalize (GObject * object)
  158 {
  159   /* Chain up to the parent class */
  160   G_OBJECT_CLASS (gtk_databox_grid_parent_class)->finalize (object);
  161 }
  162 
  163 static void
  164 gtk_databox_grid_class_init (GtkDataboxGridClass *klass)
  165 {
  166    GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
  167    GtkDataboxGraphClass *graph_class = GTK_DATABOX_GRAPH_CLASS (klass);
  168    GParamSpec *grid_param_spec;
  169 
  170    gobject_class->set_property = gtk_databox_grid_set_property;
  171    gobject_class->get_property = gtk_databox_grid_get_property;
  172    gobject_class->finalize = grid_finalize;
  173 
  174    grid_param_spec = g_param_spec_int ("grid-hlines", "grid-hlines", "Number of horizontal lines", G_MININT, G_MAXINT, 0,   /* default value */
  175                        G_PARAM_READWRITE);
  176 
  177    g_object_class_install_property (gobject_class,
  178                     GRID_HLINES, grid_param_spec);
  179 
  180    grid_param_spec = g_param_spec_int ("grid-vlines", "grid-vlines", "Number of vertical lines", G_MININT, G_MAXINT, 0, /* default value */
  181                        G_PARAM_READWRITE);
  182 
  183    g_object_class_install_property (gobject_class,
  184                     GRID_VLINES, grid_param_spec);
  185 
  186    grid_param_spec = g_param_spec_pointer ("grid-hline-vals", "Grid Hline Vals", "The locations of each of the horizontal lines", G_PARAM_READWRITE);
  187 
  188    g_object_class_install_property (gobject_class,
  189                     GRID_HLINE_VALS, grid_param_spec);
  190 
  191    grid_param_spec = g_param_spec_pointer ("grid-vline-vals", "Grid Vline Vals", "The locations of each of the vertical lines", G_PARAM_READWRITE);
  192 
  193    g_object_class_install_property (gobject_class,
  194                     GRID_VLINE_VALS, grid_param_spec);
  195 
  196    grid_param_spec = g_param_spec_int ("line-style", "line-style", "Line style of grid lines",
  197                        GTK_DATABOX_GRID_DASHED_LINES, GTK_DATABOX_GRID_DOTTED_LINES,
  198                        GTK_DATABOX_GRID_DASHED_LINES,
  199                        G_PARAM_READWRITE);
  200 
  201    g_object_class_install_property (gobject_class,
  202                     GRID_LINE_STYLE, grid_param_spec);
  203 
  204 
  205    graph_class->draw = gtk_databox_grid_real_draw;
  206    graph_class->create_gc = gtk_databox_grid_real_create_gc;
  207 }
  208 
  209 static void
  210 gtk_databox_grid_init (GtkDataboxGrid *grid)
  211 {
  212    if (grid == NULL) g_warning ("grid_init with NULL");
  213 }
  214 
  215 /**
  216  * gtk_databox_grid_new:
  217  * @hlines: number of horizontal lines in the grid
  218  * @vlines: number of vertical lines in the grid
  219  * @color: color of the grid
  220  * @size: line width of the grid
  221  *
  222  * Creates a new #GtkDataboxGrid object which can be added to a #GtkDatabox widget as nice decoration for other graphs.
  223  *
  224  * Return value: A new #GtkDataboxGrid object
  225  **/
  226 GtkDataboxGraph *
  227 gtk_databox_grid_new (gint hlines, gint vlines, GdkRGBA * color, guint size)
  228 {
  229    GtkDataboxGrid *grid;
  230    grid = g_object_new (GTK_DATABOX_TYPE_GRID,
  231             "color", color,
  232             "size", size,
  233             "grid-hlines", hlines, "grid-vlines", vlines, "grid-hline-vals",NULL, "grid-vline-vals", NULL, NULL);
  234 
  235    return GTK_DATABOX_GRAPH (grid);
  236 }
  237 
  238 /**
  239  * gtk_databox_grid_array_new:
  240  * @hlines: number of horizontal lines in the grid
  241  * @vlines: number of vertical lines in the grid
  242  * @hline_vals: a pointer to an array of gfloat horizontal grid coordinate
  243  * @vline_vals: a pointer to an array of gfloat vertical grid coordinate
  244  * @color: color of the grid
  245  * @size: line width of the grid
  246  *
  247  * Creates a new #GtkDataboxGrid object which can be added to a #GtkDatabox widget as nice decoration for other graphs.
  248  *
  249  * Return value: A new #GtkDataboxGrid object
  250  **/
  251 GtkDataboxGraph *gtk_databox_grid_array_new (gint hlines, gint vlines, gfloat * local_hline_vals, gfloat * local_vline_vals,
  252                       GdkRGBA * color, guint size)
  253 {
  254    GtkDataboxGrid *grid;
  255 
  256    grid = g_object_new (GTK_DATABOX_TYPE_GRID,
  257             "color", color,
  258             "size", size,
  259             "grid-hlines", hlines, "grid-vlines", vlines, "grid-hline-vals", local_hline_vals, "grid-vline-vals", local_vline_vals, NULL);
  260 
  261    return GTK_DATABOX_GRAPH (grid);
  262 }
  263 
  264 static void
  265 gtk_databox_grid_real_draw (GtkDataboxGraph * graph,
  266                 GtkDatabox* box)
  267 {
  268    GtkWidget *widget;
  269    GtkDataboxGrid *grid = GTK_DATABOX_GRID (graph);
  270    GtkDataboxGridPrivate *priv = gtk_databox_grid_get_instance_private(grid);
  271    gint i = 0;
  272    gfloat x;
  273    gfloat y;
  274    gint16 width;
  275    gint16 height;
  276    gfloat offset_x;
  277    gfloat offset_y;
  278    gfloat factor_x;
  279    gfloat factor_y;
  280    gint16 pixel_x;
  281    gint16 pixel_y;
  282    gfloat left, right, top, bottom;
  283    double pixel_right, pixel_left, pixel_top, pixel_bottom;
  284    double target_spacing, grid_spacing;
  285    double grid_dot[] = {0.0, 0.0};
  286    cairo_t *cr;
  287    GtkAllocation allocation;
  288 
  289    g_return_if_fail (GTK_DATABOX_IS_GRID (grid));
  290    g_return_if_fail (GTK_IS_DATABOX (box));
  291 
  292    widget = GTK_WIDGET(box);
  293    gtk_widget_get_allocation(widget, &allocation);
  294 
  295    gtk_databox_get_total_limits (box, &left, &right, &top, &bottom);
  296 
  297    cr = gtk_databox_graph_create_gc (graph, box);
  298 
  299    width = allocation.width;
  300    height = allocation.height;
  301 
  302    offset_x = left;
  303    factor_x =
  304       (right - left) / (priv->vlines + 1);
  305 
  306    offset_y = top;
  307    factor_y =
  308       (bottom - top) / (priv->hlines + 1);
  309 
  310    /* Cairo accepts spacing of dotted and dashed lines in user-space
  311     * coordinates, in our case, pixels, but using floating point
  312     * values, and we use this to our advantage!
  313     *
  314     * For normal size dotted lines, we target a dot every five pixels,
  315     * but adjust this so that horizontal and vertical grid lines
  316     * always meet at a dot.
  317     *
  318     * For normal size dashed lines, we target five pixel dashes with
  319     * five pixel spaces between them, but adjust this so that grid
  320     * crossings always occur in the middle of a dash.
  321     *
  322     * We widen the target spacing if the line size is wider.
  323     *
  324     * This doesn't work for custom hline_vals, but we'll always get
  325     * something close to five pixels per dot or dash.
  326     */
  327 
  328    pixel_right = gtk_databox_value_to_pixel_x (box, right);
  329    pixel_left = gtk_databox_value_to_pixel_x (box, left);
  330    grid_spacing = (pixel_right - pixel_left)/(priv->vlines+1);
  331    target_spacing = 4.0 + cairo_get_line_width(cr);
  332 
  333    switch (priv->line_style) {
  334    case GTK_DATABOX_GRID_DASHED_LINES:
  335      grid_spacing /= 2*round(grid_spacing/target_spacing/2);
  336      cairo_set_dash(cr, &grid_spacing, 1, grid_spacing/2);
  337      break;
  338 
  339    case GTK_DATABOX_GRID_DOTTED_LINES:
  340      grid_spacing /= round(grid_spacing/target_spacing);
  341      grid_dot[1] = grid_spacing;
  342      cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
  343      cairo_set_dash(cr, grid_dot, 2, 0.0);
  344      break;
  345 
  346    case GTK_DATABOX_GRID_SOLID_LINES:
  347      break;
  348    }
  349 
  350    if (priv->hline_vals == NULL)
  351       for (i = 0; i < priv->hlines; i++)
  352       {
  353          y = offset_y + (i + 1) * factor_y;
  354          pixel_y = gtk_databox_value_to_pixel_y (box, y);
  355          cairo_move_to (cr, 0.0, pixel_y + 0.5);
  356          cairo_line_to (cr, width, pixel_y + 0.5);
  357       }
  358    else
  359       for (i = 0; i < priv->hlines; i++)
  360       {
  361          y = priv->hline_vals[i];
  362          pixel_y = gtk_databox_value_to_pixel_y (box, y);
  363          cairo_move_to (cr, 0.0, pixel_y + 0.5);
  364          cairo_line_to (cr, width, pixel_y + 0.5);
  365       }
  366 
  367    cairo_stroke(cr);
  368 
  369    pixel_bottom = gtk_databox_value_to_pixel_y (box, bottom);
  370    pixel_top = gtk_databox_value_to_pixel_y (box, top);
  371    grid_spacing = (pixel_bottom - pixel_top)/(priv->hlines+1);
  372 
  373    switch (priv->line_style) {
  374    case GTK_DATABOX_GRID_DASHED_LINES:
  375      grid_spacing /= 2*round(grid_spacing/target_spacing/2);
  376      cairo_set_dash(cr, &grid_spacing, 1, grid_spacing/2);
  377      break;
  378 
  379    case GTK_DATABOX_GRID_DOTTED_LINES:
  380      grid_spacing /= round(grid_spacing/target_spacing);
  381      grid_dot[1] = grid_spacing;
  382      cairo_set_dash(cr, grid_dot, 2, 0.0);
  383      break;
  384 
  385    case GTK_DATABOX_GRID_SOLID_LINES:
  386      break;
  387    }
  388 
  389    if (priv->vline_vals == NULL)
  390       for (i = 0; i < priv->vlines; i++)
  391       {
  392          x = offset_x + (i + 1) * factor_x;
  393          pixel_x = gtk_databox_value_to_pixel_x (box, x);
  394          cairo_move_to (cr, pixel_x + 0.5, 0.0);
  395          cairo_line_to (cr, pixel_x + 0.5, height);
  396       }
  397    else
  398       for (i = 0; i < priv->vlines; i++)
  399       {
  400          x = priv->vline_vals[i];
  401          pixel_x = gtk_databox_value_to_pixel_x (box, x);
  402          cairo_move_to (cr, pixel_x + 0.5, 0);
  403          cairo_line_to (cr, pixel_x + 0.5, height);
  404       }
  405    cairo_stroke(cr);
  406    cairo_destroy(cr);
  407 
  408    return;
  409 }
  410 
  411 /**
  412  * gtk_databox_grid_set_hlines:
  413  * @grid: a #GtkDataboxGrid graph object
  414  * @hlines: number of vertical lines in the grid
  415  *
  416  * Sets the number of horizontal lines in the @grid.
  417  **/
  418 void
  419 gtk_databox_grid_set_hlines (GtkDataboxGrid * grid, gint hlines)
  420 {
  421    g_return_if_fail (GTK_DATABOX_IS_GRID (grid));
  422    GtkDataboxGridPrivate *priv = gtk_databox_grid_get_instance_private(grid);
  423    priv->hlines = MAX (1, hlines);
  424 
  425    g_object_notify (G_OBJECT (grid), "grid-hlines");
  426 }
  427 
  428 /**
  429  * gtk_databox_grid_get_hlines:
  430  * @grid: a #GtkDataboxGrid graph object
  431  *
  432  * Gets the number of horizontal lines in the @grid.
  433  *
  434  * Return value: Number of horizontal lines in the @grid.
  435  **/
  436 gint
  437 gtk_databox_grid_get_hlines (GtkDataboxGrid * grid)
  438 {
  439    g_return_val_if_fail (GTK_DATABOX_IS_GRID (grid), -1);
  440    GtkDataboxGridPrivate *priv = gtk_databox_grid_get_instance_private(grid);
  441    return priv->hlines;
  442 }
  443 
  444 /**
  445  * gtk_databox_grid_set_vlines:
  446  * @grid: a #GtkDataboxGrid graph object
  447  * @vlines: number of vertical lines in the grid
  448  *
  449  * Sets the number of vertical lines in the @grid.
  450  **/
  451 void
  452 gtk_databox_grid_set_vlines (GtkDataboxGrid * grid, gint vlines)
  453 {
  454    g_return_if_fail (GTK_DATABOX_IS_GRID (grid));
  455    GtkDataboxGridPrivate *priv = gtk_databox_grid_get_instance_private(grid);
  456    priv->vlines = MAX (1, vlines);
  457 
  458    g_object_notify (G_OBJECT (grid), "grid-vlines");
  459 }
  460 
  461 /**
  462  * gtk_databox_grid_get_vlines:
  463  * @grid: a #GtkDataboxGrid graph object
  464  *
  465  * Gets the number of vertical lines in the @grid.
  466  *
  467  * Return value: Number of vertical lines in the @grid.
  468  **/
  469 gint
  470 gtk_databox_grid_get_vlines (GtkDataboxGrid * grid)
  471 {
  472    g_return_val_if_fail (GTK_DATABOX_IS_GRID (grid), -1);
  473    GtkDataboxGridPrivate *priv = gtk_databox_grid_get_instance_private(grid);
  474    return priv->vlines;
  475 }
  476 
  477 /**
  478  * gtk_databox_grid_set_hline_vals:
  479  * @grid: a #GtkDataboxGrid graph object
  480  * @hline_vals: sets the pointer to the hline values for the grid
  481  *
  482  * Sets the pointer to the horizontal lines in the @grid.
  483  **/
  484 void
  485 gtk_databox_grid_set_hline_vals (GtkDataboxGrid * grid, gfloat *hline_vals)
  486 {
  487    g_return_if_fail (GTK_DATABOX_IS_GRID (grid));
  488    GtkDataboxGridPrivate *priv = gtk_databox_grid_get_instance_private(grid);
  489    priv->hline_vals = hline_vals;
  490 
  491    g_object_notify (G_OBJECT (grid), "grid-hline-vals");
  492 }
  493 
  494 /**
  495  * gtk_databox_grid_get_hline_vals:
  496  * @grid: a #GtkDataboxGrid graph object
  497  *
  498  * Gets the pointer to the horizontal line values for the @grid.
  499  *
  500  * Return value: Pointer to the horizontal line values for the @grid. (or NULL if error)
  501  **/
  502 gfloat*
  503 gtk_databox_grid_get_hline_vals (GtkDataboxGrid * grid)
  504 {
  505    g_return_val_if_fail (GTK_DATABOX_IS_GRID (grid), NULL);
  506    GtkDataboxGridPrivate *priv = gtk_databox_grid_get_instance_private(grid);
  507    return priv->hline_vals;
  508 }
  509 
  510 /**
  511  * gtk_databox_grid_set_vline_vals:
  512  * @grid: a #GtkDataboxGrid graph object
  513  * @vline_vals: sets the pointer to the vline values for the grid
  514  *
  515  * Sets the pointer to the vertical lines in the @grid.
  516  **/
  517 void
  518 gtk_databox_grid_set_vline_vals (GtkDataboxGrid * grid, gfloat *vline_vals)
  519 {
  520    g_return_if_fail (GTK_DATABOX_IS_GRID (grid));
  521    GtkDataboxGridPrivate *priv = gtk_databox_grid_get_instance_private(grid);
  522    priv->vline_vals = vline_vals;
  523 
  524    g_object_notify (G_OBJECT (grid), "grid-vline-vals");
  525 }
  526 
  527 /**
  528  * gtk_databox_grid_get_vline_vals:
  529  * @grid: a #GtkDataboxGrid graph object
  530  *
  531  * Gets the pointer to the vertical line values for the @grid.
  532  *
  533  * Return value: Pointer to the vertical line values for the @grid. (or NULL if error)
  534  **/
  535 gfloat*
  536 gtk_databox_grid_get_vline_vals (GtkDataboxGrid * grid)
  537 {
  538    g_return_val_if_fail (GTK_DATABOX_IS_GRID (grid), NULL);
  539    GtkDataboxGridPrivate *priv = gtk_databox_grid_get_instance_private(grid);
  540    return priv->vline_vals;
  541 }
  542 
  543 /**
  544  * gtk_databox_grid_set_line_style:
  545  * @grid: a #GtkDataboxGrid graph object
  546  * @line_style: GTK_DATABOX_GRID_DASHED_LINES,
  547  *   GTK_DATABOX_GRID_SOLID_LINES, or GTK_DATABOX_GRID_DOTTED_LINES
  548  *
  549  * Sets the line style to draw the lines in the @grid.
  550  **/
  551 void
  552 gtk_databox_grid_set_line_style (GtkDataboxGrid *grid, gint line_style)
  553 {
  554      g_return_if_fail (GTK_DATABOX_IS_GRID (grid));
  555      GtkDataboxGridPrivate *priv = gtk_databox_grid_get_instance_private(grid);
  556      priv->line_style = line_style;
  557 
  558      g_object_notify (G_OBJECT (grid), "line-style");
  559 }
  560 
  561 /**
  562  * gtk_databox_grid_get_line_style:
  563  * @grid: a #GtkDataboxGrid graph object
  564  *
  565  * Retrieve the line style to draw the lines in the @grid.
  566  *
  567  * Return value: GTK_DATABOX_GRID_DASHED_LINES,
  568  *   GTK_DATABOX_GRID_SOLID_LINES, or GTK_DATABOX_GRID_DOTTED_LINES
  569  **/
  570 gint
  571 gtk_databox_grid_get_line_style (GtkDataboxGrid *grid)
  572 {
  573   g_return_val_if_fail (GTK_DATABOX_IS_GRID (grid), -1);
  574   GtkDataboxGridPrivate *priv = gtk_databox_grid_get_instance_private(grid);
  575   return priv->line_style;
  576 }