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