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

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