// This may look like C code, but it is really -*- C++ -*-

/***********************************************************
Copyright 1991 by the Massachusetts Institute of Technology

Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation, and that the name of M.I.T. not be used in advertising or
publicity pertaining to distribution of the software without specific,
written prior permission.  M.I.T. makes no representations about the
suitability of this software for any purpose.  It is provided "as is"
without express or implied warranty.

Author: Roman J. Budzianowski - Project Athena MIT

******************************************************************/

#include <xt++/Intrinsic.h>
#include <xt++/Shell.h>
#include <xt++/Xaw/Label.h>
#include <xt++/Xaw/Command.h>
#include <xt++/Xaw/Form.h>
#include <xt++/Xaw/Dialog.h>
#include <xt++/Xaw/Clock.h>
#include <xt++/Xaw/Panner.h>
#include <xt++/Xaw/Porthole.h>
#include <xt++/Xaw/AsciiText.h>

#include <X11/StringDefs.h>
#include <libc.h>

#include <iostream.h>

#include "ObjectEditor.h"
#include "Objects.h"
#include "WindowStream.h"
#include "ObjectFactory.h"
#include "WidgetFactory.h"
#include "LayoutSpace.h"
#include "Application.h"

wstream     msg;		// message window stream

Application  *appl = NULL;
TopLevelShellWidget* bindings = NULL;
TopLevelShellWidget* demo = NULL;

void QuitCB(Core* w , XtPointer, XtPointer)
{
   w->GetAppContext()->ExitLoop();
}

void StartApplCB(Core* , XtPointer dpy, XtPointer)
{
   if(!appl){
      appl = new Application("appl", "Appl", (Display*)dpy);
      appl->Realize();
   }
   else
     appl->Popup();
}

void   ObjectEditorBindings(wstream&);
void   ObjectViewBindings(wstream&);
void   LayoutSpaceBindings(wstream&);

void BindingsCB(Core* , XtPointer data, XtPointer)
{
   if(!bindings){
      bindings = new TopLevelShellWidget("bindings_shell", (Core*)data);
      AsciiTextWidget* text = new AsciiTextWidget("text",bindings);
      bindings->Realize();
      wstream s;
      s.attach(text);
      s << "******** Default Bindings for the Editor Window ************\n\n";
      ObjectEditorBindings(s);
      ObjectViewBindings(s);
      s << "******** Default Bindings for the Application Window ************\n\n";
      LayoutSpaceBindings(s);
      s << flush;
   }
}

void DemoCB(Core*, XtPointer data, XtPointer)
{
   if(!demo){
      demo = new TopLevelShellWidget("demo_shell", (Core*)data);
      AsciiTextWidget* text = new AsciiTextWidget("text",demo);
      demo->Realize();
      wstream s;
      s.attach(text);
      s << "** This is an early prototype of Eureka - a visual programming **\n";
      s << "** environment.                                                **\n\n";
      s << "** Instructions for demonstrating Eureka **\n\n";
      s << " 1. create NumberLever \n";
      s << " 2. create another NumberLever \n";
      s << " 3. create Multiplier \n";
      s << " 4. connect outputs of levers with inputs of Multiplier \n";
      s << " 5. create NumberText \n";
      s << " 6. connect output of Multiplier with the appropriate input \n     of NumberText \n";
      s << " 7. open application window \n";
      s << " 8. create widgets (Cntrl-Btn1Down in each object) \n";
      s << " 9. move both scrollbars \n\n";
      s << " Second inputs of graphical objects are used for 'mapping'. \n";
      s << " Create boolean button and connect it (using splitter) to all \n";
      s << " three graphical objects and then create widget for the button.\n";
      s << " Click on the button-widget in the application window a few times - \n";
      s << " the three widgets should be unmapped and mapped.\n";
      s << flush;
   }

}

String GetObjectName()
{
   static char buffer[128];
   String name;

   msg.clear();

   msg << "Type in name of object: ";
//   msg.width(sizeof(buffer));
//   msg >> buffer >> ws;
   msg.getline(buffer,128);

//   cerr << buffer << "\n";

   msg << buffer << " it is...Please place the object.\n" << flush;
   name = (String) XtMalloc(strlen(buffer));
   strcpy(name,buffer);
   return name;
}

void  PortholeCallback(Core*, XtPointer panner_ptr, XtPointer report_ptr)
{
    XawPannerReport *report = (XawPannerReport *) report_ptr;
    Widget panner = (Widget) panner_ptr;

    panner->SetValues(XtNsliderX, (XtArgVal)report->slider_x,
		      XtNsliderY, (XtArgVal)report->slider_y);

    if (report->changed != (XawPRSliderX | XawPRSliderY)) {
       panner->SetValues(XtNsliderWidth, (XtArgVal)report->slider_width,
			 XtNsliderHeight, (XtArgVal)report->slider_height,
			 XtNcanvasWidth, (XtArgVal)report->canvas_width,
			 XtNcanvasHeight, (XtArgVal)report->canvas_height);
    }
}

void PannerCallback(Core*, XtPointer closure, XtPointer report_ptr)
{
   Core* editspace = (Core *) closure;
   XawPannerReport *report = (XawPannerReport *) report_ptr;

   editspace->SetValues(XtNx, -report->slider_x,
			XtNy, -report->slider_y);
}

main(unsigned int argc, char** argv)
{
   ApplicationContext appContext;

   Display *dpy =  appContext.OpenDisplay(NULL, argv[0], "Eureka",
                        NULL,0,
                        &argc, argv);

   ApplicationShellWidget aw( argv[0], "Eureka", dpy);

   FormWidget    form("form", aw);

   FormWidget  controls("controls",form);

   PannerWidget panner("panner", controls);

   CommandWidget quit("quit", controls);
   quit.AddCallback(XtNcallback, QuitCB, (XtPointer)NULL);

   CommandWidget start_appl("start_appl", controls);
   start_appl.AddCallback(XtNcallback, StartApplCB, (XtPointer)dpy);

   CommandWidget bindings_button("bindings", controls);
   bindings_button.AddCallback(XtNcallback, BindingsCB, (XtPointer)&aw);

   CommandWidget demo("demo", controls);
   demo.AddCallback(XtNcallback, DemoCB, (XtPointer)&aw);

   AsciiTextWidget text("msgWindow", form);

   msg.attach(&text);

   PortholeWidget porthole("porthole", form);

   ObjectEditor work(&porthole);

   SetupWorkspace for_objects(&work);
   
   ObjectFactory object_factory(aw);

   WidgetFactory widget_factory(aw);

   porthole.AddCallback(XtNreportCallback, PortholeCallback, (XtPointer) &panner);
   panner.AddCallback(XtNreportCallback, PannerCallback, (XtPointer) &work);

   aw.Realize();

   appContext.MainLoop();

}
