TGLAnnotation.cxx

Go to the documentation of this file.
00001 // @(#)root/gl:$Id: TGLAnnotation.cxx 34006 2010-06-21 10:36:05Z matevz $
00002 // Author:  Matevz and Alja Tadel  20/02/2009
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2004, 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 #include "TGLAnnotation.h"
00013 
00014 #include "TGLIncludes.h"
00015 #include "TROOT.h"
00016 #include "TColor.h"
00017 #include "TGLUtil.h"
00018 #include "TGLCamera.h"
00019 #include "TGLRnrCtx.h"
00020 #include "TGLSelectRecord.h"
00021 #include "TGLViewerBase.h"
00022 #include "TObjString.h"
00023 #include "TGFrame.h"
00024 #include "TGTextEdit.h"
00025 #include "TGButton.h"
00026 #include "TGLViewer.h"
00027 
00028 #include "TMath.h"
00029 
00030 #include <KeySymbols.h>
00031 
00032 //______________________________________________________________________________
00033 //
00034 //
00035 // GL-overaly annotation.
00036 //
00037 //
00038 
00039 ClassImp(TGLAnnotation);
00040 
00041 Color_t  TGLAnnotation::fgBackColor = kAzure + 10;
00042 Color_t  TGLAnnotation::fgTextColor = kOrange;
00043 
00044 //______________________________________________________________________________
00045 TGLAnnotation::TGLAnnotation(TGLViewerBase *parent, const char *text, Float_t posx, Float_t posy) :
00046    TGLOverlayElement(TGLOverlayElement::kAnnotation),
00047 
00048    fPosX(posx), fPosY(posy),
00049    fMouseX(0),  fMouseY(0),
00050    fDrag(kNone),
00051    fDrawW(0), fDrawH(0), fTextSizeDrag(0),
00052    fActive(kFALSE),
00053    fMainFrame(0), fTextEdit(0),
00054 
00055    fParent(0),
00056 
00057    fText(text),
00058    fTextSize(0.03),
00059    fTextAlign(TGLFont::kLeft),
00060    fBackColor(fgBackColor),
00061    fTextColor(fgTextColor),
00062    fTransparency(100),
00063    fDrawRefLine(kFALSE),
00064    fUseColorSet(kTRUE),
00065    fAllowClose(kTRUE)
00066 {
00067    // Constructor.
00068    // Create annotation as plain text
00069 
00070    parent->AddOverlayElement(this);
00071    fParent = (TGLViewer*)parent;
00072 }
00073 
00074 //______________________________________________________________________________
00075 TGLAnnotation::TGLAnnotation(TGLViewerBase *parent, const char *text, Float_t posx, Float_t posy, TGLVector3 ref) :
00076    TGLOverlayElement(TGLOverlayElement::kAnnotation),
00077    fPosX(posx), fPosY(posy),
00078    fMouseX(0),  fMouseY(0),
00079    fDrag(kNone),
00080    fDrawW(0), fDrawH(0), fTextSizeDrag(0),
00081    fActive(kFALSE),
00082    fMainFrame(0), fTextEdit(0),
00083 
00084    fParent(0),
00085 
00086    fText(text),
00087    fTextSize(0.03),
00088    fTextAlign(TGLFont::kLeft),
00089    fBackColor(fgBackColor),
00090    fTextColor(fgTextColor),
00091    fTransparency(40),
00092    fDrawRefLine(kTRUE),
00093    fUseColorSet(kTRUE),
00094    fAllowClose(kTRUE)
00095 {
00096    // Constructor.
00097    // Create annotaton by picking an object.
00098 
00099    fPointer = ref;
00100    parent->AddOverlayElement(this);
00101    fParent = (TGLViewer*)parent;
00102 }
00103 
00104 //______________________________________________________________________________
00105 TGLAnnotation::~TGLAnnotation()
00106 {
00107    // Destructor.
00108 
00109    fParent->RemoveOverlayElement(this);
00110    delete fMainFrame;
00111 }
00112 
00113 //______________________________________________________________________
00114 Bool_t TGLAnnotation::Handle(TGLRnrCtx&          rnrCtx,
00115                              TGLOvlSelectRecord& selRec,
00116                              Event_t*            event)
00117 {
00118    // Handle overlay event.
00119    // Return TRUE if event was handled.
00120 
00121    if (selRec.GetN() < 2) return kFALSE;
00122    Int_t recID = selRec.GetItem(1);
00123    switch (event->fType)
00124    {
00125       case kButtonPress:
00126       {
00127          fMouseX = event->fX;
00128          fMouseY = event->fY;
00129          fDrag = (recID == kResizeID) ? kResize : kMove;
00130          fTextSizeDrag = fTextSize;
00131          return kTRUE;
00132       }
00133       case kButtonRelease:
00134       {
00135          fDrag = kNone;
00136          if (recID == kDeleteID)
00137          {
00138             TGLViewer *v = fParent;
00139             delete this;
00140             v->RequestDraw(rnrCtx.ViewerLOD());
00141          }
00142          else if (recID == kEditID)
00143          {
00144             MakeEditor();
00145          }
00146          return kTRUE;
00147       }
00148       case kMotionNotify:
00149       {
00150          const TGLRect& vp = rnrCtx.RefCamera().RefViewport();
00151          if (vp.Width() == 0 || vp.Height() == 0) return kFALSE;
00152 
00153          if (fDrag == kMove)
00154          {
00155             fPosX += (Float_t)(event->fX - fMouseX) / vp.Width();
00156             fPosY -= (Float_t)(event->fY - fMouseY) / vp.Height();
00157             fMouseX = event->fX;
00158             fMouseY = event->fY;
00159             // Make sure we don't go offscreen (use fDraw variables set in draw)
00160             if (fPosX < 0)
00161                fPosX = 0;
00162             else if (fPosX + fDrawW > 1.0f)
00163                fPosX = 1.0f - fDrawW;
00164             if (fPosY < fDrawH)
00165                fPosY = fDrawH;
00166             else if (fPosY > 1.0f)
00167                fPosY = 1.0f;
00168          }
00169          else if (fDrag == kResize)
00170          {
00171             using namespace TMath;
00172             Float_t oovpw = 1.0f / vp.Width(), oovph = 1.0f / vp.Height();
00173 
00174             Float_t xw = oovpw * Min(Max(0, event->fX), vp.Width());
00175             Float_t yw = oovph * Min(Max(0, vp.Height() - event->fY), vp.Height());
00176 
00177             Float_t rx = Max((xw - fPosX) / (oovpw * fMouseX - fPosX), 0.0f);
00178             Float_t ry = Max((yw - fPosY) / (oovph*(vp.Height() - fMouseY) - fPosY), 0.0f);
00179 
00180             fTextSize  = Max(fTextSizeDrag * Min(rx, ry), 0.01f);
00181          }
00182          return kTRUE;
00183       }
00184       default:
00185       {
00186          return kFALSE;
00187       }
00188    }
00189 }
00190 
00191 //______________________________________________________________________________
00192 Bool_t TGLAnnotation::MouseEnter(TGLOvlSelectRecord& /*rec*/)
00193 {
00194    // Mouse has entered overlay area.
00195 
00196    fActive = kTRUE;
00197    return kTRUE;
00198 }
00199 
00200 //______________________________________________________________________
00201 void TGLAnnotation::MouseLeave()
00202 {
00203    // Mouse has left overlay area.
00204 
00205    fActive = kFALSE;
00206 }
00207 
00208 /**************************************************************************/
00209 void TGLAnnotation::Render(TGLRnrCtx& rnrCtx)
00210 {
00211    // Render the annotation.
00212 
00213    const TGLRect& vp = rnrCtx.RefCamera().RefViewport();
00214    if (vp.Width() == 0 && vp.Height() == 0)
00215       return;
00216 
00217    Float_t old_depth_range[2];
00218    glGetFloatv(GL_DEPTH_RANGE, old_depth_range);
00219    glDepthRange(0, 0.001);
00220 
00221 
00222    glPushAttrib(GL_ENABLE_BIT | GL_LINE_BIT | GL_POLYGON_BIT);
00223    TGLCapabilitySwitch lights_off(GL_LIGHTING, kFALSE);
00224    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
00225    glDisable(GL_CULL_FACE);
00226    glEnable(GL_BLEND);
00227    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00228 
00229    // prepare colors
00230    Color_t bgCol, fgCol;
00231    if (fUseColorSet)
00232    {
00233       fgCol = rnrCtx.ColorSet().Markup().GetColorIndex();
00234 
00235       TColor* c1 = gROOT->GetColor(rnrCtx.ColorSet().Markup().GetColorIndex());
00236       TColor* c2 = gROOT->GetColor(rnrCtx.ColorSet().Background().GetColorIndex());
00237       Float_t f1 = 0.5, f2 = 0.5;
00238       bgCol = TColor::GetColor(c1->GetRed()  *f1  + c2->GetRed()  *f2,
00239                                c1->GetGreen()*f1  + c2->GetGreen()*f2,
00240                                c1->GetBlue() *f1  + c2->GetBlue() *f2);
00241    }
00242    else
00243    {
00244       fgCol = fTextColor;
00245       bgCol = fBackColor;
00246    }
00247 
00248    // reset matrix
00249    rnrCtx.ProjectionMatrixPushIdentity();
00250 
00251    glPushMatrix();
00252    // set ortho camera to [0,1] [0.1]
00253    glLoadIdentity();
00254    glTranslatef(-1.0f, -1.0f, 0.0f);
00255    glScalef(2.0f, 2.0f, 1.0f);
00256 
00257    glEnable(GL_POLYGON_OFFSET_FILL);
00258    glPolygonOffset(0.1f, 1.0f);
00259 
00260    glPushMatrix();
00261 
00262    TGLUtil::LineWidth(1.0f);
00263 
00264    // move to pos
00265    glTranslatef(fPosX, fPosY, 0.0f);
00266 
00267    TObjArray  *lines = fText.Tokenize("\n");
00268    TIter       line_iter(lines);
00269    TObjString *osl;
00270 
00271    Float_t widthTxt, heightTxt, sx, sy, descent, line_height;
00272    {
00273       // get unscaled text size
00274       Int_t fs = TGLFontManager::GetFontSize(TMath::Nint(vp.Height()*fTextSize), 12, 64);
00275       rnrCtx.RegisterFontNoScale(fs, "arial", TGLFont::kTexture, fFont);
00276       descent     = fFont.GetDescent();
00277       line_height = fFont.GetLineHeight();
00278 
00279       Float_t llx, lly, llz, urx, ury, urz;
00280       widthTxt = heightTxt = 0;
00281       while ((osl = (TObjString*) line_iter()) != 0)
00282       {
00283          fFont.BBox(osl->GetString().Data(), llx, lly, llz, urx, ury, urz);
00284          widthTxt   = TMath::Max(widthTxt, urx);
00285          heightTxt += line_height;
00286       }
00287       widthTxt  += 2.0f * descent;
00288       heightTxt += 2.0f * descent;
00289 
00290       // keep proportions
00291       sy = fTextSize / (line_height + descent);
00292       sx = sy / vp.Aspect();
00293       fDrawW = sx*widthTxt;
00294       fDrawH = sy*heightTxt;
00295    }
00296    glScalef(sx, sy, 1.0f);
00297 
00298    glPushName(kMoveID);
00299 
00300    Float_t x1, x2, y1, y2;
00301    Float_t z3 =  0.0f;  // main background
00302    Float_t z2 = -0.01f; // outlines and text
00303    Float_t z1 = -0.02f; // button on top of text
00304    Float_t z0 = -0.03f; // button on top of text
00305 
00306    // main background
00307    glLoadName(kMoveID);
00308    x1 =  0.0f;
00309    x2 =  widthTxt;
00310    y1 = -heightTxt;
00311    y2 =  0.0f;
00312    TGLUtil::ColorTransparency(bgCol, fTransparency);
00313    glBegin(GL_QUADS);
00314    glVertex3f(x1, y1, z3);
00315    glVertex3f(x2, y1, z3);
00316    glVertex3f(x2, y2, z3);
00317    glVertex3f(x1, y2, z3);
00318    glEnd();
00319    // main polygon outline
00320    TGLUtil::ColorTransparency(fgCol, GetLineTransparency());
00321    glBegin(GL_LINE_LOOP);
00322    glVertex3f(x1, y1, z2);
00323    glVertex3f(x2, y1, z2);
00324    glVertex3f(x2, y2, z2);
00325    glVertex3f(x1, y2, z2);
00326    glEnd();
00327 
00328    // annotation text
00329    TGLUtil::Color(fgCol);
00330    fFont.PreRender();
00331    glPushMatrix();
00332    Float_t tx = 0;
00333    line_iter.Reset();
00334    while ((osl = (TObjString*) line_iter()) != 0)
00335    {
00336       if (fTextAlign == TGLFont::kLeft) {
00337          tx = 0;
00338       }
00339       else if  (fTextAlign == TGLFont::kCenterH) {
00340          tx = 0.5f * widthTxt - descent ;
00341       }
00342       else {
00343          tx = widthTxt - 2.0f * descent;
00344       }
00345       glTranslatef(0.0f, -line_height, 0.0f);
00346       fFont.Render(osl->GetString(), tx+descent, 0, z2, fTextAlign, TGLFont::kTop) ;
00347    }
00348    glPopMatrix();
00349    fFont.PostRender();
00350 
00351    delete lines;
00352 
00353    // buttons
00354    if (fActive)
00355    {
00356       Float_t bbox[6];
00357       fFont.PreRender();
00358       fFont.BBox("X", bbox[0], bbox[1], bbox[2], bbox[3], bbox[4], bbox[5]);
00359       glLoadName(kEditID);
00360       fFont.Render("E", descent, descent, z2, fTextAlign, TGLFont::kTop);
00361       x2 = bbox[3] + 2.0f * descent;
00362       if (fAllowClose)
00363       {
00364          glLoadName(kDeleteID);
00365          fFont.Render("X", x2 + descent, descent, z2, fTextAlign, TGLFont::kTop);
00366       }
00367       fFont.PostRender();
00368 
00369       x1 = 0.0f;
00370       y1 = 0.0f;
00371       y2 = line_height + descent;
00372       {
00373          // edit button
00374          glLoadName(kEditID);
00375          // polygon
00376          TGLUtil::ColorTransparency(bgCol, fTransparency);
00377          glBegin(GL_QUADS);
00378          glVertex3f(x1, y1, z3);
00379          glVertex3f(x2, y1, z3);
00380          glVertex3f(x2, y2, z3);
00381          glVertex3f(x1, y2, z3);
00382          glEnd();
00383          //  outline
00384          TGLUtil::ColorTransparency(fgCol, GetLineTransparency());
00385          glBegin(GL_LINE_LOOP);
00386          glVertex3f(x1, y1, z0);
00387          glVertex3f(x2, y1, z0);
00388          glVertex3f(x2, y2, z0);
00389          glVertex3f(x1, y2, z0);
00390          glEnd();
00391       }
00392       x1 += x2;
00393       x2 += x2;
00394       if (fAllowClose)
00395       {
00396          // close button
00397          glLoadName(kDeleteID);
00398          // polygon
00399          TGLUtil::ColorTransparency(bgCol, fTransparency);
00400          glBegin(GL_QUADS);
00401          glVertex3f(x1, y1, z3);
00402          glVertex3f(x2, y1, z3);
00403          glVertex3f(x2, y2, z3);
00404          glVertex3f(x1, y2, z3);
00405          glEnd();
00406          //  outline
00407          TGLUtil::ColorTransparency(fgCol, GetLineTransparency());
00408          glBegin(GL_LINE_LOOP);
00409          glVertex3f(x1, y1, z0);
00410          glVertex3f(x2, y1, z0);
00411          glVertex3f(x2, y2, z0);
00412          glVertex3f(x1, y2, z0);
00413          glEnd();
00414       }
00415       {
00416          // resize button
00417          glLoadName(kResizeID);
00418          // polygon
00419          x1 =  widthTxt - line_height;
00420          x2 =  widthTxt;
00421          y1 = -heightTxt;
00422          y2 = -heightTxt + line_height;
00423          TGLUtil::ColorTransparency(bgCol, fTransparency);
00424          glBegin(GL_QUADS);
00425          glVertex3f(x1, y1, z1);
00426          glVertex3f(x2, y1, z1);
00427          glVertex3f(x2, y2, z1);
00428          glVertex3f(x1, y2, z1);
00429          glEnd();
00430          // draw resize corner lines
00431          TGLUtil::ColorTransparency(fgCol, GetLineTransparency());
00432          glBegin(GL_LINES);
00433          Float_t aOff = 0.25*line_height;
00434          glVertex3f(x1+aOff, y1+aOff, z0);
00435          glVertex3f(x2-aOff, y1+aOff, z0);
00436          glVertex3f(x2-aOff, y1+aOff, z0);
00437          glVertex3f(x2-aOff, y2-aOff, z0);
00438          glEnd();
00439       }
00440    }
00441 
00442    glPopName();
00443 
00444    glPopMatrix();
00445 
00446    if (fDrawRefLine)
00447    {
00448       TGLVertex3 op = rnrCtx.RefCamera().WorldToViewport(fPointer);
00449       op[0] /= vp.Width();  op[1] /= vp.Height();
00450 
00451       Float_t fx = op[0] < fPosX ? 0.0f : (op[0] > fPosX + fDrawW ? 1.0f : 0.5f);
00452       Float_t fy = op[1] < fPosY-fDrawH ? 1.0f : (op[1] > fPosY ? 0.0f : 0.5f);
00453 
00454       if (fx != 0.5f || fy != 0.5f)
00455       {
00456          TGLUtil::ColorTransparency(bgCol, fTransparency);
00457          TGLUtil::LineWidth(2);
00458          glBegin(GL_LINES);
00459          glVertex3f(fPosX + fx*fDrawW, fPosY - fy*fDrawH, z3);
00460          glVertex3f(op[0], op[1], z3);
00461          glEnd();
00462       }
00463    }
00464 
00465    glPopMatrix();
00466    rnrCtx.ProjectionMatrixPop();
00467 
00468    glDepthRange(old_depth_range[0], old_depth_range[1]);
00469    glPopAttrib();
00470 }
00471 
00472 //______________________________________________________________________________
00473 Char_t TGLAnnotation::GetLineTransparency() const
00474 {
00475    // Returns transparecy of annotation outline.
00476    // If annotation is selected enforce visiblity of outline.
00477 
00478    if (fActive)
00479       return TMath::Min(70, fTransparency);
00480    else
00481       return fTransparency;
00482 }
00483 
00484 //______________________________________________________________________________
00485 void TGLAnnotation::MakeEditor()
00486 {
00487    // Show the annotation editor.
00488 
00489    if (fMainFrame == 0)
00490    {
00491       fMainFrame = new TGMainFrame(gClient->GetRoot(), 1000, 1000);
00492       fMainFrame->SetWindowName("Annotation Editor");
00493 
00494       TGVerticalFrame* vf = new TGVerticalFrame(fMainFrame);
00495 
00496       fTextEdit = new TGTextEdit(vf,  1000, 1000, kSunkenFrame);
00497       vf->AddFrame(fTextEdit,  new TGLayoutHints(kLHintsExpandX|kLHintsExpandY));
00498 
00499       TGHorizontalFrame* hf = new TGHorizontalFrame(vf);
00500 
00501       TGTextButton* btt1 = new TGTextButton(hf, "OK");
00502       hf->AddFrame(btt1, new TGLayoutHints(kLHintsExpandX, 2, 2, 2, 2));
00503 
00504       TGTextButton* btt2 = new TGTextButton(hf, "Cancel");
00505       hf->AddFrame(btt2, new TGLayoutHints(kLHintsExpandX, 2, 2, 2, 2));
00506 
00507       btt1->Connect("Clicked()", "TGLAnnotation", this, "UpdateText()");
00508       btt2->Connect("Clicked()", "TGLAnnotation", this, "CloseEditor()");
00509 
00510       vf->AddFrame(hf, new TGLayoutHints(kLHintsBottom | kLHintsRight | kLHintsExpandX, 2, 2, 5, 1));
00511 
00512       fMainFrame->AddFrame(vf,  new TGLayoutHints(kLHintsExpandX|kLHintsExpandY));
00513       fMainFrame->SetCleanup(kDeepCleanup);
00514       fMainFrame->MapSubwindows();
00515    }
00516 
00517    TGText *tgt = new TGText();
00518    tgt->LoadBuffer(fText.Data());
00519    fTextEdit->SetText(tgt);
00520 
00521    Int_t nrow = tgt->RowCount();
00522    Int_t h = nrow*20;
00523    Int_t w = fTextEdit->ReturnLongestLineWidth();
00524    fMainFrame->Resize(TMath::Max(100, w+30), TMath::Max(100, h+40));
00525 
00526    fMainFrame->Layout();
00527    fMainFrame->MapWindow();
00528 }
00529 
00530 //______________________________________________________________________________
00531 void TGLAnnotation::CloseEditor()
00532 {
00533    // Close the annotation editor.
00534 
00535    fMainFrame->UnmapWindow();
00536 }
00537 
00538 //______________________________________________________________________________
00539 void TGLAnnotation::UpdateText()
00540 {
00541    // Modify the annotation text from the text-edit widget.
00542 
00543    fText = fTextEdit->GetText()->AsString();
00544    fMainFrame->UnmapWindow();
00545    fParent->RequestDraw();
00546 }

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