/*
 *      aplot.c
 *      Test 1: plotter using the athena widget set
 *
 *      Test plotting 3 lines within 1 plotter
 *
 *      klin, Mon Jun 29 19:35:25 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/Xaw/Paned.h>

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

/*
 *      The plotter widgets
 */

static Widget plotter, xaxis, yaxis;
static Widget line1, line2, line3;

/*
 *      Create the plotter, the axes and the lines
 */

void select_callback(widget, client_data, call_data)
  Widget widget;
  XtPointer client_data;
  AtSelectCallbackData *call_data;
{
  char *r, *w;

  if(call_data->reason == AtSelectSELECTED) {
    r = "SELECTED";
    w = XtName(call_data->widget);
  }
  else {
    r = "DESELECTED";
    w = "-----";
  }
  printf("Select callback: widget: %s, reason: %s\n", w, r);
}

void MakePlotter(parent)
  Widget parent;
{
  Arg args[16];
  double min, max, tic;
  int n;

  /* Create the plotter */
  n = 0;
  XtSetArg(args[n], XtNtitle, "Plotter Demo A"); n++;
  XtSetArg(args[n], XtNshowLegend, True); n++;
  XtSetArg(args[n], XtNwidth,  640); n++;
  XtSetArg(args[n], XtNheight, 480); n++;
  XtSetArg(args[n], XtNborderWidth, 0); n++;
  plotter = XtCreateManagedWidget("plotter", atPlotterWidgetClass,
				  parent, args, n);
  XtAddCallback(plotter, XtNselectCallback, select_callback, NULL);

  /* Create the x and y axes */
  n = 0;
  XtSetArg(args[n], XtNlabel, "Time"); n++;
  XtSetArg(args[n], XtNaxisWidth, 1); n++;
  XtSetArg(args[n], XtNticsInside, True); n++;
  XtSetArg(args[n], XtNticsOutside, False); n++;
  XtSetArg(args[n], XtNlinTicFormat, "%g"); n++;
  xaxis = XtCreateWidget("xaxis", atXYAxisWidgetClass, plotter, args, n);

  n = 0;
  XtSetArg(args[n], XtNticsInside, True); n++;
  XtSetArg(args[n], XtNticsOutside, False); n++;
  XtSetArg(args[n], XtNvertical, True); n++;
  XtSetArg(args[n], XtNlabel, "Amplitude"); n++;
  XtSetArg(args[n], XtNaxisWidth, 1); n++;
  XtSetArg(args[n], XtNlinTicFormat, "%g"); n++;
  yaxis = XtCreateWidget("yaxis", atXYAxisWidgetClass, plotter, args, n);

  /* Attach the axes */
  n = 0;
  XtSetArg(args[n], XtNxAxis, xaxis); n++;
  XtSetArg(args[n], XtNyAxis, yaxis); n++;
  XtSetValues(plotter, args, n);

  /* Create the lines */
  line1 = XtVaCreateWidget("line1", atXYLinePlotWidgetClass, plotter,
			   XtNlegendName, "sinus-points",
			   XtNplotLineType, AtPlotPOINTS,
			   XtNplotMarkType, AtMarkPLUS,
			   NULL);
  line2 = XtVaCreateWidget("line2", atXYLinePlotWidgetClass, plotter,
			   XtNlegendName, "cosinus-points",
			   XtNplotLineType,  AtPlotLINEIMPULSES,
			   XtNplotLineStyle, AtLineDASHED,
			   NULL);
  line3 = XtVaCreateWidget("line3", atXYLinePlotWidgetClass, plotter,
			   XtNlegendName, "polygon",
			   XtNplotLineType, AtPlotLINEPOINTS,
			   XtNplotLineStyle, AtLineDOTTED,
			   XtNplotMarkType,  AtMarkSTAR,
			   NULL);
}

/*
 *      The data
 */

struct point {
     double xval;
     double yval1;
     double yval2;
};

#define PNUM 6
#define NNUM 18

static AtDoublePoint poly[PNUM];
static struct point curve[NNUM];

/*
 *      Create the plot data
 */

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

  poly[0].x = 1.0; poly[0].y =  1.0;
  poly[1].x = 5.0; poly[1].y =  4.0;
  poly[2].x = 8.0; poly[2].y =  3.0;
  poly[3].x = 6.0; poly[3].y = -2.0;
  poly[4].x = 3.0; poly[4].y = -3.0;
  poly[5].x = 1.0; poly[5].y =  1.0;
  for(i = 0, x = 0.125; i < NNUM; i++, x += 0.275) {
    curve[i].xval  = x;
    curve[i].yval1 = 3.5  * sin(x);
    curve[i].yval2 = 2.67 * cos(x);
  }
}

/*
 *      Attach the data to the lines
 */

void AttachData()
{
  /* Attach data from own defined data type struct point */
  AtXYLinePlotAttachData(line1,
    (XtPointer)&curve[0].xval,  AtDouble, sizeof(struct point),
    (XtPointer)&curve[0].yval1, AtDouble, sizeof(struct point),
    1, NNUM);
  AtXYLinePlotAttachData(line2,
    (XtPointer)&curve[0].xval,  AtDouble, sizeof(struct point),
    (XtPointer)&curve[0].yval2, AtDouble, sizeof(struct point),
    1, NNUM);
  /* Attach data from predefined data type AtDoublePoint */
  AtXYLinePlotAttachDoublePoints(line3, &poly[0], 1, PNUM);
}


/*
 *      Other widgets
 */

static Widget form;
static Widget quitbutton, printbutton, legendbutton;
static Widget gridbutton, subgridbutton;
static Widget originbutton, framebutton;
static Widget motionbutton, dragbutton;
static Widget selectbutton;

/*
 *      The button callbacks
 */

#ifndef __STDC__
extern int exit();
#endif

void quit_callback()
{
  exit(0);
}

void print_callback()
{
  AtPlotterGeneratePostscript("aplot.ps", (AtPlotterWidget) plotter,
			      "aplot.ps", 50, 50, 520, 400, False);
  printf("Print callback: Plot dumped to aplot.ps\n");
}

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

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

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

  XtVaGetValues(xaxis, XtNdrawGrid, &f, NULL);
  f = f ? False : True;
  XtSetArg(args[0], XtNdrawGrid, f);
  XtSetValues(xaxis, args, 1);
  XtSetValues(yaxis, args, 1);
}

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

  XtVaGetValues(xaxis, XtNdrawSubgrid, &f, NULL);
  f = f ? False : True;
  XtSetArg(args[0], XtNdrawSubgrid, f);
  XtSetValues(xaxis, args, 1);
  XtSetValues(yaxis, args, 1);
}

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

  XtVaGetValues(xaxis, XtNdrawOrigin, &f, NULL);
  f = f ? False : True;
  XtSetArg(args[0], XtNdrawOrigin, f);
  XtSetValues(xaxis, args, 1);
  XtSetValues(yaxis, args, 1);
}

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

  XtVaGetValues(xaxis, XtNdrawFrame, &f, NULL);
  f = f ? False : True;
  XtSetArg(args[0], XtNdrawFrame, f);
  XtSetValues(xaxis, args, 1);
  XtSetValues(yaxis, args, 1);
}

void get_motion_callback(widget, client_data, call_data)
  Widget widget;
  XtPointer client_data;
  AtPointCallbackData *call_data;
{
  double x, y;

  x = call_data->x1;
  y = call_data->y1;
  printf("Get motion callback: x=%lf y=%lf\n", x, y);
}

void motion_callback()
{
  Arg args[2];
  static int t = 0;

  if(t) {
    XtRemoveAllCallbacks(plotter, XtNmotionCallback);
    printf("Motion callback: get motion 1 -> 0\n");
    t = 0;
  }
  else {
    XtAddCallback(plotter, XtNmotionCallback, get_motion_callback, NULL);
    printf("Motion callback: get motion 0 -> 1\n");
    t = 1;
  }
}

static double oldxmin, oldxmax, oldymin, oldymax;

void get_drag_callback(widget, client_data, call_data)
  Widget widget;
  XtPointer client_data;
  AtRectangleCallbackData *call_data;
{
  Arg args[4];
  static double x1, y1, x2, y2;
  AtTransform tx, ty;

  tx = AtAxisGetTransform(xaxis);
  ty = AtAxisGetTransform(yaxis);
  x1 = call_data->x11;
  x2 = call_data->x12;
  y1 = call_data->y11;
  y2 = call_data->y12;
  XtSetArg(args[0], XtNmin, &x1);
  XtSetArg(args[1], XtNmax, &x2);
  XtSetArg(args[2], XtNautoScale, False);
  XtSetValues(xaxis, args, 3);
  XtSetArg(args[0], XtNmin, &y1);
  XtSetArg(args[1], XtNmax, &y2);
  XtSetArg(args[2], XtNautoScale, False);
  XtSetValues(yaxis, args, 3);
  printf("Get drag callback: tx=%d x1=%lf x2=%lf ty=%d y1=%lf y2=%lf\n",
	  tx, x1, x2, ty, y1, y2);
}

void drag_callback()
{
  Arg args[4];
  int n;
  static int t = 0;

  if(t) {
    XtSetArg(args[0], XtNmin, &oldxmin);
    XtSetArg(args[1], XtNmax, &oldxmax);
    XtSetArg(args[2], XtNautoScale, True);
    XtSetValues(xaxis, args, 3);
    XtSetArg(args[0], XtNmin, &oldymin);
    XtSetArg(args[1], XtNmax, &oldymax);
    XtSetArg(args[2], XtNautoScale, True);
    XtSetValues(yaxis, args, 3);
    XtRemoveAllCallbacks(plotter, XtNdragCallback);
    printf("Drag callback: get drag 1 -> 0\n");
    t = 0;
  }
  else {
    XtVaGetValues(xaxis, XtNmin, &oldxmin, XtNmax, &oldxmax, NULL);
    XtVaGetValues(yaxis, XtNmin, &oldymin, XtNmax, &oldymax, NULL);
    XtAddCallback(plotter, XtNdragCallback, get_drag_callback, NULL);
    printf("Drag callback: get drag 0 -> 1\n");
    t = 1;
  }
}

/*
 *      Create form and 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);

  motionbutton = XtVaCreateManagedWidget("motion", commandWidgetClass, form,
					 XtNlabel, "Motion",
					 XtNfromHoriz, framebutton,
					 NULL);
  XtAddCallback(motionbutton, XtNcallback, motion_callback, NULL);

  dragbutton = XtVaCreateManagedWidget("drag", commandWidgetClass, form,
				       XtNlabel, "Drag",
				       XtNfromHoriz, motionbutton,
				       NULL);
  XtAddCallback(dragbutton, XtNcallback, drag_callback, NULL);
}

/*
 *      Main
 */

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

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

  MakeForm(appShell);

  MakePlotter(form);
  XtVaSetValues(plotter, XtNleft, XtChainLeft, XtNfromVert, quitbutton, NULL);

  MakeData();
  AttachData();

  XtRealizeWidget(appShell);
  XtAppMainLoop(app);

  exit(0);
}
