#include <Xm/Frame.h>
#include <Xm/Form.h>
#include <Xm/RowColumn.h>
#include <Xm/PushB.h>
#include <Xm/ToggleB.h>
#include <Xm/Label.h>
#include <Xm/ArrowB.h>
#include <Xm/Scale.h>
#include <xpm.h>
#include <Vk/VkErrorDialog.h>
#include "MidwaterGui.h"
#include "mwsledDcon.h"
#include "powerDM.h"
#include "DmErrno.h"
#include "netNanny.xpm"
#include "TiburonApp.h"
 
#define dprintf if (debug) fprintf


SwingArm::SwingArm(const char *name, Widget parent, Side side,
		   MidwaterDm *dmItems)
  : DmGuiObject(name, parent)
{
  _baseWidget = XtVaCreateWidget(name, xmFrameWidgetClass, parent, 
				 NULL);
  
  installDestroyHandler();
  
  Widget mgr = 
    XtVaCreateWidget("mgr", xmRowColumnWidgetClass, _baseWidget,
		     XmNorientation, XmVERTICAL, 
		     NULL);
  
  Widget label = 
    XtVaCreateManagedWidget("label", xmLabelWidgetClass, mgr, NULL);
  
  Widget mgr2 = 
    XtVaCreateWidget("mgr2", xmRowColumnWidgetClass, mgr,
		     XmNorientation, XmHORIZONTAL,
		     NULL);

  char itemName[MaxDmNameLen];
  strcpy(itemName, POWER_DM_PREFIX);
  char *namePtr = itemName + strlen(itemName);
  
  if (side == PortSide)
    strcpy(namePtr, PORT_SA_DEPLOY_DM);
  else
    strcpy(namePtr, STBD_SA_DEPLOY_DM);

  _deploy = new MomentaryPowerSwitch("deploy", mgr2, itemName, "Deploy",
				     100, 50, 500, True);
  
  _deploy->show();
  
  if (side == PortSide)
    strcpy(namePtr, PORT_SA_STOW_DM);
  else
    strcpy(namePtr, STBD_SA_STOW_DM);

  _stow = new MomentaryPowerSwitch("stow", mgr2, itemName, "Stow",
				   100, 50, 500, True);
  
  _stow->show();

  XtManageChild(mgr2);
  

  label = XtVaCreateManagedWidget("positionLabel", xmLabelWidgetClass, mgr2,
				  NULL);
  
  _position = new DynamicLabel("position", mgr2);
  _position->show();
  
  XtManageChild(mgr2);

  mgr2 = 
    XtVaCreateWidget("mgr2", xmRowColumnWidgetClass, mgr,
		     XmNnumColumns, 2,
		     XmNpacking, XmPACK_COLUMN,
		     XmNorientation, XmHORIZONTAL,
		     NULL);

  unsigned firstValveNo;
  unsigned nValves;
  
  if (side == PortSide)
  {
    firstValveNo = 1;
    nValves = 4;
  }
  else
  {
    firstValveNo = 5;
    nValves = 3;
  }
  
  valves = new DetritusSamplerValves("valves", mgr2, 
				     nValves,
				     firstValveNo,
				     MWSLED_DM_PREFIX);
  valves->show();
  
  XtManageChild(mgr2);
  
  XtManageChild(mgr);


  if (side == SwingArm::PortSide)
  {
    _dmPosition = dmItems->portSwingArmPosition;
  }
  else
  {
    _dmPosition = dmItems->stbdSwingArmPosition;
  }

  if (addDmObject(_dmPosition, DmConsumeFlag) == -1)
    return;

  if (setConsumePeriod(Aperiodic) == -1)
    return;

  _position->setText("         ");
  
  updateGui();
}


SwingArm::~SwingArm()
{
  delete _position;
  delete valves;
}


void SwingArm::updateGui(DM_Item)
{
  DM_Time t;
  Errno errno;
  char buf[errorMsgSize];
  Int16 position;
  
  if ((errno = _dmPosition->read(&position, &t)) != SUCCESS)
  {
    sprintDmError(errno, "SwingArm::updateGui()", buf);
    setError(buf);
    return;
  }

  sprintf(buf, "%d", position);
  _position->setText(buf);
}



SwingArms::SwingArms(const char *name, Widget parent, MidwaterDm *dmItems)
{
  _baseWidget = XtVaCreateWidget(name, xmFormWidgetClass, parent,
				 NULL);
  
  installDestroyHandler();
  
  Widget label = 
    XtVaCreateManagedWidget("label", xmLabelWidgetClass, _baseWidget,
			    XmNtopAttachment, XmATTACH_FORM,
			    XmNleftAttachment, XmATTACH_FORM,
			    NULL);
  
  portSwingArm = new SwingArm("portSwingArm", _baseWidget, 
			       SwingArm::PortSide, dmItems);

  XtVaSetValues(portSwingArm->baseWidget(),
		XmNleftAttachment, XmATTACH_FORM,
		XmNtopAttachment, XmATTACH_WIDGET,
		XmNtopWidget, label,
		NULL);
  
  portSwingArm->show();

  stbdSwingArm = new SwingArm("stbdSwingArm", _baseWidget,
			       SwingArm::StbdSide, dmItems);

  XtVaSetValues(stbdSwingArm->baseWidget(),
		XmNleftAttachment, XmATTACH_WIDGET,
		XmNleftWidget, portSwingArm->baseWidget(),
		XmNtopAttachment, XmATTACH_WIDGET,
		XmNtopWidget, label,
		NULL);

  stbdSwingArm->show();

}



SwingArms::~SwingArms()
{
}


SuctionSamplerIndex::SuctionSamplerIndex(const char *name,
					 Widget parent,
					 MidwaterDm *dmItems, 
					 int period)
  : DmGuiObject(name, parent)
{
  _baseWidget = 
    XtVaCreateWidget(name, xmRowColumnWidgetClass, parent,
		     XmNorientation, XmVERTICAL,
		     NULL);

  installDestroyHandler();

  Widget mgr;
  Widget toggleMgr1, toggleMgr2;

  mgr = XtVaCreateWidget("mgr", xmFormWidgetClass, _baseWidget, NULL);

  toggleMgr1 = 
    XtVaCreateWidget("toggleMgr1", xmRowColumnWidgetClass, mgr,
		     XmNorientation, XmVERTICAL,
		     XmNleftAttachment, XmATTACH_FORM,
		     XmNtopAttachment, XmATTACH_FORM,
		     XmNbottomAttachment, XmATTACH_FORM,
		     NULL);

  _revIndex = 
    XtVaCreateManagedWidget("ccwIndex", xmArrowButtonWidgetClass, toggleMgr1,
			    XmNarrowDirection, XmARROW_LEFT,
			    NULL);

  XtAddCallback(_revIndex, XmNarmCallback, 
		&SuctionSamplerIndex::callback,
		(XtPointer )this);

  XtAddCallback(_revIndex, XmNdisarmCallback, 
		&SuctionSamplerIndex::callback,
		(XtPointer )this);

  _revIndexCurrent = new DynamicLabel("revIndexCurrent", toggleMgr1);
  _revIndexCurrent->show();
  
  XtManageChild(toggleMgr1);
  
  toggleMgr2 = 
    XtVaCreateWidget("toggleMgr2", xmRowColumnWidgetClass, mgr,
		     XmNorientation, XmVERTICAL,
		     XmNleftAttachment, XmATTACH_WIDGET,
		     XmNleftWidget, toggleMgr1,
		     XmNtopAttachment, XmATTACH_FORM,
		     XmNbottomAttachment, XmATTACH_FORM,
		     NULL);

  _fwdIndex = 
    XtVaCreateManagedWidget("cwIndex", xmArrowButtonWidgetClass, toggleMgr2,
			    XmNarrowDirection, XmARROW_RIGHT,
			    NULL);
  
  XtAddCallback(_fwdIndex, XmNarmCallback, 
		&SuctionSamplerIndex::callback,
		(XtPointer )this);

  XtAddCallback(_fwdIndex, XmNdisarmCallback, 
		&SuctionSamplerIndex::callback,
		(XtPointer )this);

  _fwdIndexCurrent = new DynamicLabel("fwdIndexCurrent", toggleMgr2);
  _fwdIndexCurrent->show();

  XtManageChild(toggleMgr2);
  
  // Get colors to use in re-drawing buttons
  XtVaGetValues(_fwdIndex,
		XmNtopShadowColor, &_lightEdgeColor, 
		XmNbottomShadowColor, &_darkEdgeColor,
		NULL);

  _autoIndex = 
    XtVaCreateManagedWidget("autoIndex", xmToggleButtonWidgetClass, mgr,
			    XmNleftAttachment, XmATTACH_WIDGET,
			    XmNleftWidget, toggleMgr2,
			    XmNtopAttachment, XmATTACH_FORM,
			    NULL);

  XtAddCallback(_autoIndex, XmNvalueChangedCallback, 
		&SuctionSamplerIndex::callback,
		(XtPointer )this);
  
  Widget label = 
    XtVaCreateManagedWidget("senseLabel", xmLabelWidgetClass, mgr, 
			    XmNleftAttachment, XmATTACH_WIDGET,
			    XmNleftWidget, _autoIndex,
			    XmNtopAttachment, XmATTACH_FORM,
			    NULL);

  _indexSense = 
    XtVaCreateManagedWidget("indexSense", xmLabelWidgetClass, mgr, 
			    XmNleftAttachment, XmATTACH_WIDGET,
			    XmNleftWidget, label,
			    XmNtopAttachment, XmATTACH_FORM,
			    NULL);
  
  
  XtManageChild(mgr);

  TiburonApp *app = (TiburonApp *)theApplication;
  app->okColors(&_atIndexForeground, &_atIndexBackground);
  app->priority2Colors(&_movingForeground, &_movingBackground);
  app->powerOnColors(&_onForeground, &_onBackground);

  // Use default foreground/background for "off" state 
  XtVaGetValues(_baseWidget, 
		XmNforeground, &_offForeground,
		XmNbackground, &_offBackground,
		NULL);
  
  app->faultColors(&_faultForeground, &_faultBackground);

  _dmIndexSense = dmItems->ssIndexSense;
  _dmAutoIndex = dmItems->ssAutoIndex;


  char prefix[MaxDmNameLen];
  strcpy(prefix, POWER_DM_PREFIX);
  char *namePtr = prefix + strlen(prefix);

  strcpy(namePtr, SS_INDEX_REV_DM);
  _dmReverse = new SwitchDm(prefix);

  strcpy(namePtr, SS_INDEX_FWD_DM);
  _dmForward = new SwitchDm(prefix);
  
  _revStatusDetector = 
    new DmInputDetector("revStatus", parent, _dmReverse->status, this);

  _fwdStatusDetector = 
    new DmInputDetector("fwdStatus", parent, _dmForward->status, this);
  
  if (addDmObject(_dmForward->request, DmProvideFlag) == -1)
    return;

  if (addDmObject(_dmForward->current, DmConsumeFlag) == -1)
    return;

  if (addDmObject(_dmReverse->request, DmProvideFlag) == -1)
    return;

  if (addDmObject(_dmReverse->current, DmConsumeFlag) == -1)
    return;

  if (addDmObject(_dmIndexSense, DmConsumeFlag) == -1)
    return;

  if (addDmObject(_dmAutoIndex, DmProvideFlag | DmConsumeFlag) == -1)
    return;

  if (setConsumePeriod(period) == -1)
    return;

  _autoMode = FALSE;
  
  _fwdSwitchStatus = _revSwitchStatus = SWITCH_OFF;
  _prevIndexSense = -999;
  
  updateFromPeer(_revStatusDetector, NULL);
  updateFromPeer(_fwdStatusDetector, NULL);
  updateGui();
}


SuctionSamplerIndex::~SuctionSamplerIndex()
{
  delete _fwdStatusDetector;
  delete _revStatusDetector;
  
  delete _dmForward;
  delete _dmReverse;

  delete _fwdIndexCurrent;
  delete _revIndexCurrent;
}


void SuctionSamplerIndex::updateGui(DM_Item handle)
{
  DM_Time t;
  Errno errno;
  char errorBuf[errorMsgSize];
  
  if ((errno = _dmAutoIndex->read(&_autoMode, &t)) != SUCCESS)
  {
    sprintDmError(errno, "SuctionSamplerIndex::updateGui()", errorBuf);
    return;
  }

  Boolean set;
  if (_autoMode)
    set = True;
  else
    set = False;
  
  XtVaSetValues(_autoIndex, XmNset, set, NULL);

  MBool value;
  
  if ((errno = _dmIndexSense->read(&value, &t)) != SUCCESS)
  {
    sprintDmError(errno, "SuctionSamplerIndex::updateGui()", errorBuf);
    return;
  }

  if (value != _prevIndexSense)
  {
    XmString xmstr;
  
    Pixel foreground, background;
  
    if (value)
    {
      foreground = _atIndexForeground;
      background = _atIndexBackground;
      xmstr = XmStringCreateSimple("YES");
    }
    else
    {
      foreground = _movingForeground;
      background = _movingBackground;
      xmstr = XmStringCreateSimple("NO");
    }

    XtVaSetValues(_indexSense, XmNlabelString, xmstr, 
		  XmNforeground, foreground, XmNbackground, background,
		  NULL);
  
    XmStringFree(xmstr);

    _prevIndexSense = value;
  }

  if (_fwdSwitchStatus == SWITCH_ON)
    updateCurrent(Forward);

  if (_revSwitchStatus == SWITCH_ON)
    updateCurrent(Reverse);
}


void SuctionSamplerIndex::updateCurrent(SuctionSamplerIndex::Direction direction)
{
  SwitchDm *dm;
  DynamicLabel *label;
  
  switch (direction)
  {
    case Forward:
    label = _fwdIndexCurrent;
    dm = _dmForward;
    break;
    
    case Reverse:
    label = _revIndexCurrent;
    dm = _dmReverse;
    break;
    
    default:
    return;
  }

  
  Int16 current;
  
  DM_Time t;

  dm->current->read(&current, &t);
  char buf[100];
  sprintf(buf, "%4.1fA", current / 1000.);
  label->setText(buf);
  
  return;
}


void SuctionSamplerIndex::updateFromPeer(DmGuiObject *peer, void *clientData)
{
  SwitchDm *switchDm;
  Widget button;
  switchStatus *status;
  DynamicLabel *label;
  
  if (peer == _revStatusDetector)
  {
    switchDm = _dmReverse;
    button = _revIndex;
    status = &_revSwitchStatus;
    label = _revIndexCurrent;
  }
  else if (peer == _fwdStatusDetector)
  {
    switchDm = _dmForward;
    button = _fwdIndex;
    status = &_fwdSwitchStatus;
    label = _fwdIndexCurrent;
  }
  else
    return;
  
  
  char errorBuf[errorMsgSize];
  
  Boolean debug = False;
  dprintf(stderr, "SuctionSamplerIndex::updateFromPeer()\n");

  DM_Time t;
  Errno err;
  
  // Read status
  Int32 value;
  
  if ((err = switchDm->status->read(&value, &t)) != SUCCESS)
  {
    sprintDmError(err, "SuctionSamplerIndex::updateFromPeer()", errorBuf);
    setError(errorBuf);
    return;
  }
  *status = value;
  
  // Set button colors appropriate to switch status
  Pixel foreground, background;
  Pixel topColor, bottomColor, selectColor, borderColor;
  
  char buf[100];

  switch (*status)
  {  
    case SWITCH_NO_POWER:
    foreground = _noPwrForeground;
    background = _noPwrBackground;
    label->setText("NO PWR");
    label->show();
    break;
    
    case SWITCH_OFF:
    foreground = _offForeground;
    background = _offBackground;
    label->setText(" ");
    break;
    
    case SWITCH_ON:
    foreground = _onForeground;
    background = _onBackground;
    label->show();
    break;
    
    case SWITCH_POWER_ERROR:
    foreground = _faultForeground;
    background = _faultBackground;
    label->setText("FAULT");
    label->show();
    break;

    default:
    return;
  }

  // Just set background color (i.e. do not change arrow color)
  XtVaSetValues(button, XmNbackground, background, NULL);
}


void SuctionSamplerIndex::toggleAuto(MBool set)
{
  DM_Time t;
  gettimeofday(&t, NULL);
  Errno errno;
  char errorBuf[errorMsgSize];
  
  if ((errno = _dmAutoIndex->write(set, &t)) != SUCCESS)
  {
    sprintDmError(errno, "SuctionSamplerIndex::toggleAuto()", errorBuf);
    theErrorDialog->postAndWait(errorBuf);
  }
}


void SuctionSamplerIndex::startStop(MBool start, Widget w)
{
  if (!start && _autoMode)
    // If auto mode, do not do anything when button is released
    return;

  
  DmEnumObject *dmRequest;
  
  if (w == _fwdIndex)
    dmRequest = _dmForward->request;
  else
    dmRequest = _dmReverse->request;
  
  DM_Time t;
  gettimeofday(&t, NULL);

  Errno errno;
  char errorBuf[errorMsgSize];
  switchStatus status;
  
  if (start)
    status = SWITCH_ON;
  else
    status = SWITCH_OFF;

  if ((errno = dmRequest->write(status, &t)) != SUCCESS)
  {
    sprintDmError(errno, "SuctionSamplerIndex::startStop()", errorBuf);
    theErrorDialog->postAndWait(errorBuf);
  }
}


void SuctionSamplerIndex::callback(Widget w,
				   XtPointer clientData,
				   XtPointer callData)
{
  SuctionSamplerIndex *obj = (SuctionSamplerIndex *)clientData;
  
  if (w == obj->_autoIndex)
  {
    XmToggleButtonCallbackStruct *cbs = 
      (XmToggleButtonCallbackStruct *)callData;

    MBool set;
    
    if (cbs->set)
      set = TRUE;
    else
      set = FALSE;
    
    obj->toggleAuto(set);
  }
  else if (w == obj->_fwdIndex || w == obj->_revIndex)
  {
    XmArrowButtonCallbackStruct *cbs = 
      (XmArrowButtonCallbackStruct *)callData;

    MBool start;
    
    if (cbs->reason == XmCR_ARM)
      start = TRUE;
    else
      start = FALSE;
    
    obj->startStop(start, w);
  }
}


SuctionSamplerPump::SuctionSamplerPump(const char *name,
				       Widget parent,
				       MidwaterDm *dmItems)
  : DmGuiObject(name, parent)
{
  _baseWidget =
    XtVaCreateWidget(name, xmRowColumnWidgetClass, parent,
		     XmNorientation, XmHORIZONTAL,
		     NULL);

  installDestroyHandler();
  
  Widget mgr, mgr2;

  mgr = _baseWidget;

  Widget label;
  
  mgr2 = 
    XtVaCreateWidget("mgr2", xmRowColumnWidgetClass, mgr, 
		     XmNorientation, XmVERTICAL, NULL);
  
  XtVaCreateManagedWidget("pumpLabel", xmLabelWidgetClass, mgr2, NULL);
			  
  XtManageChild(mgr2);
  
  mgr2 = 
    XtVaCreateWidget("mgr2", xmRowColumnWidgetClass, mgr, 
		     XmNorientation, XmVERTICAL, NULL);

  _speed = XtVaCreateManagedWidget("speed", xmScaleWidgetClass, mgr2,
				   XmNorientation, XmHORIZONTAL,
				   XmNminimum, 0,
				   XmNmaximum, 100,
				   XmNvalue, 0,
				   XmNshowValue, True,
				   NULL);

  XtAddCallback(_speed, XmNdragCallback, 
		&SuctionSamplerPump::speedCallback,
		(XtPointer )this);

  XtAddCallback(_speed, XmNvalueChangedCallback, 
		&SuctionSamplerPump::speedCallback,
		(XtPointer )this);
  
  XtVaCreateManagedWidget("speedLabel", xmLabelWidgetClass, mgr2, NULL);
  
  XtManageChild(mgr2);
  
  Widget toggleMgr = 
    XtVaCreateWidget("toggleMgr", xmRowColumnWidgetClass, mgr,
		     XmNorientation, XmHORIZONTAL,
		     XmNradioBehavior, True,
		     XmNradioAlwaysOne, True,
		     NULL);

  _stop = XtVaCreateManagedWidget("stop", xmToggleButtonWidgetClass, toggleMgr, NULL); 
  _fwd = XtVaCreateManagedWidget("fwd", xmToggleButtonWidgetClass, toggleMgr, NULL); 
  _rev = XtVaCreateManagedWidget("rev", xmToggleButtonWidgetClass, toggleMgr, NULL); 

  XtAddCallback(_stop, XmNarmCallback, &SuctionSamplerPump::directionCallback,
		(XtPointer )this);

  XtAddCallback(_fwd, XmNarmCallback, &SuctionSamplerPump::directionCallback,
		(XtPointer )this);

  XtAddCallback(_rev, XmNarmCallback, &SuctionSamplerPump::directionCallback,
		(XtPointer )this);
  
  XtManageChild(toggleMgr);
  
  XtManageChild(mgr);

  _dmSpeed = dmItems->ssPumpSpeed;
  _dmDirection = dmItems->ssPumpDirection;
  
  if (addDmObject(_dmSpeed, DmConsumeFlag | DmProvideFlag) == -1)
    return;

  if (addDmObject(_dmDirection, DmConsumeFlag | DmProvideFlag) == -1)
    return;
  
  if (setConsumePeriod(Aperiodic) == -1)
    return;

  _draggingSpeed = False;
  
  updateGui();
}


SuctionSamplerPump::~SuctionSamplerPump()
{
}


void SuctionSamplerPump::updateGui(DM_Item handle)
{
  DM_Time t;
  Errno errno;
  char errorBuf[errorMsgSize];
  Int16 speed;
  
  if (!_draggingSpeed)
  {
    if ((errno = _dmSpeed->read(&speed, &t)) != SUCCESS)
    {
      sprintDmError(errno, "SuctionSamplerPump::updateGui(), reading speed", errorBuf);
      setError(errorBuf);
      return;
    }

    XtVaSetValues(_speed, XmNvalue, speed, NULL);
  }

  Int32 direction;
  
  if ((errno = _dmDirection->read(&direction, &t)) != SUCCESS)
  {
    sprintDmError(errno, "SuctionSamplerPump::updateGui(), reading direction", errorBuf);
    setError(errorBuf);
    return;
  }

  switch (direction)
  {
    case MidwaterDm::PumpStop:
    XtVaSetValues(_stop, XmNset, True, NULL);
    XtVaSetValues(_fwd, XmNset, False, NULL);
    XtVaSetValues(_rev, XmNset, False, NULL);
    XtSetSensitive(_fwd, True);
    XtSetSensitive(_rev, True);
    break;
    
    case MidwaterDm::PumpForward:
    XtVaSetValues(_fwd, XmNset, True, NULL);
    XtVaSetValues(_stop, XmNset, False, NULL);
    XtVaSetValues(_rev, XmNset, False, NULL);
    XtSetSensitive(_fwd, True);
    XtSetSensitive(_rev, False);
    break;

    case MidwaterDm::PumpReverse:
    XtVaSetValues(_rev, XmNset, True, NULL);
    XtVaSetValues(_fwd, XmNset, False, NULL);
    XtVaSetValues(_stop, XmNset, False, NULL);
    XtSetSensitive(_fwd, False);
    XtSetSensitive(_rev, True);
    break;      
    
    default:
    sprintf(errorBuf, 
	    "SuctionSamplerPump::udpateGui(), unknown direction: %d", direction); 

    setError(errorBuf);
    return;
  }
}


void SuctionSamplerPump::setSensitive(Boolean sensitive)
{
  XtSetSensitive(_baseWidget, sensitive);
}


void SuctionSamplerPump::setSpeed(int value)
{
  DM_Time t;
  gettimeofday(&t, NULL);
  
  Int16 speed = (Int16 )value;
  Errno errno;
  char errorBuf[errorMsgSize];
  
  if ((errno = _dmSpeed->write(speed, &t)) != SUCCESS)
  {
    sprintDmError(errno, "SuctionSamplerPump::setSpeed()", errorBuf);
    fprintf(stderr, "%s\n", errorBuf);
  }
}


void SuctionSamplerPump::setDirection(MidwaterDm::PumpDirection direction)
{
  DM_Time t;
  gettimeofday(&t, NULL);
  Errno errno;
  char errorBuf[errorMsgSize];
  Int32 value = direction;
  
  if ((errno = _dmDirection->write(value, &t)) != SUCCESS)
  {
    sprintDmError(errno, "SuctionSamplerPump::setDirection()", errorBuf);
    fprintf(stderr, "%s\n", errorBuf);
  }
}



void SuctionSamplerPump::speedCallback(Widget w,
				       XtPointer clientData,
				       XtPointer callData)
{
  SuctionSamplerPump *obj = (SuctionSamplerPump *)clientData;
  
  XmScaleCallbackStruct *cbs = (XmScaleCallbackStruct *)callData;

  if (cbs->reason == XmCR_DRAG)
    obj->_draggingSpeed = True;
  else
    obj->_draggingSpeed = False;

  obj->setSpeed(cbs->value);
}


void SuctionSamplerPump::directionCallback(Widget w,
					   XtPointer clientData,
					   XtPointer callData)
{

  SuctionSamplerPump *obj = (SuctionSamplerPump *)clientData;

  MidwaterDm::PumpDirection direction;
  if (w == obj->_stop)
    direction = MidwaterDm::PumpStop;
  else if (w == obj->_fwd)
    direction = MidwaterDm::PumpForward;
  else if (w == obj->_rev)
    direction = MidwaterDm::PumpReverse;
  else
  {
    fprintf(stderr, "SuctionSamplerPump::directionCallback() - unknown direction!\n");
    return;
  }
    
  obj->setDirection(direction);
}


SuctionSampler::SuctionSampler(const char *name, Widget parent, 
			       MidwaterDm *dmItems)
{
  _baseWidget =
    XtVaCreateWidget(name, xmRowColumnWidgetClass, parent,
		     XmNorientation, XmVERTICAL,
		     NULL);
  
  installDestroyHandler();
  
  Widget label = 
    XtVaCreateManagedWidget("suctionSamplerLabel", xmLabelWidgetClass, 
			    _baseWidget, NULL);

  index = new SuctionSamplerIndex("index", _baseWidget, dmItems, 500);
  index->show();

  Widget mgr = 
    XtVaCreateWidget("mgr", xmRowColumnWidgetClass, _baseWidget, 
		     XmNorientation, XmHORIZONTAL, NULL);
  
  pump = new SuctionSamplerPump("pump", mgr, dmItems);
  pump->show();

  Widget mgr2 = 
    XtVaCreateWidget("mgr", xmRowColumnWidgetClass, mgr,
		     XmNorientation, XmVERTICAL,
		     NULL);
  
  XtVaCreateManagedWidget("nannyLabel", xmLabelWidgetClass, mgr2, NULL);
  
#ifdef ZILCH
  // Setup nanny pixmap
  XpmAttributes xpmAttributes;

  xpmAttributes.closeness = 40000;
  xpmAttributes.valuemask = XpmSize | XpmCloseness;
  
  Pixmap mask;
  
  if (XpmCreatePixmapFromData(theApplication->display(), 
			      DefaultRootWindow(theApplication->display()),
			      netNanny_xpm,
			      &_nannyPixmap,
			      &mask,
			      &xpmAttributes) != XpmSuccess)
  {
    _nannyPixmap = NULL;
  }

  XtVaCreateManagedWidget("pixmap", xmLabelWidgetClass, mgr2,
			  XmNlabelType, XmPIXMAP,
			  XmNlabelPixmap, _nannyPixmap,
			  NULL);

#else
  _nannyPixmap = NULL;  
#endif

  XtManageChild(mgr2);
  XtManageChild(mgr);
}

  
SuctionSampler::~SuctionSampler()
{
  delete index;
  delete pump;

  if (_nannyPixmap)
    XFreePixmap(theApplication->display(), _nannyPixmap);

}


MidwaterPower::MidwaterPower(const char *name, Widget parent,
			     MidwaterGui *midwaterGui)
{
  _baseWidget = XtVaCreateWidget(name, xmRowColumnWidgetClass, parent,
				XmNorientation, XmVERTICAL, NULL);
  
  installDestroyHandler();

  _midwaterGui = midwaterGui;
  
  Widget label = 
    XtVaCreateManagedWidget("powerLabel", xmLabelWidgetClass, _baseWidget, 
			    NULL);
  
  Widget mgr2 = 
    XtVaCreateWidget("mgr2", xmRowColumnWidgetClass, _baseWidget,
		     XmNorientation, XmHORIZONTAL, NULL);
  
  char itemName[MaxDmNameLen];
  strcpy(itemName, POWER_DM_PREFIX);

  char *namePtr = itemName + strlen(itemName);
  
  strcpy(namePtr, SA_POT_EXCITE_DM);
  
  armPositionSensor = 
    new PowerSwitchGui("armPositionSensor", mgr2, itemName,
		       "ArmPos Sensor", 100, 50, 500, True);
  
  armPositionSensor->addCallback(PowerSwitchGui::statusChangeCallback, this,
				 (VkCallbackMethod )
				 &MidwaterPower::statusCallback);
  
  armPositionSensor->show();

  strcpy(namePtr, SS_INDEX_EXCITE_DM);

  indexSensor = 
    new PowerSwitchGui("indexSensor", mgr2, itemName,
		       "Index Sensor", 100, 50, 500, True);
  
  indexSensor->addCallback(PowerSwitchGui::statusChangeCallback, this,
			   (VkCallbackMethod )
			   &MidwaterPower::statusCallback);
  
  indexSensor->show();

  strcpy(namePtr, TUNGSTEN_LAMP_DM);
  
  incandLight = new PowerSwitchGui("incandLight", mgr2,
				    itemName,
				    "Incand Light", 100, 50, 500, True);
  
  incandLight->show();

  strcpy(namePtr, SA_MOTOR_DM);
  
  arm = new PowerSwitchGui("arm", mgr2,
			   itemName,
			   "Swing-Arms", 100, 50, 500, True);
  
  arm->show();

  strcpy(namePtr, SS_PUMP_POWER_DM);
  
  pump = 
    new PowerSwitchGui("pump", mgr2, itemName,
		       "SS Pump", 100, 50, 500, True);
  
  pump->addCallback(PowerSwitchGui::statusChangeCallback, this,
		    (VkCallbackMethod )&MidwaterPower::statusCallback);

  pump->show();

  strcpy(namePtr, CAMERA_DM);
  
  pencilCamera = 
    new PowerSwitchGui("pencilCamera", mgr2, itemName,
		       "Camera", 100, 50, 500, True);

  pencilCamera->show();

  strcpy(namePtr, ACM_DM);
  
  acm = 
    new PowerSwitchGui("acm", mgr2, itemName,
		       "ACM", 100, 50, 500, True);

  acm->show();

  XtManageChild(mgr2);
}


MidwaterPower::~MidwaterPower()
{
  delete pump;
  delete incandLight;
  delete armPositionSensor;
  delete indexSensor;
  delete pencilCamera;
  delete acm;
}


void MidwaterPower::statusCallback(VkCallbackObject *obj,
				   void *clientData,
				   void *callData)
{
  Boolean debug = ((TiburonApp *)theApplication)->debug();
  
  dprintf(stderr, "MidwaterGui::powerSwitchCallback()\n");

  switchStatus status = (switchStatus )callData;

  if (obj == pump)
  {
    dprintf(stderr, "MidwaterGui::powerSwitchCallback() - pump status\n");

    switch (status)
    {
      case SWITCH_ON:
      case SWITCH_ON_CASCADE:
      _midwaterGui->suctionSampler->pump->setSensitive(True);
      break;
      
      default:
      _midwaterGui->suctionSampler->pump->setSensitive(False);
    }
  }
  else if (obj == armPositionSensor)
  {
    dprintf(stderr, "MidwaterGui::powerSwitchCallback() - exciter status\n");
  }
}



MidwaterGui::MidwaterGui(const char *name, Widget parent)
{
  _baseWidget = XtVaCreateWidget(name, xmFormWidgetClass, parent, NULL);
  
  installDestroyHandler();

  _dmItems = new MidwaterDm("midwaterDm", MWSLED_DM_PREFIX);

  Widget label;
  label = 
    XtVaCreateManagedWidget("hydraulicLabel", xmLabelWidgetClass, _baseWidget,
			    XmNleftAttachment, XmATTACH_FORM,
			    XmNtopAttachment, XmATTACH_FORM,
			    NULL);
  
  hydraulicSelect = new HydraulicSelect("hydraulicSelect", _baseWidget);
  XtVaSetValues(hydraulicSelect->baseWidget(),
		XmNleftAttachment, XmATTACH_WIDGET,
		XmNleftWidget, label,
		XmNtopAttachment, XmATTACH_FORM,
		NULL);
  
  hydraulicSelect->show();
  
  Widget powerFrame, armFrame, ssFrame;
  
  powerFrame =
    XtVaCreateManagedWidget("powerFrame", xmFrameWidgetClass, _baseWidget, 
			    XmNleftAttachment, XmATTACH_FORM,
			    XmNtopAttachment, XmATTACH_WIDGET,
			    XmNtopWidget, hydraulicSelect->baseWidget(),
			    XmNrightAttachment, XmATTACH_FORM,
			    NULL);

  power = new MidwaterPower("power", powerFrame, this);
  power->show();
  
  armFrame =
    XtVaCreateManagedWidget("armFrame", xmFrameWidgetClass, _baseWidget, 
			    XmNleftAttachment, XmATTACH_FORM,
			    XmNtopAttachment, XmATTACH_WIDGET,
			    XmNtopWidget, powerFrame,
			    XmNrightAttachment, XmATTACH_FORM,
			    NULL);
  
  swingArms = new SwingArms("swingArms", armFrame, _dmItems);
  swingArms->show();

  // Build array of ValveControls to use in ValveSwitchMap
  int nValves = 
    swingArms->portSwingArm->valves->nValves() + 
      swingArms->stbdSwingArm->valves->nValves();
  
  if ((_valveControl = 
       (ValveControl **)malloc(nValves * sizeof(ValveControl *))) == NULL)
  {
    fprintf(stderr, 
	    "MidwaterGui::MidwaterGui() - malloc of _valveControl failed\n");
    exit(1);
  }
  
  int j = 0;
  for (int i = 0 ; i < swingArms->portSwingArm->valves->nValves(); i++)
    _valveControl[j++] = swingArms->portSwingArm->valves->valve[i];
  
  for (int i = 0 ; i < swingArms->stbdSwingArm->valves->nValves(); i++)
    _valveControl[j++] = swingArms->stbdSwingArm->valves->valve[i];

  char itemName[MaxDmNameLen];
  
  strcpy(itemName, MWSLED_DM_PREFIX);
  strcat(itemName, "MAPPED_VALVENO");
  
  _switchMap = new ValveSwitchMap("switchMap", _baseWidget, 2,
				  itemName,
				  nValves,
				  _valveControl);
  
  XtVaSetValues(_switchMap->baseWidget(),
		XmNleftAttachment, XmATTACH_FORM,
		XmNtopAttachment, XmATTACH_WIDGET,
		XmNtopWidget, armFrame,
		XmNrightAttachment, XmATTACH_FORM,
		NULL);

  _switchMap->show();


  ssFrame =
    XtVaCreateManagedWidget("ssFrame", xmFrameWidgetClass, _baseWidget, 
			    XmNleftAttachment, XmATTACH_FORM,
			    XmNtopAttachment, XmATTACH_WIDGET,
			    XmNtopWidget, _switchMap->baseWidget(),
			    NULL);
  
  suctionSampler = new SuctionSampler("suctionSampler", ssFrame, 
				      _dmItems);
  suctionSampler->show();
}


MidwaterGui::~MidwaterGui()
{
  delete hydraulicSelect;
  delete power;
  delete swingArms;
  delete suctionSampler;
  delete _switchMap;
  free((void *)_valveControl);
}





