TGImageMap.cxx

Go to the documentation of this file.
00001 // @(#)root/gui:$Id: TGImageMap.cxx 31669 2009-12-08 15:15:47Z bellenot $
00002 // Author: Valeriy Onuchin & Fons Rademakers   18/10/2000
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2000, 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 //////////////////////////////////////////////////////////////////////////
00013 //                                                                      //
00014 // TGImageMap (with TGRegion and TGRegionWithId help classes)           //
00015 //                                                                      //
00016 // A TGImageMap provides the functionality like a clickable image in    //
00017 // a web browser with sensitive regions (MAP HTML tag).                 //
00018 //                                                                      //
00019 //////////////////////////////////////////////////////////////////////////
00020 
00021 #include "TGImageMap.h"
00022 #include "TRefCnt.h"
00023 #include "TGMenu.h"
00024 #include "TGToolTip.h"
00025 #include "TList.h"
00026 #include "TArrayS.h"
00027 
00028 
00029 ClassImp(TGRegion)
00030 ClassImp(TGRegionWithId)
00031 ClassImpQ(TGImageMap)
00032 
00033 
00034 TGRegionWithId  *gCurrentRegion; // current region
00035 
00036 static TGRegion *gEmptyRegion = 0;
00037 static Int_t gPointerX;  // current X mouse position
00038 static Int_t gPointerY;  // current Y mouse position
00039 
00040 
00041 
00042 class TGRegionData : public TRefCnt {
00043 
00044 friend class TGRegion;
00045 
00046 private:
00047    Region_t   fRgn;     // region handle
00048    Bool_t     fIsNull;  // true if null region
00049 
00050 public:
00051    TGRegionData() { fRgn = 0; fIsNull = kTRUE; AddReference(); }
00052    ~TGRegionData() { }
00053    TGRegionData &operator=(const TGRegionData &r);
00054 };
00055 
00056 //______________________________________________________________________________
00057 TGRegionData &TGRegionData::operator=(const TGRegionData &r)
00058 {
00059    // Assignemnt of region data object.
00060 
00061    fRefs   = r.fRefs;
00062    fRgn    = r.fRgn;
00063    fIsNull = r.fIsNull;
00064 
00065    return *this;
00066 }
00067 
00068 
00069 ////////////////////////////////////////////////////////////////////////////////
00070 //______________________________________________________________________________
00071 TGRegion::TGRegion()
00072 {
00073    // Create a region object.
00074 
00075    if (!gEmptyRegion)                      // avoid too many allocs
00076       gEmptyRegion = new TGRegion(kTRUE);
00077 
00078    fData = gEmptyRegion->fData;
00079    fData->AddReference();
00080 }
00081 
00082 //______________________________________________________________________________
00083 TGRegion::TGRegion(Bool_t is_null)
00084 {
00085    // Create empty region.
00086 
00087    fData          = new TGRegionData;
00088    fData->fRgn    = gVirtualX->CreateRegion();
00089    fData->fIsNull = is_null;
00090 }
00091 
00092 //______________________________________________________________________________
00093 TGRegion::TGRegion(Int_t x, Int_t y, UInt_t w, UInt_t h, ERegionType)
00094 {
00095    // Create and initialize a region with a rectangle.
00096 
00097    fData          = new TGRegionData;
00098    fData->fRgn    = gVirtualX->CreateRegion();
00099    fData->fIsNull = kFALSE;
00100 
00101    Rectangle_t xr;
00102    xr.fX      = (Short_t) x;
00103    xr.fY      = (Short_t) y;
00104    xr.fWidth  = (UShort_t) w;
00105    xr.fHeight = (UShort_t) h;
00106    gVirtualX->UnionRectWithRegion(&xr, fData->fRgn, fData->fRgn);
00107 }
00108 
00109 //______________________________________________________________________________
00110 TGRegion::TGRegion(Int_t n, TPoint *points, Bool_t winding)
00111 {
00112    // Create and intialize a region with a polygon.
00113 
00114    fData            = new TGRegionData;
00115    fData->fIsNull   = kFALSE;
00116    Point_t *gpoints = new Point_t[n];
00117 
00118    for (int i = 0; i < n; i++) {
00119       gpoints[i].fX = (Short_t) points[i].GetX();
00120       gpoints[i].fY = (Short_t) points[i].GetY();
00121    }
00122 
00123    fData->fRgn = gVirtualX->PolygonRegion(gpoints, n, winding);
00124 }
00125 
00126 //______________________________________________________________________________
00127 TGRegion::TGRegion(const TArrayS &x, const TArrayS &y, Bool_t winding)
00128 {
00129    // Create and initialize a region with an X and a Y array of points.
00130 
00131    fData          = new TGRegionData;
00132    fData->fIsNull = kFALSE;
00133 
00134    Int_t n = x.GetSize();
00135    if (n != y.GetSize()) {
00136       Error("TGRegion", "x and y arrays must have same length");
00137       return;
00138    }
00139    Point_t *gpoints = new Point_t[n];
00140 
00141    for (int i = 0; i < n; i++) {
00142       gpoints[i].fX = x.GetArray()[i];
00143       gpoints[i].fY = y.GetArray()[i];
00144    }
00145 
00146    fData->fRgn = gVirtualX->PolygonRegion(gpoints, n, winding);
00147 }
00148 
00149 //_____________________________________________________________________________
00150 TGRegion::TGRegion(Int_t n, Int_t *x, Int_t *y, Bool_t winding)
00151 {
00152    // Create and initialize a region with an X and Y array of points.
00153 
00154    fData          = new TGRegionData;
00155    fData->fIsNull = kFALSE;
00156    Point_t *gpoints = new Point_t[n];
00157 
00158    for (int i = 0; i < n; i++) {
00159       gpoints[i].fX = x[i];
00160       gpoints[i].fY = y[i];
00161    }
00162 
00163    fData->fRgn = gVirtualX->PolygonRegion(gpoints, n, winding);
00164 }
00165 
00166 //______________________________________________________________________________
00167 TGRegion::TGRegion(const TGRegion &r) : TObject(r)
00168 {
00169    // Region copy constructor.
00170 
00171    fData = r.fData;
00172    fData->AddReference();
00173 }
00174 
00175 //______________________________________________________________________________
00176 TGRegion::~TGRegion()
00177 {
00178    // Delete a region.
00179 
00180    if (fData->RemoveReference() <= 0) {
00181       gVirtualX->DestroyRegion(fData->fRgn);
00182       delete fData;
00183    }
00184 }
00185 
00186 //______________________________________________________________________________
00187 TGRegion &TGRegion::operator=(const TGRegion &r)
00188 {
00189    // Region assignment operator.
00190 
00191    if (this != &r) {
00192       r.fData->AddReference();
00193 
00194       if (fData->RemoveReference() <= 0) {
00195          gVirtualX->DestroyRegion(fData->fRgn);
00196          delete fData;
00197       }
00198       fData = r.fData;
00199    }
00200    return *this;
00201 }
00202 
00203 //______________________________________________________________________________
00204 TGRegion TGRegion::CopyRegion() const
00205 {
00206    // Copy a region.
00207 
00208    TGRegion r(fData->fIsNull);
00209    gVirtualX->UnionRegion(fData->fRgn, r.fData->fRgn, r.fData->fRgn);
00210    return r;
00211 }
00212 
00213 //______________________________________________________________________________
00214 Bool_t TGRegion::IsNull() const
00215 {
00216    // Return true if region is not set.
00217 
00218    return fData->fIsNull;
00219 }
00220 
00221 //______________________________________________________________________________
00222 Bool_t TGRegion::IsEmpty() const
00223 {
00224    // Return true if region is empty.
00225 
00226    return fData->fIsNull || gVirtualX->EmptyRegion(fData->fRgn);
00227 }
00228 
00229 //______________________________________________________________________________
00230 Bool_t TGRegion::Contains(const TPoint &p) const
00231 {
00232    // Return true if point p is contained in the region.
00233 
00234    return gVirtualX->PointInRegion((Int_t)p.GetX(), (Int_t)p.GetY(), fData->fRgn);
00235 }
00236 
00237 //______________________________________________________________________________
00238 Bool_t TGRegion::Contains(Int_t x, Int_t y) const
00239 {
00240    // Return true if point (x,y) is contained in the region.
00241 
00242    return gVirtualX->PointInRegion(x, y, fData->fRgn);
00243 }
00244 
00245 //______________________________________________________________________________
00246 TGRegion TGRegion::Unite(const TGRegion &r) const
00247 {
00248    // Return the union of this region with r.
00249 
00250    TGRegion result(kFALSE);
00251    gVirtualX->UnionRegion(fData->fRgn, r.fData->fRgn, result.fData->fRgn);
00252    return result;
00253 }
00254 
00255 //______________________________________________________________________________
00256 TGRegion TGRegion::Intersect(const TGRegion &r) const
00257 {
00258    // Returns a region which is the intersection of this region and r.
00259 
00260    TGRegion result(kFALSE);
00261    gVirtualX->IntersectRegion(fData->fRgn, r.fData->fRgn, result.fData->fRgn);
00262    return result;
00263 }
00264 
00265 //______________________________________________________________________________
00266 TGRegion TGRegion::Subtract(const TGRegion &r) const
00267 {
00268    // Returns a region which is r subtracted from this region.
00269 
00270    TGRegion result(kFALSE);
00271    gVirtualX->SubtractRegion(fData->fRgn, r.fData->fRgn, result.fData->fRgn);
00272    return result;
00273 }
00274 
00275 //______________________________________________________________________________
00276 TGRegion TGRegion::Eor(const TGRegion &r) const
00277 {
00278    // Returns a region which is the difference between the union and
00279    // intersection this region and r.
00280 
00281    TGRegion result(kFALSE);
00282    gVirtualX->XorRegion(fData->fRgn, r.fData->fRgn, result.fData->fRgn);
00283    return result;
00284 }
00285 
00286 //______________________________________________________________________________
00287 TGDimension TGRegion::GetDimension() const
00288 {
00289    // Return dimension of region (widht, height).
00290 
00291    Rectangle_t r = { 0, 0, 0, 0 };
00292    gVirtualX->GetRegionBox(fData->fRgn, &r);
00293    return TGDimension(r.fWidth, r.fHeight);
00294 }
00295 
00296 //______________________________________________________________________________
00297 TGPosition TGRegion::GetPosition() const
00298 {
00299    // Return position of region (x, y).
00300 
00301    Rectangle_t r = { 0, 0, 0, 0 };
00302    gVirtualX->GetRegionBox(fData->fRgn, &r);
00303    return TGPosition(r.fX, r.fY);
00304 }
00305 
00306 //______________________________________________________________________________
00307 Bool_t TGRegion::operator==(const TGRegion &r) const
00308 {
00309    // Region == operator.
00310 
00311    return fData == r.fData ?
00312              kTRUE : gVirtualX->EqualRegion(fData->fRgn, r.fData->fRgn);
00313 }
00314 
00315 
00316 ////////////////////////////////////////////////////////////////////////////////
00317 //______________________________________________________________________________
00318 TGRegionWithId::TGRegionWithId() : TGRegion()
00319 {
00320    // Create GUI region (with id and possible tooltip).
00321 
00322    fId    = 0;
00323    fTip   = 0;
00324    fPopup = 0;
00325 }
00326 
00327 //______________________________________________________________________________
00328 TGRegionWithId::TGRegionWithId(Int_t id, Int_t x, Int_t y,
00329                                UInt_t w, UInt_t h, ERegionType type) :
00330    TGRegion(x, y, w, h, type)
00331 {
00332    // Create GUI region (with id and possible tooltip).
00333 
00334    fId    = id;
00335    fTip   = 0;
00336    fPopup = 0;
00337 }
00338 
00339 //______________________________________________________________________________
00340 TGRegionWithId::TGRegionWithId(Int_t id, Int_t n, TPoint *points,
00341                                Bool_t winding) :
00342    TGRegion(n, points, winding)
00343 {
00344    // Create GUI region (with id and possible tooltip).
00345 
00346    fId    = id;
00347    fTip   = 0;
00348    fPopup = 0;
00349 }
00350 
00351 //______________________________________________________________________________
00352 TGRegionWithId::TGRegionWithId(const TGRegionWithId &reg) : TGRegion(reg)
00353 {
00354    // Copy constructor.
00355 
00356    fId    = reg.GetId();
00357    fTip   = 0;
00358    fPopup = 0;
00359 }
00360 
00361 //______________________________________________________________________________
00362 TGRegionWithId::TGRegionWithId(const TGRegion &reg, Int_t id) :
00363    TGRegion(reg)
00364 {
00365    // Copy ctor which allows setting of new id.
00366 
00367    fId    = id;
00368    fTip   = 0;
00369    fPopup = 0;
00370 }
00371 
00372 //______________________________________________________________________________
00373 TGRegionWithId::~TGRegionWithId()
00374 {
00375    // Cleanup.
00376 
00377    delete fTip;
00378 }
00379 
00380 //______________________________________________________________________________
00381 void TGRegionWithId::DisplayPopup()
00382 {
00383    // Display popup menu associated with this region.
00384 
00385    if (fPopup) fPopup->PlaceMenu(gPointerX, gPointerY, kFALSE, kTRUE);
00386 }
00387 
00388 //______________________________________________________________________________
00389 void TGRegionWithId::SetToolTipText(const char *text, Long_t delayms,
00390                                     const TGFrame *frame)
00391 {
00392    // Set tool tip text associated with this region. The delay is in
00393    // milliseconds (minimum 250). To remove tool tip call method with
00394    // text = 0.
00395 
00396    if (fTip) {
00397       delete fTip;
00398       fTip = 0;
00399    }
00400 
00401    if (text && strlen(text))
00402       fTip = new TGToolTip(gClient->GetDefaultRoot(), frame, text, delayms);
00403 }
00404 
00405 ////////////////////////////////////////////////////////////////////////////////
00406 //______________________________________________________________________________
00407 TGImageMap::TGImageMap(const TGWindow *p, const TGPicture *pic) :
00408    TGPictureButton(p, pic)
00409 {
00410    // Create an image map widget.
00411 
00412    fCursorMouseOut  = kPointer;
00413    fCursorMouseOver = kHand;
00414    fListOfRegions   = new TList;
00415    fTrash           = new TList;
00416    fMainTip         = 0;
00417    fNavMode = kNavRegions;
00418 
00419    SetDisabledPicture(fPic);
00420    SetState(kButtonDisabled);
00421 
00422    gVirtualX->GrabButton(fId, kAnyButton, kAnyModifier,
00423                          kButtonPressMask | kButtonReleaseMask |
00424                          kPointerMotionMask, kNone, kNone);
00425 
00426    AddInput(kKeyPressMask | kKeyReleaseMask | kPointerMotionMask |
00427             kStructureNotifyMask | kLeaveWindowMask);
00428    SetWindowName();
00429 }
00430 
00431 //______________________________________________________________________________
00432 TGImageMap::TGImageMap(const TGWindow *p, const TString &pic) :
00433    TGPictureButton(p, pic.Data())
00434 {
00435    // Create an image map widget.
00436 
00437    fCursorMouseOut  = kPointer;
00438    fCursorMouseOver = kHand;
00439    fListOfRegions   = new TList;
00440    fTrash           = new TList;
00441    fMainTip         = 0;
00442    fNavMode = kNavRegions;
00443 
00444    SetDisabledPicture(fPic);
00445    SetState(kButtonDisabled);
00446 
00447    gVirtualX->GrabButton(fId, kAnyButton, kAnyModifier,
00448                          kButtonPressMask | kButtonReleaseMask |
00449                          kPointerMotionMask, kNone, kNone);
00450 
00451    AddInput(kKeyPressMask | kKeyReleaseMask | kPointerMotionMask |
00452             kStructureNotifyMask | kLeaveWindowMask);
00453    SetWindowName();
00454 }
00455 
00456 //______________________________________________________________________________
00457 TGImageMap::~TGImageMap()
00458 {
00459    // Cleanup image map widget.
00460 
00461    delete fMainTip;
00462    fTrash->Delete();
00463    delete fTrash;
00464    fListOfRegions->Delete();
00465    delete fListOfRegions;
00466 }
00467 
00468 //______________________________________________________________________________
00469 void TGImageMap::AddRegion(const TGRegion &region, Int_t id)
00470 {
00471    // Add a region to the image map.
00472 
00473    fListOfRegions->Add(new TGRegionWithId(region, id));
00474 }
00475 
00476 //______________________________________________________________________________
00477 TGPopupMenu *TGImageMap::CreatePopup(Int_t id)
00478 {
00479    // Create popoup menu or returns existing for regions with specified id.
00480 
00481    TIter next(fListOfRegions);
00482    TGRegionWithId *region;
00483    TGPopupMenu    *popup = 0;
00484    TGPopupMenu    *newpopup = 0;
00485 
00486    while ((region = (TGRegionWithId*)next())) {
00487       if (id == region->GetId()) {
00488          popup = region->GetPopup();
00489          if (!popup && !newpopup) {
00490             newpopup = new TGPopupMenu(this);
00491             fTrash->Add(newpopup);
00492          }
00493          if (newpopup) region->SetPopup(newpopup);
00494       }
00495    }
00496    return newpopup ? newpopup : popup;
00497 }
00498 
00499 //______________________________________________________________________________
00500 TGPopupMenu *TGImageMap::GetPopup(Int_t id)
00501 {
00502    // Return popup for regions with specified id.
00503 
00504    TIter next(fListOfRegions);
00505    TGRegionWithId *region;
00506 
00507    while ((region = (TGRegionWithId*)next())) {
00508       if (id == region->GetId()) return region->GetPopup();
00509    }
00510    return 0;
00511 }
00512 
00513 //______________________________________________________________________________
00514 Bool_t TGImageMap::HandleMotion(Event_t *event)
00515 {
00516    // Handle mouse motion events.
00517 
00518    TIter next(fListOfRegions);
00519    TGRegionWithId *region;
00520 
00521    if (fNavMode != kNavRegions) return kTRUE;
00522    gPointerX = event->fX;
00523    gPointerY = event->fY;
00524 
00525    while ((region = (TGRegionWithId*)next())) {
00526       if (region->Contains(gPointerX, gPointerY)) {
00527          if (fLastVisited == region->GetId()) return kTRUE;
00528          if (fLastVisited) OnMouseOut(fLastVisited);
00529          fLastVisited = region->GetId();
00530          fTip = region->GetToolTipText();
00531          gCurrentRegion = region;
00532          OnMouseOver(fLastVisited);
00533          return kTRUE;
00534       }
00535    }
00536 
00537    if (fLastVisited) {
00538       OnMouseOut(fLastVisited);
00539       fTip = fMainTip;
00540    }
00541    fLastVisited = 0;  // main
00542    return kTRUE;
00543 }
00544 
00545 //______________________________________________________________________________
00546 Bool_t TGImageMap::HandleDoubleClick(Event_t *event)
00547 {
00548    // Handle double click events.
00549 
00550    TIter next(fListOfRegions);
00551    TGRegionWithId *region;
00552 
00553    if (fTip) fTip->Hide();
00554    if (event->fCode != kButton1 ) return kTRUE;
00555    if (fNavMode != kNavRegions) return kTRUE;
00556 
00557    gPointerX = event->fX;
00558    gPointerY = event->fY;
00559 
00560    while ((region = (TGRegionWithId*)next())) {
00561       if (region->Contains(gPointerX, gPointerY)) {
00562          DoubleClicked(region->GetId());
00563          gCurrentRegion = region;
00564          return kTRUE;
00565       }
00566    }
00567    DoubleClicked();
00568    return kTRUE;
00569 }
00570 
00571 //______________________________________________________________________________
00572 Bool_t TGImageMap::HandleButton(Event_t *event)
00573 {
00574    // Handle button events.
00575 
00576    TIter next(fListOfRegions);
00577    TGRegionWithId *region;
00578    TGPopupMenu *pop;
00579 
00580    if (fTip) fTip->Hide();
00581    if (fNavMode != kNavRegions) return kTRUE;
00582 
00583    gPointerX = event->fX;
00584    gPointerY = event->fY;
00585 
00586    while ((region = (TGRegionWithId*)next())) {
00587       if (region->Contains(gPointerX, gPointerY)) {
00588          gCurrentRegion = region;
00589          if (event->fType == kButtonPress) {
00590             if (event->fCode == kButton1 )
00591                RegionClicked(region->GetId());
00592             else if (event->fCode == kButton3 ) {
00593                pop = region->GetPopup();
00594                if (pop) pop->PlaceMenu(gPointerX, gPointerY, kFALSE, kTRUE);
00595             }
00596          }
00597          return kTRUE;
00598       }
00599    }
00600    if (event->fType == kButtonPress)
00601       Clicked();
00602    return kTRUE;
00603 }
00604 
00605 //______________________________________________________________________________
00606 void TGImageMap::SetToolTipText(const char *text, Long_t delayms)
00607 {
00608    // Set tooltip text for main region.
00609 
00610    if (fMainTip) delete fMainTip;
00611    fMainTip = 0;
00612 
00613    if (text && strlen(text))
00614       fMainTip = new TGToolTip(fClient->GetDefaultRoot(), this, text, delayms);
00615 }
00616 
00617 //______________________________________________________________________________
00618 void TGImageMap::SetToolTipText(Int_t id, const char *text, Long_t delayms)
00619 {
00620    // Set tooltip text for regions with specified id.
00621 
00622    TIter next(fListOfRegions);
00623    TGRegionWithId *region;
00624 
00625    while ((region = (TGRegionWithId*)next())) {
00626       if (id == region->GetId())
00627          region->SetToolTipText(text, delayms, this);
00628    }
00629 }
00630 
00631 //______________________________________________________________________________
00632 void TGImageMap::OnMouseOver(Int_t id)
00633 {
00634    // Handle when mouse moves over region id. Emits signal
00635    // OnMouseOver(Int_t).
00636 
00637    if (fTip) fTip->Reset();
00638    if (fMainTip) fMainTip->Hide();
00639    gVirtualX->SetCursor(fId, gVirtualX->CreateCursor(fCursorMouseOver));
00640    Emit("OnMouseOver(Int_t)", id);
00641 }
00642 
00643 //______________________________________________________________________________
00644 void TGImageMap::OnMouseOut(Int_t id)
00645 {
00646    // Handle when mouse moves from region id. Emits signal
00647    // OnMouseOut(Int_t).
00648 
00649    if(fTip) fTip->Hide();
00650    if(fMainTip) fMainTip->Reset();
00651    gVirtualX->SetCursor(fId,gVirtualX->CreateCursor(fCursorMouseOut));
00652    Emit("OnMouseOut(Int_t)",id);
00653 }
00654 
00655 //______________________________________________________________________________
00656 void TGImageMap::RegionClicked(Int_t id)
00657 {
00658    // Handle when mouse was clicked on region id. Emits signal
00659    // RegionClicked(Int_t).
00660 
00661    Emit("RegionClicked(Int_t)",id);
00662 }
00663 
00664 //______________________________________________________________________________
00665 void TGImageMap::DoubleClicked()
00666 {
00667    // Handle when mouse is double clicked on main map. Emits signal
00668    // DoubleClicked().
00669 
00670    Emit("DoubleClicked()");
00671 }
00672 
00673 //______________________________________________________________________________
00674 void TGImageMap::DoubleClicked(Int_t id)
00675 {
00676    // Handle when mouse is double clicked on region id. Emits signal
00677    // DoubleClicked(Int_t).
00678 
00679    Emit("DoubleClicked(Int_t)",id);
00680 }

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