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.