/*
 * A simple sample test program; see the Using.tex document for details.
 * 
 * Copyright 1991 by Burdett, Buckeridge & Young Ltd.
 */

/* First, the various headers required */

#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <X11/Xaw/Command.h>
#include <X11/Xaw/Form.h>

#ifdef _AtDevelopment_
#include "Plotter.h"
#include "LinePlot.h"
#include "BarPlot.h"
#include "Axis.h"
#else
#include <At/Plotter.h>
#include <At/LinePlot.h>
#include <At/BarPlot.h>
#include <At/Axis.h>
#endif

/*
 * The application data - weekly sales data for Widgets.
 */
struct profits {
     /* From database */
     long volume;
     float buy_price;
     float sell_price;
     /* calculated values */
     double sales;
     double cost;
     double profit;
};

#define NUM_WEEKS 52

struct profits profits[NUM_WEEKS];

/*
 * Read from the database - a dummy routine, we'll use random numbers
 */
void 
read_from_database()
{
     int i;
     extern int rand();
     
     for (i = 0; i < NUM_WEEKS; i++) {
	  /* Volume between 1000 and 5095 */
	  profits[i].volume = (rand() & 0xfff) + 1000;
	  /* Sell price between $15 and $25 */
	  profits[i].sell_price = (double)(rand() & 0xffffff) /
	       0xffffff * 10.0 + 15.0;
	  /* Buy price between $5 and $15 */
	  profits[i].buy_price = (double)(rand() & 0xffffff) /
	       0xffffff * 10.0 + 5.0;
     }
}

/*
 * Calculate the profit from the above data
 */

void 
calculate_profit()
{
     int i;

     for (i = 0; i < NUM_WEEKS; i++) {
	  profits[i].sales = profits[i].volume *
	       profits[i].sell_price;
	  profits[i].cost = profits[i].volume * profits[i].buy_price;
	  profits[i].profit = profits[i].sales - profits[i].cost;
     }
}


/*****************************************************************
 *
 * This is the interesting bit.  Make a simple graph, profits on left,
 * volume on right, weeknumber on bottom, profit a line graph, volume
 * a bar graph.
 */

Widget plotter, xaxis, yaxis, y2axis, line, bar;

void 
make_plotter(parent)
Widget parent;
{
     double thousandth = 1.0e-3; 
     plotter = XtVaCreateManagedWidget("plotter", atPlotterWidgetClass, parent,
				       XtNtitle, "Widget Sales & Profits",
				       XtNwidth, 600, XtNheight, 450,
				       NULL);
     /* Note axis objects are unmanaged */
     xaxis = XtVaCreateWidget("xaxis", atAxisWidgetClass, plotter,
			      XtNlabel, "Week Number",
			      XtNticFormat, "%.0f",
			      NULL);
     /* Note Y axis is vertical */
     yaxis = XtVaCreateWidget("yaxis", atAxisWidgetClass, plotter, 
			      XtNvertical, True,
			      XtNlabel, "Profit ($1,000's)",
			      XtNticMultiplier, &thousandth,
			      NULL);
     /* Note Y2 axis is vertical and mirrored */
     y2axis = XtVaCreateWidget("y2axis", atAxisWidgetClass, plotter, 
			       XtNvertical, True,
			       XtNmirror, True,
			       XtNlabel, "Volume Shipped (1,000s)",
			       XtNdrawGrid, False, /* Two grids is confusing */
			       XtNticMultiplier, &thousandth,
			       XtNticFormat, "%4.1f",
			       NULL);
     /* Now attach axes to the parent */
     XtVaSetValues(plotter, XtNxAxis, xaxis, 
		   XtNyAxis, yaxis,
		   XtNy2Axis, y2axis,
		   NULL);
     
     /* Now create the plots */
     /* The volume is scaled against y2 axis */
     bar = XtVaCreateWidget("vol", atBarPlotWidgetClass, plotter, 
			    XtNlegendName, "Volume",
			    XtNuseY2Axis, True,
			    XtNshading, AtGRAY3, /* For better PS */
			    NULL);
     /* But profit against Y axis */
     line = XtVaCreateWidget("profit", atLinePlotWidgetClass, plotter, 
			     XtNlegendName, "Profit",
			     XtNlineWidth, 2,
			     NULL);
}

/*****************************************************************
 *
 * Attach the application data to the plot children
 */

void 
attach_data()
{
     AtLinePlotAttachData(line, (XtPointer)&profits[0].profit,
			  AtDouble, sizeof (struct profits),
			  1, NUM_WEEKS);
     AtBarPlotAttachData(bar, (XtPointer)&profits[0].volume,
			 AtInt, sizeof (struct profits),
			 1, NUM_WEEKS);
}

/*****************************************************************
 *
 * This is the boring bit: a form with two buttons and the plotter as
 * children
 */

Widget form, quitbutton, printbutton;

extern int exit();

void 
quit_callback()
{
     exit(0);
}

void 
print_callback()
{
     AtPlotterGeneratePostscript("ps.out", (AtPlotterWidget)plotter, 
				 "Widget Profits", 0, 0, 400, 250, False);
     fprintf(stderr, "Plot dumped in ps.out\n");
}

void 
make_form(parent)
Widget parent;
{
     form = XtVaCreateManagedWidget("form", formWidgetClass, parent, NULL);
     quitbutton = XtVaCreateManagedWidget("quit", commandWidgetClass, form,
					  XtNlabel, "Quit",
					  XtNleft, XtChainLeft,
					  NULL);
     XtAddCallback(quitbutton, XtNcallback, quit_callback, NULL); 
     printbutton = XtVaCreateManagedWidget("print", commandWidgetClass, form,
					   XtNlabel, "Print",
					   XtNfromHoriz, quitbutton,
					   NULL);
     XtAddCallback(printbutton, XtNcallback, print_callback, NULL); 
}


int 
main(ac, av)
Cardinal ac;
char **av; 
{
     Widget appShell;
     XtAppContext app;
     
     appShell = XtAppInitialize(&app, "Test", NULL, 0, &ac, av,
				NULL, NULL, 0);

     make_form(appShell);
     make_plotter(form);
     /* Make the plotter below the buttons! */
     XtVaSetValues(plotter, XtNleft, XtChainLeft, 
		   XtNfromVert, quitbutton,
		   NULL);

     /* Now read the data and calculate it */
     read_from_database();
     calculate_profit();

     /* Now attach the data to the plot widget */
     attach_data();
     
     XtRealizeWidget(appShell);

     XtAppMainLoop(app);
     /*NOTREACHED*/
     return 0; 
}
