Logo Search packages:      
Sourcecode: gacc version File versions  Download package

gAcc_grop.c

/*
 * gAcc_grop.c
 * Thomas Nemeth, le 16.04.2000
 *
 *   Copyright (C) 1999  Thomas Nemeth
 *
 *   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
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */

#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <gtk/gtk.h>
#include "defines.h"
#include "gAcc.h"
#include "acclists.h"
#include "gAcc_grop.h"
#include "accounts.h"
#include "locale_formats.h"
#include "usefull.h"


/*** Create a graphics dialog box ********************************************/

gboolean grop_paint (GtkWidget *widget, void *data) {
    GdkColor     bleu   = { 0,     0,     0, 65535},
                 /*gris   = { 0, 43690, 43690, 43690},*/
                 vert   = { 0,     0, 43690,     0},
                 rouge  = { 0, 65535,     0,     0},
                 violet = { 0, 49152,     0, 49152},
                 blanc  = { 0, 65535, 65535, 65535},
                 noir   = { 0,     0,     0,     0};
    GdkColormap *palette;
    GdkGC       *crayon, *crayon_grid;
    GdkPoint    *point;
    GdkFont     *font;
    G_LABEL     *hscale;
    ACC_ELT     *acc;
    OPE_ELT     *ope, *first;
    float        montant, x_max, y_max, y_min;
    long int     date, date0, today; 
    char         scale_amo[MAXSTRLEN];
    int          i = 1, nb_pts;
    float        x_unit, y_unit;
    int          zero, zeroM, vscale;
    int          drawing_area_width  = GRAPH_W;
    int          drawing_area_height = GRAPH_H;
    int          GROP_SHIFT = 60;
    int          GROP_MIN   = 30;
    int          GROP_MAX;
    int          GROP_XRANGE;
    int          GROP_YRANGE;
    char        *month, *date1, *date2, *sfont, *date_s;

    /* Get default values */
    date1 = config.graph_d0;
    date2 = config.graph_d1;
    sfont = config.graph_fnt;

    #ifdef DEBUG_GACC
        printf ("%s\t%s\t%s\n", date1, date2, sfont);
        printf ("Ligne (compte) : %d\n", selected_row);
    #endif

    /* Get the drawing area size */
    gdk_window_get_size (widget->window,
                         &drawing_area_width,
                         &drawing_area_height);
    GROP_MAX    = drawing_area_height - GROP_MIN;
    GROP_YRANGE = GROP_MAX - GROP_MIN;
    GROP_XRANGE = drawing_area_width - 2 * GROP_SHIFT;

    #ifdef DEBUG_GACC
        printf ("Dimensions : %dx%d (lxh)\n",
                drawing_area_width,
                drawing_area_height);
    #endif

    /* Get firsts elements and initialize */
    acc = get_account (selected_row);
    #ifdef DEBUG_GACC
        printf ("Compte : %s\n",acc->account->name);
    #endif

    ope = acc->account->ope_list_head;
    if (ope == NULL) return FALSE;
    while (ope->operation->cancelled == VRAI) ope = ope->next;
    montant = acc->account->amount;
    #ifdef DEBUG_GACC
        printf ("Montant initial : %.2f\n", montant);
    #endif
    if (atol (date1) < atol (acc->account->date) )
        date_s = acc->account->date;
    else
        date_s = date1;
    date   = atol (ope->operation->date);
    today  = atol (date2);
    date0  = atol (date1);
    #ifdef DEBUG_GACC
        printf ("Date 1ère opération trouvée : %ld (date_s = %s)\n",
                 date, date_s);
    #endif
      /* Go to the date of today but last year */
    while ( (date < date0) && (ope != NULL) ) {
        #ifdef DEBUG_GACC
            printf ("(Recherche) Montant : %.2f\n", montant);
        #endif
        ope = ope->next;
        if (ope != NULL) date = atol (ope->operation->date);
    }
    if (ope == NULL) return FALSE;
    #ifdef DEBUG_GACC
        printf ("Date 1ère opération détectée : %ld\n", date);
    #endif
    /* We are at the good date */
    first = ope;
    if ( (atol (first->operation->date) < atol (date_s) ) &&
         (atol (first->operation->date) > atol (date1) ) )
        date_s = first->operation->date;
    /* Get the operations' number between date0 and today */
    while ( (ope!=NULL) && (date <= today) ) {
        if (ope->operation->cancelled == FAUX) i++;
        ope = ope->next;
        if (ope != NULL) date = atol (ope->operation->date);
    }
    nb_pts = i + 1;
    MY_ALLOC (point, nb_pts, GdkPoint);
    /* Create the line with x = date and y = amount */
    ope        = first;
    point[0].x = 0;
    point[0].y = montant;
    i          = 1;
    y_max      = montant;
    y_min      = montant;
    date       = atol (first->operation->date);
    #ifdef DEBUG_GACC
        printf ("Date 1ère opération utilisée : %s\n", date_s);
    #endif
    while ( (ope!=NULL) && (date <= today) ) {
        if (ope->operation->cancelled == FAUX) {
            if (ope->operation->type == CREDIT)
                montant = ope->operation->amount;
            else
                montant = -ope->operation->amount;
            #ifdef DEBUG_GACC
                printf ("Diffdays (%s, %s) = %d\n",
                         ope->operation->date,
                         date_s,
                         diffdays (ope->operation->date, date_s)
                         );
                printf ("Montant : %.2f\n", montant);
            #endif
            point[i].x = diffdays (ope->operation->date, date_s);
            point[i].y = (int) montant;
            if (montant > y_max) y_max = montant;
            if (montant < y_min) y_min = montant;
            i++;
        }
        ope = ope->next;
        if (ope != NULL) date = atol (ope->operation->date);
    }
    point[i].x = diffdays (date2, date_s);
    point[i].y = (int) montant;
    /* Recalibrate */
    x_max  = point[i].x;
    x_unit = GROP_XRANGE / x_max;
    y_unit = GROP_YRANGE / (y_max - y_min);
    zero   = GROP_MIN + y_max * y_unit;
    if (zero > GROP_MAX)
        zeroM = GROP_MAX;
    else
        zeroM = zero;
    MY_ALLOC (hscale, get_hs_nb (date_s, date2), G_LABEL);
    get_hscale (hscale, date_s, date2);
    vscale = get_vscale (y_max, y_min);
    #ifdef DEBUG_GACC
        printf ("Nombre d'opérations comptabilisées : %d\n",i);
        printf ("x_unit = %f\t y_unit = %f\t zero = %d\n", x_unit, y_unit, zero);
        printf ("Échelle Y : %d\n", vscale);
        printf ("x_max = %f, y_min = %f, y_max = %f\n", x_max,  y_min, y_max);
        printf ("Nombre de graduations pour l'échelle temporelle : %d\n",
                 get_hs_nb (date_s, date2) - 1);
        i = 0;
        while (hscale[i].x >= 0) {
            printf ("A - Mois %d (%s) à la position x = %d\n",
                     hscale[i].month,
                     get_month_ni (hscale[i].month),
                     hscale[i].x);
            i++;
        }
    #endif
    for (i = 0 ; i < nb_pts ; i++) {
        #ifdef DEBUG_GACC
          printf ("x (%d) devient : %d\n",
                     point[i].x,
                     GROP_SHIFT + (int) (point[i].x * x_unit) );
            printf ("y (%d) devient : %d\n",
                     point[i].y,
                     zero       - (int) (point[i].y * y_unit) );
        #endif
        point[i].x = GROP_SHIFT + (int) (point[i].x * x_unit);
        point[i].y = zero       - (int) (point[i].y * y_unit);
    }
    i = 0;
    while (hscale[i].x >= 0) {
        hscale[i].x = GROP_SHIFT + (int) (hscale[i].x * x_unit);
        i++;
    }
    /* Now we'll draw things */
    #ifdef DEBUG_GACC
        printf ("Nombre de points : %d\n", nb_pts);
        for (i = 0 ; i < nb_pts ; i++)
            printf (" Point %2d à (%d, %d)\n", i, point[i].x, point[i].y);
        i = 0;
        while (hscale[i].x >= 0) {
            printf ("B - Mois %d (%s) à la position x = %d\n",
                     hscale[i].month,
                     get_month_ni (hscale[i].month),
                     hscale[i].x);
            i++;
        }
    #endif
    /* Color map, window and GC initialisation */
    palette = gdk_window_get_colormap (widget->window);
    gdk_color_alloc (palette, &blanc);
    gdk_color_alloc (palette, &bleu);
    gdk_color_alloc (palette, &noir);
    gdk_color_alloc (palette, &rouge);
    gdk_color_alloc (palette, &violet);
    /*gdk_color_alloc (palette, &gris);*/
    gdk_color_alloc (palette, &vert);
    gdk_window_set_background (widget->window, &blanc);
    gdk_window_clear (widget->window);
    crayon      = gdk_gc_new (widget->window);
    crayon_grid = gdk_gc_new (widget->window);
    gdk_gc_set_background (crayon,      &blanc);
    gdk_gc_set_background (crayon_grid, &blanc);
    /* Real painting */
    gdk_gc_set_foreground (crayon_grid, &vert);
    gdk_gc_set_line_attributes (crayon_grid,
                                1,
                                GDK_LINE_ON_OFF_DASH,
                                GDK_CAP_NOT_LAST,
                                GDK_JOIN_BEVEL);
    gdk_gc_set_foreground (crayon, &noir);
    gdk_draw_line (widget->window, crayon,
        GROP_SHIFT, zeroM, GROP_XRANGE+GROP_SHIFT, zeroM);
    gdk_draw_line (widget->window, crayon,
        GROP_SHIFT, GROP_MIN, GROP_SHIFT, GROP_MAX);
    /* H. Scales drawing */
    gdk_gc_set_foreground (crayon, &violet);
    font = gdk_font_load (sfont);
    i = 0;
    while (hscale[i].x >= 0) {
        if ( (config.graph_grd == VRAI) &&
             ( (get_hs_nb (date_s, date2) - 1) > 1) ) {
            gdk_draw_line ( widget->window, crayon_grid,
                            hscale[i].x, zeroM - 1,
                            hscale[i].x, GROP_MIN);
            if ( (zeroM + 18) < GROP_MAX)
                gdk_draw_line ( widget->window, crayon_grid,
                                hscale[i].x, zeroM + 18,
                                hscale[i].x, GROP_MAX);
        }
        if ( (get_hs_nb (date_s, date2) - 1) > 1)
            gdk_draw_line ( widget->window, crayon,
                            hscale[i].x, zeroM - 1,
                            hscale[i].x, zeroM + 2);
        month = get_month_ni (hscale[i].month);
        gdk_draw_string (widget->window,        /* in what widget */
            font,                               /* font to use    */
            crayon,                             /* GC             */
            ( (get_hs_nb (date_s, date2) - 1) == 1) ?
            (drawing_area_width / 2) :
            hscale[i].x,                        /* X              */
            zeroM + 14,                         /* Y              */
            month );                            /* what to write  */
        i++;
    }
    /* V. Scales drawing */
    i = -vscale;
    while (i < y_max) {
        int y;
        i += vscale;
        y = zero - (int) (i * y_unit);
      if (i == 0) y = zeroM;
        #ifdef DEBUG_GACC
            printf ("i = %d \t y = %d  \t y_max = %.5f\n", i, y , y_max);
        #endif
        if ( (GROP_MIN < y + 1) && (y < GROP_MAX) ) {
            gdk_draw_line (widget->window, crayon,
                GROP_SHIFT - 2, y, GROP_SHIFT + 1, y);
            /*if ( (zero - zeroM) < vscale) { WHY DID I WRITE THAT ? */
                sprintf (scale_amo, "%d", i);
                gdk_draw_string (widget->window,
                    font,
                    crayon,
                    GROP_SHIFT - 4 - gdk_string_width (font, scale_amo),
                    y + 4,
                    scale_amo);
            /*} */
            if ( (i != 0) && (config.graph_grd == VRAI) )
                gdk_draw_line (widget->window, crayon_grid,
                        GROP_SHIFT + 1, y, GROP_XRANGE + GROP_SHIFT, y);
            #ifdef DEBUG_GACC
                printf ("Ligne horizontale à y = %d, montant = %d\n", y , i);
            #endif
        }
    }
    /* DRAW THE MAXIMUM GRADUATING ? no...
    gdk_draw_line (widget->window, crayon,
            GROP_SHIFT - 2,
            zero - (int) (y_max * y_unit),
            GROP_SHIFT + 1,
            zero - (int) (y_max * y_unit) );
    */
    gdk_gc_set_foreground (crayon, &rouge);
    i = -vscale;
    while (i > y_min) {
        int y = zero - (int) (i * y_unit);
        gdk_draw_line (widget->window, crayon,
            GROP_SHIFT - 2, y, GROP_SHIFT + 1, y);
        sprintf (scale_amo, "%d", i);
        gdk_draw_string (widget->window,
            font,
            crayon,
            GROP_SHIFT - 4 - gdk_string_width (font, scale_amo),
            y + 4,
            scale_amo);
        gdk_draw_line (widget->window, crayon_grid,
            GROP_SHIFT + 1, y, GROP_XRANGE + GROP_SHIFT, y);
        i -= vscale;
    }
    /* DRAW THE MINIMUM GRADUATING ? no...
    gdk_draw_line (widget->window, crayon,
            GROP_SHIFT - 2,
            zero - (int) (y_min * y_unit),
            GROP_SHIFT + 1,
            zero - (int) (y_min * y_unit) );
    */
    /* Account graph */
    gdk_gc_set_foreground (crayon, &bleu);
    gdk_draw_lines (widget->window, crayon, point, nb_pts);
    #ifdef DEBUG_GACC
        printf ("Graphic finished !\n");
    #endif
    /* Things are done : freeing memory */
    free (point);
    free (hscale);
    gdk_font_unref (font);
    gdk_gc_destroy (crayon);
    gdk_gc_destroy (crayon_grid);
    return TRUE;
}

GtkWidget *create_grop_dialog () {
    GtkWidget *GROP_Dialog;
    GtkWidget *bouton;
    GtkWidget *vbox;
    GtkWidget *frame;
    GtkWidget *bordure;
    GtkWidget *label;
    GtkWidget *drawing_area;
    ACC_ELT   *acc;

    GROP_Dialog = gtk_dialog_new ();
    gtk_window_set_title (GTK_WINDOW (GROP_Dialog), _("Graphics...") );
    gtk_signal_connect (GTK_OBJECT (GROP_Dialog), "delete_event",
                        GTK_SIGNAL_FUNC (gtk_widget_destroy),
                        NULL);
    gtk_signal_connect (GTK_OBJECT (GROP_Dialog), "destroy", 
                            GTK_SIGNAL_FUNC (gtk_widget_destroy), 
                            NULL);
    bouton = gtk_button_new_with_label ( _("OK") );
    gtk_signal_connect_object (GTK_OBJECT (bouton), "clicked",
                               GTK_SIGNAL_FUNC (gtk_widget_destroy),
                               GTK_OBJECT (GROP_Dialog));
    gtk_box_pack_start (GTK_BOX (GTK_DIALOG (GROP_Dialog)->action_area), 
                        bouton, TRUE, TRUE, 0);
    GTK_WIDGET_SET_FLAGS (GTK_WIDGET (bouton), GTK_CAN_DEFAULT);
    gtk_widget_grab_default (GTK_WIDGET (bouton) );
    gtk_widget_draw_default (GTK_WIDGET (bouton) );
    gtk_widget_show (bouton);

    frame = gtk_frame_new (_(" Operations graph with lines ") );

    gtk_container_set_border_width (
                        GTK_CONTAINER (GTK_DIALOG (GROP_Dialog)->vbox), 6);
    vbox = gtk_vbox_new (FALSE, 6);
    gtk_container_set_border_width (GTK_CONTAINER (vbox), 6);

    bordure = gtk_frame_new (NULL);
    gtk_frame_set_shadow_type (GTK_FRAME (bordure), GTK_SHADOW_IN);

    acc = get_account (selected_row);
    label = gtk_label_new (acc->account->name);
    gtk_container_add (GTK_CONTAINER (bordure), label);
    gtk_widget_show (label);

    gtk_container_add (GTK_CONTAINER (vbox), bordure);
    gtk_widget_show (bordure);

    drawing_area = gtk_drawing_area_new ();
    gtk_drawing_area_size (GTK_DRAWING_AREA (drawing_area), GRAPH_W, GRAPH_H);
    gtk_signal_connect (GTK_OBJECT (drawing_area), "expose-event",
                        GTK_SIGNAL_FUNC (grop_paint),
                        NULL);
    gtk_container_add (GTK_CONTAINER (vbox), drawing_area);
    gtk_widget_show (drawing_area);

    gtk_container_add (GTK_CONTAINER (frame), vbox);
    gtk_widget_show (vbox);

    gtk_box_pack_start (GTK_BOX (GTK_DIALOG (GROP_Dialog)->vbox), frame, TRUE,
                        TRUE, 6);
    gtk_widget_show (frame);

    return GROP_Dialog;
}

Generated by  Doxygen 1.6.0   Back to index