// @(#)root/gui:$Id$
// Author: Valeriy Onuchin & Fons Rademakers   18/10/2000

/*************************************************************************
 * Copyright (C) 1995-2021, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#ifndef ROOT_TGImageMap
#define ROOT_TGImageMap


#include "TGButton.h"
#include "TPoint.h"
#include "TGDimension.h"


class TGRegionData;
class TGPopupMenu;
class TGToolTip;
class TArrayS;


class TGRegion : public TObject {

protected:
   TGRegionData   *fData;  // data describing region

   TGRegion(Bool_t);
   TGRegion CopyRegion() const;

public:
   enum ERegionType { kRectangle,
// clang++ <v20 (-Wshadow) complains about shadowing Buttons.h global enum EEditMode. Let's silence warning:
#if defined(__clang__) && __clang_major__ < 20
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wshadow"
#endif
      kEllipse };
#if defined(__clang__) && __clang_major__ < 20
#pragma clang diagnostic pop
#endif

   TGRegion();
   TGRegion(Int_t x, Int_t y, UInt_t w, UInt_t h, ERegionType = kRectangle);
   TGRegion(Int_t n, TPoint *points, Bool_t winding = kFALSE);
   TGRegion(Int_t n, Int_t *x, Int_t *y, Bool_t winding = kFALSE);
   TGRegion(const TArrayS &x, const TArrayS &y, Bool_t winding = kFALSE);
   TGRegion(const TGRegion &reg);
   ~TGRegion() override;

   Bool_t      Contains(const TPoint &p) const;
   Bool_t      Contains(Int_t x, Int_t y) const;
   TGRegion    Unite(const TGRegion &r) const;
   TGRegion    Intersect(const TGRegion &r) const;
   TGRegion    Subtract(const TGRegion &r) const;
   TGRegion    Eor(const TGRegion &r) const;
   TGDimension GetDimension() const;
   TGPosition  GetPosition() const;
   Bool_t      IsNull() const;
   Bool_t      IsEmpty() const;

   TGRegion operator|(const TGRegion &r) const { return Unite(r); }
   TGRegion operator+(const TGRegion &r) const { return Unite(r); }
   TGRegion operator&(const TGRegion &r) const { return Intersect(r); }
   TGRegion operator-(const TGRegion &r) const { return Subtract(r); }
   TGRegion operator^(const TGRegion &r) const { return Eor(r); }
   TGRegion& operator|=(const TGRegion &r) { return *this = *this | r; }
   TGRegion& operator+=(const TGRegion &r) { return *this = *this + r; }
   TGRegion& operator&=(const TGRegion &r) { return *this = *this & r; }
   TGRegion& operator-=(const TGRegion &r) { return *this = *this - r; }
   TGRegion& operator^=(const TGRegion &r) { return *this = *this ^ r; }
   Bool_t operator==(const TGRegion &r)  const;
   Bool_t operator!=(const TGRegion &r) const { return !(operator==(r)); }
   TGRegion &operator=(const TGRegion &r);

   ClassDefOverride(TGRegion,0) // Describes a region
};


class TGRegionWithId : public TGRegion {

private:

   TGRegionWithId& operator=(const TGRegionWithId&) = delete;

protected:
   Int_t         fId;      ///< region id
   TGToolTip    *fTip;     ///< tooltip
   TGPopupMenu  *fPopup;   ///< popup menu

public:
   TGRegionWithId();
   TGRegionWithId(Int_t id, Int_t x, Int_t y, UInt_t w, UInt_t h,
                  ERegionType = kRectangle);
   TGRegionWithId(Int_t id, Int_t n, TPoint *points, Bool_t winding = kFALSE);
   TGRegionWithId(const TGRegionWithId &reg);
   TGRegionWithId(const TGRegion &reg, Int_t id);
   ~TGRegionWithId() override;

   Int_t        GetId() const { return fId; }
   TGToolTip   *GetToolTipText() const { return fTip; }
   void         SetToolTipText(const char *text, Long_t delayms,
                               const TGFrame *frame);
   TGPopupMenu *GetPopup() const { return fPopup; }
   void         SetPopup(TGPopupMenu *popup) { fPopup = popup; }
   void         DisplayPopup();

   ClassDefOverride(TGRegionWithId,0) // Region with id, tooltip text and popup menu
};


class TGImageMap : public TGPictureButton {

private:

   TGImageMap(const TGImageMap&) = delete;
   TGImageMap& operator=(const TGImageMap&) = delete;

public:
   enum ENavMode { kNavRegions, kNavGrid };

protected:
   TList      *fListOfRegions;   ///< list of regions
   ENavMode    fNavMode;         ///< navigation mode
   ECursor     fCursorMouseOver; ///< cursor shape in regions
   ECursor     fCursorMouseOut;  ///< cursor shape out of regions
   Int_t       fLastVisited;     ///< id of the last visited region
   TGToolTip  *fMainTip;         ///< tooltip text for main region
   TList      *fTrash;           ///< collect all objects that need to be cleaned up

public:
   TGImageMap(const TGWindow *p = nullptr, const TGPicture *pic = nullptr);
   TGImageMap(const TGWindow *p, const TString &pic);
   ~TGImageMap() override;

   Bool_t HandleButton(Event_t *event) override;
   Bool_t HandleDoubleClick(Event_t *event) override;
   Bool_t HandleMotion(Event_t *event) override;

   ENavMode       GetNavMode() { return fNavMode; }
   void           AddRegion(const TGRegion &region, Int_t id);
   TGPopupMenu   *CreatePopup(Int_t id);
   TGPopupMenu   *GetPopup(Int_t id);

   void SetToolTipText(const char *text, Long_t delayms = 300) override;
   void SetToolTipText(Int_t id, const char *text, Long_t delayms = 300);
   void SetCursor(ECursor cursor = kHand) { fCursorMouseOver = cursor; }
   void SetPicture(const TGPicture * /*new_pic*/) override { } // disabled

   virtual void RegionClicked(Int_t id); // *SIGNAL*
   virtual void DoubleClicked(Int_t id); // *SIGNAL*
   virtual void DoubleClicked();         // *SIGNAL*
   virtual void OnMouseOver(Int_t id);   // *SIGNAL*
   virtual void OnMouseOut(Int_t id);    // *SIGNAL*

   ClassDefOverride(TGImageMap,0)  // Clickable image (like MAP in HTML)
};

R__EXTERN TGRegionWithId *gCurrentRegion;

#endif
