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

#include <ProToolkit.h>
#include <ProFeature.h>
#include <ProSelbuffer.h>
#include <ProReference.h>
#include <ProCrvcollection.h>
#include <ProUtil.h>
#include <ProSmtFlangeWall.h>
#include <ProSheetmetal.h>
#include <ProMenuBar.h>
#include <ProPopupmenu.h>
#include <ProMdl.h>
#include <ProFeatType.h>

  
/*=====================================================================*\
FUNCTION: UserSmtFlgWallCreate
PURPOSE:  Create sheetmetal flange wall features.
\*=====================================================================*/
int UserSmtFlgWallCreate (ProCollection ref_edge_collection,
			    double bend_radius,
			    ProSection section) 
{
  ProError status;
  ProElement pro_e_feature_tree;
  ProElement pro_e_feature_type;
  ProElement pro_e_smt_wall_type;
  ProElement pro_e_std_feature_name;
  ProElement pro_e_smt_flange_type;
  ProElement pro_e_std_curve_collection_appl;
  ProElement pro_e_smt_flange_traj_crv_norm;
  ProElement pro_e_std_section;
  ProElement pro_e_sketcher;
  ProElement pro_e_smt_wall_sharps_to_bends;
  ProElement pro_e_smt_flange_sec_flip;
  ProElement pro_e_smt_flange_depth;
  ProElement pro_e_smt_flange_side_1_depth;
  ProElement pro_e_smt_flange_depth_type;
  ProElement pro_e_smt_flange_depth_offset;
  ProElement pro_e_smt_flange_side_2_depth;
  ProElement pro_e_smt_fillets;
  ProElement pro_e_smt_fillets_use_rad;
  ProElement pro_e_smt_fillets_side;
  ProElement pro_e_smt_fillets_value;
  ProElement pro_e_smt_wall_height;
  ProElement pro_e_smt_wall_height_type;
  ProElement pro_e_smt_wall_height_value;
  ProElement pro_e_smt_bend_relief;
  ProElement pro_e_smt_bend_relief_side1;
  ProElement pro_e_bend_relief_type;
  ProElement pro_e_bend_relief_width;
  ProElement pro_e_bend_relief_depth;
  ProElement pro_e_bend_relief_angle;
  ProElement pro_e_smt_bend_relief_side2;
  ProElement pro_e_smt_wall_thickness_flip;
  ProElement pro_e_smt_dev_len_calculation;
  ProElement pro_e_smt_dev_len_source;
  ProElement pro_e_smt_dev_len_y_factor;
  ProElement pro_e_smt_dev_len_y_factor_value;
  ProElement pro_e_smt_dev_len_y_factor_type;
  ProElement pro_e_smt_dev_len_bend_table;
  ProMdl model;
  ProModelitem model_item;
  ProFeatureCreateOptions *opts = 0;
  ProSelection model_sel;
  ProFeature feature;
  ProErrorlist errors;
  ProSelection feat_sel;

/*-----------------------------------------------------------------*\
Processing Element PRO_E_FEATURE_TREE
\*-----------------------------------------------------------------*/
  status = ProElementAlloc ( PRO_E_FEATURE_TREE, &pro_e_feature_tree ); 
  
/*-----------------------------------------------------------------*\
Processing Element PRO_E_FEATURE_TYPE
\*-----------------------------------------------------------------*/
  status = ProElementAlloc ( PRO_E_FEATURE_TYPE, &pro_e_feature_type );
  status = ProElementIntegerSet ( pro_e_feature_type, PRO_FEAT_WALL );
  status = ProElemtreeElementAdd ( pro_e_feature_tree, NULL, 
				   pro_e_feature_type );
  
/*-----------------------------------------------------------------*\
Processing Element PRO_E_SMT_WALL_TYPE
\*-----------------------------------------------------------------*/
  status = ProElementAlloc ( PRO_E_SMT_WALL_TYPE, &pro_e_smt_wall_type );
  status = ProElementIntegerSet ( pro_e_smt_wall_type, 
				  PRO_SMT_WALL_TYPE_FLANGE );
  status = ProElemtreeElementAdd ( pro_e_feature_tree, NULL, 
				   pro_e_smt_wall_type );
  
/*-----------------------------------------------------------------*\
Processing Element PRO_E_SMT_FLANGE_TYPE
\*-----------------------------------------------------------------*/
  status = ProElementAlloc ( PRO_E_SMT_FLANGE_TYPE, &pro_e_smt_flange_type );
  status = ProElementIntegerSet ( pro_e_smt_flange_type, 
				  PRO_FLANGE_WALL_TYPE_2D_SWEPT );
  status = ProElemtreeElementAdd ( pro_e_feature_tree, NULL, 
				   pro_e_smt_flange_type );
  
/*-----------------------------------------------------------------*\
Processing Element PRO_E_STD_CURVE_COLLECTION_APPL
\*-----------------------------------------------------------------*/
  status = ProElementAlloc ( PRO_E_STD_CURVE_COLLECTION_APPL, 
			     &pro_e_std_curve_collection_appl );
  status = ProElementCollectionSet( pro_e_std_curve_collection_appl, 
				    ref_edge_collection);
  status = ProElemtreeElementAdd ( pro_e_feature_tree, NULL, 
				   pro_e_std_curve_collection_appl );
  
/*-----------------------------------------------------------------*\
Processing Element PRO_E_SMT_FLANGE_TRAJ_CRV_NORM
\*-----------------------------------------------------------------*/
  status = ProElementAlloc ( PRO_E_SMT_FLANGE_TRAJ_CRV_NORM, 
			     &pro_e_smt_flange_traj_crv_norm );
  status = ProElementIntegerSet ( pro_e_smt_flange_traj_crv_norm, 
				  PRO_FLANGE_TRAJ_NORM_NO_FLIP);
  status = ProElemtreeElementAdd ( pro_e_feature_tree, NULL, 
				   pro_e_smt_flange_traj_crv_norm );
  
/*-----------------------------------------------------------------*\
Processing Element PRO_E_STD_SECTION
\*-----------------------------------------------------------------*/
  status = ProElementAlloc ( PRO_E_STD_SECTION, &pro_e_std_section );
  status = ProElemtreeElementAdd ( pro_e_feature_tree, NULL, 
				   pro_e_std_section  );

/*-----------------------------------------------------------------*\
Processing Element PRO_E_SKETCHER
\*-----------------------------------------------------------------*/
  status = ProElementAlloc ( PRO_E_SKETCHER, &pro_e_sketcher );
  status = ProElementSpecialvalueSet ( pro_e_sketcher, section );
  status = ProElemtreeElementAdd ( pro_e_std_section, NULL, 
				   pro_e_sketcher );
  
/*-----------------------------------------------------------------*\
Processing Element PRO_E_SMT_WALL_SHARPS_TO_BENDS
\*-----------------------------------------------------------------*/
  status = ProElementAlloc ( PRO_E_SMT_WALL_SHARPS_TO_BENDS, 
			     &pro_e_smt_wall_sharps_to_bends );
  status = ProElementIntegerSet ( pro_e_smt_wall_sharps_to_bends, 
				  PRO_B_TRUE );
  status = ProElemtreeElementAdd ( pro_e_feature_tree, NULL, 
				   pro_e_smt_wall_sharps_to_bends );
  
/*-----------------------------------------------------------------*\
Processing Element PRO_E_SMT_FLANGE_SEC_FLIP
\*-----------------------------------------------------------------*/
  status = ProElementAlloc ( PRO_E_SMT_FLANGE_SEC_FLIP, 
			     &pro_e_smt_flange_sec_flip );
  status = ProElementIntegerSet ( pro_e_smt_flange_sec_flip, 
				  PRO_B_FALSE );
  status = ProElemtreeElementAdd ( pro_e_feature_tree, NULL, 
				   pro_e_smt_flange_sec_flip );

/*-----------------------------------------------------------------*\
Processing Element PRO_E_SMT_FLANGE_DEPTH
\*-----------------------------------------------------------------*/
  status = ProElementAlloc ( PRO_E_SMT_FLANGE_DEPTH, 
			     &pro_e_smt_flange_depth );
  status = ProElemtreeElementAdd ( pro_e_feature_tree, NULL, 
				   pro_e_smt_flange_depth  );
  
/*-----------------------------------------------------------------*\
Processing Element PRO_E_SMT_FLANGE_SIDE_1_DEPTH
\*-----------------------------------------------------------------*/
  status = ProElementAlloc ( PRO_E_SMT_FLANGE_SIDE_1_DEPTH, 
			     &pro_e_smt_flange_side_1_depth );
 status = ProElemtreeElementAdd ( pro_e_smt_flange_depth, NULL, 
				  pro_e_smt_flange_side_1_depth  );

/*-----------------------------------------------------------------*\
Processing Element PRO_E_SMT_FLANGE_DEPTH_TYPE
\*-----------------------------------------------------------------*/
 status = ProElementAlloc ( PRO_E_SMT_FLANGE_DEPTH_TYPE, 
			    &pro_e_smt_flange_depth_type );
 status = ProElementIntegerSet ( pro_e_smt_flange_depth_type, 
				 PRO_WALL_LEN_TYPE_TO_END);
 status = ProElemtreeElementAdd ( pro_e_smt_flange_side_1_depth, NULL, 
				  pro_e_smt_flange_depth_type );

/*-----------------------------------------------------------------*\
Processing Element PRO_E_SMT_FLANGE_SIDE_2_DEPTH
\*-----------------------------------------------------------------*/
 status = ProElementAlloc ( PRO_E_SMT_FLANGE_SIDE_2_DEPTH, 
			    &pro_e_smt_flange_side_2_depth );
 status = ProElemtreeElementAdd ( pro_e_smt_flange_depth, NULL, 
				  pro_e_smt_flange_side_2_depth  );
 
/*-----------------------------------------------------------------*\
Processing Element PRO_E_SMT_FLANGE_DEPTH_TYPE
\*-----------------------------------------------------------------*/
 status = ProElementAlloc ( PRO_E_SMT_FLANGE_DEPTH_TYPE, 
			    &pro_e_smt_flange_depth_type );
 status = ProElementIntegerSet ( pro_e_smt_flange_depth_type, 
				 PRO_WALL_LEN_TYPE_TO_END );
 status = ProElemtreeElementAdd ( pro_e_smt_flange_side_2_depth, NULL, 
				  pro_e_smt_flange_depth_type );
 
/*-----------------------------------------------------------------*\
Processing Element PRO_E_SMT_FILLETS
\*-----------------------------------------------------------------*/
 status = ProElementAlloc ( PRO_E_SMT_FILLETS, &pro_e_smt_fillets );
 status = ProElemtreeElementAdd ( pro_e_feature_tree, NULL, 
				  pro_e_smt_fillets  );
 
/*-----------------------------------------------------------------*\
Processing Element PRO_E_SMT_FILLETS_USE_RAD
\*-----------------------------------------------------------------*/
 status = ProElementAlloc ( PRO_E_SMT_FILLETS_USE_RAD, 
			    &pro_e_smt_fillets_use_rad );
 status = ProElementIntegerSet ( pro_e_smt_fillets_use_rad, PRO_B_TRUE );
 status = ProElemtreeElementAdd ( pro_e_smt_fillets, NULL, 
				  pro_e_smt_fillets_use_rad );

/*-----------------------------------------------------------------*\
Processing Element PRO_E_SMT_FILLETS_SIDE
\*-----------------------------------------------------------------*/
 status = ProElementAlloc ( PRO_E_SMT_FILLETS_SIDE, 
			    &pro_e_smt_fillets_side );
 status = ProElementIntegerSet ( pro_e_smt_fillets_side, 
				 PRO_BEND_RAD_INSIDE );
 status = ProElemtreeElementAdd ( pro_e_smt_fillets, NULL, 
				  pro_e_smt_fillets_side );

/*-----------------------------------------------------------------*\
Processing Element PRO_E_SMT_FILLETS_VALUE
\*-----------------------------------------------------------------*/
 status = ProElementAlloc ( PRO_E_SMT_FILLETS_VALUE, 
			    &pro_e_smt_fillets_value );
 status = ProElementDoubleSet (  pro_e_smt_fillets_value, bend_radius );
 status = ProElemtreeElementAdd ( pro_e_smt_fillets, NULL, 
				  pro_e_smt_fillets_value );

/*-----------------------------------------------------------------*\
Processing Element PRO_E_SMT_WALL_HEIGHT
\*-----------------------------------------------------------------*/
 status = ProElementAlloc ( PRO_E_SMT_WALL_HEIGHT, &pro_e_smt_wall_height );
 status = ProElemtreeElementAdd ( pro_e_feature_tree, NULL, 
				  pro_e_smt_wall_height  );

/*-----------------------------------------------------------------*\
Processing Element PRO_E_SMT_WALL_HEIGHT_TYPE
\*-----------------------------------------------------------------*/
 status = ProElementAlloc ( PRO_E_SMT_WALL_HEIGHT_TYPE, 
			    &pro_e_smt_wall_height_type );
 status = ProElementIntegerSet ( pro_e_smt_wall_height_type, 
				 PRO_SMT_WALL_HEIGHT_NONE);
 status = ProElemtreeElementAdd ( pro_e_smt_wall_height, NULL, 
				  pro_e_smt_wall_height_type );
 
/*-----------------------------------------------------------------*\
Processing Element PRO_E_SMT_BEND_RELIEF
\*-----------------------------------------------------------------*/
 status = ProElementAlloc ( PRO_E_SMT_BEND_RELIEF, &pro_e_smt_bend_relief );
 status = ProElemtreeElementAdd ( pro_e_feature_tree, NULL, 
				  pro_e_smt_bend_relief  );
 
/*-----------------------------------------------------------------*\
Processing Element PRO_E_SMT_BEND_RELIEF_SIDE1
\*-----------------------------------------------------------------*/
 status = ProElementAlloc ( PRO_E_SMT_BEND_RELIEF_SIDE1, 
			    &pro_e_smt_bend_relief_side1 );
 status = ProElemtreeElementAdd ( pro_e_smt_bend_relief, NULL, 
				  pro_e_smt_bend_relief_side1  );
 
/*-----------------------------------------------------------------*\
Processing Element PRO_E_BEND_RELIEF_TYPE
\*-----------------------------------------------------------------*/
 status = ProElementAlloc ( PRO_E_BEND_RELIEF_TYPE, &pro_e_bend_relief_type );
 status = ProElementIntegerSet ( pro_e_bend_relief_type, PRO_BEND_RLF_RIP );
 status = ProElemtreeElementAdd ( pro_e_smt_bend_relief_side1, NULL, 
				  pro_e_bend_relief_type );

/*-----------------------------------------------------------------*\
Processing Element PRO_E_SMT_BEND_RELIEF_SIDE2
\*-----------------------------------------------------------------*/
 status = ProElementAlloc ( PRO_E_SMT_BEND_RELIEF_SIDE2, 
			    &pro_e_smt_bend_relief_side2 );
 status = ProElemtreeElementAdd ( pro_e_smt_bend_relief, NULL, 
				  pro_e_smt_bend_relief_side2  );
 
/*-----------------------------------------------------------------*\
Processing Element PRO_E_BEND_RELIEF_TYPE
\*-----------------------------------------------------------------*/
 status = ProElementAlloc ( PRO_E_BEND_RELIEF_TYPE, 
			    &pro_e_bend_relief_type );
 status = ProElementIntegerSet ( pro_e_bend_relief_type, PRO_BEND_RLF_RIP );
 status = ProElemtreeElementAdd ( pro_e_smt_bend_relief_side2, NULL, 
				  pro_e_bend_relief_type );
 
/*-----------------------------------------------------------------*\
Processing Element PRO_E_SMT_WALL_THICKNESS_FLIP
\*-----------------------------------------------------------------*/
 status = ProElementAlloc ( PRO_E_SMT_WALL_THICKNESS_FLIP, 
			    &pro_e_smt_wall_thickness_flip );
 status = ProElementIntegerSet ( pro_e_smt_wall_thickness_flip, 
				 PRO_B_FALSE );
 status = ProElemtreeElementAdd ( pro_e_feature_tree, NULL, 
				  pro_e_smt_wall_thickness_flip );

/*-----------------------------------------------------------------*\
Processing Element PRO_E_SMT_DEV_LEN_CALCULATION
\*-----------------------------------------------------------------*/
 status = ProElementAlloc ( PRO_E_SMT_DEV_LEN_CALCULATION, 
			    &pro_e_smt_dev_len_calculation );
 status = ProElemtreeElementAdd ( pro_e_feature_tree, NULL, 
				  pro_e_smt_dev_len_calculation  );
 
/*-----------------------------------------------------------------*\
Processing Element PRO_E_SMT_DEV_LEN_SOURCE
\*-----------------------------------------------------------------*/
 status = ProElementAlloc ( PRO_E_SMT_DEV_LEN_SOURCE, 
			    &pro_e_smt_dev_len_source );
 status = ProElementIntegerSet ( pro_e_smt_dev_len_source, 
				 PRO_DVL_SRC_FEAT_YF_ONLY );
 status = ProElemtreeElementAdd ( pro_e_smt_dev_len_calculation, NULL, 
				  pro_e_smt_dev_len_source );
 
/*-----------------------------------------------------------------*\
Processing Element PRO_E_SMT_DEV_LEN_Y_FACTOR
\*-----------------------------------------------------------------*/
 status = ProElementAlloc ( PRO_E_SMT_DEV_LEN_Y_FACTOR, 
			    &pro_e_smt_dev_len_y_factor );
 status = ProElemtreeElementAdd ( pro_e_smt_dev_len_calculation, NULL, 
				  pro_e_smt_dev_len_y_factor  );
 
/*-----------------------------------------------------------------*\
Processing Element PRO_E_SMT_DEV_LEN_Y_FACTOR_VALUE
\*-----------------------------------------------------------------*/
 status = ProElementAlloc ( PRO_E_SMT_DEV_LEN_Y_FACTOR_VALUE, 
			    &pro_e_smt_dev_len_y_factor_value );
 status = ProElementDoubleSet (  pro_e_smt_dev_len_y_factor_value, 
				 0.320000 );
 status = ProElemtreeElementAdd ( pro_e_smt_dev_len_y_factor, NULL, 
				  pro_e_smt_dev_len_y_factor_value );

/*-----------------------------------------------------------------*\
Create the feature using the element tree
\*-----------------------------------------------------------------*/
 status = ProMdlCurrentGet (&model);
 status = ProMdlToModelitem( model, &model_item );
 status = ProSelectionAlloc (NULL, &model_item, &model_sel);


  status = ProArrayAlloc(1,sizeof(ProFeatureCreateOptions),
    1, (ProArray*)&opts);

  opts[0]= PRO_FEAT_CR_NO_OPTS;

 status = ProFeatureWithoptionsCreate (model_sel, pro_e_feature_tree,
    opts, PRO_REGEN_NO_FLAGS, &feature, &errors);

  status = ProArrayFree((ProArray*)&opts);
 if (status == PRO_TK_NO_ERROR)
 {
	 ProSelectionAlloc (NULL, &feature, &feat_sel);
	 ProSelbufferClear ();
	 ProSelbufferSelectionAdd (feat_sel);
	 ProSelectionFree (&feat_sel);
 }

 return (PRO_TK_NO_ERROR);
}


/*=====================================================================*\
FUNCTION: UserSmtFlgWallCreate_OA_CreateISec
PURPOSE:  Create sheetmetal flange wall features using Object/Action 
          selection and Pro/E's predefined I-section.
\*=====================================================================*/
int UserSmtFlgWallCreate_OA_CreateISec ()
{
  ProError status;
  ProSelection* sel;
  ProCollection collection;
  ProCrvcollinstr instr;
  ProReference reference;
  ProPart part;
  ProDimension thickness_dim;
  double thickness;
  ProSection i_wall_sec;
  ProPath w_mdlpath;
  ProCharPath mdlpath, secpath;
  char* prodir;
  
/*-----------------------------------------------------------------*\
Extract the current selected edge or edge chain as the wall attachment
\*-----------------------------------------------------------------*/
  status = ProSelbufferSelectionsGet (&sel);

  status = ProSelectionCollectionGet (sel[0], &collection);

/*-----------------------------------------------------------------*\
If a single edge is selected, allocate the chain as a tangent chain
\*-----------------------------------------------------------------*/
  if (status != PRO_TK_NO_ERROR)
    {
      status = ProCrvcollectionAlloc ( &collection );
      status = ProCrvcollinstrAlloc ( PRO_CURVCOLL_TAN_INSTR, &instr );
      status = ProSelectionToReference ( sel[0], &reference );
      status = ProCrvcollinstrReferenceAdd ( instr, reference );
      status = ProCrvcollectionInstructionAdd ( collection, instr );

      ProReferenceFree (reference);
    }
 
/*-----------------------------------------------------------------*\
Extract the wall thickness to use for the bend radius
\*-----------------------------------------------------------------*/ 
  status = ProMdlCurrentGet ((ProMdl*)&part);
  status = ProSmtPartThicknessGet(part, &thickness_dim);
  status = ProDimensionValueGet (&thickness_dim, &thickness);

/*-----------------------------------------------------------------*\
Retrieve the Pro/ENGINEER default section for "I" walls
\*-----------------------------------------------------------------*/ 
  prodir = getenv ("PRO_DIRECTORY");
  if (prodir == NULL)
	return PRO_TK_INVALID_DIR;

  ProTKSprintf (secpath, "%s/text/smt/", prodir);
  ProTKSprintf (mdlpath, "%si_wall.sec", secpath);
  ProStringToWstring (w_mdlpath, mdlpath);
  status = ProMdlFiletypeLoad  (w_mdlpath,  PRO_MDLFILE_UNUSED, PRO_B_FALSE, 
					   (ProMdl*)&i_wall_sec);

/*-----------------------------------------------------------------*\
Create the feature with the extracted information
\*-----------------------------------------------------------------*/
  UserSmtFlgWallCreate (collection, thickness, i_wall_sec);

  ProCollectionFree (&collection);

  return (PRO_TK_NO_ERROR);
}

/*=====================================================================*\
FUNCTION: UserSmtFlgWallCreate_OA_CreateUserDefSec
PURPOSE:  Create sheetmetal flange wall features using Object/Action 
          selection and a user-selection 2D section.
\*=====================================================================*/
int UserSmtFlgWallCreate_OA_CreateUserDefSec ()
{
  ProError status;
  ProSelection* sel;
  ProCollection collection;
  ProCrvcollinstr instr;
  ProReference reference;
  ProPart part;
  ProDimension thickness_dim;
  double thickness;
  ProSection userdef_sec;
  ProPath w_mdlpath;
  ProCharPath mdlpath, secpath;
  char* prodir;
  
/*-----------------------------------------------------------------*\
Prompt the user to select a section for the flange wall
\*-----------------------------------------------------------------*/
  status = UserSectionOpen (&userdef_sec);
  
  if (status != PRO_TK_NO_ERROR)
    return (status);

/*-----------------------------------------------------------------*\
Extract the current selected edge or edge chain as the wall attachment
\*-----------------------------------------------------------------*/
  status = ProSelbufferSelectionsGet (&sel);

  status = ProSelectionCollectionGet (sel[0], &collection);

  if (status != PRO_TK_NO_ERROR)
    {
      status = ProCrvcollectionAlloc ( &collection );
      status = ProCrvcollinstrAlloc ( PRO_CURVCOLL_TAN_INSTR, &instr );
      status = ProSelectionToReference ( sel[0], &reference );
      status = ProCrvcollinstrReferenceAdd ( instr, reference );
      status = ProCrvcollectionInstructionAdd ( collection, instr );

      ProReferenceFree (reference);
    }
  
/*-----------------------------------------------------------------*\
Extract the wall thickness to use for the bend radius
\*-----------------------------------------------------------------*/ 
  status = ProMdlCurrentGet ((ProMdl*)&part);
  status = ProSmtPartThicknessGet(part, &thickness_dim);
  status = ProDimensionValueGet (&thickness_dim, &thickness);

/*-----------------------------------------------------------------*\
Create the feature with the extracted information
\*-----------------------------------------------------------------*/
  UserSmtFlgWallCreate (collection, thickness, userdef_sec);

  ProMdlErase (userdef_sec);
 
  ProCollectionFree (&collection);

  return (PRO_TK_NO_ERROR);
}

#define OA 1  /* Standard OA in the menu system, typically gray out 
		 the button when not usable*/
#define PM 2 /* OA in a popup menu, typically remove the button when 
	         not usable */

/*=====================================================================*\
FUNCTION: UserSmtFlgWallCreate_TestLow
PURPOSE:  Access function for the button for smt flange wall feature creation
\*=====================================================================*/
static uiCmdAccessState UserSmtFlgWallCreate_TestLow (ProSelection* sels, int mode)
{
  uiCmdAccessState access_result;
  ProBoolean should_free = PRO_B_FALSE;
  ProError status;
  ProMdl mdl;
  ProMdlType type;
  ProMdlsubtype subtype;
  int size, refs_size;
  ProCollection collection;
  ProCollectionType coll_type;
  ProCrvcollinstr* instrs;
  int i, j;
  ProCrvcollinstrType instr_type;
  ProReference* refs;
  ProModelitem item;
  ProBoolean invalid_ref;

/*-----------------------------------------------------------------*\
  Set the default return if the button is unusable.
\*-----------------------------------------------------------------*/  
  if (mode == OA)
    access_result = ACCESS_UNAVAILABLE;
  else 
    access_result = ACCESS_REMOVE;

  status = ProMdlCurrentGet (&mdl);

  if (status != PRO_TK_NO_ERROR)
    return (access_result);

  status = ProMdlTypeGet (mdl, &type);

  status = ProMdlSubtypeGet (mdl, &subtype);
  
  if (type != PRO_MDL_PART || subtype != PROMDLSTYPE_PART_SHEETMETAL)
    return (access_result);

/*-----------------------------------------------------------------*\
  If called without selections, extract the current selections from
  the buffer.
\*-----------------------------------------------------------------*/ 
  if (sels == NULL)
    {   
      status = ProSelbufferSelectionsGet (&sels);
      
      if (status != PRO_TK_NO_ERROR)
	return access_result;

      if (sels == NULL)
	return access_result;

      should_free = PRO_B_TRUE;
    }

/*-----------------------------------------------------------------*\
  This command allows only one selection.
\*-----------------------------------------------------------------*/   
  status = ProArraySizeGet (sels, &size);
  
  if (status != PRO_TK_NO_ERROR)
    return access_result;

  if (size == 1)
    {
/*-----------------------------------------------------------------*\
Extract the crv collection selected by the user
\*-----------------------------------------------------------------*/    
      status = ProSelectionCollectionGet (sels [0], &collection);
      ProTKPrintf ("Status of ProSelectionCollectionGet: %d\n\n", status);

      if (status == PRO_TK_NO_ERROR)
	{
	  status = ProCollectionTypeGet (collection, &coll_type);
	  
	  if (coll_type == PRO_COLLECTION_CRVCOLL)
	    {
/*-----------------------------------------------------------------*\
Check the instructions assigned to the curve collection.
Exclude this collection if the instruction contains a type not
supported for this feature
\*-----------------------------------------------------------------*/
	      status = ProCrvcollectionInstructionsGet (collection, &instrs);

	      status = ProArraySizeGet (instrs, &size);

	      for (i = 0; i < size; i ++)
		{
		  status = ProCrvcollinstrTypeGet (instrs[i], &instr_type);
		  
		  if (instr_type != PRO_CURVCOLL_ADD_ONE_INSTR &&
		      instr_type != PRO_CURVCOLL_TAN_INSTR &&
		      instr_type != PRO_CURVCOLL_TRIM_INSTR &&
		      instr_type != PRO_CURVCOLL_START_PNT_INSTR &&
		      instr_type != PRO_CURVCOLL_ADD_TANGENT_INSTR)
		    break;

/*-----------------------------------------------------------------*\
Check the references to ensure that the reference is an edge 
which borders a sheetmetal face.
\*-----------------------------------------------------------------*/
		  status = ProCrvcollinstrReferencesGet (instrs[i], &refs);
		  
		  status = ProArraySizeGet (refs, &refs_size);

		  invalid_ref = PRO_B_FALSE;
		  for (j = 0; j < refs_size; j ++)
		    {
		      ProReferenceTypeGet (refs[j], &item.type);
		      
		      if (item.type != PRO_EDGE)
			break;
		      
		      ProReferenceOwnerGet (refs[j], &item.owner);
		      ProReferenceIdGet (refs[j], &item.id);
		      
		      ProReferenceFree (refs[j]);
		      
		      if (!UserEdgeIsSmtFaceEdge (&item))
			invalid_ref = PRO_B_TRUE;
		    }
		  ProReferencearrayFree (refs);

		  if (invalid_ref)
		    break;

/*-----------------------------------------------------------------*\
If all instructions and references passed, the button should be active.
\*-----------------------------------------------------------------*/
		  if (i == size -1)
		    access_result = ACCESS_AVAILABLE;
		}
	      ProCrvcollinstrArrayFree (instrs);
	    }
	  ProCollectionFree (&collection);
	}
      else
	{
	  status = ProSelectionModelitemGet (sels [0], &item);

/*-----------------------------------------------------------------*\
  If the selected type is a single edge, it must border a smt face surface.
\*-----------------------------------------------------------------*/   
	  if (item.type == PRO_EDGE)
	    {
	      if (UserEdgeIsSmtFaceEdge (&item))
		access_result = ACCESS_AVAILABLE; 
	    }
	}
    }

  if (should_free)
    ProSelectionarrayFree (sels);
  
  return access_result;
}


/*=====================================================================*\
FUNCTION: UserSmtFlgWallCreate_TestMdlTree
PURPOSE:  Access function for the model tree popup menu button.	
\*=====================================================================*/
uiCmdAccessState UserSmtFlgWallCreate_TestMdlTree (uiCmdAccessMode mode)
{ 
  return UserSmtFlgWallCreate_TestLow (NULL, PM);
}

/*=====================================================================*\
FUNCTION: UserSmtFlgWallCreate_TestPM
PURPOSE:  Access function for the graphics window popup menu button.	
\*=====================================================================*/
uiCmdAccessState UserSmtFlgWallCreate_TestPM (uiCmdCmdId id,
				      ProAppData data,
				      ProSelection* sels)
{ 
  return UserSmtFlgWallCreate_TestLow (sels, PM);
}