mirror of https://github.com/XEphem/XEphem.git
1016 lines
28 KiB
C
1016 lines
28 KiB
C
/* code to manage the stuff on the sky view filter display.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <ctype.h>
|
|
#include <math.h>
|
|
#include <stdlib.h>
|
|
|
|
#include <X11/Xlib.h>
|
|
#include <Xm/Xm.h>
|
|
#include <Xm/Form.h>
|
|
#include <Xm/Frame.h>
|
|
#include <Xm/DrawingA.h>
|
|
#include <Xm/Label.h>
|
|
#include <Xm/PushB.h>
|
|
#include <Xm/RowColumn.h>
|
|
#include <Xm/ToggleB.h>
|
|
#include <Xm/Text.h>
|
|
#include <Xm/Scale.h>
|
|
|
|
#include "xephem.h"
|
|
|
|
|
|
/* info for each filter option toggle */
|
|
typedef struct {
|
|
char *label; /* label on the toggle button */
|
|
char *name; /* name of toggle button, for resource setting */
|
|
int type; /* as in Obj.o_type */
|
|
char class; /* if type==FIXED then as in Obj.f.f_class */
|
|
char state; /* 0 or 1 depending on whether this class is on */
|
|
Widget tbw; /* the toggle button widget */
|
|
} FilterTB;
|
|
|
|
/* info for a set of filters forming a category */
|
|
typedef struct {
|
|
char *label; /* label for this category */
|
|
char *ltip; /* tip for this category */
|
|
FilterTB *ftb; /* array of toggle button filters in this class */
|
|
int nftb; /* entries in ftb[] */
|
|
Widget pbw; /* the category "toggle" pushbutton */
|
|
} FilterCat;
|
|
|
|
/* struct to hold automag settings */
|
|
typedef struct {
|
|
double r; /* max FOV radius for this mag, rads */
|
|
int st; /* star faintest mag */
|
|
int ss; /* sol sys faintest mag */
|
|
int ds; /* deep-sky faintest mag */
|
|
int s; /* mag step per dot size */
|
|
} AutoMag;
|
|
|
|
static void svf_create_filter (Widget mainrc, FilterCat *fcp);
|
|
static void svf_reset (void);
|
|
static void svf_apply (void);
|
|
static int svf_bright_ok (Obj *op);
|
|
static void svf_da_cb (Widget w, XtPointer client, XtPointer call);
|
|
static void svf_draw_symbol (FilterTB *ftbp, Widget daw);
|
|
static void svf_magdrag_cb (Widget w, XtPointer client, XtPointer call);
|
|
static void svf_apply_cb (Widget w, XtPointer client, XtPointer call);
|
|
static void svf_ok_cb (Widget w, XtPointer client, XtPointer call);
|
|
static void svf_close_cb (Widget w, XtPointer client, XtPointer call);
|
|
static void svf_help_cb (Widget w, XtPointer client, XtPointer call);
|
|
static void svf_toggle_cb (Widget w, XtPointer client, XtPointer call);
|
|
static void svf_all_cb (Widget w, XtPointer client, XtPointer call);
|
|
static void svf_reset_cb (Widget w, XtPointer client, XtPointer call);
|
|
static void svf_cat_toggle_cb (Widget w, XtPointer client, XtPointer call);
|
|
static int svf_initautomag (AutoMag **ampp);
|
|
|
|
|
|
static FilterTB solsys_f[] = {
|
|
{"Planets", "Planets", PLANET, 0},
|
|
{"Elliptical", "Elliptical", ELLIPTICAL, 0},
|
|
{"Hyperbolic", "Hyperbolic", HYPERBOLIC, 0},
|
|
{"Parabolic", "Parabolic", PARABOLIC, 0},
|
|
{"Earth Sat", "EarthSat", EARTHSAT, 0}
|
|
};
|
|
|
|
static FilterTB other_f[] = {
|
|
{"Q Quasars", "Quasars", FIXED, 'Q'},
|
|
{"L Pulsars", "Pulsars", FIXED, 'L'},
|
|
{"J Radio", "Radio", FIXED, 'J'},
|
|
{"Y Supernova", "Supernova", FIXED, 'Y'},
|
|
{"R S/N Rem", "SNRemnants", FIXED, 'R'},
|
|
};
|
|
|
|
static FilterTB stars_f[] = {
|
|
{"S Single", "Stars", FIXED, 'S'},
|
|
{"B Binary", "Binary", BINARYSTAR, 0},
|
|
/* B as a subfield of FIXED merged into D as of BINARYSTAR */
|
|
{"D Double", "Double", FIXED, 'D'},
|
|
{"M Multiple", "Multiple", FIXED, 'M'},
|
|
{"V Variable", "Variable", FIXED, 'V'},
|
|
{"T Star-like", "Stellar", FIXED, 'T'}
|
|
};
|
|
|
|
static FilterTB nebulae_f[] = {
|
|
{"N Bright", "BrightNeb", FIXED, 'N'},
|
|
{"F Diffuse", "DiffuseNeb", FIXED, 'F'},
|
|
{"K Dark", "DarkNeb", FIXED, 'K'},
|
|
{"P Planetary", "PlanetaryNeb", FIXED, 'P'}
|
|
};
|
|
|
|
static FilterTB galaxies_f[] = {
|
|
{"G Spiral", "SpiralGal", FIXED, 'G'},
|
|
{"H Spherical", "SphericalGal", FIXED, 'H'},
|
|
{"A Clusters", "GalClusters", FIXED, 'A'}
|
|
};
|
|
|
|
static FilterTB clusters_f[] = {
|
|
{"C Globular", "GlobularCl", FIXED, 'C'},
|
|
{"O Open", "OpenCl", FIXED, 'O'},
|
|
{"U in Nebula", "ClInNeb", FIXED, 'U'}
|
|
};
|
|
|
|
static FilterCat filters[] = {
|
|
{"Solar System:",
|
|
"Whether to display Planets, asteroids, comets, Earth satellites",
|
|
solsys_f, XtNumber(solsys_f)},
|
|
{"Clusters:",
|
|
"Whether to display various types of star clusters",
|
|
clusters_f, XtNumber(clusters_f)},
|
|
{"Other:",
|
|
"Whether to display a variety of miscellaneous classes of objects",
|
|
other_f, XtNumber(other_f)},
|
|
{"Galaxies:",
|
|
"Whether to display galaxies and clusters of galaxies",
|
|
galaxies_f, XtNumber(galaxies_f)},
|
|
{"Nebulae:",
|
|
"Whether to display various types of nebulae, and planetary nebulae",
|
|
nebulae_f, XtNumber(nebulae_f)},
|
|
{"Stars:",
|
|
"Whether to display various classes of stars and star-like objects",
|
|
stars_f, XtNumber(stars_f)},
|
|
};
|
|
|
|
/* these form rapid lookup tables for the state of an object.
|
|
* type_table can be directly indexed by Obj.o_type and, if type is FIXED,
|
|
* fclass_table by Obj.f.f_class.
|
|
*/
|
|
static char type_table[NOBJTYPES];
|
|
static char fclass_table[NCLASSES];
|
|
|
|
#define BMAGLIMIT (-28) /* brightest setting for the Mag scale */
|
|
#define FMAGLIMIT 30 /* faintest setting for the Mag scale */
|
|
#define MAXMAGSTP 30 /* mag mag step */
|
|
static int stmag, ssmag, dsmag; /* current values of the mag limits */
|
|
static int magstp; /* current value of mag step */
|
|
static Widget stmag_w, ssmag_w, dsmag_w; /* mag scales */
|
|
static Widget magst_w; /* mag steps scale */
|
|
static Widget filter_w; /* main filter dialog */
|
|
|
|
static char skyfcategory[] = "Sky View -- Filter"; /* Save category */
|
|
|
|
/* create, but do not manage, the filter dialog.
|
|
* we also apply its state info immediately to the initial resource
|
|
* settings of the toggle buttons since they are used to set up the real filter
|
|
* right away.
|
|
*/
|
|
void
|
|
svf_create(shell_w)
|
|
Widget shell_w;
|
|
{
|
|
static struct {
|
|
char *name;
|
|
char *tip;
|
|
void (*cb)();
|
|
} ctls[] = {
|
|
/* balance in half */
|
|
{"Ok", "Apply changes and close", svf_ok_cb},
|
|
{"Apply", "Apply changes and stay up", svf_apply_cb},
|
|
{"Toggle", "Toggle all selections on->off and off->on",
|
|
svf_toggle_cb},
|
|
{"All", "Turn all selections on", svf_all_cb},
|
|
{"Reset", "Restore settings to what is now in effect",svf_reset_cb},
|
|
{"Close", "Make no changes and close", svf_close_cb},
|
|
{"Help", "Display additional information", svf_help_cb}
|
|
};
|
|
Arg args[20];
|
|
XmString str;
|
|
Widget w, f_w;
|
|
Widget rc_w, lrc_w, rrc_w, mrc_w;
|
|
int n;
|
|
int i;
|
|
|
|
/* create form */
|
|
n = 0;
|
|
XtSetArg (args[n], XmNautoUnmanage, False); n++;
|
|
XtSetArg (args[n], XmNverticalSpacing, 6); n++;
|
|
XtSetArg (args[n], XmNmarginWidth, 8); n++;
|
|
XtSetArg (args[n], XmNmarginHeight, 8); n++;
|
|
XtSetArg (args[n], XmNcolormap, xe_cm); n++;
|
|
XtSetArg (args[n], XmNdefaultPosition, False); n++;
|
|
filter_w = XmCreateFormDialog (shell_w, "SkyFilter", args, n);
|
|
set_something (filter_w, XmNcolormap, (XtArgVal)xe_cm);
|
|
XtAddCallback (filter_w, XmNhelpCallback, svf_help_cb, NULL);
|
|
sr_reg (XtParent(filter_w), "XEphem*SkyFilter.x", skyfcategory, 0);
|
|
sr_reg (XtParent(filter_w), "XEphem*SkyFilter.y", skyfcategory, 0);
|
|
|
|
/* set some stuff in the parent DialogShell.
|
|
* setting XmNdialogTitle in the Form didn't work..
|
|
*/
|
|
n = 0;
|
|
XtSetArg (args[n], XmNtitle, "xephem Sky view Filter"); n++;
|
|
XtSetValues (XtParent(filter_w), args, n);
|
|
|
|
/* put the control buttons across the bottom in a horizontal RC
|
|
*/
|
|
|
|
n = 0;
|
|
XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
|
|
XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
|
|
XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
|
|
XtSetArg (args[n], XmNisAligned, False); n++;
|
|
XtSetArg (args[n], XmNadjustLast, True); n++;
|
|
XtSetArg (args[n], XmNorientation, XmHORIZONTAL); n++;
|
|
XtSetArg (args[n], XmNpacking, XmPACK_TIGHT); n++;
|
|
XtSetArg (args[n], XmNspacing, 2); n++;
|
|
rc_w = XmCreateRowColumn (filter_w, "CRC", args, n);
|
|
XtManageChild (rc_w);
|
|
|
|
for (i = 0; i < XtNumber(ctls); i++) {
|
|
str = XmStringCreateLtoR(ctls[i].name,XmSTRING_DEFAULT_CHARSET);
|
|
n = 0;
|
|
XtSetArg (args[n], XmNalignment, XmALIGNMENT_CENTER); n++;
|
|
XtSetArg (args[n], XmNmarginWidth, 1); n++;
|
|
XtSetArg (args[n], XmNmarginLeft, 0); n++;
|
|
XtSetArg (args[n], XmNmarginRight, 0); n++;
|
|
XtSetArg (args[n], XmNlabelString, str); n++;
|
|
w = XmCreatePushButton (rc_w, "FilterCB", args, n);
|
|
wtip (w, ctls[i].tip);
|
|
XtManageChild(w);
|
|
XmStringFree (str);
|
|
XtAddCallback (w, XmNactivateCallback, ctls[i].cb, NULL);
|
|
}
|
|
|
|
/* pile all but the control buttons in a main rowcolumn */
|
|
|
|
n = 0;
|
|
XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
|
|
XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
|
|
XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
|
|
XtSetArg (args[n], XmNbottomAttachment, XmATTACH_WIDGET); n++;
|
|
XtSetArg (args[n], XmNbottomWidget, rc_w); n++;
|
|
XtSetArg (args[n], XmNpacking, XmPACK_COLUMN); n++;
|
|
XtSetArg (args[n], XmNnumColumns, 2); n++;
|
|
mrc_w = XmCreateRowColumn (filter_w, "MRC", args, n);
|
|
XtManageChild (mrc_w);
|
|
|
|
/* make the left rc */
|
|
n = 0;
|
|
lrc_w = XmCreateRowColumn (mrc_w, "LRC", args, n);
|
|
XtManageChild (lrc_w);
|
|
|
|
/* add half the FilterCats */
|
|
|
|
for (i = 0; i < XtNumber(filters)/2; i++)
|
|
svf_create_filter (lrc_w, &filters[i]);
|
|
|
|
/* add sol sys limit scale in a frame */
|
|
|
|
n = 0;
|
|
f_w = XmCreateFrame (lrc_w, "SSF", args, n);
|
|
XtManageChild (f_w);
|
|
|
|
str = XmStringCreate ("Sol Sys Lim Mag", XmSTRING_DEFAULT_CHARSET);
|
|
n = 0;
|
|
XtSetArg (args[n], XmNorientation, XmHORIZONTAL); n++;
|
|
XtSetArg (args[n], XmNminimum, BMAGLIMIT); n++;
|
|
XtSetArg (args[n], XmNmaximum, FMAGLIMIT); n++;
|
|
XtSetArg (args[n], XmNprocessingDirection, XmMAX_ON_LEFT); n++;
|
|
XtSetArg (args[n], XmNscaleMultiple, 1); n++;
|
|
XtSetArg (args[n], XmNshowValue, True); n++;
|
|
XtSetArg (args[n], XmNtitleString, str); n++;
|
|
ssmag_w = XmCreateScale (f_w, "SolSysMag", args, n);
|
|
XtAddCallback (ssmag_w, XmNdragCallback, svf_magdrag_cb, 0);
|
|
XtAddCallback (ssmag_w, XmNvalueChangedCallback, svf_magdrag_cb, 0);
|
|
wtip (ssmag_w, "Faint limit for solar system objects");
|
|
XtManageChild (ssmag_w);
|
|
XmStringFree (str);
|
|
sr_reg (ssmag_w, NULL, skyfcategory, 0);
|
|
|
|
/* add mag step scale in a frame */
|
|
|
|
n = 0;
|
|
f_w = XmCreateFrame (lrc_w, "SSF", args, n);
|
|
XtManageChild (f_w);
|
|
|
|
str = XmStringCreate ("Mag dot step", XmSTRING_DEFAULT_CHARSET);
|
|
n = 0;
|
|
XtSetArg (args[n], XmNorientation, XmHORIZONTAL); n++;
|
|
XtSetArg (args[n], XmNminimum, 1); n++;
|
|
XtSetArg (args[n], XmNmaximum, MAXMAGSTP); n++;
|
|
XtSetArg (args[n], XmNscaleMultiple, 1); n++;
|
|
XtSetArg (args[n], XmNshowValue, True); n++;
|
|
XtSetArg (args[n], XmNtitleString, str); n++;
|
|
magst_w = XmCreateScale (f_w, "MagStep", args, n);
|
|
wtip (magst_w, "Select magnitude change for each dot size step");
|
|
XtManageChild (magst_w);
|
|
XmStringFree (str);
|
|
XmScaleGetValue (magst_w, &magstp);
|
|
sr_reg (magst_w, NULL, skyfcategory, 0);
|
|
|
|
/* make the right rc */
|
|
n = 0;
|
|
XtSetArg (args[n], XmNisAligned, False); n++;
|
|
rrc_w = XmCreateRowColumn (mrc_w, "RRC", args, n);
|
|
XtManageChild (rrc_w);
|
|
|
|
/* add the other half of the FilterCat */
|
|
|
|
for (i = XtNumber(filters)/2; i < XtNumber(filters); i++)
|
|
svf_create_filter (rrc_w, &filters[i]);
|
|
|
|
/* add stars mag-scale in a frame */
|
|
|
|
n = 0;
|
|
f_w = XmCreateFrame (rrc_w, "STF", args, n);
|
|
XtManageChild (f_w);
|
|
|
|
str = XmStringCreate ("Stars Lim Mag", XmSTRING_DEFAULT_CHARSET);
|
|
n = 0;
|
|
XtSetArg (args[n], XmNorientation, XmHORIZONTAL); n++;
|
|
XtSetArg (args[n], XmNminimum, BMAGLIMIT); n++;
|
|
XtSetArg (args[n], XmNmaximum, FMAGLIMIT); n++;
|
|
XtSetArg (args[n], XmNprocessingDirection, XmMAX_ON_LEFT); n++;
|
|
XtSetArg (args[n], XmNscaleMultiple, 1); n++;
|
|
XtSetArg (args[n], XmNshowValue, True); n++;
|
|
XtSetArg (args[n], XmNtitleString, str); n++;
|
|
stmag_w = XmCreateScale (f_w, "StarMag", args, n);
|
|
XtAddCallback (stmag_w, XmNdragCallback, svf_magdrag_cb, 0);
|
|
XtAddCallback (stmag_w, XmNvalueChangedCallback, svf_magdrag_cb, 0);
|
|
wtip (stmag_w, "Faint limit for stars.");
|
|
XtManageChild (stmag_w);
|
|
XmStringFree (str);
|
|
sr_reg (stmag_w, NULL, skyfcategory, 0);
|
|
|
|
n = 0;
|
|
f_w = XmCreateFrame (rrc_w, "DSF", args, n);
|
|
XtManageChild (f_w);
|
|
|
|
str = XmStringCreate ("Deep Sky Lim Mag", XmSTRING_DEFAULT_CHARSET);
|
|
n = 0;
|
|
XtSetArg (args[n], XmNorientation, XmHORIZONTAL); n++;
|
|
XtSetArg (args[n], XmNminimum, BMAGLIMIT); n++;
|
|
XtSetArg (args[n], XmNmaximum, FMAGLIMIT); n++;
|
|
XtSetArg (args[n], XmNprocessingDirection, XmMAX_ON_LEFT); n++;
|
|
XtSetArg (args[n], XmNscaleMultiple, 1); n++;
|
|
XtSetArg (args[n], XmNshowValue, True); n++;
|
|
XtSetArg (args[n], XmNtitleString, str); n++;
|
|
dsmag_w = XmCreateScale (f_w, "DeepSkyMag", args, n);
|
|
XtAddCallback (dsmag_w, XmNdragCallback, svf_magdrag_cb, 0);
|
|
XtAddCallback (dsmag_w, XmNvalueChangedCallback, svf_magdrag_cb, 0);
|
|
wtip (dsmag_w, "Faint limit for deep sky objects.");
|
|
XtManageChild (dsmag_w);
|
|
XmStringFree (str);
|
|
sr_reg (dsmag_w, NULL, skyfcategory, 0);
|
|
|
|
/* set the real filter according to the state of the toggle buttons */
|
|
svf_apply();
|
|
}
|
|
|
|
/* return 1 if we are now up, else 0.
|
|
*/
|
|
int
|
|
svf_ismanaged()
|
|
{
|
|
|
|
return (filter_w && XtIsManaged(filter_w));
|
|
}
|
|
|
|
/* called to manage the filter dialog.
|
|
* whenever we are managed, reset the state of the toggle buttons back
|
|
* to the way the real filter is.
|
|
*/
|
|
void
|
|
svf_manage()
|
|
{
|
|
svf_reset();
|
|
XtManageChild(filter_w);
|
|
}
|
|
|
|
/* called to manage the filter dialog.
|
|
*/
|
|
void
|
|
svf_unmanage()
|
|
{
|
|
XtUnmanageChild(filter_w);
|
|
}
|
|
|
|
/* return a copy of the currently enforced type and class tables.
|
|
* this is to support sky history.
|
|
*/
|
|
void
|
|
svf_gettables (tt, ct)
|
|
char tt[NOBJTYPES];
|
|
char ct[NCLASSES];
|
|
{
|
|
(void) memcpy (tt, type_table, NOBJTYPES);
|
|
(void) memcpy (ct, fclass_table, NCLASSES);
|
|
}
|
|
|
|
/* install a new copy of the type and class tables and update the buttons
|
|
* to match.
|
|
* this is to support sky history.
|
|
*/
|
|
void
|
|
svf_settables (tt, ct)
|
|
char tt[NOBJTYPES];
|
|
char ct[NCLASSES];
|
|
{
|
|
(void) memcpy (type_table, tt, NOBJTYPES);
|
|
(void) memcpy (fclass_table, ct, NCLASSES);
|
|
|
|
svf_reset();
|
|
}
|
|
|
|
/* return the current mag limits and mag step */
|
|
void
|
|
svf_getmaglimits (int *stmagp, int *ssmagp, int *dsmagp, int *magstpp)
|
|
{
|
|
*stmagp = stmag;
|
|
*ssmagp = ssmag;
|
|
*dsmagp = dsmag;
|
|
*magstpp = magstp;
|
|
}
|
|
|
|
/* set the current deep- and near-sky limit and mag step */
|
|
void
|
|
svf_setmaglimits (st, ss, ds, s)
|
|
int st, ss, ds, s;
|
|
{
|
|
stmag = st;
|
|
ssmag = ss;
|
|
dsmag = ds;
|
|
magstp = s;
|
|
XmScaleSetValue (stmag_w, stmag);
|
|
XmScaleSetValue (ssmag_w, ssmag);
|
|
XmScaleSetValue (dsmag_w, dsmag);
|
|
XmScaleSetValue (magst_w, s);
|
|
}
|
|
|
|
/* return 1 if p satisfies the stuff in the filter dialog, else 0.
|
|
* N.B. because svf_apply() has to have already been called we do not need
|
|
* to range check the type and class.
|
|
*/
|
|
int
|
|
svf_filter_ok (op)
|
|
Obj *op;
|
|
{
|
|
int tok;
|
|
|
|
if (is_type(op,FIXEDM))
|
|
tok = fclass_table[((int)op->f_class) & (NCLASSES-1)];
|
|
else
|
|
tok = type_table[op->o_type];
|
|
|
|
if (tok)
|
|
return (svf_bright_ok (op));
|
|
|
|
return (0);
|
|
}
|
|
|
|
/* called to put up or remove the watch cursor. */
|
|
void
|
|
svf_cursor (c)
|
|
Cursor c;
|
|
{
|
|
Window win;
|
|
|
|
if (filter_w && (win = XtWindow(filter_w)) != 0) {
|
|
Display *dsp = XtDisplay(filter_w);
|
|
if (c)
|
|
XDefineCursor (dsp, win, c);
|
|
else
|
|
XUndefineCursor (dsp, win);
|
|
}
|
|
}
|
|
|
|
/* establish faintest mags according to given fov */
|
|
void
|
|
svf_automag(fov)
|
|
double fov;
|
|
{
|
|
static AutoMag amdef = {degrad(360.0), 6, 6, 8, 1};
|
|
static AutoMag *amp;
|
|
static int namp;
|
|
int i;
|
|
|
|
/* establish table sorted in ascending order by r if first time */
|
|
if (namp == 0) {
|
|
namp = svf_initautomag (&);
|
|
if (namp <= 0) {
|
|
namp = 1;
|
|
amp = &amdef;
|
|
}
|
|
}
|
|
|
|
/* search for largest entry <= current fov */
|
|
for (i = 0; i < namp && fov > amp[i].r; i++)
|
|
continue;
|
|
i %= namp;
|
|
svf_setmaglimits (amp[i].st, amp[i].ss, amp[i].ds, amp[i].s);
|
|
}
|
|
|
|
/* create one FilterCat filter category in the given RowColumn */
|
|
static void
|
|
svf_create_filter (mainrc, fcp)
|
|
Widget mainrc;
|
|
FilterCat *fcp;
|
|
{
|
|
Arg args[20];
|
|
Widget l_w;
|
|
Widget rc_w; /* rc for the label and controls */
|
|
Widget fr_w, da_w;
|
|
Widget w;
|
|
int n;
|
|
int i;
|
|
|
|
/* make a rc within a frame for the tb rowcol */
|
|
|
|
n = 0;
|
|
fr_w = XmCreateFrame (mainrc, "Frame", args, n);
|
|
XtManageChild (fr_w);
|
|
n = 0;
|
|
XtSetArg (args[n], XmNmarginWidth, 0); n++;
|
|
XtSetArg (args[n], XmNisAligned, False); n++;
|
|
rc_w = XmCreateRowColumn (fr_w, "CategoryRC", args, n);
|
|
XtManageChild (rc_w);
|
|
|
|
/* make a label for the category */
|
|
|
|
n = 0;
|
|
XtSetArg (args[n], XmNalignment, XmALIGNMENT_BEGINNING); n++;
|
|
l_w = XmCreateLabel (rc_w, fcp->label, args, n);
|
|
wtip (l_w, fcp->ltip);
|
|
XtManageChild (l_w);
|
|
|
|
/* make a pushbutton used to toggle all entries in this category */
|
|
n = 0;
|
|
XtSetArg (args[n], XmNalignment, XmALIGNMENT_CENTER); n++;
|
|
w = XmCreatePushButton (rc_w, "Toggle", args, n);
|
|
wtip (w, "Toggle all selections in this category");
|
|
XtAddCallback (w, XmNactivateCallback, svf_cat_toggle_cb,
|
|
(XtPointer)fcp);
|
|
XtManageChild (w);
|
|
|
|
/* add each filter */
|
|
|
|
for (i = 0; i < fcp->nftb; i++) {
|
|
Widget f_w;
|
|
Widget tb_w;
|
|
FilterTB *ftbp = &fcp->ftb[i];
|
|
XmString str;
|
|
|
|
n = 0;
|
|
f_w = XmCreateForm (rc_w, "FTBF", args, n);
|
|
XtManageChild (f_w);
|
|
|
|
/* create a frame around a drawing area in which to show the
|
|
* object symbol
|
|
*/
|
|
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], XmNshadowType, XmSHADOW_ETCHED_OUT); n++;
|
|
fr_w = XmCreateFrame (f_w, "SymbolF", args, n);
|
|
XtManageChild (fr_w);
|
|
n = 0;
|
|
da_w = XmCreateDrawingArea (fr_w, "SymbolDA", args, n);
|
|
XtAddCallback (da_w, XmNexposeCallback, svf_da_cb,
|
|
(XtPointer)ftbp);
|
|
XtManageChild (da_w);
|
|
|
|
/* create the filter selection toggle button */
|
|
|
|
str = XmStringCreateLtoR (ftbp->label,XmSTRING_DEFAULT_CHARSET);
|
|
n = 0;
|
|
XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
|
|
XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
|
|
XtSetArg (args[n], XmNleftAttachment, XmATTACH_WIDGET); n++;
|
|
XtSetArg (args[n], XmNleftWidget, fr_w); n++;
|
|
XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
|
|
XtSetArg (args[n], XmNlabelString, str); n++;
|
|
XtSetArg (args[n], XmNalignment, XmALIGNMENT_BEGINNING); n++;
|
|
tb_w = XmCreateToggleButton (f_w, ftbp->name, args, n);
|
|
XmStringFree(str);
|
|
XtManageChild (tb_w);
|
|
ftbp->tbw = tb_w;
|
|
sr_reg (tb_w, NULL, skyfcategory, 0);
|
|
}
|
|
}
|
|
|
|
/* set the real filter states and the toggle button states according to the
|
|
* rapid-access tables.
|
|
* also, set the mag scales and dot scales from the real mag limits.
|
|
*/
|
|
static void
|
|
svf_reset()
|
|
{
|
|
int i, j;
|
|
|
|
for (i = 0; i < XtNumber(filters); i++) {
|
|
FilterCat *fcp = &filters[i];
|
|
for (j = 0; j < fcp->nftb; j++) {
|
|
FilterTB *ftbp = &fcp->ftb[j];
|
|
ftbp->state = (ftbp->type == FIXED)
|
|
? fclass_table[(int)ftbp->class] : type_table[ftbp->type];
|
|
XmToggleButtonSetState (ftbp->tbw, ftbp->state, True);
|
|
}
|
|
}
|
|
|
|
svf_setmaglimits (stmag, ssmag, dsmag, magstp);
|
|
}
|
|
|
|
/* set the real filter and rapid-access tables according to the present state
|
|
* of the toggle buttons.
|
|
* also set the mag limits and dot scale from their controls.
|
|
*/
|
|
static void
|
|
svf_apply()
|
|
{
|
|
int i, j;
|
|
|
|
for (i = 0; i < XtNumber(filters); i++) {
|
|
FilterCat *fcp = &filters[i];
|
|
for (j = 0; j < fcp->nftb; j++) {
|
|
FilterTB *ftbp = &fcp->ftb[j];
|
|
int t = ftbp->type;
|
|
if (t < 0 || t >= XtNumber(type_table)) {
|
|
printf ("svf_apply: type out of range: %d\n", t);
|
|
abort();
|
|
}
|
|
ftbp->state = XmToggleButtonGetState (ftbp->tbw);
|
|
if (t == FIXED) {
|
|
int c = (int)ftbp->class;
|
|
if (c < 0 || c >= XtNumber(fclass_table)) {
|
|
printf ("svf_apply: FIXED class out of range: %d\n", c);
|
|
abort();
|
|
}
|
|
fclass_table[c] = ftbp->state;
|
|
} else
|
|
type_table[t] = ftbp->state;
|
|
}
|
|
}
|
|
|
|
svtb_updateCTTT(fclass_table, type_table);
|
|
|
|
XmScaleGetValue (stmag_w, &stmag);
|
|
XmScaleGetValue (ssmag_w, &ssmag);
|
|
XmScaleGetValue (dsmag_w, &dsmag);
|
|
XmScaleGetValue (magst_w, &magstp);
|
|
}
|
|
|
|
/* return 1 if db object is ever possibly brighter than allowed range; else 0.
|
|
* don't worry too much, this is just a first-stage culling. real mag cutoff
|
|
* is done later.
|
|
*/
|
|
static int
|
|
svf_bright_ok(op)
|
|
Obj *op;
|
|
{
|
|
switch (op->o_type) {
|
|
case PLANET:
|
|
/* always just go for the planets */
|
|
return (1);
|
|
/* break; */
|
|
case HYPERBOLIC: return (1); /* and interlopers */
|
|
case PARABOLIC: return (1);
|
|
case ELLIPTICAL: {
|
|
double mag; /* magnitude */
|
|
double per, aph; /* perihelion and aphelion distance */
|
|
|
|
per = op->e_a*(1.0 - op->e_e);
|
|
aph = op->e_a*(1.0 + op->e_e);
|
|
if (per <= 1.1 && aph >= 0.9)
|
|
return (1); /* might be blazing in the back yard some day */
|
|
if (op->e_mag.whichm == MAG_HG)
|
|
mag = op->e_mag.m1 + 5*log10(per*fabs(per-1.0));
|
|
else
|
|
gk_mag(op->e_mag.m1, op->e_mag.m2,
|
|
per, fabs(per-1.0), &mag);
|
|
return (mag <= ssmag);
|
|
/* break; */
|
|
}
|
|
case FIXED: /* FALLTHRU */
|
|
case BINARYSTAR:
|
|
return (get_mag(op) <= (is_deepsky(op) ? dsmag : stmag));
|
|
/* break; */
|
|
case EARTHSAT:
|
|
/* TODO: work on satellite magnitudes someday */
|
|
return (1);
|
|
default:
|
|
printf ("sv_bright_ok(): bad type: %d\n", op->o_type);
|
|
abort();
|
|
return (0); /* for lint */
|
|
}
|
|
}
|
|
|
|
/* called when a symbol drawing area is exposed.
|
|
* client is a pointer to the FilterTB.
|
|
*/
|
|
/* ARGSUSED */
|
|
static void
|
|
svf_da_cb (w, client, call)
|
|
Widget w;
|
|
XtPointer client;
|
|
XtPointer call;
|
|
{
|
|
XmDrawingAreaCallbackStruct *c = (XmDrawingAreaCallbackStruct *)call;
|
|
FilterTB *ftbp = (FilterTB *) client;
|
|
|
|
switch (c->reason) {
|
|
case XmCR_EXPOSE: {
|
|
/* turn off gravity so we get expose events for either shrink or
|
|
* expand.
|
|
*/
|
|
static int before;
|
|
XExposeEvent *e = &c->event->xexpose;
|
|
|
|
if (!before) {
|
|
XSetWindowAttributes swa;
|
|
swa.bit_gravity = ForgetGravity;
|
|
XChangeWindowAttributes (e->display, e->window,
|
|
CWBitGravity, &swa);
|
|
before = 1;
|
|
}
|
|
/* wait for the last in the series */
|
|
if (e->count != 0)
|
|
return;
|
|
}
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
|
|
svf_draw_symbol(ftbp, w);
|
|
}
|
|
|
|
/* draw the symbol used for the object described by ftbp into the
|
|
* DrawingArea widget daw.
|
|
*/
|
|
static void
|
|
svf_draw_symbol(ftbp, daw)
|
|
FilterTB *ftbp;
|
|
Widget daw;
|
|
{
|
|
static GC gc;
|
|
static Pixel fg_p, bg_p;
|
|
Display *dsp = XtDisplay(daw);
|
|
Window win = XtWindow(daw);
|
|
Obj o;
|
|
Dimension w, h;
|
|
int diam;
|
|
|
|
zero_mem ((void *)&o, sizeof(Obj));
|
|
o.o_type = ftbp->type;
|
|
switch (ftbp->type) {
|
|
case BINARYSTAR:
|
|
o.b_nbp = 1; /* just to avoid orb ele calc */
|
|
break;
|
|
case FIXED:
|
|
o.f_class = ftbp->class;
|
|
set_ratio (&o, 2, 1);
|
|
set_pa (&o, PI/2);
|
|
break;
|
|
case PLANET:
|
|
o.s_phase = 100;
|
|
break;
|
|
}
|
|
|
|
get_something (daw, XmNwidth, (XtArgVal)&w);
|
|
get_something (daw, XmNheight, (XtArgVal)&h);
|
|
diam = (w > h ? h : w) - 2; /* allow for a small border */
|
|
|
|
if (!gc) {
|
|
get_something (daw, XmNforeground, (XtArgVal)&fg_p);
|
|
get_something (daw, XmNbackground, (XtArgVal)&bg_p);
|
|
gc = XCreateGC (dsp, win, 0L, NULL);
|
|
}
|
|
|
|
XSetForeground (dsp, gc, bg_p);
|
|
XFillRectangle (dsp, win, gc, 0, 0, w, h);
|
|
XSetForeground (dsp, gc, fg_p);
|
|
sv_draw_obj (dsp, win, gc, &o, (int)w/2-1, (int)h/2-1, diam, 0);
|
|
sv_draw_obj (dsp, win, gc, NULL, 0, 0, 0, 0); /* flush */
|
|
}
|
|
|
|
/* called when either mag scale is dragged */
|
|
/* ARGSUSED */
|
|
static void
|
|
svf_magdrag_cb (w, client, call)
|
|
Widget w;
|
|
XtPointer client;
|
|
XtPointer call;
|
|
{
|
|
sv_amagoff();
|
|
}
|
|
|
|
/* called when Apply is pushed on the filter dialog */
|
|
/* ARGSUSED */
|
|
static void
|
|
svf_apply_cb (w, client, call)
|
|
Widget w;
|
|
XtPointer client;
|
|
XtPointer call;
|
|
{
|
|
svf_apply();
|
|
sv_all(mm_get_now());
|
|
}
|
|
|
|
/* called when Ok is pushed on the filter dialog */
|
|
/* ARGSUSED */
|
|
static void
|
|
svf_ok_cb (w, client, call)
|
|
Widget w;
|
|
XtPointer client;
|
|
XtPointer call;
|
|
{
|
|
svf_apply();
|
|
sv_all(mm_get_now());
|
|
XtUnmanageChild (filter_w);
|
|
}
|
|
|
|
/* called when Close is pushed on the filter dialog */
|
|
/* ARGSUSED */
|
|
static void
|
|
svf_close_cb (w, client, call)
|
|
Widget w;
|
|
XtPointer client;
|
|
XtPointer call;
|
|
{
|
|
XtUnmanageChild (filter_w);
|
|
}
|
|
|
|
/* callback from the Help button.
|
|
*/
|
|
/* ARGSUSED */
|
|
static void
|
|
svf_help_cb (w, client, call)
|
|
Widget w;
|
|
XtPointer client;
|
|
XtPointer call;
|
|
{
|
|
static char *msg[] = {
|
|
"This allows settings the types of objects to display."
|
|
};
|
|
|
|
hlp_dialog ("SkyView_filter", msg, sizeof(msg)/sizeof(msg[0]));
|
|
}
|
|
|
|
/* called when Toggle is pushed on the filter dialog */
|
|
/* ARGSUSED */
|
|
static void
|
|
svf_toggle_cb (w, client, call)
|
|
Widget w;
|
|
XtPointer client;
|
|
XtPointer call;
|
|
{
|
|
int i, j;
|
|
|
|
for (i = 0; i < XtNumber(filters); i++) {
|
|
FilterCat *fcp = &filters[i];
|
|
for (j = 0; j < fcp->nftb; j++) {
|
|
FilterTB *ftbp = &fcp->ftb[j];
|
|
XmToggleButtonSetState (ftbp->tbw,
|
|
!XmToggleButtonGetState(ftbp->tbw), True);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* called when All is pushed on the filter dialog */
|
|
/* ARGSUSED */
|
|
static void
|
|
svf_all_cb (w, client, call)
|
|
Widget w;
|
|
XtPointer client;
|
|
XtPointer call;
|
|
{
|
|
int i, j;
|
|
|
|
for (i = 0; i < XtNumber(filters); i++) {
|
|
FilterCat *fcp = &filters[i];
|
|
for (j = 0; j < fcp->nftb; j++) {
|
|
FilterTB *ftbp = &fcp->ftb[j];
|
|
XmToggleButtonSetState (ftbp->tbw, True, True);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* called when Reset is pushed on the filter dialog */
|
|
/* ARGSUSED */
|
|
static void
|
|
svf_reset_cb (w, client, call)
|
|
Widget w;
|
|
XtPointer client;
|
|
XtPointer call;
|
|
{
|
|
svf_reset();
|
|
}
|
|
|
|
/* called when the "Toggle" button is activated on a particular category.
|
|
* client is the FilterCat pointer.
|
|
*/
|
|
/* ARGSUSED */
|
|
static void
|
|
svf_cat_toggle_cb (w, client, call)
|
|
Widget w;
|
|
XtPointer client;
|
|
XtPointer call;
|
|
{
|
|
FilterCat *fcp = (FilterCat *) client;
|
|
int i;
|
|
|
|
for (i = 0; i < fcp->nftb; i++) {
|
|
FilterTB *ftbp = &fcp->ftb[i];
|
|
XmToggleButtonSetState (ftbp->tbw,
|
|
!XmToggleButtonGetState(ftbp->tbw), True);
|
|
}
|
|
}
|
|
|
|
/* given two pointers to MagAuto, return how they sort by r in qsort-style.
|
|
*/
|
|
static int
|
|
am_cf (const void * v1, const void * v2)
|
|
{
|
|
AutoMag *am1 = (AutoMag *)v1;
|
|
AutoMag *am2 = (AutoMag *)v2;
|
|
double r1 = am1->r;
|
|
double r2 = am2->r;
|
|
|
|
if (r1 < r2)
|
|
return (-1);
|
|
if (r1 > r2)
|
|
return (1);
|
|
return (0);
|
|
}
|
|
|
|
/* digest the AutoMag resource.
|
|
* the format is five values in each group, groups separated by commas.
|
|
* each group is max fov, star mag, sol sys mag, deep sky mag, step-size.
|
|
* return number of entries and put into *ampp.
|
|
* array will be sorted into ascending order of fov radius.
|
|
* N.B. don't set *ampp unless we return > 0.
|
|
*/
|
|
static int
|
|
svf_initautomag(ampp)
|
|
AutoMag **ampp;
|
|
{
|
|
static char AMResource[] = "AutoMag";
|
|
double r;
|
|
int st, ss, ds, s;
|
|
AutoMag *amp;
|
|
int sam;
|
|
int namp;
|
|
char *am;
|
|
int i;
|
|
|
|
/* get the automag resource */
|
|
am = getXRes (AMResource, NULL);
|
|
if (!am) {
|
|
xe_msg (0, "No %s resource found", AMResource);
|
|
return (0);
|
|
}
|
|
|
|
/* scan for the quads -- build up amp as we go.
|
|
* stop at first sign of trouble.
|
|
*/
|
|
sam = sizeof(AutoMag);
|
|
amp = (AutoMag *)0;
|
|
namp = 0;
|
|
while (sscanf (am, "%lf %d %d %d %d", &r, &st, &ss, &ds, &s) == 5) {
|
|
char *new = amp ? realloc ((void *)amp, (namp+1)*sam) : malloc(sam);
|
|
AutoMag *tamp;
|
|
|
|
if (!new) {
|
|
xe_msg (0, "Insufficient memory for AutoMag table");
|
|
break;
|
|
}
|
|
amp = (AutoMag *)new;
|
|
tamp = &[namp++];
|
|
tamp->r = degrad(r);
|
|
tamp->st = st;
|
|
tamp->ss = ss;
|
|
tamp->ds = ds;
|
|
tamp->s = s;
|
|
|
|
/* skip past next comma */
|
|
while (*am != ',' && *am != '\0')
|
|
am++;
|
|
if (*am == '\0')
|
|
break;
|
|
am++;
|
|
}
|
|
|
|
if (namp == 0) {
|
|
xe_msg (0, "No valid entries in AutoMag resource");
|
|
return (0);
|
|
}
|
|
|
|
/* sort into ascending order of fov radius */
|
|
qsort ((void *)amp, namp, sizeof(AutoMag), am_cf);
|
|
|
|
/* report results to message log because the format is a bit obscure */
|
|
xe_msg(0, "Sky View found %d AutoMag table entries as follows:", namp);
|
|
xe_msg(0, " FOV Stars SolSys DeepSky DotSiz");
|
|
for (i = 0; i < namp; i++) {
|
|
xe_msg (0, " %6.2f %3d %3d %3d %3d",
|
|
raddeg(amp[i].r), amp[i].st, amp[i].ss, amp[i].ds, amp[i].s);
|
|
}
|
|
|
|
*ampp = amp;
|
|
return (namp);
|
|
}
|
|
|