XEphem/GUI/xephem/plotmenu.c

1537 lines
45 KiB
C

/* code to manage the stuff on the "plot" menu.
*/
#include <stdio.h>
#include <ctype.h>
#include <math.h>
#include <stdlib.h>
#include <unistd.h>
#include <X11/Xlib.h>
#include <Xm/Xm.h>
#include <Xm/Form.h>
#include <Xm/Frame.h>
#include <Xm/DrawingA.h>
#include <Xm/FileSB.h>
#include <Xm/Label.h>
#include <Xm/CascadeB.h>
#include <Xm/PushB.h>
#include <Xm/ToggleB.h>
#include <Xm/RowColumn.h>
#include <Xm/Separator.h>
#include <Xm/TextF.h>
#include "xephem.h"
#include "lilxml.h"
static void plt_select (int whether);
static void plot_create_shell (void);
static void plt_active_cb (Widget w, XtPointer client, XtPointer call);
static void plt_select_cb (Widget w, XtPointer client, XtPointer call);
static void plt_show_cb (Widget w, XtPointer client, XtPointer call);
static void plt_savecfg_cb (Widget w, XtPointer client, XtPointer call);
static void plt_loadcfg_cb (Widget w, XtPointer client, XtPointer call);
static void plt_popdown_cb (Widget w, XtPointer client, XtPointer call);
static void plt_close_cb (Widget w, XtPointer client, XtPointer call);
static void plt_help_cb (Widget w, XtPointer client, XtPointer call);
static void plt_undo_cb (Widget w, XtPointer client, XtPointer call);
static void plt_reset (void);
static void plt_stop_selecting (void);
static void plt_turn_off (void);
static void set_x (char *name);
static void set_y (char *name);
static void add_field (char *name);
static void init_row (void);
static void plt_try_append (void);
static void plt_try_overwrite (void);
static void plt_try_cancel (void);
static void plt_try_turn_on (void);
static void plt_turn_on (char *how);
static void plt_da_manage (char *fn);
static void plt_da_destroy (Widget da_w);
static void plt_print (void);
static void plt_da_print_cb (Widget w, XtPointer client, XtPointer call);
static void plt_da_mloop_cb (Widget w, XtPointer client, XtPointer call);
static void plt_da_close_cb (Widget w, XtPointer client, XtPointer call);
static void plt_da_unmap_cb (Widget w, XtPointer client, XtPointer call);
static void plt_da_flipx_cb (Widget w, XtPointer client, XtPointer call);
static void plt_da_flipy_cb (Widget w, XtPointer client, XtPointer call);
static void plt_da_grid_cb (Widget w, XtPointer client, XtPointer call);
static void plt_da_xyr_asdate_cb (Widget w, XtPointer client, XtPointer call);
static void plt_da_xjd_asdate_cb (Widget w, XtPointer client, XtPointer call);
static void plt_da_exp_cb (Widget da_w, XtPointer client, XtPointer call);
static void plt_da_motion_eh (Widget da_w, XtPointer client, XEvent *ev, Boolean *continue_to_dispatch);
static void plt_drawall (Widget da_w);
static int plt_ano (double *sx, double *sy, int *xp, int *yp, int w2x,int arg);
#define MAXFLDNAM 32 /* longest allowed field name */
/* column indeces */
typedef enum {
T=0 /* tag label text field */,
X /* X label */,
Y /* Y label */,
FORM /* the form that holds the three above */,
NPC /* number of columns */
} PCols;
static Widget plotshell_w; /* main shell */
static Widget select_w; /* TB for selecting plot fields */
static Widget active_w; /* TB for building plot file */
static Widget prompt_w; /* what to do next label */
static Widget title_w; /* TF for user's plot title */
static Widget pfn_w; /* TF for new plot file name */
static Widget cfn_w; /* TF for new config file name */
static Widget undo_w; /* PB for undoing a field selection */
static int selecting_xy; /* one of X or Y */
static FILE *plt_fp; /* the plot file; == 0 means don't plot */
static Widget da_w_save; /* used to set up for a print action */
static char config_suffix[] = ".ptc"; /* file ext for plot config files */
static char plot_suffix[] = ".plt"; /* file ext for plot files */
static char plotcategory[] = "Tools -- Plot"; /* Save category */
static char xml_plotele[] = "XEphemPlotConfig";
/* store the name of each x and y line to track and their values.
* we get the tag straight from the Text widget in the table as needed.
*/
typedef struct {
char pl_xn[MAXFLDNAM]; /* name of x field, or 0 if none */
double pl_xv; /* last known value of x field */
char pl_yn[MAXFLDNAM]; /* name of y field, or 0 if none */
double pl_yv; /* last known value of x field */
Widget c_w[NPC]; /* column displays */
} PltLine;
static PltLine pltlines[MAXPLTLINES];
static int npltlines; /* number of completely defined plots */
/* called when the plot menu is activated via the main menu pulldown.
* if never called before, create and manage all the widgets as a child of a
* form. otherwise, just get going.
*/
void
plot_manage (void)
{
if (!plotshell_w)
plot_create_shell();
XtPopup (plotshell_w, XtGrabNone);
set_something (plotshell_w, XmNiconic, (XtArgVal)False);
}
/* called by the other menus (data, etc) as their buttons are
* selected to inform us that that button is to be included in a plot.
*/
void
plt_selection (name)
char *name;
{
if (!isUp(plotshell_w) || !XmToggleButtonGetState(select_w))
return;
add_field (name);
}
/* called as each different field is written -- just save in pltlines[]
* if we are interested in it.
* might have the same field listed more than once so can't stop if find one.
*/
void
plt_log (name, value)
char *name;
double value;
{
if (plt_fp) {
PltLine *plp;
for (plp = pltlines; plp < &pltlines[npltlines]; plp++) {
if (strcmp (name, plp->pl_xn) == 0)
plp->pl_xv = value;
if (strcmp (name, plp->pl_yn) == 0)
plp->pl_yv = value;
}
}
}
/* called when all fields have been updated and it's time to
* write the active plotfields to the current plot file, if one is open.
*/
void
plot (void)
{
if (plt_fp) {
/* plot in order of original selection */
PltLine *plp;
for (plp = pltlines; plp < &pltlines[npltlines]; plp++) {
char *lbl = XmTextFieldGetString(pltlines[plp-pltlines].c_w[T]);
(void) fprintf (plt_fp, "%s,%.12g,%.12g\n", lbl,
plp->pl_xv, plp->pl_yv);
XtFree (lbl);
}
}
}
int
plot_ison (void)
{
return (plt_fp != 0);
}
/* called to put up or remove the watch cursor. */
void
plt_cursor (c)
Cursor c;
{
Window win;
if (plotshell_w && (win = XtWindow(plotshell_w)) != 0) {
Display *dsp = XtDisplay(plotshell_w);
if (c)
XDefineCursor (dsp, win, c);
else
XUndefineCursor (dsp, win);
}
}
/* inform the other menues whether we are setting up for them to tell us
* what fields to plot.
*/
static void
plt_select(whether)
int whether;
{
all_selection_mode(whether);
}
static void
plot_create_shell (void)
{
XmString str;
Widget f_w, rc_w;
Widget pf_w, oms_w, omc_w;
Widget w, cfg_w;
Arg args[20];
char *s[1];
int i, n;
/* create the main dialog */
n = 0;
XtSetArg (args[n], XmNallowShellResize, True); n++;
XtSetArg (args[n], XmNcolormap, xe_cm); n++;
XtSetArg (args[n], XmNtitle, "xephem Plot Control"); n++;
XtSetArg (args[n], XmNiconName, "Plot"); n++;
XtSetArg (args[n], XmNdeleteResponse, XmUNMAP); n++;
plotshell_w = XtCreatePopupShell ("Plot", topLevelShellWidgetClass,
toplevel_w, args, n);
setup_icon (plotshell_w);
set_something (plotshell_w, XmNcolormap, (XtArgVal)xe_cm);
XtAddCallback (plotshell_w, XmNpopdownCallback, plt_popdown_cb, NULL);
sr_reg (plotshell_w, "XEphem*Plot.x", plotcategory, 0);
sr_reg (plotshell_w, "XEphem*Plot.y", plotcategory, 0);
n = 0;
XtSetArg (args[n], XmNmarginHeight, 10); n++;
XtSetArg (args[n], XmNmarginWidth, 10); n++;
XtSetArg (args[n], XmNverticalSpacing, 10); n++;
XtSetArg (args[n], XmNresizePolicy, XmRESIZE_ANY); n++;
pf_w = XmCreateForm (plotshell_w, "PlotF", args, n);
XtAddCallback (pf_w, XmNhelpCallback, plt_help_cb, 0);
XtManageChild (pf_w);
/* control to allow selecting an existing plot file to display */
s[0] = plot_suffix;
oms_w = createFSM (pf_w, s, 1, "auxil", plt_show_cb);
wtip (oms_w, "Select a plot configuration file to load");
set_xmstring (oms_w, XmNlabelString, "Show plot file: ");
n = 0;
XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
XtSetValues (oms_w, args, n);
/* control to allow selecting a config file to load */
s[0] = config_suffix;
omc_w = createFSM (pf_w, s, 1, "auxil", plt_loadcfg_cb);
set_xmstring (omc_w, XmNlabelString, "Load config file: ");
n = 0;
XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
XtSetArg (args[n], XmNtopWidget, oms_w); n++;
XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
XtSetValues (omc_w, args, n);
/* save config TB and its TF */
n = 0;
XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
XtSetArg (args[n], XmNtopWidget, omc_w); n++;
XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
cfg_w = XmCreateToggleButton(pf_w, "PSTB", args, n);
XtAddCallback(cfg_w, XmNvalueChangedCallback, plt_savecfg_cb, NULL);
set_xmstring (cfg_w, XmNlabelString, "Save config file: ");
wtip (cfg_w, "Save current plot definition to file");
XtManageChild (cfg_w);
n = 0;
XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
XtSetArg (args[n], XmNtopWidget, omc_w); n++;
XtSetArg (args[n], XmNleftAttachment, XmATTACH_WIDGET); n++;
XtSetArg (args[n], XmNleftWidget, cfg_w); n++;
XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
cfn_w = XmCreateTextField (pf_w, "ConfigFile", args, n);
defaultTextFN (cfn_w, 0, "myconfig.ptc", NULL);
wtip (cfn_w,
"Enter name of file in which to save current plot definition");
XtManageChild (cfn_w);
sr_reg (cfn_w, NULL, plotcategory, 0);
/* field Select PB */
n = 0;
XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
XtSetArg (args[n], XmNtopWidget, cfn_w); n++;
XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
select_w = XmCreateToggleButton(pf_w, "PSTB", args, n);
XtAddCallback(select_w, XmNvalueChangedCallback, plt_select_cb, NULL);
set_xmstring (select_w, XmNlabelString, "Select fields to plot");
wtip (select_w, "Build plot functions from selectable buttons");
XtManageChild (select_w);
/* create plot TB and its TF */
n = 0;
XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
XtSetArg (args[n], XmNtopWidget, select_w); n++;
XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
active_w = XmCreateToggleButton(pf_w, "PCTB", args, n);
XtAddCallback(active_w, XmNvalueChangedCallback, plt_active_cb, NULL);
set_xmstring (active_w, XmNlabelString, "Create plot file: ");
wtip (active_w,
"Selected fields are written to the named file at each Update");
XtManageChild (active_w);
n = 0;
XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
XtSetArg (args[n], XmNtopWidget, select_w); n++;
XtSetArg (args[n], XmNleftAttachment, XmATTACH_WIDGET); n++;
XtSetArg (args[n], XmNleftWidget, active_w); n++;
XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
pfn_w = XmCreateTextField (pf_w, "PlotFile", args, n);
defaultTextFN (pfn_w, 0, "myplot.plt", NULL);
wtip (pfn_w, "Enter name of plot file to create");
XtManageChild (pfn_w);
sr_reg (pfn_w, NULL, plotcategory, 0);
/* make a RowColumn to everything else */
n = 0;
XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
XtSetArg (args[n], XmNtopWidget, pfn_w); n++;
XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
XtSetArg (args[n], XmNspacing, 6); n++;
XtSetArg (args[n], XmNisAligned, False); n++;
XtSetArg (args[n], XmNadjustMargin, False); n++;
rc_w = XmCreateRowColumn(pf_w, "PlotRC", args, n);
XtManageChild (rc_w);
/* create title text area and its label */
n = 0;
str = XmStringCreate("Title:", XmSTRING_DEFAULT_CHARSET);
XtSetArg (args[n], XmNalignment, XmALIGNMENT_BEGINNING); n++;
XtSetArg (args[n], XmNlabelString, str); n++;
w = XmCreateLabel (rc_w, "PlotTL", args, n);
XtManageChild (w);
XmStringFree (str);
n = 0;
XtSetArg (args[n], XmNcolumns, 40); n++;
title_w = XmCreateTextField (rc_w, "PlotTitle", args, n);
wtip (title_w, "Enter a title to be written to the file");
XtManageChild (title_w);
/* create prompt line -- it will be managed as necessary */
n = 0;
XtSetArg (args[n], XmNalignment, XmALIGNMENT_BEGINNING); n++;
prompt_w = XmCreateLabel (rc_w, "PlotPrompt", args, n);
/* create the table.
* each row is in a form to control its shape.
* loop index of -1 is used to make the column headings.
* the table entries are all managed but the forms are not at this time.
*/
for (i = -1; i < MAXPLTLINES; i++) {
n = 0;
f_w = XmCreateForm (rc_w, "PlotTF", args, n);
/* save the form unless we are just making the column headings */
if (i == -1)
XtManageChild (f_w);
else
pltlines[i].c_w[FORM] = f_w;
n = 0;
XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
XtSetArg (args[n], XmNleftPosition, 0); n++;
XtSetArg (args[n], XmNrightAttachment, XmATTACH_POSITION); n++;
XtSetArg (args[n], XmNrightPosition, 20); n++;
if (i == -1) {
XtSetArg (args[n], XmNalignment, XmALIGNMENT_BEGINNING); n++;
w = XmCreateLabel (f_w, "Tag", args, n);
wtip (w, "Column of tags for each X/Y pair to plot");
XtManageChild (w);
} else {
XtSetArg (args[n], XmNmaxLength, MAXTAG); n++;
XtSetArg (args[n], XmNcolumns, MAXTAG); n++;
pltlines[i].c_w[T] = XmCreateTextField (f_w, "PlotTag", args,n);
XtManageChild (pltlines[i].c_w[T]);
}
n = 0;
XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
XtSetArg (args[n], XmNleftPosition, 30); n++;
XtSetArg (args[n], XmNrightAttachment, XmATTACH_POSITION); n++;
XtSetArg (args[n], XmNrightPosition, 65); n++;
XtSetArg (args[n], XmNalignment, XmALIGNMENT_BEGINNING); n++;
if (i == -1) {
w = XmCreateLabel (f_w, "_X_", args, n);
wtip (w, "Column of X fields for each X/Y pair to plot");
XtManageChild (w);
} else {
pltlines[i].c_w[X] = XmCreateLabel (f_w, "PlotX", args, n);
XtManageChild (pltlines[i].c_w[X]);
}
n = 0;
XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
XtSetArg (args[n], XmNleftPosition, 65); n++;
XtSetArg (args[n], XmNrightAttachment, XmATTACH_POSITION); n++;
XtSetArg (args[n], XmNrightPosition, 100); n++;
XtSetArg (args[n], XmNalignment, XmALIGNMENT_BEGINNING); n++;
if (i == -1) {
w = XmCreateLabel (f_w, "_Y_", args, n);
wtip (w, "Column of Y fields for each X/Y pair to plot");
XtManageChild (w);
} else {
pltlines[i].c_w[Y] = XmCreateLabel (f_w, "PlotY", args, n);
XtManageChild (pltlines[i].c_w[Y]);
}
}
/* create a separator */
n = 0;
w = XmCreateSeparator (rc_w, "Sep", args, n);
XtManageChild (w);
/* make a form to hold the close and help buttons evenly */
n = 0;
XtSetArg (args[n], XmNfractionBase, 10); n++;
f_w = XmCreateForm (rc_w, "PlotCF", args, n);
XtManageChild(f_w);
n = 0;
XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
XtSetArg (args[n], XmNleftPosition, 1); n++;
XtSetArg (args[n], XmNrightAttachment, XmATTACH_POSITION); n++;
XtSetArg (args[n], XmNrightPosition, 3); n++;
w = XmCreatePushButton (f_w, "Close", args, n);
wtip (w, "Close this dialog ((but continue plotting if active)");
XtAddCallback (w, XmNactivateCallback, plt_close_cb, 0);
XtManageChild (w);
n = 0;
XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
XtSetArg (args[n], XmNleftPosition, 4); n++;
XtSetArg (args[n], XmNrightAttachment, XmATTACH_POSITION); n++;
XtSetArg (args[n], XmNrightPosition, 6); n++;
XtSetArg (args[n], XmNsensitive, False); n++;
undo_w = XmCreatePushButton (f_w, "Undo", args, n);
wtip (undo_w, "Undo last choice)");
XtAddCallback (undo_w, XmNactivateCallback, plt_undo_cb, 0);
XtManageChild (undo_w);
n = 0;
XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
XtSetArg (args[n], XmNleftPosition, 7); n++;
XtSetArg (args[n], XmNrightAttachment, XmATTACH_POSITION); n++;
XtSetArg (args[n], XmNrightPosition, 9); n++;
w = XmCreatePushButton (f_w, "Help", args, n);
wtip (w, "More detailed usage information");
XtAddCallback (w, XmNactivateCallback, plt_help_cb, 0);
XtManageChild (w);
}
/* callback from one of the file names in the Show list.
* file name is label of this widget
*/
/* ARGSUSED */
static void
plt_show_cb (Widget w, XtPointer client, XtPointer call)
{
char *fn;
/* turn off plotting, if on, to make sure file is complete. */
if (XmToggleButtonGetState(active_w))
XmToggleButtonSetState(active_w, False, True);
get_xmstring (w, XmNlabelString, &fn);
plt_da_manage(fn);
XtFree (fn);
}
/* callback from one of the config file names in load.
* file name is label of this widget
*/
/* ARGSUSED */
static void
plt_loadcfg_cb (Widget w, XtPointer client, XtPointer call)
{
char buf[1024];
FILE *fp;
char *fn;
/* turn off plotting and selecting, if on */
if (XmToggleButtonGetState(active_w))
XmToggleButtonSetState(active_w, False, True);
if (XmToggleButtonGetState(select_w))
XmToggleButtonSetState(select_w, False, True);
get_xmstring (w, XmNlabelString, &fn);
fp = fopend (fn, NULL, "r");
if (fp) {
LilXML *lp = newLilXML();
XMLEle *pele = readXMLFile (fp, lp, buf);
if (!pele)
xe_msg (1, "%s:\n%s", fn, buf);
else if (strcmp (tagXMLEle(pele), xml_plotele)) {
xe_msg (1, "Not a valid plot config file");
} else {
XMLEle *ep;
plt_reset();
init_row(); /* set first tag to something and show it */
selecting_xy = X;
for (ep= nextXMLEle(pele,1); ep != NULL; ep=nextXMLEle(pele,0)){
if (strcmp (tagXMLEle(ep), "plot") == 0) {
XmTextFieldSetString (pltlines[npltlines].c_w[T],
findXMLAttValu (ep, "tag"));
add_field (findXMLAttValu (ep, "x"));
add_field (findXMLAttValu (ep, "y"));
}
}
XmTextFieldSetString (title_w,
pcdataXMLEle(findXMLEle(pele,"title")));
plt_stop_selecting();
}
delXMLEle (pele);
delLilXML (lp);
fclose (fp);
}
XtFree (fn);
}
/* callback to save current configuration to file named by cfn_w. */
/* ARGSUSED */
static void
plt_savecfg_cb (Widget w, XtPointer client, XtPointer call)
{
FILE *fp;
char *txt, *fn;
char buf[1024];
int i;
/* ignore if turning off */
if (!XmToggleButtonGetState(w))
return;
/* stop selecting if on */
if (XmToggleButtonGetState (select_w))
XmToggleButtonSetState (select_w, False, True);
/* get config file name, add suffix if not already */
fn = txt = XmTextFieldGetString (cfn_w);
if (!strstr (txt, config_suffix)) {
sprintf (fn = buf, "%s%s", txt, config_suffix);
XmTextFieldSetString (cfn_w, fn);
}
/* save each entry */
fp = fopend (fn, NULL, "w");
if (fp) {
char *title = XmTextFieldGetString (title_w);
fprintf (fp, "<%s>\n", xml_plotele);
fprintf (fp, " <title>%s</title>\n", title);
for (i = 0; i < npltlines; i++) {
PltLine *p = &pltlines[i];
char *tn = XmTextFieldGetString (p->c_w[T]);
fprintf (fp, " <plot tag='%s' x='%s' y='%s' />\n", tn,
p->pl_xn, p->pl_yn);
XtFree (tn);
}
fprintf (fp, "</%s>\n", xml_plotele);
XtFree (title);
fclose (fp);
}
/* act like a push button - give chance to see change. */
if (confirm())
xe_msg (1, "%s saved", fn);
XmToggleButtonSetState(w, False, True);
/* finished */
XtFree (txt);
}
/* callback to allow selecting plot fields */
/* ARGSUSED */
static void
plt_select_cb (Widget w, XtPointer client, XtPointer call)
{
if (XmToggleButtonGetState(w)) {
/* first turn off plotting, if on, while we change things */
if (XmToggleButtonGetState(active_w))
XmToggleButtonSetState(active_w, False, True);
plt_reset(); /* reset pltlines array and unmanage the table*/
plt_select(1); /* inform other menus to inform us of fields */
init_row(); /* set first tag to something and show it */
selecting_xy = X;
} else
plt_stop_selecting();
}
/* callback when user wants to start building a plot file */
/* ARGSUSED */
static void
plt_active_cb (Widget w, XtPointer client, XtPointer call)
{
if (XmToggleButtonGetState(w)) {
/* first turn off selecting, if on */
if (XmToggleButtonGetState(select_w))
XmToggleButtonSetState(select_w, False, True);
if (npltlines > 0)
plt_try_turn_on();
else {
xe_msg (1, "Please select at least one pair of values to plot");
XmToggleButtonSetState (w, False, False);
}
} else
plt_turn_off();
}
/* callback when the main plot window is closed */
/* ARGSUSED */
static void
plt_popdown_cb (Widget w, XtPointer client, XtPointer call)
{
}
/* callback from the Close button.
*/
/* ARGSUSED */
static void
plt_close_cb (Widget w, XtPointer client, XtPointer call)
{
XtPopdown (plotshell_w);
}
/* callback from the Help button.
*/
/* ARGSUSED */
static void
plt_help_cb (Widget w, XtPointer client, XtPointer call)
{
static char *help_msg[] = {
"This menu controls the plot generation and display functionality of xephem.",
"Select fields to form x/y pairs, enable plotting to write them to a file on",
"each xephem iteration step, then view. Each file may be titled, as desired."
};
hlp_dialog ("Plot", help_msg, sizeof(help_msg)/sizeof(help_msg[0]));
}
/* callback from the Undo button.
*/
/* ARGSUSED */
static void
plt_undo_cb (Widget w, XtPointer client, XtPointer call)
{
if (selecting_xy == X) {
if (npltlines > 0) {
/* delete row and previous y */
XtUnmanageChild (pltlines[npltlines--].c_w[FORM]);
set_y ("");
selecting_xy = Y;
}
} else if (selecting_xy == Y) {
/* clear x */
set_x ("");
selecting_xy = X;
}
}
/* forget our list, and unmanage the table.
*/
static void
plt_reset (void)
{
int i;
for (i = 0; i < npltlines; i++)
XtUnmanageChild (pltlines[i].c_w[FORM]);
npltlines = 0;
}
/* stop selecting: unmanage a partitially filled in line specs; tell
* everybody else to drop their buttons, make sure toggle is off.
*/
static void
plt_stop_selecting (void)
{
if (npltlines < MAXPLTLINES)
XtUnmanageChild (pltlines[npltlines].c_w[FORM]);
XmToggleButtonSetState (select_w, False, False);
plt_select(0);
XtUnmanageChild (prompt_w);
XtSetSensitive (undo_w, False);
}
static void
plt_turn_off (void)
{
if (plt_fp) {
(void) fclose (plt_fp);
plt_fp = 0;
}
}
/* set name as X coord on current row and change prompt to ask for Y */
static void
set_x (name)
char *name;
{
(void) strncpy (pltlines[npltlines].pl_xn, name, MAXFLDNAM-1);
set_xmstring (pltlines[npltlines].c_w[X], XmNlabelString, name);
set_xmstring (prompt_w, XmNlabelString, "Choose field for Y ..");
XtManageChild (prompt_w);
}
/* set name as Y coord on current row */
static void
set_y (name)
char *name;
{
(void) strncpy (pltlines[npltlines].pl_yn, name, MAXFLDNAM-1);
set_xmstring (pltlines[npltlines].c_w[Y], XmNlabelString, name);
}
/* init npltlines'th row and change prompt to ask for X */
static void
init_row (void)
{
char buf[100];
(void) sprintf (buf, "P%02d", npltlines+1);
XmTextFieldSetString (pltlines[npltlines].c_w[T], buf);
set_xmstring (prompt_w, XmNlabelString, "Choose field for X ..");
XtManageChild (prompt_w);
set_xmstring (pltlines[npltlines].c_w[X], XmNlabelString, " ");
set_xmstring (pltlines[npltlines].c_w[Y], XmNlabelString, " ");
XtManageChild (pltlines[npltlines].c_w[FORM]);
XtSetSensitive (undo_w, True);
}
/* add the next field to the new plot configuration being build */
static void
add_field (char *name)
{
if (selecting_xy == X) {
set_x (name);
selecting_xy = Y;
} else {
set_y (name);
++npltlines;
if (npltlines == MAXPLTLINES)
plt_stop_selecting();
else {
init_row();
selecting_xy = X;
}
}
}
/* called from the query routine when want to append to an existing plot file.*/
static void
plt_try_append (void)
{
plt_turn_on("a");
}
/* called from the query routine when want to overwrite to an existing plot
* file.
*/
static void
plt_try_overwrite (void)
{
plt_turn_on("w");
}
/* called from the query routine when want decided not to make a plot file. */
static void
plt_try_cancel (void)
{
XmToggleButtonSetState (active_w, False, False);
}
/* attempt to open file for use as a plot file.
* if it doesn't exist, then go ahead and make it.
* but if it does, first ask wheher to append or overwrite.
*/
static void
plt_try_turn_on (void)
{
char *txt;
char buf[1024], *fn;
/* add suffix if not already */
fn = txt = XmTextFieldGetString (pfn_w);
if (!strstr (txt, plot_suffix))
sprintf (fn = buf, "%s%s", txt, plot_suffix);
/* create, or modify if ok */
if (existd (fn,NULL) == 0 && confirm()) {
char buf[256];
(void) sprintf (buf, "%s exists:\nAppend or Overwrite?", fn);
query (plotshell_w, buf, "Append", "Overwrite", "Cancel",
plt_try_append, plt_try_overwrite, plt_try_cancel);
} else
plt_try_overwrite();
XtFree (txt);
}
/* turn on plotting.
* establish a file to use (and thereby set plt_fp, the plotting_is_on flag).
*/
static void
plt_turn_on (how)
char *how; /* fopen how argument */
{
char buf[1024], *fn;
char *txt;
/* add suffix if not already */
fn = txt = XmTextFieldGetString (pfn_w);
if (!strstr (txt, plot_suffix)) {
sprintf (fn = buf, "%s%s", txt, plot_suffix);
XmTextFieldSetString (pfn_w, fn);
}
/* plotting is on if file opens ok */
plt_fp = fopend (fn, NULL, how);
if (!plt_fp)
XmToggleButtonSetState (active_w, False, False);
XtFree (txt);
if (plt_fp) {
/* add a title if it's not null */
txt = XmTextFieldGetString (title_w);
if (txt[0] != '\0')
(void) fprintf (plt_fp, "* %s\n", txt);
XtFree (txt);
}
}
/* make a new drawing area widget and manage it. it's unmanaged and destroyed
* from the Close button or if something goes wrong during plotting.
* open the plot file and save it, the current state of the flipx/flipy/grid
* buttons and the filename in a DrawInfo struct in the userData resource
* for the FormDialog where the drawingarea callback can get at it each time.
* this way, we can have lots of different plots up at once yet we don't
* have to keep track of them.
* by leaving the file open, we gain some protection against it being removed
* or renamed.
*/
static void
plt_da_manage(char *fn)
{
Widget daform_w;
Widget da_w, w;
Widget mb_w, pd_w, cb_w;
XmString str;
EventMask mask;
Arg args[20];
char titlebuf[64];
int n;
DrawInfo *di;
FILE *fp;
/* first make sure we can open the plot file */
fn = XtNewString (fn);
fp = fopend (fn, "auxil", "r");
if (!fp) {
XtFree (fn);
return;
}
/* create the form dialog parent. */
n = 0;
XtSetArg (args[n], XmNcolormap, xe_cm); n++;
daform_w = XmCreateFormDialog (plotshell_w, "PlotDisplay", args, n);
set_something (daform_w, XmNcolormap, (XtArgVal)xe_cm);
XtAddCallback (daform_w, XmNmapCallback, prompt_map_cb, NULL);
/* set some stuff in the parent DialogShell.
* setting XmNdialogTitle in the Form didn't work..
*/
(void) sprintf (titlebuf, "xephem Plot of `%.*s'",
(int)sizeof(titlebuf)-20, fn);
n = 0;
XtSetArg (args[n], XmNtitle, titlebuf); n++;
XtSetValues (XtParent(daform_w), args, n);
/* make the DrawInfo structure and save it in the userData of the Form.
* the memory gets freed when the dialog is closed/unmanaged.
* the options get inited from their toggle buttons.
*/
di = (DrawInfo *) XtMalloc (sizeof(DrawInfo));
di->filename = fn;
di->fp = fp;
set_something (daform_w, XmNuserData, (XtArgVal)di);
/* create the menu bar across the top */
n = 0;
XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
mb_w = XmCreateMenuBar (daform_w, "MB", args, n);
XtManageChild (mb_w);
/* create the drawing area and connect plt_da_exp_cb().
* N.B. be sure this guys parent is the FormDialog so exp_cb can find
* the DrawInfo by looking there at its userData.
* make this as high as it is wide when it is first mapped.
* N.B. if ever want this in a frame beware that other functions
* assume that the daform_w is the parent of the DrawingArea.
*/
n = 0;
XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
XtSetArg (args[n], XmNtopWidget, mb_w); n++;
XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
XtSetArg (args[n], XmNbottomOffset, 2); n++;
XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
XtSetArg (args[n], XmNmarginWidth, 0); n++;
XtSetArg (args[n], XmNmarginHeight, 0); n++;
da_w = XmCreateDrawingArea (daform_w, "PlotMap", args, n);
XtAddCallback (da_w, XmNexposeCallback, plt_da_exp_cb, NULL);
mask = Button1MotionMask | PointerMotionMask | PointerMotionHintMask;
XtAddEventHandler (da_w, mask, False, plt_da_motion_eh, 0);
XtManageChild (da_w);
/* when unmap the form, pass the da to the unmap callback */
XtAddCallback (daform_w, XmNunmapCallback, plt_da_unmap_cb,
(XtPointer)da_w);
/* make the Control pulldown */
n = 0;
pd_w = XmCreatePulldownMenu (mb_w, "ControlPD", args, n);
n = 0;
XtSetArg (args[n], XmNsubMenuId, pd_w); n++;
XtSetArg (args[n], XmNmnemonic, 'C'); n++;
cb_w = XmCreateCascadeButton (mb_w, "ControlCB", args, n);
set_xmstring (cb_w, XmNlabelString, "Control");
XtManageChild (cb_w);
/* make the print button */
n = 0;
w = XmCreatePushButton (pd_w, "PltPrint", args, n);
XtAddCallback (w, XmNactivateCallback, plt_da_print_cb, da_w);
set_xmstring (w, XmNlabelString, "Print...");
wtip (w, "Print this plot");
XtManageChild (w);
/* make the annot button */
n = 0;
w = XmCreatePushButton (pd_w, "Ann", args, n);
XtAddCallback (w, XmNactivateCallback, ano_cb, NULL);
set_xmstring (w, XmNlabelString, "User annotation...");
wtip (w, "Open window to create and manage your own annotation");
XtManageChild (w);
/* make the movie loop button */
n = 0;
n += ml_addacc (args, n);
w = XmCreatePushButton (pd_w, "ML", args, n);
XtAddCallback (w, XmNactivateCallback, plt_da_mloop_cb, da_w);
set_xmstring (w, XmNlabelString, "Add to movie...");
wtip (w, "Add this plot to the movie loop");
XtManageChild (w);
/* add a separator */
n = 0;
w = XmCreateSeparator (pd_w, "Sep", args, n);
XtManageChild (w);
/* make the close button.
* it destroys the dialog and frees the DrawInfo struct.
*/
n = 0;
w = XmCreatePushButton (pd_w, "Close", args, n);
wtip (w, "Close this plot display");
XtAddCallback (w, XmNactivateCallback, plt_da_close_cb, daform_w);
XtManageChild (w);
/* make the View pulldown */
n = 0;
pd_w = XmCreatePulldownMenu (mb_w, "ViewPD", args, n);
n = 0;
XtSetArg (args[n], XmNsubMenuId, pd_w); n++;
XtSetArg (args[n], XmNmnemonic, 'V'); n++;
cb_w = XmCreateCascadeButton (mb_w, "ViewCB", args, n);
set_xmstring (cb_w, XmNlabelString, "View");
XtManageChild (cb_w);
str = XmStringCreate("Flip X", XmSTRING_DEFAULT_CHARSET);
n = 0;
XtSetArg (args[n], XmNvisibleWhenOff, True); n++;
XtSetArg (args[n], XmNmarginHeight, 0); n++;
XtSetArg (args[n], XmNlabelString, str); n++;
w = XmCreateToggleButton(pd_w, "FlipX", args, n);
di->flipx = XmToggleButtonGetState (w);
di->fx_w = w;
XmStringFree (str);
XtAddCallback (w, XmNvalueChangedCallback, plt_da_flipx_cb, da_w);
wtip (w, "Flip left-to-right");
XtManageChild (w);
/* TODO - can not use until fix findWFB()
* sr_reg (w, NULL, plotcategory, 1);
*/
str = XmStringCreate("Flip Y", XmSTRING_DEFAULT_CHARSET);
n = 0;
XtSetArg (args[n], XmNvisibleWhenOff, True); n++;
XtSetArg (args[n], XmNmarginHeight, 0); n++;
XtSetArg (args[n], XmNlabelString, str); n++;
w = XmCreateToggleButton(pd_w, "FlipY", args, n);
di->flipy = XmToggleButtonGetState (w);
di->fy_w = w;
XmStringFree (str);
XtAddCallback (w, XmNvalueChangedCallback, plt_da_flipy_cb, da_w);
wtip (w, "Flip top-to-bottom");
XtManageChild (w);
/* TODO - can not use until fix findWFB()
* sr_reg (w, NULL, plotcategory, 1);
*/
n = 0;
XtSetArg (args[n], XmNvisibleWhenOff, True); n++;
XtSetArg (args[n], XmNmarginHeight, 0); n++;
w = XmCreateToggleButton(pd_w, "Grid", args, n);
di->grid = XmToggleButtonGetState (w);
di->g_w = w;
XtAddCallback (w, XmNvalueChangedCallback, plt_da_grid_cb, da_w);
wtip (w, "Overlay plot with calibrated grid");
XtManageChild (w);
/* TODO - can not use until fix findWFB()
* sr_reg (w, NULL, plotcategory, 1);
*/
str = XmStringCreate("Show X-Axis Years as Dates",
XmSTRING_DEFAULT_CHARSET);
n = 0;
XtSetArg (args[n], XmNvisibleWhenOff, True); n++;
XtSetArg (args[n], XmNmarginHeight, 0); n++;
XtSetArg (args[n], XmNlabelString, str); n++;
w = XmCreateToggleButton(pd_w, "XYrAsDate", args, n);
di->xyr_asdate = XmToggleButtonGetState (w);
di->yas_w = w;
XmStringFree (str);
XtAddCallback (w, XmNvalueChangedCallback, plt_da_xyr_asdate_cb, da_w);
wtip (w, "Assume ordinate values are decimal years and display as dates");
XtManageChild (w);
/* TODO - can not use until fix findWFB()
* sr_reg (w, NULL, plotcategory, 1);
*/
str = XmStringCreate("Show X-Axis JDs as Dates",
XmSTRING_DEFAULT_CHARSET);
n = 0;
XtSetArg (args[n], XmNvisibleWhenOff, True); n++;
XtSetArg (args[n], XmNmarginHeight, 0); n++;
XtSetArg (args[n], XmNlabelString, str); n++;
w = XmCreateToggleButton(pd_w, "XJDAsDate", args, n);
di->xjd_asdate = XmToggleButtonGetState (w);
di->jas_w = w;
XmStringFree (str);
XtAddCallback (w, XmNvalueChangedCallback, plt_da_xjd_asdate_cb, da_w);
wtip (w, "Assume ordinate values are Julian dates and display as dates");
XtManageChild (w);
/* TODO - can not use until fix findWFB()
* sr_reg (w, NULL, plotcategory, 1);
*/
/* go. the expose will do the actual plotting */
XtManageChild (daform_w);
}
/* called with the DrawingArea when finished with a plot.
* use it to get the FormDialog parent and reclaim all memory in its userData
* DrawInfo and destroy the Form and hence everything in it.
*/
static void
plt_da_destroy (da_w)
Widget da_w;
{
Widget daform_w = XtParent(da_w);
DrawInfo *di;
get_something (daform_w, XmNuserData, (XtArgVal)&di);
(void) fclose (di->fp);
XtFree(di->filename);
XtFree((char *)di);
/* TODO: don't do these until fix findWFB()
sr_unreg (di->fx_w);
sr_unreg (di->fy_w);
sr_unreg (di->g_w);
sr_unreg (di->as_w);
*/
/* destroy the shell, not just the form */
while (!XtIsWMShell (daform_w))
daform_w = XtParent(daform_w);
XtDestroyWidget(daform_w);
/* invalidate the saved print widget if it matches */
if (da_w_save == da_w)
da_w_save = 0;
}
/* proceed to generate a postscript file from da_w_save if it is still up.
* reset da_w_save and call XPSClose() when finished.
*/
static void
plt_print (void)
{
if (da_w_save) {
Dimension w, h;
int iw, ih;
get_something (da_w_save, XmNwidth, (XtArgVal)&w);
get_something (da_w_save, XmNheight, (XtArgVal)&h);
iw = (int)w;
ih = (int)h;
/* draw in an area 6.5w x 8h centered 1in down from top */
if (16*iw >= 13*ih)
XPSXBegin (XtWindow(da_w_save), 0, 0, iw, ih, 1*72, 10*72,
(int)(6.5*72));
else {
int pw = 72*8*iw/ih; /* width on paper when 8 hi */
XPSXBegin (XtWindow(da_w_save), 0, 0, iw, ih,
(int)((8.5*72-pw)/2), 10*72, pw);
}
plt_drawall (da_w_save);
XPSXEnd();
XPSClose();
da_w_save = 0;
} else {
xe_msg (1, "Can not print after plot has been dismissed.");
XPSClose();
}
}
/* called when the Print button is pushed on a plot.
* store the da_w (passed in client) and ask for print setup info.
*/
/* ARGSUSED */
static void
plt_da_print_cb (Widget w, XtPointer client, XtPointer call)
{
Widget da_w = (Widget)client;
da_w_save = da_w;
XPSAsk ("Plot", plt_print);
}
/* called to add plot to the movie loop.
* use the window of the da_w (passed in client)
*/
/* ARGSUSED */
static void
plt_da_mloop_cb (Widget w, XtPointer client, XtPointer call)
{
Widget da_w = (Widget)client;
XmUpdateDisplay (da_w); /* handle expose after pulldown menu */
ml_add (XtWindow(da_w), NULL);
}
/* called when the Close button is pushed on a plot.
* just unmap the dialog (passed as client).
*/
/* ARGSUSED */
static void
plt_da_close_cb (Widget w, XtPointer client, XtPointer call)
{
XtUnmanageChild ((Widget)client);
}
/* called when a plot is unmapped, either via a WM command or the Close button.
* free the DrawInfo and destroy the DrawingArea (passed as client).
*/
/* ARGSUSED */
static void
plt_da_unmap_cb (Widget w, XtPointer client, XtPointer call)
{
plt_da_destroy ((Widget)client);
}
/* callback from the Flip X toggle button within the drawing FormDiag itself.
* toggle the x bit in the parent's DrawInfo structure and fake an expose.
* client is the DrawingArea widget.
*/
/* ARGSUSED */
static void
plt_da_flipx_cb (Widget w, XtPointer client, XtPointer call)
{
XmToggleButtonCallbackStruct *t = (XmToggleButtonCallbackStruct *) call;
Widget da_w = (Widget) client;
Widget daform_w = XtParent(da_w);
Display *dsp = XtDisplay(da_w);
Window win = XtWindow(da_w);
DrawInfo *di;
XExposeEvent ev;
Window root;
int x, y;
unsigned int nx, ny, bw, d;
get_something (daform_w, XmNuserData, (XtArgVal)&di);
di->flipx = t->set;
XGetGeometry(dsp, win, &root, &x, &y, &nx, &ny, &bw, &d);
ev.type = Expose;
ev.send_event = 1; /* gets set anyways */
ev.display = dsp;
ev.window = win;
ev.x = ev.y = 0;
ev.width = nx;
ev.height = ny;
ev.count = 0;
XSendEvent (dsp, win, /*propagate*/False, ExposureMask, (XEvent *)&ev);
}
/* callback from the Flip Y toggle button within the drawing FormDiag itself.
* toggle the y bit in the parent's DrawInfo structure and fake an expose.
* client is the DrawingArea widget.
*/
/* ARGSUSED */
static void
plt_da_flipy_cb (Widget w, XtPointer client, XtPointer call)
{
XmToggleButtonCallbackStruct *t = (XmToggleButtonCallbackStruct *) call;
Widget da_w = (Widget) client;
Widget daform_w = XtParent(da_w);
Display *dsp = XtDisplay(da_w);
Window win = XtWindow(da_w);
DrawInfo *di;
XExposeEvent ev;
Window root;
int x, y;
unsigned int nx, ny, bw, d;
get_something (daform_w, XmNuserData, (XtArgVal)&di);
di->flipy = t->set;
XGetGeometry(dsp, win, &root, &x, &y, &nx, &ny, &bw, &d);
ev.type = Expose;
ev.send_event = 1; /* gets set anyways */
ev.display = dsp;
ev.window = win;
ev.x = ev.y = 0;
ev.width = nx;
ev.height = ny;
ev.count = 0;
XSendEvent (dsp, win, /*propagate*/False, ExposureMask, (XEvent *)&ev);
}
/* callback from the grid toggle button within the drawing FormDiag itself.
* toggle the grid flag in the parent's DrawInfo structure and fake an expose.
* client is the DrawingArea widget.
*/
/* ARGSUSED */
static void
plt_da_grid_cb (Widget w, XtPointer client, XtPointer call)
{
XmToggleButtonCallbackStruct *t = (XmToggleButtonCallbackStruct *) call;
Widget da_w = (Widget) client;
Widget daform_w = XtParent(da_w);
Display *dsp = XtDisplay(da_w);
Window win = XtWindow(da_w);
DrawInfo *di;
XExposeEvent ev;
Window root;
int x, y;
unsigned int nx, ny, bw, d;
get_something (daform_w, XmNuserData, (XtArgVal)&di);
di->grid = t->set;
XGetGeometry(dsp, win, &root, &x, &y, &nx, &ny, &bw, &d);
ev.type = Expose;
ev.send_event = 1; /* gets set anyways */
ev.display = dsp;
ev.window = win;
ev.x = ev.y = 0;
ev.width = nx;
ev.height = ny;
ev.count = 0;
XSendEvent (dsp, win, /*propagate*/False, ExposureMask, (XEvent *)&ev);
}
/* callback from the X-as-Year-is-date toggle button within the drawing FormDiag itself.
* toggle the xisdate flag in the parent's DrawInfo structure and fake an
* expose. client is the DrawingArea widget.
*/
/* ARGSUSED */
static void
plt_da_xyr_asdate_cb (Widget w, XtPointer client, XtPointer call)
{
XmToggleButtonCallbackStruct *t = (XmToggleButtonCallbackStruct *) call;
Widget da_w = (Widget) client;
Widget daform_w = XtParent(da_w);
Display *dsp = XtDisplay(da_w);
Window win = XtWindow(da_w);
DrawInfo *di;
XExposeEvent ev;
Window root;
int x, y;
unsigned int nx, ny, bw, d;
/* honor this, and toggle off the other if on */
get_something (daform_w, XmNuserData, (XtArgVal)&di);
di->xyr_asdate = t->set;
if (!di->xyr_asdate && di->xjd_asdate)
return; /* we were toggled off */
if (di->xyr_asdate && di->xjd_asdate) {
di->xjd_asdate = 0;
XmToggleButtonSetState (di->jas_w, False, True);
}
XGetGeometry(dsp, win, &root, &x, &y, &nx, &ny, &bw, &d);
ev.type = Expose;
ev.send_event = 1; /* gets set anyways */
ev.display = dsp;
ev.window = win;
ev.x = ev.y = 0;
ev.width = nx;
ev.height = ny;
ev.count = 0;
XSendEvent (dsp, win, /*propagate*/False, ExposureMask, (XEvent *)&ev);
}
/* callback from the X-as-JD-is-date toggle button within the drawing FormDiag itself.
* toggle the xisdate flag in the parent's DrawInfo structure and fake an
* expose. client is the DrawingArea widget.
*/
/* ARGSUSED */
static void
plt_da_xjd_asdate_cb (Widget w, XtPointer client, XtPointer call)
{
XmToggleButtonCallbackStruct *t = (XmToggleButtonCallbackStruct *) call;
Widget da_w = (Widget) client;
Widget daform_w = XtParent(da_w);
Display *dsp = XtDisplay(da_w);
Window win = XtWindow(da_w);
DrawInfo *di;
XExposeEvent ev;
Window root;
int x, y;
unsigned int nx, ny, bw, d;
/* honor this, and toggle off the other if on */
get_something (daform_w, XmNuserData, (XtArgVal)&di);
di->xjd_asdate = t->set;
if (!di->xjd_asdate && di->xyr_asdate)
return; /* we were toggled off */
if (di->xjd_asdate && di->xyr_asdate) {
di->xyr_asdate = 0;
XmToggleButtonSetState (di->yas_w, False, True);
}
XGetGeometry(dsp, win, &root, &x, &y, &nx, &ny, &bw, &d);
ev.type = Expose;
ev.send_event = 1; /* gets set anyways */
ev.display = dsp;
ev.window = win;
ev.x = ev.y = 0;
ev.width = nx;
ev.height = ny;
ev.count = 0;
XSendEvent (dsp, win, /*propagate*/False, ExposureMask, (XEvent *)&ev);
}
/* plot drawing area's expose callback.
* redraw the graph to the (new?) size.
* get a DrawInfo from our parent's userData.
*/
/* ARGSUSED */
static void
plt_da_exp_cb (da_w, client, call)
Widget da_w;
XtPointer client;
XtPointer call;
{
XmDrawingAreaCallbackStruct *c = (XmDrawingAreaCallbackStruct *)call;
switch (c->reason) {
case XmCR_EXPOSE: {
XExposeEvent *e = &c->event->xexpose;
XSetWindowAttributes swa;
unsigned long mask = CWBitGravity;
/* turn off gravity so we get fresh exposes when grow and shrink.
* do it every time because this expose handler is used for all
* the windows -- yes, it is over kill but not worth remembering
* which windows have already been set.
*/
swa.bit_gravity = ForgetGravity;
XChangeWindowAttributes (e->display, e->window, mask, &swa);
/* wait for the last in the series */
if (e->count != 0)
return;
break;
}
default:
printf ("Unexpected da_w event. type=%d\n", c->reason);
abort();
}
/* draw the plot from scratch */
plt_drawall (da_w);
}
/* plot drawing area's motion handler.
* called when pointer moves over a plot.
* get a DrawInfo from our parent's userData.
* report data at that location
*/
static void
plt_da_motion_eh (da_w, client, ev, continue_to_dispatch)
Widget da_w;
XtPointer client;
XEvent *ev;
Boolean *continue_to_dispatch;
{
Display *dsp = XtDisplay(da_w);
Window win = XtWindow(da_w);
Window root, child;
int rx, ry, wx, wy;
unsigned mask;
Widget daform_w;
DrawInfo *di;
daform_w = XtParent(da_w);
get_something (daform_w, XmNuserData, (XtArgVal)&di);
XQueryPointer (dsp, win, &root, &child, &rx, &ry, &wx, &wy, &mask);
plot_coords (da_w, di, wx, wy);
}
/* given a drawing area, draw the plot.
* remember: the parent of the da is the form and it's userData is the di info.
*/
static void
plt_drawall (da_w)
Widget da_w;
{
Dimension w, h;
Widget daform_w;
DrawInfo *di;
watch_cursor (1);
get_something (da_w, XmNwidth, (XtArgVal)&w);
get_something (da_w, XmNheight, (XtArgVal)&h);
daform_w = XtParent(da_w);
get_something (daform_w, XmNuserData, (XtArgVal)&di);
XClearWindow (XtDisplay(da_w), XtWindow(da_w));
rewind (di->fp);
if (plot_cartesian (di, da_w, w, h) < 0) {
/* had trouble, so done with this FormDialog.
*/
xe_msg (0, "Error plotting `%s'", di->filename);
plt_da_destroy (da_w);
}
/* user annotation */
ano_draw (da_w, XtWindow(da_w), plt_ano, 0);
watch_cursor (0);
}
/* support simple pixel based annotation
*/
static int
plt_ano (double *sx, double *sy, int *xp, int *yp, int w2x, int arg)
{
if (w2x) {
*xp = (int)*sx;
*yp = (int)*sy;
} else {
*sx = (double)*xp;
*sy = (double)*yp;
}
return (1);
}