LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
ParameterSetEditDialog.cxx
Go to the documentation of this file.
9 
10 #include "TGButton.h"
11 #include "TGCanvas.h"
12 #include "TGDoubleSlider.h"
13 #include "TGFrame.h"
14 #include "TGLayout.h"
15 #include "TGListBox.h"
16 #include "TGTab.h"
17 #include "TGTableLayout.h"
18 #include "TGTextEntry.h"
19 #include "TROOT.h"
20 
21 #include <sstream>
22 
23 #include "cetlib/container_algorithms.h"
24 #include "fhiclcpp/ParameterSet.h"
26 
27 using namespace evdb;
28 using namespace std::string_literals;
29 
30 namespace {
31  // Window and row sizes in units of pixels
32  constexpr unsigned int kWidth = 500 * 11 / 10;
33  constexpr unsigned int kHeight = 500 * 11 / 10;
34  constexpr unsigned int kRowW = kWidth - 150;
35  constexpr unsigned int kRowH = 18;
36 
37  // Flags to help us decide what sort of parameter we need to build a
38  // GUI for.
39  constexpr int kSINGLE_VALUED_PARAM = 1 << 0; // Expect single value
40  constexpr int kVECTOR_PARAM = 1 << 1; // Expect multiple values
41  // constexpr int kVECTOR_OF_VECTOR_PARAM = 1<<2; // Expect multiple values -
42  // never used
43  constexpr int kHAVE_GUI_TAGS = 1 << 3; // GUI tags are present
44  constexpr int kNO_GUI_TAGS = 1 << 4; // GUI tags are not present
45  constexpr int kINTEGER_PARAM = 1 << 5; // Force the value to be int
46  constexpr int kPARAMETER_SET_PARAM = 1
47  << 6; // Value is a parameter set itself
48 
49  // The short letter codes for the various GUI objects supported. Also
50  // provide a list of all possible tags.
51 
52  std::string const kTEXT_ENTRY = "te"; // A text edit box
53  std::string const kLIST_BOX_SINGLE =
54  "lbs"; // A list box, single choice allowed
55  std::string const kLIST_BOX_MULTI =
56  "lbm"; // A list box, multuiple choices allowed
57  std::string const kRADIO_BUTTONS = "rb"; // Radio buttons
58  std::string const kCHECK_BOX = "cb"; // Check boxes
59  std::string const kSLIDER = "sl"; // Slider bar
60  std::string const kSLIDER_INT = "sli"; // Slider bar, limit to integers
61 
62  std::vector<std::string> const gsGUITAG{kTEXT_ENTRY,
63  kLIST_BOX_SINGLE,
64  kLIST_BOX_MULTI,
65  kRADIO_BUTTONS,
66  kCHECK_BOX,
67  kSLIDER,
68  kSLIDER_INT};
69  std::string maybe_quoted(std::string element)
70  {
71  // If there are any symbols in the string that have special
72  // meaning in FHiCL, then escape the string with quotes.
73  if (element.find_first_of(":[{}]@") != std::string::npos) {
74  return '"' + element + '"';
75  }
76  return element;
77  }
78 }
79 
80 //======================================================================
81 //
82 // ParameterSetEditRow methods
83 //
85  TGHorizontalFrame* lhs,
86  TGHorizontalFrame* rhs,
87  const fhicl::ParameterSet& ps,
88  const std::string& key)
89  : fFrame(frame), fKEY(key)
90 {
91  //
92  // Extract information about the parameter for which we are building
93  // the GUI
94  //
95  std::string tag; // What sort of frame to build?
96  std::vector<std::string> values; // What is the current value?
97  this->UnpackParameter(ps, key, fParamFlags, tag, fChoice, values, fGUI, fDOC);
98  if (empty(values)) {
99  // What happened here? We'll crash if we continue though, so bail out.
100  return;
101  }
102 
103  if (fParamFlags & kVECTOR_PARAM) {
104  fValue = "[";
105  auto const n = size(values);
106  for (std::size_t i = 0; i < n; ++i) {
107  fValue += values[i];
108  if (i + 1 < n)
109  fValue += ",";
110  else
111  fValue += "]";
112  }
113  } else if (fParamFlags & kPARAMETER_SET_PARAM) {
114  fValue = "{";
115  fValue += values[0];
116  fValue += "}";
117  } else {
118  fValue = values[0];
119  }
120 
121  fLeftLH = new TGLayoutHints(kLHintsLeft, 1, 1, 0, 0);
122  fRightLH = new TGLayoutHints(kLHintsRight, 1, 1, 0, 0);
123 
124  fLabel = new TGTextButton(lhs,
125  key.c_str(),
126  -1,
127  TGButton::GetDefaultGC()(),
128  TGTextButton::GetDefaultFontStruct(),
129  0);
130  lhs->AddFrame(fLabel);
131  fLabel->SetToolTipText(fDOC.c_str());
132  fLabel->SetTextJustify(kTextRight);
133 
134  if (tag == kTEXT_ENTRY) {
135  this->SetupTextEntry(rhs, fParamFlags, values);
136  }
137  if (tag == kLIST_BOX_SINGLE) {
138  this->SetupListBox(rhs, fChoice, values, false);
139  }
140  if (tag == kLIST_BOX_MULTI) {
141  this->SetupListBox(rhs, fChoice, values, true);
142  }
143  if (tag == kRADIO_BUTTONS) {
144  this->SetupRadioButtons(rhs, fChoice, values);
145  }
146  if (tag == kCHECK_BOX) {
147  this->SetupCheckButton(rhs, fChoice, values);
148  }
149  if (tag == kSLIDER) {
150  this->SetupSlider(rhs, fChoice, values);
151  }
152  if (tag == kSLIDER_INT) {
153  fParamFlags |= kINTEGER_PARAM;
154  this->SetupSlider(rhs, fChoice, values);
155  }
156 }
157 
158 //......................................................................
159 
161 {
162  cet::for_all(fCheckButton, std::default_delete<TGCheckButton>{});
163  cet::for_all(fRadioButton, std::default_delete<TGRadioButton>{});
164  delete fSlider;
165  delete fListBox;
166  delete fTextEntry;
167  delete fLeftLH;
168  delete fRightLH;
169  delete fLabel;
170 }
171 
172 //......................................................................
173 
174 void
176  const std::string& key,
177  unsigned int& flag,
178  std::string& tag,
179  std::vector<std::string>& choice,
180  std::vector<std::string>& value,
181  std::string& gui,
182  std::string& doc)
183 {
184  flag = 0;
185 
186  // Try to extract GUI tags
187  try {
188  gui = p.get<std::string>(key + ".gui");
189  doc = p.get<std::string>(key + ".doc");
190  flag |= kHAVE_GUI_TAGS;
191  }
192  catch (...) {
193  // If they aren't there, try extracting it as a normal
194  // parameter. Default to providing the user with a text entry box.
195  gui = kTEXT_ENTRY;
196  doc = "See .fcl file for documentation...";
197  flag |= kNO_GUI_TAGS;
198  }
199 
200  // Parse out the GUI string to find out what type of frame to build
201  // and the choices we should present to the user
202  ParseGUItag(gui, tag, choice);
203 
204  // Now extract the assigned value(s) of the parameter
205  //
206  // The key is either just the key, or in the case of GUI-enabled
207  // parameters the key name with ".val" appended
208  std::string valkey = key;
209  if (flag & kHAVE_GUI_TAGS)
210  valkey += ".val";
211 
212  // Try first to extract a single value.
213  try {
214  auto const v = p.get<std::string>(valkey);
215  value.push_back(maybe_quoted(v));
216  flag |= kSINGLE_VALUED_PARAM;
217  return;
218  }
219  catch (...) {
220  }
221 
222  // Could not extract as single value; try extracting multiple values
223  try {
224  auto tmp = p.get<std::vector<std::string>>(valkey);
225  for (auto& element : tmp) {
226  element = maybe_quoted(element);
227  }
228  value = move(tmp);
229  flag |= kVECTOR_PARAM;
230  if (empty(value))
231  value.push_back("");
232  return;
233  }
234  catch (...) {
235  }
236 
237  // Yikes - extracting multiple values failed; try vector of vectors, perhaps?
238  try {
239  std::vector<std::vector<std::string>> vv;
240  vv = p.get<std::vector<std::vector<std::string>>>(valkey);
241 
242  // Vectors of vectors are treated as vectors of
243  // std::strings. The strings assigned to the values are
244  // strings that FHiCL will parse as vectors. So, this:
245  //
246  // [ [0,0], [1,1] ]
247  //
248  // is represented as:
249  //
250  // size(value)=2, value[0]="[0,0]", value[1]="[1,1]"
251 
252  flag |= kVECTOR_PARAM;
253  for (std::size_t i = 0; i < size(vv); ++i) {
254  std::string s{"["};
255  auto const m = size(vv[i]);
256  for (std::size_t j = 0; j < m; ++j) {
257  s += maybe_quoted(vv[i][j]);
258  if (j + 2 < m)
259  s += ",";
260  else
261  s += "]";
262  }
263  value.push_back(s);
264  }
265  if (empty(vv))
266  value.push_back("[[]]");
267  return;
268  }
269  catch (...) {
270  }
271 
272  // Above failed; what about another fhicl::ParameterSet?
273  try {
274  auto const v = p.get<fhicl::ParameterSet>(valkey);
275  flag |= kPARAMETER_SET_PARAM;
276  value.push_back(v.to_string());
277  return;
278  }
279  catch (...) {
280  }
281 
282  // Now we are very stuck.
283  MF_LOG_ERROR("ParameterSetEditDialog") << "Failed to parse " << key << "\n"
284  << p.to_string();
285 }
286 
287 //......................................................................
288 //
289 // Parse out what we can from the "gui" tag. Expected format is:
290 // "frame_tag:choice1,choice2,choice3"
291 //
292 void
293 ParameterSetEditRow::ParseGUItag(const std::string& guitag,
294  std::string& frame,
295  std::vector<std::string>& choice)
296 {
297  // Get the frame name. Should be piece just before the ":"
298  choice.clear();
299  size_t icolon = guitag.find(':');
300  if (icolon == std::string::npos)
301  frame = guitag;
302  else
303  frame = guitag.substr(0, icolon);
304  if (!IsLegalGUItag(frame))
305  frame = kTEXT_ENTRY;
306 
307  // Get the list of choices. Should be comma separated.
308  size_t icomma = icolon;
309  while (icomma != std::string::npos) {
310  size_t spos = icomma + 1;
311  size_t epos = guitag.find(',', spos);
312  std::string s = guitag.substr(spos, epos - spos);
313  choice.push_back(s);
314  icomma = epos;
315  }
316 }
317 
318 //......................................................................
319 
320 bool
322 {
323  for (std::size_t i = 0; i < gsGUITAG.size(); ++i) {
324  if (s == gsGUITAG[i])
325  return true;
326  }
327  MF_LOG_ERROR("ParameterSetEditDialog") << s << " is not a legal GUI tag.";
328  return false;
329 }
330 
331 //......................................................................
332 
333 void
335  unsigned int flags,
336  const std::vector<std::string>& value)
337 {
338  static TColor* c = gROOT->GetColor(41);
339 
340  fTextEntry = new TGTextEntry(f);
341  f->AddFrame(fTextEntry);
342  fTextEntry->SetTextColor(c);
343 
344  fTextEntry->Connect("ReturnPressed()",
345  "evdb::ParameterSetEditRow",
346  this,
347  "TextEntryReturnPressed()");
348 
349  std::string buff;
350  if (flags & kVECTOR_PARAM)
351  buff += "[";
352  if (flags & kPARAMETER_SET_PARAM)
353  buff += "{";
354  for (std::size_t i = 0; i < size(value); ++i) {
355  buff += value[i];
356  if ((i + 1) != size(value))
357  buff += ",";
358  }
359  if (flags & kVECTOR_PARAM)
360  buff += "]";
361  if (flags & kPARAMETER_SET_PARAM)
362  buff += "}";
363  fTextEntry->SetText(buff.c_str(), 0);
364  fTextEntry->Resize(kRowW, kRowH);
365 }
366 
367 //......................................................................
368 
369 void
371  const std::vector<std::string>& choice,
372  const std::vector<std::string>& value,
373  bool ismulti)
374 {
375  fListBox = new TGListBox(f);
376  f->AddFrame(fListBox);
377  if (ismulti)
378  fListBox->SetMultipleSelections();
379 
380  for (size_t i = 0; i < choice.size(); ++i) {
381  fListBox->AddEntry(choice[i].c_str(), i);
382  for (size_t j = 0; j < size(value); ++j) {
383  if (value[j] == choice[i])
384  fListBox->Select(i);
385  }
386  }
387 
388  fListBox->Connect("SelectionChanged()",
389  "evdb::ParameterSetEditRow",
390  this,
391  "ListBoxSelectionChanged()");
392  fListBox->Connect("Selected(Int_t)",
393  "evdb::ParameterSetEditRow",
394  this,
395  "ListBoxSelected(int)");
396 
397  size_t h = kRowH * choice.size();
398  if (h > 3 * kRowH)
399  h = 3 * kRowH;
400  fListBox->Resize(kRowW, h);
401 }
402 
403 //......................................................................
404 
405 void
407  const std::vector<std::string>& choice,
408  const std::vector<std::string>& value)
409 {
410  unsigned int v = atoi(value[0].c_str());
411 
412  for (size_t i = 0; i < choice.size(); ++i) {
413  TGRadioButton* b = new TGRadioButton(f, choice[i].c_str(), i);
414  f->AddFrame(b);
415 
416  b->SetTextJustify(kTextLeft);
417  b->Connect(
418  "Clicked()", "evdb::ParameterSetEditRow", this, "RadioButtonClicked()");
419 
420  if (i == v)
421  b->SetState(kButtonDown);
422 
423  fRadioButton.push_back(b);
424  }
425 }
426 
427 //......................................................................
428 
429 void
431  const std::vector<std::string>& choice,
432  const std::vector<std::string>& value)
433 {
434  unsigned int mask;
435  unsigned int v = atoi(value[0].c_str());
436  for (size_t i = 0; i < choice.size(); ++i) {
437  TGCheckButton* b = new TGCheckButton(f, choice[i].c_str(), i);
438  f->AddFrame(b);
439  b->Connect(
440  "Clicked()", "evdb::ParameterSetEditRow", this, "CheckButtonClicked()");
441 
442  mask = (0x1) << i;
443  if (v & mask)
444  b->SetState(kButtonDown);
445 
446  fCheckButton.push_back(b);
447  }
448 }
449 //......................................................................
450 void
452  const std::vector<std::string>& choice,
453  const std::vector<std::string>& value)
454 {
455  fTextEntry = new TGTextEntry(f);
456  f->AddFrame(fTextEntry);
457 
458  std::string t;
459  if (size(value) == 1) {
460  t = value[0];
461  }
462  if (size(value) == 2) {
463  t = "[";
464  t += value[0];
465  t += ",";
466  t += value[1];
467  t += "]";
468  }
469  fTextEntry->SetText(t.c_str());
470 
471  fTextEntry->Connect("ReturnPressed()",
472  "evdb::ParameterSetEditRow",
473  this,
474  "TextEntryReturnPressed()");
475 
476  fSlider = new TGDoubleHSlider(f, 100, kDoubleScaleBoth);
477  f->AddFrame(fSlider);
478 
479  float min = atof(choice[0].c_str());
480  float max = atof(choice[1].c_str());
481 
482  float pos1 = 0;
483  float pos2 = 0;
484  if (size(value) == 1) {
485  pos1 = atof(value[0].c_str());
486  pos2 = pos1;
487  }
488  if (size(value) == 2) {
489  pos1 = atof(value[0].c_str());
490  pos2 = atof(value[1].c_str());
491  }
492 
493  fSlider->SetRange(min, max);
494  fSlider->SetPosition(pos1, pos2);
495 
496  fSlider->Connect("PositionChanged()",
497  "evdb::ParameterSetEditRow",
498  this,
499  "SliderPositionChanged()");
500 
501  fTextEntry->Resize(kRowW * 1 / 5, kRowH);
502  fSlider->Resize(kRowW * 4 / 5, 10 * kRowH);
503 }
504 
505 //......................................................................
506 
507 void
509 {
510  if (fTextEntry == nullptr)
511  return;
512 
513  const char* text = fTextEntry->GetBuffer()->GetString();
514 
515  static TColor* c = gROOT->GetColor(1);
516  fTextEntry->SetTextColor(c);
517 
518  // If we also have a slider connected to this frame, make sure its
519  // state is updated
520  if (fSlider) {
521  int n = 0;
522  float f1 = 0, f2 = 0;
523  n = sscanf(text, "[%f, %f]", &f1, &f2);
524  if (n != 2) {
525  n = sscanf(text, "%f", &f1);
526  f2 = f1;
527  }
528  fSlider->SetPosition(f1, f2);
529  }
530  fValue = text;
531  fFrame->Modified();
532 }
533 
534 //......................................................................
535 
536 void
538 {
539  // Only need to handle list boxes where multiple selections are
540  // allowed here.
541  if (fListBox->GetMultipleSelections() == false)
542  return;
543 
544  fValue = "[";
545  TList selections;
546  fListBox->GetSelectedEntries(&selections);
547  TGLBEntry* sel;
548  bool isfirst = true;
549  for (unsigned int i = 0;; ++i) {
550  sel = (TGLBEntry*)selections.At(i);
551  if (sel == 0)
552  break;
553  if (!isfirst)
554  fValue += ",";
555  fValue += fChoice[sel->EntryId()];
556  isfirst = false;
557  }
558  fValue += "]";
559  fFrame->Modified();
560 }
561 
562 //......................................................................
563 
564 void
566 {
567  //
568  // Only handle single selection list boxes here
569  //
570  if (fListBox->GetMultipleSelections())
571  return;
572  fValue = fChoice[id];
573  fFrame->Modified();
574 }
575 //......................................................................
576 
577 void
579 {
580  unsigned int value = 0;
581  TGButton* b = (TGButton*)gTQSender;
582  int id = b->WidgetId();
583  for (size_t i = 0; i < fRadioButton.size(); ++i) {
584  if (fRadioButton[i]->WidgetId() != id) {
585  fRadioButton[i]->SetState(kButtonUp);
586  } else
587  value = i;
588  }
589  char buff[256];
590  sprintf(buff, "%d", value);
591  fValue = buff;
592  fFrame->Modified();
593 }
594 
595 //......................................................................
596 
597 void
599 {
600  int value = 0;
601  for (std::size_t i = 0; i < fCheckButton.size(); ++i) {
602  if (fCheckButton[i]->IsDown())
603  value |= 1 << i;
604  }
605  char buff[256];
606  sprintf(buff, "%d", value);
607  fValue = buff;
608  fFrame->Modified();
609 }
610 
611 //......................................................................
612 
613 void
615 {
616  char buff[1024];
617  float mn, mx;
618  fSlider->GetPosition(mn, mx);
619 
620  float const ave = 0.5 * (mn + mx);
621 
622  if (fParamFlags & kINTEGER_PARAM) {
623  int const mni = rint(mn);
624  int const mxi = rint(mx);
625  int const avei = rint(ave);
626  if (fParamFlags & kVECTOR_PARAM) {
627  sprintf(buff, "[%d, %d]", mni, mxi);
628  } else {
629  sprintf(buff, "%d", avei);
630  }
631  } else {
632  if (fParamFlags & kVECTOR_PARAM) {
633  sprintf(buff, "[%.1f, %.1f]", mn, mx);
634  } else {
635  sprintf(buff, "%.1f", ave);
636  }
637  }
638  fTextEntry->SetText(buff);
639  fValue = buff;
640  fFrame->Modified();
641 }
642 
643 //......................................................................
644 
645 void
647 {
648  if (fTextEntry && fValue != fTextEntry->GetBuffer()->GetString()) {
649  this->TextEntryReturnPressed();
650  }
651 }
652 
653 //......................................................................
654 
655 std::string
657 {
658  std::ostringstream s;
659  if (fParamFlags & kNO_GUI_TAGS) {
660  s << fKEY << ":" << fValue << " ";
661  } else {
662  s << fKEY << ": { "
663  << "val:" << fValue << " "
664  << "gui:\"" << fGUI << "\" "
665  << "doc:\"" << fDOC << "\" "
666  << "}";
667  }
668  return s.str();
669 }
670 
671 //======================================================================
672 //
673 // ParameterSetEditFrame methods
674 //
676  unsigned int psetid)
677  : fParameterSetID(psetid), fIsModified(false)
678 {
679  fCanvas = new TGCanvas(mother, kWidth - 6, kHeight - 50);
680  fCanvasH = new TGLayoutHints(kLHintsExpandX | kLHintsExpandY);
681  mother->AddFrame(fCanvas, fCanvasH);
682 
683  fContainer = new TGCompositeFrame(fCanvas->GetViewPort());
684  fCanvas->SetContainer(fContainer);
685 
686  // Locate the parameter set connected to this frame
687  const ServiceTable& st = ServiceTable::Instance();
688  const fhicl::ParameterSet& pset = st.GetParameterSet(psetid);
689  std::vector<std::string> keys = pset.get_names();
690  std::size_t const nkey = size(keys);
691 
692  // Count the number of "non system" parameters - each of these will
693  // need an row in the dialog window.
694  unsigned int nparam = 0;
695  for (auto const& key : keys) {
696  if (!((key == "service_type"s) || (key == "module_type"s) ||
697  (key == "module_label"s))) {
698  ++nparam;
699  }
700  }
701 
702  //
703  // Build the layout
704  //
705  fLayout = new TGTableLayout(fContainer, nparam, 2);
706  fContainer->SetLayoutManager(fLayout);
707 
708  for (std::size_t i = 0, j = 0; i < nkey; ++i) {
709  if (!((keys[i] == "service_type") || (keys[i] == "module_type") ||
710  (keys[i] == "module_label"))) {
711 
712  TGHorizontalFrame* lhs = new TGHorizontalFrame(fContainer);
713  TGHorizontalFrame* rhs = new TGHorizontalFrame(fContainer);
714 
715  TGTableLayoutHints* lhsh = new TGTableLayoutHints(0, 1, j, j + 1);
716  TGTableLayoutHints* rhsh = new TGTableLayoutHints(1, 2, j, j + 1);
717 
718  fContainer->AddFrame(lhs, lhsh);
719  fContainer->AddFrame(rhs, rhsh);
720 
721  fLHS.push_back(lhs);
722  fRHS.push_back(rhs);
723  fLHSHints.push_back(lhsh);
724  fRHSHints.push_back(rhsh);
725 
726  fRow.push_back(new ParameterSetEditRow(this, lhs, rhs, pset, keys[i]));
727  ++j;
728  }
729  }
730 
731  fCanvas->Connect("ProcessedEvent(Event_t*)",
732  "evdb::ParameterSetEditFrame",
733  this,
734  "HandleMouseWheel(Event_t*)");
735 
736  fCanvas->Resize();
737 }
738 
739 //......................................................................
740 
742 {
743  cet::for_all(fRow, std::default_delete<ParameterSetEditRow>{});
744  cet::for_all(fRHSHints, std::default_delete<TGTableLayoutHints>{});
745  cet::for_all(fLHSHints, std::default_delete<TGTableLayoutHints>{});
746  cet::for_all(fRHS, std::default_delete<TGHorizontalFrame>{});
747  cet::for_all(fLHS, std::default_delete<TGHorizontalFrame>{});
748  delete fLayout;
749  //
750  // Parent takes care of delete for fContainer, I think. Anyhow,
751  // trying to delete it causes a seg fault.
752  //
753  // delete fContainer;
754  delete fCanvasH;
755  delete fCanvas;
756 }
757 
758 //......................................................................
759 void
761 {
762  // Handle mouse wheel to scroll.
763  if (event->fType != kButtonPress && event->fType != kButtonRelease)
764  return;
765 
766  Int_t page = 0;
767  if (event->fCode == kButton4 || event->fCode == kButton5) {
768  if (!fCanvas)
769  return;
770  if (fCanvas->GetContainer()->GetHeight())
771  page = Int_t(Float_t(fCanvas->GetViewPort()->GetHeight() *
772  fCanvas->GetViewPort()->GetHeight()) /
773  fCanvas->GetContainer()->GetHeight());
774  }
775 
776  if (event->fCode == kButton4) {
777  // scroll up
778  Int_t newpos = fCanvas->GetVsbPosition() - page;
779  if (newpos < 0)
780  newpos = 0;
781  fCanvas->SetVsbPosition(newpos);
782  }
783  if (event->fCode == kButton5) {
784  // scroll down
785  Int_t newpos = fCanvas->GetVsbPosition() + page;
786  fCanvas->SetVsbPosition(newpos);
787  }
788 }
789 
790 //......................................................................
791 void
793 {
794  fIsModified = true;
795 }
796 
797 //......................................................................
798 void
800 {
801  for (auto row : fRow) {
802  row->Finalize();
803  }
804 }
805 
806 //......................................................................
807 
808 std::string
810 {
811  std::ostringstream s;
812  for (auto row : fRow) {
813  s << row->AsFHICL() << "\n";
814  }
815  return s.str();
816 }
817 
818 //======================================================================
819 //
820 // ParameterSetEditDialog methods
821 //
823  : TGTransientFrame(gClient->GetRoot(), gClient->GetRoot(), 4, 4)
824 {
825  fTGTab = new TGTab(this);
826  this->AddFrame(fTGTab);
827 
828  fButtons = new TGHorizontalFrame(this);
829  this->AddFrame(fButtons);
830 
831  fApply = new TGTextButton(fButtons, " Apply ");
832  fCancel = new TGTextButton(fButtons, " Cancel ");
833  fDone = new TGTextButton(fButtons, " Done ");
834 
835  fButtons->AddFrame(fApply);
836  fButtons->AddFrame(fCancel);
837  fButtons->AddFrame(fDone);
838 
839  fApply->Connect("Clicked()", "evdb::ParameterSetEditDialog", this, "Apply()");
840  fCancel->Connect(
841  "Clicked()", "evdb::ParameterSetEditDialog", this, "Cancel()");
842  fDone->Connect("Clicked()", "evdb::ParameterSetEditDialog", this, "Done()");
843 
844  // Loop over all the parameter sets and build tabs for them
845  const ServiceTable& st = ServiceTable::Instance();
846  assert(psetid < st.fServices.size());
847  int which = st.fServices[psetid].fCategory;
848 
849  unsigned int i;
850  unsigned int top = 0, indx = 0;
851  for (i = 0; i < st.fServices.size(); ++i) {
852  if (st.fServices[i].fCategory == which) {
853  if (i == psetid)
854  top = indx;
855  std::string tabnm = this->TabName(st.fServices[i].fName);
856  TGCompositeFrame* f = fTGTab->AddTab(tabnm.c_str());
857  fFrames.push_back(new ParameterSetEditFrame(f, i));
858  ++indx;
859  }
860  }
861  fTGTab->SetTab(top);
862 
863  switch (which) {
864  case kDRAWING_SERVICE:
865  this->SetWindowName("Drawing Services");
866  break;
867  case kEXPERIMENT_SERVICE:
868  this->SetWindowName("Experiment Services");
869  break;
870  default:
871  this->SetWindowName("Services Configuration");
872  }
873 
874  this->MapSubwindows();
875  this->Resize(kWidth, kHeight);
876  this->MapWindow();
877 }
878 
879 //......................................................................
880 
882 {
883  unsigned int i;
884  for (i = 0; i < fFrames.size(); ++i)
885  delete fFrames[i];
886  delete fDone;
887  delete fCancel;
888  delete fApply;
889  delete fButtons;
890  delete fTGTab;
891 }
892 
893 //......................................................................
894 
895 void
897 {
898  // We're not in control of the event loop so what we can do is write
899  // the new configuration to the ServiceTable. The main driver will
900  // pick it up, apply it, and wipe it clean when a reload / next
901  // event is triggered.
902 
904  for (auto frame : fFrames) {
905  if (frame->fIsModified) {
906  unsigned int psetid = frame->fParameterSetID;
907 
908  frame->Finalize();
909  std::string p = frame->AsFHICL();
910 
911  p += "service_type:";
912  p += st.fServices[psetid].fName;
913 
914  st.fServices[psetid].fParamSet = p;
915  }
916  }
918 }
919 
920 //......................................................................
921 
922 void
924 {
925  this->SendCloseMessage();
926 }
927 
928 //......................................................................
929 
930 void
932 {
933  this->Apply();
934  this->SendCloseMessage();
935 }
936 
937 //......................................................................
938 
939 void
941 {
942  delete this;
943 }
944 
945 //......................................................................
946 //
947 // Remove any redundant text from the tab name
948 //
949 std::string
950 ParameterSetEditDialog::TabName(const std::string& s)
951 {
952  std::size_t const n = s.find("DrawingOptions");
953  return s.substr(0, n);
954 }
955 
static constexpr int kDRAWING_SERVICE
Definition: ServiceTable.h:19
std::vector< TGRadioButton * > fRadioButton
static void Set(int which)
Definition: NavState.cxx:24
void SetupListBox(TGCompositeFrame *f, const std::vector< std::string > &choice, const std::vector< std::string > &value, bool ismulti)
static ServiceTable & Instance()
std::vector< ParameterSetEditRow * > fRow
Collection of Services used in the event display.
Definition: ServiceTable.h:36
Interface to services and their configurations.
#define MF_LOG_ERROR(category)
TGLayoutHints * fRightLH
Align to right.
Float_t tmp
Definition: plot.C:35
Float_t f2
Manage all things related to colors for the event display.
ParameterSetEditFrame * fFrame
The parent frame.
void SetupSlider(TGCompositeFrame *f, const std::vector< std::string > &choice, const std::vector< std::string > &value)
TFile f
Definition: plotHisto.C:6
std::vector< std::string > fChoice
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:101
void SetupTextEntry(TGCompositeFrame *f, unsigned int flags, const std::vector< std::string > &value)
static constexpr int kEXPERIMENT_SERVICE
Definition: ServiceTable.h:20
TGLayoutHints * fLeftLH
Align to left.
std::vector< TGTableLayoutHints * > fRHSHints
std::vector< TGHorizontalFrame * > fLHS
decltype(auto) values(Coll &&coll)
Range-for loop helper iterating across the values of the specified collection.
T get(std::string const &key) const
Definition: ParameterSet.h:314
Float_t f1
static void ParseGUItag(const std::string &guitag, std::string &frame, std::vector< std::string > &choice)
A frame for editing a single paramter set.
Pop-up window for editing parameter sets.
double value
Definition: spectrum.C:18
static void UnpackParameter(const fhicl::ParameterSet &ps, const std::string &key, unsigned int &flags, std::string &tag, std::vector< std::string > &choice, std::vector< std::string > &value, std::string &gui, std::string &doc)
std::vector< TGTableLayoutHints * > fLHSHints
std::vector< ServiceTableEntry > fServices
Definition: ServiceTable.h:50
std::vector< TGHorizontalFrame * > fRHS
A single row for editing a single parameter in a set.
std::vector< ParameterSetEditFrame * > fFrames
void SetupRadioButtons(TGCompositeFrame *f, const std::vector< std::string > &choice, const std::vector< std::string > &value)
std::vector< std::string > get_names() const
fhicl::ParameterSet const & GetParameterSet(unsigned int i) const
ParameterSetEditRow(ParameterSetEditFrame *frame, TGHorizontalFrame *lhs, TGHorizontalFrame *rhs, const fhicl::ParameterSet &ps, const std::string &key)
static bool IsLegalGUItag(const std::string &s)
Char_t n[5]
void SetupCheckButton(TGCompositeFrame *f, const std::vector< std::string > &choice, const std::vector< std::string > &value)
ParameterSetEditDialog(unsigned int psetid)
std::vector< TGCheckButton * > fCheckButton
decltype(auto) constexpr empty(T &&obj)
ADL-aware version of std::empty.
Definition: StdUtils.h:109
Event finding and building.
std::string to_string() const
Definition: ParameterSet.h:196
ParameterSetEditFrame(TGCompositeFrame *mother, unsigned int psetid)
TGTextButton * fLabel
Label on the left.
std::string TabName(const std::string &s)