#include <string.h>
#include <stdlib.h>
#include "Riostream.h"
#include "TROOT.h"
#include "TCanvas.h"
#include "TClass.h"
#include "TStyle.h"
#include "TText.h"
#include "TBox.h"
#include "TCanvasImp.h"
#include "TDialogCanvas.h"
#include "TGuiFactory.h"
#include "TEnv.h"
#include "TError.h"
#include "TContextMenu.h"
#include "TControlBar.h"
#include "TInterpreter.h"
#include "TApplication.h"
#include "TColor.h"
#include "TVirtualPadEditor.h"
#include "TVirtualViewer3D.h"
#include "TPadPainter.h"
#include "TVirtualGL.h"
#include "TVirtualPS.h"
#include "TObjectSpy.h"
#include "TAxis.h"
#include "TView.h"
class TCanvasInit {
public:
TCanvasInit() { TApplication::NeedGraphicsLibs(); }
};
static TCanvasInit gCanvasInit;
Bool_t TCanvas::fgIsFolder = kFALSE;
const Size_t kDefaultCanvasSize = 20;
ClassImpQ(TCanvas)
TCanvas::TCanvas(Bool_t build) : TPad(), fDoubleBuffer(0)
{
fPainter = 0;
fUseGL = gStyle->GetCanvasPreferGL();
if (!build || TClass::IsCallingNew() != TClass::kRealNew) {
Constructor();
} else {
const char *defcanvas = gROOT->GetDefCanvasName();
char *cdef;
TList *lc = (TList*)gROOT->GetListOfCanvases();
if (lc->FindObject(defcanvas))
cdef = StrDup(Form("%s_n%d",defcanvas,lc->GetSize()+1));
else
cdef = StrDup(Form("%s",defcanvas));
Constructor(cdef, cdef, 1);
delete [] cdef;
}
}
void TCanvas::Constructor()
{
if (gThreadXAR) {
void *arr[2];
arr[1] = this;
if ((*gThreadXAR)("CANV", 2, arr, 0)) return;
}
fCanvas = 0;
fCanvasID = -1;
fCanvasImp = 0;
fBatch = kTRUE;
fUpdating = kFALSE;
fContextMenu = 0;
fSelected = 0;
fClickSelected = 0;
fSelectedPad = 0;
fClickSelectedPad = 0;
fPadSave = 0;
SetBit(kAutoExec);
SetBit(kShowEditor);
SetBit(kShowToolBar);
}
TCanvas::TCanvas(const char *name, Int_t ww, Int_t wh, Int_t winid) : TPad(), fDoubleBuffer(0)
{
fPainter = 0;
Init();
fCanvasID = winid;
fWindowTopX = 0;
fWindowTopY = 0;
fWindowWidth = ww;
fWindowHeight = wh;
fCw = ww + 4;
fCh = wh +28;
fBatch = kFALSE;
fUpdating = kFALSE;
fUseGL = gStyle->GetCanvasPreferGL();
if (fUseGL) {
fGLDevice = gGLManager->CreateGLContext(winid);
if (fGLDevice == -1)
fUseGL = kFALSE;
}
CreatePainter();
fCanvasImp = gBatchGuiFactory->CreateCanvasImp(this, name, fCw, fCh);
SetName(name);
Build();
}
TCanvas::TCanvas(const char *name, const char *title, Int_t form) : TPad(), fDoubleBuffer(0)
{
fPainter = 0;
fUseGL = gStyle->GetCanvasPreferGL();
Constructor(name, title, form);
}
void TCanvas::Constructor(const char *name, const char *title, Int_t form)
{
if (gThreadXAR) {
void *arr[6];
static Int_t ww = 500;
static Int_t wh = 500;
arr[1] = this; arr[2] = (void*)name; arr[3] = (void*)title; arr[4] =&ww; arr[5] = &wh;
if ((*gThreadXAR)("CANV", 6, arr, 0)) return;
}
Init();
SetBit(kMenuBar,1);
if (form < 0) {
form = -form;
SetBit(kMenuBar,0);
}
fCanvasID = -1;
TCanvas *old = (TCanvas*)gROOT->GetListOfCanvases()->FindObject(name);
if (old && old->IsOnHeap()) {
Warning("Constructor","Deleting canvas with same name: %s",name);
delete old;
}
if (strlen(name) == 0 || gROOT->IsBatch()) {
fWindowTopX = fWindowTopY = 0;
if (form == 1) {
fWindowWidth = gStyle->GetCanvasDefW();
fWindowHeight = gStyle->GetCanvasDefH();
} else {
fWindowWidth = 500;
fWindowHeight = 500;
}
fCw = fWindowWidth;
fCh = fWindowHeight;
fCanvasImp = gBatchGuiFactory->CreateCanvasImp(this, name, fCw, fCh);
fBatch = kTRUE;
} else {
Float_t cx = gStyle->GetScreenFactor();
if (form < 1 || form > 5) form = 1;
if (form == 1) {
UInt_t uh = UInt_t(cx*gStyle->GetCanvasDefH());
UInt_t uw = UInt_t(cx*gStyle->GetCanvasDefW());
Int_t ux = Int_t(cx*gStyle->GetCanvasDefX());
Int_t uy = Int_t(cx*gStyle->GetCanvasDefY());
fCanvasImp = gGuiFactory->CreateCanvasImp(this, name, ux, uy, uw, uh);
}
fCw = 500;
fCh = 500;
if (form == 2) fCanvasImp = gGuiFactory->CreateCanvasImp(this, name, 20, 20, UInt_t(cx*500), UInt_t(cx*500));
if (form == 3) fCanvasImp = gGuiFactory->CreateCanvasImp(this, name, 30, 30, UInt_t(cx*500), UInt_t(cx*500));
if (form == 4) fCanvasImp = gGuiFactory->CreateCanvasImp(this, name, 40, 40, UInt_t(cx*500), UInt_t(cx*500));
if (form == 5) fCanvasImp = gGuiFactory->CreateCanvasImp(this, name, 50, 50, UInt_t(cx*500), UInt_t(cx*500));
fCanvasImp->ShowMenuBar(TestBit(kMenuBar));
fBatch = kFALSE;
}
CreatePainter();
SetName(name);
SetTitle(title);
Build();
fCanvasImp->Show();
}
TCanvas::TCanvas(const char *name, const char *title, Int_t ww, Int_t wh) : TPad(), fDoubleBuffer(0)
{
fPainter = 0;
fUseGL = gStyle->GetCanvasPreferGL();
Constructor(name, title, ww, wh);
}
void TCanvas::Constructor(const char *name, const char *title, Int_t ww, Int_t wh)
{
if (gThreadXAR) {
void *arr[6];
arr[1] = this; arr[2] = (void*)name; arr[3] = (void*)title; arr[4] =&ww; arr[5] = &wh;
if ((*gThreadXAR)("CANV", 6, arr, 0)) return;
}
Init();
SetBit(kMenuBar,1);
if (ww < 0) {
ww = -ww;
SetBit(kMenuBar,0);
}
fCw = ww;
fCh = wh;
fCanvasID = -1;
TCanvas *old = (TCanvas*)gROOT->GetListOfCanvases()->FindObject(name);
if (old && old->IsOnHeap()) {
Warning("Constructor","Deleting canvas with same name: %s",name);
delete old;
}
if (strlen(name) == 0 || gROOT->IsBatch()) {
fWindowTopX = fWindowTopY = 0;
fWindowWidth = ww;
fWindowHeight = wh;
fCw = ww;
fCh = wh;
fCanvasImp = gBatchGuiFactory->CreateCanvasImp(this, name, fCw, fCh);
fBatch = kTRUE;
} else {
Float_t cx = gStyle->GetScreenFactor();
fCanvasImp = gGuiFactory->CreateCanvasImp(this, name, UInt_t(cx*ww), UInt_t(cx*wh));
fCanvasImp->ShowMenuBar(TestBit(kMenuBar));
fBatch = kFALSE;
}
CreatePainter();
SetName(name);
SetTitle(title);
Build();
fCanvasImp->Show();
}
TCanvas::TCanvas(const char *name, const char *title, Int_t wtopx, Int_t wtopy, Int_t ww, Int_t wh)
: TPad(), fDoubleBuffer(0)
{
fPainter = 0;
fUseGL = gStyle->GetCanvasPreferGL();
Constructor(name, title, wtopx, wtopy, ww, wh);
}
void TCanvas::Constructor(const char *name, const char *title, Int_t wtopx,
Int_t wtopy, Int_t ww, Int_t wh)
{
if (gThreadXAR) {
void *arr[8];
arr[1] = this; arr[2] = (void*)name; arr[3] = (void*)title;
arr[4] = &wtopx; arr[5] = &wtopy; arr[6] = &ww; arr[7] = &wh;
if ((*gThreadXAR)("CANV", 8, arr, 0)) return;
}
Init();
SetBit(kMenuBar,1);
if (wtopx < 0) {
wtopx = -wtopx;
SetBit(kMenuBar,0);
}
fCw = ww;
fCh = wh;
fCanvasID = -1;
TCanvas *old = (TCanvas*)gROOT->GetListOfCanvases()->FindObject(name);
if (old && old->IsOnHeap()) {
Warning("Constructor","Deleting canvas with same name: %s",name);
delete old;
}
if (strlen(name) == 0 || gROOT->IsBatch()) {
fWindowTopX = fWindowTopY = 0;
fWindowWidth = ww;
fWindowHeight = wh;
fCw = ww;
fCh = wh;
fCanvasImp = gBatchGuiFactory->CreateCanvasImp(this, name, fCw, fCh);
fBatch = kTRUE;
} else {
Float_t cx = gStyle->GetScreenFactor();
fCanvasImp = gGuiFactory->CreateCanvasImp(this, name, Int_t(cx*wtopx), Int_t(cx*wtopy), UInt_t(cx*ww), UInt_t(cx*wh));
fCanvasImp->ShowMenuBar(TestBit(kMenuBar));
fBatch = kFALSE;
}
CreatePainter();
SetName(name);
SetTitle(title);
Build();
fCanvasImp->Show();
}
void TCanvas::Init()
{
if (!gApplication)
TApplication::CreateApplication();
fHighLightColor = gEnv->GetValue("Canvas.HighLightColor", kRed);
SetBit(kMoveOpaque, gEnv->GetValue("Canvas.MoveOpaque", 0));
SetBit(kResizeOpaque, gEnv->GetValue("Canvas.ResizeOpaque", 0));
if (gEnv->GetValue("Canvas.ShowEventStatus", kFALSE)) SetBit(kShowEventStatus);
if (gEnv->GetValue("Canvas.ShowToolTips", kFALSE)) SetBit(kShowToolTips);
if (gEnv->GetValue("Canvas.ShowToolBar", kFALSE)) SetBit(kShowToolBar);
if (gEnv->GetValue("Canvas.ShowEditor", kFALSE)) SetBit(kShowEditor);
if (gEnv->GetValue("Canvas.AutoExec", kTRUE)) SetBit(kAutoExec);
fXsizeUser = 0;
fYsizeUser = 0;
fXsizeReal = kDefaultCanvasSize;
fYsizeReal = kDefaultCanvasSize;
fDISPLAY = "$DISPLAY";
fUpdating = kFALSE;
fRetained = kTRUE;
fSelected = 0;
fClickSelected = 0;
fSelectedX = 0;
fSelectedY = 0;
fSelectedPad = 0;
fClickSelectedPad= 0;
fPadSave = 0;
fEvent = -1;
fEventX = -1;
fEventY = -1;
fContextMenu = 0;
}
void TCanvas::Build()
{
if (fCanvasID == -1 && fCanvasImp)
fCanvasID = fCanvasImp->InitWindow();
if (fCanvasID == -1) return;
if (fCw < fCh) fXsizeReal = fYsizeReal*Float_t(fCw)/Float_t(fCh);
else fYsizeReal = fXsizeReal*Float_t(fCh)/Float_t(fCw);
gPad = this;
fCanvas = this;
fMother = (TPad*)gPad;
if (!IsBatch()) {
gVirtualX->SelectWindow(fCanvasID);
gVirtualX->SetFillColor(1);
gVirtualX->SetLineColor(1);
gVirtualX->SetMarkerColor(1);
gVirtualX->SetTextColor(1);
gVirtualX->ClearWindow();
SetDoubleBuffer(1);
fCanvasImp->GetWindowGeometry(fWindowTopX, fWindowTopY,
fWindowWidth, fWindowHeight);
Int_t dum1, dum2;
gVirtualX->GetGeometry(fCanvasID, dum1, dum2, fCw, fCh);
fContextMenu = new TContextMenu("ContextMenu");
} else {
fCw -= 4;
fCh -= 28;
}
gROOT->GetListOfCanvases()->Add(this);
if (!fPrimitives) {
fPrimitives = new TList;
SetFillColor(gStyle->GetCanvasColor());
SetFillStyle(1001);
SetGrid(gStyle->GetPadGridX(),gStyle->GetPadGridY());
SetTicks(gStyle->GetPadTickX(),gStyle->GetPadTickY());
SetLogx(gStyle->GetOptLogx());
SetLogy(gStyle->GetOptLogy());
SetLogz(gStyle->GetOptLogz());
SetBottomMargin(gStyle->GetPadBottomMargin());
SetTopMargin(gStyle->GetPadTopMargin());
SetLeftMargin(gStyle->GetPadLeftMargin());
SetRightMargin(gStyle->GetPadRightMargin());
SetBorderSize(gStyle->GetCanvasBorderSize());
SetBorderMode(gStyle->GetCanvasBorderMode());
fBorderMode=gStyle->GetCanvasBorderMode();
SetPad(0, 0, 1, 1);
Range(0, 0, 1, 1);
fPainter->SelectDrawable(fPixmapID);
PaintBorder(GetFillColor(), kTRUE);
}
if (TestBit(kMenuBar) && fCanvasImp) {
if (TestBit(kShowEventStatus)) fCanvasImp->ShowStatusBar(kTRUE);
if (TestBit(kShowToolBar)) fCanvasImp->ShowToolBar(kTRUE);
if (TestBit(kShowEditor)) fCanvasImp->ShowEditor(kTRUE);
if (TestBit(kShowToolTips)) fCanvasImp->ShowToolTips(kTRUE);
}
}
TCanvas::~TCanvas()
{
Destructor();
}
void TCanvas::Browse(TBrowser *b)
{
Draw();
cd();
if (fgIsFolder) fPrimitives->Browse(b);
}
void TCanvas::Destructor()
{
if (gThreadXAR) {
void *arr[2];
arr[1] = this;
if ((*gThreadXAR)("CDEL", 2, arr, 0)) return;
}
if (!TestBit(kNotDeleted)) return;
if (fContextMenu) { delete fContextMenu; fContextMenu = 0; }
if (!gPad) return;
Close();
delete fPainter;
}
TVirtualPad *TCanvas::cd(Int_t subpadnumber)
{
if (fCanvasID == -1) return 0;
TPad::cd(subpadnumber);
if (!IsBatch()) {
if (!fDoubleBuffer)
gVirtualX->SelectWindow(fCanvasID);
}
return gPad;
}
void TCanvas::Clear(Option_t *option)
{
if (fCanvasID == -1) return;
if ((!gROOT->IsLineProcessing()) && (!gVirtualX->IsCmdThread())) {
gInterpreter->Execute(this, IsA(), "Clear", option);
return;
}
TString opt = option;
opt.ToLower();
if (opt.Contains("d")) {
if (fPrimitives) {
TIter next(fPrimitives);
TObject *obj;
while ((obj=next())) {
obj->Clear(option);
}
}
} else {
TPad::Clear(option);
}
fSelected = 0;
fClickSelected = 0;
fSelectedPad = 0;
fClickSelectedPad = 0;
}
void TCanvas::Cleared(TVirtualPad *pad)
{
Emit("Cleared(TVirtualPad*)", (Long_t)pad);
}
void TCanvas::Closed()
{
Emit("Closed()");
}
void TCanvas::Close(Option_t *option)
{
TPad *padsave = (TPad*)gPad;
TCanvas *cansave = 0;
if (padsave) cansave = (TCanvas*)gPad->GetCanvas();
if (fCanvasID == -1) goto deletepad;
if ((!gROOT->IsLineProcessing()) && (!gVirtualX->IsCmdThread())) {
gInterpreter->Execute(this, IsA(), "Close", option);
return;
}
FeedbackMode(kFALSE);
cd();
TPad::Close(option);
if (!IsBatch()) {
gVirtualX->SelectWindow(fCanvasID);
if (fGLDevice != -1)
gGLManager->DeleteGLContext(fGLDevice);
if (fCanvasImp) fCanvasImp->Close();
}
fCanvasID = -1;
fBatch = kTRUE;
gROOT->GetListOfCanvases()->Remove(this);
SafeDelete(fCanvasImp);
deletepad:
if (cansave == this) {
gPad = (TCanvas *) gROOT->GetListOfCanvases()->First();
} else {
gPad = padsave;
}
Closed();
}
void TCanvas::CopyPixmaps()
{
if (!IsBatch()) {
CopyPixmap();
TPad::CopyPixmaps();
}
}
void TCanvas::Draw(Option_t *)
{
TCanvas *old = (TCanvas*)gROOT->GetListOfCanvases()->FindObject(GetName());
if (old == this) {
Paint();
return;
}
if (old) { gROOT->GetListOfCanvases()->Remove(old); delete old;}
if (fWindowWidth == 0) {
if (fCw !=0) fWindowWidth = fCw+4;
else fWindowWidth = 800;
}
if (fWindowHeight == 0) {
if (fCh !=0) fWindowHeight = fCh+28;
else fWindowHeight = 600;
}
fCanvasImp = gGuiFactory->CreateCanvasImp(this, GetName(), fWindowTopX, fWindowTopY,
fWindowWidth, fWindowHeight);
fCanvasImp->ShowMenuBar(TestBit(kMenuBar));
Build();
ResizePad();
fCanvasImp->Show();
Modified();
}
TObject *TCanvas::DrawClone(Option_t *option) const
{
const char *defcanvas = gROOT->GetDefCanvasName();
char *cdef;
TList *lc = (TList*)gROOT->GetListOfCanvases();
if (lc->FindObject(defcanvas))
cdef = Form("%s_n%d",defcanvas,lc->GetSize()+1);
else
cdef = Form("%s",defcanvas);
TCanvas *newCanvas = (TCanvas*)Clone();
newCanvas->SetName(cdef);
newCanvas->Draw(option);
newCanvas->Update();
return newCanvas;
}
TObject *TCanvas::DrawClonePad()
{
TPad *padsav = (TPad*)gPad;
TPad *selpad = (TPad*)gROOT->GetSelectedPad();
TPad *pad = padsav;
if (pad == this) pad = selpad;
if (padsav == 0 || pad == 0 || pad == this) {
TCanvas *newCanvas = (TCanvas*)DrawClone();
newCanvas->SetWindowSize(GetWindowWidth(),GetWindowHeight());
return newCanvas;
}
if (fCanvasID == -1) {
fCanvasImp = gGuiFactory->CreateCanvasImp(this, GetName(), fWindowTopX, fWindowTopY,
fWindowWidth, fWindowHeight);
fCanvasImp->ShowMenuBar(TestBit(kMenuBar));
fCanvasID = fCanvasImp->InitWindow();
}
this->cd();
TObject *obj, *clone;
pad->Range(fX1,fY1,fX2,fY2);
pad->SetTickx(GetTickx());
pad->SetTicky(GetTicky());
pad->SetGridx(GetGridx());
pad->SetGridy(GetGridy());
pad->SetLogx(GetLogx());
pad->SetLogy(GetLogy());
pad->SetLogz(GetLogz());
pad->SetBorderSize(GetBorderSize());
pad->SetBorderMode(GetBorderMode());
TAttLine::Copy((TAttLine&)*pad);
TAttFill::Copy((TAttFill&)*pad);
TAttPad::Copy((TAttPad&)*pad);
TIter next(GetListOfPrimitives());
while ((obj=next())) {
pad->cd();
clone = obj->Clone();
pad->GetListOfPrimitives()->Add(clone,next.GetOption());
}
pad->ResizePad();
pad->Modified();
pad->Update();
if (padsav) padsav->cd();
return 0;
}
void TCanvas::DrawEventStatus(Int_t event, Int_t px, Int_t py, TObject *selected)
{
const Int_t kTMAX=256;
static char atext[kTMAX];
if (!TestBit(kShowEventStatus) || !selected) return;
if (!fCanvasImp) return;
TVirtualPad* savepad;
savepad = gPad;
gPad = GetSelectedPad();
fCanvasImp->SetStatusText(selected->GetTitle(),0);
fCanvasImp->SetStatusText(selected->GetName(),1);
if (event == kKeyPress)
snprintf(atext, kTMAX, "%c", (char) px);
else
snprintf(atext, kTMAX, "%d,%d", px, py);
fCanvasImp->SetStatusText(atext,2);
fCanvasImp->SetStatusText(selected->GetObjectInfo(px,py),3);
gPad = savepad;
}
void TCanvas::EditorBar()
{
TVirtualPadEditor::GetPadEditor();
}
void TCanvas::EmbedInto(Int_t winid, Int_t ww, Int_t wh)
{
if(fCanvasImp) return;
fCanvasID = winid;
fWindowTopX = 0;
fWindowTopY = 0;
fWindowWidth = ww;
fWindowHeight = wh;
fCw = ww;
fCh = wh;
fBatch = kFALSE;
fUpdating = kFALSE;
fCanvasImp = gBatchGuiFactory->CreateCanvasImp(this, GetName(), fCw, fCh);
Build();
Resize();
}
void TCanvas::EnterLeave(TPad *prevSelPad, TObject *prevSelObj)
{
if (prevSelObj == fSelected) return;
TPad *padsav = (TPad *)gPad;
Int_t sevent = fEvent;
if (prevSelObj) {
gPad = prevSelPad;
prevSelObj->ExecuteEvent(kMouseLeave, fEventX, fEventY);
fEvent = kMouseLeave;
RunAutoExec();
ProcessedEvent(kMouseLeave, fEventX, fEventY, prevSelObj);
}
gPad = fSelectedPad;
if (fSelected) {
fSelected->ExecuteEvent(kMouseEnter, fEventX, fEventY);
fEvent = kMouseEnter;
RunAutoExec();
ProcessedEvent(kMouseEnter, fEventX, fEventY, fSelected);
}
fEvent = sevent;
gPad = padsav;
}
void TCanvas::ExecuteEvent(Int_t event, Int_t px, Int_t py)
{
if (gROOT->GetEditorMode()) {
TPad::ExecuteEvent(event,px,py);
return;
}
switch (event) {
case kMouseMotion:
SetCursor(kCross);
break;
}
}
void TCanvas::FeedbackMode(Bool_t set)
{
if (set) {
SetDoubleBuffer(0);
gVirtualX->SetDrawMode(TVirtualX::kInvert);
} else {
SetDoubleBuffer(1);
gVirtualX->SetDrawMode(TVirtualX::kCopy);
}
}
void TCanvas::Flush()
{
if (fCanvasID == -1) return;
TPad *padsav = (TPad*)gPad;
cd();
if (!IsBatch()) {
if (!UseGL()) {
gVirtualX->SelectWindow(fCanvasID);
gPad = padsav;
CopyPixmaps();
gVirtualX->UpdateWindow(1);
} else {
TVirtualPS *tvps = gVirtualPS;
gVirtualPS = 0;
gGLManager->MakeCurrent(fGLDevice);
fPainter->InitPainter();
Paint();
if (padsav && padsav->GetCanvas() == this) {
padsav->cd();
padsav->HighLight(padsav->GetHighLightColor());
}
fPainter->LockPainter();
gGLManager->Flush(fGLDevice);
gVirtualPS = tvps;
}
}
if (padsav) padsav->cd();
}
void TCanvas::UseCurrentStyle()
{
if ((!gROOT->IsLineProcessing()) && (!gVirtualX->IsCmdThread())) {
gInterpreter->Execute(this, IsA(), "UseCurrentStyle", "");
return;
}
TPad::UseCurrentStyle();
if (gStyle->IsReading()) {
SetFillColor(gStyle->GetCanvasColor());
fBorderSize = gStyle->GetCanvasBorderSize();
fBorderMode = gStyle->GetCanvasBorderMode();
} else {
gStyle->SetCanvasColor(GetFillColor());
gStyle->SetCanvasBorderSize(fBorderSize);
gStyle->SetCanvasBorderMode(fBorderMode);
}
}
Int_t TCanvas::GetWindowTopX()
{
if (fCanvasImp) fCanvasImp->GetWindowGeometry(fWindowTopX, fWindowTopY,
fWindowWidth,fWindowHeight);
return fWindowTopX;
}
Int_t TCanvas::GetWindowTopY()
{
if (fCanvasImp) fCanvasImp->GetWindowGeometry(fWindowTopX, fWindowTopY,
fWindowWidth,fWindowHeight);
return fWindowTopY;
}
void TCanvas::HandleInput(EEventType event, Int_t px, Int_t py)
{
TPad *pad;
TPad *prevSelPad = (TPad*) fSelectedPad;
TObject *prevSelObj = fSelected;
fPadSave = (TPad*)gPad;
cd();
fEvent = event;
fEventX = px;
fEventY = py;
switch (event) {
case kMouseMotion:
pad = Pick(px, py, prevSelObj);
if (!pad) return;
EnterLeave(prevSelPad, prevSelObj);
gPad = pad;
fSelected->ExecuteEvent(event, px, py);
RunAutoExec();
break;
case kMouseEnter:
if (!fDoubleBuffer) FeedbackMode(kTRUE);
break;
case kMouseLeave:
{
TObject *sobj = fSelected;
TPad *spad = fSelectedPad;
fSelected = 0;
fSelectedPad = 0;
EnterLeave(prevSelPad, prevSelObj);
fSelected = sobj;
fSelectedPad = spad;
if (!fDoubleBuffer) FeedbackMode(kFALSE);
}
break;
case kButton1Double:
case kButton1Down:
pad = Pick(px, py, prevSelObj);
if (!pad) return;
gPad = pad;
if (fSelected) {
FeedbackMode(kTRUE);
fSelected->ExecuteEvent(event, px, py);
RunAutoExec();
}
break;
case kButton1Motion:
case kButton1ShiftMotion:
if (fSelected) {
gPad = fSelectedPad;
fSelected->ExecuteEvent(event, px, py);
gVirtualX->Update();
if (!fSelected->InheritsFrom(TAxis::Class())) {
Bool_t resize = kFALSE;
if (fSelected->InheritsFrom(TBox::Class()))
resize = ((TBox*)fSelected)->IsBeingResized();
if (fSelected->InheritsFrom(TVirtualPad::Class()))
resize = ((TVirtualPad*)fSelected)->IsBeingResized();
if ((!resize && TestBit(kMoveOpaque)) || (resize && TestBit(kResizeOpaque))) {
gPad = fPadSave;
Update();
FeedbackMode(kTRUE);
}
}
RunAutoExec();
}
break;
case kButton1Up:
if (fSelected) {
gPad = fSelectedPad;
fSelected->ExecuteEvent(event, px, py);
RunAutoExec();
if (fPadSave)
gPad = fPadSave;
else {
gPad = this;
fPadSave = this;
}
Update();
}
break;
case kButton2Down:
pad = Pick(px, py, prevSelObj);
if (!pad) return;
gPad = pad;
FeedbackMode(kTRUE);
fSelected->Pop();
pad->cd();
if (gDebug)
printf("Current Pad: %s / %s\n", pad->GetName(), pad->GetTitle());
{
TIter next(gROOT->GetListOfCanvases());
TCanvas *tc;
while ((tc = (TCanvas *)next()))
tc->Update();
}
break;
case kButton2Motion:
case kButton2Up:
if (fSelected) {
gPad = fSelectedPad;
fSelected->ExecuteEvent(event, px, py);
RunAutoExec();
}
break;
case kButton2Double:
break;
case kButton3Down:
pad = Pick(px, py, prevSelObj);
if (!pad) return;
if (!fDoubleBuffer) FeedbackMode(kFALSE);
if (fContextMenu && !fSelected->TestBit(kNoContextMenu) &&
!pad->TestBit(kNoContextMenu) && !TestBit(kNoContextMenu))
fContextMenu->Popup(px, py, fSelected, this, pad);
break;
case kButton3Motion:
break;
case kButton3Up:
if (!fDoubleBuffer) FeedbackMode(kTRUE);
break;
case kButton3Double:
break;
case kKeyPress:
if (!fSelectedPad || !fSelected) return;
gPad = fSelectedPad;
fSelected->ExecuteEvent(event, px, py);
RunAutoExec();
break;
case kButton1Shift:
pad = Pick(px, py, prevSelObj);
if (!pad) return;
EnterLeave(prevSelPad, prevSelObj);
gPad = pad;
fSelected->ExecuteEvent(event, px, py);
RunAutoExec();
break;
case kWheelUp:
case kWheelDown:
pad = Pick(px, py, prevSelObj);
if (!pad) return;
gPad = pad;
fSelected->ExecuteEvent(event, px, py);
break;
default:
break;
}
if (fPadSave && event != kButton2Down)
fPadSave->cd();
if (event != kMouseLeave) {
ProcessedEvent(event, px, py, fSelected);
DrawEventStatus(event, px, py, fSelected);
}
}
Bool_t TCanvas::IsFolder() const
{
return fgIsFolder;
}
void TCanvas::ls(Option_t *option) const
{
TROOT::IndentLevel();
cout <<"Canvas Name=" <<GetName()<<" Title="<<GetTitle()<<" Option="<<option<<endl;
TROOT::IncreaseDirLevel();
TPad::ls(option);
TROOT::DecreaseDirLevel();
}
TCanvas *TCanvas::MakeDefCanvas()
{
const char *defcanvas = gROOT->GetDefCanvasName();
char *cdef;
TList *lc = (TList*)gROOT->GetListOfCanvases();
if (lc->FindObject(defcanvas)) {
Int_t n = lc->GetSize() + 1;
cdef = new char[strlen(defcanvas)+15];
do {
strlcpy(cdef,Form("%s_n%d", defcanvas, n++),strlen(defcanvas)+15);
} while (lc->FindObject(cdef));
} else
cdef = StrDup(Form("%s",defcanvas));
TCanvas *c = new TCanvas(cdef, cdef, 1);
::Info("TCanvas::MakeDefCanvas"," created default TCanvas with name %s",cdef);
delete [] cdef;
return c;
}
void TCanvas::MoveOpaque(Int_t set)
{
SetBit(kMoveOpaque,set);
}
void TCanvas::Paint(Option_t *option)
{
if (fCanvas) TPad::Paint(option);
}
TPad *TCanvas::Pick(Int_t px, Int_t py, TObject *prevSelObj)
{
TObjLink *pickobj = 0;
fSelected = 0;
fSelectedOpt = "";
fSelectedPad = 0;
TPad *pad = Pick(px, py, pickobj);
if (!pad) return 0;
if (!pickobj) {
fSelected = pad;
fSelectedOpt = "";
} else {
if (!fSelected) {
fSelected = pickobj->GetObject();
fSelectedOpt = pickobj->GetOption();
}
}
fSelectedPad = pad;
if (fSelected != prevSelObj)
Picked(fSelectedPad, fSelected, fEvent);
if ((fEvent == kButton1Down) || (fEvent == kButton2Down) || (fEvent == kButton3Down)) {
if (fSelected && !fSelected->InheritsFrom(TView::Class())) {
fClickSelected = fSelected;
fClickSelectedPad = fSelectedPad;
Selected(fSelectedPad, fSelected, fEvent);
fSelectedX = px;
fSelectedY = py;
}
}
return pad;
}
void TCanvas::Picked(TPad *pad, TObject *obj, Int_t event)
{
Long_t args[3];
args[0] = (Long_t) pad;
args[1] = (Long_t) obj;
args[2] = event;
Emit("Picked(TPad*,TObject*,Int_t)", args);
}
void TCanvas::Selected(TVirtualPad *pad, TObject *obj, Int_t event)
{
Long_t args[3];
args[0] = (Long_t) pad;
args[1] = (Long_t) obj;
args[2] = event;
Emit("Selected(TVirtualPad*,TObject*,Int_t)", args);
}
void TCanvas::ProcessedEvent(Int_t event, Int_t x, Int_t y, TObject *obj)
{
Long_t args[4];
args[0] = event;
args[1] = x;
args[2] = y;
args[3] = (Long_t) obj;
Emit("ProcessedEvent(Int_t,Int_t,Int_t,TObject*)", args);
}
void TCanvas::Resize(Option_t *)
{
if (fCanvasID == -1) return;
if ((!gROOT->IsLineProcessing()) && (!gVirtualX->IsCmdThread())) {
gInterpreter->Execute(this, IsA(), "Resize", "");
return;
}
TPad *padsav = (TPad*)gPad;
cd();
if (!IsBatch()) {
gVirtualX->SelectWindow(fCanvasID);
gVirtualX->ResizeWindow(fCanvasID);
fCanvasImp->GetWindowGeometry(fWindowTopX, fWindowTopY,
fWindowWidth, fWindowHeight);
Int_t dum1, dum2;
gVirtualX->GetGeometry(fCanvasID, dum1, dum2, fCw, fCh);
}
if (fXsizeUser && fYsizeUser) {
UInt_t nwh = fCh;
UInt_t nww = fCw;
Double_t rxy = fXsizeUser/fYsizeUser;
if (rxy < 1) {
UInt_t twh = UInt_t(Double_t(fCw)/rxy);
if (twh > fCh)
nww = UInt_t(Double_t(fCh)*rxy);
else
nwh = twh;
if (nww > fCw) {
nww = fCw; nwh = twh;
}
if (nwh > fCh) {
nwh = fCh; nww = UInt_t(Double_t(fCh)/rxy);
}
} else {
UInt_t twh = UInt_t(Double_t(fCw)*rxy);
if (twh > fCh)
nwh = UInt_t(Double_t(fCw)/rxy);
else
nww = twh;
if (nww > fCw) {
nww = fCw; nwh = twh;
}
if (nwh > fCh) {
nwh = fCh; nww = UInt_t(Double_t(fCh)*rxy);
}
}
fCw = nww;
fCh = nwh;
}
if (fCw < fCh) {
fYsizeReal = kDefaultCanvasSize;
fXsizeReal = fYsizeReal*Double_t(fCw)/Double_t(fCh);
}
else {
fXsizeReal = kDefaultCanvasSize;
fYsizeReal = fXsizeReal*Double_t(fCh)/Double_t(fCw);
}
TPad::ResizePad();
if (padsav) padsav->cd();
}
void TCanvas::ResizeOpaque(Int_t set)
{
SetBit(kResizeOpaque,set);
}
void TCanvas::RunAutoExec()
{
if (!TestBit(kAutoExec)) return;
if (!gPad) return;
((TPad*)gPad)->AutoExec();
}
void TCanvas::SavePrimitive(ostream &out, Option_t *option )
{
if (gStyle->GetOptFit()) {
out<<" gStyle->SetOptFit(1);"<<endl;
}
if (!gStyle->GetOptStat()) {
out<<" gStyle->SetOptStat(0);"<<endl;
}
if (!gStyle->GetOptTitle()) {
out<<" gStyle->SetOptTitle(0);"<<endl;
}
if (gROOT->GetEditHistograms()) {
out<<" gROOT->SetEditHistograms();"<<endl;
}
if (GetShowEventStatus()) {
out<<" "<<GetName()<<"->ToggleEventStatus();"<<endl;
}
if (GetShowToolTips()) {
out<<" "<<GetName()<<"->ToggleToolTips();"<<endl;
}
if (GetShowToolBar()) {
out<<" "<<GetName()<<"->ToggleToolBar();"<<endl;
}
if (GetHighLightColor() != 5) {
if (GetHighLightColor() > 228) {
TColor::SaveColor(out, GetHighLightColor());
out<<" "<<GetName()<<"->SetHighLightColor(ci);" << endl;
} else
out<<" "<<GetName()<<"->SetHighLightColor("<<GetHighLightColor()<<");"<<endl;
}
cd();
TPad::SavePrimitive(out,option);
}
void TCanvas::SaveSource(const char *filename, Option_t *option)
{
TIter next(gROOT->GetListOfClasses());
TClass *cl;
while((cl = (TClass*)next())) {
cl->ResetBit(TClass::kClassSaved);
}
char quote = '"';
ofstream out;
Int_t lenfile = strlen(filename);
char * fname;
char lcname[10];
const char *cname = GetName();
Bool_t invalid = kFALSE;
if (lenfile) {
fname = (char*)filename;
out.open(fname, ios::out);
} else {
Int_t nch = strlen(cname);
if (nch < 10) {
strlcpy(lcname,cname,10);
for (Int_t k=1;k<=nch;k++) {if (lcname[nch-k] == ' ') lcname[nch-k] = 0;}
if (lcname[0] == 0) {invalid = kTRUE; strlcpy(lcname,"c1",10); nch = 2;}
cname = lcname;
}
fname = new char[nch+3];
strlcpy(fname,cname,nch+3);
strncat(fname,".C",2);
out.open(fname, ios::out);
}
if (!out.good ()) {
Printf("SaveSource cannot open file: %s",fname);
if (!lenfile) delete [] fname;
return;
}
Int_t precision = gEnv->GetValue("Canvas.SavePrecision",7);
out.precision(precision);
TDatime t;
Float_t cx = gStyle->GetScreenFactor();
Int_t topx,topy;
UInt_t w, h;
UInt_t editorWidth = fCanvasImp->GetWindowGeometry(topx,topy,w,h);
w = UInt_t((fWindowWidth - editorWidth)/cx);
h = UInt_t((fWindowHeight)/cx);
topx = GetWindowTopX();
topy = GetWindowTopY();
if (w == 0) {
w = GetWw()+4; h = GetWh()+4;
topx = 1; topy = 1;
}
out <<"{"<<endl;
out <<"//=========Macro generated from canvas: "<<GetName()<<"/"<<GetTitle()<<endl;
out <<"//========= ("<<t.AsString()<<") by ROOT version"<<gROOT->GetVersion()<<endl;
if (gStyle->GetCanvasPreferGL())
out <<endl<<" gStyle->SetCanvasPreferGL(kTRUE);"<<endl<<endl;
if (InheritsFrom(TDialogCanvas::Class())) {
out<<" "<<ClassName()<<" *"<<cname<<" = new "<<ClassName()<<"("<<quote<<GetName()
<<quote<<", "<<quote<<GetTitle()<<quote<<","<<w<<","<<h<<");"<<endl;
} else {
out<<" TCanvas *"<<cname<<" = new TCanvas("<<quote<<GetName()<<quote<<", "<<quote<<GetTitle()
<<quote;
if (!HasMenuBar())
out<<",-"<<topx<<","<<topy<<","<<w<<","<<h<<");"<<endl;
else
out<<","<<topx<<","<<topy<<","<<w<<","<<h<<");"<<endl;
}
if (gStyle->GetOptFit()) {
out<<" gStyle->SetOptFit(1);"<<endl;
}
if (!gStyle->GetOptStat()) {
out<<" gStyle->SetOptStat(0);"<<endl;
}
if (!gStyle->GetOptTitle()) {
out<<" gStyle->SetOptTitle(0);"<<endl;
}
if (gROOT->GetEditHistograms()) {
out<<" gROOT->SetEditHistograms();"<<endl;
}
if (GetShowEventStatus()) {
out<<" "<<GetName()<<"->ToggleEventStatus();"<<endl;
}
if (GetShowToolTips()) {
out<<" "<<GetName()<<"->ToggleToolTips();"<<endl;
}
if (GetHighLightColor() != 5) {
if (GetHighLightColor() > 228) {
TColor::SaveColor(out, GetHighLightColor());
out<<" "<<GetName()<<"->SetHighLightColor(ci);" << endl;
} else
out<<" "<<GetName()<<"->SetHighLightColor("<<GetHighLightColor()<<");"<<endl;
}
cd();
if (invalid) SetName("c1");
TPad::SavePrimitive(out,option);
out<<" "<<GetName()<<"->SetSelected("<<GetName()<<");"<<endl;
if (GetShowToolBar()) {
out<<" "<<GetName()<<"->ToggleToolBar();"<<endl;
}
if (invalid) SetName(" ");
out <<"}"<<endl;
out.close();
Info("SaveSource","C++ Macro file: %s has been generated", fname);
next.Reset();
while((cl = (TClass*)next())) {
cl->ResetBit(TClass::kClassSaved);
}
if (!lenfile) delete [] fname;
}
void TCanvas::SetBatch(Bool_t batch)
{
if (gROOT->IsBatch())
fBatch = kTRUE;
else
fBatch = batch;
}
void TCanvas::SetCanvasSize(UInt_t ww, UInt_t wh)
{
if (fCanvasImp) {
fCanvasImp->SetCanvasSize(ww, wh);
fCw = ww;
fCh = wh;
ResizePad();
}
}
void TCanvas::SetCursor(ECursor cursor)
{
if (IsBatch()) return;
gVirtualX->SetCursor(fCanvasID, cursor);
}
void TCanvas::SetDoubleBuffer(Int_t mode)
{
if (IsBatch()) return;
fDoubleBuffer = mode;
gVirtualX->SetDoubleBuffer(fCanvasID, mode);
if (fDoubleBuffer) {
if (fPixmapID != -1) fPainter->SelectDrawable(fPixmapID);
} else
if (fCanvasID != -1) fPainter->SelectDrawable(fCanvasID);
}
void TCanvas::SetFixedAspectRatio(Bool_t fixed)
{
if (fixed) {
if (!fFixedAspectRatio) {
if (fCh != 0)
fAspectRatio = Double_t(fCw) / fCh;
else {
Error("SetAspectRatio", "cannot fix aspect ratio, height of canvas is 0");
return;
}
fFixedAspectRatio = kTRUE;
}
} else {
fFixedAspectRatio = kFALSE;
fAspectRatio = 0;
}
}
void TCanvas::SetFolder(Bool_t isfolder)
{
fgIsFolder = isfolder;
}
void TCanvas::SetSelected(TObject *obj)
{
fSelected = obj;
if (obj) obj->SetBit(kMustCleanup);
}
void TCanvas::SetTitle(const char *title)
{
fTitle = title;
if (fCanvasImp) fCanvasImp->SetWindowTitle(title);
}
void TCanvas::Size(Float_t xsize, Float_t ysize)
{
fXsizeUser = xsize;
fYsizeUser = ysize;
Resize();
}
void TCanvas::Streamer(TBuffer &b)
{
UInt_t R__s, R__c;
if (b.IsReading()) {
Version_t v = b.ReadVersion(&R__s, &R__c);
gPad = this;
fCanvas = this;
TPad::Streamer(b);
gPad = this;
TObjArray *colors = (TObjArray*)fPrimitives->FindObject("ListOfColors");
if (colors) {
TIter next(colors);
TColor *colold;
while ((colold = (TColor*)next())) {
if (colold) {
Int_t cn = 0;
if (colold) cn = colold->GetNumber();
TColor *colcur = gROOT->GetColor(cn);
if (colcur) {
colcur->SetRGB(colold->GetRed(),colold->GetGreen(),colold->GetBlue());
} else {
colcur = new TColor(cn,colold->GetRed(),
colold->GetGreen(),
colold->GetBlue(),
colold->GetName());
if (!colcur) return;
}
}
}
fPrimitives->Remove(colors);
colors->Delete();
delete colors;
}
fDISPLAY.Streamer(b);
b >> fDoubleBuffer;
b >> fRetained;
b >> fXsizeUser;
b >> fYsizeUser;
b >> fXsizeReal;
b >> fYsizeReal;
fCanvasID = -1;
b >> fWindowTopX;
b >> fWindowTopY;
if (v > 2) {
b >> fWindowWidth;
b >> fWindowHeight;
}
b >> fCw;
b >> fCh;
if (v <= 2) {
fWindowWidth = fCw;
fWindowHeight = fCh;
}
fCatt.Streamer(b);
Bool_t dummy;
b >> dummy; if (dummy) MoveOpaque(1);
b >> dummy; if (dummy) ResizeOpaque(1);
b >> fHighLightColor;
b >> dummy;
if (v < 2) return;
b >> dummy; if (dummy) SetBit(kShowEventStatus);
if (v > 3) {b >> dummy; if (dummy) SetBit(kAutoExec);}
b >> dummy; if (dummy) SetBit(kMenuBar);
fBatch = gROOT->IsBatch();
b.CheckByteCount(R__s, R__c, TCanvas::IsA());
} else {
TObjArray *colors = 0;
if (!b.CheckObject(gROOT->GetListOfColors(),TObjArray::Class())) {
colors = (TObjArray*)gROOT->GetListOfColors();
fPrimitives->Add(colors);
}
R__c = b.WriteVersion(TCanvas::IsA(), kTRUE);
TPad::Streamer(b);
if(colors) fPrimitives->Remove(colors);
fDISPLAY.Streamer(b);
b << fDoubleBuffer;
b << fRetained;
b << fXsizeUser;
b << fYsizeUser;
b << fXsizeReal;
b << fYsizeReal;
UInt_t w = fWindowWidth, h = fWindowHeight;
Int_t topx = fWindowTopX, topy = fWindowTopY;
UInt_t editorWidth = 0;
if(fCanvasImp) editorWidth = fCanvasImp->GetWindowGeometry(topx,topy,w,h);
b << topx;
b << topy;
b << (UInt_t)(w-editorWidth);
b << h;
b << fCw;
b << fCh;
fCatt.Streamer(b);
b << TestBit(kMoveOpaque);
b << TestBit(kResizeOpaque);
b << fHighLightColor;
b << fBatch;
b << TestBit(kShowEventStatus);
b << TestBit(kAutoExec);
b << TestBit(kMenuBar);
b.SetByteCount(R__c, kTRUE);
}
}
void TCanvas::ToggleAutoExec()
{
Bool_t autoExec = TestBit(kAutoExec);
SetBit(kAutoExec,!autoExec);
}
void TCanvas::ToggleEventStatus()
{
Bool_t showEventStatus = !TestBit(kShowEventStatus);
SetBit(kShowEventStatus,showEventStatus);
if (fCanvasImp) fCanvasImp->ShowStatusBar(showEventStatus);
}
void TCanvas::ToggleToolBar()
{
Bool_t showToolBar = !TestBit(kShowToolBar);
SetBit(kShowToolBar,showToolBar);
if (fCanvasImp) fCanvasImp->ShowToolBar(showToolBar);
}
void TCanvas::ToggleEditor()
{
Bool_t showEditor = !TestBit(kShowEditor);
SetBit(kShowEditor,showEditor);
if (fCanvasImp) fCanvasImp->ShowEditor(showEditor);
}
void TCanvas::ToggleToolTips()
{
Bool_t showToolTips = !TestBit(kShowToolTips);
SetBit(kShowToolTips, showToolTips);
if (fCanvasImp) fCanvasImp->ShowToolTips(showToolTips);
}
void TCanvas::Update()
{
if (fUpdating) return;
if (gThreadXAR) {
void *arr[2];
arr[1] = this;
if ((*gThreadXAR)("CUPD", 2, arr, 0)) return;
}
if (!fCanvasImp) return;
if (!gVirtualX->IsCmdThread()) {
gInterpreter->Execute(this, IsA(), "Update", "");
return;
}
fUpdating = kTRUE;
if (!IsBatch()) FeedbackMode(kFALSE);
if (!UseGL())
PaintModified();
Flush();
SetCursor(kCross);
fUpdating = kFALSE;
}
void TCanvas::DisconnectWidget()
{
fCanvasID = 0;
fContextMenu = 0;
}
Bool_t TCanvas::IsGrayscale()
{
return TestBit(kIsGrayscale);
}
void TCanvas::SetGrayscale(Bool_t set )
{
if (IsGrayscale() == set) return;
SetBit(kIsGrayscale, set);
Paint();
}
void TCanvas::CreatePainter()
{
if (!UseGL() || fBatch)
fPainter = new TPadPainter;
else {
fPainter = TVirtualPadPainter::PadPainter("gl");
if (!fPainter) {
Error("CreatePainter", "GL Painter creation failed! Will use default!");
fPainter = new TPadPainter;
fUseGL = kFALSE;
}
}
}
TVirtualPadPainter *TCanvas::GetCanvasPainter()
{
if (!fPainter) CreatePainter();
return fPainter;
}