// @(#):$Id: TGeoPconEditor.cxx 20882 2007-11-19 11:31:26Z rdm $
// Author: M.Gheata 

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

//////////////////////////////////////////////////////////////////////////
//                                                                      //
//  TGeoPconEditor                                                      //
//                                                                      //
//////////////////////////////////////////////////////////////////////////
//Begin_Html
/*
<img src="gif/pcon_pic.gif">
*/
//End_Html
//Begin_Html
/*
<img src="gif/pcon_ed.jpg">
*/
//End_Html

#include "TGeoPconEditor.h"
#include "TGeoTabManager.h"
#include "TGeoPcon.h"
#include "TGeoManager.h"
#include "TVirtualGeoPainter.h"
#include "TPad.h"
#include "TView.h"
#include "TGTab.h"
#include "TGComboBox.h"
#include "TGButton.h"
#include "TGTextEntry.h"
#include "TGNumberEntry.h"
#include "TGLabel.h"

ClassImp(TGeoPconEditor)

enum ETGeoPconWid {
   kPCON_NAME, kPCON_NZ, kPCON_PHI1, kPCON_DPHI, kPCON_APPLY, kPCON_UNDO
};

//______________________________________________________________________________
TGeoPconEditor::TGeoPconEditor(const TGWindow *p, Int_t width,
                                   Int_t height, UInt_t options, Pixel_t back)
   : TGeoGedFrame(p, width, height, options | kVerticalFrame, back)
{
   // Constructor for polycone editor
   fShape   = 0;
   fNsections = 0;
   fSections = 0;
   fNsecti = 0;
   fPhi1i = 0;
   fDPhii = 0;
   fZi = 0;
   fRmini = 0;
   fRmaxi = 0;
   fIsModified = kFALSE;
   fIsShapeEditable = kFALSE;

   fLHsect = new TGLayoutHints(kLHintsTop | kLHintsLeft, 0,0,2,2);
      
   // TextEntry for shape name
   MakeTitle("Name");
   fShapeName = new TGTextEntry(this, new TGTextBuffer(50), kPCON_NAME);
   fShapeName->Resize(135, fShapeName->GetDefaultHeight());
   fShapeName->SetToolTipText("Enter the polycone name");
   fShapeName->Associate(this);
   AddFrame(fShapeName, new TGLayoutHints(kLHintsLeft, 3, 1, 2, 5));

   MakeTitle("Parameters");
   // Number entry for Nsections
   TGTextEntry *nef;
   TGCompositeFrame *f1 = new TGCompositeFrame(this, 155, 10, kHorizontalFrame | kFixedWidth);
   f1->AddFrame(new TGLabel(f1, "Nz"), new TGLayoutHints(kLHintsLeft, 1, 1, 6, 0));
   fENz = new TGNumberEntry(f1, 0., 5, kPCON_NZ);
   fENz->SetNumAttr(TGNumberFormat::kNEAPositive);
   fENz->SetNumStyle(TGNumberFormat::kNESInteger);
   fENz->Resize(100,fENz->GetDefaultHeight());
   nef = (TGTextEntry*)fENz->GetNumberEntry();
   nef->SetToolTipText("Enter the  number of Z sections");
   fENz->Associate(this);
   f1->AddFrame(fENz, new TGLayoutHints(kLHintsRight, 2, 2, 2, 2));
   AddFrame(f1, new TGLayoutHints(kLHintsLeft, 2, 2, 4, 4));
   
   // Number entry for Phi1
   f1 = new TGCompositeFrame(this, 155, 10, kHorizontalFrame | kFixedWidth);
   f1->AddFrame(new TGLabel(f1, "Phi1"), new TGLayoutHints(kLHintsLeft, 1, 1, 6, 0));
   fEPhi1 = new TGNumberEntry(f1, 0., 5, kPCON_PHI1);
   fEPhi1->Resize(100,fEPhi1->GetDefaultHeight());
   nef = (TGTextEntry*)fEPhi1->GetNumberEntry();
   nef->SetToolTipText("Enter the starting phi angle [deg]");
   fEPhi1->Associate(this);
   f1->AddFrame(fEPhi1, new TGLayoutHints(kLHintsRight, 2, 2, 2, 2));
   AddFrame(f1, new TGLayoutHints(kLHintsLeft, 2, 2, 4, 4));

   // Number entry for Dphi
   f1 = new TGCompositeFrame(this, 155, 10, kHorizontalFrame | kFixedWidth);
   f1->AddFrame(new TGLabel(f1, "Dphi"), new TGLayoutHints(kLHintsLeft, 1, 1, 6, 0));
   fEDPhi = new TGNumberEntry(f1, 0., 5, kPCON_DPHI);
   fEDPhi->SetNumAttr(TGNumberFormat::kNEAPositive);
   fEDPhi->Resize(100,fEDPhi->GetDefaultHeight());
   nef = (TGTextEntry*)fEDPhi->GetNumberEntry();
   nef->SetToolTipText("Enter the phi range [deg]");
   fEDPhi->Associate(this);
   f1->AddFrame(fEDPhi, new TGLayoutHints(kLHintsRight, 2, 2, 2, 2));
   AddFrame(f1, new TGLayoutHints(kLHintsLeft, 2, 2, 4, 4));

   // TGCanvas containing sections
   MakeTitle("Pcon sections");
   fCan = new TGCanvas(this, 160, 200,  kSunkenFrame | kDoubleBorder);
   TGCompositeFrame *cont = new TGCompositeFrame(fCan->GetViewPort(), 155, 20, kVerticalFrame | kFixedWidth);
   fCan->SetContainer(cont);
   // labels for #i, Z, Rmin, Rmax
   f1 = new TGCompositeFrame(cont, 160, 10, kHorizontalFrame | kFixedWidth);
   f1->AddFrame(new TGLabel(f1, "#"), new TGLayoutHints(kLHintsLeft, 2, 20, 6, 0));
   f1->AddFrame(new TGLabel(f1, "Z"), new TGLayoutHints(kLHintsLeft, 2, 20, 6, 0));
   f1->AddFrame(new TGLabel(f1, "Rmin"), new TGLayoutHints(kLHintsLeft, 2, 20, 6, 0));
   f1->AddFrame(new TGLabel(f1, "Rmax"), new TGLayoutHints(kLHintsLeft, 2, 10, 6, 0));
   cont->AddFrame(f1, new TGLayoutHints(kLHintsLeft, 0,0,0,0));
   CreateSections(2);

   AddFrame(fCan, new TGLayoutHints(kLHintsLeft, 0, 0, 4, 4));
      
   // Delayed draw
   fDFrame = new TGCompositeFrame(this, 155, 10, kHorizontalFrame | kFixedWidth | kSunkenFrame);
   fDelayed = new TGCheckButton(fDFrame, "Delayed draw");
   fDFrame->AddFrame(fDelayed, new TGLayoutHints(kLHintsLeft , 2, 2, 4, 4));
   AddFrame(fDFrame,  new TGLayoutHints(kLHintsLeft, 6, 6, 4, 4));  

   // Buttons
   fBFrame = new TGCompositeFrame(this, 155, 10, kHorizontalFrame | kFixedWidth);
   fApply = new TGTextButton(fBFrame, "Apply");
   fBFrame->AddFrame(fApply, new TGLayoutHints(kLHintsLeft, 2, 2, 4, 4));
   fApply->Associate(this);
   fUndo = new TGTextButton(fBFrame, "Undo");
   fBFrame->AddFrame(fUndo, new TGLayoutHints(kLHintsRight , 2, 2, 4, 4));
   fUndo->Associate(this);
   AddFrame(fBFrame,  new TGLayoutHints(kLHintsLeft, 6, 6, 4, 4));  
   fUndo->SetSize(fApply->GetSize());
}

//______________________________________________________________________________
TGeoPconEditor::~TGeoPconEditor()
{
// Destructor
   if (fSections) delete fSections;
   if (fZi) delete [] fZi;
   if (fRmini) delete [] fRmini;
   if (fRmaxi) delete [] fRmaxi;
   TGFrameElement *el;
   TIter next(GetList());
   while ((el = (TGFrameElement *)next())) {
      if (el->fFrame->IsComposite()) 
         TGeoTabManager::Cleanup((TGCompositeFrame*)el->fFrame);
   }
   Cleanup();   
}

//______________________________________________________________________________
void TGeoPconEditor::ConnectSignals2Slots()
{
   // Connect signals to slots.
   fENz->Connect("ValueSet(Long_t)", "TGeoPconEditor", this, "DoNz()");
   fEPhi1->Connect("ValueSet(Long_t)", "TGeoPconEditor", this, "DoPhi()");
   fEDPhi->Connect("ValueSet(Long_t)", "TGeoPconEditor", this, "DoPhi()");
   fApply->Connect("Clicked()", "TGeoPconEditor", this, "DoApply()");
   fUndo->Connect("Clicked()", "TGeoPconEditor", this, "DoUndo()");
   fShapeName->Connect("TextChanged(const char *)", "TGeoPconEditor", this, "DoModified()");
   fInit = kFALSE;
}


//______________________________________________________________________________
void TGeoPconEditor::SetModel(TObject* obj)
{
   // Connect to a given pcon.
   if (obj == 0 || (obj->IsA() != TGeoPcon::Class())) {
      SetActive(kFALSE);
      return;                 
   } 
   fShape = (TGeoPcon*)obj;
   const char *sname = fShape->GetName();
   if (!strcmp(sname, fShape->ClassName())) fShapeName->SetText("-no_name");
   else fShapeName->SetText(sname);

   Int_t nsections = fShape->GetNz();
   fNsecti = nsections;
   fENz->SetNumber(nsections);
   fEPhi1->SetNumber(fShape->GetPhi1());
   fPhi1i = fShape->GetPhi1();
   fEDPhi->SetNumber(fShape->GetDphi());
   fDPhii = fShape->GetDphi();
   CreateSections(nsections);
   UpdateSections();
   
   fApply->SetEnabled(kFALSE);
   fUndo->SetEnabled(kFALSE);
   
   if (fInit) ConnectSignals2Slots();
   SetActive();
}

//______________________________________________________________________________
void TGeoPconEditor::CreateSections(Int_t inew)
{
// Change dynamically the number of sections.
   if (inew == fNsections) return;
   if (!fSections) fSections = new TObjArray(8);
   TGCompositeFrame *cont = (TGCompositeFrame*)fCan->GetContainer();
   TGeoPconSection *sect;
   Int_t isect;
   // new sections requested
   if (inew>fNsections) {
      for (isect=fNsections; isect<inew; isect++) {
         sect = new TGeoPconSection(cont, 150, 10, isect);
         fSections->Add(sect);
         cont->AddFrame(sect, fLHsect);
         sect->Connect("Changed(Int_t)", "TGeoPconEditor", this, "DoSectionChange(Int_t)");
      }   
   } else {
   // some sections need to be removed
      for (isect=inew; isect<fNsections; isect++) {
         sect = (TGeoPconSection*)fSections->At(isect);
         sect->HideDaughters();
         cont->HideFrame(sect);
         cont->RemoveFrame(sect);
//         sect->Disconnect("Changed(Int_t)", "TGeoPconEditor", this, "DoSectionChange(Int_t)");
         fSections->RemoveAt(isect);
         delete sect;
      }
   }   
   fNsections = inew;
   fCan->MapSubwindows();
   cont->Layout();
   cont->MapWindow();
   fCan->Layout();
}         

//______________________________________________________________________________
Bool_t TGeoPconEditor::CheckSections(Bool_t change)
{
// Check validity of sections
   TGeoPconSection *sect;
   Double_t zmin = 0;
   Double_t rmin = 0, rmax = 1.;
   for (Int_t isect=0; isect<fNsections; isect++) {
      sect = (TGeoPconSection*)fSections->At(isect);
      if (isect && (sect->GetZ()<zmin)) {
         if (!change) return kFALSE;
         sect->SetZ(zmin+1.);
      }   
      zmin = sect->GetZ();
      if (sect->GetRmin()<0 ||
          (sect->GetRmax()<0) || ((sect->GetRmin()==0) && (sect->GetRmax()==0))) {
         if (!change) return kFALSE;
         sect->SetRmin(rmin);
         sect->SetRmax(rmax);
      }   
      rmin = sect->GetRmin();
      rmax = sect->GetRmax();
   }
   return kTRUE;   
}
      
//______________________________________________________________________________
void TGeoPconEditor::UpdateSections()
{
// Update sections according fShape.
   if (fZi) delete [] fZi;
   if (fRmini) delete [] fRmini;
   if (fRmaxi) delete [] fRmaxi;
   fZi = new Double_t[fNsections];
   fRmini = new Double_t[fNsections];
   fRmaxi = new Double_t[fNsections];
   TGeoPconSection *sect;
   for (Int_t isect=0; isect<fNsections; isect++) {
      sect = (TGeoPconSection*)fSections->At(isect);
      sect->SetZ(fShape->GetZ(isect));
      fZi[isect] = fShape->GetZ(isect);
      sect->SetRmin(fShape->GetRmin(isect));
      fRmini[isect] = fShape->GetRmin(isect);
      sect->SetRmax(fShape->GetRmax(isect));
      fRmaxi[isect] = fShape->GetRmax(isect);
   }   
}      
      
//______________________________________________________________________________
Bool_t TGeoPconEditor::IsDelayed() const
{
// Check if shape drawing is delayed.
   return (fDelayed->GetState() == kButtonDown);
}

//______________________________________________________________________________
void TGeoPconEditor::DoName()
{
   // Perform name change
   DoModified();
}

//______________________________________________________________________________
void TGeoPconEditor::DoApply()
{
// Slot for applying modifications.
   const char *name = fShapeName->GetText();
   if (strcmp(name,fShape->GetName())) fShape->SetName(name);
   fApply->SetEnabled(kFALSE);
   fUndo->SetEnabled();
   if (!CheckSections()) return;
   // check if number of sections changed
   Bool_t recreate = kFALSE;
   Int_t nz = fENz->GetIntNumber();
   Double_t phi1 = fEPhi1->GetNumber();
   Double_t dphi = fEDPhi->GetNumber();
   if (nz != fShape->GetNz()) recreate = kTRUE;
   TGeoPconSection *sect;
   Int_t isect;
   if (recreate) {
      Double_t *array = new Double_t[3*(nz+1)];
      array[0] = phi1;
      array[1] = dphi;
      array[2] = nz;
      for (isect=0; isect<nz; isect++) {
         sect = (TGeoPconSection*)fSections->At(isect);
         array[3+3*isect] = sect->GetZ();
         array[4+3*isect] = sect->GetRmin();
         array[5+3*isect] = sect->GetRmax();
      }
      fShape->SetDimensions(array);
      delete [] array;
      if (fPad) {
         if (gGeoManager && gGeoManager->GetPainter() && gGeoManager->GetPainter()->IsPaintingShape()) {
            TView *view = fPad->GetView();
            if (!view) {
               fShape->Draw();
               fPad->GetView()->ShowAxis();
            } else {
               const Double_t *orig = fShape->GetOrigin();
               view->SetRange(orig[0]-fShape->GetDX(), orig[1]-fShape->GetDY(), orig[2]-fShape->GetDZ(),
                              orig[0]+fShape->GetDX(), orig[1]+fShape->GetDY(), orig[2]+fShape->GetDZ());
               Update();
            }                  
         } else Update();
      }   
      return;
   }           
   // No need to call SetDimensions   
   if (TMath::Abs(phi1-fShape->GetPhi1())>1.e-6) fShape->Phi1() = phi1;
   if (TMath::Abs(dphi-fShape->GetDphi())>1.e-6)  fShape->Dphi() = dphi;
   for (isect=0; isect<fNsections; isect++) {
      sect = (TGeoPconSection*)fSections->At(isect);
      fShape->Z(isect) = sect->GetZ();
      fShape->Rmin(isect) = sect->GetRmin();
      fShape->Rmax(isect) = sect->GetRmax();
   }   
   fShape->ComputeBBox();
   if (fPad) {
      if (gGeoManager && gGeoManager->GetPainter() && gGeoManager->GetPainter()->IsPaintingShape()) {
         TView *view = fPad->GetView();
         if (!view) {
            fShape->Draw();
            fPad->GetView()->ShowAxis();
         } else {
            const Double_t *orig = fShape->GetOrigin();
            view->SetRange(orig[0]-fShape->GetDX(), orig[1]-fShape->GetDY(), orig[2]-fShape->GetDZ(),
                           orig[0]+fShape->GetDX(), orig[1]+fShape->GetDY(), orig[2]+fShape->GetDZ());
            Update();
         }                  
      } else Update();
   }   
}

//______________________________________________________________________________
void TGeoPconEditor::DoSectionChange(Int_t isect)
{
// Change parameters of section isect;
   TGeoPconSection *sect, *sectlo=0, *secthi=0;
   sect = (TGeoPconSection*)fSections->At(isect);
   if (isect) sectlo = (TGeoPconSection*)fSections->At(isect-1);
   if (isect<fNsections-1) secthi = (TGeoPconSection*)fSections->At(isect+1);
   Double_t z = sect->GetZ();
   if (sectlo && z<sectlo->GetZ()) {
      z = sectlo->GetZ();
      sect->SetZ(z);
   }   
   if (secthi && z>secthi->GetZ()) {
      z = secthi->GetZ();
      sect->SetZ(z);
   } 
   DoModified();
   if (!IsDelayed()) DoApply();
}   

//______________________________________________________________________________
void TGeoPconEditor::DoNz()
{
// Change number of sections.
   Int_t nz = fENz->GetIntNumber();
   if (nz < 2) {
      nz = 2;
      fENz->SetNumber(nz);
   }   
   CreateSections(nz);
   CheckSections(kTRUE);
   DoModified();
   if (!IsDelayed()) DoApply();
}   

//______________________________________________________________________________
void TGeoPconEditor::DoPhi()
{
// Change phi range.
   Double_t phi1 = fEPhi1->GetNumber();
   Double_t dphi = fEDPhi->GetNumber();
   if (TMath::Abs(phi1)>360) fEPhi1->SetNumber(0);
   if (dphi>360) fEDPhi->SetNumber(360);
   DoModified();
   if (!IsDelayed()) DoApply();
}   

//______________________________________________________________________________
void TGeoPconEditor::DoModified()
{
// Slot for signaling modifications.
   fApply->SetEnabled();
}

//______________________________________________________________________________
void TGeoPconEditor::DoUndo()
{
// Slot for undoing last operation.
   fENz->SetNumber(fNsecti);
   CreateSections(fNsecti);
   fEPhi1->SetNumber(fPhi1i);
   fEDPhi->SetNumber(fDPhii);
   TGeoPconSection *sect;
   for (Int_t isect=0; isect<fNsections; isect++) {
      sect = (TGeoPconSection*)fSections->At(isect);
      sect->SetZ(fZi[isect]);
      sect->SetRmin(fRmini[isect]);
      sect->SetRmax(fRmaxi[isect]);
   }   
   DoApply();
   fUndo->SetEnabled(kFALSE);
   fApply->SetEnabled(kFALSE);
}

ClassImp(TGeoPconSection)

//______________________________________________________________________________
TGeoPconSection::TGeoPconSection(const TGWindow *p, UInt_t w, UInt_t h, Int_t id)
                :TGCompositeFrame(p,w,h,kHorizontalFrame | kFixedWidth)
{
   // Constructor.

   fNumber = id;
   TGTextEntry *nef;
   // Label with number
   AddFrame(new TGLabel(this, Form("#%i",id)), new TGLayoutHints(kLHintsLeft, 2, 4, 6, 0));
   
   // Z entry
   fEZ = new TGNumberEntry(this, 0., 5);
   fEZ->Resize(40,fEZ->GetDefaultHeight());
   nef = (TGTextEntry*)fEZ->GetNumberEntry();
   nef->SetToolTipText("Enter the Z position");
   fEZ->Associate(this);
   AddFrame(fEZ, new TGLayoutHints(kLHintsLeft, 2, 2, 2, 2));
   // Rmin entry
   fERmin = new TGNumberEntry(this, 0., 5);
   fERmin->SetNumAttr(TGNumberFormat::kNEAPositive);
   fERmin->Resize(40,fERmin->GetDefaultHeight());
   nef = (TGTextEntry*)fERmin->GetNumberEntry();
   nef->SetToolTipText("Enter the minimum radius");
   fERmin->Associate(this);
   AddFrame(fERmin, new TGLayoutHints(kLHintsLeft, 2, 2, 2, 2));
   // Rmax entry
   fERmax = new TGNumberEntry(this, 0., 5);
   fERmax->SetNumAttr(TGNumberFormat::kNEAPositive);
   fERmax->Resize(40,fERmax->GetDefaultHeight());
   nef = (TGTextEntry*)fERmax->GetNumberEntry();
   nef->SetToolTipText("Enter the maximum radius");
   fERmax->Associate(this);
   AddFrame(fERmax, new TGLayoutHints(kLHintsLeft, 2, 2, 2, 2));
   
   ConnectSignals2Slots();
   MapSubwindows();
   Layout();
}

//______________________________________________________________________________
TGeoPconSection::~TGeoPconSection()
{
// Destructor
   Cleanup();   
}

//______________________________________________________________________________
void TGeoPconSection::HideDaughters()
{
// Hide daughter frames
   fEZ->UnmapWindow();
   fERmin->UnmapWindow();
   fERmax->UnmapWindow();
}

//______________________________________________________________________________
void TGeoPconSection::Changed(Int_t i)
{
// Emit Changed(Int_t) signal.
   Emit("Changed(Int_t)", i);
}   

//______________________________________________________________________________
void TGeoPconSection::ConnectSignals2Slots()
{
// Connect signals to slots.
   fEZ->Connect("ValueSet(Long_t)", "TGeoPconSection", this, "DoZ()");
   fERmin->Connect("ValueSet(Long_t)", "TGeoPconSection", this, "DoRmin()");
   fERmax->Connect("ValueSet(Long_t)", "TGeoPconSection", this, "DoRmax()");
}

//______________________________________________________________________________
Double_t TGeoPconSection::GetZ() const
{
// Z value getter
   return fEZ->GetNumber();
}   

//______________________________________________________________________________
Double_t TGeoPconSection::GetRmin() const
{
// Rmin value getter
   return fERmin->GetNumber();
}   

//______________________________________________________________________________
Double_t TGeoPconSection::GetRmax() const
{
// Rmax value getter
   return fERmax->GetNumber();
}   

//______________________________________________________________________________
void TGeoPconSection::SetZ(Double_t z)
{
// Z value setter
   fEZ->SetNumber(z);
}   

//______________________________________________________________________________
void TGeoPconSection::SetRmin(Double_t rmin)
{
// Rmin value setter
   fERmin->SetNumber(rmin);
}   

//______________________________________________________________________________
void TGeoPconSection::SetRmax(Double_t rmax)
{
// Rmax value setter
   fERmax->SetNumber(rmax);
}   

//______________________________________________________________________________
void TGeoPconSection::DoZ()
{
// Z slot.
   Changed(fNumber);
}

//______________________________________________________________________________
void TGeoPconSection::DoRmin()
{
// Rmin slot.
   Double_t rmin = fERmin->GetNumber();
   Double_t rmax = fERmax->GetNumber();
   if (rmin>rmax-1.e-8) fERmin->SetNumber(rmax);
   Changed(fNumber);
}
   
//______________________________________________________________________________
void TGeoPconSection::DoRmax()
{
// Rmax slot.
   Double_t rmin = fERmin->GetNumber();
   Double_t rmax = fERmax->GetNumber();
   if (rmax<rmin+1.e-8) fERmax->SetNumber(rmin);
   Changed(fNumber);
}

Last change: Wed Jun 25 08:45:18 2008
Last generated: 2008-06-25 08:45

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.