/*
Copyright (c) 2024 PTC Inc. and/or Its Subsidiary Companies. All Rights Reserved.
*/
#include <ProToolkit.h>
#include <ProAnnotationFeat.h>
#include <ProAnnotationElem.h>
#include <ProMenuBar.h>
#include <ProPopupmenu.h>
#include <ProSelbuffer.h>
#include <ProSurface.h>
#include <ProGtol.h>
#include <ProUIMessage.h>
#include <ProParameter.h>
#include <ProMdl.h>
#include <PTAFExamples.h>
#include <ProTKRunTime.h>
#include <PTApplsUnicodeUtils.h>
/*====================================================================*\
FUNCTION : PTTestAccessInfoMfgTemplate()
PURPOSE : Enable/Disable access to the manufacturing template info button
\*====================================================================*/
uiCmdAccessState PTTestAccessInfoMfgTemplate (uiCmdAccessMode access_mode)
{
ProMdl mdl;
ProMdlType type;
status = ProMdlCurrentGet (&mdl);
PT_TEST_LOG_SUCC ("ProMdlCurrentGet()");
if (status != PRO_TK_NO_ERROR) return (ACCESS_UNAVAILABLE);
status = ProMdlTypeGet (mdl, &type);
PT_TEST_LOG_SUCC ("ProMdlTypeGet()");
if (type != PRO_MDL_PART && type != PRO_MDL_ASSEMBLY)
return ACCESS_INVISIBLE;
return ACCESS_AVAILABLE;
}
#define MSGFIL L"pt_mfgtemplatebom.txt"
int PTANCPPParamsList();
int PTMfgTemplateAEWriteBOM ();
#define MFG_TEMPLATE_NAME L"MFG_AE_TEMPLATE_NAME"
typedef struct
{
ProLine template_type;
ProVector orientation;
ProName orientation_label;
ProBoolean is_completed; /* runtime flag - indicates we processed this AE
into the BOM already */
} PTMfgTemplateOrientationData;
typedef struct
{
ProAnnotationElem ae;
ProAnnotationType type;
int feat_id;
void* app_data;
} PTAEInfo;
typedef ProError (*PTAEAppDataCollectionFunction) (ProAnnotationElem* ae,
void** app_data);
typedef struct
{
PTAEAppDataCollectionFunction app_collection_function;
PTAEInfo* collected_aes;
} PTAECollectionData;
/*====================================================================*\
FUNCTION : PTMfgTemplateAEInfoCollect()
PURPOSE : Collect information about the mfg template AE
\*====================================================================*/
ProError PTMfgTemplateAEInfoCollect (ProAnnotationElem* ae,
void** app_data)
{
PTMfgTemplateOrientationData* data;
ProParameter param;
ProParamvalue pvalue;
data = (PTMfgTemplateOrientationData*) calloc (1,
sizeof (PTMfgTemplateOrientationData));
/*---------------------------------------------------------------------*\
Extract the value of the template name parameter
\*---------------------------------------------------------------------*/
status = ProParameterInit (ae, MFG_TEMPLATE_NAME, ¶m);
PT_TEST_LOG_SUCC ("ProParameterInit()");
status = ProParameterValueWithUnitsGet(¶m, &pvalue, NULL);
PT_TEST_LOG_SUCC ("ProParameterValueWithUnitsGet()");
ProWstringCopy (pvalue.value.s_val, data->template_type, PRO_VALUE_UNUSED);
/*---------------------------------------------------------------------*\
Not implemented; for future use
\*---------------------------------------------------------------------*/
data->orientation [0] = 0.0;
data->orientation [1] = 0.0;
data->orientation [2] = 0.0;
data->orientation_label [0] = (wchar_t)0;
data->is_completed = PRO_B_FALSE;
*app_data = data;
return PRO_TK_NO_ERROR;
}
/*====================================================================*\
FUNCTION : PTAEIsMfgTemplate()
PURPOSE : Identifies if the AE is a manufacturing template AE
\*====================================================================*/
ProError PTAEIsMfgTemplate (ProAnnotationElem* ae, ProAppData data)
{
ProAnnotationType type;
ProParameter param;
/*---------------------------------------------------------------------*\
Check the annotation element type
\*---------------------------------------------------------------------*/
status = ProAnnotationelemTypeGet (ae, &type);
PT_TEST_LOG_SUCC ("ProAnnotationelemTypeGet()");
if (type != PRO_ANNOT_TYPE_CUSTOM)
return PRO_TK_CONTINUE;
/*---------------------------------------------------------------------*\
Check for the mfg template parameter
\*---------------------------------------------------------------------*/
status = ProParameterInit (ae, MFG_TEMPLATE_NAME, ¶m);
PT_TEST_LOG ("ProParameterInit()", status,
status != PRO_TK_NO_ERROR && status != PRO_TK_E_NOT_FOUND);
if (status != PRO_TK_NO_ERROR)
return PRO_TK_CONTINUE;
return PRO_TK_NO_ERROR;
}
/*====================================================================*\
FUNCTION : PTAEInfoCollect()
PURPOSE : Collect information on annotation elements
\*====================================================================*/
ProError PTAEInfoCollect (ProAnnotationElem* ae, ProError status,
ProAppData data)
{
PTAECollectionData* ae_data = (PTAECollectionData*) data;
PTAEInfo info;
ProFeature feat;
/*---------------------------------------------------------------------*\
Collect basic AE information: owner, id, feature that owns it
\*---------------------------------------------------------------------*/
info.ae.owner = ae->owner;
info.ae.id = ae->id;
info.ae.type = ae->type;
status = ProAnnotationelemTypeGet (ae, &info.type);
PT_TEST_LOG_SUCC ("ProAnnotationelemTypeGet()");
status = ProAnnotationelemFeatureGet (ae, &feat);
PT_TEST_LOG_SUCC ("ProAnnotationelemFeatureGet()");
info.feat_id = feat.id;
/*---------------------------------------------------------------------*\
Use the stored callback function to collect specific needed data
\*---------------------------------------------------------------------*/
if (ae_data->app_collection_function != NULL)
(*ae_data->app_collection_function) (ae, (void**) &info.app_data);
status = ProArrayObjectAdd ((ProArray*)&ae_data->collected_aes,
-1, 1, &info);
PT_TEST_LOG_SUCC ("ProArrayObjectAdd()");
return PRO_TK_NO_ERROR;
}
/*====================================================================*\
FUNCTION : PTMfgTemplateAEPrint()
PURPOSE : Print the properties of the mfg template AE (JavaScript)
\*====================================================================*/
ProError PTMfgTemplateAEPrint (FILE* fp, int parent, int node, PTAEInfo* info)
{
ProFeature feature;
ProName ae_name, af_name;
ProMdlName owner_name;
ProCharName c_ae_name, c_af_name;
char c_owner_name[PRO_MDLNAME_SIZE];
char* owner_type;
ProMdlType type;
/*---------------------------------------------------------------------*\
Extract needed info from the AE
\*---------------------------------------------------------------------*/
ProModelitemNameGet (&info->ae, ae_name);
ProWstringToString (c_ae_name, ae_name);
feature.owner = info->ae.owner;
feature.type = PRO_FEATURE;
feature.id = info->feat_id;
status = ProModelitemNameGet (&feature, af_name);
PT_TEST_LOG_SUCC ("ProModelitemNameGet()");
ProWstringToString (c_af_name, af_name);
if (status != PRO_TK_NO_ERROR)
ProTKSprintf (c_af_name, "with id %d", feature.id);
status = ProMdlMdlnameGet (info->ae.owner, owner_name);
ProWstringToString (c_owner_name, owner_name);
status = ProMdlTypeGet (info->ae.owner, &type);
if (type == PRO_MDL_PART)
owner_type = "PRT";
else
owner_type = "ASM";
/*---------------------------------------------------------------------*\
Print the JavaScript tree node.
First half includes the node level, parent, and label
Second half produces proep: URL to highlight the AE
\*---------------------------------------------------------------------*/
ProTKFprintf (fp, "d.add(%d,%d,'Annotation element %s (belongs to feature %s)',",
node, parent, c_ae_name, c_af_name);
ProTKFprintf (fp, "'proep://local_proesession?oid=%s.%s&item=annotation_element&id=%d&action=highlight');\n", c_owner_name, owner_type, info->ae.id);
return PRO_TK_NO_ERROR;
}
#define MFGINFOFILENAME "mfgtemplateinfo.html"
/*====================================================================*\
FUNCTION : PTMFGTemplateBOMHTMLWrite()
PURPOSE : Print the mfg template BOM to the HTML file
\*====================================================================*/
ProError PTMFGTemplateBOMHTMLWrite (ProMdl mdl, PTAECollectionData data)
{
ProMdlName name;
char c_name[PRO_MDLNAME_SIZE];
ProMdlType type;
char* type_str;
FILE* fp;
int size;
int index;
int node_counter = 1;
int parent_node = 0;
/*---------------------------------------------------------------------*\
Open and print the HTML introductory lines
\*---------------------------------------------------------------------*/
fp = PTApplsUnicodeFopen (MFGINFOFILENAME, "w");
ProTKFprintf (fp, "<html>\n");
ProTKFprintf (fp, "<head>\n");
ProTKFprintf (fp, "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" /=\"\">\n");
ProTKFprintf (fp, "<title>Manufaturing template info</title>\n");
ProTKFprintf (fp, "<link rel=\"StyleSheet\" href=\"dtree.css\" type=\"text/css\"/>\n");
ProTKFprintf (fp, "<script type=\"text/javascript\" src=\"dtree.js\"></script>\n");
ProTKFprintf (fp, "</head>\n");
ProTKFprintf (fp, "<body>\n");
/*---------------------------------------------------------------------*\
Print the title of the page using the model name & type
\*---------------------------------------------------------------------*/
status = ProMdlMdlnameGet (mdl, name);
PT_TEST_LOG_SUCC ("ProMdlMdlnameGet()");
ProWstringToString (c_name, name);
status = ProMdlTypeGet (mdl, &type);
PT_TEST_LOG_SUCC ("ProMdlTypeGet()");
if (type == PRO_MDL_PART)
type_str = "Part";
else
type_str = "Assembly";
ProTKFprintf (fp, "<h2>Manufacturing template information for %s %s</h2>\n", type_str, c_name);
/*---------------------------------------------------------------------*\
Print the JavaScript tree initialization code
\*---------------------------------------------------------------------*/
ProTKFprintf (fp, "<div class=\"dtree\">\n");
ProTKFprintf (fp, "<script type=\"text/javascript\">\n");
ProTKFprintf (fp, "<!--\n");
ProTKFprintf (fp, "d = new dTree('d');\n");
ProTKFprintf (fp, "d.config.useIcons = false;\n");
ProTKFprintf (fp, "d.config.useCookies = false;\n");
ProTKFprintf (fp, "d.config.useSelection = false;\n");
ProTKFprintf (fp, "d.add(0,-1,'');\n");
/*---------------------------------------------------------------------*\
For each AE, extract the MFG template data
\*---------------------------------------------------------------------*/
status = ProArraySizeGet (data.collected_aes, &size);
PT_TEST_LOG_SUCC ("ProArraySizeGet()");
for (index = 0; index < size; index ++)
{
PTMfgTemplateOrientationData* mfg_data;
ProCharPath template_name;
int j, n_instances;
mfg_data = (PTMfgTemplateOrientationData*)
data.collected_aes [index].app_data;
/*---------------------------------------------------------------------*\
Runtime flag indicates if we've already traversed and printed this AE
\*---------------------------------------------------------------------*/
if (mfg_data->is_completed)
continue;
ProWstringToString (template_name, mfg_data->template_type);
n_instances = 1;
/*---------------------------------------------------------------------*\
The first loop through the remaining AE's is to generate a count of the
AE's that use a certain template name
\*---------------------------------------------------------------------*/
for (j = index + 1; j < size; j ++)
{
PTMfgTemplateOrientationData* second_mfg_data;
int result;
second_mfg_data = (PTMfgTemplateOrientationData*)
data.collected_aes [j].app_data;
ProWstringCompare (mfg_data->template_type,
second_mfg_data->template_type,
PRO_VALUE_UNUSED,
&result);
if (result == 0)
{
n_instances ++;
}
}
/*---------------------------------------------------------------------*\
Print the tree parent node, containing the count
\*---------------------------------------------------------------------*/
ProTKFprintf (fp, "d.add(%d,0,'Template: %d x\t%s','');\n",node_counter,n_instances,template_name);
parent_node = node_counter;
node_counter++;
/*---------------------------------------------------------------------*\
Print the current AE as the first child to the parent node
\*---------------------------------------------------------------------*/
PTMfgTemplateAEPrint (fp, parent_node, node_counter, &data.collected_aes[index]);
node_counter++;
mfg_data->is_completed = PRO_B_TRUE;
/*---------------------------------------------------------------------*\
Loop through the remaining AE's again and print each matching AE as a child
of the parent node
\*---------------------------------------------------------------------*/
for (j = index + 1; j < size; j ++)
{
PTMfgTemplateOrientationData* second_mfg_data;
int result;
second_mfg_data = (PTMfgTemplateOrientationData*)
data.collected_aes [j].app_data;
ProWstringCompare (mfg_data->template_type,
second_mfg_data->template_type,
PRO_VALUE_UNUSED,
&result);
if (result == 0)
{
PTMfgTemplateAEPrint (fp, parent_node, node_counter, &data.collected_aes[j]);
second_mfg_data->is_completed = PRO_B_TRUE;
node_counter ++;
}
}
}
/*---------------------------------------------------------------------*\
Free the collected AE data
\*---------------------------------------------------------------------*/
for (index = 0; index < size; index ++)
{
PTMfgTemplateOrientationData* mfg_data;
mfg_data = (PTMfgTemplateOrientationData*)
data.collected_aes [index].app_data;
free (mfg_data);
}
ProArrayFree ((ProArray*)&data.collected_aes);
/*---------------------------------------------------------------------*\
Complete the HTML BOM
\*---------------------------------------------------------------------*/
ProTKFprintf (fp, "document.write(d);\n");
ProTKFprintf (fp, "//-->\n");
ProTKFprintf (fp, "</script>\n");
ProTKFprintf (fp, "</div>\n");
ProTKFprintf (fp, "</body>\n");
ProTKFprintf (fp, "</html>\n");
fclose (fp);
return PRO_TK_NO_ERROR;
}
/*====================================================================*\
FUNCTION : PTMfgTemplateAEWriteBOM()
PURPOSE : Menu button to write and display HTML BOM for mfg templates
\*====================================================================*/
int PTMfgTemplateAEWriteBOM ()
{
ProMdl mdl;
PTAECollectionData data;
ProFileName filename;
ProPath dir_path, path;
int window_id;
ProCharPath char_path;
/*---------------------------------------------------------------------*\
Collect the AE's in the model that match the criteria (only MFG template
AE's should be collected).
\*---------------------------------------------------------------------*/
status = ProMdlCurrentGet (&mdl);
PT_TEST_LOG_SUCC ("ProMdlCurrentGet()");
if (status != PRO_TK_NO_ERROR) return (ACCESS_UNAVAILABLE);
data.app_collection_function = PTMfgTemplateAEInfoCollect;
status = ProArrayAlloc (0, sizeof (PTAEInfo),
5, (ProArray*) &data.collected_aes);
status = ProSolidAnnotationelemsVisit (mdl,
PTAEInfoCollect,
PTAEIsMfgTemplate,
(ProAppData)&data);
PT_TEST_LOG_SUCC ("ProSolidAnnotationelemsVisit()");
/*---------------------------------------------------------------------*\
Output and display the BOM HTML
\*---------------------------------------------------------------------*/
if (status == PRO_TK_NO_ERROR)
{
PTMFGTemplateBOMHTMLWrite (mdl, data);
ProDirectoryCurrentGet (dir_path);
ProStringToWstring (path, "file://");
ProWstringConcatenate (dir_path, path,
PRO_VALUE_UNUSED);
ProStringToWstring (filename, MFGINFOFILENAME);
ProWstringConcatenate (filename, path,
PRO_VALUE_UNUSED);
ProWstringToString (char_path, path);
ProWindowCurrentGet (&window_id);
ProWindowURLShow(window_id, path);
}
return PRO_TK_NO_ERROR;
}