// $Id: EGViewer.cc,v 1.38 2005/11/02 01:07:47 thea Exp $
// Author: Alessandro Thea 2005/05/23
/*****************************************************************************
* ESAF: Euso Simulation and Analysis Framework *
* *
* Id: EGViewer *
* Package: <packagename> *
* Coordinator: <coordinator> *
* *
*****************************************************************************/
//_____________________________________________________________________________
//
// EGViewer
//
// <extensive class description>
//
// Config file parameters
// ======================
//
// <parameter name>: <parameter description>
// -Valid options: <available options>
//
#include "EGViewer.hh"
#include <iostream>
#include <fstream>
#include <TApplication.h>
#include <TCanvas.h>
#include <TFrame.h>
#include <TG3DLine.h>
#include <TGComboBox.h>
#include <TGListBox.h>
#include <TGLayout.h>
#include <TGMenu.h>
#include <TGProgressBar.h>
#include <TGStatusBar.h>
#include <TGTab.h>
#include <TLine.h>
#include <TMethodCall.h>
#include <TMutex.h>
#include <TPostScript.h>
#include <TPDF.h>
#include <TRootEmbeddedCanvas.h>
#include <TStyle.h>
#include <TText.h>
#include <TVirtualPS.h>
#include <TVirtualPadEditor.h>
#include <TGLabel.h>
#include <TGFileDialog.h>
#include <TH1.h>
#include <TGedEditor.h>
#include "KeySymbols.h"
// 28 and 19 used here to scale the canvas into a height of 28, such that the
// page title can be set above the canvas...
const Float_t kA4Width = 29.7; // A4 - width (29.7)
const Float_t kA4Height = 21.0; // A4 - height (21.0)
const Float_t kA4PrintWidth = 27.9; // A4 - width (29.7)
const Float_t kA4PrintHeight = 19.5; // A4 - height (21.0)
const Float_t kA4CanvasWHRatio = 1.5; // A4 - height (21.0)
enum EEGViewerCommands {
kFileSaveAs,
kFileSaveAsPS,
kFileSaveAsPDF,
kFileSaveAsRoot,
kFileCloseViewer,
kFileExit,
kViewEditor,
kViewCombo,
kViewX3D,
kViewOpenGL,
kTabClonePad,
kOptionStatistics,
kOptionHistTitle,
kOptionFitParams,
kOptionCanEdit,
kSizeA4,
kSize640,
kSize800,
kSize960,
kSize1024,
kSize1280,
kW_COMBO_TABS,
kW_LIST_TABS
};
static const char *gSaveAsTypes[] = { "PostScript", "*.ps",
// "Encapsulated PostScript", "*.eps",
"PDF", "*.pdf",
// "SVG", "*.svg",
// "GIF", "*.gif",
// "ROOT macros", "*.C",
"ROOT files", "*.root",
// "XML", "*.xml",
// "PNG", "*.png",
// "XPM", "*.xpm",
// "JPEG", "*.jpg",
// "TIFF", "*.tiff",
// "XCF", "*.xcf",
"All files", "*",
0, 0 };
using namespace std;
using namespace TMath;
ClassImp(EGViewer)
//_____________________________________________________________________________
EGViewer::EGViewer( const char* name, const char* title, Int_t w, Int_t h) : TGMainFrame(gClient->GetRoot(), w, h) {
//
// Constructor
//
TString wname = name ? name : "EGViewer";
TString wtitle = title ? title : wname.Data();
Constructor(wname,wtitle);
Resize(w,h);
// draw the window
MapWindow();
if ( !TThread::Self() )
gSystem->ProcessEvents();
}
//_____________________________________________________________________________
EGViewer::EGViewer(Bool_t build, const char* name, Int_t w, Int_t h) : TGMainFrame(gClient->GetRoot(), w, h) {
//
// Protected constructor
//
if ( build ) {
TString wname = name ? name : "EGViewer";
Constructor( name , name);
Resize(w,h);
}
}
//______________________________________________________________________________
Bool_t EGViewer::Constructor(const char* name, const char* title) {
//
// Build the Viewer
//
fPadLookup = kFALSE;
fOldPad = 0;
fEditor = 0;
gVirtualX->GrabKey(fId, gVirtualX->KeysymToKeycode(kKey_Left),
kKeyControlMask, kTRUE);
gVirtualX->GrabKey(fId, gVirtualX->KeysymToKeycode(kKey_Right),
kKeyControlMask, kTRUE);
gVirtualX->GrabKey(fId, gVirtualX->KeysymToKeycode(kKey_Tab),
kKeyControlMask, kTRUE);
fName = name ;
fTitle = title ? title : name;
fList = new TList;
fList->SetOwner();
// list of pointer to the tab canvases
fCanvases = new TList;
fMutex = new TMutex;
//
// Create the layout hint for the root embedded canavses
//
fLayCanvas = new TGLayoutHints(kLHintsExpandX|kLHintsExpandY);
fList->Add(fLayCanvas);
SetWindowName(fTitle);
if ( gClient ) {
AddMenuBar();
AddUserFrame();
AddTabs();
AddStatusBar();
}
UpdateWMSizeHints();
Layout();
MapSubwindows();
ShowTabList(kFALSE);
ShowEditor(kFALSE);
Resize(GetDefaultSize());
return kTRUE;
}
//_____________________________________________________________________________
EGViewer::~EGViewer() {
//
// Destructor
//
SafeDelete(fEditor);
delete fList;
delete fCanvases;
}
//______________________________________________________________________________
void EGViewer::UpdateWMSizeHints() {
//
// Sets the WM min-max size of the window not to hide the tab list.
// Sometime, if it is hidden a crash may occour.
//
// 10 pixles left fo the canvases
UInt_t minh = GetHeight()-GetTab()->GetHeight()+GetTab()->GetTabHeight()+10;
UInt_t minw = 200;
SetWMSizeHints(minw,minh,kMaxUShort,kMaxUShort,1,1);
}
//______________________________________________________________________________
void EGViewer::CloseWindow() {
DeleteWindow();
}
//______________________________________________________________________________
void EGViewer::Clear( Option_t* opt ) {
//
//
//
RemoveTabs();
}
//______________________________________________________________________________
void EGViewer::AddMenuBar() {
//
// File Menu
//
//
// Horizontal frame
//
TGLayoutHints *lay = new TGLayoutHints( kLHintsNormal|kLHintsExpandX,0,0,0,0 );
fList->Add(lay);
fMenuFrame = new TGCompositeFrame(this, GetWidth() + 4, GetHeight() + 4,
kHorizontalFrame);
fList->Add(fMenuFrame);
fFileSaveMenu = new TGPopupMenu(gClient->GetRoot());
fFileSaveMenu->AddEntry(Form("%s.ps",GetName()), kFileSaveAsPS);
fFileSaveMenu->AddEntry(Form("%s.pdf",GetName()), kFileSaveAsPDF);
fFileSaveMenu->AddEntry(Form("%s.root",GetName()), kFileSaveAsRoot);
fFileSaveMenu->Associate(this);
fFileMenu = new TGPopupMenu(gClient->GetRoot());
fFileMenu->AddEntry("Save &As...", kFileSaveAs);
fFileMenu->AddPopup("&Save", fFileSaveMenu);
fFileMenu->AddSeparator();
fFileMenu->AddEntry("C&lose viewer", kFileCloseViewer);
fFileMenu->AddEntry("E&xit", kFileExit);
fFileMenu->Associate(this);
fViewMenu = new TGPopupMenu(gClient->GetRoot());
fViewMenu->AddEntry("&Editor",kViewEditor);
fViewMenu->AddEntry("&Tab list",kViewCombo);
fViewMenu->AddSeparator();
fViewMenu->AddEntry("&X3D", kViewX3D);
fViewMenu->AddEntry("&OpenGL", kViewOpenGL);
fViewMenu->Associate(this);
fTabMenu = new TGPopupMenu(gClient->GetRoot());
fTabMenu->AddEntry("&Clone pad", kTabClonePad);
fTabMenu->Associate(this);
fOptionMenu = new TGPopupMenu(gClient->GetRoot());
fOptionMenu->AddEntry("&Statistics", kOptionStatistics);
fOptionMenu->AddEntry("Histogram &Title", kOptionHistTitle);
fOptionMenu->AddEntry("&Fit Parameters", kOptionFitParams);
fOptionMenu->AddEntry("Can Edit &Histograms", kOptionCanEdit);
fOptionMenu->Associate(this);
if (gStyle->GetOptStat())
fOptionMenu->CheckEntry(kOptionStatistics);
if (gStyle->GetOptTitle())
fOptionMenu->CheckEntry(kOptionHistTitle);
if (gStyle->GetOptFit())
fOptionMenu->CheckEntry(kOptionFitParams);
if (gROOT->GetEditHistograms())
fOptionMenu->CheckEntry(kOptionCanEdit);
fSizePaperMenu = new TGPopupMenu(gClient->GetRoot());
fSizePaperMenu->AddEntry("&A4 (640x497)",kSizeA4);
fSizeMenu = new TGPopupMenu(gClient->GetRoot());
fSizeMenu->AddEntry("Resize to &640x480",kSize640);
fSizeMenu->AddEntry("Resize to &800x600",kSize800);
fSizeMenu->AddEntry("Resize to &960x720",kSize960);
fSizeMenu->AddEntry("Resize to &1024x768",kSize1024);
fSizeMenu->AddEntry("Resize to 1&280x1024",kSize1280);
fSizeMenu->AddPopup("Resize &To...",fSizePaperMenu);
fSizeMenu->Associate(this);
//
// Menu Bar
//
TGLayoutHints *layitem = new TGLayoutHints(kLHintsNormal, 0, 4, 0, 0);
fList->Add(layitem);
fMenuBar = new TGMenuBar(fMenuFrame, 1, 1, kHorizontalFrame);
fMenuBar->AddPopup("&File", fFileMenu, layitem);
// fMenuBar->AddPopup("Lo&g", logmenu, layitem);
fMenuBar->AddPopup("&View", fViewMenu, layitem);
fMenuBar->AddPopup("&Tab", fTabMenu, layitem);
fMenuBar->AddPopup("&Options", fOptionMenu, layitem);
fMenuBar->AddPopup("&Resize", fSizeMenu, layitem);
// fMenuBar->AddPopup("&Loop", floopMenu, layitem);
// fMenuBar->BindKeys(this);
fMenuFrame->AddFrame(fMenuBar);
//
// Add everything to autodel list
//
fList->Add(fFileMenu);
fList->Add(fFileSaveMenu);
fList->Add(fViewMenu);
fList->Add(fTabMenu);
fList->Add(fSizeMenu);
fList->Add(fSizePaperMenu);
//
// Add the tab Combo box
//
TGLayoutHints* laycombo = new TGLayoutHints(kLHintsTop | kLHintsRight, 0, 4, 2, 2);
fList->Add(laycombo);
fTabCombo = new TGComboBox(fMenuFrame, kW_COMBO_TABS);
fTabCombo->Associate(this);
fMenuFrame->AddFrame(fTabCombo, laycombo);
fList->Add(fTabCombo);
fTabCombo->Resize(150,20);
AddFrame(fMenuFrame,lay);
//
// Add a 3d line at the bottom of the bar
//
TGLayoutHints *lay3D = new TGLayoutHints(kLHintsExpandX);
fList->Add(lay3D);
fLine = new TGHorizontal3DLine(this);
fList->Add(fLine);
AddFrame(fLine, lay3D);
}
//______________________________________________________________________________
void EGViewer::AddUserFrame() {
//
// Adds an empty TGCompositeFrame which might be filled by the user
//
TGLayoutHints *lay = new TGLayoutHints(kLHintsExpandX);
fList->Add(lay);
fUserFrame = new TGVerticalFrame(this, 1, 1);
AddFrame(fUserFrame, lay);
fList->Add(fUserFrame);
}
//______________________________________________________________________________
void EGViewer::AddTabs() {
//
// Add Tabs frame
//
TGLayoutHints *lay = new TGLayoutHints( kLHintsNormal|kLHintsExpandX|kLHintsExpandY, 0, 0, 0, 0 );
fList->Add(lay);
fMainFrame = new TGHorizontalFrame(this, GetWidth() + 4, GetHeight() + 4);
fList->Add(fMainFrame);
TGLayoutHints *laylistframe = new TGLayoutHints( kLHintsNormal|kLHintsExpandY, 0, 0, 0, 0 );
fList->Add(laylistframe);
fTabListFrame = new TGVerticalFrame(fMainFrame, 125, fMainFrame->GetHeight()+4, kFixedWidth);
fList->Add(fTabListFrame);
TGLayoutHints* laylbl = new TGLayoutHints(kLHintsLeft, 5, 2, 2, 2);
fList->Add(laylbl);
TGLabel* label = new TGLabel(fTabListFrame,"Tabs");
fList->Add(label);
fTabListFrame->AddFrame(label,laylbl);
fTabList = new TGListBox(fTabListFrame,kW_LIST_TABS);
fTabList->Associate(this);
fList->Add(fTabList);
// fTabList->Resize(125,20);
TGLayoutHints *laylist = new TGLayoutHints(kLHintsNormal|kLHintsExpandY|kLHintsExpandX, 2, 1, 2, 2);
fList->Add(laylist);
fTabListFrame->AddFrame(fTabList, laylist);
fMainFrame->AddFrame(fTabListFrame, laylistframe);
fTab = new TGTab(fMainFrame, fMainFrame->GetWidth()+4,fMainFrame->GetHeight()+4);
fTab->Associate(this);
// Add fTab to Frame
TGLayoutHints *laytabs = new TGLayoutHints(kLHintsNormal|kLHintsExpandX|kLHintsExpandY, 1, 2, 2, 2);
fMainFrame->AddFrame(fTab, laytabs);
TGLayoutHints *layeditframe = new TGLayoutHints( kLHintsNormal|kLHintsExpandY, 0, 0, 0, 0 );
fList->Add(layeditframe);
fEditorFrame = new TGCompositeFrame(fMainFrame, 175, fMainFrame->GetHeight()+4, kFixedWidth);
fList->Add(fEditorFrame);
fMainFrame->AddFrame(fEditorFrame, layeditframe);
fList->Add(fTab);
fList->Add(laytabs);
AddFrame(fMainFrame, lay);
}
//______________________________________________________________________________
void EGViewer::AddStatusBar() {
//
// Add the status bar
//
//
// Horizontal frame
//
TGLayoutHints *lay = new TGLayoutHints( kLHintsNormal|kLHintsExpandX,0,0,0,0 );
fStatusFrame = new TGCompositeFrame(this, GetWidth() + 4, GetHeight() + 4,
kHorizontalFrame);
fList->Add(fStatusFrame);
fList->Add(lay);
TGLayoutHints *layprog = new TGLayoutHints( kLHintsNormal,3,2,0,2 );
fProgressBar = new TGHProgressBar(fStatusFrame,150,18);
fProgressBar->SetBarColor("lightblue");
fProgressBar->ShowPosition();
fProgressBar->SetFillType(TGProgressBar::kSolidFill);
fStatusFrame->AddFrame(fProgressBar, layprog);
fList->Add(layprog);
fList->Add(fProgressBar);
fStatusBar = new TGStatusBar(fStatusFrame, 1, 1);
Int_t parts[] = { 28,10, 62 };
fStatusBar->SetParts(parts, 3);
TGLayoutHints *layb = new TGLayoutHints(kLHintsNormal|kLHintsExpandX, 2, 3, 0, 2);
fStatusFrame->AddFrame(fStatusBar, layb);
fList->Add(fStatusBar);
fList->Add(layb);
AddFrame(fStatusFrame, lay);
}
//______________________________________________________________________________
void EGViewer::CreateEditor() {
//
//
//
if (TVirtualPadEditor::GetPadEditor(kFALSE) != 0) {
TVirtualPadEditor::HideEditor();
}
fEditorFrame->SetEditable();
// next two lines are related to the old editor
fEditor = TVirtualPadEditor::LoadEditor();
fEditor->SetGlobal(kFALSE);
fEditorFrame->SetEditable(0);
}
//______________________________________________________________________________
void EGViewer::ShowEditor( Bool_t show ) {
//
//
//
UInt_t w = GetWidth();
UInt_t e = fEditorFrame->GetWidth();
UInt_t h = GetHeight();
if (show) {
if ( !fCanvases->GetEntries() ) return;
if (!fEditor) CreateEditor();
fViewMenu->CheckEntry(kViewEditor);
fEditor->Show();
fMainFrame->ShowFrame(fEditorFrame);
w += e;
} else {
fViewMenu->UnCheckEntry(kViewEditor);
if ( fEditor) fEditor->Hide();
fMainFrame->HideFrame(fEditorFrame);
//
// If the editor does not exist, do not resize the window.
// Useful in the constructor of child classes.
w -= e;
}
Resize(w,h);
}
//______________________________________________________________________________
void EGViewer::ToggleEditor() {
//
//
//
ShowEditor(!fViewMenu->IsEntryChecked(kViewEditor));
}
//______________________________________________________________________________
TGCompositeFrame* EGViewer::AddEmptyTab( const char* title ) {
//
//
//
TGCompositeFrame* f = GetTab()->AddTab(title);
//
// Combo entries handling
//
fTabCombo->AddEntry(title, fTabCombo->GetListBox()->GetNumberOfEntries());
fTabCombo->Select(GetTab()->GetCurrent());
fTabList->AddEntry(title, fTabList->GetNumberOfEntries());
fTabList->Select(GetTab()->GetCurrent());
fTabList->Layout();
fTabList->MapSubwindows();
GetTab()->Layout(); // seems to layout the TGCompositeFrame
GetTab()->MapSubwindows(); // maps the TGCompositeFrame
// display new tab in the main frame
// FIXME: Workaround because TApplication::Run is not thread safe in
// respect of ProcessEvents
if ( !TThread::Self() )
gClient->ProcessEventsFor(GetTab());
return f;
}
//______________________________________________________________________________
TCanvas* EGViewer::AddTab( const char* name, const char* title ) {
//
// Add new tab
//
if ( gROOT->IsBatch() ) {
TCanvas* c = new TCanvas( name, title ? title : name );
fList->Add(c);
fCanvases->Add(c);
return c;
}
TVirtualPad* padsave = gPad;
TGCompositeFrame *f = AddEmptyTab(title ? title: name );
// create root embedded canvas and add it to the tab
TRootEmbeddedCanvas *ec = new TRootEmbeddedCanvas(name, f, f->GetWidth(), f->GetHeight(), 0);
f->AddFrame(ec, fLayCanvas);
fList->Add(ec);
TCanvas *c = ec->GetCanvas();
c->SetBorderMode(0);
c->SetTitle(title ? title : name );
if (TestBit(kNoContextMenu))
c->SetBit(kNoContextMenu);
c->Connect("ProcessedEvent(Int_t,Int_t,Int_t,TObject*)",
"EGViewer",this,
"EventInfo(Int_t,Int_t,Int_t,TObject*)");
// layout and map new tab
GetTab()->Layout(); // seems to layout the TGCompositeFrame
GetTab()->MapSubwindows(); // maps the TGCompositeFrame
GetTab()->Layout(); // layout the embedded canvas in the frame
fTabListFrame->Layout();
// display new tab in the main frame
// FIXME: Workaround because TApplication::Run is not thread safe in
// respect of ProcessEvents
if ( !TThread::Self() )
gClient->ProcessEventsFor(GetTab());
fCanvases->Add(c);
gPad = padsave;
return c;
}
//______________________________________________________________________________
TCanvas* EGViewer::FindAddTab( const char* name, const char* title ) {
//
// Add new tab if it's not already in the list
//
TCanvas* c = FindCanvas(name);
if (!c) c = AddTab(name, title);
else c->SetTitle(title);
return c;
}
//______________________________________________________________________________
void EGViewer::RemoveTab(Int_t i ) {
//
// Remove the i-th Tab
//
TGCompositeFrame *f = GetTab()->GetTabContainer(i);
if (!f)
return;
TRootEmbeddedCanvas *ec = GetEmbeddedCanvas(f);
if (ec) {
TCanvas *c = ec->GetCanvas();
if (c) {
fCanvases->Remove(c);
if ( fEditor) {
TGedEditor* ged = dynamic_cast<TGedEditor*>(fEditor);
if ( !fCanvases->GetEntries() ) {
#ifdef DEBUG
cout << "Last canvas, close editor" << endl;
#endif /* DEBUG */
ShowEditor(kFALSE);
SafeDelete(fEditor);
} else {
ged->DisconnectEditors(c);
}
}
}
f->RemoveFrame(ec);
delete fList->Remove(ec);
}
GetTab()->RemoveTab(i);
//
// Combo entries handling
//
fTabCombo->RemoveEntry(i);
for (int j=i; j<fTabCombo->GetListBox()->GetNumberOfEntries(); j++)
{
TGTextLBEntry *entry = (TGTextLBEntry *)fTabCombo->GetListBox()->Select(j+1, kFALSE);
fTabCombo->AddEntry(entry->GetText()->GetString(), j);
fTabCombo->RemoveEntry(j+1);
}
fTabList->RemoveEntry(i);
for (int j=i; j<fTabList->GetNumberOfEntries(); j++)
{
TGTextLBEntry *entry = (TGTextLBEntry *)fTabList->Select(j+1, kFALSE);
fTabList->AddEntry(entry->GetText()->GetString(), j);
fTabList->RemoveEntry(j+1);
}
//
SelectTab(0);
fTabList->Layout();
fTabList->MapSubwindows();
GetTab()->Layout(); // seems to layout the TGCompositeFrame
GetTab()->MapSubwindows(); // maps the TGCompositeFrame
GetTab()->Layout(); // layout the embedded canvas in the frame
fTabListFrame->Layout();
// display new tab in the main frame
// FIXME: Workaround because TApplication::Run is not thread safe in
// respect of ProcessEvents
if ( !TThread::Self() )
gClient->ProcessEventsFor(GetTab());
}
//______________________________________________________________________________
void EGViewer::SelectTab(Int_t i) const {
GetTab()->SetTab(i);
fTabCombo->Select(i);
fTabList->Select(i);
if ( TCanvas* c = FindCanvasByTab(i) ) {
c->cd();
if ( fEditor ) {
TGedEditor* ged = dynamic_cast<TGedEditor*>(fEditor);
ged->SetCanvas(c);
#ifdef DEBUG
cout << "Select tab " << i << " canvas " << c << endl;
#endif /* DEBUG */
}
}
// display new tab in the main frame
// FIXME: Workaround because TApplication::Run is not thread safe in
// respect of ProcessEvents
if ( !TThread::Self() )
gClient->ProcessEventsFor(GetTab());
}
//______________________________________________________________________________
Int_t EGViewer::NextTab() const {
//
// Switch to the next tab
//
if ( !GetTab()->GetNumberOfTabs() )
return -1;
Int_t n = GetTab()->GetCurrent();
if ( ++n == GetTab()->GetNumberOfTabs() ) n=0;
SelectTab(n);
// GetTab()->SetTab(n);
// fTabCombo->Select(n);
return n;
}
//______________________________________________________________________________
Int_t EGViewer::PrevTab() const {
//
// Switch to the next tab
//
if ( !GetTab()->GetNumberOfTabs() )
return -1;
Int_t n = GetTab()->GetCurrent();
if ( --n == -1 ) n =GetTab()->GetNumberOfTabs()-1;
SelectTab(n);
return n;
}
//______________________________________________________________________________
void EGViewer::ShowTabList( Bool_t show) {
//
// Shows Tab Combo box
//
UInt_t w = GetWidth();
UInt_t e = fTabListFrame->GetWidth();
UInt_t h = GetHeight();
if ( show ) {
fViewMenu->CheckEntry( kViewCombo );
fMenuFrame->ShowFrame(fTabCombo);
fMainFrame->ShowFrame(fTabListFrame);
w += e;
} else {
fViewMenu->UnCheckEntry( kViewCombo );
fMenuFrame->HideFrame(fTabCombo);
fMainFrame->HideFrame(fTabListFrame);
w -= e;
}
Resize(w,h);
}
//______________________________________________________________________________
void EGViewer::ToggleTabList() {
//
// Toggles Tab Combo box.
//
ShowTabList( !fViewMenu->IsEntryChecked( kViewCombo ) );
}
//______________________________________________________________________________
Bool_t EGViewer::HandleEvent(Event_t* event) {
return TGFrame::HandleEvent(event);
}
//______________________________________________________________________________
Bool_t EGViewer::HandleKey(Event_t* event) {
//
// Handle keybord commands
//
//
#ifdef DEBUG
Printf("Event");
#endif
if ((event->fType == kGKeyPress) && (event->fState & kKeyControlMask)) {
UInt_t keysym;
char str[2];
gVirtualX->LookupString(event, str, sizeof(str), keysym);
switch ( keysym ) {
case kKey_Tab:
case kKey_Right:
NextTab();
return kTRUE;
case kKey_Left:
PrevTab();
return kTRUE;
}
}
return TGMainFrame::HandleKey(event);
}
//______________________________________________________________________________
Bool_t EGViewer::ProcessMessage(Long_t msg, Long_t mp1, Long_t mp2 ) {
//
// Process the messages from the GUI
//
// Can be found in WidgetMessageTypes.h
#ifdef DEBUG
//////cout << "Msg: " << GET_MSG(msg) << " Submsg:" << GET_SUBMSG(msg);
//cout << " Mp1=" << mp1 << " Mp2=" << mp2 << endl;
#endif
switch (GET_MSG(msg))
{
case kC_COMMAND: // 1
return ProcessMessageCommand(GET_SUBMSG(msg), mp1, mp2);
case kC_TEXTVIEW: // 9
return ProcessMessageTextview(GET_SUBMSG(msg), mp1, mp2);
case kC_USER: // 1001
return ProcessMessageUser(GET_SUBMSG(msg), mp1, mp2);
}
#ifdef DEBUG
//cout << "Msg: " << GET_MSG(msg) << " Submsg:" << GET_SUBMSG(msg);
//cout << " Mp1=" << mp1 << " Mp2=" << mp2 << endl;
#endif
return kTRUE;
}
//______________________________________________________________________________
Bool_t EGViewer::ProcessMessageCommand(Long_t submsg, Long_t mp1, Long_t mp2) {
//
//
//
switch (submsg) {
case kCM_MENU: // 1
return ProcessMessageCommandMenu(mp1); // mp2=userdata
case kCM_TAB: // 8
// UpdateTab(GetTab()->GetTabContainer(mp1));
// Printf("kCM_TAB");
SelectTab(mp1);
return kTRUE;
case kCM_COMBOBOX: // 7
if (mp1==kW_COMBO_TABS)
SelectTab(mp2);
return kTRUE;
case kCM_LISTBOX: // 7
if (mp1==kW_LIST_TABS)
SelectTab(mp2);
return kTRUE;
}
return kTRUE;
}
//______________________________________________________________________________
Bool_t EGViewer::ProcessMessageCommandMenu(Long_t mp1) {
//
// Menu messages
//
switch (mp1) {
case kFileSaveAs:
{
TGFileInfo fi;
fi.fFileTypes = gSaveAsTypes;
fi.fFileTypeIdx = 0;
fi.fOverwrite = kFALSE;
new TGFileDialog(gClient->GetRoot(), 0, kFDSave, &fi);
if ( fi.fFilename ) {
TString name = fi.fFilename;
if ( name.EndsWith(".ps")) SaveAsPS(name);
if ( name.EndsWith(".pdf")) SaveAsPDF(name);
if ( name.EndsWith(".root")) SaveAsRoot(name);
}
}
break;
case kFileSaveAsPS:
SaveAsPS();
break;
case kFileSaveAsPDF:
SaveAsPDF();
break;
case kFileSaveAsRoot:
SaveAsRoot();
break;
case kFileCloseViewer:
SendCloseMessage();
break;
case kFileExit:
gApplication->Terminate(0);
break;
case kViewEditor:
ToggleEditor();
break;
case kViewCombo:
ToggleTabList();
break;
case kViewX3D:
gPad->GetViewer3D("x3d");
break;
case kViewOpenGL:
gPad->GetViewer3D("ogl");
break;
case kTabClonePad:
if ( IsPadLookup() )
SetPadLookup(kFALSE);
else
SetPadLookup(kTRUE);
break;
case kOptionStatistics:
if (gStyle->GetOptStat()) {
gStyle->SetOptStat(0);
delete gPad->FindObject("stats");
fOptionMenu->UnCheckEntry(kOptionStatistics);
} else {
gStyle->SetOptStat(1);
fOptionMenu->CheckEntry(kOptionStatistics);
}
gPad->Modified();
gPad->Update();
break;
case kOptionHistTitle:
if (gStyle->GetOptTitle()) {
gStyle->SetOptTitle(0);
delete gPad->FindObject("title");
fOptionMenu->UnCheckEntry(kOptionHistTitle);
} else {
gStyle->SetOptTitle(1);
fOptionMenu->CheckEntry(kOptionHistTitle);
}
gPad->Modified();
gPad->Update();
break;
case kOptionFitParams:
if (gStyle->GetOptFit()) {
gStyle->SetOptFit(0);
fOptionMenu->UnCheckEntry(kOptionFitParams);
} else {
gStyle->SetOptFit(1);
fOptionMenu->CheckEntry(kOptionFitParams);
}
gPad->Modified();
gPad->Update();
break;
case kOptionCanEdit:
if (gROOT->GetEditHistograms()) {
gROOT->SetEditHistograms(kFALSE);
fOptionMenu->UnCheckEntry(kOptionCanEdit);
} else {
gROOT->SetEditHistograms(kTRUE);
fOptionMenu->CheckEntry(kOptionCanEdit);
}
break;
case kSizeA4:
Resize(640,A4Height(640));
break;
case kSize640:
Resize(640,480);
break;
case kSize800:
Resize(800,600);
break;
case kSize960:
Resize(960,720);
break;
case kSize1024:
Resize(1024,768);
break;
case kSize1280:
Resize(1280,1024);
break;
}
return kTRUE;
}
//______________________________________________________________________________
Bool_t EGViewer::ProcessMessageTextview(Long_t submsg, Long_t mp1, Long_t mp2) {
return kTRUE;
}
//______________________________________________________________________________
Bool_t EGViewer::ProcessMessageUser(Long_t submsg, Long_t mp1, Long_t mp2) {
return kTRUE;
}
//______________________________________________________________________________
TRootEmbeddedCanvas *EGViewer::GetEmbeddedCanvas(TGCompositeFrame *cf) const {
//
// Takes a TGCompositeFrame as argument. Searches for the first
// TRootEmbeddedCanvas which is contained by it and returns a pointer
// to the corresponding TCanvas. If it isn't found NULL is returned.
//
TIter next(cf->GetList());
TGFrameElement *f;
while ((f=(TGFrameElement*)next()))
if (f->fFrame->InheritsFrom(TRootEmbeddedCanvas::Class()))
return (TRootEmbeddedCanvas*)f->fFrame;
return NULL;
}
//______________________________________________________________________________
TCanvas* EGViewer::CurrentCanvas() const {
//
// Returns the canvas in the selected tab, otherwise 0
//
return FindCanvasByTab(GetTab()->GetCurrent());
}
//______________________________________________________________________________
TCanvas* EGViewer::FindCanvasByTab(int i) const {
//
// Returns GetCanvas of the i-th Tab.
//
// if (gROOT->IsBatch())
// return (TCanvas*)fBatch->At(i-1);
if (i<0 || i>=GetTab()->GetNumberOfTabs())
{
return NULL;
}
return FindCanvasByTab(GetTab()->GetTabContainer(i));
}
//______________________________________________________________________________
TCanvas* EGViewer::FindCanvasByTab(TGCompositeFrame *f) const {
//
// Takes a TGCompositeFrame as argument. Searches for the first
// TRootEmbeddedCanvas which is contained by it and returns a pointer
// to the corresponding TCanvas. If it isn't found NULL is returned.
//
TRootEmbeddedCanvas *ec = GetEmbeddedCanvas(f);
return ec ? ec->GetCanvas() : NULL;
}
//______________________________________________________________________________
TCanvas* EGViewer::FindCanvas(const char* name) const {
//if (gROOT->IsBatch())
// return (TCanvas*)fBatch->FindObject(name);
/*
TGFrameElement *f;
TIter next(GetTab()->GetList());
while ((f=(TGFrameElement*)next()))
{
TObject *frame = f->fFrame;
if (!frame->InheritsFrom(TGTabElement::Class()))
continue;
TGTabElement *tab = (TGTabElement*)frame;
if (tab->GetString()==name)
break;
}
// Search for the next TGCompositeFrame in the list
while ((f=(TGFrameElement*)next()))
{
Printf("%s",f->GetName());
TObject *frame = f->fFrame;
if (frame->InheritsFrom(TGCompositeFrame::Class()))
return FindCanvasByTab((TGCompositeFrame*)frame);
}
return NULL;
*/
return (TCanvas*)fCanvases->FindObject(name);
}
//______________________________________________________________________________
void EGViewer::RemoveTab( const char* name ) {
//
// Find and remove the tab with name
//
Int_t count(0);
TGFrameElement *f;
TIter next(GetTab()->GetList());
while ((f=(TGFrameElement*)next()))
{
TGTabElement *tab = dynamic_cast<TGTabElement*>(f->fFrame);
if ( tab ) {
if ( (*tab->GetText()) == name ) break;
count++;
}
}
if ( count == GetTab()->GetNumberOfTabs()) return;
RemoveTab(count);
}
//______________________________________________________________________________
void EGViewer::RemoveTabs() {
//
// Find the tab with name
//
while(GetTab()->GetNumberOfTabs())
RemoveTab(0);
}
//______________________________________________________________________________
void EGViewer::SetStatusText(const char *txt, Int_t partidx) {
//
// Set text in status bar.
//
fStatusBar->SetText(txt, partidx);
if ( !TThread::Self() )
gClient->ProcessEventsFor(fStatusBar);
}
//______________________________________________________________________________
void EGViewer::SetStatusText(const char *txt, Int_t partidx) const {
//
// Const version of SetStatusText
//
((EGViewer*)this)->SetStatusText(txt,partidx);
}
//______________________________________________________________________________
void EGViewer::UpdateTab(TGCompositeFrame *f) {
//
// Update a canvas in a tab, takes the corresponding TGCompositeFrame
// as an argument. This is necessary, because not all functions
// changing the contents of a canvas or pad can call SetModified()
// for the corresponding tab. If this is not called correctly the
// tab won't be updated calling TCanvas::Update(). So we simply
// redraw it by our own (instead we could recursively call
// TPad::Modified() for everything contained by the TCanvas and
// call TCanvas::Update() afterwards)
//
if (!f)
return;
TCanvas *c=FindCanvasByTab(f);
if (!c)
return;
//
// If we are in a multithreaded environment (gThreadXAR) we
// have to make sure, that thus function is called from
// the main thread.
//
if (gThreadXAR)
{
// Tell the X-Requester how to call this method
TString str = Form("%d", (ULong_t)f);
TMethodCall call(IsA(), "UpdateTab", "NULL");
void *arr[4] = { NULL, &call, this, (void*)(const char*)str };
// If this is not the main thread return
if (((*gThreadXAR)("METH", 4, arr, NULL)))
return;
}
//
// Secure calls to update the tabs against itself, at least
// c->Paint() or c->Flush() may crash X (bad drawable).
// This makes sure, that a X call is not interuppted by
// another X-call which was started from an gui interrrupt
// in the same thread
//
if (fMutex->TryLock())
return;
if (!c->IsBatch())
c->FeedbackMode(kFALSE); // Goto double buffer mode
//
// Doing this ourself gives us the possibility to repaint
// the canvas in any case (Paint() instead of PaintModified())
//
c->Paint(); // Repaint all pads
c->Flush(); // Copy all pad pixmaps to the screen
fMutex->UnLock();
}
//______________________________________________________________________________
Bool_t EGViewer::CloneToCanvas(TVirtualPad* pad) {
//
//
//
if (!pad) return kFALSE;
TCanvas *nc = new TCanvas("c_clone_canvas",pad->GetTitle());
DrawClonePad(nc,pad);
return kTRUE;
}
//______________________________________________________________________________
void EGViewer::AddPadToClean(TVirtualPad* pad) const {
//
//
//
TListIter next(pad->GetListOfPrimitives());
while( TObject *obj = next()) {
obj->SetBit(kCanDelete|kMustCleanup);
if ( dynamic_cast<TVirtualPad*>(obj) )
AddPadToClean((TVirtualPad*)obj);
}
}
//______________________________________________________________________________
void EGViewer::DrawClonePad(TVirtualPad *newp, TVirtualPad *oldp) const
{
if (!newp || !oldp)
return;
TVirtualPad* savepad = gPad;
const Bool_t store = TH1::AddDirectoryStatus();
TH1::AddDirectory(kFALSE);
// if ( dynamic_cast<TPad*>(newp) )
// gROOT->GetListOfCleanups()->Add(newp);
newp->cd();
newp->Range(oldp->GetUxmin(),oldp->GetUymin(),oldp->GetUxmax(),oldp->GetUymax());
oldp->TAttFill::Copy(*newp);
oldp->TAttLine::Copy(*newp);
oldp->TAttPad::Copy(*newp);
newp->SetLogx(oldp->GetLogx());
newp->SetLogy(oldp->GetLogy());
newp->SetLogz(oldp->GetLogz());
newp->SetTickx(oldp->GetTickx());
newp->SetTicky(oldp->GetTicky());
newp->SetGridx(oldp->GetGridx());
newp->SetGridy(oldp->GetGridy());
newp->SetBorderSize(oldp->GetBorderSize());
newp->SetBorderMode(oldp->GetBorderMode());
TListIter next(oldp->GetListOfPrimitives());
TObject *newobj;
while( TObject *obj = next()) {
newobj = obj->Clone();
if (!newobj) continue;
// the following lines are the same as in DrawClonePad
// Clone also important bits (FIXME: Is this correct)
newobj->SetBit(obj->TestBits(kCannotPick|kNoContextMenu));
// Clone also important bits (FIXME: Is this correct)
newobj->SetBit(kCanDelete|kMustCleanup);
// FIXME: This is a workaround for the problem with the MAstroCatalog in
// MHFalseSource. It doesn't harm. We'll still try to find the reason
if (newobj->IsA()==TPad::Class()) {
gROOT->GetListOfCleanups()->Add(newobj);
AddPadToClean((TVirtualPad*)newobj);
}
newobj->Draw(next.GetOption());
}
newp->Modified();
newp->Update();
TH1::AddDirectory(store);
savepad->cd();
}
//______________________________________________________________________________
void EGViewer::SetPadLookup( Bool_t lookup ) {
fPadLookup = lookup;
if ( fPadLookup ) {
fTabMenu->CheckEntry( kTabClonePad );
} else {
fTabMenu->UnCheckEntry( kTabClonePad );
}
}
//______________________________________________________________________________
void EGViewer::EventInfo(Int_t event, Int_t px, Int_t py, TObject *selected) {
//
// This function is called when the option "Event Status"
// in the canvas menu "Options" is selected.
//
const Int_t kTMAX=256;
static char atext[kTMAX];
TVirtualPad* savepad = gPad;
TCanvas *c = (TCanvas*)gTQSender;
// if (!c) return; delete
if ( IsPadLookup() ) {
TVirtualPad* pad = c->GetSelectedPad();
if ( c->GetEvent() == kButton1Up ) {
CloneToCanvas(pad);
SetPadLookup(kFALSE);
c->FeedbackMode(kFALSE);
}
if ( pad && fOldPad != pad) {
gVirtualX->SetLineWidth(2);
c->FeedbackMode(kTRUE);
// gVirtualX->SetDrawMode(TVirtualX::kCopy);
if ( fOldPad ) {
UInt_t px1old, py1old, px2old, py2old;
px1old = fOldPad->XtoAbsPixel(fOldPad->GetX1());
py1old = fOldPad->YtoAbsPixel(fOldPad->GetY1());
px2old = fOldPad->XtoAbsPixel(fOldPad->GetX2());
py2old = fOldPad->YtoAbsPixel(fOldPad->GetY2());
gVirtualX->DrawBox(px1old-2,py1old-2,px2old+2,py2old+2,TVirtualX::kHollow);
}
UInt_t px1, py1, px2, py2;
px1 = pad->XtoAbsPixel(pad->GetX1());
py1 = pad->YtoAbsPixel(pad->GetY1());
px2 = pad->XtoAbsPixel(pad->GetX2());
py2 = pad->YtoAbsPixel(pad->GetY2());
gVirtualX->DrawBox(px1-2,py1-2,px2+2,py2+2,TVirtualX::kHollow);
// Printf("Box");
}
fOldPad = pad;
sprintf(atext, "Select the pad to Clone");
SetStatusText(atext,2);
return;
}
if (!selected) return;
gPad = c->GetSelectedPad();
SetStatusText(selected->GetName(),0);
if (event == kKeyPress)
sprintf(atext, "%c", (char) px);
else
sprintf(atext, "%d,%d", px, py);
SetStatusText(atext,1);
SetStatusText(selected->GetObjectInfo(px,py),2);
gPad = savepad;
}
//______________________________________________________________________________
void EGViewer::SetPadFillColor(TVirtualPad &p, Int_t col) const {
//
// Set the background color in a canvas
//
TObject *obj;
// See also TPad::UseCurrentStyle
TIter next(p.GetListOfPrimitives());
while ((obj=next()))
{
if (obj->InheritsFrom(TPad::Class()))
SetPadFillColor(*(TPad*)obj, col);
if (obj->InheritsFrom(TFrame::Class()))
((TFrame*)obj)->SetFillColor(col);
}
p.SetFillColor(col);
}
//______________________________________________________________________________
void EGViewer::UpdatePSHeader(const TString &name) const {
//
// Insert the following two lines into the postscript header:
//
// %%DocumentPaperSizes: a4
// %%Orientation: Landscape
//
const TString newstr("%%DocumentPaperSizes: a4n%%Orientation: Landscapen");
ifstream fin(name);
ofstream fout(name+".$$$");
char c;
TString str;
fin >> str >> c; // Read "%!PS-Adobe-2.0n"
fout << str << endl << newstr;
// Doing it in blocks seems not to gain much for small (MB) files
while (fin)
{
fin.read(&c, 1);
fout.write(&c, 1);
}
gSystem->Unlink(name);
gSystem->Rename(name+".$$$", name);
}
////______________________________________________________________________________
//Int_t EGViewer::SaveAsPS( const char* name ) {
// //
// // Save all tabs in a PS File
// //
//
// Int_t npages = fCanvases->GetEntries();
// if ( !npages ) return 0;
//
// if ( !name ) name = GetName();
//
// TString psname(name);
// if ( !psname.EndsWith(".ps") ) psname+=".ps";
//
//
// TVirtualPad* padsave = gPad;
// TVirtualPS* pssave = gVirtualPS;
//
// TPostScript ps(psname, 112);
// ps.SetBit(TPad::kPrintingPS);
// ps.PrintFast(13, "/nan {1} def ");
//
// gVirtualPS = &ps;
//
// // Create a list to delete the canvas clones
// TList l;
// l.SetOwner();
//
// Int_t page = 0 ;
//
// TIter next(fCanvases);
//
// while( TCanvas* c=(TCanvas*)next()) {
// ps.NewPage();
//
// SetStatusText("Printing..",0);
// SetStatusText(Form("Canvas %s on page %d",c->GetTitle(),++page),2);
//
// TCanvas *clone = (TCanvas*)c->Clone();
// SetPadFillColor(*clone, kWhite);
// l.Add(clone);
//
// clone->SetBatch(kTRUE);
// // test
// clone->Size(.9*kA4Width, .9*kA4Height);
//
// ps.Range(0.925*kA4Width,0.90*kA4Height); // A4
//
// clone->Paint();
//
// gPad=clone;
//
// //
// // Create some GUI elements for a page legend
// //
// TLine line;
// //
// // Print overlaying text (NDC = %)
// //
// ps.SetTextColor(kBlack);
// ps.SetTextSize(0.025);
// ps.SetTextFont(62);
// ps.SetTextAlign(11); // left top
// ps.TextNDC(0, 1.015, TString(" ")+clone->GetTitle());
// ps.SetTextAlign(21); // cent top
// ps.TextNDC(0.5, 1.015, "ESAF");
// ps.SetTextAlign(31); // right top
// ps.TextNDC(1, 1.015, Form("Page No.%i (%i) ", page, npages));
// line.PaintLineNDC(0, 1.01, 1, 1.01);
//
// line.PaintLineNDC(0, -0.01, 1, -0.01);
// ps.SetTextAlign(13); // left top
// if ( !fTitle.IsNull() ) ps.TextNDC(0, -0.015, TString(" ")+fTitle);
// ps.SetTextAlign(33); // right top
// ps.TextNDC(1, -0.015, "Comment");
//
// clone->SetBatch(kFALSE);
// }
// gPad=NULL;
// l.Delete();
// ps.Close();
//
// UpdatePSHeader(psname);
//
// gVirtualPS = pssave;
// if (padsave)
// padsave->cd();
//
// SetStatusText(Form("Done (%d pages)",page),0);
// return page;
//
//}
//______________________________________________________________________________
Int_t EGViewer::SaveAsPS( const char* name ) {
//
// Save all tabs in a PDF File.
// FIXME: the behaviour is not well understood, use SaveAsPS instead
//
Int_t npages = fCanvases->GetEntries();
if ( !npages ) return 0;
if ( !name ) name = GetName();
TString psname(name);
if ( !psname.EndsWith(".ps") ) psname+=".ps";
TVirtualPad* padsave = gPad;
TVirtualPS* pssave = gVirtualPS;
// change to the target canvas before the first image
TCanvas* first = ((TCanvas*)fCanvases->First());
first->cd();
TPostScript *ps = new TPostScript;
ps->Range(0.9*kA4Width,0.9*kA4Height);
ps->Open(psname, 112);
ps->SetBit(TPad::kPrintingPS);
gVirtualPS = ps;
// Create a list to delete the canvas clones
Int_t page = 0 ;
TIter next(fCanvases);
while( TCanvas* c=(TCanvas*)next() ) {
// suspend writhing while arranging the canvas
ps->Off();
gPad = 0;
c->cd();
Float_t xmin = 0.03;
Float_t xmax = 0.97;
Float_t ymin = 0.06;
Float_t ymax = 0.94;
SetStatusText("Printing..",0);
SetStatusText(Form("Canvas %s on page %d",c->GetTitle(),++page),2);
TCanvas *clone = new TCanvas("", c->GetTitle());
TPad* newpad = new TPad("backgroud","backgroud",xmin,ymin,xmax,ymax,kWhite,0);
newpad->Draw();
newpad->cd();
TList* oldl = c->GetListOfPrimitives();
TListIter next(oldl);
while( TObject *obj = next()) {
TObject* newobj = obj->Clone();
newobj->SetBit(kCanDelete);
newobj->Draw();
}
clone->Size(kA4Width, kA4Height);
clone->cd();
clone->Modified();
clone->PaintModified();
SetPadFillColor(*clone, kWhite);
ps->Range(0.925*kA4Width,0.925*kA4Height);
ps->NewPage();
// write to file from now.
ps->On();
clone->Paint();
gPad=clone;
//
// Create some GUI elements for a page legend
//
TLine line;
//
// Print overlaying text (NDC = %)
//
ps->SetTextColor(kBlack);
ps->SetTextSize(0.025);
ps->SetTextFont(62);
ps->SetTextAlign(13); // left top
ps->TextNDC(xmin, ymax+0.05, TString(" ")+clone->GetTitle());
ps->SetTextAlign(23); // cent top
ps->TextNDC(0.5, ymax+0.05, "ESAF");
ps->SetTextAlign(33); // right top
ps->TextNDC(xmax, ymax+0.05, Form("Page No.%i (%i) ", page, npages));
line.PaintLineNDC(xmin, ymax+0.01, xmax, ymax+0.01);
line.PaintLineNDC(xmin, ymin-0.01, xmax, ymin-0.01);
ps->SetTextAlign(11); // left top
if ( !fTitle.IsNull() ) ps->TextNDC(xmin, ymin-0.04, TString(" ")+fTitle);
ps->SetTextAlign(31); // right top
ps->TextNDC(xmax, ymin-0.04, "Comment");
delete clone;
}
gPad=NULL;
ps->Close();
delete ps;
UpdatePSHeader(psname);
gVirtualPS = pssave;
if (padsave)
padsave->cd();
SetStatusText(Form("Done (%d pages)",page),0);
return page;
}
//______________________________________________________________________________
Int_t EGViewer::SaveAsPDF( const char* name ) {
//
// Save all tabs in a PDF File.
// FIXME: the behaviour is not well understood, use SaveAsPS instead
//
Int_t npages = fCanvases->GetEntries();
if ( !npages ) return 0;
if ( !name ) name = GetName();
TString pdfname(name);
if ( !pdfname.EndsWith(".pdf") ) pdfname+=".pdf";
TVirtualPad* padsave = gPad;
TVirtualPS* pssave = gVirtualPS;
// change to the target canvas before the first image
TCanvas* first = ((TCanvas*)fCanvases->First());
first->cd();
TPDF *pdf = new TPDF;
pdf->Open(pdfname, 112);
pdf->SetBit(TPad::kPrintingPS);
gVirtualPS = pdf;
// Create a list to delete the canvas clones
Int_t page = 0 ;
TIter next(fCanvases);
while( TCanvas* c=(TCanvas*)next() ) {
// suspend writhing while arranging the canvas
pdf->Off();
gPad = 0;
c->cd();
Float_t xmin = 0.03;
Float_t xmax = 0.97;
Float_t ymin = 0.06;
Float_t ymax = 0.94;
SetStatusText("Printing..",0);
SetStatusText(Form("Canvas %s on page %d",c->GetTitle(),page+1),2);
//______________________________________________________________________________
TCanvas *clone = new TCanvas("", c->GetTitle());
TPad* newpad = new TPad("backgroud","backgroud",xmin,ymin,xmax,ymax,kWhite,0);
newpad->Draw();
newpad->cd();
TList* oldl = c->GetListOfPrimitives();
TListIter next(oldl);
while( TObject *obj = next()) {
TObject* newobj = obj->Clone();
newobj->SetBit(kCanDelete);
newobj->Draw();
}
clone->cd();
SetPadFillColor(*clone, kWhite);
if ( page++ ) {
// use first as template
pdf->NewPage();
}
// write to file from now.
pdf->On();
clone->Paint();
gPad=clone;
//
// Create some GUI elements for a page legend
//
TLine line;
//
// Print overlaying text (NDC = %)
//
pdf->SetTextColor(kBlack);
pdf->SetTextSize(0.025);
pdf->SetTextFont(62);
pdf->SetTextAlign(13); // left top
pdf->TextNDC(xmin, ymax+0.05, TString(" ")+clone->GetTitle());
pdf->SetTextAlign(23); // cent top
pdf->TextNDC(0.5, ymax+0.05, "ESAF");
pdf->SetTextAlign(33); // right top
pdf->TextNDC(xmax, ymax+0.05, Form("Page No.%i (%i) ", page, npages));
line.PaintLineNDC(xmin, ymax+0.01, xmax, ymax+0.01);
line.PaintLineNDC(xmin, ymin-0.01, xmax, ymin-0.01);
pdf->SetTextAlign(11); // left top
if ( !fTitle.IsNull() ) pdf->TextNDC(xmin, ymin-0.04, TString(" ")+fTitle);
pdf->SetTextAlign(31); // right top
pdf->TextNDC(xmax, ymin-0.04, "Comment");
delete clone;
}
gPad=NULL;
pdf->Close();
delete pdf;
gVirtualPS = pssave;
if (padsave)
padsave->cd();
SetStatusText(Form("Done (%d pages)",page),0);
return page;
}
//______________________________________________________________________________
Int_t EGViewer::SaveAsRoot(const char* name) {
//
//
//
Int_t npages = fCanvases->GetEntries();
if ( !npages ) return 0;
if ( !name ) name = GetName();
TString rootname(name);
if ( !rootname.EndsWith(".root") ) rootname+=".root";
TFile f(rootname,"RECREATE");
Write();
f.Close();
SetStatusText(Form("%s saved", rootname.Data()),0);
return fCanvases->GetEntries();
}
//______________________________________________________________________________
Int_t EGViewer::A4Height( Int_t w ) {
Int_t bw = GetWidth()-GetTab()->GetWidth()+4; // border width
Int_t bh = GetHeight()-GetTab()->GetHeight()+GetTab()->GetTabHeight()+4; // canvas height
Int_t cw = w-bw;
Int_t ch = (Int_t)(cw/kA4CanvasWHRatio);
return ch+bh;
}
//______________________________________________________________________________
void EGViewer::ShowProgressBarPosition(Bool_t set, Bool_t percent, const char* format) {
fProgressBar->ShowPosition( set, percent, format);
}
//______________________________________________________________________________
Int_t EGViewer::Write(const char *name, Int_t option, Int_t bufsize) const {
//
//
//
return fCanvases->Write(name ? name : GetName(), kSingleKey);
}
//______________________________________________________________________________
Int_t EGViewer::Read(const char *name) {
//
//
//
TList list;
if ( !gFile )
return 0;
Int_t bytes = list.Read(name);
TIter next(&list);
while( TCanvas* c = dynamic_cast<TCanvas*>(next())) {
if (!c) continue;
TString name = c->GetName();
TString title = c->GetTitle();
TCanvas *nc = AddTab( name, !title.IsNull() ? title : name );
DrawClonePad(nc, c);
}
return bytes;
}
ClassImp(EClusterOfPrimitives)
//______________________________________________________________________________
//
// EClusterOfPrimitives
//
//______________________________________________________________________________
EClusterOfPrimitives::EClusterOfPrimitives() : TList() {
//
// Constructor
//
}
//______________________________________________________________________________
EClusterOfPrimitives::EClusterOfPrimitives( const char* name, const char* title)
: TList(), fName(name), fTitle(title) {
//
// Constructor
//
}
//______________________________________________________________________________
EClusterOfPrimitives::~EClusterOfPrimitives() {
//
// Destructor
//
}
//______________________________________________________________________________
void EClusterOfPrimitives::Draw(Option_t *option) {
//
// Draw all the objects in the list according their sequence
//
TString opt(option);
if ( opt.Contains("paint") ) {
TObject::Draw(opt);
} else {
TObjLink *lnk = FirstLink();
while (lnk) {
lnk->GetObject()->Draw(lnk->GetOption());
lnk = lnk->Next();
}
}
}
//______________________________________________________________________________
void EClusterOfPrimitives::Paint(Option_t *option) {
//
//
//
TObjLink *lnk = FirstLink();
while (lnk) {
lnk->GetObject()->Paint(lnk->GetOption());
lnk = lnk->Next();
}
}
//______________________________________________________________________________
Int_t EClusterOfPrimitives::DistancetoPrimitive(Int_t px, Int_t py) {
//
//
//
Int_t dist = 999999;
TObject* obj = 0;
TObjLink *lnk = LastLink();
while (lnk) {
Int_t newdist = lnk->GetObject()->DistancetoPrimitive(px, py);
if ( newdist < dist ) {
dist = newdist;
obj = lnk->GetObject();
}
lnk = lnk->Prev();
}
// if ( obj ) gPad->SetSelected(obj);
return dist;
}
//______________________________________________________________________________
void EClusterOfPrimitives::ExecuteEvent(Int_t event, Int_t px, Int_t py) {
//
//
//
TObject *obj = Locate(px,py);
if ( obj ) {
Printf("Located %s",obj->GetName());
obj->ExecuteEvent(event,px,py);
}
}
//______________________________________________________________________________
TObject* EClusterOfPrimitives::Locate(Int_t px, Int_t py) const {
//
// Locate the closest object
//
//
TObject *obj = 0;
Int_t dist = 999999;
TObjLink *lnk = FirstLink();
while (lnk) {
Int_t objdist = lnk->GetObject()->DistancetoPrimitive(px, py);
if ( objdist < dist ) {
dist = objdist;
obj = lnk->GetObject();
}
lnk = lnk->Next();
}
return obj;
}
//______________________________________________________________________________
char* EClusterOfPrimitives::GetObjectInfo(Int_t px, Int_t py) const {
//
//
//
TObject *obj = Locate(px,py);
if ( obj ) {
Printf("GetObjectInfo %s",obj->GetName());
return obj->GetObjectInfo(px,py);
}
return "";
}