Report 3: BarLine Chart

only for RuBoard - do not distribute or recompile

Report 3: Bar/Line Chart

Listing 12.8 is the source for barline_utils.c , the code functions that are called from callbacks.c (for the third report) to create the bar/line chart.

Listing 12.8 barline_utils.c
 #include <gtk/gtk.h>  #include <mysql.h>  /*  stdlib.h  is needed for the  atoi/atof  call. */  #include <stdlib.h>  #include "support.h"  #define SERVER  "einstein"  #define LOGIN   "kbi_user"  #define PASS    "dengissa"  #define DB      "kbi"  #define BASELINE_CHART    350   //the number of pixels from the top                                  //of the drawingarea to the "baseline"                                  //of the bars in the bar graph  #define BASELINE_MONTHS   370   //the number of pixels down to draw                                  //the month names  #define SCALE_DENOMINATOR 1235  //the division factor to scale the bars                                  //and lines to the drawingarea  #define BAR_WIDTH         25    //width in pixels of the bars  GtkWidget *frm_barline;  MYSQL           *conx;  MYSQL_RES       *result_set;  MYSQL_ROW       row;  gchar           *sql;  gchar *month_names[12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",                            "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};  gint month_bar_amounts[12];    //the values the bar chart should show  gint month_line_amounts[12];   //the values for the line chart  gint month_indents[12];        //number of pixels from the left to                                 //print the month names  void draw_bar(gint bar_left, gint bar_width, gint bar_height, gchar *bar_color);  GdkGC *get_gc(gchar *in_color)  {  /* This function will return a graphics context in the   * color as specified by the  in_color  parameter.   */  GdkGC *gc;     GdkColor my_color;     gc = gdk_gc_new(GTK_WIDGET(lookup_widget(frm_barline,             "drawingarea1"))->window);     if (!gdk_color_parse(in_color, &my_color))        {          g_print("Unable to parse %s.\n", in_color);           gtk_statusbar_push(GTK_STATUSBAR(lookup_widget(frm_barline,                 "statusbar1")), 1, "Unable to parse color.\n");           return 0L;        }     if (!gdk_colormap_alloc_color(gdk_colormap_get_system(),          &my_color, FALSE, TRUE))        {         g_print("Unable to allocate colormap for %s.\n", in_color);          gtk_statusbar_push(GTK_STATUSBAR(lookup_widget(frm_barline,                   "statusbar1")), 1, "Unable to allocate colormap.\n");           return 0L;        }  gdk_gc_set_foreground(gc, &my_color);     return gc;  }  void draw_axis_and_scales()  {  /* This function will draw the axis and scales for the graph.   */  GdkGC *gc;     gint i;     gint from_left = 90;     gc = get_gc("Black");     gdk_draw_string(        GTK_WIDGET(lookup_widget(frm_barline, "drawingarea1"))->window,         GTK_WIDGET(lookup_widget(frm_barline, "drawingarea1"))->style->font,         gc, 5, 100, "Sales (Bar)");     gdk_draw_string(        GTK_WIDGET(lookup_widget(frm_barline, "drawingarea1"))->window,         GTK_WIDGET(lookup_widget(frm_barline, "drawingarea1"))->style->font,         gc, 5, 130, "Quota (Line)");     gdk_draw_line(        GTK_WIDGET(lookup_widget(frm_barline, "drawingarea1"))->window,         gc, from_left -1, 10, from_left -1, BASELINE_MONTHS - 20);     gdk_draw_line(        GTK_WIDGET(lookup_widget(frm_barline, "drawingarea1"))->window,         gc, from_left, BASELINE_MONTHS - 20, 550, BASELINE_MONTHS - 20);  /* Establish the spacing for the months, both the names along   * the horizontal axis and the bars as well.   */  for (i=0; i<=11; i++)       {         month_indents[i] = from_left;          gdk_draw_string(           GTK_WIDGET(lookup_widget(frm_barline, "drawingarea1"))->window,            GTK_WIDGET(lookup_widget(frm_barline, "drawingarea1"))->style->font,            gc, from_left, BASELINE_MONTHS, month_names[i]);          from_left += 40;       }  }  void draw_bar_chart()  {    gint i;  /* The first thing that is necessary here is to figure out scale.   * In this case, the largest value in the data is 400,000. In the   * "drawingarea," the left line is drawn between vertical pixel   * 10 at the top and 350 at the bottom, leaving a vertical distance   * of 340 pixels in which to represent values from 0 to   * 400,000.   *   * So to calculate the scale for that area, take the maximum value   * plus a bit of padding. For this exercise, the value will be   * 420,000. When you divide that by 340, it gives a value of   * (approximately) 1,235. If you then turn the calculation around   * and divide the 400,000 value by 1,235, you should never get more   * than 340. Thus, the software can take all the values given to   * it in the 300,000 to 400,000 range and divide them by 1,235 in   * order to draw the bars to scale correctly.   *   * Note that the software could, of course, query the data   * with an  SQL max()  statement to determine what this program   * sets with a  #define  statement. In other words, the 1,235 value   * used here could be calculated from the data itself.   *   * It is from this discussion that  MAX_VALUE  is defined in the   * header section of this file.   */   /* Make repeat calls to  draw_bar()  for each month. */  for (i=0; i<=11; i++)        {          draw_bar(month_indents[i], BAR_WIDTH,                    month_bar_amounts[i]/SCALE_DENOMINATOR, "Red");        }  }    void draw_bar(gint bar_left, gint bar_width, gint bar_height, gchar *bar_color)  {    gdk_draw_rectangle(GTK_WIDGET(lookup_widget(frm_barline,               "drawingarea1"))->window, get_gc(bar_color), TRUE, bar_left,               BASELINE_CHART - bar_height,               bar_width, bar_height);  }  void draw_line(gint from_left_1, gint from_top_1,                 gint from_left_2, gint from_top_2)  {    gdk_draw_line(            GTK_WIDGET(lookup_widget(frm_barline, "drawingarea1"))->window,             get_gc("Blue"), from_left_1, from_top_1, from_left_2, from_top_2);  }  void draw_line_chart()  {  /* This function will draw the line chart by repeated calls to   *  draw_line()  .   */  gint i;     gint from_left, from_top;  /* The first thing necessary is to calculate the starting point   * for the first line. In this case, that is the middle of the   * "January" bar for the measurement from the left of the window,   * and the vertical will be  month_line_amounts[0]  .   */  from_left = month_indents[0] ++ BAR_WIDTH/2;     from_top = BASELINE_CHART - month_line_amounts[0]/SCALE_DENOMINATOR;     for (i=1; i<=11; i++)        {          draw_line(from_left, from_top,                     month_indents[i] ++ BAR_WIDTH/2,                     BASELINE_CHART - month_line_amounts[i]/SCALE_DENOMINATOR);           gdk_draw_rectangle(GTK_WIDGET(lookup_widget(frm_barline,               "drawingarea1"))->window, get_gc("RoyalBlue"),               TRUE, from_left - 2, from_top - 2, 3, 3);          from_left = month_indents[i] ++ BAR_WIDTH/2;          from_top = BASELINE_CHART - month_line_amounts[i]/SCALE_DENOMINATOR;       }  /* You need to plot a point at the December quota data point as   * the finishing touch.   */  gdk_draw_rectangle(GTK_WIDGET(lookup_widget(frm_barline,               "drawingarea1"))->window, get_gc("RoyalBlue"),               TRUE, from_left - 2, from_top - 2, 3, 3);  }  gboolean load_data()  {  /* Connect to the database and retrieve the values for   * the bar/line chart.   */  conx = mysql_init((MYSQL *)0L);     if (conx = 0L)       {         gtk_statusbar_push(GTK_STATUSBAR(lookup_widget(frm_barline,                        "statusbar1")), 1,"mysql_init problem");          return FALSE;       }     gtk_statusbar_push(GTK_STATUSBAR(lookup_widget(frm_barline,                        "statusbar1")), 1, "mysql_init ok");     conx = mysql_real_connect(conx, SERVER, LOGIN, PASS, DB, 0, 0L, 0);     if (conx = 0L)       {         gtk_statusbar_push(GTK_STATUSBAR(lookup_widget(frm_barline,                        "statusbar1")), 1,"mysql_real_connect problem");          return FALSE;       }     gtk_statusbar_push(GTK_STATUSBAR(lookup_widget(frm_barline,                        "statusbar1")), 1, "mysql_real_connect ok");     sql = g_strconcat("select * from tbl_sales_vs_quota ",                       " order by sales__month", 0L);     g_print("sql is %s\n", sql);       if (mysql_query (conx, sql) != 0)        {         gtk_statusbar_push(GTK_STATUSBAR(lookup_widget(frm_barline,                        "statusbar1")), 1, "mysql_query problem");          g_print("mysql_query problem in load_data.\n");          mysql_close(conx);          return FALSE;        }     gtk_statusbar_push(GTK_STATUSBAR(lookup_widget(frm_barline,                        "statusbar1")), 1, "mysql_query ok");     result_set = mysql_store_result(conx);     while (( row = mysql_fetch_row (result_set)) != 0)       {         static gint i = 0;  /* Convert the values returned by MySQL to integers   * and fill the arrays to hold the data values.   */  month_bar_amounts[i] = atoi(row[2]);          month_line_amounts[i] = atoi(row[3]);          g_print("data is %d and %d\n", month_bar_amounts[i],                                          month_line_amounts[i]);          i++;        }      mysql_close(conx);      return TRUE;  } 

For completeness, Listing 12.9 is callbacks.c for the bar/line chart. It is rather straightforward, and it makes a series of simple calls to the functions defined in barline_utils.c (Listing 12.8).

Listing 12.9 callbacks.c for the Bar/Line Chart
 #ifdef HAVE_CONFIG_H  #  include <config.h>  #endif  #include <gtk/gtk.h>  #include "callbacks.h"  #include "interface.h"  #include "support.h"  #include "barline_utils.h"  void  on_frm_barline_show                    (GtkWidget       *widget,                                          gpointer         user_data)  {    load_data();     draw_axis_and_scales();     draw_bar_chart();     draw_line_chart();  }  gboolean  on_frm_barline_delete_event            (GtkWidget       *widget,                                          GdkEvent        *event,                                          gpointer         user_data)  {    gtk_main_quit();     return FALSE;  }  gboolean  on_drawingarea1_event                  (GtkWidget        *widget,                                          GdkEvent         *event,                                          gpointer          user_data)  {    draw_axis_and_scales();     draw_bar_chart();     draw_line_chart();     return FALSE;  } 

Figure 12.5 shows the bar/line chart application running.

Figure 12.5. A bar/line chart program.
graphics/12fig05.gif
only for RuBoard - do not distribute or recompile


MySQL Building User Interfaces
MySQL: Building User Interfaces (Landmark)
ISBN: 073571049X
EAN: 2147483647
Year: 2001
Pages: 119

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net