Geant4 11.1.1
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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)