home *** CD-ROM | disk | FTP | other *** search
/ pc.louisiana.edu/pub/unix/ / Louisiana_UNIX.tar / Louisiana_UNIX / xspread3.0.zoo / plot_bar.c < prev    next >
C/C++ Source or Header  |  1994-06-02  |  17KB  |  498 lines

  1. /*
  2.  * Copyright (C) 1992  Board of Regents of the University of Wisconsin
  3.  * on behalf of the Department of Electrical Engineering and Computer
  4.  * Science, University of Wisconsin-Milwaukee, Milwaukee, WI 53201.
  5.  *
  6.  * This program is free software; you can redistribute it and/or modify
  7.  * it under the terms of the GNU General Public License as published by
  8.  * the Free Software Foundation; either version 2 of the License, or
  9.  * (at your option) any later version.
  10.  *
  11.  * This program is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * a copy of which is included here in file "GNU_GENERAL"
  18.  * along with this program; if not, write to the Free Software
  19.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  *
  21.  * The programs in this directory were developed by software engineering 
  22.  * teams as part of the course "Introduction to Software Engineering" 
  23.  * under the supervision of Professor G. Davida.
  24.  * This is a modification of a program written or modified by
  25.  * others.  The original copyrights, as per GNU General Public License,
  26.  * may still be applicable.  The UWM copyright is applicable only
  27.  * the those parts generated at UWM.
  28.  *
  29.  * Please send all changes, enhancements, and other comments about this
  30.  * software to
  31.  *             soft-eng@cs.uwm.edu
  32.  *
  33.  * No Warranty, expressed or implied, comes with this software.
  34.  * This software is intended to be used by not-for-profit
  35.  * organizations or by individuals for personal HOME use. 
  36.  * This software, or any of its parts, may not be used by for-profit
  37.  * organization, regardless of application or intended product or
  38.  * customer, without the permission of the Board of Regents of the 
  39.  * University  of Wisconsin is strictly forbidden. 
  40.  *
  41.  * Contact:    soft-eng@cs.uwm.edu
  42.  *            or
  43.  *        
  44.  *        Software Engineering Coordinator
  45.  *        Computer Science
  46.  *            Department of EECS
  47.  *        University of Wisconsin - Milwaukee
  48.  *        Milwaukee, WI  53201
  49.  *        414-229-4677
  50.  *
  51.  *        HISTORY,CLAIMS and CONTRIBUTIONS
  52.  */
  53. /* This function will produce a bar graph for the data input by the user. */
  54. /* All sections of this function are explained as they are implemented.   */
  55. /*    Written by: Georgiane Kondich   August 1990                         */
  56. /*                                                                        */
  57. /* Modified 10/27/91 - Dan Gruber.  Changed plot_bar to check for a valid */
  58. /* number of X labels before it Maps the window to the screen and makes   */
  59. /* it visible to the user.  This gives plot_bar a cleaner exit.           */
  60. /*                                                                        */
  61. /* Modified 12/10/91 - Dan Gruber.  Completely revised plot_bar.  It now  */
  62. /* has the ability to display up to six columns of data instead of only   */
  63. /* one.  It also uses patterns located in pattern.h for each column.      */
  64. /*                                                                        */ 
  65. /* Modified 5/94 - Dan Coppersmith.  Improved user friendliness of error  */
  66. /* function messages.
  67. /**************************************************************************/
  68.  
  69. #include <stdio.h>
  70. #include <X11/Xlib.h>
  71. #include <X11/Xutil.h>
  72. #include "config.h"
  73. #include "plot.h"
  74. #include "pattern.h"
  75. #include "graphic_gvar.h"
  76. #include "sc.h"
  77. #include "scXstuff.h"
  78. #include <math.h>
  79. #define TITLE "XSPREAD-Grapher (Bar Plot)"
  80. #define PIX_SEP 8   /* The distance between each group of bars */
  81.  
  82. #ifndef irint 
  83. #define irint(x) floor((x)+0.5)
  84. #endif
  85.  
  86.   XWMHints   Xwmh = {
  87.      (InputHint|StateHint),  /*flags*/
  88.      False,                  /*input*/
  89.      NormalState,            /*initial_state*/
  90.      0,                      /*icon pixmap*/
  91.      0,                      /*icon window*/
  92.      0, 0,                   /*icon location*/
  93.      0,                      /*icon mask*/
  94.      0,                      /*Window group*/
  95.   };
  96.  
  97. plot_bar()
  98.    { int argc = 0;
  99.     char **argv;
  100.  
  101.   
  102.       double max_y;      /* Maximum Y value                   */
  103.       double min_y;      /* Minimum Y value                   */
  104.       double Y_Range;    /* "max_y - min_y"                   */ 
  105.  
  106.       int i,j,k;         /* Iteration variables               */
  107.       int len;           /* Length of a Label                 */
  108.       int grid_l_x;      /* Size of grid separators           */ 
  109.       int grid_l_y;
  110.       int grid_h;
  111.       char str[100];     /* The Label to be drawn             */
  112.       int height,width;  /* Height and Width of the bar       */
  113.       int text_w;        /* Text width variable               */
  114.       int x,y;           /* Current x and y position          */
  115.       struct ent *p;
  116.       int looping = 1;   /* Continue looping flag             */
  117.       int draw = 0;      /* Continue drawing flag             */
  118.       int first_bar=1;   /* The first bar flag                */
  119.       int num_rows = 0;  /* The number of rows to be drawn    */
  120.       int num_cols = 0;  /* The number of columns to be drawn */
  121.       int row;           /* The current row position          */
  122.       int bars;          /* The current bar being processed   */
  123.       int labelsize;     /* The size of the Label             */
  124.       Pixmap Pattern;    /* The type of pattern to display    */
  125.  
  126.     /*
  127.      * Decide the scale for x and y axes
  128.      */
  129.   
  130.  
  131.    bars = 0;
  132.    for (i=graphic_range[0].r1; i<=graphic_range[0].r2; i++) 
  133.    {
  134.     p = lookat(i,graphic_range[0].c);
  135.     if (!(p->label)) {
  136.        continue;
  137.     }
  138.     bars++;
  139.    }
  140.  
  141.    if (bars < 1) 
  142.    {
  143.       fprintf(stderr,"\007");
  144.       if (graphic_range[0].r2 - graphic_range[0].r1 > 1)
  145.           message("x values must be strings");
  146.       else
  147.           message("Not enough valid X labels");
  148.       return;
  149.    }
  150.  
  151.      if (g_auto_man[1] == 'M') {
  152.         max_y = graphic_scale[1][1];
  153.         min_y = graphic_scale[1][0];
  154.      }    
  155.      else {
  156.        for (j=1; j < GRAPHRANGES; j++) {
  157.            if (*(graphic_range[j].col) == '\0') 
  158.            continue; 
  159.            else 
  160.            num_cols++;
  161.            row = 0;
  162.        for (i=graphic_range[j].r1; i<=graphic_range[j].r2; i++) 
  163.        {
  164.         p=lookat(i,graphic_range[j].c);
  165.         if(!(p->flags & is_valid)) continue;
  166.                 row++; 
  167.                 
  168.         if (first_bar)
  169.         {
  170.            max_y = p->v;      /*find the maximum y value*/
  171.            min_y = p->v;      /*find the minimum y value*/
  172.            first_bar = 0;
  173.         }
  174.         else
  175.         {
  176.           max_y = Max(max_y, p->v);
  177.           min_y = Min(min_y, p->v);
  178.         }
  179.            num_rows = Max(row,num_rows); 
  180.        }
  181.         }
  182.         min_y -= 0.1*(fabs(min_y)); /* so smallest bar shows */ 
  183.      }
  184.      min_y = floor(min_y);
  185.      max_y = ceil(max_y);
  186.  
  187.     /*
  188.      * Select colors for the border,  the window background,  and the
  189.      * foreground.
  190.      */
  191.  
  192.     bd = WhitePixel(dpy, DefaultScreen(dpy));
  193.     bg = BlackPixel(dpy, DefaultScreen(dpy));
  194.     fg = WhitePixel(dpy, DefaultScreen(dpy));
  195.  
  196.     /*
  197.      * Set the border width of the window,  and the gap between the text
  198.      * and the edge of the window, "pad".
  199.      */
  200.  
  201.     pad = BORDER;
  202.     bw = 1;
  203.  
  204.     /*
  205.      * Deal with providing the window with an initial position & size.
  206.      * Fill out the XSizeHints struct to inform the window manager. See
  207.      * Sections 9.1.6 & 10.3.
  208.      */
  209.  
  210.     xsh.width = XTextWidth(curfont, TITLE, 80 + pad * 2);   
  211.     xsh.flags = (PPosition | PSize);
  212.     xsh.height = WIN_H;
  213.     xsh.width =  WIN_W; 
  214.     xsh.x = (DisplayWidth(dpy, DefaultScreen(dpy)) - xsh.width) / 2;
  215.     xsh.y = (DisplayHeight(dpy, DefaultScreen(dpy)) - xsh.height) / 2;
  216.  
  217.     /*
  218.      * Create the Window with the information in the XSizeHints, the
  219.      * border width,  and the border & background pixels. See Section 3.3.
  220.      */
  221.  
  222.     win = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy),
  223.                   xsh.x, xsh.y, xsh.width, xsh.height,
  224.                   bw, bd, bg);
  225.  
  226.     /*
  227.      * Set the standard properties for the window managers. See Section
  228.      * 9.1.
  229.      */
  230.  
  231.     XSetStandardProperties(dpy, win, TITLE, TITLE, None, argv,
  232.                argc, &xsh);
  233.     XSetWMHints(dpy, win, &Xwmh);
  234.  
  235.     /*
  236.      * Ensure that the window's colormap field points to the default
  237.      * colormap,  so that the window manager knows the correct colormap to
  238.      * use for the window.  See Section 3.2.9. Also,  set the window's Bit
  239.      * Gravity to reduce Expose events.
  240.      */
  241.  
  242.     xswa.colormap = DefaultColormap(dpy, DefaultScreen(dpy));
  243.     xswa.bit_gravity = CenterGravity;
  244.     XChangeWindowAttributes(dpy, win, (CWColormap | CWBitGravity), &xswa);
  245.  
  246.     /*
  247.      * Map the window to make it visible.  See Section 3.5.
  248.      */
  249.    
  250.      XMapWindow(dpy, win);
  251.  
  252.  
  253.      /*
  254.      * Find out how big the window is now,  so that we can center
  255.      * the text in it.
  256.      */
  257.  
  258.     if (XGetWindowAttributes(dpy, win, &xwa) == 0){
  259.        fprintf(stderr,"Bar Plot: Can't access attributes for graph window\n");
  260.        exit(1);    
  261.     }
  262.  
  263.     XClearWindow(dpy, win);
  264.     XSelectInput(dpy,win, ButtonPressMask|KeyPressMask|ExposureMask);
  265.  
  266.  
  267.     while (looping) {
  268.         XEvent event;
  269.  
  270.         XNextEvent(dpy,&event);
  271.  
  272.         switch(event.type)
  273.         {
  274.         case KeyPress:
  275.         case ButtonPress: looping = 0;
  276.                   break;
  277.         case Expose: draw = 1;
  278.         }
  279.                
  280.  
  281.        if (!draw) continue;
  282.  
  283.            XDrawRectangle(dpy,win,maingcreversed,
  284.               RECT_X,RECT_Y,RECT_W,RECT_H);
  285.      
  286.  /* ----------------------------------------------------------------  */
  287.  /* This next section will draw the grid on which the bar graphs will */
  288.  /* be drawn and will display the title of the graph as well as       */
  289.  /* label the x and y axis. Written by Georgiane Kondich    Aug 1990  */
  290.  /*                                                                   */
  291.  /* Modified 12/10/91 - Dan Gruber.  This graph now displays a value  */
  292.  /*                     for each tick mark on the Y Axis.             */
  293.  /* ----------------------------------------------------------------- */
  294.           /*
  295.        * grid_l_x and grid_l_y are the length of the grid lines  
  296.        * to be drawn.  They have a value of '0' if no grids are 
  297.        * drawn.
  298.            */
  299.  
  300.            if  (graphic_grid == 'H') 
  301.            {
  302.              grid_l_x = RECT_W;
  303.              grid_l_y = 0;
  304.            }
  305.            else if (graphic_grid == 'V')
  306.            {
  307.              grid_l_x = 0;
  308.              grid_l_y = RECT_H;
  309.            }  
  310.            else if (graphic_grid == 'B')
  311.            {
  312.              grid_l_x = RECT_W;
  313.              grid_l_y = RECT_H;
  314.            }  
  315.            else 
  316.            {
  317.              grid_l_x = 0;
  318.              grid_l_y = 0;
  319.            }  
  320.  
  321.            grid_h = RECT_H /10;
  322.  
  323.        Y_Range = max_y - min_y;
  324.  
  325.          /* Calculate the width of a single bar */
  326.        width = (RECT_W - (PIX_SEP*num_rows)) / (num_cols*num_rows);
  327.                           /*^^^^^^^ we can draw
  328.                             multiple bars on one
  329.                             graph */
  330.      
  331.      /* Draw the grid, along with the labels on the Y axis */
  332.  
  333.        for (i=0; i<11; i++) {
  334.              if (i > 0 && i < 10)
  335.             XDrawLine(dpy,win,maingcreversed,
  336.                RECT_X-4, RECT_Y+i*grid_h,
  337.                RECT_X, RECT_Y+i*grid_h);
  338.          XDrawLine(dpy,win,maingcreversed,
  339.                RECT_X, RECT_Y+i*grid_h,
  340.                RECT_X+grid_l_x, RECT_Y+i*grid_h);
  341.          XDrawLine(dpy,win,maingcreversed,
  342.                RECT_X + RECT_W,RECT_Y+i*grid_h,
  343.                RECT_X+RECT_W - grid_l_x, RECT_Y+i*grid_h);
  344.  
  345.              sprintf(str,"%.1f",(max_y - Y_Range*i/10));
  346.              len = strlen(str);
  347.              text_w = XTextWidth(curfont,str,len+2);
  348.              XDrawImageString(dpy,win,maingcreversed,
  349.                         RECT_X - text_w,
  350.                         RECT_Y + i*grid_h + curfontheight/3,
  351.                         str,len);
  352.            
  353.        } /*end for loop*/
  354.            
  355.            for (i=1; i < num_rows; i++) { 
  356.              x = RECT_X + PIX_SEP*i + i*width*(num_cols);
  357.          XDrawLine(dpy,win,maingcreversed,
  358.                x, RECT_Y, x, RECT_Y+grid_l_y);
  359.          XDrawLine(dpy,win,maingcreversed,
  360.                x, RECT_Y+RECT_H, x, RECT_Y+RECT_H-grid_l_y);
  361.        } /*end for loop*/
  362.  
  363. /*
  364.  *
  365.  * Display titles at top of graph 
  366.  *
  367.  */
  368.  
  369.        len = strlen(graphic_title[0]);    
  370.        text_w = XTextWidth(curfont, graphic_title[0], len);
  371.        XDrawImageString(dpy,win,maingcreversed, 
  372.                 (WIN_W - text_w)/2, RECT_Y/3, 
  373.                 graphic_title[0], len);
  374.      
  375.  
  376.        len = strlen(graphic_title[1]);
  377.        text_w = XTextWidth(curfont, graphic_title[1],len);
  378.        XDrawImageString(dpy,win,maingcreversed, 
  379.                (WIN_W - text_w)/2, RECT_Y*2/3,
  380.                graphic_title[1],len);
  381.  
  382.        len = strlen(graphic_title[2]);
  383.        text_w=XTextWidth(curfont,graphic_title[2],len);
  384.        XDrawImageString(dpy,win,maingcreversed, 
  385.                 (WIN_W-text_w)/2, RECT_H+RECT_Y*3/2,
  386.                 graphic_title[2],len);
  387.  
  388.            len = strlen(graphic_title[3]);
  389.            text_w=XTextWidth(curfont,graphic_title[3],len);
  390.            if ((RECT_X-text_w) < 0)
  391.                x = curfontwidth;
  392.            else
  393.                x = RECT_X-text_w;
  394.            XDrawImageString(dpy,win,maingcreversed,
  395.                             x, RECT_Y - curfontheight,
  396.                             graphic_title[3],len);
  397.  
  398.  
  399.   /* --------------------------------------------------------------------*/
  400.   /* This next section will read values of the x and y center points     */
  401.   /* and find the maximum and minimum values for each, then set the      */
  402.   /* width and height paramters, convert x and y so that the origin      */
  403.   /* is at the lower left corner of the window, and then finally         */
  404.   /* draw and fill the bars.                                             */
  405.   /* ------------------------------------------------------------------- */
  406.   
  407.  
  408.  
  409.  
  410.  
  411. /*
  412.  *  Draw Labels 
  413.  */
  414.            labelsize = irint(floor( (width*num_cols)/(double)curfontwidth) -1);
  415.        y = RECT_Y + RECT_H + curfontheight;
  416.        bars = 0;
  417.        for (i=graphic_range[0].r1;i<=graphic_range[0].r2; i++)
  418.        {
  419.           p = lookat(i,graphic_range[0].c);
  420.           if (!(p->label)) continue;
  421.           bars++;
  422.           strncpy(str, p->label, labelsize);
  423.               str[labelsize] = '\0';
  424.               len = strlen(str);
  425.               text_w = XTextWidth(curfont, str, len);
  426.           x = RECT_X+(PIX_SEP)*(bars-1)+width*(bars-1)*num_cols;
  427.               x = x + (width*num_cols/2)-(text_w / 2); 
  428.           XDrawImageString(dpy,win,maingcreversed,
  429.                       x,y,
  430.                    str,strlen(str));
  431.        }
  432.      /*
  433.       * Now draw all of the bars in the graph with a different 
  434.       * pattern for each column of data.
  435.       *
  436.       */
  437.  
  438.         for(i = 1; i < GRAPHRANGES; i++){
  439.             if (*(graphic_range[i].col) == '\0') continue;
  440.             row = 0;
  441.     for(j=graphic_range[0].r1,k=graphic_range[i].r1;
  442.        (j<=graphic_range[0].r2) && (k<=graphic_range[i].r2); j++, k++) 
  443.     {
  444.               row++;
  445.           if (!((p=lookat(j,graphic_range[0].c))->label)) continue;
  446.                  
  447.               x = RECT_X+(row-1)*(PIX_SEP)+(row-1)*(num_cols)*width+width*(i-1);
  448.  
  449.           if (!((p=lookat(j,graphic_range[i].c))->flags & is_valid) 
  450.           || (p->v < min_y) || (p->v > max_y)) continue;
  451.  
  452.           height = irint((p->v - min_y) / Y_Range * RECT_H);
  453.  
  454.           y = RECT_Y + RECT_H - height;  
  455.  
  456.           /* If there are grids to be drawn, clear the area before
  457.            * the bar is drawn .
  458.                */ 
  459.               if (graphic_grid != 'C')
  460.                   XClearArea(dpy,win,x,y,width,height,False);
  461.  
  462.               /* Choose a different pattern for each column */
  463.           switch (i) {
  464.                 case 1 : Pattern = XCreateBitmapFromData(dpy,win,white_bits,
  465.                              white_width, white_height);
  466.                              break;
  467.                 case 2 : Pattern = XCreateBitmapFromData(dpy,win,gray3_bits,
  468.                              gray3_width, gray3_height);
  469.                              break;
  470.                 case 3 : Pattern = XCreateBitmapFromData(dpy,win,gray5_bits,
  471.                              gray5_width, gray5_height);
  472.                              break;
  473.                 case 4 : Pattern = XCreateBitmapFromData(dpy,win,gray2_bits,
  474.                              gray2_width, gray2_height);
  475.                              break;
  476.                 case 5 : Pattern = XCreateBitmapFromData(dpy,win,gray4_bits,
  477.                              gray4_width, gray4_height);
  478.                              break;
  479.                 case 6 : Pattern = XCreateBitmapFromData(dpy,win,gray1_bits,
  480.                              gray1_width, gray1_height);
  481.                              break; }
  482.  
  483.               /* Draw the bar with a filled pattern */
  484.               XSetStipple(dpy, maingcreversed, Pattern);
  485.               XSetFillStyle(dpy, maingcreversed, FillStippled);
  486.               XFillRectangle(dpy,win,maingcreversed,x,y,width,height);
  487.  
  488.               /* Outline the bar with a solid rectangle */
  489.               XSetFillStyle(dpy, maingcreversed, FillSolid);
  490.           XDrawRectangle(dpy,win,maingcreversed,x,y,width,height);
  491.         }
  492.      }
  493.    }
  494.    XUnmapWindow(dpy, win);
  495.    XDestroyWindow(dpy, win);
  496.  
  497. }
  498.