Geant4 11.1.1
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4GenericMessenger.cc
Go to the documentation of this file.
1// ********************************************************************
2// * License and Disclaimer *
3// * *
4// * The Geant4 software is copyright of the Copyright Holders of *
5// * the Geant4 Collaboration. It is provided under the terms and *
6// * conditions of the Geant4 Software License, included in the file *
7// * LICENSE and available at http://cern.ch/geant4/license . These *
8// * include a list of copyright holders. *
9// * *
10// * Neither the authors of this software system, nor their employing *
11// * institutes,nor the agencies providing financial support for this *
12// * work make any representation or warranty, express or implied, *
13// * regarding this software system or assume any liability for its *
14// * use. Please see the license in the file LICENSE and URL above *
15// * for the full disclaimer and the limitation of liability. *
16// * *
17// * This code implementation is the result of the scientific and *
18// * technical work of the GEANT4 collaboration. *
19// * By using, copying, modifying or distributing the software (or *
20// * any work based on the software) you agree to acknowledge its *
21// * use in resulting scientific publications, and indicate your *
22// * acceptance of all terms of the Geant4 Software license. *
23// ********************************************************************
24//
25// G4GenericMessenger
26//
27// Author:
28// P.Mato, CERN - 27 September 2012
29// Updates:
30// M.Asai, SLAC - 26 November 2013
31// Adding methods with unit declaration and making thread-safe for
32// version 10.
33// M.Asai, SLAC - 04 May 2014
34// Fix core dump when GetCurrentValue() method is invoked for
35// a command defined by DeclareMethod().
36// M.Asai, SLAC - 11 July 2021
37// Adding G4ThreeVector type without unit
38// --------------------------------------------------------------------
39
40#include "G4GenericMessenger.hh"
41#include "G4Types.hh"
42#include "G4UImessenger.hh"
43#include "G4UIcommand.hh"
45#include "G4UIcmdWith3Vector.hh"
47#include "G4UIdirectory.hh"
48#include "G4Threading.hh"
49
50#include <iostream>
51
52class G4InvalidUICommand : public std::bad_cast
53{
54 public:
55 G4InvalidUICommand() = default;
56 const char* what() const throw() override
57 {
58 return "G4InvalidUICommand: command does not exist or is of invalid type";
59 }
60};
61
63 const G4String& doc)
64 : directory(dir)
65 , object(obj)
66{
67 dircmd = new G4UIdirectory(dir);
68 dircmd->SetGuidance(doc);
69}
70
72{
73 delete dircmd;
74 for(const auto& propertie : properties)
75 {
76 delete propertie.second.command;
77 }
78 for(const auto& method : methods)
79 {
80 delete method.second.command;
81 }
82}
83
85 const G4String& name, const G4AnyType& var, const G4String& doc)
86{
87 G4String fullpath = directory + name;
88 G4UIcommand* cmd = nullptr;
89 if(var.TypeInfo() == typeid(G4ThreeVector))
90 {
91 cmd = new G4UIcmdWith3Vector(fullpath.c_str(), this);
92 (static_cast<G4UIcmdWith3Vector*>(cmd))
93 ->SetParameterName("valueX", "valueY", "valueZ", false, false);
94 }
95 else
96 {
97 cmd = new G4UIcommand(fullpath.c_str(), this);
98 char ptype;
99 if(var.TypeInfo() == typeid(int) || var.TypeInfo() == typeid(long) ||
100 var.TypeInfo() == typeid(unsigned int) ||
101 var.TypeInfo() == typeid(unsigned long))
102 { ptype = 'i'; }
103 else if(var.TypeInfo() == typeid(float) || var.TypeInfo() == typeid(double))
104 { ptype = 'd'; }
105 else if(var.TypeInfo() == typeid(bool))
106 { ptype = 'b'; }
107 else if(var.TypeInfo() == typeid(G4String))
108 { ptype = 's'; }
109 else
110 { ptype = 's'; }
111 cmd->SetParameter(new G4UIparameter("value", ptype, false));
112 }
113 if(!doc.empty())
114 { cmd->SetGuidance(doc); }
115 return properties[name] = Property(var, cmd);
116}
117
119 const G4String& name, const G4String& defaultUnit, const G4AnyType& var,
120 const G4String& doc)
121{
122 if(var.TypeInfo() != typeid(float) && var.TypeInfo() != typeid(double) &&
123 var.TypeInfo() != typeid(G4ThreeVector))
124 {
125 return DeclareProperty(name, var, doc);
126 }
127 G4String fullpath = directory + name;
128 G4UIcommand* cmd;
129 if(var.TypeInfo() == typeid(float) || var.TypeInfo() == typeid(double))
130 {
131 cmd = new G4UIcmdWithADoubleAndUnit(fullpath.c_str(), this);
132 (static_cast<G4UIcmdWithADoubleAndUnit*>(cmd))
133 ->SetParameterName("value", false, false);
134 (static_cast<G4UIcmdWithADoubleAndUnit*>(cmd))->SetDefaultUnit(defaultUnit);
135 }
136 else
137 {
138 cmd = new G4UIcmdWith3VectorAndUnit(fullpath.c_str(), this);
139 (static_cast<G4UIcmdWith3VectorAndUnit*>(cmd))
140 ->SetParameterName("valueX", "valueY", "valueZ", false, false);
141 (static_cast<G4UIcmdWith3VectorAndUnit*>(cmd))->SetDefaultUnit(defaultUnit);
142 }
143
144 if(!doc.empty())
145 {
146 cmd->SetGuidance(doc);
147 }
148 return properties[name] = Property(var, cmd);
149}
150
152 const G4String& name, const G4AnyMethod& fun, const G4String& doc)
153{
154 G4String fullpath = directory + name;
155 auto* cmd = new G4UIcommand(fullpath.c_str(), this);
156 if(!doc.empty())
157 {
158 cmd->SetGuidance(doc);
159 }
160 for(std::size_t i = 0; i < fun.NArg(); ++i)
161 {
162 G4String argNam = "arg" + ItoS((G4int)i);
163 char ptype = 's';
164 auto& tInfo = fun.ArgType(i);
165 if(tInfo == typeid(int) || tInfo == typeid(long) ||
166 tInfo == typeid(unsigned int) ||
167 tInfo == typeid(unsigned long))
168 { ptype = 'i'; }
169 else if(tInfo == typeid(float) || tInfo == typeid(double))
170 { ptype = 'd'; }
171 else if(tInfo == typeid(bool))
172 { ptype = 'b'; }
173 else if(tInfo == typeid(G4String))
174 { ptype = 's'; }
175 else
176 { ptype = 's'; }
177 cmd->SetParameter(new G4UIparameter(argNam, ptype, false));
178 }
179 return methods[name] = Method(fun, object, cmd);
180}
181
183 const G4String& name, const G4String& defaultUnit, const G4AnyMethod& fun,
184 const G4String& doc)
185{
186 G4String fullpath = directory + name;
187 if(fun.NArg() != 1)
188 {
190 ed << "G4GenericMessenger::DeclareMethodWithUnit() does not support a "
191 "method that has more than\n"
192 << "one arguments (or no argument). Please use "
193 "G4GenericMessenger::DeclareMethod method for\n"
194 << "your command <" << fullpath << ">.";
195 G4Exception("G4GenericMessenger::DeclareMethodWithUnit()", "Intercom70002",
196 FatalException, ed);
197 }
198 G4UIcommand* cmd = new G4UIcmdWithADoubleAndUnit(fullpath.c_str(), this);
199 (static_cast<G4UIcmdWithADoubleAndUnit*>(cmd))
200 ->SetParameterName("value", false, false);
201 (static_cast<G4UIcmdWithADoubleAndUnit*>(cmd))->SetDefaultUnit(defaultUnit);
202 if(!doc.empty())
203 {
204 cmd->SetGuidance(doc);
205 }
206 return methods[name] = Method(fun, object, cmd);
207}
208
210{
211 if(properties.find(command->GetCommandName()) != properties.cend())
212 {
213 Property& p = properties[command->GetCommandName()];
214 return p.variable.ToString();
215 }
216 else if(methods.find(command->GetCommandName()) != methods.cend())
217 {
218 G4cout << " GetCurrentValue() is not available for a command defined by "
219 "G4GenericMessenger::DeclareMethod()."
220 << G4endl;
221 return G4String();
222 }
223 else
224 {
225 throw G4InvalidUICommand();
226 }
227}
228
230{
231 // Check if there are units on this commands
232 if(typeid(*command) == typeid(G4UIcmdWithADoubleAndUnit))
233 {
236 }
237 else if(typeid(*command) == typeid(G4UIcmdWith3VectorAndUnit))
238 {
241 }
242
243 if(properties.find(command->GetCommandName()) != properties.cend())
244 {
245 Property& p = properties[command->GetCommandName()];
246 p.variable.FromString(newValue);
247 }
248 else if(methods.find(command->GetCommandName()) != methods.cend())
249 {
250 Method& m = methods[command->GetCommandName()];
251 if(m.method.NArg() == 0)
252 {
253 m.method.operator()(m.object);
254 }
255 else if(m.method.NArg() > 0)
256 {
257 m.method.operator()(m.object, newValue);
258 }
259 else
260 {
261 throw G4InvalidUICommand();
262 }
263 }
264}
265
267{
268 dircmd->SetGuidance(s);
269}
270
272 const G4String& unit, UnitSpec spec)
273{
274 // Change the type of command (unfortunatelly this is done a posteriory)
275 // We need to delete the old command before creating the new one and therefore
276 // we need to recover the information before the deletetion
278 {
279 G4String cmdpath = command->GetCommandPath();
281 ed << "G4GenericMessenger::Command::SetUnit() is thread-unsafe and should "
282 "not be used\n"
283 << "in multi-threaded mode. For your command <" << cmdpath << ">, use\n"
284 << " DeclarePropertyWithUnit(const G4String& name, const G4String& "
285 "defaultUnit,\n"
286 << " const G4AnyType& variable, const G4String& "
287 "doc)\n"
288 << "or\n"
289 << " DeclareMethodWithUnit(const G4String& name, const G4String& "
290 "defaultUnit,\n"
291 << " const G4AnyType& variable, const G4String& "
292 "doc)\n"
293 << "to define a command with a unit <" << unit << ">.";
294 if(spec != UnitDefault)
295 {
296 ed << "\nPlease use a default unit instead of unit category.";
297 }
298 G4Exception("G4GenericMessenger::Command::SetUnit()", "Intercom70001",
299 FatalException, ed);
300 return *this;
301 }
302
303 G4String cmdpath = command->GetCommandPath();
304 G4UImessenger* messenger = command->GetMessenger();
305 G4String range = command->GetRange();
306 std::vector<G4String> guidance;
308 G4bool par_omitable = command->GetParameter(0)->IsOmittable();
309 for(G4int i = 0; i < (G4int)command->GetGuidanceEntries(); ++i)
310 {
311 guidance.push_back(command->GetGuidanceLine(i));
312 }
313 // Before deleting the command we need to add a fake one to avoid deleting
314 // the directory entry and with its guidance
315 G4UIcommand tmp((cmdpath + "_tmp").c_str(), messenger);
316 delete command;
317
318 if(*type == typeid(float) || *type == typeid(double))
319 {
320 auto* cmd_t = new G4UIcmdWithADoubleAndUnit(cmdpath, messenger);
321 if(spec == UnitDefault)
322 {
323 cmd_t->SetDefaultUnit(unit);
324 }
325 else if(spec == UnitCategory)
326 {
327 cmd_t->SetUnitCategory(unit);
328 }
329 cmd_t->SetParameterName(par_name, par_omitable);
330 command = cmd_t;
331 }
332 else if(*type == typeid(G4ThreeVector))
333 {
334 auto* cmd_t = new G4UIcmdWith3VectorAndUnit(cmdpath, messenger);
335 if(spec == UnitDefault)
336 {
337 cmd_t->SetDefaultUnit(unit);
338 }
339 else if(spec == UnitCategory)
340 {
341 cmd_t->SetUnitCategory(unit);
342 }
343 command = cmd_t;
344 }
345 else
346 {
347 G4cerr << "Only parameters of type <double> or <float> can be associated "
348 "with units"
349 << G4endl;
350 return *this;
351 }
352 for(auto& i : guidance)
353 {
355 }
356 command->SetRange(range);
357 return *this;
358}
359
361 const G4String& name, G4bool omittable, G4bool currentAsDefault)
362{
363 return SetParameterName(0,name,omittable,currentAsDefault);
364}
365
367 G4int pIdx,
368 const G4String& name, G4bool omittable, G4bool currentAsDefault)
369{
370 if(pIdx < 0 || pIdx >= (G4int)(command->GetParameterEntries()))
371 {
372 G4cerr << "Invalid parameter index : " << pIdx << "\nMethod ignored."
373 << G4endl;
374 return *this;
375 }
376 G4UIparameter* theParam = command->GetParameter(pIdx);
377 theParam->SetParameterName(name);
378 theParam->SetOmittable(omittable);
379 theParam->SetCurrentAsDefault(currentAsDefault);
380 return *this;
381}
382
384 const G4String& namex, const G4String& namey, const G4String& namez,
385 G4bool omittable, G4bool currentAsDefault)
386{
387 if(*type != typeid(G4ThreeVector))
388 {
389 G4cerr << "This SetParameterName method is for G4ThreeVector!! "
390 << "Method ignored." << G4endl;
391 return *this;
392 }
393 G4UIparameter* theParam = command->GetParameter(0);
394 theParam->SetParameterName(namex);
395 theParam->SetOmittable(omittable);
396 theParam->SetCurrentAsDefault(currentAsDefault);
397 theParam = command->GetParameter(1);
398 theParam->SetParameterName(namey);
399 theParam->SetOmittable(omittable);
400 theParam->SetCurrentAsDefault(currentAsDefault);
401 theParam = command->GetParameter(2);
402 theParam->SetParameterName(namez);
403 theParam->SetOmittable(omittable);
404 theParam->SetCurrentAsDefault(currentAsDefault);
405 return *this;
406}
407
409 const G4String& candList)
410{
411 return SetCandidates(0,candList);
412}
413
415 G4int pIdx, const G4String& candList)
416{
417 if(pIdx < 0 || pIdx >= (G4int)(command->GetParameterEntries()))
418 {
419 G4cerr << "Invalid parameter index : " << pIdx << "\nMethod ignored."
420 << G4endl;
421 return *this;
422 }
423 G4UIparameter* theParam = command->GetParameter(pIdx);
424 theParam->SetParameterCandidates(candList);
425 return *this;
426}
427
429 const G4String& defVal)
430{
431 return SetDefaultValue(0,defVal);
432}
433
435 G4int pIdx, const G4String& defVal)
436{
437 if(pIdx < 0 || pIdx >= (G4int)(command->GetParameterEntries()))
438 {
439 G4cerr << "Invalid parameter index : " << pIdx << "\nMethod ignored."
440 << G4endl;
441 return *this;
442 }
443 G4UIparameter* theParam = command->GetParameter(pIdx);
444 theParam->SetDefaultValue(defVal);
445 return *this;
446}
@ FatalException
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
Definition: G4Exception.cc:59
std::ostringstream G4ExceptionDescription
Definition: G4Exception.hh:40
bool G4bool
Definition: G4Types.hh:86
int G4int
Definition: G4Types.hh:85
G4GLOB_DLL std::ostream G4cerr
#define G4endl
Definition: G4ios.hh:57
G4GLOB_DLL std::ostream G4cout
std::size_t NArg() const
Definition: G4AnyMethod.hh:157
const std::type_info & ArgType(size_t n=0) const
Definition: G4AnyMethod.hh:159
void FromString(const std::string &val)
Definition: G4AnyType.hh:130
const std::type_info & TypeInfo() const
Definition: G4AnyType.hh:115
std::string ToString() const
Definition: G4AnyType.hh:128
Command & DeclareMethod(const G4String &name, const G4AnyMethod &fun, const G4String &doc="")
void SetGuidance(const G4String &s)
~G4GenericMessenger() override
Command & DeclareProperty(const G4String &name, const G4AnyType &variable, const G4String &doc="")
Command & DeclareMethodWithUnit(const G4String &name, const G4String &defaultUnit, const G4AnyMethod &fun, const G4String &doc="")
G4GenericMessenger(void *obj, const G4String &dir="", const G4String &doc="")
void SetNewValue(G4UIcommand *command, G4String newValue) override
G4String GetCurrentValue(G4UIcommand *command) override
Command & DeclarePropertyWithUnit(const G4String &name, const G4String &defaultUnit, const G4AnyType &variable, const G4String &doc="")
G4InvalidUICommand()=default
const char * what() const override
G4UImessenger * GetMessenger() const
Definition: G4UIcommand.hh:145
const G4String & GetGuidanceLine(G4int i) const
Definition: G4UIcommand.hh:133
G4UIparameter * GetParameter(G4int i) const
Definition: G4UIcommand.hh:140
static G4String ConvertToString(G4bool boolVal)
Definition: G4UIcommand.cc:446
const G4String & GetCommandPath() const
Definition: G4UIcommand.hh:137
void SetParameter(G4UIparameter *const newParameter)
Definition: G4UIcommand.hh:147
void SetGuidance(const char *aGuidance)
Definition: G4UIcommand.hh:157
std::size_t GetGuidanceEntries() const
Definition: G4UIcommand.hh:129
void SetRange(const char *rs)
Definition: G4UIcommand.hh:121
static G4double ConvertToDimensionedDouble(const char *st)
Definition: G4UIcommand.cc:588
const G4String & GetCommandName() const
Definition: G4UIcommand.hh:138
const G4String & GetRange() const
Definition: G4UIcommand.hh:128
static G4ThreeVector ConvertToDimensioned3Vector(const char *st)
Definition: G4UIcommand.cc:612
G4String ItoS(G4int i)
void SetDefaultValue(const char *theDefaultValue)
void SetParameterName(const char *pName)
G4bool IsOmittable() const
void SetOmittable(G4bool om)
void SetParameterCandidates(const char *theString)
void SetCurrentAsDefault(G4bool val)
const G4String & GetParameterName() const
G4bool IsMultithreadedApplication()
Definition: G4Threading.cc:130
Command & SetParameterName(const G4String &, G4bool, G4bool=false)
Command & SetCandidates(const G4String &)
Command & SetDefaultValue(const G4String &)
const std::type_info * type
Command & SetUnit(const G4String &, UnitSpec=UnitDefault)