/* ui_main.c: user interface main window */

#include <time.h>

#include <Xm/Xm.h>
#include <Xm/RepType.h>

#include "ui.h"
#include "uit.h"
#include "render.h"
#include "canvas.h"

/********************* global declarations concerning the GUI ************************/
/* the program detects the best X visual to use and creates a suitables
 * standard colormap to use with it automatically. The way to do this depends
 * on the graphics library being used, and is coded in render.c */
XVisualInfo best_visual;
Colormap cmap;

/* the X visual info is not correctly passed from parent to sub menus
 * with Motif 1.2, so we set it explicitely ourselves when creating
 * the submenus */
Arg visargs[3];
int nrvisargs;

/* X application context and some important widgets */
XtAppContext app_context;
Widget topLevel, canvas;
Display *display;

/* current directory needed when loading MGF files. */
char *current_directory;

/* fallback resources ... in ui_defaults.c (automatically generated) */
extern char *fallback_resources[];


/* Processes pending X events */
void ProcessWaitingEvents(void)
{
  XtInputMask mask;

  while ((mask = XtAppPending(app_context))) 
    XtAppProcessEvent(app_context, mask);
}

/* Called during radiance computations - checks for events (like the user clicking
 * on some button, or moving the mouse while holding one of the mouse buttons ... ) 
 * makes the program behave much more flexible */
void CheckForEvents(void)
{
  clock_t lastt = 0;

  /* checking for events too often slows down the computations too much ... 
   * we check only once each second. */
  if (clock() - lastt < CLOCKS_PER_SEC)
    return;

  ProcessWaitingEvents();

  lastt = clock();
}

/*************************** menubar ******************************************/
/* creates the submenus in the main menu bar */
static void CreateMainMenu(Widget menuBar)
{
  CreateFileMenu(menuBar);
  CreateCameraMenu(menuBar);
  CreateRenderMenu(menuBar);
  CreateHelpMenu(menuBar);
}

void StartUserInterface(int argc, char **argv)
{
  Widget mainWindow, menuBar;
  XSetWindowAttributes wattrs;

  /* Create a toplevel widget, handle options ... */
  topLevel = XtVaAppInitialize(&app_context,	/* application context */
			       APP_CLASS_NAME,	/* application class name */
			       NULL, 0,		/* command line option list */
			       &argc, argv,	/* command line args */
			       fallback_resources, /* used when the application
						* defaults file is missing. */
			       NULL);		/* terminate varargs list */

  XmRepTypeInstallTearOffModelConverter();

  display = XtDisplay(topLevel);

  /* obtain the XVisualInfo and Colormap to use for rendering with the
   * graphics library. If a non-default visual and colormap is needed,
   * fill in the visualid, depth and colomrap in the visarg argument list,
   * so the visual can be set on each widget whenever needed. Failing to do so
   * will lead to BadMatch errors from the X server. */
  if (RenderGetVisualInfoAndColormap(XtScreen(topLevel), 
				     &best_visual,
				     &cmap)) {
    /* Set the visual, depth, and colormap for the shell - as a matter of fact, these things
     * have to be passed to all routines creating popup shells and dialogs */
    XtSetArg(visargs[0], XtNvisual, best_visual.visual);
    XtSetArg(visargs[1], XtNdepth, best_visual.depth);
    XtSetArg(visargs[2], XtNcolormap, cmap);
    nrvisargs = 3;
    XtSetValues(topLevel, visargs, nrvisargs);
  } else
    nrvisargs = 0;

  /* create main window */
  mainWindow = CreateForm(topLevel, "mainWindow");
  
  /* menubar on top of the main window */
  menuBar = CreateMenuBar(mainWindow, "menuBar");

  /* create the menus in the menubar */
  CreateMainMenu(menuBar);
  XtManageChild(menuBar);

  /* create the window in which to render (canvas window) */
  canvas = CreateCanvasWindow(mainWindow);

  /* realize all widgets - bring them on the screen */
  XtManageChild(mainWindow);
  XtRealizeWidget(topLevel);

  /* set the backing store attribuut of the canvas window to NotUseful */
  wattrs.backing_store = NotUseful;
  XChangeWindowAttributes(XtDisplay(canvas), XtWindow(canvas), CWBackingStore, &wattrs);

  /* initialize the canvas widget */
  CanvasInit(canvas);

  /* infinte loop catching and handling events */
  XtAppMainLoop(app_context);
}

