00001
00002
00003
00004
00005
00006
00007
00008
00009
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
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
00068
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
00097
00098
00099 fPointer = ref;
00100 parent->AddOverlayElement(this);
00101 fParent = (TGLViewer*)parent;
00102 }
00103
00104
00105 TGLAnnotation::~TGLAnnotation()
00106 {
00107
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
00119
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
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& )
00193 {
00194
00195
00196 fActive = kTRUE;
00197 return kTRUE;
00198 }
00199
00200
00201 void TGLAnnotation::MouseLeave()
00202 {
00203
00204
00205 fActive = kFALSE;
00206 }
00207
00208
00209 void TGLAnnotation::Render(TGLRnrCtx& rnrCtx)
00210 {
00211
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
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
00249 rnrCtx.ProjectionMatrixPushIdentity();
00250
00251 glPushMatrix();
00252
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
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
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
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;
00302 Float_t z2 = -0.01f;
00303 Float_t z1 = -0.02f;
00304 Float_t z0 = -0.03f;
00305
00306
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
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
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
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
00374 glLoadName(kEditID);
00375
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
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
00397 glLoadName(kDeleteID);
00398
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
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
00417 glLoadName(kResizeID);
00418
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
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
00476
00477
00478 if (fActive)
00479 return TMath::Min(70, fTransparency);
00480 else
00481 return fTransparency;
00482 }
00483
00484
00485 void TGLAnnotation::MakeEditor()
00486 {
00487
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
00534
00535 fMainFrame->UnmapWindow();
00536 }
00537
00538
00539 void TGLAnnotation::UpdateText()
00540 {
00541
00542
00543 fText = fTextEdit->GetText()->AsString();
00544 fMainFrame->UnmapWindow();
00545 fParent->RequestDraw();
00546 }