source: trunk/MagicSoft/Mars/mmain/MStatusDisplay.cc@ 1980

Last change on this file since 1980 was 1976, checked in by tbretz, 22 years ago
*** empty log message ***
File size: 33.0 KB
Line 
1/* ======================================================================== *\
2!
3! *
4! * This file is part of MARS, the MAGIC Analysis and Reconstruction
5! * Software. It is distributed to you in the hope that it can be a useful
6! * and timesaving tool in analysing Data of imaging Cerenkov telescopes.
7! * It is distributed WITHOUT ANY WARRANTY.
8! *
9! * Permission to use, copy, modify and distribute this software and its
10! * documentation for any purpose is hereby granted without fee,
11! * provided that the above copyright notice appear in all copies and
12! * that both that copyright notice and this permission notice appear
13! * in supporting documentation. It is provided "as is" without express
14! * or implied warranty.
15! *
16!
17!
18! Author(s): Thomas Bretz, 4/2003 <mailto:tbretz@astro-uni-wuerzburg.de>
19!
20! Copyright: MAGIC Software Development, 2003
21!
22!
23\* ======================================================================== */
24
25/////////////////////////////////////////////////////////////////////////////
26//
27// MStatusDisplay
28//
29// This status display can be used (and is used) to display results in
30// a tabbed window. The window can be written to and read from a root file
31// (see Read and Write) or printed as a postscript file (see SaveAsPS).
32//
33// It has also to half status lines which can be used to display the status
34// or something going on. Together with the status lines it has a progress
35// bar which can display the progress of a job or loop.
36// Access the progress bar by GetProgressBar()
37//
38// To add a new tab and get a pointer to the newly created TCanvas
39// use AddTab.
40//
41// If you have a MStatusDisplay and you are not sure whether it was
42// destroyed by the user meanwhile use:
43// gROOT->GetListOfSpecials()->FindObject(pointer);
44// Each MStatusDisplay is added to list list by its constructor and
45// removed from the list by the destructor.
46//
47// You can redirect an output to a MLog-logstream by calling SetLogStream().
48// To disable redirction call SetLogStream(NULL)
49//
50// Because updates to the tabs are only done/displayed if a tab is active
51// using the gui doesn't make things slower (<1%) if the first (legend
52// tab) is displayed. This gives you the possibility to look into
53// the current progress of a loop without loosing more time than the
54// single update of the tab.
55//
56/////////////////////////////////////////////////////////////////////////////
57#include "MStatusDisplay.h"
58
59#include <iostream.h>
60
61#include <TLine.h> // TLine
62#include <TText.h> // TText
63#include <TFile.h> // gFile
64#include <TFrame.h> // TFrame
65#include <TStyle.h> // gStyle
66#include <TCanvas.h> // TCanvas
67#include <TSystem.h> // gSystem
68#include <TDatime.h> // TDatime
69#include <TRandom.h> // TRandom
70#include <TObjArray.h> // TObjArray
71#include <TPostScript.h> // TPostScript
72
73#include <TGTab.h> // TGTab
74#include <TGLabel.h> // TGLabel
75#include <TG3DLine.h> // TGHorizontal3DLine
76#include <TGButton.h> // TGPictureButton
77#include <TGListBox.h> // TGListBox
78#include <TGProgressBar.h> // TGHProgressBar
79
80#include <TRootEmbeddedCanvas.h> // TRootEmbeddedCanvas
81
82#include "MLog.h" // MLog
83#include "MLogManip.h" // inf, warn, err
84
85#include "MGList.h" // MGList
86#include "MGMenu.h" // MGMenu, TGMenu
87#include "MParContainer.h" // MParContainer::GetDescriptor
88
89ClassImp(MStatusDisplay);
90
91// --------------------------------------------------------------------------
92//
93// Add menu bar to the GUI
94//
95void MStatusDisplay::AddMenuBar()
96{
97 //
98 // File Menu
99 //
100 MGPopupMenu *filemenu = new MGPopupMenu(gClient->GetRoot());
101 // filemenu->AddEntry("S&ave [F2]", kFileSave);
102 // filemenu->AddEntry("Save &As... [Shift-F2]", kFileSaveAs);
103 filemenu->AddEntry("Save As status.&ps", kFileSaveAsPS);
104 // filemenu->AddEntry("Save As status.&gif", kFileSaveAsGIF);
105 // filemenu->AddEntry("Save As status.&C", kFileSaveAsC);
106 filemenu->AddEntry("Save As status.&root", kFileSaveAsRoot);
107 filemenu->AddSeparator();
108 filemenu->AddEntry("Print with &lpr", kFilePrint);
109 filemenu->AddEntry("Set printer &name", kFilePrinterName);
110 filemenu->AddSeparator();
111 filemenu->AddEntry("E&xit", kFileExit);
112 filemenu->Associate(this);
113
114 //
115 // Tab Menu
116 //
117 MGPopupMenu *tabmenu = new MGPopupMenu(gClient->GetRoot());
118 // tabmenu->AddEntry("S&ave [F2]", kFileSave);
119 // tabmenu->AddEntry("Save &As... [Shift-F2]", kFileSaveAs);
120 tabmenu->AddEntry("Save As tab-i.&ps", kTabSaveAsPS);
121 // tabmenu->AddEntry("Save As tab-i.&gif", kTabSaveAsGIF);
122 // tabmenu->AddEntry("Save As tab-i.&C", kTabSaveAsC);
123 tabmenu->AddEntry("Save As tab-i.&root", kTabSaveAsRoot);
124 tabmenu->AddSeparator();
125 tabmenu->AddEntry("Print with &lpr", kFilePrint);
126 tabmenu->AddSeparator();
127 tabmenu->AddEntry("Next [&+]", kTabNext);
128 tabmenu->AddEntry("Previous [&-]", kTabPrevious);
129 tabmenu->Associate(this);
130
131 //
132 // Loop Menu
133 //
134 MGPopupMenu *loopmenu = new MGPopupMenu(gClient->GetRoot());
135 loopmenu->AddEntry("&Stop", kLoopStop);
136 loopmenu->Associate(this);
137
138 //
139 // Menu Bar
140 //
141 MGMenuBar *menubar = new MGMenuBar(this, 1, 1, kHorizontalFrame);
142 menubar->AddPopup("&File", filemenu, NULL);
143 menubar->AddPopup("&Tab", tabmenu, NULL);
144 menubar->AddPopup("&Loop", loopmenu, NULL);
145 menubar->BindKeys(this);
146 AddFrame(menubar);
147
148 //
149 // Line below menu bar
150 //
151 TGLayoutHints *laylinesep = new TGLayoutHints(kLHintsTop|kLHintsExpandX);
152 fList->Add(laylinesep);
153
154 TGHorizontal3DLine *linesep = new TGHorizontal3DLine(this);
155 AddFrame(linesep, laylinesep);
156
157 //
158 // Add everything to autodel list
159 //
160 fList->Add(filemenu);
161 fList->Add(loopmenu);
162 fList->Add(menubar);
163 fList->Add(tabmenu);
164 fList->Add(linesep);
165}
166
167// --------------------------------------------------------------------------
168//
169// Add the title tab
170//
171void MStatusDisplay::AddMarsTab()
172{
173 // Create Tab1
174 TGCompositeFrame *f = fTab->AddTab("-=MARS=-");
175
176 // Add MARS version
177 TString txt = "Official Release: V";
178 TGLabel *l = new TGLabel(f, txt+MARSVER);
179 fList->Add(l);
180
181 TGLayoutHints *layb = new TGLayoutHints(kLHintsCenterX|kLHintsTop, 10, 10, 10, 10);
182 fList->Add(layb);
183 f->AddFrame(l, layb);
184
185 // Add root version
186 txt = "Using ROOT v";
187 l = new TGLabel(f, txt+ROOTVER);
188 fList->Add(l);
189
190 TGLayoutHints *lay = new TGLayoutHints(kLHintsCenterX|kLHintsTop);
191 fList->Add(lay);
192 f->AddFrame(l, lay);
193
194 // Add Mars logo picture
195 const TGPicture *pic2 = fList->GetPicture("marslogo.xpm");
196 if (pic2)
197 {
198 TGPictureButton *mars = new TGPictureButton(f, pic2, kPicMars);
199 fList->Add(mars);
200 mars->Associate(this);
201
202 TGLayoutHints *lay2 = new TGLayoutHints(kLHintsCenterX|kLHintsCenterY, 10, 10, 10, 10);
203 fList->Add(lay2);
204 f->AddFrame(mars, lay2);
205 }
206
207 // Add date and time
208 TDatime d;
209 l = new TGLabel(f, d.AsString());
210 fList->Add(l);
211 f->AddFrame(l, lay);
212
213 // Add copyright notice
214 l = new TGLabel(f, "(c) MAGIC Software Development, 2000-2003");
215 fList->Add(l);
216 f->AddFrame(l, layb);
217}
218
219// --------------------------------------------------------------------------
220//
221// Adds the logbook tab to the GUI if it was not added previously.
222//
223// The logbook is updated four times a second only if the tab is visible.
224//
225// You can redirect an output to a MLog-logstream by calling SetLogStream().
226// To disable redirction call SetLogStream(NULL)
227//
228void MStatusDisplay::SetLogStream(MLog *log)
229{
230 if (log && fLogBox==NULL)
231 {
232 fLogIdx = fTab->GetNumberOfTabs();
233
234 // Create Tab1
235 TGCompositeFrame *f = fTab->AddTab("-Logbook-");
236
237 // Create TGListBox for logging contents
238 fLogBox = new TGListBox(f, 1, 1);
239 fLogBox->ChangeBackground(TGFrame::GetBlackPixel());
240
241 // Add List box to the tab
242 TGLayoutHints *lay = new TGLayoutHints(kLHintsNormal|kLHintsExpandX|kLHintsExpandY);//, 5, 6, 5);
243 f->AddFrame(fLogBox, lay);
244
245 // layout and map tab
246 Layout();
247 MapSubwindows();
248
249 // make it visible
250 gClient->ProcessEventsFor(fTab);
251 }
252
253 if (log)
254 {
255 fLog = log;
256
257 log->SetOutputGui(fLogBox, kTRUE);
258 log->DisableOutputDevice(MLog::eStdout);
259 log->EnableOutputDevice(MLog::eGui);
260
261 fLogTimer.Start();
262 }
263 else
264 {
265 fLogTimer.Stop();
266
267 fLog->DisableOutputDevice(MLog::eGui);
268 fLog->EnableOutputDevice(MLog::eStdout);
269 fLog->SetOutputGui(NULL);
270
271 fLog = &gLog;
272 }
273}
274
275// --------------------------------------------------------------------------
276//
277// Add the Tabs and the predifined Tabs to the GUI
278//
279void MStatusDisplay::AddTabs()
280{
281 fTab = new TGTab(this, 300, 300);
282
283 AddMarsTab();
284
285 // Add fTab to Frame
286 TGLayoutHints *laytabs = new TGLayoutHints(kLHintsNormal|kLHintsExpandX|kLHintsExpandY, 5, 6, 5);
287 AddFrame(fTab, laytabs);
288
289 fList->Add(fTab);
290 fList->Add(laytabs);
291}
292
293// --------------------------------------------------------------------------
294//
295// Add the progress bar to the GUI
296//
297void MStatusDisplay::AddProgressBar()
298{
299 TGLayoutHints *laybar=new TGLayoutHints(kLHintsExpandX, 5, 6, 5, 5);
300 fList->Add(laybar);
301
302 fBar=new TGHProgressBar(this);
303 fBar->ShowPosition();
304 AddFrame(fBar, laybar);
305 fList->Add(fBar);
306}
307
308
309// --------------------------------------------------------------------------
310//
311// Adds the status lines to the GUI
312//
313void MStatusDisplay::AddStatusLines()
314{
315 TGHorizontalFrame *hf = new TGHorizontalFrame(this, 1, 1);
316
317 TGCompositeFrame *f = new TGCompositeFrame(hf, 1, 1, kSunkenFrame);
318
319 fLine1 = new TGLabel(f, "");
320
321 TGLayoutHints *lay = new TGLayoutHints(kLHintsNormal|kLHintsExpandX, 0, 5);
322 f->AddFrame(fLine1, lay);
323 hf->AddFrame(f, lay);
324
325 fList->Add(f);
326 fList->Add(fLine1);
327 fList->Add(lay);
328
329 f = new TGCompositeFrame(hf, 1, 1, kSunkenFrame);
330
331 fLine2 = new TGLabel(f, "");
332 f->AddFrame(fLine2, lay);
333 hf->AddFrame(f, lay);
334
335 TGLayoutHints *layf = new TGLayoutHints(kLHintsNormal|kLHintsExpandX, 5, 0, 0, 3);
336 AddFrame(hf, layf);
337
338 fList->Add(layf);
339 fList->Add(f);
340 fList->Add(fLine2);
341 fList->Add(hf);
342}
343
344// --------------------------------------------------------------------------
345//
346// Change the text in the status line 1
347//
348void MStatusDisplay::SetStatusLine1(const char *txt)
349{
350 fLine1->SetText(txt);
351 gClient->ProcessEventsFor(fLine1);
352}
353
354// --------------------------------------------------------------------------
355//
356// Change the text in the status line 2
357//
358void MStatusDisplay::SetStatusLine2(const char *txt)
359{
360 fLine2->SetText(txt);
361 gClient->ProcessEventsFor(fLine2);
362}
363
364// --------------------------------------------------------------------------
365//
366// Display information about the name of a container
367//
368void MStatusDisplay::SetStatusLine2(const MParContainer &cont)
369{
370 TString txt = cont.GetDescriptor();
371 txt += ": ";
372 txt += cont.GetTitle();
373
374 SetStatusLine2(txt);
375}
376
377// --------------------------------------------------------------------------
378//
379// Default constructor. Opens a window with a progress bar. Get a pointer
380// to the bar by calling GetBar. This pointer can be used for the
381// eventloop.
382//
383// Be carefull: killing or closing the window while the progress meter
384// is still in use may cause segmentation faults. Please kill the window
385// always by deleting the corresponding object.
386//
387// Update time default: 10s
388//
389MStatusDisplay::MStatusDisplay(Long_t t)
390: TGMainFrame(gClient->GetRoot(), 1, 1), fTimer(this, t, kTRUE), fLog(&gLog), fLogIdx(-1), fLogTimer(this, 250, kTRUE), fLogBox(NULL)
391{
392 gROOT->GetListOfSpecials()->Add(this);
393
394 //
395 // Create a list handling GUI widgets
396 //
397 fList = new MGList;
398 fList->SetOwner();
399
400 //
401 // set the smallest and biggest size of the Main frame
402 // and move it to its appearance position
403 SetWMSizeHints(640, 548, 1280, 1024, 10, 10);
404 Move(rand()%100+50, rand()%100+50);
405
406 //
407 // Create the layout hint for the root embedded canavses
408 //
409 fLayCanvas = new TGLayoutHints(kLHintsExpandX|kLHintsExpandY);
410 fList->Add(fLayCanvas);
411
412 //
413 // Add Widgets (from top to bottom)
414 //
415 AddMenuBar();
416 AddTabs();
417 AddProgressBar();
418 AddStatusLines();
419
420 //
421 // Now do an automatic layout of the widgets and display the window
422 //
423 Layout();
424 MapSubwindows();
425
426 SetWindowName("Status Display");
427 SetIconName("Status Display");
428
429 MapWindow();
430
431 //lient->ProcessEventsFor(this);
432 gSystem->ProcessEvents();
433
434 //TSeqCollection *GetListOfCleanups() const {return fCleanups;}
435
436}
437
438// --------------------------------------------------------------------------
439//
440// Destruct the window with all its tiles. Also the Progress Bar object
441// is deleted.
442//
443MStatusDisplay::~MStatusDisplay()
444{
445 SetLogStream(NULL);
446
447 delete fList;
448
449 gROOT->GetListOfSpecials()->Remove(this);
450}
451
452// --------------------------------------------------------------------------
453//
454// Takes a TGCompositeFrame as argument. Searches for the first
455// TRootEmbeddedCanvas which is contained by it and returns a pointer
456// to the corresponding TCanvas. If it isn't found NULL is returned.
457//
458TCanvas *MStatusDisplay::GetCanvas(TGCompositeFrame *cf) const
459{
460 TIter Next(cf->GetList());
461
462 TGFrameElement *f;
463 while ((f=(TGFrameElement*)Next()))
464 if (f->fFrame->InheritsFrom(TRootEmbeddedCanvas::Class()))
465 return ((TRootEmbeddedCanvas*)f->fFrame)->GetCanvas();
466
467 return NULL;
468}
469
470// --------------------------------------------------------------------------
471//
472// Returns GetCanvas of the i-th Tab.
473//
474TCanvas *MStatusDisplay::GetCanvas(int i) const
475{
476 if (i<0 || i>=fTab->GetNumberOfTabs())
477 {
478 *fLog << warn << "MStatusDisplay::GetCanvas: Out of range." << endl;
479 return NULL;
480 }
481
482 return GetCanvas(fTab->GetTabContainer(i));
483}
484
485// --------------------------------------------------------------------------
486//
487// Searches for a TRootEmbeddedCanvas in the TGCompositeFramme of the
488// Tab with the name 'name'. Returns the corresponding TCanvas or
489// NULL if something isn't found.
490//
491TCanvas *MStatusDisplay::GetCanvas(const TString &name) const
492{
493 TGFrameElement *f;
494 TIter Next(fTab->GetList());
495 while ((f=(TGFrameElement*)Next()))
496 {
497 TObject *frame = f->fFrame;
498 if (!frame->InheritsFrom(TGTabElement::Class()))
499 continue;
500
501 TGTabElement *tab = (TGTabElement*)frame;
502 if (tab->GetString()==name)
503 break;
504 }
505
506 // Search for the next TGCompositeFrame in the list
507 while ((f=(TGFrameElement*)Next()))
508 {
509 TObject *frame = f->fFrame;
510 if (frame->InheritsFrom(TGCompositeFrame::Class()))
511 return GetCanvas((TGCompositeFrame*)frame);
512 }
513
514 return NULL;
515}
516
517// --------------------------------------------------------------------------
518//
519// Calls TCanvas::cd(), for the canvas returned by GetCanvas.
520//
521Bool_t MStatusDisplay::CdCanvas(const TString &name)
522{
523 TCanvas *c = GetCanvas(name);
524 if (!c)
525 return kFALSE;
526
527 c->cd();
528 return kTRUE;
529}
530
531// --------------------------------------------------------------------------
532//
533// Adds a new tab with the name 'name'. Adds a TRootEmbeddedCanvas to the
534// tab and returns a reference to the corresponding TCanvas.
535//
536TCanvas &MStatusDisplay::AddTab(const char *name)
537{
538 // Add new tab
539 TGCompositeFrame *f = fTab->AddTab(name);
540
541 // create root embedded canvas and add it to the tab
542 TRootEmbeddedCanvas *ec = new TRootEmbeddedCanvas(name, f, f->GetWidth(), f->GetHeight(), 0);
543 f->AddFrame(ec, fLayCanvas);
544 fList->Add(ec);
545
546 // set background and border mode of the canvas
547 TCanvas &c = *ec->GetCanvas();
548
549 c.SetFillColor(16/*165*//*17*//*203*/);
550 c.SetBorderMode(0);
551
552 // If kNoContaxtMenu set set kNoCOntextMenu of the canvas
553 if (TestBit(kNoContextMenu))
554 c.SetBit(kNoContextMenu);
555
556 // layout and map new tab
557#if ROOT_VERSION_CODE < ROOT_VERSION(3,03,00)
558 MapSubwindows();
559 Layout();
560#else
561 Layout();
562 MapSubwindows();
563#endif
564
565 // display new tab in the main frame
566 gClient->ProcessEventsFor(fTab);
567
568 *fLog << inf << "Adding Tab '" << name << "' (" << f->GetWidth() << "x";
569 *fLog << f->GetHeight() << ", TCanvas=" << &c << ")" << endl;
570
571 // return pointer to new canvas
572 return c;
573}
574
575// --------------------------------------------------------------------------
576//
577// Update a canvas in a tab, takes the corresponding TGCompositeFrame
578// as an argument
579//
580void MStatusDisplay::UpdateTab(TGCompositeFrame *f)
581{
582 if (!f)
583 return;
584
585 TCanvas *c=GetCanvas(f);
586 if (!c)
587 return;
588
589 c->Modified();
590 c->Update();
591 c->Paint();
592}
593
594// --------------------------------------------------------------------------
595//
596// Saves the given canvas (pad) or all pads (num<0) as a temporary
597// postscript file and prints it using 'lpr'. If a printer name is set
598// via SetPrinter 'lpr -Pname' is used.
599//
600Int_t MStatusDisplay::PrintToLpr(Int_t num) const
601{
602 TString name = "mars";
603
604 for (int i=0; i<6; i++)
605 name += (char)(gRandom->Uniform(25)+65);
606
607 name += ".ps";
608
609 const Int_t pages = SaveAsPS(num, name);
610 if (!pages)
611 {
612 *fLog << warn << "MStatusDisplay::PrintToLpr: Sorry, couldn't save file as temporary postscript!" << endl;
613 return 0;
614 }
615
616 TString cmd="lpr ";
617 if (!fPrinter.IsNull())
618 {
619 cmd += "-P";
620 cmd += fPrinter;
621 cmd += " ";
622 }
623 cmd += name;
624
625 gSystem->Exec(cmd);
626 gSystem->Unlink(name);
627
628 return pages;
629}
630
631// --------------------------------------------------------------------------
632//
633// Process the kC_COMMAND, kCM_MENU messages
634//
635Bool_t MStatusDisplay::ProcessMessageCommandMenu(Long_t id)
636{
637 //cout << "Menu #" << id << endl;
638 switch (id)
639 {
640 case kLoopStop:
641 case kFileExit:
642 if (id==kFileExit && !TestBit(kIsLocked))
643 delete this;
644 fStatus = (Status_t)id;
645 return kTRUE;
646/*
647 case kFileSave:
648 cout << "Save..." << endl;
649 return kTRUE;
650
651 case kFileSaveAs:
652 cout << "SaveAs..." << endl;
653 return kTRUE;
654*/
655 case kFileSaveAsPS:
656 //cout << "FileSaveAsPS..." << endl;
657 SaveAsPS();
658 return kTRUE;
659/*
660 case kFileSaveAsGIF:
661 cout << "FileSaveAsGIF..." << endl;
662 SaveAsGIF();
663 return kTRUE;
664
665 case kFileSaveAsC:
666 cout << "FileSaveAsC..." << endl;
667 SaveAsC();
668 return kTRUE;
669*/
670 case kFileSaveAsRoot:
671 SaveAsRoot();
672 return kTRUE;
673
674 case kFilePrint:
675 PrintToLpr();
676 return kTRUE;
677
678 case kTabSaveAsPS:
679 SaveAsPS(fTab->GetCurrent());
680 return kTRUE;
681/*
682 case kTabSaveAsGIF:
683 cout << "TabSaveAsGIF... " << fTab->GetCurrent() << endl;
684 SaveAsGIF(fTab->GetCurrent());
685 return kTRUE;
686
687 case kTabSaveAsC:
688 cout << "TabSaveAsC... " << fTab->GetCurrent() << endl;
689 SaveAsC(fTab->GetCurrent());
690 return kTRUE;
691*/
692 case kTabSaveAsRoot:
693 SaveAsRoot(fTab->GetCurrent());
694 return kTRUE;
695
696 case kTabPrint:
697 PrintToLpr(fTab->GetCurrent());
698 return kTRUE;
699
700 case kTabNext:
701 fTab->SetTab(fTab->GetCurrent()+1);
702 return kTRUE;
703
704 case kTabPrevious:
705 fTab->SetTab(fTab->GetCurrent()-1);
706 return kTRUE;
707 }
708 return kTRUE;
709
710 cout << "Command-Menu: Id=" << id << endl;
711}
712
713// --------------------------------------------------------------------------
714//
715// Process the kC_COMMAND messages
716//
717Bool_t MStatusDisplay::ProcessMessageCommand(Long_t submsg, Long_t mp1, Long_t mp2)
718{
719 switch (submsg)
720 {
721 case kCM_MENU:
722 return ProcessMessageCommandMenu(mp1);
723
724 case kCM_MENUSELECT:
725 cout << "Menuselect #" << mp1 << endl;
726 return kTRUE;
727
728 case kCM_TAB:
729 for (int i=1; i<fTab->GetNumberOfTabs(); i++)
730 fTab->GetTabContainer(i)->UnmapWindow();
731 UpdateTab(fTab->GetTabContainer(mp1));
732 fTab->GetTabContainer(mp1)->MapWindow();
733 /*
734 if (mp1>0)
735 fMenu->AddPopup("&CaOs", fCaOs, NULL);
736 else
737 fMenu->RemovePopup("CaOs");
738 fMenu->Resize(fMenu->GetDefaultSize());
739 MapSubwindows();
740 MapWindow();
741 */
742 return kTRUE;
743
744 case kCM_BUTTON:
745 if (mp1==kPicMars)
746 return kTRUE;
747 return kTRUE;
748 }
749
750 cout << "Command: " << "Submsg:" << submsg << " Mp1=" << mp1 << " Mp2=" << mp2 << endl;
751 return kTRUE;
752}
753
754// --------------------------------------------------------------------------
755//
756// Process the messages from the GUI
757//
758Bool_t MStatusDisplay::ProcessMessage(Long_t msg, Long_t mp1, Long_t mp2)
759{
760 switch (GET_MSG(msg))
761 {
762 case kC_COMMAND:
763 return ProcessMessageCommand(GET_SUBMSG(msg), mp1, mp2);
764 }
765
766 cout << "Msg: " << GET_MSG(msg) << " Submsg:" << GET_SUBMSG(msg);
767 cout << " Mp1=" << mp1 << " Mp2=" << mp2 << endl;
768
769 return kTRUE;
770}
771
772void MStatusDisplay::CloseWindow()
773{
774 // Got close message for this MainFrame. Calls parent CloseWindow()
775 // (which destroys the window) and terminate the application.
776 // The close message is generated by the window manager when its close
777 // window menu item is selected.
778
779 // CloseWindow must be overwritten because otherwise CloseWindow
780 // and the destructor are calling DestroyWindow which seems to be
781 // in conflict with the TRootEmbeddedCanvas.
782 delete this;
783}
784
785// --------------------------------------------------------------------------
786//
787// Calls SetBit(kNoContextMenu) for all TCanvas objects found in the
788// Tabs.
789//
790void MStatusDisplay::SetNoContextMenu(Bool_t flag)
791{
792 flag ? SetBit(kNoContextMenu) : ResetBit(kNoContextMenu);
793 for (int i=1; i<fTab->GetNumberOfTabs(); i++)
794 {
795 TCanvas *c = GetCanvas(i);
796 if (c)
797 flag ? c->SetBit(kNoContextMenu) : c->ResetBit(kNoContextMenu);
798 }
799}
800
801// --------------------------------------------------------------------------
802//
803// Updates the canvas (if existing) in the currenly displayed Tab.
804// The update intervall is controlled by StartUpdate and StopUpdate
805//
806Bool_t MStatusDisplay::HandleTimer(TTimer *timer)
807{
808 const Int_t c = fTab->GetCurrent();
809
810 // Skip Legend Tab
811 if (c==0)
812 return kTRUE;
813
814 // Update a canvas tab (if visible)
815 if (timer==&fTimer && c!=fLogIdx)
816 {
817 UpdateTab(fTab->GetCurrentContainer());
818 return kTRUE;
819 }
820
821 // update the logbook tab (if visible)
822 if (timer==&fLogTimer && c==fLogIdx)
823 {
824 fLog->UpdateGui();
825
826 if (!fLogBox->TestBit(kHasChanged))
827 return kTRUE;
828
829 fLogBox->MapSubwindows();
830 fLogBox->Layout();
831 fLogBox->ResetBit(kHasChanged);
832 return kTRUE;
833 }
834
835 return kTRUE;
836}
837
838// --------------------------------------------------------------------------
839//
840// Draws a clone of a canvas into a new canvas. Taken from TCanvas.
841//
842void MStatusDisplay::DrawClonePad(TCanvas &newc, const TCanvas &oldc) const
843{
844 //copy pad attributes
845 newc.Range(oldc.GetX1(),oldc.GetY1(),oldc.GetX2(),oldc.GetY2());
846 newc.SetTickx(oldc.GetTickx());
847 newc.SetTicky(oldc.GetTicky());
848 newc.SetGridx(oldc.GetGridx());
849 newc.SetGridy(oldc.GetGridy());
850 newc.SetLogx(oldc.GetLogx());
851 newc.SetLogy(oldc.GetLogy());
852 newc.SetLogz(oldc.GetLogz());
853 newc.SetBorderSize(oldc.GetBorderSize());
854 newc.SetBorderMode(oldc.GetBorderMode());
855 ((TAttLine&)oldc).Copy((TAttLine&)newc);
856 ((TAttFill&)oldc).Copy((TAttFill&)newc);
857 ((TAttPad&)oldc).Copy((TAttPad&)newc);
858
859 //copy primitives
860 TObject *obj;
861 TIter next(oldc.GetListOfPrimitives());
862 while ((obj=next())) {
863 gROOT->SetSelectedPad(&newc);
864 newc.GetListOfPrimitives()->Add(obj->Clone(),obj->GetDrawOption());
865 }
866 newc.Modified();
867 newc.Update();
868}
869
870// --------------------------------------------------------------------------
871//
872// Reads the contents of a saved MStatusDisplay from a file.
873//
874Int_t MStatusDisplay::Read(const char *name)
875{
876 if (!gFile)
877 {
878 *fLog << warn << "MStatusDisplay::Read: No file found. Please create a TFile first." << endl;
879 return 0;
880 }
881
882 if (!gFile->IsOpen())
883 {
884 *fLog << warn << "MStatusDisplay::Read: File not open. Please open the TFile first." << endl;
885 return 0;
886 }
887
888 TObjArray list;
889
890 const Int_t n = list.Read(name);
891 if (n==0)
892 {
893 *fLog << warn << "MStatusDisplay::Read: No objects read." << endl;
894 return 0;
895 }
896
897 TIter Next(&list);
898 TCanvas *c;
899 while ((c=(TCanvas*)Next()))
900 DrawClonePad(AddTab(c->GetName()), *c);
901
902 *fLog << inf << "MStatusDisplay: Key " << name << " with " << n << " keys read from file." << endl;
903
904 return n;
905}
906
907// --------------------------------------------------------------------------
908//
909// Writes the contents of a MStatusDisplay to a file.
910//
911Int_t MStatusDisplay::Write(Int_t num, const char *name, Int_t option, Int_t bufsize)
912{
913 if (!gFile)
914 {
915 *fLog << warn << "MStatusDisplay::Write: No file found. Please create a TFile first." << endl;
916 return 0;
917 }
918
919 if (!gFile->IsOpen())
920 {
921 *fLog << warn << "MStatusDisplay::Write: File not open. Please open the TFile first." << endl;
922 return 0;
923 }
924
925 if (!gFile->IsWritable())
926 {
927 *fLog << warn << "MStatusDisplay::Write: File not writable." << endl;
928 return 0;
929 }
930
931 if (num==0)
932 {
933 *fLog << warn << "MStatusDisplay::Write: Tab doesn't contain an embedded Canvas... skipped." << endl;
934 return 0;
935 }
936
937 if (num>=fTab->GetNumberOfTabs())
938 {
939 *fLog << warn << "MStatusDisplay::Write: Tab doesn't exist... skipped." << endl;
940 return 0;
941 }
942
943 TObjArray list;
944
945 const Int_t from = num<0 ? 1 : num;
946 const Int_t to = num<0 ? fTab->GetNumberOfTabs() : num+1;
947
948 TCanvas *c;
949 for (int i=from; i<to; i++)
950 if ((c = GetCanvas(i)))
951 list.Add(c);
952
953 const Int_t n = list.Write(name, kSingleKey);
954
955 *fLog << inf << "MStatusDisplay: " << n << " keys written to file as key " << name << "." << endl;
956
957 return n;
958}
959
960// --------------------------------------------------------------------------
961//
962// Use this to start the synchronous (GUI eventloop driven) tab update.
963// Can also be used to change the update intervall. If millisec<0
964// the intervall given in SetUpdateTime is used. If the intervall in
965// SetUpdateTime is <0 nothing is done. (Call SetUpdateTime(-1) to
966// disable the automatic update in a MEventloop.
967//
968void MStatusDisplay::StartUpdate(Int_t millisec=-1)
969{
970 if (fTimer.GetTime()<TTime(0))
971 return;
972 fTimer.Start(millisec);
973}
974
975// --------------------------------------------------------------------------
976//
977// Stops the automatic GUI update
978//
979void MStatusDisplay::StopUpdate()
980{
981 fTimer.Stop();
982}
983
984// --------------------------------------------------------------------------
985//
986// Set the update interval for the GUI update, see StartUpdate.
987//
988void MStatusDisplay::SetUpdateTime(Long_t t)
989{
990 fTimer.SetTime(t);
991}
992
993// --------------------------------------------------------------------------
994//
995// Set the background color in a canvas
996//
997void MStatusDisplay::CanvasSetFillColor(TPad &p, Int_t col) const
998{
999 TObject *obj;
1000
1001 TIter Next(p.GetListOfPrimitives());
1002 while ((obj=Next()))
1003 {
1004 if (obj->InheritsFrom(TPad::Class()))
1005 CanvasSetFillColor(*(TPad*)obj, col);
1006 if (obj->InheritsFrom(TFrame::Class()))
1007 ((TFrame*)obj)->SetFillColor(col);
1008 }
1009
1010 p.SetFillColor(col);
1011}
1012
1013void MStatusDisplay::AddExtension(TString &name, const TString &ext, Int_t num) const
1014{
1015 if (name.IsNull())
1016 {
1017 name = "status";
1018 if (num>0)
1019 {
1020 name += "-";
1021 name += num;
1022 }
1023 }
1024
1025 if (name.EndsWith("."+ext))
1026 return;
1027
1028 name += ".";
1029 name += ext;
1030}
1031
1032// --------------------------------------------------------------------------
1033//
1034// In case of num<0 all tabs are written into the PS file. If num>0
1035// the canvas in the corresponding tab is written to the file.
1036// Name is the name of the file (with or without extension).
1037//
1038// Returns the number of pages written.
1039//
1040// To write all tabs you can also use SaveAsPS(name)
1041//
1042Int_t MStatusDisplay::SaveAsPS(Int_t num, TString name) const
1043{
1044 if (num>=fTab->GetNumberOfTabs())
1045 {
1046 *fLog << warn << "Tab #" << num << " doesn't exist..." << endl;
1047 return 0;
1048 }
1049 if (num==0)
1050 {
1051 *fLog << warn << "Tab #" << num << " doesn't contain an embedded canvas..." << endl;
1052 return 0;
1053 }
1054 if (fTab->GetNumberOfTabs()<2 || !gPad)
1055 {
1056 *fLog << warn << "Sorry, you must have at least one existing canvas (gPad!=NULL)" << endl;
1057 return 0;
1058 }
1059
1060 AddExtension(name, "ps", num);
1061
1062 if (num<0)
1063 *fLog << inf << "Open ps-File: " << name << endl;
1064
1065 TPad *padsav = (TPad*)gPad;
1066 TVirtualPS *psave = gVirtualPS;
1067
1068 TPostScript ps(name, 112);
1069 ps.SetBit(TPad::kPrintingPS);
1070 ps.PrintFast(13, "/nan {1} def ");
1071
1072 gVirtualPS = &ps;
1073
1074 //
1075 // Create a list to delete the canvas clones
1076 //
1077 TList l;
1078 l.SetOwner();
1079
1080 //
1081 // Create some GUI elements for a page legend
1082 //
1083 TLine line;
1084
1085 int page = 1;
1086
1087 //
1088 // Maintain tab numbers
1089 //
1090 const Int_t from = num<0 ? 1 : num;
1091 const Int_t to = num<0 ? fTab->GetNumberOfTabs() : num+1;
1092
1093 for (int i=from; i<to; i++)
1094 {
1095 TCanvas *c;
1096 if (!(c = GetCanvas(i)))
1097 {
1098 if (num<0)
1099 *fLog << inf << " - ";
1100 *fLog << "Tab #" << i << " doesn't contain an embedded Canvas... skipped." << endl;
1101 continue;
1102 }
1103
1104 //
1105 // Init page and page size, make sure, that the canvas in the file
1106 // has the same Aspect Ratio than on the screen.
1107 //
1108 ps.NewPage();
1109
1110 Float_t psw = 26; // A4 - width
1111 Float_t psh = 20; // A4 - height
1112
1113 const Float_t cw = c->GetWw();
1114 const Float_t ch = c->GetWh();
1115
1116 if (psw/psh>cw/ch)
1117 psw = cw/ch*psh;
1118 else
1119 psh = ch/cw*psw;
1120
1121 ps.Range(psw, psh); // A4
1122
1123 //
1124 // Clone canvas and change background color and schedule for
1125 // deletion
1126 //
1127 TCanvas *n = (TCanvas*)c->Clone();
1128 CanvasSetFillColor(*n, kWhite);
1129 l.Add(n);
1130
1131 //
1132 // Paint canvas into root file
1133 //
1134 if (num<0)
1135 *fLog << inf << " - ";
1136 *fLog << "Writing Tab #" << i << ": " << c->GetName() << " (" << n << ") ";
1137 if (num>0)
1138 *fLog << "to " << name;
1139 *fLog << "..." << flush;
1140
1141 n->SetBatch(kTRUE);
1142 n->Paint();
1143
1144 //
1145 // Use the canvas as coordinate system for the overlaying text
1146 //
1147 gPad = n;
1148
1149 //
1150 // Print overlaying text (NDC = %)
1151 //
1152 ps.SetTextColor(kBlack);
1153 ps.SetTextSize(0.015);
1154 ps.SetTextFont(22);
1155 ps.SetTextAlign(11); // left top
1156 ps.TextNDC(0, 1.02, TString(" ")+n->GetName());
1157 ps.SetTextAlign(21); // cent top
1158 ps.TextNDC(0.5, 1.02, "MARS - Magic Analysis and Reconstruction Software");
1159 ps.SetTextAlign(31); // right top
1160 ps.TextNDC(1, 1.02, Form("Page No.%i (%i) ", page++, i));
1161 line.PaintLineNDC(0, 1.015, 1, 1.015);
1162
1163 //
1164 // Finish drawing page
1165 //
1166 n->SetBatch(kFALSE);
1167 if (num<0)
1168 *fLog << "done." << endl;
1169 }
1170
1171 gPad = NULL; // Important!
1172
1173 l.Delete();
1174
1175 ps.Close();
1176
1177 gVirtualPS = psave;
1178 padsav->cd();
1179
1180 *fLog << inf << "done." << endl;
1181
1182 return page-1;
1183}
1184
1185/*
1186void MStatusDisplay::SaveAsGIF(Int_t num, TString name) const
1187{
1188 AddExtension(name, "gif", num);
1189
1190 cout << "Open gif-File: " << name << endl;
1191 cout << " SORRY, not implemented." << endl;
1192}
1193
1194void MStatusDisplay::SaveAsC(Int_t num, TString name) const
1195{
1196 AddExtension(name, "C", num);
1197
1198 cout << "Open C-File: " << name << endl;
1199 cout << " SORRY, not implemented." << endl;
1200}
1201*/
1202
1203// --------------------------------------------------------------------------
1204//
1205// In case of num<0 all tabs are written into the PS file. If num>0
1206// the canvas in the corresponding tab is written to the file.
1207// Name is the name of the file (with or without extension).
1208//
1209// Returns the number of keys written.
1210//
1211// To write all tabs you can also use SaveAsPS(name)
1212//
1213Int_t MStatusDisplay::SaveAsRoot(Int_t num, TString name)
1214{
1215 if (num>=fTab->GetNumberOfTabs())
1216 {
1217 *fLog << warn << "Tab #" << num << " doesn't exist..." << endl;
1218 return 0;
1219 }
1220 if (num==0)
1221 {
1222 *fLog << warn << "Tab #" << num << " doesn't contain an embedded canvas..." << endl;
1223 return 0;
1224 }
1225 if (fTab->GetNumberOfTabs()<2 || !gPad)
1226 {
1227 *fLog << warn << "Sorry, you must have at least one existing canvas." << endl;
1228 return 0;
1229 }
1230
1231 AddExtension(name, "root", num);
1232
1233 TFile *fsave = gFile;
1234 TFile file(name, "RECREATE", "MARS - Status Window Contents", 9);
1235 const Int_t keys = Write(num);
1236 gFile = fsave;
1237
1238 return keys;
1239}
Note: See TracBrowser for help on using the repository browser.