/*
 *      Zoom.c
 *
 *      Plotter demo program using motif
 *      klin, Sat Aug 15 16:08:37 1992
 */

#include <stdio.h>
#include <math.h>

#include <Xm/XmP.h>
#include <X11/Shell.h>
#include <Xm/ArrowB.h>
#include <Xm/Form.h>
#include <Xm/Frame.h>
#include <Xm/PushB.h>
#include <Xm/RowColumn.h>
#include <Xm/Label.h>
#include <Xm/Text.h>
#include <Xm/ScrollBar.h>
#include <Xm/Separator.h>

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

#ifndef XtPointer
# define XtPointer caddr_t
#endif

#define WIDTH  580                      /* Plotter width */
#define HEIGHT 400                      /* Plotter height */
#define MARGIN 6                        /* Plotter margin */

extern Widget mainwindow;
extern Widget plotter;                  /* The main plotter */
extern Widget xaxis, yaxis;             /* The main plotter axes */
extern Widget zplotter;                 /* The zoom plotter */
extern Widget zxaxis, zyaxis;           /* The zoom plotter axes */
extern Widget zline1, zline2, zline3;   /* The demo lines */
extern Widget zline3, zline4, zline5;   /* The user lines */
extern Widget slide_label;
extern Widget dialog;

static void form_callback();
static void quit_callback();
static void print_callback();
static void motion_callback();
static void layout_callback();
static void map_callback();
static void slide_callback();

int zoom_dialog_IsPoppedUp = False;

Widget zoom_dialog = NULL;

static Widget zoomxpos_text = NULL;
static Widget zoomypos_text = NULL;
static Widget zoomxmin_text = NULL;
static Widget zoomxmax_text = NULL;
static Widget zoomymin_text = NULL;
static Widget zoomymax_text = NULL;

/*
 *      Create the zoom dialog and zoom plotter
 */

void MakeZoomDialogAndPlotter()
{
  Arg args[12];
  Cardinal n;
  XmString xms[1];

  Widget zoom_form = NULL;
  Widget zoom_frame = NULL;
  Widget menu_form = NULL;
  Widget menu_frame = NULL;
  Widget zoom_menu = NULL;
  Widget zoomquit_button = NULL;
  Widget zoomprint_button = NULL;
  Widget pseparator = NULL;
  Widget rseparator = NULL;
  Widget zoomxpos_label = NULL;
  Widget zoomypos_label = NULL;
  Widget zoomxrange_label = NULL;
  Widget zoomyrange_label = NULL;

  /* Create zoom dialog */
  n = 0;
  XtSetArg(args[n], XmNunitType, XmPIXELS); n++;
  XtSetArg(args[n], XmNx, (Position) 300); n++;
  XtSetArg(args[n], XmNy, (Position) 300); n++;
  XtSetArg(args[n], XmNdefaultPosition, False); n++;
  XtSetArg(args[n], XmNautoUnmanage, False); n++;
  xms[0] = (XmString) XmStringCreateLtoR("Plotter Demo Zoom Window", XmSTRING_DEFAULT_CHARSET);
  XtSetArg(args[n], XmNdialogTitle, xms[0]); n++;
  zoom_dialog = XmCreateFormDialog(mainwindow, "dialog", args, n);
  XtAddCallback(zoom_dialog, XmNmapCallback, map_callback, NULL);
  XmStringFree(xms[0]);

  /* Create zoom form */
  n = 0;
  XtSetArg(args[n], XmNresizePolicy, XmRESIZE_NONE); n++;
  zoom_form = XmCreateForm(zoom_dialog, "plotter_form", args, n);
  XtAddEventHandler(zoom_form, LeaveWindowMask, False, form_callback, (XtPointer) NULL);
  XtManageChild(zoom_form);

  /* Create zoom frame */
  n = 0;
  XtSetArg(args[n], XmNshadowType, XmSHADOW_OUT); n++;
  XtSetArg(args[n], XmNshadowThickness, (Dimension) 4); n++;
  zoom_frame = XmCreateFrame(zoom_form, "plotter_frame", args, n);
  XtManageChild(zoom_frame);

  n = 0;
  XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
  XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
  XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  XtSetValues(zoom_frame, args, n);

  /* Create zoom menu */
  n = 0;
  XtSetArg(args[n], XmNresizePolicy, XmRESIZE_NONE); n++;
  menu_form = XmCreateForm(zoom_dialog, "menu_form", args, n);
  XtManageChild(menu_form);

  n = 0;
  XtSetArg(args[n], XmNshadowType, XmSHADOW_OUT); n++;
  XtSetArg(args[n], XmNshadowThickness, (Dimension) 4); n++;
  menu_frame = XmCreateFrame(menu_form, "menu_frame", args, n);
  XtManageChild(menu_frame);
  n = 0;
  XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
  XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
  XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  XtSetValues(menu_frame, args, n);

  n = 0;
  XtSetArg(args[n], XmNorientation, XmVERTICAL); n++;
  XtSetArg(args[n], XmNentryAlignment, XmALIGNMENT_CENTER); n++;
  zoom_menu = XmCreateRowColumn(menu_frame, "zoom_menubar", args, n);
  XtManageChild(zoom_menu);

  n = 0;
  xms[0] = (XmString) XmStringCreateLtoR("Quit", XmSTRING_DEFAULT_CHARSET);
  XtSetArg(args[n], XmNlabelString, xms[0]); n++;
  zoomquit_button = XmCreatePushButton(zoom_menu, "button", args, n);
  XtAddCallback(zoomquit_button, XmNactivateCallback, quit_callback, (XtPointer) NULL);
  XtManageChild(zoomquit_button);
  XmStringFree(xms[0]);

  n = 0;
  xms[0] = (XmString) XmStringCreateLtoR("Print", XmSTRING_DEFAULT_CHARSET);
  XtSetArg(args[n], XmNlabelString, xms[0]); n++;
  zoomprint_button = XmCreatePushButton(zoom_menu, "button", args, n);
  XtAddCallback(zoomprint_button, XmNactivateCallback, print_callback, (XtPointer) NULL);
  XtManageChild(zoomprint_button);
  XmStringFree(xms[0]);

  n = 0;
  XtSetArg(args[n], XmNseparatorType, XmSHADOW_ETCHED_OUT); n++;
  XtSetArg(args[n], XmNorientation, XmHORIZONTAL); n++;
  pseparator = XmCreateSeparator(zoom_menu, "separator", args, n);
  XtManageChild(pseparator);

  n = 0;
  xms[0] = (XmString) XmStringCreateLtoR("X Position", XmSTRING_DEFAULT_CHARSET);
  XtSetArg(args[n], XmNlabelString, xms[0]); n++;
  zoomxpos_label = XmCreateLabel(zoom_menu, "label", args, n);
  XtManageChild(zoomxpos_label);
  XmStringFree(xms[0]);

  n = 0;
  XtSetArg(args[n], XmNhighlightThickness, (Dimension) 0); n++;
  XtSetArg(args[n], XmNautoShowCursorPosition, False); n++;
  XtSetArg(args[n], XmNeditable, False); n++;
  XtSetArg(args[n], XmNpendingDelete, False); n++;
  XtSetArg(args[n], XmNcursorPositionVisible, False); n++;
  XtSetArg(args[n], XmNverifyBell, False); n++;
  XtSetArg(args[n], XmNcolumns, 10); n++;
  XtSetArg(args[n], XmNsensitive, False); n++;
  zoomxpos_text = XmCreateText(zoom_menu, "text", args, n);
  XtManageChild(zoomxpos_text);

  n = 0;
  xms[0] = (XmString) XmStringCreateLtoR("Y Position", XmSTRING_DEFAULT_CHARSET);
  XtSetArg(args[n], XmNlabelString, xms[0]); n++;
  zoomypos_label = XmCreateLabel(zoom_menu, "label", args, n);
  XtManageChild(zoomypos_label);
  XmStringFree(xms[0]);

  n = 0;
  XtSetArg(args[n], XmNhighlightThickness, (Dimension) 0); n++;
  XtSetArg(args[n], XmNautoShowCursorPosition, False); n++;
  XtSetArg(args[n], XmNeditable, False); n++;
  XtSetArg(args[n], XmNpendingDelete, False); n++;
  XtSetArg(args[n], XmNcursorPositionVisible, False); n++;
  XtSetArg(args[n], XmNverifyBell, False); n++;
  XtSetArg(args[n], XmNcolumns, 10); n++;
  XtSetArg(args[n], XmNsensitive, False); n++;
  zoomypos_text = XmCreateText(zoom_menu, "text", args, n);
  XtManageChild(zoomypos_text);

  n = 0;
  XtSetArg(args[n], XmNseparatorType, XmSHADOW_ETCHED_OUT); n++;
  XtSetArg(args[n], XmNorientation, XmHORIZONTAL); n++;
  rseparator = XmCreateSeparator(zoom_menu, "separator", args, n);
  XtManageChild(rseparator);

  n = 0;
  xms[0] = (XmString) XmStringCreateLtoR("X Range", XmSTRING_DEFAULT_CHARSET);
  XtSetArg(args[n], XmNlabelString, xms[0]); n++;
  zoomxrange_label = XmCreateLabel(zoom_menu, "label", args, n);
  XtManageChild(zoomxrange_label);
  XmStringFree(xms[0]);

  n = 0;
  XtSetArg(args[n], XmNhighlightThickness, (Dimension) 0); n++;
  XtSetArg(args[n], XmNautoShowCursorPosition, False); n++;
  XtSetArg(args[n], XmNeditable, False); n++;
  XtSetArg(args[n], XmNpendingDelete, False); n++;
  XtSetArg(args[n], XmNcursorPositionVisible, False); n++;
  XtSetArg(args[n], XmNverifyBell, False); n++;
  XtSetArg(args[n], XmNcolumns, 10); n++;
  XtSetArg(args[n], XmNsensitive, False); n++;
  zoomxmin_text = XmCreateText(zoom_menu, "text", args, n);
  XtManageChild(zoomxmin_text);

  n = 0;
  XtSetArg(args[n], XmNhighlightThickness, (Dimension) 0); n++;
  XtSetArg(args[n], XmNautoShowCursorPosition, False); n++;
  XtSetArg(args[n], XmNeditable, False); n++;
  XtSetArg(args[n], XmNpendingDelete, False); n++;
  XtSetArg(args[n], XmNcursorPositionVisible, False); n++;
  XtSetArg(args[n], XmNverifyBell, False); n++;
  XtSetArg(args[n], XmNcolumns, 10); n++;
  XtSetArg(args[n], XmNsensitive, False); n++;
  zoomxmax_text = XmCreateText(zoom_menu, "text", args, n);
  XtManageChild(zoomxmax_text);

  n = 0;
  xms[0] = (XmString) XmStringCreateLtoR("Y Range", XmSTRING_DEFAULT_CHARSET);
  XtSetArg(args[n], XmNlabelString, xms[0]); n++;
  zoomxrange_label = XmCreateLabel(zoom_menu, "label", args, n);
  XtManageChild(zoomxrange_label);
  XmStringFree(xms[0]);

  n = 0;
  XtSetArg(args[n], XmNhighlightThickness, (Dimension) 0); n++;
  XtSetArg(args[n], XmNautoShowCursorPosition, False); n++;
  XtSetArg(args[n], XmNeditable, False); n++;
  XtSetArg(args[n], XmNpendingDelete, False); n++;
  XtSetArg(args[n], XmNcursorPositionVisible, False); n++;
  XtSetArg(args[n], XmNverifyBell, False); n++;
  XtSetArg(args[n], XmNcolumns, 10); n++;
  XtSetArg(args[n], XmNsensitive, False); n++;
  zoomymin_text = XmCreateText(zoom_menu, "text", args, n);
  XtManageChild(zoomymin_text);

  n = 0;
  XtSetArg(args[n], XmNhighlightThickness, (Dimension) 0); n++;
  XtSetArg(args[n], XmNautoShowCursorPosition, False); n++;
  XtSetArg(args[n], XmNeditable, False); n++;
  XtSetArg(args[n], XmNpendingDelete, False); n++;
  XtSetArg(args[n], XmNcursorPositionVisible, False); n++;
  XtSetArg(args[n], XmNverifyBell, False); n++;
  XtSetArg(args[n], XmNcolumns, 10); n++;
  XtSetArg(args[n], XmNsensitive, False); n++;
  zoomymax_text = XmCreateText(zoom_menu, "text", args, n);
  XtManageChild(zoomymax_text);

  /* Do the form attachments */

  n = 0;
  XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
  XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
  XtSetArg(args[n], XmNleftWidget, menu_form); n++;
  XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); n++;
  XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  XtSetValues(zoom_form, args, n);

  n = 0;
  XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
  XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
  XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  XtSetArg(args[n], XmNrightAttachment, XmATTACH_NONE); n++;
  XtSetValues(menu_form, args, n);

  /* Create the zoom plotter */
  n = 0;
  XtSetArg(args[n], XtNwidth, WIDTH); n++;
  XtSetArg(args[n], XtNheight, HEIGHT); n++;
  XtSetArg(args[n], XtNborderWidth, 0); n++;
  XtSetArg(args[n], XtNmarginWidth, MARGIN); n++;
  XtSetArg(args[n], XtNmarginHeight, MARGIN); n++;
  XtSetArg(args[n], XtNtitle, "Plotter Demo Zoom"); n++;
  XtSetArg(args[n], XtNshowTitle, False); n++;
  XtSetArg(args[n], XtNshowLegend, False); n++;
  XtSetArg(args[n], XtNusePixmap, True); n++;
  zplotter = XtCreateManagedWidget("plotter", atPlotterWidgetClass, zoom_frame, args, n);
  XtAddCallback(zplotter, XtNmotionCallback, motion_callback, NULL);
  XtAddCallback(zplotter, XtNlayoutCallback, layout_callback, NULL);

  /* Create the X axis */
  n = 0;
  XtSetArg(args[n], XtNaxisWidth, 1); n++;
  XtSetArg(args[n], XtNticsInside, True); n++;
  XtSetArg(args[n], XtNticsOutside, False); n++;
  XtSetArg(args[n], XtNdrawNumbers, False); n++;
  XtSetArg(args[n], XtNdrawGrid, True); n++;
  XtSetArg(args[n], XtNdrawSubgrid, True); n++;
  zxaxis = XtCreateWidget("axis", atXYAxisWidgetClass, zplotter, args, n);

  /* Create the Y axis */
  n = 0;
  XtSetArg(args[n], XtNvertical, True); n++;
  XtSetArg(args[n], XtNaxisWidth, 1); n++;
  XtSetArg(args[n], XtNticsInside, True); n++;
  XtSetArg(args[n], XtNticsOutside, False); n++;
  XtSetArg(args[n], XtNdrawNumbers, False); n++;
  XtSetArg(args[n], XtNdrawGrid, True); n++;
  XtSetArg(args[n], XtNdrawSubgrid, True); n++;
  zyaxis = XtCreateWidget("axis", atXYAxisWidgetClass, zplotter, args, n);

  /* Attach the axes */
  n = 0;
  XtSetArg(args[n], XtNxAxis, zxaxis); n++;
  XtSetArg(args[n], XtNyAxis, zyaxis); n++;
  XtSetValues(zplotter, args, n);

  zoom_dialog_IsPoppedUp = False;
}

/*
 *      Popup/popdown the zoom dialog
 */

void Popup_zoom(x1, x2, y1, y2)
  double x1, x2, y1, y2;
{
  double tic;
  int w;

  if( !XtIsManaged(zoom_dialog)) {
    XtManageChild(zoom_dialog);
    XtVaSetValues(XtParent(zoom_dialog), XmNshellUnitType, XmPIXELS,
					 XmNminWidth, 600,
					 XmNminHeight, 360,
					 NULL);
    XtAddCallback(plotter, XtNslideCallback, slide_callback, NULL);
  }
  XtVaGetValues(xaxis, XtNticInterval, &tic, NULL);
  XtVaSetValues(zxaxis, XtNticInterval, &tic,
			XtNautoTics, False,
			XtNroundEndpoints, False,
			NULL);
  XtVaGetValues(yaxis, XtNticInterval, &tic, NULL);
  XtVaSetValues(zyaxis, XtNticInterval, &tic,
			XtNautoTics, False,
			XtNroundEndpoints, False,
			NULL);
  XtSetSensitive(slide_label, True);
  zoom_dialog_IsPoppedUp = True;
}

void Popdown_zoom()
{
  if(zoom_dialog_IsPoppedUp || (zoom_dialog && XtIsManaged(zoom_dialog))) {
    XtUnmanageChild(zoom_dialog);
    zoom_dialog_IsPoppedUp = False;
    XtRemoveAllCallbacks(plotter, XtNslideCallback);
  }
  XtSetSensitive(slide_label, False);
}

/*
 *      The zoom dialog callbacks
 */

static void form_callback(widget, client_data, event, continue_to_dispatch)
  Widget widget;
  XtPointer client_data;
  XEvent *event;
  Boolean *continue_to_dispatch;
{
  Boolean enter = (Boolean) client_data;

  XtVaSetValues(zoomxpos_text, XmNvalue, "", NULL);
  XtVaSetValues(zoomypos_text, XmNvalue, "", NULL);
}

static void quit_callback()
{
  Popdown_zoom();
}

static char *printfile = NULL;
static void cprint_callback();

static void pprint_callback(widget, client_data, call_data)
  Widget widget;
  XtPointer client_data;
  XmSelectionBoxCallbackStruct *call_data;
{
  char msg[256];

  XtRemoveCallback(dialog, XmNokCallback, pprint_callback, NULL);
  XtRemoveCallback(dialog, XmNcancelCallback, cprint_callback, NULL);
  XmStringGetLtoR(call_data->value, XmSTRING_DEFAULT_CHARSET, &printfile);
  if(printfile && *printfile) {
    XtVaSetValues(zplotter, XtNautoRedisplay, False,
			    XtNshowTitle, True,
			    XtNshowLegend, True,
			    NULL);
    XtVaSetValues(zxaxis, XtNdrawNumbers, True, NULL);
    XtVaSetValues(zyaxis, XtNdrawNumbers, True, NULL);
    AtPlotterGeneratePostscript(printfile, (AtPlotterWidget) zplotter,
				"Sample Zoom Plot", 50, 50, 480, 320, False);
    XtVaSetValues(zxaxis, XtNdrawNumbers, False, NULL);
    XtVaSetValues(zyaxis, XtNdrawNumbers, False, NULL);
    XtVaSetValues(zplotter, XtNautoRedisplay, True,
			    XtNshowTitle, False,
			    XtNshowLegend, False,
			    NULL);
    XtFree(printfile);
    printfile = NULL;
  }
}

static void cprint_callback()
{
  XtRemoveCallback(dialog, XmNokCallback, pprint_callback, NULL);
  XtRemoveCallback(dialog, XmNcancelCallback, cprint_callback, NULL);
  printfile = NULL;
}

static void print_callback()
{
  Popup_dialog(pprint_callback, cprint_callback, "Plot Demo Zoom PS Print", "*.ps");
}

static void motion_callback(widget, client_data, call_data)
  Widget widget;
  XtPointer client_data;
  AtPointCallbackData *call_data;
{
  char xstr[64], ystr[64];

  sprintf(xstr, "%.4lf", call_data->x1);
  sprintf(ystr, "%.4lf", call_data->y1);
  XtVaSetValues(zoomxpos_text, XmNvalue, xstr, NULL);
  XtVaSetValues(zoomypos_text, XmNvalue, ystr, NULL);
}

static void map_callback(widget, client_data, call_data)
  Widget widget;
  XtPointer client_data;
  XmAnyCallbackStruct *call_data;
{
  int x, y;

  GetPointerPosition(&x, &y);
  XtVaSetValues(zoom_dialog, XmNx, x, XmNy, y, NULL);
}

static void layout_callback()
{
  char minstr[64], maxstr[64];
  double min, max;

  XtVaGetValues(zxaxis, XtNmin, &min, XtNmax, &max, NULL);
  sprintf(minstr, "%.4lf", min);
  sprintf(maxstr, "%.4lf", max);
  XtVaSetValues(zoomxmin_text, XmNvalue, minstr, NULL);
  XtVaSetValues(zoomxmax_text, XmNvalue, maxstr, NULL);
  XtVaGetValues(zyaxis, XtNmin, &min, XtNmax, &max, NULL);
  sprintf(minstr, "%.4lf", min);
  sprintf(maxstr, "%.4lf", max);
  XtVaSetValues(zoomymin_text, XmNvalue, minstr, NULL);
  XtVaSetValues(zoomymax_text, XmNvalue, maxstr, NULL);
}

static void slide_callback(widget, client_data, call_data)
  Widget widget;
  XtPointer client_data;
  AtRectangleCallbackData *call_data;
{
  double min, max;

  min = call_data->x11;
  max = call_data->x12;
  XtVaSetValues(zxaxis, XtNmin, &min, XtNmax, &max, NULL);
  min = call_data->y11;
  max = call_data->y12;
  XtVaSetValues(zyaxis, XtNmin, &min, XtNmax, &max, NULL);
}
