//////////////////////////////////////////////////////////////////////////////
//
//  Author      : Josh Grant
//  Date        : November 26th, 2001
//  File        : ParameterEditor.cpp
//  Description : Implementation of the ParameterEditor class
//
//////////////////////////////////////////////////////////////////////////////

#include <Xm/Form.h>
#include <Xm/Scale.h>
#include <Xm/ArrowB.h>
#include <Xm/TextF.h>
#include <Xm/Label.h>

#include <iostream.h>
#include <stdlib.h>

#include <Inventor/Xt/SoXtResource.h>

#include "ParameterEditor.h"

//////////////////////////////////////////////////////////////////////////////
//
// ParameterEditor class
//
//////////////////////////////////////////////////////////////////////////////

// default window height/width and layout
#define DEFAULT_WIDTH           350 // window width
#define DEFAULT_HEIGHT          600 // window height
#define ARITH_HEIGHT            400 // height of arithmitic section
#define OFFSET                  5   // offset at window borders
#define DECIMAL_PTS             3   // # of decimal pts in scale value

// text field labels
static char *fieldTitles[3] = {
  "x", "y", "z"
};

static char *thisClassName = "ParameterEditor";

ParameterEditor::ParameterEditor (Widget parent,
				  const char *name,
				  SbBool buildInsideParent)
  : SoXtComponent(parent, name, buildInsideParent)
{
  constructorCommon(TRUE);
}

ParameterEditor::ParameterEditor (Widget parent,
				  const char *name,
				  SbBool buildInsideParent,
				  SbBool buildNow)
  : SoXtComponent(parent, name, buildInsideParent)
{
  constructorCommon(buildNow);
}

//////////////////////////////////////////////////////////////////////////////
//
//  Description:
//    Called by all constructors to set up the widgets.
//
//////////////////////////////////////////////////////////////////////////////
void
ParameterEditor::constructorCommon (SbBool buildNow)
{
  setClassName(thisClassName);

  // set the component's size
  setSize(SbVec2s(DEFAULT_WIDTH, DEFAULT_HEIGHT));

  // Build the widget tree, and let SoXtComponent know about our base widget.
  if (buildNow) {
    Widget w = buildWidget(getParentWidget());
    setBaseWidget(w);
  }
}

//////////////////////////////////////////////////////////////////////////////
//
//  Description:
//    Have top widget removed.
//
//////////////////////////////////////////////////////////////////////////////
ParameterEditor::~ParameterEditor ()
{
  unregisterWidget(mgrWidget);
}

void
ParameterEditor::show ()
{
  SoXtComponent::show();

  // put my code here    
}

void
ParameterEditor::hide ()
{
  SoXtComponent::hide();

  // put my code here    
}

//////////////////////////////////////////////////////////////////////////////
//
//  Description:
//    save node pointers
//
//////////////////////////////////////////////////////////////////////////////
void
ParameterEditor::attach (ParameterEditor::PE_t *vars)
{
  variables = vars;

  // set widget values
  setInputs();
  // send new values back to the nodes
  sendInputs();
  setText();
}

//////////////////////////////////////////////////////////////////////////////
//
//  Description:
//    sets the text field widgets to the values of the nodes 
//
//////////////////////////////////////////////////////////////////////////////
void
ParameterEditor::setInputs ()
{
  char buf[80];
  int d[3];
  //const float *val;
  SbVec3f minb, maxb, vox;

  sprintf(buf, "%d", (int)(variables->xDim->getValue()));
  XmTextFieldSetString(dims[0], buf);
  sprintf(buf, "%d", (int)(variables->yDim->getValue()));
  XmTextFieldSetString(dims[1], buf);
  sprintf(buf, "%d", (int)(variables->zDim->getValue()));
  XmTextFieldSetString(dims[2], buf);
  
  sprintf(buf, "%f", variables->minBounds->getValue()[0]);
  XmTextFieldSetString(minBounds[0], buf);
  sprintf(buf, "%f", variables->minBounds->getValue()[1]);
  XmTextFieldSetString(minBounds[1], buf);
  sprintf(buf, "%f", variables->minBounds->getValue()[2]);
  XmTextFieldSetString(minBounds[2], buf);

  sprintf(buf, "%f", variables->maxBounds->getValue()[0]);
  XmTextFieldSetString(maxBounds[0], buf);
  sprintf(buf, "%f", variables->maxBounds->getValue()[1]);
  XmTextFieldSetString(maxBounds[1], buf);
  sprintf(buf, "%f", variables->maxBounds->getValue()[2]);
  XmTextFieldSetString(maxBounds[2], buf);

  strcpy(buf, variables->expression->getValue().getString());
  XmTextFieldSetString(equation, buf);
  strcpy(buf, variables->blendExpression->getValue().getString());
  XmTextFieldSetString(blendEquation, buf);

  float min, max, ival;
  Arg args[5];
  int n = 0;
  variables->data->getValue(d);//, minb, maxb, vox);
  variables->data->getMinMax(min, max);

  // set the minimum and maximum values for the scale
  XtSetArg(args[n], XmNminimum, (int)(pow(10, DECIMAL_PTS) * min)); n++;
  XtSetArg(args[n], XmNmaximum, (int)(pow(10, DECIMAL_PTS) * max)); n++;
  XtSetArg(args[n], XmNdecimalPoints, DECIMAL_PTS); n++;
  ival = variables->isoval->getValue();
  if (ival < min) ival = min;
  if (ival > max) ival = max;
  XtSetArg(args[n], XmNvalue, (int)(pow(10, DECIMAL_PTS) * ival)); n++;
  XtSetValues(isoValue, args, n);

  // set the minimum and maximum values for the blend value
  n = 0;
  XtSetArg(args[n], XmNminimum, (int)(pow(10, DECIMAL_PTS) * 0.0f)); n++;
  XtSetArg(args[n], XmNmaximum, (int)(pow(10, DECIMAL_PTS) * 1.0f)); n++;
  XtSetArg(args[n], XmNdecimalPoints, DECIMAL_PTS); n++;
  ival = variables->blendval->getValue();
  if (ival < 0.0f) ival = 0.0f;
  if (ival > 1.0f) ival = 1.0f;
  XtSetArg(args[n], XmNvalue, (int)(pow(10, DECIMAL_PTS) * ival)); n++;
  XtSetValues(blendValue, args, n);

  n = 0;
  ival = variables->vertBlend->getValue();
  XtSetArg(args[n], XmNvalue, (int)(pow(10, DECIMAL_PTS) * ival)); n++;
  XtSetValues(vertBlendValue, args, n);
}

void
ParameterEditor::resetIsoRange ()
{
  int d[3];
  SbVec3f minb, maxb, vox;
  
  float min, max, ival;
  Arg args[5];
  int n = 0;
  variables->data->getValue(d);//, minb, maxb, vox);
  variables->data->getMinMax(min, max);

  // set the minimum and maximum values for the scale
  XtSetArg(args[n], XmNminimum, (int)(pow(10, DECIMAL_PTS) * min)); n++;
  XtSetArg(args[n], XmNmaximum, (int)(pow(10, DECIMAL_PTS) * max)); n++;
  XtSetArg(args[n], XmNdecimalPoints, DECIMAL_PTS); n++;
  ival = variables->isoval->getValue();
  if (ival < min) ival = min;
  if (ival > max) ival = max;
  XtSetArg(args[n], XmNvalue, (int)(pow(10, DECIMAL_PTS) * ival)); n++;
  XtSetValues(isoValue, args, n);
}

//////////////////////////////////////////////////////////////////////////////
//
//  Description:
//    sends the widget values to the nodes.
//
//////////////////////////////////////////////////////////////////////////////
void
ParameterEditor::sendInputs ()
{
  variables->xDim->setValue(atoi(XmTextFieldGetString(dims[0])));
  variables->yDim->setValue(atoi(XmTextFieldGetString(dims[1])));
  variables->zDim->setValue(atoi(XmTextFieldGetString(dims[2])));

  variables->minBounds->setValue(atof(XmTextFieldGetString(minBounds[0])),
			         atof(XmTextFieldGetString(minBounds[1])),
			         atof(XmTextFieldGetString(minBounds[2])));
  
  variables->maxBounds->setValue(atof(XmTextFieldGetString(maxBounds[0])),
			         atof(XmTextFieldGetString(maxBounds[1])),
			         atof(XmTextFieldGetString(maxBounds[2])));

  variables->expression->setValue(XmTextFieldGetString(equation));
  variables->blendExpression->setValue(XmTextFieldGetString(blendEquation));

}

//////////////////////////////////////////////////////////////////////////////
//
//  Description:
//    sets the text value to be displayed in the viewer
//
//////////////////////////////////////////////////////////////////////////////
void
ParameterEditor::setText ()
{
  char buf[1024];
  sprintf(buf, "%.3f = ( %s ) * %.3f + ( %s ) * %.3f", 
	variables->isoval->getValue(),
	variables->expression->getValue().getString(), 
	variables->blendval->getValue(),
	variables->blendExpression->getValue().getString(), 
	1.0f - variables->blendval->getValue() );
	
  //cout << buf << endl;
  variables->text->setValue(buf);
}

//////////////////////////////////////////////////////////////////////////////
//
//  Description:
//    Builds the top widget and attaches all subsequent widgets below it.
//
//////////////////////////////////////////////////////////////////////////////
Widget
ParameterEditor::buildWidget (Widget parent)
{
  int n;
  Arg args[16];
  Widget arithControls, mcubesControls, blendControls;
  
  SbVec2s size = getSize();
  n = 0;
  if ((size[0] != 0) && (size[1] != 0)) {
    XtSetArg(args[n], XtNwidth, size[0]); n++;
    XtSetArg(args[n], XtNheight, size[1]); n++;
  }

  // create the top level widget, and register it with a class name
  mgrWidget = XtCreateWidget(getWidgetName(),
			     xmFormWidgetClass,
			     parent, args, n);
  registerWidget(mgrWidget);

  // position, build, and manage the arithmitic controls
  n = 0;
  XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
  XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  XtSetArg(args[n], XmNbottomAttachment, XmATTACH_POSITION); n++;
  XtSetArg(args[n], XmNbottomPosition, 61); n++;
  arithControls = buildArithControls(mgrWidget, args, n);
  XtManageChild(arithControls);
  
  // position, build, and manage the marching cubes controls
  n = 0;
  XtSetArg(args[n], XmNtopAttachment, XmATTACH_POSITION); n++;
  XtSetArg(args[n], XmNtopPosition, 61); n++;
  XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  XtSetArg(args[n], XmNbottomAttachment, XmATTACH_POSITION); n++;
  XtSetArg(args[n], XmNbottomPosition, 74); n++;
  mcubesControls = buildScaleWidget(mgrWidget, "Isovalue", args, n,
				    isoValue, isoValueCB);
  XtManageChild(mcubesControls);

  // position, build, and manage the marching cubes controls
  n = 0;
  XtSetArg(args[n], XmNtopAttachment, XmATTACH_POSITION); n++;
  XtSetArg(args[n], XmNtopPosition, 74); n++;
  XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  XtSetArg(args[n], XmNbottomAttachment, XmATTACH_POSITION); n++;
  XtSetArg(args[n], XmNbottomPosition, 87); n++;
  blendControls = buildScaleWidget(mgrWidget, "Blendvalue", args, n,
				   blendValue, blendValueCB);
  XtManageChild(blendControls);

  // position, build, and manage the marching cubes controls
  n = 0;
  XtSetArg(args[n], XmNminimum, (int)(pow(10, DECIMAL_PTS) * 0.0)); n++;
  XtSetArg(args[n], XmNmaximum, (int)(pow(10, DECIMAL_PTS) * 0.499999)); n++;
  XtSetArg(args[n], XmNdecimalPoints, DECIMAL_PTS); n++;
  XtSetArg(args[n], XmNtopAttachment, XmATTACH_POSITION); n++;
  XtSetArg(args[n], XmNtopPosition, 87); n++;
  XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
  blendControls = buildScaleWidget(mgrWidget, "Vertex Blend", args, n,
				   vertBlendValue, vertBlendValueCB);
  XtManageChild(blendControls);

  
  return mgrWidget;
}

//////////////////////////////////////////////////////////////////////////////
//
//  Description:
//    Builds all the text fields associated with the arithmitic
//    controls. This will be 3 rows of 3 text fields, plus one large text
//    field for the expression.
//
//////////////////////////////////////////////////////////////////////////////
Widget
ParameterEditor::buildArithControls (Widget parent, Arg args[], int n)
{
  Widget topForm, dimsForm, minForm, maxForm, expForm, bExpForm;

  XtSetArg(args[n], XtNheight, ARITH_HEIGHT); n++;
  topForm = XtCreateWidget(getWidgetName(),
			   xmFormWidgetClass,
			   parent, args, n);

  // resolution text fields
  n = 0;
  XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
  XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  XtSetArg(args[n], XmNbottomAttachment, XmATTACH_POSITION); n++;
  XtSetArg(args[n], XmNbottomPosition, 25); n++;
  dimsForm = buildTextFields(topForm, "Resolution",
			     fieldTitles, dims, 3, args, n);
  XtManageChild(dimsForm);

  // minimum bounds text fields 
  n = 0;
  XtSetArg(args[n], XmNtopAttachment, XmATTACH_POSITION); n++;
  XtSetArg(args[n], XmNtopPosition, 25); n++;
  XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  XtSetArg(args[n], XmNbottomAttachment, XmATTACH_POSITION); n++;
  XtSetArg(args[n], XmNbottomPosition, 50); n++;
  minForm = buildTextFields(topForm, "Minimum Bounds",
			     fieldTitles, minBounds, 5, args, n);
  XtManageChild(minForm);

  // maximum bounds text fields
  n = 0;
  XtSetArg(args[n], XmNtopAttachment, XmATTACH_POSITION); n++;
  XtSetArg(args[n], XmNtopPosition, 50); n++;
  XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  XtSetArg(args[n], XmNbottomAttachment, XmATTACH_POSITION); n++;
  XtSetArg(args[n], XmNbottomPosition, 70); n++;
  maxForm = buildTextFields(topForm, "Maximum Bounds",
			     fieldTitles, maxBounds, 5, args, n);
  XtManageChild(maxForm);

  // equation text field
  n = 0;
  XtSetArg(args[n], XmNtopAttachment, XmATTACH_POSITION); n++;
  XtSetArg(args[n], XmNtopPosition, 70); n++;
  XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  XtSetArg(args[n], XmNbottomAttachment, XmATTACH_POSITION); n++;
  XtSetArg(args[n], XmNbottomPosition, 85); n++;
  expForm = buildExpression(topForm, "Equation", args, n);
  XtManageChild(expForm);

  // blendEquation text field
  n = 0;
  XtSetArg(args[n], XmNtopAttachment, XmATTACH_POSITION); n++;
  XtSetArg(args[n], XmNtopPosition, 85); n++;
  XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
  bExpForm = buildExpression(topForm, "Blend Equation", args, n);
  XtManageChild(bExpForm);

  return topForm;
}

//////////////////////////////////////////////////////////////////////////////
//
//  Description:
//    Builds a row of 3 text fields based on the input parameters.  The
//    'title' is a label that will be placed over the text fields.
//    'textTitles' are the individual titles for each text fields. and the
//    'textFields' are the widgets to create the text fields in.
//
//////////////////////////////////////////////////////////////////////////////
Widget
ParameterEditor::buildTextFields (Widget parent,
				  char *title,
				  char *textTitles[3],
				  Widget textFields[3],
				  int width,
				  Arg args[], int n)
{
  int i;
  Widget form, label;
  XmString str;

  XtSetArg(args[n], XtNwidth, DEFAULT_WIDTH); n++;
  form = XtCreateWidget(getWidgetName(),
			xmFormWidgetClass,
			parent, args, n);

  // create top title
  str = XmStringCreateLocalized(title);
  n = 0;
  XtSetArg(args[n], XmNlabelString, str); n++;
  XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
  XtSetArg(args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
  XtSetArg(args[n], XmNleftPosition, 0); n++;
  XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  XtSetArg(args[n], XmNbottomAttachment, XmATTACH_POSITION); n++;
  XtSetArg(args[n], XmNbottomPosition, 50); n++;
  label = XtCreateWidget(getWidgetName(),
			 xmLabelWidgetClass,
			 form, args, n);
  XtManageChild(label);
  XmStringFree(str);

  // create the 3 different text fields
  for (i = 0; i < 3; i++) {
    str = XmStringCreateLocalized(textTitles[i]);
    n = 0;
    XtSetArg(args[n], XmNlabelString, str); n++;
    XtSetArg(args[n], XmNtopAttachment, XmATTACH_POSITION); n++;
    XtSetArg(args[n], XmNtopPosition, 50); n++;
    XtSetArg(args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
    XtSetArg(args[n], XmNleftPosition, i * 33); n++;
    label = XtCreateWidget(getWidgetName(),
			   xmLabelWidgetClass,
			   form, args, n);
    XtManageChild(label);
    XmStringFree(str);

    n = 0;
    XtSetArg(args[n], XmNtopAttachment, XmATTACH_POSITION); n++;
    XtSetArg(args[n], XmNtopPosition, 50); n++;
    XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); n++;
    XtSetArg(args[n], XmNleftWidget, label); n++;
    XtSetArg(args[n], XmNcolumns, width); n++;
    textFields[i] = XtCreateWidget(getWidgetName(),
			   xmTextFieldWidgetClass, 
			   form, args, n);
    XtAddCallback(textFields[i], XmNactivateCallback,
		  (XtCallbackProc)textFieldCB, this);
    XtManageChild(textFields[i]);
    
  }    

  return form;
}

//////////////////////////////////////////////////////////////////////////////
//
//  Description:
//    Builds a text field widget for the expression with a title.
//
//////////////////////////////////////////////////////////////////////////////
Widget
ParameterEditor::buildExpression (Widget parent,
				  char *title,
				  Arg args[], int n)
{
  Widget form, label;
  XmString str;

  XtSetArg(args[n], XtNwidth, DEFAULT_WIDTH); n++;
  form = XtCreateWidget(getWidgetName(),
			xmFormWidgetClass,
			parent, args, n);

  // create title
  str = XmStringCreateLocalized(title);
  n = 0;
  XtSetArg(args[n], XmNlabelString, str); n++;
  XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
  XtSetArg(args[n], XmNleftAttachment, XmATTACH_POSITION); n++;
  XtSetArg(args[n], XmNleftPosition, 0); n++;
  XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  XtSetArg(args[n], XmNbottomAttachment, XmATTACH_POSITION); n++;
  XtSetArg(args[n], XmNbottomPosition, 35); n++;
  label = XtCreateWidget(getWidgetName(),
			 xmLabelWidgetClass,
			 form, args, n);
  XtManageChild(label);
  XmStringFree(str);
  
  // create equation text field
  n = 0;
  XtSetArg(args[n], XmNtopAttachment, XmATTACH_POSITION); n++;
  XtSetArg(args[n], XmNtopPosition, 35); n++;
  XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
  XtSetArg(args[n], XmNcolumns, DEFAULT_WIDTH - 2*OFFSET); n++;
  
  if ( strcmp( title, "Equation" ) == 0 )
  {
      equation = XtCreateWidget(getWidgetName(),
			     xmTextFieldWidgetClass, 
			     form, args, n);
    
      XtAddCallback(equation, XmNactivateCallback,
		    (XtCallbackProc)textFieldCB, this);
      XtAddCallback(equation, XmNmotionVerifyCallback,
		    (XtCallbackProc)copyClipboard, this);
      XtManageChild(equation);   
  }
  else
  {
      blendEquation = XtCreateWidget(getWidgetName(),
			     xmTextFieldWidgetClass, 
			     form, args, n);
      
      XtAddCallback(blendEquation, XmNactivateCallback,
		    (XtCallbackProc)textFieldCB, this);
      XtAddCallback(blendEquation, XmNmotionVerifyCallback,
		    (XtCallbackProc)copyClipboard, this);
      XtManageChild(blendEquation);   
  }
  
  return form;
}

//////////////////////////////////////////////////////////////////////////////
//
//  Description:
//    Builds a scale widget for a floating point number
//
//////////////////////////////////////////////////////////////////////////////
Widget
ParameterEditor::buildScaleWidget (Widget parent,
				   char *title,
				   Arg args[], int n,
				   Widget &scale,
				   PEScaleCB *cb)
{
  XmString str;

  str = XmStringCreateLocalized(title);
  XtSetArg(args[n], XmNtitleString, str); n++;
  XtSetArg(args[n], XmNshowValue, TRUE); n++;
  XtSetArg(args[n], XmNscaleMultiple, 10); n++;
  XtSetArg(args[n], XmNorientation, XmHORIZONTAL); n++;
  scale = XtCreateWidget(getWidgetName(),
			 xmScaleWidgetClass,
			 parent, args, n);
  
  XtAddCallback(scale, XmNdragCallback,
                (XtCallbackProc)cb, this);
  XtAddCallback(scale, XmNvalueChangedCallback,
                (XtCallbackProc)cb, this);
  XmStringFree(str);

  return scale;
}

//////////////////////////////////////////////////////////////////////////////
//
//  Description:
//    callback function for each text field
//
//////////////////////////////////////////////////////////////////////////////
void
ParameterEditor::textFieldCB (Widget wdg,
			      ParameterEditor *editor,
			      XtPointer wdgData)
{
  
  editor->sendInputs();
  editor->setInputs();
  
  int val;
  XmScaleGetValue(editor->isoValue, &val);
  editor->variables->isoval->setValue((float)val / pow(10, DECIMAL_PTS));
  
  XmScaleGetValue(editor->blendValue, &val);
  editor->variables->blendval->setValue((float)val / pow(10, DECIMAL_PTS));
  editor->setText();
}

//////////////////////////////////////////////////////////////////////////////
//
//  Description:
//    callback function for the scale widget
//
//////////////////////////////////////////////////////////////////////////////
void
ParameterEditor::isoValueCB (Widget wdg,
			     ParameterEditor *editor,
			     XmScaleCallbackStruct *sd)
{
  editor->variables->isoval->setValue((float)sd->value /
				      pow(10, DECIMAL_PTS));
  editor->setText();
}

//////////////////////////////////////////////////////////////////////////////
//
//  Description:
//    callback function for the scale widget
//
//////////////////////////////////////////////////////////////////////////////
void
ParameterEditor::blendValueCB (Widget wdg,
			       ParameterEditor *editor,
			       XmScaleCallbackStruct *sd)
{
  editor->variables->blendval->setValue((float)sd->value /
				      pow(10, DECIMAL_PTS));
  editor->setText();
  editor->resetIsoRange();
}

//////////////////////////////////////////////////////////////////////////////
//
//  Description:
//    callback function for the scale widget
//
//////////////////////////////////////////////////////////////////////////////
void
ParameterEditor::vertBlendValueCB (Widget wdg,
				   ParameterEditor *editor,
				   XmScaleCallbackStruct *sd)
{
  editor->variables->vertBlend->setValue((float)sd->value /
				      pow(10, DECIMAL_PTS));
}

//////////////////////////////////////////////////////////////////////////////
//
//  Description:
//    callback function to copy the current highlighted selection into the
//    clipboard
//
//////////////////////////////////////////////////////////////////////////////
void
ParameterEditor::copyClipboard (Widget wdg,
			        ParameterEditor *editor,
			        XtPointer wdgData)
{
  XmTextFieldCopy(wdg, XtLastTimestampProcessed(editor->getDisplay()));
}
