/*
 *      cplot.c
 *      Test 3: plotter using the athena widget set
 *
 *      Test using 3 plotters, pixmaps and window, align axes
 *
 *      klin, Tue Aug  4 15:03:24 1992
 *      klin, Sat Aug 15 13:39:50 1992, <At/..> changed to <X11/At/...>
 */

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

#include <X11/At/Plotter.h>
#include <X11/At/XYAxis.h>
#include <X11/At/XYLinePlot.h>

/*
 *      The plotter widgets
 */

static Widget plotter1, xaxis1, yaxis1, line1, line2, line3;
static Widget plotter2, xaxis2, yaxis2, line4, line5, line6;
static Widget plotter3, xaxis3, yaxis3, line7, line8, line9;

static Boolean align_axes = True;
void layout_callback();

/*
 *      Create plotters, axes and lines
 */

void MakePlotter(parent)
  Widget parent;
{
  Arg args[16];
  int n;

  n = 0;
  XtSetArg(args[n], XtNtitle, "Logarithmic-Linear Plot (Pixmap)"); n++;
  XtSetArg(args[n], XtNshowLegend, True); n++;
  XtSetArg(args[n], XtNlegendTitle, "Legend plot1"); n++;
  XtSetArg(args[n], XtNfontFamily, "Helvetica"); n++;
  XtSetArg(args[n], XtNtitleSize, AtFontNORMAL); n++;
  XtSetArg(args[n], XtNtitleStyle, AtFontBOLD); n++;
  XtSetArg(args[n], XtNlegendTitleSize, AtFontSMALL); n++;
  XtSetArg(args[n], XtNlegendSize, AtFontSMALL); n++;
  XtSetArg(args[n], XtNwidth, 640); n++;
  XtSetArg(args[n], XtNheight, 240); n++;
  XtSetArg(args[n], XtNusePixmap, True); n++;
  plotter1 = XtCreateManagedWidget("plotter1", atPlotterWidgetClass, parent, args, n);
  XtAddCallback(plotter1, XtNlayoutCallback, layout_callback, (XtPointer) 1);

  n = 0;
  XtSetArg(args[n], XtNlabel, "Omega"); n++;
  XtSetArg(args[n], XtNlabelSize, AtFontSMALL); n++;
  XtSetArg(args[n], XtNnumberSize, AtFontSMALLEST); n++;
  XtSetArg(args[n], XtNaxisTransform, AtTransformLOGARITHMIC); n++;
  xaxis1  = XtCreateWidget("xaxis1", atXYAxisWidgetClass, plotter1, args, n);

  n = 0;
  XtSetArg(args[n], XtNvertical, True); n++;
  XtSetArg(args[n], XtNlabel, "Amplitude"); n++;
  XtSetArg(args[n], XtNlabelSize, AtFontSMALL); n++;
  XtSetArg(args[n], XtNnumberSize, AtFontSMALLEST); n++;
  yaxis1 = XtCreateWidget("yaxis1", atXYAxisWidgetClass, plotter1, args, n);

  n = 0;
  XtSetArg(args[n], XtNxAxis, xaxis1); n++;
  XtSetArg(args[n], XtNyAxis, yaxis1); n++;
  XtSetValues(plotter1, args, n);

  line1 = XtVaCreateWidget("line1", atXYLinePlotWidgetClass, plotter1,
			   XtNlegendName, "line1",
			   XtNplotLineType, AtLineSOLID,
			   NULL);
  line2 = XtVaCreateWidget("line2", atXYLinePlotWidgetClass, plotter1,
			   XtNlegendName, "line2",
			   XtNplotLineType, AtLineDOTTED,
			   NULL);
  line3 = XtVaCreateWidget("line3", atXYLinePlotWidgetClass, plotter1,
			   XtNlegendName, "line3",
			   XtNplotLineType, AtLineDASHED,
			   NULL);

  n = 0;
  XtSetArg(args[n], XtNtitle, "Linear-Linear Plot (Window)"); n++;
  XtSetArg(args[n], XtNlegendTitle, "Legend plot2"); n++;
  XtSetArg(args[n], XtNshowLegend, True); n++;
  XtSetArg(args[n], XtNwidth, 640); n++;
  XtSetArg(args[n], XtNheight, 240); n++;
  XtSetArg(args[n], XtNfontFamily, "Helvetica"); n++;
  XtSetArg(args[n], XtNtitleStyle, AtFontBOLD); n++;
  XtSetArg(args[n], XtNtitleSize, AtFontNORMAL); n++;
  XtSetArg(args[n], XtNlegendTitleSize, AtFontSMALL); n++;
  XtSetArg(args[n], XtNlegendSize, AtFontSMALL); n++;
  plotter2 = XtCreateManagedWidget("plotter2", atPlotterWidgetClass, parent, args, n);
  XtAddCallback(plotter2, XtNlayoutCallback, layout_callback, (XtPointer) 2);

  n = 0;
  XtSetArg(args[n], XtNlabel, "Time"); n++;
  XtSetArg(args[n], XtNlabelSize, AtFontSMALL); n++;
  XtSetArg(args[n], XtNnumberSize, AtFontSMALLEST); n++;
  xaxis2 = XtCreateWidget("xaxis2", atXYAxisWidgetClass, plotter2, args, n);

  n = 0;
  XtSetArg(args[n], XtNvertical, True); n++;
  XtSetArg(args[n], XtNlabel, "Amplitude"); n++;
  XtSetArg(args[n], XtNlabelSize, AtFontSMALL); n++;
  XtSetArg(args[n], XtNnumberSize, AtFontSMALLEST); n++;
  yaxis2 = XtCreateWidget("yaxis2", atXYAxisWidgetClass, plotter2, args, n);

  n = 0;
  XtSetArg(args[n], XtNxAxis, xaxis2); n++;
  XtSetArg(args[n], XtNyAxis, yaxis2); n++;
  XtSetValues(plotter2, args, n);

  line4 = XtVaCreateWidget("line4", atXYLinePlotWidgetClass, plotter2,
			   XtNlegendName, "sinus-points",
			   XtNplotLineType,  AtLineDASHED5,
			   XtNplotLineStyle, AtPlotPOINTS,
			   XtNplotMarkType,  AtMarkPLUS,
			   NULL);
  line5 = XtVaCreateWidget("line5", atXYLinePlotWidgetClass, plotter2,
			   XtNlegendName, "cosinus-points",
			   XtNplotLineType,  AtLineDOTTED2,
			   XtNplotLineStyle, AtPlotPOINTS,
			   XtNplotMarkType,  AtMarkXMARK,
			   NULL);
  line6 = XtVaCreateWidget("line6", atXYLinePlotWidgetClass, plotter2,
			   XtNlegendName, "polygon",
			   XtNplotLineType,  AtLineDOTTED3,
			   XtNplotLineStyle, AtPlotLINEPOINTS,
			   XtNplotMarkType,  AtMarkSTAR,
			   NULL);

  n = 0;
  XtSetArg(args[n], XtNtitle, "Logarithmic-Logarithmic Plot"); n++;
  XtSetArg(args[n], XtNshowLegend, True); n++;
  XtSetArg(args[n], XtNwidth, 640); n++;
  XtSetArg(args[n], XtNheight, 240); n++;
  XtSetArg(args[n], XtNfontFamily, "Helvetica"); n++;
  XtSetArg(args[n], XtNtitleStyle, AtFontBOLD); n++;
  XtSetArg(args[n], XtNtitleSize, AtFontNORMAL); n++;
  XtSetArg(args[n], XtNlegendTitleSize, AtFontSMALL); n++;
  XtSetArg(args[n], XtNlegendSize, AtFontSMALL); n++;
  plotter3 = XtCreateManagedWidget("plotter3", atPlotterWidgetClass, parent, args, n);
  XtAddCallback(plotter3, XtNlayoutCallback, layout_callback, (XtPointer) 3);

  n = 0;
  XtSetArg(args[n], XtNlabel, "Frequency"); n++;
  XtSetArg(args[n], XtNlabelSize, AtFontSMALL); n++;
  XtSetArg(args[n], XtNnumberSize, AtFontSMALLEST); n++;
  XtSetArg(args[n], XtNaxisTransform, AtTransformLOGARITHMIC); n++;
  xaxis3 = XtCreateWidget("xaxis3", atXYAxisWidgetClass, plotter3, args, n);

  n = 0;
  XtSetArg(args[n], XtNvertical, True); n++;
  XtSetArg(args[n], XtNlabel, "Amplitude"); n++;
  XtSetArg(args[n], XtNlabelSize, AtFontSMALL); n++;
  XtSetArg(args[n], XtNnumberSize, AtFontSMALLEST); n++;
  XtSetArg(args[n], XtNaxisTransform, AtTransformLOGARITHMIC); n++;
  yaxis3 = XtCreateWidget("yaxis3", atXYAxisWidgetClass, plotter3, args, n);

  n = 0;
  XtSetArg(args[n], XtNxAxis, xaxis3); n++;
  XtSetArg(args[n], XtNyAxis, yaxis3); n++;
  XtSetValues(plotter3, args, n);

  line7 = XtVaCreateWidget("line7", atXYLinePlotWidgetClass, plotter3,
			   XtNlegendName, "line7",
			   XtNplotLineType, AtLineDOTDASHED,
			   NULL);
  line8 = XtVaCreateWidget("line8", atXYLinePlotWidgetClass, plotter3,
			   XtNlegendName, "line8",
			   XtNplotLineType, AtLineDOTDASHED2,
			   NULL);
}

/*
 *      The data
 */

#define XNUM 100
#define XMIN 0.125
#define XMAX 31.4
#define XDIF 0.313

#define PNUM 6
#define NNUM 12

struct values {
  double xval;
  double yval1;
  double yval2;
  double yval3;
  double zval1;
  double zval2;
  double zval3;
};

struct scvals {
  double xval;
  double sval;
  double cval;
};

struct poly {
  double xval;
  double yval;
};


static struct values values[XNUM];
static struct scvals scvals[XNUM];
static struct poly poly[PNUM];
static struct poly point1[NNUM];
static struct poly point2[NNUM];

/*
 *      Create the data
 */

void MakeData()
{
  double sin(), cos();
  double x, dx;
  int i, j;

  for (x = XMIN, i = 0; x <= XMAX && i < XNUM; x += XDIF, i++) {
    values[i].xval = x;
    values[i].yval1 = 0.01 * x * sin(x);
    values[i].yval2 = 0.0125 * x * cos(x);
    values[i].yval3 = 0.025 * x * sin(x);
    values[i].zval1 = 5.0 + 4 * sin(x);
    values[i].zval2 = 5.0 + 3.75 * cos(x);
    values[i].zval3 = 5.0 + 3.15 * sin(x) * cos(x);
  }

  for(i = 0, x = -3.14; i < XNUM; i++, x += 0.0628) {
    scvals[i].xval = x;
    scvals[i].sval = 2.12 * sin(x);
    scvals[i].cval = 2.12 * cos(x);
  }

  poly[0].xval = -12.0;    poly[0].yval = 0.0;
  poly[1].xval = -1.0;     poly[1].yval = 5.0;
  poly[2].xval = 1.0;      poly[2].yval = 3.0;
  poly[3].xval = 3.0;      poly[3].yval = -0.5;
  poly[4].xval = -0.5;     poly[4].yval = -4.0;
  poly[5].xval = -12.0;    poly[5].yval = 0.0;

  for(i = 0, x = -8.0; i < NNUM; i++, x += 0.75) {
    point1[i].xval = x;
    point2[i].xval = x;
    point1[i].yval = 3.5 * sin(x);
    point2[i].yval = 2.67 * cos(x);
  }

}

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

void AttachData()
{
  AtXYLinePlotAttachData(line1,
    (XtPointer)&values[0].xval,  AtDouble, sizeof(struct values),
    (XtPointer)&values[0].yval1, AtDouble, sizeof(struct values),
    1, XNUM);
  AtXYLinePlotAttachData(line2,
    (XtPointer)&values[0].xval,  AtDouble, sizeof(struct values),
    (XtPointer)&values[0].yval2, AtDouble, sizeof(struct values),
    1, XNUM);
  AtXYLinePlotAttachData(line3,
    (XtPointer)&values[0].xval,  AtDouble, sizeof(struct values),
    (XtPointer)&values[0].yval3, AtDouble, sizeof(struct values),
    1, XNUM);

  AtXYLinePlotAttachData(line4,
    (XtPointer)&point1[0].xval, AtDouble, sizeof(struct poly),
    (XtPointer)&point1[0].yval, AtDouble, sizeof(struct poly),
    1, NNUM);
  AtXYLinePlotAttachData(line5,
    (XtPointer)&point2[0].xval, AtDouble, sizeof(struct poly),
    (XtPointer)&point2[0].yval, AtDouble, sizeof(struct poly),
    1, NNUM);
  AtXYLinePlotAttachData(line6,
    (XtPointer)&poly[0].xval, AtDouble, sizeof(struct poly),
    (XtPointer)&poly[0].yval, AtDouble, sizeof(struct poly),
    1, PNUM);

  AtXYLinePlotAttachData(line7,
    (XtPointer)&values[0].xval,  AtDouble, sizeof(struct values),
    (XtPointer)&values[0].zval1, AtDouble, sizeof(struct values),
    1, XNUM);
  AtXYLinePlotAttachData(line8,
    (XtPointer)&values[0].xval,  AtDouble, sizeof(struct values),
    (XtPointer)&values[0].zval2, AtDouble, sizeof(struct values),
    1, XNUM);
}

/*
 *      The other widgets
 */

static Widget form;
static Widget quitbutton, printbutton, legendbutton;
static Widget gridbutton, subgridbutton;
static Widget originbutton, framebutton, alignbutton;

/*
 *      The button callbacks
 */

#ifndef _STDC__
extern int exit();
#endif

void quit_callback()
{
  exit(0);
}

void print_callback()
{
  AtPlotterGeneratePostscript("cplot1.ps", (AtPlotterWidget) plotter1,
			      "plot1", 0, 0, 400, 250, False);
  AtPlotterGeneratePostscript("cplot2.ps", (AtPlotterWidget) plotter2,
			      "plot 2", 0, 0, 400, 250, False);
  AtPlotterGeneratePostscript("cplot3.ps", (AtPlotterWidget) plotter3,
			      "plot 3", 0, 0, 400, 250, False);
  printf("Print callback: Plots dumped to cplot[123].ps\n");
}

void
legend_callback()
{
  Arg args[4];
  Boolean f;
  int n;

  XtVaGetValues(plotter1, XtNshowLegend, &f, NULL);
  f = f ? False : True;
  XtSetArg(args[0], XtNshowLegend, f);
  XtSetValues(plotter1, args, 1);
  XtSetValues(plotter2, args, 1);
  XtSetValues(plotter3, args, 1);
}

void grid_callback()
{
  Arg args[2];
  Boolean f;

  XtVaGetValues(xaxis1, XtNdrawGrid, &f, NULL);
  f = f ? False : True;
  XtSetArg(args[0], XtNdrawGrid, f);
  XtSetValues(xaxis1, args, 1);
  XtSetValues(yaxis1, args, 1);
  XtSetValues(xaxis2, args, 1);
  XtSetValues(yaxis2, args, 1);
  XtSetValues(xaxis3, args, 1);
  XtSetValues(yaxis3, args, 1);
}

void subgrid_callback()
{
  Arg args[2];
  Boolean f;

  XtVaGetValues(xaxis1, XtNdrawSubgrid, &f, NULL);
  f = f ? False : True;
  XtSetArg(args[0], XtNdrawSubgrid, f);
  XtSetValues(xaxis1, args, 1);
  XtSetValues(yaxis1, args, 1);
  XtSetValues(xaxis2, args, 1);
  XtSetValues(yaxis2, args, 1);
  XtSetValues(xaxis3, args, 1);
  XtSetValues(yaxis3, args, 1);
}

void origin_callback()
{
  Arg args[2];
  Boolean f;

  XtVaGetValues(xaxis1, XtNdrawOrigin, &f, NULL);
  f = f ? False : True;
  XtSetArg(args[0], XtNdrawOrigin, f);
  XtSetValues(xaxis1, args, 1);
  XtSetValues(yaxis1, args, 1);
  XtSetValues(xaxis2, args, 1);
  XtSetValues(yaxis2, args, 1);
  XtSetValues(xaxis3, args, 1);
  XtSetValues(yaxis3, args, 1);
}

void frame_callback()
{
  Arg args[2];
  Boolean f;

  XtVaGetValues(xaxis1, XtNdrawFrame, &f, NULL);
  f = f ? False : True;
  XtSetArg(args[0], XtNdrawFrame, f);
  XtSetValues(xaxis1, args, 1);
  XtSetValues(yaxis1, args, 1);
  XtSetValues(xaxis2, args, 1);
  XtSetValues(yaxis2, args, 1);
  XtSetValues(xaxis3, args, 1);
  XtSetValues(yaxis3, args, 1);
}

void align_callback()
{
  align_axes = align_axes ? False : True;
  printf("Axis alignment required: %s\n", align_axes ? "YES" : "NO");
}

/*
 *      Align Y axes
 */

void layout_callback(w, cd, pp)
  Widget w;
  XtPointer cd;
  AtAxisPositions *pp;
{
  AtAxisPositions ap1, ap2;
  AtPlotterWidget pw1, pw2;
  Dimension y, y2;
  int who = (int) cd;

  printf("Layout required from plotter%d. Do alignment: %s\n", who,
	 align_axes ? "YES" : "NO");
  if( !align_axes)
    return;
  switch(who) {
    case 1:
      pw1 = (AtPlotterWidget) plotter3;
      pw2 = (AtPlotterWidget) plotter3;
      break;
    case 2:
      pw1 = (AtPlotterWidget) plotter1;
      pw2 = (AtPlotterWidget) plotter3;
      break;
    case 3:
      pw1 = (AtPlotterWidget) plotter1;
      pw2 = (AtPlotterWidget) plotter2;
      break;
    default:
      printf("Error in layout_callback\n");
      return;
  }
  AtPlotterGetAxisPositions(pw1, &ap1);
  AtPlotterGetAxisPositions(pw2, &ap2);
  y  = Max(pp->yaxis, ap1.yaxis);
  y  = Max(y, ap2.yaxis);
  y2 = Min(pp->y2axis, ap1.y2axis);
  y2 = Min(y2, ap2.y2axis);
  pp->position = AtPositionYAXES;
  pp->yaxis  = y;
  pp->y2axis = y2;
  printf("Align yxis -> %d y2axis -> %d\n", pp->yaxis, pp->y2axis);
  AtPlotterSetAxisPositions(pw1, pp);
  AtPlotterSetAxisPositions(pw2, pp);
  printf("Alignment done.\n");
}

/*
 *      Create forms and menu buttons
 */

void MakeForm(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);

  legendbutton = XtVaCreateManagedWidget("legend", commandWidgetClass, form,
					 XtNlabel, "Legend",
					 XtNfromHoriz, printbutton,
					 NULL);
  XtAddCallback(legendbutton, XtNcallback, legend_callback, NULL);

  gridbutton = XtVaCreateManagedWidget("grid", commandWidgetClass, form,
				       XtNlabel, "Grid",
				       XtNfromHoriz, legendbutton,
				       NULL);
  XtAddCallback(gridbutton, XtNcallback, grid_callback, NULL);

  subgridbutton = XtVaCreateManagedWidget("subgrid", commandWidgetClass, form,
					  XtNlabel, "Subgrid",
					  XtNfromHoriz, gridbutton,
					  NULL);
  XtAddCallback(subgridbutton, XtNcallback, subgrid_callback, NULL);

  originbutton = XtVaCreateManagedWidget("origin", commandWidgetClass, form,
					 XtNlabel, "Origin",
					 XtNfromHoriz, subgridbutton,
					 NULL);
  XtAddCallback(originbutton, XtNcallback, origin_callback, NULL);

  framebutton = XtVaCreateManagedWidget("frame", commandWidgetClass, form,
					XtNlabel, "Frame",
					XtNfromHoriz, originbutton,
					NULL);
  XtAddCallback(framebutton, XtNcallback, frame_callback, NULL);

  alignbutton = XtVaCreateManagedWidget("align", commandWidgetClass, form,
					XtNlabel, "Align",
					XtNfromHoriz, framebutton,
					NULL);
  XtAddCallback(alignbutton, XtNcallback, align_callback, NULL);
}

/*
 *      Main
 */

main(argc, argv)
  int argc;
  char **argv;
{
  Widget appShell;
  XtAppContext app;

  appShell = XtAppInitialize(&app, "PlotTest", NULL, 0, &argc, argv, NULL, NULL, 0);

  MakeForm(appShell);

  MakePlotter(form);
  XtVaSetValues(plotter1, XtNleft, XtChainLeft, XtNfromVert, quitbutton, NULL);
  XtVaSetValues(plotter2, XtNleft, XtChainLeft, XtNfromVert, plotter1, NULL);
  XtVaSetValues(plotter3, XtNleft, XtChainLeft, XtNfromVert, plotter2, NULL);

  MakeData();
  AttachData();

  XtRealizeWidget(appShell);
  XtAppMainLoop(app);

  exit(0);
}
