#include <stdio.h>

#include <Xm/Xm.h>
#include <Xm/DrawingA.h>
#include <Xm/RowColumn.h>
#include <Xm/PushB.h>
#include <Xm/MainW.h>
#include <Xm/ScrolledW.h>
#include <Xm/Label.h>
#include <Xm/CascadeB.h>
#include <Xm/DialogS.h>
#include <Xm/BulletinB.h>
#include <Xm/Form.h>
#include <Xm/TextF.h>

#include <X11/Xmu/Editres.h>


#include "mygraph.h"
#include "mydebug.h"
#include "point.h"
#include "line.h"

typedef struct {
    Widget  Drawing_area;
    Widget  Menu_shell;
    Widget  X_dialog,Y_dialog;
} point_draw_structure;

typedef struct {
    Widget  Drawing_area;
    Widget  Menu_shell;
    Widget  X_Start_dialog,Y_Start_dialog;
    Widget  X_End_dialog,Y_End_dialog;
} two_point_draw_structure;

int DEBUG;

void draw_line_callback (Widget where, XtPointer client_data, XtPointer call_data);
void draw_point_callback (Widget where, XtPointer client_data, XtPointer call_data);
void menu_popdown (Widget where, XtPointer client_data, XtPointer call_data);
void Make_Menu_Buttons(Widget parent,Widget db, Widget toplevel) ;
void make_point_dialog(Widget toplevel, Widget db, Widget button);
void do_point (Widget where, XtPointer client_data, XtPointer call_data);
void make_line_dialog(Widget toplevel, Widget db, Widget button);
void do_line (Widget where, XtPointer client_data, XtPointer call_data);
void Make_label_text_pair (Widget * top, Widget parent, char * label);
void Make_cancel_button(Widget parent, Widget top, Widget left, Widget shell);
Widget Make_ok_button(Widget parent, Widget top);
void make_two_point_dialog(Widget toplevel, Widget db, Widget button);
static void drawing_board_expose(Widget where, XtPointer cd,  XtPointer cld);

main (int argc, char * argv[]) {

    XtAppContext  app_context;
    Widget        toplevel,drawing_board,line_button,main_form,
                  command_form,main_menubar ;
    char  *       myclassname = "Line";
    Arg           args[10];
    int           nargs=0;
    XmString      astring;
 
    DEBUG =  NODEBUG;


/* Initialize the application */

    toplevel = XtAppInitialize(&app_context,myclassname,NULL,0,
                &argc,argv,NULL,args,nargs);

/* Create a main form to hold everything */

    nargs = 0;
    XtSetArg(args[nargs],XmNshowSeparator,True); nargs++;
    main_form = XtCreateManagedWidget("form",xmMainWindowWidgetClass,
	      toplevel,args,nargs);

    XtManageChild(main_form);


/* For now stick a label in the command window, later if we want to add a 
   language or something like that, the interface would go here */

    nargs=0;
    astring = XmStringCreateSimple("Introduction to Computer Graphics");
    XtSetArg(args[nargs],XmNlabelString,astring);nargs++;
    command_form  = XtCreateManagedWidget("label",xmLabelWidgetClass,main_form,
              args,nargs);
    XmStringFree(astring);
    XtManageChild(command_form);

/* set up a menubar for commands */

    nargs=0;
    main_menubar = XmCreateMenuBar(main_form,"message",args,nargs);
    XtManageChild(main_menubar);

/* Set up the canvas for our work */

    nargs=0;
    XtSetArg(args[nargs],XmNwidth,400); nargs++;
    XtSetArg(args[nargs],XmNheight,400); nargs++;
    XtSetArg(args[nargs],XmNtopWidget,line_button); nargs++;
    XtSetArg(args[nargs],XmNtopAttachment,XmATTACH_WIDGET); nargs++;

    drawing_board = XtCreateManagedWidget("msgs",xmDrawingAreaWidgetClass,
               main_form, args,nargs);
    XtManageChild(drawing_board);
/*    XtAddCallback(drawing_board,XmNexposeCallback,drawing_board_expose,NULL);*/

/* make the items in the menu bar, the drawing primitives need access to
   the drawing board, so this is done here */

    Make_Menu_Buttons(main_menubar,drawing_board,toplevel);

/*  put them all togeather */

    XmMainWindowSetAreas(main_form, main_menubar, command_form, NULL, NULL ,
            drawing_board);

    XtRealizeWidget(toplevel);

/* Added so edit res will work */

    XtAddEventHandler(toplevel,(EventMask) 0,True, _XEditResCheckMessages,NULL);

    XtAppMainLoop(app_context);
}

static void Quit_Callback(Widget where, XtPointer cd,  XtPointer cld) {
    exit(0);
}

static void drawing_board_expose(Widget where, XtPointer cd,  XtPointer cld) {

     line aline;

     aline.e1.x = 0; aline.e1.y = 0; aline.e2.x = 400; aline.e2.y = 400;
     dc_drawline(aline,where);
     aline.e1.x = 400; aline.e1.y = 0; aline.e2.x = 0; aline.e2.y = 400;
     dc_drawline(aline,where);
}

void Make_Menu_Buttons(Widget parent, Widget db, Widget  toplevel) {
     int nargs;
     Arg args[10];
     Widget pane, button, title, help_button;
     XmString      astring;

     nargs=0;
     pane = XmCreatePulldownMenu(parent,"pane",args,nargs);

     nargs=0;
     XtSetArg(args[nargs],XmNsubMenuId,pane); nargs++;
     XtSetArg(args[nargs],XmNmnemonic,'C'); nargs++;
     button = XmCreatePushButton(pane,"Cancel",args,nargs);
     XtManageChild(button);

     nargs=0;
     XtSetArg(args[nargs],XmNsubMenuId,pane); nargs++;
     XtSetArg(args[nargs],XmNmnemonic,'Q'); nargs++;
     button = XmCreatePushButton(pane,"Quit",args,nargs);
     XtManageChild(button);
     XtAddCallback(button,XmNactivateCallback,Quit_Callback,NULL);

     nargs=0;
     XtSetArg(args[nargs],XmNsubMenuId,pane); nargs++;
     XtSetArg(args[nargs],XmNmnemonic,'F'); nargs++;
     title = XmCreateCascadeButton(parent,"File",args,nargs);
     XtManageChild(title);

     /* primitives */

     nargs=0;
     pane = XmCreatePulldownMenu(parent,"pane",args,nargs);

     nargs=0;
     XtSetArg(args[nargs],XmNsubMenuId,pane); nargs++;
     XtSetArg(args[nargs],XmNmnemonic,'C'); nargs++;
     button = XmCreatePushButton(pane,"Cancel",args,nargs);
     XtManageChild(button);

/* The point primitive */
     nargs=0;
     XtSetArg(args[nargs],XmNsubMenuId,pane); nargs++;
     XtSetArg(args[nargs],XmNmnemonic,'P'); nargs++;
     button = XmCreatePushButton(pane,"Point",args,nargs);
     XtManageChild(button);


     make_point_dialog(toplevel, db, button);

/* make a line choice in the menu */

     nargs=0;
     XtSetArg(args[nargs],XmNsubMenuId,pane); nargs++;
     XtSetArg(args[nargs],XmNmnemonic,'L'); nargs++;
     button = XmCreatePushButton(pane,"Line",args,nargs);
     XtManageChild(button);
     /*XtAddCallback(button,XmNactivateCallback,draw_line_callback,db);*/

     make_two_point_dialog(toplevel, db, button);

     nargs=0;
     XtSetArg(args[nargs],XmNsubMenuId,pane); nargs++;
     XtSetArg(args[nargs],XmNmnemonic,'P'); nargs++;
     title = XmCreateCascadeButton(parent,"Primitives",args,nargs);
     XtManageChild(title);

     /* Help */

     nargs=0;
     pane = XmCreatePulldownMenu(parent,"pane",args,nargs);

     nargs=0;
     button = XmCreatePushButton(pane,"No Help For the Wicked",args,nargs);
     XtManageChild(button);

     nargs=0;
     XtSetArg(args[nargs],XmNsubMenuId,pane); nargs++;
     XtSetArg(args[nargs],XmNmnemonic,'H'); nargs++;
     title = XmCreateCascadeButton(parent,"Help",args,nargs);
     XtManageChild(title);

     nargs=0;
     XtSetArg(args[nargs],XmNmenuHelpWidget,title); nargs++;
     XtSetValues(parent,args,nargs);
}

void menu_popdown (Widget where, XtPointer client_data, XtPointer call_data)
{
   XtUnmanageChild((Widget) client_data);
}

void do_point (Widget where, XtPointer client_data, XtPointer call_data)
{
   char * p;
   point pt;

   p = XmTextFieldGetString((( point_draw_structure * ) client_data)->X_dialog);
   pt.x = atoi(p);

   p = XmTextFieldGetString((( point_draw_structure * ) client_data)->Y_dialog);
   pt.y = atoi(p);

   dc_draw_point(pt,(( point_draw_structure * )client_data)->Drawing_area);
   XtUnmanageChild((( point_draw_structure * ) client_data)->Menu_shell);
}

void do_line (Widget where, XtPointer client_data, XtPointer call_data)
{
   char * p;
   line aline;

   p = XmTextFieldGetString(((two_point_draw_structure * )
	   client_data)->X_Start_dialog);
   aline.e1.x = atoi(p);

   p = XmTextFieldGetString(((two_point_draw_structure * ) 
	   client_data)->Y_Start_dialog);
   aline.e1.y = atoi(p);

   p = XmTextFieldGetString(((two_point_draw_structure * )
	   client_data)->X_End_dialog);
   aline.e2.x = atoi(p);

   p = XmTextFieldGetString(((two_point_draw_structure * ) 
	    client_data)->Y_End_dialog);
   aline.e2.y = atoi(p);

   dc_drawline(aline,((two_point_draw_structure * )client_data)->Drawing_area);
   XtUnmanageChild((( two_point_draw_structure * ) client_data)->Menu_shell);
}

void draw_point_callback 
(Widget where, XtPointer client_data, XtPointer call_data) {
    XtManageChild((( point_draw_structure * )client_data)->Menu_shell);
}

void draw_line_callback 
(Widget where, XtPointer client_data, XtPointer call_data) {
    XtManageChild((( two_point_draw_structure * )client_data)->Menu_shell);
}

void make_point_dialog(Widget toplevel, Widget db, Widget button){

     int nargs;
     Arg args[10];
     XmString      astring;
     Widget ab,pn,top;
     static point_draw_structure  pass;

     pass.Drawing_area = db;

     nargs=0;
     astring = XmStringCreateSimple("Point Dialog");
     XtSetArg(args[nargs],XmNdialogTitle,astring);nargs++;
     pass.Menu_shell = XmCreateBulletinBoardDialog(toplevel,"bb",args,nargs);
     XmStringFree(astring);

/* a form widget to hold everything */

     nargs=0;
     pn = 
      XtCreateManagedWidget("pd",xmFormWidgetClass,pass.Menu_shell,args,nargs);

/* Create a title in the bullitin Board */

     nargs=0;
     astring = XmStringCreateSimple("Enter The Point");
     XtSetArg(args[nargs],XmNlabelString,astring);nargs++;
     top  = XtCreateManagedWidget("label",xmLabelWidgetClass,pn,
               args,nargs);
     XmStringFree(astring);
     XtManageChild(top);

     Make_label_text_pair (&top,pn , "X:");
     pass.X_dialog = top;

     Make_label_text_pair (&top,pn , "Y:");
     pass.Y_dialog = top;

/* make an accept button */
     ab =  Make_ok_button(pn,top);
     XtAddCallback(ab,XmNactivateCallback,do_point,&pass);

/* and finally a cancel button */
     Make_cancel_button(pn, top, ab, pass.Menu_shell);

     XtManageChild(pn);
     XtAddCallback(button,XmNactivateCallback,draw_point_callback, &pass);
}

void make_two_point_dialog(Widget toplevel, Widget db, Widget button){

     int nargs;
     Arg args[10];
     XmString      astring;
     Widget ab,pn,top;
     static two_point_draw_structure  pass;

     pass.Drawing_area = db;

     nargs=0;
     astring = XmStringCreateSimple("Point Dialog");
     XtSetArg(args[nargs],XmNdialogTitle,astring);nargs++;
     pass.Menu_shell = XmCreateBulletinBoardDialog(toplevel,"bb",args,nargs);
     XmStringFree(astring);

/* a form widget to hold everything */

     nargs=0;
     pn = 
      XtCreateManagedWidget("pd",xmFormWidgetClass,pass.Menu_shell,args,nargs);

/* Create a title in the bullitin Board */

     nargs=0;
     astring = XmStringCreateSimple("Enter The Endpoints");
     XtSetArg(args[nargs],XmNlabelString,astring);nargs++;
     top  = XtCreateManagedWidget("label",xmLabelWidgetClass,pn,
               args,nargs);
     XmStringFree(astring);
     XtManageChild(top);

     Make_label_text_pair (&top,pn , "Start X:");
     pass.X_Start_dialog = top;

     Make_label_text_pair (&top,pn , "Start Y:");
     pass.Y_Start_dialog = top;

     Make_label_text_pair (&top,pn , "End X:");
     pass.X_End_dialog = top;

     Make_label_text_pair (&top,pn , "End Y:");
     pass.Y_End_dialog = top;

/* make an accept button */
     ab =  Make_ok_button(pn,top);
     XtAddCallback(ab,XmNactivateCallback,do_line,&pass);

/* and finally a cancel button */
     Make_cancel_button(pn, top, ab, pass.Menu_shell);

     XtManageChild(pn);
     XtAddCallback(button,XmNactivateCallback,draw_line_callback, &pass);
}

Widget Make_ok_button(Widget parent, Widget top) {
     int nargs;
     Arg args[10];
     XmString      astring;
     Widget ab;

     nargs=0;
     astring = XmStringCreateSimple("OK");
     XtSetArg(args[nargs],XmNtopWidget,top);nargs++;
     XtSetArg(args[nargs],XmNtopAttachment,XmATTACH_WIDGET) ;nargs++;
     XtSetArg(args[nargs],XmNlabelString,astring);nargs++;
     ab = XtCreateManagedWidget("ok",xmPushButtonWidgetClass,parent,args,nargs);
     XtManageChild(ab);
     XmStringFree(astring);

     return(ab);
}
void Make_cancel_button(Widget parent, Widget top, Widget left, Widget shell)
{
     int nargs;
     Arg args[10];
     XmString      astring;
     Widget ab;

     nargs=0;
     astring = XmStringCreateSimple("Cancel");
     XtSetArg(args[nargs],XmNlabelString,astring);nargs++;
     XtSetArg(args[nargs],XmNtopWidget,top);nargs++;
     XtSetArg(args[nargs],XmNtopAttachment,XmATTACH_WIDGET) ;nargs++;
     XtSetArg(args[nargs],XmNleftWidget,left);nargs++;
     XtSetArg(args[nargs],XmNleftAttachment,XmATTACH_WIDGET);nargs++;
     ab = XtCreateManagedWidget("cancel",xmPushButtonWidgetClass,parent,
	    args,nargs);
     XtManageChild(ab);
     XtAddCallback(ab,XmNactivateCallback,menu_popdown,shell);
     XmStringFree(astring);
}

void Make_label_text_pair (Widget * top, Widget parent, char * label)
{
     int nargs;
     Arg args[10];
     XmString      astring;
     Widget lab, box;

     nargs=0;
     astring = XmStringCreateSimple(label);
     XtSetArg(args[nargs],XmNlabelString,astring);nargs++;
     XtSetArg(args[nargs],XmNtopWidget,*top);nargs++;
     XtSetArg(args[nargs],XmNtopAttachment,XmATTACH_WIDGET) ;nargs++;
     lab  = XtCreateManagedWidget("label",xmLabelWidgetClass,parent,
              args,nargs);
     XmStringFree(astring);
     XtManageChild(lab);

     nargs=0;
     XtSetArg(args[nargs],XmNtopWidget,*top);nargs++;
     XtSetArg(args[nargs],XmNtopAttachment,XmATTACH_WIDGET) ;nargs++;
     XtSetArg(args[nargs],XmNleftWidget,lab);nargs++;
     XtSetArg(args[nargs],XmNleftAttachment,XmATTACH_WIDGET);nargs++;
     XtSetArg(args[nargs],XmNcolumns,5);nargs++;
     box = XtCreateManagedWidget("Xfield",xmTextFieldWidgetClass,parent,
	    args,nargs);
     XtManageChild(box);

     *top = box;
}
