Geant4-11
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
57 virtual const char* what() const throw()
58 {
59 return "G4InvalidUICommand: command does not exist or is of invalid type";
60 }
61};
62
64 const G4String& doc)
65 : directory(dir)
66 , object(obj)
67{
68 dircmd = new G4UIdirectory(dir);
69 dircmd->SetGuidance(doc);
70}
71
73{
74 delete dircmd;
75 for(auto i = properties.cbegin(); i != properties.cend(); ++i)
76 delete i->second.command;
77 for(auto i = methods.cbegin(); i != methods.cend(); ++i)
78 delete i->second.command;
79}
80
82 const G4String& name, const G4AnyType& var, const G4String& doc)
83{
84 G4String fullpath = directory + name;
85 G4UIcommand* cmd = nullptr;
86 if(var.TypeInfo() == typeid(G4ThreeVector))
87 {
88 cmd = new G4UIcmdWith3Vector(fullpath.c_str(), this);
89 (static_cast<G4UIcmdWith3Vector*>(cmd))
90 ->SetParameterName("valueX", "valueY", "valueZ", false, false);
91 }
92 else
93 {
94 cmd = new G4UIcommand(fullpath.c_str(), this);
95 char ptype;
96 if(var.TypeInfo() == typeid(int) || var.TypeInfo() == typeid(long) ||
97 var.TypeInfo() == typeid(unsigned int) ||
98 var.TypeInfo() == typeid(unsigned long))
99 { ptype = 'i'; }
100 else if(var.TypeInfo() == typeid(float) || var.TypeInfo() == typeid(double))
101 { ptype = 'd'; }
102 else if(var.TypeInfo() == typeid(bool))
103 { ptype = 'b'; }
104 else if(var.TypeInfo() == typeid(G4String))
105 { ptype = 's'; }
106 else
107 { ptype = 's'; }
108 cmd->SetParameter(new G4UIparameter("value", ptype, false));
109 }
110 if(doc != "")
111 { cmd->SetGuidance(doc); }
112 return properties[name] = Property(var, cmd);
113}
114
116 const G4String& name, const G4String& defaultUnit, const G4AnyType& var,
117 const G4String& doc)
118{
119 if(var.TypeInfo() != typeid(float) && var.TypeInfo() != typeid(double) &&
120 var.TypeInfo() != typeid(G4ThreeVector))
121 {
122 return DeclareProperty(name, var, doc);
123 }
124 G4String fullpath = directory + name;
125 G4UIcommand* cmd;
126 if(var.TypeInfo() == typeid(float) || var.TypeInfo() == typeid(double))
127 {
128 cmd = new G4UIcmdWithADoubleAndUnit(fullpath.c_str(), this);
129 (static_cast<G4UIcmdWithADoubleAndUnit*>(cmd))
130 ->SetParameterName("value", false, false);
131 (static_cast<G4UIcmdWithADoubleAndUnit*>(cmd))->SetDefaultUnit(defaultUnit);
132 }
133 else
134 {
135 cmd = new G4UIcmdWith3VectorAndUnit(fullpath.c_str(), this);
136 (static_cast<G4UIcmdWith3VectorAndUnit*>(cmd))
137 ->SetParameterName("valueX", "valueY", "valueZ", false, false);
138 (static_cast<G4UIcmdWith3VectorAndUnit*>(cmd))->SetDefaultUnit(defaultUnit);
139 }
140
141 if(doc != "")
142 cmd->SetGuidance(doc);
143 return properties[name] = Property(var, cmd);
144}
145
147 const G4String& name, const G4AnyMethod& fun, const G4String& doc)
148{
149 G4String fullpath = directory + name;
150 G4UIcommand* cmd = new G4UIcommand(fullpath.c_str(), this);
151 if(doc != "")
152 cmd->SetGuidance(doc);
153 for(std::size_t i = 0; i < fun.NArg(); ++i)
154 {
155 G4String argNam = "arg" + ItoS(i);
156 char ptype = 's';
157 auto& tInfo = fun.ArgType(i);
158 if(tInfo == typeid(int) || tInfo == typeid(long) ||
159 tInfo == typeid(unsigned int) ||
160 tInfo == typeid(unsigned long))
161 { ptype = 'i'; }
162 else if(tInfo == typeid(float) || tInfo == typeid(double))
163 { ptype = 'd'; }
164 else if(tInfo == typeid(bool))
165 { ptype = 'b'; }
166 else if(tInfo == typeid(G4String))
167 { ptype = 's'; }
168 else
169 { ptype = 's'; }
170 cmd->SetParameter(new G4UIparameter(argNam, ptype, false));
171 }
172 return methods[name] = Method(fun, object, cmd);
173}
174
176 const G4String& name, const G4String& defaultUnit, const G4AnyMethod& fun,
177 const G4String& doc)
178{
179 G4String fullpath = directory + name;
180 if(fun.NArg() != 1)
181 {
183 ed << "G4GenericMessenger::DeclareMethodWithUnit() does not support a "
184 "method that has more than\n"
185 << "one arguments (or no argument). Please use "
186 "G4GenericMessenger::DeclareMethod method for\n"
187 << "your command <" << fullpath << ">.";
188 G4Exception("G4GenericMessenger::DeclareMethodWithUnit()", "Intercom70002",
189 FatalException, ed);
190 }
191 G4UIcommand* cmd = new G4UIcmdWithADoubleAndUnit(fullpath.c_str(), this);
192 (static_cast<G4UIcmdWithADoubleAndUnit*>(cmd))
193 ->SetParameterName("value", false, false);
194 (static_cast<G4UIcmdWithADoubleAndUnit*>(cmd))->SetDefaultUnit(defaultUnit);
195 if(doc != "")
196 cmd->SetGuidance(doc);
197 return methods[name] = Method(fun, object, cmd);
198}
199
201{
202 if(properties.find(command->GetCommandName()) != properties.cend())
203 {
204 Property& p = properties[command->GetCommandName()];
205 return p.variable.ToString();
206 }
207 else if(methods.find(command->GetCommandName()) != methods.cend())
208 {
209 G4cout << " GetCurrentValue() is not available for a command defined by "
210 "G4GenericMessenger::DeclareMethod()."
211 << G4endl;
212 return G4String();
213 }
214 else
215 {
216 throw G4InvalidUICommand();
217 }
218}
219
221{
222 // Check if there are units on this commands
223 if(typeid(*command) == typeid(G4UIcmdWithADoubleAndUnit))
224 {
227 }
228 else if(typeid(*command) == typeid(G4UIcmdWith3VectorAndUnit))
229 {
232 }
233
234 if(properties.find(command->GetCommandName()) != properties.cend())
235 {
236 Property& p = properties[command->GetCommandName()];
237 p.variable.FromString(newValue);
238 }
239 else if(methods.find(command->GetCommandName()) != methods.cend())
240 {
241 Method& m = methods[command->GetCommandName()];
242 if(m.method.NArg() == 0)
243 m.method.operator()(m.object);
244 else if(m.method.NArg() > 0)
245 {
246 m.method.operator()(m.object, newValue);
247 }
248 else
249 {
250 throw G4InvalidUICommand();
251 }
252 }
253}
254
256{
258}
259
261 const G4String& unit, UnitSpec spec)
262{
263 // Change the type of command (unfortunatelly this is done a posteriory)
264 // We need to delete the old command before creating the new one and therefore
265 // we need to recover the information before the deletetion
267 {
268 G4String cmdpath = command->GetCommandPath();
270 ed << "G4GenericMessenger::Command::SetUnit() is thread-unsafe and should "
271 "not be used\n"
272 << "in multi-threaded mode. For your command <" << cmdpath << ">, use\n"
273 << " DeclarePropertyWithUnit(const G4String& name, const G4String& "
274 "defaultUnit,\n"
275 << " const G4AnyType& variable, const G4String& "
276 "doc)\n"
277 << "or\n"
278 << " DeclareMethodWithUnit(const G4String& name, const G4String& "
279 "defaultUnit,\n"
280 << " const G4AnyType& variable, const G4String& "
281 "doc)\n"
282 << "to define a command with a unit <" << unit << ">.";
283 if(spec != UnitDefault)
284 {
285 ed << "\nPlease use a default unit instead of unit category.";
286 }
287 G4Exception("G4GenericMessenger::Command::SetUnit()", "Intercom70001",
288 FatalException, ed);
289 return *this;
290 }
291
292 G4String cmdpath = command->GetCommandPath();
293 G4UImessenger* messenger = command->GetMessenger();
294 G4String range = command->GetRange();
295 std::vector<G4String> guidance;
297 G4bool par_omitable = command->GetParameter(0)->IsOmittable();
298 for(std::size_t i = 0; i < command->GetGuidanceEntries(); ++i)
299 guidance.push_back(command->GetGuidanceLine(i));
300 // Before deleting the command we need to add a fake one to avoid deleting
301 // the directory entry and with its guidance
302 G4UIcommand tmp((cmdpath + "_tmp").c_str(), messenger);
303 delete command;
304
305 if(*type == typeid(float) || *type == typeid(double))
306 {
308 new G4UIcmdWithADoubleAndUnit(cmdpath, messenger);
309 if(spec == UnitDefault)
310 cmd_t->SetDefaultUnit(unit);
311 else if(spec == UnitCategory)
312 cmd_t->SetUnitCategory(unit);
313 cmd_t->SetParameterName(par_name, par_omitable);
314 command = cmd_t;
315 }
316 else if(*type == typeid(G4ThreeVector))
317 {
319 new G4UIcmdWith3VectorAndUnit(cmdpath, messenger);
320 if(spec == UnitDefault)
321 cmd_t->SetDefaultUnit(unit);
322 else if(spec == UnitCategory)
323 cmd_t->SetUnitCategory(unit);
324 command = cmd_t;
325 }
326 else
327 {
328 G4cerr << "Only parameters of type <double> or <float> can be associated "
329 "with units"
330 << G4endl;
331 return *this;
332 }
333 for(std::size_t i = 0; i < guidance.size(); ++i)
334 command->SetGuidance(guidance[i]);
335 command->SetRange(range);
336 return *this;
337}
338
340 const G4String& name, G4bool omittable, G4bool currentAsDefault)
341{
342 return SetParameterName(0,name,omittable,currentAsDefault);
343}
344
346 G4int pIdx,
347 const G4String& name, G4bool omittable, G4bool currentAsDefault)
348{
349 if(pIdx < 0 || pIdx >= (G4int)(command->GetParameterEntries()))
350 {
351 G4cerr << "Invalid parameter index : " << pIdx << "\nMethod ignored."
352 << G4endl;
353 return *this;
354 }
355 G4UIparameter* theParam = command->GetParameter(pIdx);
356 theParam->SetParameterName(name);
357 theParam->SetOmittable(omittable);
358 theParam->SetCurrentAsDefault(currentAsDefault);
359 return *this;
360}
361
363 const G4String& namex, const G4String& namey, const G4String& namez,
364 G4bool omittable, G4bool currentAsDefault)
365{
366 if(*type != typeid(G4ThreeVector))
367 {
368 G4cerr << "This SetParameterName method is for G4ThreeVector!! "
369 << "Method ignored." << G4endl;
370 return *this;
371 }
372 G4UIparameter* theParam = command->GetParameter(0);
373 theParam->SetParameterName(namex);
374 theParam->SetOmittable(omittable);
375 theParam->SetCurrentAsDefault(currentAsDefault);
376 theParam = command->GetParameter(1);
377 theParam->SetParameterName(namey);
378 theParam->SetOmittable(omittable);
379 theParam->SetCurrentAsDefault(currentAsDefault);
380 theParam = command->GetParameter(2);
381 theParam->SetParameterName(namez);
382 theParam->SetOmittable(omittable);
383 theParam->SetCurrentAsDefault(currentAsDefault);
384 return *this;
385}
386
388 const G4String& candList)
389{
390 return SetCandidates(0,candList);
391}
392
394 G4int pIdx, const G4String& candList)
395{
396 if(pIdx < 0 || pIdx >= (G4int)(command->GetParameterEntries()))
397 {
398 G4cerr << "Invalid parameter index : " << pIdx << "\nMethod ignored."
399 << G4endl;
400 return *this;
401 }
402 G4UIparameter* theParam = command->GetParameter(pIdx);
403 theParam->SetParameterCandidates(candList);
404 return *this;
405}
406
408 const G4String& defVal)
409{
410 return SetDefaultValue(0,defVal);
411}
412
414 G4int pIdx, const G4String& defVal)
415{
416 if(pIdx < 0 || pIdx >= (G4int)(command->GetParameterEntries()))
417 {
418 G4cerr << "Invalid parameter index : " << pIdx << "\nMethod ignored."
419 << G4endl;
420 return *this;
421 }
422 G4UIparameter* theParam = command->GetParameter(pIdx);
423 theParam->SetDefaultValue(defVal);
424 return *this;
425}
@ FatalException
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
Definition: G4Exception.cc:35
std::ostringstream G4ExceptionDescription
Definition: G4Exception.hh:40
static constexpr double m
Definition: G4SIunits.hh:109
static constexpr double s
Definition: G4SIunits.hh:154
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:158
const std::type_info & ArgType(size_t n=0) const
Definition: G4AnyMethod.hh:160
void FromString(const std::string &val)
Definition: G4AnyType.hh:129
const std::type_info & TypeInfo() const
Definition: G4AnyType.hh:116
std::string ToString() const
Definition: G4AnyType.hh:127
Command & DeclareMethod(const G4String &name, const G4AnyMethod &fun, const G4String &doc="")
void SetGuidance(const G4String &s)
virtual void SetNewValue(G4UIcommand *command, G4String newValue)
G4UIdirectory * dircmd
Command & DeclareProperty(const G4String &name, const G4AnyType &variable, const G4String &doc="")
virtual G4String GetCurrentValue(G4UIcommand *command)
Command & DeclareMethodWithUnit(const G4String &name, const G4String &defaultUnit, const G4AnyMethod &fun, const G4String &doc="")
G4GenericMessenger(void *obj, const G4String &dir="", const G4String &doc="")
std::map< G4String, Method > methods
Command & DeclarePropertyWithUnit(const G4String &name, const G4String &defaultUnit, const G4AnyType &variable, const G4String &doc="")
std::map< G4String, Property > properties
virtual const char * what() const
void SetDefaultUnit(const char *defUnit)
void SetUnitCategory(const char *unitCategory)
void SetUnitCategory(const char *unitCategory)
void SetDefaultUnit(const char *defUnit)
void SetParameterName(const char *theName, G4bool omittable, G4bool currentAsDefault=false)
G4UImessenger * GetMessenger() const
Definition: G4UIcommand.hh:144
const G4String & GetGuidanceLine(G4int i) const
Definition: G4UIcommand.hh:132
G4UIparameter * GetParameter(G4int i) const
Definition: G4UIcommand.hh:139
static G4String ConvertToString(G4bool boolVal)
Definition: G4UIcommand.cc:445
const G4String & GetCommandPath() const
Definition: G4UIcommand.hh:136
void SetParameter(G4UIparameter *const newParameter)
Definition: G4UIcommand.hh:146
void SetGuidance(const char *aGuidance)
Definition: G4UIcommand.hh:156
std::size_t GetGuidanceEntries() const
Definition: G4UIcommand.hh:128
void SetRange(const char *rs)
Definition: G4UIcommand.hh:120
static G4double ConvertToDimensionedDouble(const char *st)
Definition: G4UIcommand.cc:584
const G4String & GetCommandName() const
Definition: G4UIcommand.hh:137
const G4String & GetRange() const
Definition: G4UIcommand.hh:127
static G4ThreeVector ConvertToDimensioned3Vector(const char *st)
Definition: G4UIcommand.cc:608
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
const char * name(G4int ptype)
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)