3D PLM Enterprise Architecture |
User Interface - Frame |
Creating a Document's Window - Part 2How to create a multi-viewers window |
| Use Case | ||
AbstractThis article shows how to create a window to display a document. It explains more precisely the specificity of a multi-viewers window. In the other hand, the use case described in the "Creating a Document's Window - Part 1" article [1] enables you to understand how to launch a document's window from a command. |
This use case is intended to show how to create a window with several viewers for document of a given type [2].
[Top]
CAAAfrCustomWindow is a use case of the CAAApplicationFrame.edu framework that illustrates the ApplicationFrame framework capabilities.
[Top]
The CAAAfrCustomWindow use case creates a document window for CAASample documents.

[Top]
See the section entitled "How to Launch the CAAGeometry Use Case" in the "The CAAGeometry Sample" use case for a detailed description of how this use case should be launched. For the specific scenario :
Do not type the module name on the command line, but type CNEXT instead. When the application is ready, do the following:
[Top]
The CAAAfrCustomWindow use case is made up of a single class named CAAAfrCustomWindow located in the CAAAfrGeoWindows.m module of the CAAApplicationFrame.edu framework:
| Windows | InstallRootDirectory\CAAApplicationFrame.edu\CAAAfrGeoWindows.m\ |
| Unix | InstallRootDirectory/CAAApplicationFrame.edu/CAAAfrGeoWindows.m/ |
where InstallRootDirectory is the directory where the CAA CD-ROM
is installed. It includes the CAAAfrCustomWindow.h header file in the
PrivateInterfaces directory of the CAAApplicationFrame.edu framework and the
CAAAfrCustomWindow.cpp source file in the src directory.
[Top]
To create the custom window, there are five steps:
| # | Step | Where |
|---|---|---|
| 1 | Create the custom window class | LocalInterfaces and src |
| 2 | Provide the dialog object behavior | Build method |
| 3 | Provide the MDI document window behavior | Build method |
| 4 | Duplicate the window | Duplicate method |
| 5 | Delete the window | DeleteWindow and Destructor |
[Top]
This document window includes two 3D viewers of different sizes located in the upper part of the window, and a 2D viewer located in the lower part of the window. The class for this window is CAAAfrCustomWindow, whose header file is as follows.
class CAAAfrCustomWindow: public CATFrmWindow
{
public:
CAAAfrCustomWindow(const CATString & iName, CATFrmEditor * iEditor=NULL);
virtual ~CAAAfrCustomWindow();
virtual CATFrmWindow * DuplicateWindow();
virtual void DeleteWindow();
void Build();
void GetViewers(CATNavigation3DViewer ** oV1,
CATNavigation3DViewer ** oV2,
CATNavigation2DViewer ** oV3);
...
private:
CATNavigation3DViewer * _pViewer1;
CATNavigation3DViewer * _pViewer2;
CATNavigation2DViewer * _pViewer3;
CATPathElement * _pRootObjectPath;
};
|
CAAAfrCustomWindow has
DuplicateWindow method used by the New Window command of
the Window menu.DeleteWindow method called when the end user closes the
window or closes the document.Build method as all the Dialog boxes.GetViewers method to retrieve pointers to its three
viewers. The constructor class is simple.
CAAAfrCustomWindow::CAAAfrCustomWindow(const CATString & iName,
CATFrmEditor * iEditor)
: CATFrmWindow(iName, iEditor),
_pViewer1(NULL), _pViewer2(NULL), _pViewer3(NULL),
_pRootObjectPath(NULL),
{
}
|
[Top]
The dialog object behavior consists in:
The constructor creates the viewers, arranges them in the window and sets one of them the current viewer.
void CAAAfrCustomWindow::Build()
{
int width, height;
CATString ViewerName;
CATDlgFrame * FrameWindow = GetViewerFrame() ;
CATString FrameName = "FrameName";
CATDlgFrame * Frame = new CATDlgFrame(FrameWindow, FrameName,
CATDlgGridLayout|CATDlgFraNoFrame);
ViewerName = "Viewer3Dnum1";
width = 200 ; height = 200;
_pViewer1 = new CATNavigation3DViewer(Frame, ViewerName, width, height);
ViewerName = "Viewer3Dnum2" ;
width = 200 ; height = 300 ;
_pViewer2 = new CATNavigation3DViewer(Frame, ViewerName, width, height);
ViewerName = "Viewer2D" ;
width = 200 ; height = 500 ;
_pViewer3 = new CATNavigation2DViewer(Frame, ViewerName, width, height);
...
|
The viewer sizes are given in pixels. The MDI application window, here
named Frame, is the parent of the viewers. This frame has been created to be
inserted between the frame created by the CATFrmWindow ( FrameWindow
) and the viewers. It allows us to arrange the viewers with the grid layout
and not with the tabulation layout [3] which is a
little bit more complex. The FrameWindow frame has not been
created with the CATDlgGridLayout style [1].
... FrameWindow->Attach4Sides(Frame); _pViewer1->SetGridConstraints(0,0,1,1,CATGRID_4SIDES); _pViewer2->SetGridConstraints(0,1,1,1,CATGRID_4SIDES); _pViewer3->SetGridConstraints(1,0,2,1,CATGRID_4SIDES); Frame->SetGridRowResizable(0,1); Frame->SetGridRowResizable(1,1); Frame->SetGridColumnResizable(0,1); Frame->SetGridColumnResizable(1,1); ... |
The Attach4Sides method attaches the Frame
object to the four sides of the FrameWindow object. It is a
method used by the tabulation layout.
Then the SetGridConstraints method applied to _Viewer1
is located on grid cells beginning with the cell at the intersection of the
row 0 and column 0, and expands from left to right on 1 row, and from top to
bottom on 1 column. CATGRID_4SIDES means that the viewer
occupies the whole cell space. Row 0 and 1, as well as columns 0 and 1, as
first argument of the SetGridxxResizable methods, are declared
to be resizable since the second argument is 1 (on the opposite, 0 means non
resizable.)

... _pViewer1->Reframe(); SetViewer(_pViewer1); ... |
The Reframe method ensures that the whole contents of _pViewer1
is displayed, while the SetViewer method sets _pViewer1
as the current viewer. You will retrieve this viewer with the GetViewer
method of the CATFrmWindow class.
We have now a nice document window, but few interactive mechanisms are available. Let's assign them now.
[Top]
The MDI document window behavior consists in:
Still in the Build method, let's now the unique
visualization manager be aware of the document to display, under which
viewpoints. The GetEditor method of the CATFrmWindow
enables you to retrieve the editor of the constructor class.
... CATFrmEditor * pEditor = GetEditor(); CATVisManager * pVisuManager = CATVisManager::GetVisManager(); // Here is the code to retrieve the root model, pRootObject ... |
In this article the code to retrieve the model to display is not explained once it is not useful for a real V5 document.
...
if ( (NULL != pEditor ) && (NULL != pRootObject ) && (NULL != pVisuManager) )
{
_pRootObjectPath = new CATPathElement(pRootObject);
CATCommand * CommandSelector = (CATCommand*) pEditor->GetCommandSelector();
list<IID> ListIVisu3d, ListIVisu2d;
IID visu3d = IID_CATI3DGeoVisu;
IID visu2d = IID_CATI2DGeoVisu;
ListIVisu3d.fastadd(&visu3d);
ListIVisu2d.fastadd(&visu2d);
CATViewpoint * pViewPoint1 = NULL;
CATViewpoint * pViewPoint2 = NULL;
CATViewpoint * pViewPoint3 = NULL;
pViewPoint1 = (CATViewpoint*) &(_pViewer1->GetMain3DViewpoint());
pVisuManager->AttachTo(_pRootObjectPath,pViewPoint1,ListIVisu3d,CommandSelector);
pViewPoint2 = (CATViewpoint*) &(_pViewer2->GetMain3DViewpoint());
pVisuManager->AttachTo(_pRootObjectPath,pViewPoint2,ListIVisu3d,CommandSelector);
pViewPoint3 = (CATViewpoint*) &(_pViewer3->GetMain2DViewpoint());
pVisuManager->AttachTo(_pRootObjectPath,pViewPoint3,ListIVisu2d,CommandSelector);
...
|
If the editor, the visualization manager, and the root object are successfully retrieved, this root object is then turned to a CATPathElement, the command selector, that is, the command that stands at the top of the command tree [4], is retrieved, and the lists of 2D and 3D interfaces implemented by the objects of the documents are set up. Then for each viewer, its main viewpoint is retrieved and attached to the visualization manager along with the document's root object, the list of interfaces to use, and the command selector.
...
CATPSO * pPSO = pEditor->GetPSO() ; // Preselected Set Objects
CATHSO * pHSO = pEditor->GetHSO() ; // Highlighted Set Objects
pVisuManager->AttachPSOTo(pPSO, pViewPoint1);
pVisuManager->AttachPSOTo(pPSO, pViewPoint2);
pVisuManager->AttachPSOTo(pPSO, pViewPoint3);
pVisuManager->AttachHSOTo(pHSO, pViewPoint1);
pVisuManager->AttachHSOTo(pHSO, pViewPoint2);
pVisuManager->AttachHSOTo(pHSO, pViewPoint3);
CATISO * pISO = pEditor->GetISO();
pISO->AddViewer(_pViewer1);
pISO->AddViewer(_pViewer2);
pISO->AddViewer(_pViewer3);
}
}
}
...
|
This piece of code retrieves the Preselected Set of Objects (PSO) and the Highlighted Set of Objects (HSO) from the editor, and requests the visualization controller to attach the appropriate viewpoints to the PSO and to the HSO. Now, when the end user moves the mouse above a representation in a viewer, the path element corresponding to this representation is put in the PSO, is highlighted and put in the HSO.
The Interactive Set of Objects (ISO) is also retrieved. These objects are those which don't belong to the document, but that are so handy to manipulate representations in viewers, such as handles to move or deform them. The ISO now knows the three viewers.
The document window Build method is now complete.
[Top]
This is done thanks to the Duplicate method.
...
CATFrmWindow * CAAAfrCustomWindow :: DuplicateWindow()
{
CATString NameOfThis = GetBaseName().CastToCharPtr();
CAAAfrCustomWindow * pWindowToReturn = NULL;
pWindowToReturn = new CAAAfrCustomWindow(NameOfThis,GetEditor());
pWindowToReturn->Build();
pWindowToReturn->SetBaseName(GetBaseName());
float r,v,b ;
if (NULL != _pViewer1) _pViewer1->GetBackgroundColor(&r, &v, &b);
CATNavigation3DViewer * pV1 = NULL;
CATNavigation3DViewer * pV2 = NULL;
CATNavigation2DViewer * pV3 = NULL;
pWindowToReturn->GetViewers(&pV1, &pV2, &pV3);
if (NULL != pV1) pV1->SetBackgroundColor(r, v, b);
return pWindowToReturn;
}
...
|
The Duplicate method is now complete. It performs the following:
SetBaseName
method modifies the name of the first window if only one exists. At the base
name, an index is added [2].This method uses the GetViewers method below:
void CAAAfrCustomWindow :: GetViewers(CATNavigation3DViewer ** oV1,
CATNavigation3DViewer ** oV2,
CATNavigation2DViewer ** oV3)
{
*oV1 = _pViewer1;
*oV2 = _pViewer2;
*oV3 = _pViewer3;
}
|
[Top]
...
void CAAAfrCustomWindow::DeleteWindow()
{
if ( (NULL != GetEditor()) && (NULL != pViewer1) &&
(NULL != pViewer2) && (NULL != pViewer3) )
{
// Detaches Viewers from the ISO
CATISO *pISO = NULL;
pISO = GetEditor()->GetISO();
if (NULL != pISO) pISO->RemoveViewer(_pViewer1);
if (NULL != pISO) pISO->RemoveViewer(_pViewer2);
if (NULL != pISO) pISO->RemoveViewer(_pViewer3);
// Retrieves Viewpoints
CATViewpoint * pViewpoint1 = NULL;
CATViewpoint * pViewpoint2 = NULL;
CATViewpoint * pViewpoint3 = NULL;
pViewpoint1 = (CATViewPoint *) &(_pViewer1->GetMain3DViewpoint());
pViewpoint2 = (CATViewPoint *) &(_pViewer2->GetMain3DViewpoint());
pViewpoint3 = (CATViewPoint *) &(_pViewer3->GetMain2DViewpoint());
// Retrieves the unique visu manager
CATVisManager *pVisuManager = CATVisManager::GetVisManager();
if ( (NULL != pViewpoint1) &&
(NULL != pViewpoint2) &&
(NULL != pViewpoint3) && (NULL != pVisuManager) )
{
// Detaches Viewpoints from PSO and HSO
pVisuManager->DetachPSOFrom(pViewpoint1);
pVisuManager->DetachPSOFrom(pViewpoint2);
pVisuManager->DetachPSOFrom(pViewpoint3);
pVisuManager->DetachHSOFrom(pViewpoint1);
pVisuManager->DetachHSOFrom(pViewpoint2);
pVisuManager->DetachHSOFrom(pViewpoint3);
// Detaches Viewpoints from the visu manager
pVisuManager->DetachFrom(_pRootObjectPath, pViewpoint1);
pVisuManager->DetachFrom(_pRootObjectPath, pViewpoint2);
pVisuManager->DetachFrom(_pRootObjectPath, pViewpoint3);
}
}
CATFrmWindow::DeleteWindow();
}
CAAAfrCustomWindow::~CAAAfrCustomWindow()
{
if (NULL != _pRootObjectPath) delete _pRootObjectPath;
_pRootObjectPath = NULL;
}
...
|
The document window is deleted thanks to the DeleteWindow
method, that removes the viewers from the ISO, then retrieves their viewpoints
and detaches them from the PSO and from the HSO, and that recursively
calls the DeleteWindow method of the base class. The destructor
simply deletes the path to the root object. No need to delete the viewers, since
as any dialog object, they will be automatically deleted when the window itself
will be deleted.
[Top]
This use case explains the structure of a document's window class:
Build method
DuplicateWindow method to create a new instance from an
existing one. DeleteWindow method to detach the root's document and the
Interactive Set Objects from the command tree. [Top]
| [1] | Creating a Document's Window - Part 1 |
| [2] | Understanding the Application Frame Layout |
| [3] | Arranging Dialog Objects |
| [4] | The CAA Command Model |
| [Top] | |
| Version: 1 [Jan 2000] | Document created |
| Version: 2 [Mar 2003] | Document updated |
| [Top] | |
Copyright © 2000, Dassault Systèmes. All rights reserved.