#include "TGDoubleSlider.h"
#include "TGPicture.h"
#include "Riostream.h"
#include "TSystem.h"
ClassImp(TGDoubleSlider)
ClassImp(TGDoubleVSlider)
ClassImp(TGDoubleHSlider)
TGDoubleSlider::TGDoubleSlider(const TGWindow *p, UInt_t w, UInt_t h, UInt_t type, Int_t id,
                               UInt_t options, ULong_t back,
                               Bool_t reversed, Bool_t mark_ends)
   : TGFrame(p, w, h, options, back)
{
   
   fSliderPic = 0;
   fWidgetId    = id;
   fWidgetFlags = kWidgetWantFocus;
   fMsgWindow   = p;
   fScaleType = type;
   fScale = 10;
   fMove = 0;
   fReversedScale = reversed;
   fMarkEnds = mark_ends;
   gVirtualX->GrabButton(fId, kAnyButton, kAnyModifier,
                         kButtonPressMask | kButtonReleaseMask |
                         kPointerMotionMask, kNone, kNone);
   AddInput(kPointerMotionMask);
   SetWindowName();
}
void TGDoubleSlider::FixBounds(Float_t &min, Float_t &max)
{
   
   if (min > max) min = max;
   Float_t eps = 1e-6;
   if (max - min < eps) {
      if (max == 0)
         max += eps;
      else
         max += max*eps;
      if (min == 0)
         min -= eps;
      else
         min -= min*eps;
   }
}
TString TGDoubleSlider::GetSString() const
{
   
   TString stype;
   if (fScaleType) {
      if (fScaleType & kDoubleScaleNo)  {
         if (stype.Length() == 0) 
            stype  = "kDoubleScaleNo";
         else
            stype += " | kDoubleScaleNo";
      }
      if (fScaleType & kDoubleScaleDownRight) {
         if (stype.Length() == 0)
            stype  = "kDoubleScaleDownRight";
         else
            stype += " | kDoubleScaleDownRight";
      }
      if (fScaleType & kDoubleScaleBoth) {
         if (stype.Length() == 0) 
            stype  = "kDoubleScaleBoth";
         else
            stype += " | kDoubleScaleBoth";
      }
   }
   return stype;
}
void TGDoubleSlider::ChangeCursor(Event_t *event)
{
   
   static Cursor_t topCur = kNone, leftCur = kNone;
   static Cursor_t botCur = kNone, rightCur = kNone;
   Int_t hw = 0, wh = 0, xy = 0, yx = 0;
   Cursor_t minCur = kNone, maxCur = kNone;
   if (topCur == kNone)
      topCur    = gVirtualX->CreateCursor(kTopSide);
   if (leftCur == kNone)
      leftCur   = gVirtualX->CreateCursor(kLeftSide);
   if (botCur == kNone)
      botCur    = gVirtualX->CreateCursor(kBottomSide);
   if (rightCur == kNone)
      rightCur  = gVirtualX->CreateCursor(kRightSide);
   if (GetOptions() & kVerticalFrame) {
      hw = (Int_t)fWidth;
      wh = (Int_t)fHeight;
      xy = (Int_t)event->fX;
      yx = (Int_t)event->fY;
      minCur = topCur;
      maxCur = botCur;
   }
   else if (GetOptions() & kHorizontalFrame) {
      hw  = (Int_t)fHeight;
      wh  = (Int_t)fWidth;
      xy  = (Int_t)event->fY;
      yx  = (Int_t)event->fX;
      minCur = leftCur;
      maxCur = rightCur;
   }
   else return;
   
   Int_t relMin = (Int_t)((wh-16) * (fSmin - fVmin) / (fVmax - fVmin)) + 1;
   Int_t relMax = (Int_t)((wh-16) * (fSmax - fVmin) / (fVmax - fVmin) + 15);
   
   if (xy > hw/2-7 && xy < hw/2+7 && fMove != 3) {
      
      
      
      if ((yx <= (relMax - relMin) / 4 + relMin) &&
          (yx >= relMin) && (fMove != 2))
         gVirtualX->SetCursor(fId, minCur);
      
      
      
      else if ((yx >= (relMax - relMin) / 4 * 3 + relMin) && 
               (yx <= relMax) && (fMove != 1))
         gVirtualX->SetCursor(fId, maxCur);
      
      else if ((fMove < 1) || (fMove > 2))
         gVirtualX->SetCursor(fId, kNone);
   }
   
   
   else if ((fMove < 1) || (fMove > 2))
      gVirtualX->SetCursor(fId, kNone);
}
TGDoubleVSlider::TGDoubleVSlider(const TGWindow *p, UInt_t h, UInt_t type, Int_t id,
                                 UInt_t options, ULong_t back,
                                 Bool_t reversed, Bool_t mark_ends)
    : TGDoubleSlider(p, kDoubleSliderWidth, h, type, id, options, back,
                     reversed, mark_ends)
{
   
   fSliderPic = fClient->GetPicture("sliderv.xpm");
   if (!fSliderPic)
      Error("TGDoubleVSlider", "sliderv.xpm not found");
   
   fSmin = h/8*3; fSmax = h/8*5; fVmin = 0; fVmax = h;
   FixBounds(fVmin, fVmax);
   SetWindowName();
}
TGDoubleVSlider::~TGDoubleVSlider()
{
   
   if (fSliderPic) fClient->FreePicture(fSliderPic);
}
void TGDoubleVSlider::DoRedraw()
{
   
   FixBounds(fVmin, fVmax);
   
   gVirtualX->ClearWindow(fId);
   if (fSmin < fVmin) fSmin = fVmin;
   if (fSmax < fVmin) fSmax = fVmin;
   if (fSmin > fVmax) fSmin = fVmax;
   if (fSmax > fVmax) fSmax = fVmax;
   if (fSmin > fSmax) fSmin = fSmax = (fSmin + fSmax) / 2;
   int relMin = (int)((fHeight-16) * (fSmin - fVmin) / (fVmax - fVmin)) + 1;
   int relMax = (int)((fHeight-16) * (fSmax - fVmin) / (fVmax - fVmin) + 15);
   gVirtualX->DrawLine(fId, GetHilightGC()(), fWidth/2-6, relMin, fWidth/2+5, relMin);
   gVirtualX->DrawLine(fId, GetHilightGC()(), fWidth/2-6, relMin, fWidth/2-6, relMax);
   gVirtualX->DrawLine(fId, GetBlackGC()(),   fWidth/2+5, relMax, fWidth/2-6, relMax);
   gVirtualX->DrawLine(fId, GetBlackGC()(),   fWidth/2+5, relMax, fWidth/2+5, relMin);
   if (relMin-1 > 8) {
      gVirtualX->DrawLine(fId, GetShadowGC()(),  fWidth/2-1, 8, fWidth/2-1, relMin-1);
      gVirtualX->DrawLine(fId, GetHilightGC()(), fWidth/2+1, 8, fWidth/2+1, relMin-1);
      gVirtualX->DrawLine(fId, GetBlackGC()(),   fWidth/2,   8, fWidth/2,   relMin-1);
   }
   if (relMax+1 < (int)fHeight-8) {
      gVirtualX->DrawLine(fId, GetShadowGC()(),  fWidth/2-1, relMax+1, fWidth/2-1, fHeight-8);
      gVirtualX->DrawLine(fId, GetHilightGC()(), fWidth/2+1, relMax+1, fWidth/2+1, fHeight-8);
      gVirtualX->DrawLine(fId, GetBlackGC()(),   fWidth/2,   relMax+1, fWidth/2,   fHeight-8);
   }
   
   if (fScale == 1) fScale++;
   if (fScale * 2 > (int)fHeight) fScale = 0;
   if (fScale > 0 && !(fScaleType & kDoubleScaleNo)) {
      int lines = ((int)fHeight-16) / fScale;
      int remain = ((int)fHeight-16) % fScale;
      if (lines < 1) lines = 1;
      for (int i = 0; i <= lines; i++) {
         int y = i * fScale + (i * remain) / lines;
         gVirtualX->DrawLine(fId, GetBlackGC()(), fWidth/2+8, y+7, fWidth/2+10, y+7);
         if ((fScaleType && kDoubleScaleBoth))
            gVirtualX->DrawLine(fId, GetBlackGC()(), fWidth/2-9, y+7, fWidth/2-11, y+7);
      }
   }
   if (fSliderPic) {
      Int_t xpos = (fWidth/2) - (fSliderPic->GetWidth()/2);
      Int_t ypos = relMin + 2;
      fSliderPic->Draw(fId, GetBckgndGC()(), xpos, ypos);
      ypos = relMax - fSliderPic->GetHeight() - 2;
      fSliderPic->Draw(fId, GetBckgndGC()(), xpos, ypos);
   }
   if (fMarkEnds) {
      
      int y1 = (relMax - relMin) / 4 + relMin;
      int y2 = (relMax - relMin) / 4 * 3 + relMin;
      gVirtualX->DrawLine(fId, GetBlackGC()(), fWidth/2-6, y1, fWidth/2+5, y1);
      gVirtualX->DrawLine(fId, GetBlackGC()(), fWidth/2-6, y2, fWidth/2+5, y2);
   }
}
Bool_t TGDoubleVSlider::HandleButton(Event_t *event)
{
   
   if (event->fType == kButtonPress && event->fCode == kButton1) {
      
      if (event->fX < (Int_t)fWidth/2-7 || event->fX > (Int_t)fWidth/2+7) {
         return kTRUE;
      }
      fPressPoint = event->fY;
      fPressSmin  = fSmin;
      fPressSmax  = fSmax;
      int relMin = (int)((fHeight-16) * (fSmin - fVmin) / (fVmax - fVmin)) + 1;
      int relMax = (int)((fHeight-16) * (fSmax - fVmin) / (fVmax - fVmin) + 15);
      if (fPressPoint < (relMax - relMin) / 4 + relMin)
         
         fMove = 1;
      else if (fPressPoint > (relMax - relMin) / 4 * 3 + relMin)
         
         fMove = 2;
      else
         
         fMove = 3;
      SendMessage(fMsgWindow, MK_MSG(kC_VSLIDER, kSL_PRESS), fWidgetId, 0);
      fClient->ProcessLine(fCommand, MK_MSG(kC_VSLIDER, kSL_PRESS), fWidgetId, 0);
      Pressed();
      
      gVirtualX->GrabPointer(fId, kButtonPressMask | kButtonReleaseMask |
                             kPointerMotionMask, kNone, kNone,
                             kTRUE, kFALSE);
   } else if (event->fType == kButtonRelease && event->fCode == kButton1) {
      SendMessage(fMsgWindow, MK_MSG(kC_VSLIDER, kSL_RELEASE), fWidgetId, 0);
      fClient->ProcessLine(fCommand, MK_MSG(kC_VSLIDER, kSL_RELEASE), fWidgetId, 0);
      Released();
      fMove = 0;
      gVirtualX->GrabPointer(0, 0, 0, 0, kFALSE);  
   } else
      fMove = 0;
   return kTRUE;
}
Bool_t TGDoubleVSlider::HandleMotion(Event_t *event)
{
   
   ChangeCursor(event);
   if (fMove == 0) return kTRUE;
   static Long_t was = gSystem->Now();
   Long_t now = (long)gSystem->Now();
   if ((now-was) < 50) return kTRUE;
   was = now;
   int       diff;
   Float_t   oldMin, oldMax;
   diff    = event->fY - fPressPoint;
   oldMin  = fSmin;
   oldMax  = fSmax;
   if (fMove == 1) {
      
      fSmin = fPressSmin + diff * (fVmax - fVmin) / (fHeight-16);
      if (fSmin < fVmin) fSmin = fVmin;
      if (fSmin > fSmax) fSmin = fSmax;
   } else if (fMove == 2) {
      
      fSmax = fPressSmax + diff * (fVmax - fVmin) / (fHeight-16);
      if (fSmax > fVmax) fSmax = fVmax;
      if (fSmax < fSmin) fSmax = fSmin;
   } else if (fMove == 3) {
      
      Float_t logicalDiff;
      logicalDiff = diff * (fVmax - fVmin) / (fHeight-16);
      if (fPressSmax + logicalDiff > fVmax)
         logicalDiff = fVmax - fPressSmax;
      if (fPressSmin + logicalDiff < fVmin)
         logicalDiff = fVmin - fPressSmin;
      fSmax = fPressSmax + logicalDiff;
      fSmin = fPressSmin + logicalDiff;
   }
   
   if (fMove != 0 && (fSmax != oldMax || fSmin != oldMin)) {
      fClient->NeedRedraw(this);
      SendMessage(fMsgWindow, MK_MSG(kC_VSLIDER, kSL_POS), fWidgetId, 0);
      fClient->ProcessLine(fCommand, MK_MSG(kC_VSLIDER, kSL_POS), fWidgetId, 0);
      PositionChanged();
   }
   return kTRUE;
}
TGDoubleHSlider::TGDoubleHSlider(const TGWindow *p, UInt_t w, UInt_t type, Int_t id,
                                 UInt_t options, ULong_t back,
                                 Bool_t reversed, Bool_t mark_ends)
    : TGDoubleSlider(p, w, kDoubleSliderHeight, type, id, options, back,
                     reversed, mark_ends)
{
   
   fSliderPic = fClient->GetPicture("sliderh.xpm");
   if (!fSliderPic)
      Error("TGDoubleHSlider", "sliderh.xpm not found");
   
   fSmin = w/8*3; fSmax = w/8*5; fVmin = 0; fVmax = w;
   FixBounds(fVmin, fVmax);
   SetWindowName();
}
TGDoubleHSlider::~TGDoubleHSlider()
{
   
   if (fSliderPic) fClient->FreePicture(fSliderPic);
}
void TGDoubleHSlider::DoRedraw()
{
   
   FixBounds(fVmin, fVmax);
   
   gVirtualX->ClearWindow(fId);
   if (fSmin < fVmin) fSmin = fVmin;
   if (fSmax > fVmax) fSmax = fVmax;
   if (fSmin > fSmax) fSmin = fSmax = (fSmin + fSmax) / 2;
   int relMin = (int)((fWidth-16) * (fSmin - fVmin) / (fVmax - fVmin)) + 1;
   int relMax = (int)((fWidth-16) * (fSmax - fVmin) / (fVmax - fVmin) + 15);
   gVirtualX->DrawLine(fId, GetHilightGC()(), relMin, fHeight/2-6, relMin, fHeight/2+5);
   gVirtualX->DrawLine(fId, GetHilightGC()(), relMax, fHeight/2-6, relMin, fHeight/2-6);
   gVirtualX->DrawLine(fId, GetBlackGC()(),   relMax, fHeight/2+5, relMax, fHeight/2-6);
   gVirtualX->DrawLine(fId, GetBlackGC()(),   relMin, fHeight/2+5, relMax, fHeight/2+5);
   if (relMin-1 > 8) {
      gVirtualX->DrawLine(fId, GetShadowGC()(),  8, fHeight/2-1, relMin-1, fHeight/2-1);
      gVirtualX->DrawLine(fId, GetHilightGC()(), 8, fHeight/2+1, relMin-1, fHeight/2+1);
      gVirtualX->DrawLine(fId, GetBlackGC()(),   8, fHeight/2,   relMin-1, fHeight/2);
   }
   if (relMax+1 < (int)fWidth-8) {
      gVirtualX->DrawLine(fId, GetShadowGC()(),  relMax+1, fHeight/2-1, fWidth-8, fHeight/2-1);
      gVirtualX->DrawLine(fId, GetHilightGC()(), relMax+1, fHeight/2+1, fWidth-8, fHeight/2+1);
      gVirtualX->DrawLine(fId, GetBlackGC()(),   relMax+1, fHeight/2,   fWidth-8, fHeight/2);
   }
   if (fScale == 1) fScale++;
   if (fScale * 2 > (int)fWidth) fScale = 0;
   if (fScale > 0 && !(fScaleType & kDoubleScaleNo)) {
      int lines = ((int)fWidth-16) / fScale;
      int remain = ((int)fWidth-16) % fScale;
      if (lines < 1) lines = 1;
      for (int i = 0; i <= lines; i++) {
         int x = i * fScale + (i * remain) / lines;
         gVirtualX->DrawLine(fId, GetBlackGC()(), x+7, fHeight/2+8, x+7, fHeight/2+10);
         if ((fScaleType && kDoubleScaleBoth))
            gVirtualX->DrawLine(fId, GetBlackGC()(), x+7, fHeight/2-9, x+7, fHeight/2-11);
      }
   }
   if (fSliderPic) {
      Int_t ypos = (fHeight/2) - (fSliderPic->GetHeight()/2);
      Int_t xpos = relMin + 2;
      fSliderPic->Draw(fId, GetBckgndGC()(), xpos, ypos);
      xpos = relMax - fSliderPic->GetWidth() - 2;
      fSliderPic->Draw(fId, GetBckgndGC()(), xpos, ypos);
   }
   if (fMarkEnds) {
      
      int x1 = (relMax - relMin) / 4 + relMin;
      int x2 = (relMax - relMin) / 4 * 3 + relMin;
      gVirtualX->DrawLine(fId, GetBlackGC()(), x1, fHeight/2-6, x1, fHeight/2+5);
      gVirtualX->DrawLine(fId, GetBlackGC()(), x2, fHeight/2-6, x2, fHeight/2+5);
   }
}
Bool_t TGDoubleHSlider::HandleButton(Event_t *event)
{
   
   if (event->fType == kButtonPress && event->fCode == kButton1) {
      
      if (event->fY < (Int_t)fHeight/2-7 || event->fY > (Int_t)fHeight/2+7) {
         return kTRUE;
      }
      fPressPoint = event->fX;
      fPressSmin  = fSmin;
      fPressSmax  = fSmax;
      int relMin = (int)((fWidth-16) * (fSmin - fVmin) / (fVmax - fVmin)) + 1;
      int relMax = (int)((fWidth-16) * (fSmax - fVmin) / (fVmax - fVmin) + 15);
      if (fPressPoint < (relMax - relMin) / 4 + relMin)
         
         fMove = 1;
      else if (fPressPoint > (relMax - relMin) / 4 * 3 + relMin)
         
         fMove = 2;
      else
         
         fMove = 3;
      SendMessage(fMsgWindow, MK_MSG(kC_HSLIDER, kSL_PRESS), fWidgetId, 0);
      fClient->ProcessLine(fCommand, MK_MSG(kC_HSLIDER, kSL_PRESS), fWidgetId, 0);
      Pressed();
      
      gVirtualX->GrabPointer(fId, kButtonPressMask | kButtonReleaseMask |
                             kPointerMotionMask, kNone, kNone, 
                             kTRUE, kFALSE);
   } else if (event->fType == kButtonRelease && event->fCode == kButton1) {
      SendMessage(fMsgWindow, MK_MSG(kC_HSLIDER, kSL_RELEASE), fWidgetId, 0);
      fClient->ProcessLine(fCommand, MK_MSG(kC_HSLIDER, kSL_RELEASE), fWidgetId, 0);
      Released();
      fMove = 0;
      gVirtualX->GrabPointer(0, 0, 0, 0, kFALSE);  
   } else
      fMove = 0;
   return kTRUE;
}
Bool_t TGDoubleHSlider::HandleMotion(Event_t *event)
{
   
   ChangeCursor(event);
   if (fMove == 0) return kTRUE;
   static Long_t was = gSystem->Now();
   Long_t now = (long)gSystem->Now();
   if ((now-was) < 50) return kTRUE;
   was = now;
   int     diff;
   Float_t oldMin, oldMax;
   diff    = event->fX - fPressPoint;
   oldMin  = fSmin;
   oldMax  = fSmax;
   if (fMove == 1) {
      
      fSmin = fPressSmin + diff * (fVmax - fVmin) / (fWidth-16);
      if (fSmin < fVmin) fSmin = fVmin;
      if (fSmin > fSmax) fSmin = fSmax;
   } else if (fMove == 2) {
      
      fSmax = fPressSmax + diff * (fVmax - fVmin) / (fWidth-16);
      if (fSmax > fVmax) fSmax = fVmax;
      if (fSmax < fSmin) fSmax = fSmin;
   } else if (fMove == 3) {
      
      Float_t logicalDiff;
      logicalDiff = diff * (fVmax - fVmin) / (fWidth-16);
      if (fPressSmax + logicalDiff > fVmax)
         logicalDiff = fVmax - fPressSmax;
      if (fPressSmin + logicalDiff < fVmin)
         logicalDiff = fVmin - fPressSmin;
      fSmax = fPressSmax + logicalDiff;
      fSmin = fPressSmin + logicalDiff;
   }
   
   if (fMove != 0 && (fSmax != oldMax || fSmin != oldMin)) {
      fClient->NeedRedraw(this);
      SendMessage(fMsgWindow, MK_MSG(kC_HSLIDER, kSL_POS), fWidgetId, 0);
      fClient->ProcessLine(fCommand, MK_MSG(kC_HSLIDER, kSL_POS), fWidgetId, 0);
      PositionChanged();
   }
   return kTRUE;
}
void TGDoubleHSlider::SavePrimitive(ostream &out, Option_t *option )
{
    
   SaveUserColor(out, option);
   out <<"   TGDoubleHSlider *";
   out << GetName() << " = new TGDoubleHSlider(" << fParent->GetName()
       << "," << GetWidth() << ",";
   out << GetSString() << "," << WidgetId() << ",";
   out << GetOptionString() << ",ucolor";
   if (fMarkEnds) {
      switch (fReversedScale) {
         case kTRUE:
            out << ",kTRUE,kTRUE);" << endl;
            break;
         case kFALSE:
            out << ",kFALSE,kTRUE);" << endl;
            break;
      }
   } else if (fReversedScale) {
      out << ",kTRUE);" << endl;
   } else {
      out << ");" << endl;
   }
   if (fVmin != 0 || fVmax != (Int_t)fWidth)
      out << "   " << GetName() << "->SetRange(" << fVmin << "," << fVmax
          << ");" << endl;
   if (fSmin != fWidth/8*3 || fSmax != fWidth/8*5)
      out << "   " << GetName() << "->SetPosition(" << GetMinPosition()
          << "," << GetMaxPosition() << ");" << endl;
   if (fScale != 10)
      out << "   " << GetName() << "->SetScale(" << fScale << ");" << endl;
}
void TGDoubleVSlider::SavePrimitive(ostream &out, Option_t *option )
{
    
   
   SaveUserColor(out, option);
   out<<"   TGDoubleVSlider *";
   out << GetName() << " = new TGDoubleVSlider("<< fParent->GetName()
       << "," << GetHeight() << ",";
   out << GetSString() << "," << WidgetId() << ",";
   out << GetOptionString() << ",ucolor";
   if (fMarkEnds) {
      switch (fReversedScale) {
         case kTRUE:
            out << ",kTRUE,kTRUE);" << endl;
            break;
         case kFALSE:
            out << ",kFALSE,kTRUE);" << endl;
            break;
      }
   } else if (fReversedScale) {
      out << ",kTRUE);" << endl;
   } else {
      out << ");" << endl;
   }
   if (fVmin != 0 || fVmax != (Int_t)fHeight)
      out << "   " << GetName() <<"->SetRange(" << fVmin << "," << fVmax
          << ");" << endl;
   if (fSmin != fHeight/8*3 || fSmax != fHeight/8*5)
      out << "   " << GetName() << "->SetPosition(" << GetMinPosition()
          << "," << GetMaxPosition() << ");" << endl;
   if (fScale != 10)
      out << "   " << GetName() << "->SetScale(" << fScale << ");" << endl;
}
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.