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

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