static char AlarmedText_id[] = "$Header: /u/oreilly/rov/tmacs/RCS/AlarmedText.cc,v 1.11 1998/12/18 21:12:58 oreilly Exp $";


/*
$Log: AlarmedText.cc,v $
Revision 1.11  1998/12/18 21:12:58  oreilly
Remove event handlers in destructor

Revision 1.10  1997/10/03 09:26:11  oreilly
*** empty log message ***

Revision 1.9  97/09/18  13:41:12  13:41:12  oreilly (Thomas C. O'Reilly)
Free/delete stuff in destructor

Revision 1.8  97/08/12  14:33:20  14:33:20  oreilly (Thomas C. O'Reilly)
Popup menu to show alarm defintion

Revision 1.7  97/05/30  15:47:20  15:47:20  oreilly (Thomas C. O'Reilly)
*** empty log message ***

Revision 1.6  97/05/08  09:23:18  09:23:18  oreilly (Thomas C. O'Reilly)
Delete contained DmInputDetector in destructor.

Revision 1.5  97/05/06  16:24:20  16:24:20  oreilly (Thomas C. O'Reilly)
Initialize _prevValue to MAXSHORT instead of MAXINT

Revision 1.4  97/04/30  19:30:31  19:30:31  oreilly (Thomas C. O'Reilly)
Delete contained DynamicLabel object

Revision 1.3  97/03/20  12:28:41  12:28:41  oreilly (Thomas C. O'Reilly)
*** empty log message ***

Revision 1.2  96/10/28  09:11:44  09:11:44  oreilly (Thomas C. O'Reilly)
*** empty log message ***

Revision 1.1  96/07/22  10:41:46  10:41:46  oreilly (Thomas C. O'Reilly)
First external release

*/
#include <Xm/RowColumn.h>
#include <Xm/Form.h>
#include <Xm/Label.h>
#include <Vk/VkInfoDialog.h>
#include <values.h>
#include "AlarmedText.h"
#include "TiburonApp.h"
#include "AlarmedObject.h"
#include "DmErrno.h"

#define valueStringSize 100

const char *const AlarmedText::alarmUpdateCallback = "alarmUpdateCallback";

AlarmedText::AlarmedText(const char *name, Widget parent, char *format,
			 DmObject *dmObject, int period, Alarm *alarm, 
			 Boolean dynamic, float multiplier,
			 unsigned char alignment)
  : DmGuiObject(name, parent)
{
  _alarmDetector = 0;
  _format = 0;
  _dynamicText = 0;
  _priority = NoPriority;
  _valueText = 0;

  _baseWidget = 
    XtVaCreateWidget(name, xmFormWidgetClass, parent, NULL);
  
  installDestroyHandler();

  XtAddEventHandler(_baseWidget,
		    ButtonPressMask,
		    False, 
		    (XtEventHandler )&DmGuiObject::eventHandler, 
		    (XtPointer )this);

  _multiplier = 1.;
  
  if (dynamic)
  {
    _dynamicText = new DynamicLabel("value", _baseWidget, alignment);

    XtVaSetValues(_dynamicText->baseWidget(), 
		  XmNleftAttachment, XmATTACH_FORM,
		  XmNrightAttachment, XmATTACH_FORM,
		  XmNtopAttachment, XmATTACH_FORM,
		  XmNbottomAttachment, XmATTACH_FORM,
		  NULL);
		  
    _dynamicText->show();
    _dynamicText->addXtEventHandler(ButtonPressMask,
				    False,

				    (XtEventHandler )
				    &DmGuiObject::eventHandler,

				    (XtPointer )this);
    
  }
  else
  {
    _valueText = 
      XtVaCreateManagedWidget("value", xmLabelWidgetClass,
			      _baseWidget, 
			      XmNleftAttachment, XmATTACH_FORM,
			      XmNrightAttachment, XmATTACH_FORM,
			      XmNtopAttachment, XmATTACH_FORM,
			      XmNbottomAttachment, XmATTACH_FORM,
			      NULL);

    XtAddEventHandler(_valueText,
		      ButtonPressMask,
		      False, 
		      (XtEventHandler )&DmGuiObject::eventHandler, 
		      (XtPointer )this);
  
    _dynamicText = NULL;
  }
  
  if (addDmObject(dmObject, DmConsumeFlag) == -1)
    return;

  if (setConsumePeriod(period) == -1)
    return;
  
  if (alarm)
  {
    _alarmDetector = new DmInputDetector("alarmDetector", parent, 
				       alarm->dmObject(), this);
    _alarm = alarm;
  }
  else
  {
    _alarmDetector = NULL;
    _alarm = NULL;
  }
  
  _format = strdup(format);
  _nAlarmChanges = 0;
  
  // Force update of alarm object, and appropriate GUI response
  updateFromPeer(this, NULL);
}


AlarmedText::~AlarmedText()
{
  delete _alarmDetector;
  delete _dynamicText;

  if (_format)
    free(_format);

  XtRemoveEventHandler(_baseWidget,
		       ButtonPressMask,
		       False, 
		       (XtEventHandler )&DmGuiObject::eventHandler, 
		       (XtPointer )this);

  if (_valueText)
    XtRemoveEventHandler(_valueText,
			 ButtonPressMask,
			 False, 
			 (XtEventHandler )&DmGuiObject::eventHandler, 
			 (XtPointer )this);

}


void AlarmedText::updateFromPeer(DmGuiObject *peer, void *clientData)
{
  if (_alarm)
  {
    _alarm->update();
    Priority priority = _alarm->priority(_alarm->value());
    TiburonApp *app = (TiburonApp *)theApplication;
    Pixel foreground, background;
    app->priorityColors(priority, &foreground, &background);

    if (!_nAlarmChanges || priority != _priority)
    {
      if (_dynamicText)
	_dynamicText->setColors(foreground, background);
      else
	XtVaSetValues(_valueText, 
		      XmNforeground, foreground, XmNbackground, background, 
		      NULL);

      _priority = priority;
      _nAlarmChanges++;

      callCallbacks(alarmUpdateCallback, (void *)priority);
    }
  }
}


void AlarmedText::postOptions(XEvent *event)
{
  if (_alarm)
    AlarmedObject::addMenuItem(_popupMenu, _alarm);

  _popupMenu->show(event);
}



AlarmedNat16Text::AlarmedNat16Text(const char *name, Widget parent,
				   char *format, 
				   DmNat16Object *dmObject, int period,
				   Alarm *alarm, 
				   Boolean dynamic,
				   float multiplier, 
				   unsigned char alignment)
  : AlarmedText(name, parent, format, dmObject, 
		period, alarm, dynamic, multiplier, alignment)
{
  _dmObject = dmObject;
  _prevValue = MAXSHORT;
  updateGui();
}


void AlarmedNat16Text::updateGui(DM_Item handle)
{
  MBool debug = FALSE;
  Nat16 value;
  DM_Time t;
  Errno errno;
  char errorBuf[errorMsgSize];
  char buf[100];

  // Read value and update Widget
  if ((errno = _dmObject->read(&value, &t)) != SUCCESS)
  {
    sprintf(buf, "AlarmedNat16Text::updateGui(), item \"%s\" ", 
	    _dmObject->getName());

    sprintDmError(errno, buf, errorBuf);
    setError(errorBuf);
  }
  else if (value != _prevValue)
  {
    char buf[valueStringSize];
    sprintf(buf, _format, value * _multiplier);

    if (setText((const char *)buf))
      _prevValue = value;

    dprintf(stderr, "AlarmedNat16Text::updateGui() - %s\n", buf);
  }
}



AlarmedInt16Text::AlarmedInt16Text(const char *name, Widget parent,
				   char *format, 
				   DmInt16Object *dmObject, int period,
				   Alarm *alarm, Boolean dynamic,
				   float multiplier,
				   unsigned char alignment)
  : AlarmedText(name, parent, format, dmObject, 
		period, alarm, dynamic, multiplier, alignment)
{
  _dmObject = dmObject;
  _prevValue = MAXSHORT;
  updateGui();
}


void AlarmedInt16Text::updateGui(DM_Item handle)
{
  Int16 value;
  DM_Time t;
  Errno errno;
  char errorBuf[errorMsgSize];
  char buf[100];

  // Read value and update Widget
  if ((errno = _dmObject->read(&value, &t)) != SUCCESS)
  {
    sprintf(buf, "AlarmedInt16Text::updateGui(), item \"%s\" ", 
	    _dmObject->getName());

    sprintDmError(errno, buf, errorBuf);
    setError(errorBuf);
  }
  else if (value != _prevValue)
  {
    char buf[valueStringSize];
    sprintf(buf, _format, value * _multiplier);

    if (setText(buf))
      _prevValue = value;
  }
}



AlarmedFlt32Text::AlarmedFlt32Text(const char *name, Widget parent,
				   char *format,
				   DmFlt32Object *dmObject, int period,
				   Alarm *alarm, Boolean dynamic,
				   float multiplier, 
				   unsigned char alignment)
  : AlarmedText(name, parent, format, dmObject, 
		period, alarm, dynamic, multiplier, alignment)
{
  _dmObject = dmObject;
  _prevValue = MAXFLOAT;
  updateGui();
}


void AlarmedFlt32Text::updateGui(DM_Item handle)
{
  Flt32 value;
  DM_Time t;
  Errno errno;
  char errorBuf[errorMsgSize];
  char buf[100];

  // Read value and update Widget
  if ((errno = _dmObject->read(&value, &t)) != SUCCESS)
  {
    sprintf(buf, "AlarmedFlt32Text::updateGui(), item \"%s\" ", 
	    _dmObject->getName());

    sprintDmError(errno, buf, errorBuf);
    setError(errorBuf);
  }
  else if (value != _prevValue)
  {
    char buf[valueStringSize];
    sprintf(buf, _format, value * _multiplier);

    if (setText(buf))
      _prevValue = value;
  }
}


Boolean AlarmedText::setText(const char *text)
{
  if (_dynamicText)
  {
    return _dynamicText->setText(text);
  }
  else
  {
    XmString xmstr = XmStringCreateSimple((char *)text);
    XtVaSetValues(_valueText, XmNlabelString, xmstr, NULL);
    XmStringFree(xmstr);
    return True;
  }
}


Priority AlarmedText::priority()
{
  return _priority;
}
