/*
 * $Id: sv_draw.c,v 1.3 89/11/11 19:43:17 tynor Exp $
 *----------------------------------------------------------------------------
 *	FPLAN - Flight Planner
 *	Steve Tynor
 *	tynor@prism.gatech.edu
 *
 *	This program is in the public domain. Permission to copy,
 * distribute, modify this program is hearby given as long as this header
 * remains. If you redistribute this program after modifying it, please
 * document your changes so that I do not take the blame (or credit) for
 * those changes.  If you fix bugs or add features, please send me a
 * patch so that I can keep the 'official' version up-to-date.
 *
 *	Bug reports are welcome and I'll make an attempt to fix those
 * that are reported.
 *
 *	USE AT YOUR OWN RISK! I assume no responsibility for any
 * errors in this program, its database or documentation. I will make an
 * effort to fix bugs, but if you crash and burn because, for example,
 * fuel estimates in this program were inaccurate, it's your own fault
 * for trusting somebody else's code! Remember, as PIC, it's _your_
 * responsibility to do complete preflight planning. Use this program as
 * a flight planning aid, but verify its results before using them.
 *----------------------------------------------------------------------------
 */

#ifdef GFX_SUNVIEW 

/*
 *==============================================================================
 * Graphics routines for Sunview
 *==============================================================================
 */

#include "wp_info.h"
#include <suntool/sunview.h>
#include <suntool/canvas.h>
#include <suntool/panel.h>
#include <suntool/scrollbar.h>

static char rcsid[] = "$Id: sv_draw.c,v 1.3 89/11/11 19:43:17 tynor Exp $";

static double min_lat;
static double max_lat;
static double min_long;
static double max_long;

#define PIX_OR (PIX_SRC | PIX_DST) /* Rasterop */

Pixfont *font;
#define DEFAULT_SCALE 100 /* pixels per degree */
#define SV_MARGIN 40

Panel panel;
Frame frame;
Canvas canvas;
static BOOLEAN brief_mode;
int scale = DEFAULT_SCALE;
BOOLEAN first_time;
Scrollbar vert_scroll, horiz_scroll;

/*----------------------------------------------------------------------------*/
static void sv_draw_pt (canvas, x, y)
     Canvas canvas;
     int x, y;
{
   pw_writebackground (canvas_pixwin (canvas), x-1, y-1, 3, 3,
		       PIX_NOT (PIX_SRC));
}

/*----------------------------------------------------------------------------*/
static void sv_draw_str (canvas, x, y, str)
     Canvas canvas;
     int x, y;
     char *str;
{
   pw_text (canvas_pixwin (canvas), x+3, y+3, PIX_OR, font, str);
}

/*----------------------------------------------------------------------------*/
static void sv_project (latitude, longitude, x, y)
double latitude, longitude;
int *x, *y;
{
   /*
    * NOTE: this is "Tynor's naive projection system" - ignores the curvature
    * of the earth:
    */

   *x = SV_MARGIN + (int) ((max_long - longitude) * (double) scale);
   *y = SV_MARGIN + (int) ((max_lat - latitude  ) * (double) scale);
}

/*----------------------------------------------------------------------------*/
static void sv_draw_db (canvas, db)
     Canvas canvas;
     DATABASE_INFO *db;
{
   int x, y;

   sv_project (db->latitude, db->longitude, &x, &y);
   sv_draw_pt (canvas, x, y);
   sv_draw_str (canvas, x, y,
		 (db->mode != WP_INCREMENTAL) ? db->desig : db->name);
}

/*----------------------------------------------------------------------------*/
static void sv_draw_leg (canvas, db1, db2)
     Canvas canvas;
     DATABASE_INFO *db1, *db2;
{
   int x1, y1, x2, y2;

   sv_project (db1->latitude, db1->longitude, &x1, &y1);
   sv_project (db2->latitude, db2->longitude, &x2, &y2);

   pw_vector (canvas_pixwin (canvas), x1, y1, x2, y2, PIX_OR, 1);
}

/*----------------------------------------------------------------------------*/
static void sv_scroll_to (db)
     DATABASE_INFO *db;
{
   int x, y;

   sv_project (db->latitude, db->longitude, &x, &y);

   /*
    * try to center the waypoint on the canvas
    */
   scrollbar_scroll_to (horiz_scroll, 
			MIN ((int)window_get (canvas, CANVAS_WIDTH, 0),
			     MAX (0, 
				  x - (int)window_get (canvas, 
						       WIN_WIDTH, 0) / 2)));
   scrollbar_scroll_to (vert_scroll, 
			MIN ((int)window_get (canvas, CANVAS_HEIGHT, 0),
			     MAX (0, 
				  y - (int)window_get (canvas, 
						       WIN_HEIGHT, 0) / 2)));
}

/*----------------------------------------------------------------------------*/
static void sv_redraw ()
{
   int width, height, i;

#define MIN_WIDTH 400
#define XTRA_WIDTH   30 /* frame needs to be this much bigger than the canvas */
#define XTRA_HEIGHT 100 /* frame needs to be this much bigger than the canvas */

   width  = ABS ((int) ((max_long - min_long) * (double) scale)) + 
      2 * SV_MARGIN;
   height = ABS ((int) ((max_lat - min_lat)   * (double) scale)) +
      2 * SV_MARGIN;

   width = MAX (width, MIN_WIDTH);

   window_set (canvas, CANVAS_HEIGHT, height, 0);
   window_set (canvas, CANVAS_WIDTH, width, 0);

   pw_writebackground (canvas_pixwin (canvas), 0, 0, 3000, 3000, PIX_SRC);

   for (i = 0; i < num_cached; i++) {
      sv_draw_db (canvas, cache[i]);
   }

   for (i = 0; i < num_waypoints - 1; i++) {
      sv_draw_leg (canvas, waypoints[i].db, waypoints[i+1].db);
      if ((!brief_mode) && (waypoints[i].db->mode == WP_INCREMENTAL))
	 sv_draw_db (canvas, waypoints[i].db);
   }

   if (first_time) {
      Pixrect *screen = pr_open ("/dev/fb");

      window_set (frame, WIN_WIDTH, MIN (screen->pr_size.x, 
					 XTRA_WIDTH + width), 0);
      window_set (frame, WIN_HEIGHT, MIN (screen->pr_size.y,
					  XTRA_HEIGHT + height), 0);
      first_time = FALSE;
      sv_scroll_to (waypoints[0].db);
   }
}

/*----------------------------------------------------------------------------*/
sv_quit_event_proc (item, event)
     Panel_item item;
     Event *event;
{
   window_destroy (frame);
}

/*----------------------------------------------------------------------------*/
sv_brief_event_proc (item, event)
     Panel_item item;
     Event *event;
{
   brief_mode = (int) panel_get (item, PANEL_VALUE, 0);
   sv_redraw ();
}

/*----------------------------------------------------------------------------*/
sv_tofirst_event_proc (item, event)
     Panel_item item;
     Event *event;
{
   sv_scroll_to (waypoints[0].db);
}

/*----------------------------------------------------------------------------*/
sv_tolast_event_proc (item, event)
     Panel_item item;
     Event *event;
{
   sv_scroll_to (waypoints[num_waypoints-1].db);
}

/*----------------------------------------------------------------------------*/
sv_scale_event_proc (item, event)
     Panel_item item;
     Event *event;
{
   scale = (int) panel_get (item, PANEL_VALUE, 0);
   sv_redraw ();
}

/*----------------------------------------------------------------------------*/
void sv_draw (brief)
     BOOLEAN brief;
{

   min_max_lat_long (&min_lat, &max_lat, &min_long, &max_long);

   brief_mode = brief;
   font = pf_open ("/usr/lib/fonts/fixedwidthfonts/screen.r.7");

   frame = window_create (NULL, FRAME,
			  FRAME_LABEL, "FPLAN",
			  0);

   panel = window_create (frame, PANEL,
			  0);
   
   panel_create_item (panel, PANEL_BUTTON,
		      PANEL_NOTIFY_PROC, sv_quit_event_proc,
		      PANEL_LABEL_IMAGE, panel_button_image (panel,
							     "Quit", 0, 0),
		      PANEL_ITEM_X,	   ATTR_COL (0),
		      PANEL_ITEM_Y,	   ATTR_ROW (0),
		      0);

   panel_create_item (panel, PANEL_BUTTON,
		      PANEL_NOTIFY_PROC, sv_tofirst_event_proc,
		      PANEL_LABEL_IMAGE, panel_button_image (panel,
							     "To First", 0, 0),
		      0);

   panel_create_item (panel, PANEL_BUTTON,
		      PANEL_NOTIFY_PROC, sv_tolast_event_proc,
		      PANEL_LABEL_IMAGE, panel_button_image (panel,
							     "To Last", 0, 0),
		      0);

   panel_create_item (panel, PANEL_CYCLE,
		      PANEL_LABEL_STRING,   "Brief:",
		      PANEL_CHOICE_STRINGS, "NO", "YES", 0,
		      PANEL_NOTIFY_PROC,    sv_brief_event_proc,
		      PANEL_VALUE, 	    brief_mode,
		      0);		

   panel_create_item (panel, PANEL_SLIDER,
		      PANEL_LABEL_STRING, "Scale:",
		      PANEL_VALUE, 	   scale,
		      PANEL_MIN_VALUE, 	   5,
		      PANEL_MAX_VALUE, 	   400,
		      PANEL_SLIDER_WIDTH,  200,
		      PANEL_NOTIFY_PROC,   sv_scale_event_proc,
		      0);		

   window_fit_height (panel);

   horiz_scroll = scrollbar_create(0);
   vert_scroll = scrollbar_create(0);

   canvas = window_create (frame, CANVAS,
			   CANVAS_AUTO_SHRINK, FALSE,
			   WIN_VERTICAL_SCROLLBAR, vert_scroll,
			   WIN_HORIZONTAL_SCROLLBAR, horiz_scroll,
			   CANVAS_WIDTH, 1,
			   CANVAS_HEIGHT, 1,
			   0);
   scrollbar_set (horiz_scroll, SCROLL_ADVANCED_MODE, 1, 0);
   scrollbar_set (vert_scroll, SCROLL_ADVANCED_MODE, 1, 0);

   first_time = TRUE;
   sv_redraw ();
   window_main_loop (frame);
}

#endif /* GFX_SUNVIEW */
