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

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