Expand/Collapse Specification Tree Nodes-如何在特征树中移除对象

摘要

本文介绍如何展开或折叠特征树的节点。

本示例学习要点

CAACafSpecTree 示例程序

  • 程序功能说明
  • 程序运行方法
  • 代码存放路径

操作步骤

简述

参考资料

本示例学习内容
本示例旨在讲解如何展开与折叠特征树节点。特征树由节点图谱构成,采用模型 - 视图 - 控制器(MVC)架构管理,各模块说明如下:

    模型(M):模型元素实现了 CATINavigateObject 接口 [1]。
    控制器(C):为 CATNavigController 类的实例。
    视图(V):节点图谱在专属查看器中展示(该类未对外暴露),不参与特征树的节点导航操作。

本示例基于 CATFrmNavigWindow 类中的节点图谱开发。CATFrmNavigWindow 是 CATFrmGraphAnd3DWindow 类的基类,而后者也是零件窗口、装配窗口的基类。通过本示例,你将掌握以下操作:

    从 CATFrmNavigWindow 类中获取控制器;
    借助图谱控制器,获取与对象(特征)关联的图形节点;
    实现节点的展开与折叠。

CAACafSpecTree 示例程序

CAACafSpecTree 是 CAACATIAApplicationFrame.edu 开发框架下的示例用例,用于演示 CATIAApplicationFrame 框架与 ObjectModelerBase 框架的功能特性。

CAACafSpecTree 功能说明

CAACafSpecTree 是零件文档中可用的一条命令,即展开 / 折叠命令,可通过工具栏和菜单栏调用。
图 1:展开 / 折叠命令

图片

 

展开 / 折叠命令属于状态对话框命令[2],可供用户对零件文档特征树的节点执行展开或折叠操作。该命令包含两种工作模式:

  展开 / 折叠模式

用户在特征树或三维视图中选中对象后,特征树会展示该对象的下级内容;若下级内容已处于展示状态,则会将其折叠。
图 2:选中 Point.2 前后效果

图片

 再次选中 Point.2,该节点就会被折叠。

全部展开

 

从选中对象开始,将特征树完全展开。示例如下:

图 3:选中 Part1 后的效果

图片

 该命令默认使用第一种模式(展开 / 折叠)。若要启用第二种模式,需导出变量 CAACafSpecTreeExpandMode,具体操作参见运行 CAACafSpecTree章节。

运行 CAACafSpecTree

如需运行 CAACafSpecTree,需先配置编译环境,编译该示例及其依赖项,再配置运行环境,最后执行示例程序 [3]。
正式运行前,请编辑接口字典文件 CAAMechanicalModeler.edu.dico,该文件位于 CAAMechanicalModeler.edu 框架的字典目录下,路径如下:
  • Windows 系统 安装根目录 \CAAMechanicalModeler.edu\CAAMechanicalModelerEduRscCNext.m\src\CNext\code\dictionary\
  • UNIX 系统安装根目录 / CAAMechanicalModeler.edu/CAAMechanicalModelerEduRscCNext.m/src/CNext/code/dictionary/
其中安装根目录为 CAA 安装包的存放路径。
在该文件中,移除以下两行代码前的 # 符号,之后执行 mkCreateRuntimeView 命令。

#CAAMmrPartWksAddin          CATIWorkbenchAddin              libCAAMmrPartWksAddin
#CAAMmrPartWksAddin          CATIPrtWksAddin                 libCAAMmrPartWksAddin

以上两行配置对应零件工作台插件,该插件隶属于 CAAMechanicalModeler.edu 框架下的 CAAMmrPartWksAddin.m 模块,作用是在零件文档界面中添加上文的展开 / 折叠命令。
随后在执行 mkrun 命令的终端窗口中,命令行不要输入模块名,改为输入 CNEXT。应用程序启动完成后,请按以下步骤操作:
  1. 点击文件菜单,选择新建
  2. 在新建文档对话框中选中零件,点击确定
  3. 依次创建点、直线、凸台等特征
  4. 点击工具菜单,选择展开 / 折叠命令
  5. 在特征树中选取对象
  6. 在三维视图中选取对象
  7. 点击开始菜单,选择退出
在执行 mkrun 命令的窗口中,导出环境变量 CAACafSpecTreeExpandMode,命令如下:
  • Windows 系统:set CAACafSpecTreeExpandMode=CAACafSpecTreeExpandAllNodes
  • UNIX 系统:export CAACafSpecTreeExpandMode=CAACafSpecTreeExpandAllNodes
之后继续在该窗口执行操作:命令行中不要输入模块名,直接输入 CNEXT。程序启动完成后,按以下步骤操作:
  1. 点击文件菜单,选择新建
  2. 在新建文档窗口中选择零件,点击确定
  3. 创建点、直线、凸台等特征
  4. 点击工具菜单,选择展开 / 折叠
  5. 在特征树中选中对象
  6. 点击开始菜单,选择退出

 

CAACafSpecTree 代码位置

CAACafSpecTree 示例程序由两个类组成:
  1.  CAACafCollapseExpandCmd 类

该类位于 CAACATIAApplicationFrm.edu 框架下的 CAACafSpecTree.m 模块中。
此类继承自 CATStateCommand,用于实现零件文档特征树节点的展开与折叠功能。头文件(.h)和源文件(.cpp)分别存放于 LocalInterfaces 目录与 src 目录,本文对源文件添加了详尽注释。
  • Windows 路径:安装根目录 \CAACATIAApplicationFrm.edu\CAACafSpecTree.m\
  • Unix 路径:安装根目录 / CAACATIAApplicationFrm.edu/CAACafSpecTree.m/
其中安装根目录为 CAA 安装包所在目录。
  1. CAAMmrPartWksAdn 类

该类位于 CAAMechanicalModeler.edu 框架下的 CAAMmrPartWksAddin.m 模块中。
本文不对该类展开详述,它用于定义零件工作台插件,内置展开 / 折叠命令。
  • Windows 路径: 安装根目录 \CAAMechanicalModeler.edu\CAAMmrPartWksAddin.m\
  • Unix 路径:安装根目录 / CAAMechanicalModeler.edu/CAAMmrPartWksAddin.m/
其中安装根目录为 CAA 安装包所在目录。

实现步骤

CAACafSpecTree 程序包含五大逻辑步骤:
  1. 获取 CATNavigController 类实例
  2. 实现 BuildGraph 方法
  3. 展开特征树至选中对象节点
  4. 对选中对象节点执行展开 / 折叠操作
  5. 从选中对象开始展开全部节点

获取 CATNavigController 类实例

特征树控制器从当前窗口中获取,这段代码在 CAACafCollapseExpandCmd 类的构造函数中实现。
...
CATFrmLayout * pLayout = CATFrmLayout::GetCurrentLayout();
if ( NULL != pLayout )
{
   CATFrmWindow * pCurrentWindow = pLayout->GetCurrentWindow();

   if ( NULL != pCurrentWindow )
   {
       if ( 1 == pCurrentWindow->IsAKindOf("CATFrmNavigGraphicWindow") )
       {
           CATFrmNavigGraphicWindow * pFrmNavigGraphicWindow =
               (CATFrmNavigGraphicWindow*) pCurrentWindow ;

           CATNavigBox * pNavigBox = NULL ;
           pNavigBox = pFrmNavigGraphicWindow->GetNavigBox();

           if ( NULL != pNavigBox )
           {
              _pNavigController = pNavigBox->GetController();
           }
       }
   }
}
...
整个会话周期内,全局唯一的 CATFrmLayout 类实例 [4] 负责管理窗口列表,通过 GetCurrentWindow 方法可获取当前活动窗口。若需要展开当前文档所有窗口内的节点图谱,请参考框架相关文档 [4],其中介绍了如何获取一份文档对应的全部窗口。
若当前窗口属于 CATFrmNavigGraphicWindow 类实例,便可拿到用于承载图谱控制器的 CATNavigBox 对象。_pNavigController 是本命令类中定义的成员变量,类型为 CATNavigController

 

实现 BuildGraph 方法

按照常规逻辑,BuildGraph 方法分为三部分:
  1. 创建交互代理
  2. 创建状态
  3. 根据交互代理定义状态间的跳转关系

...

_daObjectToExpandNode = new CATPathElementAgent("SelObjectToExpandNodeId");
_daObjectToExpandNode->AddElementType(IID_CATINavigateObject);
_daObjectToExpandNode->SetBehavior(CATDlgEngRepeat | CATDlgEngWithPSOHSO );
                            
CATDialogState *stGetObjState = GetInitialState("stGetObjStateId");
stGetObjState->AddDialogAgent(_daObjectToExpandNode);

CATDialogTransition *pTransition = AddTransition
(
   stGetObjState,
   stGetObjState,
   IsLastModifiedAgentCondition(_daObjectToExpandNode),
   Action((ActionMethod) & CAACafCollapseExpandCmd::ExpandObject)
);

...

_daObjectToExpandNode拾取代理,用于在特征树或三维视图中选取对象。通过 AddElementType 方法限定,所选对象必须实现 CATINavigateObject 接口 [5]。CATDlgEngWithPSOHSO 行为表示选中对象后将其高亮显示;CATDlgEngRepeat 行为支持重复使用该代理,无需重复初始化。
本状态命令仅包含一个状态:stGetObjState,状态标识为 stGetObjStateId
当用户选中有效元素时,会触发唯一的状态跳转,并调用 ExpandObject 方法。

展开特征树至选中对象

ExpandObject 方法的第一步是获取选中对象。对拾取代理 _daObjectToExpandNode 调用 GetValue 方法,可得到 CATPathElement 类实例指针,以此获取选中对象的完整路径。
...
CATBoolean CAACafCollapseExpandCmd::ExpandObject(void *iDummy)
{
     CATPathElement * pObjPath = _daObjectToExpandNode->GetValue();
     CATBaseUnknown * pObjectToExpand = NULL;
     
     if ( NULL != pObjPath)
     {
         if ( pObjPath->GetSize() > 0 )
         {
            // 选取路径的末端节点
            pObjectToExpand = (*pObjPath)[pObjPath->GetSize()-1];
         }
...
pObjectToExpand 是路径的叶子节点。若该对象在特征树中未显示,则需要将其展开展示。想要查看对象的下级内容,前提是该对象本身必须处于可见状态,下方代码将具体说明实现方式。
...
// 遍历路径中除末尾叶子节点外的所有父级节点
        for ( int j = 0 ; j <= pObjPath->GetSize()-2 ; j++)
        {
            // 获取当前层级的父对象
            CATBaseUnknown * pFatherObjectToExpand = (*pObjPath)[j];

            CATListValCATBaseUnknown_var * pNodeList = NULL ;
            // 通过特征树控制器获取该父对象对应的所有关联节点
            pNodeList = _pNavigController->GetAssociatedElements(pFatherObjectToExpand);
        
            if ( NULL != pNodeList )
            {
                // 获取节点总数
                int nbNodes = pNodeList->Size();
                // 逐个遍历节点
                for ( int k= 1 ; k <= nbNodes ; k++ )
                {
                    CATIGraphNode_var graphNode = (*pNodeList)[k];
                    if ( NULL_var != graphNode )
                    {
                        // 判断节点是否处于折叠状态
                        if ( 0 == graphNode->IsExpanded() )
                        {
                            // 转为导航元素接口
                            CATINavigElement_var spNavigElement = graphNode ;
                            if ( NULL_var != spNavigElement )
                            {
                                // 执行节点展开后的后续处理
                                spNavigElement->ProcessAfterExpand();
...
选取路径与特征树的层级结构保持一致。因此需要遍历整条路径,从顶层节点直至叶子节点的上一级节点,逐一确认这些节点的内容是否可见。pFatherObjectToExpand 就是当前待检查的节点。
CATNavigController 类的 GetAssociatedElements 方法,可获取入参对象对应的关联节点(在产品装配中,单个零件可被多次实例化)。节点可通过 CATIGraphNodeCATINavigElement 两个接口进行操作:前者提供 IsExpanded 方法,用于判断节点的展开状态;若节点处于折叠状态,则可调用后者的 ProcessAfterExpand 方法将其展开。
当选中对象在特征树中正常显示后,程序会根据环境变量 _pExpandMode 执行对应逻辑:要么从该节点开始展开所有下级节点(详见从选中对象展开全部节点章节),要么仅对当前节点执行单次展开或折叠操作(详见展开 / 折叠选中节点章节)。
...
  if ( (NULL != _pExpandMode) &&
          (0==strcmp("CAACafSpecTreeExpandAllNodes",_pExpandMode)) )
         {
             ExpandAllNode(pObjectToExpand);
         }else
         {
             ExpandCollapseNode(pObjectToExpand);
         }
...
_pExpandModeCAACafCollapseExpandCmd 类的构造函数中,通过全局函数 CATGetEnvValue 完成初始化,具体实现可参考对应代码。

展开 / 折叠选中对象节点

该流程与路径中叶子节点的上级节点处理逻辑基本一致。iObject 是选中路径的叶子节点,详见前文章节。本逻辑不会预先判断节点展开状态,直接调用 ProcessAfterExpand 方法:若节点处于折叠状态则执行展开,若已展开则执行折叠。
...
void CAACafCollapseExpandCmd::ExpandCollapseNode(CATBaseUnknown_var iObject)
{
   ...     
        CATListValCATBaseUnknown_var * pNodeList = NULL ;
        // 获取当前对象对应的所有关联节点
        pNodeList = _pNavigController->GetAssociatedElements(iObject);

        if ( NULL != pNodeList )
        {
           int nbNodes = pNodeList->Size();
           // 遍历所有关联节点
           for ( int i= 1 ; i <= nbNodes ; i++ )
           {
               CATBaseUnknown_var spNode = (*pNodeList)[i];
               if ( NULL_var != spNode )
               {
                   // 转换为导航元素接口
                   CATINavigElement_var spNavigElement = spNode ;
                   if ( NULL_var != spNavigElement )
                   {
                      // 切换节点展开/折叠状态
                      spNavigElement->ProcessAfterExpand();          
 ...
}
...

从选中对象展开所有节点

该处理流程与选取路径中叶子节点上方的其他节点完全一致。iObject 是选取路径的叶子节点,仅当叶子节点未展开时,才会调用 ProcessAfterExpand 方法。
void CAACafCollapseExpandCmd::ExpandAllNode(CATBaseUnknown_var iObject)
{     
    if ( NULL_var != iObject )
    {
        CATListValCATBaseUnknown_var * pNodeList = NULL ;
        pNodeList = _pNavigController->GetAssociatedElements(iObject);

        if ( NULL != pNodeList )
        {
           int nbNodes = pNodeList->Size();
           for ( int i= 1 ; i <= nbNodes ; i++ )
           {
              CATIGraphNode_var graphNode = (*pNodeList)[i];
              if ( NULL_var != graphNode )
              {
                  if ( 0 == graphNode->IsExpanded() )
                  {
                      CATINavigElement_var spNavigElement = graphNode ;
                      if ( NULL_var != spNavigElement )
                      {
                         spNavigElement->ProcessAfterExpand();
...
当你确认特征树已经展开至选中对象的内容后,需要对其子节点执行相同的操作。CATINavigateObject 接口可用于获取元素的子节点 [1]。
CATINavigateObject_var spNavigateObject = iObject ;
        if ( NULL_var != spNavigateObject )
        {
           CATListValCATBaseUnknown_var* pListChild = NULL ;
           pListChild = spNavigateObject->GetChildren();

           if ( NULL != pListChild )
           {
              for ( int t = 1 ; t <= pListChild->Size() ; t++)
              {
                 CATBaseUnknown_var spOnChild = (*pListChild)[t];
                 ExpandAllNode(spOnChild);
              }
           }
        }
...

简要总结

本示例讲解如何在特征树中定位显示指定元素,以及对其下级内容执行展开或折叠操作。
posted @ 2026-06-08 13:42  Breadss  阅读(8)  评论(0)    收藏  举报