home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / x / volume19 / xephem / part20 / moonmenu.c < prev    next >
C/C++ Source or Header  |  1993-05-15  |  15KB  |  526 lines

  1. /* code to manage the stuff on the moon display.
  2.  */
  3.  
  4. #include <stdio.h>
  5. #include <ctype.h>
  6. #include <math.h>
  7. #if defined(__STDC__)
  8. #include <stdlib.h>
  9. #endif
  10. #include <X11/Xlib.h>
  11. #include <Xm/Xm.h>
  12. #include <Xm/Form.h>
  13. #include <Xm/Frame.h>
  14. #include <Xm/DrawingA.h>
  15. #include <Xm/Label.h>
  16. #include <Xm/PushB.h>
  17. #include <Xm/ToggleB.h>
  18. #include <Xm/Text.h>
  19. #include "astro.h"
  20. #include "circum.h"
  21.  
  22.  
  23. extern Widget toplevel_w;
  24.  
  25. #if defined(__STDC__) || defined(__cplusplus)
  26. #define P_(s) s
  27. #else
  28. #define P_(s) ()
  29. #endif
  30.  
  31. extern Now *mm_get_now P_((void));
  32. extern Obj *db_basic P_((int id));
  33. extern void db_update P_((Obj *op));
  34. extern void get_something P_((Widget w, char *resource, char *value));
  35. extern void timestamp P_((Now *np, Widget w));
  36.  
  37. void m_manage P_((void));
  38. int m_ison P_((void));
  39. void m_update P_((Now *np, int how_much));
  40. void m_cursor P_((Cursor c));
  41. static void m_create_form P_((void));
  42. static void m_close_cb P_((Widget w, XtPointer client, XtPointer call));
  43. static void m_mapvw_cb P_((Widget w, XtPointer client, XtPointer call));
  44. static void m_eshine_cb P_((Widget w, XtPointer client, XtPointer call));
  45. static void m_da_exp_cb P_((Widget w, XtPointer client, XtPointer call));
  46. static void m_draw P_((int force));
  47. static void m_draw_mapview P_((double el));
  48. static void m_draw_grview P_((double el));
  49.  
  50. #undef P_
  51.  
  52. /* get the small moonbit map and its dimension defines.
  53.  * moon is roughly centered within the map, with a radius of some 200 pixels.
  54.  * exact values set by trial and error.
  55.  */
  56. #include "smallfm.xbm"
  57. #define    MRAD    191                /* radius of moon image */
  58. #define    TOPMAR    (smallfm_height/2 - MRAD + 2)    /* top margin */
  59. #define    LEFTMAR    (smallfm_width/2 - MRAD)    /* left margin */
  60.  
  61. #define    NSTARS    300    /* number of fake background stars in graphical view */
  62.  
  63. static Widget mform_w;        /* main moon form dialog */
  64. static Widget mda_w;        /* moon drawring area */
  65. static Widget eshine_w;        /* whether we want to show earthshine */
  66. static Widget mapvw_w;        /* toggle button that selects which view */
  67. static Widget dt_w;        /* date/time stamp widget */
  68.  
  69. #define    MAPVW_W    (smallfm_width+20)
  70. #define    MAPVW_H    (smallfm_height+40)
  71.  
  72. /* called when the moon view is activated via the main menu pulldown.
  73.  * if never called before, create and manage all the widgets as a child of a
  74.  * form. otherwise, just toggle whether the form is managed.
  75.  */
  76. void
  77. m_manage ()
  78. {
  79.     if (!mform_w)
  80.         m_create_form();
  81.     
  82.     if (XtIsManaged(mform_w))
  83.         XtUnmanageChild (mform_w);
  84.     else {
  85.         XtManageChild (mform_w);
  86.         /* let the initial expose do the drawing */
  87.     }
  88. }
  89.  
  90. m_ison()
  91. {
  92.     return (mform_w && XtIsManaged(mform_w));
  93. }
  94.  
  95. void
  96. m_update (np, how_much)
  97. Now *np;
  98. int how_much;
  99. {
  100.     if (!mform_w || !XtIsManaged(mform_w))
  101.         return;
  102.  
  103.     m_draw (how_much);
  104.     timestamp (np, dt_w);
  105. }
  106.  
  107. /* called to put up or remove the watch cursor.  */
  108. void
  109. m_cursor (c)
  110. Cursor c;
  111. {
  112.     Window win;
  113.  
  114.     if (mform_w && (win = XtWindow(mform_w))) {
  115.         Display *dsp = XtDisplay(mform_w);
  116.         if (c)
  117.         XDefineCursor (dsp, win, c);
  118.         else
  119.         XUndefineCursor (dsp, win);
  120.     }
  121. }
  122.  
  123. static void
  124. m_create_form()
  125. {
  126.     Widget frame_w;
  127.     Widget f_w, fr_w;
  128.     Widget w;
  129.     XmString str;
  130.     Arg args[20];
  131.     int n;
  132.  
  133.     /* create master form */
  134.     n = 0;
  135.     XtSetArg (args[n], XmNautoUnmanage, False); n++;
  136.     XtSetArg (args[n], XmNhorizontalSpacing, 5); n++;
  137.     XtSetArg (args[n], XmNverticalSpacing, 5); n++;
  138.     XtSetArg (args[n], XmNdefaultPosition, False); n++;
  139.     mform_w = XmCreateFormDialog (toplevel_w, "Moon", args, n);
  140.  
  141.     /* set some stuff in the parent DialogShell.
  142.      * setting XmNdialogTitle in the Form didn't work..
  143.      */
  144.     n = 0;
  145.     XtSetArg (args[n], XmNtitle, "xephem Moon View"); n++;
  146.     XtSetValues (XtParent(mform_w), args, n);
  147.  
  148.     /* make a Form to hold the bottom controls */
  149.  
  150.     n = 0;
  151.     XtSetArg (args[n], XmNfractionBase, 13); n++;
  152.     XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
  153.     XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  154.     XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  155.     f_w = XmCreateForm (mform_w, "MoonCtlForm", args, n);
  156.     XtManageChild (f_w);
  157.  
  158.         /* make the close button */
  159.  
  160.         n = 0;
  161.         XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
  162.         XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
  163.         XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
  164.         XtSetArg (args[n], XmNleftPosition, 1); n++;
  165.         XtSetArg (args[n], XmNrightAttachment, XmATTACH_POSITION); n++;
  166.         XtSetArg (args[n], XmNrightPosition, 4); n++;
  167.         w = XmCreatePushButton (f_w, "Close", args, n);
  168.         XtAddCallback (w, XmNactivateCallback, m_close_cb, 0);
  169.         XtManageChild (w);
  170.  
  171.         /* make the earthshine toggle button in a frame */
  172.  
  173.         n = 0;
  174.         XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
  175.         XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
  176.         XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
  177.         XtSetArg (args[n], XmNleftPosition, 5); n++;
  178.         XtSetArg (args[n], XmNrightAttachment, XmATTACH_POSITION); n++;
  179.         XtSetArg (args[n], XmNrightPosition, 8); n++;
  180.         fr_w = XmCreateFrame (f_w, "EarthshineFr", args, n);
  181.         XtManageChild (fr_w);
  182.         eshine_w = XmCreateToggleButton (fr_w, "Earthshine", args, n);
  183.         XtAddCallback (eshine_w, XmNvalueChangedCallback, m_eshine_cb, 0);
  184.         XtManageChild (eshine_w);
  185.  
  186.         /* make the view option toggle button in a frame */
  187.  
  188.         n = 0;
  189.         XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
  190.         XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
  191.         XtSetArg (args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
  192.         XtSetArg (args[n], XmNleftPosition, 9); n++;
  193.         XtSetArg (args[n], XmNrightAttachment, XmATTACH_POSITION); n++;
  194.         XtSetArg (args[n], XmNrightPosition, 12); n++;
  195.         fr_w = XmCreateFrame(f_w,"MMapViewFr", args, n);
  196.         XtManageChild (fr_w);
  197.         str = XmStringCreate("Bitmap View", XmSTRING_DEFAULT_CHARSET);
  198.         n = 0;
  199.         XtSetArg (args[n], XmNlabelString, str); n++;
  200.         mapvw_w = XmCreateToggleButton(fr_w, "BitmapView", args, n);
  201.         XtAddCallback(mapvw_w, XmNvalueChangedCallback, m_mapvw_cb, 0);
  202.         XtManageChild (mapvw_w);
  203.         XmStringFree (str);
  204.  
  205.     /* make a label for the date stamp */
  206.  
  207.     n = 0;
  208.     XtSetArg (args[n], XmNbottomAttachment, XmATTACH_WIDGET); n++;
  209.     XtSetArg (args[n], XmNbottomWidget, f_w); n++;
  210.     XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  211.     XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  212.     XtSetArg (args[n], XmNrecomputeSize, False); n++;
  213.     dt_w = XmCreateLabel (mform_w, "DateStamp", args, n);
  214.     timestamp (mm_get_now(), dt_w);    /* sets initial size */
  215.     XtManageChild (dt_w);
  216.  
  217.     /* make a frame for the drawing area */
  218.  
  219.     n = 0;
  220.     XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
  221.     XtSetArg (args[n], XmNbottomAttachment, XmATTACH_WIDGET); n++;
  222.     XtSetArg (args[n], XmNbottomWidget, dt_w); n++;
  223.     XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  224.     XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  225.     XtSetArg (args[n], XmNshadowType, XmSHADOW_ETCHED_OUT); n++;
  226.     frame_w = XmCreateFrame (mform_w, "MoonFrame", args, n);
  227.     XtManageChild (frame_w);
  228.  
  229.     /* make a drawing area in the frame for the sky */
  230.     n = 0;
  231.     XtSetArg (args[n], XmNwidth, MAPVW_W); n++;
  232.     XtSetArg (args[n], XmNheight, MAPVW_H); n++;
  233.     XtSetArg (args[n], XmNmarginWidth, 0); n++;
  234.     XtSetArg (args[n], XmNmarginHeight, 0); n++;
  235.     mda_w = XmCreateDrawingArea (frame_w, "MoonDA", args, n);
  236.     XtManageChild (mda_w);
  237.     XtAddCallback (mda_w, XmNexposeCallback, m_da_exp_cb, 0);
  238. }
  239.  
  240. /* callback from the Close button.
  241.  */
  242. /* ARGSUSED */
  243. static void
  244. m_close_cb (w, client, call)
  245. Widget w;
  246. XtPointer client;
  247. XtPointer call;
  248. {
  249.     XtUnmanageChild (mform_w);
  250. }
  251.  
  252. /* callback from the Map view toggle button.
  253.  */
  254. /* ARGSUSED */
  255. static void
  256. m_mapvw_cb (w, client, call)
  257. Widget w;
  258. XtPointer client;
  259. XtPointer call;
  260. {
  261.     m_update (mm_get_now(), 1);
  262. }
  263.  
  264. /* callback from the earthshine toggle button.
  265.  */
  266. /* ARGSUSED */
  267. static void
  268. m_eshine_cb (w, client, call)
  269. Widget w;
  270. XtPointer client;
  271. XtPointer call;
  272. {
  273.     m_update (mm_get_now(), 1);
  274. }
  275.  
  276. /* expose (or reconfig) of moon drawing area.
  277.  * just redraw the scene to the current window size.
  278.  */
  279. /* ARGSUSED */
  280. static void
  281. m_da_exp_cb (w, client, call)
  282. Widget w;
  283. XtPointer client;
  284. XtPointer call;
  285. {
  286.     XmDrawingAreaCallbackStruct *c = (XmDrawingAreaCallbackStruct *)call;
  287.  
  288.     switch (c->reason) {
  289.     case XmCR_EXPOSE: {
  290.         /* turn off gravity so we get expose events for either shrink or
  291.          * expand.
  292.          */
  293.         static before;
  294.         XExposeEvent *e = &c->event->xexpose;
  295.  
  296.         if (!before) {
  297.         XSetWindowAttributes swa;
  298.         swa.bit_gravity = ForgetGravity;
  299.         XChangeWindowAttributes (e->display, e->window,
  300.                                 CWBitGravity, &swa);
  301.         before = 1;
  302.         }
  303.         /* wait for the last in the series */
  304.         if (e->count != 0)
  305.         return;
  306.         break;
  307.         }
  308.     default:
  309.         printf ("Unexpected mda_w event. type=%d\n", c->reason);
  310.         exit(1);
  311.     }
  312.  
  313.     m_update (mm_get_now(), 1);
  314. }
  315.  
  316. /* draw moon, always if force or scene has changed.
  317.  */
  318. static void
  319. m_draw (force)
  320. int force;
  321. {
  322.     static double last_el;
  323.     Obj *op;
  324.     double el;
  325.  
  326.     /* get new elongation */
  327.     op = db_basic (MOON);
  328.     db_update (op);
  329.     el = degrad(op->s_elong);
  330.  
  331.     /* don't bother if not forcing and hasn't changed 1 degree */
  332.     if (!force && fabs (el - last_el) < degrad(1.0))
  333.         return;
  334.     last_el = el;
  335.  
  336.     if (XmToggleButtonGetState(mapvw_w)) {
  337.         /* drawing pixmap view so insure a good initial size at least
  338.          */
  339.         Arg args[20];
  340.         int n;
  341.  
  342.         n = 0;
  343.         XtSetArg (args[n], XmNwidth, MAPVW_W); n++;
  344.         XtSetArg (args[n], XmNheight, MAPVW_H); n++;
  345.         XtSetValues (mda_w, args, n);
  346.         XtManageChild (XtParent(eshine_w));
  347.         XtManageChild (eshine_w);
  348.         m_draw_mapview (el);
  349.     } else {
  350.         /* want graphical view */
  351.         XtUnmanageChild (eshine_w);
  352.         XtUnmanageChild (XtParent(eshine_w));
  353.         m_draw_grview (el);
  354.     }
  355. }
  356.  
  357. /* version that draws moon using genuine bitmap image. */
  358. static void
  359. m_draw_mapview (el)
  360. double el;
  361. {
  362.     static GC m_fgc;
  363.     Display *dsp = XtDisplay (mda_w);
  364.     Window win = XtWindow (mda_w);
  365.     double cosel;
  366.     XImage *xim;
  367.     unsigned char *m;
  368.     int y;    /* y coord: 0 is center, up is + */
  369.     int earthshine = XmToggleButtonGetState(eshine_w);
  370.  
  371.     if (!m_fgc) {
  372.         /* make gc from MoonDA colors
  373.          */
  374.         XGCValues gcv;
  375.         unsigned int gcm;
  376.  
  377.         gcm = GCForeground | GCBackground;
  378.         get_something (mda_w, XmNforeground, (char *)&gcv.background);
  379.         get_something (mda_w, XmNbackground, (char *)&gcv.foreground);
  380.  
  381.         m_fgc = XCreateGC (dsp, win, gcm, &gcv);
  382.     }
  383.  
  384.     /* make a copy so we can darken some of it */
  385.     m = (unsigned char *)XtMalloc(smallfm_width*smallfm_height/8);
  386.     (void) memcpy (m, smallfm_bits, smallfm_width*smallfm_height/8);
  387.  
  388.     cosel = cos(el);
  389.     for (y = MRAD; y > -MRAD; y--) {
  390.         int lx, rx;    /* left and right edge of scan line to darken */
  391.         int r, c;    /* X row/col coords */
  392.         lx = -sqrt((double)(MRAD*MRAD - y*y));
  393.         rx = -lx * cosel;
  394.         if (el < 0) {
  395.         int tmp = rx;
  396.         rx = -lx;
  397.         lx = -tmp;
  398.         }
  399.         r = TOPMAR + MRAD - y;
  400.         for (c = LEFTMAR + MRAD + lx; c < LEFTMAR + MRAD + rx; c++)
  401.         if (!earthshine || (c & 3) != 3 || (y & 3) != 3)
  402.             m[r*smallfm_width/8 + c/8] |= (1 << (c%8)); /* 1 is bkgnd */
  403.     }
  404.  
  405.     xim = XCreateImage (dsp, XDefaultVisual (dsp, 0),
  406.         /* depth */        1,
  407.         /* format */    XYBitmap, 
  408.         /* offset */    0,
  409.         /* data */        (char *)m,
  410.         /* width */        smallfm_width, 
  411.         /* height */    smallfm_height,
  412.         /* pad */        8,
  413.         /* bpl */        0);
  414.     xim->bitmap_bit_order = LSBFirst;
  415.     xim->byte_order = LSBFirst;
  416.  
  417.     XPutImage (dsp, win, m_fgc, xim, 0, 0, 0, 0,
  418.                         smallfm_width, smallfm_height);
  419.     XDestroyImage (xim);    /* also frees m */
  420. }
  421.  
  422. /* version that draws moon using just simple graphics */
  423. static void
  424. m_draw_grview (el)
  425. double el;
  426. {
  427.     static GC m_fgc, m_bgc;
  428.     static XPoint *stars;
  429.     static int last_w, last_h;
  430.     Display *dsp = XtDisplay (mda_w);
  431.     Window win = XtWindow (mda_w);
  432.     Window root;
  433.     int x, y;
  434.     unsigned int bw, d;
  435.     unsigned w, h;        /* actual size of drawing area window */
  436.     unsigned md;        /* moon circle diameter */
  437.     int la1, la2, ta1, ta2; /* limb and terminator start and extent */
  438.     int wid;        /* distance from meridian to terminator */
  439.     int xb, yb;        /* x and y borders, eg, (w-nx)/2 */
  440.     Pixmap pm;
  441.  
  442.     if (!m_fgc) {
  443.         /* make gcs from MoonDA colors
  444.          */
  445.         XGCValues gcv;
  446.         unsigned int gcm;
  447.  
  448.         gcm = GCForeground | GCBackground;
  449.         get_something (mda_w, XmNforeground, (char *)&gcv.foreground);
  450.         get_something (mda_w, XmNbackground, (char *)&gcv.background);
  451.         m_fgc = XCreateGC (dsp, win, gcm, &gcv);
  452.  
  453.         get_something (mda_w, XmNbackground, (char *)&gcv.foreground);
  454.         get_something (mda_w, XmNforeground, (char *)&gcv.background);
  455.         m_bgc = XCreateGC (dsp, win, gcm, &gcv);
  456.     }
  457.  
  458.  
  459.     /* get size of window now and make a fresh pixmap to match.
  460.      * we draw the scene in the pixmap then copy it to the window.
  461.      * otherwise, you can see it drawing and it flashes and looks ugly.
  462.      */
  463.     XGetGeometry (dsp, win, &root, &x, &y, &w, &h, &bw, &d);
  464.     pm = XCreatePixmap (dsp, win, w, h, d);
  465.     XFillRectangle (dsp, pm, m_bgc, 0, 0, w, h);
  466.  
  467.     /* set moon diameter so it is centered within the bounding rectangle
  468.      * of the window.
  469.      * this code sets it to match the borders of the map view and makes
  470.      * the diameter even so it divides evenly.
  471.      */
  472.     md = ((w > h) ? MRAD*h/(MRAD+TOPMAR) : MRAD*w/(MRAD+LEFTMAR)) & (~1);
  473.     xb = (w - md)/2;
  474.     yb = (h - md)/2;
  475.  
  476.     la1 = el >= 0.0 ? -90*64 : 90*64;
  477.     la2 = 180*64;
  478.     wid = fabs(md/2*cos(el))+0.5;
  479.     ta1 = el >= PI/2 || (el <= 0 && el >= -PI/2) ? 90*64 : -90*64;
  480.     ta2 = 180*64;
  481.  
  482.     /* dsp, win, gc, x, y, w, h, start_ang, ang_extent */
  483.     /* draw the lit hemisphere to the limb */
  484.     XFillArc (dsp, pm, m_fgc, xb, yb, md, md, la1, la2);
  485.  
  486.     /* draw the portion from the terminator to the meridian */
  487.     if (la1 < 0 && ta1 < 0 || la1 > 0 && ta1 > 0) {
  488.         /* crescent, so draw in background color */
  489.         XFillArc (dsp, pm, m_bgc, md/2-wid+xb, yb, 2*wid, md, ta1, ta2);
  490.     } else {
  491.         /* gibbous, so draw in foreground color */
  492.         XFillArc (dsp, pm, m_fgc, md/2-wid+xb, yb, 2*wid, md, ta1, ta2);
  493.     }
  494.  
  495.     /* add in the background stars */
  496.     if (!stars || last_w != w || last_h != h) {
  497.         /* sprinkle NSTARS stars outside the moon's circle of radius r.
  498.          */
  499.         double rr = 0.25*md*md; /* = (md/2)*(md/2); */
  500.         int i;
  501.         if (stars)
  502.         XtFree ((char *)stars);
  503.         stars = (XPoint *) XtMalloc (NSTARS * sizeof(XPoint));
  504.         for (i = 0; i < NSTARS; ) {
  505.         x = ((rand() >> 2) & 0xfff) * (w-1) / 0xfff;
  506.         y = ((rand() >> 2) & 0xfff) * (h-1) / 0xfff;
  507.         /* compare the candidate y with the y on the ellipse at the
  508.          * candidate x to decide whether to draw the point.
  509.          */
  510. #define        SQR(x) ((x)*(x))
  511.         if (SQR(y-h/2) > rr - SQR(x-w/2)) {
  512.             stars[i].x = (short)x;
  513.             stars[i].y = (short)y;
  514.             i++;
  515.         }
  516.         }
  517.     }
  518.     XDrawPoints (dsp, pm, m_fgc, stars, NSTARS, CoordModeOrigin);
  519.  
  520.     XCopyArea (dsp, pm, win, m_fgc, 0, 0, w, h, 0, 0);
  521.     XFreePixmap (dsp, pm);
  522.  
  523.     last_w = w;
  524.     last_h = h;
  525. }
  526.