source: trunk/MagicSoft/Mars/mbase/MStatusDisplay.cc@ 2773

Last change on this file since 2773 was 2773, checked in by tbretz, 21 years ago
*** empty log message ***
File size: 62.0 KB
Line 
1/* ======================================================================== *\
2!
3! *
4! * This file is part of MARS, the MAGIC Analysis and Reconstruction
5! * Software. It is distributed to you in the hope that it can be a useful
6! * and timesaving tool in analysing Data of imaging Cerenkov telescopes.
7! * It is distributed WITHOUT ANY WARRANTY.
8! *
9! * Permission to use, copy, modify and distribute this software and its
10! * documentation for any purpose is hereby granted without fee,
11! * provided that the above copyright notice appear in all copies and
12! * that both that copyright notice and this permission notice appear
13! * in supporting documentation. It is provided "as is" without express
14! * or implied warranty.
15! *
16!
17!
18! Author(s): Thomas Bretz, 4/2003 <mailto:tbretz@astro-uni-wuerzburg.de>
19!
20! Copyright: MAGIC Software Development, 2003
21!
22!
23\* ======================================================================== */
24
25/////////////////////////////////////////////////////////////////////////////
26//
27// MStatusDisplay
28//
29// This status display can be used (and is used) to display results in
30// a tabbed window. The window can be written to and read from a root file
31// (see Read and Write) or printed as a postscript file (see SaveAsPS).
32//
33// To write gif files of C-Macros use SaveAsGif() or SaveAsC().
34// Direct printing to the default printer (via lpr) can be done by
35// PrintToLpr().
36//
37// It has also to half status lines which can be used to display the status
38// or something going on. Together with the status lines it has a progress
39// bar which can display the progress of a job or loop.
40// Access the progress bar by GetProgressBar()
41//
42// To add a new tab and get a pointer to the newly created TCanvas
43// use AddTab.
44//
45// If you have a MStatusDisplay and you are not sure whether it was
46// destroyed by the user meanwhile use:
47// gROOT->GetListOfSpecials()->FindObject(pointer);
48// Each MStatusDisplay is added to list list by its constructor and
49// removed from the list by the destructor.
50//
51// You can redirect an output to a MLog-logstream by calling SetLogStream().
52// To disable redirction call SetLogStream(NULL)
53//
54// Because updates to the tabs are only done/displayed if a tab is active
55// using the gui doesn't make things slower (<1%) if the first (legend
56// tab) is displayed. This gives you the possibility to look into
57// the current progress of a loop without loosing more time than the
58// single update of the tab.
59//
60/////////////////////////////////////////////////////////////////////////////
61#include "MStatusDisplay.h"
62
63#include <fstream> // fstream
64
65#include <TLine.h> // TLine
66#include <TText.h> // TText
67#include <TFile.h> // gFile
68#include <TFrame.h> // TFrame
69#include <TStyle.h> // gStyle
70#include <TCanvas.h> // TCanvas
71#include <TSystem.h> // gSystem
72#include <TDatime.h> // TDatime
73#include <TRandom.h> // TRandom
74#include <TThread.h> // TThread::Self()
75#include <TBrowser.h> // TBrowser
76#include <TObjArray.h> // TObjArray
77#include <TPostScript.h> // TPostScript
78#include <TMethodCall.h> // TMethodCall
79
80//#include <TRint.h> // gApplication, TRint::Class()
81#include <TInterpreter.h> // gInterpreter
82
83#include <TGTab.h> // TGTab
84#include <TGLabel.h> // TGLabel
85#include <TG3DLine.h> // TGHorizontal3DLine
86#include <TGButton.h> // TGPictureButton
87#include <TGTextView.h> // TGTextView
88#include <TGStatusBar.h> // TGStatusBar
89#include <TGProgressBar.h> // TGHProgressBar
90
91#include <TRootEmbeddedCanvas.h> // TRootEmbeddedCanvas
92
93#include "MLog.h" // MLog
94#include "MLogManip.h" // inf, warn, err
95
96#include "MGList.h" // MGList
97#include "MGMenu.h" // MGMenu, TGMenu
98#include "MSearch.h" // MSearch
99#include "MParContainer.h" // MParContainer::GetDescriptor
100
101#undef DEBUG
102//#define DEBUG
103
104ClassImp(MStatusDisplay);
105
106using namespace std;
107
108// ------------ Workaround for a non working TGTextView::Search -------------
109#if ROOT_VERSION_CODE < ROOT_VERSION(3,02,05)
110class MGTextView : public TGTextView
111{
112public:
113 MGTextView(const TGWindow *parent, UInt_t w, UInt_t h, Int_t id = -1,
114 UInt_t sboptions = 0, ULong_t back = GetWhitePixel()) :
115 TGTextView(parent, w, h, id, sboptions, back) {}
116 MGTextView(const TGWindow *parent, UInt_t w, UInt_t h, TGText *text,
117 Int_t id = -1, UInt_t sboptions = 0, ULong_t back = GetWhitePixel()) :
118 TGTextView(parent, w, h, text, id, sboptions, back) {}
119 MGTextView(const TGWindow *parent, UInt_t w, UInt_t h, const char *string,
120 Int_t id = -1, UInt_t sboptions = 0, ULong_t back = GetWhitePixel()) :
121 TGTextView(parent, w, h, string, id, sboptions, back) {}
122
123 void Mark(Long_t xPos, Long_t yPos) { TGTextView::Mark(xPos, yPos); }
124 void UnMark() { TGTextView::UnMark(); }
125
126 Bool_t Search(const char *string, Bool_t direction, Bool_t caseSensitive)
127 {
128 // Taken from TGTextView::Search and modified.
129
130 TGLongPosition pos, pos2;
131 pos2.fX = pos2.fY = 0;
132 if (fIsMarked) {
133 if (!direction)
134 {
135 pos2.fX = fMarkedStart.fX;
136 pos2.fY = fMarkedStart.fY;
137 }
138 else
139 {
140 pos2.fX = fMarkedEnd.fX + 1;
141 pos2.fY = fMarkedEnd.fY;
142 }
143 }
144 if (!fText->Search(&pos, pos2, string, direction, caseSensitive))
145 return kFALSE;
146 UnMark();
147 fIsMarked = kTRUE;
148 fMarkedStart.fY = fMarkedEnd.fY = pos.fY;
149 fMarkedStart.fX = pos.fX;
150 fMarkedEnd.fX = fMarkedStart.fX + strlen(string);
151 pos.fY = ToObjYCoord(fVisible.fY);
152 if ((fMarkedStart.fY < pos.fY) ||
153 (ToScrYCoord(fMarkedStart.fY) >= (Int_t)fCanvas->GetHeight()))
154 pos.fY = fMarkedStart.fY;
155 pos.fX = ToObjXCoord(fVisible.fX, pos.fY);
156 if ((fMarkedStart.fX < pos.fX) ||
157 (ToScrXCoord(fMarkedStart.fX, pos.fY) >= (Int_t)fCanvas->GetWidth()))
158 pos.fX = fMarkedStart.fX;
159
160 SetVsbPosition((ToScrYCoord(pos.fY) + fVisible.fY)/fScrollVal.fY);
161 SetHsbPosition((ToScrXCoord(pos.fX, pos.fY) + fVisible.fX)/fScrollVal.fX);
162 DrawRegion(0, (Int_t)ToScrYCoord(fMarkedStart.fY), fCanvas->GetWidth(),
163 UInt_t(ToScrYCoord(fMarkedEnd.fY+1) - ToScrYCoord(fMarkedEnd.fY)));
164
165 return kTRUE;
166 }
167};
168#else
169#define MGTextView TGTextView
170#endif
171// --------------------------------------------------------------------------
172
173// --------------------------------------------------------------------------
174//
175// Add menu bar to the GUI
176//
177void MStatusDisplay::AddMenuBar()
178{
179 //
180 // File Menu
181 //
182 MGPopupMenu *filemenu = new MGPopupMenu(gClient->GetRoot());
183 // filemenu->AddEntry("Save &As...", kFileSaveAs);
184 filemenu->AddEntry("New Can&vas", kFileCanvas);
185 filemenu->AddEntry("New &Browser", kFileBrowser);
186 filemenu->AddSeparator();
187 filemenu->AddEntry("Save As status.&ps", kFileSaveAsPS);
188 filemenu->AddEntry("Save As status.&gif", kFileSaveAsGIF);
189 filemenu->AddEntry("Save As status.&C", kFileSaveAsC);
190 filemenu->AddEntry("Save As status.&root", kFileSaveAsRoot);
191 filemenu->AddSeparator();
192 filemenu->AddEntry("Re&set", kFileReset);
193 filemenu->AddSeparator();
194 filemenu->AddEntry("Print with &lpr", kFilePrint);
195 //filemenu->AddEntry("Set printer &name", kFilePrinterName);
196 filemenu->AddSeparator();
197 filemenu->AddEntry("C&lose", kFileClose);
198 filemenu->AddEntry("E&xit", kFileExit);
199 filemenu->Associate(this);
200
201 //
202 // Tab Menu
203 //
204 MGPopupMenu *tabmenu = new MGPopupMenu(gClient->GetRoot());
205 // tabmenu->AddEntry("Save &As...", kFileSaveAs);
206 tabmenu->AddEntry("Next [&+]", kTabNext);
207 tabmenu->AddEntry("Previous [&-]", kTabPrevious);
208 tabmenu->AddSeparator();
209 tabmenu->AddEntry("Save As tab-i.&ps", kTabSaveAsPS);
210 tabmenu->AddEntry("Save As tab-i.&gif", kTabSaveAsGIF);
211 tabmenu->AddEntry("Save As tab-i.&C", kTabSaveAsC);
212 tabmenu->AddEntry("Save As tab-i.&root", kTabSaveAsRoot);
213 tabmenu->AddSeparator();
214 tabmenu->AddEntry("Re&move", kTabRemove);
215 tabmenu->AddSeparator();
216 tabmenu->AddEntry("Print with &lpr", kTabPrint);
217 tabmenu->Associate(this);
218
219 //
220 // Loop Menu
221 //
222 MGPopupMenu *loopmenu = new MGPopupMenu(gClient->GetRoot());
223 loopmenu->AddEntry("&Stop", kLoopStop);
224 loopmenu->Associate(this);
225
226 //
227 // Loop Menu
228 //
229 MGPopupMenu *sizemenu = new MGPopupMenu(gClient->GetRoot());
230 sizemenu->AddEntry("Fit to 640x&480", kSize640);
231 sizemenu->AddEntry("Fit to 800x&600", kSize800);
232 sizemenu->AddEntry("Fit to 960x7&20", kSize960);
233 sizemenu->AddEntry("Fit to 1024x&768", kSize1024);
234 sizemenu->AddEntry("Fit to 1280x&1024", kSize1280);
235 sizemenu->Associate(this);
236
237 //
238 // Log Menu
239 //
240 MGPopupMenu *logmenu = new MGPopupMenu(gClient->GetRoot());
241 logmenu->AddEntry("&Copy Selected", kLogCopy);
242 logmenu->AddEntry("Cl&ear all", kLogClear);
243 logmenu->AddSeparator();
244 logmenu->AddEntry("Select &All", kLogSelect);
245 logmenu->AddSeparator();
246 logmenu->AddEntry("&Find...", kLogFind);
247 logmenu->AddSeparator();
248 logmenu->AddEntry("&Save", kLogSave);
249 logmenu->AddEntry("Save &append", kLogAppend);
250 logmenu->Associate(this);
251
252 //
253 // Menu Bar
254 //
255 TGLayoutHints *layitem = new TGLayoutHints(kLHintsNormal, 0, 4, 0, 0);
256 fList->Add(layitem);
257
258 MGMenuBar *menubar = new MGMenuBar(this, 1, 1, kHorizontalFrame);
259 menubar->AddPopup("&File", filemenu, layitem);
260 menubar->AddPopup("Lo&g", logmenu, layitem);
261 menubar->AddPopup("&Size", sizemenu, layitem);
262 menubar->AddPopup("&Tab", tabmenu, layitem);
263 menubar->AddPopup("&Loop", loopmenu, layitem);
264 menubar->BindKeys(this);
265 AddFrame(menubar);
266
267 //
268 // Line below menu bar
269 //
270 TGLayoutHints *laylinesep = new TGLayoutHints(kLHintsTop|kLHintsExpandX);
271 fList->Add(laylinesep);
272
273 TGHorizontal3DLine *linesep = new TGHorizontal3DLine(this);
274 AddFrame(linesep, laylinesep);
275
276 //
277 // Add everything to autodel list
278 //
279 fList->Add(filemenu);
280 fList->Add(loopmenu);
281 fList->Add(sizemenu);
282 fList->Add(menubar);
283 fList->Add(tabmenu);
284 fList->Add(logmenu);
285 fList->Add(linesep);
286}
287
288// --------------------------------------------------------------------------
289//
290// Adds an empty TGCompositeFrame which might be filled by the user
291//
292void MStatusDisplay::AddUserFrame()
293{
294 TGLayoutHints *lay=new TGLayoutHints(kLHintsExpandX);
295 fList->Add(lay);
296
297 fUserFrame = new TGCompositeFrame(this, 1, 1);
298 AddFrame(fUserFrame, lay);
299 fList->Add(fUserFrame);
300}
301
302// --------------------------------------------------------------------------
303//
304// Add the title tab
305//
306void MStatusDisplay::AddMarsTab()
307{
308 // Create Tab1
309 TGCompositeFrame *f = fTab->AddTab("-=MARS=-");
310
311 // Add MARS version
312 TGLabel *l = new TGLabel(f, Form("Official Release: V%s", MARSVER));
313 fList->Add(l);
314
315 TGLayoutHints *layb = new TGLayoutHints(kLHintsCenterX|kLHintsTop, 10, 10, 5, 5);
316 fList->Add(layb);
317 f->AddFrame(l, layb);
318
319 // Add root version
320 l = new TGLabel(f, Form("Using ROOT v%s", ROOTVER));
321 fList->Add(l);
322
323 TGLayoutHints *lay = new TGLayoutHints(kLHintsCenterX|kLHintsTop);
324 fList->Add(lay);
325 f->AddFrame(l, lay);
326
327 // Add Mars logo picture
328 const TGPicture *pic2 = fList->GetPicture("marslogo.xpm");
329 if (pic2)
330 {
331 TGPictureButton *mars = new TGPictureButton(f, pic2, kPicMars);
332 fList->Add(mars);
333 mars->Associate(this);
334
335 TGLayoutHints *lay2 = new TGLayoutHints(kLHintsCenterX|kLHintsCenterY, 10, 10, 5, 5);
336 fList->Add(lay2);
337 f->AddFrame(mars, lay2);
338 }
339
340 // Add date and time
341 TDatime d;
342 l = new TGLabel(f, d.AsString());
343 fList->Add(l);
344 f->AddFrame(l, lay);
345
346 // Add copyright notice
347 l = new TGLabel(f, "(c) MAGIC Software Development, 2000-2003");
348 fList->Add(l);
349 f->AddFrame(l, layb);
350
351 TGLayoutHints *layc = new TGLayoutHints(kLHintsCenterX|kLHintsTop, 10, 10, 0, 5);
352 fList->Add(layc);
353
354 l = new TGLabel(f, "<< Thomas Bretz >>");
355 fList->Add(l);
356 f->AddFrame(l, layc);
357}
358
359// --------------------------------------------------------------------------
360//
361// Adds the logbook tab to the GUI if it was not added previously.
362//
363// The logbook is updated four times a second only if the tab is visible.
364//
365// You can redirect an output to a MLog-logstream by calling SetLogStream().
366// To disable redirction call SetLogStream(NULL)
367//
368// if enable==kFALSE the stdout is disabled/enabled. Otherwise stdout
369// is ignored.
370//
371void MStatusDisplay::SetLogStream(MLog *log, Bool_t enable)
372{
373 if (gROOT->IsBatch())
374 return;
375
376 if (log && fLogBox==NULL)
377 {
378 fLogIdx = fTab->GetNumberOfTabs();
379
380 // Create Tab1
381 TGCompositeFrame *f = fTab->AddTab("-Logbook-");
382
383 // Create Text View
384 fLogBox = new MGTextView(f, 1, 1); // , -1, 0, TGFrame::GetDefaultFrameBackground());
385 if (fFont)
386 fLogBox->SetFont(fFont);
387 //fLogBox->Associate(this);
388
389 // Add List box to the tab
390 TGLayoutHints *lay = new TGLayoutHints(kLHintsNormal|kLHintsExpandX|kLHintsExpandY,2,2,2,2);
391 f->AddFrame(fLogBox, lay);
392
393 // layout and map tab
394 Layout();
395 MapSubwindows();
396
397 // make it visible
398 // FIXME: This is a workaround, because TApplication::Run is not
399 // thread safe against ProcessEvents. We assume, that if
400 // we are not in the Main-Thread ProcessEvents() is
401 // called by the TApplication Event Loop...
402 if (!TThread::Self()/*gApplication->InheritsFrom(TRint::Class())*/)
403 gClient->ProcessEventsFor(fTab);
404 }
405
406 if (log)
407 {
408 fLog = log;
409
410 log->SetOutputGui(fLogBox, kTRUE);
411 log->EnableOutputDevice(MLog::eGui);
412 if (!enable)
413 log->DisableOutputDevice(MLog::eStdout);
414
415 fLogTimer.Start();
416 }
417 else
418 {
419 fLogTimer.Stop();
420
421 fLog->DisableOutputDevice(MLog::eGui);
422 fLog->SetOutputGui(NULL);
423 if (!enable)
424 fLog->EnableOutputDevice(MLog::eStdout);
425
426 fLog = &gLog;
427 }
428}
429
430// --------------------------------------------------------------------------
431//
432// Add the Tabs and the predifined Tabs to the GUI
433//
434void MStatusDisplay::AddTabs()
435{
436 fTab = new TGTab(this, 300, 300);
437
438 AddMarsTab();
439
440 // Add fTab to Frame
441 TGLayoutHints *laytabs = new TGLayoutHints(kLHintsNormal|kLHintsExpandX|kLHintsExpandY, 5, 5, 5);
442 AddFrame(fTab, laytabs);
443
444 fList->Add(fTab);
445 fList->Add(laytabs);
446}
447
448// --------------------------------------------------------------------------
449//
450// Add the progress bar to the GUI. The Progress Bar range is set to
451// (0,1) as default.
452//
453void MStatusDisplay::AddProgressBar()
454{
455 TGLayoutHints *laybar=new TGLayoutHints(kLHintsExpandX, 5, 5, 5, 5);
456 fList->Add(laybar);
457
458 fBar=new TGHProgressBar(this);
459 fBar->SetRange(0, 1);
460 fBar->ShowPosition();
461 AddFrame(fBar, laybar);
462 fList->Add(fBar);
463}
464
465// --------------------------------------------------------------------------
466//
467// Set the progress bar position between 0 and 1. The Progress bar range
468// is assumed to be (0,1)
469//
470void MStatusDisplay::SetProgressBarPosition(Float_t p)
471{
472 fBar->SetPosition(p);
473}
474
475// --------------------------------------------------------------------------
476//
477// Adds the status bar to the GUI
478//
479void MStatusDisplay::AddStatusBar()
480{
481 fStatusBar = new TGStatusBar(this, 1, 1);
482
483 //
484 // Divide it like the 'Golden Cut' (goldener Schnitt)
485 //
486 // 1-a a
487 // 1: ------|----
488 //
489 // a/(1-a) = (1-a)/1
490 // a^2+a-1 = 0
491 // a = (-1+-sqrt(1+4))/2 = sqrt(5)/2-1/2 = 0.618
492 //
493 Int_t p[2] = {38, 62};
494
495 fStatusBar->SetParts(p, 2);
496
497 TGLayoutHints *layb = new TGLayoutHints(kLHintsNormal|kLHintsExpandX, 5, 4, 0, 3);
498 AddFrame(fStatusBar, layb);
499
500 fList->Add(fStatusBar);
501 fList->Add(layb);
502}
503
504// --------------------------------------------------------------------------
505//
506// Change the text in the status line 1
507//
508void MStatusDisplay::SetStatusLine1(const char *txt)
509{
510 if (gROOT->IsBatch())
511 return;
512 fStatusBar->SetText(txt, 0);
513
514 // FIXME: This is a workaround, because TApplication::Run is not
515 // thread safe against ProcessEvents. We assume, that if
516 // we are not in the Main-Thread ProcessEvents() is
517 // called by the TApplication Event Loop...
518 if (!TThread::Self()/*gApplication->InheritsFrom(TRint::Class())*/)
519 gClient->ProcessEventsFor(fStatusBar);
520}
521
522// --------------------------------------------------------------------------
523//
524// Change the text in the status line 2
525//
526void MStatusDisplay::SetStatusLine2(const char *txt)
527{
528 if (gROOT->IsBatch())
529 return;
530 fStatusBar->SetText(txt, 1);
531
532 // FIXME: This is a workaround, because TApplication::Run is not
533 // thread safe against ProcessEvents. We assume, that if
534 // we are not in the Main-Thread ProcessEvents() is
535 // called by the TApplication Event Loop...
536 if (!TThread::Self()/*gApplication->InheritsFrom(TRint::Class())*/)
537 gClient->ProcessEventsFor(fStatusBar);
538}
539
540// --------------------------------------------------------------------------
541//
542// Display information about the name of a container
543//
544void MStatusDisplay::SetStatusLine2(const MParContainer &cont)
545{
546 SetStatusLine2(Form("%s: %s", cont.GetDescriptor(), cont.GetTitle()));
547}
548
549// --------------------------------------------------------------------------
550//
551// Default constructor. Opens a window with a progress bar. Get a pointer
552// to the bar by calling GetBar. This pointer can be used for the
553// eventloop.
554//
555// Be carefull: killing or closing the window while the progress meter
556// is still in use may cause segmentation faults. Please kill the window
557// always by deleting the corresponding object.
558//
559// Update time default: 10s
560//
561MStatusDisplay::MStatusDisplay(Long_t t)
562: TGMainFrame(NULL, 1, 1), fName("MStatusDisplay"), fLog(&gLog), fTab(NULL), fTimer(this, t, kTRUE), fStatus(kLoopNone), fLogIdx(-1), fLogTimer(this, 250, kTRUE), fLogBox(NULL), fIsLocked(0)
563{
564 // p==NULL means: Take gClient->GetRoot() if not in batch mode
565 // see TGWindow::TGWindow()
566
567 //
568 // This is a possibility for the user to check whether this
569 // object has already been deleted. It will be removed
570 // from the list in the destructor.
571 //
572 gROOT->GetListOfSpecials()->Add(this);
573
574 fFont = gVirtualX->LoadQueryFont("7x13bold");
575 fMutex = new TMutex;
576
577 //
578 // In case we are in batch mode use a list of canvases
579 // instead of the Root Embedded Canvases in the TGTab
580 //
581 fBatch = new TList;
582 fBatch->SetOwner();
583
584 //
585 // Create a list handling GUI widgets
586 //
587 fList = new MGList;
588 fList->SetOwner();
589
590 //
591 // Create the layout hint for the root embedded canavses
592 //
593 fLayCanvas = new TGLayoutHints(kLHintsExpandX|kLHintsExpandY);
594 fList->Add(fLayCanvas);
595
596 //
597 // Add Widgets (from top to bottom)
598 //
599 if (gClient) // BATCH MODE
600 {
601 AddMenuBar();
602 AddUserFrame();
603 AddTabs();
604 AddProgressBar();
605 AddStatusBar();
606 }
607
608 //
609 // set the smallest and biggest size of the Main frame
610 // and move it to its appearance position
611 SetWMSizeHints(570, 480, 1280, 980, 1, 1);
612 MoveResize(rand()%100+570, rand()%100+480, 570, 480);
613
614 //
615 // Now do an automatic layout of the widgets and display the window
616 //
617 Layout();
618 MapSubwindows();
619
620 SetWindowName("Status Display");
621 SetIconName("Status Display");
622
623 MapWindow();
624
625 // FIXME: This is a workaround, because TApplication::Run is not
626 // thread safe against ProcessEvents. We assume, that if
627 // we are not in the Main-Thread ProcessEvents() is
628 // called by the TApplication Event Loop...
629 if (!TThread::Self()/*gApplication->InheritsFrom(TRint::Class())*/)
630 gSystem->ProcessEvents();
631}
632
633// --------------------------------------------------------------------------
634//
635// Destruct the window with all its tiles. Also the Progress Bar object
636// is deleted.
637//
638MStatusDisplay::~MStatusDisplay()
639{
640#if ROOT_VERSION_CODE < ROOT_VERSION(3,10,01)
641 fTab = NULL; // See HandleEvent
642#endif
643
644 //
645 // Delete object from global object table so it cannot
646 // be deleted by chance a second time
647 //
648 gInterpreter->DeleteGlobal(this);
649
650 //
651 // This is a possibility for the user to check whether this
652 // object has already been deleted. It has been added
653 // to the list in the constructor.
654 //
655 gROOT->GetListOfSpecials()->Remove(this);
656
657 SetLogStream(NULL);
658
659 //
660 // Delete the list of objects corresponding to this object
661 //
662 delete fList;
663
664 //
665 // Delete the list list of canvases used in batch mode
666 // instead of the Root Embedded Canvases in the TGTab
667 //
668 delete fBatch;
669
670 //
671 // Delete the font used for the logging window
672 //
673 if (fFont)
674 gVirtualX->DeleteFont(fFont);
675
676 //
677 // Delete mutex
678 //
679 delete fMutex;
680}
681
682// --------------------------------------------------------------------------
683//
684// Takes a TGCompositeFrame as argument. Searches for the first
685// TRootEmbeddedCanvas which is contained by it and returns a pointer
686// to the corresponding TCanvas. If it isn't found NULL is returned.
687//
688TRootEmbeddedCanvas *MStatusDisplay::GetEmbeddedCanvas(TGCompositeFrame *cf) const
689{
690 TIter Next(cf->GetList());
691
692 TGFrameElement *f;
693 while ((f=(TGFrameElement*)Next()))
694 if (f->fFrame->InheritsFrom(TRootEmbeddedCanvas::Class()))
695 return (TRootEmbeddedCanvas*)f->fFrame;
696
697 return NULL;
698}
699
700// --------------------------------------------------------------------------
701//
702// Takes a TGCompositeFrame as argument. Searches for the first
703// TRootEmbeddedCanvas which is contained by it and returns a pointer
704// to the corresponding TCanvas. If it isn't found NULL is returned.
705//
706TCanvas *MStatusDisplay::GetCanvas(TGCompositeFrame *cf) const
707{
708 TRootEmbeddedCanvas *ec = GetEmbeddedCanvas(cf);
709 return ec ? ec->GetCanvas() : NULL;
710}
711
712// --------------------------------------------------------------------------
713//
714// Returns GetCanvas of the i-th Tab.
715//
716TCanvas *MStatusDisplay::GetCanvas(int i) const
717{
718 if (gROOT->IsBatch())
719 return (TCanvas*)fBatch->At(i-1);
720
721 if (i<0 || i>=fTab->GetNumberOfTabs())
722 {
723 *fLog << warn << "MStatusDisplay::GetCanvas: Out of range." << endl;
724 return NULL;
725 }
726
727 return GetCanvas(fTab->GetTabContainer(i));
728}
729
730// --------------------------------------------------------------------------
731//
732// Searches for a TRootEmbeddedCanvas in the TGCompositeFramme of the
733// Tab with the name 'name'. Returns the corresponding TCanvas or
734// NULL if something isn't found.
735//
736TCanvas *MStatusDisplay::GetCanvas(const TString &name) const
737{
738 TGFrameElement *f;
739 TIter Next(fTab->GetList());
740 while ((f=(TGFrameElement*)Next()))
741 {
742 TObject *frame = f->fFrame;
743 if (!frame->InheritsFrom(TGTabElement::Class()))
744 continue;
745
746 TGTabElement *tab = (TGTabElement*)frame;
747 if (tab->GetString()==name)
748 break;
749 }
750
751 // Search for the next TGCompositeFrame in the list
752 while ((f=(TGFrameElement*)Next()))
753 {
754 TObject *frame = f->fFrame;
755 if (frame->InheritsFrom(TGCompositeFrame::Class()))
756 return GetCanvas((TGCompositeFrame*)frame);
757 }
758
759 return NULL;
760}
761
762// --------------------------------------------------------------------------
763//
764// Calls TCanvas::cd(), for the canvas returned by GetCanvas.
765//
766Bool_t MStatusDisplay::CdCanvas(const TString &name)
767{
768 TCanvas *c = GetCanvas(name);
769 if (!c)
770 return kFALSE;
771
772 c->cd();
773 return kTRUE;
774}
775
776TGCompositeFrame *MStatusDisplay::AddRawTab(const char *name)
777{
778 // Add new tab
779 TGCompositeFrame *f = fTab->AddTab(name);
780
781 // layout and map new tab
782 Layout();
783 MapSubwindows();
784 Layout();
785
786 // display new tab in the main frame
787 // FIXME: This is a workaround, because TApplication::Run is not
788 // thread safe against ProcessEvents. We assume, that if
789 // we are not in the Main-Thread ProcessEvents() is
790 // called by the TApplication Event Loop...
791 if (!TThread::Self()/*gApplication->InheritsFrom(TRint::Class())*/)
792 gClient->ProcessEventsFor(fTab);
793
794 *fLog << inf << "Adding Raw Tab '" << name << "' (" << f->GetWidth() << "x";
795 *fLog << f->GetHeight() << ")" << endl;
796
797 // return pointer to new canvas
798 return f;
799}
800
801// --------------------------------------------------------------------------
802//
803// Adds a new tab with the name 'name'. Adds a TRootEmbeddedCanvas to the
804// tab and returns a reference to the corresponding TCanvas.
805//
806TCanvas &MStatusDisplay::AddTab(const char *name)
807{
808 if (gROOT->IsBatch())
809 {
810 TCanvas *c = new TCanvas(name, name);
811 fBatch->Add(c);
812 return *c;
813 }
814
815 // Add new tab
816 TGCompositeFrame *f = fTab->AddTab(name);
817
818 // create root embedded canvas and add it to the tab
819 TRootEmbeddedCanvas *ec = new TRootEmbeddedCanvas(name, f, f->GetWidth(), f->GetHeight(), 0);
820 f->AddFrame(ec, fLayCanvas);
821 fList->Add(ec);
822
823 // set background and border mode of the canvas
824 TCanvas &c = *ec->GetCanvas();
825
826 c.SetFillColor(16/*165*//*17*//*203*/);
827 c.SetBorderMode(0);
828
829 // If kNoContextMenu set set kNoContextMenu of the canvas
830 if (TestBit(kNoContextMenu))
831 c.SetBit(kNoContextMenu);
832
833 // layout and map new tab
834 Layout(); // seems to layout the TGCompositeFrame
835 MapSubwindows(); // maps the TGCompositeFrame
836 Layout(); // layout the embedded canvas in the frame
837
838 // display new tab in the main frame
839 // FIXME: This is a workaround, because TApplication::Run is not
840 // thread safe against ProcessEvents. We assume, that if
841 // we are not in the Main-Thread ProcessEvents() is
842 // called by the TApplication Event Loop...
843 if (!TThread::Self()/*gApplication->InheritsFrom(TRint::Class())*/)
844 gClient->ProcessEventsFor(fTab);
845
846 *fLog << inf << "Adding Tab '" << name << "' (" << f->GetWidth() << "x";
847 *fLog << f->GetHeight() << ", TCanvas=" << &c << ")" << endl;
848
849 // return pointer to new canvas
850 return c;
851}
852
853// --------------------------------------------------------------------------
854//
855// Update a canvas in a tab, takes the corresponding TGCompositeFrame
856// as an argument. This is necessary, because not all functions
857// changing the contents of a canvas or pad can call SetModified()
858// for the corresponding tab. If this is not called correctly the
859// tab won't be updated calling TCanvas::Update(). So we simply
860// redraw it by our own (instead we could recursively call
861// TPad::Modified() for everything contained by the TCanvas and
862// call TCanvas::Update() afterwards)
863//
864void MStatusDisplay::UpdateTab(TGCompositeFrame *f)
865{
866 if (!f)
867 return;
868
869 TCanvas *c=GetCanvas(f);
870 if (!c)
871 return;
872
873 //
874 // If we are in a multithreaded environment (gThreadXAR) we
875 // have to make sure, that thus function is called from
876 // the main thread.
877 //
878 if (gThreadXAR)
879 {
880 // Tell the X-Requester how to call this method
881 TString str = Form("%d", (ULong_t)f);
882
883 TMethodCall call(IsA(), "UpdateTab", "NULL");
884 void *arr[4] = { NULL, &call, this, (void*)(const char*)str };
885
886 // If this is not the main thread return
887 if (((*gThreadXAR)("METH", 4, arr, NULL)))
888 return;
889 }
890
891 //
892 // Secure calls to update the tabs against itself, at least
893 // c->Paint() or c->Flush() may crash X (bad drawable).
894 // This makes sure, that a X call is not interuppted by
895 // another X-call which was started from an gui interrrupt
896 // in the same thread
897 //
898 if (fMutex->TryLock())
899 return;
900
901#if ROOT_VERSION_CODE < ROOT_VERSION(3,10,02)
902 TPad *padsav = (TPad*)gPad;
903 if (!gPad)
904 c->cd();
905#endif
906
907 if (!c->IsBatch())
908 c->FeedbackMode(kFALSE); // Goto double buffer mode
909
910 //
911 // Doing this ourself gives us the possibility to repaint
912 // the canvas in any case (Paint() instead of PaintModified())
913 //
914 c->Paint(); // Repaint all pads
915 c->Flush(); // Copy all pad pixmaps to the screen
916
917#if ROOT_VERSION_CODE < ROOT_VERSION(3,10,02)
918 if (padsav)
919 padsav->cd();
920 else
921 gPad=NULL;
922#endif
923
924 //c->SetCursor(kCross);
925
926 // Old version
927 //c->Modified();
928 //c->Update();
929 //c->Paint();
930
931 fMutex->UnLock();
932}
933
934// --------------------------------------------------------------------------
935//
936// Saves the given canvas (pad) or all pads (num<0) as a temporary
937// postscript file and prints it using 'lpr'. If a printer name is set
938// via SetPrinter 'lpr -Pname' is used.
939//
940Int_t MStatusDisplay::PrintToLpr(Int_t num)
941{
942 TString name = "mars";
943
944 for (int i=0; i<6; i++)
945 name += (char)(gRandom->Uniform(25)+65);
946
947 name += ".ps";
948
949 const Int_t pages = SaveAsPS(num, name);
950
951 SetStatusLine1("Printing...");
952 SetStatusLine2("");
953
954 if (!pages)
955 {
956 *fLog << warn << "MStatusDisplay::PrintToLpr: Sorry, couldn't save file as temporary postscript!" << endl;
957 SetStatusLine2("Failed!");
958 return 0;
959 }
960
961 TString cmd="lpr ";
962 if (!fPrinter.IsNull())
963 {
964 cmd += "-P";
965 cmd += fPrinter;
966 cmd += " ";
967 }
968 cmd += name;
969
970 gSystem->Exec(cmd);
971 gSystem->Unlink(name);
972
973 SetStatusLine2(Form("Done (%dpage(s))", pages));
974
975 return pages;
976}
977
978// --------------------------------------------------------------------------
979//
980// Remove tab no i if this tab contains a TRootEmbeddedCanvas
981//
982void MStatusDisplay::RemoveTab(int i)
983{
984 TGCompositeFrame *f = fTab->GetTabContainer(i);
985 if (!f)
986 return;
987
988 TRootEmbeddedCanvas *ec = GetEmbeddedCanvas(f);
989 if (!ec)
990 return;
991
992 TCanvas *c = ec->GetCanvas();
993 if (!c)
994 return;
995
996 const TString name(c->GetName());
997
998 f->RemoveFrame(ec);
999 delete fList->Remove(ec);
1000
1001 fTab->RemoveTab(i);
1002 fTab->SetTab(0);
1003
1004 // Looks strange...
1005 // const Int_t n = fTab->GetNumberOfTabs();
1006 // fTab->SetTab(i<=n-1 ? i : i-1);
1007
1008 // layout and map new tab
1009 Layout(); // seems to layout the TGCompositeFrame
1010 MapSubwindows(); // maps the TGCompositeFrame
1011 Layout(); // layout the embedded canvas in the frame
1012
1013 // display new tab in the main frame
1014 // FIXME: This is a workaround, because TApplication::Run is not
1015 // thread safe against ProcessEvents. We assume, that if
1016 // we are not in the Main-Thread ProcessEvents() is
1017 // called by the TApplication Event Loop...
1018 if (!TThread::Self()/*gApplication->InheritsFrom(TRint::Class())*/)
1019 gClient->ProcessEventsFor(fTab);
1020
1021 *fLog << inf << "Removed Tab #" << i << " '" << name << "'" << endl;
1022}
1023
1024// --------------------------------------------------------------------------
1025//
1026// Use this to check whether the MStatusDisplay still contains the
1027// TCanvas c. It could be removed meanwhile by menu usage.
1028//
1029Bool_t MStatusDisplay::HasCanvas(const TCanvas *c) const
1030{
1031 if (!c)
1032 return kFALSE;
1033
1034 if (gROOT->IsBatch())
1035 return (Bool_t)fBatch->FindObject(c);
1036
1037 for (int i=1; i<fTab->GetNumberOfTabs(); i++)
1038 if (c==GetCanvas(i))
1039 return kTRUE;
1040 return kFALSE;
1041}
1042
1043/*
1044 if (...)
1045 fMenu->AddPopup("&CaOs", fCaOs, NULL);
1046 else
1047 fMenu->RemovePopup("CaOs");
1048 fMenu->Resize(fMenu->GetDefaultSize());
1049 MapSubwindows();
1050 MapWindow();
1051 */
1052
1053void MStatusDisplay::Reset()
1054{
1055 for (int i=fTab->GetNumberOfTabs()-1; i>0; i--)
1056 RemoveTab(i);
1057}
1058
1059// --------------------------------------------------------------------------
1060//
1061// Process the kC_COMMAND, kCM_MENU messages
1062//
1063Bool_t MStatusDisplay::ProcessMessageCommandMenu(Long_t id)
1064{
1065 switch (id)
1066 {
1067 case kLoopStop:
1068 case kFileClose:
1069 case kFileExit:
1070 if (id==kFileExit || id==kFileClose)
1071 CloseWindow();
1072 fStatus = (Status_t)id;
1073 return kTRUE;
1074
1075 case kFileCanvas:
1076 new TCanvas;
1077 return kTRUE;
1078
1079 case kFileBrowser:
1080 new TBrowser;
1081 return kTRUE;
1082
1083 case kFileReset:
1084 Reset();
1085 return kTRUE;
1086 /*
1087 case kFileSave:
1088 cout << "Save..." << endl;
1089 return kTRUE;
1090
1091 case kFileSaveAs:
1092 cout << "SaveAs..." << endl;
1093 return kTRUE;
1094*/
1095 case kFileSaveAsPS:
1096 SaveAsPS();
1097 return kTRUE;
1098
1099 case kFileSaveAsGIF:
1100 SaveAsGIF();
1101 return kTRUE;
1102
1103 case kFileSaveAsC:
1104 SaveAsC();
1105 return kTRUE;
1106
1107 case kFileSaveAsRoot:
1108 SaveAsRoot();
1109 return kTRUE;
1110
1111 case kFilePrint:
1112 PrintToLpr();
1113 return kTRUE;
1114
1115 case kTabSaveAsPS:
1116 SaveAsPS(fTab->GetCurrent());
1117 return kTRUE;
1118
1119 case kTabSaveAsGIF:
1120 SaveAsGIF(fTab->GetCurrent());
1121 return kTRUE;
1122
1123 case kTabSaveAsC:
1124 SaveAsC(fTab->GetCurrent());
1125 return kTRUE;
1126
1127 case kTabSaveAsRoot:
1128 SaveAsRoot(fTab->GetCurrent());
1129 return kTRUE;
1130
1131 case kTabPrint:
1132 PrintToLpr(fTab->GetCurrent());
1133 return kTRUE;
1134
1135 case kTabNext:
1136 fTab->SetTab(fTab->GetCurrent()+1);
1137 return kTRUE;
1138
1139 case kTabPrevious:
1140 fTab->SetTab(fTab->GetCurrent()-1);
1141 return kTRUE;
1142
1143 case kTabRemove:
1144 RemoveTab(fTab->GetCurrent());
1145 return kTRUE;
1146
1147 case kSize640:
1148 Resize(570, 480);
1149 return kTRUE;
1150 case kSize800:
1151 Resize(740, 600);
1152 return kTRUE;
1153 case kSize960:
1154 Resize(880, 700);
1155 return kTRUE;
1156 case kSize1024:
1157 Resize(980, 768);
1158 return kTRUE;
1159 case kSize1280:
1160 Resize(1280, 980);
1161 return kTRUE;
1162
1163 case kLogClear:
1164 fLogBox->Clear();
1165 return kTRUE;
1166 case kLogCopy:
1167 fLogBox->Copy();
1168 return kTRUE;
1169 case kLogSelect:
1170 fLogBox->SelectAll();
1171 return kTRUE;
1172 case kLogFind:
1173 new MSearch(this);
1174 return kTRUE;
1175 case kLogSave:
1176 SetStatusLine1("Saving log...");
1177 SetStatusLine2("");
1178 *fLog << inf << "Saving log... " << flush;
1179 if (fLogBox->GetText()->Save("statusdisplay.log"))
1180 {
1181 *fLog << "done." << endl;
1182 SetStatusLine2("done.");
1183 }
1184 else
1185 {
1186 *fLog << "failed!" << endl;
1187 SetStatusLine2("Failed!");
1188 }
1189 return kTRUE;
1190
1191 case kLogAppend:
1192 SetStatusLine1("Appending logg...");
1193 SetStatusLine2("");
1194 *fLog << inf << "Appending log... " << flush;
1195 if (fLogBox->GetText()->Append("statusdisplay.log"))
1196 {
1197 *fLog << "done." << endl;
1198 SetStatusLine2("done.");
1199 }
1200 else
1201 {
1202 *fLog << "failed!" << endl;
1203 SetStatusLine2("Failed!");
1204 }
1205 return kTRUE;
1206#ifdef DEBUG
1207 default:
1208 cout << "Command-Menu #" << id << endl;
1209#endif
1210 }
1211 return kTRUE;
1212
1213}
1214
1215// --------------------------------------------------------------------------
1216//
1217// Process the kC_COMMAND messages
1218//
1219Bool_t MStatusDisplay::ProcessMessageCommand(Long_t submsg, Long_t mp1, Long_t mp2)
1220{
1221 switch (submsg)
1222 {
1223 case kCM_MENU: // 1
1224 return ProcessMessageCommandMenu(mp1); // mp2=userdata
1225 case kCM_TAB: // 8
1226 /*
1227 for (int i=0; i<fTab->GetNumberOfTabs(); i++)
1228 fTab->GetTabContainer(i)->UnmapWindow();
1229 */
1230 UpdateTab(fTab->GetTabContainer(mp1));
1231 //fTab->GetTabContainer(mp1)->MapWindow();
1232
1233 /*
1234 if (mp1>0)
1235 fMenu->AddPopup("&CaOs", fCaOs, NULL);
1236 else
1237 fMenu->RemovePopup("CaOs");
1238 fMenu->Resize(fMenu->GetDefaultSize());
1239 MapSubwindows();
1240 MapWindow();
1241 */
1242 return kTRUE;
1243#ifdef DEBUG
1244 case kCM_MENUSELECT: // 2
1245 cout << "Command-Menuselect #" << mp1 << " (UserData=" << (void*)mp2 << ")" << endl;
1246 return kTRUE;
1247
1248 case kCM_BUTTON: // 3
1249 cout << "Command-Button." << endl;
1250 return kTRUE;
1251
1252 case kCM_CHECKBUTTON: // 4
1253 cout << "Command-CheckButton." << endl;
1254 return kTRUE;
1255
1256 case kCM_RADIOBUTTON: // 5
1257 cout << "Command-RadioButton." << endl;
1258 return kTRUE;
1259
1260 case kCM_LISTBOX: // 6
1261 cout << "Command-Listbox #" << mp1 << " (LineId #" << mp2 << ")" << endl;
1262 return kTRUE;
1263
1264 case kCM_COMBOBOX: // 7
1265 cout << "Command-ComboBox." << endl;
1266 return kTRUE;
1267 default:
1268 cout << "Command: " << "Submsg:" << submsg << " Mp1=" << mp1 << " Mp2=" << mp2 << endl;
1269#endif
1270 }
1271 return kTRUE;
1272}
1273
1274// --------------------------------------------------------------------------
1275//
1276// Process the kC_TEXTVIEW messages
1277//
1278Bool_t MStatusDisplay::ProcessMessageTextview(Long_t submsg, Long_t mp1, Long_t mp2)
1279{
1280 // kC_TEXTVIEW, kTXT_ISMARKED, widget id, [true|false] //
1281 // kC_TEXTVIEW, kTXT_DATACHANGE, widget id, 0 //
1282 // kC_TEXTVIEW, kTXT_CLICK2, widget id, position (y << 16) | x) //
1283 // kC_TEXTVIEW, kTXT_CLICK3, widget id, position (y << 16) | x) //
1284 // kC_TEXTVIEW, kTXT_F3, widget id, true //
1285 // kC_TEXTVIEW, kTXT_OPEN, widget id, 0 //
1286 // kC_TEXTVIEW, kTXT_CLOSE, widget id, 0 //
1287 // kC_TEXTVIEW, kTXT_SAVE, widget id, 0 //
1288#ifdef DEBUG
1289 switch (submsg)
1290 {
1291 case kTXT_ISMARKED:
1292 cout << "Textview-IsMarked #" << mp1 << " " << (mp2?"yes":"no") << endl;
1293 return kTRUE;
1294
1295 case kTXT_DATACHANGE:
1296 cout << "Textview-DataChange #" << mp1 << endl;
1297 return kTRUE;
1298
1299 case kTXT_CLICK2:
1300 cout << "Textview-Click2 #" << mp1 << " x=" << (mp2&0xffff) << " y= " << (mp2>>16) << endl;
1301 return kTRUE;
1302
1303 case kTXT_CLICK3:
1304 cout << "Textview-Click3 #" << mp1 << " x=" << (mp2&0xffff) << " y= " << (mp2>>16) << endl;
1305 return kTRUE;
1306
1307 case kTXT_F3:
1308 cout << "Textview-F3 #" << mp1 << endl;
1309 return kTRUE;
1310
1311 case kTXT_OPEN:
1312 cout << "Textview-Open #" << mp1 << endl;
1313 return kTRUE;
1314
1315 case kTXT_CLOSE:
1316 cout << "Textview-Close #" << mp1 << endl;
1317 return kTRUE;
1318
1319 case kTXT_SAVE:
1320 cout << "Textview-Save #" << mp1 << endl;
1321 return kTRUE;
1322
1323 default:
1324 cout << "Textview: " << "Submsg:" << submsg << " Mp1=" << mp1 << " Mp2=" << mp2 << endl;
1325 }
1326#endif
1327 return kTRUE;
1328}
1329
1330// --------------------------------------------------------------------------
1331//
1332// Process the kC_USER messages
1333//
1334Bool_t MStatusDisplay::ProcessMessageUser(Long_t submsg, Long_t mp1, Long_t mp2)
1335{
1336 // kS_START, case sensitive | backward<<1, char *txt
1337 switch (submsg)
1338 {
1339 case kS_START:
1340 fLogBox->Search((char*)mp2, !(mp1&2>>1), mp1&1);
1341 return kTRUE;
1342#ifdef DEBUG
1343 default:
1344 cout << "User: " << "Submsg:" << submsg << " Mp1=" << mp1 << " Mp2=" << mp2 << endl;
1345#endif
1346 }
1347 return kTRUE;
1348}
1349
1350// --------------------------------------------------------------------------
1351//
1352// Process the messages from the GUI
1353//
1354Bool_t MStatusDisplay::ProcessMessage(Long_t msg, Long_t mp1, Long_t mp2)
1355{
1356 // Can be found in WidgetMessageTypes.h
1357#ifdef DEBUG
1358 cout << "Msg: " << GET_MSG(msg) << " Submsg:" << GET_SUBMSG(msg);
1359 cout << " Mp1=" << mp1 << " Mp2=" << mp2 << endl;
1360#endif
1361 switch (GET_MSG(msg))
1362 {
1363 case kC_COMMAND: // 1
1364 return ProcessMessageCommand(GET_SUBMSG(msg), mp1, mp2);
1365
1366 case kC_TEXTVIEW: // 9
1367 return ProcessMessageTextview(GET_SUBMSG(msg), mp1, mp2);
1368
1369 case kC_USER: // 1001
1370 return ProcessMessageUser(GET_SUBMSG(msg), mp1, mp2);
1371 }
1372#ifdef DEBUG
1373 cout << "Msg: " << GET_MSG(msg) << " Submsg:" << GET_SUBMSG(msg);
1374 cout << " Mp1=" << mp1 << " Mp2=" << mp2 << endl;
1375#endif
1376 return kTRUE;
1377}
1378
1379void MStatusDisplay::CloseWindow()
1380{
1381 // Got close message for this MainFrame. Calls parent CloseWindow()
1382 // (which destroys the window) and terminate the application.
1383 // The close message is generated by the window manager when its close
1384 // window menu item is selected.
1385
1386 // CloseWindow must be overwritten because otherwise CloseWindow
1387 // and the destructor are calling DestroyWindow which seems to be
1388 // in conflict with the TRootEmbeddedCanvas.
1389
1390 // FIXME: Make sure that the Status Display is deleted from every
1391 // where (eg Eventloop) first!
1392
1393 gLog << dbg << fName << " is on heap: " << (int)IsOnHeap() << endl;
1394
1395 if (TestBit(kExitLoopOnExit) || TestBit(kExitLoopOnClose))
1396 {
1397 gLog << dbg << "CloseWindow() calling ExitLoop." << endl;
1398 gSystem->ExitLoop();
1399 }
1400
1401 if (fIsLocked<=0 && IsOnHeap())
1402 {
1403 gLog << dbg << "delete " << fName << ";" << endl;
1404 delete this;
1405 }
1406 fStatus = kFileExit;
1407 gLog << dbg << fName << ".fStatus=kFileExit;" << endl;
1408}
1409
1410// --------------------------------------------------------------------------
1411//
1412// Calls SetBit(kNoContextMenu) for all TCanvas objects found in the
1413// Tabs.
1414//
1415void MStatusDisplay::SetNoContextMenu(Bool_t flag)
1416{
1417 if (fIsLocked>1 || gROOT->IsBatch())
1418 return;
1419
1420 flag ? SetBit(kNoContextMenu) : ResetBit(kNoContextMenu);
1421
1422 for (int i=1; i<fTab->GetNumberOfTabs(); i++)
1423 {
1424 TCanvas *c = GetCanvas(i);
1425 if (c)
1426 flag ? c->SetBit(kNoContextMenu) : c->ResetBit(kNoContextMenu);
1427 }
1428}
1429
1430// --------------------------------------------------------------------------
1431//
1432// Updates the canvas (if existing) in the currenly displayed Tab.
1433// The update intervall is controlled by StartUpdate and StopUpdate
1434//
1435Bool_t MStatusDisplay::HandleTimer(TTimer *timer)
1436{
1437 if (gROOT->IsBatch())
1438 return kTRUE;
1439
1440 const Int_t c = fTab->GetCurrent();
1441
1442 // Skip Legend Tab
1443 if (c==0)
1444 return kTRUE;
1445
1446 // Update a canvas tab (if visible)
1447 if (timer==&fTimer && c!=fLogIdx)
1448 {
1449 UpdateTab(fTab->GetCurrentContainer());
1450 return kTRUE;
1451 }
1452
1453 // update the logbook tab (if visible)
1454 if (timer==&fLogTimer && c==fLogIdx)
1455 {
1456 fLog->UpdateGui();
1457
1458 /*
1459 if (!fLogBox->TestBit(kHasChanged))
1460 return kTRUE;
1461
1462 fLogBox->ResetBit(kHasChanged);
1463 */
1464 return kTRUE;
1465 }
1466
1467 return kTRUE;
1468}
1469
1470// --------------------------------------------------------------------------
1471//
1472// Draws a clone of a canvas into a new canvas. Taken from TCanvas.
1473//
1474void MStatusDisplay::DrawClonePad(TCanvas &newc, const TCanvas &oldc) const
1475{
1476 //copy pad attributes
1477 newc.Range(oldc.GetX1(),oldc.GetY1(),oldc.GetX2(),oldc.GetY2());
1478 newc.SetTickx(oldc.GetTickx());
1479 newc.SetTicky(oldc.GetTicky());
1480 newc.SetGridx(oldc.GetGridx());
1481 newc.SetGridy(oldc.GetGridy());
1482 newc.SetLogx(oldc.GetLogx());
1483 newc.SetLogy(oldc.GetLogy());
1484 newc.SetLogz(oldc.GetLogz());
1485 newc.SetBorderSize(oldc.GetBorderSize());
1486 newc.SetBorderMode(oldc.GetBorderMode());
1487 ((TAttLine&)oldc).Copy((TAttLine&)newc);
1488 ((TAttFill&)oldc).Copy((TAttFill&)newc);
1489 ((TAttPad&)oldc).Copy((TAttPad&)newc);
1490
1491 //copy primitives
1492 TObject *obj;
1493 TIter next(oldc.GetListOfPrimitives());
1494 while ((obj=next())) {
1495 gROOT->SetSelectedPad(&newc);
1496 newc.GetListOfPrimitives()->Add(obj->Clone(),obj->GetDrawOption());
1497 }
1498 newc.Modified();
1499 newc.Update();
1500}
1501
1502// --------------------------------------------------------------------------
1503//
1504// Reads the contents of a saved MStatusDisplay from a file.
1505//
1506Int_t MStatusDisplay::Read(const char *name)
1507{
1508 if (!gFile)
1509 {
1510 *fLog << warn << "MStatusDisplay::Read: No file found. Please create a TFile first." << endl;
1511 return 0;
1512 }
1513
1514 if (!gFile->IsOpen())
1515 {
1516 *fLog << warn << "MStatusDisplay::Read: File not open. Please open the TFile first." << endl;
1517 return 0;
1518 }
1519
1520 TObjArray list;
1521
1522 const Int_t n = list.Read(name);
1523 if (n==0)
1524 {
1525 *fLog << warn << "MStatusDisplay::Read: No objects read." << endl;
1526 return 0;
1527 }
1528
1529 TIter Next(&list);
1530
1531 TObject *o=Next();
1532 if (!o)
1533 {
1534 *fLog << err << "MStatusDisplay: First entry missing in " << name << "." << endl;
1535 return 0;
1536 }
1537
1538 fTitle = o->GetTitle();
1539
1540 TCanvas *c;
1541 while ((c=(TCanvas*)Next()))
1542 DrawClonePad(AddTab(c->GetName()), *c);
1543
1544 *fLog << inf << "MStatusDisplay: Key " << name << " with " << n << " keys read from file." << endl;
1545
1546 return n;
1547}
1548
1549// --------------------------------------------------------------------------
1550//
1551// Writes the contents of a MStatusDisplay to a file.
1552//
1553Int_t MStatusDisplay::Write(Int_t num, const char *name, Int_t option, Int_t bufsize)
1554{
1555 if (!gFile)
1556 {
1557 *fLog << warn << "MStatusDisplay::Write: No file found. Please create a TFile first." << endl;
1558 return 0;
1559 }
1560
1561 if (!gFile->IsOpen())
1562 {
1563 *fLog << warn << "MStatusDisplay::Write: File not open. Please open the TFile first." << endl;
1564 return 0;
1565 }
1566
1567 if (!gFile->IsWritable())
1568 {
1569 *fLog << warn << "MStatusDisplay::Write: File not writable." << endl;
1570 return 0;
1571 }
1572
1573 if (num==0)
1574 {
1575 *fLog << warn << "MStatusDisplay::Write: Tab doesn't contain an embedded Canvas... skipped." << endl;
1576 return 0;
1577 }
1578
1579 if (!gROOT->IsBatch() && num>=fTab->GetNumberOfTabs())
1580 {
1581 *fLog << warn << "MStatusDisplay::Write: Tab doesn't exist... skipped." << endl;
1582 return 0;
1583 }
1584 if (gROOT->IsBatch() && num>fBatch->GetSize())
1585 {
1586 *fLog << warn << "MStatusDisplay::Write: Tab doesn't exist... skipped." << endl;
1587 return 0;
1588 }
1589
1590 TObjArray list;
1591
1592 TNamed named;
1593 named.SetTitle(fTitle);
1594 list.Add(&named);
1595
1596 const Int_t max = gROOT->IsBatch() ? fBatch->GetSize()+1 : fTab->GetNumberOfTabs();
1597 const Int_t from = num<0 ? 1 : num;
1598 const Int_t to = num<0 ? max : num+1;
1599
1600 TCanvas *c;
1601 for (int i=from; i<to; i++)
1602 if ((c = GetCanvas(i)))
1603 list.Add(c);
1604
1605 const Int_t n = list.Write(name, kSingleKey);
1606
1607 *fLog << inf << "MStatusDisplay: " << n << " keys written to file as key " << name << "." << endl;
1608
1609 return n;
1610}
1611
1612// --------------------------------------------------------------------------
1613//
1614// Use this to start the synchronous (GUI eventloop driven) tab update.
1615// Can also be used to change the update intervall. If millisec<0
1616// the intervall given in SetUpdateTime is used. If the intervall in
1617// SetUpdateTime is <0 nothing is done. (Call SetUpdateTime(-1) to
1618// disable the automatic update in a MEventloop.
1619//
1620void MStatusDisplay::StartUpdate(Int_t millisec)
1621{
1622 if (fIsLocked>1)
1623 return;
1624
1625 if (fTimer.GetTime()<TTime(0))
1626 return;
1627 fTimer.Start(millisec);
1628}
1629
1630// --------------------------------------------------------------------------
1631//
1632// Stops the automatic GUI update
1633//
1634void MStatusDisplay::StopUpdate()
1635{
1636 if (fIsLocked>1)
1637 return;
1638
1639 fTimer.Stop();
1640}
1641
1642// --------------------------------------------------------------------------
1643//
1644// Set the update interval for the GUI update, see StartUpdate.
1645//
1646void MStatusDisplay::SetUpdateTime(Long_t t)
1647{
1648 fTimer.SetTime(t);
1649}
1650
1651// --------------------------------------------------------------------------
1652//
1653// Set the background color in a canvas
1654//
1655void MStatusDisplay::CanvasSetFillColor(TPad &p, Int_t col) const
1656{
1657 TObject *obj;
1658
1659 // See also TPad::UseCurrentStyle
1660 TIter Next(p.GetListOfPrimitives());
1661 while ((obj=Next()))
1662 {
1663 if (obj->InheritsFrom(TPad::Class()))
1664 CanvasSetFillColor(*(TPad*)obj, col);
1665 if (obj->InheritsFrom(TFrame::Class()))
1666 ((TFrame*)obj)->SetFillColor(col);
1667 }
1668
1669 p.SetFillColor(col);
1670}
1671
1672void MStatusDisplay::AddExtension(TString &name, const TString &ext, Int_t num) const
1673{
1674 if (name.IsNull())
1675 {
1676 name = "status";
1677 if (num>0)
1678 {
1679 name += "-";
1680 name += num;
1681 }
1682 }
1683
1684 if (name.EndsWith("."+ext))
1685 return;
1686
1687 name += ".";
1688 name += ext;
1689}
1690
1691Bool_t MStatusDisplay::CheckTabForCanvas(int num) const
1692{
1693 if (gROOT->IsBatch())
1694 return num>0 && num<=fBatch->GetSize() || num<0;
1695
1696 if (num>=fTab->GetNumberOfTabs())
1697 {
1698 *fLog << warn << "Tab #" << num << " doesn't exist..." << endl;
1699 return kFALSE;
1700 }
1701 if (num==0)
1702 {
1703 *fLog << warn << "Tab #" << num << " doesn't contain an embedded canvas..." << endl;
1704 return kFALSE;
1705 }
1706 if (fTab->GetNumberOfTabs()<2 || !gPad)
1707 {
1708 *fLog << warn << "Sorry, you must have at least one existing canvas (gPad!=NULL)" << endl;
1709 return kFALSE;
1710 }
1711 return kTRUE;
1712}
1713
1714// --------------------------------------------------------------------------
1715//
1716// Insert the following two lines into the postscript header:
1717//
1718// %%DocumentPaperSizes: a4
1719// %%Orientation: Landscape
1720//
1721void MStatusDisplay::UpdatePSHeader(const TString &name) const
1722{
1723 const TString newstr("%%DocumentPaperSizes: a4\n%%Orientation: Landscape\n");
1724 const Int_t l = newstr.Length();
1725
1726 Long_t t[4]; // { id, size, flags, modtime }
1727 gSystem->GetPathInfo(name, t, t+1, t+2, t+3);
1728
1729 char *c[2] = { new char[l], new char[l] };
1730
1731 fstream f(name, ios::in|ios::out);
1732
1733 TString str;
1734 f >> str >> c[0][0]; // Read "%!PS-Adobe-2.0\n" (Mini Header)
1735 f.read(c[0], l);
1736 f.seekp(-l, ios::cur);
1737 f.write(newstr, l);
1738
1739 int i=0;
1740 while (1)
1741 {
1742 f.read(c[(i+1)%2], l);
1743 f.seekp(-l, ios::cur);
1744
1745 if (f)
1746 {
1747 f.write(c[i%2],l);
1748 i++;
1749 i%=2;
1750 continue;
1751 }
1752
1753 const Int_t ssz = str.Length()+1; // Length of Mini-Header
1754 const Int_t block = t[1]-ssz; // Length of block to be shifted
1755 const Int_t size = block%l; // Reminder
1756 const Int_t pos = (block/l)*l + ssz + 1; // Position to start writing
1757
1758 f.clear();
1759 f.seekp(pos);
1760 f.write(c[i%2], l);
1761 f.write(c[(i+1)%2], size);
1762 break;
1763 }
1764
1765 delete c[1];
1766 delete c[0];
1767}
1768
1769// --------------------------------------------------------------------------
1770//
1771// In case of num<0 all tabs are written into the PS file. If num>0
1772// the canvas in the corresponding tab is written to the file.
1773// Name is the name of the file (with or without extension).
1774//
1775// Returns the number of pages written.
1776//
1777// To write all tabs you can also use SaveAsPS(name)
1778//
1779// If the third argument is given a bottom line is drawn with the text
1780// under it. If no argument is given a bottom line is drawn if
1781// fTitle (SetTitle) is not empty.
1782//
1783Int_t MStatusDisplay::SaveAsPS(Int_t num, TString name, const TString addon)
1784{
1785 SetStatusLine1("Writing Postscript file...");
1786 SetStatusLine2("");
1787
1788 if (!CheckTabForCanvas(num))
1789 {
1790 SetStatusLine2("Failed!");
1791 return 0;
1792 }
1793
1794 AddExtension(name, "ps", num);
1795
1796 if (num<0)
1797 *fLog << inf << "Open ps-File: " << name << endl;
1798
1799 TPad *padsav = (TPad*)gPad;
1800 TVirtualPS *psave = gVirtualPS;
1801
1802 TDatime d;
1803
1804 TPostScript ps(name, 112);
1805 ps.SetBit(TPad::kPrintingPS);
1806 ps.PrintFast(13, "/nan {1} def ");
1807
1808 gVirtualPS = &ps;
1809
1810 //
1811 // Create a list to delete the canvas clones
1812 //
1813 TList l;
1814 l.SetOwner();
1815
1816 //
1817 // Create some GUI elements for a page legend
1818 //
1819 TLine line;
1820
1821 int page = 1;
1822
1823 //
1824 // Maintain tab numbers
1825 //
1826 const Int_t max = gROOT->IsBatch() ? fBatch->GetSize()+1 : fTab->GetNumberOfTabs();
1827 const Int_t from = num<0 ? 1 : num;
1828 const Int_t to = num<0 ? max : num+1;
1829
1830 for (int i=from; i<to; i++)
1831 {
1832 TCanvas *c;
1833 if (!(c = GetCanvas(i)))
1834 {
1835 if (num<0)
1836 *fLog << inf << " - ";
1837 *fLog << "Tab #" << i << " doesn't contain an embedded Canvas... skipped." << endl;
1838 continue;
1839 }
1840
1841 SetStatusLine2(Form("Tab #%d", i));
1842
1843 //
1844 // Init page and page size, make sure, that the canvas in the file
1845 // has the same Aspect Ratio than on the screen.
1846 //
1847 ps.NewPage();
1848
1849 //
1850 // 28 is used here to scale the canvas into a height of 28,
1851 // such that the page title can be set above the canvas...
1852 //
1853 Float_t psw = 28.0; // A4 - width (29.7)
1854 Float_t psh = 21.0; // A4 - height (21.0)
1855
1856 const Float_t cw = c->GetWw();
1857 const Float_t ch = c->GetWh();
1858
1859 if (psw/psh>cw/ch)
1860 psw = cw/ch*psh;
1861 else
1862 psh = ch/cw*psw;
1863
1864 ps.Range(psw, psh); // A4
1865
1866 //
1867 // Clone canvas and change background color and schedule for
1868 // deletion
1869 //
1870 TCanvas *n = (TCanvas*)c->Clone();
1871 CanvasSetFillColor(*n, kWhite);
1872 l.Add(n);
1873
1874 //
1875 // Paint canvas into root file
1876 //
1877 if (num<0)
1878 *fLog << inf << " - ";
1879 *fLog << inf << "Writing Tab #" << i << ": " << c->GetName() << " (" << c << ") ";
1880 if (num>0)
1881 *fLog << "to " << name;
1882 *fLog << "..." << flush;
1883
1884 n->SetBatch(kTRUE);
1885 n->Paint();
1886
1887 //
1888 // Use the canvas as coordinate system for the overlaying text
1889 //
1890 gPad = n;
1891
1892 //
1893 // Print overlaying text (NDC = %)
1894 //
1895 ps.SetTextColor(kBlack);
1896 ps.SetTextSize(0.015);
1897 ps.SetTextFont(22);
1898 ps.SetTextAlign(11); // left top
1899 ps.TextNDC(0, 1.015, TString(" ")+n->GetName());
1900 ps.SetTextAlign(21); // cent top
1901 ps.TextNDC(0.5, 1.015, TString("MARS - Magic Analysis and Reconstruction Software - ")+d.AsString());
1902 ps.SetTextAlign(31); // right top
1903 ps.TextNDC(1, 1.015, Form("Page No.%i (%i) ", page++, i));
1904 line.PaintLineNDC(0, 1.01, 1, 1.01);
1905
1906 TString txt(addon.IsNull() ? fTitle : addon);
1907 if (!txt.IsNull())
1908 {
1909 line.PaintLineNDC(0, -0.00, 1, -0.00);
1910 ps.SetTextAlign(23); // cent bottom
1911 ps.TextNDC(0.5, -0.005, txt);
1912 }
1913
1914 //
1915 // Finish drawing page
1916 //
1917 n->SetBatch(kFALSE);
1918 if (num<0)
1919 *fLog << "done." << endl;
1920 }
1921
1922 gPad = NULL; // Important!
1923 l.Delete();
1924
1925 ps.Close();
1926 UpdatePSHeader(name);
1927
1928 gVirtualPS = psave;
1929 if (padsav)
1930 padsav->cd();
1931
1932 *fLog << inf << "done." << endl;
1933
1934 SetStatusLine2(Form("Done (%dpages)", page-1));
1935
1936 return page-1;
1937}
1938
1939Bool_t MStatusDisplay::SaveAsGIF(Int_t num, TString name)
1940{
1941 if (gROOT->IsBatch())
1942 {
1943 *fLog << warn << "Sorry, writing gif-files is not available in batch mode." << endl;
1944 return 0;
1945 }
1946 SetStatusLine1("Writing GIF file...");
1947 SetStatusLine2("");
1948
1949 if (!CheckTabForCanvas(num))
1950 {
1951 SetStatusLine2("Failed!");
1952 return 0;
1953 }
1954
1955 AddExtension(name, "gif", num);
1956
1957 if (num<0)
1958 *fLog << inf << "Writing gif-Files..." << endl;
1959
1960 TPad *padsav = (TPad*)gPad;
1961
1962 int page = 1;
1963
1964 //
1965 // Maintain tab numbers
1966 //
1967 const Int_t from = num<0 ? 1 : num;
1968 const Int_t to = num<0 ? fTab->GetNumberOfTabs() : num+1;
1969
1970 for (int i=from; i<to; i++)
1971 {
1972 TCanvas *c;
1973 if (!(c = GetCanvas(i)))
1974 {
1975 if (num<0)
1976 *fLog << inf << " - ";
1977 *fLog << "Tab #" << i << " doesn't contain an embedded Canvas... skipped." << endl;
1978 continue;
1979 }
1980
1981 SetStatusLine2(Form("Tab #%d", i));
1982
1983 //
1984 // Clone canvas and change background color and schedule for
1985 // deletion
1986 //
1987 //TCanvas *n = (TCanvas*)c->Clone();
1988 //CanvasSetFillColor(*n, kWhite);
1989
1990 //
1991 // Paint canvas into root file
1992 //
1993 TString writename = name;
1994 if (num<0)
1995 {
1996 TString numname = "-";
1997 numname += i;
1998 writename.Insert(name.Last('.'), numname);
1999 }
2000 if (num<0)
2001 *fLog << inf << " - ";
2002 *fLog << inf << "Writing Tab #" << i << " to " << writename << ": " << c->GetName() << " (" << c << ") ";
2003 if (num>0)
2004 *fLog << "to " << name;
2005 *fLog << "..." << flush;
2006
2007 c->Draw();
2008 c->SaveAs(writename);
2009 /*
2010 n->Draw();
2011 n->SaveAs(writename);
2012 delete n;
2013 */
2014
2015 if (num<0)
2016 *fLog << "done." << endl;
2017 }
2018
2019 padsav->cd();
2020
2021 *fLog << inf << "done." << endl;
2022
2023 SetStatusLine2("Done.");
2024
2025 return page-1;
2026}
2027
2028Bool_t MStatusDisplay::SaveAsC(Int_t num, TString name)
2029{
2030 SetStatusLine1("Writing C++ file...");
2031 SetStatusLine2("");
2032
2033 if (!CheckTabForCanvas(num))
2034 {
2035 SetStatusLine2("Failed!");
2036 return 0;
2037 }
2038
2039 AddExtension(name, "C", num);
2040
2041 if (num<0)
2042 *fLog << inf << "Writing C-Files..." << endl;
2043
2044 TPad *padsav = (TPad*)gPad;
2045
2046 int page = 1;
2047
2048 //
2049 // Maintain tab numbers
2050 //
2051 const Int_t from = num<0 ? 1 : num;
2052 const Int_t to = num<0 ? fTab->GetNumberOfTabs() : num+1;
2053
2054 for (int i=from; i<to; i++)
2055 {
2056 TCanvas *c;
2057 if (!(c = GetCanvas(i)))
2058 {
2059 if (num<0)
2060 *fLog << inf << " - ";
2061 *fLog << "Tab #" << i << " doesn't contain an embedded Canvas... skipped." << endl;
2062 continue;
2063 }
2064
2065 SetStatusLine2(Form("Tab #%d", i));
2066
2067 //
2068 // Clone canvas and change background color and schedule for
2069 // deletion
2070 //
2071 TCanvas *n = (TCanvas*)c->Clone();
2072 CanvasSetFillColor(*n, kWhite);
2073
2074 //
2075 // Paint canvas into root file
2076 //
2077 TString writename = name;
2078 if (num<0)
2079 {
2080 TString numname = "-";
2081 numname += i;
2082 writename.Insert(name.Last('.'), numname);
2083 }
2084 if (num<0)
2085 *fLog << inf << " - ";
2086 *fLog << inf << "Writing Tab #" << i << " to " << writename << ": " << c->GetName() << " (" << n << ") ";
2087 if (num>0)
2088 *fLog << "to " << name;
2089 *fLog << "..." << flush;
2090
2091 n->SaveSource(writename, "");
2092 delete n;
2093
2094 if (num<0)
2095 *fLog << "done." << endl;
2096 }
2097
2098 padsav->cd();
2099
2100 *fLog << inf << "done." << endl;
2101
2102 SetStatusLine2("Done.");
2103
2104 return page-1;
2105}
2106
2107// --------------------------------------------------------------------------
2108//
2109// In case of num<0 all tabs are written into the PS file. If num>0
2110// the canvas in the corresponding tab is written to the file.
2111// Name is the name of the file (with or without extension).
2112//
2113// Returns the number of keys written.
2114//
2115// To write all tabs you can also use SaveAsPS(name)
2116//
2117Int_t MStatusDisplay::SaveAsRoot(Int_t num, TString name)
2118{
2119 SetStatusLine1("Writing root file...");
2120 SetStatusLine2("");
2121
2122 if (!CheckTabForCanvas(num))
2123 {
2124 SetStatusLine2("Failed!");
2125 return 0;
2126 }
2127
2128 AddExtension(name, "root", num);
2129
2130 TFile *fsave = gFile;
2131 TFile file(name, "RECREATE", "MARS - Status Window Contents", 9);
2132 const Int_t keys = Write(num);
2133 gFile = fsave;
2134
2135 SetStatusLine2("Done.");
2136
2137 return keys;
2138}
2139
2140Bool_t MStatusDisplay::HandleConfigureNotify(Event_t *evt)
2141{
2142 //
2143 // The initialization of the GUI is not yet enough finished...
2144 //
2145 if (!fTab)
2146 return kTRUE;
2147
2148 UInt_t w = evt->fWidth;
2149 UInt_t h = evt->fHeight;
2150
2151 /*
2152 cout << "Old: " << GetWidth() << " " << GetHeight() << " " << GetBorderWidth() << endl;
2153 cout << "New: " << w << " " << h << " ";
2154 cout << "New: " << GetDefaultWidth() << " " << GetDefaultHeight() << " " << endl;
2155 */
2156
2157 Bool_t wchanged = w!=GetWidth();
2158 Bool_t hchanged = h!=GetHeight();
2159
2160 if (!wchanged && !hchanged)
2161 {
2162 Layout();
2163 // FIXME: Make sure that this doesn't result in endless loops.
2164 return kTRUE;
2165 }
2166
2167
2168 if (GetWidth()==1 && GetHeight()==1)
2169 return kTRUE;
2170
2171 // calculate the constant part of the window
2172 const UInt_t cw = GetWidth() -fTab->GetWidth();
2173 const UInt_t ch = GetHeight()-fTab->GetHeight();
2174
2175 // calculate new size of frame (canvas @ 1:sqrt(2))
2176 if (hchanged)
2177 w = (UInt_t)((h-ch)*sqrt(2.)+.5)+cw;
2178 else
2179 h = (UInt_t)((w-cw)/sqrt(2.)+.5)+ch;
2180
2181 // resize frame
2182 Resize(w, h);
2183
2184 return kTRUE;
2185}
2186
2187Bool_t MStatusDisplay::HandleEvent(Event_t *event)
2188{
2189 Bool_t rc = TGMainFrame::HandleEvent(event);
2190
2191 //
2192 // This fixes a bug in older root versions which makes
2193 // TCanvas crash if gPad==NULL. So we make sure, that
2194 // gPad!=NULL -- be carfull, this may have other side
2195 // effects.
2196 //
2197#if ROOT_VERSION_CODE < ROOT_VERSION(3,10,01)
2198 if (!gPad && fTab)
2199 for (int i=0; i<fTab->GetNumberOfTabs(); i++)
2200 {
2201 TCanvas *c = GetCanvas(i);
2202 if (c)
2203 {
2204 c->cd();
2205 gLog << dbg << "MStatusDisplay::HandleEvent - Workaround: gPad=" << gPad << "." << endl;
2206 break;
2207 }
2208 }
2209#endif
2210
2211 return rc;
2212}
2213
2214/*
2215 // --------------------------------------------------------------------------
2216//
2217// Opens a save as dialog, and tries to store the canvas
2218// in the given output format
2219//
2220void MGEvtDisplay::SaveAsDialog() const
2221{
2222 static const char *gSaveAsTypes[] =
2223 {
2224 "PostScript", "*.ps",
2225 "Encapsulated PostScript", "*.eps",
2226 "Gif files", "*.gif",
2227 "Macro files", "*.C",
2228 "ROOT files", "*.root",
2229 "All files", "*",
2230 NULL, NULL
2231 };
2232
2233 static TString dir(".");
2234
2235 TGFileInfo fi; // fFileName and fIniDir deleted in ~TGFileInfo
2236
2237 fi.fFileTypes = (const char**)gSaveAsTypes;
2238 fi.fIniDir = StrDup(dir);
2239
2240 new TGFileDialog(fClient->GetRoot(), this, kFDSave, &fi);
2241
2242 if (!fi.fFilename)
2243 return;
2244
2245 dir = fi.fIniDir;
2246
2247 if (strstr(fi.fFilename, ".root") ||
2248 strstr(fi.fFilename, ".ps") ||
2249 strstr(fi.fFilename, ".eps") ||
2250 strstr(fi.fFilename, ".gif"))
2251 {
2252 fCanvas->SaveAs(fi.fFilename);
2253 return;
2254 }
2255 if (strstr(fi.fFilename, ".C"))
2256 {
2257 fCanvas->SaveSource(fi.fFilename);
2258 return;
2259 }
2260 Warning("SaveAsDialog", "Unknown Extension: %s", fi.fFilename);
2261}
2262*/
Note: See TracBrowser for help on using the repository browser.