Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TBox.cxx
Go to the documentation of this file.
1 // @(#)root/graf:$Id$
2 // Author: Rene Brun 12/12/94
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2000, 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 <stdlib.h>
13 
14 #include "Riostream.h"
15 #include "TROOT.h"
16 #include "TBox.h"
17 #include "TVirtualPad.h"
18 #include "TVirtualX.h"
19 #include "TClass.h"
20 #include "TMath.h"
21 #include "TPoint.h"
22 
23 ClassImp(TBox);
24 
25 /** \class TBox
26 \ingroup BasicGraphics
27 
28 Create a Box.
29 
30 A box is defined by :
31 
32 - Its bottom left coordinates x1,y1
33 - Its top right coordinates x2,y2
34 
35 A box has line attributes (see TAttLine) and fill area attributes (see TAttFill).
36 */
37 
38 ////////////////////////////////////////////////////////////////////////////////
39 /// Box default constructor.
40 
41 TBox::TBox(): TObject(), TAttLine(), TAttFill()
42 {
43  fTip = 0;
44  fX1 = 0.;
45  fY1 = 0.;
46  fX2 = 0.;
47  fY2 = 0.;
48  fResizing = kTRUE;
49 }
50 
51 ////////////////////////////////////////////////////////////////////////////////
52 /// Box standard constructor.
53 
54 TBox::TBox(Double_t x1, Double_t y1, Double_t x2, Double_t y2)
55  : TObject(), TAttLine(), TAttFill()
56 {
57  if (x2 >= x1) {fX1 =x1; fX2 = x2;}
58  else {fX1 = x2; fX2 = x1;}
59  if (y2 >= y1) {fY1 =y1; fY2 = y2;}
60  else {fY1 = y2; fY2 = y1;}
61  fResizing = kFALSE;
62  fTip = 0;
63 }
64 
65 ////////////////////////////////////////////////////////////////////////////////
66 /// Box destructor.
67 
68 TBox::~TBox()
69 {
70  if (fTip && gPad) {
71  gPad->CloseToolTip(fTip);
72  gPad->DeleteToolTip(fTip);
73  }
74 }
75 
76 ////////////////////////////////////////////////////////////////////////////////
77 /// Box copy constructor.
78 
79 TBox::TBox(const TBox &box) : TObject(box), TAttLine(box), TAttFill(box), TAttBBox2D(box)
80 {
81  fX1 = 0.;
82  fY1 = 0.;
83  fX2 = 0.;
84  fY2 = 0.;
85  fResizing = kTRUE;
86  ((TBox&)box).TBox::Copy(*this);
87 }
88 
89 ////////////////////////////////////////////////////////////////////////////////
90 /// Assignment operator.
91 
92 TBox& TBox::operator=(const TBox& b)
93 {
94  if(this!=&b) {
95  TObject::operator=(b);
96  TAttLine::operator=(b);
97  TAttFill::operator=(b);
98  fTip=b.fTip;
99  fX1=b.fX1;
100  fY1=b.fY1;
101  fX2=b.fX2;
102  fY2=b.fY2;
103  fResizing=b.fResizing;
104  }
105  return *this;
106 }
107 
108 ////////////////////////////////////////////////////////////////////////////////
109 /// Copy a Box.
110 
111 void TBox::Copy(TObject &obj) const
112 {
113  TObject::Copy(obj);
114  TAttLine::Copy(((TBox&)obj));
115  TAttFill::Copy(((TBox&)obj));
116  ((TBox&)obj).fX1 = fX1;
117  ((TBox&)obj).fY1 = fY1;
118  ((TBox&)obj).fX2 = fX2;
119  ((TBox&)obj).fY2 = fY2;
120  ((TBox&)obj).fResizing = fResizing;
121  ((TBox&)obj).fTip = 0; //FIXME
122 }
123 
124 ////////////////////////////////////////////////////////////////////////////////
125 /// Compute distance from point px,py to a box.
126 ///
127 /// Compute the closest distance of approach from point px,py to the
128 /// edges of this box.
129 /// The distance is computed in pixels units.
130 ///
131 /// In case of a filled box the distance returned is 0 if the point
132 /// (px,py) is inside the box, and is huge if the point is outside.
133 
134 Int_t TBox::DistancetoPrimitive(Int_t px, Int_t py)
135 {
136  Int_t pxl, pyl, pxt, pyt;
137  Int_t px1 = gPad->XtoAbsPixel(fX1);
138  Int_t py1 = gPad->YtoAbsPixel(fY1);
139  Int_t px2 = gPad->XtoAbsPixel(fX2);
140  Int_t py2 = gPad->YtoAbsPixel(fY2);
141 
142  Bool_t isBox = !(InheritsFrom("TPave") || InheritsFrom("TWbox"));
143 
144  if (isBox) {
145  if (gPad->GetLogx()) {
146  if (fX1>0) px1 = gPad->XtoAbsPixel(TMath::Log10(fX1));
147  if (fX2>0) px2 = gPad->XtoAbsPixel(TMath::Log10(fX2));
148  }
149  if (gPad->GetLogy()) {
150  if (fY1>0) py1 = gPad->YtoAbsPixel(TMath::Log10(fY1));
151  if (fY2>0) py2 = gPad->YtoAbsPixel(TMath::Log10(fY2));
152  }
153  }
154 
155  if (px1 < px2) {pxl = px1; pxt = px2;}
156  else {pxl = px2; pxt = px1;}
157  if (py1 < py2) {pyl = py1; pyt = py2;}
158  else {pyl = py2; pyt = py1;}
159 
160  // Are we inside the box?
161  if (GetFillStyle()) {
162  if ( (px >= pxl && px <= pxt) && (py >= pyl && py <= pyt) ) return 0;
163  else return 9999;
164  }
165 
166  // Are we on the edges?
167  Int_t dxl = TMath::Abs(px - pxl);
168  if (py < pyl) dxl += pyl - py;
169  if (py > pyt) dxl += py - pyt;
170  Int_t dxt = TMath::Abs(px - pxt);
171  if (py < pyl) dxt += pyl - py;
172  if (py > pyt) dxt += py - pyt;
173  Int_t dyl = TMath::Abs(py - pyl);
174  if (px < pxl) dyl += pxl - px;
175  if (px > pxt) dyl += px - pxt;
176  Int_t dyt = TMath::Abs(py - pyt);
177  if (px < pxl) dyt += pxl - px;
178  if (px > pxt) dyt += px - pxt;
179 
180  Int_t distance = dxl;
181  if (dxt < distance) distance = dxt;
182  if (dyl < distance) distance = dyl;
183  if (dyt < distance) distance = dyt;
184 
185  return distance - Int_t(0.5*fLineWidth);
186 }
187 
188 ////////////////////////////////////////////////////////////////////////////////
189 /// Draw this box with its current attributes.
190 /// if the box has no fill style (ie fill style=0), the box contour is drawn
191 /// if the box has a fill style, the box contour is not drawn by default.
192 /// to force the contour to be drawn, specify option "l"
193 
194 void TBox::Draw(Option_t *option)
195 {
196  AppendPad(option);
197 
198 }
199 
200 ////////////////////////////////////////////////////////////////////////////////
201 /// Draw this box with new coordinates.
202 
203 TBox *TBox::DrawBox(Double_t x1, Double_t y1,Double_t x2, Double_t y2)
204 {
205  TBox *newbox = new TBox(x1,y1,x2,y2);
206  TAttLine::Copy(*newbox);
207  TAttFill::Copy(*newbox);
208  newbox->SetBit(kCanDelete);
209  newbox->AppendPad();
210  return newbox;
211 }
212 
213 ////////////////////////////////////////////////////////////////////////////////
214 /// Execute action corresponding to one event.
215 ///
216 /// This member function is called when a BOX/WBOX/PAD object is clicked.
217 ///
218 /// If the mouse is clicked in one of the 4 corners of the box (pA,pB,pC,pD)
219 /// the box is resized with the rubber rectangle.
220 ///
221 /// If the mouse is clicked inside the box, the box is moved.
222 ///
223 /// If the mouse is clicked on the 4 edges (pL,pR,pTop,pBot), the box is
224 /// rescaled parallel to this edge (same as Motif window manager).
225 ///
226 /// Note that this function is duplicated on purpose by TPad::ExecuteEvent.
227 /// If somebody modifies this function, may be similar changes should also
228 /// be applied to TPad::ExecuteEvent.
229 
230 void TBox::ExecuteEvent(Int_t event, Int_t px, Int_t py)
231 {
232  if (!gPad) return;
233  if (!gPad->IsEditable() && event != kMouseEnter) return;
234 
235  if (TestBit(kCannotMove)) return;
236 
237  Bool_t isBox = !(InheritsFrom("TPave") || InheritsFrom("TWbox"));
238 
239  const Int_t kMaxDiff = 7;
240  const Int_t kMinSize = 20;
241 
242  static Int_t px1, px2, py1, py2, pxl, pyl, pxt, pyt, pxold, pyold;
243  static Int_t px1p, px2p, py1p, py2p, pxlp, pylp, pxtp, pytp;
244  static Double_t oldX1, oldY1, oldX2, oldY2;
245  static Bool_t pA, pB, pC, pD, pTop, pL, pR, pBot, pINSIDE;
246  Int_t wx, wy;
247  TVirtualPad *parent = gPad;
248  Bool_t opaque = gPad->OpaqueMoving();
249  Bool_t ropaque = gPad->OpaqueResizing();
250 
251  HideToolTip(event);
252 
253  switch (event) {
254 
255  case kMouseEnter:
256  if (fTip) gPad->ResetToolTip(fTip);
257  break;
258 
259  case kButton1Double:
260  px1 = -1; //used by kButton1Up
261  break;
262 
263  case kArrowKeyPress:
264  case kButton1Down:
265 
266  oldX1 = fX1;
267  oldY1 = fY1;
268  oldX2 = fX2;
269  oldY2 = fY2;
270  gVirtualX->SetLineColor(-1);
271  TAttLine::Modify(); //Change line attributes only if necessary
272  if (GetFillColor())
273  gVirtualX->SetLineColor(GetFillColor());
274  else
275  gVirtualX->SetLineColor(1);
276  gVirtualX->SetLineWidth(2);
277 
278  // No break !!!
279 
280  case kMouseMotion:
281 
282  px1 = gPad->XtoAbsPixel(GetX1());
283  py1 = gPad->YtoAbsPixel(GetY1());
284  px2 = gPad->XtoAbsPixel(GetX2());
285  py2 = gPad->YtoAbsPixel(GetY2());
286 
287  if (isBox) {
288  if (gPad->GetLogx()) {
289  if (fX1>0) px1 = gPad->XtoAbsPixel(TMath::Log10(fX1));
290  if (fX2>0) px2 = gPad->XtoAbsPixel(TMath::Log10(fX2));
291  }
292  if (gPad->GetLogy()) {
293  if (fY1>0) py1 = gPad->YtoAbsPixel(TMath::Log10(fY1));
294  if (fY2>0) py2 = gPad->YtoAbsPixel(TMath::Log10(fY2));
295  }
296  }
297 
298  if (px1 < px2) {
299  pxl = px1;
300  pxt = px2;
301  } else {
302  pxl = px2;
303  pxt = px1;
304  }
305  if (py1 < py2) {
306  pyl = py1;
307  pyt = py2;
308  } else {
309  pyl = py2;
310  pyt = py1;
311  }
312 
313  px1p = parent->XtoAbsPixel(parent->GetX1()) + parent->GetBorderSize();
314  py1p = parent->YtoAbsPixel(parent->GetY1()) - parent->GetBorderSize();
315  px2p = parent->XtoAbsPixel(parent->GetX2()) - parent->GetBorderSize();
316  py2p = parent->YtoAbsPixel(parent->GetY2()) + parent->GetBorderSize();
317 
318  if (px1p < px2p) {
319  pxlp = px1p;
320  pxtp = px2p;
321  } else {
322  pxlp = px2p;
323  pxtp = px1p;
324  }
325  if (py1p < py2p) {
326  pylp = py1p;
327  pytp = py2p;
328  } else {
329  pylp = py2p;
330  pytp = py1p;
331  }
332 
333  pA = pB = pC = pD = pTop = pL = pR = pBot = pINSIDE = kFALSE;
334 
335  // case pA
336  if (TMath::Abs(px - pxl) <= kMaxDiff && TMath::Abs(py - pyl) <= kMaxDiff) {
337  pxold = pxl; pyold = pyl; pA = kTRUE;
338  gPad->SetCursor(kTopLeft);
339  }
340  // case pB
341  if (TMath::Abs(px - pxt) <= kMaxDiff && TMath::Abs(py - pyl) <= kMaxDiff) {
342  pxold = pxt; pyold = pyl; pB = kTRUE;
343  gPad->SetCursor(kTopRight);
344  }
345  // case pC
346  if (TMath::Abs(px - pxt) <= kMaxDiff && TMath::Abs(py - pyt) <= kMaxDiff) {
347  pxold = pxt; pyold = pyt; pC = kTRUE;
348  gPad->SetCursor(kBottomRight);
349  }
350  // case pD
351  if (TMath::Abs(px - pxl) <= kMaxDiff && TMath::Abs(py - pyt) <= kMaxDiff) {
352  pxold = pxl; pyold = pyt; pD = kTRUE;
353  gPad->SetCursor(kBottomLeft);
354  }
355 
356  if ((px > pxl+kMaxDiff && px < pxt-kMaxDiff) &&
357  TMath::Abs(py - pyl) < kMaxDiff) { // top edge
358  pxold = pxl; pyold = pyl; pTop = kTRUE;
359  gPad->SetCursor(kTopSide);
360  }
361 
362  if ((px > pxl+kMaxDiff && px < pxt-kMaxDiff) &&
363  TMath::Abs(py - pyt) < kMaxDiff) { // bottom edge
364  pxold = pxt; pyold = pyt; pBot = kTRUE;
365  gPad->SetCursor(kBottomSide);
366  }
367 
368  if ((py > pyl+kMaxDiff && py < pyt-kMaxDiff) &&
369  TMath::Abs(px - pxl) < kMaxDiff) { // left edge
370  pxold = pxl; pyold = pyl; pL = kTRUE;
371  gPad->SetCursor(kLeftSide);
372  }
373 
374  if ((py > pyl+kMaxDiff && py < pyt-kMaxDiff) &&
375  TMath::Abs(px - pxt) < kMaxDiff) { // right edge
376  pxold = pxt; pyold = pyt; pR = kTRUE;
377  gPad->SetCursor(kRightSide);
378  }
379 
380  if ((px > pxl+kMaxDiff && px < pxt-kMaxDiff) &&
381  (py > pyl+kMaxDiff && py < pyt-kMaxDiff)) { // inside box
382  pxold = px; pyold = py; pINSIDE = kTRUE;
383  if (event == kButton1Down)
384  gPad->SetCursor(kMove);
385  else
386  gPad->SetCursor(kCross);
387  }
388 
389  fResizing = kFALSE;
390  if (pA || pB || pC || pD || pTop || pL || pR || pBot)
391  fResizing = kTRUE;
392 
393  if (!pA && !pB && !pC && !pD && !pTop && !pL && !pR && !pBot && !pINSIDE)
394  gPad->SetCursor(kCross);
395 
396  break;
397 
398  case kArrowKeyRelease:
399  case kButton1Motion:
400 
401  wx = wy = 0;
402 
403  if (pA) {
404  if (!ropaque) gVirtualX->DrawBox(pxold, pyt, pxt, pyold, TVirtualX::kHollow); // draw the old box
405  if (px > pxt-kMinSize) { px = pxt-kMinSize; wx = px; }
406  if (py > pyt-kMinSize) { py = pyt-kMinSize; wy = py; }
407  if (px < pxlp) { px = pxlp; wx = px; }
408  if (py < pylp) { py = pylp; wy = py; }
409  if (!ropaque) gVirtualX->DrawBox(px , pyt, pxt, py, TVirtualX::kHollow); // draw the new box
410  }
411  if (pB) {
412  if (!ropaque) gVirtualX->DrawBox(pxl , pyt, pxold, pyold, TVirtualX::kHollow);
413  if (px < pxl+kMinSize) { px = pxl+kMinSize; wx = px; }
414  if (py > pyt-kMinSize) { py = pyt-kMinSize; wy = py; }
415  if (px > pxtp) { px = pxtp; wx = px; }
416  if (py < pylp) { py = pylp; wy = py; }
417  if (!ropaque) gVirtualX->DrawBox(pxl , pyt, px , py, TVirtualX::kHollow);
418  }
419  if (pC) {
420  if (!ropaque) gVirtualX->DrawBox(pxl , pyl, pxold, pyold, TVirtualX::kHollow);
421  if (px < pxl+kMinSize) { px = pxl+kMinSize; wx = px; }
422  if (py < pyl+kMinSize) { py = pyl+kMinSize; wy = py; }
423  if (px > pxtp) { px = pxtp; wx = px; }
424  if (py > pytp) { py = pytp; wy = py; }
425  if (!ropaque) gVirtualX->DrawBox(pxl , pyl, px , py, TVirtualX::kHollow);
426  }
427  if (pD) {
428  if (!ropaque) gVirtualX->DrawBox(pxold, pyold, pxt, pyl, TVirtualX::kHollow);
429  if (px > pxt-kMinSize) { px = pxt-kMinSize; wx = px; }
430  if (py < pyl+kMinSize) { py = pyl+kMinSize; wy = py; }
431  if (px < pxlp) { px = pxlp; wx = px; }
432  if (py > pytp) { py = pytp; wy = py; }
433  if (!ropaque) gVirtualX->DrawBox(px , py , pxt, pyl, TVirtualX::kHollow);
434  }
435  if (pTop) {
436  if (!ropaque) gVirtualX->DrawBox(px1, py1, px2, py2, TVirtualX::kHollow);
437  py2 += py - pyold;
438  if (py2 > py1-kMinSize) { py2 = py1-kMinSize; wy = py2; }
439  if (py2 < py2p) { py2 = py2p; wy = py2; }
440  if (!ropaque) gVirtualX->DrawBox(px1, py1, px2, py2, TVirtualX::kHollow);
441  }
442  if (pBot) {
443  if (!ropaque) gVirtualX->DrawBox(px1, py1, px2, py2, TVirtualX::kHollow);
444  py1 += py - pyold;
445  if (py1 < py2+kMinSize) { py1 = py2+kMinSize; wy = py1; }
446  if (py1 > py1p) { py1 = py1p; wy = py1; }
447  if (!ropaque) gVirtualX->DrawBox(px1, py1, px2, py2, TVirtualX::kHollow);
448  }
449  if (pL) {
450  if (!ropaque) gVirtualX->DrawBox(px1, py1, px2, py2, TVirtualX::kHollow);
451  px1 += px - pxold;
452  if (px1 > px2-kMinSize) { px1 = px2-kMinSize; wx = px1; }
453  if (px1 < px1p) { px1 = px1p; wx = px1; }
454  if (!ropaque) gVirtualX->DrawBox(px1, py1, px2, py2, TVirtualX::kHollow);
455  }
456  if (pR) {
457  if (!ropaque) gVirtualX->DrawBox(px1, py1, px2, py2, TVirtualX::kHollow);
458  px2 += px - pxold;
459  if (px2 < px1+kMinSize) { px2 = px1+kMinSize; wx = px2; }
460  if (px2 > px2p) { px2 = px2p; wx = px2; }
461  if (!ropaque) gVirtualX->DrawBox(px1, py1, px2, py2, TVirtualX::kHollow);
462  }
463  if (pINSIDE) {
464  if (!opaque) gVirtualX->DrawBox(px1, py1, px2, py2, TVirtualX::kHollow); // draw the old box
465  Int_t dx = px - pxold;
466  Int_t dy = py - pyold;
467  px1 += dx; py1 += dy; px2 += dx; py2 += dy;
468  if (px1 < px1p) { dx = px1p - px1; px1 += dx; px2 += dx; wx = px+dx; }
469  if (px2 > px2p) { dx = px2 - px2p; px1 -= dx; px2 -= dx; wx = px-dx; }
470  if (py1 > py1p) { dy = py1 - py1p; py1 -= dy; py2 -= dy; wy = py-dy; }
471  if (py2 < py2p) { dy = py2p - py2; py1 += dy; py2 += dy; wy = py+dy; }
472  if (!opaque) gVirtualX->DrawBox(px1, py1, px2, py2, TVirtualX::kHollow); // draw the new box
473  }
474 
475  if (wx || wy) {
476  if (wx) px = wx;
477  if (wy) py = wy;
478  gVirtualX->Warp(px, py);
479  }
480 
481  pxold = px;
482  pyold = py;
483 
484 
485  if ((pINSIDE && opaque) || (fResizing && ropaque)) {
486  if (pA) {
487  fX1 = gPad->AbsPixeltoX(pxold);
488  fY1 = gPad->AbsPixeltoY(pyt);
489  fX2 = gPad->AbsPixeltoX(pxt);
490  fY2 = gPad->AbsPixeltoY(pyold);
491  }
492  if (pB) {
493  fX1 = gPad->AbsPixeltoX(pxl);
494  fY1 = gPad->AbsPixeltoY(pyt);
495  fX2 = gPad->AbsPixeltoX(pxold);
496  fY2 = gPad->AbsPixeltoY(pyold);
497  }
498  if (pC) {
499  fX1 = gPad->AbsPixeltoX(pxl);
500  fY1 = gPad->AbsPixeltoY(pyold);
501  fX2 = gPad->AbsPixeltoX(pxold);
502  fY2 = gPad->AbsPixeltoY(pyl);
503  }
504  if (pD) {
505  fX1 = gPad->AbsPixeltoX(pxold);
506  fY1 = gPad->AbsPixeltoY(pyold);
507  fX2 = gPad->AbsPixeltoX(pxt);
508  fY2 = gPad->AbsPixeltoY(pyl);
509  }
510  if (pTop || pBot || pL || pR || pINSIDE) {
511  fX1 = gPad->AbsPixeltoX(px1);
512  fY1 = gPad->AbsPixeltoY(py1);
513  fX2 = gPad->AbsPixeltoX(px2);
514  fY2 = gPad->AbsPixeltoY(py2);
515  }
516 
517  if (isBox) {
518  if (gPad->GetLogx()) {
519  fX1 = TMath::Power(10,fX1);
520  fX2 = TMath::Power(10,fX2);
521  }
522  if (gPad->GetLogy()) {
523  fY1 = TMath::Power(10,fY1);
524  fY2 = TMath::Power(10,fY2);
525  }
526  }
527 
528  if (pINSIDE) gPad->ShowGuidelines(this, event, 'i', true);
529  if (pTop) gPad->ShowGuidelines(this, event, 't', true);
530  if (pBot) gPad->ShowGuidelines(this, event, 'b', true);
531  if (pL) gPad->ShowGuidelines(this, event, 'l', true);
532  if (pR) gPad->ShowGuidelines(this, event, 'r', true);
533  if (pA) gPad->ShowGuidelines(this, event, '1', true);
534  if (pB) gPad->ShowGuidelines(this, event, '2', true);
535  if (pC) gPad->ShowGuidelines(this, event, '3', true);
536  if (pD) gPad->ShowGuidelines(this, event, '4', true);
537  gPad->Modified(kTRUE);
538  }
539 
540  break;
541 
542  case kButton1Up:
543  if (gROOT->IsEscaped()) {
544  gROOT->SetEscape(kFALSE);
545  if (opaque) {
546  this->SetX1(oldX1);
547  this->SetY1(oldY1);
548  this->SetX2(oldX2);
549  this->SetY2(oldY2);
550  gPad->Modified(kTRUE);
551  gPad->Update();
552  }
553  break;
554  }
555 
556  if (opaque || ropaque) {
557  gPad->ShowGuidelines(this, event);
558  } else {
559  if (px1 < 0 ) break;
560  if (pA) {
561  fX1 = gPad->AbsPixeltoX(pxold);
562  fY1 = gPad->AbsPixeltoY(pyt);
563  fX2 = gPad->AbsPixeltoX(pxt);
564  fY2 = gPad->AbsPixeltoY(pyold);
565  }
566  if (pB) {
567  fX1 = gPad->AbsPixeltoX(pxl);
568  fY1 = gPad->AbsPixeltoY(pyt);
569  fX2 = gPad->AbsPixeltoX(pxold);
570  fY2 = gPad->AbsPixeltoY(pyold);
571  }
572  if (pC) {
573  fX1 = gPad->AbsPixeltoX(pxl);
574  fY1 = gPad->AbsPixeltoY(pyold);
575  fX2 = gPad->AbsPixeltoX(pxold);
576  fY2 = gPad->AbsPixeltoY(pyl);
577  }
578  if (pD) {
579  fX1 = gPad->AbsPixeltoX(pxold);
580  fY1 = gPad->AbsPixeltoY(pyold);
581  fX2 = gPad->AbsPixeltoX(pxt);
582  fY2 = gPad->AbsPixeltoY(pyl);
583  }
584  if (pTop || pBot || pL || pR || pINSIDE) {
585  fX1 = gPad->AbsPixeltoX(px1);
586  fY1 = gPad->AbsPixeltoY(py1);
587  fX2 = gPad->AbsPixeltoX(px2);
588  fY2 = gPad->AbsPixeltoY(py2);
589  }
590 
591  if (isBox) {
592  if (gPad->GetLogx()) {
593  fX1 = TMath::Power(10,fX1);
594  fX2 = TMath::Power(10,fX2);
595  }
596  if (gPad->GetLogy()) {
597  fY1 = TMath::Power(10,fY1);
598  fY2 = TMath::Power(10,fY2);
599  }
600  }
601  if (pINSIDE) {
602  // if it was not a pad that was moved then it must have been
603  // a box or something like that so we have to redraw the pad
604  if (parent == gPad) gPad->Modified(kTRUE);
605  }
606  }
607 
608  if (pA || pB || pC || pD || pTop || pL || pR || pBot) gPad->Modified(kTRUE);
609 
610  if (!opaque) {
611  gVirtualX->SetLineColor(-1);
612  gVirtualX->SetLineWidth(-1);
613  }
614 
615  break;
616 
617  case kButton1Locate:
618 
619  ExecuteEvent(kButton1Down, px, py);
620 
621  while (1) {
622  px = py = 0;
623  event = gVirtualX->RequestLocator(1, 1, px, py);
624 
625  ExecuteEvent(kButton1Motion, px, py);
626 
627  if (event != -1) { // button is released
628  ExecuteEvent(kButton1Up, px, py);
629  return;
630  }
631  }
632  }
633 }
634 
635 ////////////////////////////////////////////////////////////////////////////////
636 /// Hide tool tip depending on the event type. Typically tool tips
637 /// are hidden when event is not a kMouseEnter and not a kMouseMotion
638 /// event.
639 
640 void TBox::HideToolTip(Int_t event)
641 {
642  if (event != kMouseEnter && event != kMouseMotion && fTip && gPad)
643  gPad->CloseToolTip(fTip);
644 }
645 
646 ////////////////////////////////////////////////////////////////////////////////
647 /// Function which returns 1 if point x,y lies inside the box, 0 otherwise.
648 
649 Int_t TBox::IsInside(Double_t x, Double_t y) const
650 {
651  if (x < fX1 || x > fX2) return 0;
652  if (y < fY1 || y > fY2) return 0;
653  return 1;
654 }
655 
656 ////////////////////////////////////////////////////////////////////////////////
657 /// List this box with its attributes.
658 
659 void TBox::ls(Option_t *) const
660 {
661  TROOT::IndentLevel();
662  printf("%s X1= %f Y1=%f X2=%f Y2=%f\n",IsA()->GetName(),fX1,fY1,fX2,fY2);
663 }
664 
665 ////////////////////////////////////////////////////////////////////////////////
666 /// Paint this box with its current attributes.
667 
668 void TBox::Paint(Option_t *option)
669 {
670  PaintBox(gPad->XtoPad(fX1),gPad->YtoPad(fY1),gPad->XtoPad(fX2),gPad->YtoPad(fY2),option);
671 }
672 
673 ////////////////////////////////////////////////////////////////////////////////
674 /// Draw this box with new coordinates.
675 
676 void TBox::PaintBox(Double_t x1, Double_t y1, Double_t x2, Double_t y2, Option_t *option)
677 {
678  TAttLine::Modify(); //Change line attributes only if necessary
679  TAttFill::Modify(); //Change fill area attributes only if necessary
680 
681  if (option) {
682  TString opt = option;
683  opt.ToLower();
684  if (opt.Contains("l")) gPad->PaintBox(x1,y1,x2,y2,"l");
685  else gPad->PaintBox(x1,y1,x2,y2);
686  } else {
687  gPad->PaintBox(x1,y1,x2,y2);
688  }
689 }
690 
691 ////////////////////////////////////////////////////////////////////////////////
692 /// Dump this box with its attributes.
693 
694 void TBox::Print(Option_t *) const
695 {
696  printf("%s X1=%f Y1=%f X2=%f Y2=%f",IsA()->GetName(),fX1,fY1,fX2,fY2);
697  if (GetLineColor() != 1) printf(" Color=%d",GetLineColor());
698  if (GetLineStyle() != 1) printf(" Style=%d",GetLineStyle());
699  if (GetLineWidth() != 1) printf(" Width=%d",GetLineWidth());
700  if (GetFillColor() != 0) printf(" FillColor=%d",GetFillColor());
701  if (GetFillStyle() != 0) printf(" FillStyle=%d",GetFillStyle());
702  printf("\n");
703 }
704 
705 ////////////////////////////////////////////////////////////////////////////////
706 /// Save primitive as a C++ statement(s) on output stream out
707 
708 void TBox::SavePrimitive(std::ostream &out, Option_t * /*= ""*/)
709 {
710  if (gROOT->ClassSaved(TBox::Class())) {
711  out<<" ";
712  } else {
713  out<<" TBox *";
714  }
715  out<<"box = new TBox("<<fX1<<","<<fY1<<","<<fX2<<","<<fY2<<");"<<std::endl;
716 
717  SaveFillAttributes(out,"box",0,1001);
718  SaveLineAttributes(out,"box",1,1,1);
719 
720  out<<" box->Draw();"<<std::endl;
721 }
722 
723 ////////////////////////////////////////////////////////////////////////////////
724 /// Set tool tip text associated with this box. The delay is in
725 /// milliseconds (minimum 250). To remove tool tip call method with
726 /// text = 0.
727 
728 void TBox::SetToolTipText(const char *text, Long_t delayms)
729 {
730  if (!gPad) {
731  Warning("SetToolTipText", "a canvas must exist before setting the tool tip text");
732  return;
733  }
734 
735  if (fTip) {
736  gPad->DeleteToolTip(fTip);
737  fTip = 0;
738  }
739 
740  if (text && strlen(text))
741  fTip = gPad->CreateToolTip(this, text, delayms);
742 }
743 
744 ////////////////////////////////////////////////////////////////////////////////
745 /// Stream an object of class TBox.
746 
747 void TBox::Streamer(TBuffer &R__b)
748 {
749  if (R__b.IsReading()) {
750  UInt_t R__s, R__c;
751  Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
752  if (R__v > 1) {
753  R__b.ReadClassBuffer(TBox::Class(), this, R__v, R__s, R__c);
754  return;
755  }
756  //====process old versions before automatic schema evolution
757  TObject::Streamer(R__b);
758  TAttLine::Streamer(R__b);
759  TAttFill::Streamer(R__b);
760  Float_t x1,y1,x2,y2;
761  R__b >> x1; fX1 = x1;
762  R__b >> y1; fY1 = y1;
763  R__b >> x2; fX2 = x2;
764  R__b >> y2; fY2 = y2;
765  R__b.CheckByteCount(R__s, R__c, TBox::IsA());
766  //====end of old versions
767 
768  } else {
769  R__b.WriteClassBuffer(TBox::Class(),this);
770  }
771 }
772 
773 ////////////////////////////////////////////////////////////////////////////////
774 /// Return the "bounding Box" of the Box
775 
776 Rectangle_t TBox::GetBBox()
777 {
778  Rectangle_t BBox;
779  Int_t px1, py1, px2, py2;
780  px1 = gPad->XtoPixel(fX1);
781  px2 = gPad->XtoPixel(fX2);
782  py1 = gPad->YtoPixel(fY1);
783  py2 = gPad->YtoPixel(fY2);
784 
785  Int_t tmp;
786  if (px1>px2) { tmp = px1; px1 = px2; px2 = tmp;}
787  if (py1>py2) { tmp = py1; py1 = py2; py2 = tmp;}
788 
789  BBox.fX = px1;
790  BBox.fY = py1;
791  BBox.fWidth = px2-px1;
792  BBox.fHeight = py2-py1;
793 
794  return (BBox);
795 }
796 
797 ////////////////////////////////////////////////////////////////////////////////
798 /// Return the center of the Box as TPoint in pixels
799 
800 TPoint TBox::GetBBoxCenter()
801 {
802  TPoint p;
803  p.SetX(gPad->XtoPixel(TMath::Min(fX1,fX2)+0.5*(TMath::Max(fX1, fX2)-TMath::Min(fX1, fX2))));
804  p.SetY(gPad->YtoPixel(TMath::Min(fY1,fY2)+0.5*(TMath::Max(fY1, fY2)-TMath::Min(fY1, fY2))));
805  return(p);
806 }
807 
808 ////////////////////////////////////////////////////////////////////////////////
809 /// Set center of the Box
810 
811 void TBox::SetBBoxCenter(const TPoint &p)
812 {
813  Double_t w = TMath::Max(fX1, fX2)-TMath::Min(fX1, fX2);
814  Double_t h = TMath::Max(fY1, fY2)-TMath::Min(fY1, fY2);
815  if (fX2>fX1) {
816  this->SetX1(gPad->PixeltoX(p.GetX())-0.5*w);
817  this->SetX2(gPad->PixeltoX(p.GetX())+0.5*w);
818  }
819  else {
820  this->SetX2(gPad->PixeltoX(p.GetX())-0.5*w);
821  this->SetX1(gPad->PixeltoX(p.GetX())+0.5*w);
822  }
823  if (fY2>fY1) {
824  this->SetY1(gPad->PixeltoY(p.GetY()-gPad->VtoPixel(0))-0.5*h);
825  this->SetY2(gPad->PixeltoY(p.GetY()-gPad->VtoPixel(0))+0.5*h);
826  }
827  else {
828  this->SetY2(gPad->PixeltoY(p.GetY()-gPad->VtoPixel(0))-0.5*h);
829  this->SetY1(gPad->PixeltoY(p.GetY()-gPad->VtoPixel(0))+0.5*h);
830  }
831 }
832 
833 ////////////////////////////////////////////////////////////////////////////////
834 /// Set X coordinate of the center of the Box
835 
836 void TBox::SetBBoxCenterX(const Int_t x)
837 {
838  if (x<0) return;
839  Double_t w = TMath::Max(fX1, fX2)-TMath::Min(fX1, fX2);
840  if (fX2>fX1) {
841  this->SetX1(gPad->PixeltoX(x)-0.5*w);
842  this->SetX2(gPad->PixeltoX(x)+0.5*w);
843  }
844  else {
845  this->SetX2(gPad->PixeltoX(x)-0.5*w);
846  this->SetX1(gPad->PixeltoX(x)+0.5*w);
847  }
848 }
849 
850 ////////////////////////////////////////////////////////////////////////////////
851 /// Set Y coordinate of the center of the Box
852 
853 void TBox::SetBBoxCenterY(const Int_t y)
854 {
855  if (y<0) return;
856  Double_t h = TMath::Max(fY1, fY2)-TMath::Min(fY1, fY2);
857  if (fY2>fY1) {
858  this->SetY1(gPad->PixeltoY(y-gPad->VtoPixel(0))-0.5*h);
859  this->SetY2(gPad->PixeltoY(y-gPad->VtoPixel(0))+0.5*h);
860  }
861  else {
862  this->SetY2(gPad->PixeltoY(y-gPad->VtoPixel(0))-0.5*h);
863  this->SetY1(gPad->PixeltoY(y-gPad->VtoPixel(0))+0.5*h);
864  }
865 }
866 
867 ////////////////////////////////////////////////////////////////////////////////
868 /// Set left hand side of BoundingBox to a value
869 /// (resize in x direction on left)
870 
871 void TBox::SetBBoxX1(const Int_t x)
872 {
873  if (x<0) return;
874  fX1 = gPad->PixeltoX(x);
875 }
876 
877 ////////////////////////////////////////////////////////////////////////////////
878 /// Set right hand side of BoundingBox to a value
879 /// (resize in x direction on right)
880 
881 void TBox::SetBBoxX2(const Int_t x)
882 {
883  if (x<0) return;
884  fX2 = gPad->PixeltoX(x);
885 }
886 
887 ////////////////////////////////////////////////////////////////////////////////
888 /// Set top of BoundingBox to a value (resize in y direction on top)
889 
890 void TBox::SetBBoxY1(const Int_t y)
891 {
892  if (y<0) return;
893  fY2 = gPad->PixeltoY(y - gPad->VtoPixel(0));
894 }
895 
896 ////////////////////////////////////////////////////////////////////////////////
897 /// Set bottom of BoundingBox to a value
898 /// (resize in y direction on bottom)
899 
900 void TBox::SetBBoxY2(const Int_t y)
901 {
902  if (y<0) return;
903  fY1 = gPad->PixeltoY(y - gPad->VtoPixel(0));
904 }