/*
	Copyright (c) 2024 PTC Inc. and/or Its Subsidiary Companies. All Rights Reserved.
*/

#include <GearDesign.h>

#include <ProUI.h>
#include <ProUIDialog.h>
#include <ProParameter.h>
#include <ProUIRadiogroup.h>
#include <ProUILabel.h>
#include <ProUICascadebutton.h>
#include <ProUICheckbutton.h>
#include <ProUIDashboard.h>
#include <ProUIDrawingarea.h>
#include <ProUIInputpanel.h>
#include <ProUIPushbutton.h>
#include <ProUISpinbox.h>
#include <ProUITable.h>
#include <UtilString.h>
#include <ProUITab.h>
#include <ProMessage.h>
#include <stdlib.h>


#define GD_UI_MAIN "geardesigndlg"

#define GD_UI_CLOSEBTN "CloseBtn"
#define GD_UI_CLOSEBTN_M "CloseBtn_M"
#define GD_UI_LOADBTN_M "LoadBtn_M"
#define GD_UI_GEARTYPE_GROUP_M "GearTypeGroup_M"

#define GD_UI_LOADBTN_RMB "LoadBtn_RMB"
#define GD_UI_GEARTYPE_GROUP_RMB "GearTypeGroup_RMB"


#define GD_UI_TOOL_DELETE_M "DeleteBtn_M"
#define GD_UI_TOOL_MODIFY_M "ModifyBtn_M"
#define GD_UI_TOOL_REGENERATE_M "RegenerateBtn_M"
#define GD_UI_TOOL_MATERIAL_M "MaterialBtn_M"
#define GD_UI_TOOL_SAVEDVIEWS_CASCADE_M  "SavedViewsCascade_M"
#define GD_UI_TOOL_VIEW_CHOICE_M "SavedViewsChoice_M"
#define GD_UI_TOOL_VIEW_DEFAULTCREATE_M "CreateDefaultView_M"
#define GD_UI_TOOL_VIEW_STORE_M "StoreView_M"

#define GD_UI_GROUP_SPUR "SPUR"
#define GD_UI_GROUP_RING "RING"
#define GD_UI_GROUP_HELICAL "HELICAL"

#define GD_UI_LOADBTN "LoadBtn"

#define GD_UI_CREATEBTN "CreateButton"

#define GD_UI_MAINTAB "GearDesignSteps"

#define GD_UI_DATUM_LAYOUT "DefaultDatums"
#define GD_UI_DISK_LAYOUT "GearDisk"
#define GD_UI_HOLE_LAYOUT "GearHole"
#define GD_UI_HUB_LAYOUT "GearHub"
#define GD_UI_BACKPLATE_LAYOUT "GearBackPlate"
#define GD_UI_TEETH_LAYOUT "GearTeeth"

#define GD_UI_LABEL_COMPLETED "CreatedLabel"
#define GD_UI_LABEL_NOT_COMPLETED "NotCreatedLabel"

#define GD_UI_STATUS_TABLE "ComponentsTable"

#define GD_UI_STATUS_DONECOL "Created"
#define GD_UI_STATUS_COMPCOL "Component"
#define GD_UI_STATUS_REQCOL "Required"

#define GD_UI_DATUM_ROW "Datums"
#define GD_UI_DISK_ROW "Disk"
#define GD_UI_HOLE_ROW "Hole"
#define GD_UI_HUB_ROW "Hub"
#define GD_UI_BACKPLATE_ROW "Back Plate"
#define GD_UI_TEETH_ROW "Teeth"

#define GD_UI_XOFFSET_INPUT "XOffsetInput"
#define GD_UI_YOFFSET_INPUT "YOffsetInput"
#define GD_UI_ZOFFSET_INPUT "ZOffsetInput"

#define GD_UI_GEARDISK_W_INPUT "GearDiskWidth"
#define GD_UI_GEARDISK_D_INPUT "GearDiskDiameter"

#define GD_UI_GEARHOLE_D_INPUT "GearHoleDiameter"
#define GD_UI_KEYWAY_W_INPUT "KeywayWidth"
#define GD_UI_KEYWAY_H_INPUT "KeywayHeight"
#define GD_UI_KEYWAY_W_LABEL "KeywayWidthLabel"
#define GD_UI_KEYWAY_H_LABEL "KeywayHeightLabel"
#define GD_UI_INCLUDE_KEYWAY "IncludeKeywayCheck"

#define GD_UI_GEARHUB_D_INPUT "HubDiameter"
#define GD_UI_GEARHUB_T_INPUT "HubThickness"
#define GD_UI_KEY_W_INPUT "KeyWidth"
#define GD_UI_KEY_H_INPUT "KeyHeight"
#define GD_UI_KEY_W_LABEL "KeyWidthLabel"
#define GD_UI_KEY_H_LABEL "KeyHeightLabel"
#define GD_UI_INCLUDE_KEY "IncludeKeyCheck"

#define GD_UI_BN_R_INPUT "BackNotchRadius"
#define GD_UI_BP_D_INPUT "BackPlateDiameter"
#define GD_UI_BP_T_INPUT "BackPlateThickness"
#define GD_UI_BN_R_LABEL "BackNotchRadiusLabel"
#define GD_UI_INCLUDE_BN "IncludeBacknotchCheck"

#define GD_UI_N_TEETH_SPINBOX "NumTeeth"
#define GD_UI_TOOTH_INNER_SURF_LABEL "ToothInnerSurfaceLabel"
#define GD_UI_TOOTH_INNER_SURF_INPUT "ToothInnerSurface"
#define GD_UI_TOOTH_PRESSURE_ANGLE "GearToothPressureAngle"
#define GD_UI_TOOTH_P1_INPUT "GearToothParam1"
#define GD_UI_HELIX_ANGLE "HelixAngle"
#define GD_UI_HELIX_ANGLE_LABEL "HelixAngleLabel"

#define GD_UI_MENUPANE_RMB "MenuPane_RMB"

static int ProTKGDUIDatumFromUIUpdate (GearParam* g_ptr);
static int ProTKGDUIDatumUIUpdate (GearParam* g_ptr);
static int ProTKGDUIDiskFromUIUpdate (GearParam* g_ptr);
static int ProTKGDUIDiskUIUpdate (GearParam* g_ptr);
static int ProTKGDUIHoleFromUIUpdate (GearParam* g_ptr);
static int ProTKGDUIHoleUIUpdate (GearParam* g_ptr);
static int ProTKGDUIHubFromUIUpdate (GearParam* g_ptr);
static int ProTKGDUIHubUIUpdate (GearParam* g_ptr);
static int ProTKGDUIBackplateFromUIUpdate (GearParam* g_ptr);
static int ProTKGDUIBackplateUIUpdate (GearParam* g_ptr);
static int ProTKGDUITeethFromUIUpdate (GearParam* g_ptr);
static int ProTKGDUITeethUIUpdate (GearParam* g_ptr);
static ProBoolean ProTKGDUICreateButtonUpdate (GearParam* g_ptr);
int ProTKGDUIStatusTableInit (GearParam* g_ptr);
int ProTKGDUIStatusTableRowUpdate (GearParam* g_ptr, ProTKGDStep step, char* new_row_name);

typedef int (*ProTKGDUIInteractionFunction) (GearParam* g_ptr);

/*--------------------------------------------------------------------*\
    Links creation step to table and layouts in the UI.
\*--------------------------------------------------------------------*/
typedef struct 
{
  ProTKGDStep  step;
  char*        step_layout;
  char*        step_row_name;
  ProTKGDUIInteractionFunction  update_from_ui_function;
  ProTKGDUIInteractionFunction  update_ui_function;
} ProTKGDUIStepComponent;

static ProTKGDUIStepComponent gd_components [] = 
{
  {PTK_GD_DATUM, GD_UI_DATUM_LAYOUT, GD_UI_DATUM_ROW, 
   ProTKGDUIDatumFromUIUpdate, ProTKGDUIDatumUIUpdate},
  {PTK_GD_DISK, GD_UI_DISK_LAYOUT, GD_UI_DISK_ROW, 
   ProTKGDUIDiskFromUIUpdate, ProTKGDUIDiskUIUpdate},
  {PTK_GD_HOLE, GD_UI_HOLE_LAYOUT, GD_UI_HOLE_ROW,
   ProTKGDUIHoleFromUIUpdate, ProTKGDUIHoleUIUpdate},
  {PTK_GD_HUB, GD_UI_HUB_LAYOUT, GD_UI_HUB_ROW, 
   ProTKGDUIHubFromUIUpdate, ProTKGDUIHubUIUpdate},
  {PTK_GD_BACKPLATE, GD_UI_BACKPLATE_LAYOUT, GD_UI_BACKPLATE_ROW, 
   ProTKGDUIBackplateFromUIUpdate, ProTKGDUIBackplateUIUpdate},
  {PTK_GD_TEETH, GD_UI_TEETH_LAYOUT, GD_UI_TEETH_ROW, 
   ProTKGDUITeethFromUIUpdate, ProTKGDUITeethUIUpdate},
};

static ProError status;

/*=============================================================*\
  Function: 	ProTKGDUIDatumUIUpdate
  Purpose:	Datum parameters -> UI
\*=============================================================*/
int ProTKGDUIDatumUIUpdate (GearParam* g_ptr)
{
  status = ProUIInputpanelDoubleSet (GD_UI_MAIN, GD_UI_XOFFSET_INPUT, g_ptr->datum_x_offset);
  status = ProUIInputpanelDoubleSet (GD_UI_MAIN, GD_UI_YOFFSET_INPUT, g_ptr->datum_y_offset);
  status = ProUIInputpanelDoubleSet (GD_UI_MAIN, GD_UI_ZOFFSET_INPUT, g_ptr->datum_z_offset);

  ProTKGDUICreateButtonUpdate (g_ptr);

  return PRO_TK_NO_ERROR;
}

/*=============================================================*\
  Function: 	ProTKGDUIDatumFromUIUpdate
  Purpose:	Datum parameters <- UI
\*=============================================================*/
int ProTKGDUIDatumFromUIUpdate (GearParam* g_ptr)
{
  status = ProUIInputpanelDoubleGet (GD_UI_MAIN, GD_UI_XOFFSET_INPUT, &g_ptr->datum_x_offset);
  status = ProUIInputpanelDoubleGet (GD_UI_MAIN, GD_UI_YOFFSET_INPUT, &g_ptr->datum_y_offset);
  status = ProUIInputpanelDoubleGet (GD_UI_MAIN, GD_UI_ZOFFSET_INPUT, &g_ptr->datum_z_offset);

  return PRO_TK_NO_ERROR;
}

/*=============================================================*\
  Function: 	ProTKGDUIDiskUIUpdate
  Purpose:	Disk parameters -> UI
\*=============================================================*/
int ProTKGDUIDiskUIUpdate (GearParam* g_ptr)
{
  status = ProUIInputpanelDoubleSet (GD_UI_MAIN, GD_UI_GEARDISK_D_INPUT, g_ptr->gear_diam);
  status = ProUIInputpanelDoubleSet (GD_UI_MAIN, GD_UI_GEARDISK_W_INPUT, g_ptr->gear_depth);
  
  
  if (g_ptr->gear_type == HELICAL_GEAR)
    {
      ProUILabelShow (GD_UI_MAIN, GD_UI_HELIX_ANGLE_LABEL);
      ProUIInputpanelShow (GD_UI_MAIN, GD_UI_HELIX_ANGLE);
      status = ProUIInputpanelDoubleSet (GD_UI_MAIN, GD_UI_HELIX_ANGLE, g_ptr->helix_angle);
    }
  else
    {
      ProUILabelHide (GD_UI_MAIN, GD_UI_HELIX_ANGLE_LABEL);
      ProUIInputpanelHide (GD_UI_MAIN, GD_UI_HELIX_ANGLE);

    }
  
  if (ProTKGDUICreateButtonUpdate (g_ptr))
    {
      if (g_ptr->gear_depth == 0.0 || g_ptr->gear_diam == 0.0)
	ProUIPushbuttonDisable (GD_UI_MAIN, GD_UI_CREATEBTN);
      else
	ProUIPushbuttonEnable (GD_UI_MAIN, GD_UI_CREATEBTN);
    }

   return PRO_TK_NO_ERROR;
}

/*=============================================================*\
  Function: 	ProTKGDUIDiskFromUIUpdate
  Purpose:	Disk parameters <- UI
\*=============================================================*/
int ProTKGDUIDiskFromUIUpdate (GearParam* g_ptr)
{
  status = ProUIInputpanelDoubleGet (GD_UI_MAIN, GD_UI_GEARDISK_D_INPUT, &g_ptr->gear_diam);
  status = ProUIInputpanelDoubleGet (GD_UI_MAIN, GD_UI_GEARDISK_W_INPUT, &g_ptr->gear_depth);
  if (g_ptr->gear_type == HELICAL_GEAR)
  {
    ProUIInputpanelDoubleGet (GD_UI_MAIN, GD_UI_HELIX_ANGLE, &g_ptr->helix_angle);
  }
  return PRO_TK_NO_ERROR;
}

/*=============================================================*\
  Function: 	ProTKGDUIKeywayUIUpdate
  Purpose:	Keyway parameters -> UI
\*=============================================================*/
int ProTKGDUIKeywayUIUpdate (GearParam* g_ptr, ProBoolean create)
{
  if (create)
    {
      ProUILabelEnable (GD_UI_MAIN, GD_UI_KEYWAY_W_LABEL);
      ProUILabelEnable (GD_UI_MAIN, GD_UI_KEYWAY_H_LABEL);
      ProUIInputpanelEnable (GD_UI_MAIN, GD_UI_KEYWAY_W_INPUT);
      ProUIInputpanelEnable (GD_UI_MAIN, GD_UI_KEYWAY_H_INPUT);
    }
  else
    {
      ProUILabelDisable (GD_UI_MAIN, GD_UI_KEYWAY_W_LABEL);
      ProUILabelDisable (GD_UI_MAIN, GD_UI_KEYWAY_H_LABEL);
      ProUIInputpanelDisable (GD_UI_MAIN, GD_UI_KEYWAY_W_INPUT);
      ProUIInputpanelDisable (GD_UI_MAIN, GD_UI_KEYWAY_H_INPUT);
    }

  ProUIInputpanelDoubleSet (GD_UI_MAIN, GD_UI_KEYWAY_W_INPUT, g_ptr->keyway_in_width);
  ProUIInputpanelDoubleSet (GD_UI_MAIN, GD_UI_KEYWAY_H_INPUT, g_ptr->keyway_in_height);

   return PRO_TK_NO_ERROR;
}

/*=============================================================*\
  Function: 	ProTKGDUIKeywayFromUIUpdate
  Purpose:	Keyway parameters <- UI
\*=============================================================*/
int ProTKGDUIKeywayFromUIUpdate (GearParam* g_ptr)
{
  status = ProUIInputpanelDoubleGet (GD_UI_MAIN, GD_UI_KEYWAY_W_INPUT, &g_ptr->keyway_in_width);
  status = ProUIInputpanelDoubleGet (GD_UI_MAIN, GD_UI_KEYWAY_H_INPUT, &g_ptr->keyway_in_height);
  
  return PRO_TK_NO_ERROR;
}

/*=============================================================*\
  Function: 	ProTKGDUIHoleUIUpdate
  Purpose:	Hole parameters -> UI
\*=============================================================*/
int ProTKGDUIHoleUIUpdate (GearParam* g_ptr)
{
  ProBoolean show_keyway;

  status = ProUIInputpanelDoubleSet (GD_UI_MAIN, GD_UI_GEARHOLE_D_INPUT, g_ptr->inner_diam);
  
  if (ProTKGDUICreateButtonUpdate (g_ptr))
    {
      if (g_ptr->inner_diam == 0.0)
	ProUIPushbuttonDisable (GD_UI_MAIN, GD_UI_CREATEBTN);
      else
	ProUIPushbuttonEnable (GD_UI_MAIN, GD_UI_CREATEBTN);
    }
 
  show_keyway = (g_ptr->keyway_created)?PRO_B_TRUE:PRO_B_FALSE;

  ProTKGDUIKeywayUIUpdate (g_ptr, show_keyway);

  if (g_ptr->keyway_created)
    ProUICheckbuttonSet (GD_UI_MAIN, GD_UI_INCLUDE_KEYWAY);


   return PRO_TK_NO_ERROR;
}

/*=============================================================*\
  Function: 	ProTKGDUIHoleFromUIUpdate
  Purpose:	Hole parameters <- UI
\*=============================================================*/
int ProTKGDUIHoleFromUIUpdate (GearParam* g_ptr)
{
  status = ProUIInputpanelDoubleGet (GD_UI_MAIN, GD_UI_GEARHOLE_D_INPUT, &g_ptr->inner_diam);
 
  return PRO_TK_NO_ERROR;
}

/*=============================================================*\
  Function: 	ProTKGDUIKeyUIUpdate
  Purpose:	Key parameters -> UI
\*=============================================================*/
int ProTKGDUIKeyUIUpdate (GearParam* g_ptr, ProBoolean create)
{
  if (create)
    {
      ProUILabelEnable (GD_UI_MAIN, GD_UI_KEY_W_LABEL);
      ProUILabelEnable (GD_UI_MAIN, GD_UI_KEY_H_LABEL);
      ProUIInputpanelEnable (GD_UI_MAIN, GD_UI_KEY_W_INPUT);
      ProUIInputpanelEnable (GD_UI_MAIN, GD_UI_KEY_H_INPUT);
    }
  else
    {
      ProUILabelDisable (GD_UI_MAIN, GD_UI_KEY_W_LABEL);
      ProUILabelDisable (GD_UI_MAIN, GD_UI_KEY_H_LABEL);
      ProUIInputpanelDisable (GD_UI_MAIN, GD_UI_KEY_W_INPUT);
      ProUIInputpanelDisable (GD_UI_MAIN, GD_UI_KEY_H_INPUT);
    }

  ProUIInputpanelDoubleSet (GD_UI_MAIN, GD_UI_KEY_W_INPUT, g_ptr->keyway_out_width);
  ProUIInputpanelDoubleSet (GD_UI_MAIN, GD_UI_KEY_H_INPUT, g_ptr->keyway_out_height);

   return PRO_TK_NO_ERROR;
}

/*=============================================================*\
  Function: 	ProTKGDUIKeyFromUIUpdate
  Purpose:	Key parameters <- UI
\*=============================================================*/
int ProTKGDUIKeyFromUIUpdate (GearParam* g_ptr)
{
  status = ProUIInputpanelDoubleGet (GD_UI_MAIN, GD_UI_KEY_W_INPUT, &g_ptr->keyway_out_width);
  status = ProUIInputpanelDoubleGet (GD_UI_MAIN, GD_UI_KEY_H_INPUT, &g_ptr->keyway_out_height);
  
  return PRO_TK_NO_ERROR;
}

/*=============================================================*\
  Function: 	ProTKGDUIHubUIUpdate
  Purpose:	Hub parameters -> UI
\*=============================================================*/
int ProTKGDUIHubUIUpdate (GearParam* g_ptr)
{
  ProBoolean show_key;

  status = ProUIInputpanelDoubleSet (GD_UI_MAIN, GD_UI_GEARHUB_D_INPUT, g_ptr->hub_out_diam);
  status = ProUIInputpanelDoubleSet (GD_UI_MAIN, GD_UI_GEARHUB_T_INPUT, g_ptr->hub_depth);

  if (ProTKGDUICreateButtonUpdate (g_ptr))
    {
      if (g_ptr->hub_out_diam == 0.0 || g_ptr->hub_depth == 0.0)
	ProUIPushbuttonDisable (GD_UI_MAIN, GD_UI_CREATEBTN);
      else
	ProUIPushbuttonEnable (GD_UI_MAIN, GD_UI_CREATEBTN);
    }
  show_key = (g_ptr->key_created)?PRO_B_TRUE:PRO_B_FALSE;

  ProTKGDUIKeyUIUpdate (g_ptr, show_key);

  if (g_ptr->key_created)
    ProUICheckbuttonSet (GD_UI_MAIN, GD_UI_INCLUDE_KEY);

   return PRO_TK_NO_ERROR;
}

/*=============================================================*\
  Function: 	ProTKGDUIHubFromUIUpdate
  Purpose:	Hub parameters <- UI
\*=============================================================*/
int ProTKGDUIHubFromUIUpdate (GearParam* g_ptr)
{
  status = ProUIInputpanelDoubleGet (GD_UI_MAIN, GD_UI_GEARHUB_D_INPUT, &g_ptr->hub_out_diam);
  status = ProUIInputpanelDoubleGet (GD_UI_MAIN, GD_UI_GEARHUB_T_INPUT, &g_ptr->hub_depth);
 
  return PRO_TK_NO_ERROR;
}

/*=============================================================*\
  Function: 	ProTKGDUIBacknotchUIUpdate
  Purpose:	Backnotch parameters -> UI
\*=============================================================*/
int ProTKGDUIBacknotchUIUpdate (GearParam* g_ptr, ProBoolean create)
{
  if (create)
    {
      ProUILabelEnable (GD_UI_MAIN, GD_UI_BN_R_LABEL);
      ProUIInputpanelEnable (GD_UI_MAIN, GD_UI_BN_R_INPUT);
    }
  else
    {
      ProUILabelDisable (GD_UI_MAIN, GD_UI_BN_R_LABEL);
      ProUIInputpanelDisable (GD_UI_MAIN, GD_UI_BN_R_INPUT);
    }

  ProUIInputpanelDoubleSet (GD_UI_MAIN, GD_UI_BN_R_INPUT, g_ptr->backnotch_rad);

   return PRO_TK_NO_ERROR;
}

/*=============================================================*\
  Function: 	ProTKGDUIBacknotchFromUIUpdate
  Purpose:	Backnotch parameters <- UI
\*=============================================================*/
int ProTKGDUIBacknotchFromUIUpdate (GearParam* g_ptr)
{
  status = ProUIInputpanelDoubleGet (GD_UI_MAIN, GD_UI_BN_R_INPUT, &g_ptr->backnotch_rad);
  
  return PRO_TK_NO_ERROR;
}

/*=============================================================*\
  Function: 	ProTKGDUIBackplateUIUpdate
  Purpose:	Backplate parameters -> UI
\*=============================================================*/
int ProTKGDUIBackplateUIUpdate (GearParam* g_ptr)
{
  ProBoolean show_bn;

  status = ProUIInputpanelDoubleSet (GD_UI_MAIN, GD_UI_BP_D_INPUT, g_ptr->backplate_diam);
  status = ProUIInputpanelDoubleSet (GD_UI_MAIN, GD_UI_BP_T_INPUT, g_ptr->backplate_depth);

  if (ProTKGDUICreateButtonUpdate (g_ptr))
    {
      if (/*g_ptr->backplate_created || */g_ptr->backplate_diam == 0.0 || g_ptr->backplate_depth == 0.0)
	ProUIPushbuttonDisable (GD_UI_MAIN, GD_UI_CREATEBTN);
      else
	ProUIPushbuttonEnable (GD_UI_MAIN, GD_UI_CREATEBTN);
    }

  show_bn = (g_ptr->backnotch_created)?PRO_B_TRUE:PRO_B_FALSE;

  ProTKGDUIBacknotchUIUpdate (g_ptr, show_bn);

  if (g_ptr->backnotch_created)
    ProUICheckbuttonSet (GD_UI_MAIN, GD_UI_INCLUDE_BN);

   return PRO_TK_NO_ERROR;
}

/*=============================================================*\
  Function: 	ProTKGDUIBackplateFromUIUpdate
  Purpose:	Backplate parameters <- UI
\*=============================================================*/
int ProTKGDUIBackplateFromUIUpdate (GearParam* g_ptr)
{
  status = ProUIInputpanelDoubleGet (GD_UI_MAIN, GD_UI_BP_D_INPUT, &g_ptr->backplate_diam);
  status = ProUIInputpanelDoubleGet (GD_UI_MAIN, GD_UI_BP_T_INPUT, &g_ptr->backplate_depth);
 
  return PRO_TK_NO_ERROR;
}

/*=============================================================*\
  Function: 	ProTKGDUITeethUIUpdate
  Purpose:	Teeth parameters -> UI
\*=============================================================*/
int ProTKGDUITeethUIUpdate (GearParam* g_ptr)
{
  status = ProUIInputpanelDoubleSet (GD_UI_MAIN, GD_UI_TOOTH_PRESSURE_ANGLE, g_ptr->Pressure_angle);
  status = ProUIInputpanelDoubleSet (GD_UI_MAIN, GD_UI_TOOTH_P1_INPUT, g_ptr->tooth_par1);
  status = ProUISpinboxIntegerSet (GD_UI_MAIN, GD_UI_N_TEETH_SPINBOX, g_ptr->n_of_teeth);

  if (g_ptr->gear_type == RING_GEAR)
    {
      ProUILabelShow (GD_UI_MAIN, GD_UI_TOOTH_INNER_SURF_LABEL);
      ProUIInputpanelShow (GD_UI_MAIN, GD_UI_TOOTH_INNER_SURF_INPUT);
      ProUIInputpanelDoubleSet (GD_UI_MAIN, GD_UI_TOOTH_INNER_SURF_INPUT,
				g_ptr->inner_diam);
    }
  else
    {
      ProUILabelHide (GD_UI_MAIN, GD_UI_TOOTH_INNER_SURF_LABEL);
      ProUIInputpanelHide (GD_UI_MAIN, GD_UI_TOOTH_INNER_SURF_INPUT);

    }
  if (ProTKGDUICreateButtonUpdate (g_ptr))
    {
      if ( g_ptr->Pressure_angle == 0.0 ||
	   g_ptr->tooth_par1  == 0.0 || g_ptr->n_of_teeth == 0)
	ProUIPushbuttonDisable (GD_UI_MAIN, GD_UI_CREATEBTN);
      else
	ProUIPushbuttonEnable (GD_UI_MAIN, GD_UI_CREATEBTN);
    }
   return PRO_TK_NO_ERROR;
}

/*=============================================================*\
  Function: 	ProTKGDUITeethFromUIUpdate
  Purpose:	Teeth parameters <- UI
\*=============================================================*/
int ProTKGDUITeethFromUIUpdate (GearParam* g_ptr)
{
  status = ProUIInputpanelDoubleGet (GD_UI_MAIN, GD_UI_TOOTH_PRESSURE_ANGLE, &g_ptr->Pressure_angle);
  status = ProUIInputpanelDoubleGet (GD_UI_MAIN, GD_UI_TOOTH_P1_INPUT, &g_ptr->tooth_par1);
  status = ProUISpinboxIntegerGet (GD_UI_MAIN, GD_UI_N_TEETH_SPINBOX, &g_ptr->n_of_teeth);

  if (g_ptr->gear_type == RING_GEAR)
    ProUIInputpanelDoubleGet (GD_UI_MAIN, GD_UI_TOOTH_INNER_SURF_INPUT,
			      &g_ptr->inner_diam);

  return PRO_TK_NO_ERROR;
}


/*=============================================================*\
  Function: 	ProTKGDUIStepFromTableGet
  Purpose:	Utility: Get step id from table row
\*=============================================================*/
int ProTKGDUIStepFromTableGet (char* table_row, ProTKGDStep* step)
{
  int ii;
  for (ii = 0;  ii < NUM_GD_STEPS; ii ++)
    {
      if (strcmp (table_row, gd_components[ii].step_row_name) == 0)
	{
	  *step = gd_components [ii].step;
	  return (int)PRO_TK_NO_ERROR;
	}
    }
  return (int)PRO_TK_GENERAL_ERROR;
}

/*=============================================================*\
  Function: 	ProTKGDUICreateButtonUpdate
  Purpose:	Utility: Update sensitivity of "Create" menu button
\*=============================================================*/
ProBoolean ProTKGDUICreateButtonUpdate (GearParam* g_ptr)
{
  ProTKGDStep step = g_ptr->current_step;
  ProBoolean enable;

  switch (step)
    {
    case  PTK_GD_DATUM:
      enable = (g_ptr->datum_created ?  PRO_B_FALSE : PRO_B_TRUE);
      break;
    case PTK_GD_DISK:
      enable = (g_ptr->disk_created ?  PRO_B_FALSE : PRO_B_TRUE);
      break;
    case PTK_GD_HOLE:
      enable = (g_ptr->hole_created ?  PRO_B_FALSE : PRO_B_TRUE);
      break;
    case PTK_GD_HUB:
      enable = (g_ptr->hub_created ?  PRO_B_FALSE : PRO_B_TRUE);
      break;
    case PTK_GD_BACKPLATE:
      enable = (g_ptr->backplate_created ?  PRO_B_FALSE : PRO_B_TRUE);
      break;
    case PTK_GD_TEETH:
      enable = (g_ptr->teeth_created ?  PRO_B_FALSE : PRO_B_TRUE);
      break;
    }

  if (enable)
    {
      if (step != PTK_GD_DATUM && !g_ptr->datum_created)
	enable = PRO_B_FALSE;

      if (step != PTK_GD_DATUM && step != PTK_GD_DISK && !g_ptr->disk_created)
	enable = PRO_B_FALSE;

      if (g_ptr->gear_type == RING_GEAR)
	if (step != PTK_GD_DATUM && step != PTK_GD_DISK && step != PTK_GD_BACKPLATE && !g_ptr->backplate_created)
	  enable = PRO_B_FALSE;
    }

  if (enable)
    ProUIPushbuttonEnable (GD_UI_MAIN, GD_UI_CREATEBTN);
  else
    ProUIPushbuttonDisable (GD_UI_MAIN, GD_UI_CREATEBTN);

  return enable;
}


/*=============================================================*\
  Function: 	ProTKGDUIToggleType
  Purpose:	Utility: toggle type (ring <-> spur) in the UI
\*=============================================================*/
void ProTKGDUIToggleType (GearParam* g_ptr)
{
  /* Clear status table */
  ProUITableCellComponentDelete (GD_UI_MAIN, GD_UI_STATUS_TABLE,
				 GD_UI_DATUM_ROW, GD_UI_STATUS_DONECOL);
  ProUITableCellComponentDelete (GD_UI_MAIN, GD_UI_STATUS_TABLE,
				 GD_UI_DISK_ROW, GD_UI_STATUS_DONECOL);
  if (g_ptr->gear_type == HELICAL_GEAR)
    {
      ProUILabelShow (GD_UI_MAIN, GD_UI_HELIX_ANGLE_LABEL);
      ProUIInputpanelShow (GD_UI_MAIN, GD_UI_HELIX_ANGLE);
    }
  else
    {     
      ProUILabelHide (GD_UI_MAIN, GD_UI_HELIX_ANGLE_LABEL);
      ProUIInputpanelHide (GD_UI_MAIN, GD_UI_HELIX_ANGLE);
    }
  ProUITableCellComponentDelete (GD_UI_MAIN, GD_UI_STATUS_TABLE,
				 GD_UI_HOLE_ROW, GD_UI_STATUS_DONECOL);
  ProUITableCellComponentDelete (GD_UI_MAIN, GD_UI_STATUS_TABLE,
				 GD_UI_HUB_ROW, GD_UI_STATUS_DONECOL);
  ProUITableCellComponentDelete (GD_UI_MAIN, GD_UI_STATUS_TABLE,
				 GD_UI_BACKPLATE_ROW, GD_UI_STATUS_DONECOL);
  ProUITableCellComponentDelete (GD_UI_MAIN, GD_UI_STATUS_TABLE,
				 GD_UI_TEETH_ROW, GD_UI_STATUS_DONECOL);

  ProUITableRownamesSet (GD_UI_MAIN, GD_UI_STATUS_TABLE, 0, NULL);

  if (g_ptr->gear_type == RING_GEAR)
    {
      ProUILabelShow (GD_UI_MAIN, GD_UI_TOOTH_INNER_SURF_LABEL);
      ProUIInputpanelShow (GD_UI_MAIN, GD_UI_TOOTH_INNER_SURF_INPUT);
    }
  else
    {     
      ProUILabelHide (GD_UI_MAIN, GD_UI_TOOTH_INNER_SURF_LABEL);
      ProUIInputpanelHide (GD_UI_MAIN, GD_UI_TOOTH_INNER_SURF_INPUT);
    }
  /* Reinitialize it */
  ProTKGDUIStatusTableInit (g_ptr);
}


/*=============================================================*\
  Function: 	ProTKGDUISelectNext
  Purpose:	Utility: select next item (typically after creation)
\*=============================================================*/
int   ProTKGDUISelectNext (GearParam* g_ptr, ProTKGDStep step)
{
  ProTKGDStepInfo* order;
  int ii, current_index;
  ProTKGDStep next_step;
  char * next_select [2];

  switch (g_ptr->gear_type)
    {
    case SPUR_GEAR:
      order = (ProTKGDStepInfo*)spur_gear_designinfo;
      break;
    case HELICAL_GEAR:
      order = (ProTKGDStepInfo*)helical_gear_designinfo;
      break;
    case RING_GEAR:
      order = (ProTKGDStepInfo*)ring_gear_designinfo;
      break;
    }

  for (ii = 0; ii < NUM_GD_STEPS; ii++)
    {
      if (order[ii].step == step)
	{
	  current_index = ii;
	  break;
	}
    }
  
  ProTKGDUIStatusTableRowUpdate (g_ptr, step, gd_components[step].step_row_name);

  if (current_index != NUM_GD_STEPS - 1)
    {
      next_step = order [current_index + 1].step;
      next_select[0] = gd_components[next_step].step_row_name;
      next_select[1] = GD_UI_STATUS_COMPCOL;
      
      g_ptr->current_step = next_step;
      
      ProUITableSelectednamesSet (GD_UI_MAIN, GD_UI_STATUS_TABLE,
				  2, next_select);
   
      ProUITabSelectednamesSet (GD_UI_MAIN, GD_UI_MAINTAB,
				1, &gd_components[next_step].step_layout);

      gd_components [next_step].update_ui_function (g_ptr); 
    }

  return PRO_TK_NO_ERROR;
}

/*=============================================================*\
  Function: 	ProTKGDUIStatusTableRowUpdate
  Purpose:	Utility: update the creation status icon in table
\*=============================================================*/
int ProTKGDUIStatusTableRowUpdate (GearParam* g_ptr,
				   ProTKGDStep step,
				   char* new_row_name)
{
  ProBoolean created = PRO_B_FALSE;
  char* current_component;
  char* new_component;
  char* source_label;

  switch (step)
    {
    case PTK_GD_DATUM:
      if (g_ptr->datum_created)
	created = PRO_B_TRUE;
      new_component = "DatumCreatedLabel";
      break;
    case PTK_GD_DISK:
      if (g_ptr->disk_created)
	created = PRO_B_TRUE;
      new_component = "DiskCreatedLabel";
      break;
    case PTK_GD_HOLE:
      if (g_ptr->hole_created)
	created = PRO_B_TRUE;
      new_component = "HoleCreatedLabel";
      break;
    case PTK_GD_HUB:
      if (g_ptr->hub_created)
	created = PRO_B_TRUE;
      new_component = "HubCreatedLabel";
      break;
    case PTK_GD_BACKPLATE:
      if (g_ptr->backplate_created)
	created = PRO_B_TRUE;
      new_component = "BackplateCreatedLabel";
      break;
    case PTK_GD_TEETH:
      if (g_ptr->teeth_created)
	created = PRO_B_TRUE;
      new_component = "TeethCreatedLabel";
      break;
    }

  ProUITableCellComponentDelete (GD_UI_MAIN,
				 GD_UI_STATUS_TABLE,
				 new_row_name,
				 GD_UI_STATUS_DONECOL);
  if (created)
    source_label = GD_UI_LABEL_COMPLETED;
  else
    source_label = GD_UI_LABEL_NOT_COMPLETED;

  ProUITableCellComponentCopy (GD_UI_MAIN,
			       GD_UI_STATUS_TABLE,
			       new_row_name,
			       GD_UI_STATUS_DONECOL,
			       GD_UI_MAIN,
			       source_label,
			       new_component);

  return PRO_TK_NO_ERROR;
}


/*=============================================================*\
  Function: 	ProTKGDUIStatusTableRowAdd
  Purpose:	Utility: add the designated row to the table
\*=============================================================*/
int ProTKGDUIStatusTableRowAdd (GearParam* g_ptr,
				ProTKGDStep step,
				ProBoolean required)
{
  char ** row_names;
  int n_rows;
  char * new_row_name = gd_components [step].step_row_name;
  ProLine new_row_label;
  
  status = ProUITableRownamesGet (GD_UI_MAIN, GD_UI_STATUS_TABLE, 
			 &n_rows, &row_names);
  if (status == PRO_TK_NO_ERROR && n_rows > 0)
    {   
      ProUITableRowsInsert (GD_UI_MAIN, GD_UI_STATUS_TABLE,
			    row_names [n_rows-1], 1, 
			    &new_row_name);
      
      ProStringarrayFree (row_names, n_rows);
    }
  else
    {
      ProUITableRowsInsert (GD_UI_MAIN, GD_UI_STATUS_TABLE,
			      NULL, 1, 
			      &new_row_name);
    }


  ProStringToWstring (new_row_label, new_row_name);
  ProUITableCellLabelSet (GD_UI_MAIN, GD_UI_STATUS_TABLE,
			  new_row_name, GD_UI_STATUS_COMPCOL,
			  new_row_label);

  ProUITableCellLabelSet (GD_UI_MAIN, GD_UI_STATUS_TABLE,
			  new_row_name, GD_UI_STATUS_REQCOL,
			  (required?L"Required":L"Optional"));
			
			
  ProTKGDUIStatusTableRowUpdate (g_ptr, step, new_row_name);

  return PRO_TK_NO_ERROR;
}

/*=============================================================*\
  Function: 	ProTKGDUIStatusTableInit
  Purpose:	Utility: initialize the creation status table
\*=============================================================*/
int ProTKGDUIStatusTableInit (GearParam* g_ptr)
{
  ProTKGDStepInfo* order;
  int ii;

  switch (g_ptr->gear_type)
    {
    case SPUR_GEAR:
      order = (ProTKGDStepInfo*)spur_gear_designinfo;
      break;
    case HELICAL_GEAR:
      order = (ProTKGDStepInfo*)helical_gear_designinfo;
      break;
    case RING_GEAR:
      order = (ProTKGDStepInfo*)ring_gear_designinfo;
      break;
    }

  for (ii = 0; ii < NUM_GD_STEPS; ii++)
    {
      ProTKGDUIStatusTableRowAdd (g_ptr, order [ii].step, order [ii].required);
    }

  return PRO_TK_NO_ERROR;
}


/*=================== UI ACTION FUNCTIONS =====================*/

/*=============================================================*\
  Function: 	ProTKGDUICloseAction
  Purpose:	Close button action function
\*=============================================================*/
void ProTKGDUICloseAction (char* dialog,
			   char *component,
			   ProAppData appdata)
{
  ProUIDialogExit (dialog, 0);
}

/*=============================================================*\
  Function: 	ProTKGDUIDiskInputAction
  Purpose:	Disk params input action function
\*=============================================================*/
void ProTKGDUIDiskInputAction (char* dialog,
				 char *component,
				 ProAppData appdata)
{
  GearParam* g_ptr = (GearParam*)appdata;

  ProTKGDUIDiskFromUIUpdate (g_ptr);

  ProTKGDUIDiskUIUpdate (g_ptr);
}

/*=============================================================*\
  Function: 	ProTKGDUIHoleInputAction
  Purpose:	Hole params input action function
\*=============================================================*/
void ProTKGDUIHoleInputAction (char* dialog,
				 char *component,
				 ProAppData appdata)
{
  GearParam* g_ptr = (GearParam*)appdata;

  ProTKGDUIHoleFromUIUpdate (g_ptr);

  ProTKGDUIHoleUIUpdate (g_ptr);
}

/*=============================================================*\
  Function: 	ProTKGDUITableSelectAction
  Purpose:	Table selection action function
\*=============================================================*/
void ProTKGDUITableSelectAction (char* dialog,
				 char *component,
				 ProAppData appdata)
{
  GearParam* g_ptr = (GearParam*)appdata;
  ProTKGDStep step;
  int n_sel;
  char** selections;
  ProCharLine sel_row;

  ProUITableSelectednamesGet (GD_UI_MAIN, GD_UI_STATUS_TABLE,
			      &n_sel, &selections);
  
  /* Need to know only the selected row in the table */
  strcpy (sel_row, selections [0]);
  
  ProStringarrayFree (selections, n_sel);

  ProTKGDUIStepFromTableGet (sel_row, &step);

  status = ProUITabSelectednamesSet (GD_UI_MAIN, GD_UI_MAINTAB,
			    1, &gd_components [step].step_layout);

  g_ptr->current_step = step;
  gd_components [step].update_ui_function (g_ptr);
}



/*=============================================================*\
  Function: 	ProTKGDUICreateAction
  Purpose:	"Create" button action function
\*=============================================================*/
void ProTKGDUICreateAction (char* dialog,
				 char *component,
				 ProAppData appdata)
{
  ProError err;
  ProBoolean keyway, key, bn;
  GearParam* g_ptr = (GearParam*)appdata;
  char ** selected_layout;
  int num_selected;
  ProTKGDStep step = g_ptr->current_step;

  gd_components [step].update_from_ui_function (g_ptr);

  switch (step)
    {
    case PTK_GD_DATUM:
      ProUserCreateDatum (g_ptr);
      break;
    case PTK_GD_DISK:
      ProUserCreateDisk (g_ptr);
      break;
    case PTK_GD_HOLE:
      ProUserCreateHole (g_ptr);
      
      ProUICheckbuttonGetState (GD_UI_MAIN, GD_UI_INCLUDE_KEYWAY, &keyway);
      
      if (keyway)
	{
	  ProTKGDUIKeywayFromUIUpdate (g_ptr);
	  ProUserCreateKeyway (g_ptr);
	}
      ProUIRadiogroupDisable (GD_UI_MAIN, GD_UI_GEARTYPE_GROUP_M);


      break;
    case PTK_GD_HUB:
      ProUserCreateHub (g_ptr);

      ProUICheckbuttonGetState (GD_UI_MAIN, GD_UI_INCLUDE_KEY, &key);
      
      if (key)
	{
	  ProTKGDUIKeyFromUIUpdate (g_ptr);
	  ProUserCreateKey (g_ptr);
	}
      
      ProUIRadiogroupDisable (GD_UI_MAIN, GD_UI_GEARTYPE_GROUP_M);

      
      break;
    case PTK_GD_BACKPLATE:
      ProUserCreateBackPlate (g_ptr);

      ProUICheckbuttonGetState (GD_UI_MAIN, GD_UI_INCLUDE_BN, &bn);
      
      if (bn)
	{
	  ProTKGDUIBacknotchFromUIUpdate (g_ptr);
	  ProUserCreateBackNotch (g_ptr);
	}
      ProUIRadiogroupDisable (GD_UI_MAIN, GD_UI_GEARTYPE_GROUP_M);


      break;
    case PTK_GD_TEETH:
      if (g_ptr->gear_type == RING_GEAR)
	ProUserCreateToothSurf (g_ptr);
      
      ProUserCreateTooth (g_ptr);

      ProUserCreateTeeth (g_ptr);
      
      ProUIRadiogroupDisable (GD_UI_MAIN, GD_UI_GEARTYPE_GROUP_M);

      break;
    }

  gd_components [step].update_ui_function (g_ptr);

  ProTKGDUISelectNext (g_ptr, step);

  return;
}

/*=============================================================*\
  Function: 	ProTKGDUIHubInputAction
  Purpose:	Hub params input action function
\*=============================================================*/
void ProTKGDUIHubInputAction (char* dialog,
				 char *component,
				 ProAppData appdata)
{
  GearParam* g_ptr = (GearParam*)appdata;

  ProTKGDUIHubFromUIUpdate (g_ptr);

  ProTKGDUIHubUIUpdate (g_ptr);
}

/*=============================================================*\
  Function: 	ProTKGDUIBackplateInputAction
  Purpose:	Backplate params input action function
\*=============================================================*/
void ProTKGDUIBackplateInputAction (char* dialog,
				 char *component,
				 ProAppData appdata)
{
  GearParam* g_ptr = (GearParam*)appdata;

  ProTKGDUIBackplateFromUIUpdate (g_ptr);

  ProTKGDUIBackplateUIUpdate (g_ptr);
}

/*=============================================================*\
  Function: 	ProTKGDUITeethInputAction
  Purpose:	Teeth params input action function
\*=============================================================*/
void ProTKGDUITeethInputAction (char* dialog,
				 char *component,
				 ProAppData appdata)
{
  GearParam* g_ptr = (GearParam*)appdata;

  ProTKGDUITeethFromUIUpdate (g_ptr);

  ProTKGDUITeethUIUpdate (g_ptr);
}

/*=============================================================*\
  Function: 	ProTKGDUITeethUpdateAction
  Purpose:	Teeth params update action function (spinbox)
\*=============================================================*/
void ProTKGDUITeethUpdateAction (char* dialog,
				 char *component,
				 ProAppData appdata)
{
  GearParam* g_ptr = (GearParam*)appdata;
  
  ProTKGDUITeethFromUIUpdate (g_ptr);

  ProTKGDUITeethUIUpdate (g_ptr);
} 

/*=============================================================*\
  Function: 	ProTKGDUIIncludeKeywayAction
  Purpose:	Include keyway checkbox  action function
\*=============================================================*/
void ProTKGDUIIncludeKeywayAction (char* dialog,
				 char *component,
				 ProAppData appdata)
{
  ProBoolean keyway;
  GearParam* g_ptr = (GearParam*)appdata;
   
  ProUICheckbuttonGetState (GD_UI_MAIN, GD_UI_INCLUDE_KEYWAY, &keyway);

  ProTKGDUIKeywayUIUpdate (g_ptr, keyway);
}

/*=============================================================*\
  Function: 	ProTKGDUIIncludeKeyAction
  Purpose:	Include key checkbox action function
\*=============================================================*/
void ProTKGDUIIncludeKeyAction (char* dialog,
				 char *component,
				 ProAppData appdata)
{
  ProBoolean key;
  GearParam* g_ptr = (GearParam*)appdata;
   
  ProUICheckbuttonGetState (GD_UI_MAIN, GD_UI_INCLUDE_KEY, &key);

  ProTKGDUIKeyUIUpdate (g_ptr, key);
}

/*=============================================================*\
  Function: 	ProTKGDUIIncludeBacknotchAction
  Purpose:	Include backnotch checkbox action function
\*=============================================================*/
void ProTKGDUIIncludeBacknotchAction (char* dialog,
				 char *component,
				 ProAppData appdata)
{
  ProBoolean bn;
  GearParam* g_ptr = (GearParam*)appdata;
   
  ProUICheckbuttonGetState (GD_UI_MAIN, GD_UI_INCLUDE_BN, &bn);

  ProTKGDUIBacknotchUIUpdate (g_ptr, bn);
}

/*=============================================================*\
  Function: 	ProTKGDUIToggleTypeAction
  Purpose:	Action function for menu radiogroup (type)
\*=============================================================*/
void ProTKGDUIToggleTypeAction (char* dialog,
				 char *component,
				 ProAppData appdata)
{
  GearParam* g_ptr = (GearParam*)appdata;
  int n_sels;
  char** sel_names;
  int new_type;
  
  ProUIRadiogroupSelectednamesGet (GD_UI_MAIN, component,
				   &n_sels, &sel_names);

  if (strcmp (sel_names[0], GD_UI_GROUP_SPUR) == 0)
    new_type = SPUR_GEAR;
  
  /*if(strcmp (sel_names[0], GD_UI_GROUP_RING) == 0)
    new_type = RING_GEAR;*/
  
  if(strcmp (sel_names[0], GD_UI_GROUP_HELICAL) == 0)
    new_type = HELICAL_GEAR;
    
  else
    new_type = RING_GEAR;

  ProStringarrayFree (sel_names, n_sels);

  if (new_type == g_ptr->gear_type)
    return;

  g_ptr->gear_type = new_type;

  ProTKGDUIToggleType (g_ptr);
}

/*=============================================================*\
  Function: 	ProTKGDUILoadParamsAction
  Purpose:	Action function for "Load Params" button
\*=============================================================*/
void  ProTKGDUILoadParamsAction (char* dialog,
				 char *component,
				 ProAppData appdata)
{
  GearParam* g_ptr = (GearParam*)appdata;
     int m_id, action, first=0;
    ProName   name;
    static int mode=0;
    ProLine   w_ext;
    char line[PRO_PATH_SIZE];
    ProParameter param;
    ProParamvalue parvalue;
    ProModelitem modelitem;
    ProPath  *w_path_arr, w_def_path, w_sel_path;
    ProName  *w_path_lab_arr;
    ProError err;
    char dlg_name [PRO_LINE_SIZE];
    char* rg_entry;
	ProName unit_type; 
    int cur_type = g_ptr->gear_type;
	ProMdlName new_name;

    strcpy (dlg_name, dialog);

/*-----------------------------------------------------------------*\
    Check Gear Design
\*-----------------------------------------------------------------*/
   
    ProMdlToModelitem(g_ptr->model, &modelitem);
    ProStringToWstring(name, "Gear_Design");
    err = ProParameterInit(&modelitem, name, &param);
  
    ProMessageDisplay(MSGFIL, "PROTKGD Select a parameter file");
    
    ProStringToWstring(w_def_path, ".");
    ProStringToWstring(w_ext, "*.txt");
    
    /* No default dirs */
    err = ProArrayAlloc(0, sizeof(ProPath), 1, (ProArray*)&w_path_arr);
    err = ProArrayAlloc(0, sizeof(ProPath), 1, (ProArray*)&w_path_lab_arr);
    
    /* Open file */
    err = ProFileMdlnameOpen(NULL, w_ext, w_path_arr, w_path_lab_arr, w_def_path, NULL,
		      w_sel_path);
    
    ProArrayFree((ProArray*)&w_path_arr);
    ProArrayFree((ProArray*)&w_path_lab_arr);
  

    ProWstringToString(line, w_sel_path);
    first = 1;
    
    if (ProUserReadParamFile(line ,g_ptr)!=0)
      return;

      
    if (g_ptr->gear_type != cur_type)
      ProTKGDUIToggleType (g_ptr);

    /*if (g_ptr->gear_type == RING_GEAR)
      rg_entry = GD_UI_GROUP_RING;*/
    if(g_ptr->gear_type == SPUR_GEAR)
      rg_entry = GD_UI_GROUP_SPUR;
    if(g_ptr->gear_type == HELICAL_GEAR)
      rg_entry = GD_UI_GROUP_HELICAL;
    else
      rg_entry = GD_UI_GROUP_SPUR;
    ProUIRadiogroupSelectednamesSet (GD_UI_MAIN,
				     GD_UI_GEARTYPE_GROUP_M,
				     1, &rg_entry);

    ProTKGDUIDatumUIUpdate (g_ptr);
    ProTKGDUIDiskUIUpdate (g_ptr);
    ProTKGDUIHoleUIUpdate (g_ptr);
    ProTKGDUIHubUIUpdate (g_ptr);
    ProTKGDUIBackplateUIUpdate (g_ptr);
    ProTKGDUITeethUIUpdate (g_ptr);

    ProParamvalueSet(&parvalue, (void *)w_sel_path, PRO_PARAM_STRING);
    ProParameterWithUnitsCreate(&modelitem, name, &parvalue, NULL, &param);
    ProStringToWstring(new_name, g_ptr->name);
    ProMdlnameRename(g_ptr->model, new_name);

    ProStringToWstring(name, g_ptr->material);
    ProPartMaterialSet((ProPart)g_ptr->model, name);

	{
		ProUnititem* units;
		ProUnitsystem new_system;
		ProError status;

		switch(g_ptr->units)
		{
		case PRO_UNITLENGTH_CM:
			ProStringToWstring(unit_type, "cm");
			break;
		case PRO_UNITLENGTH_FT:
			ProStringToWstring(unit_type, "ft");
			break;
		case PRO_UNITLENGTH_IN:
			ProStringToWstring(unit_type, "in");
			break;
		case PRO_UNITLENGTH_M:
			ProStringToWstring(unit_type, "m");
			break;
		case PRO_UNITLENGTH_MM:
			ProStringToWstring(unit_type, "mm");
			break;
		}

		status = ProArrayAlloc (1, sizeof (ProUnititem), 1, (ProArray*)&units);
		status = ProUnitInit (g_ptr->model, unit_type, &units[0]);
		status = ProMdlUnitsystemCreate (g_ptr->model, PRO_UNITSYSTEM_MLT,
			L"ParamLen M T", units, &new_system);
		status = ProMdlPrincipalunitsystemSet(g_ptr->model, &new_system,
			PRO_UNITCONVERT_SAME_SIZE, PRO_B_TRUE, PRO_VALUE_UNUSED);
	}

}

/*=============================================================*\
  Function: 	ProTKGDUIDeleteAction
  Purpose:	Delete button action function
\*=============================================================*/
void  ProTKGDUIDeleteAction (char* dialog, char* component, 
			      ProAppData appdata)
{
    GearParam* g_ptr = (GearParam*)appdata;

    ProUserDeleteDesign (g_ptr);
}

/*=============================================================*\
  Function: 	ProTKGDUIModifyAction
  Purpose:	Modify button action function
\*=============================================================*/
void  ProTKGDUIModifyAction (char* dialog, char* component, 
			      ProAppData appdata)
{
    GearParam* g_ptr = (GearParam*)appdata;

    ProUserModifyDesign (g_ptr);
}

/*=============================================================*\
  Function: 	ProTKGDUIRegenerateAction
  Purpose:	Regenerate button action function
\*=============================================================*/
void  ProTKGDUIRegenerateAction (char* dialog, char* component, 
			      ProAppData appdata)
{
    GearParam* g_ptr = (GearParam*)appdata;

    ProUserRegenerate (g_ptr);
}

/*=============================================================*\
  Function: 	ProTKGDUIMaterialAction
  Purpose:	Set Material button action function
\*=============================================================*/
void  ProTKGDUIMaterialAction (char* dialog, char* component, 
			      ProAppData appdata)
{
    GearParam* g_ptr = (GearParam*)appdata;

    ProUserMaterial (g_ptr);
}

/*=============================================================*\
  Function: 	ProTKGDUIViewSelectAction
  Purpose:	Saved view selection action function
\*=============================================================*/
void  ProTKGDUIViewSelectAction (char* dialog, char* component, 
			      ProAppData appdata)
{
    GearParam* g_ptr = (GearParam*)appdata;
    char** names;
    int n_names;
    ProName new_view;
    ProView view;
    
    ProUIRadiogroupSelectednamesGet (GD_UI_MAIN,
				     GD_UI_TOOL_VIEW_CHOICE_M,
				     &n_names, &names);

    ProStringToWstring (new_view, names [0]);
    ProStringarrayFree (names, n_names);

    ProViewRetrieve(g_ptr->model, new_view, &view);
}

/*=============================================================*\
  Function: 	ProTKGDUIViewSelectAction
  Purpose:	Utility: update contents of the saved views radiogroup
\*=============================================================*/
void ProTKGDUIViewNamesUpdate (GearParam* g_ptr)
{
  ProError err;
  ProLine* names;
  int num_views;
  int ii, len;
  char** new_names;
  wchar_t** new_labels;

  err = ProViewNamesGet(g_ptr->model, &names, NULL, &num_views);
  if (err != PRO_TK_NO_ERROR || num_views<=0)
    {
      ProUICascadebuttonDisable (GD_UI_MAIN,
				 GD_UI_TOOL_SAVEDVIEWS_CASCADE_M);
    }	
  else
    {
      ProUICascadebuttonEnable (GD_UI_MAIN,
				GD_UI_TOOL_SAVEDVIEWS_CASCADE_M);
    
      new_names = (char**) calloc (num_views, sizeof (char*));
      new_labels = (wchar_t**) calloc (num_views, sizeof (wchar_t*));
      for (ii = 0; ii < num_views; ii++)
	{
	  len = ProUtilWstrLen (names [ii]) + 1;
	  new_names [ii] = (char*) calloc (len, sizeof (char));
	  ProWstringToString (new_names [ii], names [ii]);
	  new_labels [ii] = (wchar_t*) calloc (len,  sizeof (wchar_t));
	  ProUtilWstrcpy (new_labels [ii], names [ii]);
	}
      ProUIRadiogroupNamesSet (GD_UI_MAIN, GD_UI_TOOL_VIEW_CHOICE_M,
			       num_views, new_names);
      ProUIRadiogroupLabelsSet (GD_UI_MAIN, GD_UI_TOOL_VIEW_CHOICE_M,
			       num_views, new_labels);

      for (ii = 0; ii < num_views; ii++)
	{
	  free (new_names [ii]);
	  free (new_labels [ii]);
	}
      free (new_names);
      free (new_labels);
      ProArrayFree ((ProArray*)&names);
    }

}

/*=============================================================*\
  Function: 	ProTKGDUIDefaultViewCreateAction
  Purpose:	Create Default Views action function
\*=============================================================*/
void  ProTKGDUIDefaultViewCreateAction (char* dialog, char* component, 
			      ProAppData appdata)
{
    GearParam* g_ptr = (GearParam*)appdata;

    ProUserCreateViewAuto (g_ptr);

    ProTKGDUIViewNamesUpdate (g_ptr);
}

/*=============================================================*\
  Function: 	ProTKGDUIViewStoreAction
  Purpose:	Save View action function
\*=============================================================*/
void  ProTKGDUIViewStoreAction (char* dialog, char* component, 
			      ProAppData appdata)
{
    GearParam* g_ptr = (GearParam*)appdata;

    ProUserCreateViewManual (g_ptr);

    ProTKGDUIViewNamesUpdate (g_ptr);
}

/*=============================================================*\
  Function: 	ProUserNewgearUI
  Purpose:	Initialize and launch the Gear Design dialog
\*=============================================================*/
int ProUserNewgearUI()
{
  ProError err;
  int ui_status;
  GearParam *g_ptr;
  ProMdl model;
  
  err = ProMdlCurrentGet(&model);
  if (err != PRO_TK_NO_ERROR)
    return (-1);
  
  g_ptr = (GearParam*)calloc(1, sizeof(GearParam));
  memset (g_ptr, '\0', sizeof (GearParam));
  g_ptr->model = (ProPart)model;
  g_ptr->current_step = PTK_GD_DATUM;
  
  ProUserAssignParamDef (g_ptr);

/*-----------------------------------------------------------------*\
    Collect information about created features
\*-----------------------------------------------------------------*/
  if (ProUserCheckFeatures(g_ptr)!=PRO_TK_NO_ERROR)
    {
      ProMessageDisplay(MSGFIL, "USER Error while check Gear Design");
      return (-1);
    }	

  err = ProUIDialogCreate (GD_UI_MAIN, GD_UI_MAIN);

  if (err != PRO_TK_NO_ERROR)
    return PRO_TK_GENERAL_ERROR;
  
  /* UI Initialization */

  err = ProUIDialogCloseActionSet (GD_UI_MAIN, 
				   (ProUIAction)ProTKGDUICloseAction, NULL);

  /* Close actions */
  err = ProUIPushbuttonActivateActionSet (GD_UI_MAIN, GD_UI_CLOSEBTN,
				       (ProUIAction)ProTKGDUICloseAction, NULL);
  
  err = ProUIPushbuttonActivateActionSet (GD_UI_MAIN, GD_UI_CLOSEBTN_M,
				       (ProUIAction)ProTKGDUICloseAction, NULL);

  /* Load actions */
  err = ProUIPushbuttonActivateActionSet (GD_UI_MAIN, GD_UI_LOADBTN_M,
					  (ProUIAction)ProTKGDUILoadParamsAction, g_ptr);


  err = ProUIPushbuttonActivateActionSet (GD_UI_MAIN, GD_UI_LOADBTN_RMB,
					  (ProUIAction)ProTKGDUILoadParamsAction, g_ptr);



  /* Toggle state action */

  err = ProUIRadiogroupSelectActionSet (GD_UI_MAIN, GD_UI_GEARTYPE_GROUP_M,
					(ProUIAction)ProTKGDUIToggleTypeAction, g_ptr);

  err = ProUIRadiogroupSelectActionSet (GD_UI_MAIN, GD_UI_GEARTYPE_GROUP_RMB,
					(ProUIAction)ProTKGDUIToggleTypeAction, g_ptr);


  /* Create action */
  err = ProUIPushbuttonActivateActionSet (GD_UI_MAIN, GD_UI_CREATEBTN,
				       (ProUIAction)ProTKGDUICreateAction, 
					  g_ptr);

  /* Checkbutton actions */
  err = ProUICheckbuttonActivateActionSet (GD_UI_MAIN, GD_UI_INCLUDE_KEYWAY,
					   (ProUIAction)ProTKGDUIIncludeKeywayAction, g_ptr);

  err = ProUICheckbuttonActivateActionSet (GD_UI_MAIN, GD_UI_INCLUDE_KEY,
					   (ProUIAction)ProTKGDUIIncludeKeyAction, g_ptr);

  err = ProUICheckbuttonActivateActionSet (GD_UI_MAIN, GD_UI_INCLUDE_BN,
					   (ProUIAction)ProTKGDUIIncludeBacknotchAction, g_ptr);

  /* Input actions */
  err = ProUIInputpanelInputActionSet (GD_UI_MAIN, GD_UI_GEARDISK_W_INPUT,
				       (ProUIAction)ProTKGDUIDiskInputAction,
				       g_ptr);

  err = ProUIInputpanelInputActionSet (GD_UI_MAIN, GD_UI_GEARDISK_D_INPUT,
				       (ProUIAction)ProTKGDUIDiskInputAction,
				       g_ptr);
  
  err = ProUIInputpanelInputActionSet (GD_UI_MAIN, GD_UI_HELIX_ANGLE,
				       (ProUIAction)ProTKGDUIDiskInputAction,
				       g_ptr);

  err = ProUIInputpanelInputActionSet (GD_UI_MAIN, GD_UI_GEARHOLE_D_INPUT,
				       (ProUIAction)ProTKGDUIHoleInputAction,
				       g_ptr);
				       

  err = ProUIInputpanelInputActionSet (GD_UI_MAIN, GD_UI_TOOTH_P1_INPUT,
				       (ProUIAction)ProTKGDUITeethInputAction,
				       g_ptr);

  err = ProUIInputpanelInputActionSet (GD_UI_MAIN, GD_UI_GEARHUB_D_INPUT,
				       (ProUIAction)ProTKGDUIHubInputAction,
				       g_ptr);

  err = ProUIInputpanelInputActionSet (GD_UI_MAIN, GD_UI_GEARHUB_T_INPUT,
				       (ProUIAction)ProTKGDUIHubInputAction,
				       g_ptr);

  err = ProUIInputpanelInputActionSet (GD_UI_MAIN, GD_UI_BP_D_INPUT,
				       (ProUIAction)ProTKGDUIBackplateInputAction,
				       g_ptr);

  err = ProUIInputpanelInputActionSet (GD_UI_MAIN, GD_UI_BP_T_INPUT,
				       (ProUIAction)ProTKGDUIBackplateInputAction,
				       g_ptr);

  err = ProUIInputpanelInputActionSet (GD_UI_MAIN, GD_UI_TOOTH_PRESSURE_ANGLE,
				       (ProUIAction)ProTKGDUITeethInputAction,
				       g_ptr);

  err = ProUIInputpanelInputActionSet (GD_UI_MAIN, GD_UI_TOOTH_INNER_SURF_INPUT,
				       (ProUIAction)ProTKGDUITeethInputAction,
				       g_ptr);

  err = ProUISpinboxUpdateActionSet (GD_UI_MAIN, GD_UI_N_TEETH_SPINBOX,
				     (ProUIAction)ProTKGDUITeethUpdateAction,
				     g_ptr);

  
  
    /* Update table */
  ProTKGDUIStatusTableInit (g_ptr);

  err = ProUITableSelectActionSet (GD_UI_MAIN, GD_UI_STATUS_TABLE,
				     (ProUIAction)ProTKGDUITableSelectAction,
				     g_ptr);

  ProTKGDUIDatumUIUpdate (g_ptr);
  ProTKGDUIDiskUIUpdate (g_ptr);
  ProTKGDUIHoleUIUpdate (g_ptr);
  ProTKGDUIHubUIUpdate (g_ptr);
  ProTKGDUIBackplateUIUpdate (g_ptr);
  ProTKGDUITeethUIUpdate (g_ptr);

  /* Tools actions */
  err = ProUIPushbuttonActivateActionSet (GD_UI_MAIN, GD_UI_TOOL_DELETE_M,
				     (ProUIAction)ProTKGDUIDeleteAction,
				     g_ptr);

  err = ProUIPushbuttonActivateActionSet (GD_UI_MAIN, GD_UI_TOOL_MODIFY_M,
				     (ProUIAction)ProTKGDUIModifyAction,
				     g_ptr);

  err = ProUIPushbuttonActivateActionSet (GD_UI_MAIN, GD_UI_TOOL_REGENERATE_M,
				     (ProUIAction)ProTKGDUIRegenerateAction,
				     g_ptr);

  err = ProUIPushbuttonActivateActionSet (GD_UI_MAIN, GD_UI_TOOL_MATERIAL_M,
				     (ProUIAction)ProTKGDUIMaterialAction,
				     g_ptr);

  ProTKGDUIViewNamesUpdate (g_ptr);

  err = ProUIRadiogroupSelectActionSet (GD_UI_MAIN, GD_UI_TOOL_VIEW_CHOICE_M,
				     (ProUIAction)ProTKGDUIViewSelectAction,
				     g_ptr);

  err = ProUIPushbuttonActivateActionSet (GD_UI_MAIN, 
					  GD_UI_TOOL_VIEW_DEFAULTCREATE_M,
					  (ProUIAction)ProTKGDUIDefaultViewCreateAction,
					  g_ptr);

  err = ProUIPushbuttonActivateActionSet (GD_UI_MAIN, GD_UI_TOOL_VIEW_STORE_M,
				     (ProUIAction)ProTKGDUIViewStoreAction,
				     g_ptr);

  /* Popup menu */
  err = ProUIDialogPopupmenuSet (GD_UI_MAIN, GD_UI_MENUPANE_RMB);


  err = ProUIDialogActivate (GD_UI_MAIN, &ui_status);
  
  if (err != PRO_TK_NO_ERROR)
    return PRO_TK_GENERAL_ERROR;

  err = ProUIDialogDestroy (GD_UI_MAIN);

  free (g_ptr);

  return PRO_TK_NO_ERROR;
}