/*
* Copyright (C) 1992 Board of Regents of the University of Wisconsin
* on behalf of the Department of Electrical Engineering and Computer
* Science, University of Wisconsin-Milwaukee, Milwaukee, WI 53201.
*
* 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
* a copy of which is included here in file "GNU_GENERAL"
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* The programs in this directory were developed by software engineering
* teams as part of the course "Introduction to Software Engineering"
* under the supervision of Professor G. Davida.
* This is a modification of a program written or modified by
* others. The original copyrights, as per GNU General Public License,
* may still be applicable. The UWM copyright is applicable only
* the those parts generated at UWM.
*
* Please send all changes, enhancements, and other comments about this
* software to
* soft-eng@cs.uwm.edu
*
* No Warranty, expressed or implied, comes with this software.
* This software is intended to be used by not-for-profit
* organizations or by individuals for personal HOME use.
* This software, or any of its parts, may not be used by for-profit
* organization, regardless of application or intended product or
* customer, without the permission of the Board of Regents of the
* University of Wisconsin.
*
* Contact: soft-eng@cs.uwm.edu
* or
*
* Software Engineering Coordinator
* Computer Science
* Department of EECS
* University of Wisconsin - Milwaukee
* Milwaukee, WI 53201
* 414-229-4677
*
* HISTORY,CLAIMS and CONTRIBUTIONS
*/
/*************************************************************************
* This procedure displays a stacked bar graph for the values chosen *
* by the user. It displays one bar for each row chosen and 'stacks' *
* one section for each column chosen. It uses patterns located in *
* the file pattern.h *
* Dan Gruber - December 1991 *
* Modified 5/94 by Dan Coppersmith to improve user friendliness of *
* error messages. *
*************************************************************************
*/
#include <config.h>
#ifdef HAVE_X11_X_H /* this code for now is X specific */
#include <curses.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include "plot.h"
#include "pattern.h"
#include "graphic_gvar.h"
#include "sc.h"
#include "scXstuff.h"
#include <math.h>
#define TITLE "XSPREAD-Grapher (Stacked Bar Plot)"
#define PIX_SEP 5
#ifndef irint
#define irint(x) floor((x)+0.5)
#endif
XWMHints SBwmh = {
(InputHint|StateHint), /*flags*/
False, /*input*/
NormalState, /*initial_state*/
0, /*icon pixmap*/
0, /*icon window*/
0, 0, /*icon location*/
0, /*icon mask*/
0, /*Window group*/
};
void
plot_stacked_bar()
{ int argc = 0;
char **argv = 0;
double max_y, min_y, Y_Range;
int i,j /* ,k */; /* Iteration variables */
int grid_l_x; /* The size of the grid separators */
int grid_l_y;
int grid_h;
int height, width; /* Height and width of a bar */
char str[100]; /* The label to be drawn */
int text_w; /* The width of a label in pixels */
int len; /* The length of a label */
int x,y; /* X and Y coordinates for the bar */
struct ent *p, *val;
int looping = 1; /* Continue looping variable */
int draw = 0; /* Continue drawing variable */
int first_bar = 1; /* first bar flag */
int number_of_bars; /* Total number of bars */
int bars = 0; /* Current bar */
int labelsize; /* Maximum size of label to be drawn */
double Row_Total[20]; /* Row Total */
int Y_Position[20]; /* Position to draw next portion of bar */
Pixmap Pattern; /* Type of pattern to be drawn */
/*---- Colors & fonts added by Rama Devi ---------*/
Colormap cmap;
XColor exactBlack, exactOrange;
XColor exactGreen, exactGoldenrod, exactOrchid;
XColor exactYellow, exactGreenYellow, exactAquamarine;
XColor Black, Orange;
XColor Green, Goldenrod, Orchid, Yellow, GreenYellow, Aquamarine;
extern XFontStruct *curfont; /* Font descriptor struct for current font */
extern Font curfontid; /* resource id of current font */
extern int curfontwidth,
curfontheight; /* pixel dimensions of current font */
/*
* Decide the scale for x and y axes
*/
for (i=graphic_range[0].r1; i<=graphic_range[0].r2; i++)
{
p=lookat(i,graphic_range[0].c);
if(!(p->label)) continue;
bars++;
Row_Total[bars] = 0;
Y_Position[bars] = 0;
}
if (bars < 1)
{
fprintf(stderr,"\007");
if (graphic_range[0].r2 - graphic_range[0].r1 > 1)
message("x values must be strings");
else
message("Not enough valid X labels");
return;
}
number_of_bars = bars;
if (g_auto_man[1] == 'M') {
max_y = graphic_scale[1][1];
min_y = graphic_scale[1][0];
}
else {
for (j=1; j < GRAPHRANGES; j++){
if (*(graphic_range[j].col) == '\0') continue;
bars = 0;
/*-----for (i=graphic_range[j].r1; i<=graphic_range[j].r2; i++)------*/
for (i=graphic_range[0].r1; i<=graphic_range[0].r2; i++)
{
/*----- p=lookat(i,graphic_range[j].c); ---commented Rama Devi--*/
/* if(!(p->flags & is_valid)) continue; */
p=lookat(i,graphic_range[0].c); /*---added by Rama Devi ---*/
if(!(p->label)) continue; /*---added by Rama Devi ---*/
bars++;
/*--- The following lines added by Rama Devi ---------*/
if (( i >= graphic_range[j].r1) && (i <= graphic_range[j].r2))
{
val =lookat(i,graphic_range[j].c);
if (val->flags & is_valid){
/*------------------------------------------------------*/
Row_Total[bars] = Row_Total[bars] + (val->v);
if (first_bar){
min_y = val->v;
first_bar = 0;
} else
min_y = Min(min_y, val->v);
}
}
}
}
first_bar = 1;
for (i=1; i<=bars; i++){
if (first_bar){
max_y = Row_Total[i];
first_bar = 0;
} else {
max_y = Max(max_y, Row_Total[i]);
}
}
min_y -= 0.1*(fabs(min_y));
max_y += 0.1*(fabs(max_y));
}
max_y = ceil(max_y);
min_y = floor(min_y);
/*
* Select colors for the border, the window background, and the
* foreground.
*/
/*---- Colors and fonts added by Rama Devi --*/
cmap = DefaultColormap(dpy, DefaultScreen(dpy));
if ((XAllocNamedColor(dpy, cmap, "Black", &exactBlack,
&Black) != 0) && (XAllocNamedColor (dpy, cmap,
"Orange", &exactOrange, &Orange) != 0))
{
bd = Orange.pixel;
bg = Black.pixel;
fg = Orange.pixel;
}
else
{
bd = WhitePixel(dpy, DefaultScreen(dpy));
bg = BlackPixel(dpy, DefaultScreen(dpy));
fg = WhitePixel(dpy, DefaultScreen(dpy));
}
if (userfont == NULL)
curfont = XLoadQueryFont(dpy, SC_FONT);
else
curfont = XLoadQueryFont(dpy, userfont);
if (curfont == NULL)
{
fprintf(stderr, "%s: Display %s doesn't know font \"%s\" \n",
progname, DisplayString(dpy), userfont == NULL ? SC_FONT : userfont);
exit(1);
}
/* initialize the font-related globals */
/* usefont(curfont); */
curfontid = curfont->fid;
curfontheight = curfont->max_bounds.ascent + curfont->max_bounds.descent;
curfontwidth = curfont->max_bounds.width;
/*
* Set the border width of the window, and the gap between the text
* and the edge of the window, "pad".
*/
pad = BORDER;
bw = 1;
/*
* Deal with providing the window with an initial position & size.
* Fill out the XSizeHints struct to inform the window manager. See
* Sections 9.1.6 & 10.3.
*/
xsh.width = XTextWidth(curfont, TITLE, 80 + pad * 2);
xsh.flags = (PPosition | PSize);
xsh.height = WIN_H;
xsh.width = WIN_W;
xsh.x = (DisplayWidth(dpy, DefaultScreen(dpy)) - xsh.width) / 2;
xsh.y = (DisplayHeight(dpy, DefaultScreen(dpy)) - xsh.height) / 2;
/*
* Create the Window with the information in the XSizeHints, the
* border width, and the border & background pixels. See Section 3.3.
*/
win = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy),
xsh.x, xsh.y, xsh.width, xsh.height,
/*--- bw, bd, bg); ---*/
bw, fg, bg);
/*
* Set the standard properties for the window managers. See Section
* 9.1.
*/
XSetStandardProperties(dpy, win, TITLE, TITLE, None, argv,
argc, &xsh);
XSetWMHints(dpy, win, &SBwmh);
/*
* Ensure that the window's colormap field points to the default
* colormap, so that the window manager knows the correct colormap to
* use for the window. See Section 3.2.9. Also, set the window's Bit
* Gravity to Orchiduce Expose events.
*/
xswa.colormap = DefaultColormap(dpy, DefaultScreen(dpy));
xswa.bit_gravity = CenterGravity;
XChangeWindowAttributes(dpy, win, (CWColormap | CWBitGravity), &xswa);
/*--- The following statement is added by Rama Devi ---*/
cmap = DefaultColormap(dpy, DefaultScreen(dpy));
if ((XAllocNamedColor (dpy, cmap, "Orange", &exactOrange, &Orange) != 0))
{
maingcreversed = XCreateGC(dpy, win, 0,0);
XSetFont(dpy, maingcreversed, curfontid);
XSetForeground (dpy, maingcreversed, Orange.pixel);
XSetBackground (dpy, maingcreversed, Black.pixel);
}
else
{
maingcreversed = XCreateGC(dpy, win, 0,0);
XSetFont(dpy, maingcreversed, curfontid);
XSetForeground (dpy, maingcreversed, fg);
XSetBackground (dpy, maingcreversed, bg);
} /*---*/
/*
* Map the window to make it visible. See Section 3.5.
*/
XMapWindow(dpy, win);
/*
* Find out how big the window is now, so that we can center
* the text in it.
*/
if (XGetWindowAttributes(dpy, win, &xwa) == 0){
fprintf(stderr,"Stacked Bar Plot: Can't access attributes for graph window\n");
exit(1);
}
XClearWindow(dpy, win);
XSelectInput(dpy,win, ButtonPressMask|KeyPressMask|ExposureMask);
while (looping) {
XEvent event;
XNextEvent(dpy,&event);
switch(event.type)
{
case KeyPress:
case ButtonPress: looping = 0;
break;
case Expose: draw = 1;
}
if (!draw) continue;
XDrawRectangle(dpy,win,maingcreversed,
RECT_X,RECT_Y,RECT_W,RECT_H);
/*
* Calculate the length of the grid lines. grid_l_x and
* grid_l_y are set to '0' if a line should not be drawn.
*/
if (graphic_grid == 'H')
{
grid_l_x = RECT_W;
grid_l_y = 0;
}
else if (graphic_grid == 'V')
{
grid_l_x = 0;
grid_l_y = RECT_H;
}
else if (graphic_grid == 'B')
{
grid_l_x = RECT_W;
grid_l_y = RECT_H;
}
else
{
grid_l_x = 0;
grid_l_y = 0;
}
Y_Range = max_y - min_y;
/* The width of each bar */
width = (RECT_W - (PIX_SEP * (number_of_bars)))/number_of_bars;
grid_h = RECT_H /10;
/* Draw the grid along with the labels on the Y-Axis */
for (i=0; i<11; i++) {
if (i > 0 && i < 10)
XDrawLine(dpy,win,maingcreversed,
RECT_X-4, RECT_Y+i*grid_h,
RECT_X, RECT_Y+i*grid_h);
XDrawLine(dpy,win,maingcreversed,
RECT_X, RECT_Y+i*grid_h,
RECT_X+grid_l_x, RECT_Y+i*grid_h);
XDrawLine(dpy,win,maingcreversed,
RECT_X + RECT_W,RECT_Y+i*grid_h,
RECT_X+RECT_W - grid_l_x, RECT_Y+i*grid_h);
sprintf(str,"%.1f",(max_y - Y_Range*i/10));
len = strlen(str);
text_w = XTextWidth(curfont,str,len+2);
XDrawImageString(dpy,win,maingcreversed,
RECT_X - text_w,
RECT_Y + i*grid_h + curfontheight/3,
str,len);
} /*end for loop*/
for (i=1; i < number_of_bars; i++) {
x = RECT_X + (PIX_SEP * i) + (width * i);
XDrawLine(dpy,win,maingcreversed,
x, RECT_Y, x, RECT_Y+grid_l_y);
XDrawLine(dpy,win,maingcreversed,
x, RECT_Y+RECT_H, x, RECT_Y+RECT_H-grid_l_y);
} /*end for loop*/
/*
*
* Draw titles at top of graph
*
*/
len = strlen(graphic_title[0]);
text_w = XTextWidth(curfont, graphic_title[0], len);
XDrawImageString(dpy,win,maingcreversed,
(WIN_W - text_w)/2, RECT_Y/3,
graphic_title[0], len);
len = strlen(graphic_title[1]);
text_w = XTextWidth(curfont, graphic_title[1],len);
XDrawImageString(dpy,win,maingcreversed,
(WIN_W - text_w)/2, RECT_Y*2/3,
graphic_title[1],len);
len = strlen(graphic_title[2]);
text_w=XTextWidth(curfont,graphic_title[2],len);
XDrawImageString(dpy,win,maingcreversed,
(WIN_W-text_w)/2, RECT_H+RECT_Y*3/2,
graphic_title[2],len);
len = strlen(graphic_title[3]);
text_w=XTextWidth(curfont,graphic_title[3],len);
if ((RECT_X-text_w) < 0)
x = curfontwidth;
else
x = RECT_X-text_w;
XDrawImageString(dpy,win,maingcreversed,
x, RECT_Y - curfontheight,
graphic_title[3],len);
/* --------------------------------------------------------------------*/
/* This next section will read values of the x and y center points */
/* and find the maximum and minimum values for each, then set the */
/* width and height paramters, convert x and y so that the origin */
/* is at the lower left corner of the window, and then finally */
/* draw and fill the bars. */
/* ------------------------------------------------------------------- */
/*
* Draw Labels on the X-Axis
*/
labelsize = irint(floor(width/(double)curfontwidth)-1);
y = RECT_Y + RECT_H + curfontheight;
bars = 0;
for (i=graphic_range[0].r1;i<=graphic_range[0].r2; i++)
{
p = lookat(i,graphic_range[0].c);
if (!(p->label)) continue;
strncpy(str, p->label, labelsize);
str[labelsize] = '\0';
x = RECT_X+(PIX_SEP*bars)+(width*bars)+(width/2);
x = x - (curfontwidth*strlen(str))/2;
bars++;
XDrawImageString(dpy,win,maingcreversed,
x,y,
str,strlen(str));
}
bars = 0;
for (i=graphic_range[0].r1; i<=graphic_range[0].r2; i++)
{
p=lookat(i,graphic_range[0].c); /*---added by Rama Devi --------*/
if(!(p->label)) continue; /*---added by Rama Devi --------*/
bars++;
Y_Position[bars] = 0;
}
for (i = 1; i < GRAPHRANGES; i++){
if (*(graphic_range[i].col) == '\0') continue;
bars = 0;
/*----------the following lines are commented by Rama Devi --------
-------- for(j=graphic_range[0].r1, k=graphic_range[i].r1;
(j<=graphic_range[0].r2) && (k<=graphic_range[i].r2); j++, k++){
if (!((p=lookat(j,graphic_range[0].c))->label)) continue; ----*/
/*------The following lines added by Rama Devi ------------------*/
for (j = graphic_range[0].r1; j <= graphic_range[0].r2; j++)
{
p=lookat(j,graphic_range[0].c);
if(!(p->label)) continue;
/*----------------------------------------------------------------*/
x = RECT_X + ((PIX_SEP)*(bars)) + (width*bars);
bars++;
/*-------the following lines commented by Rama Devi --------------
-----if (!((val=lookat(j,graphic_range[i].c))->flags & is_valid)
|| (val->v < min_y) || (val->v > max_y)) continue; ---------*/
/*-------The following lines added by Rama Devi ---------------*/
if ((j >= graphic_range[i].r1) && (j <= graphic_range[i].r2))
{
val = lookat(j, graphic_range[i].c);
if (val->flags & is_valid) {
/*-----------------------------------------------------------*/
/*
* Calculate the height of the bar. If it is the 'lowest'
* piece of the bar, subtract off the value of the min_y
* for an accurate height.
*/
if (i == 1)
height = irint((val->v - min_y) / Y_Range * RECT_H);
else
height = irint(val->v / Y_Range * RECT_H);
y = RECT_Y + RECT_H - height - Y_Position[bars];
Y_Position[bars] = Y_Position[bars] + height;
/* clear the area before drawing the bar */
if (graphic_grid != 'C')
XClearArea(dpy,win,x,y,width,height,False);
/* choose a pattern to be used */
switch (i) {
case 1 : Pattern = XCreateBitmapFromData(dpy,win,dark_wide_weave_bits,
dark_wide_weave_width, dark_wide_weave_height);
/*---- The following two statements added by Rama Devi ----*/
cmap = DefaultColormap(dpy, DefaultScreen(dpy));
if ((XAllocNamedColor (dpy, cmap, "Green", &exactGreen, &Green) != 0))
{
XSetForeground (dpy, maingcreversed, Green.pixel);
XSetBackground (dpy, maingcreversed, Black.pixel);
}
else
{
XSetForeground (dpy, maingcreversed, fg);
XSetBackground (dpy, maingcreversed, bg);
}
break;
case 2: Pattern = XCreateBitmapFromData(dpy,win,dark_root_weave_bits,
dark_root_weave_width, dark_root_weave_height);
/*---- The following two statements added by Rama Devi ----*/
cmap = DefaultColormap(dpy, DefaultScreen(dpy));
if ((XAllocNamedColor (dpy, cmap, "Orchid", &exactOrchid, &Orchid) != 0))
{
XSetForeground (dpy, maingcreversed, Orchid.pixel);
XSetBackground (dpy, maingcreversed, Black.pixel);
}
else
{
XSetForeground (dpy, maingcreversed, fg);
XSetBackground (dpy, maingcreversed, bg);
}
break;
case 3: Pattern = XCreateBitmapFromData(dpy,win,dark_cross_weave_bits,
dark_cross_weave_width, dark_cross_weave_height);
/*---- The following two statements added by Rama Devi ----*/
cmap = DefaultColormap(dpy, DefaultScreen(dpy));
if ((XAllocNamedColor (dpy, cmap, "GreenYellow", &exactGreenYellow, &GreenYellow) != 0))
{
XSetForeground (dpy, maingcreversed, GreenYellow.pixel);
XSetBackground (dpy, maingcreversed, Black.pixel);
}
else
{
XSetForeground (dpy, maingcreversed, fg);
XSetBackground (dpy, maingcreversed, bg);
}
break;
case 4: Pattern = XCreateBitmapFromData(dpy,win,light_wide_weave_bits,
light_wide_weave_width, light_wide_weave_height);
/*---- The following two statements added by Rama Devi ----*/
cmap = DefaultColormap(dpy, DefaultScreen(dpy));
if ((XAllocNamedColor (dpy, cmap, "Goldenrod", &exactGoldenrod, &Goldenrod) != 0))
{
XSetForeground (dpy, maingcreversed, Goldenrod.pixel);
XSetBackground (dpy, maingcreversed, Black.pixel);
}
else
{
XSetForeground (dpy, maingcreversed, fg);
XSetBackground (dpy, maingcreversed, bg);
}
break;
case 5 : Pattern = XCreateBitmapFromData(dpy,win,light_root_weave_bits,
light_root_weave_width, light_root_weave_height);
/*---- The following two statements added by Rama Devi ----*/
cmap = DefaultColormap(dpy, DefaultScreen(dpy));
if ((XAllocNamedColor (dpy, cmap, "Aquamarine", &exactAquamarine, &Aquamarine) != 0))
{
XSetForeground (dpy, maingcreversed, Aquamarine.pixel);
XSetBackground (dpy, maingcreversed, Black.pixel);
}
else
{
XSetForeground (dpy, maingcreversed, fg);
XSetBackground (dpy, maingcreversed, bg);
}
break;
case 6: Pattern = XCreateBitmapFromData(dpy,win,light_cross_weave_bits,
light_cross_weave_width, light_cross_weave_height);
/*---- The following two statements added by Rama Devi ----*/
cmap = DefaultColormap(dpy, DefaultScreen(dpy));
if ((XAllocNamedColor (dpy, cmap, "Yellow", &exactYellow, &Yellow)
!= 0))
{
XSetForeground (dpy, maingcreversed, Yellow.pixel);
XSetBackground (dpy, maingcreversed, Black.pixel);
}
else
{
XSetForeground (dpy, maingcreversed, fg);
XSetBackground (dpy, maingcreversed, bg);
}
break;
}
/* Display a filled portion of the bar */
XSetStipple(dpy, maingcreversed, Pattern);
XSetFillStyle(dpy, maingcreversed, FillStippled);
XFillRectangle(dpy,win,maingcreversed,x,y,width,height);
/* Draw a solid outline around the bar */
XSetFillStyle(dpy, maingcreversed, FillSolid);
XDrawRectangle(dpy,win,maingcreversed,x,y,width,height);
} /*---*/
} /*----*/
}
}
/*---- The following two statements added by Rama Devi ----*/
cmap = DefaultColormap(dpy, DefaultScreen(dpy));
if ((XAllocNamedColor (dpy, cmap, "Orange", &exactOrange, &Orange) != 0))
{
XSetForeground (dpy, maingcreversed, Orange.pixel);
XSetBackground (dpy, maingcreversed, Black.pixel);
}
else
{
XSetForeground (dpy, maingcreversed, fg);
XSetBackground (dpy, maingcreversed, bg);
}
}
cmap = DefaultColormap (dpy, DefaultScreen (dpy));
if (backg && (XAllocNamedColor (dpy, cmap, backg, &exactOrange, &Orange) != 0))
{
bg = Orange.pixel;
}
else
{
bg = WhitePixel(dpy, DefaultScreen(dpy)); /* background */
}
if (foreg && (XAllocNamedColor (dpy, cmap, foreg, &exactBlack, &Black) != 0))
{
fg = Black.pixel;
}
else
{
fg = BlackPixel(dpy, DefaultScreen(dpy)); /* foreground */
}
XSetForeground (dpy, maingc, fg);
XSetBackground (dpy, maingc, bg);
XSetForeground (dpy, maingcreversed, bg);
XSetBackground (dpy, maingcreversed, fg);
XSetForeground(dpy, invertgc, fg);
XUnmapWindow(dpy, win);
XDestroyWindow(dpy, win);
}
#endif /* HAVE_X11_X_H this code for now is X specific */
syntax highlighted by Code2HTML, v. 0.9.1