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

Last change on this file since 2347 was 2299, checked in by tbretz, 22 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("Next [&+]", kTabNext);
197 tabmenu->AddEntry("Previous [&-]", kTabPrevious);
198 tabmenu->AddSeparator();
199 tabmenu->AddEntry("Save As tab-i.&ps", kTabSaveAsPS);
200 tabmenu->AddEntry("Save As tab-i.&gif", kTabSaveAsGIF);
201 tabmenu->AddEntry("Save As tab-i.&C", kTabSaveAsC);
202 tabmenu->AddEntry("Save As tab-i.&root", kTabSaveAsRoot);
203 tabmenu->AddSeparator();
204 tabmenu->AddEntry("Re&move", kTabRemove);
205 tabmenu->AddSeparator();
206 tabmenu->AddEntry("Print with &lpr", kFilePrint);
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 (!c)
843 return kFALSE;
844
845 if (gROOT->IsBatch())
846 return (Bool_t)fBatch->FindObject(c);
847
848 for (int i=1; i<fTab->GetNumberOfTabs(); i++)
849 if (c==GetCanvas(i))
850 return kTRUE;
851 return kFALSE;
852}
853
854/*
855 if (...)
856 fMenu->AddPopup("&CaOs", fCaOs, NULL);
857 else
858 fMenu->RemovePopup("CaOs");
859 fMenu->Resize(fMenu->GetDefaultSize());
860 MapSubwindows();
861 MapWindow();
862 */
863
864// --------------------------------------------------------------------------
865//
866// Process the kC_COMMAND, kCM_MENU messages
867//
868Bool_t MStatusDisplay::ProcessMessageCommandMenu(Long_t id)
869{
870 switch (id)
871 {
872 case kLoopStop:
873 case kFileExit:
874 if (id==kFileExit)
875 delete this;
876 fStatus = (Status_t)id;
877 return kTRUE;
878
879 case kFileCanvas:
880 new TCanvas;
881 return kTRUE;
882
883 case kFileBrowser:
884 new TBrowser;
885 return kTRUE;
886
887 case kFileReset:
888 for (int i=fTab->GetNumberOfTabs()-1; i>0; i--)
889 RemoveTab(i);
890 return kTRUE;
891 /*
892 case kFileSave:
893 cout << "Save..." << endl;
894 return kTRUE;
895
896 case kFileSaveAs:
897 cout << "SaveAs..." << endl;
898 return kTRUE;
899*/
900 case kFileSaveAsPS:
901 SaveAsPS();
902 return kTRUE;
903
904 case kFileSaveAsGIF:
905 SaveAsGIF();
906 return kTRUE;
907
908 case kFileSaveAsC:
909 SaveAsC();
910 return kTRUE;
911
912 case kFileSaveAsRoot:
913 SaveAsRoot();
914 return kTRUE;
915
916 case kFilePrint:
917 PrintToLpr();
918 return kTRUE;
919
920 case kTabSaveAsPS:
921 SaveAsPS(fTab->GetCurrent());
922 return kTRUE;
923
924 case kTabSaveAsGIF:
925 SaveAsGIF(fTab->GetCurrent());
926 return kTRUE;
927
928 case kTabSaveAsC:
929 SaveAsC(fTab->GetCurrent());
930 return kTRUE;
931
932 case kTabSaveAsRoot:
933 SaveAsRoot(fTab->GetCurrent());
934 return kTRUE;
935
936 case kTabPrint:
937 PrintToLpr(fTab->GetCurrent());
938 return kTRUE;
939
940 case kTabNext:
941 fTab->SetTab(fTab->GetCurrent()+1);
942 return kTRUE;
943
944 case kTabPrevious:
945 fTab->SetTab(fTab->GetCurrent()-1);
946 return kTRUE;
947
948 case kTabRemove:
949 RemoveTab(fTab->GetCurrent());
950 return kTRUE;
951
952 case kSize640:
953 Resize(570, 480);
954 return kTRUE;
955 case kSize800:
956 Resize(740, 600);
957 return kTRUE;
958 case kSize960:
959 Resize(880, 700);
960 return kTRUE;
961 case kSize1024:
962 Resize(980, 768);
963 return kTRUE;
964 case kSize1280:
965 Resize(1280, 980);
966 return kTRUE;
967
968 case kLogClear:
969 fLogBox->Clear();
970 return kTRUE;
971 case kLogCopy:
972 fLogBox->Copy();
973 return kTRUE;
974 case kLogSelect:
975 fLogBox->SelectAll();
976 return kTRUE;
977 case kLogFind:
978 new MSearch(this);
979 return kTRUE;
980 case kLogSave:
981 SetStatusLine1("Saving log...");
982 SetStatusLine2("");
983 *fLog << inf << "Saving log... " << flush;
984 if (fLogBox->GetText()->Save("statusdisplay.log"))
985 {
986 *fLog << "done." << endl;
987 SetStatusLine2("done.");
988 }
989 else
990 {
991 *fLog << "failed!" << endl;
992 SetStatusLine2("Failed!");
993 }
994 return kTRUE;
995
996 case kLogAppend:
997 SetStatusLine1("Appending logg...");
998 SetStatusLine2("");
999 *fLog << inf << "Appending log... " << flush;
1000 if (fLogBox->GetText()->Append("statusdisplay.log"))
1001 {
1002 *fLog << "done." << endl;
1003 SetStatusLine2("done.");
1004 }
1005 else
1006 {
1007 *fLog << "failed!" << endl;
1008 SetStatusLine2("Failed!");
1009 }
1010 return kTRUE;
1011#ifdef DEBUG
1012 default:
1013 cout << "Command-Menu #" << id << endl;
1014#endif
1015 }
1016 return kTRUE;
1017
1018}
1019
1020// --------------------------------------------------------------------------
1021//
1022// Process the kC_COMMAND messages
1023//
1024Bool_t MStatusDisplay::ProcessMessageCommand(Long_t submsg, Long_t mp1, Long_t mp2)
1025{
1026 switch (submsg)
1027 {
1028 case kCM_MENU:
1029 return ProcessMessageCommandMenu(mp1); // mp2=userdata
1030 case kCM_TAB:
1031 for (int i=1; i<fTab->GetNumberOfTabs(); i++)
1032 fTab->GetTabContainer(i)->UnmapWindow();
1033 UpdateTab(fTab->GetTabContainer(mp1));
1034 fTab->GetTabContainer(mp1)->MapWindow();
1035 /*
1036 if (mp1>0)
1037 fMenu->AddPopup("&CaOs", fCaOs, NULL);
1038 else
1039 fMenu->RemovePopup("CaOs");
1040 fMenu->Resize(fMenu->GetDefaultSize());
1041 MapSubwindows();
1042 MapWindow();
1043 */
1044 return kTRUE;
1045#ifdef DEBUG
1046 case kCM_MENUSELECT:
1047 cout << "Command-Menuselect #" << mp1 << " (UserData=" << (void*)mp2 << ")" << endl;
1048 return kTRUE;
1049
1050 case kCM_BUTTON:
1051 cout << "Command-Button." << endl;
1052 return kTRUE;
1053
1054 case kCM_CHECKBUTTON:
1055 cout << "Command-CheckButton." << endl;
1056 return kTRUE;
1057
1058 case kCM_RADIOBUTTON:
1059 cout << "Command-RadioButton." << endl;
1060 return kTRUE;
1061
1062 case kCM_LISTBOX:
1063 cout << "Command-Listbox #" << mp1 << " (LineId #" << mp2 << ")" << endl;
1064 return kTRUE;
1065
1066 case kCM_COMBOBOX:
1067 cout << "Command-ComboBox." << endl;
1068 return kTRUE;
1069 default:
1070 cout << "Command: " << "Submsg:" << submsg << " Mp1=" << mp1 << " Mp2=" << mp2 << endl;
1071#endif
1072 }
1073 return kTRUE;
1074}
1075
1076// --------------------------------------------------------------------------
1077//
1078// Process the kC_TEXTVIEW messages
1079//
1080Bool_t MStatusDisplay::ProcessMessageTextview(Long_t submsg, Long_t mp1, Long_t mp2)
1081{
1082 // kC_TEXTVIEW, kTXT_ISMARKED, widget id, [true|false] //
1083 // kC_TEXTVIEW, kTXT_DATACHANGE, widget id, 0 //
1084 // kC_TEXTVIEW, kTXT_CLICK2, widget id, position (y << 16) | x) //
1085 // kC_TEXTVIEW, kTXT_CLICK3, widget id, position (y << 16) | x) //
1086 // kC_TEXTVIEW, kTXT_F3, widget id, true //
1087 // kC_TEXTVIEW, kTXT_OPEN, widget id, 0 //
1088 // kC_TEXTVIEW, kTXT_CLOSE, widget id, 0 //
1089 // kC_TEXTVIEW, kTXT_SAVE, widget id, 0 //
1090#ifdef DEBUG
1091 switch (submsg)
1092 {
1093 case kTXT_ISMARKED:
1094 cout << "Textview-IsMarked #" << mp1 << " " << (mp2?"yes":"no") << endl;
1095 return kTRUE;
1096
1097 case kTXT_DATACHANGE:
1098 cout << "Textview-DataChange #" << mp1 << endl;
1099 return kTRUE;
1100
1101 case kTXT_CLICK2:
1102 cout << "Textview-Click2 #" << mp1 << " x=" << (mp2&0xffff) << " y= " << (mp2>>16) << endl;
1103 return kTRUE;
1104
1105 case kTXT_CLICK3:
1106 cout << "Textview-Click3 #" << mp1 << " x=" << (mp2&0xffff) << " y= " << (mp2>>16) << endl;
1107 return kTRUE;
1108
1109 case kTXT_F3:
1110 cout << "Textview-F3 #" << mp1 << endl;
1111 return kTRUE;
1112
1113 case kTXT_OPEN:
1114 cout << "Textview-Open #" << mp1 << endl;
1115 return kTRUE;
1116
1117 case kTXT_CLOSE:
1118 cout << "Textview-Close #" << mp1 << endl;
1119 return kTRUE;
1120
1121 case kTXT_SAVE:
1122 cout << "Textview-Save #" << mp1 << endl;
1123 return kTRUE;
1124
1125 default:
1126 cout << "Textview: " << "Submsg:" << submsg << " Mp1=" << mp1 << " Mp2=" << mp2 << endl;
1127 }
1128#endif
1129 return kTRUE;
1130}
1131
1132// --------------------------------------------------------------------------
1133//
1134// Process the kC_USER messages
1135//
1136Bool_t MStatusDisplay::ProcessMessageUser(Long_t submsg, Long_t mp1, Long_t mp2)
1137{
1138 // kS_START, case sensitive | backward<<1, char *txt
1139 switch (submsg)
1140 {
1141 case kS_START:
1142 fLogBox->Search((char*)mp2, !(mp1&2>>1), mp1&1);
1143 return kTRUE;
1144#ifdef DEBUG
1145 default:
1146 cout << "User: " << "Submsg:" << submsg << " Mp1=" << mp1 << " Mp2=" << mp2 << endl;
1147#endif
1148 }
1149 return kTRUE;
1150}
1151
1152// --------------------------------------------------------------------------
1153//
1154// Process the messages from the GUI
1155//
1156Bool_t MStatusDisplay::ProcessMessage(Long_t msg, Long_t mp1, Long_t mp2)
1157{
1158 // Can be found in WidgetMessageTypes.h
1159 cout << "Msg: " << GET_MSG(msg) << " Submsg:" << GET_SUBMSG(msg);
1160 cout << " Mp1=" << mp1 << " Mp2=" << mp2 << endl;
1161 switch (GET_MSG(msg))
1162 {
1163 case kC_COMMAND:
1164 return ProcessMessageCommand(GET_SUBMSG(msg), mp1, mp2);
1165
1166 case kC_TEXTVIEW:
1167 return ProcessMessageTextview(GET_SUBMSG(msg), mp1, mp2);
1168
1169 case kC_USER:
1170 return ProcessMessageUser(GET_SUBMSG(msg), mp1, mp2);
1171 }
1172#ifdef DEBUG
1173 cout << "Msg: " << GET_MSG(msg) << " Submsg:" << GET_SUBMSG(msg);
1174 cout << " Mp1=" << mp1 << " Mp2=" << mp2 << endl;
1175#endif
1176 return kTRUE;
1177}
1178
1179void MStatusDisplay::CloseWindow()
1180{
1181 // Got close message for this MainFrame. Calls parent CloseWindow()
1182 // (which destroys the window) and terminate the application.
1183 // The close message is generated by the window manager when its close
1184 // window menu item is selected.
1185
1186 // CloseWindow must be overwritten because otherwise CloseWindow
1187 // and the destructor are calling DestroyWindow which seems to be
1188 // in conflict with the TRootEmbeddedCanvas.
1189 delete this;
1190}
1191
1192// --------------------------------------------------------------------------
1193//
1194// Calls SetBit(kNoContextMenu) for all TCanvas objects found in the
1195// Tabs.
1196//
1197void MStatusDisplay::SetNoContextMenu(Bool_t flag)
1198{
1199 if (fIsLocked>1 || gROOT->IsBatch())
1200 return;
1201
1202 flag ? SetBit(kNoContextMenu) : ResetBit(kNoContextMenu);
1203 for (int i=1; i<fTab->GetNumberOfTabs(); i++)
1204 {
1205 TCanvas *c = GetCanvas(i);
1206 if (c)
1207 flag ? c->SetBit(kNoContextMenu) : c->ResetBit(kNoContextMenu);
1208 }
1209}
1210
1211// --------------------------------------------------------------------------
1212//
1213// Updates the canvas (if existing) in the currenly displayed Tab.
1214// The update intervall is controlled by StartUpdate and StopUpdate
1215//
1216Bool_t MStatusDisplay::HandleTimer(TTimer *timer)
1217{
1218 if (gROOT->IsBatch())
1219 return kTRUE;
1220
1221 const Int_t c = fTab->GetCurrent();
1222
1223 // Skip Legend Tab
1224 if (c==0)
1225 return kTRUE;
1226
1227 // Update a canvas tab (if visible)
1228 if (timer==&fTimer && c!=fLogIdx)
1229 {
1230 UpdateTab(fTab->GetCurrentContainer());
1231 return kTRUE;
1232 }
1233
1234 // update the logbook tab (if visible)
1235 if (timer==&fLogTimer && c==fLogIdx)
1236 {
1237 fLog->UpdateGui();
1238
1239 /*
1240 if (!fLogBox->TestBit(kHasChanged))
1241 return kTRUE;
1242
1243 fLogBox->ResetBit(kHasChanged);
1244 */
1245 return kTRUE;
1246 }
1247
1248 return kTRUE;
1249}
1250
1251// --------------------------------------------------------------------------
1252//
1253// Draws a clone of a canvas into a new canvas. Taken from TCanvas.
1254//
1255void MStatusDisplay::DrawClonePad(TCanvas &newc, const TCanvas &oldc) const
1256{
1257 //copy pad attributes
1258 newc.Range(oldc.GetX1(),oldc.GetY1(),oldc.GetX2(),oldc.GetY2());
1259 newc.SetTickx(oldc.GetTickx());
1260 newc.SetTicky(oldc.GetTicky());
1261 newc.SetGridx(oldc.GetGridx());
1262 newc.SetGridy(oldc.GetGridy());
1263 newc.SetLogx(oldc.GetLogx());
1264 newc.SetLogy(oldc.GetLogy());
1265 newc.SetLogz(oldc.GetLogz());
1266 newc.SetBorderSize(oldc.GetBorderSize());
1267 newc.SetBorderMode(oldc.GetBorderMode());
1268 ((TAttLine&)oldc).Copy((TAttLine&)newc);
1269 ((TAttFill&)oldc).Copy((TAttFill&)newc);
1270 ((TAttPad&)oldc).Copy((TAttPad&)newc);
1271
1272 //copy primitives
1273 TObject *obj;
1274 TIter next(oldc.GetListOfPrimitives());
1275 while ((obj=next())) {
1276 gROOT->SetSelectedPad(&newc);
1277 newc.GetListOfPrimitives()->Add(obj->Clone(),obj->GetDrawOption());
1278 }
1279 newc.Modified();
1280 newc.Update();
1281}
1282
1283// --------------------------------------------------------------------------
1284//
1285// Reads the contents of a saved MStatusDisplay from a file.
1286//
1287Int_t MStatusDisplay::Read(const char *name)
1288{
1289 if (!gFile)
1290 {
1291 *fLog << warn << "MStatusDisplay::Read: No file found. Please create a TFile first." << endl;
1292 return 0;
1293 }
1294
1295 if (!gFile->IsOpen())
1296 {
1297 *fLog << warn << "MStatusDisplay::Read: File not open. Please open the TFile first." << endl;
1298 return 0;
1299 }
1300
1301 TObjArray list;
1302
1303 const Int_t n = list.Read(name);
1304 if (n==0)
1305 {
1306 *fLog << warn << "MStatusDisplay::Read: No objects read." << endl;
1307 return 0;
1308 }
1309
1310 TIter Next(&list);
1311 TCanvas *c;
1312 while ((c=(TCanvas*)Next()))
1313 DrawClonePad(AddTab(c->GetName()), *c);
1314
1315 *fLog << inf << "MStatusDisplay: Key " << name << " with " << n << " keys read from file." << endl;
1316
1317 return n;
1318}
1319
1320// --------------------------------------------------------------------------
1321//
1322// Writes the contents of a MStatusDisplay to a file.
1323//
1324Int_t MStatusDisplay::Write(Int_t num, const char *name, Int_t option, Int_t bufsize)
1325{
1326 if (!gFile)
1327 {
1328 *fLog << warn << "MStatusDisplay::Write: No file found. Please create a TFile first." << endl;
1329 return 0;
1330 }
1331
1332 if (!gFile->IsOpen())
1333 {
1334 *fLog << warn << "MStatusDisplay::Write: File not open. Please open the TFile first." << endl;
1335 return 0;
1336 }
1337
1338 if (!gFile->IsWritable())
1339 {
1340 *fLog << warn << "MStatusDisplay::Write: File not writable." << endl;
1341 return 0;
1342 }
1343
1344 if (num==0)
1345 {
1346 *fLog << warn << "MStatusDisplay::Write: Tab doesn't contain an embedded Canvas... skipped." << endl;
1347 return 0;
1348 }
1349
1350 if (!gROOT->IsBatch() && num>=fTab->GetNumberOfTabs())
1351 {
1352 *fLog << warn << "MStatusDisplay::Write: Tab doesn't exist... skipped." << endl;
1353 return 0;
1354 }
1355 if (gROOT->IsBatch() && num>fBatch->GetSize())
1356 {
1357 *fLog << warn << "MStatusDisplay::Write: Tab doesn't exist... skipped." << endl;
1358 return 0;
1359 }
1360
1361 TObjArray list;
1362
1363 const Int_t max = gROOT->IsBatch() ? fBatch->GetSize()+1 : fTab->GetNumberOfTabs();
1364 const Int_t from = num<0 ? 1 : num;
1365 const Int_t to = num<0 ? max : num+1;
1366
1367 TCanvas *c;
1368 for (int i=from; i<to; i++)
1369 if ((c = GetCanvas(i)))
1370 list.Add(c);
1371
1372 const Int_t n = list.Write(name, kSingleKey);
1373
1374 *fLog << inf << "MStatusDisplay: " << n << " keys written to file as key " << name << "." << endl;
1375
1376 return n;
1377}
1378
1379// --------------------------------------------------------------------------
1380//
1381// Use this to start the synchronous (GUI eventloop driven) tab update.
1382// Can also be used to change the update intervall. If millisec<0
1383// the intervall given in SetUpdateTime is used. If the intervall in
1384// SetUpdateTime is <0 nothing is done. (Call SetUpdateTime(-1) to
1385// disable the automatic update in a MEventloop.
1386//
1387void MStatusDisplay::StartUpdate(Int_t millisec)
1388{
1389 if (fIsLocked>1)
1390 return;
1391
1392 if (fTimer.GetTime()<TTime(0))
1393 return;
1394 fTimer.Start(millisec);
1395}
1396
1397// --------------------------------------------------------------------------
1398//
1399// Stops the automatic GUI update
1400//
1401void MStatusDisplay::StopUpdate()
1402{
1403 if (fIsLocked>1)
1404 return;
1405
1406 fTimer.Stop();
1407}
1408
1409// --------------------------------------------------------------------------
1410//
1411// Set the update interval for the GUI update, see StartUpdate.
1412//
1413void MStatusDisplay::SetUpdateTime(Long_t t)
1414{
1415 fTimer.SetTime(t);
1416}
1417
1418// --------------------------------------------------------------------------
1419//
1420// Set the background color in a canvas
1421//
1422void MStatusDisplay::CanvasSetFillColor(TPad &p, Int_t col) const
1423{
1424 TObject *obj;
1425
1426 // See also TPad::UseCurrentStyle
1427 TIter Next(p.GetListOfPrimitives());
1428 while ((obj=Next()))
1429 {
1430 if (obj->InheritsFrom(TPad::Class()))
1431 CanvasSetFillColor(*(TPad*)obj, col);
1432 if (obj->InheritsFrom(TFrame::Class()))
1433 ((TFrame*)obj)->SetFillColor(col);
1434 }
1435
1436 p.SetFillColor(col);
1437}
1438
1439void MStatusDisplay::AddExtension(TString &name, const TString &ext, Int_t num) const
1440{
1441 if (name.IsNull())
1442 {
1443 name = "status";
1444 if (num>0)
1445 {
1446 name += "-";
1447 name += num;
1448 }
1449 }
1450
1451 if (name.EndsWith("."+ext))
1452 return;
1453
1454 name += ".";
1455 name += ext;
1456}
1457
1458Bool_t MStatusDisplay::CheckTabForCanvas(int num) const
1459{
1460 if (gROOT->IsBatch())
1461 return num>0 && num<=fBatch->GetSize() || num<0;
1462
1463 if (num>=fTab->GetNumberOfTabs())
1464 {
1465 *fLog << warn << "Tab #" << num << " doesn't exist..." << endl;
1466 return kFALSE;
1467 }
1468 if (num==0)
1469 {
1470 *fLog << warn << "Tab #" << num << " doesn't contain an embedded canvas..." << endl;
1471 return kFALSE;
1472 }
1473 if (fTab->GetNumberOfTabs()<2 || !gPad)
1474 {
1475 *fLog << warn << "Sorry, you must have at least one existing canvas (gPad!=NULL)" << endl;
1476 return kFALSE;
1477 }
1478 return kTRUE;
1479}
1480
1481// --------------------------------------------------------------------------
1482//
1483// Insert the following two lines into the postscript header:
1484//
1485// %%DocumentPaperSizes: a4
1486// %%Orientation: Landscape
1487//
1488void MStatusDisplay::UpdatePSHeader(const TString &name) const
1489{
1490 const TString newstr("%%DocumentPaperSizes: a4\n%%Orientation: Landscape\n");
1491 const Int_t l = newstr.Length();
1492
1493 Long_t t[4]; // { id, size, flags, modtime }
1494 gSystem->GetPathInfo(name, t, t+1, t+2, t+3);
1495
1496 char *c[2] = { new char[l], new char[l] };
1497
1498 fstream f(name, ios::in|ios::out);
1499
1500 TString str;
1501 f >> str >> c[0][0]; // Read "%!PS-Adobe-2.0\n" (Mini Header)
1502 f.read(c[0], l);
1503 f.seekp(-l, ios::cur);
1504 f.write(newstr, l);
1505
1506 int i=0;
1507 while (1)
1508 {
1509 f.read(c[(i+1)%2], l);
1510 f.seekp(-l, ios::cur);
1511
1512 if (f)
1513 {
1514 f.write(c[i%2],l);
1515 i++;
1516 i%=2;
1517 continue;
1518 }
1519
1520 const Int_t ssz = str.Length()+1; // Length of Mini-Header
1521 const Int_t block = t[1]-ssz; // Length of block to be shifted
1522 const Int_t size = block%l; // Reminder
1523 const Int_t pos = (block/l)*l + ssz + 1; // Position to start writing
1524
1525 f.clear();
1526 f.seekp(pos);
1527 f.write(c[i%2], l);
1528 f.write(c[(i+1)%2], size);
1529 break;
1530 }
1531
1532 delete c[1];
1533 delete c[0];
1534}
1535
1536// --------------------------------------------------------------------------
1537//
1538// In case of num<0 all tabs are written into the PS file. If num>0
1539// the canvas in the corresponding tab is written to the file.
1540// Name is the name of the file (with or without extension).
1541//
1542// Returns the number of pages written.
1543//
1544// To write all tabs you can also use SaveAsPS(name)
1545//
1546Int_t MStatusDisplay::SaveAsPS(Int_t num, TString name)
1547{
1548 SetStatusLine1("Writing Postscript file...");
1549 SetStatusLine2("");
1550
1551 if (!CheckTabForCanvas(num))
1552 {
1553 SetStatusLine2("Failed!");
1554 return 0;
1555 }
1556
1557 AddExtension(name, "ps", num);
1558
1559 if (num<0)
1560 *fLog << inf << "Open ps-File: " << name << endl;
1561
1562 TPad *padsav = (TPad*)gPad;
1563 TVirtualPS *psave = gVirtualPS;
1564
1565 TPostScript ps(name, 112);
1566 ps.SetBit(TPad::kPrintingPS);
1567 ps.PrintFast(13, "/nan {1} def ");
1568
1569 gVirtualPS = &ps;
1570
1571 //
1572 // Create a list to delete the canvas clones
1573 //
1574 TList l;
1575 l.SetOwner();
1576
1577 //
1578 // Create some GUI elements for a page legend
1579 //
1580 TLine line;
1581
1582 int page = 1;
1583
1584 //
1585 // Maintain tab numbers
1586 //
1587 const Int_t max = gROOT->IsBatch() ? fBatch->GetSize()+1 : fTab->GetNumberOfTabs();
1588 const Int_t from = num<0 ? 1 : num;
1589 const Int_t to = num<0 ? max : num+1;
1590
1591 for (int i=from; i<to; i++)
1592 {
1593 TCanvas *c;
1594 if (!(c = GetCanvas(i)))
1595 {
1596 if (num<0)
1597 *fLog << inf << " - ";
1598 *fLog << "Tab #" << i << " doesn't contain an embedded Canvas... skipped." << endl;
1599 continue;
1600 }
1601
1602 SetStatusLine2(Form("Tab #%d", i));
1603
1604 //
1605 // Init page and page size, make sure, that the canvas in the file
1606 // has the same Aspect Ratio than on the screen.
1607 //
1608 ps.NewPage();
1609
1610 Float_t psw = 26; // A4 - width
1611 Float_t psh = 20; // A4 - height
1612
1613 const Float_t cw = c->GetWw();
1614 const Float_t ch = c->GetWh();
1615
1616 if (psw/psh>cw/ch)
1617 psw = cw/ch*psh;
1618 else
1619 psh = ch/cw*psw;
1620
1621 ps.Range(psw, psh); // A4
1622
1623 //
1624 // Clone canvas and change background color and schedule for
1625 // deletion
1626 //
1627 TCanvas *n = (TCanvas*)c->Clone();
1628 CanvasSetFillColor(*n, kWhite);
1629 l.Add(n);
1630 //
1631 // Paint canvas into root file
1632 //
1633 if (num<0)
1634 *fLog << inf << " - ";
1635 *fLog << inf << "Writing Tab #" << i << ": " << c->GetName() << " (" << c << ") ";
1636 if (num>0)
1637 *fLog << "to " << name;
1638 *fLog << "..." << flush;
1639
1640 n->SetBatch(kTRUE);
1641 n->Paint();
1642
1643 //
1644 // Use the canvas as coordinate system for the overlaying text
1645 //
1646 gPad = n;
1647
1648 //
1649 // Print overlaying text (NDC = %)
1650 //
1651 ps.SetTextColor(kBlack);
1652 ps.SetTextSize(0.015);
1653 ps.SetTextFont(22);
1654 ps.SetTextAlign(11); // left top
1655 ps.TextNDC(0, 1.02, TString(" ")+n->GetName());
1656 ps.SetTextAlign(21); // cent top
1657 ps.TextNDC(0.5, 1.02, "MARS - Magic Analysis and Reconstruction Software");
1658 ps.SetTextAlign(31); // right top
1659 ps.TextNDC(1, 1.02, Form("Page No.%i (%i) ", page++, i));
1660 line.PaintLineNDC(0, 1.015, 1, 1.015);
1661
1662 //
1663 // Finish drawing page
1664 //
1665 n->SetBatch(kFALSE);
1666 if (num<0)
1667 *fLog << "done." << endl;
1668 }
1669
1670 gPad = NULL; // Important!
1671 l.Delete();
1672
1673 ps.Close();
1674 UpdatePSHeader(name);
1675
1676 gVirtualPS = psave;
1677 if (padsav)
1678 padsav->cd();
1679
1680 *fLog << inf << "done." << endl;
1681
1682 SetStatusLine2(Form("Done (%dpages)", page-1));
1683
1684 return page-1;
1685}
1686
1687Bool_t MStatusDisplay::SaveAsGIF(Int_t num, TString name)
1688{
1689 if (gROOT->IsBatch())
1690 {
1691 *fLog << warn << "Sorry, writing gif-files is not available in batch mode." << endl;
1692 return 0;
1693 }
1694 SetStatusLine1("Writing GIF file...");
1695 SetStatusLine2("");
1696
1697 if (!CheckTabForCanvas(num))
1698 {
1699 SetStatusLine2("Failed!");
1700 return 0;
1701 }
1702
1703 AddExtension(name, "gif", num);
1704
1705 if (num<0)
1706 *fLog << inf << "Writing gif-Files..." << endl;
1707
1708 TPad *padsav = (TPad*)gPad;
1709
1710 int page = 1;
1711
1712 //
1713 // Maintain tab numbers
1714 //
1715 const Int_t from = num<0 ? 1 : num;
1716 const Int_t to = num<0 ? fTab->GetNumberOfTabs() : num+1;
1717
1718 for (int i=from; i<to; i++)
1719 {
1720 TCanvas *c;
1721 if (!(c = GetCanvas(i)))
1722 {
1723 if (num<0)
1724 *fLog << inf << " - ";
1725 *fLog << "Tab #" << i << " doesn't contain an embedded Canvas... skipped." << endl;
1726 continue;
1727 }
1728
1729 SetStatusLine2(Form("Tab #%d", i));
1730
1731 //
1732 // Clone canvas and change background color and schedule for
1733 // deletion
1734 //
1735 //TCanvas *n = (TCanvas*)c->Clone();
1736 //CanvasSetFillColor(*n, kWhite);
1737
1738 //
1739 // Paint canvas into root file
1740 //
1741 TString writename = name;
1742 if (num<0)
1743 {
1744 TString numname = "-";
1745 numname += i;
1746 writename.Insert(name.Last('.'), numname);
1747 }
1748 if (num<0)
1749 *fLog << inf << " - ";
1750 *fLog << inf << "Writing Tab #" << i << " to " << writename << ": " << c->GetName() << " (" << c << ") ";
1751 if (num>0)
1752 *fLog << "to " << name;
1753 *fLog << "..." << flush;
1754
1755 c->Draw();
1756 c->SaveAs(writename);
1757 /*
1758 n->Draw();
1759 n->SaveAs(writename);
1760 delete n;
1761 */
1762
1763 if (num<0)
1764 *fLog << "done." << endl;
1765 }
1766
1767 padsav->cd();
1768
1769 *fLog << inf << "done." << endl;
1770
1771 SetStatusLine2("Done.");
1772
1773 return page-1;
1774}
1775
1776Bool_t MStatusDisplay::SaveAsC(Int_t num, TString name)
1777{
1778 SetStatusLine1("Writing C++ file...");
1779 SetStatusLine2("");
1780
1781 if (!CheckTabForCanvas(num))
1782 {
1783 SetStatusLine2("Failed!");
1784 return 0;
1785 }
1786
1787 AddExtension(name, "C", num);
1788
1789 if (num<0)
1790 *fLog << inf << "Writing C-Files..." << endl;
1791
1792 TPad *padsav = (TPad*)gPad;
1793
1794 int page = 1;
1795
1796 //
1797 // Maintain tab numbers
1798 //
1799 const Int_t from = num<0 ? 1 : num;
1800 const Int_t to = num<0 ? fTab->GetNumberOfTabs() : num+1;
1801
1802 for (int i=from; i<to; i++)
1803 {
1804 TCanvas *c;
1805 if (!(c = GetCanvas(i)))
1806 {
1807 if (num<0)
1808 *fLog << inf << " - ";
1809 *fLog << "Tab #" << i << " doesn't contain an embedded Canvas... skipped." << endl;
1810 continue;
1811 }
1812
1813 SetStatusLine2(Form("Tab #%d", i));
1814
1815 //
1816 // Clone canvas and change background color and schedule for
1817 // deletion
1818 //
1819 TCanvas *n = (TCanvas*)c->Clone();
1820 CanvasSetFillColor(*n, kWhite);
1821
1822 //
1823 // Paint canvas into root file
1824 //
1825 TString writename = name;
1826 if (num<0)
1827 {
1828 TString numname = "-";
1829 numname += i;
1830 writename.Insert(name.Last('.'), numname);
1831 }
1832 if (num<0)
1833 *fLog << inf << " - ";
1834 *fLog << inf << "Writing Tab #" << i << " to " << writename << ": " << c->GetName() << " (" << n << ") ";
1835 if (num>0)
1836 *fLog << "to " << name;
1837 *fLog << "..." << flush;
1838
1839 n->SaveSource(writename, "");
1840 delete n;
1841
1842 if (num<0)
1843 *fLog << "done." << endl;
1844 }
1845
1846 padsav->cd();
1847
1848 *fLog << inf << "done." << endl;
1849
1850 SetStatusLine2("Done.");
1851
1852 return page-1;
1853}
1854
1855// --------------------------------------------------------------------------
1856//
1857// In case of num<0 all tabs are written into the PS file. If num>0
1858// the canvas in the corresponding tab is written to the file.
1859// Name is the name of the file (with or without extension).
1860//
1861// Returns the number of keys written.
1862//
1863// To write all tabs you can also use SaveAsPS(name)
1864//
1865Int_t MStatusDisplay::SaveAsRoot(Int_t num, TString name)
1866{
1867 SetStatusLine1("Writing root file...");
1868 SetStatusLine2("");
1869
1870 if (!CheckTabForCanvas(num))
1871 {
1872 SetStatusLine2("Failed!");
1873 return 0;
1874 }
1875
1876 AddExtension(name, "root", num);
1877
1878 TFile *fsave = gFile;
1879 TFile file(name, "RECREATE", "MARS - Status Window Contents", 9);
1880 const Int_t keys = Write(num);
1881 gFile = fsave;
1882
1883 SetStatusLine2("Done.");
1884
1885 return keys;
1886}
1887
1888Bool_t MStatusDisplay::HandleConfigureNotify(Event_t *evt)
1889{
1890 //cout << "----- Start -----" << endl;
1891
1892 UInt_t w = evt->fWidth;
1893 UInt_t h = evt->fHeight;
1894
1895 //cout << "Old: " << GetWidth() << " " << GetHeight() << " " << GetBorderWidth() << endl;
1896 //cout << "New: " << w << " " << h << endl;
1897
1898 Bool_t wchanged = w!=GetWidth();
1899 Bool_t hchanged = h!=GetHeight();
1900
1901 if (!wchanged && !hchanged)
1902 {
1903 Layout();
1904 return kTRUE;
1905 }
1906
1907 if (GetWidth()==1 && GetHeight()==1)
1908 return kTRUE;
1909
1910 // calculate the constant part of the window
1911 const UInt_t cw = GetWidth() -fTab->GetWidth();
1912 const UInt_t ch = GetHeight()-fTab->GetHeight();
1913
1914 // canculate new size of frame (canvas @ 1:sqrt(2))
1915 if (hchanged)
1916 w = (UInt_t)((h-ch)*sqrt(2.)+.5)+cw;
1917 else
1918 h = (UInt_t)((w-cw)/sqrt(2.)+.5)+ch;
1919
1920 //cout << "Res: " << w << " " << h << " " << evt->fX << " " << evt->fY << endl;
1921
1922 // resize frame
1923 Resize(w, h);
1924
1925 return kTRUE;
1926}
1927
1928Bool_t MStatusDisplay::HandleEvent(Event_t *event)
1929{
1930 /*
1931 if (event->fType!=9)
1932 {
1933 cout << "Event: " << event->fType << " ";
1934 cout << event->fX << " " << event->fY << endl;
1935 }
1936 */
1937 /*
1938 switch (event->fType) {
1939 case kConfigureNotify:
1940 //while (gVirtualX->CheckEvent(fId, kConfigureNotify, *event))
1941 // ;
1942 HandleConfigureNotify(event);
1943 return kTRUE;
1944 }
1945 */
1946 // if (event->fType==kConfigureNotify && event->fX!=0 && event->fY!=0)
1947 // return kTRUE;
1948
1949 return TGMainFrame::HandleEvent(event);
1950}
1951
Note: See TracBrowser for help on using the repository browser.