Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TEveViewer.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 "TEveViewer.h"
13 #include "TEveScene.h"
14 #include "TEveSceneInfo.h"
15 
16 #include "TEveManager.h"
17 #include "TEveSelection.h"
18 
19 #include "TGLFormat.h"
20 #include "TGLSAViewer.h"
21 #include "TGLEmbeddedViewer.h"
22 #include "TGLScenePad.h"
23 
24 #include "TGLEventHandler.h"
25 
26 #include "TApplication.h"
27 #include "TEnv.h"
28 #include "TSystem.h"
29 
30 /** \class TEveViewer
31 \ingroup TEve
32 Eve representation of TGLViewer.
33 
34 The gl-viewer is owned by this class and is deleted in destructor.
35 
36 The frame is not deleted, it is expected that the gl-viewer implementation
37 will delete that. TGLSAViewer and TGEmbeddedViewer both do so.
38 This could be an optional argument to SetGLViewer. A frame could be
39 passed as well.
40 
41 When stand-alone viewer is requested, it will come up with menu-hiding
42 enabled by default. If you dislike this, add the following line to rootrc
43 file (or set corresponding gEnv entry in application initialization):
44 ~~~ {.cpp}
45  Eve.Viewer.HideMenus: off
46 ~~~
47 */
48 
49 ClassImp(TEveViewer);
50 
51 Bool_t TEveViewer::fgInitInternal = kFALSE;
52 Bool_t TEveViewer::fgRecreateGlOnDockOps = kFALSE;
53 
54 ////////////////////////////////////////////////////////////////////////////////
55 /// Constructor.
56 ///
57 /// The base-class TEveWindowFrame is constructed without a frame so
58 /// a default composite-frame is instantiated and stored in fGUIFrame.
59 /// Cleanup is set to no-cleanup as viewers need to be zapped with some
60 /// more care.
61 
62 TEveViewer::TEveViewer(const char* n, const char* t) :
63  TEveWindowFrame(0, n, t),
64  fGLViewer (0),
65  fGLViewerFrame (0)
66 {
67  SetChildClass(TEveSceneInfo::Class());
68  fGUIFrame->SetCleanup(kNoCleanup); // the gl-viewer's frame deleted elsewhere.
69 
70  if (!fgInitInternal)
71  {
72  InitInternal();
73  }
74 }
75 
76 ////////////////////////////////////////////////////////////////////////////////
77 /// Destructor.
78 
79 TEveViewer::~TEveViewer()
80 {
81  fGLViewer->SetEventHandler(0);
82 
83  fGLViewerFrame->UnmapWindow();
84  GetGUICompositeFrame()->RemoveFrame(fGLViewerFrame);
85  fGLViewerFrame->ReparentWindow(gClient->GetDefaultRoot());
86  TTimer::SingleShot(150, "TGLViewer", fGLViewer, "Delete()");
87 }
88 
89 ////////////////////////////////////////////////////////////////////////////////
90 /// Initialize static data-members according to running conditions.
91 
92 void TEveViewer::InitInternal()
93 {
94  // Determine if display is running on a mac.
95  // This also works for ssh connection mac->linux.
96  fgRecreateGlOnDockOps = (gVirtualX->SupportsExtension("Apple-WM") == 1);
97 
98  fgInitInternal = kTRUE;
99 }
100 
101 ////////////////////////////////////////////////////////////////////////////////
102 /// Virtual function called before a window is undocked.
103 /// On mac we have to force recreation of gl-context.
104 
105 void TEveViewer::PreUndock()
106 {
107  TEveWindowFrame::PreUndock();
108  if (fgRecreateGlOnDockOps)
109  {
110  // Mac only: TGLWidget can be already deleted
111  // in case of recursive delete
112  if (fGLViewer->GetGLWidget())
113  {
114  fGLViewer->DestroyGLWidget();
115  }
116  }
117 }
118 
119 ////////////////////////////////////////////////////////////////////////////////
120 /// Virtual function called after a window is docked.
121 /// On mac we have to force recreation of gl-context.
122 
123 void TEveViewer::PostDock()
124 {
125  if (fgRecreateGlOnDockOps) {
126  fGLViewer->CreateGLWidget();
127  }
128  TEveWindowFrame::PostDock();
129 }
130 
131 ////////////////////////////////////////////////////////////////////////////////
132 /// Return TEveViewer icon.
133 
134 const TGPicture* TEveViewer::GetListTreeIcon(Bool_t)
135 {
136  return TEveElement::fgListTreeIcons[1];
137 }
138 
139 ////////////////////////////////////////////////////////////////////////////////
140 /// Set TGLViewer that is represented by this object.
141 /// The old gl-viewer is deleted.
142 
143 void TEveViewer::SetGLViewer(TGLViewer* viewer, TGFrame* frame)
144 {
145  delete fGLViewer;
146  fGLViewer = viewer;
147  fGLViewerFrame = frame;
148 
149  fGLViewer->SetSmartRefresh(kTRUE);
150 }
151 
152 ////////////////////////////////////////////////////////////////////////////////
153 /// Spawn new GLViewer and adopt it.
154 
155 TGLSAViewer* TEveViewer::SpawnGLViewer(TGedEditor* ged, Bool_t stereo, Bool_t quad_buf)
156 {
157  static const TEveException kEH("TEveViewer::SpawnGLViewer ");
158 
159  TGCompositeFrame* cf = GetGUICompositeFrame();
160 
161  TGLFormat *form = 0;
162  if (stereo && quad_buf)
163  {
164  form = new TGLFormat;
165  form->SetStereo(kTRUE);
166  }
167 
168  cf->SetEditable(kTRUE);
169  TGLSAViewer* v = 0;
170  try
171  {
172  v = new TGLSAViewer(cf, 0, ged, form);
173  }
174  catch (std::exception&)
175  {
176  Error("SpawnGLViewer", "Insufficient support from the graphics hardware. Aborting.");
177  gApplication->Terminate(1);
178  }
179  cf->SetEditable(kFALSE);
180  v->ToggleEditObject();
181  v->DisableCloseMenuEntries();
182  if (gEnv->GetValue("Eve.Viewer.HideMenus", 1) == 1)
183  {
184  v->EnableMenuBarHiding();
185  }
186  SetGLViewer(v, v->GetFrame());
187 
188  if (stereo)
189  v->SetStereo(kTRUE, quad_buf);
190 
191  if (fEveFrame == 0)
192  PreUndock();
193 
194  return v;
195 }
196 
197 ////////////////////////////////////////////////////////////////////////////////
198 /// Spawn new GLViewer and adopt it.
199 
200 TGLEmbeddedViewer* TEveViewer::SpawnGLEmbeddedViewer(TGedEditor* ged, Int_t border)
201 {
202  static const TEveException kEH("TEveViewer::SpawnGLEmbeddedViewer ");
203 
204  TGCompositeFrame* cf = GetGUICompositeFrame();
205 
206  TGLEmbeddedViewer* v = new TGLEmbeddedViewer(cf, 0, ged, border);
207  SetGLViewer(v, v->GetFrame());
208 
209  cf->AddFrame(fGLViewerFrame, new TGLayoutHints(kLHintsNormal | kLHintsExpandX | kLHintsExpandY));
210 
211  fGLViewerFrame->MapWindow();
212 
213  if (fEveFrame == 0)
214  PreUndock();
215 
216  return v;
217 }
218 
219 ////////////////////////////////////////////////////////////////////////////////
220 /// Redraw viewer immediately.
221 
222 void TEveViewer::Redraw(Bool_t resetCameras)
223 {
224  if (resetCameras) fGLViewer->PostSceneBuildSetup(kTRUE);
225  fGLViewer->RequestDraw(TGLRnrCtx::kLODHigh);
226 }
227 
228 ////////////////////////////////////////////////////////////////////////////////
229 /// Switch stereo mode.
230 /// This only works TGLSAViewers and, of course, with stereo support
231 /// provided by the OpenGL driver.
232 
233 void TEveViewer::SwitchStereo()
234 {
235  TGLSAViewer *v = dynamic_cast<TGLSAViewer*>(fGLViewer);
236 
237  if (!v) {
238  Warning("SwitchStereo", "Only supported for TGLSAViewer.");
239  return;
240  }
241 
242  v->DestroyGLWidget();
243  TGLFormat *f = v->GetFormat();
244 switch_stereo:
245  f->SetStereo(!f->IsStereo());
246  v->SetStereo(f->IsStereo());
247  try
248  {
249  v->CreateGLWidget();
250  }
251  catch (std::exception&)
252  {
253  Error("SwitchStereo", "Insufficient support from the graphics hardware. Reverting.");
254  goto switch_stereo;
255  }
256 }
257 
258 ////////////////////////////////////////////////////////////////////////////////
259 /// Add 'scene' to the list of scenes.
260 
261 void TEveViewer::AddScene(TEveScene* scene)
262 {
263  static const TEveException eh("TEveViewer::AddScene ");
264 
265  TGLSceneInfo* glsi = fGLViewer->AddScene(scene->GetGLScene());
266  if (glsi != 0) {
267  TEveSceneInfo* si = new TEveSceneInfo(this, scene, glsi);
268  AddElement(si);
269  } else {
270  throw(eh + "scene already in the viewer.");
271  }
272 }
273 
274 ////////////////////////////////////////////////////////////////////////////////
275 /// Remove element 'el' from the list of children and also remove
276 /// appropriate GLScene from GLViewer's list of scenes.
277 /// Virtual from TEveElement.
278 
279 void TEveViewer::RemoveElementLocal(TEveElement* el)
280 {
281  fGLViewer->RemoveScene(((TEveSceneInfo*)el)->GetGLScene());
282 }
283 
284 ////////////////////////////////////////////////////////////////////////////////
285 /// Remove all children, forwarded to GLViewer.
286 /// Virtual from TEveElement.
287 
288 void TEveViewer::RemoveElementsLocal()
289 {
290  fGLViewer->RemoveAllScenes();
291 }
292 
293 ////////////////////////////////////////////////////////////////////////////////
294 /// Object to be edited when this is selected, returns the TGLViewer.
295 /// Virtual from TEveElement.
296 
297 TObject* TEveViewer::GetEditorObject(const TEveException& eh) const
298 {
299  if (!fGLViewer)
300  throw(eh + "fGLViewer not set.");
301  return fGLViewer;
302 }
303 
304 ////////////////////////////////////////////////////////////////////////////////
305 /// Receive a pasted object. TEveViewer only accepts objects of
306 /// class TEveScene.
307 /// Virtual from TEveElement.
308 
309 Bool_t TEveViewer::HandleElementPaste(TEveElement* el)
310 {
311  static const TEveException eh("TEveViewer::HandleElementPaste ");
312 
313  TEveScene* scene = dynamic_cast<TEveScene*>(el);
314  if (scene != 0) {
315  AddScene(scene);
316  return kTRUE;
317  } else {
318  Warning(eh.Data(), "class TEveViewer only accepts TEveScene paste argument.");
319  return kFALSE;
320  }
321 }
322 
323 /** \class TEveViewerList
324 \ingroup TEve
325 List of Viewers providing common operations on TEveViewer collections.
326 */
327 
328 ClassImp(TEveViewerList);
329 
330 ////////////////////////////////////////////////////////////////////////////////
331 
332 TEveViewerList::TEveViewerList(const char* n, const char* t) :
333  TEveElementList(n, t),
334  fShowTooltip (kTRUE),
335 
336  fBrightness(0),
337  fUseLightColorSet(kFALSE)
338 {
339  // Constructor.
340 
341  SetChildClass(TEveViewer::Class());
342  Connect();
343 }
344 
345 ////////////////////////////////////////////////////////////////////////////////
346 /// Destructor.
347 
348 TEveViewerList::~TEveViewerList()
349 {
350  Disconnect();
351 }
352 
353 ////////////////////////////////////////////////////////////////////////////////
354 /// Call base-class implementation.
355 /// If compound is open and compound of the new element is not set,
356 /// the el's compound is set to this.
357 
358 void TEveViewerList::AddElement(TEveElement* el)
359 {
360  TEveElementList::AddElement(el);
361  el->IncParentIgnoreCnt();
362 }
363 
364 ////////////////////////////////////////////////////////////////////////////////
365 /// Decompoundofy el, call base-class version.
366 
367 void TEveViewerList::RemoveElementLocal(TEveElement* el)
368 {
369  el->DecParentIgnoreCnt();
370  TEveElementList::RemoveElementLocal(el);
371 }
372 
373 ////////////////////////////////////////////////////////////////////////////////
374 /// Decompoundofy children, call base-class version.
375 
376 void TEveViewerList::RemoveElementsLocal()
377 {
378  for (List_i i=fChildren.begin(); i!=fChildren.end(); ++i)
379  {
380  (*i)->DecParentIgnoreCnt();
381  }
382 
383  TEveElementList::RemoveElementsLocal();
384 }
385 
386 ////////////////////////////////////////////////////////////////////////////////
387 /// Connect to TGLViewer class-signals.
388 
389 void TEveViewerList::Connect()
390 {
391  TQObject::Connect("TGLViewer", "MouseOver(TObject*,UInt_t)",
392  "TEveViewerList", this, "OnMouseOver(TObject*,UInt_t)");
393 
394  TQObject::Connect("TGLViewer", "ReMouseOver(TObject*,UInt_t)",
395  "TEveViewerList", this, "OnReMouseOver(TObject*,UInt_t)");
396 
397  TQObject::Connect("TGLViewer", "UnMouseOver(TObject*,UInt_t)",
398  "TEveViewerList", this, "OnUnMouseOver(TObject*,UInt_t)");
399 
400  TQObject::Connect("TGLViewer", "Clicked(TObject*,UInt_t,UInt_t)",
401  "TEveViewerList", this, "OnClicked(TObject*,UInt_t,UInt_t)");
402 
403  TQObject::Connect("TGLViewer", "ReClicked(TObject*,UInt_t,UInt_t)",
404  "TEveViewerList", this, "OnReClicked(TObject*,UInt_t,UInt_t)");
405 
406  TQObject::Connect("TGLViewer", "UnClicked(TObject*,UInt_t,UInt_t)",
407  "TEveViewerList", this, "OnUnClicked(TObject*,UInt_t,UInt_t)");
408 }
409 
410 ////////////////////////////////////////////////////////////////////////////////
411 /// Disconnect from TGLViewer class-signals.
412 
413 void TEveViewerList::Disconnect()
414 {
415  TQObject::Disconnect("TGLViewer", "MouseOver(TObject*,UInt_t)",
416  this, "OnMouseOver(TObject*,UInt_t)");
417 
418  TQObject::Disconnect("TGLViewer", "ReMouseOver(TObject*,UInt_t)",
419  this, "OnReMouseOver(TObject*,UInt_t)");
420 
421  TQObject::Disconnect("TGLViewer", "UnMouseOver(TObject*,UInt_t)",
422  this, "OnUnMouseOver(TObject*,UInt_t)");
423 
424  TQObject::Disconnect("TGLViewer", "Clicked(TObject*,UInt_t,UInt_t)",
425  this, "OnClicked(TObject*,UInt_t,UInt_t)");
426 
427  TQObject::Disconnect("TGLViewer", "ReClicked(TObject*,UInt_t,UInt_t)",
428  this, "OnReClicked(TObject*,UInt_t,UInt_t)");
429 
430  TQObject::Disconnect("TGLViewer", "UnClicked(TObject*,UInt_t,UInt_t)",
431  this, "OnUnClicked(TObject*,UInt_t,UInt_t)");
432 }
433 
434 ////////////////////////////////////////////////////////////////////////////////
435 /// Repaint viewers that are tagged as changed.
436 
437 void TEveViewerList::RepaintChangedViewers(Bool_t resetCameras, Bool_t dropLogicals)
438 {
439  for (List_i i=fChildren.begin(); i!=fChildren.end(); ++i)
440  {
441  TGLViewer* glv = ((TEveViewer*)*i)->GetGLViewer();
442  if (glv->IsChanged())
443  {
444  if (resetCameras) glv->PostSceneBuildSetup(kTRUE);
445  if (dropLogicals) glv->SetSmartRefresh(kFALSE);
446 
447  glv->RequestDraw(TGLRnrCtx::kLODHigh);
448 
449  if (dropLogicals) glv->SetSmartRefresh(kTRUE);
450  }
451  }
452 }
453 
454 ////////////////////////////////////////////////////////////////////////////////
455 /// Repaint all viewers.
456 
457 void TEveViewerList::RepaintAllViewers(Bool_t resetCameras, Bool_t dropLogicals)
458 {
459  for (List_i i=fChildren.begin(); i!=fChildren.end(); ++i)
460  {
461  TGLViewer* glv = ((TEveViewer*)*i)->GetGLViewer();
462 
463  if (resetCameras) glv->PostSceneBuildSetup(kTRUE);
464  if (dropLogicals) glv->SetSmartRefresh(kFALSE);
465 
466  glv->RequestDraw(TGLRnrCtx::kLODHigh);
467 
468  if (dropLogicals) glv->SetSmartRefresh(kTRUE);
469  }
470 }
471 
472 ////////////////////////////////////////////////////////////////////////////////
473 /// Delete annotations from all viewers.
474 
475 void TEveViewerList::DeleteAnnotations()
476 {
477  for (List_i i=fChildren.begin(); i!=fChildren.end(); ++i)
478  {
479  TGLViewer* glv = ((TEveViewer*)*i)->GetGLViewer();
480  glv->DeleteOverlayAnnotations();
481  }
482 }
483 
484 ////////////////////////////////////////////////////////////////////////////////
485 /// Callback done from a TEveScene destructor allowing proper
486 /// removal of the scene from affected viewers.
487 
488 void TEveViewerList::SceneDestructing(TEveScene* scene)
489 {
490  for (List_i i=fChildren.begin(); i!=fChildren.end(); ++i)
491  {
492  TEveViewer* viewer = (TEveViewer*) *i;
493  List_i j = viewer->BeginChildren();
494  while (j != viewer->EndChildren())
495  {
496  TEveSceneInfo* sinfo = (TEveSceneInfo*) *j;
497  ++j;
498  if (sinfo->GetScene() == scene)
499  viewer->RemoveElement(sinfo);
500  }
501  }
502 }
503 
504 ////////////////////////////////////////////////////////////////////////////////
505 /// Show / hide tooltip for various MouseOver events.
506 /// Must be called from slots where sender is TGLEventHandler.
507 
508 void TEveViewerList::HandleTooltip()
509 {
510  if (fShowTooltip)
511  {
512  TGLViewer *glw = dynamic_cast<TGLViewer*>((TQObject*) gTQSender);
513  TGLEventHandler *glh = (TGLEventHandler*) glw->GetEventHandler();
514  if (gEve->GetHighlight()->NumChildren() == 1)
515  {
516  TString title(gEve->GetHighlight()->FirstChild()->GetHighlightTooltip());
517  if ( ! title.IsNull())
518  glh->TriggerTooltip(title);
519  }
520  else
521  {
522  glh->RemoveTooltip();
523  }
524  }
525 }
526 
527 ////////////////////////////////////////////////////////////////////////////////
528 /// Slot for global TGLViewer::MouseOver() signal.
529 ///
530 /// The attempt is made to determine the TEveElement being
531 /// represented by the physical shape and global highlight is updated
532 /// accordingly.
533 ///
534 /// If TEveElement::IsPickable() returns false, the element is not
535 /// highlighted.
536 ///
537 /// Highlight is always in single-selection mode.
538 
539 void TEveViewerList::OnMouseOver(TObject *obj, UInt_t /*state*/)
540 {
541  TEveElement *el = dynamic_cast<TEveElement*>(obj);
542  if (el && !el->IsPickable())
543  el = 0;
544 
545  void *qsender = gTQSender;
546  gEve->GetHighlight()->UserPickedElement(el, kFALSE);
547  gTQSender = qsender;
548 
549  HandleTooltip();
550 }
551 
552 ////////////////////////////////////////////////////////////////////////////////
553 /// Slot for global TGLViewer::ReMouseOver().
554 ///
555 /// The obj is dyn-casted to the TEveElement and global selection is
556 /// updated accordingly.
557 ///
558 /// If TEveElement::IsPickable() returns false, the element is not
559 /// selected.
560 
561 void TEveViewerList::OnReMouseOver(TObject *obj, UInt_t /*state*/)
562 {
563  TEveElement* el = dynamic_cast<TEveElement*>(obj);
564  if (el && !el->IsPickable())
565  el = 0;
566 
567  void *qsender = gTQSender;
568  gEve->GetHighlight()->UserRePickedElement(el);
569  gTQSender = qsender;
570 
571  HandleTooltip();
572 }
573 
574 ////////////////////////////////////////////////////////////////////////////////
575 /// Slot for global TGLViewer::UnMouseOver().
576 ///
577 /// The obj is dyn-casted to the TEveElement and global selection is
578 /// updated accordingly.
579 ///
580 /// If TEveElement::IsPickable() returns false, the element is not
581 /// selected.
582 
583 void TEveViewerList::OnUnMouseOver(TObject *obj, UInt_t /*state*/)
584 {
585  TEveElement* el = dynamic_cast<TEveElement*>(obj);
586  if (el && !el->IsPickable())
587  el = 0;
588 
589  void *qsender = gTQSender;
590  gEve->GetHighlight()->UserUnPickedElement(el);
591  gTQSender = qsender;
592 
593  HandleTooltip();
594 }
595 
596 ////////////////////////////////////////////////////////////////////////////////
597 /// Slot for global TGLViewer::Clicked().
598 ///
599 /// The obj is dyn-casted to the TEveElement and global selection is
600 /// updated accordingly.
601 ///
602 /// If TEveElement::IsPickable() returns false, the element is not
603 /// selected.
604 
605 void TEveViewerList::OnClicked(TObject *obj, UInt_t /*button*/, UInt_t state)
606 {
607  TEveElement* el = dynamic_cast<TEveElement*>(obj);
608  if (el && !el->IsPickable())
609  el = 0;
610  gEve->GetSelection()->UserPickedElement(el, state & kKeyControlMask);
611 }
612 
613 ////////////////////////////////////////////////////////////////////////////////
614 /// Slot for global TGLViewer::ReClicked().
615 ///
616 /// The obj is dyn-casted to the TEveElement and global selection is
617 /// updated accordingly.
618 ///
619 /// If TEveElement::IsPickable() returns false, the element is not
620 /// selected.
621 
622 void TEveViewerList::OnReClicked(TObject *obj, UInt_t /*button*/, UInt_t /*state*/)
623 {
624  TEveElement* el = dynamic_cast<TEveElement*>(obj);
625  if (el && !el->IsPickable())
626  el = 0;
627  gEve->GetSelection()->UserRePickedElement(el);
628 }
629 
630 ////////////////////////////////////////////////////////////////////////////////
631 /// Slot for global TGLViewer::UnClicked().
632 ///
633 /// The obj is dyn-casted to the TEveElement and global selection is
634 /// updated accordingly.
635 ///
636 /// If TEveElement::IsPickable() returns false, the element is not
637 /// selected.
638 
639 void TEveViewerList::OnUnClicked(TObject *obj, UInt_t /*button*/, UInt_t /*state*/)
640 {
641  TEveElement* el = dynamic_cast<TEveElement*>(obj);
642  if (el && !el->IsPickable())
643  el = 0;
644  gEve->GetSelection()->UserUnPickedElement(el);
645 }
646 
647 ////////////////////////////////////////////////////////////////////////////////
648 /// Set color brightness.
649 
650 void TEveViewerList::SetColorBrightness(Float_t b)
651 {
652  TEveUtil::SetColorBrightness(b, 1);
653 }
654 
655 ////////////////////////////////////////////////////////////////////////////////
656 /// Switch background color.
657 
658 void TEveViewerList::SwitchColorSet()
659 {
660  fUseLightColorSet = ! fUseLightColorSet;
661  for (List_i i=fChildren.begin(); i!=fChildren.end(); ++i)
662  {
663  TGLViewer* glv = ((TEveViewer*)*i)->GetGLViewer();
664  if ( fUseLightColorSet)
665  glv->UseLightColorSet();
666  else
667  glv->UseDarkColorSet();
668 
669  glv->RequestDraw(TGLRnrCtx::kLODHigh);
670  }
671 }