source: trunk/MagicSoft/Mars/mbase/MStatusDisplay.cc@ 2498

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