Geant4 Cross Reference |
1 // ******************************************* 1 2 // * License and Disclaimer 3 // * 4 // * The Geant4 software is copyright of th 5 // * the Geant4 Collaboration. It is provided 6 // * conditions of the Geant4 Software License 7 // * LICENSE and available at http://cern.ch/ 8 // * include a list of copyright holders. 9 // * 10 // * Neither the authors of this software syst 11 // * institutes,nor the agencies providing fin 12 // * work make any representation or warran 13 // * regarding this software system or assum 14 // * use. Please see the license in the file 15 // * for the full disclaimer and the limitatio 16 // * 17 // * This code implementation is the result 18 // * technical work of the GEANT4 collaboratio 19 // * By using, copying, modifying or distri 20 // * any work based on the software) you ag 21 // * use in resulting scientific publicati 22 // * acceptance of all terms of the Geant4 Sof 23 // ******************************************* 24 // 25 // G4UIcommandTree 26 // 27 // Author: Makoto Asai (SLAC), 1998 28 // Midified: Makoto Asai (SLAC), 2021 29 // Improve output HTML file layout and add o 30 // command/directory names in alphabetic ord 31 // ------------------------------------------- 32 33 #include "G4UIcommandTree.hh" 34 35 #include "G4StateManager.hh" 36 #include "G4UIdirectory.hh" 37 #include "G4UImanager.hh" 38 #include "G4ios.hh" 39 40 #include <fstream> 41 42 // ------------------------------------------- 43 G4UIcommandTree::G4UIcommandTree(const char* t 44 { 45 pathName = thePathName; 46 } 47 48 // ------------------------------------------- 49 G4UIcommandTree::~G4UIcommandTree() 50 { 51 for (auto& i : tree) { 52 delete i; 53 } 54 } 55 56 // ------------------------------------------- 57 G4bool G4UIcommandTree::operator==(const G4UIc 58 { 59 return (pathName == right.GetPathName()); 60 } 61 62 // ------------------------------------------- 63 G4bool G4UIcommandTree::operator!=(const G4UIc 64 { 65 return (pathName != right.GetPathName()); 66 } 67 68 // ------------------------------------------- 69 void G4UIcommandTree::AddNewCommand(G4UIcomman 70 { 71 G4String commandPath = newCommand->GetComman 72 G4String remainingPath = commandPath; 73 remainingPath.erase(0, pathName.length()); 74 if (remainingPath.empty()) { 75 if (guidance == nullptr) { 76 guidance = newCommand; 77 if (!(newCommand->ToBeBroadcasted())) { 78 broadcastCommands = false; 79 } 80 if (workerThreadOnly) { 81 newCommand->SetWorkerThreadOnly(); 82 } 83 } 84 return; 85 } 86 87 if (guidance != nullptr) { 88 auto* dir = static_cast<G4UIdirectory*>(gu 89 ifSort = dir->IfSort(); 90 } 91 std::size_t i = remainingPath.find('/'); 92 if (i == std::string::npos) { 93 // Adding a new command to this directory 94 std::size_t n_commandEntry = command.size( 95 for (std::size_t i_thCommand = 0; i_thComm 96 if (remainingPath == command[i_thCommand 97 // a command of same name has already 98 if (G4UImanager::GetUIpointer()->GetVe 99 G4ExceptionDescription ed; 100 ed << "Command <" << commandPath << 101 G4Exception("G4UIcommandTree::AddNew 102 // FatalException, 103 JustWarning, ed); 104 } 105 return; 106 } 107 } 108 if (!broadcastCommands) { 109 newCommand->SetToBeBroadcasted(false); 110 } 111 if (workerThreadOnly) { 112 newCommand->SetWorkerThreadOnly(); 113 } 114 if (ifSort) { 115 auto j = command.cbegin(); 116 for (; j != command.cend(); ++j) { 117 if (newCommand->GetCommandPath() < (*j 118 break; 119 } 120 } 121 command.insert(j, newCommand); 122 } 123 else { 124 command.push_back(newCommand); 125 } 126 return; 127 } 128 129 // Adding a new command to a sub-directory 130 G4String nextPath = pathName; 131 nextPath.append(remainingPath.substr(0, i + 132 std::size_t n_treeEntry = tree.size(); 133 for (std::size_t i_thTree = 0; i_thTree < n_ 134 if (nextPath == tree[i_thTree]->GetPathNam 135 if (!broadcastCommands) { 136 newCommand->SetToBeBroadcasted(false); 137 } 138 tree[i_thTree]->AddNewCommand(newCommand 139 return; 140 } 141 } 142 // Creating a new sub-directory 143 auto* newTree = new G4UIcommandTree(nextPath 144 if (ifSort) { 145 auto j = tree.cbegin(); 146 for (; j != tree.cend(); ++j) { 147 if (newTree->GetPathName() < (*j)->GetPa 148 break; 149 } 150 } 151 tree.insert(j, newTree); 152 } 153 else { 154 tree.push_back(newTree); 155 } 156 if (!broadcastCommands) { 157 newCommand->SetToBeBroadcasted(false); 158 } 159 // In case a new sub-directry is created wit 160 // (most-likely this is the case), inherit t 161 newCommand->SetDefaultSortFlag(ifSort); 162 newTree->AddNewCommand(newCommand, workerThr 163 return; 164 } 165 166 // ------------------------------------------- 167 void G4UIcommandTree::RemoveCommand(G4UIcomman 168 { 169 if (workerThreadOnly && !(aCommand->IsWorker 170 return; 171 } 172 G4String commandPath = aCommand->GetCommandP 173 commandPath.erase(0, pathName.length()); 174 if (commandPath.empty()) { 175 guidance = nullptr; 176 } 177 else { 178 std::size_t i = commandPath.find('/'); 179 if (i == std::string::npos) { 180 // Find command 181 std::size_t n_commandEntry = command.siz 182 for (std::size_t i_thCommand = 0; i_thCo 183 if (commandPath == command[i_thCommand 184 command.erase(command.begin() + i_th 185 break; 186 } 187 } 188 } 189 else { 190 // Find path 191 G4String nextPath = pathName; 192 nextPath.append(commandPath.substr(0, i 193 std::size_t n_treeEntry = tree.size(); 194 for (std::size_t i_thTree = 0; i_thTree 195 if (nextPath == tree[i_thTree]->GetPat 196 tree[i_thTree]->RemoveCommand(aComma 197 G4int n_commandRemain = tree[i_thTre 198 G4int n_treeRemain = tree[i_thTree]- 199 if (n_commandRemain == 0 && n_treeRe 200 G4UIcommandTree* emptyTree = tree[ 201 tree.erase(tree.begin() + i_thTree 202 delete emptyTree; 203 } 204 break; 205 } 206 } 207 } 208 } 209 } 210 211 // ------------------------------------------- 212 G4UIcommand* G4UIcommandTree::FindPath(const c 213 { 214 // This function tries to match a command na 215 216 G4String remainingPath = commandPath; 217 if (remainingPath.find(pathName) == std::str 218 return nullptr; 219 } 220 remainingPath.erase(0, pathName.length()); 221 std::size_t i = remainingPath.find('/'); 222 if (i == std::string::npos) { 223 // Find command 224 std::size_t n_commandEntry = command.size( 225 for (std::size_t i_thCommand = 0; i_thComm 226 if (remainingPath == command[i_thCommand 227 return command[i_thCommand]; 228 } 229 } 230 } 231 else { 232 // Find path 233 G4String nextPath = pathName; 234 nextPath.append(remainingPath.substr(0, i 235 std::size_t n_treeEntry = tree.size(); 236 for (std::size_t i_thTree = 0; i_thTree < 237 if (nextPath == tree[i_thTree]->GetPathN 238 return tree[i_thTree]->FindPath(comman 239 } 240 } 241 } 242 return nullptr; 243 } 244 245 // ------------------------------------------- 246 G4UIcommandTree* G4UIcommandTree::FindCommandT 247 { 248 // Try to match a command or a path with the 249 // @commandPath : command or path to match 250 // @return the commandTree found or nullptr 251 252 G4String remainingPath = commandPath; 253 if (remainingPath.find(pathName) == std::str 254 return nullptr; 255 } 256 remainingPath.erase(0, pathName.length()); 257 std::size_t i = remainingPath.find('/'); 258 if (i != std::string::npos) { 259 // Find path 260 G4String nextPath = pathName; 261 nextPath.append(remainingPath.substr(0, i 262 std::size_t n_treeEntry = tree.size(); 263 for (std::size_t i_thTree = 0; i_thTree < 264 if (tree[i_thTree]->GetPathName() == com 265 return tree[i_thTree]; 266 } 267 if (nextPath == tree[i_thTree]->GetPathN 268 return tree[i_thTree]->FindCommandTree 269 } 270 } 271 } 272 else { 273 return this; 274 } 275 return nullptr; 276 } 277 278 // ------------------------------------------- 279 G4String G4UIcommandTree::CompleteCommandPath( 280 { 281 G4String pName = aCommandPath; 282 G4String remainingPath = aCommandPath; 283 G4String empty = ""; 284 G4String matchingPath = empty; 285 286 // find the tree 287 auto jpre = pName.rfind('/'); 288 if (jpre != G4String::npos) { 289 pName.erase(jpre + 1); 290 } 291 G4UIcommandTree* aTree = FindCommandTree(pNa 292 293 if (aTree == nullptr) { 294 return empty; 295 } 296 297 if (pName.find(pName) == std::string::npos) 298 return empty; 299 } 300 301 std::vector<G4String> paths; 302 303 // list matched directories/commands 304 G4String strtmp; 305 G4int nMatch = 0; 306 307 G4int Ndir = aTree->GetTreeEntry(); 308 G4int Ncmd = aTree->GetCommandEntry(); 309 310 // directory ... 311 for (G4int idir = 1; idir <= Ndir; ++idir) { 312 const G4String& fpdir = aTree->GetTree(idi 313 // matching test 314 if (fpdir.find(remainingPath, 0) == 0) { 315 if (nMatch == 0) { 316 matchingPath = fpdir; 317 } 318 else { 319 matchingPath = GetFirstMatchedString(f 320 } 321 ++nMatch; 322 paths.push_back(fpdir); 323 } 324 } 325 326 if (paths.size() >= 2) { 327 G4cout << "Matching directories :" << G4en 328 for (const auto& path : paths) { 329 G4cout << path << G4endl; 330 } 331 } 332 333 // command ... 334 std::vector<G4String> commands; 335 336 for (G4int icmd = 1; icmd <= Ncmd; ++icmd) { 337 G4String fpcmd = aTree->GetPathName() + aT 338 // matching test 339 if (fpcmd.find(remainingPath, 0) == 0) { 340 if (nMatch == 0) { 341 matchingPath = fpcmd + " "; 342 } 343 else { 344 strtmp = fpcmd + " "; 345 matchingPath = GetFirstMatchedString(m 346 } 347 nMatch++; 348 commands.emplace_back(fpcmd + " "); 349 } 350 } 351 352 if (commands.size() >= 2) { 353 G4cout << "Matching commands :" << G4endl; 354 for (const auto& matched : commands) { 355 G4cout << matched << G4endl; 356 } 357 } 358 359 return matchingPath; 360 } 361 362 // ------------------------------------------- 363 G4String G4UIcommandTree::GetFirstMatchedStrin 364 { 365 std::size_t nlen1 = str1.length(); 366 std::size_t nlen2 = str2.length(); 367 368 std::size_t nmin = nlen1 < nlen2 ? nlen1 : n 369 370 G4String strMatched; 371 for (G4int i = 0; i < (G4int)nmin; ++i) { 372 if (str1[i] == str2[i]) { 373 strMatched += str1[i]; 374 } 375 else { 376 break; 377 } 378 } 379 380 return strMatched; 381 } 382 383 // ------------------------------------------- 384 void G4UIcommandTree::ListCurrent() const 385 { 386 G4cout << "Command directory path : " << pat 387 if (guidance != nullptr) { 388 guidance->List(); 389 } 390 G4cout << " Sub-directories : " << G4endl; 391 std::size_t n_treeEntry = tree.size(); 392 for (std::size_t i_thTree = 0; i_thTree < n_ 393 G4cout << " " << tree[i_thTree]->GetPath 394 if ((tree[i_thTree]->GetGuidance() != null 395 && tree[i_thTree]->GetGuidance()->IsWo 396 { 397 G4cout << " @ "; 398 } 399 else { 400 G4cout << " "; 401 } 402 G4cout << tree[i_thTree]->GetTitle() << G4 403 } 404 G4cout << " Commands : " << G4endl; 405 std::size_t n_commandEntry = command.size(); 406 for (std::size_t i_thCommand = 0; i_thComman 407 G4cout << " " << command[i_thCommand]->G 408 if (command[i_thCommand]->IsWorkerThreadOn 409 G4cout << " @ "; 410 } 411 else { 412 G4cout << " * "; 413 } 414 G4cout << command[i_thCommand]->GetTitle() 415 } 416 } 417 418 // ------------------------------------------- 419 void G4UIcommandTree::ListCurrentWithNum() con 420 { 421 G4cout << "Command directory path : " << pat 422 if (guidance != nullptr) { 423 guidance->List(); 424 } 425 G4int i = 0; 426 G4cout << " Sub-directories : " << G4endl; 427 std::size_t n_treeEntry = tree.size(); 428 for (std::size_t i_thTree = 0; i_thTree < n_ 429 ++i; 430 G4cout << " " << i << ") " << tree[i_thTre 431 << tree[i_thTree]->GetTitle() << G4 432 } 433 G4cout << " Commands : " << G4endl; 434 std::size_t n_commandEntry = command.size(); 435 for (std::size_t i_thCommand = 0; i_thComman 436 ++i; 437 G4cout << " " << i << ") " << command[i_th 438 << command[i_thCommand]->GetTitle() 439 } 440 } 441 442 // ------------------------------------------- 443 void G4UIcommandTree::List() const 444 { 445 ListCurrent(); 446 std::size_t n_commandEntry = command.size(); 447 for (std::size_t i_thCommand = 0; i_thComman 448 command[i_thCommand]->List(); 449 } 450 std::size_t n_treeEntry = tree.size(); 451 for (std::size_t i_thTree = 0; i_thTree < n_ 452 tree[i_thTree]->List(); 453 } 454 } 455 456 // ------------------------------------------- 457 G4String G4UIcommandTree::CreateFileName(const 458 { 459 G4String fn = pName; 460 std::size_t idxs; 461 while ((idxs = fn.find('/')) != std::string: 462 fn[(G4int)idxs] = '_'; 463 } 464 fn += ".html"; 465 return fn; 466 } 467 468 // ------------------------------------------- 469 G4String G4UIcommandTree::ModStr(const char* s 470 { 471 G4String sx; 472 G4String str = strS; 473 for (G4int i = 0; i < G4int(str.length()); + 474 char c = str[i]; 475 switch (c) { 476 case '<': 477 sx += "<"; 478 break; 479 case '>': 480 sx += ">"; 481 break; 482 case '&': 483 sx += "&"; 484 break; 485 default: 486 sx += c; 487 } 488 } 489 return sx; 490 } 491 492 // ------------------------------------------- 493 void G4UIcommandTree::CreateHTML(const G4Strin 494 { 495 G4String ofileName = CreateFileName(pathName 496 std::ofstream oF(ofileName, std::ios::out); 497 498 oF << "<html><head><title>Commands in " << M 499 oF << "<style> \ 500 table,table td,table th { \ 501 border:1px solid #eee \ 502 } \ 503 table td,table th { \ 504 padding:5px 20px; \ 505 line-height:1.3; \ 506 text-align:inherit \ 507 } \ 508 a { \ 509 color:#17a81a; \ 510 text-decoration:none; \ 511 transition-duration:0.3s \ 512 } \ 513 a:hover { \ 514 color:#17a81a \ 515 } \ 516 table { \ 517 border-collapse:collapse; \ 518 border-spacing:0; \ 519 margin-bottom:5px; \ 520 } \ 521 h1 { \ 522 font-size:2.25em; \ 523 font-weight:300; \ 524 letter-spacing:-1px; \ 525 line-height:1.15em; \ 526 margin-bottom:0.5em; \ 527 word-wrap:break-word \ 528 } \ 529 h2 { \ 530 font-size:1.5em; \ 531 font-weight:300; \ 532 letter-spacing:-1px; \ 533 line-height:1.15em; \ 534 margin-bottom:0.5em; \ 535 word-wrap:break-word \ 536 } \ 537 h3 { \ 538 color:#26282a; \ 539 font-weight:300; \ 540 font-size:1.3em; \ 541 padding:15px 0 15px 0; \ 542 border-bottom:2px #eee solid; \ 543 word-wrap:break-word \ 544 } \ 545 .sidebar { \ 546 display:block; \ 547 position:relative; \ 548 position:sticky; \ 549 float:left; \ 550 -webkit-box-sizing:border-box; \ 551 -moz-box-sizing:border-box; \ 552 -ms-box-sizing:border-box; \ 553 box-sizing:border-box; \ 554 width:20%; \ 555 padding-right:20px \ 556 } \ 557 .context { \ 558 width:80%; \ 559 display:inline-block; \ 560 background-color:#fff; \ 561 padding: 25px 35px 20px 30px; \ 562 -webkit-box-sizing:border-box; \ 563 -moz-box-sizing:border-box; \ 564 -ms-box-sizing:border-box; \ 565 box-sizing:border-box \ 566 } \ 567 </style>" 568 << G4endl; 569 oF << "<body bgcolor=\"#ffffff\">" << G4endl 570 571 // Left Panel 572 if (createHTMLTreeLevel == 0) { 573 oF << "<div class=\"sidebar\">" << sideBar 574 } 575 // Right Panel 576 oF << "<div class=\"context\">"; 577 oF << "<h1>" << ModStr(pathName) << "</h1>" 578 579 if (guidance != nullptr) { 580 for (G4int i = 0; i < (G4int)guidance->Get 581 oF << ModStr(guidance->GetGuidanceLine(i 582 } 583 } 584 if (!tree.empty()) { 585 G4String menu = ""; 586 G4String newSideBar = ""; 587 menu += "<h2>Sub-directories </h2><table>" 588 newSideBar += "<h2><a href=\"" + ofileName 589 // Build menu short version 590 for (auto& i_thTree : tree) { 591 newSideBar += "<tr><td><a href=\"" + Cre 592 + ModStr(i_thTree->GetPath 593 } 594 // Build menu 595 for (auto& i_thTree : tree) { 596 menu += "<tr><td><a href=\"" + CreateFil 597 + ModStr(i_thTree->GetPathName() 598 menu += "</td><td>" + ModStr(i_thTree->G 599 } 600 menu += "</table>"; 601 newSideBar += "</table>"; 602 for (auto& i_thTree : tree) { 603 createHTMLTreeLevel++; 604 i_thTree->CreateHTML(newSideBar); 605 createHTMLTreeLevel--; 606 } 607 oF << menu << G4endl; 608 } 609 610 if (!command.empty()) { 611 oF << "<h2>Commands </h2>" << G4endl; 612 613 // resume 614 oF << "<table>" << G4endl; 615 for (std::size_t i_thCommand = 0; i_thComm 616 G4UIcommand* cmd = command[i_thCommand]; 617 oF << "<tr><td><a href=\"#c" << i_thComm 618 oF << "</a></td></tr>" << G4endl; 619 } 620 oF << "</table>" << G4endl; 621 for (std::size_t i_thCommand = 0; i_thComm 622 G4UIcommand* cmd = command[i_thCommand]; 623 oF << "<h3 id=\"c" << i_thCommand << "\" 624 if (cmd->GetParameterEntries() > 0) { 625 for (G4int i_thParam = 0; i_thParam < 626 oF << " [<i>" << ModStr(cmd->GetPara 627 } 628 } 629 oF << "</h3>" << G4endl; 630 oF << "<p>" << G4endl; 631 for (G4int i = 0; i < (G4int)cmd->GetGui 632 oF << ModStr(cmd->GetGuidanceLine(i)) 633 } 634 if (!(cmd->GetRange()).empty()) { 635 oF << "<p>Range : " << ModStr(cmd->Get 636 } 637 std::vector<G4ApplicationState>* availab 638 if (availabelStateList->size() == 6) { 639 oF << "<p>Available at all Geant4 stat 640 } 641 else { 642 oF << "<p>Available Geant4 state(s) : 643 for (auto& ias : *availabelStateList) 644 oF << G4StateManager::GetStateManage 645 } 646 } 647 if (cmd->GetParameterEntries() > 0) { 648 oF << "<p>Parameters<table border=1>" 649 for (G4int i_thParam = 0; i_thParam < 650 G4UIparameter* prm = cmd->GetParamet 651 oF << "<tr><td>" << ModStr(prm->GetP 652 oF << "<td>type " << prm->GetParamet 653 oF << "<td>"; 654 if (prm->IsOmittable()) { 655 oF << "Omittable : "; 656 if (prm->GetCurrentAsDefault()) { 657 oF << "current value is used as 658 } 659 else { 660 oF << "default value = " << prm- 661 } 662 } 663 oF << "<td>"; 664 if (!(prm->GetParameterRange()).empt 665 oF << "Parameter range : " << ModS 666 } 667 else if (!(prm->GetParameterCandidat 668 oF << "Parameter candidates : " << 669 } 670 } 671 oF << "</table>" << G4endl; 672 } 673 } 674 } 675 oF << "</div></body></html>" << G4endl; 676 oF.close(); 677 } 678 679 // ------------------------------------------- 680 G4UIcommandTree* G4UIcommandTree::GetTree(cons 681 { 682 G4String comName = comNameC; 683 for (auto& i : tree) { 684 if (comName == i->GetPathName()) { 685 return i; 686 } 687 } 688 return nullptr; 689 } 690