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

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