Salome HOME
Redesign SALOME documentation
[modules/gui.git] / doc / salome / gui / input / use_case_builder.rst
1 .. _use_case_builder: 
2
3 *************************************************************************************
4 Customize data tree representation in the Object browser by means of use case builder
5 *************************************************************************************
6
7 .. contents:: Table of Contents
8
9 In SALOME, the representation of the data tree in the Object browser for the *full*
10 (CORBA-based) module is done basing on the study contents as it is supplied by SALOME
11 data server (SALOMEDS). In contrast to the *light* module which data tree is completely
12 defined and can be easily attuned by the module specific implementation, *full* module
13 must publish its data in the CORBA study by means of the corresponding API of SALOME
14 data server, namely **SALOMEDS::StudyBuilder**.
15
16 As soon as data entities are published
17 in the study, they are shown in the Object browser, in the same order as they appear
18 in the study tree. Re-arrangement of the data entities with such approach is not a 
19 trivial task: for example, when copying/moving any data entity at the new position
20 within the tree, it is necessary to copy all its attributes as well
21 and to clear (in case of move operation) the data entity at the original position. Also, it is not possible to
22 make some data items in the tree "invisible" for the user (though it might be useful).
23
24 Use case builder provides an alternative and more flexible way for customizing the
25 data tree representation. It implements another approach to the data tree hierarchy,
26 based on the tree node attributes. With use case builder it is possible to arrange
27 and easily re-arrange the data items in the data tree in any appropriate way.
28
29 For example, with use case builder it is easy to implement such operations as
30 :ref:`drag_and_drop` and Copy/Cut/Paste. With use case builder approach
31 it is not important how data entities are arranged in the study tree, they even may 
32 lie on the same level - use case builder allows providing custom data tree
33 representation, completely indepedent on the study data tree itself. It is even possible
34 to hide some data entities in the tree representation while still keeping them in the
35 study (to store specific module data).
36
37 Object browser automatically checks it the module root data object
38 contains a tree node attribute and switches to the browsing of the
39 data tree for such module using the use case
40 builder. Otherwise, it browses data using an ordinary study tree iterator. Thus, it is
41 possible to have in the same study some modules based on use case builder approach and
42 others not using it.
43
44 .. _use_case_builder_usage:
45
46 Use case builder
47 ================
48
49 To obtain a reference to the use case builder, the function **GetUseCaseBuilder()** 
50 of the **SALOMEDS::Study** interface can be used:
51
52 ::
53
54         interface Study
55         {
56          // Get reference to the use case builder
57           UseCaseBuilder GetUseCaseBuilder(); 
58         };
59
60 **SALOMEDS::UseCaseBuilder** interface of the **SALOMEDS CORBA** module provides several
61 methods that can be used to build a custom data tree. Its API is similar to the API of
62 **SALOMEDS::StudyBuilder** interface - it operates with terms  *"father object"* and
63 *"child object"*. In addition, use case builder uses term *"current object"* that is
64 used as a parent of the children objects added if the parent is not explicitly 
65 specified.
66
67 ::
68
69         interface UseCaseBuilder
70         {
71           // Set top-level root object of the use case tree as the current one.
72           // This method is usually used to add SComponent items to the top level of the tree
73           boolean SetRootCurrent();
74   
75          // Set the object theObject as the current object of the use case builder
76           boolean SetCurrentObject(in SObject theObject);
77   
78           // Append object SObject to the end of children list of the current object
79          boolean Append(in SObject theObject);
80   
81           // Append object SObject to the end of children list of the parent object theFather
82           boolean AppendTo(in SObject theFather, in SObject theObject);
83          
84           // Insert object theFirst before the object theNext (under the same parent object)
85           boolean InsertBefore(in SObject theFirst, in SObject theNext);
86   
87           // Remove object from the use case tree (without removing it from the study)
88           boolean Remove(in SObject theObject);
89           
90          // Check if the object theObject has children (in the use case tree)
91           boolean HasChildren(in SObject theObject);
92           
93           // Get father object of the given object theObject in the use cases tree
94           SObject GetFather(in SObject theObject);
95          
96           // Check if given object theObject is added to the use case tree
97          boolean IsUseCaseNode(in SObject theObject);
98          
99           // Get the current object of the use case builder
100           SObject GetCurrentObject();
101         };
102
103
104 .. _browse_use_case_tree: 
105
106 Browsing use case data tree
107 ===========================
108
109 Browsing the use case tree can be done by means of the use case iterator, that is
110 provided by the  **SALOMEDS::UseCaseIterator** interface of the **SALOMEDS CORBA**
111 module. Access to the use case iterator can be done via **SALOMEDS::UseCaseBuilder**
112 interface:
113
114 ::
115
116         interface UseCaseBuilder
117         {
118           // Get a reference to the use case iterator and initialize it
119           // by the given object theObject
120           UseCaseIterator GetUseCaseIterator(in SObject theObject);
121         };
122
123
124 The API of the **SALOMEDS::UseCaseIterator** interface is similar to the 
125 **SALOMEDS::ChildIterator**:
126
127 ::
128
129         interface UseCaseIterator
130         {
131           // Activate or reset use case iterator; boolean parameter allLevels
132           // specifies if the iterator should browse recursively on all sub-levels or
133           // on the first sub-level only.
134           void Init(in boolean allLevels);
135           // Check if the iterator can browse to the next item
136           boolean More();
137           // Browse the iterator to the next object
138           void Next();
139           // Get the object currently pointed by the iterator
140           SObject Value();
141         };
142
143 Typical usage of the **UseCaseIterator** is as follows:
144
145 ::
146
147         // get use case builder
148         SALOMEDS::UseCaseBuilder_var useCaseBuilder = study->GetUseCaseBuilder();
149
150         // get the use case iterator
151         SALOMEDS::UseCaseIterator_var iter = useCaseIter->GetUseCaseIterator( sobject.in() );
152         // iterate through the sub-items recursively
153         for ( useCaseIter->Init( true ); useCaseIter->More(); useCaseIter->Next() ) {
154           SALOMEDS::SObject_var child = useCaseIter->Value();
155           // do something with the child
156           // ...
157           // clean-up
158          child->UnRegister();
159         }
160         // clean-up
161         useCaseIter->UnRegister();
162         useCaseBuilder->UnRegister();
163
164 .. _use_case_compatibility:
165
166 Remark about compatibility with existing studies
167 ================================================
168
169 If you decide to switch your module to the use case builder approach to provide
170 customization for the data tree representation, you must take care of compatibility
171 with existing SALOME studies. Basically it means that you have to add
172 a simple code to  **Load()** (and **LoadASCII()** if necessary) method
173 of your module, which adds tree node attributes to all data entities
174 in the data tree of your module. The simplest way to do
175 this is to iterate through all data items and recursively add them to
176 the use case builder:
177
178 ::
179
180         // find component
181         SALOMEDS::SComponent_var comp = study->FindComponent( "MYMODULE" );
182         // add tree node attributes only if component data is present in the study
183         if ( !CORBA::is_nil( comp ) ) {
184           // get the use case builder
185           SALOMEDS::UseCaseBuilder_var useCaseBuilder = study->GetUseCaseBuilder();
186           // check if tree nodes are already set
187           if ( !useCaseBuilder->IsUseCaseNode( comp.in() ) ) {
188             // set the current node of the use case builder to the root
189             useCaseBuilder->SetRootCurrent();
190             // add component item to the top level of the use case tree
191             useCaseBuilder->Append( comp.in() );
192             // iterate through all child items recursively
193             SALOMEDS::ChildIterator_var iter = study->NewChildIterator( comp.in() );
194             for ( iter->InitEx( true ); iter->More(); iter->Next() ) {
195               SALOMEDS::SObject_var sobj   = iter->Value();
196               SALOMEDS::SObject_var father = sobj->GetFather();
197               // add an object to the corresponding level in the use case tree
198               useCaseBuilder->AppendTo( father.in(), sobj.in() );
199               // clean up (avoid memory leaks)
200               sobj->UnRegister();
201               father->UnRegister();
202             }
203           }
204           useCaseBuilder->UnRegister(); // clean up
205         }
206