Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TEveDigitSet.cxx
Go to the documentation of this file.
1 // @(#)root/eve:$Id$
2 // Authors: Matevz Tadel & Alja Mrak-Tadel: 2006, 2007
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2007, 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 #include "TEveDigitSet.h"
13 #include "TEveManager.h"
14 #include "TEveTrans.h"
15 
16 #include "TColor.h"
17 #include "TRefArray.h"
18 
19 
20 /** \class TEveDigitSet
21 \ingroup TEve
22 Base-class for storage of digit collections; provides
23 transformation matrix (TEveTrans), signal to color mapping
24 (TEveRGBAPalette) and visual grouping (TEveFrameBox).
25 
26 Base-class for displaying a digit collection.
27 Provides common services for:
28  - specifying signal / color per digit;
29  - specifying object reference per digit;
30  - controlling palette and thresholds (external object TEveRGBAPalette);
31  - showing a frame around the digits (external object TEveFrameBox);
32  - specifying transformation matrix for the whole collection;
33  by data-member of class TEveTrans.
34 
35 Use method DigitId(TObject* id) to assign additional identification
36 to the last created digit. By calling SetOwnIds(kTRUE) tje
37 digit-set becomes the owner of the assigned objects and deletes
38 them on destruction.
39 Note that TRef is used for referencing the objects and if you
40 instantiate the objects just to pass them to digit-set you should
41 also call TProcessID::Get/SetObjectCount() at the beginning / end
42 of processing of an event. See documentation for class TRef, in
43 particular section 'ObjectNumber'.
44 
45 If you use value-is-color mode and want to use transparency, set
46 the transparency to non-zero value so that GL-renderer will be
47 properly informed.
48 
49 If you want to use single color for all elements call:
50 ~~~ {.cpp}
51  UseSingleColor()
52 ~~~
53 Palette controls will not work in this case.
54 
55 A pointer to a rectangle / box of class TEveFrameBox can be set via
56 ~~~ {.cpp}
57  void SetFrame(TEveFrameBox* b);
58 ~~~
59 A single TEveFrameBox can be shared among several digit-sets (it is
60 reference-counted). The following flags affect how the frame-box will drawn
61 and used for selection and highlight:
62 ~~~ {.cpp}
63  Bool_t fSelectViaFrame;
64  Bool_t fHighlightFrame;
65 ~~~
66 TEveDigitSet is sub-classed from TEveSecondarySelectable -- this means
67 individual digits can be selected. By calling:
68 ~~~ {.cpp}
69  TEveSecondarySelectable::SetAlwaysSecSelect(kTRUE);
70 ~~~
71 one can enforce immediate feedback (highlight, tooltip and select on normal
72 left-mouse click) on given digit-set.
73 
74 See also:
75 ~~~ {.cpp}
76  TEveQuadSet: rectangle, hexagon or line per digit
77  TEveBoxSet a 3D box per digit
78 ~~~
79 */
80 
81 ClassImp(TEveDigitSet);
82 
83 ////////////////////////////////////////////////////////////////////////////////
84 
85 TEveDigitSet::TEveDigitSet(const char* n, const char* t) :
86  TEveElement (fColor),
87  TNamed (n, t),
88 
89  fDigitIds (0),
90  fDefaultValue (kMinInt),
91  fValueIsColor (kFALSE),
92  fSingleColor (kFALSE),
93  fAntiFlick (kTRUE),
94  fOwnIds (kFALSE),
95  fPlex (),
96  fLastDigit (0),
97  fLastIdx (-1),
98 
99  fColor (kWhite),
100  fFrame (0),
101  fPalette (0),
102  fRenderMode (kRM_AsIs),
103  fSelectViaFrame (kFALSE),
104  fHighlightFrame (kFALSE),
105  fDisableLighting(kTRUE),
106  fHistoButtons (kTRUE),
107  fEmitSignals (kFALSE),
108  fCallbackFoo (0),
109  fTooltipCBFoo (0)
110 {
111  // Constructor.
112 
113  fCanEditMainColor = kTRUE;
114  fCanEditMainTransparency = kTRUE;
115  InitMainTrans();
116 }
117 
118 ////////////////////////////////////////////////////////////////////////////////
119 /// Destructor.
120 /// Unreference frame and palette. Destroy referenced objects if they
121 /// are owned by the TEveDigitSet.
122 
123 TEveDigitSet::~TEveDigitSet()
124 {
125  SetFrame(0);
126  SetPalette(0);
127  if (fOwnIds)
128  ReleaseIds();
129  delete fDigitIds;
130 }
131 
132 ////////////////////////////////////////////////////////////////////////////////
133 /// Protected method called whenever a new digit is added.
134 
135 TEveDigitSet::DigitBase_t* TEveDigitSet::NewDigit()
136 {
137  fLastIdx = fPlex.Size();
138  fLastDigit = new (fPlex.NewAtom()) DigitBase_t(fDefaultValue);
139  return fLastDigit;
140 }
141 
142 ////////////////////////////////////////////////////////////////////////////////
143 /// Protected method. Release and delete the referenced objects, the
144 /// ownership is *NOT* checked.
145 
146 void TEveDigitSet::ReleaseIds()
147 {
148  if (fDigitIds)
149  {
150  const Int_t N = fDigitIds->GetSize();
151 
152  for (Int_t i = 0; i < N; ++i)
153  delete fDigitIds->At(i);
154 
155  fDigitIds->Expand(0);
156  }
157 }
158 
159 ////////////////////////////////////////////////////////////////////////////////
160 /// Instruct digit-set to use single color for its digits.
161 /// Call SetMainColor/Transparency to initialize it.
162 
163 void TEveDigitSet::UseSingleColor()
164 {
165  fSingleColor = kTRUE;
166 }
167 
168 ////////////////////////////////////////////////////////////////////////////////
169 /// Override from TEveElement, forward to Frame.
170 
171 void TEveDigitSet::SetMainColor(Color_t color)
172 {
173  if (fSingleColor)
174  {
175  TEveElement::SetMainColor(color);
176  }
177  else if (fFrame)
178  {
179  fFrame->SetFrameColor(color);
180  fFrame->StampBackPtrElements(kCBColorSelection);
181  }
182 }
183 
184 ////////////////////////////////////////////////////////////////////////////////
185 /// Virtual function called when both fSelected is false and
186 /// fImpliedSelected is 0.
187 
188 void TEveDigitSet::UnSelected()
189 {
190  fSelectedSet.clear();
191  TEveElement::UnSelected();
192 }
193 
194 ////////////////////////////////////////////////////////////////////////////////
195 /// Virtual function called when both fHighlighted is false and
196 /// fImpliedHighlighted is 0.
197 
198 void TEveDigitSet::UnHighlighted()
199 {
200  fHighlightedSet.clear();
201  TEveElement::UnHighlighted();
202 }
203 
204 ////////////////////////////////////////////////////////////////////////////////
205 /// Return tooltip for highlighted element if always-sec-select is set.
206 /// Otherwise return the tooltip for this element.
207 
208 TString TEveDigitSet::GetHighlightTooltip()
209 {
210  if (fHighlightedSet.empty()) return "";
211 
212  if (GetAlwaysSecSelect())
213  {
214  if (fTooltipCBFoo)
215  {
216  return (fTooltipCBFoo)(this, *fHighlightedSet.begin());
217  }
218  else if (fDigitIds)
219  {
220  TObject *o = GetId(*fHighlightedSet.begin());
221  if (o)
222  return TString(o->GetName());
223  }
224  return TString::Format("%s; idx=%d", GetElementName(), *fHighlightedSet.begin());
225  }
226  else
227  {
228  return TEveElement::GetHighlightTooltip();
229  }
230 }
231 
232 ////////////////////////////////////////////////////////////////////////////////
233 /// Instruct underlying memory allocator to regroup itself into a
234 /// contiguous memory chunk.
235 
236 void TEveDigitSet::RefitPlex()
237 {
238  fPlex.Refit();
239 }
240 
241 ////////////////////////////////////////////////////////////////////////////////
242 /// Iterate over the digits and determine min and max signal values.
243 
244 void TEveDigitSet::ScanMinMaxValues(Int_t& min, Int_t& max)
245 {
246  if (fValueIsColor || fPlex.Size() == 0)
247  {
248  min = max = 0;
249  return;
250  }
251 
252  min = kMaxInt;
253  max = kMinInt;
254  for (Int_t c=0; c<fPlex.VecSize(); ++c)
255  {
256  Char_t* a = fPlex.Chunk(c);
257  Int_t n = fPlex.NAtoms(c);
258  while (n--)
259  {
260  Int_t v = ((DigitBase_t*)a)->fValue;
261  if (v < min) min = v;
262  if (v > max) max = v;
263  a += fPlex.S();
264  }
265  }
266  if (min == max)
267  --min;
268 }
269 
270 ////////////////////////////////////////////////////////////////////////////////
271 /// Set current digit -- the one that will receive calls to
272 /// DigitValue/Color/Id/UserData() functions.
273 /// Note that various AddXyzz() functions set the current digit to the newly
274 /// added one.
275 
276 void TEveDigitSet::SetCurrentDigit(Int_t idx)
277 {
278  fLastIdx = idx;
279  fLastDigit = GetDigit(idx);
280 }
281 
282 ////////////////////////////////////////////////////////////////////////////////
283 /// Set signal value for the last digit added.
284 
285 void TEveDigitSet::DigitValue(Int_t value)
286 {
287  fLastDigit->fValue = value;
288 }
289 
290 ////////////////////////////////////////////////////////////////////////////////
291 /// Set color for the last digit added.
292 
293 void TEveDigitSet::DigitColor(Color_t ci)
294 {
295  TEveUtil::ColorFromIdx(ci, (UChar_t*) & fLastDigit->fValue, kTRUE);
296 }
297 
298 ////////////////////////////////////////////////////////////////////////////////
299 /// Set color for the last digit added.
300 
301 void TEveDigitSet::DigitColor(Color_t ci, Char_t transparency)
302 {
303  TEveUtil::ColorFromIdx(ci, (UChar_t*) & fLastDigit->fValue, transparency);
304 }
305 
306 ////////////////////////////////////////////////////////////////////////////////
307 /// Set color for the last digit added.
308 
309 void TEveDigitSet::DigitColor(UChar_t r, UChar_t g, UChar_t b, UChar_t a)
310 {
311  UChar_t* x = (UChar_t*) & fLastDigit->fValue;
312  x[0] = r; x[1] = g; x[2] = b; x[3] = a;
313 }
314 
315 ////////////////////////////////////////////////////////////////////////////////
316 /// Set color for the last digit added.
317 
318 void TEveDigitSet::DigitColor(UChar_t* rgba)
319 {
320  UChar_t* x = (UChar_t*) & fLastDigit->fValue;
321  x[0] = rgba[0]; x[1] = rgba[1]; x[2] = rgba[2]; x[3] = rgba[3];
322 }
323 
324 ////////////////////////////////////////////////////////////////////////////////
325 /// Set external object reference for the last digit added.
326 
327 void TEveDigitSet::DigitId(TObject* id)
328 {
329  DigitId(fLastIdx, id);
330 }
331 
332 ////////////////////////////////////////////////////////////////////////////////
333 /// Set user-data for the last digit added.
334 
335 void TEveDigitSet::DigitUserData(void* ud)
336 {
337  fLastDigit->fUserData = ud;
338 }
339 
340 ////////////////////////////////////////////////////////////////////////////////
341 /// Set external object reference for digit n.
342 
343 void TEveDigitSet::DigitId(Int_t n, TObject* id)
344 {
345  if (!fDigitIds)
346  fDigitIds = new TRefArray;
347 
348  if (fOwnIds && n < fDigitIds->GetSize() && fDigitIds->At(n))
349  delete fDigitIds->At(n);
350 
351  fDigitIds->AddAtAndExpand(id, n);
352 }
353 
354 ////////////////////////////////////////////////////////////////////////////////
355 /// Set user-data for digit n.
356 
357 void TEveDigitSet::DigitUserData(Int_t n, void* ud)
358 {
359  GetDigit(n)->fUserData = ud;
360 }
361 
362 ////////////////////////////////////////////////////////////////////////////////
363 /// Return external TObject associated with digit n.
364 
365 TObject* TEveDigitSet::GetId(Int_t n) const
366 {
367  return fDigitIds ? fDigitIds->At(n) : 0;
368 }
369 
370 ////////////////////////////////////////////////////////////////////////////////
371 /// Get user-data associated with digit n.
372 
373 void* TEveDigitSet::GetUserData(Int_t n) const
374 {
375  return GetDigit(n)->fUserData;
376 }
377 
378 ////////////////////////////////////////////////////////////////////////////////
379 /// Paint this object. Only direct rendering is supported.
380 
381 void TEveDigitSet::Paint(Option_t*)
382 {
383  PaintStandard(this);
384 }
385 
386 ////////////////////////////////////////////////////////////////////////////////
387 /// Called from renderer when a digit with index idx is selected.
388 /// This is by-passed when always-secondary-select is active.
389 
390 void TEveDigitSet::DigitSelected(Int_t idx)
391 {
392  DigitBase_t *qb = GetDigit(idx);
393  TObject *obj = GetId(idx);
394 
395  if (fCallbackFoo) {
396  (fCallbackFoo)(this, idx, obj);
397  }
398  if (fEmitSignals) {
399  SecSelected(this, idx);
400  } else {
401  printf("TEveDigitSet::DigitSelected idx=%d, value=%d, obj=0x%lx\n",
402  idx, qb->fValue, (ULong_t)obj);
403  if (obj)
404  obj->Print();
405  }
406 }
407 
408 ////////////////////////////////////////////////////////////////////////////////
409 /// Emit a SecSelected signal.
410 /// This is by-passed when always-secondary-select is active.
411 
412 void TEveDigitSet::SecSelected(TEveDigitSet* qs, Int_t idx)
413 {
414  Long_t args[2];
415  args[0] = (Long_t) qs;
416  args[1] = (Long_t) idx;
417 
418  Emit("SecSelected(TEveDigitSet*, Int_t)", args);
419 }
420 
421 ////////////////////////////////////////////////////////////////////////////////
422 /// Set TEveFrameBox pointer.
423 
424 void TEveDigitSet::SetFrame(TEveFrameBox* b)
425 {
426  if (fFrame == b) return;
427  if (fFrame) fFrame->DecRefCount(this);
428  fFrame = b;
429  if (fFrame) {
430  fFrame->IncRefCount(this);
431  if (!fSingleColor) {
432  SetMainColorPtr(fFrame->PtrFrameColor());
433  }
434  } else {
435  SetMainColorPtr(&fColor);
436  }
437 }
438 
439 ////////////////////////////////////////////////////////////////////////////////
440 /// Set TEveRGBAPalette pointer.
441 
442 void TEveDigitSet::SetPalette(TEveRGBAPalette* p)
443 {
444  if (fPalette == p) return;
445  if (fPalette) fPalette->DecRefCount();
446  fPalette = p;
447  if (fPalette) fPalette->IncRefCount();
448 }
449 
450 ////////////////////////////////////////////////////////////////////////////////
451 /// Make sure the TEveRGBAPalette pointer is not null.
452 /// If it is not set, a new one is instantiated and the range is set
453 /// to current min/max signal values.
454 
455 TEveRGBAPalette* TEveDigitSet::AssertPalette()
456 {
457  if (fPalette == 0) {
458  fPalette = new TEveRGBAPalette;
459  if (!fValueIsColor) {
460  Int_t min, max;
461  ScanMinMaxValues(min, max);
462  fPalette->SetLimits(min, max);
463  fPalette->SetMinMax(min, max);
464  }
465  }
466  return fPalette;
467 }