/************************************************************************/
/* Copyright 1993 MBARI							*/
/************************************************************************/
/* $Header: /usr/tiburon/unix/gui/proto/RCS/power.c,v 1.1 1998/01/28 16:17:12 oreilly Exp $			*/
/* Summary  : Creation and Callback Routines for Power screen of ROV GUI*/
/* Filename : power.c							*/
/* Author   : Bob Herlien (rah)						*/
/* Project  : New ROV							*/
/* $Revision: 1.1 $							*/
/* Created  : 05/21/92							*/
/************************************************************************/
/* Modification History:						*/
/* $Log: power.c,v $
 * Revision 1.1  1998/01/28 16:17:12  oreilly
 * Initial revision
 *
 * Revision 2.2  96/05/15  11:15:29  11:15:29  bobh (Bob Herlien)
 * Still supporting proto during final vehicle build
 * 
 * Revision 2.0  95/09/20  14:22:59  14:22:59  hebo (Bob Herlien)
 * Support for final vehicle integration.  AC, PDU micros.
 * 
 * Revision 1.6  93/12/17  15:04:50  15:04:50  hebo (Bob Herlien)
 * December Wet Test
 * 
 * Revision 1.5  93/07/08  18:10:50  18:10:50  hebo (Bob Herlien)
 * Prior to Prototype Phase I testing
 * 
 * Revision 1.2  93/01/21  10:34:15  10:34:15  hebo (Bob Herlien)
 * Changes after Level 0
 * 
 * Revision 1.0  92/11/20  12:03:26  12:03:26  hebo (Bob Herlien)
 * Initial revision
 * 
*/
/************************************************************************/

#include <sys/types.h>
#include <mbari/types.h>
#include <mbari/const.h>
#include <X11/Intrinsic.h>
#include <Xm/Xm.h>
#include <Xm/Frame.h>
#include <Xm/Form.h>
#include <Xm/PushB.h>
#include <Xm/Label.h>
#include <Xm/DialogS.h>
#include <Xm/RowColumn.h>
#include <Xm/TextF.h>
#include <X11/Xc/Xc.h>
#include <X11/Xc/ToggleB.h>
#include "rov.h"
#include "tiburon.h"
#include <microdef.h>
#include <ibc_card.h>
#include <powerDM.h>
#include <powerTypes.h>
#include <thrusterDM.h>
#include "power.h"
#include "alarm.h"
#include "ibc.h"
#include "rdmif.h"

typedef Errno	(*ErrFuncPtr)();


/********************************/
/*	External Functions	*/
/********************************/

Extern Widget	rovError( Widget parent, char *msg );
Extern Void	ibcStartTimeout( ibcItemDesc *idp, char *dmprefix );
Extern Void	ibcStopTimeout( ibcItemDesc *idp );
Extern ibcItemDesc *copyIbcItemDesc( Reg ibcItemDesc *idp );
Extern Widget	createIbcGroup( Widget parent, ibcItemSet *isp,
			        Dimension width, Int32 lpos, Int32 rpos );
Extern Void	createIbcItems( Reg ibcItemDesc *idp, char *dmprefix );
Extern Widget	CreateacForm( Widget parent );
Extern Widget	CreateregenForm( Widget parent );
Extern Void	initAC( Void );
Extern Void	initRegen( Void );
Extern MBool	graphItemInUse( DM_Item item );


/********************************/
/*	External Data		*/
/********************************/

Extern XtAppContext	appcontext;	/* The application context	*/
Extern AppData		appdata;	/* Application-wide resources	*/
Extern Select		v240Sel, a48Sel, b48Sel, acSel, regenSel;
Extern ibcItemDesc	*switchItemDesc[];
Extern char		buff[];		/* Misc buffer used application-wide*/


/********************************/
/*	Forward Declarations	*/
/********************************/

Errno powerSwitchCreate( Widget w, pwrSwitch *sp, Int32 xpos, Int32 ypos,
			 pwrObjDesc *pdp );
Errno powerBoardCreate( Widget w, pwrBoard *bp );
Errno powerCanCreate( Widget w, pwrCan *cp, Int32 xpos, Int32 ypos,
		      pwrObjDesc *pdp );
Errno powerBusCreate( Widget w, pwrBus *bp, Int32 xpos, Int32 ypos );
Errno powerLabelCreate( Widget w, char *labelString, Int32 xpos, Int32 ypos );


/********************************/
/*	Module Local Data	*/
/********************************/

MLocal char	*pwr_name = TIBURON_DM_PREFIX "POWER.";
MLocal char	*req_name = ".SWITCH_REQ";
MLocal char	*sts_name = ".SWITCH_STATUS";
MLocal MBool	pwr_diag = FALSE;
MLocal Widget	pwrFormW, pwrDiagWidget, pwrDialog;
MLocal XtIntervalId	timeoutId;
MLocal Pixel	pwrToggleOnColor;
MLocal char	pwrBuff[1024];

MLocal switchStatus switchNoPwrSts = SWITCH_NO_POWER;

MLocal Int32	sw_pos[] = { 2, 24, 43, 62, 81 };

MLocal Pixel	*pwrFgColors[] = 
{&appdata.nopwr_fg, &appdata.pwroff_fg, &appdata.pwron_fg, &appdata.pwrerr_fg};

MLocal Pixel	*pwrBgColors[] = 
{&appdata.nopwr_bg, &appdata.pwroff_bg, &appdata.pwron_bg, &appdata.pwrerr_bg};

MLocal ErrFuncPtr	createFuncs[] = 
{ powerCanCreate, powerBoardCreate, powerSwitchCreate, powerBusCreate,
  powerLabelCreate };

/* Positioning of Power Setpoint Dialogs */
MLocal Int32	pwrPos = 0;
MLocal Dimension pwrDialogX[] = {  50, 500,  50, 500,  50, 500 };
MLocal Dimension pwrDialogY[] = { 300, 300, 500, 500, 100, 100 };


/************************************************************************/
/* Function    : pwrSwitchEach						*/
/* Purpose     : Call a function for each power switch in pwrObjDesc	*/
/* Inputs      : Power object descriptor, Function to call, parameter	*/
/* Outputs     : None							*/
/************************************************************************/
    Void
pwrSwitchEach( pwrObjDesc *pdp, FuncPtr fn, DWord parm )
{
    Reg pwrObj		*pp;
    Reg pwrCan		*cp;
    Reg pwrBoard	*bp;
    Reg pwrSwitch	*swp;
    Reg Nat32		i, j, k;

    for ( i = 0, pp = pdp->pd_obj; i < pdp->pd_nobjs; i++, pp++ )
	switch( pp->po_type )
	{
	  case PO_CAN:
	    cp = (pwrCan *)pp->po_ptr;
	    for ( j = 0; 
		 ((bp = cp->can_bd[j]) != BOARD_NULL) && (j < IBC_MAX_CARDS);
		 j++ )
		for ( k = 0; k < MAX_SWITCHES; k++ )
		    if ( (swp = bp->bd_sw[k]) != SWITCH_NULL )
			(*fn)(swp, parm);
	    break;

	  case PO_SW:
	    (*fn)(pp->po_ptr, parm);
	    break;

	  case PO_BUS:
	  case PO_LABEL:
	    break;
	}

} /* pwrSwitchEach() */


/************************************************************************/
/* Function    : pwrButtonState						*/
/* Purpose     : Callback for setting power button state		*/
/* Inputs      : Widget ID, Client Data, Call Data			*/
/* Outputs     : None							*/
/************************************************************************/
    Void
pwrButtonState( Widget w, switchStatus state, XmAnyCallbackStruct *call_data )
{
    XtVaSetValues( w, XmNbackground, *pwrBgColors[state],
		      XmNforeground, *pwrFgColors[state], NULL );

} /* pwrButtonState() */


/************************************************************************/
/* Function    : pwrSwitchGetState					*/
/* Purpose     : Get and Display power button state			*/
/* Inputs      : Power Switch ptr					*/
/* Outputs     : None							*/
/************************************************************************/
    Void
pwrSwitchGetState( pwrSwitch *swp, DWord chvec )
{
    switchStatus	state, bstate;
    motorEnableState	dmstate;

    if ( (swp->sw_sts != NO_ITEM) && ((chvec & swp->sw_grpbit) != 0) )
	switch (swp->sw_type )
	{
	  case SW_TOGGLE:
	  case SW_MOTOR_TOGGLE:
	    if ( rdm_read(swp->sw_sts, (char *)&dmstate,
			  sizeof(motorEnableState)) == SUCCESS )
		switch( dmstate )
		{
		  case DISABLE_MOTOR:
		    XtVaSetValues( swp->sw_widget, XcNonColor,
				   pwrToggleOnColor, XcNstate, XcOff, NULL );
		    break;

		  case ENABLE_MOTOR:
		    XtVaSetValues( swp->sw_widget, XcNonColor,
				   pwrToggleOnColor, XcNstate, XcOn, NULL );
		    break;

		  default:
		    XtVaSetValues( swp->sw_widget, XcNonColor,
				   *pwrBgColors[SWITCH_POWER_ERROR],
				   XcNstate, XcOn, NULL );
		    break;
		}
	    break;

	  default:
	    if ( rdm_read(swp->sw_sts, (char *)&state, sizeof(state))
			== SUCCESS )
	    {
		XtVaSetValues( swp->sw_widget, 
			       XmNbackground, *pwrBgColors[state],
			       XmNforeground, *pwrFgColors[state], NULL );

		if ( swp->sw_bus != BUS_NULL )
		{
		    bstate = (state == SWITCH_ON) ? SWITCH_ON : SWITCH_NO_POWER;
		    XtVaSetValues( swp->sw_bus->pb_widget, 
				   XmNbackground, *pwrBgColors[bstate],
				   XmNforeground, *pwrFgColors[bstate], NULL );
		}
	    }
	}

} /* pwrSwitchGetState() */


/************************************************************************/
/* Function    : pwrPushButtonCreate					*/
/* Purpose     : Create a PushButton in an IBC form for power screen	*/
/* Inputs      : Unused widget ID, ibcItem ptr				*/
/* Outputs     : None							*/
/************************************************************************/
	Void
pwrPushButtonCreate( Widget parent, ibcItem *itm )
{
    itm->widget = XtVaCreateManagedWidget(
			    itm->ptrparm, xmPushButtonWidgetClass, parent,
			    XmNleftAttachment, XmATTACH_POSITION,
			    XmNrightAttachment, XmATTACH_POSITION,
			    XmNleftPosition, itm->parm1,
			    XmNrightPosition, itm->parm2,
			    XmNrecomputeSize, False,
			    NULL);

    itm->auxWid1 = pwrDialog;

    if ( itm->activate )
	XtAddCallback( itm->widget, XmNactivateCallback, itm->activate, itm );

} /* pushButtonCreate() */


/************************************************************************/
/* Function    : pwrTimeoutProc						*/
/* Purpose     : Routine called to periodically update Power screen	*/
/* Inputs      : Power Object Descriptor pointer			*/
/* Outputs     : None							*/
/* Comment     : Typically called at 2 Hz.  Be quick!			*/
/************************************************************************/
	Void
pwrTimeoutProc( pwrObjDesc *pp, XtIntervalId *id )
{
    Reg DWord	changes;

    if ( (changes = rdm_get_group_changes(pp->pd_group)) != 0 )
	pwrSwitchEach( pp, pwrSwitchGetState, changes );

    timeoutId = XtAppAddTimeOut(appcontext, appdata.power_update,
				(XtTimerCallbackProc)pwrTimeoutProc, pp);

} /* pwrTimeoutProc() */


/************************************************************************/
/* Function    : pwrDiagCallback					*/
/* Purpose     : Callback for setting Diagnostics Button		*/
/* Inputs      : Widget ID, Client Data, Call Data			*/
/* Outputs     : None							*/
/************************************************************************/
    Void
pwrDiagCallback( Widget w, XtPointer unused, XmAnyCallbackStruct *call_data )
{
    pwrDiagWidget = w;
    pwr_diag = !pwr_diag;
    
    if ( pwr_diag )
	XtVaSetValues( w, XmNbackground, *pwrBgColors[SWITCH_ON],
		          XmNforeground, *pwrFgColors[SWITCH_ON], NULL );
    else
	XtVaSetValues( w, XmNbackground, *pwrBgColors[SWITCH_OFF],
		          XmNforeground, *pwrFgColors[SWITCH_OFF], NULL );

} /* pwrDiagCallback() */


/************************************************************************/
/* Function    : pwrDiagDeleteCallback					*/
/* Purpose     : Callback when Diagnostic Dialog is Destroyed		*/
/* Inputs      : Widget ID, Item descriptor, Call data			*/
/* Outputs     : None							*/
/************************************************************************/
    Void
pwrDiagDeleteCallback( Widget w, ibcItemDesc *idp, XmAnyCallbackStruct *unused )
{
    ibcStopTimeout( idp );
    XtFree( (char *)idp );

} /* pwrDiagDeleteCallback() */


/************************************************************************/
/* Function    : pwrDiagCancelCallback					*/
/* Purpose     : Callback when Cancel button pressed in Diagnostic Dialog*/
/* Inputs      : Widget ID, IBC item, Call data				*/
/* Outputs     : None							*/
/* Comment     : Destroys the dialog widget, which causes a call to the	*/
/*		 destroy callback					*/
/************************************************************************/
    Void
pwrDiagCancelCallback( Widget w, ibcItem *itm, XmAnyCallbackStruct *unused )
{
    XtDestroyWidget( itm->auxWid1 );

} /* pwrDiagCancelCallback() */


/************************************************************************/
/* Function    : startPwrDialog						*/
/* Purpose     : Start the Power Diagnostic Dialog			*/
/* Inputs      : pwrSwitch struct					*/
/* Outputs     : None							*/
/************************************************************************/
    Void
startPwrDialog( pwrSwitch *swp )
{
    Reg ibcItemDesc	*idp;
    Reg char		*prefix;
    Reg pwrSwitch	*sw3;
    Reg Widget		dialogRowCol;

    pwr_diag = FALSE;

    XtVaSetValues( pwrDiagWidget, XmNbackground, *pwrBgColors[SWITCH_OFF],
		   XmNforeground, *pwrFgColors[SWITCH_OFF], NULL );

    if ( swp->sw_dmname == NULL )
    {
	rovError( pwrFormW, "No Setpoints for\nUnimplemented Switch" );
	return;
    }

    if ( (idp = copyIbcItemDesc(switchItemDesc[swp->sw_type])) == NULLID )
    {
	rovError( swp->sw_widget, "Out of Memory" );
	return;
    }

    pwrDialog = XmCreateDialogShell(pwrFormW, swp->sw_name, (ArgList)NULL, 0);
    
    XtVaSetValues( pwrDialog, XmNdeleteResponse, XmDESTROY,
		   XmNallowShellResize, True, XmNdefaultPosition, False, 
		   XmNx, pwrDialogX[pwrPos], XmNy, pwrDialogY[pwrPos], 
		   XmNtitle, swp->sw_dmname, NULL );

    if ( ++pwrPos >= XtNumber(pwrDialogX) )
	pwrPos = 0;

    XtAddCallback( pwrDialog, XmNdestroyCallback,
		   (XtCallbackProc)pwrDiagDeleteCallback, idp );

    sprintf( pwrBuff, "%s%s.", pwr_name, swp->sw_dmname );
    prefix = pwrBuff;

    switch( swp->sw_type )
    {
      case SW_LPVICOR:
      case SW_LPSWITCH3:
	if ( swp->sw_board != BOARD_NULL )
	    sprintf( prefix, "%s%s", 
		     TIBURON_DM_PREFIX, swp->sw_board->bd_dmname );
	break;
    }

    createIbcItems( idp, prefix );

    /* Note - switch item descriptors contain only one ibcItemSet each */
    dialogRowCol = 
	createIbcGroup( pwrDialog, idp->ibcSets[0], PWR_DIALOG_WIDTH,
		        PWR_INFO_LEFT_POS, PWR_INFO_RT_POS );

    XtManageChild( dialogRowCol );

    ibcStartTimeout( idp, prefix );

    if ( (swp->sw_type == SW_LP) && (swp->sw_board != BOARD_NULL) )
    {
	sw3 = swp->sw_board->bd_sw[0];

	if ( sw3->sw_type == SW_LPSWITCH3 )
	    startPwrDialog( sw3 );
    }

} /* startPwrDialog() */


/************************************************************************/
/* Function    : pwrSwitchCallback					*/
/* Purpose     : Callback when user hits Power Switch			*/
/* Inputs      : Widget ID, pwrSwitch struct, Call Data			*/
/* Outputs     : None							*/
/************************************************************************/
    Void
pwrSwitchCallback( Widget w, pwrSwitch *swp, XmPushButtonCallbackStruct *pbd )
{
    switchStatus	state;

    if ( pwr_diag )
    {
	startPwrDialog( swp );
	return;
    }

    if ( (appdata.debug & DBL_CLICK) && (pbd->click_count == 2) )
	startPwrDialog( swp );		/* Use 2nd click to start Dialog*/
					/*   and restore switch status	*/

    if ( swp->sw_sts != NO_ITEM )
	if ( rdm_read(swp->sw_sts, (char *)&state, sizeof(state)) == SUCCESS )
	{
	    state = (state == SWITCH_OFF) ? SWITCH_ON : SWITCH_OFF;

	    rdm_write( swp->sw_req, (char *)&state, sizeof(state) );

/* For debugging Power screen only */
	    if ( appdata.debug & PWR_DEBUG )
		rdm_write( swp->sw_sts, (char *)&state, sizeof(state) );
	}

} /* pwrSwitchCallback() */


/************************************************************************/
/* Function    : pwrToggleCallback					*/
/* Purpose     : Callback when user hits Toggle Switch			*/
/* Inputs      : Widget ID, pwrSwitch struct, Call Data			*/
/* Outputs     : None							*/
/************************************************************************/
    Void
pwrToggleCallback( Widget w, pwrSwitch *swp, XmAnyCallbackStruct *unused )
{
    XcToggleState	state;
    motorEnableState	dmstate;

    XcToggleGet( w, &state );
    dmstate = (state == XcOn) ? ENABLE_MOTOR : DISABLE_MOTOR;

    if ( pwr_diag )
    {
	pwr_diag = FALSE;
	XcToggleSet( w, (state == XcOn) ? XcOff : XcOn );
	XtVaSetValues( pwrDiagWidget, XmNbackground, *pwrBgColors[SWITCH_OFF],
		       XmNforeground, *pwrFgColors[SWITCH_OFF], NULL );
	rovError( w, "No Setpts\nUse Motor Screen" );
    }
    else
    {
	rdm_write( swp->sw_req, (char *)&dmstate, sizeof(motorEnableState) );
	pwrSwitchGetState( swp, ~0 );
    }

} /* pwrToggleCallback() */


/************************************************************************/
/* Function    : powerSwitchCreate					*/
/* Purpose     : Create a power switch					*/
/* Inputs      : Parent, pwrSwitch struct, x and y position, pwrObjDesc	*/
/* Outputs     : Error Number						*/
/************************************************************************/
     Errno
powerSwitchCreate( Widget w, pwrSwitch *sp, Int32 xpos, Int32 ypos,
		   pwrObjDesc *pdp )
{
    XmString	label;
    Reg Errno	rtn;

    switch( sp->sw_type )
    {
      case SW_LPSWITCH3:
	return( SUCCESS );

      case SW_MOTOR_TOGGLE:
	sp->sw_widget = XtVaCreateManagedWidget(
				sp->sw_name, xcToggleButtonWidgetClass, w,
				XmNwidth, SW_WIDTH, XmNheight, TOGGLE_HEIGHT,
				XmNtopAttachment, XmATTACH_POSITION,
				XmNtopPosition, ypos,
				XmNleftAttachment, XmATTACH_POSITION,
				XmNleftPosition, xpos,
				XcNlabel, sp->sw_name, NULL);

	XtAddCallback( sp->sw_widget, XmNactivateCallback, 
		       (XtCallbackProc)pwrToggleCallback, sp );

	XtVaGetValues( sp->sw_widget, XcNonColor, &pwrToggleOnColor, NULL );

	if ( sp->sw_dmname != NULL )
	{
	    sprintf(buff, "%s%s", sp->sw_dmname, MOTOR_ENABLE_REQ_DM);
	
	    if ( (rtn = rdm_create(buff, 1, &sp->sw_req, TOGGLE_DMTYPE, 1))
			!= SUCCESS )
		return( rtn );

	    sprintf(buff, "%s%s", sp->sw_dmname, MOTOR_ENABLE_STATUS_DM);

	    if ( (rtn = rdm_create(buff, 1, &sp->sw_sts, TOGGLE_DMTYPE, 1))
			!= SUCCESS )
		return( rtn );

	    if ( rtn = (rdm_start_multiple(sp->sw_req)) != SUCCESS )
		return( rtn );

	    rdm_group_add_item( pdp->pd_group, sp->sw_sts, &sp->sw_grpbit );
	}

	return( SUCCESS );

      case SW_TOGGLE:
	sp->sw_widget = XtVaCreateManagedWidget(
				sp->sw_name, xcToggleButtonWidgetClass, w,
				XmNwidth, SW_WIDTH, XmNheight, TOGGLE_HEIGHT,
				XmNtopAttachment, XmATTACH_POSITION,
				XmNtopPosition, ypos,
				XmNleftAttachment, XmATTACH_POSITION,
				XmNleftPosition, xpos,
				XcNlabel, sp->sw_name, NULL);

	XtAddCallback( sp->sw_widget, XmNactivateCallback, 
		       (XtCallbackProc)pwrToggleCallback, sp );

	XtVaGetValues( sp->sw_widget, XcNonColor, &pwrToggleOnColor, NULL );

	if ( sp->sw_dmname != NULL )
	{
	    if ( rtn = (rdm_create(sp->sw_dmname, 1, &sp->sw_req,
				   TOGGLE_DMTYPE, 1)) != SUCCESS )
		return( rtn );

	    sp->sw_sts = sp->sw_req;

	    if ( rtn = (rdm_start_multiple(sp->sw_req)) != SUCCESS )
		return( rtn );

	    rdm_group_add_item( pdp->pd_group, sp->sw_sts, &sp->sw_grpbit );
	}

	return( SUCCESS );

      case SW_DISABLED:
	label = XmStringCreateLtoR(sp->sw_name, XmSTRING_DEFAULT_CHARSET);

	sp->sw_widget = XtVaCreateManagedWidget(
				sp->sw_name, xmPushButtonWidgetClass, w,
				XmNwidth, SW_WIDTH, XmNheight, SW_HEIGHT,
				XmNrecomputeSize, False,
				XmNbackground, *pwrBgColors[SWITCH_OFF],
				XmNtopAttachment, XmATTACH_POSITION,
				XmNtopPosition, ypos,
				XmNleftAttachment, XmATTACH_POSITION,
				XmNleftPosition, xpos,
				XmNlabelString, label, NULL);
	XmStringFree( label );
	XtSetSensitive( sp->sw_widget, FALSE );

	return( SUCCESS );

      default:
	label = XmStringCreateLtoR(sp->sw_name, XmSTRING_DEFAULT_CHARSET);

	sp->sw_widget = XtVaCreateManagedWidget(
				sp->sw_name, xmPushButtonWidgetClass, w,
				XmNwidth, SW_WIDTH, XmNheight, SW_HEIGHT,
				XmNrecomputeSize, False,
				XmNbackground, *pwrBgColors[SWITCH_NO_POWER],
				XmNtopAttachment, XmATTACH_POSITION,
				XmNtopPosition, ypos,
				XmNleftAttachment, XmATTACH_POSITION,
				XmNleftPosition, xpos,
				XmNlabelString, label, NULL);
	XmStringFree( label );

	XtAddCallback( sp->sw_widget, XmNactivateCallback, 
		       (XtCallbackProc)pwrSwitchCallback, sp );

	if ( sp->sw_dmname != NULL )
	{
	    sprintf(buff, "%s%s%s", pwr_name, sp->sw_dmname, req_name );
	
	    if ( (rtn = rdm_create(buff, 1, &sp->sw_req, SWITCH_REQ_DMTYPE, 1))
			!= SUCCESS )
		return( rtn );

	    sprintf(buff, "%s%s%s", pwr_name, sp->sw_dmname, sts_name );

	    if ( (rtn = rdm_create(buff, 1, &sp->sw_sts, SWITCH_STS_DMTYPE, 1))
			!= SUCCESS )
		return( rtn );

	    if ( (rtn = rdm_start_multiple(sp->sw_req)) != SUCCESS )
		return( rtn );

	    rdm_group_add_item( pdp->pd_group, sp->sw_sts, &sp->sw_grpbit );

/* For debugging Power screen only */
	    if ( appdata.debug & PWR_DEBUG )
		rdm_start_multiple( sp->sw_sts );
	}

	return( SUCCESS );

    } /* switch(sp->sw_type) */

} /* powerSwitchCreate() */


/************************************************************************/
/* Function    : powerBusCreate						*/
/* Purpose     : Create a Label to depict a power bus			*/
/* Inputs      : Parent, pwrBus struct, x and y position		*/
/* Outputs     : Error Number						*/
/************************************************************************/
     Errno
powerBusCreate( Widget w, pwrBus *bp, Int32 xpos, Int32 ypos )
{
    XmString	str;

    str = XmStringCreateSimple("");

    if ( bp->pb_orient == BUS_HORIZ )
	bp->pb_widget = XtVaCreateManagedWidget(
				"pwrbus", xmLabelWidgetClass, w,
				XmNheight, BUS_HEIGHT,
				XmNtopAttachment, XmATTACH_POSITION,
				XmNtopPosition, ypos,
				XmNleftAttachment, XmATTACH_POSITION,
				XmNleftPosition, xpos,
				XmNrightAttachment, XmATTACH_POSITION,
				XmNrightPosition, bp->pb_x2,
				XmNbackground, *pwrBgColors[SWITCH_ON],
				XmNlabelString, str, NULL);
    else
	bp->pb_widget = XtVaCreateManagedWidget(
				"pwrbus", xmLabelWidgetClass, w,
				XmNwidth, BUS_HEIGHT,
				XmNtopAttachment, XmATTACH_POSITION,
				XmNtopPosition, ypos,
				XmNleftAttachment, XmATTACH_POSITION,
				XmNleftPosition, xpos,
				XmNbottomAttachment, XmATTACH_POSITION,
				XmNbottomPosition, bp->pb_x2,
				XmNbackground, *pwrBgColors[SWITCH_ON],
				XmNlabelString, str, NULL);

    XmStringFree( str );

    if ( bp->pb_sw != SWITCH_NULL )
	bp->pb_sw->sw_bus = bp;

    return( SUCCESS );

} /* powerBusCreate() */


/************************************************************************/
/* Function    : powerLabelCreate					*/
/* Purpose     : Create a Label						*/
/* Inputs      : Parent, Label string, x and y position			*/
/* Outputs     : Error Number						*/
/************************************************************************/
     Errno
powerLabelCreate( Widget w, char *labelString, Int32 xpos, Int32 ypos )
{
    XmString	str;

    str = XmStringCreateSimple( labelString );

    XtVaCreateManagedWidget( "pwrLabel", xmLabelWidgetClass, w,
			     XmNheight, BUS_HEIGHT,
				XmNtopAttachment, XmATTACH_POSITION,
				XmNtopPosition, ypos,
				XmNleftAttachment, XmATTACH_POSITION,
				XmNleftPosition, xpos,
				XmNlabelString, str, NULL);

    XmStringFree( str );

    return( SUCCESS );

} /* powerLabelCreate() */


/************************************************************************/
/* Function    : powerBoardCreate					*/
/* Purpose     : Create function to store board ptrs into switches	*/
/* Inputs      : Parent, pwrBoard struct				*/
/* Outputs     : Error Number						*/
/************************************************************************/
     Errno
powerBoardCreate( Widget w, pwrBoard *bp )
{
    Reg pwrSwitch	*swp;
    Reg Nat32		i;

    for ( i = 0; i < MAX_SWITCHES; i++ )
	if ( (swp = bp->bd_sw[i]) != SWITCH_NULL )
	    swp->sw_board = bp;

    return( SUCCESS );

} /* powerBoardCreate() */


/************************************************************************/
/* Function    : powerCanCreate						*/
/* Purpose     : Create a Can with power switches			*/
/* Inputs      : Parent, pwrCan struct, x and y position, DM Group	*/
/* Outputs     : Error Number						*/
/************************************************************************/
     Errno
powerCanCreate( Widget w, pwrCan *cp, Int32 xpos, Int32 ypos, pwrObjDesc *pdp )
{
    Reg Errno		rtn;
    Reg pwrBoard	*bp;
    Reg pwrSwitch	*swp;
    Reg Int32		i, n, j, formheight, width;
    XmString		str;
    Widget		frame, form, bdform, label, prev;

    for ( n = 0; cp->can_bd[n] != BOARD_NULL; n++ )
	;					/* Count number of boards */

    formheight = n * (SW_HEIGHT + SW_SPACING) + LABEL_HEIGHT;
    width = (cp->can_nsw * (SW_WIDTH + SW_SPACING)) + QLPSW_SPACING;

    frame = XtVaCreateManagedWidget( 
		"canframe", xmFrameWidgetClass, w,
		XmNwidth, width, XmNheight, formheight,
		XmNtopAttachment, XmATTACH_POSITION,
		XmNtopPosition, ypos,
		XmNleftAttachment, XmATTACH_POSITION,
		XmNleftPosition, xpos, NULL );
    cp->can_frame = frame;

    form = XtVaCreateManagedWidget( 
		"canform", xmFormWidgetClass, frame,
		XmNwidth, width, XmNheight, formheight, NULL );

    str = XmStringCreateLtoR( cp->can_name, XmSTRING_DEFAULT_CHARSET);
    label = XtVaCreateManagedWidget( 
		"canlabel", xmLabelWidgetClass, form,
		XmNwidth, width, XmNheight, LABEL_HEIGHT,
		XmNtopAttachment, XmATTACH_FORM,
		XmNleftAttachment, XmATTACH_FORM,
		XmNrightAttachment, XmATTACH_FORM,
		XmNlabelString, str, NULL);
    XmStringFree( str );

    for ( i = 0, prev = label; i < n; i++ )
    {
	bdform = XtVaCreateManagedWidget( 
			"bdform", xmFormWidgetClass, form,
			XmNwidth, width, 
			XmNheight, SW_HEIGHT + SW_SPACING,
			XmNtopAttachment, XmATTACH_WIDGET,
			XmNtopWidget, prev,
			XmNleftAttachment, XmATTACH_FORM,
			XmNrightAttachment, XmATTACH_FORM, 
			XmNfractionBase, 100*cp->can_nsw/MAX_SWITCHES, NULL );

	bp = cp->can_bd[i];

	for ( j = 0; j < cp->can_nsw; j++ )
	{
	    if ( (swp = bp->bd_sw[j]) == SWITCH_NULL )
		continue;

	    if ( powerSwitchCreate(bdform, swp, sw_pos[j],
		    SW_SPACING/((SW_HEIGHT + SW_SPACING) * 2), pdp) != SUCCESS )
		break;

	    swp->sw_board = bp;
	}

	prev = bdform;
    }

    return( SUCCESS );

} /* powerCanCreate() */


/************************************************************************/
/* Function    : selectSwitchFn						*/
/* Purpose     : Function called for each switch at select time		*/
/* Inputs      : pwrSwitch Ptr						*/
/* Outputs     : None							*/
/************************************************************************/
    Void
selectSwitchFn( pwrSwitch *swp )
{
    if ( swp->sw_sts != NO_ITEM )
    {
	rdm_start_consumer( swp->sw_sts, DM_STATIC, NULL );
	pwrSwitchGetState( swp, ~0 );
    }

} /* selectSwitchFn() */


/************************************************************************/
/* Function    : powerBusSelect						*/
/* Purpose     : Callback function to select a power bus screen		*/
/* Inputs      : Select Struct Ptr					*/
/* Outputs     : None							*/
/************************************************************************/
    Void
powerBusSelect( Select *sp )
{
    Reg pwrObjDesc	*pp;

    pp = (pwrObjDesc *)(sp->ptr1);
    pwrSwitchEach( pp, selectSwitchFn, 0 );
    timeoutId = XtAppAddTimeOut(appcontext, appdata.power_update,
				(XtTimerCallbackProc)pwrTimeoutProc, pp);

} /* powerBusSelect() */


/************************************************************************/
/* Function    : unselectSwitchFn					*/
/* Purpose     : Function called for each switch at unselect time	*/
/* Inputs      : pwrSwitch Ptr						*/
/* Outputs     : None							*/
/************************************************************************/
    Void
unselectSwitchFn( pwrSwitch *swp )
{
    if ( (swp->sw_sts != NO_ITEM) && !graphItemInUse(swp->sw_sts) )
	rdm_stop_consumer( swp->sw_sts );

} /* unselectSwitchFn() */


/************************************************************************/
/* Function    : powerBusUnselect					*/
/* Purpose     : Callback function to unselect a power bus screen	*/
/* Inputs      : Select Struct Ptr					*/
/* Outputs     : None							*/
/************************************************************************/
    Void
powerBusUnselect( Select *sp )
{
    Reg pwrObjDesc	*pp;

    XtRemoveTimeOut( timeoutId );
    pp = (pwrObjDesc *)(sp->ptr1);
    pwrSwitchEach( pp, unselectSwitchFn, 0 );

} /* powerBusUnselect() */


/************************************************************************/
/* Function    : initPower						*/
/* Purpose     : Initialize function for Power screen			*/
/* Inputs      : None							*/
/* Outputs     : None							*/
/************************************************************************/
    Void
initPower( Void )
{
    initAC();
    initRegen();

} /* initPower() */


/************************************************************************/
/* Function    : createPowerScreen					*/
/* Purpose     : Create screen form for one power bus			*/
/* Inputs      : Parent Widget, Select ptr				*/
/* Outputs     : Form widget						*/
/************************************************************************/
    Widget
createPowerScreen( Widget w, Select *sp )
{
    Reg pwrObj		*pop;
    Reg pwrObjDesc	*pdp;
    Reg Int32		x, y, i;
    
    pdp = (pwrObjDesc *)(sp->ptr1);
    *sp->display = XtVaCreateWidget(sp->ptr2, xmFormWidgetClass, w, 
				    XmNresizePolicy, XmRESIZE_GROW,
				    XmNx, 0, XmNy, 0,
				    XmNwidth, 850, XmNheight, 560, NULL );

    pdp->pd_group = rdm_create_group( pdp->pd_errs );

    for ( i = 0, pop = pdp->pd_obj; i < pdp->pd_nobjs; i++, pop++ )
	(*createFuncs[pop->po_type])(*sp->display, pop->po_ptr, pop->po_xpos,
				     pop->po_ypos, pdp);

    return( *sp->display );

} /* createPowerScreen() */


/************************************************************************/
/* Function    : createPowerForm					*/
/* Purpose     : Callback for creating powerAppForm			*/
/* Inputs      : Widget ID, Client Data, Call Data			*/
/* Outputs     : None							*/
/************************************************************************/
    Void
createPowerForm( Widget w, XtPointer client_data, 
		 XmAnyCallbackStruct *call_data )
{
    pwrFormW = w;
    createPowerScreen( w, &v240Sel );
    XtManageChild( *v240Sel.display );
    createPowerScreen( w, &a48Sel );
    createPowerScreen( w, &b48Sel );
    *acSel.display = CreateacForm( w );
    *regenSel.display = CreateregenForm( w );

} /* createPowerForm() */


/************************************************************************/
/* Function    : updateTypeLabel					*/
/* Purpose     : Update Label with Enumerated data in parm field	*/
/* Inputs      : Thruster item pointer					*/
/* Outputs     : None							*/
/************************************************************************/
	Void
updateTypeLabel( ibcItem *itm )
{
    XmTextFieldSetString( itm->widget, *((char **)(itm->ptrparm)+itm->parm1) );

} /* updateTypeLabel() */
