static char AlarmEditor_id[] = "$Header: /u/oreilly/rov/tmacs/RCS/AlarmEditor.cc,v 1.8 1998/12/18 19:26:55 oreilly Exp $";


/*
$Log: AlarmEditor.cc,v $
Revision 1.8  1998/12/18 19:26:55  oreilly
Attach alarm level form to right side of main form

Revision 1.7  1997/10/03 09:23:09  oreilly
Added PsuAlarmText

Revision 1.6  97/09/10  08:31:25  08:31:25  oreilly (Thomas C. O'Reilly)
Took out debug messages

Revision 1.5  97/08/12  14:14:19  14:14:19  oreilly (Thomas C. O'Reilly)
Display thresholds and monitored item for GraduatedAlarms

Revision 1.4  97/05/30  15:43:19  15:43:19  oreilly (Thomas C. O'Reilly)
*** empty log message ***

Revision 1.3  97/03/20  12:28:29  12:28:29  oreilly (Thomas C. O'Reilly)
*** empty log message ***

Revision 1.2  96/10/28  09:11:34  09:11:34  oreilly (Thomas C. O'Reilly)
*** empty log message ***

Revision 1.1  96/07/22  10:41:24  10:41:24  oreilly (Thomas C. O'Reilly)
First external release

*/
#include <stdlib.h>
#include <Xm/List.h>
#include <Xm/Form.h>
#include <Xm/ToggleB.h>
#include <Xm/ToggleBG.h>
#include <Xm/PushB.h>
#include <Xm/Separator.h>
#include <Vk/VkInfoDialog.h>
#include <Vk/VkErrorDialog.h>
#include "AlarmEditor.h"
#include "TiburonApp.h"
#include "AlarmedText.h"


#define dprintf if (debug) fprintf

ValueBox::ValueBox(const char *name, Widget parent)
  : VkComponent(name)
{
  _baseWidget = 
    XtVaCreateWidget(name, xmRowColumnWidgetClass, parent, 
		     XmNorientation, XmHORIZONTAL,
		     NULL);

  installDestroyHandler();

  _mgr = _baseWidget;
  _errorLabel = NULL;
  _value = NULL;
  _dmObject = NULL;

  ((TiburonApp *)theApplication)->priority1Colors(&_errorFg, &_errorBg);
}


ValueBox::~ValueBox()
{
  delete _value;
  delete _dmObject;
}


void ValueBox::clear()
{
  if (_errorLabel)
  {
    XtDestroyWidget(_errorLabel);
    _errorLabel = NULL;
  }
  
  if (_value)
  {
    delete _value;
    _value = NULL;
  }

  if (_dmObject)
  {
    delete _dmObject;
    _dmObject = NULL;
  }
}


void ValueBox::setErrorLabel(char *errorBuf)
{
  Boolean debug = False;
  
  clear();
  dprintf(stderr, "setErrorLabel(): \"%s\"\n", errorBuf); 
  
  XmString xmstr = XmStringCreateSimple(errorBuf);

  _errorLabel = 
    XtVaCreateManagedWidget("errorLabel", xmLabelWidgetClass, _mgr,
			    XmNforeground, _errorFg, 
			    XmNbackground, _errorBg,
			    XmNlabelString, xmstr, 
			    NULL);

  XtManageChild(_mgr);
  XtManageChild(_baseWidget);
  
  XmStringFree(xmstr);

  Boolean mappedWhenManaged;
  Dimension width, height; 
  XtVaGetValues(_errorLabel, 
		XmNwidth, &width,
		XmNheight, &height,
		XmNmappedWhenManaged, &mappedWhenManaged, 
		NULL);
  
  dprintf(stderr, 
	  "_errorLabel for %s: width=%d, height=%d\n", _name, width, height);
  
  dprintf(stderr, 
	  "_errorLabel for %s: "
	  "realized=%d, managed=%d, mappedWhenManaged=%d\n",
	  _name,
	  XtIsRealized(_errorLabel),
	  XtIsManaged(_errorLabel),
	  mappedWhenManaged);

  XtVaGetValues(_mgr, XmNmappedWhenManaged, &mappedWhenManaged, NULL);

  dprintf(stderr, 
	  "_mgr for %s: "
	  "realized=%d, managed=%d, mappedWhenManaged=%d\n",
	  _name,
	  XtIsRealized(_mgr),
	  XtIsManaged(_mgr),
	  mappedWhenManaged);
  
  return;
}


DM_Item ValueBox::findItem(const char *itemName, DM_Type *type)
{
  DM_Item dmItem = NULL;
  Boolean error = False;
  char errorBuf[errorMsgSize];

  if (!itemName)
  {
    strcpy(errorBuf, "Not specified");
    error = True;
  }
  else
  {
    dmItem = dm_lookup((char *)itemName, 0);
    if (!dmItem)
    {
      sprintf(errorBuf, "\"%s\" not found", itemName);
      error = True;
    }
  }

  if (error)
  {
    setErrorLabel(errorBuf);
    return NULL;
  }

  DmItemSts status;
  if (dm_item_status(dmItem, &status) != SUCCESS)
  {
    theErrorDialog->postAndWait("ValueBox::findItem() - "
				"dm_item_status() failed\n");
    
    return NULL;
  }

  *type = status.is_type;

  dm_item_status_free(&status);
  
  return dmItem;
}


ThresholdBox::ThresholdBox(const char *name, Widget parent)
  : ValueBox(name, parent)
{
}


ThresholdBox::~ThresholdBox()
{
}


int ThresholdBox::createThreshold(IbcAlarm *alarm, int value) 
{
  Boolean debug = False;
  
  const char *itemName;
  
  switch (value)
  {
    case MICRO_WARNING:
    itemName = alarm->warningThresholdItem();
    break;

    case MICRO_ALARM:
    itemName = alarm->alarmThresholdItem();
    break;

    default:
    return -1;
  }

  DM_Type type;
  
  if (!findItem(itemName, &type))
    return -1;
  
  // TEST TEST TEST
  Dimension width, height;
  XtVaGetValues(_mgr, XmNwidth, &width, XmNheight, &height, NULL);
  dprintf(stderr, "createThreshold: parent width=%d, height=%d\n",
	  width, height);

  DmText *threshold = NULL;
  
  switch (type)
  {
    case DM_INT16:
    threshold = new DmInt16Text("dmText", _mgr, itemName, Aperiodic);
    break;

    case DM_NAT16:
    threshold = new DmNat16Text("dmText", _mgr, itemName, Aperiodic);
    break;
    
    case DM_FLT32:
    threshold = new DmFlt32Text("dmText", _mgr, itemName, Aperiodic);
    break;
    
    default:
    threshold = NULL;

    char buf[50];
    DmObject::sprintDataType(type, buf);
    
    dprintf(stderr, 
	    "AlarmEditor::createThreshold() - unsupported DM type; %s\n",
	    buf);
  }

  if (threshold)
  {
    threshold->text->setColumns(6);
    dprintf(stderr, "Showing threshold for value %d\n", value);
    threshold->realize();
    threshold->show();
    XtManageChild(_mgr);
  }
  
  _value = threshold;
  return 0;
}



MonitoredValueBox::MonitoredValueBox(const char *name, Widget parent)
  : ValueBox(name, parent)
{
  Widget label = 
    XtVaCreateManagedWidget("label", xmLabelWidgetClass, _baseWidget,
			    NULL);

  _mgr = XtVaCreateWidget("mgr", xmRowColumnWidgetClass, _baseWidget,
			  XmNorientation, XmHORIZONTAL,
			  NULL);

  XtManageChild(_mgr);
}


MonitoredValueBox::~MonitoredValueBox()
{
}


int MonitoredValueBox::createValue(GraduatedAlarm *alarm)
{
  Boolean debug = False;
  
  clear();

  DM_Item dmItem;
  Boolean error = False;
  char errorBuf[errorMsgSize];
  
  const char *itemName = alarm->monitoredItem();

  DM_Type type;
  if (!findItem(itemName, &type))
  {
    dprintf(stderr, "createValue() - couldn't find item:\n%s\n", itemName);
    return -1;
  }
  
  const int period = 500;
  
  AlarmedText *alarmedText = NULL;
  
  switch (type)
  {
    case DM_INT16:
    _dmObject = new DmInt16Object(itemName);
    
    alarmedText = new AlarmedInt16Text("alarmedText", _mgr, "%-3.0f", 
				       (DmInt16Object *)_dmObject, 
				       period,
				       alarm, 
				       Dynamic);
    break;

    case DM_NAT16:
    _dmObject = new DmNat16Object(itemName);
    
    alarmedText = new AlarmedNat16Text("alarmedText", _mgr, "%-3.0f", 
				       (DmNat16Object *)_dmObject, 
				       period,
				       alarm, 
				       Dynamic);
    break;
    
    case DM_FLT32:
    
    _dmObject = new DmFlt32Object(itemName);
    
    alarmedText = new AlarmedFlt32Text("alarmedText", _mgr, "%-3.0f", 
				       (DmFlt32Object *)_dmObject, 
				       period,
				       alarm, 
				       Dynamic);
    break;


    default:
    char errorBuf[errorMsgSize];
    sprintf(errorBuf, "\"%s\": type %d unsupported", itemName, type);
    setErrorLabel(errorBuf);
    return -1;
  }

  if (alarmedText)
  {
    dprintf(stderr, "createValue() - created alarmedText\n");
    
    alarmedText->show();
  }
  
  _value = alarmedText;


  if (_value)
  {
    _value->realize();
    _value->show();
    XtManageChild(_mgr);
  }

  // TEST TEST TEST
  Dimension width, height;
  XtVaGetValues(_mgr, XmNwidth, &width, XmNheight, &height, NULL);
  dprintf(stderr, "createValue() - mgr width=%d, height=%d\n",
	  width, height);

  return 0;
}


PsuValue::PsuValue(const char *name, Widget parent)
{
  _alarmText = 0;
  
  _baseWidget = XtVaCreateWidget(name, xmRowColumnWidgetClass, parent,
				 XmNorientation, XmHORIZONTAL,
				 NULL);
  
  installDestroyHandler();

  XtVaCreateManagedWidget("label", xmLabelWidgetClass, _baseWidget, NULL);
}


PsuValue::~PsuValue()
{
  delete _alarmText;
}


int PsuValue::createDescription(PsuAlarm *alarm)
{
  delete _alarmText;
  _alarmText = new PsuAlarmText("alarmText", _baseWidget, alarm);
  _alarmText->realize();
  _alarmText->show();
  XtManageChild(_baseWidget);
  return 0;
}


void PsuValue::clear()
{
  delete _alarmText;
  _alarmText = 0;
}


inline int AlarmEditor::stringCompare(const void *p1, const void *p2)
{
  return strcmp((const char *)*(char **)p1, (const char *)*(char **)p2);
}


AlarmEditor::AlarmEditor(const char *name, Widget parent) 
  : VkComponent(name)
{
  _monitoredValue = 0;
  _psuValue = 0;
  
  _baseWidget = XtVaCreateWidget(_name, xmFormWidgetClass, parent, 
				 XmNfractionBase, 5,
				 NULL, 0);

  installDestroyHandler();

  Widget workArea = 
    XtCreateWidget("", xmFormWidgetClass, _baseWidget, NULL, 0);

  MBool debug = FALSE;
  
  Widget mainLabel = XtVaCreateManagedWidget("alarmItems", xmLabelWidgetClass,
					     workArea, NULL);

  Arg args[10];
  int nArgs = 0;
  XtSetArg(args[nArgs], XmNlistSizePolicy, XmRESIZE_IF_POSSIBLE);
  nArgs++;
  /* Set scrollBarDisplayPolicy to xmAS_NEEDED, because if it's xmSTATIC
     then updating the list doesn't seem to properly update the scrollbar */
  XtSetArg(args[nArgs], XmNscrollBarDisplayPolicy, XmAS_NEEDED);
  nArgs++;
  XtSetArg(args[nArgs], XmNselectionPolicy, XmSINGLE_SELECT);
  nArgs++;
  XtSetArg(args[nArgs], XmNtopAttachment, XmATTACH_WIDGET);
  nArgs++;
  XtSetArg(args[nArgs], XmNtopWidget, mainLabel);
  nArgs++;  

  _listWidget = 
    XmCreateScrolledList(workArea, "alarmListWidget", args, nArgs);

  XtVaSetValues(XtParent(_listWidget),
		XmNleftAttachment, XmATTACH_FORM,
		XmNtopAttachment, XmATTACH_WIDGET,
		XmNtopWidget, mainLabel,
		XmNrightAttachment, XmATTACH_FORM,
		NULL);
  
  XtAddCallback(_listWidget, XmNsingleSelectionCallback, 
		&AlarmEditor::listSelectCallback, (XtPointer )this);
  
  TiburonApp *app = (TiburonApp *)theApplication;
  _alarms = app->systemAlarms;
  
  char **namePtr = (char **)malloc(_alarms->nAlarms() * sizeof(char *));
  if (namePtr == NULL)
  {
    fprintf(stderr, "AlarmEditor::AlarmEditor() - out of memory\n");
    exit(1);
  }

  // Sort alarm item names alphabetically  
  SListIter<Alarm *> alarms(_alarms->alarmList);
  
  alarms.reset();
  
  Alarm **alarm;
  int i;
  for (i = 0; alarm = alarms.next(); i++)
    namePtr[i] = strdup((*alarm)->name());

  dprintf(stderr, "AlarmEditor() - got %d names, nAlarms()=%d\n",
	  i, _alarms->nAlarms());

  int n = _alarms->nAlarms();

  qsort((void *)namePtr, n, sizeof(char *), &AlarmEditor::stringCompare);

  
  dprintf(stderr, "Gen %d alarm names\n", _alarms->nAlarms());

  for (i = 0; i < _alarms->nAlarms(); i++)
  {
    XmString xmstr = XmStringCreateSimple(namePtr[i]);
    XmListAddItem(_listWidget, xmstr, 0);
    XmStringFree(xmstr);
  }

  for (i = 0; i < _alarms->nAlarms(); i++)
    free(namePtr[i]);
  
  free(namePtr);

  XtManageChild(_listWidget);
  _entryMgr = XtVaCreateWidget("entryMgr", xmFormWidgetClass, workArea,
			       XmNtopAttachment, XmATTACH_WIDGET,
			       XmNtopWidget, _listWidget,
			       XmNleftAttachment, XmATTACH_FORM,
			       XmNrightAttachment, XmATTACH_FORM,
			       NULL);
  
  _itemName = 
    XtVaCreateManagedWidget("", xmLabelWidgetClass, 
			    _entryMgr, 
			    XmNtopAttachment, XmATTACH_FORM,
			    XmNleftAttachment, XmATTACH_FORM,
			    NULL);

  _itemType = 
    XtVaCreateManagedWidget("", xmLabelWidgetClass, 
			    _entryMgr, 
			    XmNtopAttachment, XmATTACH_WIDGET,
			    XmNtopWidget, _itemName,
			    XmNleftAttachment, XmATTACH_FORM,
			    NULL);
  
  _mnemonic = new LabeledText(_entryMgr, "mnemonic", XmHORIZONTAL);
  XtVaSetValues(_mnemonic->baseWidget(),
		XmNtopAttachment, XmATTACH_WIDGET,
		XmNtopWidget, _itemType,
		XmNleftAttachment, XmATTACH_FORM,
		NULL);
  
  _ackAllChanges = 
    XtVaCreateManagedWidget("ackAllChanges", 
			    xmToggleButtonWidgetClass,
			    _entryMgr,
			    XmNtopAttachment, XmATTACH_WIDGET,
			    XmNtopWidget, _mnemonic->baseWidget(),
			    XmNleftAttachment, XmATTACH_FORM,
			    NULL);

  _monitoredValue = 
    new MonitoredValue("monitoredValueBox", _entryMgr);
  
  XtVaSetValues(_monitoredValue->baseWidget(),
		XmNleftAttachment, XmATTACH_FORM,
		XmNrightAttachment, XmATTACH_FORM,
		XmNtopAttachment, XmATTACH_WIDGET,
		XmNtopWidget, _ackAllChanges,
		NULL);

  _monitoredValue->clear();
  _monitoredValue->show();

  _psuValue = new PsuValue("psuValue", _entryMgr);

  XtVaSetValues(_psuValue->baseWidget(),
		XmNtopAttachment, XmATTACH_WIDGET,
		XmNtopWidget, _monitoredValue->baseWidget(),
		XmNleftAttachment, XmATTACH_FORM,
		XmNrightAttachment, XmATTACH_FORM,
		NULL);
		
  _psuValue->clear();
  _psuValue->show();
  
  _valueHeader = 
    XtVaCreateManagedWidget("value", xmLabelWidgetClass, _entryMgr,
			    XmNtopAttachment, XmATTACH_WIDGET,
			    XmNtopWidget, _psuValue->baseWidget(),
			    XmNtopOffset, 30,
			    XmNleftAttachment, XmATTACH_FORM,
			    NULL);  

  Widget headerSeparator =
    XtVaCreateManagedWidget("headerSeparator", xmSeparatorWidgetClass, 
			    _entryMgr,
			    XmNleftAttachment, XmATTACH_FORM,
			    XmNrightAttachment, XmATTACH_FORM,
			    XmNtopAttachment, XmATTACH_WIDGET,
			    XmNtopWidget, _valueHeader,
			    NULL);  

  Pixel plainForeground, plainBackground;

  XtVaGetValues(_baseWidget, 
		XmNforeground, &plainForeground,
		XmNbackground, &plainBackground,
		NULL);
  
  for (i = 0; i < MaxAlarmValue; i++)
  {
    int topOffset;
    
    Widget topWidget;

    if (i == 0)
    {
      topWidget = headerSeparator;
      topOffset = 10;
    }
    else
    {
      topWidget = _priorityToggleBox[i - 1];
      topOffset = 0;
    }
    
    char name[30];

    sprintf(name, "value%d", i);
    
    _valueLabel[i] = 
      XtVaCreateManagedWidget(name, xmLabelWidgetClass, _entryMgr,
			      XmNtopAttachment, XmATTACH_WIDGET,
			      XmNtopWidget, topWidget,
			      XmNtopOffset, topOffset,
			      XmNleftAttachment, XmATTACH_FORM,
			      NULL);
    
    sprintf(name, "priorities%d", i);
    
    const int leftPosition = 15;
    
    _priorityToggleBox[i] = 
      XtVaCreateWidget(name, xmRowColumnWidgetClass, _entryMgr, 
		       XmNisHomogeneous, True,
		       XmNentryClass, xmToggleButtonGadgetClass,
		       XmNradioBehavior, True,
		       XmNorientation, XmHORIZONTAL,
		       XmNtopAttachment, XmATTACH_WIDGET,
		       XmNtopWidget, topWidget,
		       XmNtopOffset, topOffset,
		       XmNleftAttachment, XmATTACH_POSITION,
		       XmNleftPosition, leftPosition, 
		       NULL);
  
    Widget toggleButton;
    for (int p = 0; p < NPriorityLevels; p++)
    {
      Pixel foreground, background;
      app->priorityColors((Priority )(p + 1), &foreground, &background);
      
      sprintf(name, "priority%d", p + 1);
      
      toggleButton = 
	XtVaCreateManagedWidget(name, 
				xmToggleButtonWidgetClass,
				_priorityToggleBox[i], 
				XmNforeground, foreground,
				XmNbackground, background,
				NULL);
    }

    toggleButton = 
      XtVaCreateManagedWidget("noPriority",
			      xmToggleButtonWidgetClass,
			      _priorityToggleBox[i], 
			      XmNforeground, plainForeground,
			      XmNbackground, plainBackground,
			      NULL);

    XtManageChild(_priorityToggleBox[i]);

    _thresholdBox[i] = new ThresholdBox("thresholdBox", _entryMgr);
    
    XtVaSetValues(_thresholdBox[i]->baseWidget(),
		  XmNleftAttachment, XmATTACH_WIDGET,
		  XmNleftWidget, _priorityToggleBox[i],
		  XmNrightAttachment, XmATTACH_FORM,
		  XmNtopAttachment, XmATTACH_WIDGET,
		  XmNtopWidget, topWidget,
		  XmNtopOffset, topOffset,
		  NULL);

    _thresholdBox[i]->clear();
    _thresholdBox[i]->show();
  }

  Widget label = 
    XtVaCreateManagedWidget("priorityHeader", xmLabelWidgetClass, _entryMgr,
			    XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET,
			    XmNleftWidget, _priorityToggleBox[0],
			    XmNbottomAttachment, XmATTACH_WIDGET,
			    XmNbottomWidget, headerSeparator,
			    NULL);

  _thresholdHeader = 
    XtVaCreateManagedWidget("thresholdHeader", xmLabelWidgetClass, _entryMgr,
			    XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET,
			    XmNleftWidget, _thresholdBox[0]->baseWidget(),
			    XmNbottomAttachment, XmATTACH_WIDGET,
			    XmNbottomWidget, headerSeparator,
			    NULL);
  

  XtSetMappedWhenManaged(_thresholdHeader, False);

  XtSetMappedWhenManaged(_entryMgr, False);
  XtManageChild(_entryMgr);


  XtVaSetValues(workArea,
		XmNleftAttachment, XmATTACH_FORM,
		XmNrightAttachment, XmATTACH_FORM,
		XmNtopAttachment, XmATTACH_FORM,
		XmNbottomAttachment, XmATTACH_FORM,
		NULL);
		
  XtManageChild(workArea);

  XtManageChild(_baseWidget);

}


AlarmEditor::~AlarmEditor()
{
  delete _monitoredValue;
  delete _psuValue;
}


void AlarmEditor::selectItem(char *name)
{
  XmString xmstr = XmStringCreateSimple(name);
  XmListSelectItem(_listWidget, xmstr, True);
  XmListSetItem(_listWidget, xmstr);
  XmStringFree(xmstr);
}


void AlarmEditor::displayItem(char *name)
{
  MBool debug = FALSE;
  dprintf(stderr, "Selected item %s\n", name);

  SListIter<Alarm *> alarms(_alarms->alarmList);
  alarms.reset();
  Alarm **alarm;
  MBool found = FALSE;
  while (alarm = alarms.next())
  {
    if (!strcmp(name, (*alarm)->name()))
    {
      found = TRUE;
      break;
    }
  }
  if (!found)
  {
    fprintf(stderr, 
	    "AlarmEditor::displayItem() - couldn't find \"%s\" in "
	    "system alarm list\n",
	    name);
    exit(1);
  }
  char str[512];
  XmString xmstr;
  
  sprintf(str, "DM Item: %s", (*alarm)->name());
  xmstr = XmStringCreateSimple(str);
  XtVaSetValues(_itemName, XmNlabelString, xmstr, NULL);
  XmStringFree(xmstr);
  sprintf(str, "Alarm type: %s", Alarm::typeMnemonic((*alarm)->type()));
  xmstr = XmStringCreateSimple(str);  
  XtVaSetValues(_itemType, XmNlabelString, xmstr, NULL);  
  XmStringFree(xmstr);
  _mnemonic->set((*alarm)->itemMnemonic());
  dprintf(stderr, "ackAllChanges: %d\n", (*alarm)->ackAllChanges());
  
  if ((*alarm)->eventAlarm())
  {
    // Events must always be acknowledged
    XtVaSetValues(_ackAllChanges, XmNset, True, NULL);
    XtSetSensitive(_ackAllChanges, False);
  }
  else
  {
    XtSetSensitive(_ackAllChanges, True);
    if ((*alarm)->ackAllChanges())
      XtVaSetValues(_ackAllChanges, XmNset, True, NULL);
    else
      XtVaSetValues(_ackAllChanges, XmNset, False, NULL);
  }

  XtUnmanageChildren(_valueLabel, MaxAlarmValue);
  XtUnmanageChildren(_priorityToggleBox, MaxAlarmValue);  
  XtUnmapWidget(_thresholdHeader);
  
  for (int i = 0; i < MaxAlarmValue; i++)
  {
    _thresholdBox[i]->clear();
    _thresholdBox[i]->hide();
  }
  
  _monitoredValue->clear();
  _monitoredValue->hide();
  _psuValue->clear();
  _psuValue->hide();

  int numButtons;
  WidgetList buttons;

  if (!(*alarm)->multiValued())
  {
    XmString xmstr = XmStringCreateSimple("");
    XtVaSetValues(_valueHeader, XmNlabelString, xmstr, NULL);
    XmStringFree(xmstr);
    xmstr = XmStringCreateSimple(" ");
    XtVaSetValues(_valueLabel[0], XmNlabelString, xmstr, NULL);
    XmStringFree(xmstr);

    
    // Set priority toggle button
    XtVaGetValues(_priorityToggleBox[0], XmNnumChildren, &numButtons,
		  XmNchildren, &buttons, NULL );
    
    Priority priority = (*alarm)->priority(NoAlarmValue);
    int p;
    if (priority == NoPriority)
      // Last button represents "NoPriority"
      p = numButtons - 1;
    else
      p = priority - 1;

    for (int i = 0; i < numButtons; i++) 
    {
      if (i == p)
	XtVaSetValues(buttons[i], XmNset, True, NULL);
      else
	XtVaSetValues(buttons[i], XmNset, False, NULL);
    }

    XtVaSetValues(_priorityToggleBox[0], 
		  XmNmenuHistory, buttons[p], NULL);
    
    XtManageChild(_valueLabel[0]);
    XtManageChild(_priorityToggleBox[0]);
    if (psuAlarm((*alarm)->type()))
    {
      _psuValue->createDescription((PsuAlarm *)(*alarm));
      _psuValue->show();
      XtManageChild(_entryMgr);
    }
  }
  else
  {
    XmString xmstr = XmStringCreateSimple("Value");
    XtVaSetValues(_valueHeader, XmNlabelString, xmstr, NULL);
    XmStringFree(xmstr);

    int nLabel = 0;
    for (int value = 0; ; value++)
    {
      if (value == (*alarm)->okayValue())
	continue;
    
      char *mnem = Alarm::valueMnemonic((*alarm)->type(), value);
      if (!strcmp(mnem, Alarm::UnkValueMnem))
	// Done
	  break;

      XmString xmstr = XmStringCreateSimple(mnem);
      XtVaSetValues(_valueLabel[nLabel], XmNlabelString, xmstr, NULL);
      XmStringFree(xmstr);

      // Set priority toggle button
      XtVaGetValues(_priorityToggleBox[nLabel], XmNnumChildren, &numButtons,
		    XmNchildren, &buttons, NULL );
    
      Priority priority = (*alarm)->priority(value);
      int p;
      if (priority == NoPriority)
        // Last button represents "NoPriority"
	p = numButtons - 1;
      else
	p = priority - 1;

      for (int i = 0; i < numButtons; i++) 
      {
	if (i == p)
	  XtVaSetValues(buttons[i], XmNset, True, NULL);
	else
	  XtVaSetValues(buttons[i], XmNset, False, NULL);
      }
      
      XtVaSetValues(_priorityToggleBox[nLabel], 
		    XmNmenuHistory, buttons[p], NULL);

      if ((*alarm)->type() == IbcAlarmType)
      {
	IbcAlarm *ibcAlarm = (IbcAlarm *)(*alarm);
	_thresholdBox[nLabel]->createThreshold(ibcAlarm, value);
      }
      nLabel++;
    }

    XtManageChildren(_valueLabel, nLabel);
    XtManageChildren(_priorityToggleBox, nLabel);
    if ((*alarm)->type() == IbcAlarmType)
    {
      XtMapWidget(_thresholdHeader);
      for (int i = 0; i < nLabel; i++)
	_thresholdBox[i]->show();

      XtManageChild(_entryMgr);
    }

    if ((*alarm)->graduated())
    {
      dprintf(stderr, "Show monitored value\n");
      
      _monitoredValue->createValue((GraduatedAlarm *)(*alarm));
      _monitoredValue->show();
      XtManageChild(_entryMgr);
    }
  }

  XtMapWidget(_entryMgr);
}


void AlarmEditor::updateAlarmItem()
{
  MBool debug = FALSE;
  
  int nSelected;
  XmString *selectedItem;
  
  XtVaGetValues(_listWidget, XmNselectedItems, &selectedItem,
		XmNselectedItemCount, &nSelected, NULL);
  
  dprintf(stderr, "AlarmEditor::updateAlarmItem() - %d selected items\n",
	  nSelected);

  if (!nSelected)
    // No item selected
    return;
   
  char *itemName;
  XmStringGetLtoR(selectedItem[0], XmSTRING_DEFAULT_CHARSET, &itemName);

  MBool found = FALSE;
  Alarm **alarm;

  SListIter<Alarm *> alarms(_alarms->alarmList);

  alarms.reset();
  while (alarm = alarms.next())
  {
    if (!strcmp(itemName, (*alarm)->name()))
    {
      found = TRUE;
      break;
    }
  }
  if (!found)
  {
    fprintf(stderr, 
	    "AlarmEditor::updateAlarmItem() - couldn't find \"%s\" in "
	    "system alarm list\n", itemName);
    exit(1);
  }
  XtFree(itemName);

  (*alarm)->setItemMnemonic((char *)_mnemonic->get());
  Boolean set;
  XtVaGetValues(_ackAllChanges, XmNset, &set, NULL);
  (*alarm)->setAckAllChanges((MBool )set);

  int numButtons;
  WidgetList buttons;

  if (!(*alarm)->multiValued())
  {
    XtVaGetValues(_priorityToggleBox[0], XmNnumChildren, &numButtons,
		  XmNchildren, &buttons, NULL );

    for (int p = 0; p < numButtons; p++)
    {
      Boolean set;
      XtVaGetValues(buttons[p], XmNset, &set, NULL);
      if (set)
      {
	if (p < numButtons - 1)
	  (*alarm)->setPriority((Priority )(p + 1));
	else
          // Last button in toggleBox is "NoPriority"
	  (*alarm)->setPriority(NoPriority);

	break;
      }
    }
  }
  else
  {
    int nLabel = 0;
    for (int value = 0; ; value++)
    {
      if (value == (*alarm)->okayValue())
	continue;
    
      char *mnem = Alarm::valueMnemonic((*alarm)->type(), value);
      if (!strcmp(mnem, Alarm::UnkValueMnem))
	// Done
	  break;

      XtVaGetValues(_priorityToggleBox[nLabel], XmNnumChildren, &numButtons,
		    XmNchildren, &buttons, NULL );
    
      for (int p = 0; p < numButtons; p++)
      {
	Boolean set;
	XtVaGetValues(buttons[p], XmNset, &set, NULL);
	if (set)
	{
	  if (p < numButtons - 1)
	    (*alarm)->setPriority(value, (Priority )(p + 1));
	  else
          // Last button in toggleBox is "NoPriority"
	  (*alarm)->setPriority(value, NoPriority);

	  break;
	}
      }
      nLabel++;
    }
  }
}


void AlarmEditor::listSelectCallback(Widget w, XtPointer clientData, 
				     XtPointer callData)
{
  AlarmEditor *obj = (AlarmEditor *)clientData;
  XmListCallbackStruct *cb = (XmListCallbackStruct *)callData;
  if (!cb->selected_item_count)
  {
    XtUnmapWidget(obj->_entryMgr);    
    return;
  }
  
  XtManageChild(obj->_entryMgr);
  char *choice;
  XmStringGetLtoR(cb->item, XmSTRING_DEFAULT_CHARSET, &choice);
  obj->displayItem(choice);
  XtFree(choice);
}






