source: tags/Mars-V0.8.1/mmain/MStatusDisplay.cc

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