0030268: Inspectors - improvements in VInspector plugin
[occt.git] / tools / ToolsDraw / ToolsDraw.cxx
1 // Created on: 2017-06-16
2 // Created by: Natalia ERMOLAEVA
3 // Copyright (c) 2017 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement. 
15
16 #include <inspector/ToolsDraw.hxx>
17
18 #include <AIS_InteractiveContext.hxx>
19 #include <BRep_Builder.hxx>
20 #include <BRepTools.hxx>
21 #include <DBRep.hxx>
22 #include <DDocStd.hxx>
23 #include <Draw.hxx>
24 #include <Draw_PluginMacro.hxx>
25 #include <NCollection_DataMap.hxx>
26 #include <Standard_Stream.hxx>
27 #include <TDocStd_Application.hxx>
28 #include <TopoDS_Shape.hxx>
29 #include <ViewerTest.hxx>
30 #include <ViewerTest_DoubleMapOfInteractiveAndName.hxx>
31
32 #include <inspector/TInspectorAPI_PluginParameters.hxx>
33 #include <inspector/TInspector_Communicator.hxx>
34
35 #if ! defined(_WIN32)
36 extern ViewerTest_DoubleMapOfInteractiveAndName& GetMapOfAIS();
37 #else
38 Standard_EXPORT ViewerTest_DoubleMapOfInteractiveAndName& GetMapOfAIS();
39 #endif
40
41 static TInspector_Communicator* MyCommunicator;
42
43 // =======================================================================
44 // function : Communicator
45 // purpose  : defines plugin library name by the command argument
46 // =======================================================================
47 TInspector_Communicator* ToolsDraw::Communicator()
48 {
49   return MyCommunicator;
50 }
51
52 // =======================================================================
53 // function : convertToPluginName
54 // purpose  : defines plugin library name by the command argument
55 // =======================================================================
56 Standard_Boolean convertToPluginName (const TCollection_AsciiString& theArgument,
57                                       TCollection_AsciiString& thePluginName)
58 {
59   TCollection_AsciiString anArgument = theArgument;
60   anArgument.LowerCase();
61
62   if (anArgument == "dfbrowser")       { thePluginName = "TKDFBrowser"; return Standard_True; }
63   else if (anArgument == "shapeview")  { thePluginName = "TKShapeView"; return Standard_True; }
64   else if (anArgument == "vinspector") { thePluginName = "TKVInspector"; return Standard_True; }
65
66   return Standard_False;
67 }
68
69 // =======================================================================
70 // function : getArgumentPlugins
71 // purpose  : fills container of plugin names by the next following plugin names
72 // =======================================================================
73 void getArgumentPlugins (Standard_Integer theArgsNb, const char** theArgs, Standard_Integer& theIt,
74                          NCollection_List<TCollection_AsciiString>& thePlugins)
75 {
76   while (theIt != theArgsNb)
77   {
78     TCollection_AsciiString aPluginName;
79     if (convertToPluginName (theArgs[theIt], aPluginName))
80     {
81       if (!thePlugins.Contains (aPluginName))
82         thePlugins.Append (aPluginName);
83     }
84     else
85     {
86       break;
87     }
88     theIt++;
89   }
90   theIt--; // the last not processed parameter is the next argument
91 }
92
93 // =======================================================================
94 // function : tinspector
95 // purpose  : 
96 // =======================================================================
97 static int tinspector (Draw_Interpretor& di, Standard_Integer theArgsNb, const char** theArgs)
98 {
99   if (theArgsNb < 1)
100   {
101     std::cout << "Error: wrong number of arguments.\n";
102     return 1;
103   }
104
105   // parse command arguments
106   NCollection_List<TCollection_AsciiString> aPlugins;
107   NCollection_DataMap<TCollection_AsciiString, NCollection_List<Handle(Standard_Transient)> > aParameters;
108   NCollection_DataMap<TCollection_AsciiString, TCollection_AsciiString > anOpenFileParameters;
109   TCollection_AsciiString aPluginNameToActivate;
110   Standard_Boolean aNeedToUpdateContent = Standard_False,
111                    aNeedToHideInspector = Standard_False,
112                    aNeedToShowInspector = Standard_False,
113                    aNeedToPrintState = Standard_False,
114                    aNeedDirectory = Standard_False;
115   TCollection_AsciiString aTemporaryDirectory;
116
117   NCollection_List<Handle(Standard_Transient)> aDefaultParameters;
118   TCollection_AsciiString aDefaultOpenFileParameter;
119
120   NCollection_List<Handle(Standard_Transient)> anObjectsToSelect;
121   NCollection_List<TCollection_AsciiString> anItemNamesToSelect;
122
123   for (Standard_Integer anIt = 1; anIt < theArgsNb; ++anIt)
124   {
125     TCollection_AsciiString aParam (theArgs[anIt]);
126     aParam.LowerCase();
127
128     if (aParam.IsEqual ("-plugins")) // [-plugins {name1 [name2] ... [name3] | all}]
129     {
130       anIt++;
131       getArgumentPlugins (theArgsNb, theArgs, anIt, aPlugins);
132     }
133     else if (aParam.IsEqual ("-activate")) // [-activate name]
134     {
135       anIt++;
136       if (anIt == theArgsNb)
137       {
138         std::cout << "Empty argument of '" << aParam << "'.\n";
139         return 1;
140       }
141       TCollection_AsciiString aPluginName;
142       if (convertToPluginName (theArgs[anIt], aPluginName))
143         aPluginNameToActivate = aPluginName;
144     }
145     else if (aParam.IsEqual ("-shape")) // [-shape object [name1] ... [nameN]]
146     {
147       anIt++;
148       if (anIt == theArgsNb)
149       {
150         std::cout << "Empty argument of '" << aParam << "'.\n";
151         return 1;
152       }
153       TopoDS_Shape aShape = DBRep::Get (theArgs[anIt]);
154       anIt++;
155       if (aShape.IsNull())
156       {
157         std::cout << "Wrong shape name: " << aParam << ".\n";
158         return 1;
159       }
160       NCollection_List<TCollection_AsciiString> anArgPlugins;
161       getArgumentPlugins (theArgsNb, theArgs, anIt, anArgPlugins);
162
163       if (anArgPlugins.IsEmpty())
164       {
165         aDefaultParameters.Append (aShape.TShape());
166         anItemNamesToSelect.Append (TInspectorAPI_PluginParameters::ParametersToString (aShape));
167       }
168       else
169       {
170         for (NCollection_List<TCollection_AsciiString>::Iterator anArgIt (anArgPlugins);
171              anArgIt.More(); anArgIt.Next())
172         {
173           NCollection_List<Handle(Standard_Transient)> aPluginParameters;
174           aParameters.Find (anArgIt.Value(), aPluginParameters);
175           aPluginParameters.Append (aShape.TShape());
176           anItemNamesToSelect.Append (TInspectorAPI_PluginParameters::ParametersToString (aShape));
177           aParameters.Bind (anArgIt.Value(), aPluginParameters);
178         }
179       }
180     }
181     else if (aParam.IsEqual ("-open")) // [-open file_name [name1] ... [nameN]]
182     {
183       anIt++;
184       if (anIt == theArgsNb)
185       {
186         std::cout << "Empty argument of '" << aParam << "'.\n";
187         return 1;
188       }
189       TCollection_AsciiString aFileName (theArgs[anIt]);
190       anIt++;
191
192       NCollection_List<TCollection_AsciiString> anArgPlugins;
193       getArgumentPlugins(theArgsNb, theArgs, anIt, anArgPlugins);
194       if (anArgPlugins.IsEmpty())
195         aDefaultOpenFileParameter = aFileName;
196       else
197       {
198         for (NCollection_List<TCollection_AsciiString>::Iterator anArgIt (anArgPlugins);
199           anArgIt.More(); anArgIt.Next())
200         {
201           NCollection_List<Handle(Standard_Transient)> aPluginParameters;
202           aParameters.Find (anArgIt.Value(), aPluginParameters);
203           anOpenFileParameters.Bind (anArgIt.Value(), aFileName);
204         }
205       }
206     }
207     else if (aParam.IsEqual ("-directory")) // [-directory path]"
208     {
209       anIt++;
210       if (anIt == theArgsNb)
211       {
212         std::cout << "Empty argument of '" << aParam << "'.\n";
213         return 1;
214       }
215       aNeedDirectory = true;
216       aParam = theArgs[anIt];
217       aTemporaryDirectory = aParam.IsEqual ("default") ? "" : aParam;
218     }
219     else if (aParam.IsEqual ("-state")) // [-state]
220     {
221       aNeedToPrintState = Standard_True;
222     }
223     else if (aParam.IsEqual ("-update")) // [-update]
224     {
225       aNeedToUpdateContent = Standard_True;
226     }
227     else if (aParam.IsEqual ("-select")) // [-select {name|object}]
228     {
229       anIt++;
230       if (anIt == theArgsNb)
231       {
232         std::cout << "Empty argument of '" << aParam << "'.\n";
233         return 1;
234       }
235       // search shape with given name
236       TopoDS_Shape aShape = DBRep::Get (theArgs[anIt]);
237       if (!aShape.IsNull())
238       {
239         anObjectsToSelect.Append (aShape.TShape());
240         anItemNamesToSelect.Append (TInspectorAPI_PluginParameters::ParametersToString (aShape));
241       }
242       // search prsentations with given name
243       Handle(AIS_InteractiveObject) anIO;
244       GetMapOfAIS().Find2 (theArgs[anIt], anIO);
245       if (!anIO.IsNull())
246       {
247         anObjectsToSelect.Append (anIO);
248       }
249       // give parameters as a container of names
250       aParam = TCollection_AsciiString (theArgs[anIt]);
251       while (!aParam.StartsWith ("-"))
252       {
253         anItemNamesToSelect.Append (aParam);
254         anIt++;
255         if (anIt >= theArgsNb)
256           break;
257         aParam = theArgs[anIt];
258       }
259       anIt--;
260     }
261     else if (aParam.IsEqual ("-show")) // [-show {0|1} = 1]
262     {
263       anIt++;
264       if (anIt == theArgsNb)
265       {
266         std::cout << "Empty argument of '" << aParam << "'.\n";
267         return 1;
268       }
269       aNeedToHideInspector = Draw::Atoi (theArgs[anIt]) == 0;
270       aNeedToShowInspector = Draw::Atoi (theArgs[anIt]) > 0;
271     }
272     else
273     {
274       std::cout << "Wrong argument of command: " << aParam.ToCString() << "\n";
275       return 1;
276     }
277   }
278
279   // start inspector
280   Standard_Boolean isTInspectorCreation = !MyCommunicator;
281   if (!MyCommunicator)
282     MyCommunicator = new TInspector_Communicator();
283
284   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
285   if (!aContext.IsNull())
286     aDefaultParameters.Append (aContext);
287
288   // Sets OCAF application into DFBrowser
289   const Handle(TDocStd_Application)& anApplication = DDocStd::GetApplication();
290   // Initialize standard document formats at creation - they should
291   // be available even if this DRAW plugin is not loaded by pload command
292   if (!anApplication.IsNull())
293   {
294     NCollection_List<Handle(Standard_Transient)> aDFBrowserParameters;
295     aParameters.Find ("TKDFBrowser", aDFBrowserParameters);
296     aDFBrowserParameters.Append (anApplication);
297     aParameters.Bind ("TKDFBrowser", aDFBrowserParameters);
298   }
299
300   // by starting, if the plugns were not defined, register all
301   if (isTInspectorCreation)
302   {
303     if (aPlugins.IsEmpty())
304     {
305       aPlugins.Append ("TKDFBrowser");
306       aPlugins.Append ("TKShapeView");
307       aPlugins.Append ("TKVInspector");
308     }
309     aPluginNameToActivate = !aPluginNameToActivate.IsEmpty() ? aPluginNameToActivate : aPlugins.First();
310   }
311
312   // register plugin from parameters
313   for (NCollection_List<TCollection_AsciiString>::Iterator aPluginNameIt (aPlugins);
314        aPluginNameIt.More(); aPluginNameIt.Next())
315     MyCommunicator->RegisterPlugin (aPluginNameIt.Value());
316
317   // init all registered plugins with the default and parameters values
318   NCollection_List<TCollection_AsciiString> aRegisteredPlugins = MyCommunicator->RegisteredPlugins();
319   for (NCollection_List<TCollection_AsciiString>::Iterator anIterator (aRegisteredPlugins);
320     anIterator.More(); anIterator.Next())
321   {
322     TCollection_AsciiString aPluginName = anIterator.Value();
323     NCollection_List<Handle(Standard_Transient)> aParameterValues;
324     aParameters.Find (aPluginName, aParameterValues);
325
326     for (NCollection_List<Handle(Standard_Transient)>::Iterator aDefIt (aDefaultParameters);
327          aDefIt.More(); aDefIt.Next())
328       aParameterValues.Append (aDefIt.Value());
329     MyCommunicator->Init (aPluginName, aParameterValues, Standard_True);
330   }
331
332   if (!aPluginNameToActivate.IsEmpty())
333     MyCommunicator->Activate (!aPluginNameToActivate.IsEmpty() ? aPluginNameToActivate : aPlugins.First());
334
335   if (!anOpenFileParameters.IsEmpty())
336   {
337     for (NCollection_DataMap<TCollection_AsciiString, TCollection_AsciiString >::Iterator anOpenIt
338       (anOpenFileParameters); anOpenIt.More(); anOpenIt.Next())
339       MyCommunicator->OpenFile (anOpenIt.Key(), anOpenIt.Value());
340   }
341   else if (!aDefaultOpenFileParameter.IsEmpty()) // open file in active plugin
342     MyCommunicator->OpenFile ("", aDefaultOpenFileParameter);
343
344   if (!anObjectsToSelect.IsEmpty())
345     MyCommunicator->SetSelected (anObjectsToSelect);
346
347   if (!anItemNamesToSelect.IsEmpty())
348     MyCommunicator->SetSelected (anItemNamesToSelect);
349
350   if (aNeedDirectory)
351     MyCommunicator->SetTemporaryDirectory (aTemporaryDirectory);
352
353   if (aNeedToUpdateContent)
354     MyCommunicator->UpdateContent();
355
356   if (isTInspectorCreation || aNeedToShowInspector)
357     MyCommunicator->SetVisible (true);
358
359   if (aNeedToHideInspector)
360     MyCommunicator->SetVisible (false);
361
362   if (aNeedToPrintState)
363   {
364     Standard_SStream aSStream;
365     MyCommunicator->Dump (aSStream);
366     di << aSStream << "\n";
367   }
368
369   return 0;
370 }
371
372 // =======================================================================
373 // function : Commands
374 // purpose  : 
375 // =======================================================================
376 void ToolsDraw::Commands(Draw_Interpretor& theCommands)
377 {
378   const char *group = "Tools";
379
380   // display
381   theCommands.Add ("tinspector",
382     "tinspector [-plugins {name1 ... [nameN] | all}]"
383     "\n\t\t:            [-activate name]"
384     "\n\t\t:            [-shape object [name1] ... [nameN]]"
385     "\n\t\t:            [-open file_name [name1] ... [nameN]]"
386     "\n\t\t:            [-update]"
387     "\n\t\t:            [-select {object | name1 ... [nameN]}]"
388     "\n\t\t:            [-show {0|1} = 1]"
389     "\n\t\t:            [-directory path|<default>]"
390     "\n\t\t:            [-state]"
391     "\n\t\t: Starts tool of inspection."
392     "\n\t\t: Options:"
393     "\n\t\t:  -plugins enters plugins that should be added in the inspector."
394     "\n\t\t:           Available names are: dfbrowser, vinspector and shapeview."
395     "\n\t\t:           Plugins order will be the same as defined in arguments."
396     "\n\t\t:           'all' adds all available plugins in the order:"
397     "\n\t\t:                 DFBrowser, VInspector and ShapeView."
398     "\n\t\t:           If at the first call this option is not used, 'all' option is applied;"
399     "\n\t\t:  -activate activates the plugin in the tool view."
400     "\n\t\t:           If at the first call this option is not used, the first plugin is activated;"
401     "\n\t\t:  -shape initializes plugin/s by the shape object. If 'name' is empty, initializes all plugins;"
402     "\n\t\t:  -open gives the file to the plugin/s. If the plugin is active, after open, update content will be done;"
403     "\n\t\t:  -update updates content of the active plugin;"
404     "\n\t\t:  -select sets the parameter that should be selected in an active tool view."
405     "\n\t\t:          Depending on active tool the parameter is:"
406     "\n\t\t:          ShapeView: 'object' is an instance of TopoDS_Shape TShape,"
407     "\n\t\t:          DFBrowser: 'name' is an entry of TDF_Label and name2(optionaly) for TDF_Attribute type name,"
408     "\n\t\t:          VInspector: 'object' is an instance of AIS_InteractiveObject;"
409     "\n\t\t:  -show sets Inspector view visible or hidden. The first call of this command will show it."
410     "\n\t\t:  -directory sets Inspector temporary directory. Preferences file is stored there."
411     "\n\t\t:  -state print some current information about inspector, like name of active plugin, temporary director.",
412       __FILE__, tinspector, group);
413
414 }
415
416 // =======================================================================
417 // function : Factory
418 // purpose  : 
419 // =======================================================================
420 void ToolsDraw::Factory (Draw_Interpretor& theDI)
421 {
422   // definition of Tools Command
423   ToolsDraw::Commands (theDI);
424
425 #ifdef OCCT_DEBUG
426       theDI << "Draw Plugin : OCC Tools commands are loaded\n";
427 #endif
428 }
429
430 // Declare entry point PLUGINFACTORY
431 DPLUGIN (ToolsDraw)