Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TGLViewerEditor.cxx
Go to the documentation of this file.
1 // @(#)root/gl:$Id$
2 // Author: Alja Mrak-Tadel, Matevz Tadel, Timur Pocheptsov 08/03/2006
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2006, 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 <cstring>
13 
14 #include "TGedEditor.h"
15 #include "TGNumberEntry.h"
16 #include "TGButtonGroup.h"
17 #include "TGColorSelect.h"
18 #include "TGTextEntry.h"
19 #include "TVirtualGL.h"
20 #include "TG3DLine.h"
21 #include "TGButton.h"
22 #include "TColor.h"
23 #include "TString.h"
24 #include "TGLabel.h"
25 #include "TClass.h"
26 #include "TGTab.h"
27 #include "TGComboBox.h"
28 #include "TError.h"
29 
30 #include "TGLViewerEditor.h"
31 #include "TGLViewer.h"
32 #include "TGLLightSetEditor.h"
33 #include "TGLClipSetEditor.h"
34 #include "TGLUtil.h"
35 #include "TGLCameraOverlay.h"
36 #include "TGLAutoRotator.h"
37 
38 /** \class TGLViewerEditor
39 \ingroup opengl
40 GUI editor for TGLViewer.
41 */
42 
43 namespace {
44 
45 void SetLabeledNEntryState(TGNumberEntry *entry, Bool_t enabled);
46 
47 }
48 
49 ClassImp(TGLViewerEditor);
50 
51 TGLViewerEditor::TGLViewerEditor(const TGWindow *p, Int_t width, Int_t height, UInt_t options, Pixel_t back) :
52  TGedFrame(p, width, height, options | kVerticalFrame, back),
53  fGuidesFrame(0),
54  fClipFrame(0),
55  fClearColor(0),
56  fIgnoreSizesOnUpdate(0),
57  fResetCamerasOnUpdate(0),
58  fUpdateScene(0),
59  fCameraHome(0),
60  fMaxSceneDrawTimeHQ(0),
61  fMaxSceneDrawTimeLQ(0),
62  fPointSizeScale(0), fLineWidthScale(0),
63  fPointSmooth(0), fLineSmooth(0),
64  fWFLineWidth(0), fOLLineWidth(0),
65 
66  fCameraCenterExt(0),
67  fCaptureCenter(0),
68  fCameraCenterX(0),
69  fCameraCenterY(0),
70  fCameraCenterZ(0),
71  fCaptureAnnotate(),
72  fAxesType(0),
73  fAxesContainer(0),
74  fAxesNone(0),
75  fAxesEdge(0),
76  fAxesOrigin(0),
77  fAxesDepthTest(0),
78  fRefContainer(0),
79  fReferenceOn(0),
80  fReferencePosX(0),
81  fReferencePosY(0),
82  fReferencePosZ(0),
83  fCamContainer(0),
84  fCamMode(0),
85  fCamOverlayOn(0),
86  fClipSet(0),
87  fARotDt(0), fARotWPhi(0), fARotATheta(0), fARotWTheta(0), fARotADolly(0), fARotWDolly(0),
88  fASavImageGUIBaseName(0), fASavImageGUIOutMode(0),
89  fStereoZeroParallax(0), fStereoEyeOffsetFac(0), fStereoFrustumAsymFac(0),
90  fViewer(0),
91  fIsInPad(kTRUE)
92 {
93  // Constructor.
94 
95  CreateStyleTab();
96  CreateGuidesTab();
97  CreateClippingTab();
98  CreateExtrasTab();
99 }
100 
101 //______________________________________________________________________________
102 
103 TGLViewerEditor::~TGLViewerEditor()
104 {
105  // Destructor.
106 
107 }
108 
109 ////////////////////////////////////////////////////////////////////////////////
110 /// Connect signals to slots.
111 
112 void TGLViewerEditor::ConnectSignals2Slots()
113 {
114  fClearColor->Connect("ColorSelected(Pixel_t)", "TGLViewerEditor", this, "DoClearColor(Pixel_t)");
115  fIgnoreSizesOnUpdate->Connect("Toggled(Bool_t)", "TGLViewerEditor", this, "DoIgnoreSizesOnUpdate()");
116  fResetCamerasOnUpdate->Connect("Toggled(Bool_t)", "TGLViewerEditor", this, "DoResetCamerasOnUpdate()");
117  fUpdateScene->Connect("Pressed()", "TGLViewerEditor", this, "DoUpdateScene()");
118  fCameraHome->Connect("Pressed()", "TGLViewerEditor", this, "DoCameraHome()");
119  fMaxSceneDrawTimeHQ->Connect("ValueSet(Long_t)", "TGLViewerEditor", this, "UpdateMaxDrawTimes()");
120  fMaxSceneDrawTimeLQ->Connect("ValueSet(Long_t)", "TGLViewerEditor", this, "UpdateMaxDrawTimes()");
121  fPointSizeScale->Connect("ValueSet(Long_t)", "TGLViewerEditor", this, "UpdatePointLineStuff()");
122  fLineWidthScale->Connect("ValueSet(Long_t)", "TGLViewerEditor", this, "UpdatePointLineStuff()");
123  fPointSmooth->Connect("Clicked()", "TGLViewerEditor", this, "UpdatePointLineStuff()");
124  fLineSmooth ->Connect("Clicked()", "TGLViewerEditor", this, "UpdatePointLineStuff()");
125  fWFLineWidth->Connect("ValueSet(Long_t)", "TGLViewerEditor", this, "UpdatePointLineStuff()");
126  fOLLineWidth->Connect("ValueSet(Long_t)", "TGLViewerEditor", this, "UpdatePointLineStuff()");
127 
128  fCameraCenterExt->Connect("Clicked()", "TGLViewerEditor", this, "DoCameraCenterExt()");
129  fCaptureCenter->Connect("Clicked()", "TGLViewerEditor", this, "DoCaptureCenter()");
130  fDrawCameraCenter->Connect("Clicked()", "TGLViewerEditor", this, "DoDrawCameraCenter()");
131  fCameraCenterX->Connect("ValueSet(Long_t)", "TGLViewerEditor", this, "UpdateCameraCenter()");
132  fCameraCenterY->Connect("ValueSet(Long_t)", "TGLViewerEditor", this, "UpdateCameraCenter()");
133  fCameraCenterZ->Connect("ValueSet(Long_t)", "TGLViewerEditor", this, "UpdateCameraCenter()");
134 
135  fCaptureAnnotate->Connect("Clicked()", "TGLViewerEditor", this, "DoAnnotation()");
136 
137  fAxesContainer->Connect("Clicked(Int_t)", "TGLViewerEditor", this, "UpdateViewerAxes(Int_t)");
138 
139  fReferenceOn->Connect("Clicked()", "TGLViewerEditor", this, "UpdateViewerReference()");
140  fReferencePosX->Connect("ValueSet(Long_t)", "TGLViewerEditor", this, "UpdateViewerReference()");
141  fReferencePosY->Connect("ValueSet(Long_t)", "TGLViewerEditor", this, "UpdateViewerReference()");
142  fReferencePosZ->Connect("ValueSet(Long_t)", "TGLViewerEditor", this, "UpdateViewerReference()");
143 
144  fCamMode->Connect("Selected(Int_t)", "TGLViewerEditor", this, "DoCameraOverlay()");
145  fCamOverlayOn->Connect("Clicked()", "TGLViewerEditor", this, "DoCameraOverlay()");
146 
147  //
148  fRotateSceneOn->Connect("Clicked()", "TGLViewerEditor", this, "SetRotatorMode()");
149 
150  fSceneRotDt->Connect("ValueSet(Long_t)", "TGLViewerEditor", this, "UpdateRotator()");
151  fARotDt ->Connect("ValueSet(Long_t)", "TGLViewerEditor", this, "UpdateRotator()");
152  fARotWPhi ->Connect("ValueSet(Long_t)", "TGLViewerEditor", this, "UpdateRotator()");
153  fARotATheta->Connect("ValueSet(Long_t)", "TGLViewerEditor", this, "UpdateRotator()");
154  fARotWTheta->Connect("ValueSet(Long_t)", "TGLViewerEditor", this, "UpdateRotator()");
155  fARotADolly->Connect("ValueSet(Long_t)", "TGLViewerEditor", this, "UpdateRotator()");
156  fARotWDolly->Connect("ValueSet(Long_t)", "TGLViewerEditor", this, "UpdateRotator()");
157 
158  fASavImageGUIBaseName->Connect("TextChanged(char*", "TGLViewerEditor", this, "DoASavImageGUIBaseName(char*)");
159  fASavImageGUIOutMode->Connect("Clicked(Int_t)", "TGLViewerEditor", this, "DoASavImageGUIOutMode(Int_t)");
160 
161  fStereoZeroParallax ->Connect("ValueSet(Long_t)", "TGLViewerEditor", this, "UpdateStereo()");
162  fStereoEyeOffsetFac ->Connect("ValueSet(Long_t)", "TGLViewerEditor", this, "UpdateStereo()");
163  fStereoFrustumAsymFac->Connect("ValueSet(Long_t)", "TGLViewerEditor", this, "UpdateStereo()");
164  fStereoZeroParallax ->Connect("ValueChanged(Long_t)", "TGLViewerEditor", this, "UpdateStereo()");
165  fStereoEyeOffsetFac ->Connect("ValueChanged(Long_t)", "TGLViewerEditor", this, "UpdateStereo()");
166  fStereoFrustumAsymFac->Connect("ValueChanged(Long_t)", "TGLViewerEditor", this, "UpdateStereo()");
167 
168  fInit = kFALSE;
169 }
170 
171 ////////////////////////////////////////////////////////////////////////////////
172 /// Initiate redraw of the viewer.
173 
174 void TGLViewerEditor::ViewerRedraw()
175 {
176  if (gGLManager && fIsInPad)
177  gGLManager->MarkForDirectCopy(fViewer->GetDev(), kTRUE);
178  fViewer->RequestDraw();
179 }
180 
181 ////////////////////////////////////////////////////////////////////////////////
182 /// Sets model or disables/hides viewer.
183 
184 void TGLViewerEditor::SetModel(TObject* obj)
185 {
186  fViewer = 0;
187 
188  fViewer = static_cast<TGLViewer *>(obj);
189  fIsInPad = (fViewer->GetDev() != -1);
190 
191  SetGuides();
192 
193  if (fInit)
194  ConnectSignals2Slots();
195 
196  fLightSet->SetModel(fViewer->GetLightSet());
197  fClipSet->SetModel(fViewer->GetClipSet());
198 
199  // style tab
200  fClearColor->SetColor(TColor::Number2Pixel(fViewer->RnrCtx().ColorSet().Background().GetColorIndex()), kFALSE);
201  fClearColor->Enable(!fViewer->IsUsingDefaultColorSet());
202  fIgnoreSizesOnUpdate->SetState(fViewer->GetIgnoreSizesOnUpdate() ? kButtonDown : kButtonUp);
203  fResetCamerasOnUpdate->SetState(fViewer->GetResetCamerasOnUpdate() ? kButtonDown : kButtonUp);
204  fMaxSceneDrawTimeHQ->SetNumber(fViewer->GetMaxSceneDrawTimeHQ());
205  fMaxSceneDrawTimeLQ->SetNumber(fViewer->GetMaxSceneDrawTimeLQ());
206  fPointSizeScale->SetNumber(fViewer->GetPointScale());
207  fLineWidthScale->SetNumber(fViewer->GetLineScale ());
208  fPointSmooth->SetState(fViewer->GetSmoothPoints() ? kButtonDown : kButtonUp);
209  fLineSmooth ->SetState(fViewer->GetSmoothLines () ? kButtonDown : kButtonUp);
210  fWFLineWidth->SetNumber(fViewer->WFLineW());
211  fOLLineWidth->SetNumber(fViewer->OLLineW());
212  //camera look at
213  TGLCamera & cam = fViewer->CurrentCamera();
214  fCameraCenterExt->SetDown(cam.GetExternalCenter());
215  fDrawCameraCenter->SetDown(fViewer->GetDrawCameraCenter());
216  Double_t* la = cam.GetCenterVec();
217  fCameraCenterX->SetNumber(la[0]);
218  fCameraCenterY->SetNumber(la[1]);
219  fCameraCenterZ->SetNumber(la[2]);
220  fCameraCenterX->SetState(fCameraCenterExt->IsDown());
221  fCameraCenterY->SetState(fCameraCenterExt->IsDown());
222  fCameraCenterZ->SetState(fCameraCenterExt->IsDown());
223 
224  // push action
225  fCaptureCenter->SetTextColor((fViewer->GetPushAction() == TGLViewer::kPushCamCenter) ? 0xa03060 : 0x000000);
226  fCaptureAnnotate->SetDown( (fViewer->GetPushAction() == TGLViewer::kPushAnnotate), kFALSE);
227 
228  {
229  TGLAutoRotator *r = fViewer->GetAutoRotator();
230 
231  fSceneRotDt->SetNumber(r->GetDeltaPhi());
232  fARotDt ->SetNumber(r->GetDt());
233  fARotWPhi ->SetNumber(r->GetWPhi());
234  fARotATheta->SetNumber(r->GetATheta());
235  fARotWTheta->SetNumber(r->GetWTheta());
236  fARotADolly->SetNumber(r->GetADolly());
237  fARotWDolly->SetNumber(r->GetWDolly());
238 
239  fASavImageGUIBaseName->SetText(r->GetImageGUIBaseName());
240  fASavImageGUIOutMode ->SetButton(r->GetImageGUIOutMode());
241 
242  Bool_t rotate_standard = ! fViewer->GetAutoRotator()->GetRotateScene();
243  fRotateSceneOn->SetState(rotate_standard ? kButtonUp : kButtonDown);
244  SetLabeledNEntryState(fSceneRotDt, ! rotate_standard);
245  SetLabeledNEntryState(fARotDt, rotate_standard);
246  SetLabeledNEntryState(fARotWPhi, rotate_standard);
247  SetLabeledNEntryState(fARotATheta, rotate_standard);
248  SetLabeledNEntryState(fARotWTheta, rotate_standard);
249  SetLabeledNEntryState(fARotADolly, rotate_standard);
250  SetLabeledNEntryState(fARotWDolly, rotate_standard);
251  }
252 
253  if (fViewer->GetStereo())
254  {
255  fStereoZeroParallax ->SetNumber(fViewer->GetStereoZeroParallax());
256  fStereoEyeOffsetFac ->SetNumber(fViewer->GetStereoEyeOffsetFac());
257  fStereoFrustumAsymFac->SetNumber(fViewer->GetStereoFrustumAsymFac());
258  fStereoFrame->MapWindow();
259  }
260  else
261  {
262  fStereoFrame->UnmapWindow();
263  }
264 }
265 
266 ////////////////////////////////////////////////////////////////////////////////
267 /// Clear-color was changed.
268 
269 void TGLViewerEditor::DoClearColor(Pixel_t color)
270 {
271  fViewer->RnrCtx().ColorSet().Background().SetColor(Color_t(TColor::GetColor(color)));
272  ViewerRedraw();
273 }
274 
275 ////////////////////////////////////////////////////////////////////////////////
276 /// ResetCamerasOnUpdate was toggled.
277 
278 void TGLViewerEditor::DoIgnoreSizesOnUpdate()
279 {
280  fViewer->SetIgnoreSizesOnUpdate(fIgnoreSizesOnUpdate->IsOn());
281  if (fIgnoreSizesOnUpdate->IsOn())
282  fViewer->UpdateScene();
283 }
284 
285 ////////////////////////////////////////////////////////////////////////////////
286 /// ResetCamerasOnUpdate was toggled.
287 
288 void TGLViewerEditor::DoResetCamerasOnUpdate()
289 {
290  fViewer->SetResetCamerasOnUpdate(fResetCamerasOnUpdate->IsOn());
291 }
292 
293 ////////////////////////////////////////////////////////////////////////////////
294 /// UpdateScene was clicked.
295 
296 void TGLViewerEditor::DoUpdateScene()
297 {
298  fViewer->UpdateScene();
299 }
300 
301 ////////////////////////////////////////////////////////////////////////////////
302 /// CameraHome was clicked.
303 
304 void TGLViewerEditor::DoCameraHome()
305 {
306  fViewer->ResetCurrentCamera();
307  ViewerRedraw();
308 }
309 
310 ////////////////////////////////////////////////////////////////////////////////
311 /// Slot for fMaxSceneDrawTimeHQ and fMaxSceneDrawTimeLQ.
312 
313 void TGLViewerEditor::UpdateMaxDrawTimes()
314 {
315  fViewer->SetMaxSceneDrawTimeHQ(fMaxSceneDrawTimeHQ->GetNumber());
316  fViewer->SetMaxSceneDrawTimeLQ(fMaxSceneDrawTimeLQ->GetNumber());
317 }
318 
319 ////////////////////////////////////////////////////////////////////////////////
320 /// Slot for point-sizes and line-widths.
321 
322 void TGLViewerEditor::UpdatePointLineStuff()
323 {
324  fViewer->SetPointScale(fPointSizeScale->GetNumber());
325  fViewer->SetLineScale (fLineWidthScale->GetNumber());
326  fViewer->SetSmoothPoints(fPointSmooth->IsDown());
327  fViewer->SetSmoothLines (fLineSmooth->IsDown());
328  fViewer->SetWFLineW(fWFLineWidth->GetNumber());
329  fViewer->SetOLLineW(fOLLineWidth->GetNumber());
330  ViewerRedraw();
331 }
332 
333 ////////////////////////////////////////////////////////////////////////////////
334 /// Update viewer with GUI state.
335 
336 void TGLViewerEditor::DoCameraOverlay()
337 {
338  TGLCameraOverlay* co = fViewer->GetCameraOverlay();
339 
340  if (fViewer->CurrentCamera().IsPerspective())
341  {
342  co->SetShowPerspective(fCamOverlayOn->IsDown());
343  co->SetPerspectiveMode((TGLCameraOverlay::EMode)fCamMode->GetSelected());
344  }
345  else
346  {
347  co->SetShowOrthographic(fCamOverlayOn->IsDown());
348  co->SetOrthographicMode((TGLCameraOverlay::EMode)fCamMode->GetSelected());
349  }
350  ViewerRedraw();
351 }
352 
353 ////////////////////////////////////////////////////////////////////////////////
354 /// Set external camera center.
355 
356 void TGLViewerEditor::DoCameraCenterExt()
357 {
358  TGLCamera& cam = fViewer->CurrentCamera();
359  cam.SetExternalCenter(fCameraCenterExt->IsDown());
360 
361  fCameraCenterX->SetState(fCameraCenterExt->IsDown());
362  fCameraCenterY->SetState(fCameraCenterExt->IsDown());
363  fCameraCenterZ->SetState(fCameraCenterExt->IsDown());
364 
365  ViewerRedraw();
366 }
367 
368 ////////////////////////////////////////////////////////////////////////////////
369 /// Capture camera-center via picking.
370 
371 void TGLViewerEditor::DoCaptureCenter()
372 {
373  fViewer->PickCameraCenter();
374  ViewerRedraw();
375 }
376 
377 ////////////////////////////////////////////////////////////////////////////////
378 /// Draw camera center.
379 
380 void TGLViewerEditor::DoDrawCameraCenter()
381 {
382  fViewer->SetDrawCameraCenter(fDrawCameraCenter->IsDown());
383  ViewerRedraw();
384 }
385 
386 ////////////////////////////////////////////////////////////////////////////////
387 /// Update current camera with GUI state.
388 
389 void TGLViewerEditor::UpdateCameraCenter()
390 {
391  TGLCamera& cam = fViewer->CurrentCamera();
392  cam.SetCenterVec(fCameraCenterX->GetNumber(), fCameraCenterY->GetNumber(), fCameraCenterZ->GetNumber());
393  ViewerRedraw();
394 }
395 
396 ////////////////////////////////////////////////////////////////////////////////
397 /// Create annotation via picking.
398 
399 void TGLViewerEditor::DoAnnotation()
400 {
401  fViewer->PickAnnotate();
402 }
403 
404 ////////////////////////////////////////////////////////////////////////////////
405 /// Update viewer with GUI state.
406 
407 void TGLViewerEditor::UpdateViewerAxes(Int_t id)
408 {
409  if(id < 4)
410  {
411  fAxesType = id -1;
412  for (Int_t i = 1; i < 4; i++) {
413  TGButton * button = fAxesContainer->GetButton(i);
414  if (i == id)
415  button->SetDown(kTRUE);
416  else
417  button->SetDown(kFALSE);
418  }
419  }
420  Bool_t axdt = fAxesContainer->GetButton(4)->IsDown();
421  const Double_t refPos[] = {fReferencePosX->GetNumber(), fReferencePosY->GetNumber(), fReferencePosZ->GetNumber()};
422  fViewer->SetGuideState(fAxesType, axdt, fReferenceOn->IsDown(), refPos);
423  UpdateReferencePosState();
424 }
425 
426 ////////////////////////////////////////////////////////////////////////////////
427 /// Update viewer with GUI state.
428 
429 void TGLViewerEditor::UpdateViewerReference()
430 {
431  const Double_t refPos[] = {fReferencePosX->GetNumber(), fReferencePosY->GetNumber(), fReferencePosZ->GetNumber()};
432  fViewer->SetGuideState(fAxesType, fAxesContainer->GetButton(4)->IsDown(), fReferenceOn->IsDown(), refPos);
433  UpdateReferencePosState();
434 }
435 
436 ////////////////////////////////////////////////////////////////////////////////
437 /// Helper function to create fixed width TGLabel and TGNumberEntry in same row.
438 
439 TGNumberEntry* TGLViewerEditor::MakeLabeledNEntry(TGCompositeFrame* p, const char* name,
440  Int_t labelw,Int_t nd, Int_t style)
441 {
442  TGHorizontalFrame *rfr = new TGHorizontalFrame(p);
443  TGHorizontalFrame *labfr = new TGHorizontalFrame(rfr, labelw, 20, kFixedSize);
444  TGLabel *lab = new TGLabel(labfr, name);
445  labfr->AddFrame(lab, new TGLayoutHints(kLHintsLeft | kLHintsBottom, 0, 0, 0) );
446  rfr->AddFrame(labfr, new TGLayoutHints(kLHintsLeft | kLHintsBottom, 0, 0, 0));
447 
448  TGNumberEntry* ne = new TGNumberEntry(rfr, 0.0f, nd, -1, (TGNumberFormat::EStyle)style);
449  rfr->AddFrame(ne, new TGLayoutHints(kLHintsLeft | kLHintsExpandX | kLHintsBottom, 2, 0, 0));
450 
451  p->AddFrame(rfr, new TGLayoutHints(kLHintsLeft, 0, 0, 1, 0));
452  return ne;
453 }
454 
455 ////////////////////////////////////////////////////////////////////////////////
456 /// Creates "Style" tab.
457 
458 void TGLViewerEditor::CreateStyleTab()
459 {
460  MakeTitle("Update behaviour");
461  fIgnoreSizesOnUpdate = new TGCheckButton(this, "Ignore sizes");
462  fIgnoreSizesOnUpdate->SetToolTipText("Ignore bounding-box sizes on scene update");
463  AddFrame(fIgnoreSizesOnUpdate, new TGLayoutHints(kLHintsLeft, 4, 1, 1, 1));
464  fResetCamerasOnUpdate = new TGCheckButton(this, "Reset on update");
465  fResetCamerasOnUpdate->SetToolTipText("Reset camera on scene update");
466  AddFrame(fResetCamerasOnUpdate, new TGLayoutHints(kLHintsLeft, 4, 1, 1, 1));
467 
468  TGCompositeFrame* af = this;
469  fUpdateScene = new TGTextButton(af, "Update Scene", 130);
470  af->AddFrame(fUpdateScene, new TGLayoutHints(kLHintsLeft | kLHintsExpandX, 1, 1, 8, 1));
471  fCameraHome = new TGTextButton(af, "Camera Home", 130);
472  af->AddFrame(fCameraHome, new TGLayoutHints(kLHintsLeft | kLHintsExpandX, 1, 1, 1, 3));
473  fMaxSceneDrawTimeHQ = MakeLabeledNEntry(af, "Max HQ draw time:", 120, 6, TGNumberFormat::kNESInteger);
474  fMaxSceneDrawTimeHQ->SetLimits(TGNumberFormat::kNELLimitMin, 0, 1e6);
475  fMaxSceneDrawTimeHQ->GetNumberEntry()->SetToolTipText("Maximum time spent in scene drawing\nin high-quality mode [ms].");
476  fMaxSceneDrawTimeLQ = MakeLabeledNEntry(af, "Max LQ draw time:", 120, 6, TGNumberFormat::kNESInteger);
477  fMaxSceneDrawTimeLQ->SetLimits(TGNumberFormat::kNELLimitMin, 0, 1e6);
478  fMaxSceneDrawTimeLQ->GetNumberEntry()->SetToolTipText("Maximum time spent in scene drawing\nin low-quality mode (during rotation etc).");
479 
480  TGHorizontalFrame* hf = new TGHorizontalFrame(this);
481  TGLabel* lab = new TGLabel(hf, "Clear Color");
482  hf->AddFrame(lab, new TGLayoutHints(kLHintsLeft|kLHintsBottom, 1, 4, 8, 3));
483  fClearColor = new TGColorSelect(hf, 0, -1);
484  hf->AddFrame(fClearColor, new TGLayoutHints(kLHintsLeft, 1, 1, 8, 1));
485  AddFrame(hf, new TGLayoutHints(kLHintsLeft, 2, 1, 1, 1));
486 
487  // LightSet
488  fLightSet = new TGLLightSetSubEditor(this);
489  fLightSet->Connect("Changed()", "TGLViewerEditor", this, "ViewerRedraw()");
490  AddFrame(fLightSet, new TGLayoutHints(kLHintsTop | kLHintsExpandX, 2, 0, 0, 0));
491 
492  // Point-sizes / line-widths.
493  hf = new TGHorizontalFrame(af);
494  fPointSizeScale = MakeLabeledNEntry(hf, "Point-size scale:", 116, 4, TGNumberFormat::kNESRealOne);
495  fPointSizeScale->SetLimits(TGNumberFormat::kNELLimitMinMax, 0.1, 16);
496  fPointSmooth = new TGCheckButton(hf);
497  fPointSmooth->SetToolTipText("Use smooth points.");
498  hf->AddFrame(fPointSmooth, new TGLayoutHints(kLHintsNormal, 3, 0, 3, 0));
499  af->AddFrame(hf);
500  hf = new TGHorizontalFrame(af);
501  fLineWidthScale = MakeLabeledNEntry(hf, "Line-width scale:", 116, 4, TGNumberFormat::kNESRealOne);
502  fLineWidthScale->SetLimits(TGNumberFormat::kNELLimitMinMax, 0.1, 16);
503  fLineSmooth = new TGCheckButton(hf);
504  fLineSmooth->SetToolTipText("Use smooth lines.");
505  hf->AddFrame(fLineSmooth, new TGLayoutHints(kLHintsNormal, 3, 0, 3, 0));
506  af->AddFrame(hf);
507  fWFLineWidth = MakeLabeledNEntry(af, "Wireframe line-width:", 116, 4, TGNumberFormat::kNESRealOne);
508  fWFLineWidth->SetLimits(TGNumberFormat::kNELLimitMinMax, 0.1, 16);
509  fOLLineWidth = MakeLabeledNEntry(af, "Outline line-width:", 116, 4, TGNumberFormat::kNESRealOne);
510  fOLLineWidth->SetLimits(TGNumberFormat::kNELLimitMinMax, 0.1, 16);
511 }
512 
513 ////////////////////////////////////////////////////////////////////////////////
514 /// Create "Guides" tab.
515 
516 void TGLViewerEditor::CreateGuidesTab()
517 {
518  fGuidesFrame = CreateEditorTabSubFrame("Guides");
519 
520  // external camera look at point
521  TGGroupFrame* grf = new TGGroupFrame(fGuidesFrame, "Camera center:", kVerticalFrame);
522  fDrawCameraCenter = new TGCheckButton(grf, "Show", 50);
523  grf->AddFrame(fDrawCameraCenter, new TGLayoutHints(kLHintsTop | kLHintsLeft, 0, 0, 1, 1));
524  fCameraCenterExt = new TGCheckButton(grf, "External", 50);
525  grf->AddFrame(fCameraCenterExt, new TGLayoutHints(kLHintsLeft, 0, 0, 1, 0));
526  fGuidesFrame->AddFrame(grf, new TGLayoutHints(kLHintsTop| kLHintsLeft | kLHintsExpandX, 2, 3, 3, 0));
527  Int_t labw = 20;
528  fCameraCenterX = MakeLabeledNEntry(grf, "X:", labw, 8, TGNumberFormat::kNESRealThree);
529  fCameraCenterY = MakeLabeledNEntry(grf, "Y:", labw, 8, TGNumberFormat::kNESRealThree);
530  fCameraCenterZ = MakeLabeledNEntry(grf, "Z:", labw, 8, TGNumberFormat::kNESRealThree);
531  fCaptureCenter = new TGTextButton(grf, " Pick center ");
532  grf->AddFrame(fCaptureCenter, new TGLayoutHints(kLHintsNormal, labw + 2, 0, 2, 0));
533 
534  // annotate
535  TGGroupFrame* annf = new TGGroupFrame(fGuidesFrame, "Annotation");
536  fGuidesFrame->AddFrame(annf, new TGLayoutHints(kLHintsTop | kLHintsCenterX | kLHintsExpandX, 2, 3, 0, 0));
537  fCaptureAnnotate = new TGCheckButton(annf, "Pick annotation");
538  annf->AddFrame(fCaptureAnnotate, new TGLayoutHints(kLHintsTop | kLHintsCenterX | kLHintsExpandX));
539 
540  // reference container
541  fRefContainer = new TGGroupFrame(fGuidesFrame, "Reference marker");
542  fGuidesFrame->AddFrame(fRefContainer, new TGLayoutHints(kLHintsTop | kLHintsCenterX | kLHintsExpandX, 2, 3, 0, 0));
543  fReferenceOn = new TGCheckButton(fRefContainer, "Show");
544  fRefContainer->AddFrame(fReferenceOn, new TGLayoutHints(kLHintsTop | kLHintsCenterX | kLHintsExpandX));
545  fReferencePosX = MakeLabeledNEntry(fRefContainer, "X:", labw, 8, TGNumberFormat::kNESRealThree );
546  fReferencePosY = MakeLabeledNEntry(fRefContainer, "Y:", labw, 8, TGNumberFormat::kNESRealThree );
547  fReferencePosZ = MakeLabeledNEntry(fRefContainer, "Z:", labw, 8, TGNumberFormat::kNESRealThree );
548 
549  // axes
550  fAxesContainer = new TGButtonGroup(fGuidesFrame, "Axes");
551  fAxesNone = new TGRadioButton(fAxesContainer, "None", 1);
552  fAxesEdge = new TGRadioButton(fAxesContainer, "Edge", 2);
553  fAxesOrigin = new TGRadioButton(fAxesContainer, "Origin", 3);
554  fAxesDepthTest = new TGCheckButton(fAxesContainer, "DepthTest",4);
555  fGuidesFrame->AddFrame(fAxesContainer, new TGLayoutHints(kLHintsTop | kLHintsCenterX | kLHintsExpandX, 2, 3, 0, 0));
556 
557  // camera overlay
558  fCamContainer = new TGGroupFrame(fGuidesFrame, "Camera overlay");
559  fGuidesFrame->AddFrame(fCamContainer, new TGLayoutHints(kLHintsTop | kLHintsCenterX | kLHintsExpandX, 2, 3, 0, 0));
560  fCamOverlayOn = new TGCheckButton(fCamContainer, "Show");
561  fCamContainer->AddFrame(fCamOverlayOn, new TGLayoutHints(kLHintsTop | kLHintsCenterX | kLHintsExpandX));
562  TGHorizontalFrame* chf = new TGHorizontalFrame(fCamContainer);
563  TGLabel* lab = new TGLabel(chf, "Mode");
564  chf->AddFrame(lab, new TGLayoutHints(kLHintsLeft|kLHintsBottom, 1, 4, 1, 2));
565  fCamMode = new TGComboBox(chf);
566  fCamMode->AddEntry("Plane", TGLCameraOverlay::kPlaneIntersect);
567  fCamMode->AddEntry("Bar", TGLCameraOverlay::kBar);
568  fCamMode->AddEntry("Axis", TGLCameraOverlay::kAxis);
569  fCamMode->AddEntry("Grid Front", TGLCameraOverlay::kGridFront);
570  fCamMode->AddEntry("Grid Back", TGLCameraOverlay::kGridBack);
571  TGListBox* lb = fCamMode->GetListBox();
572  lb->Resize(lb->GetWidth(), 5*18);
573  fCamMode->Resize(90, 20);
574  chf->AddFrame(fCamMode, new TGLayoutHints(kLHintsTop, 1, 1, 1, 1));
575  fCamContainer->AddFrame(chf);
576 }
577 
578 ////////////////////////////////////////////////////////////////////////////////
579 /// Create GUI controls - clip type (none/plane/box) and plane/box properties.
580 
581 void TGLViewerEditor::CreateClippingTab()
582 {
583  fClipFrame = CreateEditorTabSubFrame("Clipping");
584 
585  fClipSet = new TGLClipSetSubEditor(fClipFrame);
586  fClipSet->Connect("Changed()", "TGLViewerEditor", this, "ViewerRedraw()");
587  fClipFrame->AddFrame(fClipSet, new TGLayoutHints(kLHintsTop | kLHintsExpandX, 2, 0, 0, 0));
588 }
589 
590 ////////////////////////////////////////////////////////////////////////////////
591 /// Create Extra Tab controls - camera rotator and stereo.
592 
593 void TGLViewerEditor::CreateExtrasTab()
594 {
595  Int_t labw = 80;
596 
597  TGCompositeFrame *tab = CreateEditorTabSubFrame("Extras"), *p = 0;
598 
599  // ----- Auto rotator -----
600 
601  p = new TGGroupFrame(tab, "Auto rotator", kVerticalFrame);
602 
603  //
604  fRotateSceneOn = new TGCheckButton(p, "Rotate all objects");
605  fRotateSceneOn->SetToolTipText("This covers a very specific use-case and is most likely not what you need.\nProceed at your own risk. Sorry about that.");
606  p->AddFrame(fRotateSceneOn, new TGLayoutHints(kLHintsLeft, 4, 1, 1, 1));
607 
608  fSceneRotDt = MakeLabeledNEntry(p, "Delta Phi:", labw, 5, TGNumberFormat::kNESRealThree);
609  fSceneRotDt->SetLimits(TGNumberFormat::kNELLimitMinMax, 0.005, 0.06);
610 
611  fARotDt = MakeLabeledNEntry(p, "Delta T:", labw, 5, TGNumberFormat::kNESRealThree);
612  fARotDt->SetLimits(TGNumberFormat::kNELLimitMinMax, 0.001, 1);
613 
614  fARotWPhi = MakeLabeledNEntry(p, "Omega Phi:", labw, 5, TGNumberFormat::kNESRealTwo);
615  fARotWPhi->SetLimits(TGNumberFormat::kNELLimitMinMax, -10, 10);
616 
617  fARotATheta = MakeLabeledNEntry(p, "A Theta:", labw, 5, TGNumberFormat::kNESRealTwo);
618  fARotATheta->SetLimits(TGNumberFormat::kNELLimitMinMax, 0.01, 1);
619 
620  fARotWTheta = MakeLabeledNEntry(p, "Omega Theta:", labw, 5, TGNumberFormat::kNESRealTwo);
621  fARotWTheta->SetLimits(TGNumberFormat::kNELLimitMinMax, -10, 10);
622 
623  fARotADolly = MakeLabeledNEntry(p, "A Dolly:", labw, 5, TGNumberFormat::kNESRealTwo);
624  fARotADolly->SetLimits(TGNumberFormat::kNELLimitMinMax, 0.01, 1);
625 
626  fARotWDolly = MakeLabeledNEntry(p, "Omega Dolly:", labw, 5, TGNumberFormat::kNESRealTwo);
627  fARotWDolly->SetLimits(TGNumberFormat::kNELLimitMinMax, -10, 10);
628 
629  {
630  TGCompositeFrame *l = new TGHorizontalFrame(p);
631 
632  TGTextButton *b = new TGTextButton(l, "Start");
633  b->Connect("Clicked()", "TGLViewerEditor", this, "DoRotatorStart()");
634  l->AddFrame(b, new TGLayoutHints(kLHintsLeft | kLHintsExpandX));
635 
636  b = new TGTextButton(l, "Stop");
637  b->Connect("Clicked()", "TGLViewerEditor", this, "DoRotatorStop()");
638  l->AddFrame(b, new TGLayoutHints(kLHintsLeft | kLHintsExpandX));
639 
640  p->AddFrame(l, new TGLayoutHints(kLHintsTop | kLHintsExpandX, 0, 0, 4, 0));
641  }
642 
643  tab->AddFrame(p, new TGLayoutHints(kLHintsTop | kLHintsExpandX));
644 
645  // ----- Auto Save Images -----
646 
647  p = new TGGroupFrame(tab, "Auto save images", kVerticalFrame);
648 
649  fASavImageGUIBaseName = new TGTextEntry(p);
650  fASavImageGUIBaseName->SetDefaultSize(160, 0);
651  p->AddFrame(fASavImageGUIBaseName, new TGLayoutHints(kLHintsTop | kLHintsExpandX, 0, 0, 4, 0));
652 
653  fASavImageGUIOutMode = new TGButtonGroup(p, "Output mode", kChildFrame|kHorizontalFrame);
654  new TGRadioButton(fASavImageGUIOutMode, "GIF+ ");
655  new TGRadioButton(fASavImageGUIOutMode, "PNG set ");
656  fASavImageGUIOutMode->SetLayoutHints(new TGLayoutHints(kLHintsLeft | kLHintsBottom, 0, 0, 2, -10));
657  p->AddFrame(fASavImageGUIOutMode, new TGLayoutHints(kLHintsTop | kLHintsCenterX | kLHintsExpandX, 2, 3, 2, 2));
658 
659  {
660  TGCompositeFrame *l = new TGHorizontalFrame(p);
661 
662  TGTextButton *b = new TGTextButton(l, "Start");
663  b->Connect("Clicked()", "TGLViewerEditor", this, "DoASavImageStart()");
664  l->AddFrame(b, new TGLayoutHints(kLHintsLeft | kLHintsExpandX));
665 
666  b = new TGTextButton(l, "Stop");
667  b->Connect("Clicked()", "TGLViewerEditor", this, "DoASavImageStop()");
668  l->AddFrame(b, new TGLayoutHints(kLHintsLeft | kLHintsExpandX));
669 
670  p->AddFrame(l, new TGLayoutHints(kLHintsTop | kLHintsExpandX, 0, 0, 4, 0));
671  }
672 
673  tab->AddFrame(p, new TGLayoutHints(kLHintsTop | kLHintsExpandX));
674 
675  // ----- Stereo -----
676 
677  fStereoFrame = p = new TGGroupFrame(tab, "Stereo", kVerticalFrame);
678 
679  // Int_t labw = 80;
680 
681  fStereoZeroParallax = MakeLabeledNEntry(p, "Zero parallax:", labw, 5, TGNumberFormat::kNESRealThree);
682  fStereoZeroParallax->SetLimits(TGNumberFormat::kNELLimitMinMax, 0, 1);
683 
684  fStereoEyeOffsetFac = MakeLabeledNEntry(p, "Eye offset:", labw, 5, TGNumberFormat::kNESRealTwo);
685  fStereoEyeOffsetFac->SetLimits(TGNumberFormat::kNELLimitMinMax, 0, 2);
686 
687  fStereoFrustumAsymFac = MakeLabeledNEntry(p, "Asymetry:", labw, 5, TGNumberFormat::kNESRealTwo);
688  fStereoFrustumAsymFac->SetLimits(TGNumberFormat::kNELLimitMinMax, 0, 2);
689 
690  tab->AddFrame(p, new TGLayoutHints(kLHintsTop | kLHintsExpandX));
691 }
692 
693 
694 ////////////////////////////////////////////////////////////////////////////////
695 /// Enable/disable reference position (x/y/z) number edits based on
696 /// reference check box.
697 
698 void TGLViewerEditor::UpdateReferencePosState()
699 {
700  fReferencePosX->SetState(fReferenceOn->IsDown());
701  fReferencePosY->SetState(fReferenceOn->IsDown());
702  fReferencePosZ->SetState(fReferenceOn->IsDown());
703 }
704 
705 ////////////////////////////////////////////////////////////////////////////////
706 /// Configuration of guides GUI called from SetModel().
707 
708 void TGLViewerEditor::SetGuides()
709 {
710  Bool_t axesDepthTest = kFALSE;
711  Bool_t referenceOn = kFALSE;
712  Double_t referencePos[3] = {0.};
713  fViewer->GetGuideState(fAxesType, axesDepthTest, referenceOn, referencePos);
714 
715  for (Int_t i = 1; i < 4; i++) {
716  TGButton * btn = fAxesContainer->GetButton(i);
717  if (fAxesType+1 == i)
718  btn->SetDown(kTRUE);
719  else
720  btn->SetDown(kFALSE);
721  }
722  fAxesContainer->GetButton(4)->SetOn(axesDepthTest, kFALSE);
723 
724  fReferenceOn->SetDown(referenceOn);
725  fReferencePosX->SetNumber(referencePos[0]);
726  fReferencePosY->SetNumber(referencePos[1]);
727  fReferencePosZ->SetNumber(referencePos[2]);
728  UpdateReferencePosState();
729 
730  // overlay
731  TGLCameraOverlay* co = fViewer->GetCameraOverlay();
732  TGCompositeFrame *fr = (TGCompositeFrame*)((TGFrameElement*) fCamContainer->GetList()->Last() )->fFrame;
733 
734  if (fViewer->CurrentCamera().IsOrthographic())
735  {
736  fCamOverlayOn->SetDown(co->GetShowOrthographic());
737  fr->ShowFrame(fCamMode);
738 
739 
740  if (! fr->IsMapped()) {
741  fr->MapSubwindows();
742  fr->MapWindow();
743  fCamContainer->MapWindow();
744  fCamContainer->MapWindow();
745  fCamMode->Select(co->GetOrthographicMode(), kFALSE);
746  }
747  }
748  else
749  {
750  fCamOverlayOn->SetDown(co->GetShowPerspective());
751 
752  // only mode implemented for perspective camera
753  fCamMode->Select(co->GetPerspectiveMode(), kFALSE);
754  fr->HideFrame(fCamMode);
755  if (fr->IsMapped())
756  fr->UnmapWindow();
757  }
758 }
759 
760 ////////////////////////////////////////////////////////////////////////////////
761 
762 void TGLViewerEditor::SetRotatorMode()
763 {
764  if (TGLAutoRotator * const r = fViewer->GetAutoRotator()) {
765  r->Stop();
766 
767  if (fRotateSceneOn->IsOn()) {
768  r->SetDeltaPhi(fSceneRotDt->GetNumber());
769 
770  SetLabeledNEntryState(fSceneRotDt, kTRUE);
771  SetLabeledNEntryState(fARotDt, kFALSE);
772  SetLabeledNEntryState(fARotWPhi, kFALSE);
773  SetLabeledNEntryState(fARotATheta, kFALSE);
774  SetLabeledNEntryState(fARotWTheta, kFALSE);
775  SetLabeledNEntryState(fARotADolly, kFALSE);
776  SetLabeledNEntryState(fARotWDolly, kFALSE);
777  } else {
778  SetLabeledNEntryState(fSceneRotDt, kFALSE);
779  SetLabeledNEntryState(fARotDt, kTRUE);
780  SetLabeledNEntryState(fARotWPhi, kTRUE);
781  SetLabeledNEntryState(fARotATheta, kTRUE);
782  SetLabeledNEntryState(fARotWTheta, kTRUE);
783  SetLabeledNEntryState(fARotADolly, kTRUE);
784  SetLabeledNEntryState(fARotWDolly, kTRUE);
785  }
786 
787  r->SetRotateScene(fRotateSceneOn->IsOn());
788  }
789 }
790 
791 ////////////////////////////////////////////////////////////////////////////////
792 /// Update rotator related variables.
793 
794 void TGLViewerEditor::UpdateRotator()
795 {
796  TGLAutoRotator *r = fViewer->GetAutoRotator();
797  if (fRotateSceneOn->IsOn()) {
798  r->SetDeltaPhi(fSceneRotDt->GetNumber());
799  } else {
800  r->SetDt (fARotDt->GetNumber());
801  r->SetWPhi (fARotWPhi->GetNumber());
802  r->SetATheta(fARotATheta->GetNumber());
803  r->SetWTheta(fARotWTheta->GetNumber());
804  r->SetADolly(fARotADolly->GetNumber());
805  r->SetWDolly(fARotWDolly->GetNumber());
806  }
807 }
808 
809 ////////////////////////////////////////////////////////////////////////////////
810 /// Start auto-rotator.
811 
812 void TGLViewerEditor::DoRotatorStart()
813 {
814  TGLAutoRotator *r = fViewer->GetAutoRotator();
815  if (!r->IsRunning())
816  r->SetRotateScene(fRotateSceneOn->IsOn());
817 
818  r->Start();
819 }
820 
821 ////////////////////////////////////////////////////////////////////////////////
822 /// Stop auto-rotator.
823 
824 void TGLViewerEditor::DoRotatorStop()
825 {
826  fViewer->GetAutoRotator()->Stop();
827 }
828 
829 ////////////////////////////////////////////////////////////////////////////////
830 /// Update base-name.
831 
832 void TGLViewerEditor::DoASavImageGUIBaseName(const char* t)
833 {
834  TGLAutoRotator *r = fViewer->GetAutoRotator();
835  r->SetImageGUIBaseName(t);
836 }
837 
838 ////////////////////////////////////////////////////////////////////////////////
839 /// Update output mode.
840 
841 void TGLViewerEditor::DoASavImageGUIOutMode(Int_t m)
842 {
843  TGLAutoRotator *r = fViewer->GetAutoRotator();
844  r->SetImageGUIOutMode(m);
845 }
846 
847 ////////////////////////////////////////////////////////////////////////////////
848 /// Start auto-rotator image auto-save.
849 
850 void TGLViewerEditor::DoASavImageStart()
851 {
852  TGLAutoRotator *r = fViewer->GetAutoRotator();
853  if (r->GetImageAutoSave())
854  {
855  Warning("DoASavImageStart", "AutoSave in progress.");
856  return;
857  }
858 
859  r->StartImageAutoSaveWithGUISettings();
860 }
861 
862 ////////////////////////////////////////////////////////////////////////////////
863 /// Stop auto-rotator image auto-save.
864 
865 void TGLViewerEditor::DoASavImageStop()
866 {
867  TGLAutoRotator *r = fViewer->GetAutoRotator();
868  if (!r->GetImageAutoSave())
869  {
870  Warning("DoASavImageStop", "AutoSave not in progress.");
871  return;
872  }
873 
874  r->StopImageAutoSave();
875 }
876 
877 ////////////////////////////////////////////////////////////////////////////////
878 /// Update stereo related variables.
879 
880 void TGLViewerEditor::UpdateStereo()
881 {
882  fViewer->SetStereoZeroParallax (fStereoZeroParallax->GetNumber());
883  fViewer->SetStereoEyeOffsetFac (fStereoEyeOffsetFac->GetNumber());
884  fViewer->SetStereoFrustumAsymFac(fStereoFrustumAsymFac->GetNumber());
885  ViewerRedraw();
886 }
887 
888 //Aux. functions that do not have to be members.
889 
890 namespace {
891 
892 //Here's how we create a number entry and its label:
893 
894 // TGHorizontalFrame *rfr = new TGHorizontalFrame(p);
895 // TGHorizontalFrame *labfr = new TGHorizontalFrame(rfr, labelw, 20, kFixedSize);
896 // TGLabel *lab = new TGLabel(labfr, name);
897 // labfr->AddFrame(lab, new TGLayoutHints(kLHintsLeft | kLHintsBottom, 0, 0, 0) );
898 // rfr->AddFrame(labfr, new TGLayoutHints(kLHintsLeft | kLHintsBottom, 0, 0, 0));
899 //
900 // TGNumberEntry* ne = new TGNumberEntry(rfr, 0.0f, nd, -1, (TGNumberFormat::EStyle)style);
901 // rfr->AddFrame(ne, new TGLayoutHints(kLHintsLeft | kLHintsExpandX | kLHintsBottom, 2, 0, 0));
902 //
903 // p->AddFrame(rfr, new TGLayoutHints(kLHintsLeft, 0, 0, 1, 0));
904 
905 ////////////////////////////////////////////////////////////////////////////////
906 
907 TGLabel *FindLabelForNEntry(TGNumberEntry *entry)
908 {
909  if (!entry) {
910  //I would prefer an assert here.
911  ::Error("FindLabelForNEntry", "parameter 'entry' is null");
912  return 0;
913  }
914 
915  TGLabel *label = 0;
916 
917  if (const TGHorizontalFrame * const grandpa = dynamic_cast<const TGHorizontalFrame *>(entry->GetParent())) {
918  if (TList * const parents = grandpa->GetList()) {
919  TIter next1(parents);
920  while (TGFrameElement * const frameElement = dynamic_cast<TGFrameElement *>(next1())) {
921  if (TGHorizontalFrame * const parent = dynamic_cast<TGHorizontalFrame *>(frameElement->fFrame)) {
922  if (TList * const children = parent->GetList()) {
923  TIter next2(children);
924  while (TGFrameElement * const candidate = dynamic_cast<TGFrameElement *>(next2())) {
925  if ((label = dynamic_cast<TGLabel *>(candidate->fFrame)))
926  break;
927  }
928  }
929  }
930 
931  if (label)
932  break;
933  }
934  }
935  }
936 
937  return label;
938 }
939 
940 ////////////////////////////////////////////////////////////////////////////////
941 ///This is quite an ugly hack but still not as ugly as having 5-6 additional
942 ///TGLabels as data members.
943 
944 void SetLabeledNEntryState(TGNumberEntry *entry, Bool_t enabled)
945 {
946  if (!entry) {
947  //I would prefer an assert here.
948  ::Error("SetLabeledNEntryState", "parameter 'entry' is null");
949  return;
950  }
951 
952  entry->SetState(enabled);
953  if (TGLabel * const label = FindLabelForNEntry(entry))
954  //Wah!
955  label->Disable(!enabled);
956 }
957 
958 }