home *** CD-ROM | disk | FTP | other *** search
/ pc.louisiana.edu/pub/unix/ / Louisiana_UNIX.tar / Louisiana_UNIX / xspread3.0.zoo / plot_stk_bar.c < prev    next >
C/C++ Source or Header  |  1994-06-02  |  16KB  |  488 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. /*************************************************************************
  54.  *  This procedure displays a stacked bar graph for the values chosen    *
  55.  *  by the user.  It displays one bar for each row chosen and 'stacks'   *
  56.  *  one section for each column chosen.  It uses patterns located in     *
  57.  *  the file pattern.h                                                   *
  58.  *  Dan Gruber - December 1991                                           *
  59.  *    Modified 5/94 by Dan Coppersmith to improve user friendliness of   *
  60.  *    error messages.                                                    *
  61.  *************************************************************************
  62.  */
  63.  
  64. #include <stdio.h>
  65. #include <X11/Xlib.h>
  66. #include <X11/Xutil.h>
  67. #include "config.h"
  68. #include "plot.h"
  69. #include "pattern.h"
  70. #include "graphic_gvar.h"
  71. #include "sc.h"
  72. #include "scXstuff.h"
  73. #include <math.h>
  74. #define TITLE "XSPREAD-Grapher (Stacked Bar Plot)"
  75. #define PIX_SEP 5
  76.  
  77. #ifndef irint
  78. #define irint(x) floor((x)+0.5)
  79. #endif
  80.  
  81.   XWMHints   SBwmh = {
  82.      (InputHint|StateHint),  /*flags*/
  83.      False,                  /*input*/
  84.      NormalState,            /*initial_state*/
  85.      0,                      /*icon pixmap*/
  86.      0,                      /*icon window*/
  87.      0, 0,                   /*icon location*/
  88.      0,                      /*icon mask*/
  89.      0,                      /*Window group*/
  90.   };
  91.  
  92. plot_stacked_bar()
  93.    { int argc = 0;
  94.     char **argv;
  95.  
  96.   
  97.       double  max_y, min_y, Y_Range;
  98.  
  99.       int i,j,k;            /* Iteration variables                  */
  100.       int grid_l_x;         /* The size of the grid separators      */
  101.       int grid_l_y;
  102.       int grid_h;
  103.       int height, width;    /* Height and width of a bar            */
  104.       char str[100];        /* The label to be drawn                */
  105.       int text_w;           /* The width of a label in pixels       */
  106.       int len;              /* The length of a label                */
  107.       int x,y;              /* X and Y coordinates for the bar      */ 
  108.       struct ent *p, *val;
  109.       int looping = 1;      /* Continue looping variable            */
  110.       int draw = 0;         /* Continue drawing variable            */
  111.       int first_bar = 1;    /* first bar flag                       */
  112.       int number_of_bars;   /* Total number of bars                 */
  113.       int bars = 0;         /* Current bar                          */
  114.       int labelsize;        /* Maximum size of label to be drawn    */ 
  115.       double Row_Total[20]; /* Row Total                            */
  116.       int Y_Position[20];   /* Position to draw next portion of bar */
  117.       Pixmap Pattern;       /* Type of pattern to be drawn          */
  118.  
  119.     /*
  120.      * Decide the scale for x and y axes
  121.      */
  122.   
  123.   for (i=graphic_range[0].r1; i<=graphic_range[0].r2; i++) 
  124.   {
  125.      p=lookat(i,graphic_range[0].c);
  126.      if(!(p->label)) continue;
  127.      bars++;
  128.      Row_Total[bars] = 0;
  129.      Y_Position[bars] = 0;
  130.   }
  131.  
  132.   if (bars < 1) 
  133.   {
  134.      fprintf(stderr,"\007");
  135.      if (graphic_range[0].r2 - graphic_range[0].r1 > 1)
  136.     message("x values must be strings");
  137.      else
  138.          message("Not enough valid X labels");
  139.      return;
  140.   }
  141.  
  142.   number_of_bars = bars;
  143.  
  144.     if (g_auto_man[1] == 'M') {
  145.        max_y = graphic_scale[1][1];
  146.        min_y = graphic_scale[1][0];
  147.     }    
  148.     else {
  149.        for (j=1; j < GRAPHRANGES; j++){
  150.           if (*(graphic_range[j].col) == '\0') continue;
  151.           bars = 0;
  152.           for (i=graphic_range[j].r1; i<=graphic_range[j].r2; i++) 
  153.       {
  154.              p=lookat(i,graphic_range[j].c);
  155.             /* if(!(p->flags & is_valid)) continue; */
  156.              bars++;
  157.              Row_Total[bars] = Row_Total[bars] + (p->v);
  158.              if (first_bar){
  159.                  min_y = p->v;
  160.                  first_bar = 0;
  161.              } else 
  162.                  min_y = Min(min_y, p->v);
  163.           }
  164.        }
  165.        first_bar = 1;
  166.        for (i=1; i<=bars; i++){
  167.           if (first_bar){
  168.              max_y = Row_Total[i];
  169.              first_bar = 0;
  170.           } else {
  171.                max_y = Max(max_y, Row_Total[i]);
  172.             }
  173.        }
  174.        min_y -= 0.1*(fabs(min_y));
  175.        max_y += 0.1*(fabs(max_y));
  176.     }
  177.     max_y = ceil(max_y);
  178.     min_y = floor(min_y);     
  179.  
  180.     /*
  181.      * Select colors for the border,  the window background,  and the
  182.      * foreground.
  183.      */
  184.  
  185.     bd = WhitePixel(dpy, DefaultScreen(dpy));
  186.     bg = BlackPixel(dpy, DefaultScreen(dpy));
  187.     fg = WhitePixel(dpy, DefaultScreen(dpy));
  188.  
  189.     /*
  190.      * Set the border width of the window,  and the gap between the text
  191.      * and the edge of the window, "pad".
  192.      */
  193.  
  194.     pad = BORDER;
  195.     bw = 1;
  196.  
  197.     /*
  198.      * Deal with providing the window with an initial position & size.
  199.      * Fill out the XSizeHints struct to inform the window manager. See
  200.      * Sections 9.1.6 & 10.3.
  201.      */
  202.  
  203.     xsh.width = XTextWidth(curfont, TITLE, 80 + pad * 2);   
  204.     xsh.flags = (PPosition | PSize);
  205.     xsh.height = WIN_H;
  206.     xsh.width =  WIN_W; 
  207.     xsh.x = (DisplayWidth(dpy, DefaultScreen(dpy)) - xsh.width) / 2;
  208.     xsh.y = (DisplayHeight(dpy, DefaultScreen(dpy)) - xsh.height) / 2;
  209.  
  210.     /*
  211.      * Create the Window with the information in the XSizeHints, the
  212.      * border width,  and the border & background pixels. See Section 3.3.
  213.      */
  214.  
  215.     win = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy),
  216.                   xsh.x, xsh.y, xsh.width, xsh.height,
  217.                   bw, bd, bg);
  218.  
  219.     /*
  220.      * Set the standard properties for the window managers. See Section
  221.      * 9.1.
  222.      */
  223.  
  224.     XSetStandardProperties(dpy, win, TITLE, TITLE, None, argv,
  225.                argc, &xsh);
  226.     XSetWMHints(dpy, win, &SBwmh);
  227.  
  228.     /*
  229.      * Ensure that the window's colormap field points to the default
  230.      * colormap,  so that the window manager knows the correct colormap to
  231.      * use for the window.  See Section 3.2.9. Also,  set the window's Bit
  232.      * Gravity to reduce Expose events.
  233.      */
  234.  
  235.     xswa.colormap = DefaultColormap(dpy, DefaultScreen(dpy));
  236.     xswa.bit_gravity = CenterGravity;
  237.     XChangeWindowAttributes(dpy, win, (CWColormap | CWBitGravity), &xswa);
  238.  
  239.     /*
  240.      * Map the window to make it visible.  See Section 3.5.
  241.      */
  242.    
  243.      XMapWindow(dpy, win); 
  244.  
  245.  
  246.      /*
  247.      * Find out how big the window is now,  so that we can center
  248.      * the text in it.
  249.      */
  250.  
  251.     if (XGetWindowAttributes(dpy, win, &xwa) == 0){
  252.        fprintf(stderr,"Stacked Bar Plot: Can't access attributes for graph window\n");
  253.        exit(1);    
  254.     }
  255.  
  256.     XClearWindow(dpy, win);
  257.     XSelectInput(dpy,win, ButtonPressMask|KeyPressMask|ExposureMask);
  258.  
  259.  
  260.     while (looping) {
  261.         XEvent event;
  262.  
  263.         XNextEvent(dpy,&event);
  264.  
  265.         switch(event.type)
  266.         {
  267.         case KeyPress:
  268.         case ButtonPress: looping = 0;
  269.                   break;
  270.         case Expose: draw = 1;
  271.         }
  272.                
  273.  
  274.        if (!draw) continue;
  275.  
  276.            XDrawRectangle(dpy,win,maingcreversed,
  277.               RECT_X,RECT_Y,RECT_W,RECT_H);
  278.  
  279.           /* 
  280.        *  Calculate the length of the grid lines.  grid_l_x and 
  281.        *  grid_l_y are set to '0' if a line should not be drawn.
  282.            */
  283.  
  284.            if  (graphic_grid == 'H') 
  285.            {
  286.              grid_l_x = RECT_W;
  287.              grid_l_y = 0;
  288.            }
  289.            else if (graphic_grid == 'V')
  290.            {
  291.              grid_l_x = 0;
  292.              grid_l_y = RECT_H;
  293.            }  
  294.            else if (graphic_grid == 'B')
  295.            {
  296.              grid_l_x = RECT_W;
  297.              grid_l_y = RECT_H;
  298.            }  
  299.            else 
  300.            {
  301.              grid_l_x = 0;
  302.              grid_l_y = 0;
  303.            }  
  304.  
  305.            Y_Range = max_y - min_y; 
  306.  
  307.            /* The width of each bar */
  308.            width = (RECT_W - (PIX_SEP * (number_of_bars)))/number_of_bars;
  309.  
  310.            grid_h = RECT_H /10;
  311.          
  312.      
  313.      /* Draw the grid along with the labels on the Y-Axis */
  314.  
  315.        for (i=0; i<11; i++) {
  316.              if (i > 0 && i < 10)
  317.              XDrawLine(dpy,win,maingcreversed,
  318.                RECT_X-4, RECT_Y+i*grid_h,
  319.                RECT_X, RECT_Y+i*grid_h);
  320.          XDrawLine(dpy,win,maingcreversed,
  321.                RECT_X, RECT_Y+i*grid_h,
  322.                RECT_X+grid_l_x, RECT_Y+i*grid_h);
  323.          XDrawLine(dpy,win,maingcreversed,
  324.                RECT_X + RECT_W,RECT_Y+i*grid_h,
  325.                RECT_X+RECT_W - grid_l_x, RECT_Y+i*grid_h);
  326.  
  327.              sprintf(str,"%.1f",(max_y - Y_Range*i/10));
  328.              len = strlen(str);
  329.              text_w = XTextWidth(curfont,str,len+2);
  330.              XDrawImageString(dpy,win,maingcreversed,
  331.                        RECT_X - text_w,
  332.                        RECT_Y + i*grid_h + curfontheight/3,
  333.                        str,len);
  334.  
  335.        } /*end for loop*/
  336.  
  337.        for (i=1; i < number_of_bars; i++) {
  338.              x = RECT_X + (PIX_SEP * i) + (width * i);
  339.          XDrawLine(dpy,win,maingcreversed,
  340.                x, RECT_Y, x, RECT_Y+grid_l_y);
  341.          XDrawLine(dpy,win,maingcreversed,
  342.                x, RECT_Y+RECT_H, x, RECT_Y+RECT_H-grid_l_y);
  343.        } /*end for loop*/
  344.  
  345.           /*
  346.            *
  347.            * Draw titles at top of graph 
  348.            *
  349.            */
  350.  
  351.        len = strlen(graphic_title[0]);    
  352.        text_w = XTextWidth(curfont, graphic_title[0], len);
  353.        XDrawImageString(dpy,win,maingcreversed, 
  354.                 (WIN_W - text_w)/2, RECT_Y/3, 
  355.                 graphic_title[0], len);
  356.      
  357.  
  358.        len = strlen(graphic_title[1]);
  359.        text_w = XTextWidth(curfont, graphic_title[1],len);
  360.        XDrawImageString(dpy,win,maingcreversed, 
  361.                (WIN_W - text_w)/2, RECT_Y*2/3,
  362.                graphic_title[1],len);
  363.  
  364.        len = strlen(graphic_title[2]);
  365.        text_w=XTextWidth(curfont,graphic_title[2],len);
  366.        XDrawImageString(dpy,win,maingcreversed, 
  367.                 (WIN_W-text_w)/2, RECT_H+RECT_Y*3/2,
  368.                 graphic_title[2],len);
  369.  
  370.        len = strlen(graphic_title[3]);
  371.        text_w=XTextWidth(curfont,graphic_title[3],len);
  372.            if ((RECT_X-text_w) < 0) 
  373.                x = curfontwidth;
  374.            else
  375.                x = RECT_X-text_w;
  376.        XDrawImageString(dpy,win,maingcreversed,
  377.                 x, RECT_Y - curfontheight,
  378.                 graphic_title[3],len);        
  379.  
  380.   /* --------------------------------------------------------------------*/
  381.   /* This next section will read values of the x and y center points     */
  382.   /* and find the maximum and minimum values for each, then set the      */
  383.   /* width and height paramters, convert x and y so that the origin      */
  384.   /* is at the lower left corner of the window, and then finally         */
  385.   /* draw and fill the bars.                                             */
  386.   /* ------------------------------------------------------------------- */
  387.  
  388. /*
  389.  *  Draw Labels on the X-Axis
  390.  */
  391.  
  392.            labelsize = irint(floor(width/(double)curfontwidth)-1);
  393.        y = RECT_Y + RECT_H + curfontheight;
  394.        bars = 0;
  395.        for (i=graphic_range[0].r1;i<=graphic_range[0].r2; i++)
  396.        {
  397.           p = lookat(i,graphic_range[0].c);
  398.           if (!(p->label)) continue;
  399.               strncpy(str, p->label, labelsize);
  400.               str[labelsize] = '\0';
  401.           x = RECT_X+(PIX_SEP*bars)+(width*bars)+(width/2);
  402.               x = x - (curfontwidth*strlen(str))/2;
  403.           bars++;
  404.           XDrawImageString(dpy,win,maingcreversed,
  405.                       x,y,
  406.                    str,strlen(str));
  407.        }
  408.  
  409.         bars = 0;
  410.         for (i=graphic_range[0].r1; i<=graphic_range[0].r2; i++) 
  411.         {
  412.            bars++;
  413.            Y_Position[bars] = 0;
  414.         }
  415.  
  416.         
  417.         for (i = 1; i < GRAPHRANGES; i++){
  418.             if (*(graphic_range[i].col) == '\0') continue;
  419.  
  420.             bars = 0;
  421.             for(j=graphic_range[0].r1, k=graphic_range[i].r1;
  422.            (j<=graphic_range[0].r2) && (k<=graphic_range[i].r2); j++, k++){ 
  423.  
  424.           if (!((p=lookat(j,graphic_range[0].c))->label)) continue;
  425.  
  426.           x = RECT_X + ((PIX_SEP)*(bars)) + (width*bars);
  427.           bars++;
  428.  
  429.  
  430.           if (!((val=lookat(j,graphic_range[i].c))->flags & is_valid) 
  431.           || (val->v < min_y) || (val->v > max_y)) continue;
  432.  
  433.               /* 
  434.            *  Calculate the height of the bar.  If it is the 'lowest'
  435.            *  piece of the bar, subtract off the value of the min_y
  436.            *  for an accurate height.
  437.                */
  438.  
  439.               if (i == 1) 
  440.              height = irint((val->v - min_y) / Y_Range * RECT_H);
  441.               else 
  442.              height = irint(val->v / Y_Range * RECT_H);
  443.  
  444.           y = RECT_Y + RECT_H - height - Y_Position[bars];  
  445.  
  446.               Y_Position[bars] = Y_Position[bars] + height;
  447.  
  448.               /* clear the area before drawing the bar */ 
  449.               if (graphic_grid != 'C') 
  450.                  XClearArea(dpy,win,x,y,width,height,False); 
  451.  
  452.               /* choose a pattern to be used */
  453.               switch (i) {
  454.                 case 1 : Pattern = XCreateBitmapFromData(dpy,win,white_bits,
  455.                              white_width, white_height);
  456.                              break;
  457.                 case 2 : Pattern = XCreateBitmapFromData(dpy,win,gray3_bits,
  458.                              gray3_width, gray3_height);
  459.                              break;
  460.                 case 3 : Pattern = XCreateBitmapFromData(dpy,win,gray5_bits,
  461.                              gray5_width, gray5_height);
  462.                              break;
  463.                 case 4 : Pattern = XCreateBitmapFromData(dpy,win,gray2_bits,
  464.                              gray2_width, gray2_height);
  465.                              break;
  466.                 case 5 : Pattern = XCreateBitmapFromData(dpy,win,gray4_bits,
  467.                              gray4_width, gray4_height);
  468.                              break;
  469.                 case 6 : Pattern = XCreateBitmapFromData(dpy,win,gray1_bits,
  470.                              gray1_width, gray1_height);
  471.                              break; }
  472.  
  473.               /* Display a filled portion of the bar */
  474.               XSetStipple(dpy, maingcreversed, Pattern); 
  475.               XSetFillStyle(dpy, maingcreversed, FillStippled);
  476.           XFillRectangle(dpy,win,maingcreversed,x,y,width,height); 
  477.               
  478.           /* Draw a solid outline around the bar */
  479.               XSetFillStyle(dpy, maingcreversed, FillSolid);
  480.           XDrawRectangle(dpy,win,maingcreversed,x,y,width,height);
  481.         }
  482.      }
  483.    }
  484.    XUnmapWindow(dpy, win);
  485.    XDestroyWindow(dpy, win);
  486.  
  487. }
  488.