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

Last change on this file since 7825 was 7825, checked in by tbretz, 18 years ago
*** empty log message ***
File size: 82.7 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-2006
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()/SaveAsPNG() or SaveAsC().
34// Direct printing to the default printer (via lpr) can be done by
35// PrintPS().
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 <TH1.h> // TH1::AddDirectory
66#include <TPDF.h> // TPDF
67#include <TSVG.h> // TSVG
68#include <TEnv.h> // TEnv
69#include <TLine.h> // TLine
70#include <TText.h> // TText
71#include <TFile.h> // gFile
72#include <TFrame.h> // TFrame
73#include <TStyle.h> // gStyle
74#include <TCanvas.h> // TCanvas
75#include <TSystem.h> // gSystem
76#include <TDatime.h> // TDatime
77#include <TRandom.h> // TRandom
78#include <TRegexp.h> // TRegexp
79#include <TThread.h> // TThread::Self()
80#include <TBrowser.h> // TBrowser
81#include <TObjArray.h> // TObjArray
82#include <TPostScript.h> // TPostScript
83#include <TMethodCall.h> // TMethodCall
84
85#include <TInterpreter.h> // gInterpreter
86
87#include <TGTab.h> // TGTab
88#include <TGLabel.h> // TGLabel
89#include <TG3DLine.h> // TGHorizontal3DLine
90#include <TGButton.h> // TGPictureButton
91#include <TGTextView.h> // TGTextView
92#include <TGComboBox.h> // TGComboBox
93#include <TGStatusBar.h> // TGStatusBar
94#include <TGFileDialog.h> // TGFileDialog
95#include <TGProgressBar.h> // TGHProgressBar
96#include <TGTextEditDialogs.h> // TGPrintDialog
97#include <TRootEmbeddedCanvas.h> // TRootEmbeddedCanvas
98
99#include "MString.h"
100
101#include "MLog.h" // MLog
102#include "MLogManip.h" // inf, warn, err
103
104#include "MGList.h" // MGList
105#include "MGMenu.h" // MGMenu, TGMenu
106#include "MSearch.h" // MSearch
107#include "MParContainer.h" // MParContainer::GetDescriptor
108#include "MStatusArray.h" // MStatusArray
109
110#undef DEBUG
111//#define DEBUG
112
113ClassImp(MStatusDisplay);
114
115using namespace std;
116
117// ------------ Workaround for a non working TGTextView::Search -------------
118#if ROOT_VERSION_CODE < ROOT_VERSION(3,02,05)
119class MGTextView : public TGTextView
120{
121public:
122 MGTextView(const TGWindow *parent, UInt_t w, UInt_t h, Int_t id = -1,
123 UInt_t sboptions = 0, ULong_t back = GetWhitePixel()) :
124 TGTextView(parent, w, h, id, sboptions, back) {}
125 MGTextView(const TGWindow *parent, UInt_t w, UInt_t h, TGText *text,
126 Int_t id = -1, UInt_t sboptions = 0, ULong_t back = GetWhitePixel()) :
127 TGTextView(parent, w, h, text, id, sboptions, back) {}
128 MGTextView(const TGWindow *parent, UInt_t w, UInt_t h, const char *string,
129 Int_t id = -1, UInt_t sboptions = 0, ULong_t back = GetWhitePixel()) :
130 TGTextView(parent, w, h, string, id, sboptions, back) {}
131
132 void Mark(Long_t xPos, Long_t yPos) { TGTextView::Mark(xPos, yPos); }
133 void UnMark() { TGTextView::UnMark(); }
134
135 Bool_t Search(const char *string, Bool_t direction, Bool_t caseSensitive)
136 {
137 // Taken from TGTextView::Search and modified.
138
139 TGLongPosition pos, pos2;
140 pos2.fX = pos2.fY = 0;
141 if (fIsMarked) {
142 if (!direction)
143 {
144 pos2.fX = fMarkedStart.fX;
145 pos2.fY = fMarkedStart.fY;
146 }
147 else
148 {
149 pos2.fX = fMarkedEnd.fX + 1;
150 pos2.fY = fMarkedEnd.fY;
151 }
152 }
153 if (!fText->Search(&pos, pos2, string, direction, caseSensitive))
154 return kFALSE;
155 UnMark();
156 fIsMarked = kTRUE;
157 fMarkedStart.fY = fMarkedEnd.fY = pos.fY;
158 fMarkedStart.fX = pos.fX;
159 fMarkedEnd.fX = fMarkedStart.fX + strlen(string);
160 pos.fY = ToObjYCoord(fVisible.fY);
161 if ((fMarkedStart.fY < pos.fY) ||
162 (ToScrYCoord(fMarkedStart.fY) >= (Int_t)fCanvas->GetHeight()))
163 pos.fY = fMarkedStart.fY;
164 pos.fX = ToObjXCoord(fVisible.fX, pos.fY);
165 if ((fMarkedStart.fX < pos.fX) ||
166 (ToScrXCoord(fMarkedStart.fX, pos.fY) >= (Int_t)fCanvas->GetWidth()))
167 pos.fX = fMarkedStart.fX;
168
169 SetVsbPosition((ToScrYCoord(pos.fY) + fVisible.fY)/fScrollVal.fY);
170 SetHsbPosition((ToScrXCoord(pos.fX, pos.fY) + fVisible.fX)/fScrollVal.fX);
171 DrawRegion(0, (Int_t)ToScrYCoord(fMarkedStart.fY), fCanvas->GetWidth(),
172 UInt_t(ToScrYCoord(fMarkedEnd.fY+1) - ToScrYCoord(fMarkedEnd.fY)));
173
174 return kTRUE;
175 }
176};
177#else
178#define MGTextView TGTextView
179#endif
180
181// --------------------------------------------------------------------------
182
183TGCompositeFrame *MStatusDisplay::GetTabContainer(const char *name) const
184{
185#if ROOT_VERSION_CODE < ROOT_VERSION(4,03,05)
186 if (!fTab)
187 return 0;
188
189 TGFrameElement *el;
190 TGTabElement *tab = 0;
191 TGCompositeFrame *comp = 0;
192
193 TIter next(fTab->GetList());
194 next(); // skip first container
195
196 while ((el = (TGFrameElement *) next())) {
197 el = (TGFrameElement *) next();
198 comp = (TGCompositeFrame *) el->fFrame;
199 next();
200 tab = (TGTabElement *)el->fFrame;
201 if (name == tab->GetText()->GetString()) {
202 return comp;
203 }
204 }
205
206 return 0;
207#else
208 return fTab ? fTab->GetTabContainer(name) : 0;
209#endif
210}
211
212TGTabElement *MStatusDisplay::GetTabTab(const char *name) const
213{
214#if ROOT_VERSION_CODE < ROOT_VERSION(4,03,05)
215 if (!fTab)
216 return 0;
217
218 TGFrameElement *el;
219 TGTabElement *tab = 0;
220
221 TIter next(fTab->GetList());
222 next(); // skip first container
223
224 while ((el = (TGFrameElement *) next())) {
225 next();
226 tab = (TGTabElement *)el->fFrame;
227 if (name == tab->GetText()->GetString()) {
228 return tab;
229 }
230 }
231
232 return 0;
233#else
234 return fTab ? fTab->GetTabTab(name) : 0;
235#endif
236}
237// --------------------------------------------------------------------------
238
239
240// --------------------------------------------------------------------------
241//
242// Add menu bar to the GUI
243//
244void MStatusDisplay::AddMenuBar()
245{
246 //
247 // File Menu
248 //
249 MGPopupMenu *filemenu = new MGPopupMenu(gClient->GetRoot());
250 filemenu->AddEntry("New &Canvas", kFileCanvas);
251 filemenu->AddEntry("New &Browser", kFileBrowser);
252 filemenu->AddEntry("New &Tab", kFileTab);
253 filemenu->AddSeparator();
254
255 const TString fname(MString::Form("Save %s.", gROOT->GetName()));
256 MGPopupMenu *savemenu = new MGPopupMenu(gClient->GetRoot());
257 savemenu->AddEntry(MString::Form("%s&ps", fname.Data()), kFileSaveAsPS);
258 savemenu->AddEntry(MString::Form("%sp&df", fname.Data()), kFileSaveAsPDF);
259 savemenu->AddEntry(MString::Form("%s&svg", fname.Data()), kFileSaveAsSVG);
260 savemenu->AddSeparator();
261 savemenu->AddEntry(MString::Form("%sp&ng", fname.Data()), kFileSaveAsPNG);
262 savemenu->AddEntry(MString::Form("%s&gif", fname.Data()), kFileSaveAsGIF);
263 savemenu->AddEntry(MString::Form("%s&jpg", fname.Data()), kFileSaveAsJPG);
264 savemenu->AddEntry(MString::Form("%s&xpm", fname.Data()), kFileSaveAsXPM);
265 //savemenu->AddEntry("Save status.x&cf", kFileSaveAsXCF);
266 //savemenu->AddEntry("Save status.&tiff", kFileSaveAsTIFF);
267 savemenu->AddEntry("Save status.&bmp", kFileSaveAsBMP);
268 savemenu->AddEntry("Save status.&xml", kFileSaveAsXML);
269 savemenu->AddSeparator();
270 savemenu->AddEntry(MString::Form("%s&C", fname.Data()), kFileSaveAsC);
271 savemenu->AddEntry(MString::Form("%s&root", fname.Data()), kFileSaveAsRoot);
272 savemenu->Associate(this);
273
274 filemenu->AddEntry("&Open...", kFileOpen);
275 filemenu->AddPopup("&Save", savemenu);
276 filemenu->AddEntry("Save &As...", kFileSaveAs);
277 filemenu->AddSeparator();
278 filemenu->AddEntry("&Reset", kFileReset);
279 filemenu->AddSeparator();
280 filemenu->AddEntry("&Print", kFilePrint);
281 filemenu->AddSeparator();
282 filemenu->AddEntry("C&lose", kFileClose);
283 filemenu->AddEntry("E&xit", kFileExit);
284 filemenu->Associate(this);
285
286 //
287 // Tab Menu
288 //
289 MGPopupMenu *tabmenu = new MGPopupMenu(gClient->GetRoot());
290 tabmenu->AddEntry("Next [&+]", kTabNext);
291 tabmenu->AddEntry("Previous [&-]", kTabPrevious);
292 tabmenu->AddSeparator();
293
294 const TString fname2(MString::Form("Save %s-i.", gROOT->GetName()));
295 MGPopupMenu *savemenu2 = new MGPopupMenu(gClient->GetRoot());
296 savemenu2->AddEntry(MString::Form("%s&ps", fname2.Data()), kTabSaveAsPS);
297 savemenu2->AddEntry(MString::Form("%sp&df", fname2.Data()), kTabSaveAsPDF);
298 savemenu2->AddEntry(MString::Form("%s&svg", fname2.Data()), kTabSaveAsSVG);
299 savemenu2->AddSeparator();
300 savemenu2->AddEntry(MString::Form("%sp&ng", fname2.Data()), kTabSaveAsPNG);
301 savemenu2->AddEntry(MString::Form("%s&gif", fname2.Data()), kTabSaveAsGIF);
302 savemenu2->AddEntry(MString::Form("%s&jpg", fname2.Data()), kTabSaveAsJPG);
303 savemenu2->AddEntry(MString::Form("%s&xpm", fname2.Data()), kTabSaveAsXPM);
304 //savemenu->AddEntry("Save status.x&cf", kFileSaveAsXCF);
305 //savemenu->AddEntry("Save status.&tiff", kFileSaveAsTIFF);
306 savemenu->AddEntry("Save status.&bmp", kFileSaveAsBMP);
307 savemenu->AddEntry("Save status.&xml", kFileSaveAsXML);
308 savemenu2->AddSeparator();
309 savemenu2->AddEntry(MString::Form("%s&C", fname2.Data()), kTabSaveAsC);
310 savemenu2->AddEntry(MString::Form("%s&root", fname2.Data()), kTabSaveAsRoot);
311 savemenu2->Associate(this);
312
313 tabmenu->AddPopup("&Save", savemenu2);
314 tabmenu->AddEntry("Save tab &As...", kTabSaveAs);
315 tabmenu->AddSeparator();
316 tabmenu->AddEntry("&Remove", kTabRemove);
317 tabmenu->AddSeparator();
318 tabmenu->AddEntry("&Print", kTabPrint);
319 tabmenu->Associate(this);
320
321 //
322 // Loop Menu
323 //
324 MGPopupMenu *loopmenu = new MGPopupMenu(gClient->GetRoot());
325 loopmenu->AddEntry("&Stop", kLoopStop);
326 loopmenu->Associate(this);
327
328 //
329 // Loop Menu
330 //
331 MGPopupMenu *sizemenu = new MGPopupMenu(gClient->GetRoot());
332 sizemenu->AddEntry("Fit to 640x&480", kSize640);
333 sizemenu->AddEntry("Fit to 768x&576", kSize768);
334 sizemenu->AddEntry("Fit to 800x&600", kSize800);
335 sizemenu->AddEntry("Fit to 960x7&20", kSize960);
336 sizemenu->AddEntry("Fit to 1024x&768", kSize1024);
337 sizemenu->AddEntry("Fit to 1152x&864", kSize1152);
338 sizemenu->AddEntry("Fit to 1280x&1024", kSize1280);
339 sizemenu->AddEntry("Fit to 1400x1050", kSize1400);
340 sizemenu->AddEntry("Fit to 1600x1200", kSize1600);
341 sizemenu->Associate(this);
342
343 //
344 // Log Menu
345 //
346 MGPopupMenu *logmenu = new MGPopupMenu(gClient->GetRoot());
347 logmenu->AddEntry("&Copy Selected", kLogCopy);
348 logmenu->AddEntry("Cl&ear all", kLogClear);
349 logmenu->AddSeparator();
350 logmenu->AddEntry("Select &All", kLogSelect);
351 logmenu->AddSeparator();
352 logmenu->AddEntry("&Find...", kLogFind);
353 logmenu->AddSeparator();
354 logmenu->AddEntry("&Save", kLogSave);
355 logmenu->AddEntry("Save &append", kLogAppend);
356 logmenu->AddSeparator();
357 logmenu->AddEntry("&Print", kLogPrint);
358 logmenu->Associate(this);
359
360 //
361 // Menu Bar
362 //
363 TGLayoutHints *layitem = new TGLayoutHints(kLHintsNormal, 0, 4, 0, 0);
364 fList->Add(layitem);
365
366 MGMenuBar *menubar = new MGMenuBar(this, 1, 1, kHorizontalFrame);
367 menubar->AddPopup("&File", filemenu, layitem);
368 menubar->AddPopup("Lo&g", logmenu, layitem);
369 menubar->AddPopup("&Size", sizemenu, layitem);
370 menubar->AddPopup("&Tab", tabmenu, layitem);
371 menubar->AddPopup("&Loop", loopmenu, layitem);
372 menubar->BindKeys(this);
373 AddFrame(menubar);
374
375 //
376 // Line below menu bar
377 //
378 TGLayoutHints *laylinesep = new TGLayoutHints(kLHintsTop|kLHintsExpandX);
379 fList->Add(laylinesep);
380
381 TGHorizontal3DLine *linesep = new TGHorizontal3DLine(this);
382 AddFrame(linesep, laylinesep);
383
384 //
385 // Add everything to autodel list
386 //
387 fList->Add(savemenu);
388 fList->Add(savemenu2);
389 fList->Add(filemenu);
390 fList->Add(loopmenu);
391 fList->Add(sizemenu);
392 fList->Add(menubar);
393 fList->Add(tabmenu);
394 fList->Add(logmenu);
395 fList->Add(linesep);
396}
397
398// --------------------------------------------------------------------------
399//
400// Adds an empty TGCompositeFrame which might be filled by the user
401//
402void MStatusDisplay::AddUserFrame()
403{
404 TGLayoutHints *lay=new TGLayoutHints(kLHintsExpandX);
405 fList->Add(lay);
406
407 fUserFrame = new TGCompositeFrame(this, 1, 1);
408 AddFrame(fUserFrame, lay);
409 fList->Add(fUserFrame);
410}
411
412char *rot128(char *c)
413{
414 char *rc=c;
415 while (*c) *c++ += 128;
416 return rc;
417}
418
419// --------------------------------------------------------------------------
420//
421// Add the title tab
422//
423void MStatusDisplay::AddMarsTab()
424{
425 // Create Tab1
426 TGCompositeFrame *f = fTab->AddTab("-=MARS=-");
427
428 // Add list of tabs
429
430 TGComboBox *filter = new TGComboBox(f, kTabs);
431 fList->Add(filter);
432 filter->Associate(this);
433 filter->AddEntry("-=MARS=-", 0);
434 filter->Select(0);
435
436 TGLayoutHints *lay3 = new TGLayoutHints(kLHintsCenterX|kLHintsTop, 10, 10, 10, 5);
437 fList->Add(lay3);
438 f->AddFrame(filter, lay3);
439
440 // Add MARS version
441 TGLabel *l = new TGLabel(f, MString::Form("Official Release: V%s", MARSVER));
442 fList->Add(l);
443
444 filter->SetWidth(l->GetWidth());
445 filter->SetHeight(4*l->GetHeight()/3);
446
447 TGLayoutHints *layb = new TGLayoutHints(kLHintsCenterX|kLHintsTop, 10, 10, 5, 5);
448 fList->Add(layb);
449 f->AddFrame(l, layb);
450
451 // Add root version
452 l = new TGLabel(f, MString::Form("Using ROOT v%s", ROOTVER));
453 fList->Add(l);
454
455 TGLayoutHints *lay = new TGLayoutHints(kLHintsCenterX|kLHintsTop);
456 fList->Add(lay);
457 f->AddFrame(l, lay);
458
459 // Add Mars logo picture
460 const TGPicture *pic2 = fList->GetPicture("marslogo.xpm");
461 if (pic2)
462 {
463 TGPictureButton *mars = new TGPictureButton(f, pic2, kPicMars);
464 fList->Add(mars);
465 mars->Associate(this);
466
467 TGLayoutHints *lay2 = new TGLayoutHints(kLHintsCenterX|kLHintsCenterY, 10, 10, 5, 5);
468 fList->Add(lay2);
469 f->AddFrame(mars, lay2);
470 }
471
472 // Add date and time
473 TDatime d;
474 l = new TGLabel(f, d.AsString());
475 fList->Add(l);
476 f->AddFrame(l, lay);
477
478 // Add copyright notice
479 l = new TGLabel(f, "(c) MAGIC Software Development, 2000-2006");
480 fList->Add(l);
481 f->AddFrame(l, layb);
482
483 TGLayoutHints *layc = new TGLayoutHints(kLHintsCenterX|kLHintsTop, 10, 10, 0, 5);
484 fList->Add(layc);
485
486 char *txt = "<< Thomas Bretz >>";
487 l = new TGLabel(f, txt);
488 fList->Add(l);
489 f->AddFrame(l, layc);
490}
491
492// --------------------------------------------------------------------------
493//
494// Adds the logbook tab to the GUI if it was not added previously.
495//
496// The logbook is updated four times a second only if the tab is visible.
497//
498// You can redirect an output to a MLog-logstream by calling SetLogStream().
499// To disable redirction call SetLogStream(NULL)
500//
501// if enable==kFALSE the stdout is disabled/enabled. Otherwise stdout
502// is ignored.
503//
504void MStatusDisplay::SetLogStream(MLog *log, Bool_t enable)
505{
506 if (gROOT->IsBatch())
507 return;
508
509 if (log && fLogBox==NULL)
510 {
511 fLogIdx = fTab->GetNumberOfTabs();
512
513 // Create Tab1
514 TGCompositeFrame *f = AddRawTab("-Logbook-");//fTab->AddTab("-Logbook-");
515
516 // Create Text View
517 fLogBox = new MGTextView(f, 1, 1); // , -1, 0, TGFrame::GetDefaultFrameBackground());
518 if (fFont)
519 fLogBox->SetFont(fFont);
520 //fLogBox->Associate(this);
521
522 // Add List box to the tab
523 TGLayoutHints *lay = new TGLayoutHints(kLHintsNormal|kLHintsExpandX|kLHintsExpandY,2,2,2,2);
524 f->AddFrame(fLogBox, lay);
525
526 // layout and map tab
527 Layout();
528 MapSubwindows();
529
530 // make it visible
531 // FIXME: This is a workaround, because TApplication::Run is not
532 // thread safe against ProcessEvents. We assume, that if
533 // we are not in the Main-Thread ProcessEvents() is
534 // called by the TApplication Event Loop...
535 if (!TThread::Self()/*gApplication->InheritsFrom(TRint::Class())*/)
536 gClient->ProcessEventsFor(fTab);
537 }
538
539 if (log)
540 {
541 fLog = log;
542
543 log->SetOutputGui(fLogBox, kTRUE);
544 log->EnableOutputDevice(MLog::eGui);
545 if (!enable)
546 log->DisableOutputDevice(MLog::eStdout);
547
548 fLogTimer.Start();
549 }
550 else
551 {
552 fLogTimer.Stop();
553
554 fLog->DisableOutputDevice(MLog::eGui);
555 fLog->SetOutputGui(NULL);
556 if (!enable)
557 fLog->EnableOutputDevice(MLog::eStdout);
558
559 fLog = &gLog;
560 }
561}
562
563// --------------------------------------------------------------------------
564//
565// Add the Tabs and the predifined Tabs to the GUI
566//
567void MStatusDisplay::AddTabs()
568{
569 fTab = new TGTab(this, 300, 300);
570
571 AddMarsTab();
572
573 // Add fTab to Frame
574 TGLayoutHints *laytabs = new TGLayoutHints(kLHintsNormal|kLHintsExpandX|kLHintsExpandY, 5, 5, 5);
575 AddFrame(fTab, laytabs);
576
577 fList->Add(fTab);
578 fList->Add(laytabs);
579}
580
581// --------------------------------------------------------------------------
582//
583// Add the progress bar to the GUI. The Progress Bar range is set to
584// (0,1) as default.
585//
586void MStatusDisplay::AddProgressBar()
587{
588 TGLayoutHints *laybar=new TGLayoutHints(kLHintsExpandX, 5, 5, 5, 5);
589 fList->Add(laybar);
590
591 fBar=new TGHProgressBar(this);
592 fBar->SetRange(0, 1);
593 fBar->ShowPosition();
594 AddFrame(fBar, laybar);
595 fList->Add(fBar);
596}
597
598// --------------------------------------------------------------------------
599//
600// Set the progress bar position between 0 and 1. The Progress bar range
601// is assumed to be (0,1)
602//
603void MStatusDisplay::SetProgressBarPosition(Float_t p)
604{
605 fBar->SetPosition(p);
606}
607
608// --------------------------------------------------------------------------
609//
610// Adds the status bar to the GUI
611//
612void MStatusDisplay::AddStatusBar()
613{
614 fStatusBar = new TGStatusBar(this, 1, 1);
615
616 //
617 // Divide it like the 'Golden Cut' (goldener Schnitt)
618 //
619 // 1-a a
620 // 1: ------|----
621 //
622 // a/(1-a) = (1-a)/1
623 // a^2+a-1 = 0
624 // a = (-1+-sqrt(1+4))/2 = sqrt(5)/2-1/2 = 0.618
625 //
626 Int_t p[] = {38-2, 62-8, 10};
627
628 fStatusBar->SetParts(p, 3);
629
630 TGLayoutHints *layb = new TGLayoutHints(kLHintsNormal|kLHintsExpandX, 5, 4, 0, 3);
631 AddFrame(fStatusBar, layb);
632
633 fList->Add(fStatusBar);
634 fList->Add(layb);
635}
636
637// --------------------------------------------------------------------------
638//
639// Change the text in the status line 1
640//
641void MStatusDisplay::SetStatusLine(const char *txt, Int_t i)
642{
643 if (gROOT->IsBatch())
644 return;
645 fStatusBar->SetText(txt, i);
646
647 // FIXME: This is a workaround, because TApplication::Run is not
648 // thread safe against ProcessEvents. We assume, that if
649 // we are not in the Main-Thread ProcessEvents() is
650 // called by the TApplication Event Loop...
651 if (!TThread::Self()/*gApplication->InheritsFrom(TRint::Class())*/)
652 gClient->ProcessEventsFor(fStatusBar);
653}
654
655// --------------------------------------------------------------------------
656//
657// Display information about the name of a container
658//
659void MStatusDisplay::SetStatusLine2(const MParContainer &cont)
660{
661 SetStatusLine2(MString::Form("%s: %s", cont.GetDescriptor().Data(), cont.GetTitle()));
662}
663
664// --------------------------------------------------------------------------
665//
666// Default constructor. Opens a window with a progress bar. Get a pointer
667// to the bar by calling GetBar. This pointer can be used for the
668// eventloop.
669//
670// Be carefull: killing or closing the window while the progress meter
671// is still in use may cause segmentation faults. Please kill the window
672// always by deleting the corresponding object.
673//
674// Update time default: 10s
675//
676MStatusDisplay::MStatusDisplay(Long_t t)
677: 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)
678{
679 // p==NULL means: Take gClient->GetRoot() if not in batch mode
680 // see TGWindow::TGWindow()
681
682 //
683 // This is a possibility for the user to check whether this
684 // object has already been deleted. It will be removed
685 // from the list in the destructor.
686 //
687// gROOT->GetListOfSpecials()->Add(this);
688
689 fFont = gVirtualX->LoadQueryFont("7x13bold");
690 fMutex = new TMutex;
691
692 //
693 // In case we are in batch mode use a list of canvases
694 // instead of the Root Embedded Canvases in the TGTab
695 //
696 fBatch = new TList;
697 fBatch->SetOwner();
698
699 //
700 // Create a list handling GUI widgets
701 //
702 fList = new MGList;
703 fList->SetOwner();
704
705 //
706 // Create the layout hint for the root embedded canavses
707 //
708 fLayCanvas = new TGLayoutHints(kLHintsExpandX|kLHintsExpandY);
709 fList->Add(fLayCanvas);
710
711 //
712 // Add Widgets (from top to bottom)
713 //
714 // In newer root versions gClient!=NULL in batch mode!
715 if (!gClient || !gClient->GetRoot() || gROOT->IsBatch()) // BATCH MODE
716 return;
717
718 AddMenuBar();
719 AddUserFrame();
720 AddTabs();
721 AddProgressBar();
722 AddStatusBar();
723
724 //
725 // set the smallest and biggest size of the Main frame
726 // and move it to its appearance position
727 SetWMSizeHints(572, 480, 2048, 1536, 1, 1);
728 MoveResize(rand()%100+572, rand()%100+480, 572, 480);
729
730 //
731 // Now do an automatic layout of the widgets and display the window
732 //
733 Layout();
734 MapSubwindows();
735
736 SetWindowName("Status Display");
737 SetIconName("Status Display");
738
739 MapWindow();
740
741 // FIXME: This is a workaround, because TApplication::Run is not
742 // thread safe against ProcessEvents. We assume, that if
743 // we are not in the Main-Thread ProcessEvents() is
744 // called by the TApplication Event Loop...
745 if (!TThread::Self()/*gApplication->InheritsFrom(TRint::Class())*/)
746 gSystem->ProcessEvents();
747}
748
749// --------------------------------------------------------------------------
750//
751// Destruct the window with all its tiles. Also the Progress Bar object
752// is deleted.
753//
754MStatusDisplay::~MStatusDisplay()
755{
756#if ROOT_VERSION_CODE < ROOT_VERSION(3,10,01)
757 fTab = NULL; // See HandleEvent
758#endif
759
760 //
761 // Delete object from global object table so it cannot
762 // be deleted by chance a second time
763 //
764 gInterpreter->DeleteGlobal(this);
765
766 //
767 // This is a possibility for the user to check whether this
768 // object has already been deleted. It has been added
769 // to the list in the constructor.
770 //
771 gROOT->GetListOfSpecials()->Remove(this);
772
773 SetLogStream(NULL);
774
775 //
776 // Delete the list of objects corresponding to this object
777 //
778 delete fList;
779
780 //
781 // Delete the list of canvases used in batch mode
782 // instead of the Root Embedded Canvases in the TGTab
783 //
784 delete fBatch;
785
786 //
787 // Delete the font used for the logging window
788 //
789 if (fFont)
790 gVirtualX->DeleteFont(fFont);
791
792 //
793 // Delete mutex
794 //
795 delete fMutex;
796}
797
798// --------------------------------------------------------------------------
799//
800// Takes a TGCompositeFrame as argument. Searches for the first
801// TRootEmbeddedCanvas which is contained by it and returns a pointer
802// to the corresponding TCanvas. If it isn't found NULL is returned.
803//
804TRootEmbeddedCanvas *MStatusDisplay::GetEmbeddedCanvas(TGCompositeFrame *cf) const
805{
806 TIter Next(cf->GetList());
807
808 TGFrameElement *f;
809 while ((f=(TGFrameElement*)Next()))
810 if (f->fFrame->InheritsFrom(TRootEmbeddedCanvas::Class()))
811 return (TRootEmbeddedCanvas*)f->fFrame;
812
813 return NULL;
814}
815
816// --------------------------------------------------------------------------
817//
818// Takes a TGCompositeFrame as argument. Searches for the first
819// TRootEmbeddedCanvas which is contained by it and returns a pointer
820// to the corresponding TCanvas. If it isn't found NULL is returned.
821//
822TCanvas *MStatusDisplay::GetCanvas(TGCompositeFrame *cf) const
823{
824 TRootEmbeddedCanvas *ec = GetEmbeddedCanvas(cf);
825 return ec ? ec->GetCanvas() : NULL;
826}
827
828// --------------------------------------------------------------------------
829//
830// Returns the range of tabs containing valid canvases for the condition
831// num.
832//
833void MStatusDisplay::GetCanvasRange(Int_t &from, Int_t &to, Int_t num) const
834{
835 const Int_t max = gROOT->IsBatch() ? fBatch->GetSize()+1 : fTab->GetNumberOfTabs();
836
837 from = num<0 ? 1 : num;
838 to = num<0 ? max : num+1;
839}
840
841// --------------------------------------------------------------------------
842//
843// Returns GetCanvas of the i-th Tab.
844//
845TCanvas *MStatusDisplay::GetCanvas(int i) const
846{
847 if (gROOT->IsBatch())
848 return (TCanvas*)fBatch->At(i-1);
849
850 if (i<0 || i>=fTab->GetNumberOfTabs())
851 {
852 *fLog << warn << "MStatusDisplay::GetCanvas: Out of range." << endl;
853 return NULL;
854 }
855
856 return GetCanvas(fTab->GetTabContainer(i));
857}
858
859// --------------------------------------------------------------------------
860//
861// Returns j-th pad of the i-th Tab.
862// Sets the pad to fill an entire window.
863//
864// This function can be used if single pad's out of an MStatusDisplay
865// have to be stored to file.
866//
867// ATTENTION: This function modifies the requested tab in MStatusDisplay itself!
868//
869TVirtualPad *MStatusDisplay::GetFullPad(const Int_t i, const Int_t j)
870{
871 if (!GetCanvas(i))
872 {
873 *fLog << warn << "MStatusDisplay::GetFullPad: i-th canvas not dound." << endl;
874 return NULL;
875 }
876
877 TVirtualPad *vpad = GetCanvas(i)->GetPad(j);
878 if (!vpad)
879 {
880 *fLog << warn << "MStatusDisplay::GetFullPad: Pad is out of range." << endl;
881 return NULL;
882 }
883
884 vpad->SetPad(0.,0.,1.,1.);
885 return vpad;
886}
887
888// --------------------------------------------------------------------------
889//
890// Searches for a TRootEmbeddedCanvas in the TGCompositeFramme of the
891// Tab with the name 'name'. Returns the corresponding TCanvas or
892// NULL if something isn't found.
893//
894TCanvas *MStatusDisplay::GetCanvas(const TString &name) const
895{
896 if (gROOT->IsBatch())
897 return (TCanvas*)fBatch->FindObject(name);
898
899 TGFrameElement *f;
900 TIter Next(fTab->GetList());
901 while ((f=(TGFrameElement*)Next()))
902 {
903 TObject *frame = f->fFrame;
904 if (!frame->InheritsFrom(TGTabElement::Class()))
905 continue;
906
907 TGTabElement *tab = (TGTabElement*)frame;
908 if (tab->GetString()==name)
909 break;
910 }
911
912 // Search for the next TGCompositeFrame in the list
913 while ((f=(TGFrameElement*)Next()))
914 {
915 TObject *frame = f->fFrame;
916 if (frame->InheritsFrom(TGCompositeFrame::Class()))
917 return GetCanvas((TGCompositeFrame*)frame);
918 }
919
920 return NULL;
921}
922
923// --------------------------------------------------------------------------
924//
925// Calls TCanvas::cd(), for the canvas returned by GetCanvas.
926//
927Bool_t MStatusDisplay::CdCanvas(const TString &name)
928{
929 TCanvas *c = GetCanvas(name);
930 if (!c)
931 return kFALSE;
932
933 c->cd();
934 return kTRUE;
935}
936
937TGCompositeFrame *MStatusDisplay::AddRawTab(const char *name)
938{
939 // Add new tab
940 TGCompositeFrame *f = fTab->AddTab(name);
941
942 TGComboBox *box = (TGComboBox*)fList->FindWidget(kTabs);
943 box->AddEntry(name, box->GetListBox()->GetNumberOfEntries());
944
945 // layout and map new tab
946 Layout();
947 MapSubwindows();
948 Layout();
949
950 // display new tab in the main frame
951 // FIXME: This is a workaround, because TApplication::Run is not
952 // thread safe against ProcessEvents. We assume, that if
953 // we are not in the Main-Thread ProcessEvents() is
954 // called by the TApplication Event Loop...
955 if (!TThread::Self()/*gApplication->InheritsFrom(TRint::Class())*/)
956 gClient->ProcessEventsFor(fTab);
957
958 *fLog << inf << "Adding Raw Tab '" << name << "' (" << f->GetWidth() << "x";
959 *fLog << f->GetHeight() << ")" << endl;
960
961 // return pointer to new canvas
962 return f;
963}
964
965// --------------------------------------------------------------------------
966//
967// This function was connected to all created canvases. It is used
968// to redirect GetObjectInfo into our own status bar.
969//
970// The 'connection' is done in AddTab
971//
972void MStatusDisplay::EventInfo(Int_t event, Int_t px, Int_t py, TObject *selected)
973{
974 // Writes the event status in the status bar parts
975 if (!selected)
976 return;
977
978 TCanvas *c = (TCanvas*)gTQSender;
979
980 TVirtualPad* save=gPad;
981
982 gPad = c ? c->GetSelectedPad() : NULL;
983
984 if (gPad)
985 SetStatusLine2(selected->GetObjectInfo(px,py));
986
987 gPad=save;
988}
989
990// --------------------------------------------------------------------------
991//
992// Adds a new tab with the name 'name'. Adds a TRootEmbeddedCanvas to the
993// tab and returns a reference to the corresponding TCanvas.
994//
995TCanvas &MStatusDisplay::AddTab(const char *name)
996{
997 if (gROOT->IsBatch())
998 {
999 TCanvas *c = new TCanvas(name, name);
1000 fBatch->Add(c);
1001 return *c;
1002 }
1003
1004 // Add new tab
1005 TGCompositeFrame *f = fTab->AddTab(name);
1006
1007 // create root embedded canvas and add it to the tab
1008 TRootEmbeddedCanvas *ec = new TRootEmbeddedCanvas(name, f, f->GetWidth(), f->GetHeight(), 0);
1009 f->AddFrame(ec, fLayCanvas);
1010 fList->Add(ec);
1011
1012 // set background and border mode of the canvas
1013 TCanvas &c = *ec->GetCanvas();
1014
1015 c.SetFillColor(16/*165*//*17*//*203*/);
1016 c.SetFrameBorderMode(0);
1017 c.SetBorderMode(0);
1018
1019 // If kNoContextMenu set set kNoContextMenu of the canvas
1020 if (TestBit(kNoContextMenu))
1021 c.SetBit(kNoContextMenu);
1022
1023 // Connect all TCanvas::ProcessedEvent to this->EventInfo
1024 // This means, that after TCanvas has processed an event
1025 // EventInfo of this class is called, see TCanvas::HandleInput
1026 c.Connect("ProcessedEvent(Int_t,Int_t,Int_t,TObject*)",
1027 "MStatusDisplay", this, "EventInfo(Int_t,Int_t,Int_t,TObject*)");
1028
1029 TGComboBox *box = (TGComboBox*)fList->FindWidget(kTabs);
1030 box->AddEntry(name, box->GetListBox()->GetNumberOfEntries());
1031
1032 // layout and map new tab
1033 Layout(); // seems to layout the TGCompositeFrame
1034 MapSubwindows(); // maps the TGCompositeFrame
1035 Layout(); // layout the embedded canvas in the frame
1036
1037 // display new tab in the main frame
1038 // FIXME: This is a workaround, because TApplication::Run is not
1039 // thread safe against ProcessEvents. We assume, that if
1040 // we are not in the Main-Thread ProcessEvents() is
1041 // called by the TApplication Event Loop...
1042 if (!TThread::Self()/*gApplication->InheritsFrom(TRint::Class())*/)
1043 gClient->ProcessEventsFor(fTab);
1044
1045 *fLog << inf << "Adding Tab '" << name << "' (" << f->GetWidth() << "x";
1046 *fLog << f->GetHeight() << ", TCanvas=" << &c << ")" << endl;
1047
1048 // return pointer to new canvas
1049 return c;
1050}
1051
1052// --------------------------------------------------------------------------
1053//
1054// Update a canvas in a tab, takes the corresponding TGCompositeFrame
1055// as an argument. This is necessary, because not all functions
1056// changing the contents of a canvas or pad can call SetModified()
1057// for the corresponding tab. If this is not called correctly the
1058// tab won't be updated calling TCanvas::Update(). So we simply
1059// redraw it by our own (instead we could recursively call
1060// TPad::Modified() for everything contained by the TCanvas and
1061// call TCanvas::Update() afterwards)
1062//
1063void MStatusDisplay::UpdateTab(TGCompositeFrame *f)
1064{
1065 if (!f)
1066 return;
1067
1068 TCanvas *c=GetCanvas(f);
1069 if (!c)
1070 return;
1071
1072 //
1073 // If we are in a multithreaded environment (gThreadXAR) we
1074 // have to make sure, that thus function is called from
1075 // the main thread.
1076 //
1077 if (gThreadXAR)
1078 {
1079 // Tell the X-Requester how to call this method
1080 TString str = MString::Form("%d", (ULong_t)f);
1081
1082 TMethodCall call(IsA(), "UpdateTab", "NULL");
1083 void *arr[4] = { NULL, &call, this, (void*)(const char*)str };
1084
1085 // If this is not the main thread return
1086 if (((*gThreadXAR)("METH", 4, arr, NULL)))
1087 return;
1088 }
1089
1090 //
1091 // Secure calls to update the tabs against itself, at least
1092 // c->Paint() or c->Flush() may crash X (bad drawable).
1093 // This makes sure, that a X call is not interuppted by
1094 // another X-call which was started from an gui interrrupt
1095 // in the same thread
1096 //
1097 if (fMutex->TryLock())
1098 return;
1099
1100#if ROOT_VERSION_CODE < ROOT_VERSION(3,10,02)
1101 TPad *padsav = (TPad*)gPad;
1102 if (!gPad)
1103 c->cd();
1104#endif
1105
1106 if (!c->IsBatch())
1107 c->FeedbackMode(kFALSE); // Goto double buffer mode
1108
1109 //
1110 // Doing this ourself gives us the possibility to repaint
1111 // the canvas in any case (Paint() instead of PaintModified())
1112 //
1113 c->Paint(); // Repaint all pads
1114 c->Flush(); // Copy all pad pixmaps to the screen
1115
1116#if ROOT_VERSION_CODE < ROOT_VERSION(3,10,02)
1117 if (padsav)
1118 padsav->cd();
1119 else
1120 gPad=NULL;
1121#endif
1122
1123 //c->SetCursor(kCross);
1124
1125 // Old version
1126 //c->Modified();
1127 //c->Update();
1128 //c->Paint();
1129
1130 fMutex->UnLock();
1131}
1132
1133TString MStatusDisplay::PrintDialog(TString &p, TString &c, TString &t, const char *ext)
1134{
1135 // If not in batch mode open a user dialog
1136 if (!gROOT->IsBatch())
1137 {
1138 char *cprinter = StrDup(p);
1139 char *ccmd = StrDup(c);
1140
1141 Int_t rc=0;
1142 new TGPrintDialog(fClient->GetRoot(), this, 400, 150, &cprinter, &ccmd, &rc);
1143 if (rc)
1144 {
1145 p = cprinter; // default has been changed
1146 c = ccmd;
1147 }
1148
1149 delete [] cprinter;
1150 delete [] ccmd;
1151
1152 if (!rc)
1153 return "";
1154 }
1155
1156
1157 if (c.Contains("%f") && ext)
1158 {
1159 // Get temporary file name
1160 TString name = "mars";
1161
1162 FILE *f = gSystem->TempFileName(name, t);
1163 if (!f)
1164 {
1165 *fLog << warn << "MStatusDisplay::PrintDialog: Couldn't create temporary file in " << t << endl;
1166 SetStatusLine2("failed!");
1167 return "";
1168 }
1169 fclose(f);
1170
1171 // remove temp file
1172 gSystem->Unlink(name);
1173 name += ".";
1174 name += ext;
1175
1176 t = name;
1177 }
1178
1179 // compile command
1180 TString cmd(c);
1181
1182 // if sprinter.IsNull we assume that everything around %p can
1183 // be omitted and the program uses some kind of default
1184 if (p.IsNull())
1185 {
1186 TString sub;
1187 while (1)
1188 {
1189 sub = TString(cmd(TRegexp(" .*%p.* "))).Strip(TString::kBoth);
1190 if (sub.IsNull())
1191 break;
1192
1193 cmd.ReplaceAll(sub, "");
1194 }
1195 }
1196
1197 cmd.ReplaceAll("%p", p);
1198 cmd.ReplaceAll("%f", t);
1199
1200 return cmd;
1201}
1202
1203// --------------------------------------------------------------------------
1204//
1205// Saves the given canvas (pad) or all pads (num<0) as a temporary
1206// postscript file and prints it.
1207//
1208// The default command line c is: lpr -P%p %f
1209// %p: printer name
1210// %f: temporary file name
1211//
1212// The default printer name p is: <empty>
1213//
1214// Both can be changed in .rootrc by:
1215// PrintPS.Printer
1216// PrintPS.Command
1217//
1218// Ant the location of the temporary file t can by changed by
1219// Print.Directory
1220// the default is the system default directory (normally /tmp)
1221//
1222Int_t MStatusDisplay::PrintPS(Int_t num, const char *p, const char *c, const char *t)
1223{
1224 static TString sprinter = gEnv->GetValue("PrintPS.Printer", p&&*p?p:"");
1225 static TString scmd = gEnv->GetValue("PrintPS.Command", c&&*c?c:"lpr -P%p %f");
1226
1227 TString tmp = gEnv->GetValue("Print.Directory", t&&*t?t:gSystem->TempDirectory());
1228
1229 TString cmd = PrintDialog(sprinter, scmd, tmp, "ps");
1230 if (cmd.IsNull())
1231 return 0;
1232
1233 // set status lines
1234 SetStatusLine1("Printing...");
1235 SetStatusLine2("");
1236
1237 // print to temporary file
1238 const Int_t pages = SaveAsPS(num, tmp);
1239
1240 // check
1241 if (!pages)
1242 {
1243 *fLog << warn << "MStatusDisplay::Print: Sorry, couldn't save file as temporary postscript!" << endl;
1244 SetStatusLine2("Failed!");
1245 return 0;
1246 }
1247
1248 // execute command
1249 *fLog << dbg << "Executing: " << cmd << endl;
1250 gSystem->Exec(cmd);
1251
1252 // remove temporary file
1253 gSystem->Unlink(tmp);
1254
1255 SetStatusLine2(MString::Form("Done (%dpage(s))", pages));
1256
1257 return pages;
1258}
1259
1260// --------------------------------------------------------------------------
1261//
1262// Remove tab no i if this tab contains a TRootEmbeddedCanvas
1263//
1264void MStatusDisplay::RemoveTab(int i)
1265{
1266 TGCompositeFrame *f = fTab->GetTabContainer(i);
1267 if (!f)
1268 return;
1269
1270 TRootEmbeddedCanvas *ec = GetEmbeddedCanvas(f);
1271 if (!ec)
1272 return;
1273
1274 TCanvas *c = ec->GetCanvas();
1275 if (!c)
1276 return;
1277
1278 const TString name(c->GetName());
1279
1280 f->RemoveFrame(ec);
1281 delete fList->Remove(ec);
1282
1283 fTab->RemoveTab(i);
1284 fTab->SetTab(0);
1285
1286 TGComboBox *box = (TGComboBox*)fList->FindWidget(kTabs);
1287 box->RemoveEntry(i);
1288 for (int j=i; j<box->GetListBox()->GetNumberOfEntries(); j++)
1289 {
1290 TGTextLBEntry *entry = (TGTextLBEntry *)box->GetListBox()->Select(j+1, kFALSE);
1291 box->AddEntry(entry->GetText()->GetString(), j);
1292 box->RemoveEntry(j+1);
1293 }
1294 box->GetListBox()->Select(0);
1295
1296 // Looks strange...
1297 // const Int_t n = fTab->GetNumberOfTabs();
1298 // fTab->SetTab(i<=n-1 ? i : i-1);
1299
1300 // layout and map new tab
1301 Layout(); // seems to layout the TGCompositeFrame
1302 MapSubwindows(); // maps the TGCompositeFrame
1303 Layout(); // layout the embedded canvas in the frame
1304
1305 // display new tab in the main frame
1306 // FIXME: This is a workaround, because TApplication::Run is not
1307 // thread safe against ProcessEvents. We assume, that if
1308 // we are not in the Main-Thread ProcessEvents() is
1309 // called by the TApplication Event Loop...
1310 if (!TThread::Self()/*gApplication->InheritsFrom(TRint::Class())*/)
1311 gClient->ProcessEventsFor(fTab);
1312
1313 *fLog << inf << "Removed Tab #" << i << " '" << name << "'" << endl;
1314}
1315
1316// --------------------------------------------------------------------------
1317//
1318// Use this to check whether the MStatusDisplay still contains the
1319// TCanvas c. It could be removed meanwhile by menu usage.
1320//
1321Bool_t MStatusDisplay::HasCanvas(const TCanvas *c) const
1322{
1323 if (!c)
1324 return kFALSE;
1325
1326 if (gROOT->IsBatch())
1327 return (Bool_t)fBatch->FindObject(c);
1328
1329 for (int i=1; i<fTab->GetNumberOfTabs(); i++)
1330 if (c==GetCanvas(i))
1331 return kTRUE;
1332 return kFALSE;
1333}
1334
1335/*
1336 if (...)
1337 fMenu->AddPopup("&CaOs", fCaOs, NULL);
1338 else
1339 fMenu->RemovePopup("CaOs");
1340 fMenu->Resize(fMenu->GetDefaultSize());
1341 MapSubwindows();
1342 MapWindow();
1343 */
1344
1345void MStatusDisplay::Reset()
1346{
1347 if (gROOT->IsBatch())
1348 {
1349 fBatch->Delete();
1350 return;
1351 }
1352
1353 for (int i=fTab->GetNumberOfTabs()-1; i>0; i--)
1354 RemoveTab(i);
1355}
1356
1357Bool_t MStatusDisplay::SaveLogAsPS(const char *n) const
1358{
1359 TString name(n);
1360 AddExtension(name, "ps");
1361
1362 // Code taken from TGTextEdit::Print
1363 const TString pipe = MString::Form("a2ps -o%s", name.Data());
1364 FILE *p = gSystem->OpenPipe(pipe, "w");
1365 if (!p)
1366 {
1367 *fLog << err << "ERROR - Couldn't open pipe " << pipe << endl;
1368 return kFALSE;
1369 }
1370
1371 TGText *text = fLogBox->GetText();
1372
1373 char *buf1, *buf2;
1374 Long_t len;
1375 ULong_t i = 0;
1376 TGLongPosition pos;
1377
1378 pos.fX = pos.fY = 0;
1379 while (pos.fY < text->RowCount())
1380 {
1381 len = text->GetLineLength(pos.fY);
1382 buf1 = text->GetLine(pos, len);
1383 buf2 = new char[len + 2];
1384 strncpy(buf2, buf1, (UInt_t)len);
1385 buf2[len] = '\n';
1386 buf2[len+1] = '\0';
1387 while (buf2[i] != '\0') {
1388 if (buf2[i] == '\t') {
1389 ULong_t j = i+1;
1390 while (buf2[j] == 16 && buf2[j] != '\0')
1391 j++;
1392 strcpy(buf2+i+1, buf2+j);
1393 }
1394 i++;
1395 }
1396 fwrite(buf2, sizeof(char), strlen(buf2)+1, p);
1397
1398 delete [] buf1;
1399 delete [] buf2;
1400 pos.fY++;
1401 }
1402 gSystem->ClosePipe(p);
1403 return kTRUE;
1404}
1405
1406// --------------------------------------------------------------------------
1407//
1408// Print the log text.
1409//
1410// The default command line c is: a2ps -P%p
1411// %p: printer name
1412//
1413// The default printer name p is: <empty>
1414//
1415// Both can be changed in .rootrc by:
1416// PrintText.Printer
1417// PrintText.Command
1418//
1419Bool_t MStatusDisplay::PrintLog(const char *p, const char *c)
1420{
1421 static TString sprinter = gEnv->GetValue("PrintText.Printer", p&&*p?p:"");
1422 static TString scmd = gEnv->GetValue("PrintText.Command", c&&*c?c:"a2ps -P%p");
1423
1424 TString tmp;
1425 TString cmd = PrintDialog(sprinter, scmd, tmp);
1426 if (cmd.IsNull())
1427 return kFALSE;
1428
1429 // set status lines
1430 SetStatusLine1("Printing...");
1431 SetStatusLine2("");
1432
1433 // print to temporary file
1434 if (!SaveLogAsPS(cmd))
1435 {
1436 *fLog << warn << "MStatusDisplay::PrintLog: Sorry, couldn't create postscript!" << endl;
1437 SetStatusLine2("Failed!");
1438 return kFALSE;
1439 }
1440
1441 // execute command
1442 *fLog << dbg << "Executing: " << cmd << endl;
1443 gSystem->Exec(cmd);
1444
1445 SetStatusLine2("Done.");
1446
1447 return kTRUE;
1448}
1449
1450// --------------------------------------------------------------------------
1451//
1452// Process the kC_COMMAND, kCM_MENU messages
1453//
1454Bool_t MStatusDisplay::ProcessMessageCommandMenu(Long_t id)
1455{
1456 switch (id)
1457 {
1458 case kLoopStop:
1459 case kFileClose:
1460 case kFileExit:
1461 if (id==kFileExit || id==kFileClose)
1462 if (Close())
1463 delete this;
1464 fStatus = (Status_t)id;
1465 return kTRUE;
1466
1467 case kFileCanvas:
1468 new TCanvas;
1469 return kTRUE;
1470
1471 case kFileBrowser:
1472 new TBrowser;
1473 return kTRUE;
1474
1475 case kFileTab:
1476 AddTab(MString::Form("%d", fTab->GetNumberOfTabs()));
1477 return kTRUE;
1478
1479 case kFileReset:
1480 Reset();
1481 return kTRUE;
1482
1483 case kFileOpen:
1484 Open();
1485 return kTRUE;
1486
1487 case kFileSaveAs:
1488 SaveAs();
1489 return kTRUE;
1490
1491 case kFileSaveAsPS:
1492 SaveAsPS();
1493 return kTRUE;
1494
1495 case kFileSaveAsPDF:
1496 SaveAsPDF();
1497 return kTRUE;
1498
1499 case kFileSaveAsSVG:
1500 SaveAsSVG();
1501 return kTRUE;
1502
1503 case kFileSaveAsPNG:
1504 SaveAsPNG();
1505 return kTRUE;
1506
1507 case kFileSaveAsGIF:
1508 SaveAsGIF();
1509 return kTRUE;
1510
1511 case kFileSaveAsXPM:
1512 SaveAsXPM();
1513 return kTRUE;
1514
1515 case kFileSaveAsJPG:
1516 SaveAsJPG();
1517 return kTRUE;
1518
1519 //case kFileSaveAsXCF:
1520 // SaveAsXCF();
1521 // return kTRUE;
1522
1523 //case kFileSaveAsTIFF:
1524 // SaveAsTIFF();
1525 // return kTRUE;
1526
1527 case kFileSaveAsBMP:
1528 SaveAsBMP();
1529 return kTRUE;
1530
1531 case kFileSaveAsXML:
1532 SaveAsXML();
1533 return kTRUE;
1534
1535 case kFileSaveAsC:
1536 SaveAsC();
1537 return kTRUE;
1538
1539 case kFileSaveAsRoot:
1540 SaveAsRoot();
1541 return kTRUE;
1542
1543 case kFilePrint:
1544 PrintPS();
1545 return kTRUE;
1546
1547 case kTabSaveAs:
1548 SaveAs(fTab->GetCurrent());
1549 return kTRUE;
1550
1551 case kTabSaveAsPS:
1552 SaveAsPS(fTab->GetCurrent());
1553 return kTRUE;
1554
1555 case kTabSaveAsPDF:
1556 SaveAsPDF(fTab->GetCurrent());
1557 return kTRUE;
1558
1559 case kTabSaveAsSVG:
1560 SaveAsSVG(fTab->GetCurrent());
1561 return kTRUE;
1562
1563 case kTabSaveAsPNG:
1564 SaveAsPNG(fTab->GetCurrent());
1565 return kTRUE;
1566
1567 case kTabSaveAsGIF:
1568 SaveAsGIF(fTab->GetCurrent());
1569 return kTRUE;
1570
1571 case kTabSaveAsXPM:
1572 SaveAsXPM(fTab->GetCurrent());
1573 return kTRUE;
1574
1575 case kTabSaveAsJPG:
1576 SaveAsJPG(fTab->GetCurrent());
1577 return kTRUE;
1578
1579 //case kTabSaveAsXCF:
1580 // SaveAsXCF(fTab->GetCurrent());
1581 // return kTRUE;
1582
1583 //case kTabSaveAsTIFF:
1584 // SaveAsTIFF(fTab->GetCurrent());
1585 // return kTRUE;
1586
1587 case kTabSaveAsBMP:
1588 SaveAsBMP(fTab->GetCurrent());
1589 return kTRUE;
1590
1591 case kTabSaveAsXML:
1592 SaveAsXML(fTab->GetCurrent());
1593 return kTRUE;
1594
1595 case kTabSaveAsC:
1596 SaveAsC(fTab->GetCurrent());
1597 return kTRUE;
1598
1599 case kTabSaveAsRoot:
1600 SaveAsRoot(fTab->GetCurrent());
1601 return kTRUE;
1602
1603 case kTabPrint:
1604 PrintPS(fTab->GetCurrent());
1605 return kTRUE;
1606
1607 case kTabNext:
1608 fTab->SetTab(fTab->GetCurrent()+1);
1609 return kTRUE;
1610
1611 case kTabPrevious:
1612 fTab->SetTab(fTab->GetCurrent()-1);
1613 return kTRUE;
1614
1615 case kTabRemove:
1616 RemoveTab(fTab->GetCurrent());
1617 return kTRUE;
1618
1619 case kSize640:
1620 Resize(572, 480);
1621 return kTRUE;
1622 case kSize768:
1623 Resize(714, 576);
1624 return kTRUE;
1625 case kSize800:
1626 Resize(750, 600);
1627 return kTRUE;
1628 case kSize960:
1629 Resize(900, 700);
1630 return kTRUE;
1631 case kSize1024:
1632 Resize(1000, 768);
1633 return kTRUE;
1634 case kSize1152:
1635 Resize(1147, 864);
1636 return kTRUE;
1637 case kSize1280:
1638 Resize(1321, 980);
1639 return kTRUE;
1640 case kSize1400:
1641 Resize(1426, 1050);
1642 return kTRUE;
1643 case kSize1600:
1644 Resize(1550, 1400);
1645 return kTRUE;
1646
1647 case kLogClear:
1648 fLogBox->Clear();
1649 return kTRUE;
1650 case kLogCopy:
1651 fLogBox->Copy();
1652 return kTRUE;
1653 case kLogSelect:
1654 fLogBox->SelectAll();
1655 return kTRUE;
1656 case kLogFind:
1657 new MSearch(this);
1658 return kTRUE;
1659 case kLogSave:
1660 SetStatusLine1("Saving log...");
1661 SetStatusLine2("");
1662 *fLog << inf << "Saving log... " << flush;
1663 if (fLogBox->GetText()->Save(MString::Form("%s.log", gROOT->GetName())))
1664 {
1665 *fLog << "done." << endl;
1666 SetStatusLine2("done.");
1667 }
1668 else
1669 {
1670 *fLog << "failed!" << endl;
1671 SetStatusLine2("Failed!");
1672 }
1673 return kTRUE;
1674
1675 case kLogAppend:
1676 SetStatusLine1("Appending log...");
1677 SetStatusLine2("");
1678 *fLog << inf << "Appending log... " << flush;
1679 if (fLogBox->GetText()->Append(MString::Form("%s.log", gROOT->GetName())))
1680 {
1681 *fLog << "done." << endl;
1682 SetStatusLine2("done.");
1683 }
1684 else
1685 {
1686 *fLog << "failed!" << endl;
1687 SetStatusLine2("Failed!");
1688 }
1689 return kTRUE;
1690
1691 case kLogPrint:
1692 PrintLog();
1693 return kTRUE;
1694#ifdef DEBUG
1695 default:
1696 cout << "Command-Menu #" << id << endl;
1697#endif
1698 }
1699 return kTRUE;
1700
1701}
1702
1703// --------------------------------------------------------------------------
1704//
1705// Process the kC_COMMAND messages
1706//
1707Bool_t MStatusDisplay::ProcessMessageCommand(Long_t submsg, Long_t mp1, Long_t mp2)
1708{
1709 switch (submsg)
1710 {
1711 case kCM_MENU: // 1
1712 return ProcessMessageCommandMenu(mp1); // mp2=userdata
1713 case kCM_TAB: // 8
1714 /*
1715 for (int i=0; i<fTab->GetNumberOfTabs(); i++)
1716 fTab->GetTabContainer(i)->UnmapWindow();
1717 */
1718 UpdateTab(fTab->GetTabContainer(mp1));
1719 //fTab->GetTabContainer(mp1)->MapWindow();
1720
1721 /*
1722 if (mp1>0)
1723 fMenu->AddPopup("&CaOs", fCaOs, NULL);
1724 else
1725 fMenu->RemovePopup("CaOs");
1726 fMenu->Resize(fMenu->GetDefaultSize());
1727 MapSubwindows();
1728 MapWindow();
1729 */
1730 return kTRUE;
1731 case kCM_COMBOBOX: // 7
1732 if (mp1==kTabs)
1733 fTab->SetTab(mp2);
1734 return kTRUE;
1735#ifdef DEBUG
1736 case kCM_MENUSELECT: // 2
1737 cout << "Command-Menuselect #" << mp1 << " (UserData=" << (void*)mp2 << ")" << endl;
1738 return kTRUE;
1739
1740 case kCM_BUTTON: // 3
1741 cout << "Command-Button." << endl;
1742 return kTRUE;
1743
1744 case kCM_CHECKBUTTON: // 4
1745 cout << "Command-CheckButton." << endl;
1746 return kTRUE;
1747
1748 case kCM_RADIOBUTTON: // 5
1749 cout << "Command-RadioButton." << endl;
1750 return kTRUE;
1751
1752 case kCM_LISTBOX: // 6
1753 cout << "Command-Listbox #" << mp1 << " (LineId #" << mp2 << ")" << endl;
1754 return kTRUE;
1755 default:
1756 cout << "Command: " << "Submsg:" << submsg << " Mp1=" << mp1 << " Mp2=" << mp2 << endl;
1757#endif
1758 }
1759 return kTRUE;
1760}
1761
1762// --------------------------------------------------------------------------
1763//
1764// Process the kC_TEXTVIEW messages
1765//
1766Bool_t MStatusDisplay::ProcessMessageTextview(Long_t submsg, Long_t mp1, Long_t mp2)
1767{
1768 // kC_TEXTVIEW, kTXT_ISMARKED, widget id, [true|false] //
1769 // kC_TEXTVIEW, kTXT_DATACHANGE, widget id, 0 //
1770 // kC_TEXTVIEW, kTXT_CLICK2, widget id, position (y << 16) | x) //
1771 // kC_TEXTVIEW, kTXT_CLICK3, widget id, position (y << 16) | x) //
1772 // kC_TEXTVIEW, kTXT_F3, widget id, true //
1773 // kC_TEXTVIEW, kTXT_OPEN, widget id, 0 //
1774 // kC_TEXTVIEW, kTXT_CLOSE, widget id, 0 //
1775 // kC_TEXTVIEW, kTXT_SAVE, widget id, 0 //
1776#ifdef DEBUG
1777 switch (submsg)
1778 {
1779 case kTXT_ISMARKED:
1780 cout << "Textview-IsMarked #" << mp1 << " " << (mp2?"yes":"no") << endl;
1781 return kTRUE;
1782
1783 case kTXT_DATACHANGE:
1784 cout << "Textview-DataChange #" << mp1 << endl;
1785 return kTRUE;
1786
1787 case kTXT_CLICK2:
1788 cout << "Textview-Click2 #" << mp1 << " x=" << (mp2&0xffff) << " y= " << (mp2>>16) << endl;
1789 return kTRUE;
1790
1791 case kTXT_CLICK3:
1792 cout << "Textview-Click3 #" << mp1 << " x=" << (mp2&0xffff) << " y= " << (mp2>>16) << endl;
1793 return kTRUE;
1794
1795 case kTXT_F3:
1796 cout << "Textview-F3 #" << mp1 << endl;
1797 return kTRUE;
1798
1799 case kTXT_OPEN:
1800 cout << "Textview-Open #" << mp1 << endl;
1801 return kTRUE;
1802
1803 case kTXT_CLOSE:
1804 cout << "Textview-Close #" << mp1 << endl;
1805 return kTRUE;
1806
1807 case kTXT_SAVE:
1808 cout << "Textview-Save #" << mp1 << endl;
1809 return kTRUE;
1810
1811 default:
1812 cout << "Textview: " << "Submsg:" << submsg << " Mp1=" << mp1 << " Mp2=" << mp2 << endl;
1813 }
1814#endif
1815 return kTRUE;
1816}
1817
1818// --------------------------------------------------------------------------
1819//
1820// Process the kC_USER messages
1821//
1822Bool_t MStatusDisplay::ProcessMessageUser(Long_t submsg, Long_t mp1, Long_t mp2)
1823{
1824 // kS_START, case sensitive | backward<<1, char *txt
1825 switch (submsg)
1826 {
1827 case kS_START:
1828 fLogBox->Search((char*)mp2, !(mp1&2>>1), mp1&1);
1829 return kTRUE;
1830#ifdef DEBUG
1831 default:
1832 cout << "User: " << "Submsg:" << submsg << " Mp1=" << mp1 << " Mp2=" << mp2 << endl;
1833#endif
1834 }
1835 return kTRUE;
1836}
1837
1838// --------------------------------------------------------------------------
1839//
1840// Process the messages from the GUI
1841//
1842Bool_t MStatusDisplay::ProcessMessage(Long_t msg, Long_t mp1, Long_t mp2)
1843{
1844 // Can be found in WidgetMessageTypes.h
1845#ifdef DEBUG
1846 cout << "Msg: " << GET_MSG(msg) << " Submsg:" << GET_SUBMSG(msg);
1847 cout << " Mp1=" << mp1 << " Mp2=" << mp2 << endl;
1848#endif
1849 switch (GET_MSG(msg))
1850 {
1851 case kC_COMMAND: // 1
1852 return ProcessMessageCommand(GET_SUBMSG(msg), mp1, mp2);
1853
1854 case kC_TEXTVIEW: // 9
1855 return ProcessMessageTextview(GET_SUBMSG(msg), mp1, mp2);
1856
1857 case kC_USER: // 1001
1858 return ProcessMessageUser(GET_SUBMSG(msg), mp1, mp2);
1859 }
1860#ifdef DEBUG
1861 cout << "Msg: " << GET_MSG(msg) << " Submsg:" << GET_SUBMSG(msg);
1862 cout << " Mp1=" << mp1 << " Mp2=" << mp2 << endl;
1863#endif
1864 return kTRUE;
1865}
1866
1867Bool_t MStatusDisplay::Close()
1868{
1869 // Got close message for this MainFrame. Calls parent CloseWindow()
1870 // (which destroys the window) and terminate the application.
1871 // The close message is generated by the window manager when its close
1872 // window menu item is selected.
1873
1874 // CloseWindow must be overwritten because otherwise CloseWindow
1875 // and the destructor are calling DestroyWindow which seems to be
1876 // in conflict with the TRootEmbeddedCanvas.
1877
1878 // FIXME: Make sure that the Status Display is deleted from every
1879 // where (eg Eventloop) first!
1880
1881 //gLog << dbg << fName << " is on heap: " << (int)IsOnHeap() << endl;
1882
1883 if (TestBit(kExitLoopOnExit) || TestBit(kExitLoopOnClose))
1884 {
1885 //gLog << dbg << "CloseWindow() calling ExitLoop." << endl;
1886 gSystem->ExitLoop();
1887 }
1888
1889 if (fIsLocked<=0 && IsOnHeap())
1890 return kTRUE;
1891
1892 fStatus = kFileExit;
1893 return kFALSE;
1894}
1895
1896void MStatusDisplay::CloseWindow()
1897{
1898 if (Close())
1899 delete this;
1900}
1901
1902// --------------------------------------------------------------------------
1903//
1904// Calls SetBit(kNoContextMenu) for all TCanvas objects found in the
1905// Tabs.
1906//
1907void MStatusDisplay::SetNoContextMenu(Bool_t flag)
1908{
1909 if (fIsLocked>1 || gROOT->IsBatch())
1910 return;
1911
1912 flag ? SetBit(kNoContextMenu) : ResetBit(kNoContextMenu);
1913
1914 for (int i=1; i<fTab->GetNumberOfTabs(); i++)
1915 {
1916 TCanvas *c = GetCanvas(i);
1917 if (c)
1918 flag ? c->SetBit(kNoContextMenu) : c->ResetBit(kNoContextMenu);
1919 }
1920}
1921
1922// --------------------------------------------------------------------------
1923//
1924// Update the memory display in the status bar
1925//
1926void MStatusDisplay::UpdateMemory() const
1927{
1928 const TString path = MString::Form("/proc/%d/status", gSystem->GetPid());
1929 if (gSystem->AccessPathName(path, kFileExists))
1930 return;
1931
1932 TEnv env(path);
1933 const UInt_t kb = env.GetValue("VmSize", 0);
1934 if (kb==0)
1935 return;
1936
1937 char type = 'k';
1938 Float_t val = kb;
1939
1940 if (val>999)
1941 {
1942 type = 'M';
1943 val /= 1000;
1944 }
1945 if (val>999)
1946 {
1947 type = 'G';
1948 val /= 1000;
1949 }
1950 const TString txt = MString::Form("%.1f%c", val, type);
1951 fStatusBar->SetText(txt, 2);
1952}
1953
1954// --------------------------------------------------------------------------
1955//
1956// Updates the canvas (if existing) in the currenly displayed Tab.
1957// The update intervall is controlled by StartUpdate and StopUpdate
1958//
1959Bool_t MStatusDisplay::HandleTimer(TTimer *timer)
1960{
1961 if (gROOT->IsBatch())
1962 return kTRUE;
1963
1964 UpdateMemory();
1965
1966 const Int_t c = fTab->GetCurrent();
1967
1968 // Skip Legend Tab
1969 if (c==0)
1970 return kTRUE;
1971
1972 // Update a canvas tab (if visible)
1973 if (timer==&fTimer && c!=fLogIdx)
1974 {
1975 UpdateTab(fTab->GetCurrentContainer());
1976 return kTRUE;
1977 }
1978
1979 // update the logbook tab (if visible)
1980 if (timer==&fLogTimer && c==fLogIdx)
1981 {
1982 fLog->UpdateGui();
1983
1984 /*
1985 if (!fLogBox->TestBit(kHasChanged))
1986 return kTRUE;
1987
1988 fLogBox->ResetBit(kHasChanged);
1989 */
1990 return kTRUE;
1991 }
1992
1993 return kTRUE;
1994}
1995
1996// --------------------------------------------------------------------------
1997//
1998// Draws a clone of a canvas into a new canvas. Taken from TCanvas.
1999//
2000void MStatusDisplay::DrawClonePad(TCanvas &newc, TCanvas &oldc) const
2001{
2002 //copy pad attributes
2003 newc.Range(oldc.GetX1(),oldc.GetY1(),oldc.GetX2(),oldc.GetY2());
2004 newc.SetTickx(oldc.GetTickx());
2005 newc.SetTicky(oldc.GetTicky());
2006 newc.SetGridx(oldc.GetGridx());
2007 newc.SetGridy(oldc.GetGridy());
2008 newc.SetLogx(oldc.GetLogx());
2009 newc.SetLogy(oldc.GetLogy());
2010 newc.SetLogz(oldc.GetLogz());
2011 newc.SetBorderSize(oldc.GetBorderSize());
2012 newc.SetBorderMode(oldc.GetBorderMode());
2013 ((TAttLine&)oldc).Copy((TAttLine&)newc);
2014 ((TAttFill&)oldc).Copy((TAttFill&)newc);
2015 ((TAttPad&)oldc).Copy((TAttPad&)newc);
2016
2017 // This must be there: Otherwise GetDrawOption() won't work
2018 TVirtualPad *padsav = gPad;
2019 oldc.cd();
2020
2021 const Bool_t store = TH1::AddDirectoryStatus();
2022 TH1::AddDirectory(kFALSE);
2023
2024 //copy primitives
2025 TObject *obj;
2026 TIter next(oldc.GetListOfPrimitives());
2027 while ((obj=next()))
2028 {
2029 // Old line - I think it is not necessary anymore because of the cd()
2030 //gROOT->SetSelectedPad(&newc);
2031
2032 // Now make a clone of the object
2033 TObject *clone = obj->Clone();
2034
2035 // Clone also important bits (FIXME: Is this correct)
2036 clone->SetBit(obj->TestBits(kCannotPick|kNoContextMenu));
2037
2038 // Now make sure that the clones are deleted at a later time
2039 clone->SetBit(kCanDelete|kMustCleanup);
2040
2041 // FIXME: This is a workaround for the problem with the MAstroCatalog in
2042 // MHFalseSource. It doesn't harm. We'll still try to find the reason
2043 if (clone->IsA()==TPad::Class())
2044 gROOT->GetListOfCleanups()->Add(clone);
2045
2046 // Add the clone and its draw-option to the current pad
2047 TVirtualPad *save2 = gPad;
2048 gPad = &oldc; // Don't do this before Clone()!
2049 newc.GetListOfPrimitives()->Add(clone, obj->GetDrawOption());
2050 gPad = save2;
2051 }
2052 newc.Modified();
2053 newc.Update();
2054
2055 TH1::AddDirectory(store);
2056
2057 padsav->cd();
2058}
2059
2060Bool_t MStatusDisplay::Display(const TObjArray &list, const char *tab)
2061{
2062 TIter Next(&list);
2063
2064 TObject *o=Next();
2065 if (!o)
2066 {
2067 *fLog << err << "MStatusDisplay::Display: No entry in TObjArray." << endl;
2068 return kFALSE;
2069 }
2070
2071 fTitle = o->GetTitle();
2072
2073 TCanvas *c;
2074 while ((c=(TCanvas*)Next()))
2075 //if (!GetCanvas(c->GetName()))
2076 if (!tab || c->GetName()==(TString)tab)
2077 DrawClonePad(c->GetName(), *c);
2078
2079 return kTRUE;
2080}
2081
2082// --------------------------------------------------------------------------
2083//
2084// Reads the contents of a saved MStatusDisplay from a file.
2085//
2086Int_t MStatusDisplay::Read(const char *name, const char *tab)
2087{
2088 if (!gFile)
2089 {
2090 *fLog << warn << "MStatusDisplay::Read: No file found. Please create a TFile first." << endl;
2091 return 0;
2092 }
2093
2094 if (!gFile->IsOpen())
2095 {
2096 *fLog << warn << "MStatusDisplay::Read: File not open. Please open the TFile first." << endl;
2097 return 0;
2098 }
2099
2100 MStatusArray list;
2101
2102 const Int_t n = list.Read(name);
2103 if (n==0)
2104 {
2105 *fLog << warn << "MStatusDisplay::Read: No objects read." << endl;
2106 return 0;
2107 }
2108
2109 if (!Display(list, tab))
2110 {
2111 *fLog << err << "MStatusDisplay::Display: No entry in " << name << "." << endl;
2112 return 0;
2113 }
2114
2115 *fLog << inf << "MStatusDisplay: Key " << name << " with " << n << " keys read from file." << endl;
2116
2117 return n;
2118}
2119
2120// --------------------------------------------------------------------------
2121//
2122// Writes the contents of a MStatusDisplay to a file.
2123//
2124Int_t MStatusDisplay::Write(Int_t num, const char *name, Int_t option, Int_t bufsize) const
2125{
2126 if (!gFile)
2127 {
2128 *fLog << warn << "MStatusDisplay::Write: No file found. Please create a TFile first." << endl;
2129 return 0;
2130 }
2131
2132 if (!gFile->IsOpen())
2133 {
2134 *fLog << warn << "MStatusDisplay::Write: File not open. Please open the TFile first." << endl;
2135 return 0;
2136 }
2137
2138 if (!gFile->IsWritable())
2139 {
2140 *fLog << warn << "MStatusDisplay::Write: File not writable." << endl;
2141 return 0;
2142 }
2143
2144 if (num==0)
2145 {
2146 *fLog << warn << "MStatusDisplay::Write: Tab doesn't contain an embedded Canvas... skipped." << endl;
2147 return 0;
2148 }
2149
2150 if (!gROOT->IsBatch() && num>=fTab->GetNumberOfTabs())
2151 {
2152 *fLog << warn << "MStatusDisplay::Write: Tab doesn't exist... skipped." << endl;
2153 return 0;
2154 }
2155 if (gROOT->IsBatch() && num>fBatch->GetSize())
2156 {
2157 *fLog << warn << "MStatusDisplay::Write: Tab doesn't exist... skipped." << endl;
2158 return 0;
2159 }
2160
2161 MStatusArray list;
2162
2163 TNamed named;
2164 named.SetTitle(fTitle);
2165 list.Add(&named);
2166
2167 Int_t from, to;
2168 GetCanvasRange(from, to, num);
2169
2170 TCanvas *c;
2171 for (int i=from; i<to; i++)
2172 if ((c = GetCanvas(i)))
2173 list.Add(c);
2174
2175 const Int_t n = list.Write(name, kSingleKey);
2176
2177 //*fLog << inf << "MStatusDisplay: " << n << " keys written to file as key " << name << "." << endl;
2178
2179 return n;
2180}
2181
2182// --------------------------------------------------------------------------
2183//
2184// Use this to start the synchronous (GUI eventloop driven) tab update.
2185// Can also be used to change the update intervall. If millisec<0
2186// the intervall given in SetUpdateTime is used. If the intervall in
2187// SetUpdateTime is <0 nothing is done. (Call SetUpdateTime(-1) to
2188// disable the automatic update in a MEventloop.
2189//
2190void MStatusDisplay::StartUpdate(Int_t millisec)
2191{
2192 if (fIsLocked>1)
2193 return;
2194
2195 if (fTimer.GetTime()<TTime(0))
2196 return;
2197 fTimer.Start(millisec);
2198}
2199
2200// --------------------------------------------------------------------------
2201//
2202// Stops the automatic GUI update
2203//
2204void MStatusDisplay::StopUpdate()
2205{
2206 if (fIsLocked>1)
2207 return;
2208
2209 fTimer.Stop();
2210}
2211
2212// --------------------------------------------------------------------------
2213//
2214// Set the update interval for the GUI update, see StartUpdate.
2215//
2216void MStatusDisplay::SetUpdateTime(Long_t t)
2217{
2218 fTimer.SetTime(t);
2219}
2220
2221// --------------------------------------------------------------------------
2222//
2223// Set the background color in a canvas
2224//
2225void MStatusDisplay::CanvasSetFillColor(TPad &p, Int_t col) const
2226{
2227 TObject *obj;
2228
2229 // See also TPad::UseCurrentStyle
2230 TIter Next(p.GetListOfPrimitives());
2231 while ((obj=Next()))
2232 {
2233 if (obj->InheritsFrom(TPad::Class()))
2234 CanvasSetFillColor(*(TPad*)obj, col);
2235 if (obj->InheritsFrom(TFrame::Class()))
2236 ((TFrame*)obj)->SetFillColor(col);
2237 }
2238
2239 p.SetFillColor(col);
2240}
2241
2242// --------------------------------------------------------------------------
2243//
2244// If the filename name doesn't end with ext, ext is added to the end.
2245// If name.IsNull() "status" is assumed and the a number (>0) is added
2246// as "status-6".
2247// The extension is returned.
2248//
2249const TString &MStatusDisplay::AddExtension(TString &name, const TString &ext, Int_t num) const
2250{
2251 if (name.IsNull())
2252 {
2253 name = gROOT->GetName();
2254 if (num>0)
2255 {
2256 name += "-";
2257 name += num;
2258 }
2259 }
2260
2261 if (name.EndsWith("."+ext))
2262 return ext;
2263
2264 name += ".";
2265 name += ext;
2266
2267 return ext;
2268}
2269
2270Bool_t MStatusDisplay::CheckTabForCanvas(int num) const
2271{
2272 if (gROOT->IsBatch())
2273 return num>0 && num<=fBatch->GetSize() || num<0;
2274
2275 if (num>=fTab->GetNumberOfTabs())
2276 {
2277 *fLog << warn << "Tab #" << num << " doesn't exist..." << endl;
2278 return kFALSE;
2279 }
2280 if (num==0)
2281 {
2282 *fLog << warn << "Tab #" << num << " doesn't contain an embedded canvas..." << endl;
2283 return kFALSE;
2284 }
2285 if (fTab->GetNumberOfTabs()<2 || !gPad)
2286 {
2287 *fLog << warn << "Sorry, you must have at least one existing canvas (gPad!=NULL)" << endl;
2288 return kFALSE;
2289 }
2290 return kTRUE;
2291}
2292
2293// --------------------------------------------------------------------------
2294//
2295// Insert the following two lines into the postscript header:
2296//
2297// %%DocumentPaperSizes: a4
2298// %%Orientation: Landscape
2299//
2300void MStatusDisplay::UpdatePSHeader(const TString &name) const
2301{
2302 const TString newstr("%%DocumentPaperSizes: a4\n%%Orientation: Landscape\n");
2303
2304 ifstream fin(name);
2305 ofstream fout(name+".$$$");
2306
2307 char c;
2308
2309 TString str;
2310 fin >> str >> c; // Read "%!PS-Adobe-2.0\n"
2311 fout << str << endl << newstr;
2312
2313 // Doing it in blocks seems not to gain much for small (MB) files
2314 while (fin)
2315 {
2316 fin.read(&c, 1);
2317 fout.write(&c, 1);
2318 }
2319
2320 gSystem->Unlink(name);
2321 gSystem->Rename(name+".$$$", name);
2322}
2323
2324void MStatusDisplay::PSToolsRange(TVirtualPS &vps, Float_t psw, Float_t psh) const
2325{
2326 if (vps.InheritsFrom(TPostScript::Class()))
2327 static_cast<TPostScript&>(vps).Range(psw, psh);
2328 // if (vps.InheritsFrom(TPDF::Class()))
2329 // static_cast<TPDF&>(vps).Range(psw*0.69, psh*0.69);
2330 // if (vps.InheritsFrom(TSVG::Class()))
2331 // static_cast<TSVG&>(vps).Range(psw, psh);
2332}
2333
2334void MStatusDisplay::PSToolsTextNDC(TVirtualPS &vps, Double_t u, Double_t v, const char *string) const
2335{
2336 if (vps.InheritsFrom(TPostScript::Class()))
2337 static_cast<TPostScript&>(vps).TextNDC(u, v, string);
2338 if (vps.InheritsFrom(TPDF::Class()))
2339 static_cast<TPDF&>(vps).TextNDC(u, v, string);
2340 // if (vps.InheritsFrom(TSVG::Class()))
2341 // static_cast<TSVG&>(vps).TextNDC(u, v, string);
2342}
2343
2344// --------------------------------------------------------------------------
2345//
2346// Write some VGF (vector graphics format). Currently PS, PDF and SVG
2347// is available. Specified by ext.
2348//
2349// In case of num<0 all tabs are written into the VGF file. If num>0
2350// the canvas in the corresponding tab is written to the file.
2351// Name is the name of the file (with or without extension).
2352//
2353// Returns the number of pages written.
2354//
2355// To write all tabs you can also use SaveAsVGF(name, ext)
2356//
2357// If the third argument is given a bottom line is drawn with the text
2358// under it. If no argument is given a bottom line is drawn if
2359// fTitle (SetTitle) is not empty.
2360//
2361Int_t MStatusDisplay::SaveAsVGF(Int_t num, TString name, const TString addon, const TString ext)
2362{
2363 SetStatusLine1(Form("Writing %s file...",ext.Data()));
2364 SetStatusLine2("");
2365
2366 if (!CheckTabForCanvas(num))
2367 {
2368 SetStatusLine2("Failed!");
2369 return 0;
2370 }
2371
2372 AddExtension(name, ext, num);
2373
2374 if (num<0)
2375 *fLog << inf << "Open " << ext << "-File: " << name << endl;
2376
2377 TPad *padsav = (TPad*)gPad;
2378 TVirtualPS *psave = gVirtualPS;
2379
2380 TDatime d;
2381
2382 Int_t type = -1;
2383
2384 TVirtualPS *ps =0;
2385 if (!ext.CompareTo("ps", TString::kIgnoreCase))
2386 {
2387 ps = new TPostScript(name, 112);
2388 type = 1;
2389 }
2390 if (!ext.CompareTo("pdf", TString::kIgnoreCase))
2391 {
2392 ps = new TPDF(name, 112);
2393 type = 2;
2394 }
2395 if (!ext.CompareTo("svg", TString::kIgnoreCase))
2396 {
2397 ps = new TSVG(name, 112);
2398 type = 3;
2399 }
2400
2401 if (!ps)
2402 {
2403 *fLog << err << "Extension " << ext << " unknown..." << endl;
2404 SetStatusLine2("Failed!");
2405 return 0;
2406 }
2407
2408 ps->SetBit(TPad::kPrintingPS);
2409 if (type==1)
2410 ps->PrintFast(13, "/nan {1} def ");
2411
2412 gVirtualPS = ps;
2413
2414 //
2415 // Create a list to delete the canvas clones
2416 //
2417 TList l;
2418 l.SetOwner();
2419
2420 //
2421 // Create some GUI elements for a page legend
2422 //
2423 TLine line;
2424
2425 int page = 1;
2426
2427 //
2428 // Maintain tab numbers
2429 //
2430 Int_t from, to;
2431 GetCanvasRange(from, to, num);
2432
2433 for (int i=from; i<to; i++)
2434 {
2435 TCanvas *c;
2436 if (!(c = GetCanvas(i)))
2437 {
2438 if (num<0)
2439 *fLog << inf << " - ";
2440 *fLog << "Tab #" << i << " doesn't contain an embedded Canvas... skipped." << endl;
2441 continue;
2442 }
2443
2444 SetStatusLine2(MString::Form("Tab #%d", i));
2445
2446 //
2447 // Init page and page size, make sure, that the canvas in the file
2448 // has the same Aspect Ratio than on the screen.
2449 //
2450 if (type==1 || i>from)
2451 ps->NewPage();
2452
2453 //
2454 // 28 is used here to scale the canvas into a height of 28,
2455 // such that the page title can be set above the canvas...
2456 //
2457 Float_t psw = 28.0; // A4 - width (29.7)
2458 Float_t psh = 21.0; // A4 - height (21.0)
2459
2460 const Float_t cw = c->GetWw();
2461 const Float_t ch = c->GetWh();
2462
2463 if (psw/psh>cw/ch)
2464 psw = cw/ch*psh;
2465 else
2466 psh = ch/cw*psw;
2467
2468 PSToolsRange(*ps, psw, psh);
2469
2470 //
2471 // Clone canvas and change background color and schedule for
2472 // deletion
2473 //
2474 TCanvas *n = (TCanvas*)c->Clone();
2475 CanvasSetFillColor(*n, kWhite);
2476 l.Add(n);
2477
2478 //
2479 // Paint canvas into root file
2480 //
2481 if (num<0)
2482 *fLog << inf << " - ";
2483 *fLog << inf << "Writing Tab #" << i << ": " << c->GetName() << " (" << c << ") ";
2484 if (num>0)
2485 *fLog << "to " << name;
2486 *fLog << "... " << flush;
2487
2488 n->SetBatch(kTRUE);
2489 n->Paint();
2490
2491 //
2492 // Use the canvas as coordinate system for the overlaying text
2493 //
2494 gPad = n;
2495 //n->cd();
2496
2497 //
2498 // Print overlaying text (NDC = %)
2499 //
2500 // align phi col font size (11=left top)
2501 TAttText(11, 0, kBlack, 22, 0.015).Copy(*ps);
2502 PSToolsTextNDC(*ps, 0, 1.015, TString(" ")+n->GetName());
2503 ps->SetTextAlign(21); // cent top
2504 PSToolsTextNDC(*ps, 0.5, 1.015, TString("MARS - Magic Analysis and Reconstruction Software - ")+d.AsString());
2505 ps->SetTextAlign(31); // right top
2506 PSToolsTextNDC(*ps, 1, 1.015, MString::Form("Page No.%i (%i) ", page++, i));
2507 line.PaintLineNDC(0, 1.01, 1, 1.01);
2508
2509 TString txt(addon.IsNull() ? fTitle : addon);
2510 if (!txt.IsNull())
2511 {
2512 line.PaintLineNDC(0, -0.00, 1, -0.00);
2513 ps->SetTextAlign(11); // left top
2514 PSToolsTextNDC(*ps, 0, -0.015, TString(" ")+txt);
2515 ps->SetTextAlign(31); // right top
2516 PSToolsTextNDC(*ps, 1, -0.015, "(c) 2000-2006, Thomas Bretz ");
2517 }
2518
2519 //
2520 // Finish drawing page
2521 //
2522 n->SetBatch(kFALSE);
2523 *fLog << "done." << endl;
2524 }
2525
2526 gPad = NULL; // Important!
2527 l.Delete();
2528
2529 ps->Close();
2530 delete ps;
2531
2532 if (type==1)
2533 {
2534 SetStatusLine2("Updating header of PS file...");
2535
2536 if (num<0)
2537 *fLog << " - Updating header of PS file... " << flush;
2538 UpdatePSHeader(name);
2539 if (num<0)
2540 *fLog << inf << "done." << endl;
2541 }
2542
2543 gVirtualPS = psave;
2544 if (padsav)
2545 padsav->cd();
2546
2547 if (num<0)
2548 *fLog << inf << "done." << endl;
2549
2550 SetStatusLine2(MString::Form("Done (%dpages)", page-1));
2551
2552 return page-1;
2553}
2554
2555Bool_t MStatusDisplay::SaveAsImage(Int_t num, TString name, TImage::EImageFileTypes type)
2556{
2557#if ROOT_VERSION_CODE < ROOT_VERSION(5,12,00)
2558 if (gROOT->IsBatch())
2559 {
2560 *fLog << warn << "Sorry, writing image-files is not available in batch mode." << endl;
2561 return 0;
2562 }
2563#endif
2564
2565 SetStatusLine1("Writing image file...");
2566 SetStatusLine2("please be patient!");
2567
2568 if (!CheckTabForCanvas(num))
2569 {
2570 SetStatusLine2("Failed!");
2571 return 0;
2572 }
2573
2574 TString ext;
2575 switch (type)
2576 {
2577 case TImage::kXpm:
2578 case TImage::kZCompressedXpm:
2579 ext = AddExtension(name, "xpm", num);
2580 break;
2581// case TImage::kGZCompressedXpm:
2582// ext = AddExtension(name, "xpm.gz", num);
2583// break;
2584 case TImage::kPng:
2585 ext = AddExtension(name, "png", num);
2586 break;
2587 case TImage::kJpeg:
2588 ext = AddExtension(name, "jpg", num);
2589 break;
2590 case TImage::kGif:
2591 ext = AddExtension(name, "gif", num);
2592 break;
2593// case TImage::kTiff:
2594// ext = AddExtension(name, "tiff", num);
2595// break;
2596// case TImage::kPpm:
2597// ext = AddExtension(name, "ppm", num);
2598// break;
2599// case TImage::kPnm:
2600// ext = AddExtension(name, "pnm", num);
2601// break;
2602// case TImage::kIco:
2603// ext = AddExtension(name, "ico", num);
2604// break;
2605// case TImage::kCur:
2606// ext = AddExtension(name, "cur", num);
2607// break;
2608 case TImage::kBmp:
2609 ext = AddExtension(name, "bmp", num);
2610 break;
2611// case TImage::kXcf:
2612// ext = AddExtension(name, "xcf", num);
2613// break;
2614// case TImage::kXbm:
2615// ext = AddExtension(name, "xbm", num);
2616// break;
2617// case TImage::kFits:
2618// ext = AddExtension(name, "fits", num);
2619// break;
2620// case TImage::kTga:
2621// ext = AddExtension(name, "tga", num);
2622// break;
2623 case TImage::kXml:
2624 ext = AddExtension(name, "xml", num);
2625 break;
2626 default:
2627 *fLog << warn << "Sorry, unknown or unsupported file type..." << endl;
2628 return 0;
2629 }
2630
2631 if (num<0)
2632 *fLog << inf << "Writing " << ext << "-Files..." << endl;
2633
2634 TPad *padsav = (TPad*)gPad;
2635
2636 int page = 1;
2637
2638 //
2639 // Maintain tab numbers
2640 //
2641 Int_t from, to;
2642 GetCanvasRange(from, to, num);
2643
2644 for (int i=from; i<to; i++)
2645 {
2646 TCanvas *c;
2647 if (!(c = GetCanvas(i)))
2648 {
2649 if (num<0)
2650 *fLog << inf << " - ";
2651 *fLog << "Tab #" << i << " doesn't contain an embedded Canvas... skipped." << endl;
2652 continue;
2653 }
2654
2655 SetStatusLine2(MString::Form("Tab #%d", i));
2656
2657 //
2658 // Clone canvas and change background color and schedule for
2659 // deletion
2660 //
2661 TCanvas *n = c;
2662 //TCanvas *n = (TCanvas*)c->Clone();
2663 //CanvasSetFillColor(*n, kWhite);
2664
2665 //
2666 // Paint canvas into root file
2667 //
2668 TString writename = name;
2669 if (num<0)
2670 {
2671 TString numname = "-";
2672 numname += i;
2673 writename.Insert(name.Last('.'), numname);
2674 }
2675 if (num<0)
2676 *fLog << inf << " - ";
2677 *fLog << inf << "Writing Tab #" << i << " to " << writename << ": " << c->GetName() << " (" << c << ") ";
2678 if (num>0)
2679 *fLog << "to " << name;
2680 *fLog << "..." << flush;
2681
2682#if ROOT_VERSION_CODE < ROOT_VERSION(4,04,00)
2683 n->Draw();
2684
2685 if (type==TImage::kGif)
2686 n->SaveAs(writename); // FIXME: Seems not to work well in TImage! (root 3.10/02)
2687 else
2688 {
2689 TImage *img = TImage::Create();
2690 img->FromPad(n);
2691 img->WriteImage(writename, type);
2692 delete img;
2693 }
2694#else
2695 //gROOT->SetBatch();
2696 n->Print(writename);
2697 //gROOT->SetBatch(kFALSE);
2698#endif
2699 // delete n;
2700 if (num<0)
2701 *fLog << "done." << endl;
2702 }
2703
2704 if (padsav)
2705 padsav->cd();
2706
2707 *fLog << inf << "done." << endl;
2708
2709 SetStatusLine2("Done.");
2710
2711 return page-1;
2712}
2713
2714Bool_t MStatusDisplay::SaveAsC(Int_t num, TString name)
2715{
2716 SetStatusLine1("Writing C++ file...");
2717 SetStatusLine2("");
2718
2719 if (!CheckTabForCanvas(num))
2720 {
2721 SetStatusLine2("Failed!");
2722 return 0;
2723 }
2724
2725 AddExtension(name, "C", num);
2726
2727 if (num<0)
2728 *fLog << inf << "Writing C-Files..." << endl;
2729
2730 TPad *padsav = (TPad*)gPad;
2731
2732 int page = 1;
2733
2734 //
2735 // Maintain tab numbers
2736 //
2737 Int_t from, to;
2738 GetCanvasRange(from, to, num);
2739
2740 for (int i=from; i<to; i++)
2741 {
2742 TCanvas *c;
2743 if (!(c = GetCanvas(i)))
2744 {
2745 if (num<0)
2746 *fLog << inf << " - ";
2747 *fLog << "Tab #" << i << " doesn't contain an embedded Canvas... skipped." << endl;
2748 continue;
2749 }
2750
2751 SetStatusLine2(MString::Form("Tab #%d", i));
2752
2753 //
2754 // Clone canvas and change background color and schedule for
2755 // deletion
2756 //
2757 TCanvas *n = (TCanvas*)c->Clone();
2758 CanvasSetFillColor(*n, kWhite);
2759
2760 //
2761 // Paint canvas into root file
2762 //
2763 TString writename = name;
2764 if (num<0)
2765 {
2766 TString numname = "-";
2767 numname += i;
2768 writename.Insert(name.Last('.'), numname);
2769 }
2770 if (num<0)
2771 *fLog << inf << " - ";
2772 *fLog << inf << "Writing Tab #" << i << " to " << writename << ": " << c->GetName() << " (" << n << ") ";
2773 if (num>0)
2774 *fLog << "to " << name;
2775 *fLog << "..." << flush;
2776
2777 n->SaveSource(writename, "");
2778 delete n;
2779
2780 if (num<0)
2781 *fLog << "done." << endl;
2782 }
2783
2784 if (padsav)
2785 padsav->cd();
2786
2787 *fLog << inf << "done." << endl;
2788
2789 SetStatusLine2("Done.");
2790
2791 return page-1;
2792}
2793
2794// --------------------------------------------------------------------------
2795//
2796// In case of num<0 all tabs are written into the PS file. If num>0
2797// the canvas in the corresponding tab is written to the file.
2798// Name is the name of the file (with or without extension).
2799//
2800// Returns the number of keys written.
2801//
2802// To write all tabs you can also use SaveAsPS(name)
2803//
2804Int_t MStatusDisplay::SaveAsRoot(Int_t num, TString name)
2805{
2806 SetStatusLine1("Writing root file...");
2807 SetStatusLine2("");
2808
2809 if (!CheckTabForCanvas(num))
2810 {
2811 SetStatusLine2("Failed!");
2812 return 0;
2813 }
2814
2815 AddExtension(name, "root", num);
2816
2817 TFile *fsave = gFile;
2818 TFile file(name, "RECREATE", "MARS - Status Window Contents", 9);
2819 const Int_t keys = Write(num);
2820 gFile = fsave;
2821
2822 SetStatusLine2("Done.");
2823
2824 return keys;
2825}
2826
2827// --------------------------------------------------------------------------
2828//
2829// Determin File type to save file as by extension. Allowed extensions are:
2830// root, ps, pdf, svg, gif, png, jpg, xpm, C
2831//
2832// returns -1 if file type is unknown. Otherwise return value of SaveAs*
2833//
2834Int_t MStatusDisplay::SaveAs(Int_t num, TString name)
2835{
2836 if (name.EndsWith(".root")) return SaveAsRoot(num, name);
2837 if (name.EndsWith(".ps")) return SaveAsPS(num, name);
2838 if (name.EndsWith(".pdf")) return SaveAsPDF(num, name);
2839 if (name.EndsWith(".svg")) return SaveAsSVG(num, name);
2840 if (name.EndsWith(".gif")) return SaveAsGIF(num, name);
2841 if (name.EndsWith(".png")) return SaveAsPNG(num, name);
2842 if (name.EndsWith(".bmp")) return SaveAsBMP(num, name);
2843 if (name.EndsWith(".xml")) return SaveAsXML(num, name);
2844 if (name.EndsWith(".jpg")) return SaveAsJPG(num, name);
2845 if (name.EndsWith(".xpm")) return SaveAsXPM(num, name);
2846 if (name.EndsWith(".C")) return SaveAsC(num, name);
2847 return -1;
2848}
2849
2850// --------------------------------------------------------------------------
2851//
2852// Opens a save as dialog
2853//
2854Int_t MStatusDisplay::SaveAs(Int_t num)
2855{
2856 static const char *gSaveAsTypes[] =
2857 {
2858 "PostScript", "*.ps",
2859 "Acrobat pdf", "*.pdf",
2860 "SVG vector", "*.svg",
2861 "Gif files", "*.gif",
2862 "Png files", "*.png",
2863 "Gif files", "*.gif",
2864 "Jpeg files", "*.jpeg",
2865 "Xpm files", "*.xpm",
2866 "Bmp files", "*.bmp",
2867 "Xml files", "*.xml",
2868 "Macro files", "*.C",
2869 "ROOT files", "*.root",
2870 "All files", "*",
2871 NULL, NULL
2872 };
2873
2874 static TString dir(".");
2875
2876 TGFileInfo fi; // fFileName and fIniDir deleted in ~TGFileInfo
2877
2878 fi.fFileTypes = (const char**)gSaveAsTypes;
2879 fi.fIniDir = StrDup(dir);
2880
2881 new TGFileDialog(fClient->GetRoot(), this, kFDSave, &fi);
2882
2883 if (!fi.fFilename)
2884 return 0;
2885
2886 dir = fi.fIniDir;
2887
2888 const Int_t rc = SaveAs(num, fi.fFilename);
2889 if (rc>=0)
2890 return rc;
2891
2892 Warning("MStatusDisplay::SaveAs", "Unknown Extension: %s", fi.fFilename);
2893 return 0;
2894}
2895
2896// --------------------------------------------------------------------------
2897//
2898// Open contents of a MStatusDisplay with key name from file fname.
2899//
2900Int_t MStatusDisplay::Open(TString fname, const char *name)
2901{
2902 TFile file(fname, "READ");
2903 if (file.IsZombie())
2904 {
2905 gLog << warn << "WARNING - Cannot open file " << fname << endl;
2906 return 0;
2907 }
2908
2909 return Read(name);
2910}
2911
2912// --------------------------------------------------------------------------
2913//
2914// Opens an open dialog
2915//
2916Int_t MStatusDisplay::Open()
2917{
2918 static const char *gOpenTypes[] =
2919 {
2920 "ROOT files", "*.root",
2921 "All files", "*",
2922 NULL, NULL
2923 };
2924
2925 static TString dir(".");
2926
2927 TGFileInfo fi; // fFileName and fIniDir deleted in ~TGFileInfo
2928
2929 fi.fFileTypes = (const char**)gOpenTypes;
2930 fi.fIniDir = StrDup(dir);
2931
2932 new TGFileDialog(fClient->GetRoot(), this, kFDOpen, &fi);
2933
2934 if (!fi.fFilename)
2935 return 0;
2936
2937 dir = fi.fIniDir;
2938
2939 return Open(fi.fFilename);
2940}
2941
2942Bool_t MStatusDisplay::HandleConfigureNotify(Event_t *evt)
2943{
2944 //
2945 // The initialization of the GUI is not yet enough finished...
2946 //
2947 if (!fTab)
2948 return kTRUE;
2949
2950 UInt_t w = evt->fWidth;
2951 UInt_t h = evt->fHeight;
2952
2953 const Bool_t wchanged = w!=GetWidth();
2954 const Bool_t hchanged = h!=GetHeight();
2955
2956 if (!wchanged && !hchanged)
2957 {
2958 Layout();
2959 // FIXME: Make sure that this doesn't result in endless loops.
2960 return kTRUE;
2961 }
2962
2963 if (GetWidth()==1 && GetHeight()==1)
2964 return kTRUE;
2965
2966 // calculate the constant part of the window
2967 const UInt_t cw = GetWidth() -fTab->GetWidth();
2968 const UInt_t ch = GetHeight()-fTab->GetHeight()+fTab->GetTabHeight();
2969
2970 // calculate new size of frame (canvas @ 2:3)
2971 if (hchanged)
2972 w = TMath::Nint((h-ch)*1.5+cw);
2973 else
2974 h = TMath::Nint((w-cw)/1.5+ch);
2975
2976 // resize frame
2977 Resize(w, h);
2978
2979 return kTRUE;
2980}
2981
2982Bool_t MStatusDisplay::HandleEvent(Event_t *event)
2983{
2984 // Instead of doing this in CloseWindow (called from HandleEvent)
2985 // we do it here. This makes sure, that handle event doesn't
2986 // execute code after deleting this.
2987 if (event->fType==kDestroyNotify)
2988 {
2989 if (Close())
2990 delete this;
2991// Close();
2992 return kTRUE;
2993 }
2994
2995 const Bool_t rc = TGMainFrame::HandleEvent(event);
2996
2997 //
2998 // This fixes a bug in older root versions which makes
2999 // TCanvas crash if gPad==NULL. So we make sure, that
3000 // gPad!=NULL -- be carfull, this may have other side
3001 // effects.
3002 //
3003#if ROOT_VERSION_CODE < ROOT_VERSION(3,10,01)
3004 if (!gPad && fTab)
3005 for (int i=0; i<fTab->GetNumberOfTabs(); i++)
3006 {
3007 TCanvas *c = GetCanvas(i);
3008 if (c)
3009 {
3010 c->cd();
3011 gLog << dbg << "MStatusDisplay::HandleEvent - Workaround: gPad=" << gPad << "." << endl;
3012 break;
3013 }
3014 }
3015#endif
3016
3017 return rc;
3018}
Note: See TracBrowser for help on using the repository browser.