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

Last change on this file since 2555 was 2550, checked in by tbretz, 21 years ago
*** empty log message ***
File size: 61.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", kFilePrint);
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), fTab(NULL), fTimer(this, t, kTRUE), fStatus(kLoopNone), fLog(&gLog), 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 // set the smallest and biggest size of the Main frame
592 // and move it to its appearance position
593 SetWMSizeHints(570, 480, 1280, 980, 1, 1);
594 Move(rand()%100+50, rand()%100+50);
595 Resize(570, 480);
596
597 //
598 // Create the layout hint for the root embedded canavses
599 //
600 fLayCanvas = new TGLayoutHints(kLHintsExpandX|kLHintsExpandY);
601 fList->Add(fLayCanvas);
602
603 //
604 // Add Widgets (from top to bottom)
605 //
606 if (gClient) // BATCH MODE
607 {
608 AddMenuBar();
609 AddUserFrame();
610 AddTabs();
611 AddProgressBar();
612 AddStatusBar();
613 }
614
615 //
616 // Now do an automatic layout of the widgets and display the window
617 //
618 Layout();
619 MapSubwindows();
620
621 SetWindowName("Status Display");
622 SetIconName("Status Display");
623
624 MapWindow();
625
626 // FIXME: This is a workaround, because TApplication::Run is not
627 // thread safe against ProcessEvents. We assume, that if
628 // we are not in the Main-Thread ProcessEvents() is
629 // called by the TApplication Event Loop...
630 if (!TThread::Self()/*gApplication->InheritsFrom(TRint::Class())*/)
631 gSystem->ProcessEvents();
632}
633
634// --------------------------------------------------------------------------
635//
636// Destruct the window with all its tiles. Also the Progress Bar object
637// is deleted.
638//
639MStatusDisplay::~MStatusDisplay()
640{
641#if ROOT_VERSION_CODE < ROOT_VERSION(3,10,01)
642 fTab = NULL; // See HandleEvent
643#endif
644
645 //
646 // Delete object from global object table so it cannot
647 // be deleted by chance a second time
648 //
649 gInterpreter->DeleteGlobal(this);
650
651 //
652 // This is a possibility for the user to check whether this
653 // object has already been deleted. It has been added
654 // to the list in the constructor.
655 //
656 gROOT->GetListOfSpecials()->Remove(this);
657
658 SetLogStream(NULL);
659
660 //
661 // Delete the list of objects corresponding to this object
662 //
663 delete fList;
664
665 //
666 // Delete the list list of canvases used in batch mode
667 // instead of the Root Embedded Canvases in the TGTab
668 //
669 delete fBatch;
670
671 //
672 // Delete the font used for the logging window
673 //
674 if (fFont)
675 gVirtualX->DeleteFont(fFont);
676
677 //
678 // Delete mutex
679 //
680 delete fMutex;
681}
682
683// --------------------------------------------------------------------------
684//
685// Takes a TGCompositeFrame as argument. Searches for the first
686// TRootEmbeddedCanvas which is contained by it and returns a pointer
687// to the corresponding TCanvas. If it isn't found NULL is returned.
688//
689TRootEmbeddedCanvas *MStatusDisplay::GetEmbeddedCanvas(TGCompositeFrame *cf) const
690{
691 TIter Next(cf->GetList());
692
693 TGFrameElement *f;
694 while ((f=(TGFrameElement*)Next()))
695 if (f->fFrame->InheritsFrom(TRootEmbeddedCanvas::Class()))
696 return (TRootEmbeddedCanvas*)f->fFrame;
697
698 return NULL;
699}
700
701// --------------------------------------------------------------------------
702//
703// Takes a TGCompositeFrame as argument. Searches for the first
704// TRootEmbeddedCanvas which is contained by it and returns a pointer
705// to the corresponding TCanvas. If it isn't found NULL is returned.
706//
707TCanvas *MStatusDisplay::GetCanvas(TGCompositeFrame *cf) const
708{
709 TRootEmbeddedCanvas *ec = GetEmbeddedCanvas(cf);
710 return ec ? ec->GetCanvas() : NULL;
711}
712
713// --------------------------------------------------------------------------
714//
715// Returns GetCanvas of the i-th Tab.
716//
717TCanvas *MStatusDisplay::GetCanvas(int i) const
718{
719 if (gROOT->IsBatch())
720 return (TCanvas*)fBatch->At(i-1);
721
722 if (i<0 || i>=fTab->GetNumberOfTabs())
723 {
724 *fLog << warn << "MStatusDisplay::GetCanvas: Out of range." << endl;
725 return NULL;
726 }
727
728 return GetCanvas(fTab->GetTabContainer(i));
729}
730
731// --------------------------------------------------------------------------
732//
733// Searches for a TRootEmbeddedCanvas in the TGCompositeFramme of the
734// Tab with the name 'name'. Returns the corresponding TCanvas or
735// NULL if something isn't found.
736//
737TCanvas *MStatusDisplay::GetCanvas(const TString &name) const
738{
739 TGFrameElement *f;
740 TIter Next(fTab->GetList());
741 while ((f=(TGFrameElement*)Next()))
742 {
743 TObject *frame = f->fFrame;
744 if (!frame->InheritsFrom(TGTabElement::Class()))
745 continue;
746
747 TGTabElement *tab = (TGTabElement*)frame;
748 if (tab->GetString()==name)
749 break;
750 }
751
752 // Search for the next TGCompositeFrame in the list
753 while ((f=(TGFrameElement*)Next()))
754 {
755 TObject *frame = f->fFrame;
756 if (frame->InheritsFrom(TGCompositeFrame::Class()))
757 return GetCanvas((TGCompositeFrame*)frame);
758 }
759
760 return NULL;
761}
762
763// --------------------------------------------------------------------------
764//
765// Calls TCanvas::cd(), for the canvas returned by GetCanvas.
766//
767Bool_t MStatusDisplay::CdCanvas(const TString &name)
768{
769 TCanvas *c = GetCanvas(name);
770 if (!c)
771 return kFALSE;
772
773 c->cd();
774 return kTRUE;
775}
776
777TGCompositeFrame *MStatusDisplay::AddRawTab(const char *name)
778{
779 // Add new tab
780 TGCompositeFrame *f = fTab->AddTab(name);
781
782 // layout and map new tab
783 Layout();
784 MapSubwindows();
785 Layout();
786
787 // display new tab in the main frame
788 // FIXME: This is a workaround, because TApplication::Run is not
789 // thread safe against ProcessEvents. We assume, that if
790 // we are not in the Main-Thread ProcessEvents() is
791 // called by the TApplication Event Loop...
792 if (!TThread::Self()/*gApplication->InheritsFrom(TRint::Class())*/)
793 gClient->ProcessEventsFor(fTab);
794
795 *fLog << inf << "Adding Raw Tab '" << name << "' (" << f->GetWidth() << "x";
796 *fLog << f->GetHeight() << ")" << endl;
797
798 // return pointer to new canvas
799 return f;
800}
801
802// --------------------------------------------------------------------------
803//
804// Adds a new tab with the name 'name'. Adds a TRootEmbeddedCanvas to the
805// tab and returns a reference to the corresponding TCanvas.
806//
807TCanvas &MStatusDisplay::AddTab(const char *name)
808{
809 if (gROOT->IsBatch())
810 {
811 TCanvas *c = new TCanvas(name, name);
812 fBatch->Add(c);
813 return *c;
814 }
815
816 // Add new tab
817 TGCompositeFrame *f = fTab->AddTab(name);
818
819 // create root embedded canvas and add it to the tab
820 TRootEmbeddedCanvas *ec = new TRootEmbeddedCanvas(name, f, f->GetWidth(), f->GetHeight(), 0);
821 f->AddFrame(ec, fLayCanvas);
822 fList->Add(ec);
823
824 // set background and border mode of the canvas
825 TCanvas &c = *ec->GetCanvas();
826
827 c.SetFillColor(16/*165*//*17*//*203*/);
828 c.SetBorderMode(0);
829
830 // If kNoContextMenu set set kNoContextMenu of the canvas
831 if (TestBit(kNoContextMenu))
832 c.SetBit(kNoContextMenu);
833
834 // layout and map new tab
835 Layout(); // seems to layout the TGCompositeFrame
836 MapSubwindows(); // maps the TGCompositeFrame
837 Layout(); // layout the embedded canvas in the frame
838
839 // display new tab in the main frame
840 // FIXME: This is a workaround, because TApplication::Run is not
841 // thread safe against ProcessEvents. We assume, that if
842 // we are not in the Main-Thread ProcessEvents() is
843 // called by the TApplication Event Loop...
844 if (!TThread::Self()/*gApplication->InheritsFrom(TRint::Class())*/)
845 gClient->ProcessEventsFor(fTab);
846
847 *fLog << inf << "Adding Tab '" << name << "' (" << f->GetWidth() << "x";
848 *fLog << f->GetHeight() << ", TCanvas=" << &c << ")" << endl;
849
850 // return pointer to new canvas
851 return c;
852}
853
854// --------------------------------------------------------------------------
855//
856// Update a canvas in a tab, takes the corresponding TGCompositeFrame
857// as an argument. This is necessary, because not all functions
858// changing the contents of a canvas or pad can call SetModified()
859// for the corresponding tab. If this is not called correctly the
860// tab won't be updated calling TCanvas::Update(). So we simply
861// redraw it by our own (instead we could recursively call
862// TPad::Modified() for everything contained by the TCanvas and
863// call TCanvas::Update() afterwards)
864//
865void MStatusDisplay::UpdateTab(TGCompositeFrame *f)
866{
867 if (!f)
868 return;
869
870 TCanvas *c=GetCanvas(f);
871 if (!c)
872 return;
873
874 //
875 // If we are in a multithreaded environment (gThreadXAR) we
876 // have to make sure, that thus function is called from
877 // the main thread.
878 //
879 if (gThreadXAR)
880 {
881 // Tell the X-Requester how to call this method
882 TString str = Form("%d", (ULong_t)f);
883
884 TMethodCall call(IsA(), "UpdateTab", "NULL");
885 void *arr[4] = { NULL, &call, this, (void*)(const char*)str };
886
887 // If this is not the main thread return
888 if (((*gThreadXAR)("METH", 4, arr, NULL)))
889 return;
890 }
891
892 //
893 // Secure calls to update the tabs against itself, at least
894 // c->Paint() or c->Flush() may crash X (bad drawable).
895 // This makes sure, that a X call is not interuppted by
896 // another X-call which was started from an gui interrrupt
897 // in the same thread
898 //
899 if (fMutex->TryLock())
900 return;
901
902#if ROOT_VERSION_CODE < ROOT_VERSION(3,10,02)
903 TPad *padsav = (TPad*)gPad;
904 if (!gPad)
905 c->cd();
906#endif
907
908 if (!c->IsBatch())
909 c->FeedbackMode(kFALSE); // Goto double buffer mode
910
911 //
912 // Doing this ourself gives us the possibility to repaint
913 // the canvas in any case (Paint() instead of PaintModified())
914 //
915 c->Paint(); // Repaint all pads
916 c->Flush(); // Copy all pad pixmaps to the screen
917
918#if ROOT_VERSION_CODE < ROOT_VERSION(3,10,02)
919 if (padsav)
920 padsav->cd();
921 else
922 gPad=NULL;
923#endif
924
925 //c->SetCursor(kCross);
926
927 // Old version
928 //c->Modified();
929 //c->Update();
930 //c->Paint();
931
932 fMutex->UnLock();
933}
934
935// --------------------------------------------------------------------------
936//
937// Saves the given canvas (pad) or all pads (num<0) as a temporary
938// postscript file and prints it using 'lpr'. If a printer name is set
939// via SetPrinter 'lpr -Pname' is used.
940//
941Int_t MStatusDisplay::PrintToLpr(Int_t num)
942{
943 TString name = "mars";
944
945 for (int i=0; i<6; i++)
946 name += (char)(gRandom->Uniform(25)+65);
947
948 name += ".ps";
949
950 const Int_t pages = SaveAsPS(num, name);
951
952 SetStatusLine1("Printing...");
953 SetStatusLine2("");
954
955 if (!pages)
956 {
957 *fLog << warn << "MStatusDisplay::PrintToLpr: Sorry, couldn't save file as temporary postscript!" << endl;
958 SetStatusLine2("Failed!");
959 return 0;
960 }
961
962 TString cmd="lpr ";
963 if (!fPrinter.IsNull())
964 {
965 cmd += "-P";
966 cmd += fPrinter;
967 cmd += " ";
968 }
969 cmd += name;
970
971 gSystem->Exec(cmd);
972 gSystem->Unlink(name);
973
974 SetStatusLine2(Form("Done (%dpages)", pages));
975
976 return pages;
977}
978
979// --------------------------------------------------------------------------
980//
981// Remove tab no i if this tab contains a TRootEmbeddedCanvas
982//
983void MStatusDisplay::RemoveTab(int i)
984{
985 TGCompositeFrame *f = fTab->GetTabContainer(i);
986 if (!f)
987 return;
988
989 TRootEmbeddedCanvas *ec = GetEmbeddedCanvas(f);
990 if (!ec)
991 return;
992
993 TCanvas *c = ec->GetCanvas();
994 if (!c)
995 return;
996
997 const TString name(c->GetName());
998
999 f->RemoveFrame(ec);
1000 delete fList->Remove(ec);
1001
1002 fTab->RemoveTab(i);
1003 fTab->SetTab(0);
1004
1005 // Looks strange...
1006 // const Int_t n = fTab->GetNumberOfTabs();
1007 // fTab->SetTab(i<=n-1 ? i : i-1);
1008
1009 // layout and map new tab
1010 Layout(); // seems to layout the TGCompositeFrame
1011 MapSubwindows(); // maps the TGCompositeFrame
1012 Layout(); // layout the embedded canvas in the frame
1013
1014 // display new tab in the main frame
1015 // FIXME: This is a workaround, because TApplication::Run is not
1016 // thread safe against ProcessEvents. We assume, that if
1017 // we are not in the Main-Thread ProcessEvents() is
1018 // called by the TApplication Event Loop...
1019 if (!TThread::Self()/*gApplication->InheritsFrom(TRint::Class())*/)
1020 gClient->ProcessEventsFor(fTab);
1021
1022 *fLog << inf << "Removed Tab #" << i << " '" << name << "'" << endl;
1023}
1024
1025// --------------------------------------------------------------------------
1026//
1027// Use this to check whether the MStatusDisplay still contains the
1028// TCanvas c. It could be removed meanwhile by menu usage.
1029//
1030Bool_t MStatusDisplay::HasCanvas(const TCanvas *c) const
1031{
1032 if (!c)
1033 return kFALSE;
1034
1035 if (gROOT->IsBatch())
1036 return (Bool_t)fBatch->FindObject(c);
1037
1038 for (int i=1; i<fTab->GetNumberOfTabs(); i++)
1039 if (c==GetCanvas(i))
1040 return kTRUE;
1041 return kFALSE;
1042}
1043
1044/*
1045 if (...)
1046 fMenu->AddPopup("&CaOs", fCaOs, NULL);
1047 else
1048 fMenu->RemovePopup("CaOs");
1049 fMenu->Resize(fMenu->GetDefaultSize());
1050 MapSubwindows();
1051 MapWindow();
1052 */
1053
1054// --------------------------------------------------------------------------
1055//
1056// Process the kC_COMMAND, kCM_MENU messages
1057//
1058Bool_t MStatusDisplay::ProcessMessageCommandMenu(Long_t id)
1059{
1060 switch (id)
1061 {
1062 case kLoopStop:
1063 case kFileClose:
1064 case kFileExit:
1065 if (id==kFileExit || id==kFileClose)
1066 CloseWindow();
1067 fStatus = (Status_t)id;
1068 return kTRUE;
1069
1070 case kFileCanvas:
1071 new TCanvas;
1072 return kTRUE;
1073
1074 case kFileBrowser:
1075 new TBrowser;
1076 return kTRUE;
1077
1078 case kFileReset:
1079 for (int i=fTab->GetNumberOfTabs()-1; i>0; i--)
1080 RemoveTab(i);
1081 return kTRUE;
1082 /*
1083 case kFileSave:
1084 cout << "Save..." << endl;
1085 return kTRUE;
1086
1087 case kFileSaveAs:
1088 cout << "SaveAs..." << endl;
1089 return kTRUE;
1090*/
1091 case kFileSaveAsPS:
1092 SaveAsPS();
1093 return kTRUE;
1094
1095 case kFileSaveAsGIF:
1096 SaveAsGIF();
1097 return kTRUE;
1098
1099 case kFileSaveAsC:
1100 SaveAsC();
1101 return kTRUE;
1102
1103 case kFileSaveAsRoot:
1104 SaveAsRoot();
1105 return kTRUE;
1106
1107 case kFilePrint:
1108 PrintToLpr();
1109 return kTRUE;
1110
1111 case kTabSaveAsPS:
1112 SaveAsPS(fTab->GetCurrent());
1113 return kTRUE;
1114
1115 case kTabSaveAsGIF:
1116 SaveAsGIF(fTab->GetCurrent());
1117 return kTRUE;
1118
1119 case kTabSaveAsC:
1120 SaveAsC(fTab->GetCurrent());
1121 return kTRUE;
1122
1123 case kTabSaveAsRoot:
1124 SaveAsRoot(fTab->GetCurrent());
1125 return kTRUE;
1126
1127 case kTabPrint:
1128 PrintToLpr(fTab->GetCurrent());
1129 return kTRUE;
1130
1131 case kTabNext:
1132 fTab->SetTab(fTab->GetCurrent()+1);
1133 return kTRUE;
1134
1135 case kTabPrevious:
1136 fTab->SetTab(fTab->GetCurrent()-1);
1137 return kTRUE;
1138
1139 case kTabRemove:
1140 RemoveTab(fTab->GetCurrent());
1141 return kTRUE;
1142
1143 case kSize640:
1144 Resize(570, 480);
1145 return kTRUE;
1146 case kSize800:
1147 Resize(740, 600);
1148 return kTRUE;
1149 case kSize960:
1150 Resize(880, 700);
1151 return kTRUE;
1152 case kSize1024:
1153 Resize(980, 768);
1154 return kTRUE;
1155 case kSize1280:
1156 Resize(1280, 980);
1157 return kTRUE;
1158
1159 case kLogClear:
1160 fLogBox->Clear();
1161 return kTRUE;
1162 case kLogCopy:
1163 fLogBox->Copy();
1164 return kTRUE;
1165 case kLogSelect:
1166 fLogBox->SelectAll();
1167 return kTRUE;
1168 case kLogFind:
1169 new MSearch(this);
1170 return kTRUE;
1171 case kLogSave:
1172 SetStatusLine1("Saving log...");
1173 SetStatusLine2("");
1174 *fLog << inf << "Saving log... " << flush;
1175 if (fLogBox->GetText()->Save("statusdisplay.log"))
1176 {
1177 *fLog << "done." << endl;
1178 SetStatusLine2("done.");
1179 }
1180 else
1181 {
1182 *fLog << "failed!" << endl;
1183 SetStatusLine2("Failed!");
1184 }
1185 return kTRUE;
1186
1187 case kLogAppend:
1188 SetStatusLine1("Appending logg...");
1189 SetStatusLine2("");
1190 *fLog << inf << "Appending log... " << flush;
1191 if (fLogBox->GetText()->Append("statusdisplay.log"))
1192 {
1193 *fLog << "done." << endl;
1194 SetStatusLine2("done.");
1195 }
1196 else
1197 {
1198 *fLog << "failed!" << endl;
1199 SetStatusLine2("Failed!");
1200 }
1201 return kTRUE;
1202#ifdef DEBUG
1203 default:
1204 cout << "Command-Menu #" << id << endl;
1205#endif
1206 }
1207 return kTRUE;
1208
1209}
1210
1211// --------------------------------------------------------------------------
1212//
1213// Process the kC_COMMAND messages
1214//
1215Bool_t MStatusDisplay::ProcessMessageCommand(Long_t submsg, Long_t mp1, Long_t mp2)
1216{
1217 switch (submsg)
1218 {
1219 case kCM_MENU:
1220 return ProcessMessageCommandMenu(mp1); // mp2=userdata
1221 case kCM_TAB:
1222 /*
1223 for (int i=0; i<fTab->GetNumberOfTabs(); i++)
1224 fTab->GetTabContainer(i)->UnmapWindow();
1225 */
1226 UpdateTab(fTab->GetTabContainer(mp1));
1227 //fTab->GetTabContainer(mp1)->MapWindow();
1228
1229 /*
1230 if (mp1>0)
1231 fMenu->AddPopup("&CaOs", fCaOs, NULL);
1232 else
1233 fMenu->RemovePopup("CaOs");
1234 fMenu->Resize(fMenu->GetDefaultSize());
1235 MapSubwindows();
1236 MapWindow();
1237 */
1238 return kTRUE;
1239#ifdef DEBUG
1240 case kCM_MENUSELECT:
1241 cout << "Command-Menuselect #" << mp1 << " (UserData=" << (void*)mp2 << ")" << endl;
1242 return kTRUE;
1243
1244 case kCM_BUTTON:
1245 cout << "Command-Button." << endl;
1246 return kTRUE;
1247
1248 case kCM_CHECKBUTTON:
1249 cout << "Command-CheckButton." << endl;
1250 return kTRUE;
1251
1252 case kCM_RADIOBUTTON:
1253 cout << "Command-RadioButton." << endl;
1254 return kTRUE;
1255
1256 case kCM_LISTBOX:
1257 cout << "Command-Listbox #" << mp1 << " (LineId #" << mp2 << ")" << endl;
1258 return kTRUE;
1259
1260 case kCM_COMBOBOX:
1261 cout << "Command-ComboBox." << endl;
1262 return kTRUE;
1263 default:
1264 cout << "Command: " << "Submsg:" << submsg << " Mp1=" << mp1 << " Mp2=" << mp2 << endl;
1265#endif
1266 }
1267 return kTRUE;
1268}
1269
1270// --------------------------------------------------------------------------
1271//
1272// Process the kC_TEXTVIEW messages
1273//
1274Bool_t MStatusDisplay::ProcessMessageTextview(Long_t submsg, Long_t mp1, Long_t mp2)
1275{
1276 // kC_TEXTVIEW, kTXT_ISMARKED, widget id, [true|false] //
1277 // kC_TEXTVIEW, kTXT_DATACHANGE, widget id, 0 //
1278 // kC_TEXTVIEW, kTXT_CLICK2, widget id, position (y << 16) | x) //
1279 // kC_TEXTVIEW, kTXT_CLICK3, widget id, position (y << 16) | x) //
1280 // kC_TEXTVIEW, kTXT_F3, widget id, true //
1281 // kC_TEXTVIEW, kTXT_OPEN, widget id, 0 //
1282 // kC_TEXTVIEW, kTXT_CLOSE, widget id, 0 //
1283 // kC_TEXTVIEW, kTXT_SAVE, widget id, 0 //
1284#ifdef DEBUG
1285 switch (submsg)
1286 {
1287 case kTXT_ISMARKED:
1288 cout << "Textview-IsMarked #" << mp1 << " " << (mp2?"yes":"no") << endl;
1289 return kTRUE;
1290
1291 case kTXT_DATACHANGE:
1292 cout << "Textview-DataChange #" << mp1 << endl;
1293 return kTRUE;
1294
1295 case kTXT_CLICK2:
1296 cout << "Textview-Click2 #" << mp1 << " x=" << (mp2&0xffff) << " y= " << (mp2>>16) << endl;
1297 return kTRUE;
1298
1299 case kTXT_CLICK3:
1300 cout << "Textview-Click3 #" << mp1 << " x=" << (mp2&0xffff) << " y= " << (mp2>>16) << endl;
1301 return kTRUE;
1302
1303 case kTXT_F3:
1304 cout << "Textview-F3 #" << mp1 << endl;
1305 return kTRUE;
1306
1307 case kTXT_OPEN:
1308 cout << "Textview-Open #" << mp1 << endl;
1309 return kTRUE;
1310
1311 case kTXT_CLOSE:
1312 cout << "Textview-Close #" << mp1 << endl;
1313 return kTRUE;
1314
1315 case kTXT_SAVE:
1316 cout << "Textview-Save #" << mp1 << endl;
1317 return kTRUE;
1318
1319 default:
1320 cout << "Textview: " << "Submsg:" << submsg << " Mp1=" << mp1 << " Mp2=" << mp2 << endl;
1321 }
1322#endif
1323 return kTRUE;
1324}
1325
1326// --------------------------------------------------------------------------
1327//
1328// Process the kC_USER messages
1329//
1330Bool_t MStatusDisplay::ProcessMessageUser(Long_t submsg, Long_t mp1, Long_t mp2)
1331{
1332 // kS_START, case sensitive | backward<<1, char *txt
1333 switch (submsg)
1334 {
1335 case kS_START:
1336 fLogBox->Search((char*)mp2, !(mp1&2>>1), mp1&1);
1337 return kTRUE;
1338#ifdef DEBUG
1339 default:
1340 cout << "User: " << "Submsg:" << submsg << " Mp1=" << mp1 << " Mp2=" << mp2 << endl;
1341#endif
1342 }
1343 return kTRUE;
1344}
1345
1346// --------------------------------------------------------------------------
1347//
1348// Process the messages from the GUI
1349//
1350Bool_t MStatusDisplay::ProcessMessage(Long_t msg, Long_t mp1, Long_t mp2)
1351{
1352 // Can be found in WidgetMessageTypes.h
1353 cout << "Msg: " << GET_MSG(msg) << " Submsg:" << GET_SUBMSG(msg);
1354 cout << " Mp1=" << mp1 << " Mp2=" << mp2 << endl;
1355 switch (GET_MSG(msg))
1356 {
1357 case kC_COMMAND:
1358 return ProcessMessageCommand(GET_SUBMSG(msg), mp1, mp2);
1359
1360 case kC_TEXTVIEW:
1361 return ProcessMessageTextview(GET_SUBMSG(msg), mp1, mp2);
1362
1363 case kC_USER:
1364 return ProcessMessageUser(GET_SUBMSG(msg), mp1, mp2);
1365 }
1366#ifdef DEBUG
1367 cout << "Msg: " << GET_MSG(msg) << " Submsg:" << GET_SUBMSG(msg);
1368 cout << " Mp1=" << mp1 << " Mp2=" << mp2 << endl;
1369#endif
1370 return kTRUE;
1371}
1372
1373void MStatusDisplay::CloseWindow()
1374{
1375 // Got close message for this MainFrame. Calls parent CloseWindow()
1376 // (which destroys the window) and terminate the application.
1377 // The close message is generated by the window manager when its close
1378 // window menu item is selected.
1379
1380 // CloseWindow must be overwritten because otherwise CloseWindow
1381 // and the destructor are calling DestroyWindow which seems to be
1382 // in conflict with the TRootEmbeddedCanvas.
1383
1384 // FIXME: Make sure that the Status Display is deleted from every
1385 // where (eg Eventloop) first!
1386
1387 gLog << dbg << "MStatusDisplay is on heap: " << (int)IsOnHeap() << endl;
1388
1389 if (TestBit(kExitLoopOnExit))
1390 gSystem->ExitLoop();
1391 if (TestBit(kExitLoopOnClose))
1392 gSystem->ExitLoop();
1393
1394 if (fIsLocked<=0 && IsOnHeap())
1395 delete this;
1396 fStatus = kFileExit;
1397}
1398
1399// --------------------------------------------------------------------------
1400//
1401// Calls SetBit(kNoContextMenu) for all TCanvas objects found in the
1402// Tabs.
1403//
1404void MStatusDisplay::SetNoContextMenu(Bool_t flag)
1405{
1406 if (fIsLocked>1 || gROOT->IsBatch())
1407 return;
1408
1409 flag ? SetBit(kNoContextMenu) : ResetBit(kNoContextMenu);
1410
1411 for (int i=1; i<fTab->GetNumberOfTabs(); i++)
1412 {
1413 TCanvas *c = GetCanvas(i);
1414 if (c)
1415 flag ? c->SetBit(kNoContextMenu) : c->ResetBit(kNoContextMenu);
1416 }
1417}
1418
1419// --------------------------------------------------------------------------
1420//
1421// Updates the canvas (if existing) in the currenly displayed Tab.
1422// The update intervall is controlled by StartUpdate and StopUpdate
1423//
1424Bool_t MStatusDisplay::HandleTimer(TTimer *timer)
1425{
1426 if (gROOT->IsBatch())
1427 return kTRUE;
1428
1429 const Int_t c = fTab->GetCurrent();
1430
1431 // Skip Legend Tab
1432 if (c==0)
1433 return kTRUE;
1434
1435 // Update a canvas tab (if visible)
1436 if (timer==&fTimer && c!=fLogIdx)
1437 {
1438 UpdateTab(fTab->GetCurrentContainer());
1439 return kTRUE;
1440 }
1441
1442 // update the logbook tab (if visible)
1443 if (timer==&fLogTimer && c==fLogIdx)
1444 {
1445 fLog->UpdateGui();
1446
1447 /*
1448 if (!fLogBox->TestBit(kHasChanged))
1449 return kTRUE;
1450
1451 fLogBox->ResetBit(kHasChanged);
1452 */
1453 return kTRUE;
1454 }
1455
1456 return kTRUE;
1457}
1458
1459// --------------------------------------------------------------------------
1460//
1461// Draws a clone of a canvas into a new canvas. Taken from TCanvas.
1462//
1463void MStatusDisplay::DrawClonePad(TCanvas &newc, const TCanvas &oldc) const
1464{
1465 //copy pad attributes
1466 newc.Range(oldc.GetX1(),oldc.GetY1(),oldc.GetX2(),oldc.GetY2());
1467 newc.SetTickx(oldc.GetTickx());
1468 newc.SetTicky(oldc.GetTicky());
1469 newc.SetGridx(oldc.GetGridx());
1470 newc.SetGridy(oldc.GetGridy());
1471 newc.SetLogx(oldc.GetLogx());
1472 newc.SetLogy(oldc.GetLogy());
1473 newc.SetLogz(oldc.GetLogz());
1474 newc.SetBorderSize(oldc.GetBorderSize());
1475 newc.SetBorderMode(oldc.GetBorderMode());
1476 ((TAttLine&)oldc).Copy((TAttLine&)newc);
1477 ((TAttFill&)oldc).Copy((TAttFill&)newc);
1478 ((TAttPad&)oldc).Copy((TAttPad&)newc);
1479
1480 //copy primitives
1481 TObject *obj;
1482 TIter next(oldc.GetListOfPrimitives());
1483 while ((obj=next())) {
1484 gROOT->SetSelectedPad(&newc);
1485 newc.GetListOfPrimitives()->Add(obj->Clone(),obj->GetDrawOption());
1486 }
1487 newc.Modified();
1488 newc.Update();
1489}
1490
1491// --------------------------------------------------------------------------
1492//
1493// Reads the contents of a saved MStatusDisplay from a file.
1494//
1495Int_t MStatusDisplay::Read(const char *name)
1496{
1497 if (!gFile)
1498 {
1499 *fLog << warn << "MStatusDisplay::Read: No file found. Please create a TFile first." << endl;
1500 return 0;
1501 }
1502
1503 if (!gFile->IsOpen())
1504 {
1505 *fLog << warn << "MStatusDisplay::Read: File not open. Please open the TFile first." << endl;
1506 return 0;
1507 }
1508
1509 TObjArray list;
1510
1511 const Int_t n = list.Read(name);
1512 if (n==0)
1513 {
1514 *fLog << warn << "MStatusDisplay::Read: No objects read." << endl;
1515 return 0;
1516 }
1517
1518 TIter Next(&list);
1519 TCanvas *c;
1520 while ((c=(TCanvas*)Next()))
1521 DrawClonePad(AddTab(c->GetName()), *c);
1522
1523 *fLog << inf << "MStatusDisplay: Key " << name << " with " << n << " keys read from file." << endl;
1524
1525 return n;
1526}
1527
1528// --------------------------------------------------------------------------
1529//
1530// Writes the contents of a MStatusDisplay to a file.
1531//
1532Int_t MStatusDisplay::Write(Int_t num, const char *name, Int_t option, Int_t bufsize)
1533{
1534 if (!gFile)
1535 {
1536 *fLog << warn << "MStatusDisplay::Write: No file found. Please create a TFile first." << endl;
1537 return 0;
1538 }
1539
1540 if (!gFile->IsOpen())
1541 {
1542 *fLog << warn << "MStatusDisplay::Write: File not open. Please open the TFile first." << endl;
1543 return 0;
1544 }
1545
1546 if (!gFile->IsWritable())
1547 {
1548 *fLog << warn << "MStatusDisplay::Write: File not writable." << endl;
1549 return 0;
1550 }
1551
1552 if (num==0)
1553 {
1554 *fLog << warn << "MStatusDisplay::Write: Tab doesn't contain an embedded Canvas... skipped." << endl;
1555 return 0;
1556 }
1557
1558 if (!gROOT->IsBatch() && num>=fTab->GetNumberOfTabs())
1559 {
1560 *fLog << warn << "MStatusDisplay::Write: Tab doesn't exist... skipped." << endl;
1561 return 0;
1562 }
1563 if (gROOT->IsBatch() && num>fBatch->GetSize())
1564 {
1565 *fLog << warn << "MStatusDisplay::Write: Tab doesn't exist... skipped." << endl;
1566 return 0;
1567 }
1568
1569 TObjArray list;
1570
1571 const Int_t max = gROOT->IsBatch() ? fBatch->GetSize()+1 : fTab->GetNumberOfTabs();
1572 const Int_t from = num<0 ? 1 : num;
1573 const Int_t to = num<0 ? max : num+1;
1574
1575 TCanvas *c;
1576 for (int i=from; i<to; i++)
1577 if ((c = GetCanvas(i)))
1578 list.Add(c);
1579
1580 const Int_t n = list.Write(name, kSingleKey);
1581
1582 *fLog << inf << "MStatusDisplay: " << n << " keys written to file as key " << name << "." << endl;
1583
1584 return n;
1585}
1586
1587// --------------------------------------------------------------------------
1588//
1589// Use this to start the synchronous (GUI eventloop driven) tab update.
1590// Can also be used to change the update intervall. If millisec<0
1591// the intervall given in SetUpdateTime is used. If the intervall in
1592// SetUpdateTime is <0 nothing is done. (Call SetUpdateTime(-1) to
1593// disable the automatic update in a MEventloop.
1594//
1595void MStatusDisplay::StartUpdate(Int_t millisec)
1596{
1597 if (fIsLocked>1)
1598 return;
1599
1600 if (fTimer.GetTime()<TTime(0))
1601 return;
1602 fTimer.Start(millisec);
1603}
1604
1605// --------------------------------------------------------------------------
1606//
1607// Stops the automatic GUI update
1608//
1609void MStatusDisplay::StopUpdate()
1610{
1611 if (fIsLocked>1)
1612 return;
1613
1614 fTimer.Stop();
1615}
1616
1617// --------------------------------------------------------------------------
1618//
1619// Set the update interval for the GUI update, see StartUpdate.
1620//
1621void MStatusDisplay::SetUpdateTime(Long_t t)
1622{
1623 fTimer.SetTime(t);
1624}
1625
1626// --------------------------------------------------------------------------
1627//
1628// Set the background color in a canvas
1629//
1630void MStatusDisplay::CanvasSetFillColor(TPad &p, Int_t col) const
1631{
1632 TObject *obj;
1633
1634 // See also TPad::UseCurrentStyle
1635 TIter Next(p.GetListOfPrimitives());
1636 while ((obj=Next()))
1637 {
1638 if (obj->InheritsFrom(TPad::Class()))
1639 CanvasSetFillColor(*(TPad*)obj, col);
1640 if (obj->InheritsFrom(TFrame::Class()))
1641 ((TFrame*)obj)->SetFillColor(col);
1642 }
1643
1644 p.SetFillColor(col);
1645}
1646
1647void MStatusDisplay::AddExtension(TString &name, const TString &ext, Int_t num) const
1648{
1649 if (name.IsNull())
1650 {
1651 name = "status";
1652 if (num>0)
1653 {
1654 name += "-";
1655 name += num;
1656 }
1657 }
1658
1659 if (name.EndsWith("."+ext))
1660 return;
1661
1662 name += ".";
1663 name += ext;
1664}
1665
1666Bool_t MStatusDisplay::CheckTabForCanvas(int num) const
1667{
1668 if (gROOT->IsBatch())
1669 return num>0 && num<=fBatch->GetSize() || num<0;
1670
1671 if (num>=fTab->GetNumberOfTabs())
1672 {
1673 *fLog << warn << "Tab #" << num << " doesn't exist..." << endl;
1674 return kFALSE;
1675 }
1676 if (num==0)
1677 {
1678 *fLog << warn << "Tab #" << num << " doesn't contain an embedded canvas..." << endl;
1679 return kFALSE;
1680 }
1681 if (fTab->GetNumberOfTabs()<2 || !gPad)
1682 {
1683 *fLog << warn << "Sorry, you must have at least one existing canvas (gPad!=NULL)" << endl;
1684 return kFALSE;
1685 }
1686 return kTRUE;
1687}
1688
1689// --------------------------------------------------------------------------
1690//
1691// Insert the following two lines into the postscript header:
1692//
1693// %%DocumentPaperSizes: a4
1694// %%Orientation: Landscape
1695//
1696void MStatusDisplay::UpdatePSHeader(const TString &name) const
1697{
1698 const TString newstr("%%DocumentPaperSizes: a4\n%%Orientation: Landscape\n");
1699 const Int_t l = newstr.Length();
1700
1701 Long_t t[4]; // { id, size, flags, modtime }
1702 gSystem->GetPathInfo(name, t, t+1, t+2, t+3);
1703
1704 char *c[2] = { new char[l], new char[l] };
1705
1706 fstream f(name, ios::in|ios::out);
1707
1708 TString str;
1709 f >> str >> c[0][0]; // Read "%!PS-Adobe-2.0\n" (Mini Header)
1710 f.read(c[0], l);
1711 f.seekp(-l, ios::cur);
1712 f.write(newstr, l);
1713
1714 int i=0;
1715 while (1)
1716 {
1717 f.read(c[(i+1)%2], l);
1718 f.seekp(-l, ios::cur);
1719
1720 if (f)
1721 {
1722 f.write(c[i%2],l);
1723 i++;
1724 i%=2;
1725 continue;
1726 }
1727
1728 const Int_t ssz = str.Length()+1; // Length of Mini-Header
1729 const Int_t block = t[1]-ssz; // Length of block to be shifted
1730 const Int_t size = block%l; // Reminder
1731 const Int_t pos = (block/l)*l + ssz + 1; // Position to start writing
1732
1733 f.clear();
1734 f.seekp(pos);
1735 f.write(c[i%2], l);
1736 f.write(c[(i+1)%2], size);
1737 break;
1738 }
1739
1740 delete c[1];
1741 delete c[0];
1742}
1743
1744// --------------------------------------------------------------------------
1745//
1746// In case of num<0 all tabs are written into the PS file. If num>0
1747// the canvas in the corresponding tab is written to the file.
1748// Name is the name of the file (with or without extension).
1749//
1750// Returns the number of pages written.
1751//
1752// To write all tabs you can also use SaveAsPS(name)
1753//
1754Int_t MStatusDisplay::SaveAsPS(Int_t num, TString name)
1755{
1756 SetStatusLine1("Writing Postscript file...");
1757 SetStatusLine2("");
1758
1759 if (!CheckTabForCanvas(num))
1760 {
1761 SetStatusLine2("Failed!");
1762 return 0;
1763 }
1764
1765 AddExtension(name, "ps", num);
1766
1767 if (num<0)
1768 *fLog << inf << "Open ps-File: " << name << endl;
1769
1770 TPad *padsav = (TPad*)gPad;
1771 TVirtualPS *psave = gVirtualPS;
1772
1773 TDatime d;
1774
1775 TPostScript ps(name, 112);
1776 ps.SetBit(TPad::kPrintingPS);
1777 ps.PrintFast(13, "/nan {1} def ");
1778
1779 gVirtualPS = &ps;
1780
1781 //
1782 // Create a list to delete the canvas clones
1783 //
1784 TList l;
1785 l.SetOwner();
1786
1787 //
1788 // Create some GUI elements for a page legend
1789 //
1790 TLine line;
1791
1792 int page = 1;
1793
1794 //
1795 // Maintain tab numbers
1796 //
1797 const Int_t max = gROOT->IsBatch() ? fBatch->GetSize()+1 : fTab->GetNumberOfTabs();
1798 const Int_t from = num<0 ? 1 : num;
1799 const Int_t to = num<0 ? max : num+1;
1800
1801 for (int i=from; i<to; i++)
1802 {
1803 TCanvas *c;
1804 if (!(c = GetCanvas(i)))
1805 {
1806 if (num<0)
1807 *fLog << inf << " - ";
1808 *fLog << "Tab #" << i << " doesn't contain an embedded Canvas... skipped." << endl;
1809 continue;
1810 }
1811
1812 SetStatusLine2(Form("Tab #%d", i));
1813
1814 //
1815 // Init page and page size, make sure, that the canvas in the file
1816 // has the same Aspect Ratio than on the screen.
1817 //
1818 ps.NewPage();
1819
1820 //
1821 // 26 is used here to scale the canvas into a height of 26,
1822 // such that the page title can be set above the canvas...
1823 //
1824 Float_t psw = 26; //29.7; // A4 - width
1825 Float_t psh = 21.0; // A4 - height
1826
1827 const Float_t cw = c->GetWw();
1828 const Float_t ch = c->GetWh();
1829
1830 if (psw/psh>cw/ch)
1831 psw = cw/ch*psh;
1832 else
1833 psh = ch/cw*psw;
1834
1835 ps.Range(psw, psh); // A4
1836
1837 //
1838 // Clone canvas and change background color and schedule for
1839 // deletion
1840 //
1841 TCanvas *n = (TCanvas*)c->Clone();
1842 CanvasSetFillColor(*n, kWhite);
1843 l.Add(n);
1844 //
1845 // Paint canvas into root file
1846 //
1847 if (num<0)
1848 *fLog << inf << " - ";
1849 *fLog << inf << "Writing Tab #" << i << ": " << c->GetName() << " (" << c << ") ";
1850 if (num>0)
1851 *fLog << "to " << name;
1852 *fLog << "..." << flush;
1853
1854 n->SetBatch(kTRUE);
1855 n->Paint();
1856
1857 //
1858 // Use the canvas as coordinate system for the overlaying text
1859 //
1860 gPad = n;
1861
1862 //
1863 // Print overlaying text (NDC = %)
1864 //
1865 ps.SetTextColor(kBlack);
1866 ps.SetTextSize(0.015);
1867 ps.SetTextFont(22);
1868 ps.SetTextAlign(11); // left top
1869 ps.TextNDC(0, 1.02, TString(" ")+n->GetName());
1870 ps.SetTextAlign(21); // cent top
1871 ps.TextNDC(0.5, 1.02, TString("MARS - Magic Analysis and Reconstruction Software - ")+d.AsString());
1872 ps.SetTextAlign(31); // right top
1873 ps.TextNDC(1, 1.02, Form("Page No.%i (%i) ", page++, i));
1874 line.PaintLineNDC(0, 1.015, 1, 1.015);
1875
1876 //
1877 // Finish drawing page
1878 //
1879 n->SetBatch(kFALSE);
1880 if (num<0)
1881 *fLog << "done." << endl;
1882 }
1883
1884 gPad = NULL; // Important!
1885 l.Delete();
1886
1887 ps.Close();
1888 UpdatePSHeader(name);
1889
1890 gVirtualPS = psave;
1891 if (padsav)
1892 padsav->cd();
1893
1894 *fLog << inf << "done." << endl;
1895
1896 SetStatusLine2(Form("Done (%dpages)", page-1));
1897
1898 return page-1;
1899}
1900
1901Bool_t MStatusDisplay::SaveAsGIF(Int_t num, TString name)
1902{
1903 if (gROOT->IsBatch())
1904 {
1905 *fLog << warn << "Sorry, writing gif-files is not available in batch mode." << endl;
1906 return 0;
1907 }
1908 SetStatusLine1("Writing GIF file...");
1909 SetStatusLine2("");
1910
1911 if (!CheckTabForCanvas(num))
1912 {
1913 SetStatusLine2("Failed!");
1914 return 0;
1915 }
1916
1917 AddExtension(name, "gif", num);
1918
1919 if (num<0)
1920 *fLog << inf << "Writing gif-Files..." << endl;
1921
1922 TPad *padsav = (TPad*)gPad;
1923
1924 int page = 1;
1925
1926 //
1927 // Maintain tab numbers
1928 //
1929 const Int_t from = num<0 ? 1 : num;
1930 const Int_t to = num<0 ? fTab->GetNumberOfTabs() : num+1;
1931
1932 for (int i=from; i<to; i++)
1933 {
1934 TCanvas *c;
1935 if (!(c = GetCanvas(i)))
1936 {
1937 if (num<0)
1938 *fLog << inf << " - ";
1939 *fLog << "Tab #" << i << " doesn't contain an embedded Canvas... skipped." << endl;
1940 continue;
1941 }
1942
1943 SetStatusLine2(Form("Tab #%d", i));
1944
1945 //
1946 // Clone canvas and change background color and schedule for
1947 // deletion
1948 //
1949 //TCanvas *n = (TCanvas*)c->Clone();
1950 //CanvasSetFillColor(*n, kWhite);
1951
1952 //
1953 // Paint canvas into root file
1954 //
1955 TString writename = name;
1956 if (num<0)
1957 {
1958 TString numname = "-";
1959 numname += i;
1960 writename.Insert(name.Last('.'), numname);
1961 }
1962 if (num<0)
1963 *fLog << inf << " - ";
1964 *fLog << inf << "Writing Tab #" << i << " to " << writename << ": " << c->GetName() << " (" << c << ") ";
1965 if (num>0)
1966 *fLog << "to " << name;
1967 *fLog << "..." << flush;
1968
1969 c->Draw();
1970 c->SaveAs(writename);
1971 /*
1972 n->Draw();
1973 n->SaveAs(writename);
1974 delete n;
1975 */
1976
1977 if (num<0)
1978 *fLog << "done." << endl;
1979 }
1980
1981 padsav->cd();
1982
1983 *fLog << inf << "done." << endl;
1984
1985 SetStatusLine2("Done.");
1986
1987 return page-1;
1988}
1989
1990Bool_t MStatusDisplay::SaveAsC(Int_t num, TString name)
1991{
1992 SetStatusLine1("Writing C++ file...");
1993 SetStatusLine2("");
1994
1995 if (!CheckTabForCanvas(num))
1996 {
1997 SetStatusLine2("Failed!");
1998 return 0;
1999 }
2000
2001 AddExtension(name, "C", num);
2002
2003 if (num<0)
2004 *fLog << inf << "Writing C-Files..." << endl;
2005
2006 TPad *padsav = (TPad*)gPad;
2007
2008 int page = 1;
2009
2010 //
2011 // Maintain tab numbers
2012 //
2013 const Int_t from = num<0 ? 1 : num;
2014 const Int_t to = num<0 ? fTab->GetNumberOfTabs() : num+1;
2015
2016 for (int i=from; i<to; i++)
2017 {
2018 TCanvas *c;
2019 if (!(c = GetCanvas(i)))
2020 {
2021 if (num<0)
2022 *fLog << inf << " - ";
2023 *fLog << "Tab #" << i << " doesn't contain an embedded Canvas... skipped." << endl;
2024 continue;
2025 }
2026
2027 SetStatusLine2(Form("Tab #%d", i));
2028
2029 //
2030 // Clone canvas and change background color and schedule for
2031 // deletion
2032 //
2033 TCanvas *n = (TCanvas*)c->Clone();
2034 CanvasSetFillColor(*n, kWhite);
2035
2036 //
2037 // Paint canvas into root file
2038 //
2039 TString writename = name;
2040 if (num<0)
2041 {
2042 TString numname = "-";
2043 numname += i;
2044 writename.Insert(name.Last('.'), numname);
2045 }
2046 if (num<0)
2047 *fLog << inf << " - ";
2048 *fLog << inf << "Writing Tab #" << i << " to " << writename << ": " << c->GetName() << " (" << n << ") ";
2049 if (num>0)
2050 *fLog << "to " << name;
2051 *fLog << "..." << flush;
2052
2053 n->SaveSource(writename, "");
2054 delete n;
2055
2056 if (num<0)
2057 *fLog << "done." << endl;
2058 }
2059
2060 padsav->cd();
2061
2062 *fLog << inf << "done." << endl;
2063
2064 SetStatusLine2("Done.");
2065
2066 return page-1;
2067}
2068
2069// --------------------------------------------------------------------------
2070//
2071// In case of num<0 all tabs are written into the PS file. If num>0
2072// the canvas in the corresponding tab is written to the file.
2073// Name is the name of the file (with or without extension).
2074//
2075// Returns the number of keys written.
2076//
2077// To write all tabs you can also use SaveAsPS(name)
2078//
2079Int_t MStatusDisplay::SaveAsRoot(Int_t num, TString name)
2080{
2081 SetStatusLine1("Writing root file...");
2082 SetStatusLine2("");
2083
2084 if (!CheckTabForCanvas(num))
2085 {
2086 SetStatusLine2("Failed!");
2087 return 0;
2088 }
2089
2090 AddExtension(name, "root", num);
2091
2092 TFile *fsave = gFile;
2093 TFile file(name, "RECREATE", "MARS - Status Window Contents", 9);
2094 const Int_t keys = Write(num);
2095 gFile = fsave;
2096
2097 SetStatusLine2("Done.");
2098
2099 return keys;
2100}
2101
2102Bool_t MStatusDisplay::HandleConfigureNotify(Event_t *evt)
2103{
2104 //
2105 // The initialization of the GUI is not yet enough finished...
2106 //
2107 if (!fTab)
2108 return kTRUE;
2109
2110 UInt_t w = evt->fWidth;
2111 UInt_t h = evt->fHeight;
2112
2113 /*
2114 cout << "Old: " << GetWidth() << " " << GetHeight() << " " << GetBorderWidth() << endl;
2115 cout << "New: " << w << " " << h << " ";
2116 cout << "New: " << GetDefaultWidth() << " " << GetDefaultHeight() << " " << endl;
2117 */
2118
2119 //Bool_t wchanged = w!=GetWidth();
2120 Bool_t hchanged = h!=GetHeight();
2121 /*
2122 if (!wchanged && !hchanged)
2123 {
2124 Layout();
2125 // FIXME: Make sure that this doesn't result in endless loops.
2126 // return kTRUE;
2127 }
2128 */
2129
2130 if (GetWidth()==1 && GetHeight()==1)
2131 return kTRUE;
2132
2133 // calculate the constant part of the window
2134 const UInt_t cw = GetWidth() -fTab->GetWidth();
2135 const UInt_t ch = GetHeight()-fTab->GetHeight();
2136
2137 // calculate new size of frame (canvas @ 1:sqrt(2))
2138 if (hchanged)
2139 w = (UInt_t)((h-ch)*sqrt(2.)+.5)+cw;
2140 else
2141 h = (UInt_t)((w-cw)/sqrt(2.)+.5)+ch;
2142
2143 // resize frame
2144 Resize(w, h);
2145
2146 return kTRUE;
2147}
2148
2149Bool_t MStatusDisplay::HandleEvent(Event_t *event)
2150{
2151 Bool_t rc = TGMainFrame::HandleEvent(event);
2152
2153 //
2154 // This fixes a bug in older root versions which makes
2155 // TCanvas crash if gPad==NULL. So we make sure, that
2156 // gPad!=NULL -- be carfull, this may have other side
2157 // effects.
2158 //
2159#if ROOT_VERSION_CODE < ROOT_VERSION(3,10,01)
2160 if (!gPad && fTab)
2161 for (int i=0; i<fTab->GetNumberOfTabs(); i++)
2162 {
2163 TCanvas *c = GetCanvas(i);
2164 if (c)
2165 {
2166 c->cd();
2167 gLog << dbg << "MStatusDisplay::HandleEvent - Workaround: gPad=" << gPad << "." << endl;
2168 break;
2169 }
2170 }
2171#endif
2172
2173 return rc;
2174}
2175
2176/*
2177 // --------------------------------------------------------------------------
2178//
2179// Opens a save as dialog, and tries to store the canvas
2180// in the given output format
2181//
2182void MGEvtDisplay::SaveAsDialog() const
2183{
2184 static const char *gSaveAsTypes[] =
2185 {
2186 "PostScript", "*.ps",
2187 "Encapsulated PostScript", "*.eps",
2188 "Gif files", "*.gif",
2189 "Macro files", "*.C",
2190 "ROOT files", "*.root",
2191 "All files", "*",
2192 NULL, NULL
2193 };
2194
2195 static TString dir(".");
2196
2197 TGFileInfo fi; // fFileName and fIniDir deleted in ~TGFileInfo
2198
2199 fi.fFileTypes = (const char**)gSaveAsTypes;
2200 fi.fIniDir = StrDup(dir);
2201
2202 new TGFileDialog(fClient->GetRoot(), this, kFDSave, &fi);
2203
2204 if (!fi.fFilename)
2205 return;
2206
2207 dir = fi.fIniDir;
2208
2209 if (strstr(fi.fFilename, ".root") ||
2210 strstr(fi.fFilename, ".ps") ||
2211 strstr(fi.fFilename, ".eps") ||
2212 strstr(fi.fFilename, ".gif"))
2213 {
2214 fCanvas->SaveAs(fi.fFilename);
2215 return;
2216 }
2217 if (strstr(fi.fFilename, ".C"))
2218 {
2219 fCanvas->SaveSource(fi.fFilename);
2220 return;
2221 }
2222 Warning("SaveAsDialog", "Unknown Extension: %s", fi.fFilename);
2223}
2224*/
Note: See TracBrowser for help on using the repository browser.