/* 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; }