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

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