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

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