TGLEventHandler.cxx

Go to the documentation of this file.
00001 // @(#)root/gl:$Id: TGLEventHandler.cxx 34337 2010-07-06 10:20:38Z matevz $
00002 // Author: Bertrand Bellenot   29/01/2008
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2008, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 //////////////////////////////////////////////////////////////////////////
00013 //                                                                      //
00014 // TGLEventHandler                                                      //
00015 //                                                                      //
00016 //////////////////////////////////////////////////////////////////////////
00017 
00018 
00019 #include "TGLEventHandler.h"
00020 #include "TGEventHandler.h"
00021 #include "TGLViewer.h"
00022 #include "TGLWidget.h"
00023 #include "TGWindow.h"
00024 #include "TPoint.h"
00025 #include "TVirtualPad.h" // Remove when pad removed - use signal
00026 #include "TVirtualX.h"
00027 #include "TGClient.h"
00028 #include "TVirtualGL.h"
00029 #include "TGLOverlay.h"
00030 #include "TGLLogicalShape.h"
00031 #include "TGLPhysicalShape.h"
00032 #include "TContextMenu.h"
00033 #include "TGToolTip.h"
00034 #include "KeySymbols.h"
00035 #include "TGLAnnotation.h"
00036 #include "TEnv.h"
00037 #include "TMath.h"
00038 
00039 //______________________________________________________________________________
00040 //
00041 // Base-class and default implementation of event-handler for TGLViewer.
00042 //
00043 // This allows for complete disentanglement of GL-viewer from GUI
00044 // event handling. Further, alternative event-handlers can easily be
00045 // designed and set at run-time.
00046 //
00047 // The signals about object being selected or hovered above are
00048 // emitted via the TGLViewer itself.
00049 //
00050 // The following rootrc settings influence the behaviour:
00051 // OpenGL.EventHandler.ViewerCentricControls:  1
00052 // OpenGL.EventHandler.ArrowKeyFactor:        -1.0
00053 // OpenGL.EventHandler.MouseDragFactor:       -1.0
00054 // OpenGL.EventHandler.MouseWheelFactor:      -1.0
00055 
00056 
00057 ClassImp(TGLEventHandler);
00058 
00059 //______________________________________________________________________________
00060 TGLEventHandler::TGLEventHandler(TGWindow *w, TObject *obj) :
00061    TGEventHandler      ("TGLEventHandler", w, obj),
00062    fGLViewer           ((TGLViewer *)obj),
00063    fMouseTimer         (0),
00064    fLastPos            (-1, -1),
00065    fLastMouseOverPos   (-1, -1),
00066    fLastMouseOverShape (0),
00067    fTooltip            (0),
00068    fActiveButtonID     (0),
00069    fLastEventState     (0),
00070    fIgnoreButtonUp     (kFALSE),
00071    fInPointerGrab      (kFALSE),
00072    fMouseTimerRunning  (kFALSE),
00073    fTooltipShown       (kFALSE),
00074    fTooltipPixelTolerance (3),
00075    fSecSelType(TGLViewer::kOnRequest),
00076    fDoInternalSelection(kTRUE),
00077    fViewerCentricControls(kFALSE)
00078 {
00079    // Constructor.
00080 
00081    fMouseTimer = new TTimer(this, 80);
00082    fTooltip    = new TGToolTip(0, 0, "", 650);
00083    fTooltip->Hide();
00084    fViewerCentricControls = gEnv->GetValue("OpenGL.EventHandler.ViewerCentricControls", 0) != 0;
00085    fArrowKeyFactor   = gEnv->GetValue("OpenGL.EventHandler.ArrowKeyFactor",   1.0);
00086    fMouseDragFactor  = gEnv->GetValue("OpenGL.EventHandler.MouseDragFactor",  1.0);
00087    fMouseWheelFactor = gEnv->GetValue("OpenGL.EventHandler.MouseWheelFactor", 1.0);
00088 }
00089 
00090 //______________________________________________________________________________
00091 TGLEventHandler::~TGLEventHandler()
00092 {
00093    // Destructor.
00094 
00095    delete fMouseTimer;
00096    delete fTooltip;
00097 }
00098 
00099 //______________________________________________________________________________
00100 void TGLEventHandler::GrabMouse()
00101 {
00102    // Acquire mouse grab.
00103 
00104    if (!fInPointerGrab)
00105    {
00106       gVirtualX->GrabPointer(fGLViewer->GetGLWidget()->GetId(),
00107                              kButtonPressMask | kButtonReleaseMask | kPointerMotionMask,
00108                              kNone, kNone, kTRUE, kFALSE);
00109       fInPointerGrab = kTRUE;
00110    }
00111 }
00112 
00113 //______________________________________________________________________________
00114 void TGLEventHandler::UnGrabMouse()
00115 {
00116    // Release mouse grab.
00117 
00118    if (fInPointerGrab)
00119    {
00120       gVirtualX->GrabPointer(0, 0, 0, 0, kFALSE);
00121       fInPointerGrab = kFALSE;
00122    }
00123 }
00124 
00125 //______________________________________________________________________________
00126 void TGLEventHandler::SelectForClicked(Event_t *event)
00127 {
00128    // Run selection (optionally with on secondary selection) and emit
00129    // corresponding Clicked() signals.
00130    // Protected method.
00131 
00132    fGLViewer->RequestSelect(fLastPos.fX, fLastPos.fY);
00133 
00134    TGLPhysicalShape *pshp = fGLViewer->fSelRec.GetPhysShape();
00135    TGLLogicalShape  *lshp = pshp ? const_cast<TGLLogicalShape*>(pshp->GetLogical()) : 0;
00136    TObject          *obj  = lshp ? lshp->GetExternal() : 0;
00137       
00138    // secondary selection
00139    if (lshp && (event->fState & kKeyMod1Mask || (fSecSelType == TGLViewer::kOnRequest && lshp->AlwaysSecondarySelect())))
00140    {
00141       fGLViewer->RequestSecondarySelect(fLastPos.fX, fLastPos.fY);
00142       fGLViewer->fSecSelRec.SetMultiple(event->fState & kKeyControlMask);
00143 
00144       lshp->ProcessSelection(*fGLViewer->fRnrCtx, fGLViewer->fSecSelRec);
00145 
00146       switch (fGLViewer->fSecSelRec.GetSecSelResult())
00147       {
00148          case TGLSelectRecord::kEnteringSelection:
00149             fGLViewer->Clicked(obj, event->fCode, event->fState);
00150             break;
00151          case TGLSelectRecord::kLeavingSelection:
00152             fGLViewer->UnClicked(obj, event->fCode, event->fState);
00153             break;
00154          case TGLSelectRecord::kModifyingInternalSelection:
00155             fGLViewer->ReClicked(obj, event->fCode, event->fState);
00156             break;
00157          default:
00158             break;
00159       }
00160    }
00161    else
00162    {
00163       fGLViewer->Clicked(obj);
00164       fGLViewer->Clicked(obj, event->fCode, event->fState);
00165    }
00166 }
00167 
00168 //______________________________________________________________________________
00169 void TGLEventHandler::SelectForMouseOver()
00170 {
00171    // Run selection (optionally with on secondary selection) and emit
00172    // corresponding MouseOver() signals.
00173    // Protected method.
00174 
00175    fGLViewer->RequestSelect(fLastPos.fX, fLastPos.fY);
00176 
00177    TGLPhysicalShape *pshp = fGLViewer->fSelRec.GetPhysShape();
00178    TGLLogicalShape  *lshp = pshp ? const_cast<TGLLogicalShape*>(pshp->GetLogical()) : 0;
00179    TObject          *obj  = lshp ? lshp->GetExternal() : 0;
00180 
00181    if (lshp && (fSecSelType == TGLViewer::kOnRequest && lshp->AlwaysSecondarySelect()))
00182    {
00183       fGLViewer->RequestSecondarySelect(fLastPos.fX, fLastPos.fY);
00184       fGLViewer->fSecSelRec.SetMultiple(kFALSE);
00185       fGLViewer->fSecSelRec.SetHighlight(kTRUE);
00186 
00187       lshp->ProcessSelection(*fGLViewer->fRnrCtx, fGLViewer->fSecSelRec);
00188 
00189       fGLViewer->fSecSelRec.SetHighlight(kFALSE);
00190 
00191       switch (fGLViewer->fSecSelRec.GetSecSelResult())
00192       {
00193          case TGLSelectRecord::kEnteringSelection:
00194             fGLViewer->MouseOver(obj, fLastEventState);
00195             break;
00196          case TGLSelectRecord::kModifyingInternalSelection:
00197             fGLViewer->ReMouseOver(obj, fLastEventState);
00198             break;
00199          case TGLSelectRecord::kLeavingSelection:
00200             fGLViewer->UnMouseOver(obj, fLastEventState);
00201             break;
00202          default:
00203             break;
00204       }
00205    }
00206    else if (fLastMouseOverShape != pshp)
00207    {
00208       fGLViewer->MouseOver(pshp);
00209       fGLViewer->MouseOver(pshp, fLastEventState);
00210       fGLViewer->MouseOver(obj,  fLastEventState);
00211    }
00212    fLastMouseOverShape = pshp;
00213    fLastMouseOverPos   = fLastPos;
00214 }
00215 
00216 //==============================================================================
00217 
00218 //______________________________________________________________________________
00219 void TGLEventHandler::ExecuteEvent(Int_t event, Int_t px, Int_t py)
00220 {
00221    // Process event of type 'event' - one of EEventType types,
00222    // occuring at window location px, py
00223    // This is provided for use when embedding GL viewer into pad
00224 
00225    /*enum EEventType {
00226    kNoEvent       =  0,
00227    kButton1Down   =  1, kButton2Down   =  2, kButton3Down   =  3, kKeyDown  =  4,
00228    kButton1Up     = 11, kButton2Up     = 12, kButton3Up     = 13, kKeyUp    = 14,
00229    kButton1Motion = 21, kButton2Motion = 22, kButton3Motion = 23, kKeyPress = 24,
00230    kButton1Locate = 41, kButton2Locate = 42, kButton3Locate = 43,
00231    kMouseMotion   = 51, kMouseEnter    = 52, kMouseLeave    = 53,
00232    kButton1Double = 61, kButton2Double = 62, kButton3Double = 63
00233 
00234    enum EGEventType {
00235    kGKeyPress, kKeyRelease, kButtonPress, kButtonRelease,
00236    kMotionNotify, kEnterNotify, kLeaveNotify, kFocusIn, kFocusOut,
00237    kExpose, kConfigureNotify, kMapNotify, kUnmapNotify, kDestroyNotify,
00238    kClientMessage, kSelectionClear, kSelectionRequest, kSelectionNotify,
00239    kColormapNotify, kButtonDoubleClick, kOtherEvent*/
00240 
00241    // Map our event EEventType (base/inc/Buttons.h) back to Event_t (base/inc/GuiTypes.h)
00242    // structure, and call appropriate HandleXyzz() function
00243    Event_t eventSt;
00244    eventSt.fX = px;
00245    eventSt.fY = py;
00246    eventSt.fState = 0;
00247 
00248    if (event != kKeyPress) {
00249       eventSt.fY -= Int_t((1 - gPad->GetHNDC() - gPad->GetYlowNDC()) * gPad->GetWh());
00250       eventSt.fX -= Int_t(gPad->GetXlowNDC() * gPad->GetWw());
00251    }
00252 
00253    switch (event) {
00254       case kMouseMotion:
00255          eventSt.fCode = kMouseMotion;
00256          eventSt.fType = kMotionNotify;
00257          HandleMotion(&eventSt);
00258          break;
00259       case kButton1Down:
00260       case kButton1Up:
00261       {
00262          eventSt.fCode = kButton1;
00263          eventSt.fType = event == kButton1Down ? kButtonPress:kButtonRelease;
00264          HandleButton(&eventSt);
00265       }
00266       break;
00267       case kButton2Down:
00268       case kButton2Up:
00269       {
00270          eventSt.fCode = kButton2;
00271          eventSt.fType = event == kButton2Down ? kButtonPress:kButtonRelease;
00272          HandleButton(&eventSt);
00273       }
00274       break;
00275       case kButton3Down:
00276       {
00277          eventSt.fState = kKeyShiftMask;
00278          eventSt.fCode = kButton1;
00279          eventSt.fType = kButtonPress;
00280          HandleButton(&eventSt);
00281       }
00282       break;
00283       case kButton3Up:
00284       {
00285          eventSt.fCode = kButton3;
00286          eventSt.fType = kButtonRelease;//event == kButton3Down ? kButtonPress:kButtonRelease;
00287          HandleButton(&eventSt);
00288       }
00289       break;
00290       case kButton1Double:
00291       case kButton2Double:
00292       case kButton3Double:
00293       {
00294          eventSt.fCode = kButton1Double ? kButton1 : kButton2Double ? kButton2 : kButton3;
00295          eventSt.fType = kButtonDoubleClick;
00296          HandleDoubleClick(&eventSt);
00297       }
00298       break;
00299       case kButton1Motion:
00300       case kButton2Motion:
00301       case kButton3Motion:
00302       {
00303 
00304          eventSt.fCode = event == kButton1Motion ? kButton1 : event == kButton2Motion ? kButton2 : kButton3;
00305          eventSt.fType = kMotionNotify;
00306          HandleMotion(&eventSt);
00307       }
00308       break;
00309       case kKeyPress: // We only care about full key 'presses' not individual down/up
00310       {
00311          eventSt.fType = kGKeyPress;
00312          eventSt.fCode = py; // px contains key code - need modifiers from somewhere
00313          HandleKey(&eventSt);
00314       }
00315       break;
00316       case 6://trick :)
00317          if (fGLViewer->CurrentCamera().Zoom(+50, kFALSE, kFALSE)) { //TODO : val static const somewhere
00318             if (fGLViewer->fGLDevice != -1) {
00319                gGLManager->MarkForDirectCopy(fGLViewer->fGLDevice, kTRUE);
00320                gVirtualX->SetDrawMode(TVirtualX::kCopy);
00321             }
00322             fGLViewer->RequestDraw();
00323          }
00324          break;
00325       case 5://trick :)
00326          if (fGLViewer->CurrentCamera().Zoom(-50, kFALSE, kFALSE)) { //TODO : val static const somewhere
00327             if (fGLViewer->fGLDevice != -1) {
00328                gGLManager->MarkForDirectCopy(fGLViewer->fGLDevice, kTRUE);
00329                gVirtualX->SetDrawMode(TVirtualX::kCopy);
00330             }
00331             fGLViewer->RequestDraw();
00332          }
00333          break;
00334       case 7://trick :)
00335          eventSt.fState = kKeyShiftMask;
00336          eventSt.fCode = kButton1;
00337          eventSt.fType = kButtonPress;
00338          HandleButton(&eventSt);
00339          break;
00340       default:
00341       {
00342         // Error("TGLEventHandler::ExecuteEvent", "invalid event type");
00343       }
00344    }
00345 }
00346 
00347 //______________________________________________________________________________
00348 Bool_t TGLEventHandler::HandleEvent(Event_t *event)
00349 {
00350    // Handle generic Event_t type 'event' - provided to catch focus changes
00351    // and terminate any interaction in viewer.
00352 
00353    if (event->fType == kFocusIn) {
00354       if (fGLViewer->fDragAction != TGLViewer::kDragNone) {
00355          Error("TGLEventHandler::HandleEvent", "active drag-action at focus-in.");
00356          fGLViewer->fDragAction = TGLViewer::kDragNone;
00357       }
00358       StartMouseTimer();
00359    }
00360    if (event->fType == kFocusOut) {
00361       if (fGLViewer->fDragAction != TGLViewer::kDragNone) {
00362          Warning("TGLEventHandler::HandleEvent", "drag-action active at focus-out.");
00363          fGLViewer->fDragAction = TGLViewer::kDragNone;
00364       }
00365       StopMouseTimer();
00366       ClearMouseOver();
00367    }
00368 
00369    return kTRUE;
00370 }
00371 
00372 //______________________________________________________________________________
00373 Bool_t TGLEventHandler::HandleFocusChange(Event_t *event)
00374 {
00375    // Handle generic Event_t type 'event' - provided to catch focus changes
00376    // and terminate any interaction in viewer.
00377 
00378    fGLViewer->MouseIdle(0, 0, 0);
00379    if (event->fType == kFocusIn) {
00380       if (fGLViewer->fDragAction != TGLViewer::kDragNone) {
00381          Error("TGLEventHandler::HandleFocusChange", "active drag-action at focus-in.");
00382          fGLViewer->fDragAction = TGLViewer::kDragNone;
00383       }
00384       StartMouseTimer();
00385       fGLViewer->Activated();
00386    }
00387    if (event->fType == kFocusOut) {
00388       if (fGLViewer->fDragAction != TGLViewer::kDragNone) {
00389          Warning("TGLEventHandler::HandleFocusChange", "drag-action active at focus-out.");
00390          fGLViewer->fDragAction = TGLViewer::kDragNone;
00391       }
00392       StopMouseTimer();
00393       ClearMouseOver();
00394    }
00395 
00396    return kTRUE;
00397 }
00398 
00399 //______________________________________________________________________________
00400 Bool_t TGLEventHandler::HandleCrossing(Event_t *event)
00401 {
00402    // Handle generic Event_t type 'event' - provided to catch focus changes
00403    // and terminate any interaction in viewer.
00404 
00405    // Ignore grab and ungrab events.
00406    if (event->fCode != 0) {
00407       return kTRUE;
00408    }
00409 
00410    fGLViewer->MouseIdle(0, 0, 0);
00411    if (event->fType == kEnterNotify) {
00412       if (fGLViewer->fDragAction != TGLViewer::kDragNone) {
00413          Error("TGLEventHandler::HandleCrossing", "active drag-action at enter-notify.");
00414          fGLViewer->fDragAction = TGLViewer::kDragNone;
00415       }
00416       StartMouseTimer();
00417       // Maybe, maybe not...
00418       fGLViewer->Activated();
00419    }
00420    if (event->fType == kLeaveNotify) {
00421       if (fGLViewer->fDragAction != TGLViewer::kDragNone) {
00422          Warning("TGLEventHandler::HandleCrossing", "drag-action active at leave-notify.");
00423          fGLViewer->fDragAction = TGLViewer::kDragNone;
00424       }
00425       StopMouseTimer();
00426       ClearMouseOver();
00427    }
00428 
00429    return kTRUE;
00430 }
00431 
00432 //______________________________________________________________________________
00433 Bool_t TGLEventHandler::HandleButton(Event_t * event)
00434 {
00435    // Handle mouse button 'event'.
00436 
00437    if (fGLViewer->IsLocked()) {
00438       if (gDebug>2) {
00439          Info("TGLEventHandler::HandleButton", "ignored - viewer is %s",
00440               fGLViewer->LockName(fGLViewer->CurrentLock()));
00441       }
00442       return kFALSE;
00443    }
00444 
00445    // Handle mouse-wheel events first.
00446    if (event->fCode > kButton3)
00447    {
00448       // On Win32 only button release events come for mouse wheel.
00449       // Note: Modifiers (ctrl/shift) disabled as fState doesn't seem to
00450       // have correct modifier flags with mouse wheel under Windows.
00451 
00452       if (event->fType == kButtonRelease)
00453       {
00454          Bool_t redraw = kFALSE;
00455 
00456          Int_t zoom = TMath::Nint(fMouseWheelFactor * ControlValue(50));
00457          switch(event->fCode)
00458          {
00459             case kButton5: // Zoom out (dolly or adjust camera FOV).
00460                redraw = fGLViewer->CurrentCamera().Zoom(zoom, kFALSE, kFALSE);
00461                break;
00462 
00463             case kButton4: // Zoom in (dolly or adjust camera FOV).
00464                redraw = fGLViewer->CurrentCamera().Zoom(-zoom, kFALSE, kFALSE);
00465                break;
00466 
00467             case kButton6:
00468             case kButton7: // Ignore for now.
00469                break;
00470          }
00471 
00472          if (redraw)
00473             fGLViewer->fRedrawTimer->RequestDraw(10, TGLRnrCtx::kLODMed);
00474       }
00475       return kTRUE;
00476    }
00477 
00478    // Now we know we have Button 1 -> 3.
00479    // Allow a single action/button down/up pairing - block others
00480    if (fActiveButtonID && event->fCode != fActiveButtonID)
00481    {
00482       return kTRUE;
00483    }
00484    else
00485    {
00486       fActiveButtonID = event->fCode;
00487    }
00488 
00489 
00490    // Button DOWN
00491    if (event->fType == kButtonPress)
00492    {
00493       GrabMouse();
00494 
00495       fGLViewer->MouseIdle(0, 0, 0);
00496 
00497       fButtonPushPos.fX = event->fX;
00498       fButtonPushPos.fY = event->fY;
00499 
00500       if (fGLViewer->GetPushAction() != TGLViewer::kPushStd)
00501       {
00502          fGLViewer->RequestSelect(event->fX, event->fY);
00503          if (fGLViewer->fSelRec.GetN() > 0)
00504          {
00505             TGLVector3 v(event->fX, event->fY, 0.5*fGLViewer->fSelRec.GetMinZ());
00506             fGLViewer->CurrentCamera().WindowToViewport(v);
00507             v = fGLViewer->CurrentCamera().ViewportToWorld(v);
00508             if (fGLViewer->GetPushAction() == TGLViewer::kPushCamCenter)
00509             {
00510                fGLViewer->CurrentCamera().SetExternalCenter(kTRUE);
00511                fGLViewer->CurrentCamera().SetCenterVec(v.X(), v.Y(), v.Z());
00512             }
00513             else
00514             {
00515                TGLSelectRecord& rec = fGLViewer->GetSelRec();
00516                TObject* obj = rec.GetObject();
00517                TGLRect& vp = fGLViewer->CurrentCamera().RefViewport();
00518                new TGLAnnotation(fGLViewer, obj->GetTitle(),
00519                                  event->fX * 1.0f/vp.Width(),
00520                                  1 - event->fY * 1.0f/vp.Height(), v);
00521             }
00522 
00523             fGLViewer->RequestDraw();
00524          }
00525          return kTRUE;
00526       }
00527 
00528       Bool_t handled = kFALSE;
00529 
00530       if (fGLViewer->fDragAction == TGLViewer::kDragNone && fGLViewer->fCurrentOvlElm)
00531       {
00532          if (fGLViewer->fCurrentOvlElm->Handle(*fGLViewer->fRnrCtx, fGLViewer->fOvlSelRec, event))
00533          {
00534             handled     = kTRUE;
00535             fGLViewer->fDragAction = TGLViewer::kDragOverlay;
00536             fGLViewer->RequestDraw();
00537          }
00538       }
00539 
00540       if ( ! handled)
00541       {
00542          switch(event->fCode)
00543          {
00544             // LEFT mouse button
00545             case kButton1:
00546             {
00547                fGLViewer->fDragAction = TGLViewer::kDragCameraRotate;
00548                if (fMouseTimer)
00549                {
00550                   fMouseTimer->TurnOff();
00551                   fMouseTimer->Reset();
00552                }
00553                break;
00554             }
00555             // MIDDLE mouse button
00556             case kButton2:
00557             {
00558                fGLViewer->fDragAction = TGLViewer::kDragCameraTruck;
00559                break;
00560             }
00561             // RIGHT mouse button
00562             case kButton3:
00563             {
00564                fGLViewer->fDragAction = TGLViewer::kDragCameraDolly;
00565                break;
00566             }
00567          }
00568       }
00569    }
00570    // Button UP
00571    else if (event->fType == kButtonRelease)
00572    {
00573       fActiveButtonID = 0;
00574 
00575       if (fInPointerGrab)
00576       {
00577          UnGrabMouse();
00578       }
00579       else
00580       {
00581          Warning("TGLEventHandler::HandleButton", "Unexpected button-release.");
00582       }
00583 
00584       if (fIgnoreButtonUp)
00585       {
00586          fIgnoreButtonUp = kFALSE;
00587          return kTRUE;
00588       }
00589 
00590       if (fGLViewer->GetPushAction() != TGLViewer::kPushStd)
00591       {
00592          // This should be 'tool' dependant.
00593          fGLViewer->fPushAction = TGLViewer::kPushStd;
00594          fGLViewer->RefreshPadEditor(fGLViewer);
00595          return kTRUE;
00596       }
00597       else if (fGLViewer->fDragAction == TGLViewer::kDragOverlay && fGLViewer->fCurrentOvlElm)
00598       {
00599          fGLViewer->fCurrentOvlElm->Handle(*fGLViewer->fRnrCtx, fGLViewer->fOvlSelRec, event);
00600          fGLViewer->OverlayDragFinished();
00601          if (fGLViewer->RequestOverlaySelect(event->fX, event->fY))
00602             fGLViewer->RequestDraw();
00603       }
00604       else if (fGLViewer->fDragAction >= TGLViewer::kDragCameraRotate &&
00605                fGLViewer->fDragAction <= TGLViewer::kDragCameraDolly)
00606       {
00607          fGLViewer->RequestDraw(TGLRnrCtx::kLODHigh);
00608       }
00609 
00610       fGLViewer->fDragAction = TGLViewer::kDragNone;
00611 
00612       if (fGLViewer->fGLDevice != -1)
00613       {
00614          gGLManager->MarkForDirectCopy(fGLViewer->fGLDevice, kFALSE);
00615       }
00616 
00617       if (event->fX == fButtonPushPos.fX && event->fY == fButtonPushPos.fY)
00618       {
00619          if (event->fCode == kButton1)
00620          {
00621             if (event->fState & kKeyShiftMask && fDoInternalSelection)
00622             {
00623                if (fGLViewer->RequestSelect(event->fX, event->fY))
00624                {
00625                   fGLViewer->ApplySelection();
00626                }
00627             }
00628             else
00629             {
00630                SelectForClicked(event);
00631             }
00632          }
00633          else if (event->fCode == kButton3)
00634          {
00635             Int_t    x, y;
00636             Window_t childdum;
00637             gVirtualX->TranslateCoordinates(fGLViewer->fGLWidget->GetId(), gClient->GetDefaultRoot()->GetId(),
00638                                             event->fX, event->fY, x, y, childdum);
00639 
00640             fGLViewer->RequestSelect(event->fX, event->fY);
00641 
00642             PopupContextMenu(fGLViewer->fSelRec.GetPhysShape(), event, x, y);
00643          }
00644       }
00645 
00646       if (event->fCode == kButton1 && fMouseTimer)
00647       {
00648          fMouseTimer->TurnOn();
00649       }
00650    }
00651 
00652    return kTRUE;
00653 }
00654 
00655 //______________________________________________________________________________
00656 Bool_t TGLEventHandler::HandleDoubleClick(Event_t *event)
00657 {
00658    // Handle mouse double click 'event'.
00659 
00660    if (fGLViewer->IsLocked()) {
00661       if (gDebug>3) {
00662          Info("TGLEventHandler::HandleDoubleClick", "ignored - viewer is %s",
00663             fGLViewer->LockName(fGLViewer->CurrentLock()));
00664       }
00665       return kFALSE;
00666    }
00667 
00668    if (event->fCode > 3)
00669       return kTRUE;
00670 
00671    if (fActiveButtonID)
00672       return kTRUE;
00673 
00674    fActiveButtonID = event->fCode;
00675    GrabMouse();
00676 
00677    fGLViewer->MouseIdle(0, 0, 0);
00678    if (event->fCode == kButton1)
00679    {
00680       fGLViewer->DoubleClicked();
00681       if (fGLViewer->GetSelected() == 0)
00682          fGLViewer->SelectionChanged();
00683    }
00684    return kTRUE;
00685 }
00686 
00687 //______________________________________________________________________________
00688 Bool_t TGLEventHandler::HandleConfigureNotify(Event_t *event)
00689 {
00690    // Handle configure notify 'event' - a window resize/movement.
00691 
00692    if (fGLViewer->IsLocked())
00693    {
00694       if (gDebug > 0) {
00695          Info("TGLEventHandler::HandleConfigureNotify", "ignored - viewer is %s",
00696             fGLViewer->LockName(fGLViewer->CurrentLock()));
00697       }
00698       return kFALSE;
00699    }
00700    if (event)
00701    {
00702       fGLViewer->SetViewport(event->fX, event->fY, event->fWidth, event->fHeight);
00703       fGLViewer->fRedrawTimer->RequestDraw(10, TGLRnrCtx::kLODMed);
00704    }
00705    return kTRUE;
00706 }
00707 
00708 //______________________________________________________________________________
00709 Bool_t TGLEventHandler::HandleExpose(Event_t * event)
00710 {
00711    // Handle window expose 'event' - show.
00712 
00713    if (event->fCount != 0) return kTRUE;
00714 
00715    if (fGLViewer->IsLocked()) {
00716       if (gDebug > 0) {
00717          Info("TGLViewer::HandleExpose", "ignored - viewer is %s",
00718             fGLViewer->LockName(fGLViewer->CurrentLock()));
00719       }
00720       return kFALSE;
00721    }
00722 
00723    fGLViewer->fRedrawTimer->RequestDraw(20, TGLRnrCtx::kLODHigh);
00724    return kTRUE;
00725 }
00726 
00727 //______________________________________________________________________________
00728 Bool_t TGLEventHandler::HandleKey(Event_t *event)
00729 {
00730    // Handle keyboard 'event'.
00731 
00732    // We only handle key-press events.
00733    if (event->fType == kKeyRelease)
00734       return kTRUE;
00735 
00736    if (fTooltipShown)
00737       fTooltip->Hide();
00738 
00739    fLastEventState = event->fState;
00740 
00741    fGLViewer->MouseIdle(0, 0, 0);
00742    if (fGLViewer->IsLocked()) {
00743       if (gDebug>3) {
00744          Info("TGLEventHandler::HandleKey", "ignored - viewer is %s",
00745               fGLViewer->LockName(fGLViewer->CurrentLock()));
00746       }
00747       return kFALSE;
00748    }
00749 
00750    char tmp[10] = {0};
00751    UInt_t keysym = 0;
00752 
00753    if (fGLViewer->fGLDevice == -1)
00754       gVirtualX->LookupString(event, tmp, sizeof(tmp), keysym);
00755    else
00756       keysym = event->fCode;
00757    fGLViewer->fRnrCtx->SetEventKeySym(keysym);
00758 
00759    Bool_t redraw = kFALSE;
00760    if (fGLViewer->fCurrentOvlElm &&
00761        fGLViewer->fCurrentOvlElm->Handle(*fGLViewer->fRnrCtx, fGLViewer->fOvlSelRec, event))
00762    {
00763       redraw = kTRUE;
00764    }
00765    else
00766    {
00767       const Bool_t mod1 = event->fState & kKeyControlMask;
00768       const Bool_t mod2 = event->fState & kKeyShiftMask;
00769 
00770       const Int_t shift = TMath::Nint(fArrowKeyFactor * ControlValue(10));
00771 
00772       switch (keysym)
00773       {
00774          case kKey_R:
00775          case kKey_r:
00776             fGLViewer->SetStyle(TGLRnrCtx::kFill);
00777             redraw = kTRUE;
00778             break;
00779          case kKey_E:
00780          case kKey_e:
00781             fGLViewer->SwitchColorSet();
00782             redraw = kTRUE;
00783             break;
00784          case kKey_W:
00785          case kKey_w:
00786             fGLViewer->SetStyle(TGLRnrCtx::kWireFrame);
00787             redraw = kTRUE;
00788             break;
00789          case kKey_T:
00790          case kKey_t:
00791             fGLViewer->SetStyle(TGLRnrCtx::kOutline);
00792             redraw = kTRUE;
00793             break;
00794 
00795          case kKey_F1:
00796             fGLViewer->RequestSelect(fLastPos.fX, fLastPos.fY);
00797             fGLViewer->MouseIdle(fGLViewer->fSelRec.GetPhysShape(), (UInt_t)fLastPos.fX, (UInt_t)fLastPos.fY);
00798             break;
00799 
00800             // Camera
00801          case kKey_Plus:
00802          case kKey_J:
00803          case kKey_j:
00804             redraw = fGLViewer->CurrentCamera().Dolly(shift, mod1, mod2);
00805             break;
00806          case kKey_Minus:
00807          case kKey_K:
00808          case kKey_k:
00809             redraw = fGLViewer->CurrentCamera().Dolly(-shift, mod1, mod2);
00810             break;
00811          case kKey_Up:
00812             redraw = fGLViewer->CurrentCamera().Truck(0, shift, mod1, mod2);
00813             break;
00814          case kKey_Down:
00815             redraw = fGLViewer->CurrentCamera().Truck(0, -shift, mod1, mod2);
00816             break;
00817          case kKey_Left:
00818             redraw = fGLViewer->CurrentCamera().Truck(-shift, 0, mod1, mod2);
00819             break;
00820          case kKey_Right:
00821             redraw = fGLViewer->CurrentCamera().Truck(shift, 0, mod1, mod2);
00822             break;
00823          case kKey_Home:
00824             if (mod1) {
00825                TGLCamera &cam = fGLViewer->CurrentCamera();
00826                cam.SetExternalCenter(!cam.GetExternalCenter());
00827                fGLViewer->RefreshPadEditor(fGLViewer);
00828             } else {
00829                fGLViewer->ResetCurrentCamera();
00830             }
00831             redraw = kTRUE;
00832             break;
00833 
00834             // Toggle debugging mode
00835          case kKey_d:
00836             fGLViewer->fDebugMode = !fGLViewer->fDebugMode;
00837             redraw = kTRUE;
00838             Info("OpenGL viewer debug mode : ", fGLViewer->fDebugMode ? "ON" : "OFF");
00839             break;
00840             // Forced rebuild for debugging mode
00841          case kKey_D:
00842             if (fGLViewer->fDebugMode) {
00843                Info("OpenGL viewer FORCED rebuild", " ");
00844                fGLViewer->UpdateScene();
00845             }
00846          default:;
00847       } // switch
00848    }
00849 
00850    if (redraw) {
00851       if (fGLViewer->fGLDevice != -1)
00852          gGLManager->MarkForDirectCopy(fGLViewer->fGLDevice, kTRUE);
00853       fGLViewer->RequestDraw();
00854    }
00855 
00856    return kTRUE;
00857 }
00858 
00859 //______________________________________________________________________________
00860 Bool_t TGLEventHandler::HandleMotion(Event_t * event)
00861 {
00862    // Handle mouse motion 'event'.
00863 
00864    fGLViewer->MouseIdle(0, 0, 0);
00865    if (fGLViewer->IsLocked()) {
00866       if (gDebug>3) {
00867          Info("TGLEventHandler::HandleMotion", "ignored - viewer is %s",
00868               fGLViewer->LockName(fGLViewer->CurrentLock()));
00869       }
00870       return kFALSE;
00871    }
00872 
00873    Bool_t processed = kFALSE, changed = kFALSE;
00874    Short_t lod = TGLRnrCtx::kLODMed;
00875 
00876    // Camera interface requires GL coords - Y inverted
00877    Int_t  xDelta = TMath::Nint(fMouseDragFactor * ControlValue(event->fX - fLastPos.fX));
00878    Int_t  yDelta = TMath::Nint(fMouseDragFactor * ControlValue(event->fY - fLastPos.fY));
00879    Bool_t mod1   = event->fState & kKeyControlMask;
00880    Bool_t mod2   = event->fState & kKeyShiftMask;
00881 
00882    if (fMouseTimerRunning) StopMouseTimer();
00883 
00884    if (fTooltipShown &&
00885        ( TMath::Abs(event->fXRoot - fTooltipPos.fX) > fTooltipPixelTolerance ||
00886          TMath::Abs(event->fYRoot - fTooltipPos.fY) > fTooltipPixelTolerance ))
00887    {
00888       RemoveTooltip();
00889    }
00890 
00891    if (fGLViewer->fDragAction == TGLViewer::kDragNone)
00892    {
00893       if (fGLViewer->fRedrawTimer->IsPending()) {
00894          if (gDebug > 2)
00895             Info("TGLEventHandler::HandleMotion", "Redraw pending, ignoring.");
00896          return kTRUE;
00897       }
00898       changed = fGLViewer->RequestOverlaySelect(event->fX, event->fY);
00899       if (fGLViewer->fCurrentOvlElm)
00900          processed = fGLViewer->fCurrentOvlElm->Handle(*fGLViewer->fRnrCtx, fGLViewer->fOvlSelRec, event);
00901       lod = TGLRnrCtx::kLODHigh;
00902       if ( ! processed && ! fMouseTimerRunning)
00903          StartMouseTimer();
00904    }
00905    else if (fGLViewer->fDragAction == TGLViewer::kDragCameraRotate)
00906    {
00907       processed = Rotate(xDelta, yDelta, mod1, mod2);
00908    }
00909    else if (fGLViewer->fDragAction == TGLViewer::kDragCameraTruck)
00910    {
00911       processed = fGLViewer->CurrentCamera().Truck(xDelta, -yDelta, mod1, mod2);
00912    }
00913    else if (fGLViewer->fDragAction == TGLViewer::kDragCameraDolly)
00914    {
00915       processed = fGLViewer->CurrentCamera().Dolly(yDelta - xDelta, mod1, mod2);
00916    }
00917    else if (fGLViewer->fDragAction == TGLViewer::kDragOverlay)
00918    {
00919       if (fGLViewer->fCurrentOvlElm)
00920          processed = fGLViewer->fCurrentOvlElm->Handle(*fGLViewer->fRnrCtx, fGLViewer->fOvlSelRec, event);
00921    }
00922 
00923    fLastPos.fX = event->fX;
00924    fLastPos.fY = event->fY;
00925 
00926    fLastGlobalPos.fX = event->fXRoot;
00927    fLastGlobalPos.fY = event->fYRoot;
00928 
00929    if (processed || changed) {
00930       if (fGLViewer->fGLDevice != -1) {
00931          gGLManager->MarkForDirectCopy(fGLViewer->fGLDevice, kTRUE);
00932          gVirtualX->SetDrawMode(TVirtualX::kCopy);
00933       }
00934 
00935       fGLViewer->RequestDraw(lod);
00936    }
00937 
00938    return processed;
00939 }
00940 
00941 //______________________________________________________________________________
00942 Bool_t TGLEventHandler::Rotate(Int_t xDelta, Int_t yDelta, Bool_t mod1, Bool_t mod2)
00943 {
00944    // Method to handle action TGLViewer::kDragCameraRotate.
00945 
00946    return fGLViewer->CurrentCamera().Rotate(xDelta, -yDelta, mod1, mod2);
00947 }
00948 
00949 //______________________________________________________________________________
00950 Bool_t TGLEventHandler::HandleTimer(TTimer *t)
00951 {
00952    // If mouse delay timer times out emit signal.
00953 
00954    if (t != fMouseTimer) return kFALSE;
00955 
00956    fMouseTimerRunning = kFALSE;
00957 
00958    if (fGLViewer->fRedrawTimer->IsPending()) {
00959       if (gDebug > 2)
00960          Info("TGLEventHandler::HandleTimer", "Redraw pending, ignoring.");
00961       return kTRUE;
00962    }
00963 
00964    if (fGLViewer->fDragAction == TGLViewer::kDragNone)
00965    {
00966       if (fLastMouseOverPos != fLastPos)
00967       {
00968          SelectForMouseOver();
00969       }
00970    }
00971    return kTRUE;
00972 }
00973 
00974 //______________________________________________________________________________
00975 void TGLEventHandler::StartMouseTimer()
00976 {
00977    // Start mouse timer in single-shot mode.
00978 
00979    fMouseTimer->Start(-1, kTRUE);
00980    fMouseTimerRunning = kTRUE;
00981 }
00982 
00983 //______________________________________________________________________________
00984 void TGLEventHandler::StopMouseTimer()
00985 {
00986    // Make sure mouse timers are not running.
00987 
00988    fMouseTimerRunning = kFALSE;
00989    fMouseTimer->Stop();
00990 }
00991 
00992 //______________________________________________________________________________
00993 void TGLEventHandler::ClearMouseOver()
00994 {
00995    // Clear mouse-over state and emit mouse-over signals.
00996    // Current overlay element is also told the mouse has left.
00997 
00998    fLastMouseOverPos.fX = fLastMouseOverPos.fY = -1;
00999    fLastMouseOverShape = 0;
01000    fGLViewer->MouseOver(fLastMouseOverShape);
01001    fGLViewer->MouseOver(fLastMouseOverShape, fLastEventState);
01002    fGLViewer->MouseOver((TObject*)0, fLastEventState);
01003 
01004    fGLViewer->ClearCurrentOvlElm();
01005 }
01006 
01007 //______________________________________________________________________________
01008 void TGLEventHandler::Repaint()
01009 {
01010    // Handle window expose 'event' - show.
01011 
01012    if (fGLViewer->IsLocked()) {
01013       if (gDebug > 0) {
01014          Info("TGLViewer::HandleExpose", "ignored - viewer is %s",
01015             fGLViewer->LockName(fGLViewer->CurrentLock()));
01016       }
01017       return;
01018    }
01019    fGLViewer->fRedrawTimer->RequestDraw(20, TGLRnrCtx::kLODHigh);
01020 }
01021 
01022 //______________________________________________________________________________
01023 void TGLEventHandler::PopupContextMenu(TGLPhysicalShape* pshp, Event_t * /*event*/,
01024                                        Int_t gx, Int_t gy)
01025 {
01026    // Popup context menu.
01027 
01028    if (!fGLViewer->fContextMenu)
01029    {
01030       fGLViewer->fContextMenu = new TContextMenu("glcm", "GL Viewer Context Menu");
01031    }
01032 
01033    if (pshp)
01034    {
01035       fActiveButtonID = 0;
01036       UnGrabMouse();
01037 
01038       pshp->InvokeContextMenu(*fGLViewer->fContextMenu, gx, gy);
01039    }
01040 
01041    // This is dangerous ... should have special menu, probably even
01042    // tool / context specific.
01043    // else 
01044    // {
01045    //    fGLViewer->fContextMenu->Popup(x, y, fGLViewer);
01046    // }
01047 }
01048 
01049 //______________________________________________________________________________
01050 void TGLEventHandler::TriggerTooltip(const char* text)
01051 {
01052    // Trigger display of tooltip.
01053 
01054    static UInt_t screenW = 0, screenH = 0;
01055    fTooltipPos   = fLastGlobalPos;
01056    fTooltipShown = kTRUE;
01057    fTooltip->SetText(text);
01058    Int_t x = fTooltipPos.fX + 16, y = fTooltipPos.fY + 16;
01059    if (screenW == 0 || screenH == 0) {
01060       screenW = gClient->GetDisplayWidth();
01061       screenH = gClient->GetDisplayHeight();
01062    }
01063    if (x + 5 + fTooltip->GetWidth() > screenW) {
01064       x = screenW - fTooltip->GetWidth() - 5;
01065       if (y + 5 + fTooltip->GetHeight() > screenH) {
01066          y -= (25 + fTooltip->GetHeight());
01067       }
01068    }
01069    if (y + 5 + fTooltip->GetHeight() > screenH) {
01070       y = screenH - fTooltip->GetHeight() - 10;
01071    }
01072    fTooltip->SetPosition(x, y);
01073    fTooltip->Reset();
01074 }
01075 
01076 //______________________________________________________________________________
01077 void TGLEventHandler::RemoveTooltip()
01078 {
01079    // Hide the tooltip.
01080 
01081    fTooltip->Hide();
01082    fTooltipShown = kFALSE;
01083 }
01084 
01085 //______________________________________________________________________________
01086 void TGLEventHandler::SetMouseOverSelectDelay(Int_t ms)
01087 {
01088    // Set delay of mouse-over probe (highlight).
01089 
01090    fMouseTimer->SetTime(ms);
01091 }
01092 
01093 //______________________________________________________________________________
01094 void TGLEventHandler::SetMouseOverTooltipDelay(Int_t ms)
01095 {
01096    // Set delay of tooltip timer.
01097 
01098    fTooltip->SetDelay(ms);
01099 }

Generated on Tue Jul 5 14:18:06 2011 for ROOT_528-00b_version by  doxygen 1.5.1