Mechanical Modeler |
Creating a Command to Edit a User FeatureImplementing CATIEdit onto a User Feature |
|
Use Case |
AbstractThis article shows how to create a command to edit a User Feature of a given type by implementing the CATIEdit interface |
This use case is intended to show you how to create a command to edit a User Feature of a given type in implementing the CATIEdit interface. This interface is implemented on a late type whose the name is the type of the User Feature. This article describes how to:
Before getting to the use case itself, it is important to already be familiar with the basic notions of User Features. See the referenced article [1] for a detailed overview.
This article has been updated in V5R13 to take the Ordered Geometrical Set into account. The following icon is in front of each piece of code newly added or modified. On the other hand, it does not have been functionally modified to take into account the solid and surfacic features set.
[Top]
CAAMcaUdfEdit is a use case of the CAAMechanicalCommands.edu framework that illustrates MechanicalCommands and MechanicalModelerUI framework capabilities.
[Top]
In the CAAUdfLoft Part document you have the CAAUserFeatureSample
User Feature reference [2]. This file, as all
the files indicated in this article, is located in the InputData
module of the CAAMechanicalCommands.edu framework.
Double click on the CAAUserFeatureSample
feature: the
"Userfeature Definition" Dialog box appears [Fig 2].
Select the "Type" tab and observe that the "Instance Type"
field is empty.
The CAAUdfLoftWithType Part document contains the same User Feature
reference, CAAUserFeatureSample
, enriched with the "CAAUdfLoft"
type. The following picture shows the "Userfeature
Definition" Dialog box [Fig 3] when this feature is
edited.
Notice that:
CAA
:
there you set the company-based prefixUdfLoft
CAAUdfLoft
. To set a type to an User Feature reference there are two means:
SetType
method) or retrieve (GetType
method) the type of the User
Feature.In the CAAUdfModelWithTypeInst Part document you will find an instance of the
CAAUserFeatureSample
feature with the CAAUdfLoft
type.
This instance is named CAAUserFeatureToEdit
.
When you double click on the CAAUserFeatureToEdit
feature, in
place of the default edit command, the following dialog box appears:
This dialog box is the CAAMcaUdfLoftEditCreateCmd class which contains
Refer to the use case "Creating a User Feature Reference" [2]
for details about the inputs and the roles of the "CAAUserFeatureSample"
User Feature.
To replace the default command we have implemented the CATIEdit
interface [3] on the CAAUdfLoft
late
type. This interface contains the method, Activate,
which returns a
pointer to the command that edits the object. This command is the CAAMcaUdfLoftEditCreateCmd
command which derives from CATPrtPanelStateCmd (MechanicalModelerUI
framework). It is recommended to derive from this class to benefit from
Mechanical Modeler behaviors (update, input validation ...)
The CAAMcaUdfLoftEditCreateCmd command is a CATStateCommand which has two state charts:
An error prevents to edit the User Feature
A notify window displays the error message and the command is ended when the end user clicks on the Ok or Close Button.
The User Feature can be normally edited
The "CAAUdfLoft" dialog box [Fig 5] is instantiated. The end user can:
- Click OK: the user feature instance is modified with the current value
- Click Close/Cancel to cancel the edition
- Select a feature
- Click Preview to see the user feature instance with the current value
This UML [4] diagram shows the transitions triggered at each end user interaction:
- The transition between the Cancel state and the Null State are automatically defined by the CATStateCommand class
- The loop transition to select a feature is defined in the CAAMcaUdfLoftEditCreateCmd class
- All the others transitions are defined in the CATMMUIPanelStateCmd class
[Top]
To launch CAAMcaUdfEdit , you will need to set up the build time environment, then compile CAAMcaUdfEdit along with its prerequisites, set up the run time environment, and then execute the use case [5].
First scenario, to set a type to an User Feature reference:
Launch CATIA. When the application is ready:
Second scenario, to see the new edit command:
Launch CATIA. When the application is ready:
Third scenario, to see the default edit command:
Launch CATIA. When the application is ready:
CAAUdfLoft.CATPart,
CAAUdfModelWithTypeInst.CATPart,
and CAAUdfModelWithInstances.CATPart
are included in the directory CAAMechanicalCommands.edu/InputData
InstallRootDirectory/CAAMechanicalCommands.edu/InputData
InstallRootDirectory\CAAMechanicalCommands.edu\InputData
[Top]
The CAAMcaUdfEdit use case is made of several classes located in the CAAMcaUdfEdit.m module of the CAAMechanicalCommands.edu framework:
Windows |
InstallRootDirectory\CAAMechanicalCommands.edu\CAAMcaUdfEdit.m\ |
Unix | InstallRootDirectory/CAAMechanicalCommands.edu/CAAMcaUdfEdit.m/ |
where InstallRootDirectory
is the directory where the CAA CD-ROM
is installed.
[Top]
There are three logical steps in the CAAMcaUdfEdit use case:
[Top]
The implementation class is CAAEMcaEditUdfLoft. This section describes:
#include "CATExtIEdit.h" class CAAEMcaEditUdfLoft : public CATExtIEdit { CATDeclareClass; public : CAAEMcaEditUdfLoft(); virtual ~CAAEMcaEditUdfLoft(); virtual CATCommand * Activate(CATPathElement * iPath); private : CAAEMcaEditUdfLoft(const CAAEMcaEditUdfLoft &iObjectToCopy); CAAEMcaEditUdfLoft & operator = (const CAAEMcaEditUdfLoft &iObjectToCopy); }; |
The CAAEMcaEditUdfLoft
C++ class derives from the CATExtIEdit
adapter class. The CATDeclareClass
macro declares that the CAAEMcaEditUdfLoft
class belongs to a component. The copy constructor and the
"=" operator are set as private to prevent the compiler from
automatically creating them as public.
#include "CAAEMcaEditUdfLoft.h" #include "CAAMcaUdfLoftEditCreateCmd.h" #include "CATISpecObject.h" #include "CATPathElement.h" CATImplementClass( CAAEMcaEditUdfLoft, DataExtension, CATIEdit, CAAUdfLoft); TIE_CATImplementBOA(CATIEdit,CAAEMcaEditUdfLoft); |
The CATImplementClass
macro is used in conjunction with the
CATDeclareClass
macro in the class header file to express that
the class is part of a CAA V5 Object Modeler component. Its argument read as
follows:
DataExtension
: the CAA V5 Object Modeler class type.
CATIEdit:
The name of implemented interface
CAAUdfLoft
: the name of the extended component . CAAUdfLoft
is the instance type that you find in the
"Userfeature Definition" dialog box, "Type" tab, when
you edit the User Feature reference. Refer to the [Fig 3].The CATImplementBOA
macro replaces the
TIE_CATIEdit
macro. Its arguments are the BOA-implemented
interface and the extension class name respectively.
... CAAEMcaEditUdfLoft::CAAEMcaEditUdfLoft() { } CAAEMcaEditUdfLoft::~CAAEMcaEditUdfLoft() { } ... |
... CATCommand * CAAEMcaEditUdfLoft::Activate (CATPathElement * iPath) { CATCommand * pCommand = NULL ; if ( NULL != iPath ) { CATBaseUnknown* piUk= NULL; piUk= iPath->CurrentElement(); if ( NULL != piUk ) { CATISpecObject *piSpecOnEditFeature = NULL; HRESULT rc = piUk->QueryInterface(IID_CATISpecObject, (void **)&piSpecOnEditFeature); if (SUCCEEDED(rc)) { pCommand = new CAAMcaUdfLoftEditCreateCmd( piSpecOnEditFeature ); piSpecOnEditFeature->Release(); piSpecOnEditFeature = NULL; } } } return pCommand ; } |
In most cases, the object to edit is the one implementing CATIEdit,
so you can retrieve a pointer on it thanks to this
. But in this
particular case, the implementation is done on a late type, so you need to
retrieve a pointer on the object to edit thanks to the input argument iPath
.
In the interface dictionary dedicated to the CAAMechanicalCommands.edu
framework, it is necessary to add the following line to indicate that the CAAUdfLoft
component
implements the CATIEdit interface in the CAAMcaUdfEdit.m
module.
CAAUdfLoft CATIEdit libCAAMcaUdfEdit
[Top]
The command CAAMcaUdfLoftEditCreateCmd is a command which can edit and
create a CAAUdfLoft
User Feature. In this section we have only
extracted the code to make an edition. The "Instantiating Interactively a
User Feature" [6] use case details the
complementary code which are in this article preceded by the comment
"Create Code":
From V5R13, to ensure the insertion of CAAUdfLoft
user features
into an ordered set, the CAAMcaUdfLoftEditCreateCmd command must now:
This section describes:
CAAMcaUdfLoftEditCreateCmd
header file.
#include "CATPrtPanelStateCmd.h" // To derive from class CAAMcaUdfLoftDlg ; // Dialog box to edit the user feature class CATFeatureImportAgent ; // To select features class CATIUdfInstantiate ; // Interface to instantiate a user feature class CATDocument ; // Used by the RetrieveTheUFRef method class CATDlgNotify ; // Dialog box to display the error message class CATPathElement ; // Input selected class CAAMcaUdfLoftEditCreateCmd: public CATPrtPanelStateCmd { CmdDeclareResource( CAAMcaUdfLoftEditCreateCmd, CATPrtPanelStateCmd ) public: CAAMcaUdfLoftEditCreateCmd(CATISpecObject *iObjectToEdit); ... virtual ~CAAMcaUdfLoftEditCreateCmd(); private: CAAMcaUdfLoftEditCreateCmd(const CAAMcaUdfLoftEditCreateCmd &iObjectToCopy); CAAMcaUdfLoftEditCreateCmd & operator = (const CAAMcaUdfLoftEditCreateCmd &iObjectToCopy); ... |
The CAAMcaUdfLoftEditCreateCmd command derives from the CATPrtPanelStateCmd command that enables to benefit from MechanicalModeler behaviors: update, inputs validation ... The copy constructor and the "=" operator are set as private to prevent the compiler from automatically creating them as public. Notice that the default constructor is not set as private because it is set as public in creation mode.
The CmdDeclareResource
macro states that the resources of the CAAMcaUdfLoftEditCreateCmd
command are located in the CAAMcaUdfLoftEditCreateCmd.CATNls
file. If resources were assigned to the CATPrtPanelStateCmd class, they
would be concatenated with the resources for CAAMcaUdfLoftEditCreateCmd
.
... HRESULT InitCommand(); HRESULT CheckUserFeatureType(CATISpecObject * iUserFeature); ... |
In the InitCommand
method we have
grouped together the common code to call in the constructors, for edition and
for creation. For our command, this code creates only the dialog box to
display the input even though the parameter as not proceeded.
The CheckUserFeatureType
method
checks that the feature to edit has the CAAUdfLoft
type.
Some methods are overriden from CATPrtPanelStateCmd or from its
parent class: CATMMUIPanelStateCmd: GiveMyPanel,
OkAction and PreviewAction.
We will see that in case of the two first methods, it is mandatory to
override them; in the case of the third, is is necessary here since the dialog
box includes a Preview button.
... virtual CATDlgDialog* GiveMyPanel(); virtual CATBoolean OkAction(void * iUsefuldata); virtual CATBoolean PreviewAction(void * iUsefuldata); ... |
Below is a CATStateCommand with its BuildGraph
method, its condition method CheckInput
and its action methods: SelectPoint
and CloseErrorDialogBox
.
... virtual void BuildGraph(); ... virtual CATBoolean CheckInput(void * iUsefuldata); virtual CATBoolean SelectPoint(void * iUsefuldata); virtual CATBoolean CloseErrorDialogBox(void * iUsefuldata); ... |
V5R13 novelty. To manage the current feature, the following methods have been added:
... virtual CATBoolean CancelAction(void * iUsefuldata); ... CATStatusChangeRC Activate (CATCommand * iCmd,CATNotification * iNotif); CATStatusChangeRC Deactivate (CATCommand * iCmd,CATNotification * iNotif); virtual CATBoolean InitAction(void * iUsefuldata); virtual CATBoolean BeforeBuildGraph(); virtual CATBoolean IsUFInsideOrderedBody(); ... |
The first part of the data members concerns the error management
... private: CATString _ErrorKey ; CATDlgNotify * _pErrorDialogBox; CATDialogAgent * _pAgentErrorDialogBox ; ... |
When an error occurs in the constructor, a dialog box, _pErrorDialogBoxis, is launched and which displays the error.
_ErrorKey
contains the type of the error. This string enables
the creation of a keyword used to search the NLS message to display in the _pErrorDialogBox
dialog box. _pAgentErrorDialogBox
is an agent to trigger
the transition between the first state and the Cancel state when the end user
clicks OK or Close [Fig. 6].
The next part concerns the input acquisition.
... CAAMcaUdfLoftDlg * _pInputDialogBox; CATFeatureImportAgent * _pFeatureAgent ; CATPathElement * _pFirstPoint ; CATPathElement * _pSecondPoint ; CATPathElement * _pSelectedPath ; }; |
The dialog box to display the input is _pInputDialogBox
.
_pFeatureAgent
is the agent used to select the input in the
specification tree or in 3D.
_pFirstPoint
and _pSecondPoint
contain pointers
on the initial inputs, or on the selected inputs during the life of the
command. These two pointers enable to modify the edited User Feature in the OkAction
when the end user clicks OK, or in the PreviewAction
when he
clicks on the Preview Button. _pSelectedPath
is a storage path
valuated in the CheckInput
condition method and used in the SelectPoint
action method to valuate _pFirstPoint
or _pSecondPoint
.
V5R13 novelty. The last data member is the current feature when the command is
launched. _spSpecObjOnPreviousCurrentFeat
is kept to be restored
at the end of the command (excepted in case of successful creation into an
ordered set, because the new feature must stay the current one).
... CATISpecObject_var _spSpecObjOnPreviousCurrentFeat ; }; |
Notice that the feature to edit is not a data member of this class. This
feature is set in the _MyFeature
data member of the CATMMUIPanelStateCmd
class. After the affectation, we retrieve this smart pointer thanks to the
GiveMyFeature
method, always defined in the grand-parent class.
CAAMcaUdfLoftEditCreateCmd
source file.
//Local Framework #include "CAAMcaUdfLoftEditCreateCmd.h" #include "CAAMcaUdfLoftDlg.h" // Dialog box to display the inputs //ObjectModelerBase Framework #include "CATSessionServices.h" // Lock and Unlock #include "CATDocumentServices.h" // Open, Remove #include "CATInit.h" // To retrieve the root container #include "CATDocument.h" // Document which contains the user feature // to instantiate //DialogEngine Framework #include "CATFeatureImportAgent.h" // To select a feature #include "CATDialogTransition.h" // To set resource ID to transitions // Dialog Framework #include "CATDlgNotify.h" // The dialog box in case of failure //MechanicalCommands Framework #include "CATIUdfFeatureUser.h" // To return the type of the u.f. #include "CATIUdfFeatureInstance.h" // To modify the u.f. #include "CATIUdfInstantiate.h" // To instantiate a new u.f. #include "CATIUdfFactory.h" // To retrieve the u.f. to isntantiate //MecModInterfaces Framework #include "CATIPrtContainer.h" // The root container #include "CATIPrtPart.h" // The mechanical Part //ObjectSpecsModeler Framework #include "CATIAlias.h" // To retrieve the name of the features //ApplicationFrame Framework #include "CATApplicationFrame.h" // To retrieve the parent dialog boxes #include "CATFrmEditor.h" // To unset the repeat command //System framework #include "CATGetEnvValue.h" //Visualization framework #include "CATPathElement.h" ... CAAMcaUdfLoftEditCreateCmd::CAAMcaUdfLoftEditCreateCmd(CATISpecObject *iObjectToEdit): CATPrtPanelStateCmd ("CAAMcaUdfLoftEditCreateCmd", CATDlgEngOneShot, CATCommandModeExclusive,0), _pInputDialogBox(NULL),_pAgentErrorDialogBox(NULL),_pFeatureAgent(NULL), _ErrorKey("NoError"), _pErrorDialogBox(NULL),_pFirstPoint(NULL),_pSecondPoint(NULL),_pSelectedPath(NULL) { HRESULT rc = E_FAIL ; if ( NULL != iObjectToEdit ) { rc = InitCommand(); if ( SUCCEEDED(rc) ) { rc = CheckUserFeatureType(iObjectToEdit); if ( SUCCEEDED(rc) ) { CATIUdfFeatureInstance_var spIUdfFeatureInstance = iObjectToEdit ; if (NULL_var != spIUdfFeatureInstance) { _MyFeature = iObjectToEdit ; CATBaseUnknown_var spBUknInput ; CATBaseUnknown * pBUknInput = NULL ; CATIAlias_var spAliasInput ; // first Input spIUdfFeatureInstance->GetInput(1,spBUknInput); spAliasInput = spBUknInput ; CATUnicodeString FirstName = spAliasInput->GetAlias() ; pBUknInput = (CATBaseUnknown *) spBUknInput ; _pFirstPoint = new CATPathElement(pBUknInput); // second input spIUdfFeatureInstance->GetInput(2,spBUknInput); spAliasInput = spBUknInput ; CATUnicodeString SecondName = spAliasInput->GetAlias() ; pBUknInput = (CATBaseUnknown *) spBUknInput ; _pSecondPoint = new CATPathElement(pBUknInput); // Initialize the edit dialog box _pInputDialogBox->InitPointName(FirstName,SecondName); // The end user can click the Ok and Preview buttons _pInputDialogBox->SetOKSensitivity(CATDlgEnable); _pInputDialogBox->SetPREVIEWSensitivity(CATDlgEnable); } } } } if ( FAILED(rc) ) { _ErrorKey = "InternalError"; } } |
The arguments of the CATPrtPanelStateCmd are the following:
CATDlgEngOneShot
: when the command is ended, it is not
relaunched. The end user selects the repeat mode by double clicking
the icon in the toolbar (in creation mode)CATCommandModeExclusive
: same as for any command which
modifies a document0
. You can
retrieve the mode by the GetMode
method_pInputDialogBox i
s created in the InitCommand
method.
After the validation of the type of iObjectToEdit
, thanks to
the CheckUserFeatureType
method, the inputs dialog box
is initialized. The CATIUserFeatureInstance interface enables the
retrieval of the two input of the User Feature.
_pSecondPoint
and _pFirstPoint
are
initialized with the initial input values.
The InitPointName
is a method used to valuate the dialog
objects with the alias name of the input values. Since the two input
values already exist, the Ok
and the Preview
buttons are accessible to the end user.
... CAAMcaUdfLoftEditCreateCmd::~CAAMcaUdfLoftEditCreateCmd() { if ( NULL != _pInputDialogBox ) { _pInputDialogBox->RequestDelayedDestruction(); _pInputDialogBox = NULL ; } if ( NULL != _pErrorDialogBox ) { _pErrorDialogBox->RequestDelayedDestruction(); _pErrorDialogBox = NULL ; } if ( NULL != _pAgentErrorDialogBox ) { _pAgentErrorDialogBox->RequestDelayedDestruction(); _pAgentErrorDialogBox = NULL ; } if ( NULL != _pFeatureAgent ) { _pFeatureAgent->RequestDelayedDestruction(); _pFeatureAgent = NULL ; } if ( NULL != _pFirstPoint ) { _pFirstPoint->Release(); _pFirstPoint = NULL ; } if ( NULL != _pSecondPoint ) { _pSecondPoint->Release(); _pSecondPoint = NULL ; } if ( NULL != _pSelectedPath ) { _pSelectedPath ->Release(); _pSelectedPath = NULL ; } } ... |
The destructor of a CATStateCommand contains a RequestDelayedDestruction
for each agent created in the BuildGraph
method. States and
transitions are automatically deleted by the CATStateCommand.
... HRESULT CAAMcaUdfLoftEditCreateCmd::InitCommand() { HRESULT rc = E_FAIL ; CATApplicationFrame * pFrame = NULL ; pFrame = CATApplicationFrame::GetFrame(); if ( NULL != pFrame ) { if ( NULL != pFrame->GetMainWindow() ) { _pInputDialogBox = new CAAMcaUdfLoftDlg(pFrame->GetMainWindow()); _pInputDialogBox->Build(); _pInputDialogBox->SetOKSensitivity(CATDlgDisable); _pInputDialogBox->SetPREVIEWSensitivity(CATDlgDisable); rc = S_OK ; } } return rc ; } ... |
The dialog parent of the input dialog box is the same dialog object which
contains also all the windows for the current document. This parent object
is returned by the GetMainWindow
method applied to the unique CATApplicationFrame
pointer of the session.
This method is also used in case of creation, so the default behavior of
the input dialog box, is to hide the Ok
and the Preview
button as long as the two input values are not valuated.
... CATDlgDialog* CAAMcaUdfLoftEditCreateCmd::GiveMyPanel() { return _pInputDialogBox ; } ... |
This method returns the dialog box used in the state chart [Fig.7]. In fact this method will be mainly called by the CATMMUIPanelStateCmd class to create transitions when the end user clicks on the Ok, Cancel, Preview and Close Buttons.
... HRESULT CAAMcaUdfLoftEditCreateCmd::CheckUserFeatureType(CATISpecObject * iUserFeature) { HRESULT rc = E_FAIL ; CATIUdfFeatureUser_var spIUdfFeatureUser = iUserFeature ; if ( (NULL_var != spIUdfFeatureUser) ) { CATUnicodeString CAAUdfLoft("CAAUdfLoft"); CATUnicodeString Type ; spIUdfFeatureUser->GetType(Type); if ( CAAUdfLoft == Type ) { rc = S_OK ; } } return rc; } ... |
The iUserFeature
input argument represents the feature
whose type must be checked. Thanks to the CATIUdfFeatureUser
interface, the type can be compared with CAAUdfLoft
.
When there is an error in the constructor, a specific state chart is defined [Fig.6].
... void CAAMcaUdfLoftEditCreateCmd::BuildGraph() { BeforeBuildGraph(); if ( CATString("NoError") != _ErrorKey ) { CATApplicationFrame * pFrame = NULL ; pFrame = CATApplicationFrame::GetFrame(); if ( NULL != pFrame ) { if ( NULL != pFrame->GetMainWindow() ) { _pErrorDialogBox = new CATDlgNotify(pFrame->GetMainWindow(), "Error", CATDlgNfyError| CATDlgNfyOK | CATDlgWndModal); CATUnicodeString ErrorMessage ; CATString KeyOfTheErrorMessage = "Error." + _ErrorKey ; ErrorMessage = CATMsgCatalog::BuildMessage("CAAMcaUdfLoftEditCreateCmd", KeyOfTheErrorMessage,NULL,0, "Error in the CAAMcaUdfLoftEditCreateCmd command"); _pErrorDialogBox->SetText(ErrorMessage); _pErrorDialogBox->SetVisibility(CATDlgShow); CATDialogState *pErrorState = GetInitialState("ErrorStateId"); _pAgentErrorDialogBox = new CATDialogAgent("PanelError"); pErrorState->AddDialogAgent(_pAgentErrorDialogBox); _pAgentErrorDialogBox->AcceptOnNotify(_pErrorDialogBox, _pErrorDialogBox->GetNfyOKNotification()); _pAgentErrorDialogBox->AcceptOnNotify(_pErrorDialogBox, _pErrorDialogBox->GetWindCloseNotification()); AddTransition(pErrorState,GetCancelState(), IsOutputSetCondition(_pAgentErrorDialogBox), Action((ActionMethod) &CAAMcaUdfLoftEditCreateCmd::CloseErrorDialogBox)); } } }else ... |
Before V5R13, at the beginning of the BuildGraph
method there
was the method to create the user feature. This method has been off-set in
the BeforeBuildGraph
method which also manages the current feature.
If an error occurs in the constructor, an error dialog box appears, _pErrorDialogBox
. This CATDlgNotify has the same parent as the _pInputDialogBox
,
which is the dialog object returned by the GetMainWindow
method.
This dialog box displays a message depending on the error's type. KeyOfTheErrorMessage
is a string built from the type of the error. In the CAAMcaUdfLoftEditCreateCmd.CATNls
file, see the NLS section, the
different message are defined and retrieved thanks to the BuildMessage
method of the CATMsgCatalog class. If the keyword is not found in the
NLS file, the default message is the last argument of the BuildMessage
method: "Error in the CAAMcaUdfLoftEditCreateCmd command
".
The first and unique state is created using the GetInitialState
method that also creates an automatic transition from the initial state to
this state. An identifier ( ErrorStateId
) is assigned to the
state to set a prompt displayed in the status bar when the state is active.
In the NLS part , you have the
definition of this prompt. The AddDialogAgent
method associates
the dialog agent, _pAgentErrorDialogBox
, with the state.
Here is the BuildGraph
method when there is no error. An
other state chart is defined [Fig.7].
... { _pInputDialogBox ->SetVisibility(CATDlgShow); CATIUdfFeatureInstance_var spIUdfFeatureInstance = GiveMyFeature() ; CATUnicodeString Role ; spIUdfFeatureInstance->GetInputRole(1,Role); _pInputDialogBox->SetRole(1,Role); spIUdfFeatureInstance->GetInputRole(2,Role); _pInputDialogBox->SetRole(2,Role); CATDialogState * pInputState = GetInitialPanelState("InputStateId"); _pFeatureAgent = new CATFeatureImportAgent("PointAgentId"); _pFeatureAgent->SetBehavior(CATDlgEngWithPSOHSO | CATDlgEngWithPrevaluation); pInputState ->AddDialogAgent(_pFeatureAgent); CATDialogTransition * pInputTransition = AddTransition(pInputState,pInputState, AndCondition(IsOutputSetCondition(_pFeatureAgent), Condition((ConditionMethod) & CAAMcaUdfLoftEditCreateCmd::CheckInput)), Action((ActionMethod) &CAAMcaUdfLoftEditCreateCmd::SelectPoint)); pInputTransition->SetResourceID("InputTransitionId"); } } ... |
In this part of the code, the input dialog box is visualized in order for the feature to be edited.
Notice the initialization of the dialog box: in the constructor we have
set the name of the input values. This operation is not available in case of
creation mode, since the input values are not yet valuated. However, the
role of the input values, independent of the instances, are set in the BuildGraph
method in a part available to the creation and edition modes.
The feature to edit is retrieved by the GiveMyFeature
method. This method is defined in the CAAMMUIPanelStateCmd class and
returns a smart pointer on the feature, _MyFeature
. This
feature is initialized in the constructor of the edition mode and in a
specific method of the creation mode.
A state, pInputState
, is created by the CAAMMUIPanelStateCmd
class thanks to the GetInitialPanelState
method. This method
defines transitions on the OK, Cancel, Preview and Close button.
In this method we have defined only one transition, those when the end
user selects a feature in 3D or in the specification tree. It is a loop
transition between the unique state pInputState
. The agent of
selection, _pFeatureAgent
, is a CATFeatureImportAgent without
filtering. The analysis of the selection will be done in the condition
method, the CheckInput
method and if the selected feature can
be an input to the user feature reference, the SelectPoint
will
be executed.
This is a condition method, called each time the end user selects a feature.
... CATBoolean CAAMcaUdfLoftEditCreateCmd::CheckInput( void *UsefulData) { CATBoolean rcode = FALSE; CATPathElement * pPathElt= _pFeatureAgent->GetValue(); if ( NULL != pPathElt ) { int i = _pInputDialogBox->GetActiveEditorNumber(); CATIUdfFeatureInstance_var spFeatInst = GiveMyFeature(); CATPathElement * pFilterPath = NULL ; HRESULT rc = spFeatInst->FilterInput(i,pPathElt,&pFilterPath); if ( SUCCEEDED(rc) && ( NULL != pFilterPath) ) { if ( 0 != pFilterPath->GetSize() ) { CATBaseUnknown * pLeaf = NULL ; pLeaf = (*pFilterPath)[pFilterPath->GetSize()-1]; if ( NULL != pLeaf ) { rcode = TRUE ; _pSelectedPath = pFilterPath ; _pSelectedPath->AddRef() ; } } pFilterPath->Release(); pFilterPath = NULL ; } } if ( FALSE == rcode ) { _pFeatureAgent->InitializeAcquisition(); } return rcode; } ... |
The current input is given by the dialog box which manages the current
selector. This is done by the GetActiveEditorNumber
method.
The verification is done by the FilterInput
method. In fact,
you request to the User Feature itself to verify if the selected object is a
valid input. The output of this method is a new CATPathElement, pFilterPath
,
and if this path is not empty it is the new input.
If the selected feature is not correct, the agent of acquisition, _pFeatureAgent, must be reset in order to be used in the next loop.
This is an action method called when the selected input has been
validated by the CheckInput
condition method.
... CATBoolean CAAMcaUdfLoftEditCreateCmd::SelectPoint( void *UsefulData) { if ( NULL != _pSelectedPath ) { int i = _pInputDialogBox->GetActiveEditorNumber(); if ( i == 1 ) { if ( NULL != _pFirstPoint ) _pFirstPoint->Release(); _pFirstPoint = _pSelectedPath ; } if ( i == 2 ) { if ( NULL != _pSecondPoint ) _pSecondPoint->Release(); _pSecondPoint = _pSelectedPath ; } CATBaseUnknown * pLeaf = NULL ; pLeaf = (*_pSelectedPath)[_pSelectedPath->GetSize()-1]; if ( NULL != pLeaf ) { CATIAlias * pIAlias = NULL ; HRESULT rc = pLeaf->QueryInterface(IID_CATIAlias,(void**)& pIAlias); if ( SUCCEEDED(rc) ) { _pInputDialogBox->SetPointName(i,pIAlias->GetAlias()); pIAlias->Release(); pIAlias = NULL ; } } _pSelectedPath = NULL ; } if ( (NULL != _pFirstPoint ) && ( NULL != _pSecondPoint) ) { _pInputDialogBox->SetOKSensitivity(CATDlgEnable); _pInputDialogBox->SetPREVIEWSensitivity(CATDlgEnable); } // To enable a new selection with the same agent _pFeatureAgent->InitializeAcquisition(); return TRUE; } ... |
_pFirstPoint
or_pSecondPoint
are valuated with
the path defined in the CheckInput
method and if the two points
are valuated, the end user can click on the Ok and Preview Button.
This method is called in the BuildGraph
method to:
... CATISpecObject_var spSpecObjOnLocalPreviousCurrentFeat ; spSpecObjOnLocalPreviousCurrentFeat = GetCurrentFeature(); ... |
GetCurrentFeature
is the method of the CATMMUIStateCommand
class. This call is done before the CreateFeature call because the Instantiate
method the CATIUdfInstantiate interface will set the new User
Feature as the current one.
... if ( 1 == GetMode() ) { CreateFeature(); } ... |
In case of creation, the CreateFeature
method instantiates
the user feature. It is explained in the referenced article [6].
... CATBoolean IsInsideOrderedBody = FALSE ; rc = IsUFInsideOrderedBodyIsInsideOrderedBody ); if ( TRUE == IsInsideOrderedBody ) { _spSpecObjOnPreviousCurrentFeat = spSpecObjOnLocalPreviousCurrentFeat ; } ... |
Once the user feature is created, and even
in edition mode, you check the type of the set aggregating the user
feature. The IsUFInsideOrderedBody
method is the same method
as the IsCombCrvInsideOrderedBody
of the
CAAMmrCombCrvPanelStCmd class. Refer to the CAAMmrCombinedCurveUI use case
[8] to see an implementation of a such method. _spSpecObjOnPreviousCurrentFeat
, the data member of the CAAMcaUdfLoftEditCreateCmd
state
command contains the current feature before to launch the command in case
of user feature into an ordered set.
... if ( (NULL_var != GiveMyFeature()) && (NULL !=GetEditor()) ) { CATIBuildPath *piBuildPath = NULL; rc = GiveMyFeature()->QueryInterface( IID_CATIBuildPath, (void**) &piBuildPath ); if ( SUCCEEDED(rc) && (NULL!=piBuildPath) ) { CATPathElement Context = GetEditor()->GetUIActiveObject(); CATPathElement * pPathElement = NULL ; rc = piBuildPath->ExtractPathElement(&Context,&pPathElement); if ( NULL != pPathElement ) { SetActiveObject(pPathElement); pPathElement->Release(); ... |
In any case, you should call the SetActiveObject
with a
path containing the user feature.
This is an action method called once the end user has clicked on the Ok
button of the input dialog box. This action method has been set in a
transition created by the GetInitialPanelState
method. You
overwrite this method to set the new inputs on the feature to edit, those
returned by the GiveMyFeature
method. At the end of this
method, it is important to call the OkAction
of the CATPrtPanelStateCmd
to benefit from the update and the input validation.
... CATBoolean CAAMcaUdfLoftEditCreateCmd::OkAction( void *UsefulData) { CATIUdfFeatureInstance_var spIUdfFeatureInstance = GiveMyFeature() ; spIUdfFeatureInstance->SetNewInput(1,_pFirstPoint); spIUdfFeatureInstance->SetNewInput(2,_pSecondPoint); if (0 == GetMode()) { CATBoolean IsInsideOrderedBody = FALSE ; IsUFInsideOrderedBody(IsInsideOrderedBody ); if ( TRUE == IsInsideOrderedBody ) { SetCurrentFeature(_spSpecObjOnPreviousCurrentFeat); } } CATBoolean rc = CATPrtPanelStateCmd::OkAction(UsefulData); return rc; } ... |
Since V513, before calling the OkAction
of the parent command,
you should restore the kept current feature in case of edition (GetMode
returns 0
) and if the user feature is into an ordered set. _spSpecObjOnPreviousCurrentFeat
is a data member initialized in the BeforeBuildGraph
method.
This is an action method called once the end user has clicked on the
Preview Button of the input dialog box. This action method has been set on a
transition created by the GetInitialPanelState
method. You can
overwrite this method to set the new inputs on the feature to edit, those
returned by the GiveMy
Feature method. At the end of this
method, it is important to call the PreviewAction
of the CATPrtPanelStateCmd
to benefit from the update and the input validation.
... CATBoolean CAAMcaUdfLoftEditCreateCmd::PreviewAction( void *UsefulData) { CATIUdfFeatureInstance_var spIUdfFeatureInstance = GiveMyFeature() ; spIUdfFeatureInstance->SetNewInput(1,_pFirstPoint); spIUdfFeatureInstance->SetNewInput(2,_pSecondPoint); CATBoolean rc = CATPrtPanelStateCmd::PreviewAction(UsefulData); return rc; } ... |
This is an action method called once the end user has clicked on the
Cancel button of the input dialog box. This action method has been set in a
transition created by the GetInitialPanelState
method. You
overwrite this method to restore the current feature, in edition and
creation mode, the user feature must only be into an OGS. spSpecObjOnPreviousCurrentFeat
is a data member initialized in the BeforeBuildGraph
method.
At the end of this method, it is important to call the CancelAction
of the CATPrtPanelStateCmd to benefit from the parent command code.
... CATBoolean CAAMcaUdfLoftEditCreateCmd::CancelAction( void *UsefulData) { CATBoolean IsInsideOrderedBody = FALSE ; IsUFInsideOrderedBody(IsInsideOrderedBody); if ( TRUE == IsInsideOrderedBody) { SetCurrentFeature(_spSpecObjOnPreviousCurrentFeat); } CATBoolean rc = CATPrtPanelStateCmd::CancelAction(UsefulData); return rc; } ... |
This method has been override in V5R13.
This method is an action method called when the end user clicks Ok
or Close
. It prevent a loop when the end user double clicks on
the icon in the toolbar (creation mode).
... CATBoolean CAAMcaUdfLoftEditCreateCmd::CloseErrorDialogBox( void *UsefulData) { if ( NULL != GetEditor() ) { GetEditor()->UnsetRepeatedCommand(); } return TRUE; } ... |
These both methods are CATCommand methods. The first one is called each time the focus manager gives the focus to the command [9], and the second one when it looses it.
... CATStatusChangeRC CAAMcaUdfLoftEditCreateCmd::Activate (CATCommand * iCmd, CATNotification * iNotif) { if ( NULL_var != GiveMyFeature() ) { CATBoolean IsInsideOrderedBody= FALSE ; IsUFInsideOrderedBody(IsInsideOrderedBody); if ( TRUE == IsInsideOrderedBody) { SetCurrentFeature(GiveMyFeature()); ... |
When the user feature is into an ordered set checked by the IsUFInsideOrderedBody
method, the user feature must be set the current one.
... CATStatusChangeRC CAAMcaUdfLoftEditCreateCmd::Deactivate (CATCommand * iCmd, CATNotification * iNotif) { CATBoolean IsInsideOrderedBody= FALSE ; IsUFInsideOrderedBody(IsInsideOrderedBody); if ( TRUE == IsInsideOrderedBody) { SetCurrentFeature(_spSpecObjOnPreviousCurrentFeat); } ... |
When the user feature is into an ordered set, checked by the IsUFInsideOrderedBody
method, the kept user feature is set as the current one. spSpecObjOnPreviousCurrentFeat
is a data member initialized in the BeforeBuildGraph
method.
It is a method of the parent command. You should overwrite to prevent to execute the code of the parent command.
... CATBoolean CAAMcaUdfLoftEditCreateCmd::InitAction (void * iUseful) { return TRUE ; } ... |
The CAAMcaUdfLoftEditCreateCmd.CATNls
file is located in the CAAMechanicalCommands.edu/Cnext/resources/msgcatalog
directory. It contains:
... Error.InternalError = "Internal error"; |
CAAMcaUdfLoftEditCreateCmd.UndoTitle = "CAAUdfLoft Definition"; |
CAAMcaUdfLoftEditCreateCmd.ErrorStateId.Message = "Click ok to end the command"; CAAMcaUdfLoftEditCreateCmd.InputStateId.Message = "Select points to give new inputs"; |
CAAMcaUdfLoftEditCreateCmd.InputTransitionId.UndoTitle = "Element selection"; |
[Top]
This dialog box is a CAAMcaUdfLoftDlg class.This section describes:
#include "CATDlgDialog.h" class CATDlgSelectorList; class CATDlgLabel; class CAAMcaUdfLoftDlg: public CATDlgDialog { DeclareResource(CAAMcaUdfLoftDlg,CATDlgDialog) ; public : CAAMcaUdfLoftDlg(CATDialog *iParent); virtual ~CAAMcaUdfLoftDlg(); void Build(); void InitPointName(CATUnicodeString iName1 , CATUnicodeString iName2 ); void SetRole(int iPointNumber , CATUnicodeString iName ); void SetPointName(int iPointNumber , CATUnicodeString iName ); int GetActiveEditorNumber(); private : CAAMcaUdfLoftDlg (); CAAMcaUdfLoftDlg(const CAAMcaUdfLoftDlg &iObjectToCopy); CAAMcaUdfLoftDlg & operator = (const CAAMcaUdfLoftDlg &iObjectToCopy); virtual void EditorSelect (CATCommand *, CATNotification* , CATCommandClientData data); private : int _ActiveEditor ; CATDlgSelectorList * _pEditorOfThePoint1 ; CATDlgSelectorList * _pEditorOfThePoint2; CATDlgLabel * _pLabelOfThePoint1 ; CATDlgLabel * _pLabelOfThePoint2 ; }; |
The CAAMcaUdfLoftDlg class derives from the CATDlgDialog class and contains the following methods:
Build
, to construct the dialog object,
InitPointName
to valuate the CATDlgSelectorList with
the name of the input and SetRole
to set the role of the
input as the title of the CATDlgLabelGetActiveEditorNumber
to
retrieve the current input selected and SetPointName
to
change the name in the current CATDlgSelectorList.EditorSelect
method is a callback executed when the end
user clicks on a CATDlgSelectorList. It is the means for the end
user to change the current inputTo display the name of the input, we have chosen a CATDlgSelectorList dialog object even though a CATDlgEditor with the CATDlgEdtReadOnly style could have been used as well. But the selected lines of the CATDlgSelectorList are highlighted, it is not the case of the CATDlgEditor class. The highlight is the visual means for the end user to know which input will be valuated with its selection. Notice that in this command the CATDlgSelectorList are highlighted each one in his turn.
#include "CAAMcaUdfLoftDlg.h" // Dialog Framework #include "CATDlgGridConstraints.h" #include "CATDlgLabel.h" #include "CATDlgSelectorList.h" #include "CATMsgCatalog.h" CAAMcaUdfLoftDlg::CAAMcaUdfLoftDlg(CATDialog * iParent): CATDlgDialog (iParent,"CAAMcaUdfLoftDlg", CATDlgWndBtnOKCancelPreview | CATDlgGridLayout), _pLabelOfThePoint1(NULL),_pLabelOfThePoint2(NULL), _pEditorOfThePoint1(NULL),_pEditorOfThePoint2(NULL) { } CAAMcaUdfLoftDlg::~CAAMcaUdfLoftDlg() { _pLabelOfThePoint1 = NULL ; _pLabelOfThePoint2 = NULL ; _pEditorOfThePoint1 = NULL ; _pEditorOfThePoint2 = NULL ; } |
The style of the dialog box is
CATDlgWndBtnOKCancelPreview
Among the recommended styles for a CATDlgDialog we have chosen a dialog box with three buttons at the bottom: OK, Cancel and Preview. The Preview button is not mandatory.
The frame layout is managed using a grid.
void CAAMcaUdfLoftDlg::Build() { // Labels _pLabelOfThePoint1 = new CATDlgLabel(this, "LabelOfThePoint1"); _pLabelOfThePoint1 -> SetGridConstraints(0, 0, 1, 1, CATGRID_4SIDES); _pLabelOfThePoint2 = new CATDlgLabel(this, "LabelOfThePoint2"); _pLabelOfThePoint2 -> SetGridConstraints(1, 0, 1, 1, CATGRID_4SIDES); // Editor _pEditorOfThePoint1 = new CATDlgSelectorList(this, "EditorOfThePoint1"); _pEditorOfThePoint1 -> SetVisibleTextHeight(1); _pEditorOfThePoint1 -> SetGridConstraints(0, 1, 1, 1, CATGRID_4SIDES); _pEditorOfThePoint2 = new CATDlgSelectorList(this, "EditorOfThePoint2"); _pEditorOfThePoint2 -> SetVisibleTextHeight(1); _pEditorOfThePoint2 -> SetGridConstraints(1, 1, 1, 1, CATGRID_4SIDES); CATUnicodeString NoSelectionMsg ; NoSelectionMsg = CATMsgCatalog::BuildMessage("CAAMcaUdfLoftDlg", "NoSelectionMsg",NULL,0, "no selection"); _pEditorOfThePoint1 -> SetLine(NoSelectionMsg); _pEditorOfThePoint2 -> SetLine(NoSelectionMsg); int RowNb = 0 ; _pEditorOfThePoint1->SetSelect(&RowNb, 1); _ActiveEditor = 1 ; AddAnalyseNotificationCB (_pEditorOfThePoint1, _pEditorOfThePoint1->GetListSelectNotification(), (CATCommandMethod)&CAAMcaUdfLoftDlg::EditorSelect, (void*)1); AddAnalyseNotificationCB (_pEditorOfThePoint2, _pEditorOfThePoint2->GetListSelectNotification(), (CATCommandMethod)&CAAMcaUdfLoftDlg::EditorSelect, (void*)2); } |
The _pEditorOfThePoint1
and _pEditorOfThePoint2
data
members are pointers to instances of the CATDlgSelectorList
class with one line,
SetVisibleTextHeight(1)
. This line
contains a default message at the beginning. This message is retrieved in
the CAAMcaUdfLoftDlg.CATNls file (see the
NLS section), thanks to the static BuildMessage
method. If
the Keyword NoSelectionMsg
is not found, the default message:
"no selection
" is the last argument of the static
method.
The SetSelect
on _pEditorOfThePoint1
enables to
highlight the first and unique line of this selector list.
void CAAMcaUdfLoftDlg::EditorSelect(CATCommand* cmd, CATNotification* evt, CATCommandClientData data) { int number = (int) data; if (_ActiveEditor != number) { if ( _pEditorOfThePoint1 == cmd ) { _pEditorOfThePoint2->ClearSelect(); } else if ( _pEditorOfThePoint2 == cmd ) { _pEditorOfThePoint1->ClearSelect(); } } _ActiveEditor = number; } |
This callback method enables the end user to change itself the current
input. When it is the case, the selected selector list is automatically
highlighted, and with this method the last selected selector list is
dehighlighted thanks to the ClearSelect
method.
int CAAMcaUdfLoftDlg::GetActiveEditorNumber() { if (_pEditorOfThePoint1->IsSelect(0)) _ActiveEditor= 1; if (_pEditorOfThePoint2->IsSelect(0)) _ActiveEditor= 2; return _ActiveEditor; } |
void CAAMcaUdfLoftDlg::SetPointName(int iPointNumber , CATUnicodeString iName ) { int RowNb = 0; if ( 1 == iPointNumber ) { _pEditorOfThePoint1->ClearLine(); _pEditorOfThePoint1->SetLine ( iName ); _pEditorOfThePoint2->SetSelect(&RowNb, 1); }else { _pEditorOfThePoint2->ClearLine(); _pEditorOfThePoint2->SetLine (iName); _pEditorOfThePoint1->SetSelect(&RowNb, 1); } } |
This method is called each time the end user selects a valid feature as
input. The current selector list is modified with the new name: ClearLine
and SetLine
on the current selector. Notice that the current
selector list is no longer highlighted. (ClearLine
and SetLine
deshighlights the line if it was selected). Finally, the SetSelect
method on the next selector list highlights it.
void CAAMcaUdfLoftDlg::SetRole(int iPointNumber , CATUnicodeString iName ) { int RowNb = 0; if ( 1 == iPointNumber ) { _pLabelOfThePoint1-> SetTitle(iName+" "); }else { _pLabelOfThePoint2-> SetTitle(iName+" "); } } |
To set a title for a CATDlgLabel outside the constructor, your NlS
file does not have the Title
keyword.
void CAAMcaUdfLoftDlg::InitPointName(CATUnicodeString iName1 , CATUnicodeString iName2 ) { _pEditorOfThePoint1->ClearLine(); _pEditorOfThePoint1->SetLine (iName1); _pEditorOfThePoint2->ClearLine(); _pEditorOfThePoint2->SetLine (iName2); int RowNb = 0 ; _pEditorOfThePoint1->SetSelect(&RowNb, 1); _ActiveEditor = 1 ; } |
The CAAMcaUdfLoftDlg.CATNls file is
located in the CAAMechanicalCommands.edu/Cnext/resources/msgcatalog
directory. It contains:
Title ="CAAUdfLoft Definition" ; ... |
... Help = "Dialog box to edit or create a user feature which two inputs."; ... |
... LabelOfThePoint1.LongHelp ="Role of the first input" ; LabelOfThePoint2.LongHelp ="Role of the second input" ; EditorOfThePoint1.LongHelp ="Alias name of the first input, or no selection if the input is not valuated" ; EditorOfThePoint2.LongHelp ="Alias name of the second input, or no selection if the input is not valuated" ; ... |
... LabelOfThePoint1.ShortHelp ="First input" ; LabelOfThePoint2.ShortHelp ="Second input" ; EditorOfThePoint1.ShortHelp ="First input's alias name" ; EditorOfThePoint2.ShortHelp ="Second input's alias name" ; ... |
... LabelOfThePoint1.Help ="Role of the first input" ; LabelOfThePoint2.Help ="Role of the second input" ; EditorOfThePoint1.Help ="Alias name of the first input, or no selection if the input is not valuated" ; EditorOfThePoint2.Help ="Alias name of the second input, or no selection if the input is not valuated" ; ... |
... NoSelectionMsg = "no selection"; |
[Top]
This use case has demonstrated how to provide a new command to edit a User Feature of a given type by implementing the CATIEdit interface. This command is a CATStateCommand which derives from the CATPrtPanelStateCmd class in order to benefit from the MechanicalModeler behaviors.
[Top]
Version: 1 [Feb 2002] | Document created |
Version: 2 [Nov 2003] | Document updated to take into account the Ordered Geometrical Set |
Version: 3 [Jan 2005] | CATImplementBOA usage instead TIE_CATIEdit |
[Top] |
Copyright © 2002, Dassault Systèmes. All rights reserved.