// ----------------------------------------------------------------------------
//
// Copyright (C) Columbia University, 1994. All Rights Reserved.
// Sameer A. Nene, Shree K. Nayar, Hiroshi Murase
//
// See file LICENSE for details of software license agreement.
//
// ----------------------------------------------------------------------------
//
// xreporter.C
//
// Author:               Sameer Nene
// Date:                 08/25/94
// Version:              1.0
// Modification History:
// Bugs:
//
// Classes:
//   XReporter
//
// Notes:
//   This module contains implementation of classes declared in xreporter.h
//   
// ----------------------------------------------------------------------------

#define NO_XMSTRINGS

#include <X11/cursorfont.h>
#include <X11/Xlib.h>
#include <Xm/DialogS.h>
#include <Xm/DrawingA.h>
#include <Xm/Form.h>
#include <Xm/Frame.h>
#include <Xm/LabelG.h>
#include <Xm/PushB.h>
#include <Xm/PushBG.h>
#include <Xm/SeparatoG.h>
#include <iostream.h>
#include "xreporter.h"

int XReporter::d_pos, XReporter::d_bpressed, XReporter::d_direc;
Cursor XReporter::d_cursor = 0;
Widget XReporter::d_dialog = 0, XReporter::d_darea = 0,
XReporter::d_button = 0, XReporter::d_messg = 0, XReporter::d_topshell = 0,
XReporter::d_ind = 0;

void XReporter::int_cb(Widget, XtPointer, XtPointer)
{
  d_bpressed = BUTTONPRESSED;
}

void XReporter::checkPendingEvents()
{
  Display *dpy;
  Window win;
  XEvent event;
  
  dpy = XtDisplay(d_topshell);
  win = XtWindow(d_button);
  while(XCheckMaskEvent(dpy, ButtonPressMask | ButtonReleaseMask | ButtonMotionMask | PointerMotionMask | KeyPressMask | KeyReleaseMask,
			&event)) {
    if(event.xany.window == win)
      XtDispatchEvent(&event);
    else
      if(event.type == ButtonPress || event.type == KeyPress)
	XBell(dpy, 50);
  }  
}

void XReporter::updateStatus()
{
  Display *display;
  Dimension width;
  
  display = XtDisplay(d_topshell);

  XtVaGetValues(d_darea, XmNwidth, &width, NULL);
  XtVaSetValues(d_ind, XmNx, d_pos * width / STATUS_POSITIONS, NULL);
		
  if(d_direc == UP) {
    if(++d_pos == STATUS_POSITIONS) {
      d_direc = DOWN;
      d_pos -= 2;
    }
  }
  else
    if(--d_pos == -1) {
      d_direc = UP;
      d_pos += 2;
    }
}  

void XReporter::showWindow(Widget topshell, const char *message, int flag)
{
  Widget form1, form2, sep, button1, frame;
  Dimension width;
  XSetWindowAttributes attrs;
  Display *display = XtDisplay(topshell);

  if(d_dialog != 0)
    return;

  d_topshell = topshell;
  d_bpressed = NOBUTTONPRESSED;

  if(d_cursor == 0)
    d_cursor = XCreateFontCursor(XtDisplay(topshell), XC_watch);
  attrs.cursor = d_cursor;
  XChangeWindowAttributes(display, XtWindow(topshell), CWCursor, &attrs);
  XFlush(display);

  d_dialog = XtVaCreatePopupShell("Computing...", xmDialogShellWidgetClass,
				  topshell, NULL);

  form1 = XtVaCreateWidget("form", xmFormWidgetClass, d_dialog,
			   XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL,
			   NULL);

  form2 = XtVaCreateWidget("form", xmFormWidgetClass, form1,
			   XmNfractionBase, 5,
			   XmNleftAttachment, XmATTACH_FORM,
			   XmNrightAttachment, XmATTACH_FORM,
			   XmNbottomAttachment, XmATTACH_FORM,
			   NULL);
  d_button = form2;
  button1 = XtVaCreateManagedWidget("Interrupt", xmPushButtonGadgetClass, form2,
				    XmNsensitive, flag == INTERRUPTIBLE ? True : False,
				    XmNleftAttachment, XmATTACH_POSITION,
				    XmNleftPosition, 2,
				    XmNrightAttachment, XmATTACH_POSITION,
				    XmNrightPosition, 3,
				    XmNtopAttachment, XmATTACH_POSITION,
				    XmNtopPosition, 1,
				    XmNbottomAttachment, XmATTACH_POSITION,
				    XmNbottomPosition, 4,
				    NULL);
  XtAddCallback(button1, XmNactivateCallback, int_cb, 0);
  XtManageChild(form2);

  sep = XtVaCreateManagedWidget("sep", xmSeparatorGadgetClass, form1,
				XmNorientation, XmHORIZONTAL,
				XmNleftAttachment, XmATTACH_FORM,
				XmNrightAttachment, XmATTACH_FORM,
				XmNbottomAttachment, XmATTACH_WIDGET,
				XmNbottomWidget, form2,
				NULL);

  d_messg = XtVaCreateManagedWidget(message, xmLabelGadgetClass, form1,
				    XmNtopAttachment, XmATTACH_FORM,
				    XmNtopOffset, 10,
				    XmNleftAttachment, XmATTACH_FORM,
				    XmNrightAttachment, XmATTACH_FORM,
				    NULL);

  frame = XtVaCreateWidget("frame", xmFrameWidgetClass, form1,
			   XmNshadowType, XmSHADOW_IN,
			   XmNtopAttachment, XmATTACH_WIDGET,
			   XmNtopWidget, d_messg,
			   XmNtopOffset, 10,
			   XmNleftAttachment, XmATTACH_FORM,
			   XmNleftOffset, 10,
			   XmNrightAttachment, XmATTACH_FORM,
			   XmNrightOffset, 10,
			   XmNbottomAttachment, XmATTACH_WIDGET,
			   XmNbottomWidget, sep,
			   XmNbottomOffset, 10,
			   NULL);

  d_darea = XtVaCreateWidget("draw", xmDrawingAreaWidgetClass, frame,
			     XmNbackground, BlackPixelOfScreen(DefaultScreenOfDisplay(display)),
			     XmNmarginHeight, 0, XmNmarginWidth, 0,
			     NULL);
			     
  d_ind = XtVaCreateManagedWidget(" ", xmPushButtonWidgetClass, d_darea,
				  XmNx, 0, XmNy, 0,
				  XmNwidth, 0, XmNheight, STATUS_AREA_HEIGHT,
				  NULL);
  
  d_pos = 0;
  d_direc = UP;

  XtManageChild(d_darea);
  XtManageChild(frame);
  XtManageChild(form1);
  XtManageChild(d_dialog);

  XtVaGetValues(d_darea, XmNwidth, &width, NULL);
  XtVaSetValues(d_ind, XmNwidth, width / STATUS_POSITIONS, NULL);

  XmUpdateDisplay(d_dialog);
  XFlush(display);
}

void XReporter::showWaitCursor(Widget topshell)
{
  XSetWindowAttributes attrs;

  if(d_cursor == 0)
    d_cursor = XCreateFontCursor(XtDisplay(topshell), XC_watch);
  attrs.cursor = d_cursor;
  XChangeWindowAttributes(XtDisplay(topshell), XtWindow(topshell), CWCursor, &attrs);
  XFlush(XtDisplay(topshell));
}

int XReporter::display_status()
{
  if(d_dialog != 0) {
    updateStatus();
    XmUpdateDisplay(d_dialog);
    XFlush(XtDisplay(d_topshell));
    checkPendingEvents();
    return d_bpressed;
  }
  return NOBUTTONPRESSED;
}

int XReporter::display_status(const char *message)
{
  XmString str = XmStringCreateSimple((char*)message);
  XtVaSetValues(d_messg, XmNlabelString, str, NULL);
  XmStringFree(str);
  if(d_dialog != 0) {
    updateStatus();
    XmUpdateDisplay(d_dialog);
    XFlush(XtDisplay(d_topshell));
    checkPendingEvents();
    return d_bpressed;
  }
  return NOBUTTONPRESSED;
}

int XReporter::get_key_status()
{
  if(d_dialog != 0) {
    XmUpdateDisplay(d_dialog);
    XFlush(XtDisplay(d_topshell));
    checkPendingEvents();
    return d_bpressed;
  }
  return NOBUTTONPRESSED;
}

void XReporter::destroyWindow()
{
  XSetWindowAttributes attrs;

  if(d_dialog != 0) {
    XtDestroyWidget(d_dialog);
    attrs.cursor = None;
    XChangeWindowAttributes(XtDisplay(d_topshell), XtWindow(d_topshell),
			    CWCursor, &attrs);
    XFlush(XtDisplay(d_topshell));
    d_dialog = 0;
    d_pos = 0;
  }
}

void XReporter::showNormalCursor(Widget topshell)
{
  XSetWindowAttributes attrs;
  
  attrs.cursor = None;
  XChangeWindowAttributes(XtDisplay(topshell), XtWindow(topshell),
			  CWCursor, &attrs);
  XFlush(XtDisplay(topshell));
}
