GSI Object Oriented Online Offline (Go4)  GO4-6.1.4
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
TGo4ViewPanel.cpp
Go to the documentation of this file.
1 // $Id: TGo4ViewPanel.cpp 3119 2021-03-30 07:23:37Z linev $
2 //-----------------------------------------------------------------------
3 // The GSI Online Offline Object Oriented (Go4) Project
4 // Experiment Data Processing at EE department, GSI
5 //-----------------------------------------------------------------------
6 // Copyright (C) 2000- GSI Helmholtzzentrum fuer Schwerionenforschung GmbH
7 // Planckstr. 1, 64291 Darmstadt, Germany
8 // Contact: http://go4.gsi.de
9 //-----------------------------------------------------------------------
10 // This software can be used under the license agreements as stated
11 // in Go4License.txt file which is part of the distribution.
12 //-----------------------------------------------------------------------
13 
14 // JAM2016: activate this for global ROOT "escape mode" before redraw (NOT RECOMMENDED)
15 // otherwise, escape mode will reset global arrays of TGraph painter class only
16 //#define GLOBALESCAPE 1
17 
18 #include "TGo4ViewPanel.h"
19 
20 #include "RVersion.h"
21 
22 #include "TF1.h"
23 #include "TH1.h"
24 #include "TH2.h"
25 #include "TVirtualX.h"
26 #include "THStack.h"
27 #include "TGraph.h"
28 #include "TMultiGraph.h"
29 #include "TColor.h"
30 #include "TCanvas.h"
31 #include "TFrame.h"
32 #include "TArrayD.h"
33 #include "TCutG.h"
34 #include "TArrow.h"
35 #include "TList.h"
36 #include "TLatex.h"
37 #include "TPaveStats.h"
38 #include "TPaveLabel.h"
39 #include "TLegend.h"
40 #include "TStyle.h"
41 #include "TROOT.h"
42 #include "TMath.h"
43 #include "TClass.h"
44 #include "TSystem.h"
45 #include "TCanvasImp.h"
46 
47 #include <QMenu>
48 #include <QMenuBar>
49 #include <QStatusBar>
50 #include <QFileDialog>
51 #include <QTimer>
52 #include <QInputDialog>
53 #include <QTime>
54 #include <QtCore/QSignalMapper>
55 
56 #ifdef __GO4X11__
57 #include "QRootCanvas.h"
58 #endif
59 #ifdef __GO4WEB__
60 #include "QWebCanvas.h"
61 #endif
62 
63 //#include "QRootApplication.h"
64 
65 #include "TGo4Log.h"
66 #include "TGo4Picture.h"
67 #include "TGo4Fitter.h"
68 #include "TGo4Marker.h"
69 #include "TGo4WinCond.h"
70 #include "TGo4PolyCond.h"
71 #include "TGo4CondArray.h"
72 #include "TGo4WinCondView.h"
73 #include "TGo4PolyCondView.h"
74 #include "TGo4LockGuard.h"
75 #include "TGo4MdiArea.h"
76 #include "TGo4ASImage.h"
77 #include "TGo4PrintWidget.h"
78 #include "TGo4Slot.h"
79 #include "TGo4ObjectProxy.h"
80 #include "TGo4LinkProxy.h"
81 #include "TGo4DrawObjProxy.h"
82 #include "TGo4DrawCloneProxy.h"
83 #include "TGo4Iter.h"
84 #include "TGo4BrowserProxy.h"
85 #include "TGo4QSettings.h"
86 
87 const char* NoStackDrawOption = "nostack, ";
88 
89 class TPadGuard {
90  TVirtualPad *fSave;
91 public:
92 
93  TPadGuard(TVirtualPad *repl = 0)
94  {
95  fSave = gPad;
96  gPad = repl;
97  }
98 
100  {
101  gPad = fSave;
102  }
103 };
104 
105 
106 TGo4ViewPanel::TGo4ViewPanel(QWidget *parent, const char* name) :
107  QGo4Widget(parent, name)
108 {
109  setupUi(this);
110 
111  QObject::connect(CursorB, SIGNAL(toggled(bool)), this, SLOT(SetCursorMode(bool)));
112  QObject::connect(RegionB, SIGNAL(toggled(bool)), this, SLOT(SetRegionMode(bool)));
113  QObject::connect(FreezeMode, SIGNAL(toggled(bool)), this, SLOT(SetFreezeMouseMode(bool)));
114  QObject::connect(LatexB, SIGNAL(toggled(bool)), this, SLOT(SetLateXMode(bool)));
115  QObject::connect(DrawB, SIGNAL(toggled(bool)), this, SLOT(SetDrawingMode(bool)));
116  QObject::connect(PrintLogB, SIGNAL(pressed()), this, SLOT(LogMarkerValues()));
117  QObject::connect(PolyB, SIGNAL(toggled(bool)), this, SLOT(SetPolygonMode(bool)));
118  QObject::connect(SelectedMarkerCmb, SIGNAL(activated(int)), this, SLOT(SelectedMarkerCmb_activated(int)));
119  QObject::connect(DelSelectedMarker, SIGNAL(clicked()), this, SLOT(DelSelectedMarker_clicked()));
120  QObject::connect(GetConditionBtn, SIGNAL(clicked()), this, SLOT(GetConditionBtn_clicked()));
121  QObject::connect(InfoConditionBtn, SIGNAL(clicked()), this, SLOT(InfoConditionBtn_clicked()));
122  QObject::connect(EditConditionBtn, SIGNAL(clicked()), this, SLOT(EditConditionBtn_clicked()));
123  QObject::connect(SetConditionBtn, SIGNAL(clicked()), this, SLOT(SetConditionBtn_clicked()));
124 
125  // TODO: viewpanel does not closed when press close button
126  setAttribute(Qt::WA_DeleteOnClose);
127 
128  fPanelName = objectName();
129 
130  fxActivePad = 0;
131 
133  fxRepaintTimerPad = 0;
134  fxResizeTimerPad = 0;
136  fbFreezeTitle = false;
137  fFreezedTitle = "";
138  fbApplyToAllFlag = false;
139  fbAutoZoomFlag = false;
140  fbCanvasCrosshair = false;
141 
142  fbCloneFlag = true;
143  fbModifiedSignalFlag = false;
144  fbLeaveFocusAfterCondEnd = false;
145 
146  // setup of marker editor
147  fbMarkEditorVisible = false;
148  fbTypingMode = true;
149  MarkerPanel->setVisible(false);
151  fiPickCounter = 0;
152  fbPickAgain = false;
153 
154  setWindowTitle(GetPanelName());
155 
156  QSizePolicy sizePolicy3(static_cast<QSizePolicy::Policy>(7), static_cast<QSizePolicy::Policy>(7));
157  sizePolicy3.setHorizontalStretch(0);
158  sizePolicy3.setVerticalStretch(20);
159 
160  fxQCanvas = 0;
161  fxWCanvas = 0;
162 
163  CanvasStatus = 0;
164 
165 #ifdef __GO4WEB__
166  if (go4sett->getWebBasedCanvas()) {
167  fxWCanvas = new QWebCanvas(this);
168 
169  fxWCanvas->setMinimumSize(QSize(50, 50));
170  sizePolicy3.setHeightForWidth(fxWCanvas->sizePolicy().hasHeightForWidth());
171  fxWCanvas->setSizePolicy(sizePolicy3);
172 
173  fxGridLayout->addWidget(fxWCanvas, 1, 1, 1, 1);
174 
175  fxWCanvas->setObjectName(GetPanelName());
176  fxWCanvas->getCanvas()->SetName(GetPanelName());
177  }
178 #endif
179 
180 #ifdef __GO4X11__
181  if (!fxWCanvas) {
182  fxQCanvas = new QRootCanvas(this);
183  // fxQCanvas->setObjectName(QStringLiteral("fxQCanvas"));
184  fxQCanvas->setMinimumSize(QSize(50, 50));
185  sizePolicy3.setHeightForWidth(fxQCanvas->sizePolicy().hasHeightForWidth());
186  fxQCanvas->setSizePolicy(sizePolicy3);
187 
188  fxGridLayout->addWidget(fxQCanvas, 1, 1, 1, 1);
189 
190  fxQCanvas->setObjectName(GetPanelName());
191  fxQCanvas->getCanvas()->SetName(GetPanelName());
192  fxQCanvas->setEditorFrame(EditorFrame);
193  }
194 #endif
195 
196 // printf("Resize x %d y %d\n", go4sett->lastPanelSize().width(), go4sett->lastPanelSize().height());
197 // resize(go4sett->lastPanelSize());
198 
199  fSelectMenu = 0;
200  fSelectMap = 0;
201 
202  fMenuBar = new QMenuBar(MenuFrame);
203  fMenuBar->setMinimumWidth(50);
204  fMenuBar->setNativeMenuBar(kFALSE); // disable putting this to screen menu. for MAC style WMs
205 
206  QMenu* fileMenu = fMenuBar->addMenu("F&ile");
207  fileMenu->addAction("&Save as...", this, SLOT(SaveCanvas()));
208  fileMenu->addAction("Print...", this, SLOT(PrintCanvas()));
209  fileMenu->addAction("Produce &Picture", this, SLOT(ProducePicture()));
210  fileMenu->addAction("Produce &Graph from markers", this,
211  SLOT(ProduceGraphFromMarkers()));
212 
213 // fileMenu->addAction("Copy to T&Canvas in Memory", this, SLOT(SendToBrowser()));
214 // fileMenu->addAction("&Load marker setup...", this, SLOT(LoadMarkers()));
215 // fileMenu->addAction("Save &marker setup...", this, SLOT(SaveMarkers()));
216  fileMenu->addAction("Cl&ose", this, SLOT(ClosePanel()));
217 
218  //Edit Menu
219  QMenu* editMenu = fMenuBar->addMenu("&Edit");
220 
221  AddChkAction(editMenu, "Show marker &editor", fbMarkEditorVisible, this,
222  SLOT(SetMarkerPanel()));
223 
224  bool ed_visible = false, ed_allowed = true;
225 
226 #ifdef __GO4X11__
227  if (!fxWCanvas) {
228  ed_visible = fxQCanvas->isEditorVisible();
229  ed_allowed = fxQCanvas->isEditorAllowed();
230  }
231 #endif
232 
233  fxCanvasEditorChk = AddChkAction(editMenu, "Show &ROOT attributes editor",
234  ed_visible, this, SLOT(StartRootEditor()));
235  fxCanvasEditorChk->setEnabled(ed_allowed);
236 
237  bool status_flag = go4sett->getPadEventStatus();
238  fxCanvasEventstatusChk = AddChkAction(editMenu, "Show &event status", status_flag, this,
239  SLOT(ShowEventStatus()));
240 
241  editMenu->addAction("Start &condition editor", this,
242  SLOT(StartConditionEditor()));
243 
244  editMenu->addSeparator();
245  editMenu->addAction("Clear &markers", this, SLOT(ClearAllMarkers()));
246  editMenu->addAction("Clear &pad", this, SLOT(ClearActivePad()));
247  editMenu->addAction("Clear c&anvas", this, SLOT(ClearCanvas()));
248 
249  fSelectMap = new QSignalMapper(this);
250  connect(fSelectMap, SIGNAL(mapped(int)), this,
251  SLOT(SelectMenuItemActivated(int)));
252  fSelectMenu = fMenuBar->addMenu("&Select");
253 
254  fOptionsMap = new QSignalMapper(this);
255  fOptionsMenu = fMenuBar->addMenu("&Options");
256  connect(fOptionsMenu, SIGNAL(aboutToShow()), this,
257  SLOT(AboutToShowOptionsMenu()));
258  connect(fOptionsMap, SIGNAL(mapped(int)), this,
259  SLOT(OptionsMenuItemActivated(int)));
260 
264  AddIdAction(fOptionsMenu, fOptionsMap, "Histogram &Statistics", StatisticsId);
265  AddIdAction(fOptionsMenu, fOptionsMap, "Multiplot &Legend", SetLegendId);
266 
267  fOptionsMenu->addSeparator();
268  AddIdAction(fOptionsMenu, fOptionsMap, "Histogram &Title", SetTitleId);
271  AddIdAction(fOptionsMenu, fOptionsMap, "Draw item name", DrawItemnameId);
272  fOptionsMenu->addSeparator();
273  AddIdAction(fOptionsMenu, fOptionsMap, "&1:1 Coordinate ratio", SetXYRatioOneId);
274  fOptionsMenu->addSeparator();
275  AddIdAction(fOptionsMenu, fOptionsMap, "&X-Axis displays time", AxisTimeDisplayId);
276  AddIdAction(fOptionsMenu, fOptionsMap, "Set X-Axis time format...", SetTimeFormatId);
277  fOptionsMenu->addSeparator();
278  AddIdAction(fOptionsMenu, fOptionsMap, "&Keep Viewpanel Title", FreezeTitleId);
279  AddIdAction(fOptionsMenu, fOptionsMap, "Set &Viewpanel Title...", SetTitleTextId);
280 
281  QCheckBox* box1 = new QCheckBox("Apply to all", MenuFrame);
282  box1->setObjectName("ApplyToAllCheck");
283  connect(box1, SIGNAL(toggled(bool)), this, SLOT(ApplyToAllToggled(bool)));
284 
285  fAutoScaleCheck = new QCheckBox("AutoScale", MenuFrame);
286  fAutoScaleCheck->setObjectName("AutoScaleCheck");
287  connect(fAutoScaleCheck, SIGNAL(toggled(bool)), this, SLOT(AutoScaleToggled(bool)));
288 
289  QHBoxLayout* menugrid = new QHBoxLayout(0/*MenuFrame*/);
290  menugrid->setContentsMargins(0,0,0,0);
291  menugrid->setSpacing(0);
292  menugrid->addWidget(fMenuBar, 10, Qt::AlignLeft);
293  menugrid->addWidget(box1, 1, Qt::AlignRight);
294  menugrid->addWidget(fAutoScaleCheck, 1, Qt::AlignRight);
295 
296  fxGridLayout->addLayout(menugrid, 0, 0, 1, 2);
297 
298  // status widget
299 
300  if (fxWCanvas) {
301  // TODO: one can get status from webcanvas here
302 #ifdef __GO4WEB__
303  fxWCanvas->setStatusBarVisible(status_flag);
304 
305  connect(fxWCanvas, SIGNAL(CanvasDropEvent(QDropEvent*,TPad*)), this,
306  SLOT(CanvasDropEventSlot(QDropEvent*,TPad*)));
307 
308  connect(fxWCanvas, SIGNAL(SelectedPadChanged(TPad*)), this,
309  SLOT(SetActivePad(TPad*)));
310 
311  connect(fxWCanvas, SIGNAL(PadClicked(TPad*,int,int)), this,
312  SLOT(PadClickedSlot(TPad*,int,int)));
313 
314  connect(fxWCanvas, SIGNAL(PadDblClicked(TPad*,int,int)), this,
315  SLOT(PadDoubleClickedSlot(TPad*,int,int)));
316 
317  connect(fxWCanvas, SIGNAL(CanvasUpdated()), this,
318  SLOT(CanvasUpdatedSlot()));
319 
320 #endif
321  } else {
322 #ifdef __GO4X11__
323  CanvasStatus = new QStatusBar(this);
324  fxGridLayout->addWidget(CanvasStatus, 3, 0, 1, 2);
325  CanvasStatus->setVisible(false);
327  fxQCanvas->setStatusBarVisible(status_flag);
328 
329  connect(fxQCanvas, SIGNAL(CanvasDropEvent(QDropEvent*,TPad*)), this,
330  SLOT(CanvasDropEventSlot(QDropEvent*,TPad*)));
331  connect(fxQCanvas, SIGNAL(SelectedPadChanged(TPad*)), this,
332  SLOT(SetActivePad(TPad*)));
333  connect(fxQCanvas, SIGNAL(PadClicked(TPad*)), this,
334  SLOT(PadClickedSlot(TPad*)));
335  connect(fxQCanvas, SIGNAL(PadDoubleClicked(TPad*)), this,
336  SLOT(PadDoubleClickedSlot(TPad*)));
337  connect(fxQCanvas, SIGNAL(MenuCommandExecuted(TObject*, const char*)),
338  this, SLOT(MenuCommandExecutedSlot(TObject*, const char*)));
339  connect(fxQCanvas, SIGNAL(CanvasLeaveEvent()), this,
340  SLOT(RefreshButtons()));
341  connect(fxQCanvas, SIGNAL(CanvasUpdated()), this,
342  SLOT(CanvasUpdatedSlot()));
343 #endif
344  }
345 }
346 
348 {
349  TGo4LockGuard lock;
350 
351  // we should delete all markers first, while they
352  // have internal reference on the pad, which will be
353  // deleted by the net canvas->Clear() call
355 
357 
358  GetCanvas()->Clear();
359 
360  fxRepaintTimerPad = 0;
361 
363 
364  if (gPad != 0)
365  if (IsPanelPad((TPad*) gPad)) {
366  gPad = 0;
367  }
368 
369  if (gROOT->GetSelectedPad() != 0)
370  if (IsPanelPad((TPad*) gROOT->GetSelectedPad()))
371  gROOT->SetSelectedPad(0);
372 }
373 
375 {
376  fbaPanelName = fPanelName.toLatin1();
377  return fbaPanelName.constData();
378 }
379 
380 void TGo4ViewPanel::SetPanelName(const char* newname)
381 {
382  fPanelName = newname;
383 }
384 
386 {
387  return GetTopSlot(true);
388 }
389 
390 TGo4Slot* TGo4ViewPanel::AddNewSlot(const char* name, TGo4Slot* parent)
391 {
392  if (parent == 0)
393  parent = GetPanelSlot();
394  return new TGo4Slot(parent, name, "title");
395 }
396 
398 {
399  // do nothing
400 }
401 
402 void TGo4ViewPanel::linkedObjectUpdated(const char* linkname, TObject* obj)
403 {
404  if (linkname == 0)
405  return;
406 
407  if (strcmp(linkname, "PadRangeAxisChanged") == 0) {
409  } else if (strcmp(linkname, "PadModified") == 0) {
410  if (IsRedrawBlocked())
411  return;
413  QTimer::singleShot(1, this, SLOT(ProcessPadModifiedSignal()));
414  fbModifiedSignalFlag = true;
415  }
416 }
417 
418 void TGo4ViewPanel::linkedUpdated(TGo4Slot* slot, TObject* obj)
419 {
420  if (slot == 0)
421  return;
422 
423  if (IsRedrawBlocked())
424  return;
425 
426  Int_t kind = GetDrawKind(slot);
427 
428  TGo4Slot* padslot = slot;
429  if (kind != kind_PadSlot)
430  padslot = slot->GetParent();
431 
432  if (((kind > 0) && (kind < 100)) || (kind == kind_Condition)
433  || (kind == kind_Latex) || (kind == kind_Func)) {
434  TGo4Picture* padopt = GetPadOptions(padslot);
435 
436  if (padopt != 0) {
437  padopt->SetContentModified(true);
438  padopt->SetPadModified();
439 
440  // in this small period other objects can come,
441  // therefore only one repaint will be done
443  }
444  }
445 }
446 
447 void TGo4ViewPanel::linkedRemoved(TGo4Slot* slot, TObject* obj)
448 {
449  if (slot == 0)
450  return;
451 
452  if (IsRedrawBlocked())
453  return;
454 
455  int kind = GetDrawKind(slot);
456 
457  if (kind == kind_ThisPad) {
458  TPad* pad = (TPad*) obj;
459  if (pad != 0)
460  PadDeleted(pad);
461  return;
462  }
463 
464  TGo4Slot* padslot = slot;
465  if (kind != kind_PadSlot)
466  padslot = slot->GetParent();
467 
468  CheckObjectsAssigments(GetSlotPad(padslot), padslot);
469 
470  if (((kind > 0) && (kind < 100)) || (kind == kind_Condition)
471  || (kind == kind_Latex) || (kind == kind_Func)) {
473  TGo4Picture* padopt = GetPadOptions(padslot);
474  if (padopt != 0) {
475  padopt->SetPadModified();
477  }
478  }
479 }
480 
481 bool TGo4ViewPanel::IsAcceptDrag(const char * itemname, TClass * cl, int kind)
482 {
483  if (cl == 0)
484  return false;
485  int cando = Browser()->ItemCanDo(itemname);
486  return TGo4BrowserProxy::CanDrawItem(cando)
487  || cl->InheritsFrom(TGo4Condition::Class());
488 }
489 
490 void TGo4ViewPanel::DropOnPad(TPad* pad, const char * itemname, TClass * cl, int kind)
491 {
492  if (cl == 0) return;
493  if (pad == 0) pad = GetCanvas();
494 
495  if (cl->InheritsFrom(TGo4Fitter::Class())) {
496  SetActivePad(pad);
497  EditItem(itemname);
498  return;
499  }
500  int cando = Browser()->ItemCanDo(itemname);
502  && !cl->InheritsFrom(TGo4Condition::Class()))
503  return;
504 
505  if (AddDrawObject(pad, kind_Link, itemname, 0, false, 0) == 0) return;
506 
507  SetActivePad(pad);
508 
510 
511  Browser()->GetBrowserObject(itemname,
512  go4sett->getFetchDataWhenDraw() ? 2 : 1);
513 }
514 
515 // ****************************************************************
516 
518 {
519  TGo4LockGuard lock;
520 
521  // create appropriate entry in OM
522  UpdatePadStatus(GetCanvas(), true);
523 
524  fAutoScaleCheck->setChecked(GetPadOptions(GetCanvas())->IsAutoScale());
525 
526 #ifdef __GO4X11__
527  // JAM 5-2019 construct top window for ged editor already here, otherwise problems with Qt4
529 
530  // adjust canvas size before any drawing will be done
531  if (fxQCanvas) fxQCanvas->Resize();
532 #endif
533 
534  // fMenuBar
535  connect(TGo4MdiArea::Instance(),
536  SIGNAL(panelSignal(TGo4ViewPanel*, TPad*, int)), this,
537  SLOT(panelSlot(TGo4ViewPanel*, TPad*, int)));
538 
539  // printf("Resize again x %d y %d\n", go4sett->lastPanelSize().width(), go4sett->lastPanelSize().height());
540  // resize(go4sett->lastPanelSize());
541 
543 
545 
546  //fxQCanvas->Modified();
547 
549 }
550 
552 {
553  parentWidget()->close();
554 }
555 
557 {
558  // std::cout <<"TGo4ViewPanel::SetMouseMode sets mouse mode: "<< mode << std::endl;
559  fiMouseMode = mode;
560 }
561 
563 {
564  return fiMouseMode;
565 }
566 
568 {
569  TGo4Slot* padslot = GetPadSlot(pad);
570  if (padslot == 0) return QString();
571  return QString(padslot->GetPar("::SelMarker"));
572 }
573 
575 {
576  TGo4Slot* padslot = GetPadSlot(pad);
577  if (padslot == 0) return -1;
578  Int_t selindex = -1;
579  if (!padslot->GetIntPar("::SelIndex", selindex)) return -1;
580  return selindex;
581 }
582 
583 TGo4Slot* TGo4ViewPanel::GetSelectedSlot(TPad* pad, int* selkind, TObject** selobj)
584 {
585  if (selkind != 0) *selkind = kind_None;
586  if (selobj != 0) *selobj = 0;
587 
588  TGo4Slot* padslot = GetPadSlot(pad);
589  QString selname = GetSelectedMarkerName(pad);
590  int selindex = GetSelectedMarkerIndex(pad);
591 
592  if ((padslot == 0) || (selname.length() == 0)) return 0;
593 
594  for (int n = 0; n < padslot->NumChilds(); n++) {
595  TGo4Slot* subslot = padslot->GetChild(n);
596  int drawkind = GetDrawKind(subslot);
597  TObject* obj = subslot->GetAssignedObject();
598 
599  if ((drawkind == kind_Link) && (obj != 0)) {
600  if (obj->InheritsFrom(TGo4Condition::Class()))
601  drawkind = kind_Condition;
602  }
603 
604  if ((drawkind == kind_Marker) || (drawkind == kind_Window)
605  || (drawkind == kind_Poly) || (drawkind == kind_Latex)
606  || (drawkind == kind_Arrow) || (drawkind == kind_Condition)) {
607 
608  if ((obj == 0) || (selname != obj->GetName()))
609  continue;
610 
611  if (drawkind == kind_Condition) {
612  TGo4Condition* selcond = dynamic_cast<TGo4Condition*>(obj);
613  if (obj->InheritsFrom(TGo4CondArray::Class())) {
614  TGo4CondArray* arr = (TGo4CondArray*) obj;
615  selcond = 0;
616  if ((selindex >= 0) && (selindex < arr->GetNumber()))
617  selcond = arr->At(selindex);
618  }
619  drawkind = kind_None;
620  obj = selcond;
621  if (selcond != 0) {
622  if (selcond->InheritsFrom(TGo4WinCond::Class()))
623  drawkind = kind_Window;
624  else if (selcond->InheritsFrom(TGo4PolyCond::Class()))
625  drawkind = kind_Poly;
626  }
627  }
628  if (selkind != 0)
629  *selkind = drawkind;
630  if (selobj != 0)
631  *selobj = obj;
632  return subslot;
633  }
634  }
635  return 0;
636 }
637 
639 {
640  TGo4Slot* slot = GetSelectedSlot(pad, 0, 0);
641  if (slot == 0)
642  return false;
643 
644  return (GetDrawKind(slot) == kind_Condition);
645 }
646 
647 TPad* TGo4ViewPanel::FindPadWithItem(const char* itemname)
648 {
649  TGo4Iter iter(GetPanelSlot(), kTRUE);
650  while (iter.next()) {
651  TGo4Slot* subslot = iter.getslot();
652  int drawkind = GetDrawKind(subslot);
653  if ((drawkind == kind_Link) || (drawkind == kind_Condition) || (drawkind == kind_Latex) || (drawkind == kind_Func)) {
654  const char* linkname = GetLinkedName(subslot);
655  if (linkname != 0)
656  if (strcmp(linkname, itemname) == 0)
657  return GetSlotPad(subslot->GetParent());
658  }
659  }
660  return 0;
661 }
662 
663 const char* TGo4ViewPanel::GetDrawItemName(int itemcnt)
664 {
665  int cnt = 0;
666 
667  TGo4Iter iter(GetPanelSlot(), kTRUE);
668  while (iter.next()) {
669  TGo4Slot* subslot = iter.getslot();
670  int drawkind = GetDrawKind(subslot);
671  if ((drawkind == kind_Link) || (drawkind == kind_Condition)) {
672  const char* linkname = GetLinkedName(subslot);
673  if (linkname != 0) {
674  if (cnt++ == itemcnt) return linkname;
675  }
676  }
677  }
678 
679  return 0;
680 }
681 
682 
683 void TGo4ViewPanel::UndrawItemOnPanel(const char* itemname)
684 {
685  TGo4LockGuard lock;
686 
687  TObjArray delslots;
688 
689  TGo4Iter iter(GetPanelSlot(), kTRUE);
690  while (iter.next()) {
691  TGo4Slot* subslot = iter.getslot();
692  int drawkind = GetDrawKind(subslot);
693  if ((drawkind == kind_Link) || (drawkind == kind_Condition) || (drawkind == kind_Latex) || (drawkind == kind_Func)) {
694  const char* linkname = GetLinkedName(subslot);
695  if ((linkname != 0) && (strcmp(linkname, itemname) == 0)) {
696  delslots.Add(subslot);
697  TGo4Slot* padslot = subslot->GetParent();
698  TGo4Picture* padopt = GetPadOptions(padslot);
699  if (padopt != 0)
700  padopt->SetPadModified();
701  }
702  }
703  }
704  if (delslots.GetLast() >= 0) {
705  delslots.Delete();
707  }
708 }
709 
710 void TGo4ViewPanel::SetSelectedMarker(TPad* pad, const QString& selname,
711  int selindex)
712 {
713  TGo4LockGuard lock;
714 
715  TGo4Slot* padslot = GetPadSlot(pad);
716  if (padslot == 0)
717  return;
718 
719  if (selname.length() == 0)
720  selindex = -1;
721 
722  int oldselindex = GetSelectedMarkerIndex(pad);
723  QString oldselname = GetSelectedMarkerName(pad);
724 
725  TGo4Slot* oldsel = GetSelectedSlot(pad, 0, 0);
726  if (oldsel != 0)
727  SetSpecialDrawOption(oldsel, 0);
728 
729  if (selname.length() > 0)
730  padslot->SetPar("::SelMarker", selname.toLatin1().constData());
731  else
732  padslot->RemovePar("::SelMarker");
733 
734  if (selindex > -1)
735  padslot->SetIntPar("::SelIndex", selindex);
736  else
737  padslot->RemovePar("::SelIndex");
738 
739  int newselkind = 0;
740  TObject* newselobj = 0;
741  TGo4Slot* newselslot = GetSelectedSlot(pad, &newselkind, &newselobj);
742 
743  if ((selindex >= 0) && (newselslot != 0)) {
744  QString drawopt("sel=");
745  drawopt += QString::number(selindex);
746  SetSpecialDrawOption(newselslot, drawopt.toLatin1().constData());
747  }
748 
749  if (((oldselindex != selindex) || (oldselname != selname))
750  && ((oldselindex >= 0) || (selindex >= 0))) {
751  MarkPadModified(pad);
752  ShootRepaintTimer(pad);
753  } else if (newselobj != 0) {
754  // this will bring object to the top
755  newselobj->Pop();
756  // very special case, normally one should not call pad->Update()
757  pad->Update();
758  }
759 
760 }
761 
762 void TGo4ViewPanel::SetSelectedMarkerByMouseClick(TPad* pad, const char* name)
763 {
764  TGo4LockGuard lock;
765 
766  if (!fbMarkEditorVisible) return;
767  TGo4Slot* padslot = GetPadSlot(pad);
768  if (padslot == 0) return;
769 
770  bool find = false;
771 
772  for (int n = 0; n < padslot->NumChilds(); n++) {
773  TGo4Slot* subslot = padslot->GetChild(n);
774  int drawkind = GetDrawKind(subslot);
775  if ((drawkind == kind_Marker) || (drawkind == kind_Window)
776  || (drawkind == kind_Poly)) {
777  TObject* obj = subslot->GetAssignedObject();
778  if ((obj != 0) && (strcmp(obj->GetName(), name) == 0)) {
779  SetSelectedMarker(pad, name, -1);
780  SetActiveObj(pad, drawkind, subslot);
781  find = true;
782  break;
783  }
784  }
785  if (drawkind != kind_Condition) continue;
786  TGo4Condition* cond =
787  dynamic_cast<TGo4Condition*>(subslot->GetAssignedObject());
788  if (cond==0) continue;
789 
790  if (strcmp(cond->GetName(), name) == 0) {
791  SetSelectedMarker(pad, name, -1);
792 
793  if (cond->InheritsFrom(TGo4PolyCond::Class()))
794  drawkind = kind_Poly;
795  else
796  drawkind = kind_Window;
797 
798  SetActiveObj(pad, drawkind, subslot);
799  find = true;
800  break;
801  }
802 
803  TGo4CondArray* arr = dynamic_cast<TGo4CondArray*>(cond);
804  if (arr == 0)
805  continue;
806 
807  for (int ncon = 0; ncon < arr->GetNumber(); ncon++)
808  if (strcmp(arr->At(ncon)->GetName(), name) == 0) {
809  SetSelectedMarker(pad, arr->GetName(), ncon);
810  if (arr->At(ncon)->InheritsFrom(TGo4PolyCond::Class()))
811  drawkind = kind_Poly;
812  else
813  drawkind = kind_Window;
814  SetActiveObj(pad, drawkind, subslot);
815  find = true;
816  break;
817  }
818  }
819  if (find)
820  RefreshButtons();
821 }
822 
824 {
825  TGo4LockGuard lock;
826 
827  int selectedkind;
828  TGo4Slot* selslot = GetSelectedSlot(GetActivePad(), &selectedkind, 0);
829 
830  if (selslot == 0)
831  return;
832 
833  if (selectedkind == kind_Window) {
834  FreezeMode->setChecked(false);
835  RegionB->setChecked(true);
837  } else if (selectedkind == kind_Poly) {
838  FreezeMode->setChecked(false);
839  PolyB->setChecked(true);
841  } else
842  return;
843 
844  MarkPadModified(pad);
845  ShootRepaintTimer(pad);
846 }
847 
848 void TGo4ViewPanel::SwitchMarkerButton(int kind, bool on)
849 {
850  if (!fbTypingMode)
851  return;
852  // std::cout <<"TGo4ViewPanel::SwitchMarkerButton for kind:"<<kind<<", on:"<< on << std::endl;
853 
855  if (!on) {
857  } else {
858  fiPickCounter = 0;
859  switch (kind) {
860  case kind_Marker:
862  break;
863  case kind_Window:
865  break;
866  case kind_Poly:
868  break;
869  case kind_Latex:
871  break;
872  case kind_Arrow:
874  break;
875  default:
877  break;
878  }
879  int selectedkind;
880  TGo4Slot* selslot = GetSelectedSlot(GetActivePad(), &selectedkind, 0);
881  if (selectedkind != kind)
882  SetSelectedMarker(GetActivePad(), "", -1);
883  }
884 
885  RefreshButtons();
886 }
887 
889 {
891 }
892 
894 {
896 }
897 
899 {
901 }
902 
904 {
906 }
907 
909 {
911 }
912 
914 {
915  if (!fbTypingMode)
916  return;
917  fbPickAgain = on;
918  RefreshButtons();
919 }
920 
922 {
923  TGo4LockGuard lock;
924 
925  MarkerPanel->setVisible(fbMarkEditorVisible);
926 
927 #ifdef __GO4X11__
928  if (fxQCanvas)
930 #endif
931 
932 // if(!fbMarkEditorVisible) return;
933 
934  bool iscondition = IsConditionSelected(GetActivePad());
935 
936  fbTypingMode = false;
937  GetConditionBtn->setVisible(iscondition);
938  InfoConditionBtn->setVisible(iscondition);
939  EditConditionBtn->setVisible(iscondition);
940  SetConditionBtn->setVisible(iscondition);
941  if (iscondition) {
942  TGo4Slot* slot = GetSelectedSlot(GetActivePad(), 0, 0);
943  TGo4Condition* cond =
944  slot == 0 ? 0 : dynamic_cast<TGo4Condition*>(slot->GetAssignedObject());
945  ModifyConditionBtn->setVisible((cond != 0) && (cond->IsChanged() != 0));
946 
947  QString iconname = ":/icons/right.png";
948  QString tooltip = "Refresh condition from analysis";
949  if (!BrowserItemRemote(GetLinkedName(slot))) {
950  iconname = ":/icons/refresh.png";
951  tooltip = "Refresh condition from source";
952  }
953  GetConditionBtn->setIcon(QIcon(iconname));
954  GetConditionBtn->setToolTip(tooltip);
955 
956  } else
957  ModifyConditionBtn->setVisible(false);
958 
959  switch (GetMouseMode()) {
960  case kMouseROOT:
961  CursorB->setChecked(false);
962  RegionB->setChecked(false);
963  LatexB->setChecked(false);
964  DrawB->setChecked(false);
965  PolyB->setChecked(false);
966  break;
967  case kMousePickCursor:
968  CursorB->setChecked(true);
969  RegionB->setChecked(false);
970  LatexB->setChecked(false);
971  DrawB->setChecked(false);
972  PolyB->setChecked(false);
973  break;
974  case kMousePickLimits:
975  CursorB->setChecked(false);
976  RegionB->setChecked(true);
977  LatexB->setChecked(false);
978  DrawB->setChecked(false);
979  PolyB->setChecked(false);
980  break;
981  case kMousePickPolygon:
982  CursorB->setChecked(false);
983  RegionB->setChecked(false);
984  LatexB->setChecked(false);
985  DrawB->setChecked(false);
986  PolyB->setChecked(true);
987  break;
988  case kMousePickLatex:
989  CursorB->setChecked(false);
990  RegionB->setChecked(false);
991  LatexB->setChecked(true);
992  DrawB->setChecked(false);
993  PolyB->setChecked(false);
994  break;
995  case kMouseDraw: // currently, we only draw arrows:
996  CursorB->setChecked(false);
997  RegionB->setChecked(false);
998  LatexB->setChecked(false);
999  DrawB->setChecked(true);
1000  PolyB->setChecked(false);
1001  break;
1002  default:
1003  CursorB->setChecked(false);
1004  RegionB->setChecked(false);
1005  LatexB->setChecked(false);
1006  DrawB->setChecked(false);
1007  PolyB->setChecked(false);
1008  break;
1009  }; // switch()
1010  FreezeMode->setChecked(fbPickAgain);
1011 
1012  SelectedMarkerCmb->clear();
1013  SelectedMarkerCmb->addItem("new");
1014 
1015  TGo4Slot* slot = GetPadSlot(GetActivePad());
1016  int findindx = -1;
1017 
1018  QString selname = GetSelectedMarkerName(GetActivePad());
1019  int selindex = GetSelectedMarkerIndex(GetActivePad());
1020 
1021  if (slot != 0)
1022  for (int n = 0; n < slot->NumChilds(); n++) {
1023  TGo4Slot* subslot = slot->GetChild(n);
1024  int drawkind = GetDrawKind(subslot);
1025  if ((drawkind == kind_Marker) || (drawkind == kind_Window)
1026  || (drawkind == kind_Poly) || (drawkind == kind_Condition)) {
1027  TObject* obj = subslot->GetAssignedObject();
1028  if (obj == 0)
1029  continue;
1030 
1031  if (obj->InheritsFrom(TGo4CondArray::Class())) {
1032  TGo4CondArray* arr = (TGo4CondArray*) obj;
1033  for (int ncon = 0; ncon < arr->GetNumber(); ncon++) {
1034  TGo4Condition* sub = arr->At(ncon);
1035  QString fullname(arr->GetName());
1036  fullname += "/Sub";
1037  fullname += QString::number(ncon);
1038  SelectedMarkerCmb->addItem(fullname);
1039 
1040  if ((selname == obj->GetName()) && (selindex == ncon))
1041  findindx = SelectedMarkerCmb->count() - 1;
1042  }
1043  } else {
1044  SelectedMarkerCmb->addItem(obj->GetName());
1045  if (selname == obj->GetName())
1046  findindx = SelectedMarkerCmb->count() - 1;
1047  }
1048  }
1049  }
1050 
1051  if (findindx < 0) {
1052  findindx = 0;
1053  SetSelectedMarker(GetActivePad(), "", -1);
1054  }
1055 
1056  SelectedMarkerCmb->setCurrentIndex(findindx);
1057  DelSelectedMarker->setEnabled((findindx > 0) /*&& !iscondition*/);
1058 
1059  if (fbMarkEditorVisible) {
1060  MarkerPanel->ensurePolished();
1061  MarkerPanel->update();
1062  MarkerPanel->show();
1063  }
1064  fbTypingMode = true;
1065 }
1066 
1068 {
1069  if (!fbTypingMode)
1070  return;
1071  if (indx == 0)
1072  SetSelectedMarker(GetActivePad(), "", -1);
1073  else {
1074  QString selname = SelectedMarkerCmb->itemText(indx);
1075  int selindex = -1;
1076  int p = selname.indexOf("/Sub");
1077  if (p > 0) {
1078  selindex = selname.mid(p + 4).toInt();
1079  selname.truncate(p);
1080  } else
1081  selindex = -1;
1082  SetSelectedMarker(GetActivePad(), selname, selindex);
1083  }
1084 
1085  int drawkind = 0;
1086  TGo4Slot* slot = GetSelectedSlot(GetActivePad(), &drawkind, 0);
1087 
1088  if ((slot != 0) && (drawkind > 0)) {
1089  SetActiveObj(GetActivePad(), drawkind, slot);
1090  SwitchMarkerButton(drawkind, true);
1091  } else
1093 }
1094 
1096 {
1097  if (!fbTypingMode) return;
1098  TGo4Slot* slot = GetSelectedSlot(GetActivePad(), 0, 0);
1099  if (slot == 0) return;
1100  delete slot;
1101  SetSelectedMarker(GetActivePad(), "", -1);
1102  RedrawPanel(GetActivePad(), true);
1103 }
1104 
1106 {
1108  if (!fbMarkEditorVisible) {
1109  // switch back to normal root mouse when editor is hidden
1112  gROOT->SetEditorMode("");
1113  fiPickCounter = 0;
1114  }
1115  RefreshButtons();
1117 }
1118 
1120 {
1121  if (!fbTypingMode)
1122  return;
1123 
1124  TGo4Slot* slot = GetPadSlot(GetActivePad());
1125  if (slot == 0)
1126  return;
1127 
1128  for (int n = 0; n < slot->NumChilds(); n++) {
1129  TGo4Slot* subslot = slot->GetChild(n);
1130  int drawkind = GetDrawKind(subslot);
1131  TObject* obj = subslot->GetAssignedObject();
1132  if ((drawkind < kind_Condition) || (obj == 0))
1133  continue;
1134  switch (drawkind) {
1135  case kind_Marker:
1136  obj->Print("*");
1137  break;
1138  case kind_Latex:
1139  obj->Print("*");
1140  break;
1141  case kind_Arrow:
1142  obj->Print("go4log");
1143  break;
1144  case kind_Window:
1145  case kind_Poly:
1146  case kind_Condition:
1147  obj->Print("go4log-limits-stats");
1148  break;
1149  }
1150  }
1151 }
1152 
1154 {
1155  TGo4LockGuard lock;
1156 
1157  TPad* pad = IsApplyToAllFlag() ? GetCanvas() : GetActivePad();
1158  if (pad == 0)
1159  pad = GetCanvas();
1160 
1162 
1163  RedrawPanel(pad, true);
1164 }
1165 
1166 void TGo4ViewPanel::ProcessMarkersClear(TPad *pad, bool withsubpads)
1167 {
1168  if (pad == 0) return;
1169 
1175  if (!withsubpads) return;
1176 
1177  TGo4Slot* slot = GetPadSlot(pad);
1178  if (slot == 0) return;
1179 
1180  TGo4Iter iter(slot, true);
1181  while (iter.next()) {
1182  TPad* subpad = GetSlotPad(iter.getslot());
1183  if (subpad != 0)
1184  ProcessMarkersClear(subpad, false);
1185  }
1186 }
1187 
1189 {
1190  TGo4Slot* slot = GetSelectedSlot(GetActivePad(), 0, 0);
1191  if (GetDrawKind(slot) != kind_Condition)
1192  return;
1193  const char* itemname = GetLinkedName(slot);
1194  if (itemname == 0)
1195  return;
1196 
1197  Browser()->GetBrowserObject(itemname, 2);
1198 
1199  RefreshButtons();
1200 }
1201 
1203 {
1204  TGo4Slot* slot = GetSelectedSlot(GetActivePad(), 0, 0);
1205  if (GetDrawKind(slot) != kind_Condition)
1206  return;
1207  const char* itemname = GetLinkedName(slot);
1208  if (itemname != 0)
1209  ShowItemInfo(itemname);
1210 }
1211 
1213 {
1214  TGo4Slot* slot = GetSelectedSlot(GetActivePad(), 0, 0);
1215  if (GetDrawKind(slot) != kind_Condition) return;
1216  const char* itemname = GetLinkedName(slot);
1217  if (itemname != 0)
1218  EditItem(itemname);
1219 }
1220 
1222 {
1223  TGo4Slot* slot = GetSelectedSlot(GetActivePad(), 0, 0);
1224  if (GetDrawKind(slot) != kind_Condition) return;
1225  const char* itemname = GetLinkedName(slot);
1226  if (itemname != 0) {
1227  UpdateItemInAnalysis(itemname);
1228  TGo4Condition* cond = dynamic_cast<TGo4Condition*>(slot->GetAssignedObject());
1229  if(cond!=0) cond->SetChanged(kFALSE);
1230  RefreshButtons();
1231  }
1232 }
1233 
1235 {
1236  QFileDialog fd(this, "Save Markers of active pad into", QString(),
1237  "ROOT file (*.root)");
1238  fd.setFileMode(QFileDialog::AnyFile);
1239  fd.setAcceptMode(QFileDialog::AcceptSave);
1240  if (fd.exec() == QDialog::Accepted) {
1241  QStringList flst = fd.selectedFiles();
1242  if (flst.isEmpty())
1243  return;
1244 
1245  QString filename = flst[0];
1246  if (!filename.endsWith(".root"))
1247  filename.append(".root");
1248 // fxTGo4PreviewPanelSlots->SaveMarkerSetup(filename,"Markersetup");
1249  }
1250 }
1251 
1253 {
1254  QFileDialog fd(this, "Load Marker setup from:", QString(),
1255  "ROOT file (*.root)");
1256  fd.setFileMode(QFileDialog::ExistingFile);
1257  if (fd.exec() == QDialog::Accepted) {
1258  QStringList flst = fd.selectedFiles();
1259  if (flst.isEmpty())
1260  return;
1261  QString filename = flst[0];
1262  }
1263 }
1264 
1266 {
1267  TGo4LockGuard lock;
1268 
1269  if (fxActivePad != pad)
1271 
1272  raise();
1273 
1274  if (pad == 0) {
1275  if (!fxWCanvas) {
1276  GetCanvas()->SetSelected(0);
1277  GetCanvas()->SetSelectedPad(0);
1278  CanvasUpdate();
1279  }
1280  return;
1281  }
1282 
1283  fxActivePad = pad;
1284  if (!fxWCanvas) {
1285  fxActivePad->cd();
1286  GetCanvas()->SetSelectedPad(fxActivePad);
1287  }
1288 
1290 
1291  // no need for update of web canvas here
1292  if (!fxWCanvas) {
1293  BlockPanelRedraw(true);
1294  CanvasUpdate();
1295  BlockPanelRedraw(false);
1296  }
1297 
1299 
1302 }
1303 
1304 void TGo4ViewPanel::PadClickedSlot(TPad* pad, int px, int py)
1305 {
1306  TGo4LockGuard lock;
1307  SetActivePad(pad);
1308 
1309  if (pad == 0)
1310  return;
1311  if ((px<0) || (py<0)) {
1312  px = pad->GetEventX();
1313  py = pad->GetEventY();
1314  }
1315  // std::cout <<"TGo4ViewPanel:PadClickedSlot() begins with mouse mode: "<< fiMouseMode << ", px:"<<px<<", py:"<<py << std::endl;
1316 
1317  Double_t x = pad->PadtoX(pad->AbsPixeltoX(px));
1318  Double_t y = pad->PadtoY(pad->AbsPixeltoY(py));
1319 
1320  bool docreate = GetSelectedMarkerName(pad).length() == 0;
1321  bool docheck = false;
1322  bool iscreated = false;
1323 
1324  switch (fiMouseMode) {
1325  case kMouseROOT: {
1326  TObject *obj = GetCanvas()->GetSelected();
1327  if (obj != 0)
1328  if (obj->InheritsFrom(TGo4Marker::Class())
1329  || obj->InheritsFrom(TGo4WinCondView::Class())
1330  || obj->InheritsFrom(TGo4PolyCondView::Class()))
1331  SetSelectedMarkerByMouseClick(pad, obj->GetName());
1332 
1333  break;
1334  }
1335 
1336  case kMousePickCursor: {
1337  // we have a click on our working pad, get coordinates:
1338  gROOT->SetEditorMode("");
1339  //std::cout <<"TGo4ViewPanel:PadClickedSlot() picks cursor with docreate: "<< docreate <<std::endl;
1340 
1341  if (docreate) {
1342  TGo4Marker* mark = new TGo4Marker(x, y, 28);
1343  AddMarkerObj(pad, kind_Marker, mark);
1344  Int_t ix = TGo4Marker::GetInstances() - 1;
1345  mark->SetMarkerColor((ix) % 6 + 2);
1346  mark->SetHistogram(GetPadHistogram(pad));
1347  if (!fbPickAgain)
1348  fiMouseMode = kMouseROOT; // reset pick
1349  mark->Draw("");
1350  } else {
1351  TGo4Marker* mark = dynamic_cast<TGo4Marker*>(GetActiveObj(pad, kind_Marker));
1352  if(mark!=0) {
1353  mark->SetX(x);
1354  mark->SetY(y);
1355  }
1356  if (!fbPickAgain) fiMouseMode=kMouseROOT; // reset pick
1357  }
1358  CanvasUpdate(true);
1359 
1360 // RedrawPanel(pad, true);
1361  break;
1362  }
1363 
1364  case kMousePickLimits: {
1365  gROOT->SetEditorMode("");
1366  TGo4WinCond* conny = 0;
1367  Double_t xmin(x), xmax(x), ymin(y), ymax(y);
1368  if (fiPickCounter == 0) {
1369  // pick the first time after enabling limits record:
1370  if (docreate) {
1371  TH1* hist = GetPadHistogram(pad);
1372  bool fbTwoDimRegion = (hist != 0) && (hist->GetDimension() > 1);
1373  int ix = GetNumMarkers(pad, kind_Window);
1374  QString name = "Region " + QString::number(ix + 1);
1375  conny = new TGo4WinCond(name.toLatin1().constData());
1376  iscreated = true;
1377  if (fbTwoDimRegion)
1378  conny->SetValues(0, 0, 0, 0);
1379  else
1380  conny->SetValues(0, 0);
1381  conny->SetLineColor(GetAutoColor(ix%9 + 1));
1382  conny->SetFillColor(GetAutoColor(ix%9 + 1));
1383  conny->SetFillStyle(3002);
1384  conny->SetWorkHistogram(hist);
1385  // adjust two dim region to one dim defaults
1386  conny->SetYRMSDraw(fbTwoDimRegion && conny->IsXRMSDraw());
1387  conny->SetYMeanDraw(fbTwoDimRegion && conny->IsXMeanDraw());
1388  conny->SetYMaxDraw(fbTwoDimRegion && conny->IsXMaxDraw());
1389  AddMarkerObj(pad, kind_Window, conny);
1390  } else
1391  conny = dynamic_cast<TGo4WinCond*>(GetActiveObj(pad, kind_Window));
1392  if(conny==0) return;
1393  fiPickCounter++;
1394  } else
1395  if (fiPickCounter==1) {
1396  conny = dynamic_cast<TGo4WinCond*> (GetActiveObj(pad, kind_Window));
1397  if(conny==0) return;
1398  xmin = conny->GetXLow();
1399  ymin = conny->GetYLow();
1400  fiPickCounter=0;
1402  docheck = true;
1403  } else {
1404  std::cout <<"TGo4ViewPanel:PadClickedSlot() NEVER COME HERE" << std::endl;
1405  return;
1406  }
1407  // do not change original condition dimension
1408  if (conny->GetDimension() > 1)
1409  conny->SetValues(xmin, xmax, ymin, ymax);
1410  else
1411  conny->SetValues(xmin, xmax);
1412 
1413  TGo4Slot* condslot = GetSelectedSlot(pad, 0, 0);
1414  if (GetDrawKind(condslot) == kind_Condition) {
1415  TGo4Condition* maincond =
1416  dynamic_cast<TGo4Condition*>(condslot->GetAssignedObject());
1417  if (maincond) maincond->SetChanged();
1418  }
1419 
1420  conny->SetChanged();
1421  if (iscreated)
1422  conny->Draw("");
1423  CanvasUpdate(true);
1424  // std::cout <<"TGo4ViewPanel:PadClickedSlot() after CanvasUpdate for windowr"<<std::endl;
1425 
1426 
1427  // RedrawPanel(pad, true);
1428  break;
1429  }
1430 
1431  case kMousePickPolygon: {
1432  // std::cout <<"TGo4ViewPanel:PadClickedSlot() in kMousePickPolygon, fiPickCounter="<<fiPickCounter << std::endl;
1433  gROOT->SetEditorMode("");
1434  TGo4PolyCond* cond = 0;
1435 
1436  if (fiPickCounter == 0) {
1437  // pick the first time after enabling limits record:
1438  if (docreate) {
1439  // std::cout <<"TGo4ViewPanel:PadClickedSlot() creates polygon" << std::endl;
1440  TH1* hist = GetPadHistogram(pad);
1441  int ix = GetNumMarkers(pad, kind_Poly);
1442  QString name = "Polygon " + QString::number(ix + 1);
1443  cond = new TGo4PolyCond(name.toLatin1().constData());
1444  iscreated = true;
1445  AddMarkerObj(pad, kind_Poly, cond);
1446  cond->SetWorkHistogram(hist);
1447  } else {
1448  // std::cout <<"TGo4ViewPanel:PadClickedSlot() works on existing polygon" << std::endl;
1449 
1450  cond = dynamic_cast<TGo4PolyCond*>(GetActiveObj(pad, kind_Poly));
1451  // start region from the beginning
1452  if (cond!=0) {
1453  TCutG* cut = cond->GetCut(kTRUE);
1454  delete cut;
1455  }
1456  }
1457  if(cond==0) return;
1458  fiPickCounter++;
1459  } else {
1460  cond = dynamic_cast<TGo4PolyCond*> (GetActiveObj(pad, kind_Poly));
1461  if(cond==0) return;
1462  fiPickCounter++;
1463  }
1464 
1465  if (cond != 0) {
1466  TCutG* cut = cond->GetCut(kFALSE);
1467  // this insert point in last mouse position
1468  if (cut == 0) {
1469  cut = new TCutG(TGo4PolyCond::NextAvailableName(), 1);
1470  cut->SetPoint(0, x, y);
1471  cut->SetPoint(1, x, y); // JAM2019- otherwise we will lose first point to zero when defining next ones
1472  cond->SetValuesDirect(cut);
1473  } else {
1474  //cut->InsertPoint(); // JAM2019 - this gives ROOT6 error also without webcanvas
1475  cut->SetPoint(fiPickCounter, x, y);
1476  }
1477 
1478  cond->SetChanged();
1479 
1480  int ix = GetNumMarkers(pad, kind_Poly);
1481 
1482  cond->SetLineColor(GetAutoColor(ix%9 + 1));
1483  cond->SetFillColor(GetAutoColor(ix%9 + 1));
1484  cond->SetFillStyle(3002);
1485  }
1486 
1487  // mark condition
1488  TGo4Slot* condslot = GetSelectedSlot(pad, 0, 0);
1489  if (GetDrawKind(condslot) == kind_Condition) {
1490  TGo4Condition* maincond =
1491  dynamic_cast<TGo4Condition*>(condslot->GetAssignedObject());
1492  if (maincond) maincond->SetChanged();
1493  }
1494 
1495  if (iscreated)
1496  cond->Draw("");
1497  CanvasUpdate(true);
1498 // std::cout <<"TGo4ViewPanel:PadClickedSlot() after CanvasUpdate for polygon"<<std::endl;
1499 
1500 
1501  // RedrawPanel(pad, true);
1502  break;
1503  }
1504 
1505  case kMousePickLatex: {
1506  gROOT->SetEditorMode("");
1507  if (docreate) {
1508  int ix = GetNumMarkers(pad, kind_Latex);
1509  QString name = QString("Label ") + QString::number(ix + 1);
1510  bool ok;
1511  QString txt = QInputDialog::getText(this,
1512  "Enter new LaTeX label text:", name, QLineEdit::Normal,
1513  QString(), &ok);
1514  if (ok && (txt.length() > 0)) {
1515  TLatex* latex = new TLatex(x, y, name.toLatin1().constData());
1516  latex->SetName(name.toLatin1().constData());
1517  latex->SetTitle(txt.toLatin1().constData());
1518  AddMarkerObj(pad, kind_Latex, latex);
1519  latex->Draw();
1520  } else {
1522  }
1523  } else {
1524  TLatex* latex = dynamic_cast<TLatex*>(GetActiveObj(pad, kind_Latex));
1525  if(latex!=0) {
1526  latex->SetX(x);
1527  latex->SetY(y);
1528  }
1529  }
1530  if (!fbPickAgain)
1531  fiMouseMode = kMouseROOT; // reset pick
1532 
1533 // pad->Modified();
1534 // pad->Update();
1535 
1536  CanvasUpdate(true);
1537  // std::cout <<"TGo4ViewPanel:PadClickedSlot() after CanvasUpdate for latex"<<std::endl;
1538 
1539 
1540 // RedrawPanel(pad, true);
1541  break;
1542  }
1543 
1544  case kMouseDraw: {
1545  gROOT->SetEditorMode("");
1546  if (fiPickCounter == 0) {
1547  // pick the first time after enabling limits record:
1548  TArrow* arrow = new TArrow(x, y, x, y, 0.02);
1549  AddMarkerObj(pad, kind_Arrow, arrow);
1550  fiPickCounter++;
1551  arrow->Draw("");
1552  } else if (fiPickCounter == 1) {
1553  TArrow* arrow = dynamic_cast<TArrow*>(GetActiveObj(pad, kind_Arrow));
1554  if(arrow!=0) {
1555  arrow->SetX2(x);
1556  arrow->SetY2(y);
1557  }
1558  if(!fbPickAgain) fiMouseMode=kMouseROOT; // reset pick
1559  fiPickCounter=0;
1560  } else {
1561  std::cout <<"TGo4ViewPanel:MouseClick() NEVER COME HERE" << std::endl;
1562  return;
1563  }
1564  // do not change original arrow dimension
1565 // pad->Modified();
1566 // pad->Update();
1567 
1568  CanvasUpdate(true);
1569  // std::cout <<"TGo4ViewPanel:PadClickedSlot() after CanvasUpdate for arrow"<<std::endl;
1570 
1571  // RedrawPanel(pad, true);
1572  break;
1573  }
1574  }
1575  // std::cout <<"TGo4ViewPanel:PadClickedSlot() has docheck: "<< docheck <<std::endl;
1576 
1577  if (docheck)
1578  CheckActionAtTheEnd(pad);
1579 }
1580 
1582 {
1583  // std::cout <<"TGo4ViewPanel::CheckActionAtTheEnd"<< std::endl;
1584 
1585  bool goback = true;
1586 
1587 // uncomment this code to have loop mode for array of conditions
1588 
1589 // if(fbPickAgain) {
1590 // QString selname = GetSelectedMarkerName(pad);
1591 // int selindex = GetSelectedMarkerIndex(pad);
1592 // if (selindex>=0) {
1593 // TGo4Slot* slot = GetSelectedSlot(pad, 0, 0);
1594 // TGo4CondArray* arr = 0;
1595 // if (slot!=0)
1596 // arr = dynamic_cast<TGo4CondArray*> (slot->GetAssignedObject());
1597 // if (arr!=0) {
1598 // if (selindex<arr->GetNumber()-1) {
1599 // SetSelectedMarker(pad, selname, selindex+1);
1600 // goback = false;
1601 // }
1602 // else
1603 // SetSelectedMarker(pad, "", -1);
1604 // }
1605 // }
1606 // }
1607  if (goback) {
1609  ServiceCall("ActivateConditionEditor");
1610  fbLeaveFocusAfterCondEnd = false;
1611 // MarkPadModified(pad);
1612 // ShootRepaintTimer(pad);
1613  }
1614 }
1615 
1617 {
1618  bool res = false;
1619  bool needredraw = false; // complete repaint
1620  bool needupdate = false; // only pad update
1621  bool needrefresh = true; //false; // refresh buttons
1622  bool docheck = false;
1623  bool candelete = !IsConditionSelected(pad);
1624  //std::cout <<"TGo4ViewPanel::CompleteMarkerEdit begins with mouse mode: "<< fiMouseMode << std::endl;
1625 
1626  switch (fiMouseMode) {
1627  case kMousePickLimits: {
1628  if (fiPickCounter > 0) {
1629  TGo4WinCond* cond = dynamic_cast<TGo4WinCond*>(GetActiveObj(pad, kind_Window));
1630  if (cond!=0) {
1631  if (candelete) DeleteDrawObject(pad, cond);
1632  needredraw = true;
1633  }
1634  fiPickCounter = 0;
1636  docheck = true;
1637  }
1638 
1639  res = true;
1640  break;
1641  }
1642 
1643  case kMousePickPolygon: {
1644  if (fiPickCounter>0) {
1645  TGo4PolyCond* cond = dynamic_cast<TGo4PolyCond*> (GetActiveObj(pad,kind_Poly));
1646  if (cond!=0) {
1647  bool delcond = true;
1648  TCutG* cut = cond->GetCut(kFALSE);
1649  if (cut!=0) {
1650  int n = cut->GetN();
1651  Double_t x, y;
1652  cut->GetPoint(0, x, y);
1653  delcond = (n<3);
1654 
1655  if (n>=3)
1656  cut->SetPoint(n, x, y);
1657 
1658  int ix = GetNumMarkers(pad, kind_Poly);
1659  cond->SetLineColor(GetAutoColor(ix%9 + 1));
1660  cond->SetFillColor(GetAutoColor(ix%9 + 1));
1661  cond->SetFillStyle(3002);
1662  }
1663 
1664  if (delcond && candelete) {
1665  DeleteDrawObject(pad, cond);
1666  needredraw = true;
1667  } else {
1668  needupdate = true;
1669  }
1670  }
1672  fiPickCounter = 0;
1673  docheck = true;
1674  }
1675 
1676  needrefresh = true;
1677  res = true;
1678  break;
1679  }
1680 
1681  case kMouseDraw: {
1682  if (fiPickCounter>0) {
1683  TArrow* arrow = dynamic_cast<TArrow*> (GetActiveObj(pad, kind_Arrow));
1684  if (arrow!=0) {
1685  DeleteDrawObject(pad, arrow);
1686  needredraw = true;
1687  }
1688  fiPickCounter = 0;
1690  }
1691  res = true;
1692  break;
1693  }
1694  }
1695  if (needredraw)
1696  RedrawPanel(pad, true);
1697  else {
1698  if (needupdate) {
1699  CanvasUpdate(true);
1700 // pad->Modified();
1701 // pad->Update();
1702  }
1703  if (needrefresh)
1704  RefreshButtons();
1705  }
1706 
1707  if (docheck)
1708  CheckActionAtTheEnd(pad);
1709 
1710  return res;
1711 }
1712 
1713 void TGo4ViewPanel::PadDoubleClickedSlot(TPad* pad, int, int)
1714 {
1715  // std::cout <<"TGo4ViewPanel::PadDoubleClickedSlot"<< std::endl;
1716  if (CompleteMarkerEdit(pad)) return;
1717  if (fxDoubleClickTimerPad != 0) return;
1718 
1719  fxDoubleClickTimerPad = pad;
1720  QTimer::singleShot(100, this, SLOT(ProcessPadDoubleClick()));
1721 }
1722 
1723 void TGo4ViewPanel::CanvasDropEventSlot(QDropEvent* event, TPad* pad)
1724 {
1725  emit widgetService(this, service_DropEvent, (const char*) pad, event);
1726 }
1727 
1729 {
1730  if (fxDoubleClickTimerPad == 0) return;
1731 
1732  if (GetNumberOfPads(GetCanvas()) <= 1) {
1733  MoveScale(1,0,0,0);
1735  return;
1736  }
1737 
1738  TGo4Picture pic;
1741 
1742  if (pic.GetNumObjNames() == 0) return;
1743 
1744  TGo4ViewPanel* newpanel = CreateViewPanel();
1745  newpanel->ProcessPictureRedraw("", newpanel->GetCanvas(), &pic);
1746  newpanel->ShootRepaintTimer();
1747 }
1748 
1749 
1750 TH1 *TGo4ViewPanel::Get_fHistogram(TObject *obj, bool force)
1751 {
1752  // return fHistogram member of THStack, TMultiGraph, TGraph
1753  if (!obj) return 0;
1754 
1755  Long_t offset =obj->IsA()->GetDataMemberOffset("fHistogram");
1756  if (offset <= 0) return 0;
1757 
1758  TH1 **hist = (TH1 **)((char*) obj + offset);
1759 
1760  if (!force || IsWebCanvas()) return *hist;
1761 
1762  if (obj->IsA()==THStack::Class())
1763  return ((THStack *)obj)->GetHistogram();
1764 
1765  if (obj->IsA() == TMultiGraph::Class())
1766  return ((TMultiGraph *)obj)->GetHistogram();
1767 
1768  TGraph *gr = dynamic_cast<TGraph *> (obj);
1769  if (gr) return gr->GetHistogram();
1770 
1771  return *hist;
1772 }
1773 
1774 
1775 void TGo4ViewPanel::MenuCommandExecutedSlot(TObject* obj, const char* cmdname)
1776 {
1777  TPad* pad = dynamic_cast<TPad*>(obj);
1778  if (pad != 0)
1779  UpdatePadStatus(pad, true);
1780 
1781  Browser()->Scan_gROOT();
1782 
1783  if ((strcmp(cmdname, "UnZoom") == 0) && obj->InheritsFrom(TAxis::Class())) {
1784 
1785  // this code is done specially to treat unzoom in the THStack
1786 
1787  TGo4Iter iter(GetPanelSlot(), kTRUE);
1788  TGo4Slot* subslot = 0;
1789 
1790  do {
1791  if (subslot == 0)
1792  subslot = GetPanelSlot();
1793  else
1794  subslot = iter.getslot();
1795 
1796  TPad* subpad = GetSlotPad(subslot);
1797  if (subpad == 0)
1798  continue;
1799 
1800  TGo4Slot* sislot = GetSuperimposeSlot(subslot);
1801  if (sislot == 0)
1802  continue;
1803 
1804  THStack* hs = dynamic_cast<THStack*>(sislot->GetAssignedObject());
1805 
1806  // prevent creation of histogram when not exists
1807  TH1 *framehisto = Get_fHistogram(hs);
1808  if (!framehisto) continue;
1809 
1810  if (framehisto->GetXaxis() != obj) continue;
1811 
1812  TIter next(hs->GetHists());
1813  TH1* hs_h1 = 0;
1814  while ((hs_h1 = (TH1*) next()) != 0)
1815  hs_h1->GetXaxis()->UnZoom();
1816 
1817  return;
1818  } while (iter.next());
1819  }
1820 }
1821 
1823 {
1824  //std::cout <<"UUUUUUUU TGo4ViewPanel::CanvasUpdatedSlot()"<< std::endl;
1825  if (fxWCanvas) {
1826  TCanvasImp *imp = GetCanvas()->GetCanvasImp();
1827  fxCanvasEventstatusChk->setChecked(imp->HasStatusBar());
1828  fxCanvasEditorChk->setChecked(imp->HasEditor());
1829  } else {
1830 
1831  ResizeGedEditor();
1832  }
1833 }
1834 
1836 {
1837  ServiceCall("SavePanelCanvas");
1838 }
1839 
1841 {
1842  TGo4Picture* pic = new TGo4Picture(GetPanelName(), "Copy of picture");
1843 
1844  MakePictureForPad(pic, GetCanvas(), false);
1845 
1846  SaveObjectInMemory("", pic);
1847 }
1848 
1850 {
1851  // get list of markers here
1852  TObjArray markers;
1854  Int_t npts = markers.GetEntries();
1855  //std::cout <<"Found "<<npts<<" markers in pad" << std::endl;
1856  if (npts == 0)
1857  return;
1858  // create arrays of length
1859  TArrayD x(npts), y(npts);
1860  // copy marker values to array:
1861  for (Int_t j = 0; j < npts; ++j) {
1862  TGo4Marker* mark = dynamic_cast<TGo4Marker*>(markers[j]);
1863  if (mark == 0) {
1864  std::cout << "NEVER COME HERE: no marker at index " << j << std::endl;
1865  return;
1866  }
1867  x[j] = mark->GetX();
1868  y[j] = mark->GetY();
1869  //std::cout <<"Set point "<<j <<" to x="<<x[j]<<", y="<<y[j]<< std::endl;
1870  }
1871 
1872  // create graph from points array:
1873  TString grname = GetPanelName() + TString("-Markergraph");
1874  TGraph* graf = new TGraph(npts, x.GetArray(), y.GetArray());
1875  graf->SetName(grname.Data());
1876  graf->SetMarkerStyle(28);
1877  SaveObjectInMemory("", graf);
1878 }
1879 
1880 void TGo4ViewPanel::MakePictureForPad(TGo4Picture* pic, TPad* pad, bool useitemname)
1881 {
1882  TGo4Picture* padopt = GetPadOptions(pad);
1883  TGo4Slot* slot = GetPadSlot(pad);
1884  if ((padopt == 0) || (slot == 0)) return;
1885 
1886  pic->CopyOptionsFrom(padopt);
1887 
1890 
1891  if (pad == GetCanvas() && fbFreezeTitle)
1892  pic->SetTitle(fFreezedTitle.toLatin1().constData());
1893 
1894  if (!padopt->IsXYRatioOne())
1895  pic->SetFrameAttr(pad);
1896 
1897  int objnamenum = 0;
1898 
1899  for (int n = 0; n < slot->NumChilds(); n++) {
1900  TGo4Slot* subslot = slot->GetChild(n);
1901  int kind = GetDrawKind(subslot);
1902 
1903  if ((kind == kind_Arrow) || (kind == kind_Latex) || (kind == kind_Marker)
1904  || (kind == kind_Window) || (kind == kind_Poly) || (kind == kind_Func)
1905  || (kind == kind_Specials)) {
1906  TObject* obj = subslot->GetAssignedObject();
1907  const char* drawopt = GetSpecialDrawOption(subslot);
1908 
1909  if (obj != 0) {
1910  if (dynamic_cast<TLatex*>(obj) || dynamic_cast<TF1*>(obj)) {
1911  // test here if we have local object or monitored remote one
1912  if (dynamic_cast<TGo4ObjectProxy*>(subslot->GetProxy())) {
1913  // make clone when really needed
1914  pic->AddSpecialObject(obj->Clone(), drawopt);
1915  } else if (dynamic_cast<TGo4LinkProxy*>(subslot->GetProxy())) {
1916  const char* itemname = GetLinkedName(subslot);
1917  if (itemname != 0)
1918  pic->AddObjName(itemname, drawopt);
1919  } else {
1920  TGo4Log::Error("MakePictureForPad NEVER COME HERE, unknown proxy type");
1921  }
1922  } else {
1923  obj = obj->Clone();
1924 
1925  TGo4Marker* mark = dynamic_cast<TGo4Marker*>(obj);
1926  if (mark != 0) mark->DeletePainter();
1927  TGo4Condition* cond = dynamic_cast<TGo4Condition*>(obj);
1928  if (cond != 0) cond->DeletePainter();
1929 
1930  pic->AddSpecialObject(obj, drawopt);
1931  }
1932  }
1933  continue;
1934  }
1935 
1936  if ((kind != kind_Link) && (kind != kind_Condition))
1937  continue;
1938 
1939  const char* drawopt = padopt->GetDrawOption(objnamenum++);
1940 
1941  if (useitemname) {
1942  const char* itemname = GetLinkedName(subslot);
1943  if (itemname != 0)
1944  pic->AddObjName(itemname, drawopt);
1945  } else {
1946  TNamed* nm = dynamic_cast<TNamed*>(subslot->GetAssignedObject());
1947  if (nm!=0) pic->AddObjName(nm->GetName(), drawopt);
1948  }
1949 
1950  Int_t rebinx, rebiny;
1951  if (subslot->GetIntPar("::HasRebinX", rebinx))
1952  pic->SetRebinX(rebinx);
1953  if (subslot->GetIntPar("::HasRebinY", rebiny))
1954  pic->SetRebinY(rebiny);
1955  }
1956 
1957  TObjArray pads;
1958 
1959  for (int n = 0; n < slot->NumChilds(); n++) {
1960  TGo4Slot* subslot = slot->GetChild(n);
1961  TPad* subpad = GetSlotPad(subslot);
1962  if (subpad != 0)
1963  pads.Add(subpad);
1964  }
1965  if (pads.GetLast() < 0)
1966  return;
1967 
1968  double lastx = -1;
1969  int xcnt = 0, sizex = 1, sizey = 1;
1970  for (int n = 0; n <= pads.GetLast(); n++) {
1971  TPad* subpad = (TPad*) pads.At(n);
1972  double mitx = subpad->GetXlowNDC() + subpad->GetWNDC() / 2.;
1973  if (mitx > lastx) {
1974  xcnt++;
1975  lastx = mitx;
1976  } else {
1977  xcnt = 0;
1978  lastx = -1;
1979  }
1980  if (xcnt > sizex)
1981  sizex = xcnt;
1982  }
1983 
1984  while (sizex * sizey <= pads.GetLast())
1985  sizey++;
1986 
1987  pic->SetDivision(sizey, sizex);
1988 
1989  for (int ny = 0; ny < sizey; ny++)
1990  for (int nx = 0; nx < sizex; nx++) {
1991  int indx = ny * sizex + nx;
1992  if (indx > pads.GetLast())
1993  break;
1994  TPad* subpad = (TPad*) pads.At(indx);
1995  MakePictureForPad(pic->Pic(ny, nx), subpad, useitemname);
1996  }
1997 }
1998 
2000 {
2001  TGo4PrintWidget dlg;
2002  if (dlg.exec() != QDialog::Accepted)
2003  return;
2004 
2006 
2007  QString outfile = "~/go4printout.ps";
2008  QString PrnCmd = dlg.GetPrintProg() + " -P " + dlg.GetPrinter() + " "
2009  + outfile;
2010  QString DelCmd = QString("rm -f ") + outfile;
2011 
2012  GetCanvas()->Print(outfile.toLatin1().constData());
2013  gSystem->Exec(PrnCmd.toLatin1().constData());
2014  gSystem->Exec(DelCmd.toLatin1().constData());
2015 }
2016 
2018 {
2019  bool visible = false;
2020  std::cout << "DDDDDDDDD TGo4ViewPanel::StartRootEditor()" << std::endl;
2021  if (fxQCanvas) {
2022 #ifdef __GO4X11__
2023  if (!fxQCanvas->isEditorAllowed()) return;
2024 
2025  visible = !fxQCanvas->isEditorVisible();
2026 
2027  if (visible)
2029 
2031 #endif
2032  } else if (fxWCanvas) {
2033 
2034 #ifdef __GO4WEB__
2035 
2036  // SetActivePad(GetCanvas());
2037 
2038  visible = !fxWCanvas->isEditorVisible();
2039 
2040  fxWCanvas->setEditorVisible(visible);
2041 
2042 #endif
2043  }
2044 
2045  if (visible)
2047 
2048  show();
2049 
2050  ResizeGedEditor();
2051 }
2052 
2054 {
2055  TGo4Slot* padslot = GetPadSlot(GetActivePad());
2056  if (padslot == 0)
2057  return;
2058 
2059  for (int n = 0; n < padslot->NumChilds(); n++) {
2060  TGo4Slot* subslot = padslot->GetChild(n);
2061  int drawkind = GetDrawKind(subslot);
2062  if (drawkind != kind_Condition)
2063  continue;
2064  const char* itemname = GetLinkedName(subslot);
2065  if (itemname != 0) {
2066  EditItem(itemname);
2067  return;
2068  }
2069  }
2070 }
2071 
2073 {
2074  if (pad == 0) return;
2075 
2076  double defleft =gStyle->GetPadLeftMargin(); // always refer to ideal margins
2077  double defright =gStyle->GetPadRightMargin();
2078  double deftop =gStyle->GetPadTopMargin();
2079  double defbottom =gStyle->GetPadBottomMargin();
2080 
2081  double dx = fabs(pad->AbsPixeltoX(1) - pad->AbsPixeltoX(0));
2082  double dy = fabs(pad->AbsPixeltoY(1) - pad->AbsPixeltoY(0));
2083  //std::cout <<"-- dx:"<<dx<<", dy:"<<dy<< std::endl;
2084  if ((dx <= 0) || (dy <= 0)) return;
2085  double ratio = dx / dy;
2086  //std::cout <<"-- Ratio is:"<<ratio<< std::endl;
2087  if(fabs(1.0-ratio) < 1.0E-3)
2088  {
2089  //std::cout <<"DO NOT CHANGE!"<< std::endl;
2090  return; // do not change margins again!
2091  }
2092 
2093 
2094  if (ratio < 1.) {
2095 
2096  double left = pad->GetLeftMargin();
2097  double right = pad->GetRightMargin();
2098  double change = (1. - left - right) * (1 - ratio);
2099  //std::cout <<"-- left:"<<left<<", right:"<<right<<", change:"<<change<< std::endl;
2100  double newleft = left + change / 2.;
2101  double newright = right + change / 2.;
2102  double newtop = pad->GetTopMargin();
2103  double newbottom = pad->GetBottomMargin();
2104  //std::cout << " -- newleft"<<newleft<<", newright"<<newright;
2105  //std::cout <<"newtop:"<<newtop<<", newbottom:"<<newbottom<< std::endl;
2106  double shrink=newtop- deftop; // zoom everything consistent to the default margins
2107  if(shrink>newleft-defleft) shrink = newleft-defleft; // avoid exceeding default boundaries
2108  if(shrink>newright-defright) shrink = newright-defright; // avoid exceeding default boundaries
2109 
2110  // now scale all margins up to the point that any margin reaches default margin:
2111  newtop = newtop - shrink;
2112  newbottom = newbottom - shrink;
2113  newleft = newleft - shrink;
2114  newright = newright - shrink;
2115  //std::cout << "after shrink="<<shrink<<" :";
2116  //std::cout << " -- newleft"<<newleft<<", newright"<<newright;
2117  //std::cout <<"newtop:"<<newtop<<", newbottom:"<<newbottom<< std::endl;
2118 
2119  pad->SetLeftMargin(newleft);
2120  pad->SetRightMargin(newright);
2121  pad->SetTopMargin(newtop);
2122  pad->SetBottomMargin(newbottom);
2123  } else {
2124 
2125  double bottom = pad->GetBottomMargin();
2126  double top = pad->GetTopMargin();
2127  double change = (1. - bottom - top) * (1. - 1 / ratio);
2128  //std::cout <<"-- left:"<<left<<", right:"<<right<<", change:"<<change<< std::endl;
2129  double newleft=pad->GetLeftMargin();
2130  double newright=pad->GetRightMargin();
2131  double newtop= top + change / 2.;
2132  double newbottom= bottom + change / 2.;
2133  //std::cout << " -- newleft"<<newleft<<", newright"<<newright;
2134  //std::cout <<"newtop:"<<newtop<<", newbottom:"<<newbottom<< std::endl;
2135  double shrink=newleft - defleft;
2136  if(shrink>newtop-deftop) shrink=newtop-deftop; // avoid exceeding default boundaries
2137  if(shrink>newbottom-defbottom) shrink=newbottom-defbottom; // avoid exceeding default boundaries
2138  // now scale all margins up to the point that any margin reaches default margin:
2139  newtop = newtop - shrink;
2140  newbottom = newbottom -shrink;
2141  newleft = newleft- shrink;
2142  newright = newright - shrink;
2143  //std::cout << "after shrink="<<shrink<<" :";
2144  //std::cout << " -- newleft"<<newleft<<", newright"<<newright;
2145  //std::cout <<"newtop:"<<newtop<<", newbottom:"<<newbottom<< std::endl;
2146 
2147  pad->SetTopMargin(newtop);
2148  pad->SetBottomMargin(newbottom);
2149  pad->SetLeftMargin(newleft);
2150  pad->SetRightMargin(newright);
2151  }
2152 }
2153 
2155 {
2156  if (pad == 0) return;
2157  pad->SetLeftMargin(gStyle->GetPadLeftMargin());
2158  pad->SetRightMargin(gStyle->GetPadRightMargin());
2159  pad->SetTopMargin(gStyle->GetPadTopMargin());
2160  pad->SetBottomMargin(gStyle->GetPadBottomMargin());
2161 }
2162 
2164 {
2165  TPad* pad = GetActivePad();
2166  if (pad == 0)
2167  pad = GetCanvas();
2168 
2169  ClearPad(pad, true, false);
2170 
2171  RedrawPanel(pad, true);
2172 }
2173 
2175 {
2176  // TGo4LockGuard glob;
2177 
2178  ClearPad(GetCanvas(), true, true);
2179 
2181 
2182  RedrawPanel(GetCanvas(), true);
2183 }
2184 
2186 {
2187  TPad* pad = GetActivePad();
2188  if (pad == 0)
2189  pad = GetCanvas();
2190 
2191  TGo4Picture *padopt = GetPadOptions(pad);
2192 
2193  SetIdAction(fOptionsMap, StatisticsId, true, padopt->IsHisStats());
2196  SetIdAction(fOptionsMap, SetTitleId, true, padopt->IsHisTitle());
2198  padopt->IsTitleTime());
2200  padopt->IsTitleDate());
2202  padopt->IsTitleItem());
2205  SetIdAction(fOptionsMap, SetLegendId, true, padopt->IsLegendDraw());
2207  padopt->IsXAxisTimeDisplay());
2209 
2210 }
2211 
2213 {
2214  TGo4LockGuard lock;
2215  if (id == BringToFrontId) {
2219  }
2220  return;
2221  }
2222 
2223  int selected = TGo4Picture::PictureIndex;
2224 
2225  if (id != MasterSelectId)
2226  selected = id - FirstSelectId;
2227 
2228  TGo4Slot* slot = GetPadSlot(GetActivePad());
2229  if (slot == 0)
2230  return;
2231 
2232  int wasselected = GetSelectedObjectIndex(slot);
2233 
2234  SetSelectedObjectIndex(slot, selected);
2235 
2236  if (selected != wasselected) {
2239  }
2240 
2241  if (selected != TGo4Picture::PictureIndex)
2243 }
2244 
2246 {
2247  bool flag = true;
2248  if (fxQCanvas) {
2249 #ifdef __GO4X11__
2250  flag = !fxQCanvas->isStatusBarVisible();
2252 #endif
2253  } else if (fxWCanvas) {
2254 #ifdef __GO4WEB__
2255  flag = !fxWCanvas->isStatusBarVisible();
2257 #endif
2258  }
2259 
2260  fxCanvasEventstatusChk->setChecked(flag);
2261  if (!flag)
2263 }
2264 
2265 void TGo4ViewPanel::UpdatePadStatus(TPad* pad, bool removeitems)
2266 {
2267  if (GetPadSlot(pad) == 0)
2268  return;
2269 
2270  BlockPanelRedraw(true);
2271  ProcessPadStatusUpdate(pad, 0, removeitems);
2272  BlockPanelRedraw(false);
2273 }
2274 
2276  bool removeitems)
2277 {
2278  if (pad == 0)
2279  return;
2280 
2281  TGo4Slot* slot = 0;
2282 
2283  bool setdefaults = false;
2284  if (parent == 0) {
2285  slot = GetPadSlot(pad);
2286  if (slot == 0)
2287  return;
2288  } else {
2289  slot = parent->FindChild(pad->GetName());
2290  // create slot for subpad if not existing
2291  if (slot == 0) {
2292  slot = AddNewSlot(pad->GetName(), parent);
2293  SetDrawKind(slot, kind_PadSlot);
2294  setdefaults = true;
2295  }
2296  }
2297 
2298  SetSlotPad(slot, pad);
2299 
2300  TGo4Picture* padopt = GetPadOptions(slot);
2301 
2302  padopt->SetPadModified();
2303 
2304  bool issubpads = false;
2305 
2306  bool isdupluicate = false;
2307 
2308  // check if pads with duplicate names appears in list.
2309  // Remove first copies. Can appiar by RMB menu Divide call
2310  do {
2311  TObjArray subpads;
2312  isdupluicate = false;
2313  TIter iter(pad->GetListOfPrimitives());
2314  TObject* obj = 0;
2315  while ((obj = iter()) != 0) {
2316  TPad* subpad = dynamic_cast<TPad*>(obj);
2317  if (subpad == 0)
2318  continue;
2319  issubpads = true;
2320  if (subpads.FindObject(subpad->GetName()) != 0)
2321  isdupluicate = true;
2322  if (!isdupluicate)
2323  subpads.Add(subpad);
2324  }
2325  if (isdupluicate) {
2326  pad->GetListOfPrimitives()->RemoveAll(&subpads);
2327  subpads.Delete();
2328  subpads.Compress();
2329  padopt->SetPadModified();
2330  }
2331 
2332  } while (isdupluicate);
2333 
2334  // remove all subslots, which are correspond to non-existing subpads
2335  for (int n = slot->NumChilds() - 1; n >= 0; n--) {
2336  TGo4Slot* subslot = slot->GetChild(n);
2337  TPad* subpad = GetSlotPad(subslot);
2338  if (subpad != 0) {
2339  if (pad->GetListOfPrimitives()->FindObject(subpad) == 0)
2340  delete subslot;
2341  else
2342  issubpads = true;
2343  }
2344  }
2345 
2346  if (setdefaults)
2347  SetPadDefaults(pad);
2348 
2349  if (!issubpads)
2350  return;
2351 
2352  TIter iter(pad->GetListOfPrimitives());
2353  TObjArray removedItems;
2354  TObject* obj = 0;
2355  while ((obj = iter()) != 0) {
2356  TPad* subpad = dynamic_cast<TPad*>(obj);
2357  if (subpad != 0)
2358  ProcessPadStatusUpdate(subpad, slot, removeitems);
2359  else
2360  removedItems.Add(obj);
2361  }
2362 
2363  pad->GetListOfPrimitives()->RemoveAll(&removedItems);
2364 
2365  if (removeitems)
2366  ClearPadItems(slot, 0);
2367 }
2368 
2369 TGo4Slot* TGo4ViewPanel::AddDrawObject(TPad* pad, int kind, const char* itemname,
2370  TObject* obj, bool owner, const char* drawopt)
2371 {
2372  TGo4Slot* padslot = GetPadSlot(pad);
2373 
2374  if (padslot == 0) {
2375  if (owner) delete obj;
2376  return 0;
2377  }
2378 
2379  //std::cout << "Add object = " << (obj ? obj->ClassName() : "---") << " pad = " << pad->GetName() << " kind = " << kind << std::endl;
2380 
2381  // clear only if link is added
2382  if (kind < 100)
2383  ClearPad(pad, false, true);
2384 
2385  TGo4Slot* tgtslot = 0;
2386 
2387  if (kind == kind_Link) {
2388  TClass* cl = Browser()->ItemClass(itemname);
2389  if ((cl != 0) && cl->InheritsFrom(TGo4Condition::Class()))
2390  UndrawItem(itemname);
2391 
2392 // std::cout << "Item " << itemname << " class = " << (cl ? cl->GetName() : "null") << std::endl;
2393 
2394  TGo4Slot* brslot = Browser()->BrowserSlot(itemname);
2395 
2396  if (brslot != 0) {
2397  tgtslot = AddNewSlot(brslot->GetName(), padslot);
2398  SetLinkedName(tgtslot, itemname);
2399  if (fbCloneFlag)
2400  tgtslot->SetProxy(new TGo4DrawCloneProxy(brslot, this));
2401  else
2402  tgtslot->SetProxy(new TGo4LinkProxy(brslot));
2403  }
2404  } else {
2405 
2406  QString newslotname = itemname;
2407  if ((newslotname.length() == 0)
2408  || (padslot->FindChild(newslotname.toLatin1().constData()) != 0)) {
2409  int cnt = 0;
2410  do {
2411  if ((itemname == 0) || (*itemname == 0))
2412  newslotname = "::SpecialObject_";
2413  else
2414  newslotname = itemname;
2415  newslotname += QString::number(cnt++);
2416  } while (padslot->FindChild(newslotname.toLatin1().constData()) != 0);
2417  }
2418  tgtslot = AddNewSlot(newslotname.toLatin1().constData(), padslot);
2419  tgtslot->SetProxy(new TGo4ObjectProxy(obj, owner));
2420  }
2421 
2422  if (tgtslot == 0) return 0;
2423 
2424  if (kind < 100)
2426 
2427  tgtslot->SetPar("::FirstDraw", "true");
2428  SetDrawKind(tgtslot, kind);
2429  SetSpecialDrawOption(tgtslot, drawopt);
2430 
2431  TGo4Picture* padopt = GetPadOptions(padslot);
2432  if (padopt != 0) {
2433  padopt->SetContentModified(true);
2434  padopt->SetPadModified();
2435  if ((kind < 100) && (drawopt != 0))
2436  padopt->SetDrawOption(drawopt, TGo4Picture::PictureIndex);
2437  }
2438 
2439  return tgtslot;
2440 }
2441 
2442 TGo4Slot* TGo4ViewPanel::GetDrawObjectSlot(TPad* pad, const char* name)
2443 {
2444  TGo4Slot* slot = GetPadSlot(pad);
2445 
2446  return slot == 0 ? 0 : slot->FindChild(name);
2447 }
2448 
2449 TObject* TGo4ViewPanel::GetDrawObject(TPad* pad, const char* name)
2450 {
2451  TGo4Slot* subslot = GetDrawObjectSlot(pad, name);
2452 
2453  return subslot == 0 ? 0 : subslot->GetAssignedObject();
2454 }
2455 
2456 void TGo4ViewPanel::DeleteDrawObject(TPad* pad, const char* name)
2457 {
2458  TGo4Slot* padslot = GetPadSlot(pad);
2459 
2460  TGo4Slot* subslot = padslot == 0 ? 0 : padslot->FindChild(name);
2461 
2462  if (subslot != 0) {
2463  delete subslot;
2464  TGo4Picture* padopt = GetPadOptions(padslot);
2465  if (padopt != 0)
2466  padopt->SetPadModified();
2467  }
2468 }
2469 
2470 void TGo4ViewPanel::DeleteDrawObject(TPad* pad, TObject* obj)
2471 {
2472  TGo4Slot* padslot = GetPadSlot(pad);
2473  if (padslot == 0)
2474  return;
2475  for (int n = 0; n < padslot->NumChilds(); n++) {
2476  TGo4Slot* subslot = padslot->GetChild(n);
2477  if (GetDrawKind(subslot) < 0)
2478  continue;
2479  if (subslot->GetAssignedObject() == obj) {
2480  delete subslot;
2481  break;
2482  }
2483  }
2484 }
2485 
2486 void TGo4ViewPanel::CollectSpecialObjects(TPad* pad, TObjArray* objs,
2487  int selectkind)
2488 {
2489  TGo4Slot* slot = GetPadSlot(pad);
2490  if ((slot == 0) || (objs == 0))
2491  return;
2492 
2493  for (int n = 0; n < slot->NumChilds(); n++) {
2494  TGo4Slot* subslot = slot->GetChild(n);
2495  Int_t kind = GetDrawKind(subslot);
2496  if (kind < 0)
2497  continue;
2498  if ((kind != kind_Link) && ((selectkind < 0) || (kind == selectkind))) {
2499  TObject* obj = subslot->GetAssignedObject();
2500  if (obj != 0)
2501  objs->Add(obj);
2502  }
2503  }
2504 }
2505 
2506 bool TGo4ViewPanel::DeleteDrawObjects(TPad* pad, int kindtodelete)
2507 {
2508  TGo4Slot* slot = GetPadSlot(pad);
2509  TGo4Picture* padopt = GetPadOptions(slot);
2510 
2511  if ((slot == 0) || (padopt == 0))
2512  return false;
2513 
2514  bool res = false;
2515 
2516  for (int n = slot->NumChilds() - 1; n >= 0; n--) {
2517  TGo4Slot* subslot = slot->GetChild(n);
2518  Int_t kind = GetDrawKind(subslot);
2519  if (kind < 0)
2520  continue;
2521  if ((kind != kind_Link)
2522  && ((kindtodelete < 0) || (kind == kindtodelete))) {
2523  res = true;
2524  delete subslot;
2525  }
2526  }
2527  if (res)
2528  padopt->SetPadModified();
2529  return true;
2530 }
2531 
2532 void TGo4ViewPanel::SetPadSuperImpose(TPad* pad, bool on)
2533 {
2534  TGo4Picture* padopt = GetPadOptions(pad);
2535  if (padopt != 0) {
2536  padopt->SetSuperimpose(on);
2537  padopt->SetPadModified();
2538  }
2539 }
2540 
2542 {
2543  fbModifiedSignalFlag = false;
2544  if (GetActivePad() == 0)
2545  return;
2546 
2548  GetPadOptions(GetActivePad()), true))
2550 }
2551 
2552 bool TGo4ViewPanel::ScanDrawOptions(TPad* pad, TGo4Slot* padslot,
2553  TGo4Picture* pic, bool onlyscan)
2554 {
2555  TGo4LockGuard lock;
2556 
2557  if ((pad == 0) || (pic == 0) || (padslot == 0))
2558  return false;
2559 
2560  bool optchanged = false;
2561  TObjLink* link = pad->GetListOfPrimitives()->FirstLink();
2562 
2563  while (link != 0) {
2564  const char* clname = link->GetObject()->ClassName();
2565  if ((strcmp(clname, "TFrame") == 0) || (strcmp(clname, "TLegend") == 0)) {
2566 
2567  // comment out, can never be working
2568  //TPaveText* titl = dynamic_cast<TPaveText*>(link->GetObject());
2569  //if (titl &&(strcmp(titl->GetName(),"title")==0))
2570  // pic->SetTitleAttr(titl);
2571 
2572  link = link->Next();
2573  } else
2574  break;
2575  }
2576 
2577  // take draw options from first drawn object
2578  if (link != 0) {
2579 
2580  TString newopt(link->GetOption());
2581  Int_t drawoptindx =
2582  GetSuperimposeSlot(padslot) == 0 ? 0 : TGo4Picture::PictureIndex;
2583  TString oldopt(pic->GetDrawOption(drawoptindx));
2584 
2585  while (newopt.BeginsWith(NoStackDrawOption, TString::kIgnoreCase))
2586  newopt.Remove(0, strlen(NoStackDrawOption));
2587 
2588  if (!oldopt.Contains("asimage"))
2589  if ((newopt.Length() != oldopt.Length())
2590  || (newopt.CompareTo(oldopt, TString::kIgnoreCase) != 0)) {
2591  optchanged = true;
2592  pic->SetDrawOption(newopt.Data(), drawoptindx);
2593  }
2594 
2595  TH1* h1 = dynamic_cast<TH1*>(link->GetObject());
2596  // access axis properties of graphs
2597  if(h1==0) {
2598  TGraph* gr = dynamic_cast<TGraph*> (link->GetObject());
2599  if(gr) h1 = Get_fHistogram(gr);
2600  }
2601 
2602  if (h1 != 0) {
2603  TPaveStats* stats =
2604  dynamic_cast<TPaveStats*>(h1->GetListOfFunctions()->FindObject("stats"));
2605  if (h1->TestBit(TH1::kNoStats)) {
2606  pic->SetHisStats(kFALSE);
2607  } else {
2608  pic->SetHisStats(kTRUE);
2609  pic->SetStatsAttr(stats);
2610  }
2611  // test: set here time display
2612  TAxis* xax = h1->GetXaxis();
2613  pic->SetXAxisAttTime(xax->GetTimeDisplay(), xax->GetTimeFormat() ,TGo4Picture::PictureIndex);
2614  //std::cout <<"Set time attributes to pad options: display:"<<xax->GetTimeDisplay()<<", format:"<< xax->GetTimeFormat()<< std::endl;
2615  }
2616 
2617  }
2618 
2619  if (pad->GetLogx() != pic->GetLogScale(0)) {
2620  pic->SetLogScale(0, pad->GetLogx());
2621  optchanged = true;
2622  }
2623 
2624  if (pad->GetLogy() != pic->GetLogScale(1)) {
2625  pic->SetLogScale(1, pad->GetLogy());
2626  optchanged = true;
2627  }
2628 
2629  if (pad->GetLogz() != pic->GetLogScale(2)) {
2630  pic->SetLogScale(2, pad->GetLogz());
2631  optchanged = true;
2632  }
2633 
2634  if (pad == GetCanvas())
2635  fbCanvasCrosshair = pad->HasCrosshair();
2636 
2637  TPaveText* titl =
2638  dynamic_cast<TPaveText*>(pad->GetListOfPrimitives()->FindObject("title"));
2639  if(titl) {
2640  pic->SetTitleAttr(titl);
2641  optchanged = true;
2642  }
2643 
2644  TObjArray objs, objslots;
2645 
2646  CollectMainDrawObjects(padslot, &objs, &objslots, 0);
2647  ScanObjectsDrawOptions(onlyscan, padslot, &objs, &objslots);
2648 
2649  return optchanged;
2650 }
2651 
2653  TObjArray* objs, TObjArray* objslots)
2654 {
2655  TGo4Picture* pic = GetPadOptions(padslot);
2656 
2657  TPad* pad = GetSlotPad(padslot);
2658  if ((pad != 0) && (pic != 0)) {
2659  if (padslot->GetPar("::DrawOptAssigned") != 0) {
2661  } else if (!onlyscan) {
2663  padslot->SetPar("::DrawOptAssigned", "1");
2664  }
2665  }
2666 
2667  if ((padslot == 0) || (pic == 0) || (objs == 0) || (objslots == 0))
2668  return;
2669 
2670  for (int n = 0; n <= objs->GetLast(); n++) {
2671  TObject* obj = objs->At(n);
2672  TGo4Slot* subslot = (TGo4Slot*) objslots->At(n);
2673 
2674  if ((obj == 0) || (subslot == 0))
2675  continue;
2676 
2677  if (subslot->GetPar("::DrawOptAssigned") != 0) {
2678  pic->SetDrawAttributes(obj, n);
2679  } else if (!onlyscan) {
2680  pic->GetDrawAttributes(obj, n);
2681  subslot->SetPar("::DrawOptAssigned", "1");
2682  }
2683  }
2684 }
2685 
2687  TObjArray* objslots, int modifier)
2688 {
2689  // modifier == 0 - no objects can be deleted
2690  // == 1 - objects of same types should be in the list
2691  // == 2 - only last object survive
2692  if ((slot == 0) || (objs == 0))
2693  return;
2694 
2695  TObjArray mainslots;
2696 
2697  int lastobjtype = 0;
2698 
2699  for (int n = 0; n < slot->NumChilds(); n++) {
2700  TGo4Slot* subslot = slot->GetChild(n);
2701  Int_t kind = GetDrawKind(subslot);
2702 
2703  if ((kind <= 0) || (kind >= kind_Additional))
2704  continue;
2705 
2706  TObject* obj = subslot->GetAssignedObject();
2707 
2708  if (obj == 0)
2709  continue;
2710 
2711  int objtype = 0;
2712 
2713  if (obj->InheritsFrom(TH1::Class()))
2714  objtype = 1;
2715  else if (obj->InheritsFrom(TGraph::Class()))
2716  objtype = 2;
2717  else if (obj->InheritsFrom(TMultiGraph::Class()))
2718  objtype = 3;
2719  else if (obj->InheritsFrom(THStack::Class()))
2720  objtype = 4;
2721 
2722  // can happen condition here, which is add as link and not identified as condition yet
2723  // should both be recognized as "main" draw object
2724  if (objtype > 0) {
2725  lastobjtype = objtype;
2726  mainslots.Add(subslot);
2727  }
2728  }
2729 
2730  Bool_t deletesomething = kFALSE;
2731 
2732  for (int n = 0; n <= mainslots.GetLast(); n++) {
2733  TGo4Slot* subslot = (TGo4Slot*) mainslots.At(n);
2734  TObject* obj = subslot->GetAssignedObject();
2735  Int_t objtype = 0;
2736  if (obj->InheritsFrom(TH1::Class()))
2737  objtype = 1;
2738  else if (obj->InheritsFrom(TGraph::Class()))
2739  objtype = 2;
2740  else if (obj->InheritsFrom(TMultiGraph::Class()))
2741  objtype = 3;
2742  else if (obj->InheritsFrom(THStack::Class()))
2743  objtype = 4;
2744 
2745  // check if all main object correspond to type of last object
2746  // if no, delete
2747 
2748  if ((n < mainslots.GetLast())
2749  && ((modifier == 2) || ((modifier == 1) && (lastobjtype != objtype)))) {
2750  delete subslot;
2751  deletesomething = kTRUE;
2752  } else {
2753  objs->Add(obj);
2754  if (objslots != 0)
2755  objslots->Add(subslot);
2756  TGo4DrawCloneProxy* pr =
2757  dynamic_cast<TGo4DrawCloneProxy*>(subslot->GetProxy());
2758  if(pr!=0) {
2759  pr->UpdateTitle();
2760  pr->PerformRebin();
2761  }
2762  }
2763  }
2764 
2765  if (deletesomething)
2766  CleanupGedEditor();
2767 
2768  for (int n = 0; n < slot->NumChilds(); n++) {
2769  TGo4Slot* subslot = slot->GetChild(n);
2770 
2771  Int_t kind = GetDrawKind(subslot);
2772  if ((kind >= kind_Additional) && (kind < kind_Specials)) {
2773  TObject* obj = subslot->GetAssignedObject();
2774  if (obj != 0) {
2775  objs->Add(obj);
2776  if (objslots != 0)
2777  objslots->Add(subslot);
2778  }
2779  }
2780  }
2781 }
2782 
2784  if (indx<0) indx = 0;
2785 
2786  switch (indx % 10) {
2787  case 0: return kBlack;
2788  case 1: return kRed;
2789  case 2: return kGreen;
2790  case 3: return kBlue;
2791  case 4: return kCyan;
2792  case 5: return kOrange;
2793  case 6: return kSpring;
2794  case 7: return kViolet;
2795  case 8: return kPink;
2796  case 9: return kAzure;
2797  }
2798 
2799  return kBlack;
2800 }
2801 
2802 
2804  TGo4Slot* sislot, TGo4Slot* legslot, TObjArray* objs,
2805  TObjArray * objslots, bool showitems)
2806 {
2807  if ((sislot == 0) || (objs == 0) || (padopt == 0)) return 0;
2808  TObject* oldobj = sislot->GetAssignedObject();
2809 
2810  Bool_t ishstack = kFALSE;
2811  Bool_t isgstack = kFALSE;
2812  Bool_t iserror = kFALSE;
2813  Bool_t resetcolors = kFALSE;
2814 
2815  for (int n = 0; n <= objs->GetLast(); n++) {
2816  TObject* obj = objs->At(n);
2817  if (obj->InheritsFrom(TH1::Class()))
2818  ishstack = kTRUE;
2819  else if (obj->InheritsFrom(TGraph::Class()))
2820  isgstack = kTRUE;
2821  else
2822  iserror = kTRUE;
2823  }
2824 
2825  // if error, no superimpose is allowed
2826  if (iserror || (ishstack && isgstack)) {
2827  TGo4Log::Error("Superimpose of multiple objects with different types");
2828  std::cout<< "Superimpose of multiple objects with different types"<< std::endl;
2829  return 0;
2830  }
2831 
2832  if (ishstack) {
2833  THStack* hs = dynamic_cast<THStack*>(oldobj);
2834 
2835  if (hs == 0) {
2836  hs = new THStack(objs->First()->GetName(), objs->First()->GetTitle());
2837  sislot->SetProxy(new TGo4DrawObjProxy(hs, kTRUE, kTRUE));
2838  resetcolors = kTRUE;
2839  } else {
2840  if (hs->GetHists())
2841  hs->GetHists()->Clear();
2842  }
2843 
2844  for (int n = 0; n <= objs->GetLast(); n++) {
2845  TH1* histo = (TH1*) objs->At(n);
2846  TGo4Slot* objslot = (TGo4Slot*) objslots->At(n);
2847 
2848  Int_t kind = GetDrawKind(objslot);
2849  Int_t objindx = padslot->GetIndexOf(objslot); // slot index for object starts from 2
2850 
2851  if (resetcolors || (kind == kind_FitModels) || (objslot->GetPar("::FirstDraw") != 0)) {
2852  histo->SetLineColor(GetAutoColor(n));
2853  if ((go4sett->getDrawLineWidth() > 1) && (histo->GetLineWidth()==1))
2854  histo->SetLineWidth(go4sett->getDrawLineWidth());
2855  }
2856 
2857  histo->GetXaxis()->UnZoom();
2858 
2859  const char* drawopt = padopt->GetDrawOption(n);
2860  if (drawopt == 0)
2861  drawopt = GetSpecialDrawOption(objslot);
2862 
2863  objslot->RemovePar("::FirstDraw");
2864 
2865  hs->Add(histo, drawopt);
2866  }
2867  oldobj = hs;
2868  } else if (isgstack) {
2869  TMultiGraph* mgr = dynamic_cast<TMultiGraph*>(oldobj);
2870  if (mgr == 0) {
2871  mgr = new TMultiGraph(objs->First()->GetName(),
2872  objs->First()->GetTitle());
2873  sislot->SetProxy(new TGo4DrawObjProxy(mgr, kTRUE, kTRUE));
2874  resetcolors = kTRUE;
2875  } else if (mgr->GetListOfGraphs()) {
2876  mgr->GetListOfGraphs()->Clear();
2877  }
2878 
2879  for (int n = 0; n <= objs->GetLast(); n++) {
2880  TGraph* gr = (TGraph*) objs->At(n);
2881  TGo4Slot* objslot = (TGo4Slot*) objslots->At(n);
2882 
2883  Int_t kind = GetDrawKind(objslot);
2884 
2885  TString drawopt = padopt->GetDrawOption(n);
2886  if (drawopt.Length() == 0)
2887  drawopt = GetSpecialDrawOption(objslot);
2888  if (drawopt.Length() == 0)
2889  drawopt = go4sett->getTGraphDrawOpt().toLatin1().constData();
2890 
2891  drawopt.ToLower();
2892 
2893  // suppress multiple drawing of axis for subgraphs
2894  if (n > 0) drawopt.ReplaceAll("a", "");
2895 
2896  Bool_t first_draw = objslot->GetPar("::FirstDraw") != 0;
2897 
2898  Int_t objindx = padslot->GetIndexOf(objslot); // slot index for object starts from 2
2899 
2900  if (resetcolors || (kind == kind_FitModels) || first_draw) {
2901  // use only basic 9 colors
2902  Int_t nextcol = GetAutoColor(((objindx + 7) % 9));
2903  gr->SetLineColor(nextcol);
2904  gr->SetMarkerColor(nextcol);
2905  if ((go4sett->getDrawLineWidth() > 1) && (gr->GetLineWidth()==1))
2906  gr->SetLineWidth(go4sett->getDrawLineWidth());
2907  }
2908 
2909  if (first_draw && (n==0)) {
2910  TAxis *ax = gr->GetXaxis();
2911  if ((ax!=0) && ax->GetTimeDisplay()) {
2912  padopt->SetHisStats(kFALSE);
2913  padopt->SetXAxisTimeDisplay(kTRUE);
2914  padopt->SetXAxisTimeFormat(ax->GetTimeFormat());
2915  }
2916  }
2917 
2918  objslot->RemovePar("::FirstDraw");
2919 
2920  mgr->Add(gr, drawopt.Data());
2921  }
2922  oldobj = mgr;
2923  }
2924 
2925  if ((ishstack || isgstack) && (legslot != 0)) {
2926  TLegend* legend = dynamic_cast<TLegend*>(legslot->GetAssignedObject());
2927 
2928  if (legend == 0) {
2929  double miny = 0.94 - 0.03 * objs->GetLast();
2930  if (miny < 0.6) miny = 0.6; else if (miny>0.92) miny = 0.92;
2931  legend = new TLegend(0.6, miny, 0.95, 0.99);
2932  legend->SetBorderSize(2);
2933  legend->SetName("fitlegend");
2934  legslot->SetProxy(new TGo4ObjectProxy(legend, kTRUE));
2935  } else {
2936  legend->Clear();
2937  }
2938 
2939  for(int n=0;n<=objs->GetLast();n++) {
2940  TObject* stob = objs->At(n);
2941 
2942  const char* objname = stob->GetName();
2943 
2944  if (showitems && (objslots!=0)) {
2945  const char* itemname = GetLinkedName((TGo4Slot*) objslots->At(n));
2946  if (itemname!=0) objname = itemname;
2947  }
2948 
2949  TString ldrawopt = "l";
2950 
2951  if (!ishstack) {
2952  ldrawopt = "";
2953  TString drawopt = padopt->GetDrawOption(n);
2954  drawopt.ToLower();
2955  if (drawopt.Contains("l")) ldrawopt+="l";
2956  if (drawopt.Contains("p")) ldrawopt+="p";
2957  }
2958 
2959  if (ldrawopt.Length()==0) ldrawopt = "l";
2960 
2961  legend->AddEntry(stob, objname, ldrawopt.Data());
2962  }
2963  }
2964 
2965  return oldobj;
2966 }
2967 
2968 void TGo4ViewPanel::Divide(int numX, int numY)
2969 {
2970  TPad* pad = GetActivePad();
2971 
2972  TGo4Slot* padslot = GetPadSlot(pad);
2973  if ((pad == 0) || (padslot == 0)) return;
2974 
2975  ClearPad(pad, true, true);
2976  RedrawPanel(pad, true);
2977 
2978  if ((numX > 1) || (numY > 1)) {
2979  pad->Divide(numX, numY);
2980 
2981  UpdatePadStatus(pad, true);
2982 
2983  RedrawPanel(pad, true);
2984  }
2985 
2986  // note: number of pads will be changed in list of previewpanelstatus by InitPad
2987 // RefreshButtons();
2988 }
2989 
2990 void TGo4ViewPanel::SetSlotPad(TGo4Slot* padslot, TPad* pad)
2991 {
2992  TGo4Slot* tgtslot = padslot->FindChild("::ThisPad");
2993  if (tgtslot == 0)
2994  tgtslot = new TGo4Slot(padslot, "::ThisPad", "Special object");
2995  tgtslot->SetProxy(new TGo4ObjectProxy(pad, kFALSE));
2996  SetDrawKind(tgtslot, kind_ThisPad);
2997  ConnectPad(pad);
2998 
2999  AllocatePadOptions(pad);
3000 }
3001 
3003 {
3004  if (pad == GetCanvas())
3005  return GetPanelSlot();
3006 
3007  TGo4Iter iter(GetPanelSlot(), kTRUE);
3008  while (iter.next()) {
3009  TGo4Slot* subslot = iter.getslot();
3010  if (GetDrawKind(subslot) == kind_PadSlot)
3011  if (GetSlotPad(subslot) == pad)
3012  return subslot;
3013  }
3014  return 0;
3015 }
3016 
3018 {
3019  if (slot == 0)
3020  return 0;
3021 
3022  TGo4Slot* tgtslot = slot->FindChild("::ThisPad");
3023 
3024  return tgtslot == 0 ? 0 : (TPad*) tgtslot->GetAssignedObject();
3025 }
3026 
3028 {
3029  if (padslot == 0)
3030  return false;
3031  for (int n = 0; n < padslot->NumChilds(); n++)
3032  if (GetSlotPad(padslot->GetChild(n)) != 0)
3033  return true;
3034  return false;
3035 }
3036 
3038 {
3039  return IsPadHasSubPads(GetPadSlot(pad));
3040 }
3041 
3043 {
3044  TGo4Picture* padopt = GetPadOptions(pad);
3045  if (padopt != 0)
3046  padopt->SetPadModified();
3047 }
3048 
3050 {
3051  return GetPadSlot(pad) != 0;
3052 }
3053 
3055 {
3056  if (toppad == 0)
3057  toppad = GetCanvas();
3058  int number = 1;
3059  TGo4Iter iter(GetPadSlot(toppad), kTRUE);
3060  while (iter.next()) {
3061  TPad* pad = GetSlotPad(iter.getslot());
3062  if (pad != 0)
3063  number++;
3064  }
3065  return number;
3066 }
3067 
3068 TPad* TGo4ViewPanel::GetSubPad(TPad* toppad, int num, bool onlytoplevel)
3069 {
3070  if (toppad == 0)
3071  toppad = GetCanvas();
3072  TGo4Slot* slot = GetPadSlot(toppad);
3073  if (slot == 0)
3074  return 0;
3075 
3076  int cnt = -1;
3077  if (!onlytoplevel || !IsPadHasSubPads(slot))
3078  cnt++;
3079 
3080  if (num == cnt)
3081  return toppad;
3082 
3083  TGo4Iter iter(slot, kTRUE);
3084  while (iter.next()) {
3085  TGo4Slot* subslot = iter.getslot();
3086  TPad* pad = GetSlotPad(subslot);
3087  if (pad == 0)
3088  continue;
3089  if (!onlytoplevel || !IsPadHasSubPads(subslot))
3090  cnt++;
3091  if (num == cnt)
3092  return pad;
3093  }
3094  return 0;
3095 }
3096 
3097 void TGo4ViewPanel::ProducePadsList(TObjArray* arr, TPad* toppad)
3098 {
3099  if (arr == 0)
3100  return;
3101  if (toppad == 0)
3102  toppad = GetCanvas();
3103 
3104  arr->Add(toppad);
3105 
3106  TGo4Iter iter(GetPadSlot(toppad), kTRUE);
3107  while (iter.next()) {
3108  TPad* pad = GetSlotPad(iter.getslot());
3109  if (pad != 0)
3110  arr->Add(pad);
3111  }
3112 }
3113 
3114 const char* TGo4ViewPanel::GetDrawObjectLinkName(TPad * pad, TObject* obj)
3115 {
3116  TGo4Slot* slot = GetPadSlot(pad);
3117  if ((pad == 0) || (slot == 0) || (obj == 0))
3118  return 0;
3119 
3120  for (int n = 0; n < slot->NumChilds(); n++) {
3121  TGo4Slot* subslot = slot->GetChild(n);
3122  if (subslot->GetAssignedObject() == obj)
3123  return GetLinkedName(subslot);
3124  }
3125  return 0;
3126 }
3127 
3129 {
3130  return padslot == 0 ? 0 : padslot->FindChild("::Superimpose");
3131 }
3132 
3134 {
3135  TGo4Slot* slot = GetPadSlot(pad);
3136  if ((pad == 0) || (slot == 0))
3137  return 0;
3138 
3139  for (int n = 0; n < slot->NumChilds(); n++) {
3140  TGo4Slot* subslot = slot->GetChild(n);
3141  Int_t kind = GetDrawKind(subslot);
3142  if ((kind <= 0) || (kind >= kind_Additional))
3143  continue;
3144  TObject* obj = subslot->GetAssignedObject();
3145  if (obj != 0)
3146  return subslot;
3147  }
3148  return 0;
3149 }
3150 
3152 {
3153  TGo4Slot* slot = GetPadMainObjectSlot(pad);
3154  return slot == 0 ? 0 : slot->GetAssignedObject();
3155 }
3156 
3158 {
3159 #ifdef __GO4X11__
3160  if (fxQCanvas)
3161  return fxQCanvas->getCanvas();
3162 #endif
3163 
3164 #ifdef __GO4WEB__
3165  if (fxWCanvas)
3166  return fxWCanvas->getCanvas();
3167 #endif
3168 
3169  return 0;
3170 }
3171 
3173 {
3174  // std::cout <<"TGo4ViewPanel::CanvasUpdate with modify: "<< modify << std::endl;
3175 
3176  if (fxQCanvas) {
3177 #ifdef __GO4X11__
3178  if (modify) fxQCanvas->Modified();
3179  fxQCanvas->Update();
3180 #endif
3181  } else if (fxWCanvas) {
3182 #ifdef __GO4WEB__
3183  if (modify) fxWCanvas->Modified();
3184  fxWCanvas->Update();
3185 #endif
3186  }
3187 }
3188 
3190 {
3191  return fxActivePad;
3192 }
3193 
3195 {
3196  TGo4Slot* padslot = GetPadSlot(pad);
3197  if (padslot == 0)
3198  return;
3199 
3200  TGo4Slot* tgtslot = padslot->FindChild("::PadOptions");
3201  if (tgtslot == 0) {
3202  tgtslot = new TGo4Slot(padslot, "::PadOptions", "Pad options slot");
3203  TGo4Picture* opt = new TGo4Picture;
3205  tgtslot->SetProxy(new TGo4ObjectProxy(opt, kTRUE));
3206  SetDrawKind(tgtslot, kind_PadOptions);
3207  }
3208 }
3209 
3211 {
3212  return GetPadOptions(GetPadSlot(pad));
3213 }
3214 
3216 {
3217  if (padslot == 0)
3218  return 0;
3219  TGo4Slot* tgtslot = padslot->FindChild("::PadOptions");
3220  return (tgtslot == 0) ? 0 : (TGo4Picture*) tgtslot->GetAssignedObject();
3221 }
3222 
3224 {
3225  TGo4Slot* padslot = GetPadSlot(pad);
3226 
3227  if ((pad == 0) || (padslot == 0))
3228  return 0;
3229 
3230  TObject* obj = 0;
3231 
3232  TGo4Slot* sislot = GetSuperimposeSlot(padslot);
3233  if (sislot != 0)
3234  obj = sislot->GetAssignedObject();
3235 
3236  if (obj == 0)
3237  obj = GetPadMainObject(pad);
3238  if (obj == 0)
3239  return 0;
3240 
3241  if (obj->InheritsFrom(TH1::Class()))
3242  return (TH1*) obj;
3243 
3244  TPadGuard lock(fxWCanvas ? 0 : gPad); // replace gPad to avoid redrawing of canvas
3245 
3246  if (obj->InheritsFrom(TGraph::Class()))
3247  // return graph histogram - if need create them in not web case
3248  return Get_fHistogram(obj, true);
3249 
3250  if (obj->InheritsFrom(THStack::Class()))
3251  return Get_fHistogram(obj, true);
3252 
3253  if (obj->InheritsFrom(TMultiGraph::Class())) {
3254  TMultiGraph* mg = dynamic_cast<TMultiGraph*>(obj);
3255  if (mg) {
3256  // do not force here, otherwise never come to the TGraph
3257  TH1 *h = Get_fHistogram(mg);
3258  if (h) return h;
3259 
3260  TGraph* gr = 0;
3261  TIter iter(mg->GetListOfGraphs());
3262  while ((gr = (TGraph*) iter()) != 0) {
3263  h = Get_fHistogram(gr, true);
3264  if (h) return h;
3265  }
3266  }
3267  }
3268 
3269  return 0;
3270 }
3271 
3273 {
3274  if (on)
3276  else
3278 }
3279 
3281 {
3282  return fiSkipRedrawCounter > 0;
3283 }
3284 
3286 {
3287  TGo4Slot* slot = GetPadSlot(GetActivePad());
3288  if (slot == 0)
3289  return;
3290 
3291  fSelectMenu->clear();
3292 
3293  TGo4Slot* sislot = GetSuperimposeSlot(slot);
3294 
3295  TObjArray objs, objslots;
3296  CollectMainDrawObjects(slot, &objs, &objslots, 0);
3297 
3298  Int_t nselectitem = 0;
3299 
3300  int selected = GetSelectedObjectIndex(slot);
3301 
3302  if ((selected > objs.GetLast())
3303  || ((selected == TGo4Picture::PictureIndex) && (sislot == 0))) {
3304  SetSelectedObjectIndex(slot, 0);
3305  selected = 0;
3306  }
3307 
3308  if (sislot != 0) {
3309  AddIdAction(fSelectMenu, fSelectMap, "Master object", MasterSelectId);
3310  fSelectMenu->addSeparator();
3311  nselectitem++;
3312  }
3313 
3314  QString capt = GetPanelName();
3315 
3316  QString fulllist = "";
3317  QString selslotname = "";
3318 
3319  for (int n = 0; n <= objslots.GetLast(); n++) {
3320  TGo4Slot* subslot = (TGo4Slot*) objslots.At(n);
3321  AddIdAction(fSelectMenu, fSelectMap, objs.At(n)->GetName(),
3322  FirstSelectId + n);
3323  nselectitem++;
3324 
3325  QString subslotname = subslot->GetName();
3326  if (n == selected) {
3327  subslotname = QString("[") + subslotname + QString("]");
3328  selslotname = subslotname;
3329  }
3330  if (n > 0) fulllist += ", ";
3331  fulllist += subslotname;
3332  }
3333 
3334  if ((selected != TGo4Picture::PictureIndex) && (objslots.GetLast() > 0)
3335  && (selected < objslots.GetLast())) {
3336  fSelectMenu->addSeparator();
3338  QString("Show ") + selslotname + QString(" on top"),
3339  BringToFrontId);
3340  }
3341 
3342  if ((selected == TGo4Picture::PictureIndex) && (fulllist.length() > 0))
3343  fulllist = QString("[") + fulllist + QString("]");
3344 
3345  fSelectMenu->setEnabled(nselectitem > 0);
3346 
3347  if (nselectitem > 0) {
3348  if (selected == TGo4Picture::PictureIndex)
3349  SetIdAction(fSelectMap, MasterSelectId, true, true);
3350  else
3351  SetIdAction(fSelectMap, FirstSelectId + selected, true, true);
3352  }
3353 
3354  if (fulllist.length() > 0) {
3355  capt += ": ";
3356  capt += fulllist;
3357  }
3358 
3359  if (capt.length() > 60) {
3360  capt.truncate(58);
3361  capt += "...";
3362  }
3363 
3364  if (!fbFreezeTitle)
3365  setWindowTitle(capt);
3366 }
3367 
3369 {
3370  if (slot == 0)
3371  return;
3372  if (kind <= 0)
3373  slot->RemovePar("::DrawKind");
3374  else
3375  slot->SetIntPar("::DrawKind", kind);
3376 }
3377 
3378 void TGo4ViewPanel::SetSpecialDrawOption(TGo4Slot* slot, const char* drawopt)
3379 {
3380  if (slot == 0)
3381  return;
3382  if (drawopt != 0)
3383  slot->SetPar("::DrawOpt", drawopt);
3384  else
3385  slot->RemovePar("::DrawOpt");
3386 }
3387 
3389 {
3390  if (slot == 0)
3391  return -1;
3392  Int_t kind;
3393  if (!slot->GetIntPar("::DrawKind", kind))
3394  return -1;
3395  return kind;
3396 }
3397 
3399 {
3400  return (slot == 0) ? 0 : slot->GetPar("::DrawOpt");
3401 }
3402 
3404 {
3405  if (slot != 0)
3406  slot->SetIntPar("::SelectedObject", indx);
3407 }
3408 
3410 {
3411  if (slot == 0)
3412  return 0;
3413  Int_t indx = 0;
3414  if (!slot->GetIntPar("::SelectedObject", indx))
3415  indx = 0;
3416  return indx;
3417 }
3418 
3419 TObject* TGo4ViewPanel::GetSelectedObject(TPad * pad, const char** drawopt)
3420 {
3421  TGo4Slot* slot = GetPadSlot(pad);
3422  TGo4Picture* padopt = GetPadOptions(slot);
3423  if ((slot == 0) || (padopt == 0))
3424  return 0;
3425 
3426  int indx = GetSelectedObjectIndex(slot);
3427 
3428  TGo4Slot* sislot = GetSuperimposeSlot(slot);
3429  if ((sislot != 0) && (indx == TGo4Picture::PictureIndex)) {
3430  if (drawopt != 0)
3431  *drawopt = padopt->GetDrawOption(TGo4Picture::PictureIndex);
3432  return sislot->GetAssignedObject();
3433  }
3434 
3435  TObjArray objs, objslots;
3436  CollectMainDrawObjects(slot, &objs, &objslots, 0);
3437 
3438  if (objs.GetLast() < 0)
3439  return 0;
3440 
3441  if ((indx > objs.GetLast()) || (indx < 0))
3442  indx = 0;
3443 
3444  if (drawopt != 0) {
3445  const char* resopt = padopt->GetDrawOption(indx);
3446  if (resopt == 0)
3447  resopt = GetSpecialDrawOption((TGo4Slot*) objslots.At(indx));
3448 
3449  *drawopt = resopt;
3450  }
3451 
3452  return objs.At(indx);
3453 }
3454 
3456 {
3457  TGo4Slot* slot = GetPadSlot(pad);
3458  TGo4Picture* padopt = GetPadOptions(slot);
3459  if ((slot == 0) || (padopt == 0))
3460  return false;
3461 
3462  int indx = GetSelectedObjectIndex(slot);
3463 
3464  TObjArray objs, objslots;
3465  CollectMainDrawObjects(slot, &objs, &objslots, 0);
3466 
3467  // no sense to shift object which is already at the end
3468  if ((objs.GetLast() <= 0) || (indx == objs.GetLast()))
3469  return false;
3470 
3471  TGo4Slot* selslot = (TGo4Slot*) objslots.At(indx);
3472  TGo4Slot* lastslot = (TGo4Slot*) objslots.Last();
3473 
3474  if (!slot->ShiftSlotAfter(selslot, lastslot))
3475  return false;
3476 
3477  SetSelectedObjectIndex(slot, objs.GetLast());
3478 
3479  return true;
3480 }
3481 
3483 {
3484  if ((pad == 0) || (padslot == 0)) return;
3485 
3486  TObjArray objs, objslots;
3487  CollectMainDrawObjects(padslot, &objs, &objslots, 0);
3488 
3489  int indx = GetSelectedObjectIndex(padslot);
3490  if (indx < 0) indx = 0;
3491 
3492  TH1* selhisto = dynamic_cast<TH1*>((indx <= objs.GetLast()) ? objs.At(indx) : 0);
3493  if (selhisto == 0)
3494  selhisto = GetPadHistogram(pad);
3495 
3496  for (int n = 0; n < padslot->NumChilds(); n++) {
3497  TGo4Slot* subslot = padslot->GetChild(n);
3498  Int_t kind = GetDrawKind(subslot);
3499  TObject* obj = subslot->GetAssignedObject();
3500  if (obj == 0) continue;
3501 
3502  TGo4Marker* mark = 0;
3503  TGo4Condition* cond = 0;
3504 
3505  // reset condition and marker histogram
3506  if ((kind >= kind_Specials) && (kind < kind_Other)) {
3507  if (obj->InheritsFrom(TGo4Condition::Class()))
3508  cond = (TGo4Condition*) obj;
3509  else if (obj->InheritsFrom(TGo4Marker::Class()))
3510  mark = (TGo4Marker*) obj;
3511  } else if (kind == kind_Condition)
3512  cond = dynamic_cast<TGo4Condition*>(obj);
3513 
3514  TH1* oldhisto = 0;
3515 
3516  if (cond != 0)
3517  oldhisto = cond->GetWorkHistogram();
3518  else if (mark != 0)
3519  oldhisto = mark->GetHistogram();
3520 
3521  if (oldhisto != 0)
3522  if (objs.FindObject(oldhisto) == 0)
3523  oldhisto = 0;
3524 
3525  if (oldhisto == 0) {
3526  if (cond != 0) {
3527  cond->SetWorkHistogram(selhisto);
3528  } else if (mark != 0) {
3529  mark->SetHistogram(selhisto);
3530  }
3531  }
3532  }
3533 }
3534 
3535 void TGo4ViewPanel::SetFreezedTitle(const QString& title)
3536 {
3537  QString mycaption = GetPanelName();
3538  mycaption += ": ";
3539  mycaption += title;
3540  setWindowTitle(mycaption);
3541  fbFreezeTitle = true;
3542  fFreezedTitle = title;
3543 }
3544 
3546 {
3547  if ((pad == 0) || (padslot == 0))
3548  return;
3549 
3550  TGo4Picture* pic = 0;
3551  TGo4Slot* picslot = 0;
3552  TCanvas* canv = 0;
3553  TGo4Slot* canvslot = 0;
3554 
3555  int numcond = 0;
3556 
3557  for (int n = 0; n < padslot->NumChilds(); n++) {
3558  TGo4Slot* subslot = padslot->GetChild(n);
3559  Int_t kind = GetDrawKind(subslot);
3560  if (kind == kind_Condition)
3561  numcond++;
3562 
3563  TObject* obj = subslot->GetAssignedObject();
3564  if (obj == 0)
3565  continue;
3566 
3567  if ((kind < 0) || (kind >= 100))
3568  continue;
3569 
3570  // change drawkind of condition which is drawn as normal object
3571  if (obj->InheritsFrom(TGo4Condition::Class())) {
3572  numcond++;
3573  TGo4Condition* cond = static_cast<TGo4Condition*>(obj);
3574  cond->SetLineColor(GetAutoColor(numcond));
3575  cond->SetFillColor(GetAutoColor(numcond));
3576  cond->SetFillStyle(3444);
3577  SetDrawKind(subslot, kind_Condition);
3578  continue;
3579  }
3580 
3581  if (obj->InheritsFrom(TLatex::Class())) {
3582  SetDrawKind(subslot, kind_Latex);
3583  continue;
3584  }
3585  // JAM test
3586  if (obj->InheritsFrom(TF1::Class())) {
3587  SetDrawKind(subslot, kind_Func);
3588  continue;
3589  }
3590  if (pic == 0) {
3591  pic = dynamic_cast<TGo4Picture*>(obj);
3592  if (pic != 0)
3593  picslot = subslot;
3594  }
3595 
3596  if (canv == 0) {
3597  canv = dynamic_cast<TCanvas*>(obj);
3598  if (canv != 0)
3599  canvslot = subslot;
3600  }
3601  }
3602 
3603  if (pic != 0) {
3604 
3605  ClearPadItems(padslot, picslot);
3606 
3607  // remove all subpads if any but do not remove items while picture is there
3608  ClearPad(pad, false, true);
3609 
3610  ProcessPictureRedraw(GetLinkedName(picslot), pad, pic);
3611 
3612  if (pad == GetCanvas())
3613  SetFreezedTitle(pic->GetTitle());
3614 
3615  // remove picture from the pad
3616  delete picslot;
3617 
3618  return;
3619  }
3620 
3621  if (canv != 0) {
3622  // remove all other
3623  ClearPadItems(padslot, canvslot);
3624 
3625  // remove all subpads if any but do not remove items while picture is there
3626  ClearPad(pad, false, true);
3627 
3628  TVirtualPad* padsav = gPad;
3629 
3630  ProcessCanvasAdopt(pad, canv, GetLinkedName(canvslot));
3631 
3632  if (padsav != 0)
3633  padsav->cd();
3634 
3635  delete canvslot;
3636  }
3637 }
3638 
3639 void TGo4ViewPanel::ProcessPictureRedraw(const char* picitemname, TPad* pad, TGo4Picture* pic)
3640 {
3641  if ((pad == 0) || (pic == 0)) return;
3642 
3643  if (pic->IsDivided()) {
3644  pad->Divide(pic->GetDivX(), pic->GetDivY());
3645 
3646  // this create appropriate entries in the OM
3647  UpdatePadStatus(pad, false);
3648 
3649  for (Int_t posy = 0; posy < pic->GetDivY(); posy++)
3650  for (Int_t posx = 0; posx < pic->GetDivX(); posx++) {
3651  TGo4Picture* sub = pic->FindPic(posy, posx);
3652  if (sub != 0)
3653  ProcessPictureRedraw(picitemname,
3654  (TPad*) pad->GetPad(posy * pic->GetDivX() + posx + 1),
3655  sub);
3656  }
3657 
3658  return;
3659  }
3660 
3661  TGo4Picture* padopt = GetPadOptions(pad);
3662  if (padopt == 0) {
3663  TGo4Log::Error("Internal problem in view panel redraw");
3664  return;
3665  }
3666 
3667  pic->GetFrameAttr(pad); // do it only once, pad preserves automatically
3668 
3670 
3671  SetAutoZoomFlag(pic->IsAutoZoom());
3672 
3673  padopt->CopyOptionsFrom(pic);
3674 
3676 
3677  TGo4BrowserProxy* brcont = Browser();
3678 
3679  Option_t* drawopt = pic->GetDrawOption(TGo4Picture::PictureIndex);
3680  if (drawopt != 0)
3682 
3683  Int_t ndraw = 0;
3684 
3685  for (Int_t n = 0; n < pic->GetNumObjNames(); n++) {
3686  Option_t* drawopt = pic->GetDrawOption(n);
3687  if (drawopt != 0)
3688  pic->SetDrawOption(drawopt, n);
3689 
3690  const char* objname = pic->GetObjName(n);
3691 
3692  TString drawname;
3693 
3694  if (brcont->DefineRelatedObject(picitemname, objname, drawname)) {
3695 
3696  TGo4Slot* slot = AddDrawObject(pad, kind_Link, drawname.Data(), 0, false, 0);
3697 
3698  brcont->GetBrowserObject(drawname.Data(), go4sett->getFetchDataWhenDraw() ? 2 : 1);
3699  ndraw++;
3700 
3701  if (pic->GetRebinX(n) > 1) {
3702  slot->SetIntPar("::DoRebinX", pic->GetRebinX(n));
3703  slot->SetIntPar("::HasRebinX", pic->GetRebinX(n));
3704  }
3705 
3706  if (pic->GetRebinY(n) > 1) {
3707  slot->SetIntPar("::DoRebinY", pic->GetRebinY(n));
3708  slot->SetIntPar("::HasRebinY", pic->GetRebinY(n));
3709  }
3710  }
3711  }
3712 
3713  if (ndraw > 1)
3714  padopt->SetSuperimpose(kTRUE);
3715 
3716  TListIter iter(pic->GetSpecialObjects());
3717  TObject* obj = 0;
3718  while ((obj = iter()) != 0) {
3719  Option_t* drawopt = iter.GetOption();
3720  if (dynamic_cast<TArrow*>(obj) != 0)
3721  AddMarkerObj(pad, kind_Arrow, obj->Clone());
3722  else if (dynamic_cast<TLatex*>(obj) != 0)
3723  AddMarkerObj(pad, kind_Latex, obj->Clone());
3724  else if (dynamic_cast<TGo4Marker*>(obj) != 0)
3725  AddMarkerObj(pad, kind_Marker, obj->Clone());
3726  else if (dynamic_cast<TGo4WinCond*>(obj) != 0)
3727  AddMarkerObj(pad, kind_Window, obj->Clone());
3728  else if (dynamic_cast<TGo4PolyCond*>(obj) != 0)
3729  AddMarkerObj(pad, kind_Poly, obj->Clone());
3730  else if (dynamic_cast<TPaveLabel*>(obj) != 0)
3731  AddDrawObject(pad, kind_Specials, obj->GetName(), obj->Clone(), kTRUE,
3732  drawopt ? drawopt : "br");
3733  else
3734  AddDrawObject(pad, kind_Specials, obj->GetName(), obj->Clone(), kTRUE,
3735  drawopt);
3736  }
3737 
3738  padopt->SetPadModified();
3739 }
3740 
3741 void TGo4ViewPanel::ProcessCanvasAdopt(TPad* tgtpad, TPad* srcpad,
3742  const char* srcpaditemname)
3743 {
3744  if ((tgtpad == 0) || (srcpad == 0)) return;
3745 
3746  TGo4Slot* padslot = GetPadSlot(tgtpad);
3747 
3748  TGo4Picture* padopt = GetPadOptions(tgtpad);
3749 
3750  if ((padopt == 0) || (padslot == 0)) return;
3751 
3752  tgtpad->SetTickx(srcpad->GetTickx());
3753  tgtpad->SetTicky(srcpad->GetTicky());
3754  tgtpad->SetGridx(srcpad->GetGridx());
3755  tgtpad->SetGridy(srcpad->GetGridy());
3756  tgtpad->SetBorderSize(srcpad->GetBorderSize());
3757  tgtpad->SetBorderMode(srcpad->GetBorderMode());
3758  srcpad->TAttLine::Copy(*tgtpad);
3759  srcpad->TAttFill::Copy(*tgtpad);
3760  srcpad->TAttPad::Copy(*tgtpad);
3761 
3762  tgtpad->SetPhi(srcpad->GetPhi());
3763  tgtpad->SetTheta(srcpad->GetTheta());
3764 
3765  int nsubpads = 0, nmain = 0, mainkind = 0;
3766  TObjLink* link = srcpad->GetListOfPrimitives()->FirstLink();
3767  while (link != 0) {
3768  TObject* obj = link->GetObject();
3769  const char* drawopt = link->GetOption();
3770 
3771  TH1* h1 = 0;
3772 
3773  int kind = 0;
3774 
3775  TPad* srcsubpad = dynamic_cast<TPad*>(obj);
3776 
3777  TString itemname = TString::Format("%s/%s", srcpaditemname,
3778  obj->GetName());
3779 
3780  if (srcsubpad != 0) {
3781  nsubpads++;
3782  QString subpadname = tgtpad->GetName();
3783  subpadname += "_";
3784  subpadname += QString::number(nsubpads);
3785 
3786  Double_t xlow, ylow, xup, yup;
3787 
3788  srcsubpad->GetPadPar(xlow, ylow, xup, yup);
3789 
3790  tgtpad->cd();
3791  TPad* tgtsubpad = new TPad(subpadname.toLatin1().constData(),
3792  srcsubpad->GetName(), xlow, ylow, xup, yup);
3793  tgtsubpad->SetNumber(nsubpads);
3794  tgtsubpad->Draw();
3795 
3796  TGo4Slot* subpadslot = AddNewSlot(tgtsubpad->GetName(), padslot);
3797  SetDrawKind(subpadslot, kind_PadSlot);
3798  SetSlotPad(subpadslot, tgtsubpad);
3799 
3800  ProcessCanvasAdopt(tgtsubpad, srcsubpad, itemname.Data());
3801  } else if (dynamic_cast<TGo4Condition*>(obj) != 0) {
3802  TGo4Condition* cond = (TGo4Condition*) obj->Clone();
3803  cond->SetWorkHistogram(0);
3804  AddDrawObject(tgtpad, kind_Condition, cond->GetName(), cond, kTRUE, 0);
3805  } else if (dynamic_cast<TGo4Marker*>(obj) != 0) {
3806  TGo4Marker* mark = (TGo4Marker*) obj->Clone();
3807  mark->SetHistogram(0);
3808  AddDrawObject(tgtpad, kind_Marker, mark->GetName(), mark, kTRUE, 0);
3809  } else if (dynamic_cast<TLatex*>(obj) != 0) {
3810  AddDrawObject(tgtpad, kind_Latex, obj->GetName(), obj->Clone(), kTRUE,
3811  0);
3812  } else if (dynamic_cast<TPaveLabel*>(obj) != 0) {
3813  AddDrawObject(tgtpad, kind_Specials, obj->GetName(), obj->Clone(),
3814  kTRUE, drawopt ? drawopt : "br");
3815  } else if (dynamic_cast<TArrow*>(obj) != 0) {
3816  AddDrawObject(tgtpad, kind_Arrow, obj->GetName(), obj->Clone(), kTRUE,
3817  0);
3818  } else
3819 
3820  if (dynamic_cast<TH1*>(obj) != 0) {
3821  kind = 1;
3822  h1 = (TH1*) obj;
3823  } else
3824 
3825  if (dynamic_cast<TGraph*>(obj) != 0) {
3826  kind = 2;
3827  h1 = Get_fHistogram(obj);
3828  } else
3829 
3830  if (dynamic_cast<THStack*>(obj) != 0) {
3831  kind = 3;
3832  h1 = Get_fHistogram(obj);
3833  } else
3834 
3835  if (dynamic_cast<TMultiGraph*>(obj) != 0) {
3836  kind = 4;
3837  h1 = Get_fHistogram(obj);
3838  } else {
3839 // std::cout << tgtpad->GetName() << ": Add other object ???" << obj->GetName() << std::endl;
3840  }
3841 
3842  // only first object is added,
3843  // make superimpose only for histos and graphs
3844  if ((kind > 0) && ((mainkind == 0) || ((kind == mainkind) && (kind < 3)))) {
3845 
3846  if (drawopt != 0)
3847  padopt->SetDrawOption(drawopt, nmain);
3848 
3849  AddDrawObject(tgtpad, knd_Reference, obj->GetName(), obj, false, 0);
3850 
3851  mainkind = kind;
3852 
3853  if ((h1 != 0) && (nmain == 0)) {
3854  TakeFullRangeFromHisto(h1, padopt, nmain == 0);
3855  Int_t ndim = h1->GetDimension();
3856  TakeSelectedAxisRange(0, padopt, h1->GetXaxis());
3857  if (ndim > 1)
3858  TakeSelectedAxisRange(1, padopt, h1->GetYaxis());
3859  if (ndim > 2)
3860  TakeSelectedAxisRange(2, padopt, h1->GetZaxis());
3861  if (ndim < 3) {
3862  Double_t selmin = h1->GetMinimum();
3863  Double_t selmax = h1->GetMaximum();
3864 
3865  if (selmin < selmax)
3866  padopt->SetRange(ndim, selmin, selmax);
3867 
3868  padopt->SetAutoScale(
3869  !h1->TestBit(TH1::kIsZoomed) || (selmin >= selmax));
3870  }
3871  }
3872 
3873  nmain++;
3874  }
3875 
3876  link = link->Next();
3877  }
3878 
3879  if (nmain > 1)
3880  padopt->SetSuperimpose(kTRUE);
3881 
3882  if (nsubpads == 0)
3883  ScanDrawOptions(srcpad, padslot, padopt, false);
3884 }
3885 
3886 void TGo4ViewPanel::RedrawPanel(TPad* pad, bool force)
3887 {
3888  if (IsRedrawBlocked()) return;
3889 
3890  TGo4LockGuard lock;
3891 
3892  BlockPanelRedraw(true);
3893 
3894 #ifdef __GO4X11__
3895 
3896  // JAM2016: does this help for some array conflicts in TGraph painter? YES!
3897  // must be done once before pad->Clear in ProcessPadRedraw, so we do it here instead for each subpad
3898 #ifdef GLOBALESCAPE
3899  if (fxQCanvas) {
3900  gROOT->SetEscape();
3901  fxQCanvas->HandleInput(kButton1Up, 0, 0);
3902  fxQCanvas->HandleInput(kMouseMotion, 0, 0); // stolen from TRootEmbeddedCanvas::HandleContainerKey
3903  // SL2016 - one need to reset escape status back, some other functionality (like zooming) may not work
3904  gROOT->SetEscape(kFALSE);
3905  }
3906 
3907 #else
3908  // JAM 2016: only reset crucial static arrays in TGraph subclasses, do not escape complete root...
3909  // turned out to have strange side effects with TBox which also has static variables reacting on escape flag :(
3910  if(fxQCanvas) { // just for the scope to delete dummy graph on stack
3911  gPad = pad;
3912  Bool_t oldmodified = gPad->IsModified();
3913  TGraph dummy(1);
3914  gROOT->SetEscape();
3915  dummy.ExecuteEvent(kButton1Up, 0, 0); // will reset escape flag internally
3916  gPad->Modified(oldmodified); // probably not necessary, since we only use escape mode in event handler. But who knows what future root brings?
3917  }
3918 #endif
3919 #endif
3920 
3921  bool isanychildmodified = false;
3922  bool ispadupdatecalled = false;
3923 
3924  QTime starttm = QTime::currentTime();
3925  bool intime = true;
3926 
3927 
3928  // this loop done to allow consequent update of multi-pad canvas
3929  // each subpad separately redrawn in ProcessPadRedraw() method and
3930  // than pad->Update() is called. If it takes too long,
3931  // loop is finishing and via paint timer will be activated later
3932 
3933  do {
3934  TPad* selpad = TGo4MdiArea::Instance()->GetSelectedPad();
3935 
3936  isanychildmodified = ProcessPadRedraw(pad, force);
3937 
3939 
3940  // here pad->Update should redraw only modified subpad
3941  if (isanychildmodified) {
3942  CanvasUpdate();
3943  ispadupdatecalled = true;
3944  }
3945 
3946  int delay = starttm.msecsTo(QTime::currentTime());
3947  intime = (delay >= 0) && (delay < 100);
3948 
3949  } while (!force && isanychildmodified && intime);
3950 
3951  if (GetActivePad() != 0)
3953 
3954  RefreshButtons();
3955 
3956  // to correctly select active pad, one should call canvas->Update()
3957  if (!ispadupdatecalled)
3958  CanvasUpdate();
3959 
3961 
3962  BlockPanelRedraw(false);
3963 
3964  if (!force && isanychildmodified)
3965  ShootRepaintTimer(pad);
3966 }
3967 
3968 bool TGo4ViewPanel::ProcessPadRedraw(TPad* pad, bool force)
3969 {
3970  TGo4Slot* slot = GetPadSlot(pad);
3971  if (slot == 0) return false;
3972 
3973  TGo4Picture* padopt = GetPadOptions(slot);
3974  if (padopt == 0) return false;
3975 
3976  bool ischilds = false;
3977  bool ischildmodified = false;
3978 
3979  CheckObjectsAssigments(pad, slot);
3980 
3981  CheckForSpecialObjects(pad, slot);
3982 
3983  // this parameter ensure that all pads will be scanned one after another
3984  Int_t lastdrawnpad = 0;
3985  if (!force)
3986  if (!slot->GetIntPar("::LastDrawnPad", lastdrawnpad))
3987  lastdrawnpad = 0;
3988 
3989  Int_t subpadindx = 0;
3990 
3991  // first redraw all subpads
3992  for (int n = 0; n < slot->NumChilds(); n++) {
3993  subpadindx = (n + lastdrawnpad) % slot->NumChilds();
3994  TPad* subpad = GetSlotPad(slot->GetChild(subpadindx));
3995  if (subpad == 0) continue;
3996  ischilds = true;
3997  if (ProcessPadRedraw(subpad, force)) {
3998  ischildmodified = true;
3999  if (!force) break; // break if any of child is modified
4000  }
4001  }
4002 
4003  if (!force && ischildmodified)
4004  slot->SetIntPar("::LastDrawnPad", subpadindx);
4005  else
4006  slot->RemovePar("::LastDrawnPad");
4007 
4008  if (!force && !padopt->IsPadModified())
4009  return ischildmodified;
4010 
4011  bool updatecontent = padopt->IsContentModified();
4012 
4013  padopt->SetPadModified(false);
4014  padopt->SetContentModified(false);
4015 
4016  // do not draw anything else if subpads are there
4017  if (ischilds) return ischildmodified;
4018 
4019  pad->Clear();
4020 
4021  pad->SetCrosshair(fbCanvasCrosshair);
4022  pad->SetLogx(padopt->GetLogScale(0));
4023  pad->SetLogy(padopt->GetLogScale(1));
4024  pad->SetLogz(padopt->GetLogScale(2));
4025 
4026  TObjArray objs, objslots;
4027  CollectMainDrawObjects(slot, &objs, &objslots,
4028  padopt->IsSuperimpose() ? 1 : 2);
4029 
4030  ScanObjectsDrawOptions(false, slot, &objs, &objslots);
4031 
4032  TGo4Slot* sislot = GetSuperimposeSlot(slot);
4033  TGo4Slot* legslot = slot->FindChild("::Legend");
4034  TGo4Slot* asislot = slot->FindChild("::ASImage");
4035 
4036  // if nothing to draw, delete all additional slots and exit
4037  if (objs.GetLast() < 0) {
4038  delete sislot;
4039  delete legslot;
4040  delete asislot;
4041 
4042  RedrawSpecialObjects(pad, slot);
4043 
4045 
4046  // indicate that nothing is happen
4047  return true;
4048  }
4049 
4050  TH2* asihisto = 0;
4051 
4052  TObject* drawobj = 0;
4053 
4054  // Bool_t dosuperimpose = padopt->IsSuperimpose() && (objs.GetLast()>0);
4055  Bool_t dosuperimpose = objs.GetLast() > 0;
4056 
4057  const char* drawopt = padopt->GetDrawOption(0);
4058 
4059  Bool_t doasiimage = !dosuperimpose && !fxWCanvas &&
4060  objs.Last()->InheritsFrom(TH2::Class());
4061 
4062  if (drawopt && TString(drawopt).Contains("asimage")) {
4063  if (!doasiimage) { drawopt = "col"; padopt->SetDrawOption("col", 0); }
4064  } else {
4065  doasiimage = kFALSE;
4066  }
4067 
4068  if (dosuperimpose) {
4069  if (sislot == 0)
4070  sislot = new TGo4Slot(slot, "::Superimpose", "place for superimpose object");
4071  if (padopt->IsLegendDraw()) {
4072  if (legslot == 0)
4073  legslot = new TGo4Slot(slot, "::Legend", "place for legends object");
4074  } else
4075  if (legslot != 0) {
4076  delete legslot;
4077  legslot = 0;
4078  }
4079 
4080  drawobj = ProduceSuperimposeObject(slot, padopt, sislot, legslot, &objs,
4081  &objslots, padopt->IsTitleItem());
4082  if (drawobj == 0)
4083  dosuperimpose = kFALSE;
4084  }
4085 
4086  if (!dosuperimpose) {
4087  if (sislot != 0) {
4088  delete sislot;
4089  sislot = 0;
4090  }
4091  if (legslot != 0) {
4092  delete legslot;
4093  legslot = 0;
4094  }
4095  drawobj = objs.Last();
4096  }
4097 
4098  if (doasiimage) {
4099  asihisto = dynamic_cast<TH2*>(drawobj);
4100  if (asihisto == 0)
4101  doasiimage = false;
4102  else {
4103  if (asislot == 0)
4104  asislot = new TGo4Slot(slot, "::ASImage", "place for Go4 ASI image");
4105  TGo4ASImage* image =
4106  dynamic_cast<TGo4ASImage*>(asislot->GetAssignedObject());
4107  if(image==0) {
4108  image = new TGo4ASImage;
4109  asislot->SetProxy(new TGo4ObjectProxy(image, kTRUE));
4110  updatecontent = true;
4111  }
4112  if (updatecontent)
4113  image->SetHistogramContent(asihisto);
4114 
4115  drawobj = image;
4116  }
4117  }
4118 
4119  if (!doasiimage) {
4120  if (asislot != 0) {
4121  delete asislot;
4122  asislot = 0;
4123  }
4124  }
4125 
4126  gPad = pad; // instead of pad->cd(), while it is redraw frame
4127  if (drawobj != 0) {
4128  bool first_draw = (slot->GetPar("::PadFirstDraw") == 0);
4129  if (first_draw) slot->SetPar("::PadFirstDraw", "true");
4130 
4131  if (drawobj->InheritsFrom(TH1::Class())) {
4132  TH1* h1 = (TH1*) drawobj;
4133  h1->SetBit(kCanDelete, kFALSE);
4134  RedrawHistogram(pad, padopt, h1, updatecontent, first_draw);
4135  } else if (drawobj->InheritsFrom(THStack::Class())) {
4136  THStack* hs = (THStack*) drawobj;
4137  RedrawStack(pad, padopt, hs, dosuperimpose, updatecontent);
4138  } else if (drawobj->InheritsFrom(TGraph::Class())) {
4139  TGraph* gr = (TGraph*) drawobj;
4140  RedrawGraph(pad, padopt, gr, updatecontent, first_draw);
4141  } else if (drawobj->InheritsFrom(TMultiGraph::Class())) {
4142  TMultiGraph* mg = (TMultiGraph*) drawobj;
4143  RedrawMultiGraph(pad, padopt, mg, dosuperimpose, updatecontent);
4144  } else if (dynamic_cast<TGo4ASImage*>(drawobj) != 0) {
4145  TGo4ASImage* ai = (TGo4ASImage*) drawobj;
4146  RedrawImage(pad, padopt, ai, asihisto, updatecontent);
4147  }
4148  }
4149 
4150  if (legslot != 0)
4151  RedrawLegend(pad, padopt, legslot);
4152 
4153  if (!doasiimage)
4154  RedrawSpecialObjects(pad, slot);
4155 
4157 
4158  return true;
4159 }
4160 
4161 void TGo4ViewPanel::RedrawHistogram(TPad *pad, TGo4Picture* padopt, TH1 *his, bool scancontent, bool first_draw)
4162 {
4163  if ((pad == 0) || (padopt == 0) || (his == 0)) return;
4164 
4165  if (scancontent)
4166  TakeFullRangeFromHisto(his, padopt, true);
4167 
4168  TString drawopt(padopt->GetDrawOption(0));
4169  if (drawopt.Length() == 0) {
4170  if (his->GetDimension() == 1)
4171  drawopt = go4sett->getTH1DrawOpt().toLatin1().constData();
4172  else if (his->GetDimension() == 2)
4173  drawopt = go4sett->getTH2DrawOpt().toLatin1().constData();
4174  else if (his->GetDimension() == 3)
4175  drawopt = go4sett->getTH3DrawOpt().toLatin1().constData();
4176  }
4177 
4178  drawopt.ToUpper();
4179 
4180  if (first_draw && (go4sett->getDrawLineWidth() > 1) && (his->GetLineWidth()==1))
4181  his->SetLineWidth(go4sett->getDrawLineWidth());
4182 
4183  // only activate panel defaults if no fill color set by user:
4184  if (first_draw && (go4sett->getDrawFillColor()>0) && (his->GetFillColor()==0))
4185  his->SetFillColor(go4sett->getDrawFillColor());
4186  if (first_draw && (go4sett->getDrawFillStyle()!=1001) && (his->GetFillStyle()==1001))
4187  his->SetFillStyle(go4sett->getDrawFillStyle());
4188 
4189  Int_t nlvl = padopt->GetHisContour();
4190  if (nlvl > 0) his->SetContour(nlvl);
4191 
4192  his->SetStats(padopt->IsHisStats());
4193  his->SetBit(TH1::kNoTitle, !padopt->IsHisTitle());
4194  his->Draw(drawopt.Data());
4195 
4196  SetSelectedRangeToHisto(pad, his, 0, padopt, true);
4197 }
4198 
4199 void TGo4ViewPanel::RedrawStack(TPad *pad, TGo4Picture* padopt, THStack * hs,
4200  bool dosuperimpose, bool scancontent)
4201 {
4202  if ((pad == 0) || (padopt == 0) || (hs == 0)) return;
4203 
4204  if (scancontent) {
4205  TIter iter(hs->GetHists());
4206  TH1 *h1 = 0;
4207  bool first = true;
4208  while ((h1 = (TH1*) iter()) != 0) {
4209  TakeFullRangeFromHisto(h1, padopt, first);
4210  first = false;
4211  }
4212  }
4213 
4214  // never draw statistics with stack
4215 
4216  Int_t drawoptindx = dosuperimpose ? TGo4Picture::PictureIndex : 0;
4217  TString drawopt(padopt->GetDrawOption(drawoptindx));
4218  if (drawopt.Length() == 0)
4219  drawopt = "hist";
4220  if (!drawopt.Contains(NoStackDrawOption, TString::kIgnoreCase))
4221  drawopt.Prepend(NoStackDrawOption);
4222 
4223  hs->Draw(drawopt.Data());
4224  // do not access histogram in web canvas - causes redraw of the complete canvas
4225  TH1* framehisto = Get_fHistogram(hs, true);
4226  if (framehisto == 0) return;
4227 
4228  framehisto->SetStats(false);
4229  framehisto->SetBit(TH1::kNoTitle, !padopt->IsHisTitle());
4230  TH1* h1 = dynamic_cast<TH1*>(hs->GetHists() ? hs->GetHists()->First() : 0);
4231  if (h1!=0) {
4232  hs->SetTitle(h1->GetTitle());
4233  framehisto->SetTitle(h1->GetTitle());
4234  framehisto->GetXaxis()->SetTitle(h1->GetXaxis()->GetTitle());
4235  framehisto->GetYaxis()->SetTitle(h1->GetYaxis()->GetTitle());
4236  framehisto->GetZaxis()->SetTitle(h1->GetZaxis()->GetTitle());
4237  }
4238 
4239  SetSelectedRangeToHisto(pad, framehisto, hs, padopt, false);
4240 }
4241 
4242 void TGo4ViewPanel::RedrawGraph(TPad *pad, TGo4Picture* padopt, TGraph * gr, bool scancontent, bool first_draw)
4243 {
4244  if ((pad == 0) || (padopt == 0) || (gr == 0)) return;
4245 
4246  if (scancontent) {
4247  TakeFullRangeFromGraph(gr, padopt, true);
4248  gr->SetEditable(kFALSE);
4249  }
4250 
4251  TString drawopt = padopt->GetDrawOption(0);
4252 
4253  // when graph drawn for the first time, check if time units used in axis
4254  if (first_draw) {
4255  TAxis *ax = gr->GetXaxis();
4256  if ((ax!=0) && ax->GetTimeDisplay()) {
4257  padopt->SetHisStats(kFALSE);
4258  padopt->SetXAxisTimeDisplay(kTRUE);
4259  padopt->SetXAxisTimeFormat(ax->GetTimeFormat());
4260  if (drawopt.Length() == 0) {
4261  drawopt = go4sett->getTGraphDrawOpt().toLatin1().constData();
4262  padopt->SetDrawOption(drawopt);
4263  }
4264  }
4265  if ((go4sett->getDrawLineWidth() > 1) && (gr->GetLineWidth()==1))
4266  gr->SetLineWidth(go4sett->getDrawLineWidth());
4267 
4268 
4269  // only activate panel defaults if no fill color set by user:
4270  if ((go4sett->getDrawFillColor()>0) && (gr->GetFillColor()==0))
4271  gr->SetFillColor(go4sett->getDrawFillColor());
4272  if ((go4sett->getDrawFillStyle()!=1001) && (gr->GetFillStyle()==1001))
4273  gr->SetFillStyle(go4sett->getDrawFillStyle());
4274  }
4275 
4276  if (drawopt.Length() == 0)
4277  drawopt = go4sett->getTGraphDrawOpt().toLatin1().constData();
4278 
4279  TH1* framehisto = Get_fHistogram(gr);
4280  if (framehisto) {
4281  framehisto->SetStats(padopt->IsHisStats());
4282  framehisto->SetBit(TH1::kNoTitle, !padopt->IsHisTitle());
4283  }
4284 
4285  gr->Draw(drawopt.Data());
4286 
4287  if (!framehisto && !IsWebCanvas()) {
4288  framehisto = gr->GetHistogram();
4289  if (framehisto && ((framehisto->TestBit(TH1::kNoStats) == padopt->IsHisStats()) || (framehisto->TestBit(TH1::kNoTitle) == padopt->IsHisTitle()))) {
4290  framehisto->SetStats(padopt->IsHisStats());
4291  framehisto->SetBit(TH1::kNoTitle, !padopt->IsHisTitle());
4292  gr->Draw(drawopt.Data());
4293  }
4294  }
4295 
4296  SetSelectedRangeToHisto(pad, framehisto, 0, padopt, false);
4297 }
4298 
4300  TMultiGraph * mg, bool dosuperimpose, bool scancontent)
4301 {
4302  if ((pad == 0) || (padopt == 0) || (mg == 0)) return;
4303 
4304  TIter iter(mg->GetListOfGraphs());
4305  TGraph *gr(0), *firstgr(0);
4306  bool first = true;
4307  while ((gr = (TGraph*) iter()) != 0) {
4308  if (scancontent) {
4309  gr->SetEditable(kFALSE);
4310  TakeFullRangeFromGraph(gr, padopt, first);
4311  }
4312  if (first)
4313  firstgr = gr;
4314  first = false;
4315  }
4316 
4317  Int_t drawoptindx = dosuperimpose ? TGo4Picture::PictureIndex : 0;
4318  TString drawopt(padopt->GetDrawOption(drawoptindx));
4319  if (drawopt.Length() == 0)
4320  drawopt = go4sett->getTGraphDrawOpt().toLatin1().constData();
4321  if (dosuperimpose)
4322  drawopt = "";
4323 
4324  if (IsWebCanvas()) {
4325  mg->Draw(drawopt.Data());
4326  return;
4327  }
4328 
4329  TH1* framehisto = (dosuperimpose && (firstgr != 0)) ? firstgr->GetHistogram() : mg->GetHistogram();
4330 
4331  if (framehisto == 0) {
4332  // this is workaround to prevent recreation of framehistogram in TMultiGraph::Paint
4333  mg->Draw(drawopt.Data());
4334  framehisto = (dosuperimpose && (firstgr != 0)) ? firstgr->GetHistogram() : mg->GetHistogram();
4335  }
4336 
4337  if (framehisto == 0) {
4338  TGo4Log::Error("Internal problem with MultiGraph drawing - cannot access frame histo");
4339  return;
4340  }
4341 
4342  SetSelectedRangeToHisto(pad, framehisto, 0, padopt, false);
4343 
4344  // try to avoid flicker of range when in fullscale: set range before and after draw
4345  Double_t miny, maxy, selmin, selmax;
4346  if (padopt->GetFullRange(1, miny, maxy) && !padopt->GetRangeY(selmin, selmax)) {
4347  if (padopt->GetLogScale(1)) {
4348  if (maxy <= 0) maxy = 1.;
4349  if ((miny <= 0) || (miny >= maxy)) {
4350  miny = maxy * 1e-4;
4351  if (miny > 1.) miny = 1.;
4352  }
4353  } else {
4354  maxy *= ((maxy>0) ? 1.1 : 0.9);
4355  miny *= ((miny>0) ? 0.9 : 1.1);
4356  }
4357  framehisto->SetMaximum(maxy);
4358  framehisto->SetMinimum(miny);
4359  }
4360 
4361  framehisto->SetStats(kFALSE); // never draw statistics with multigraph
4362  framehisto->SetBit(TH1::kNoTitle, !padopt->IsHisTitle());
4363 
4364  // set title of first TGraph to TMultiGraph and frame histo
4365  if (firstgr != 0) {
4366  mg->SetTitle(firstgr->GetTitle());
4367  framehisto->SetTitle(firstgr->GetTitle());
4368  framehisto->GetXaxis()->SetTitle(firstgr->GetXaxis()->GetTitle());
4369  framehisto->GetYaxis()->SetTitle(firstgr->GetYaxis()->GetTitle());
4370  }
4371 
4372  mg->Draw(drawopt.Data());
4373 }
4374 
4376  TH2* asihisto, bool scancontent)
4377 {
4378  if ((pad == 0) || (padopt == 0) || (im == 0)) return;
4379 
4380  im->SetDrawData(asihisto, this, pad);
4381 
4382  if (scancontent)
4383  TakeFullRangeFromHisto(asihisto, padopt, true);
4384 
4385  TString drawopt(padopt->GetDrawOption(0));
4386 
4387  double uminx, umaxx, uminy, umaxy;
4388  padopt->GetRange(0, uminx, umaxx);
4389  padopt->GetRange(1, uminy, umaxy);
4390  im->SetSelectedRange(uminx, umaxx, uminy, umaxy);
4391 
4392  im->SetPaletteEnabled(drawopt.Contains("Z"));
4393 
4394  im->Draw();
4395 }
4396 
4398  TGo4Slot* legslot)
4399 {
4400  if (legslot == 0) return;
4401  TLegend* legend = dynamic_cast<TLegend*>(legslot->GetAssignedObject());
4402  //legend->SetBit(kCanDelete, kFALSE); // jam2016
4403  if(legend!=0) legend->Draw();
4404 }
4405 
4407 {
4408  if ((pad == 0) || (padslot == 0))
4409  return;
4410 
4411  CheckObjectsAssigments(pad, padslot);
4412 
4413  QString selname = GetSelectedMarkerName(pad);
4414  TObject* selectedobj = 0;
4415  const char* selectdrawopt = 0;
4416  Int_t numtf1=0;
4417  for (int n = 0; n < padslot->NumChilds(); n++) {
4418  TGo4Slot* subslot = padslot->GetChild(n);
4419 
4420  Int_t kind = GetDrawKind(subslot);
4421 
4422  if ((kind < kind_Specials) || (kind >= kind_Other))
4423  continue;
4424 
4425  TObject* obj = subslot->GetAssignedObject();
4426  if (obj == 0)
4427  continue;
4428 
4429  TString drawopt = GetSpecialDrawOption(subslot);
4430  if(obj->InheritsFrom(TF1::Class())){
4431  if(!pad->GetListOfPrimitives()->IsEmpty())
4432  drawopt.Append("LSAME"); // for correct overlay of TF1 objects JAM
4433  TF1* func = dynamic_cast<TF1*>(obj);
4434  Int_t objindx = padslot->GetIndexOf(subslot);
4435  func->SetLineColor(GetAutoColor(((objindx+7) % 9) + 1)); // 9 basic colors for superimpose of tf1, like for other superimpose
4436  }
4437 
4438  if ((selname == obj->GetName()) && (selectedobj == 0)) {
4439  selectedobj = obj;
4440  selectdrawopt = drawopt.Data();
4441  } else {
4442  //obj->SetBit(kCanDelete, kFALSE); // jam2016
4443  obj->Draw(drawopt.Data());
4444  }
4445  }
4446 
4447  // if one has selected object on the pad, one should
4448  // draw it as last to bring it to the front of other
4449  if (selectedobj != 0){
4450  //selectedobj->SetBit(kCanDelete, kFALSE); // jam2016
4451  selectedobj->Draw(selectdrawopt ? selectdrawopt : "");
4452  }
4453 
4454 }
4455 
4457 {
4458  return fbAutoZoomFlag;
4459 }
4460 
4462 {
4463  fbAutoZoomFlag = on;
4464 }
4465 
4467 {
4468  return fbApplyToAllFlag;
4469 }
4470 
4472 {
4473  return fbFreezeTitle;
4474 }
4475 
4477  int value, const char* drawopt)
4478 {
4479  TGo4LockGuard lock;
4480  TGo4Picture* subopt = GetPadOptions(padslot);
4481  if (subopt == 0) return;
4482  switch (kind) {
4483  case 0:
4484  case 1:
4485  case 2: {
4486  int selindx = GetSelectedObjectIndex(padslot);
4487  subopt->SetDrawOption(drawopt, selindx);
4488  subopt->SetPadModified();
4489  break;
4490  }
4491  case 100: {
4492  subopt->SetPadModified();
4493  break;
4494  }
4495  case 101: {
4496  TPad* subpad = GetSlotPad(padslot);
4497  if (subpad != 0) {
4498  subpad->SetFillColor(value);
4499  if (subpad->GetFrame())
4500  subpad->GetFrame()->SetFillColor(value);
4501  }
4502  subopt->SetPadModified();
4503  break;
4504  }
4505  case 16: {
4506  // this is for setting time axis format:
4507  subopt->SetXAxisTimeFormat(drawopt);
4508  subopt->SetPadModified();
4509  break;
4510  }
4511 
4512  default:
4513  subopt->ChangeDrawOption(kind, value);
4514  break;
4515  }
4516 }
4517 
4518 void TGo4ViewPanel::ChangeDrawOption(int kind, int value, const char* drawopt)
4519 {
4520  TGo4LockGuard lock;
4521 
4522  bool scanall = IsApplyToAllFlag();
4523 
4524  if (kind == 100) {
4525  gStyle->SetPalette(value);
4526  scanall = true;
4527  }
4528 
4529  TPad* pad = scanall ? GetCanvas() : GetActivePad();
4530 
4531  if (pad == 0)
4532  pad = GetCanvas();
4533 
4534  TGo4Slot* slot = GetPadSlot(pad);
4535  if (slot == 0) return;
4536 
4537  ChangeDrawOptionForPad(slot, kind, value, drawopt);
4538 
4539  TGo4Iter iter(slot, true);
4540  while (iter.next())
4541  ChangeDrawOptionForPad(iter.getslot(), kind, value, drawopt);
4542 
4543  RedrawPanel(pad, false);
4544 }
4545 
4546 void TGo4ViewPanel::ResetPadFillColors(TPad* pad, int col, TPad* backup)
4547 {
4548  TGo4LockGuard lock;
4549  if (pad == 0)
4550  return;
4551  if(backup) col=backup->GetFillColor();
4552  pad->SetFillColor((Color_t) col);
4553  //pad->Modified(); // for image formats, display window bitmap has to change
4554  //std::cout<<"ResetPadFillColors sets color "<<col<<" to pad "<< (unsigned long) pad<<", name:"<<pad->GetName()<<", backup was "<<backup << std::endl;
4555  TIter iter(pad->GetListOfPrimitives());
4556  TObject* obj = 0;
4557  while ((obj = iter()) != 0) {
4558  TPad* subpad = dynamic_cast<TPad*>(obj);
4559  TFrame* fram = dynamic_cast<TFrame*>(obj);
4560  if (subpad != 0){
4561  //std::cout<<"ResetPadFillColors finds subpad " << (unsigned long) subpad << std::endl;
4562  TPad* backpad=0;
4563  if(backup)
4564  {
4565  backpad=dynamic_cast<TPad*>(backup->GetListOfPrimitives()->FindObject(subpad->GetName()));
4566  // debug only:
4567 // if(backpad)
4568 // {
4569 // col=backpad->GetFillColor();
4570 // std::cout<<"ResetPadFillColors finds backup pad "<<backpad->GetName()<<" with color "<< col << std::endl;
4571 // }
4572  // end debug
4573  }
4574  ResetPadFillColors(subpad, col, backpad);
4575  }
4576  else if (fram != 0)
4577  {
4578  if(backup)
4579  {
4580  TFrame* backframe=dynamic_cast<TFrame*>(backup->GetListOfPrimitives()->FindObject(fram->GetName()));
4581  if(backframe)
4582  {
4583  col=backframe->GetFillColor();
4584  //std::cout<<"ResetPadFillColors finds backup frame "<<backframe->GetName()<<" with color "<< col << std::endl;
4585  }
4586  }
4587  //std::cout<<"ResetPadFillColors sets color "<<col<<" to subframe "<< (unsigned long) fram->GetName()<< std::endl;
4588  fram->SetFillColor((Color_t) col);
4589  }
4590  }
4591 
4592 }
4593 
4594 void TGo4ViewPanel::ClearPad(TPad* pad, bool removeitems, bool removesubpads)
4595 {
4596  TGo4LockGuard lock;
4597 
4598  BlockPanelRedraw(true);
4599  CleanupGedEditor();
4600  ProcessPadClear(pad, removeitems, removesubpads);
4601  if (GetActivePad() == 0)
4603  GetCanvas()->SetSelected(0);
4604  BlockPanelRedraw(false);
4605 }
4606 
4608 {
4609  if (padslot == 0) return;
4610 
4611  for (int n = padslot->NumChilds() - 1; n >= 0; n--) {
4612  TGo4Slot* subslot = padslot->GetChild(n);
4613  int kind = GetDrawKind(subslot);
4614  if ((kind < kind_Permanet) && (subslot != remain)) {
4615  delete subslot;
4616  }
4617  }
4618 }
4619 
4620 void TGo4ViewPanel::ProcessPadClear(TPad * pad, bool removeitems, bool removesubpads)
4621 {
4622  TGo4Slot* slot = GetPadSlot(pad);
4623  TGo4Picture* padopt = GetPadOptions(slot);
4624  if ((slot == 0) || (padopt == 0))
4625  return;
4626 
4627 // padopt->Clear(""); // remove all settings completely
4628  padopt->SetPadModified();
4629 
4630  if (removeitems)
4631  ClearPadItems(slot, 0);
4632 
4633  CheckObjectsAssigments(pad, slot);
4634 
4635  for (int n = slot->NumChilds() - 1; n >= 0; n--) {
4636  TGo4Slot* subslot = slot->GetChild(n);
4637 
4638  TPad* subpad = GetSlotPad(subslot);
4639  if (subpad == 0)
4640  continue;
4641  ProcessPadClear(subpad, removeitems || removesubpads, removesubpads);
4642  if (!removesubpads)
4643  continue;
4644  if (fxActivePad == subpad)
4645  fxActivePad = 0;
4646 
4647  delete subslot;
4648 
4649  pad->GetListOfPrimitives()->Remove(subpad);
4650 
4652 
4653  if (GetCanvas()->GetSelectedPad() == subpad)
4654  GetCanvas()->SetSelectedPad(0);
4655 
4656  delete subpad;
4657  }
4658 
4660 }
4661 
4663 {
4664  TGo4LockGuard lock;
4665 
4666  if (pad == 0) return;
4667 
4668  {
4669  TPadGuard lock; // workaround to avoid canvas update
4670  gStyle->SetOptStat(go4sett->getOptStat());
4671  }
4672 
4673  if (go4sett->getOptStatW()>0) gStyle->SetStatW(go4sett->getOptStatW()*0.01);
4674  if (go4sett->getOptStatH()>0) gStyle->SetStatH(go4sett->getOptStatH()*0.01);
4675 
4677  bool show_status = go4sett->getPadEventStatus();
4678 
4679  int fiPadcolorR, fiPadcolorG, fiPadcolorB;
4680  go4sett->getCanvasColor(fiPadcolorR, fiPadcolorG, fiPadcolorB);
4681  int padfillcolor = TColor::GetColor(fiPadcolorR, fiPadcolorG, fiPadcolorB);
4682 
4683  if (padfillcolor != 0) {
4684  // now define associated colors for WBOX shading
4685  // note: root restricts this mechanism to number<50
4686  // we extend it since TGX11ttf expects the shadow color
4687  // the following are copies from TColor code:
4688  Int_t nplanes = 16;
4689  if (gVirtualX)
4690  gVirtualX->GetPlanes(nplanes);
4691  if (nplanes == 0)
4692  nplanes = 16;
4693  TColor *normal = gROOT->GetColor(padfillcolor);
4694  if (normal != 0) {
4695  Float_t h, l, s;
4696  normal->GetHLS(h, l, s);
4697  const char* cname = normal->GetName();
4698  // assign the color numbers and names for shading:
4699  Float_t dr, dg, db, lr, lg, lb;
4700  TColor *dark = gROOT->GetColor(100 + padfillcolor);
4701  if (dark == 0) {
4702  new TColor(100 + padfillcolor, -1, -1, -1,
4703  Form("%s%s", cname, "_dark"));
4704  dark = gROOT->GetColor(100 + padfillcolor);
4705  }
4706  TColor *light = gROOT->GetColor(150 + padfillcolor);
4707  if (light == 0) {
4708  new TColor(150 + padfillcolor, -1, -1, -1,
4709  Form("%s%s", cname, "_bright"));
4710  light = gROOT->GetColor(150 + padfillcolor);
4711  }
4712 
4713  // set dark color
4714  TColor::HLStoRGB(h, 0.7 * l, s, dr, dg, db);
4715  if (dark != 0) {
4716  if (nplanes > 8)
4717  dark->SetRGB(dr, dg, db);
4718  else
4719  dark->SetRGB(0.3, 0.3, 0.3);
4720  }
4721 
4722  // set light color
4723  TColor::HLStoRGB(h, 1.2 * l, s, lr, lg, lb);
4724  if (light != 0) {
4725  if (nplanes > 8)
4726  light->SetRGB(lr, lg, lb);
4727  else
4728  light->SetRGB(0.8, 0.8, 0.8);
4729  }
4730  } else { // if(normal)
4731  TGo4Log::Error("Internal problem in view panel: Could not assign root shadow colors for number %d", padfillcolor);
4732  }
4733  }
4734 
4735  pad->SetCrosshair(fbCanvasCrosshair);
4736  pad->SetFillColor(padfillcolor);
4737 
4738 #ifdef __GO4X11__
4739  if (fxQCanvas)
4740  if (show_status != fxQCanvas->isStatusBarVisible())
4741  ShowEventStatus();
4742 #endif
4743 
4744  TGo4Picture* padopt = GetPadOptions(pad);
4745  if (padopt != 0) {
4747  padopt->SetDrawOption(0, 0);
4748  padopt->SetTitleTime(go4sett->getDrawTimeFlag());
4749  padopt->SetTitleDate(go4sett->getDrawDateFlag());
4750  padopt->SetTitleItem(go4sett->getDrawItemFlag());
4752  }
4753 }
4754 
4756 {
4757  if (pad == 0)
4758  return;
4759  TString output = pad->GetName();
4760  output.Append(": ");
4761  TGo4Picture* padopt = GetPadOptions(pad);
4762  if (padopt != 0)
4763  if (padopt->IsSuperimpose())
4764  output.Append(" SuperImpose:");
4765 
4766  if (IsApplyToAllFlag())
4767  output.Append(" All Pads:");
4768  output.Append(" Ready");
4769 
4770  if (fxQCanvas) {
4771 #ifdef __GO4X11__
4772  fxQCanvas->showStatusMessage(output.Data());
4773 #endif
4774  } else if (fxWCanvas) {
4775  printf("Implement display pad status in web canvas\n");
4776  }
4777 }
4778 
4779 void TGo4ViewPanel::MoveScale(int expandfactor, int xaction, int yaction, int zaction)
4780 {
4781  TPad* selpad = IsApplyToAllFlag() ? GetCanvas() : GetActivePad();
4782  if (selpad == 0)
4783  return;
4784 
4785  TGo4Picture* padopt = GetPadOptions(selpad);
4786  if (padopt) {
4787  TObject* padhist = GetPadMainObject(selpad);
4788 
4789  MoveSingleScale(expandfactor, xaction, 0, padopt, padhist);
4790  MoveSingleScale(expandfactor, yaction, 1, padopt, padhist);
4791  MoveSingleScale(expandfactor, zaction, 2, padopt, padhist);
4792  if ((xaction == 0) && (yaction == 0) && (zaction == 0)) {
4793  padopt->ClearRange();
4794  padopt->SetAutoScale(true);
4795  }
4796  padopt->SetPadModified();
4797  }
4798 
4799  if (IsApplyToAllFlag()) {
4800  TGo4Iter iter(GetPadSlot(selpad), kTRUE);
4801  while (iter.next()) {
4802  TPad* subpad = GetSlotPad(iter.getslot());
4803  padopt = GetPadOptions(subpad);
4804  if (padopt == 0) continue;
4805 
4806  TObject* padhist = GetPadMainObject(subpad);
4807 
4808  MoveSingleScale(expandfactor, xaction, 0, padopt, padhist);
4809  MoveSingleScale(expandfactor, yaction, 1, padopt, padhist);
4810  MoveSingleScale(expandfactor, zaction, 2, padopt, padhist);
4811  if ((xaction == 0) && (yaction == 0) && (zaction == 0)) {
4812  padopt->ClearRange();
4813  padopt->SetAutoScale(true);
4814  }
4815  padopt->SetPadModified();
4816  }
4817  }
4818 
4819  RedrawPanel(selpad, false);
4820 }
4821 
4822 void TGo4ViewPanel::MoveSingleScale(int expandfactor, int action, int naxis,
4823  TGo4Picture* padopt, TObject* padobj)
4824 {
4825  if (action <= 0) return;
4826 
4827  double new_umin, new_umax, fmin, fmax, tmin, tmax;
4828  double fact = expandfactor / 100.;
4829 
4830  bool sel = padopt->GetRange(naxis, new_umin, new_umax) && (action!=6);
4831 
4832  padopt->GetFullRange(naxis, fmin, fmax);
4833 
4834  // we use number of dimensions to determine if we have contents
4835  int ndim = padopt->GetFullRangeDim();
4836 
4837  if (!sel || (new_umin >= new_umax)) { new_umin = fmin; new_umax = fmax; }
4838 
4839  double shift = (new_umax - new_umin) * fact;
4840  // protect if changes is out of full axis ranges
4841  if (shift <= 0) return;
4842 
4843  switch (action) {
4844  case 1:
4845  if ((new_umax + shift) > fmax) // SlotShiftL
4846  shift = fmax - new_umax;
4847  new_umin += shift;
4848  new_umax += shift;
4849  break;
4850  case 2:
4851  if (new_umin - shift < fmin) // SlotShiftR
4852  shift = new_umin - fmin;
4853  new_umin -= shift;
4854  new_umax -= shift;
4855  break;
4856  case 3:
4857  if (ndim == 1) {
4858  new_umax -= shift; // Expand 1d upper
4859  if (naxis < 1) // lower only for X
4860  new_umin += shift; // Expand 1d lower X
4861  }
4862  if (ndim == 2) {
4863  new_umax -= shift; // Expand 2d upper
4864  if (naxis < 2) // lower only for X,Y
4865  new_umin += shift; // Expand 1d lower X,Y
4866  }
4867  break;
4868  case 4:
4869  if (ndim == 1) { // Shrink 1d upper
4870  if (naxis < 1) { // X axis
4871  tmax = (-fact * new_umin + (1. - fact) * new_umax)
4872  / (1. - 2. * fact);
4873  tmin = (-fact * new_umax + (1. - fact) * new_umin)
4874  / (1. - 2. * fact); // Shrink 1d X
4875  } else { // content, lower has not been expanded
4876  tmax = (-fact * new_umin + new_umax) / (1. - fact);
4877  tmin = (-fact * new_umax + (1. - fact) * new_umin)
4878  / (1. - 2. * fact); // Shrink 1d X
4879  }
4880  }
4881  if (ndim == 2) {
4882  if (naxis < 2) { // X,Y axis
4883  tmax = (-fact * new_umin + (1. - fact) * new_umax)
4884  / (1. - 2. * fact);
4885  tmin = (-fact * new_umax + (1. - fact) * new_umin)
4886  / (1. - 2. * fact); // Shrink 1d X
4887  } else { // content, lower has not been expanded
4888  tmax = (-fact * new_umin + new_umax) / (1. - fact);
4889  tmin = (-fact * new_umax + (1. - fact) * new_umin)
4890  / (1. - 2. * fact); // Shrink 1d X
4891  }
4892  }
4893  new_umin = tmin;
4894  new_umax = tmax;
4895  if (new_umin < fmin)
4896  new_umin = fmin;
4897  if (new_umax > fmax)
4898  new_umax = fmax;
4899  break;
4900 
4901  case 5: // Auto-zoom
4902  case 6: { // Auto zoom, but ignore selected range
4903  TH1* padhist = dynamic_cast<TH1*>(padobj);
4904 
4905  if (padhist==0) break;
4906 
4907  if (naxis >= ndim) break;
4908 
4909  TAxis* axis = padhist->GetXaxis();
4910  if (naxis==1) axis = padhist->GetYaxis();
4911  if (naxis==2) axis = padhist->GetZaxis();
4912 
4913  // keep selected bins
4914  Int_t sel_l = sel ? axis->GetFirst() : 0;
4915  Int_t sel_r = sel ? axis->GetLast() : axis->GetNbins();
4916 
4917  Int_t firstbin(0), lastbin(0);
4918 
4919  // X axis in case of 1-dim histogram
4920  if ((ndim==1) && (naxis==0)) {
4921  for (Int_t n1 = 1; n1<=padhist->GetNbinsX(); n1++) {
4922  Double_t v = padhist->GetBinContent(n1);
4923  if (TMath::Abs(v)<1e-10) continue;
4924  if ((n1<sel_l) || (n1>sel_r)) continue;
4925  lastbin = n1;
4926  if (firstbin==0) firstbin = n1;
4927  }
4928  }
4929 
4930  // X,Y axis in case of 2-dim histogram
4931  if ((ndim==2) && (naxis<2))
4932  for (Int_t n1 = 1; n1<=padhist->GetNbinsX(); n1++)
4933  for (Int_t n2 = 1; n2<=padhist->GetNbinsY(); n2++) {
4934  Double_t v = padhist->GetBinContent(n1,n2);
4935  if (TMath::Abs(v)<1e-10) continue;
4936  Int_t bin = naxis==0 ? n1 : n2;
4937  if ((bin<sel_l) || (bin>sel_r)) continue;
4938  if ((lastbin==0) || (bin>lastbin)) lastbin = bin;
4939  if ((firstbin==0) || (bin<firstbin)) firstbin = bin;
4940  }
4941 
4942  // X,Y,Z axis in case of 3-dim histogram
4943  if ((ndim==3) && (naxis<3))
4944  for (Int_t n1 = 1; n1<=padhist->GetNbinsX(); n1++)
4945  for (Int_t n2 = 1; n2<=padhist->GetNbinsY(); n2++)
4946  for (Int_t n3 = 1; n3<=padhist->GetNbinsZ(); n3++) {
4947  Double_t v = padhist->GetBinContent(n1,n2,n3);
4948  if (TMath::Abs(v)<1e-10) continue;
4949  Int_t bin = naxis==0 ? n1 : ((naxis==1) ? n2 : n3);
4950  if ((bin<sel_l) || (bin>sel_r)) continue;
4951  if ((lastbin==0) || (bin>lastbin)) lastbin = bin;
4952  if ((firstbin==0) || (bin<firstbin)) firstbin = bin;
4953  }
4954 
4955  if (firstbin>0) {
4956 
4957  if (firstbin >= lastbin) { firstbin--; lastbin++; }
4958 
4959  if (firstbin<=3) firstbin = 1;
4960  if (lastbin >=axis->GetNbins()-3) lastbin = axis->GetNbins();
4961 
4962  Double_t left = axis->GetBinLowEdge(firstbin);
4963  Double_t right = axis->GetBinUpEdge(lastbin);
4964 
4965  Double_t margin = (right - left) * fact;
4966  left -= margin; right += margin;
4967 
4968  if ((left <= new_umin) && (right >= new_umax)) return;
4969 
4970  if (left > new_umin) new_umin = left;
4971  if (right < new_umax) new_umax = right;
4972 
4973  if (action==6) axis->SetRange(firstbin,lastbin);
4974  }
4975 
4976  break;
4977  }
4978 
4979  default:
4980  return;
4981  }
4982 
4983  TakeSelectedAxisRange(naxis, padopt, new_umin, new_umax, false);
4984 
4985  if (naxis == ndim)
4986  if (padopt->GetRange(naxis, new_umin, new_umax))
4987  padopt->SetAutoScale(kFALSE);
4988 }
4989 
4990 void TGo4ViewPanel::TakeFullRangeFromHisto(TH1* h1, TGo4Picture* padopt, bool isfirsthisto)
4991 {
4992  if ((h1 == 0) || (padopt == 0)) return;
4993 
4994  TAxis* xax = h1->GetXaxis();
4995  TAxis* yax = h1->GetYaxis();
4996  TAxis* zax = h1->GetZaxis();
4997  int ndim = h1->GetDimension();
4998 
4999  if (isfirsthisto) {
5000  padopt->SetFullRangeDim(ndim);
5001  padopt->SetFullRange(0, xax->GetBinLowEdge(1),
5002  xax->GetBinUpEdge(xax->GetNbins()));
5003  if (ndim > 1)
5004  padopt->SetFullRange(1, yax->GetBinLowEdge(1),
5005  yax->GetBinUpEdge(yax->GetNbins()));
5006  else
5007  padopt->ClearFullRange(2);
5008 
5009  if (ndim > 2)
5010  padopt->SetFullRange(2, zax->GetBinLowEdge(1),
5011  zax->GetBinUpEdge(zax->GetNbins()));
5012  } else
5013  ndim = padopt->GetFullRangeDim();
5014 
5015  if (ndim >= 3)
5016  return;
5017 
5018  Int_t dimindx = (ndim == 1) ? 1 : 2;
5019 
5020  Double_t minimum = 0, maximum = 0;
5021  Bool_t first = kTRUE;
5022  if (!isfirsthisto) {
5023  padopt->GetFullRange(dimindx, minimum, maximum);
5024  first = kFALSE;
5025  }
5026 
5027  for (Int_t biny = 1; biny <= yax->GetNbins(); biny++)
5028  for (Int_t binx = 1; binx <= xax->GetNbins(); binx++) {
5029  Int_t bin = h1->GetBin(binx, biny);
5030  Double_t value = h1->GetBinContent(bin);
5031  if (first) {
5032  minimum = value;
5033  maximum = value;
5034  first = kFALSE;
5035  }
5036  if (value < minimum)
5037  minimum = value;
5038  else if (value > maximum)
5039  maximum = value;
5040  }
5041 
5042  padopt->SetFullRange(dimindx, minimum, maximum);
5043 }
5044 
5045 void TGo4ViewPanel::TakeFullRangeFromGraph(TGraph * gr, TGo4Picture * padopt, bool isfirst)
5046 {
5047  if ((gr == 0) || (padopt == 0)) return;
5048 
5049  Double_t minx(0), maxx(0), miny(0), maxy(0), xx, yy;
5050  if (isfirst) {
5051  if (gr->GetN() > 0) {
5052  gr->GetPoint(0, minx, miny);
5053  maxx = minx;
5054  maxy = miny;
5055  }
5056  } else {
5057  padopt->GetFullRange(0, minx, maxx);
5058  padopt->GetFullRange(1, miny, maxy);
5059  }
5060 
5061  for (Int_t n = 0; n < gr->GetN(); n++) {
5062  gr->GetPoint(n, xx, yy);
5063  if (xx < minx)
5064  minx = xx;
5065  else if (xx > maxx)
5066  maxx = xx;
5067  if (yy < miny)
5068  miny = yy;
5069  else if (yy > maxy)
5070  maxy = yy;
5071  }
5072 
5073  padopt->SetFullRangeDim(1);
5074  padopt->SetFullRange(0, minx, maxx);
5075  padopt->SetFullRange(1, miny, maxy);
5076  padopt->ClearFullRange(2);
5077 }
5078 
5079 void TGo4ViewPanel::SetSelectedRangeToHisto(TPad* pad, TH1* h1, THStack* hs,
5080  TGo4Picture* padopt, bool isthishisto)
5081 {
5082  // set selected range, stats and title position for histogram
5083 
5084  if ((h1 == 0) || (padopt == 0) || (pad == 0)) return;
5085 
5086  int ndim = padopt->GetFullRangeDim();
5087 
5088  bool autoscale = padopt->IsAutoScale();
5089 
5090  double hmin(0.), hmax(0.), umin, umax;
5091 
5092  TAxis* ax = h1->GetXaxis();
5093 
5094  if (IsAutoZoomFlag() && isthishisto) {
5095  MoveSingleScale(1., 6, 0, padopt, h1);
5096  if (ndim>1) MoveSingleScale(1., 6, 1, padopt, h1);
5097  if (ndim>2) MoveSingleScale(1., 6, 2, padopt, h1);
5098  } else if (padopt->GetRange(0, umin, umax)) {
5099  // note: go4 range was full visible range of histogram
5100  // in new ROOT automatic shift of ranges can appear,
5101  // to prevent this, center of each bin should be used
5102 
5103  Int_t i1 = ax->FindFixBin(umin);
5104  Int_t i2 = ax->FindFixBin(umax);
5105  if (i1<i2) ax->SetRange(i1,i2);
5106  else { ax->UnZoom(); padopt->ClearRange(0); }
5107  } else {
5108  ax->UnZoom();
5109  }
5110 
5111  TAxis* ay = h1->GetYaxis();
5112 
5113  if (padopt->GetRange(1, umin, umax)) {
5114  if (!autoscale && (ndim == 1)) {
5115  hmin = umin;
5116  hmax = umax;
5117  ay = 0;
5118  }
5119 
5120  // note: go4 range was full visible range of histogram
5121  // in new ROOT automatic shift of ranges can appear,
5122  // to prevent this, center of each bin should be used
5123 
5124  if (ndim>1) {
5125  Int_t i1 = ay->FindFixBin(umin);
5126  Int_t i2 = ay->FindFixBin(umax);
5127  if (i1<i2) { ay->SetRange(i1,i2); ay = 0; }
5128  }
5129  }
5130 
5131  if (ay!=0) {
5132  ay->UnZoom();
5133  padopt->ClearRange(1);
5134  // workaround for the 5.34/11 version
5135  if ((ndim==1) && (h1->GetMinimum()==0) && (h1->GetMaximum()==1)) {
5136  h1->SetMinimum();
5137  h1->SetMaximum();
5138  }
5139  }
5140 
5141  TAxis* az = h1->GetZaxis();
5142 
5143  if (padopt->GetRange(2, umin, umax) && (ndim > 1)) {
5144  if (!autoscale && (ndim == 2)) {
5145  hmin = umin;
5146  hmax = umax;
5147  az = 0;
5148  }
5149  // note: go4 range was full visible range of histogram
5150  // in new ROOT automatic shift of ranges can appear,
5151  // to prevent this, center of each bin should be used
5152 
5153  if (ndim>2) {
5154  Int_t i1 = az->FindFixBin(umin);
5155  Int_t i2 = az->FindFixBin(umax);
5156  if (i1<i2) { az->SetRange(i1,i2); az = 0; }
5157  }
5158  }
5159 
5160  if (az!=0) {
5161  az->UnZoom();
5162  padopt->ClearRange(2);
5163  }
5164 
5165  if (hmin != hmax) {
5166  // if scale axis is log, prevent negative values, otherwise
5167  // histogram will not be displayed
5168  if (padopt->GetLogScale(ndim)) {
5169  if (hmax <= 0) hmax = 1.;
5170  if ((hmin <= 0) || (hmin >= hmax)) {
5171  hmin = hmax * 1e-4;
5172  if (hmin > 1.) hmin = 1;
5173  }
5174  }
5175 
5176  h1->SetMinimum(hmin);
5177  h1->SetMaximum(hmax);
5178  h1->SetBit(TH1::kIsZoomed);
5179  if (hs != 0) {
5180  hs->SetMinimum(hmin);
5181  hs->SetMaximum(hmax);
5182  }
5183  } else {
5184  // this is autoscale mode
5185 
5186  if (hs != 0) {
5187 
5188  if (ndim == 1) {
5189  TIter next(hs->GetHists());
5190  TH1* hs_h1 = 0;
5191  while ((hs_h1 = (TH1*) next()) != 0) {
5192  if (padopt->GetRange(0, umin, umax)) {
5193  // note: go4 range was full visible range of histogram
5194  // in new ROOT automatic shift of ranges can appear,
5195  // to prevent this, center of each bin should be used
5196  TAxis* ax = hs_h1->GetXaxis();
5197  Int_t i1 = ax->FindFixBin(umin);
5198  Int_t i2 = ax->FindFixBin(umax);
5199  if (i1<i2) { ax->SetRange(i1,i2); }
5200  else { ax->UnZoom(); padopt->ClearRange(0); }
5201  } else {
5202  hs_h1->GetXaxis()->UnZoom();
5203  }
5204 
5205  hs_h1->GetYaxis()->UnZoom();
5206  hs_h1->SetMinimum();
5207  hs_h1->SetMaximum();
5208  }
5209  }
5210 
5211  hs->SetMinimum();
5212  hs->SetMaximum();
5213  }
5214 
5215  h1->SetMinimum();
5216  h1->SetMaximum();
5217  h1->ResetBit(TH1::kIsZoomed);
5218 
5219  // here one can estimate actual range which will be displayed on canvas
5220 
5221  if (ndim < 3) {
5222 
5223  Double_t selmin = h1->GetMinimum();
5224  Double_t selmax = h1->GetMaximum();
5225 
5226  if (selmin >= selmax) {
5227  padopt->ClearRange(ndim);
5228  } else {
5229  bool islogscale = (ndim == 1) && (padopt->GetLogScale(1) > 0);
5230 
5231  if (islogscale) {
5232  if ((selmin > 0) && (selmax > 0)) {
5233  selmin = TMath::Log10(selmin) + TMath::Log10(0.5);
5234  selmin = TMath::Power(10, selmin);
5235  selmax = TMath::Log10(selmax)
5236  + TMath::Log10(2 * (0.9 / 0.95));
5237  selmax = TMath::Power(10, selmax);
5238  }
5239 
5240  } else {
5241  Double_t yMARGIN = gStyle->GetHistTopMargin();
5242  Double_t dymin = yMARGIN * (selmax - selmin);
5243  if ((selmin >= 0) && (selmin - dymin < 0))
5244  selmin = 0;
5245  else
5246  selmin -= dymin;
5247  selmax += yMARGIN * (selmax - selmin);
5248  }
5249 
5250  padopt->SetRange(ndim, selmin, selmax);
5251  }
5252  }
5253  }
5254 
5255  if (padopt->IsHisStats() && isthishisto) {
5256  TPaveStats* stats =
5257  dynamic_cast<TPaveStats*>(h1->GetListOfFunctions()->FindObject("stats"));
5258  if (stats==0) {
5259  stats = new TPaveStats(
5260  gStyle->GetStatX()-gStyle->GetStatW(),
5261  gStyle->GetStatY()-gStyle->GetStatH(),
5262  gStyle->GetStatX(),
5263  gStyle->GetStatY(),"brNDC");
5264  stats->SetParent(h1);
5265  stats->UseCurrentStyle();
5266  stats->SetName("stats");
5267  h1->GetListOfFunctions()->Add(stats);
5268  stats->ConvertNDCtoPad(); // need to bypass TPave init problem
5269  }
5270  padopt->GetStatsAttr(stats);
5271  }
5272 
5273  if (padopt->IsHisTitle() && padopt->HasTitleAttr()) {
5274  TPaveText* titl =
5275  dynamic_cast<TPaveText*>(pad->GetListOfPrimitives()->FindObject("title"));
5276 
5277  if (titl==0) {
5278  titl = new TPaveText(gStyle->GetTitleX()-gStyle->GetTitleW(),
5279  gStyle->GetTitleY()-gStyle->GetTitleH(),
5280  gStyle->GetTitleX(),
5281  gStyle->GetTitleY(),"blNDC");
5282  titl->UseCurrentStyle();
5283  titl->SetFillColor(gStyle->GetTitleFillColor());
5284  titl->SetFillStyle(gStyle->GetTitleStyle());
5285  titl->SetName("title");
5286  titl->SetBorderSize(gStyle->GetTitleBorderSize());
5287  titl->SetTextColor(gStyle->GetTitleTextColor());
5288  titl->SetTextFont(gStyle->GetTitleFont(""));
5289  if (gStyle->GetTitleFont("")%10 > 2)
5290  titl->SetTextSize(gStyle->GetTitleFontSize());
5291  titl->AddText(h1->GetTitle());
5292  titl->SetBit(kCanDelete);
5293  pad->GetListOfPrimitives()->Add(titl);
5294  titl->ConvertNDCtoPad(); // need to bypass TPave init problem
5295  }
5296  padopt->GetTitleAttr(titl);
5297  }
5298 
5299  // add here setting the time format properties:
5300  TAxis* xax = h1->GetXaxis();
5301  xax->SetTimeDisplay(padopt->IsXAxisTimeDisplay());
5302  xax->SetTimeFormat(padopt->GetXAxisTimeFormat());
5303 
5304  // JAM 2016 finally we evaluate the rectangular axis scale property:
5305  //std::cout<< "SetSelectedRangeToHisto - 1:1 is "<< padopt->IsXYRatioOne()<< std::endl;
5306  if (padopt->IsXYRatioOne()) {
5307  RectangularRatio(pad);
5308  } else {
5309  DefaultPadMargin(pad);
5310  }
5311 }
5312 
5313 bool TGo4ViewPanel::GetVisibleRange(TPad* pad, int naxis, double& min, double& max)
5314 {
5315  TGo4Picture* padopt = GetPadOptions(pad);
5316  if (padopt == 0) return false;
5317 
5318  int NumDim = padopt->GetFullRangeDim();
5319 
5320  if ((naxis < 0) || (naxis > NumDim)) return false;
5321 
5322  bool res = padopt->GetRange(naxis, min, max);
5323  if (!res || (min >= max))
5324  res = padopt->GetFullRange(naxis, min, max);
5325  return res;
5326 }
5327 
5329  double selmin, double selmax, bool force)
5330 {
5331  if ((selmin == -1.) && (selmax == -1.)) return false;
5332 
5333  double min, max, umin, umax;
5334 
5335  bool full = padopt->GetFullRange(naxis, min, max);
5336  bool sel = padopt->GetRange(naxis, umin, umax);
5337 
5338  if (!full || (min >= max) || (selmin >= selmax)) {
5339  padopt->ClearRange(naxis);
5340  return true;
5341  }
5342 
5343  double delta = (max - min) / 100000.;
5344  bool changed = false;
5345 
5346  if (umin < umax) {
5347  if (fabs(umin - selmin) > delta) {
5348  umin = selmin;
5349  changed = true;
5350  }
5351  if (fabs(umax - selmax) > delta) {
5352  umax = selmax;
5353  changed = true;
5354  }
5355  } else {
5356  umin = selmin;
5357  umax = selmax;
5358  changed = true;
5359  }
5360 
5361  if ((selmin < min + delta) && (selmax > max - delta) && !force) {
5362  padopt->ClearRange(naxis);
5363  } else {
5364  padopt->SetRange(naxis, umin, umax);
5365  }
5366 
5367  return changed;
5368 }
5369 
5370 bool TGo4ViewPanel::TakeSelectedAxisRange(int naxis, TGo4Picture* padopt, TAxis* ax)
5371 {
5372  Double_t selmin, selmax;
5373 
5374  // check if something selected on axis
5375  if (((ax->GetFirst() <= 0) && (ax->GetLast() >= ax->GetNbins() - 1))
5376  || (ax->GetFirst() >= ax->GetLast())) {
5377  selmin = -1111;
5378  selmax = -1111;
5379  } else {
5380  selmin = ax->GetBinCenter(ax->GetFirst());
5381  selmax = ax->GetBinCenter(ax->GetLast());
5382  }
5383 
5384  return TakeSelectedAxisRange(naxis, padopt, selmin, selmax, false);
5385 }
5386 
5388 {
5389  TGo4LockGuard lock;
5390 
5391  TGo4Picture* padopt = GetPadOptions(pad);
5392 
5393  if (IsRedrawBlocked() || (pad == 0) || (padopt == 0)) return;
5394 
5395  // check if we have histogram and can take range from it
5396  TH1* h1 = GetPadHistogram(pad);
5397 
5398  if (h1 != 0) {
5399  Int_t ndim = padopt->GetFullRangeDim();
5400 
5401  TakeSelectedAxisRange(0, padopt, h1->GetXaxis());
5402  if (ndim > 1)
5403  TakeSelectedAxisRange(1, padopt, h1->GetYaxis());
5404  if (ndim > 2)
5405  TakeSelectedAxisRange(2, padopt, h1->GetZaxis());
5406  if (ndim < 3) {
5407 
5408  bool iszoomed = h1->TestBit(TH1::kIsZoomed);
5409 
5410  padopt->SetAutoScale(!iszoomed);
5411  //h1->SetMinimum();
5412  //h1->SetMaximum();
5413 
5414  Double_t selmin = h1->GetMinimum();
5415  Double_t selmax = h1->GetMaximum();
5416 
5417  if (iszoomed) {
5418  padopt->SetRange(ndim, selmin, selmax);
5419  } else if (selmin >= selmax) {
5420  padopt->ClearRange(ndim);
5421  } else {
5422 
5423  bool islogscale = (ndim == 1) && (pad->GetLogy() > 0);
5424 
5425  if (islogscale) {
5426  if ((selmin > 0) && (selmax > 0)) {
5427  selmin = TMath::Log10(selmin) + TMath::Log10(0.5);
5428  selmin = TMath::Power(10, selmin);
5429  selmax = TMath::Log10(selmax)
5430  + TMath::Log10(2 * (0.9 / 0.95));
5431  selmax = TMath::Power(10, selmax);
5432  }
5433 
5434  } else {
5435  Double_t yMARGIN = 0.05;
5436 #if ROOT_VERSION_CODE > ROOT_VERSION(5,0,9)
5437  yMARGIN = gStyle->GetHistTopMargin();
5438 #endif
5439  Double_t dymin = yMARGIN * (selmax - selmin);
5440  if ((selmin >= 0) && (selmin - dymin < 0))
5441  selmin = 0;
5442  else
5443  selmin -= dymin;
5444  selmax += yMARGIN * (selmax - selmin);
5445  }
5446 
5447  padopt->SetRange(ndim, selmin, selmax);
5448  }
5449  }
5450 
5451  // inform that options were changed in panel
5453  return;
5454  }
5455 
5456  Double_t rxmin, rxmax, rymin, rymax;
5457  pad->GetRangeAxis(rxmin, rymin, rxmax, rymax);
5458 
5459  if (pad->GetLogx() > 0) {
5460  rxmin = TMath::Power(10., rxmin);
5461  rxmax = TMath::Power(10., rxmax);
5462  }
5463 
5464  if (pad->GetLogy() > 0) {
5465  rymin = TMath::Power(10., rymin);
5466  rymax = TMath::Power(10., rymax);
5467  }
5468 
5469  PadRangeAxisChanged(pad, rxmin, rxmax, rymin, rymax);
5470 }
5471 
5472 void TGo4ViewPanel::PadRangeAxisChanged(TPad* pad, double rxmin, double rxmax,
5473  double rymin, double rymax)
5474 {
5475  TGo4LockGuard lock;
5476 
5477  if (IsRedrawBlocked() || (pad == 0)) return;
5478 
5479  TGo4Picture* padopt = GetPadOptions(pad);
5480  if (padopt == 0) return;
5481 
5482  TakeSelectedAxisRange(0, padopt, rxmin, rxmax, false);
5483  TakeSelectedAxisRange(1, padopt, rymin, rymax, false);
5484 
5486 }
5487 
5488 void TGo4ViewPanel::GetSelectedRange(int& ndim, bool& autoscale, double& xmin,
5489  double& xmax, double& ymin, double& ymax, double& zmin, double& zmax)
5490 {
5491  ndim = 0;
5492  TGo4Picture* padopt = GetPadOptions(GetActivePad());
5493  if (padopt == 0) return;
5494 
5495  ndim = padopt->GetFullRangeDim();
5496  autoscale = padopt->IsAutoScale();
5497 
5498  GetVisibleRange(GetActivePad(), 0, xmin, xmax);
5499  GetVisibleRange(GetActivePad(), 1, ymin, ymax);
5500  GetVisibleRange(GetActivePad(), 2, zmin, zmax);
5501 }
5502 
5504 {
5505  fbApplyToAllFlag = on;
5506 
5507  QCheckBox* box1 = findChild<QCheckBox*>("ApplyToAllCheck");
5508  if (box1 != 0) box1->setChecked(on);
5509 }
5510 
5511 void TGo4ViewPanel::SetAutoScale(bool on, TPad* selpad)
5512 {
5513  TGo4LockGuard lock;
5514 
5515  bool modified = false;
5516  bool applytoall = false;
5517  bool redraw_immediately = (selpad == 0);
5518 
5519  if (selpad == 0) {
5520  applytoall = IsApplyToAllFlag();
5521  selpad = applytoall ? GetCanvas() : GetActivePad();
5522  }
5523  if (selpad == 0)
5524  return;
5525 
5526  TGo4Picture* padopt = GetPadOptions(selpad);
5527  if (padopt != 0) {
5528  if (on != padopt->IsAutoScale())
5529  padopt->SetPadModified();
5530  padopt->SetAutoScale(on);
5531  modified = modified || padopt->IsPadModified();
5532  }
5533 
5534  if (applytoall) {
5535  TGo4Iter iter(GetPadSlot(selpad), kTRUE);
5536  while (iter.next()) {
5537  TPad* subpad = GetSlotPad(iter.getslot());
5538  padopt = GetPadOptions(subpad);
5539  if (padopt == 0)
5540  continue;
5541  if (on != padopt->IsAutoScale())
5542  padopt->SetPadModified();
5543  padopt->SetAutoScale(on);
5544  modified = modified || padopt->IsPadModified();
5545  }
5546  }
5547 
5548  if (modified && redraw_immediately)
5549  RedrawPanel(selpad, false);
5550 }
5551 
5552 void TGo4ViewPanel::SetSelectedRange(double xmin, double xmax, double ymin,
5553  double ymax, double zmin, double zmax)
5554 {
5555  TGo4LockGuard lock;
5556 
5557  TPad* selpad = IsApplyToAllFlag() ? GetCanvas() : GetActivePad();
5558  if (selpad == 0)
5559  return;
5560 
5561  TGo4Picture* padopt = GetPadOptions(selpad);
5562  if (padopt != 0) {
5563  Int_t ndim = padopt->GetFullRangeDim();
5564 
5565  TakeSelectedAxisRange(0, padopt, xmin, xmax, true);
5566  if (ndim > 1)
5567  TakeSelectedAxisRange(1, padopt, ymin, ymax, true);
5568  if (ndim > 2)
5569  TakeSelectedAxisRange(2, padopt, zmin, zmax, true);
5570  if (!padopt->IsAutoScale()) {
5571  if (ndim == 1)
5572  TakeSelectedAxisRange(1, padopt, ymin, ymax, true);
5573  if (ndim == 2)
5574  TakeSelectedAxisRange(2, padopt, zmin, zmax, true);
5575  }
5576  padopt->SetPadModified();
5577  }
5578 
5579  if (IsApplyToAllFlag()) {
5580  TGo4Iter iter(GetPadSlot(selpad), kTRUE);
5581  while (iter.next()) {
5582  TPad* subpad = GetSlotPad(iter.getslot());
5583  padopt = GetPadOptions(subpad);
5584  if (padopt == 0)
5585  continue;
5586  Int_t ndim = padopt->GetFullRangeDim();
5587  TakeSelectedAxisRange(0, padopt, xmin, xmax, true);
5588  if (ndim > 1)
5589  TakeSelectedAxisRange(1, padopt, ymin, ymax, true);
5590  if (ndim > 2)
5591  TakeSelectedAxisRange(2, padopt, zmin, zmax, true);
5592  if (!padopt->IsAutoScale()) {
5593  if (ndim == 1)
5594  TakeSelectedAxisRange(1, padopt, ymin, ymax, true);
5595  if (ndim == 2)
5596  TakeSelectedAxisRange(2, padopt, zmin, zmax, true);
5597  }
5598 
5599  padopt->SetPadModified();
5600  }
5601  }
5602 
5603  RedrawPanel(selpad, false);
5604 }
5605 
5606 void TGo4ViewPanel::resizeEvent(QResizeEvent * e)
5607 {
5608 
5609  // store size of top widget -
5610  // size of top widget will be restored when new panel is created
5611  go4sett->storePanelSize(parentWidget(), "ViewPanel");
5612  //std::cout<< "TGo4ViewPanel::resizeEvent"<<std::endl;
5613  TPad* selpad = IsApplyToAllFlag() ? GetCanvas() : GetActivePad();
5614  if (selpad == 0)
5615  return;
5616  // only if we are in 1:1 aspect ratio, we might need a redraw here:
5617  TGo4Slot* slot = GetPadSlot(selpad);
5618  if (slot == 0) return;
5619  TGo4Picture* padopt = GetPadOptions(slot);
5620  if (padopt == 0) return;
5621 
5622  if (padopt->IsXYRatioOne())
5623  {
5624  //std::cout<< "TGo4ViewPanel::resizeEvent with ratio :1"<<std::endl;
5625  // note: we need to delay execution of redraw, since resize Event in QtROOT canvas will
5626  // also happen in timer 100ms after us -> new coordinates are not refreshed here!
5627  fxResizeTimerPad=selpad;
5628  QTimer::singleShot(1000, this, SLOT(checkResizeSlot()));
5629  }
5630 }
5631 
5633 {
5634  //std::cout<< "TGo4ViewPanel::ResizeGedEditor is called with canvas" << (long) fxQCanvas <<std::endl;
5635 #ifdef __GO4X11__
5637 #endif
5638 }
5639 
5641 {
5642  if (obj && !obj->InheritsFrom(THStack::Class()) && !obj->InheritsFrom(TMultiGraph::Class())) {
5643  if (fxQCanvas) {
5644 #ifdef __GO4X11__
5646 #endif
5647  } else if (fxWCanvas) {
5648 #ifdef __GO4WEB__
5650 #endif
5651  }
5652  }
5653 }
5654 
5656 {
5657 #ifdef __GO4X11__
5658  if (fxQCanvas)
5660 #endif
5661 }
5662 
5664 {
5666 }
5667 
5669 {
5670  if (IsRepaintTimerActive()) return;
5671 
5672  if (pad == 0) pad = GetCanvas();
5673 
5674  fxRepaintTimerPad = pad;
5676 }
5677 
5679 {
5680  return fxRepaintTimerPad != 0;
5681 }
5682 
5684 {
5685  TPad* pad = fxRepaintTimerPad;
5686  fxRepaintTimerPad = 0;
5687  if (pad != 0)
5688  RedrawPanel(pad, false);
5689 }
5690 
5692 {
5693  TPad* pad = fxResizeTimerPad;
5694  fxResizeTimerPad = 0;
5695  if (pad != 0)
5696  RedrawPanel(pad, true);
5697 }
5698 
5700 {
5701  TGo4Slot* slot = GetPadSlot(pad);
5702  if (slot != 0)
5703  delete slot;
5704 
5705  GetCanvas()->SetSelectedPad(GetCanvas());
5706  GetCanvas()->SetSelected(GetCanvas());
5708 }
5709 
5710 // marker functions
5711 
5712 int TGo4ViewPanel::GetNumMarkers(TPad* pad, int kind)
5713 {
5714  TGo4Slot* slot = GetPadSlot(pad);
5715  if (slot == 0)
5716  return 0;
5717 
5718  int res = 0;
5719 
5720  for (int n = 0; n < slot->NumChilds(); n++) {
5721  TGo4Slot* subslot = slot->GetChild(n);
5722  if (GetDrawKind(subslot) == kind)
5723  res++;
5724  }
5725  return res;
5726 }
5727 
5728 void TGo4ViewPanel::AddMarkerObj(TPad* pad, int kind, TObject* obj)
5729 {
5730  TGo4Slot* padslot = GetPadSlot(pad);
5731  if (padslot == 0) {
5732  delete obj;
5733  return;
5734  }
5735 
5736  QString basename;
5737  switch (kind) {
5738  case kind_Marker:
5739  basename = "Marker";
5740  break;
5741  case kind_Window:
5742  basename = "Window";
5743  break;
5744  case kind_Poly:
5745  basename = "Polygon";
5746  break;
5747  case kind_Latex:
5748  basename = "Latex";
5749  break;
5750  case kind_Arrow:
5751  basename = "Arrow";
5752  break;
5753  default:
5754  basename = "Something";
5755  break;
5756  }
5757 
5758  QString slotname;
5759  int cnt = 0;
5760  do {
5761  slotname = basename + QString::number(cnt++);
5762  } while (padslot->FindChild(slotname.toLatin1().constData()) != 0);
5763 
5764  TGo4Slot* objslot = AddDrawObject(pad, kind, slotname.toLatin1().constData(), obj, true, 0);
5765 
5766  SetActiveObj(pad, kind, objslot);
5767 }
5768 
5769 void TGo4ViewPanel::SetActiveObj(TPad* pad, int kind, TGo4Slot* activeslot)
5770 {
5771  TGo4Slot* slot = GetPadSlot(pad);
5772  if (slot == 0)
5773  return;
5774 
5775  for (int n = 0; n < slot->NumChilds(); n++) {
5776  TGo4Slot* subslot = slot->GetChild(n);
5777  int drawkind = GetDrawKind(subslot);
5778  if (drawkind != kind)
5779  continue;
5780 
5781  if (subslot != activeslot)
5782  subslot->RemovePar("::ActiveMarker");
5783  else
5784  subslot->SetPar("::ActiveMarker", "1");
5785  }
5786 }
5787 
5788 TObject* TGo4ViewPanel::GetActiveObj(TPad* pad, int kind)
5789 {
5790  int selkind;
5791  TObject* selobj;
5792  TGo4Slot* selslot = GetSelectedSlot(pad, &selkind, &selobj);
5793  if ((kind == selkind) && (selobj != 0))
5794  return selobj;
5795 
5796  TGo4Slot* slot = GetPadSlot(pad);
5797  if (slot == 0)
5798  return 0;
5799 
5800  TObject* lastobj = 0;
5801 
5802  for (int n = 0; n < slot->NumChilds(); n++) {
5803  TGo4Slot* subslot = slot->GetChild(n);
5804  int drawkind = GetDrawKind(subslot);
5805  if (drawkind != kind)
5806  continue;
5807 
5808  lastobj = subslot->GetAssignedObject();
5809  if (subslot->GetPar("::ActiveMarker") != 0)
5810  return lastobj;
5811  }
5812 
5813  return lastobj;
5814 }
5815 
5816 QString TGo4ViewPanel::GetActiveObjName(TPad* pad, int kind)
5817 {
5818  TObject* obj = GetActiveObj(pad, kind);
5819  return (obj == 0) ? QString("null") : QString(obj->GetName());
5820 }
5821 
5823 {
5824  TGo4LockGuard lock;
5825  switch (id) {
5826  case CrosshairId: {
5828  GetCanvas()->SetCrosshair(fbCanvasCrosshair);
5829 
5830 #if ROOT_VERSION_CODE < ROOT_VERSION(4,0,8)
5831 
5832  TGo4Iter(GetPadSlot(GetCanvas()), true);
5833  while (iter.next()) {
5834  TPad* subpad = GetSlotPad(iter.getslot());
5835  if (subpad!=0) {
5836  subpad->SetCrosshair(fbCanvasCrosshair);
5837  subpad->Modified();
5838  }
5839  }
5840 #endif
5841 
5842  CanvasUpdate(true);
5844  break;
5845  }
5846 
5847  case FreezeTitleId: {
5849  break;
5850  }
5851 
5852  case AutoZoomId: {
5854  if (fbAutoZoomFlag) RedrawPanel(GetCanvas(), true);
5855  break;
5856  }
5857 
5858  case SetTitleTextId: {
5859  bool ok = false;
5860  QString mycaption = windowTitle();
5861  QString oldtitle = mycaption.remove(fPanelName + ": ");
5862  QString text = QInputDialog::getText(this, GetPanelName(),
5863  "Enter Viewpanel Title:", QLineEdit::Normal, oldtitle, &ok);
5864  if (ok && !text.isEmpty())
5865  SetFreezedTitle(text);
5866  break;
5867  }
5868 
5869  case SetTimeFormatId: {
5870  bool ok = false;
5871  TPad* pad = GetActivePad();
5872  if (pad == 0) pad = GetCanvas();
5873  TGo4Picture *padopt = GetPadOptions(pad);
5874  QString oldfmt = padopt->GetXAxisTimeFormat();
5875  QString text = QInputDialog::getText(this, GetPanelName(),
5876  "Enter Axis time format:", QLineEdit::Normal, oldfmt, &ok);
5877  if (ok && !text.isEmpty()) {
5878  //std::cout <<"changed time format to"<<(const char*)text.toLatin1() << std::endl;
5879  //padopt->SetXAxisTimeFormat(text.toLatin1());
5880  //padopt->SetPadModified();
5881  ChangeDrawOption(id - 1000, 0, text.toLatin1());
5882  }
5883  break;
5884  }
5885 
5886  default:
5887  if (id > 1000) {
5888  QAction* act = SetIdAction(fOptionsMap, id);
5889  bool s = act ? act->isChecked() : false;
5890  ChangeDrawOption(id - 1000, s, 0);
5891  }
5892  break;
5893  }
5894 }
5895 
5897 {
5898 // if (IsRedrawBlocked()) return;
5899 
5900  fbApplyToAllFlag = on;
5901 }
5902 
5904 {
5905  if (IsRedrawBlocked())
5906  return;
5907 
5908  SetAutoScale(on, 0);
5909 }
5910 
5911 void TGo4ViewPanel::panelSlot(TGo4ViewPanel * panel, TPad * pad, int signalid)
5912 {
5913  if (panel != this)
5914  return;
5915 
5916  BlockPanelRedraw(true);
5917 
5918  TGo4Picture* padopt = GetPadOptions(GetActivePad());
5919  if (padopt != 0)
5920  fAutoScaleCheck->setChecked(padopt->IsAutoScale());
5921 
5922  BlockPanelRedraw(false);
5923 }
5924 
5926 {
5927  if (IsRedrawBlocked())
5928  return;
5929 
5930  ChangeDrawOption(11, on, "");
5931 }
virtual void SetMouseMode(int mode)
virtual void ShootRepaintTimer()
virtual Bool_t IsXRMSDraw()
void CanvasUpdate(bool modify=false)
bool fbCanvasCrosshair
virtual TObject * GetDrawObject(TPad *pad, const char *name)
virtual void CheckActionAtTheEnd(TPad *pad)
TPad * fxActivePad
virtual bool IsPadHasSubPads(TGo4Slot *padslot)
void showStatusMessage(const char *msg)
virtual void SwitchMarkerButton(int kind, bool on)
virtual void linkedRemoved(TGo4Slot *slot, TObject *obj)
virtual void ResetWidget()
virtual void RectangularRatio(TPad *pad)
virtual void PrintCanvas()
void SetRange(Int_t naxis, Double_t min, Double_t max)
void SetTitleTime(Bool_t on=kTRUE)
virtual Double_t GetYLow()
Definition: TGo4WinCond.h:59
void Modified(Bool_t=1)
virtual void linkedUpdated(TGo4Slot *slot, TObject *obj)
bool IsContentModified() const
Bool_t GetIntPar(const char *name, Int_t &value)
Definition: TGo4Slot.cxx:642
Int_t GetDivX()
Definition: TGo4Picture.h:54
virtual void SetPadDefaults(TPad *pad)
QString getTGraphDrawOpt()
bool isStatusBarVisible()
virtual void TakeFullRangeFromHisto(TH1 *h1, TGo4Picture *padopt, bool isfirsthisto)
void setPrinterSett(const QString &name, const QString &cmd)
const char * GetXAxisTimeFormat()
virtual const char * GetName() const
Definition: TGo4Marker.h:103
virtual TGo4Slot * GetSuperimposeSlot(TGo4Slot *slot)
virtual void ApplyToAllToggled(bool)
Int_t GetNumObjNames()
QSignalMapper * fOptionsMap
virtual void RedrawImage(TPad *pad, TGo4Picture *padopt, TGo4ASImage *im, TH2 *asihisto, bool scancontent)
bool isStatusBarVisible()
Definition: QWebCanvas.cpp:238
void SetAutoZoom(bool on)
bool UpdateItemInAnalysis(const char *itemname, TObject *obj=0)
Definition: QGo4Widget.cpp:386
void SetIntPar(const char *name, Int_t value)
Definition: TGo4Slot.cxx:635
virtual void StartConditionEditor()
virtual const char * GetDrawObjectLinkName(TPad *pad, TObject *obj)
bool getStatBoxVisible()
virtual void SetFreezeMouseMode(bool on)
virtual void MakePictureForPad(TGo4Picture *pic, TPad *pad, bool useitemname)
void AddObjName(const char *name, Option_t *DrawOption=0)
TObject * GetBrowserObject(const char *name, Int_t update=0)
QAction * fxCanvasEventstatusChk
virtual void ActivateInGedEditor(TObject *obj)
virtual void SetDrawKind(TGo4Slot *slot, int kind)
virtual int GetAutoColor(int indx)
virtual void SetYMaxDraw(Bool_t on)
virtual void SetActivePad(TPad *pad)
bool fbModifiedSignalFlag
virtual bool IsRedrawBlocked()
void SetProxy(TGo4Proxy *cont)
Definition: TGo4Slot.cxx:310
virtual bool ProcessPadRedraw(TPad *pad, bool force)
void SetDrawData(TH2 *histo, TGo4ViewPanel *panel, TPad *pad)
Definition: TGo4ASImage.cpp:59