// @(#)root/gpad:$Id$
// Author: Rene Brun   10/03/2007

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

#include "Riostream.h"
#include "TROOT.h"
#include "TColorWheel.h"
#include "TCanvas.h"
#include "TText.h"
#include "TGraph.h"
#include "TArc.h"
#include "TLine.h"
#include "TColor.h"
#include "TMath.h"

ClassImp(TColorWheel)

//______________________________________________________________________________
/* Begin_Html
<center><h2>TColorWheel : Draw the ROOT Color Wheel.</h2></center>
The wheel contains the recommended 216 colors to be used in web applications.
The colors in the Color Wheel are created by TColor::CreateColorWheel.
<p>Using this color set for your text, background or graphics will give your
application a consistent appearance across different platforms and browsers.
<p>Colors are grouped by hue, the aspect most important in human perception.
Touching color chips have the same hue, but with different brightness and vividness.
<p>Colors of slightly different hues <b>clash</b>. If you intend to display
colors of the same hue together, you should pick them from the same group.
<p>Each color chip is identified by a mnemonic (e.g. kYellow) and a number.
The keywords, kRed, kBlue, kYellow, kPink, etc are defined in the header file <b>Rtypes.h</b>
that is included in all ROOT other header files. We strongly recommend to use these keywords
in your code instead of hardcoded color numbers, e.g.:
<pre>
   myObject.SetFillColor(kRed);
   myObject.SetFillColor(kYellow-10);
   myLine.SetLineColor(kMagenta+2);
</pre>

End_Html
Begin_Macro(source)
{
   TColorWheel *w = new TColorWheel();
   w->Draw();
   return w->GetCanvas();
}
End_Macro */

//______________________________________________________________________________
TColorWheel::TColorWheel() :TNamed("wheel","ROOT Color Wheel")
{
   // constructor

   fCanvas = 0;
   fArc    = 0;
   fLine   = 0;
   fText   = 0;
   fGraph  = 0;
   fRmin   = 2.1;
   fRmax   = 9.5;
   fR0     = 4;
   fDr     = 1;
   fRgray  = 1.8;
   fX[ 0]  = fR0-0.2*fDr; fY[ 0] =  0;
   fX[ 1]  = fR0+fDr;     fY[ 1] =  0.75*fDr;
   fX[ 2]  = fR0+fDr;     fY[ 2] = -0.75*fDr;
   fX[ 3]  = fR0+2.2*fDr; fY[ 3] =  1.5*fDr;
   fX[ 4]  = fR0+2.2*fDr; fY[ 4] =  0;
   fX[ 5]  = fR0+2.2*fDr; fY[ 5] = -1.5*fDr;
   fX[ 6]  = fR0+3.4*fDr; fY[ 6] =  2.2*fDr;
   fX[ 7]  = fR0+3.4*fDr; fY[ 7] =  0.7*fDr;
   fX[ 8]  = fR0+3.4*fDr; fY[ 8] = -0.7*fDr;
   fX[ 9]  = fR0+3.4*fDr; fY[ 9] = -2.2*fDr;
   fX[10]  = fR0+4.6*fDr; fY[10] =  2.8*fDr;
   fX[11]  = fR0+4.6*fDr; fY[11] =  1.4*fDr;
   fX[12]  = fR0+4.6*fDr; fY[12] =  0;
   fX[13]  = fR0+4.6*fDr; fY[13] = -1.4*fDr;
   fX[14]  = fR0+4.6*fDr; fY[14] = -2.8*fDr;

   SetBit(kCanDelete);
}

//______________________________________________________________________________
TColorWheel::~TColorWheel()
{
   // destructor

   //delete fCanvas;  please don't do that
   delete fArc;
   delete fLine;
   delete fText;
   delete fGraph;
}

//______________________________________________________________________________
Int_t TColorWheel::DistancetoPrimitive(Int_t px, Int_t py)
{
   // always return the color wheel

   if (px+py < 0) return 1;
   return 0;
}


//______________________________________________________________________________
void TColorWheel::Draw(Option_t *option)
{
   // Paint the color wheel

   if (!fCanvas) {
      fCanvas = new TCanvas("wheel","ROOT Color Wheel",10,10,400,400);
      fCanvas->ToggleEventStatus();
   }
   fCanvas->Range(-10.5,-10.5,10.5,10.5);
   fCanvas->SetBorderMode(0);
   fCanvas->SetFillColor(TColor::GetColor(243,241,174));
   AppendPad(option);
}

//______________________________________________________________________________
Int_t TColorWheel::GetColor(Int_t px, Int_t py) const
{
   // Return the color number pointed by the mouse

   Double_t x = fCanvas->AbsPixeltoX(px);
   Double_t y = fCanvas->AbsPixeltoY(py);
   Int_t n = 0;

   n = InGray(x,y);                   if (n >= 0) return n;
   n = InCircles   (x,y,kMagenta, 0); if (n >= 0) return n;
   n = InRectangles(x,y,kPink,   30); if (n >= 0) return n;
   n = InCircles   (x,y,kRed,    60); if (n >= 0) return n;
   n = InRectangles(x,y,kOrange, 90); if (n >= 0) return n;
   n = InCircles   (x,y,kYellow,120); if (n >= 0) return n;
   n = InRectangles(x,y,kSpring,150); if (n >= 0) return n;
   n = InCircles   (x,y,kGreen, 180); if (n >= 0) return n;
   n = InRectangles(x,y,kTeal,  210); if (n >= 0) return n;
   n = InCircles   (x,y,kCyan,  240); if (n >= 0) return n;
   n = InRectangles(x,y,kAzure, 270); if (n >= 0) return n;
   n = InCircles   (x,y,kBlue,  300); if (n >= 0) return n;
   n = InRectangles(x,y,kViolet,330); if (n >= 0) return n;
   return -1;
}

//______________________________________________________________________________
char  *TColorWheel::GetObjectInfo(Int_t px, Int_t py) const
{
   // Return the color number pointed by the mouse

   static char info[50];
   info[0] = 0;

   Int_t n = GetColor(px,py);
   if (n < 0) return info;
   TColor *color = gROOT->GetColor(n);
   if (!color) return info;
   Int_t r = (Int_t)(255.01*color->GetRed());
   Int_t g = (Int_t)(255.01*color->GetGreen());
   Int_t b = (Int_t)(255.01*color->GetBlue());
   snprintf(info,50,"col %d, %s, r=%3d, g=%3d, b=%3d",n,color->GetName(),r,g,b);
   return info;
}

//______________________________________________________________________________
Int_t TColorWheel::InCircles(Double_t x, Double_t y, Int_t coffset, Double_t angle) const
{
   // Return the color number when the mouse point to a circle

   Double_t ang = angle*TMath::DegToRad();
   Double_t u,v;
   Rotate(x,y,u,v,ang);
   Double_t r2 = 0.7*0.7*fDr*fDr;
   for (Int_t i=0;i<15;i++) {
      Double_t dx = u-fX[i];
      Double_t dy = v-fY[i];
      if (dx*dx+dy*dy < r2) return coffset+i-10;
   }
   return -1;
}

//______________________________________________________________________________
Int_t TColorWheel::InGray(Double_t x, Double_t y) const
{
   // Return the color number when the mouse point to the gray circle

   if (x*x+y*y > fRgray*fRgray) return -1;
   Double_t ang = TMath::ATan2(y,x)*TMath::RadToDeg();
   if (ang < 0) ang += 360;
   if (ang <  60) return kWhite;
   if (ang < 120) return kGray;
   if (ang < 180) return kGray+1;
   if (ang < 240) return kGray+2;
   if (ang < 300) return kGray+3;
   return kBlack;
}

//______________________________________________________________________________
Int_t TColorWheel::InRectangles(Double_t x, Double_t y, Int_t coffset, Double_t angle) const
{
   // Return the color number when the mouse point to a rectangle

   Double_t ang = angle*TMath::DegToRad();
   Double_t u,v;
   Rotate(x,y,u,v,ang);
   if (TMath::Abs(v) > 1) return -1;
   if (u < fRmin || u > fRmax) return -1;
   Int_t div = (Int_t)(10*(u-fRmin)/(fRmax-fRmin));
   if (v > 0) return coffset + div+1;
   return coffset+div-9;
}

//______________________________________________________________________________
void TColorWheel::Paint(Option_t * /*option*/)
{
   // Paint the color wheel

   if (!fArc) {
      fArc   = new TArc;
      fLine  = new TLine;
      fText  = new TText();
      fGraph = new TGraph();
   }
   PaintGray();
   PaintCircles   (kMagenta, 0);
   PaintRectangles(kPink,   30);
   PaintCircles   (kRed,    60);
   PaintRectangles(kOrange, 90);
   PaintCircles   (kYellow,120);
   PaintRectangles(kSpring,150);
   PaintCircles   (kGreen, 180);
   PaintRectangles(kTeal,  210);
   PaintCircles   (kCyan,  240);
   PaintRectangles(kAzure, 270);
   PaintCircles   (kBlue,  300);
   PaintRectangles(kViolet,330);

   fText->SetTextFont(72);
   fText->SetTextColor(kBlue);
   fText->SetTextAlign(11);
   fText->SetTextSize(0.03);
   fText->SetTextAngle(0);
   fText->PaintText(-10.2,-10.2,"ROOT Color Wheel");
}

//______________________________________________________________________________
void TColorWheel::PaintCircle(Int_t coffset,Int_t n, Double_t x, Double_t y, Double_t ang) const
{
   // Draw one color of type circle

   Double_t u,v;
   Rotate(x,y,u,v,ang);
   Int_t colorn = coffset+n;
   TColor *color = gROOT->GetColor(colorn);
   if (!color) return;
   fArc->SetFillColor(colorn);
   fArc->SetLineColor(14);
   Double_t r = 0.7*fDr;
   fArc->PaintEllipse(u,v,r,r,0,360,0);
   fText->SetTextSize(0.03);
   fText->SetTextAlign(22);
   if (255*color->GetLight() <150 && n != 0) fText->SetTextColor(0);
   if (n>0) fText->PaintText(u,v,Form("+%d",n));
   else     fText->PaintText(u,v,Form("%d", n));
}

//______________________________________________________________________________
void TColorWheel::PaintCircles(Int_t coffset, Double_t angle) const
{
   // Draw all colors of type circle

   Double_t ang = TMath::DegToRad()*angle;
   Double_t u,v,u0,v0;
   Rotate(fR0+4.6*fDr,2.8*fDr,u0,v0,ang);
   Rotate(fR0+5.8*fDr,2.1*fDr,u,v,ang);
   fLine->PaintLine(u,v,u0,v0);
   fText->SetTextAlign(22);
   fText->SetTextFont(72);
   fText->SetTextColor(1);
   fText->SetTextSize(0.03);
   Double_t tangle = angle-90;
   if (angle == 240) tangle = -30;
   if (angle == 300) tangle =  30;
   TColor *col = gROOT->GetColor(coffset);
   if (!col) return;
   fText->SetTextAngle(tangle);
   fText->PaintText(u,v,col->GetName());

   for (Int_t i=0;i<15;i++) {
      PaintCircle(coffset,i-10, fX[i], fY[i],    ang);
   }
}

//______________________________________________________________________________
void TColorWheel::PaintRectangles(Int_t coffset, Double_t angle) const
{
   // Draw all colors of type rectangle

   Double_t ang = TMath::DegToRad()*angle;
   Double_t rmin = fRmin, rmax=fRmax;
   Double_t dr = (rmax-rmin)/10;
   Double_t dy = -1.0;

   Double_t u,v,u0,v0;
   Rotate(rmax+0.62*dr,0,u,v,ang);
   Rotate(rmax-dr,0.9*dy,u0,v0,ang);
   fLine->PaintLine(u,v,u0,v0);
   fText->SetTextAlign(22);
   fText->SetTextFont(72);
   fText->SetTextColor(1);
   fText->SetTextSize(0.03);
   Double_t tangle = angle+90;
   if (angle == 30)  tangle = -60;
   if (angle == 90)  tangle = 0;
   if (angle == 150) tangle = 60;
   if (angle == 210) tangle = -60;
   if (angle == 270) tangle = 0;
   fText->SetTextAngle(tangle);
   TColor *color = gROOT->GetColor(coffset);
   if (!color) return;
   fText->PaintText(u,v,color->GetName());

   Double_t x[5],y[5];
   Int_t n=-10;
   for (Int_t j=0;j<2;j++) {
      for (Int_t i=0;i<10;i++) {
         n++;
         Int_t colorn = coffset +n;
         color = gROOT->GetColor(colorn);
         Rotate(rmin+i*dr,    0,x[0],y[0],ang);
         Rotate(rmin+i*dr,   dy,x[1],y[1],ang);
         Rotate(rmin+i*dr+dr,dy,x[2],y[2],ang);
         Rotate(rmin+i*dr+dr, 0,x[3],y[3],ang);
         fGraph->SetFillColor(colorn);
         fGraph->PaintGraph(4,x,y,"f");
         Rotate(rmin+i*dr+0.5*dr,0.5*dy,x[0],y[0],ang);
         fText->SetTextSize(0.03);
         fText->SetTextAlign(22);
         if (color) {
            if (255*color->GetLight() <110) fText->SetTextColor(0);
         }
         Double_t tang = angle-90;
         if (angle > 180) tang -=180;
         fText->SetTextAngle(tang);
         if (n > 0) fText->PaintText(x[0],y[0],Form("+%d",n));
         else       fText->PaintText(x[0],y[0],Form("%d",n));
      }
      dy=1;
   }

   Rotate(rmin,-dy,x[0],y[0],ang);
   Rotate(rmax,-dy,x[1],y[1],ang);
   Rotate(rmax, dy,x[2],y[2],ang);
   Rotate(rmin, dy,x[3],y[3],ang);
   Rotate(rmin,-dy,x[4],y[4],ang);
   fGraph->SetLineColor(1);
   fGraph->SetLineWidth(1);
   fGraph->PaintGraph(5,x,y,"l");
   fLine->SetLineWidth(1);
   Rotate(rmin+3*dr,-dy,x[0],y[0],ang);
   Rotate(rmin+3*dr, dy,x[1],y[1],ang);
   fLine->PaintLine(x[0],y[0],x[1],y[1]);
   Rotate(rmin+6*dr,-dy,x[0],y[0],ang);
   Rotate(rmin+6*dr, dy,x[1],y[1],ang);
   fLine->PaintLine(x[0],y[0],x[1],y[1]);
   Rotate(rmin+9*dr,-dy,x[0],y[0],ang);
   Rotate(rmin+9*dr, dy,x[1],y[1],ang);
   fLine->PaintLine(x[0],y[0],x[1],y[1]);
   Rotate(rmin+7*dr,-dy,x[0],y[0],ang);
   Rotate(rmin+7*dr, dy,x[1],y[1],ang);
   fLine->PaintLine(x[0],y[0],x[1],y[1]);
   Rotate(rmin+6*dr,0,x[0],y[0],ang);
   Rotate(rmax, 0,x[1],y[1],ang);
   fLine->PaintLine(x[0],y[0],x[1],y[1]);
}

//______________________________________________________________________________
void TColorWheel::PaintGray() const
{
   // Draw the gray colors + white + black

   Double_t r = fRgray;
   fArc->SetFillColor(kWhite);
   fArc->PaintEllipse(0,0,r,r,0,60,0);
   fArc->SetFillColor(kGray);
   fArc->PaintEllipse(0,0,r,r,60,120,0);
   fArc->SetFillColor(kGray+1);
   fArc->PaintEllipse(0,0,r,r,120,180,0);
   fArc->SetFillColor(kGray+2);
   fArc->PaintEllipse(0,0,r,r,180,240,0);
   fArc->SetFillColor(kGray+3);
   fArc->PaintEllipse(0,0,r,r,240,300,0);
   fArc->SetFillColor(kBlack);
   fArc->PaintEllipse(0,0,r,r,300,360,0);

   fText->SetTextAlign(22);
   fText->SetTextFont(62);
   fText->SetTextColor(1);
   fText->SetTextSize(0.02);
   fText->SetTextAngle(40);
   fText->PaintText(0.5*r,0.3*r,"kWhite");
   fText->SetTextAngle(0);
   fText->PaintText(0,0.8*r,"kGray");
   fText->SetTextColor(10);
   fText->SetTextFont(72);
   fText->SetTextSize(0.03);
   fText->PaintText(-0.6*r, 0.3*r,"+1");
   fText->PaintText(-0.6*r,-0.3*r,"+2");
   fText->PaintText(0,-0.6*r,"+3");
   fText->SetTextAngle(-40);
   fText->SetTextSize(0.02);
   fText->SetTextFont(62);
   fText->PaintText(0.5*r,-0.35*r,"kBlack");
}

//______________________________________________________________________________
void TColorWheel::Rotate(Double_t x, Double_t y, Double_t &u, Double_t &v, Double_t ang) const
{
   // Rotate point x,y with an angle=ang

   u = x*TMath::Cos(ang)  + y*TMath::Sin(ang);
   v = x*TMath::Sin(ang)  - y*TMath::Cos(ang);
}
