/*
<img src="gif/TGraphEditor.gif">
*/
//End_Html
#include "TGComboBox.h"
#include "TGButtonGroup.h"
#include "TGraphEditor.h"
#include "TGTextEntry.h"
#include "TGToolTip.h"
#include "TGLabel.h"
#include "TGraph.h"
#include "TVirtualPad.h"
#include "TGraphErrors.h"
ClassImp(TGraphEditor)
enum EGraphWid {
kShape = 0,
kSHAPE_NOLINE,
kSHAPE_SMOOTH,
kSHAPE_SIMPLE,
kSHAPE_BAR,
kSHAPE_FILL,
kMARKER_ONOFF,
kGRAPH_TITLE,
kGRAPH_LINE_WIDTH,
kGRAPH_LINE_SIDE
};
TGraphEditor::TGraphEditor(const TGWindow *p, Int_t width,
Int_t height, UInt_t options, Pixel_t back)
: TGedFrame(p, width, height, options | kVerticalFrame, back)
{
fGraph = 0;
MakeTitle("Title");
fTitlePrec = 2;
fTitle = new TGTextEntry(this, new TGTextBuffer(50), kGRAPH_TITLE);
fTitle->Resize(135, fTitle->GetDefaultHeight());
fTitle->SetToolTipText("Enter the graph title string");
AddFrame(fTitle, new TGLayoutHints(kLHintsLeft, 3, 1, 2, 5));
TGCompositeFrame *f2 = new TGCompositeFrame(this, 80, 20, kVerticalFrame);
fgr = new TGButtonGroup(f2,3,1,3,5,"Shape");
fgr->SetRadioButtonExclusive(kTRUE);
fShape = new TGRadioButton(fgr,"No Line",kSHAPE_NOLINE);
fShape->SetToolTipText("The points are not connected by a line");
fShape0 = new TGRadioButton(fgr,"Smooth Line ",kSHAPE_SMOOTH);
fShape0->SetToolTipText("Draw a smooth graph curve");
fShape1 = new TGRadioButton(fgr,"Simple Line ",kSHAPE_SIMPLE);
fShape1->SetToolTipText("Draw a simple poly-line between the graph points");
fShape2 = new TGRadioButton(fgr,"Bar Chart",kSHAPE_BAR);
fShape2->SetToolTipText("Draw a bar chart at each graph point");
fShape3 = new TGRadioButton(fgr,"Fill area",kSHAPE_FILL);
fShape3->SetToolTipText("A fill area is drawn");
fgr->SetLayoutHints(fShape1lh=new TGLayoutHints(kLHintsLeft, 0,3,0,0), fShape1);
fgr->Show();
fgr->ChangeOptions(kFitWidth|kChildFrame|kVerticalFrame);
f2->AddFrame(fgr, new TGLayoutHints(kLHintsLeft, 4, 0, 0, 0));
fMarkerOnOff = new TGCheckButton(f2,"Show Marker",kMARKER_ONOFF);
fMarkerOnOff->SetToolTipText("Make Marker visible/invisible");
f2->AddFrame(fMarkerOnOff, new TGLayoutHints(kLHintsTop, 5, 1, 0, 3));
AddFrame(f2, new TGLayoutHints(kLHintsTop, 1, 1, 0, 0));
MakeTitle("Exclusion Zone");
TGCompositeFrame *f3 = new TGCompositeFrame(this, 80, 20, kHorizontalFrame);
AddFrame(f3, new TGLayoutHints(kLHintsTop, 1, 1, 5, 0));
fExSide = new TGCheckButton(f3,"+-",kGRAPH_LINE_SIDE);
fExSide->SetToolTipText("Zone is drawing side");
f3->AddFrame(fExSide, new TGLayoutHints(kLHintsTop, 5, 1, 0, 0));
fWidthCombo = new TGLineWidthComboBox(f3, kGRAPH_LINE_WIDTH,
kHorizontalFrame | kSunkenFrame | kDoubleBorder,
GetWhitePixel(), kTRUE);
fWidthCombo->Resize(91, 20);
f3->AddFrame(fWidthCombo, new TGLayoutHints(kLHintsLeft, 7, 1, 1, 1));
fWidthCombo->Associate(f3);
}
TGraphEditor::~TGraphEditor()
{
delete fShape;
delete fShape0;
delete fShape1;
delete fShape2;
delete fShape3;
delete fShape1lh;
}
void TGraphEditor::ConnectSignals2Slots()
{
fTitle->Connect("TextChanged(const char *)","TGraphEditor",this,"DoTitle(const char *)");
fgr->Connect("Clicked(Int_t)","TGraphEditor",this,"DoShape()");
fMarkerOnOff->Connect("Toggled(Bool_t)","TGraphEditor",this,"DoMarkerOnOff(Bool_t)");
fWidthCombo->Connect("Selected(Int_t)", "TGraphEditor", this, "DoGraphLineWidth()");
fExSide->Connect("Clicked()","TGraphEditor",this,"DoGraphLineWidth()");
fInit = kFALSE;
}
void TGraphEditor::SetModel(TObject* obj)
{
fGraph = (TGraph *)obj;
fAvoidSignal = kTRUE;
const char *text = fGraph->GetTitle();
fTitle->SetText(text);
TString opt = GetDrawOption();
opt.ToUpper();
Int_t i=0;
Bool_t make=kFALSE;
TString dum = opt;
Int_t l = opt.Length()-1;
while (i < l) {
dum.Remove(dum.First(opt[i]),1);
if (dum.Contains(opt[i])){
opt.Remove(opt.First(opt[i]),1);
l--;
i--;
make=kTRUE;
}
i++;
}
if (opt.Contains("C")) {
fgr->SetButton(kSHAPE_SMOOTH, kTRUE);
fDrawShape='C';
} else if (opt.Contains("L")) {
fgr->SetButton(kSHAPE_SIMPLE, kTRUE);
fDrawShape='L';
} else if (opt.Contains("B")){
fgr->SetButton(kSHAPE_BAR, kTRUE);
fDrawShape='B';
} else if (opt.Contains("F")){
fgr->SetButton(kSHAPE_FILL, kTRUE);
fDrawShape='F';
} else {
fgr->SetButton(kSHAPE_NOLINE, kTRUE);
fDrawShape=' ';
}
if (make) SetDrawOption(opt);
if (opt=="A" || opt=="AP" || opt=="PA" || opt == "P") {
if (!opt.Contains("P"))
opt +="P";
fMarkerOnOff->SetState(kButtonDisabled);
} else if (opt.Contains("P")) {
fMarkerOnOff->SetState(kButtonDown);
} else fMarkerOnOff->SetState(kButtonUp);
if (fGraph->GetLineWidth()<0) fExSide->SetState(kButtonDown, kFALSE);
else fExSide->SetState(kButtonUp, kFALSE);
fWidthCombo->Select(TMath::Abs(Int_t(fGraph->GetLineWidth()/100)), kFALSE);
if (fInit) ConnectSignals2Slots();
fAvoidSignal = kFALSE;
}
void TGraphEditor::DoTitle(const char *text)
{
if (fAvoidSignal) return;
fGraph->SetTitle(text);
Update();
}
void TGraphEditor::DoShape()
{
if (fAvoidSignal) return;
TString opt;
if (fGraph->InheritsFrom(TGraphErrors::Class()))
opt = fGraph->GetDrawOption();
else
opt = GetDrawOption();
opt.ToUpper();
Int_t s = 0;
if (fShape->GetState() == kButtonDown) s = kSHAPE_NOLINE;
else if (fShape0->GetState() == kButtonDown) s = kSHAPE_SMOOTH;
else if (fShape1->GetState() == kButtonDown) s = kSHAPE_SIMPLE;
else if (fShape2->GetState() == kButtonDown) s = kSHAPE_BAR;
else s = kSHAPE_FILL;
switch (s) {
case kSHAPE_NOLINE: {
if (opt.Contains(fDrawShape))
opt.Remove(opt.First(fDrawShape),1);
fDrawShape = ' ';
fMarkerOnOff->SetState(kButtonDisabled);
break;
}
case kSHAPE_SMOOTH: {
if (fDrawShape == ' ')
opt +="C";
else if (opt.Contains(fDrawShape))
opt.Replace(opt.First(fDrawShape),1,'C');
fDrawShape = 'C';
break;
}
case kSHAPE_SIMPLE: {
if (fDrawShape == ' ')
opt +="L";
else if (opt.Contains(fDrawShape))
opt.Replace(opt.First(fDrawShape),1,'L');
fDrawShape='L';
break;
}
case kSHAPE_BAR: {
if (fDrawShape == ' ')
opt +="B";
else if (opt.Contains(fDrawShape))
opt.Replace(opt.First(fDrawShape),1,'B');
fDrawShape='B';
break;
}
case kSHAPE_FILL: {
if (fDrawShape == ' ')
opt +="F";
else if (opt.Contains(fDrawShape))
opt.Replace(opt.First(fDrawShape),1,'F');
fDrawShape='F';
break;
}
}
if (gPad) gPad->GetVirtCanvas()->SetCursor(kWatch);
gVirtualX->SetCursor(GetId(), gVirtualX->CreateCursor(kWatch));
if (opt.Contains("P"))
fMarkerOnOff->SetState(kButtonDown);
else
fMarkerOnOff->SetState(kButtonUp);
if (opt=="A" || opt=="AP" || opt=="PA" || opt == "P") {
if (!opt.Contains("P"))
opt +="P";
fMarkerOnOff->SetState(kButtonDisabled);
}
if (opt.Contains("L") || opt.Contains("C")) {
if (fGraph->GetLineWidth()<0) fExSide->SetState(kButtonDown, kFALSE);
else fExSide->SetState(kButtonUp, kFALSE);
fWidthCombo->SetEnabled(kTRUE);
} else {
fExSide->SetState(kButtonDisabled);
fWidthCombo->SetEnabled(kFALSE);
}
SetDrawOption(opt);
if (gPad) gPad->GetVirtCanvas()->SetCursor(kPointer);
gVirtualX->SetCursor(GetId(), gVirtualX->CreateCursor(kPointer));
}
void TGraphEditor::DoMarkerOnOff(Bool_t on)
{
if (fAvoidSignal) return;
TString t = GetDrawOption();
t.ToUpper();
if (on) {
if (!t.Contains("P")) t+="P";
fShape->SetState(kButtonEngaged);
} else {
while (t.Contains("P")) t.Remove(t.First("P"),1);
fShape->SetState(kButtonDisabled);
}
SetDrawOption(t);
}
void TGraphEditor::DoGraphLineWidth()
{
if (fAvoidSignal) return;
Int_t width = fWidthCombo->GetSelected();
Int_t lineWidth = TMath::Abs(fGraph->GetLineWidth()%100);
Int_t side = 1;
if (fExSide->GetState() == kButtonDown) side = -1;
fGraph->SetLineWidth(side*(100*width+lineWidth));
Update();
}