Logo ROOT  
Reference Guide
Loading...
Searching...
No Matches
TGLAnnotation.cxx
Go to the documentation of this file.
1// @(#)root/gl:$Id$
2// Author: Matevz and Alja Tadel 20/02/2009
3
4/*************************************************************************
5 * Copyright (C) 1995-2004, 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 "TGLAnnotation.h"
13
14#include "TGLIncludes.h"
15#include "TROOT.h"
16#include "TColor.h"
17#include "TGLUtil.h"
18#include "TGLCamera.h"
19#include "TGLRnrCtx.h"
20#include "TGLSelectRecord.h"
21#include "TGLViewerBase.h"
22#include "TObjString.h"
23#include "TGTextEdit.h"
24#include "TGButton.h"
25#include "TGLViewer.h"
26
27#include "TMath.h"
28
29#include <KeySymbols.h>
30
31/** \class TGLAnnotation
32\ingroup opengl
33GL-overlay annotation.
34*/
35
36
39
40////////////////////////////////////////////////////////////////////////////////
41
44
45 fPosX(posx), fPosY(posy),
46 fMouseX(0), fMouseY(0),
47 fDrag(kNone),
48 fDrawW(0), fDrawH(0), fTextSizeDrag(0),
50 fMainFrame(nullptr), fTextEdit(nullptr),
51
52 fParent(nullptr),
53
54 fText(text),
55 fTextSize(0.03),
56 fTextAlign(TGLFont::kLeft),
59 fTransparency(100),
63{
64 // Constructor.
65 // Create annotation as plain text
66
67 parent->AddOverlayElement(this);
68 fParent = (TGLViewer*)parent;
69}
70
71////////////////////////////////////////////////////////////////////////////////
72
75 fPosX(posx), fPosY(posy),
76 fMouseX(0), fMouseY(0),
77 fDrag(kNone),
78 fDrawW(0), fDrawH(0), fTextSizeDrag(0),
80 fMainFrame(nullptr), fTextEdit(nullptr),
81
82 fParent(nullptr),
83
84 fText(text),
85 fTextSize(0.03),
86 fTextAlign(TGLFont::kLeft),
89 fTransparency(40),
93{
94 // Constructor.
95 // Create annotation by picking an object.
96
97 fPointer = ref;
98 parent->AddOverlayElement(this);
99 fParent = (TGLViewer*)parent;
100}
101
102////////////////////////////////////////////////////////////////////////////////
103/// Destructor.
104
106{
107 fParent->RemoveOverlayElement(this);
108 delete fMainFrame;
109}
110
111////////////////////////////////////////////////////////////////////////////////
112/// Handle overlay event.
113/// Return TRUE if event was handled.
114
116 TGLOvlSelectRecord& selRec,
117 Event_t* event)
118{
119 if (selRec.GetN() < 2) return kFALSE;
120 Int_t recID = selRec.GetItem(1);
121 switch (event->fType)
122 {
123 case kButtonPress:
124 {
125 fMouseX = event->fX;
126 fMouseY = event->fY;
127 fDrag = (recID == kResizeID) ? kResize : kMove;
129 return kTRUE;
130 }
131 case kButtonRelease:
132 {
133 fDrag = kNone;
134 if (recID == kDeleteID)
135 {
137 delete this;
138 v->RequestDraw(rnrCtx.ViewerLOD());
139 }
140 else if (recID == kEditID)
141 {
142 MakeEditor();
143 }
144 return kTRUE;
145 }
146 case kMotionNotify:
147 {
148 const TGLRect& vp = rnrCtx.RefCamera().RefViewport();
149 if (vp.Width() == 0 || vp.Height() == 0) return kFALSE;
150
151 if (fDrag == kMove)
152 {
153 fPosX += (Float_t)(event->fX - fMouseX) / vp.Width();
154 fPosY -= (Float_t)(event->fY - fMouseY) / vp.Height();
155 fMouseX = event->fX;
156 fMouseY = event->fY;
157 // Make sure we don't go offscreen (use fDraw variables set in draw)
158 if (fPosX < 0)
159 fPosX = 0;
160 else if (fPosX + fDrawW > 1.0f)
161 fPosX = 1.0f - fDrawW;
162 if (fPosY < fDrawH)
163 fPosY = fDrawH;
164 else if (fPosY > 1.0f)
165 fPosY = 1.0f;
166 }
167 else if (fDrag == kResize)
168 {
169 using namespace TMath;
170 Float_t oovpw = 1.0f / vp.Width(), oovph = 1.0f / vp.Height();
171
172 Float_t xw = oovpw * Min(Max(0, event->fX), vp.Width());
173 Float_t yw = oovph * Min(Max(0, vp.Height() - event->fY), vp.Height());
174
175 Float_t rx = Max((xw - fPosX) / (oovpw * fMouseX - fPosX), 0.0f);
176 Float_t ry = Max((yw - fPosY) / (oovph*(vp.Height() - fMouseY) - fPosY), 0.0f);
177
178 fTextSize = Max(fTextSizeDrag * Min(rx, ry), 0.01f);
179 }
180 return kTRUE;
181 }
182 default:
183 {
184 return kFALSE;
185 }
186 }
187}
188
189////////////////////////////////////////////////////////////////////////////////
190/// Mouse has entered overlay area.
191
197
198////////////////////////////////////////////////////////////////////////////////
199/// Mouse has left overlay area.
200
205
206////////////////////////////////////////////////////////////////////////////////
207/// Render the annotation.
208
210{
211 const TGLRect& vp = rnrCtx.RefCamera().RefViewport();
212 if (vp.Width() == 0 && vp.Height() == 0)
213 return;
214
215 Float_t old_depth_range[2];
216 glGetFloatv(GL_DEPTH_RANGE, old_depth_range);
217 glDepthRange(0, 0.001);
218
219
220 glPushAttrib(GL_ENABLE_BIT | GL_LINE_BIT | GL_POLYGON_BIT);
221 TGLCapabilitySwitch lights_off(GL_LIGHTING, kFALSE);
222 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
223 glDisable(GL_CULL_FACE);
224 glEnable(GL_BLEND);
225 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
226
227 // prepare colors
228 Color_t bgCol = fBackColor;
229 Color_t fgCol = fTextColor;
230
231 if (fUseColorSet)
232 {
233 fgCol = rnrCtx.ColorSet().Markup().GetColorIndex();
234
235 TColor* c1 = gROOT->GetColor(rnrCtx.ColorSet().Markup().GetColorIndex());
236 TColor* c2 = gROOT->GetColor(rnrCtx.ColorSet().Background().GetColorIndex());
237
238 if (c1 && c2) {
239 Float_t f1 = 0.5, f2 = 0.5;
240 bgCol = TColor::GetColor(c1->GetRed() *f1 + c2->GetRed() *f2,
241 c1->GetGreen()*f1 + c2->GetGreen()*f2,
242 c1->GetBlue() *f1 + c2->GetBlue() *f2);
243 }
244 }
245
246 // reset matrix
248
249 glPushMatrix();
250 // set ortho camera to [0,1] [0.1]
251 glLoadIdentity();
252 glTranslatef(-1.0f, -1.0f, 0.0f);
253 glScalef(2.0f, 2.0f, 1.0f);
254
255 glEnable(GL_POLYGON_OFFSET_FILL);
256 glPolygonOffset(0.1f, 1.0f);
257
258 glPushMatrix();
259
260 TGLUtil::LineWidth(1.0f);
261
262 // move to pos
263 glTranslatef(fPosX, fPosY, 0.0f);
264
265 TObjArray *lines = fText.Tokenize("\n");
266 TIter line_iter(lines);
267 TObjString *osl;
268
269 Float_t widthTxt, heightTxt, sx, sy, descent, line_height;
270 {
271 // get unscaled text size
273 rnrCtx.RegisterFontNoScale(fs, "arial", TGLFont::kTexture, fFont);
274 descent = fFont.GetDescent();
275 line_height = fFont.GetLineHeight();
276
277 Float_t llx, lly, llz, urx, ury, urz;
278 widthTxt = heightTxt = 0;
279 while ((osl = (TObjString*) line_iter()) != nullptr)
280 {
281 fFont.BBox(osl->GetString().Data(), llx, lly, llz, urx, ury, urz);
282 widthTxt = TMath::Max(widthTxt, urx);
283 heightTxt += line_height;
284 }
285 widthTxt += 2.0f * descent;
286 heightTxt += 2.0f * descent;
287
288 // keep proportions
289 sy = fTextSize / (line_height + descent);
290 sx = sy / vp.Aspect();
291 fDrawW = sx*widthTxt;
292 fDrawH = sy*heightTxt;
293 }
294 glScalef(sx, sy, 1.0f);
295
296 glPushName(kMoveID);
297
298 Float_t x1, x2, y1, y2;
299 Float_t z3 = 0.0f; // main background
300 Float_t z2 = -0.01f; // outlines and text
301 Float_t z1 = -0.02f; // button on top of text
302 Float_t z0 = -0.03f; // button on top of text
303
304 // main background
305 glLoadName(kMoveID);
306 x1 = 0.0f;
307 x2 = widthTxt;
308 y1 = -heightTxt;
309 y2 = 0.0f;
311 glBegin(GL_QUADS);
312 glVertex3f(x1, y1, z3);
313 glVertex3f(x2, y1, z3);
314 glVertex3f(x2, y2, z3);
315 glVertex3f(x1, y2, z3);
316 glEnd();
317 // main polygon outline
319 glBegin(GL_LINE_LOOP);
320 glVertex3f(x1, y1, z2);
321 glVertex3f(x2, y1, z2);
322 glVertex3f(x2, y2, z2);
323 glVertex3f(x1, y2, z2);
324 glEnd();
325
326 // annotation text
327 TGLUtil::Color(fgCol);
328 fFont.PreRender();
329 glPushMatrix();
330 Float_t tx = 0;
331 line_iter.Reset();
332 while ((osl = (TObjString*) line_iter()) != nullptr)
333 {
334 if (fTextAlign == TGLFont::kLeft) {
335 tx = 0;
336 }
337 else if (fTextAlign == TGLFont::kCenterH) {
338 tx = 0.5f * widthTxt - descent ;
339 }
340 else {
341 tx = widthTxt - 2.0f * descent;
342 }
343 glTranslatef(0.0f, -line_height, 0.0f);
344 fFont.Render(osl->GetString(), tx+descent, 0, z2, fTextAlign, TGLFont::kTop) ;
345 }
346 glPopMatrix();
347 fFont.PostRender();
348
349 delete lines;
350
351 // buttons
352 if (fActive)
353 {
354 Float_t bbox[6];
355 fFont.PreRender();
356 fFont.BBox("X", bbox[0], bbox[1], bbox[2], bbox[3], bbox[4], bbox[5]);
357 glLoadName(kEditID);
358 fFont.Render("E", descent, descent, z2, fTextAlign, TGLFont::kTop);
359 x2 = bbox[3] + 2.0f * descent;
360 if (fAllowClose)
361 {
362 glLoadName(kDeleteID);
363 fFont.Render("X", x2 + descent, descent, z2, fTextAlign, TGLFont::kTop);
364 }
365 fFont.PostRender();
366
367 x1 = 0.0f;
368 y1 = 0.0f;
369 y2 = line_height + descent;
370 {
371 // edit button
372 glLoadName(kEditID);
373 // polygon
375 glBegin(GL_QUADS);
376 glVertex3f(x1, y1, z3);
377 glVertex3f(x2, y1, z3);
378 glVertex3f(x2, y2, z3);
379 glVertex3f(x1, y2, z3);
380 glEnd();
381 // outline
383 glBegin(GL_LINE_LOOP);
384 glVertex3f(x1, y1, z0);
385 glVertex3f(x2, y1, z0);
386 glVertex3f(x2, y2, z0);
387 glVertex3f(x1, y2, z0);
388 glEnd();
389 }
390 x1 += x2;
391 x2 += x2;
392 if (fAllowClose)
393 {
394 // close button
395 glLoadName(kDeleteID);
396 // polygon
398 glBegin(GL_QUADS);
399 glVertex3f(x1, y1, z3);
400 glVertex3f(x2, y1, z3);
401 glVertex3f(x2, y2, z3);
402 glVertex3f(x1, y2, z3);
403 glEnd();
404 // outline
406 glBegin(GL_LINE_LOOP);
407 glVertex3f(x1, y1, z0);
408 glVertex3f(x2, y1, z0);
409 glVertex3f(x2, y2, z0);
410 glVertex3f(x1, y2, z0);
411 glEnd();
412 }
413 {
414 // resize button
415 glLoadName(kResizeID);
416 // polygon
417 x1 = widthTxt - line_height;
418 x2 = widthTxt;
419 y1 = -heightTxt;
420 y2 = -heightTxt + line_height;
422 glBegin(GL_QUADS);
423 glVertex3f(x1, y1, z1);
424 glVertex3f(x2, y1, z1);
425 glVertex3f(x2, y2, z1);
426 glVertex3f(x1, y2, z1);
427 glEnd();
428 // draw resize corner lines
430 glBegin(GL_LINES);
431 Float_t aOff = 0.25*line_height;
432 glVertex3f(x1+aOff, y1+aOff, z0);
433 glVertex3f(x2-aOff, y1+aOff, z0);
434 glVertex3f(x2-aOff, y1+aOff, z0);
435 glVertex3f(x2-aOff, y2-aOff, z0);
436 glEnd();
437 }
438 }
439
440 glPopName();
441
442 glPopMatrix();
443
444 if (fDrawRefLine)
445 {
447 op[0] /= vp.Width(); op[1] /= vp.Height();
448
449 Float_t fx = op[0] < fPosX ? 0.0f : (op[0] > fPosX + fDrawW ? 1.0f : 0.5f);
450 Float_t fy = op[1] < fPosY-fDrawH ? 1.0f : (op[1] > fPosY ? 0.0f : 0.5f);
451
452 if (fx != 0.5f || fy != 0.5f)
453 {
456 glBegin(GL_LINES);
457 glVertex3f(fPosX + fx*fDrawW, fPosY - fy*fDrawH, z3);
458 glVertex3f(op[0], op[1], z3);
459 glEnd();
460 }
461 }
462
463 glPopMatrix();
464 rnrCtx.ProjectionMatrixPop();
465
466 glDepthRange(old_depth_range[0], old_depth_range[1]);
467 glPopAttrib();
468}
469
470////////////////////////////////////////////////////////////////////////////////
471/// Returns transparency of annotation outline.
472/// If annotation is selected enforce visibility of outline.
473
475{
476 if (fActive)
477 return TMath::Min(70, fTransparency);
478 else
479 return fTransparency;
480}
481
482////////////////////////////////////////////////////////////////////////////////
483/// Show the annotation editor.
484
486{
487 if (fMainFrame == nullptr)
488 {
489 fMainFrame = new TGMainFrame(gClient->GetRoot(), 1000, 1000);
490 fMainFrame->SetWindowName("Annotation Editor");
491
493
494 fTextEdit = new TGTextEdit(vf, 1000, 1000, kSunkenFrame);
496
498
499 TGTextButton* btt1 = new TGTextButton(hf, "OK");
500 hf->AddFrame(btt1, new TGLayoutHints(kLHintsExpandX, 2, 2, 2, 2));
501
502 TGTextButton* btt2 = new TGTextButton(hf, "Cancel");
503 hf->AddFrame(btt2, new TGLayoutHints(kLHintsExpandX, 2, 2, 2, 2));
504
505 btt1->Connect("Clicked()", "TGLAnnotation", this, "UpdateText()");
506 btt2->Connect("Clicked()", "TGLAnnotation", this, "CloseEditor()");
507
508 vf->AddFrame(hf, new TGLayoutHints(kLHintsBottom | kLHintsRight | kLHintsExpandX, 2, 2, 5, 1));
509
511 fMainFrame->SetCleanup(kDeepCleanup);
512 fMainFrame->MapSubwindows();
513 }
514
515 TGText *tgt = new TGText();
516 tgt->LoadBuffer(fText.Data());
517 fTextEdit->SetText(tgt);
518
519 Int_t nrow = tgt->RowCount();
520 Int_t h = nrow*20;
521 Int_t w = fTextEdit->ReturnLongestLineWidth();
522 fMainFrame->Resize(TMath::Max(100, w+30), TMath::Max(100, h+40));
523
524 fMainFrame->Layout();
525 fMainFrame->MapWindow();
526}
527
528////////////////////////////////////////////////////////////////////////////////
529/// Close the annotation editor.
530
532{
533 fMainFrame->UnmapWindow();
534}
535
536////////////////////////////////////////////////////////////////////////////////
537/// Modify the annotation text from the text-edit widget.
538
540{
541 fText = fTextEdit->GetText()->AsString();
542 fMainFrame->UnmapWindow();
543 fParent->RequestDraw();
544}
@ kButtonRelease
Definition GuiTypes.h:61
@ kButtonPress
Definition GuiTypes.h:61
@ kMotionNotify
Definition GuiTypes.h:62
@ kSunkenFrame
Definition GuiTypes.h:384
#define h(i)
Definition RSha256.hxx:106
int Int_t
Signed integer 4 bytes (int).
Definition RtypesCore.h:59
char Char_t
Character 1 byte (char).
Definition RtypesCore.h:51
bool Bool_t
Boolean (0=false, 1=true) (bool).
Definition RtypesCore.h:77
constexpr Bool_t kFALSE
Definition RtypesCore.h:108
short Color_t
Color number (short).
Definition RtypesCore.h:99
float Float_t
Float 4 bytes (float).
Definition RtypesCore.h:71
constexpr Bool_t kTRUE
Definition RtypesCore.h:107
@ kOrange
Definition Rtypes.h:68
@ kAzure
Definition Rtypes.h:68
#define gClient
Definition TGClient.h:157
@ kDeepCleanup
Definition TGFrame.h:42
@ kLHintsRight
Definition TGLayout.h:26
@ kLHintsExpandY
Definition TGLayout.h:31
@ kLHintsBottom
Definition TGLayout.h:29
@ kLHintsExpandX
Definition TGLayout.h:30
#define gROOT
Definition TROOT.h:417
static Int_t GetColor(const char *hexcolor)
virtual void AddFrame(TGFrame *f, TGLayoutHints *l=nullptr)
Add frame to the composite frame using the specified layout hints.
Definition TGFrame.cxx:1109
A composite frame that layout their children in horizontal way.
Definition TGFrame.h:387
static Color_t fgBackColor
TGLAnnotation(const TGLAnnotation &)=delete
Bool_t MouseEnter(TGLOvlSelectRecord &selRec) override
Mouse has entered overlay area.
Bool_t Handle(TGLRnrCtx &rnrCtx, TGLOvlSelectRecord &selRec, Event_t *event) override
Handle overlay event.
static Color_t fgTextColor
TGMainFrame * fMainFrame
Float_t fTextSize
Bool_t fDrawRefLine
void MakeEditor()
Show the annotation editor.
void UpdateText()
Modify the annotation text from the text-edit widget.
Color_t fTextColor
TGTextEdit * fTextEdit
TGLViewer * fParent
Float_t fDrawH
! width and height when drawing
void CloseEditor()
Close the annotation editor.
TGLFont::ETextAlignH_e fTextAlign
Char_t GetLineTransparency() const
Returns transparency of annotation outline.
~TGLAnnotation() override
Destructor.
void MouseLeave() override
Mouse has left overlay area.
Bool_t fUseColorSet
Int_t fMouseY
! last mouse position
void Render(TGLRnrCtx &rnrCtx) override
Render the annotation.
Float_t fTextSizeDrag
! text-size at start of drag
Char_t fTransparency
Color_t fBackColor
TGLVector3 fPointer
TGLVertex3 WorldToViewport(const TGLVertex3 &worldVertex, TGLMatrix *modviewMat=nullptr) const
Convert a 3D world vertex to '3D' viewport (screen) one.
TGLRect & RefViewport()
Definition TGLCamera.h:128
TGLColor & Markup()
Definition TGLUtil.h:854
TGLColor & Background()
Definition TGLUtil.h:851
Color_t GetColorIndex() const
Returns color-index representing the color.
Definition TGLUtil.cxx:1210
static Int_t GetFontSize(Int_t ds)
Get availabe font size.
A wrapper class for FTFont.
TGLOverlayElement(const TGLOverlayElement &)=delete
Selection record for overlay objects.
Viewport (pixel base) 2D rectangle class.
Definition TGLUtil.h:422
Int_t Height() const
Definition TGLUtil.h:452
Int_t Width() const
Definition TGLUtil.h:450
Double_t Aspect() const
Definition TGLUtil.h:500
The TGLRnrCtx class aggregates data for a given redering context as needed by various parts of the RO...
Definition TGLRnrCtx.h:41
void RegisterFontNoScale(Int_t size, Int_t file, Int_t mode, TGLFont &out)
Get font in the GL rendering context.
TGLColorSet & ColorSet()
Return reference to current color-set (top of the stack).
TGLCamera & RefCamera()
Definition TGLRnrCtx.h:157
Short_t ViewerLOD() const
Definition TGLRnrCtx.h:171
void ProjectionMatrixPushIdentity()
void ProjectionMatrixPop()
UInt_t GetItem(Int_t i) const
static void ColorTransparency(Color_t color_index, Char_t transparency=0)
Set color from color_index and ROOT-style transparency (default 0).
Definition TGLUtil.cxx:1732
static void Color(const TGLColor &color)
Set color from TGLColor.
Definition TGLUtil.cxx:1688
static Float_t LineWidth()
Get the line-width, taking the global scaling into account.
Definition TGLUtil.cxx:1934
3 component (x/y/z) vector class.
Definition TGLUtil.h:248
3 component (x/y/z) vertex class.
Definition TGLUtil.h:84
Base class for GL viewers.
virtual void AddOverlayElement(TGLOverlayElement *el)
Add overlay element.
Base GL viewer object - used by both standalone and embedded (in pad) GL.
Definition TGLViewer.h:55
This class describes layout hints used by the layout classes.
Definition TGLayout.h:50
Defines top level windows that interact with the system Window Manager.
Definition TGFrame.h:399
Yield an action as soon as it is clicked.
Definition TGButton.h:142
A TGTextEdit is a specialization of TGTextView.
Definition TGTextEdit.h:22
A TGText is a multi line text buffer.
Definition TGText.h:57
Long_t RowCount() const
Definition TGText.h:106
Bool_t LoadBuffer(const char *txtbuf)
Load a 0 terminated buffer. Lines will be split at ' '.
Definition TGText.cxx:511
A composite frame that layout their children in vertical way.
Definition TGFrame.h:376
void Reset()
An array of TObjects.
Definition TObjArray.h:31
Collectable string class.
Definition TObjString.h:28
const TString & GetString() const
Definition TObjString.h:46
Bool_t Connect(const char *signal, const char *receiver_class, void *receiver, const char *slot)
Non-static method is used to connect from the signal of this object to the receiver slot.
Definition TQObject.cxx:865
const char * Data() const
Definition TString.h:384
TText * text
return c1
Definition legend1.C:41
TF1 * f1
Definition legend1.C:11
return c2
Definition legend2.C:14
TMath.
Definition TMathBase.h:35
Int_t Nint(T x)
Round to nearest integer. Rounds half integers to the nearest even integer.
Definition TMath.h:704
Short_t Max(Short_t a, Short_t b)
Returns the largest of a and b.
Definition TMathBase.h:249
Short_t Min(Short_t a, Short_t b)
Returns the smallest of a and b.
Definition TMathBase.h:197
Event structure.
Definition GuiTypes.h:175
EGEventType fType
of event (see EGEventType)
Definition GuiTypes.h:176
Int_t fY
pointer x, y coordinates in event window
Definition GuiTypes.h:179
Int_t fX
Definition GuiTypes.h:179