Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TGraphEditor.cxx
Go to the documentation of this file.
1 // @(#)root/ged:$Id$
2 // Author: Carsten Hof 16/08/04
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2004, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 
13 //////////////////////////////////////////////////////////////////////////
14 // //
15 // TGraphEditor //
16 // //
17 // Implements GUI for graph attributes. //
18 // //
19 // Title': set the title of the graph //
20 // Change the Shape of the graph: //
21 // 'No Line' = " ": just draw unconnected points //
22 // 'Simple Line' = "L":simple poly line between every point is drawn//
23 // 'Smooth Line' = "C":smooth curve is drawn //
24 // 'Bar Chart' = "B": A bar chart is drawn at each point //
25 // 'Fill Area' = "F": A fill area is drawn //
26 // Check box: 'Marker On/Off' Set Marker visible/invisible //
27 // //
28 //////////////////////////////////////////////////////////////////////////
29 //Begin_Html
30 /*
31 <img src="gif/TGraphEditor.gif">
32 */
33 //End_Html
34 
35 #include "TGComboBox.h"
36 #include "TGButtonGroup.h"
37 #include "TGraphEditor.h"
38 #include "TGTextEntry.h"
39 #include "TGToolTip.h"
40 #include "TGLabel.h"
41 #include "TGraph.h"
42 #include "TVirtualPad.h"
43 #include "TGraphErrors.h"
44 
45 ClassImp(TGraphEditor);
46 
47 enum EGraphWid {
48  kShape = 0,
49  kSHAPE_NOLINE,
50  kSHAPE_SMOOTH,
51  kSHAPE_SIMPLE,
52  kSHAPE_BAR,
53  kSHAPE_FILL,
54  kMARKER_ONOFF,
55  kGRAPH_TITLE,
56  kGRAPH_LINE_WIDTH,
57  kGRAPH_LINE_SIDE
58 };
59 
60 //______________________________________________________________________________
61 
62 TGraphEditor::TGraphEditor(const TGWindow *p, Int_t width,
63  Int_t height, UInt_t options, Pixel_t back)
64  : TGedFrame(p, width, height, options | kVerticalFrame, back)
65 {
66  // Constructor of graph editor.
67 
68  fGraph = 0;
69  // TextEntry to change the title
70  MakeTitle("Title");
71 
72  fTitlePrec = 2;
73  fTitle = new TGTextEntry(this, new TGTextBuffer(50), kGRAPH_TITLE);
74  fTitle->Resize(135, fTitle->GetDefaultHeight());
75  fTitle->SetToolTipText("Enter the graph title string");
76  // better take kLHintsLeft and Right - Right is not working at the moment
77  AddFrame(fTitle, new TGLayoutHints(kLHintsLeft, 3, 1, 2, 5));
78 
79  // Radio Buttons to change the draw options of the graph
80  TGCompositeFrame *f2 = new TGCompositeFrame(this, 80, 20, kVerticalFrame);
81  fgr = new TGButtonGroup(f2,3,1,3,5,"Shape");
82  fgr->SetRadioButtonExclusive(kTRUE);
83  fShape = new TGRadioButton(fgr,"No Line",kSHAPE_NOLINE); // no draw option
84  fShape->SetToolTipText("The points are not connected by a line");
85  fShape0 = new TGRadioButton(fgr,"Smooth Line ",kSHAPE_SMOOTH); // option C
86  fShape0->SetToolTipText("Draw a smooth graph curve");
87  fShape1 = new TGRadioButton(fgr,"Simple Line ",kSHAPE_SIMPLE); // option L
88  fShape1->SetToolTipText("Draw a simple poly-line between the graph points");
89  fShape2 = new TGRadioButton(fgr,"Bar Chart",kSHAPE_BAR); // option B
90  fShape2->SetToolTipText("Draw a bar chart at each graph point");
91  fShape3 = new TGRadioButton(fgr,"Fill area",kSHAPE_FILL); // option F
92  fShape3->SetToolTipText("A fill area is drawn");
93 
94  fgr->SetLayoutHints(fShape1lh=new TGLayoutHints(kLHintsLeft, 0,3,0,0), fShape1);
95  fgr->Show();
96  fgr->ChangeOptions(kFitWidth|kChildFrame|kVerticalFrame);
97  f2->AddFrame(fgr, new TGLayoutHints(kLHintsLeft, 4, 0, 0, 0));
98 
99  // CheckBox to activate/deactivate the drawing of the Marker
100  fMarkerOnOff = new TGCheckButton(f2,"Show Marker",kMARKER_ONOFF);
101  fMarkerOnOff->SetToolTipText("Make Marker visible/invisible");
102  f2->AddFrame(fMarkerOnOff, new TGLayoutHints(kLHintsTop, 5, 1, 0, 3));
103  AddFrame(f2, new TGLayoutHints(kLHintsTop, 1, 1, 0, 0));
104 
105  // Exclusion zone parameters
106  MakeTitle("Exclusion Zone");
107  TGCompositeFrame *f3 = new TGCompositeFrame(this, 80, 20, kHorizontalFrame);
108  AddFrame(f3, new TGLayoutHints(kLHintsTop, 1, 1, 5, 0));
109 
110  fExSide = new TGCheckButton(f3,"+-",kGRAPH_LINE_SIDE);
111  fExSide->SetToolTipText("Zone is drawing side");
112  f3->AddFrame(fExSide, new TGLayoutHints(kLHintsTop, 5, 1, 0, 0));
113 
114  fWidthCombo = new TGLineWidthComboBox(f3, kGRAPH_LINE_WIDTH,
115  kHorizontalFrame | kSunkenFrame | kDoubleBorder,
116  GetWhitePixel(), kTRUE);
117  fWidthCombo->Resize(91, 20);
118  f3->AddFrame(fWidthCombo, new TGLayoutHints(kLHintsLeft, 7, 1, 1, 1));
119  fWidthCombo->Associate(f3);
120 }
121 
122 //______________________________________________________________________________
123 
124 TGraphEditor::~TGraphEditor()
125 {
126  // Destructor of graph editor.
127 
128  // children of TGButonGroup are not deleted
129  delete fShape;
130  delete fShape0;
131  delete fShape1;
132  delete fShape2;
133  delete fShape3;
134  delete fShape1lh;
135 }
136 
137 //______________________________________________________________________________
138 
139 void TGraphEditor::ConnectSignals2Slots()
140 {
141  // Connect signals to slots.
142 
143  fTitle->Connect("TextChanged(const char *)","TGraphEditor",this,"DoTitle(const char *)");
144  fgr->Connect("Clicked(Int_t)","TGraphEditor",this,"DoShape()");
145  fMarkerOnOff->Connect("Toggled(Bool_t)","TGraphEditor",this,"DoMarkerOnOff(Bool_t)");
146  fWidthCombo->Connect("Selected(Int_t)", "TGraphEditor", this, "DoGraphLineWidth()");
147  fExSide->Connect("Clicked()","TGraphEditor",this,"DoGraphLineWidth()");
148 
149  fInit = kFALSE; // connect the slots to the signals only once
150 }
151 
152 //______________________________________________________________________________
153 
154 void TGraphEditor::SetModel(TObject* obj)
155 {
156  // Pick up the used values of graph attributes.
157 
158  fGraph = (TGraph *)obj;
159  fAvoidSignal = kTRUE;
160 
161  // set the Title TextEntry
162  const char *text = fGraph->GetTitle();
163  fTitle->SetText(text);
164 
165  TString opt = GetDrawOption();
166  opt.ToUpper();
167  Int_t i=0;
168  Bool_t make=kFALSE;
169  // Remove characters which appear twice in the draw option
170  TString dum = opt;
171  Int_t l = opt.Length()-1;
172  while (i < l) {
173  dum.Remove(dum.First(opt[i]),1);
174  if (dum.Contains(opt[i])){
175  opt.Remove(opt.First(opt[i]),1);
176  l--;
177  i--;
178  make=kTRUE;
179  }
180  i++;
181  }
182  // initialise the RadioButton group which shows the drawoption
183  if (opt.Contains("C")) {
184  fgr->SetButton(kSHAPE_SMOOTH, kTRUE);
185  fDrawShape='C';
186  } else if (opt.Contains("L")) {
187  fgr->SetButton(kSHAPE_SIMPLE, kTRUE);
188  fDrawShape='L';
189  } else if (opt.Contains("B")){
190  fgr->SetButton(kSHAPE_BAR, kTRUE);
191  fDrawShape='B';
192  } else if (opt.Contains("F")){
193  fgr->SetButton(kSHAPE_FILL, kTRUE);
194  fDrawShape='F';
195  } else {
196  fgr->SetButton(kSHAPE_NOLINE, kTRUE);
197  fDrawShape=' ';
198  }
199  if (make) SetDrawOption(opt);
200  // if the draw option is A, P, AP the P option cannot be removed,
201  // we deactivate the CheckBox
202  // also initialising the MarkerOnOff checkbutton (== P option)
203  if (opt=="A" || opt=="AP" || opt=="PA" || opt == "P") {
204  if (!opt.Contains("P"))
205  opt +="P";
206  fMarkerOnOff->SetState(kButtonDisabled);
207  } else if (opt.Contains("P")) {
208  fMarkerOnOff->SetState(kButtonDown);
209  } else fMarkerOnOff->SetState(kButtonUp);
210 
211  // Exclusion zone parameters
212  if (fGraph->GetLineWidth()<0) fExSide->SetState(kButtonDown, kFALSE);
213  else fExSide->SetState(kButtonUp, kFALSE);
214  fWidthCombo->Select(TMath::Abs(Int_t(fGraph->GetLineWidth()/100)), kFALSE);
215 
216  if (fInit) ConnectSignals2Slots();
217  fAvoidSignal = kFALSE;
218 }
219 
220 //______________________________________________________________________________
221 
222 void TGraphEditor::DoTitle(const char *text)
223 {
224  // Slot for setting the graph title.
225 
226  if (fAvoidSignal) return;
227  fGraph->SetTitle(text);
228  Update();
229 }
230 
231 //______________________________________________________________________________
232 
233 void TGraphEditor::DoShape()
234 {
235  // Slot connected to the draw options.
236 
237  if (fAvoidSignal) return;
238  TString opt;
239  if (fGraph->InheritsFrom(TGraphErrors::Class()))
240  opt = fGraph->GetDrawOption();
241  else
242  opt = GetDrawOption();
243 
244  opt.ToUpper();
245  Int_t s = 0;
246  if (fShape->GetState() == kButtonDown) s = kSHAPE_NOLINE;
247  else if (fShape0->GetState() == kButtonDown) s = kSHAPE_SMOOTH;
248  else if (fShape1->GetState() == kButtonDown) s = kSHAPE_SIMPLE;
249  else if (fShape2->GetState() == kButtonDown) s = kSHAPE_BAR;
250  else s = kSHAPE_FILL;
251 
252  switch (s) {
253 
254  // change draw option to No Line:
255  case kSHAPE_NOLINE: {
256  if (opt.Contains(fDrawShape))
257  opt.Remove(opt.First(fDrawShape),1);
258  fDrawShape = ' ';
259  fMarkerOnOff->SetState(kButtonDisabled);
260  break;
261  }
262 
263  // change draw option to Smooth Line (C)
264  case kSHAPE_SMOOTH: {
265  if (fDrawShape == ' ')
266  opt +="C";
267  else if (opt.Contains(fDrawShape))
268  opt.Replace(opt.First(fDrawShape),1,'C');
269  fDrawShape = 'C';
270  break;
271  }
272 
273  // change draw option to Simple Line (L)
274  case kSHAPE_SIMPLE: {
275  if (fDrawShape == ' ')
276  opt +="L";
277  else if (opt.Contains(fDrawShape))
278  opt.Replace(opt.First(fDrawShape),1,'L');
279  fDrawShape='L';
280  break;
281  }
282 
283  // change draw option to Bar Chart (B)
284  case kSHAPE_BAR: {
285  if (fDrawShape == ' ')
286  opt +="B";
287  else if (opt.Contains(fDrawShape))
288  opt.Replace(opt.First(fDrawShape),1,'B');
289  fDrawShape='B';
290  break;
291  }
292 
293  // change draw option to Fill Area (F)
294  case kSHAPE_FILL: {
295  if (fDrawShape == ' ')
296  opt +="F";
297  else if (opt.Contains(fDrawShape))
298  opt.Replace(opt.First(fDrawShape),1,'F');
299  fDrawShape='F';
300  break;
301  }
302  }
303 
304  if (gPad && gPad->GetVirtCanvas())
305  gPad->GetVirtCanvas()->SetCursor(kWatch);
306  gVirtualX->SetCursor(GetId(), gVirtualX->CreateCursor(kWatch));
307 
308  // set/reset the Marker CheckBox
309  if (opt.Contains("P"))
310  fMarkerOnOff->SetState(kButtonDown);
311  else
312  fMarkerOnOff->SetState(kButtonUp);
313  if (opt=="A" || opt=="AP" || opt=="PA" || opt == "P") {
314  if (!opt.Contains("P"))
315  opt +="P";
316  fMarkerOnOff->SetState(kButtonDisabled);
317  }
318 
319  // set/reset the exclusion zone CheckBox
320  if (opt.Contains("L") || opt.Contains("C")) {
321  if (fGraph->GetLineWidth()<0) fExSide->SetState(kButtonDown, kFALSE);
322  else fExSide->SetState(kButtonUp, kFALSE);
323  fWidthCombo->SetEnabled(kTRUE);
324  } else {
325  fExSide->SetState(kButtonDisabled);
326  fWidthCombo->SetEnabled(kFALSE);
327  }
328 
329  SetDrawOption(opt);
330  if (gPad && gPad->GetVirtCanvas())
331  gPad->GetVirtCanvas()->SetCursor(kPointer);
332  gVirtualX->SetCursor(GetId(), gVirtualX->CreateCursor(kPointer));
333 }
334 
335 //______________________________________________________________________________
336 
337 void TGraphEditor::DoMarkerOnOff(Bool_t on)
338 {
339  // Slot for setting markers as visible/invisible.
340 
341  if (fAvoidSignal) return;
342  TString t = GetDrawOption();
343  t.ToUpper();
344 
345  // showing the marker:
346  if (on) {
347  if (!t.Contains("P")) t+="P";
348  fShape->SetState(kButtonEngaged);
349  } else {
350  // remove the marker option P
351  while (t.Contains("P")) t.Remove(t.First("P"),1);
352  fShape->SetState(kButtonDisabled);
353  }
354  SetDrawOption(t);
355 }
356 
357 //______________________________________________________________________________
358 
359 void TGraphEditor::DoGraphLineWidth()
360 {
361  // Slot connected to the graph line width.
362 
363  if (fAvoidSignal) return;
364  Int_t width = fWidthCombo->GetSelected();
365  Int_t lineWidth = TMath::Abs(fGraph->GetLineWidth()%100);
366  Int_t side = 1;
367  if (fExSide->GetState() == kButtonDown) side = -1;
368  fGraph->SetLineWidth(side*(100*width+lineWidth));
369  Update();
370 }
371