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

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