//*CMZ : 2.22/02 21/05/99 10.59.52 by Rene Brun
//*CMZ : 2.22/01 19/05/99 12.47.17 by Rene Brun
//*CMZ : 2.20/05 15/12/98 09.17.21 by Rene Brun
//*CMZ : 2.20/01 02/12/98 18.03.03 by Fons Rademakers
//*CMZ : 2.00/11 08/08/98 22.20.54 by Rene Brun
//*CMZ : 2.00/00 11/02/98 13.14.46 by Rene Brun
//*CMZ : 1.03/09 10/12/97 09.32.36 by Rene Brun
//*-- Author : Nicolas Brun 12/12/94
//*KEEP,CopyRight,T=C.
/*************************************************************************
* Copyright(c) 1995-1999, The ROOT System, All rights reserved. *
* Authors: Rene Brun, Fons Rademakers. *
* For list of contributors see $ROOTSYS/AA_CREDITS. *
* *
* Permission to use, copy, modify and distribute this software and its *
* documentation for non-commercial purposes is hereby granted without *
* fee, provided that the above copyright notice appears in all copies *
* and that both the copyright notice and this permission notice appear *
* in the supporting documentation. The authors make no claims about the *
* suitability of this software for any purpose. It is provided "as is" *
* without express or implied warranty. *
*************************************************************************/
//*KEND.
#include <fstream.h>
#include <iostream.h>
//*KEEP,TROOT.
#include "TROOT.h"
//*KEEP,TVirtualPad.
#include "TVirtualPad.h"
//*KEEP,TText.
#include "TText.h"
//*KEEP,TGXW.
#include "TGXW.h"
//*KEEP,TMath.
#include "TMath.h"
//*KEND.
const Int_t kTextNDC = BIT(14);
ClassImp(TText)
//______________________________________________________________________________
//
// TText is the base class for several text objects.
// See TAttText for a list of text attributes or fonts.
//
// By default, the text is drawn in the pad coordinates system.
// One can draw in NDC coordinates [0,1] if the function SetNDC
// is called for a TText object.
// In case a text is drawn to a PostScript file (see TPostScript)
// the following characters have a special action:
//
// ` : go to greek
// ' : go to special characters
// ~ : go to ZapfDingbats
// ? : go to subscript
// ^ : go to superscript
// ! : go to normal level of script
// & : backspace one character
// # : end of greek or of ZapfDingbats
//
// This special characters have no effect on the screen.
//
//______________________________________________________________________________
TText::TText(): TNamed(), TAttText()
{
//*-*-*-*-*-*-*-*-*-*-*Text default constructor*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-* ========================
}
//______________________________________________________________________________
TText::TText(Coord_t x, Coord_t y, const Text_t *text) : TNamed("",text), TAttText()
{
//*-*-*-*-*-*-*-*-*-*-*Text normal constructor*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-* =======================
fX=x; fY=y;
}
//______________________________________________________________________________
TText::~TText()
{
//*-*-*-*-*-*-*-*-*-*-*Text default destructor*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-* =======================
}
//______________________________________________________________________________
TText::TText(const TText &text)
{
((TText&)text).Copy(*this);
}
//______________________________________________________________________________
void TText::Copy(TObject &obj)
{
//*-*-*-*-*-*-*-*-*-*-*Copy this text to text*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-* ======================
((TText&)obj).fX = fX;
((TText&)obj).fY = fY;
TNamed::Copy(obj);
TAttText::Copy(((TText&)obj));
}
//______________________________________________________________________________
Int_t TText::DistancetoPrimitive(Int_t px, Int_t py)
{
//*-*-*-*-*-*-*-*-*-*-*Compute distance from point px,py to a string*-*-*-*-*
//*-* =============================================
// Compute the closest distance of approach from point px,py to this text.
// The rectangle surrounding this string is evaluated.
// if point is in rectangle, the distance is set to zero.
//
Int_t Ax,Ay,Bx,By,Cx,Cy,Dx,Dy,pxl,pxt,pyl,pyt;
Int_t ptx, pty;
Ax = Ay = pxl = pxt = pyl = pyt = 0;
if (TestBit(kTextNDC)) {
ptx = gPad->UtoPixel(fX);
pty = gPad->VtoPixel(fY);
} else {
ptx = gPad->XtoAbsPixel(fX);
pty = gPad->YtoAbsPixel(fY);
}
const Text_t *text = GetTitle();
Int_t len = strlen(text);
Float_t fh = (fTextSize*gPad->GetAbsHNDC())*Float_t(gPad->GetWh());
Int_t h = Int_t(fh/2);
Int_t w = h*len;
Int_t err = 1;
Int_t X1c,X2c,X3c,X4c;
Short_t halign = fTextAlign/10;
Short_t valign = fTextAlign - 10*halign;
if (fTextAngle < err || TMath::Abs(fTextAngle-180) < err || fTextAngle>360-err) {
Int_t signe = 1;
if (TMath::Abs(fTextAngle-180) < err) signe = -1;
switch (halign) { //*-* compute bounding box horizontal alignment
case 1 : pxl = ptx; pxt = ptx + signe*w; break; //left
case 2 : pxl = ptx - signe*w/2; pxt = ptx + signe*w/2; break; //center
case 3 : pxl = ptx - signe*w; pxt = ptx; break; //right
};
switch (valign) { //*-* compute bounding box vertical alignment
case 1 : pyl = pty - signe*3/2*h; pyt = pty; break; //bottom
case 2 : pyl = pty - signe*h/2; pyt = pty + signe*h/2; break; //center
case 3 : pyl = pty + signe*h/2; pyt = pty + signe*3*h/2; break; //top
};
if (fTextAngle <err || fTextAngle>360-err) if ((px >= pxl && px <= pxt) && (py >= pyl && py <= pyt)) return 0;
if (TMath::Abs(fTextAngle-180)<2) if ((px <= pxl && px >= pxt) && (py <= pyl && py >= pyt)) return 0;
return 9999;
}
if (TMath::Abs(fTextAngle-90) < err || TMath::Abs(fTextAngle-270)<err) {
Int_t signe = 1;
if (TMath::Abs(fTextAngle-270)<err) signe = -1;
switch (halign) { //*-* compute bounding box horizontal alignment
case 1 : pyt = pty; pyl = pty - signe*w; break; //left
case 2 : pyl = pty - signe*w/2; pyt = pty + signe*w/2; break; //center
case 3 : pyt = pty + signe*w; pyl = pty; break; //right
};
switch (valign) { //*-* compute bounding box vertical alignment
case 1 : pxl = ptx - signe*3/2*h; pxt = ptx; break; //bottom
case 2 : pxl = ptx - signe*h/2; pxt = ptx + signe*h/2; break; //center
case 3 : pxl = ptx + signe*h/2; pxt = ptx + signe*3*h/2; break; //top
};
if (TMath::Abs(fTextAngle-90)<err) if ((px >= pxl && px <= pxt) && (py >= pyl && py <= pyt)) return 0;
if (TMath::Abs(fTextAngle-270)<err) if ((px <= pxl && px >= pxt) && (py <= pyl && py >= pyt)) return 0;
return 9999;
}
Float_t co = TMath::Cos(fTextAngle*0.0175);
Float_t si = TMath::Sin(fTextAngle*0.0175);
if (halign == 1) {
switch (valign) {
case 1 : Ax = ptx; Ay = pty; break;
case 2 : Ax = ptx + Int_t((si*h/2+0.5)); Ay = pty + Int_t((co*h/2+0.5)); break;
case 3 : Ax = ptx + Int_t((si*h*3/2+0.5)); Ay = pty + Int_t((co*h*3/2+0.5)); break;
}
}
if (halign == 2) {
switch (valign) {
case 1 : Ax = ptx - Int_t((co*w/2+0.5)); Ay = pty + Int_t((si*w/2+0.5)); break;
case 2 : Ax = ptx - Int_t((co*w/2+si*h/2+0.5)); Ay = pty + Int_t((si*w/2+co*h/2+0.5)); break;
case 3 : Ax = ptx - Int_t((co*w/2+si*h*3/2+0.5)); Ay = pty + Int_t((si*w/2+co*h*3/2+0.5)); break;
}
}
if (halign == 3) {
switch (valign) {
case 1 : Ax = ptx - Int_t((co*w+0.5)); Ay = pty + Int_t((si*w+0.5)); break;
case 2 : Ax = ptx - Int_t((co*w+si*h/2+0.5)); Ay = pty + Int_t((si*w+co*h/2+0.5)); break;
case 3 : Ax = ptx - Int_t((co*w+si*h*3/2+0.5)); Ay = pty + Int_t((si*w+co*h*3/2+0.5)); break;
}
}
Bx = Ax - Int_t((si*h+0.5)); By = Ay - Int_t((co*h+0.5));
Cx = Bx + Int_t((co*w+0.5)); Cy = By - Int_t((si*w+0.5));
Dx = Ax + Int_t((co*w+0.5)); Dy = Ay - Int_t((si*w+0.5));
if (Cy==By) X1c = px;
else X1c = (py-Cy)*(Cx-Bx)/(Cy-By)+Cx;
if (Dy==Cy) X2c = px;
else X2c = (py-Cy)*(Dx-Cx)/(Dy-Cy)+Cx;
if (Dy==Ay) X3c = px;
else X3c = (py-Dy)*(Dx-Ax)/(Dy-Ay)+Dx;
if (Ay==By) X4c = px;
else X4c = (py-Ay)*(Ax-Bx)/(Ay-By)+Ax;
if (fTextAngle<90) if (px >= X1c && px <= X2c && px >= X4c && px <= X3c) return 0;
if (fTextAngle<180) if (px >= X1c && px >= X2c && px <= X4c && px <= X3c) return 0;
if (fTextAngle<270) if (px <= X1c && px >= X2c && px <= X4c && px >= X3c) return 0;
if (fTextAngle<360) if (px <= X1c && px <= X2c && px >= X4c && px >= X3c) return 0;
return 9999;
}
//______________________________________________________________________________
void TText::Draw(Option_t *option)
{
//*-*-*-*-*-*-*-*-*-*-*Draw this text with its current attributes*-*-*-*-*-*-*
//*-* ==========================================
AppendPad(option);
}
//______________________________________________________________________________
TText *TText::DrawText(Coord_t x, Coord_t y, const Text_t *text)
{
//*-*-*-*-*-*-*-*-*-*-*Draw this text with new coordinates*-*-*-*-*-*-*-*-*-*
//*-* ===================================
TText *newtext = new TText(x, y, text);
TAttText::Copy(*newtext);
newtext->SetBit(kCanDelete);
if (TestBit(kTextNDC)) newtext->SetNDC();
newtext->AppendPad();
return newtext;
}
//______________________________________________________________________________
TText *TText::DrawTextNDC(Coord_t x, Coord_t y, const Text_t *text)
{
//*-*-*-*-*-*-*-*-*-*-*Draw this text with new coordinates in NDC*-*-*-*-*-*
//*-* ==========================================
TText *newtext = DrawText(x, y, text);
newtext->SetNDC();
return newtext;
}
//______________________________________________________________________________
void TText::ExecuteEvent(Int_t event, Int_t px, Int_t py)
{
//*-*-*-*-*-*-*-*-*-*-*Execute action corresponding to one event*-*-*-*
//*-* =========================================
// This member function must be implemented to realize the action
// corresponding to the mouse click on the object in the window
//
static Int_t px1, py1, pxold, pyold, Size, hauteur, largeur;
static Bool_t resize,turn;
Int_t dx, dy;
Int_t kMaxDiff = 8;
const Text_t *text = GetTitle();
Int_t len = strlen(text);
Float_t sizetowin = gPad->GetAbsHNDC()*Float_t(gPad->GetWh());
Float_t fh = (fTextSize*sizetowin);
Int_t h = Int_t(fh/2);
Int_t w = h*len;
Short_t halign = fTextAlign/10;
Short_t valign = fTextAlign - 10*halign;
Float_t co,si,dtheta,norm;
static Bool_t droite;
static Float_t theta;
Int_t Ax,Ay,Hx,Hy,Bx,By,Cx,Cy;
Ax = Ay = 0;
Float_t lambda, x2,y2,xy;
Float_t dpx,dpy,xp1,yp1;
switch (event) {
case kButton1Down:
gGXW->SetTextColor(-1); // invalidate current text color (use xor mode)
TAttText::Modify(); //*-*Change text attributes only if necessary
// No break !!!
case kMouseMotion:
if (TestBit(kTextNDC)) {
px1 = gPad->UtoPixel(fX);
py1 = gPad->VtoPixel(fY);
} else {
px1 = gPad->XtoAbsPixel(fX);
py1 = gPad->YtoAbsPixel(fY);
}
theta = fTextAngle;
Size = 0;
pxold = px; pyold = py;
co = TMath::Cos(fTextAngle*0.0175);
si = TMath::Sin(fTextAngle*0.0175);
resize = turn = kFALSE;
if (halign == 1) {
switch (valign) {
case 1 : Ax = px1; Ay = py1; break;
case 2 : Ax = px1+Int_t(si*h/2); Ay = py1+Int_t(co*h/2); break;
case 3 : Ax = px1+Int_t(si*h*3/2); Ay = py1+Int_t(co*h*3/2); break;
}
}
if (halign == 2) {
switch (valign) {
case 1 : Ax = px1-Int_t(co*w/2); Ay = py1+Int_t(si*w/2); break;
case 2 : Ax = px1-Int_t(co*w/2+si*h/2); Ay = py1+Int_t(si*w/2+co*h/2); break;
case 3 : Ax = px1-Int_t(co*w/2+si*h*3/2); Ay = py1+Int_t(si*w/2+co*h*3/2); break;
}
}
if (halign == 3) {
switch (valign) {
case 1 : Ax = px1-Int_t(co*w); Ay = py1+Int_t(si*w); break;
case 2 : Ax = px1-Int_t(co*w+si*h/2); Ay = py1+Int_t(si*w+co*h/2); break;
case 3 : Ax = px1-Int_t(co*w+si*h*3/2); Ay = py1+Int_t(si*w+co*h*3/2); break;
}
}
if (halign != 3) {Hx = Ax+Int_t(co*w-si*h/2); Hy = Ay-Int_t(si*w-co*h/2); droite = kFALSE;}
else {Hx = Ax-Int_t(si*h/2); Hy = Ay-Int_t(co*h/2); droite = kTRUE;}
if ((TMath::Abs(px-Hx)<kMaxDiff*2) && (TMath::Abs(py-Hy)<kMaxDiff*2)) {gPad->SetCursor(kRotate); turn = kTRUE; break;}
Bx = Ax-Int_t(si*h); By = Ay-Int_t(co*h);
if (valign == 3) {Bx = Ax; By = Ay;}
Cx = Bx+Int_t(co*w); Cy = By-Int_t(si*w);
lambda = Float_t(((px-Bx)*(Cx-Bx)+(py-By)*(Cy-By)))/Float_t(((Cx-Bx)*(Cx-Bx)+(Cy-By)*(Cy-By)));
x2 = Float_t(px) - lambda*Float_t(Cx-Bx)-Float_t(Bx);
y2 = Float_t(py) - lambda*Float_t(Cy-By)-Float_t(By);
xy = Float_t((px-Ax)*(px-Ax)+(py-Ay)*(py-Ay));
if ((TMath::Sqrt(x2*x2+y2*y2) < kMaxDiff/2) && (TMath::Sqrt(xy) <= w*0.3)) {
if (fTextAngle == 0 || fTextAngle == 180) gPad->SetCursor(kArrowVer);
else {
if (fTextAngle == 90 || fTextAngle == 270) gPad->SetCursor(kArrowHor);
else gPad->SetCursor(kHand);
}
hauteur = valign;
largeur = halign;
resize = kTRUE;
break;
}
gPad->SetCursor(kMove);
break;
case kButton1Motion:
gGXW->DrawText(px1, py1, theta, gGXW->GetTextMagnitude(), GetTitle(), TGXW::kClear);
if (turn) {
norm = TMath::Sqrt(Double_t((py-py1)*(py-py1)+(px-px1)*(px-px1)));
if (norm>0) {
theta = TMath::ACos((px-px1)/norm);
dtheta= TMath::ASin((py1-py)/norm);
if (dtheta<0) theta = -theta;
theta = theta/TMath::ACos(-1)*180;
if (theta<0) theta += 360;
if (droite) {theta = theta+180; if (theta>=360) theta -= 360;}
}
}
else if (resize) {
co = TMath::Cos(fTextAngle*0.0175);
si = TMath::Sin(fTextAngle*0.0175);
if (largeur == 1) {
switch (valign) {
case 1 : Ax = px1; Ay = py1; break;
case 2 : Ax = px1+Int_t(si*h/2); Ay = py1+Int_t(co*h/2); break;
case 3 : Ax = px1+Int_t(si*h*3/2); Ay = py1+Int_t(co*h*3/2); break;
}
}
if (largeur == 2) {
switch (valign) {
case 1 : Ax = px1-Int_t(co*w/2); Ay = py1+Int_t(si*w/2); break;
case 2 : Ax = px1-Int_t(co*w/2+si*h/2); Ay = py1+Int_t(si*w/2+co*h/2); break;
case 3 : Ax = px1-Int_t(co*w/2+si*h*3/2); Ay = py1+Int_t(si*w/2+co*h*3/2); break;
}
}
if (largeur == 3) {
switch (valign) {
case 1 : Ax = px1-Int_t(co*w); Ay = py1+Int_t(si*w); break;
case 2 : Ax = px1-Int_t(co*w+si*h/2); Ay = py1+Int_t(si*w+co*h/2); break;
case 3 : Ax = px1-Int_t(co*w+si*h*3/2); Ay = py1+Int_t(si*w+co*h*3/2); break;
}
}
if (hauteur == 3) {Bx = Ax-Int_t(si*h); By = Ay-Int_t(co*h);}
else {Bx = Ax; By = Ay;}
Cx = Bx+Int_t(co*w); Cy = By-Int_t(si*w);
lambda = Float_t(((px-Bx)*(Cx-Bx)+(py-By)*(Cy-By)))/Float_t(((Cx-Bx)*(Cx-Bx)+(Cy-By)*(Cy-By)));
x2 = Float_t(px) - lambda*Float_t(Cx-Bx)-Float_t(Bx);
y2 = Float_t(py) - lambda*Float_t(Cy-By)-Float_t(By);
Size = Int_t(TMath::Sqrt(x2*x2+y2*y2)*2);
if (Size<4) Size = 4;
SetTextSize(Size/sizetowin);
TAttText::Modify();
}
else {
dx = px - pxold; px1 += dx;
dy = py - pyold; py1 += dy;
}
gGXW->DrawText(px1, py1, theta, gGXW->GetTextMagnitude(), GetTitle(), TGXW::kClear);
pxold = px; pyold = py;
break;
case kButton1Up:
if (TestBit(kTextNDC)) {
dpx = gPad->GetX2() - gPad->GetX1();
dpy = gPad->GetY2() - gPad->GetY1();
xp1 = gPad->GetX1();
yp1 = gPad->GetY1();
fX = (gPad->AbsPixeltoX(px1)-xp1)/dpx;
fY = (gPad->AbsPixeltoY(py1)-yp1)/dpy;
} else {
fX = gPad->AbsPixeltoX(px1);
fY = gPad->AbsPixeltoY(py1);
}
fTextAngle = theta;
gPad->Modified(kTRUE);
gGXW->SetTextColor(-1);
break;
case kButton1Locate:
ExecuteEvent(kButton1Down, px, py);
while (1) {
px = py = 0;
event = gGXW->RequestLocator(1, 1, px, py);
ExecuteEvent(kButton1Motion, px, py);
if (event != -1) { // button is released
ExecuteEvent(kButton1Up, px, py);
return;
}
}
}
}
//______________________________________________________________________________
void TText::ls(Option_t *)
{
//*-*-*-*-*-*-*-*-*-*-*-*List this text with its attributes*-*-*-*-*-*-*-*-*
//*-* ==================================
IndentLevel();
printf("Text X=%f Y=%f Text=%sn",fX,fY,GetTitle());
}
//______________________________________________________________________________
void TText::Paint(Option_t *)
{
//*-*-*-*-*-*-*-*-*-*-*Paint this text with its current attributes*-*-*-*-*-*-*
//*-* ===========================================
TAttText::Modify(); //Change text attributes only if necessary
if (TestBit(kTextNDC)) gPad->PaintTextNDC(fX,fY,GetTitle());
else gPad->PaintText(fX,fY,GetTitle());
}
//______________________________________________________________________________
void TText::PaintText(Coord_t x, Coord_t y, const Text_t *text)
{
//*-*-*-*-*-*-*-*-*-*-*Draw this text with new coordinates*-*-*-*-*-*-*-*-*-*
//*-* ===================================
TAttText::Modify(); //Change text attributes only if necessary
gPad->PaintText(x,y,text);
}
//______________________________________________________________________________
void TText::PaintTextNDC(Coord_t u, Coord_t v, const Text_t *text)
{
//*-*-*-*-*-*-*-*-*-*-*Draw this text with new coordinates in NDC*-*-*-*-*-*-*
//*-* ==========================================
TAttText::Modify(); //Change text attributes only if necessary
gPad->PaintTextNDC(u,v,text);
}
//______________________________________________________________________________
void TText::Print(Option_t *)
{
//*-*-*-*-*-*-*-*-*-*-*Dump this text with its attributes*-*-*-*-*-*-*-*-*-*
//*-* ==================================
printf("Text X=%f Y=%f Text=%s Font=%d Size=%f",fX,fY,GetTitle(),GetTextFont(),GetTextSize());
if (GetTextColor() != 1 ) printf(" Color=%d",GetTextColor());
if (GetTextAlign() != 10) printf(" Align=%d",GetTextAlign());
if (GetTextAngle() != 0 ) printf(" Angle=%f",GetTextAngle());
printf("n");
}
//______________________________________________________________________________
void TText::SavePrimitive(ofstream &out, Option_t *)
{
// Save primitive as a C++ statement(s) on output stream out
char quote = '"';
if (gROOT->ClassSaved(TText::Class())) {
out<<" ";
} else {
out<<" TText *";
}
out<<"text = new TText("<<fX<<","<<fY<<","<<quote<<GetTitle()<<quote<<");"<<endl;
SaveTextAttributes(out,"text",11,0,1,62,1);
out<<" text->Draw();"<<endl;
}
//______________________________________________________________________________
void TText::SetNDC(Bool_t isNDC)
{
// Set NDC mode on if isNDC = kTRUE, off otherwise
ResetBit(kTextNDC);
if (isNDC) SetBit(kTextNDC);
}
ROOT page - Class index - Top of the page
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.