/*****************************************************************************/
/*  pyth   -   Draw the 'Tree of Pythagoras'  -   Version 1.0                */
/*                                                                           */
/*                 Copyright (c) 1992 by Carsten Tschach                     */
/*****************************************************************************/

#include <stdio.h>
#include <X11/Xlib.h>
#include <xview/xview.h>
#include <xview/panel.h>
#include <xview/notice.h>
#include <xview/canvas.h>
#include <xview/svrimage.h>
#include <xview/icon.h>
#include <xview/xv_xrect.h>


#define  FrameSizeX        650
#define  FrameSizeY        450


#define pyth_width         64
#define pyth_height        64

short pyth_bits[] = {
#include "pyth.icon"
};




Frame         frame, subframe;
Panel         panel, subpanel;
Canvas        canvas;
Display       *display;
Window        Canvas_window;
GC            gc;
int           CanvasSizeX, CanvasSizeY;

int           Iteration = 8;


/*****************************************************************************/
/*                    M A I N  -  P R O C E D U R E                          */
/****************************************************************************/

main(argc, argv)
int   argc;
char *argv[];
{
  Icon          icon;
  Server_image  pyth_icon;

  void quit_program();
  void show_info();
  void redraw_image();
  void resize_image();
  void draw_new_iteration();

  xv_init(XV_INIT_ARGC_PTR_ARGV, &argc, argv, NULL);

  frame = (Frame) xv_create(NULL, FRAME,
			    XV_WIDTH,           (int) FrameSizeX,
			    XV_HEIGHT,          (int) FrameSizeY,
			    FRAME_LABEL,        argv[0],
			    FRAME_SHOW_FOOTER,  TRUE,
			    NULL);

  panel = (Panel) xv_create(frame, PANEL, NULL);

  xv_create(panel, PANEL_BUTTON,
	    PANEL_LABEL_STRING, "Quit",
	    PANEL_NOTIFY_PROC,  quit_program,
	    NULL);

  xv_create(panel, PANEL_BUTTON,
	    PANEL_LABEL_STRING, "Info",
	    PANEL_NOTIFY_PROC,  show_info, 
	    NULL);

  xv_create(panel, PANEL_SLIDER,
	    PANEL_LABEL_STRING,     "Iteration: ",
	    PANEL_VALUE,            Iteration,
	    PANEL_MIN_VALUE,        1,
	    PANEL_MAX_VALUE,        18,
	    PANEL_SLIDER_WIDTH,     200,
	    PANEL_NOTIFY_PROC,      draw_new_iteration,
	    NULL);

  canvas = (Canvas)xv_create(frame, CANVAS,
			     XV_Y,                  50,
			     CANVAS_X_PAINT_WINDOW, TRUE,
			     NULL);

  display        = (Display *)xv_get(frame, XV_DISPLAY, NULL);
  Canvas_window  = (Window)   xv_get(canvas_paint_window(canvas), XV_XID,NULL);
  gc             = DefaultGC(display, DefaultScreen(display));

  xv_set(canvas, CANVAS_REPAINT_PROC, redraw_image,
	         CANVAS_RESIZE_PROC,  resize_image,
	         NULL);


  create_info();

  pyth_icon = (Server_image)xv_create(NULL, SERVER_IMAGE,
				      XV_WIDTH,             pyth_width,
				      XV_HEIGHT,            pyth_height,
				      SERVER_IMAGE_BITS,    pyth_bits,
				      NULL);

  icon = (Icon)xv_create(frame, ICON,
			 ICON_TRANSPARENT,    TRUE,
			 ICON_IMAGE,          pyth_icon,
			 XV_X,                100,
			 XV_Y,                100,
			 NULL);

  xv_set(frame, FRAME_ICON, icon, NULL);


  xv_main_loop(frame);
}



/*****************************************************************************/
/* Procedures for exiting the program after user confirmation                */
/*****************************************************************************/

void quit_program(item, event)
Panel_item     item;
Event          *event;
{
  int          result;

  result = notice_prompt(panel, NULL,
		 NOTICE_FOCUS_XY,        event_x(event), event_y(event),
		 NOTICE_MESSAGE_STRINGS, "Do you really want to quit ?", NULL,
		 NOTICE_BUTTON_YES,      "Yes",
		 NOTICE_BUTTON_NO,       "No",
		 NULL);

  if (result == NOTICE_YES) {
    xv_destroy_safe(frame);
    exit(0);
  }
}


/*****************************************************************************/
/* Procedures for displaying the program-info                                */
/*****************************************************************************/

create_info()
{
  void wait_for_info_ok();


  subframe = (Frame)xv_create(frame, FRAME_CMD,
			      XV_WIDTH,    10,
			      XV_HEIGHT,   10,
			      FRAME_LABEL, "Info about pyth",
			      NULL);

  subpanel = (Panel)xv_create(subframe, PANEL, NULL);
  
  (void) xv_create(subpanel, PANEL_MESSAGE,
		   PANEL_LABEL_STRING, 
		   "      pyth 1.0   -   Tree of Pythagoras",
		   NULL);

  (void) xv_create(subpanel, PANEL_MESSAGE,
		   PANEL_NEXT_ROW,     -2,
		   PANEL_LABEL_STRING,
		   " Copyright (c) 1992 by Carsten Tschach",
		   NULL);

  (void) xv_create(subpanel, PANEL_BUTTON,
		   PANEL_NEXT_ROW,     -3,
		   XV_X,               110,
		   PANEL_LABEL_STRING, "Ok",
		   PANEL_NOTIFY_PROC,  wait_for_info_ok,
		   NULL);
    
    window_fit(subpanel);
    window_fit(subframe); 
}  


void show_info()
{
  xv_set(subframe, XV_SHOW, TRUE, NULL);
}


void wait_for_info_ok(item, event)
Panel_item     item;
Event          *event;
{
  if ((int)xv_get(subframe, FRAME_CMD_PUSHPIN_IN) == FALSE)
    xv_set(subframe, XV_SHOW, FALSE, NULL);
}


/*****************************************************************************/
/* Procedure */



/*Window        xwin; */
/*GC            gc;
int           maxx, maxy; */

void redraw_image(canvas, paint_win, disp, win, xrects)
Canvas        canvas;
Xv_Window     paint_win;
Display       *disp;
Window        win; 
Xv_xrectlist  *xrects;
{
/*  xwin    = win;  */

  CanvasSizeX = (int) xv_get(canvas, CANVAS_WIDTH,  NULL);
  CanvasSizeY = (int) xv_get(canvas, CANVAS_HEIGHT, NULL);

  draw_full_tree();  
}

/*****************************************************************************/
/* Procedures for redrawing the tree after the windowsize changed            */
/*****************************************************************************/

void resize_image(canvas, width, height)
Canvas        canvas;
int           width, height;
{
  CanvasSizeX = width;
  CanvasSizeY = height;

  xv_set(canvas, CANVAS_HEIGHT, height, NULL);
  xv_set(canvas, CANVAS_WIDTH,  width,  NULL);

  XClearWindow(display, Canvas_window);  

  draw_full_tree(); 
}


/*****************************************************************************/
/* Procedure for redrawing the tree with a new iteration                     */
/*****************************************************************************/

void draw_new_iteration(item, value, event)
Panel_item    item;
int           value;
Event         *event;
{
  if (Iteration > value) XClearWindow(display, Canvas_window); 
  
  Iteration = (int)value;

  draw_full_tree();
}


/*****************************************************************************/
/* Procedures for drawing the tree                                           */
/*****************************************************************************/

draw_full_tree()
{
  xv_set(frame, FRAME_BUSY, TRUE, NULL);

  draw_tree((float)(-CanvasSizeX / 10.0), 0.0, 
	    (float)( CanvasSizeY / 20.0), 0.0, Iteration);

  xv_set(frame, FRAME_BUSY, FALSE, NULL);
}


draw_tree(a1, a2, b1, b2, t)
float           a1, a2, b1, b2;
int             t;
{
  float         n1, n2, c1, c2, d1, d2, e1, e2; 

  if (t > 0)
    {
      n1 = -b2 + a2;   n2 = -a1 + b1;
      c1 =  b1 + n1;   c2 =  b2 + n2;
      d1 =  a1 + n1;   d2 =  a2 + n2;
      draw_line(a1, a2, b1, b2); 
      draw_line(b1, b2, c1, c2);
      draw_line(c1, c2, d1, d2);
      draw_line(d1, d2, a1, a2);
      e1 = d1 + 0.36 * (c1 - d1) + 0.48 * n1;
      e2 = d2 + 0.36 * (c2 - d2) + 0.48 * n2;
      draw_tree(e1, e2, c1, c2, (t - 1));
      draw_tree(d1, d2, e1, e2, (t - 1));
    } 
}
  

/*****************************************************************************/
/* Procedure for drawing a line                                              */
/****************************************************************************/

draw_line(a1, a2, b1, b2)
float         a1, a2, b1, b2;
{
  int         c1, c2, d1, d2;


  c1 = (int) (CanvasSizeX / 2 + a1);   c2 = (int) a2 + 20;
  d1 = (int) (CanvasSizeX / 2 + b1);   d2 = (int) b2 + 20;

  XDrawLine(display, Canvas_window, gc, c1, CanvasSizeY - c2 - 1, 
	                                d1, CanvasSizeY - d2 - 1);
}
  










