// @(#):$Id: TGeoMatrixEditor.cxx 21494 2007-12-19 15:50:40Z brun $
// 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.             *
 *************************************************************************/

//______________________________________________________________________________
//                                                                      
//  TGeoTranslationEditor, TGeoRotationEditor, TGeoCombiTransEditor
//     Editors for different types of TGeo matrices.
//______________________________________________________________________________

#include "TGeoMatrixEditor.h"
#include "TGeoTabManager.h"
#include "TGeoMatrix.h"
#include "TPad.h"
#include "TGTab.h"
#include "TGComboBox.h"
#include "TGButton.h"
#include "TGButtonGroup.h"
#include "TGTextEntry.h"
#include "TGNumberEntry.h"
#include "TGLabel.h"

ClassImp(TGeoTranslationEditor)

enum ETGeoMatrixWid {
   kMATRIX_NAME, kMATRIX_DX, kMATRIX_DY, kMATRIX_DZ,
   kMATRIX_PHI, kMATRIX_THETA, kMATRIX_PSI,
   kMATRIX_APPLY, kMATRIX_CANCEL, kMATRIX_UNDO
};

//______________________________________________________________________________
TGeoTranslationEditor::TGeoTranslationEditor(const TGWindow *p, Int_t width,
                                   Int_t height, UInt_t options, Pixel_t back)
   : TGeoGedFrame(p, width, height, options | kVerticalFrame, back)
{
   // Constructor for translation editor
   fTranslation   = 0;
   fDxi = fDyi = fDzi = 0.0;
   fNamei = "";
   fIsModified = kFALSE;
   fIsEditable = kFALSE;
      
   // TextEntry for name
   MakeTitle("Name");
   fTransName = new TGTextEntry(this, new TGTextBuffer(50), kMATRIX_NAME);
   fTransName->Resize(135, fTransName->GetDefaultHeight());
   fTransName->SetToolTipText("Enter the translation name");
   fTransName->Associate(this);
   AddFrame(fTransName, new TGLayoutHints(kLHintsLeft, 3, 1, 2, 5));

   TGTextEntry *nef;
   MakeTitle("Translations on axes");
   TGCompositeFrame *compxyz = new TGCompositeFrame(this, 118, 30, kVerticalFrame | kRaisedFrame | kDoubleBorder);
   // Number entry for dx
   TGCompositeFrame *f1 = new TGCompositeFrame(compxyz, 118, 10, kHorizontalFrame |
                                 kLHintsExpandX | kFixedWidth | kOwnBackground);
   f1->AddFrame(new TGLabel(f1, "DX"), new TGLayoutHints(kLHintsLeft, 1, 1, 6, 0));
   fTransDx = new TGNumberEntry(f1, 0., 5, kMATRIX_DX);
   nef = (TGTextEntry*)fTransDx->GetNumberEntry();
   nef->SetToolTipText("Enter the translation on X");
   fTransDx->Associate(this);
   f1->AddFrame(fTransDx, new TGLayoutHints(kLHintsLeft | kLHintsExpandX , 2, 2, 2, 2));
   compxyz->AddFrame(f1, new TGLayoutHints(kLHintsLeft | kLHintsExpandX , 2, 2, 2, 2));
   
   // Number entry for dy
   TGCompositeFrame *f2 = new TGCompositeFrame(compxyz, 118, 10, kHorizontalFrame |
                                 kLHintsExpandX | kFixedWidth | kOwnBackground);
   f2->AddFrame(new TGLabel(f2, "DY"), new TGLayoutHints(kLHintsLeft, 1, 1, 6, 0));
   fTransDy = new TGNumberEntry(f2, 0., 5, kMATRIX_DY);
   nef = (TGTextEntry*)fTransDy->GetNumberEntry();
   nef->SetToolTipText("Enter the translation on Y");
   fTransDy->Associate(this);
   f2->AddFrame(fTransDy, new TGLayoutHints(kLHintsLeft | kLHintsExpandX , 2, 2, 2, 2));
   compxyz->AddFrame(f2, new TGLayoutHints(kLHintsLeft | kLHintsExpandX , 2, 2, 2, 2));
   
   // Number entry for dx
   TGCompositeFrame *f3 = new TGCompositeFrame(compxyz, 118, 10, kHorizontalFrame |
                                 kLHintsExpandX | kFixedWidth | kOwnBackground);
   f3->AddFrame(new TGLabel(f3, "DZ"), new TGLayoutHints(kLHintsLeft, 1, 1, 6, 0));
   fTransDz = new TGNumberEntry(f3, 0., 5, kMATRIX_DZ);
   nef = (TGTextEntry*)fTransDz->GetNumberEntry();
   nef->SetToolTipText("Enter the translation on Z");
   fTransDz->Associate(this);
   f3->AddFrame(fTransDz, new TGLayoutHints(kLHintsLeft | kLHintsExpandX , 2, 2, 2, 2));
   compxyz->AddFrame(f3, new TGLayoutHints(kLHintsLeft | kLHintsExpandX , 2, 2, 2, 2));
   
   compxyz->Resize(150,30);
   AddFrame(compxyz, new TGLayoutHints(kLHintsLeft, 6, 6, 2, 2));
      
   // Buttons
   TGCompositeFrame *f23 = new TGCompositeFrame(this, 118, 20, kHorizontalFrame | kSunkenFrame | kDoubleBorder);
   fApply = new TGTextButton(f23, "&Apply");
   f23->AddFrame(fApply, new TGLayoutHints(kLHintsLeft, 2, 2, 4, 4));
   fApply->Associate(this);
   fCancel = new TGTextButton(f23, "&Cancel");
   f23->AddFrame(fCancel, new TGLayoutHints(kLHintsCenterX, 2, 2, 4, 4));
   fCancel->Associate(this);
   fUndo = new TGTextButton(f23, " &Undo ");
   f23->AddFrame(fUndo, new TGLayoutHints(kLHintsRight , 2, 2, 4, 4));
   fUndo->Associate(this);
   AddFrame(f23,  new TGLayoutHints(kLHintsLeft, 6, 6, 2, 2));  
   fUndo->SetSize(fCancel->GetSize());
   fApply->SetSize(fCancel->GetSize());
}

//______________________________________________________________________________
TGeoTranslationEditor::~TGeoTranslationEditor()
{
// Destructor.
   TGFrameElement *el;
   TIter next(GetList());
   while ((el = (TGFrameElement *)next())) {
      if (el->fFrame->IsComposite()) 
         TGeoTabManager::Cleanup((TGCompositeFrame*)el->fFrame);
   }
   Cleanup();   
}

//______________________________________________________________________________
void TGeoTranslationEditor::ConnectSignals2Slots()
{
   // Connect signals to slots.
   fApply->Connect("Clicked()", "TGeoTranslationEditor", this, "DoApply()");
   fCancel->Connect("Clicked()", "TGeoTranslationEditor", this, "DoCancel()");
   fUndo->Connect("Clicked()", "TGeoTranslationEditor", this, "DoUndo()");
   fTransName->Connect("TextChanged(const char *)", "TGeoTranslationEditor", this, "DoModified()");
   fTransDx->Connect("ValueSet(Long_t)", "TGeoTranslationEditor", this, "DoDx()");
   fTransDy->Connect("ValueSet(Long_t)", "TGeoTranslationEditor", this, "DoDy()");
   fTransDz->Connect("ValueSet(Long_t)", "TGeoTranslationEditor", this, "DoDz()");
   fTransDx->GetNumberEntry()->Connect("TextChanged(const char *)", "TGeoTranslationEditor", this, "DoDx()");
   fTransDy->GetNumberEntry()->Connect("TextChanged(const char *)", "TGeoTranslationEditor", this, "DoDy()");
   fTransDz->GetNumberEntry()->Connect("TextChanged(const char *)", "TGeoTranslationEditor", this, "DoDz()");
   fInit = kFALSE;
}


//______________________________________________________________________________
void TGeoTranslationEditor::SetModel(TObject* obj)
{
   // Connect to the new matrix.
   if (obj == 0 || (obj->IsA()!=TGeoTranslation::Class())) {
      SetActive(kFALSE);
      return;                 
   } 
   fTranslation = (TGeoTranslation*)obj;
   fDxi = fTranslation->GetTranslation()[0];
   fDyi = fTranslation->GetTranslation()[1];
   fDzi = fTranslation->GetTranslation()[2];
   const char *sname = fTranslation->GetName();
   if (!strcmp(sname, fTranslation->ClassName())) fTransName->SetText("no_name");
   else {
      fTransName->SetText(sname);
      fNamei = sname;
   }   
   fTransDx->SetNumber(fDxi);
   fTransDy->SetNumber(fDyi);
   fTransDz->SetNumber(fDzi);
   fApply->SetEnabled(kFALSE);
   fUndo->SetEnabled(kFALSE);
   fCancel->SetEnabled(kFALSE);
   
   if (fInit) ConnectSignals2Slots();
   SetActive();
}

//______________________________________________________________________________
void TGeoTranslationEditor::DoName()
{
// Slot for name.
   const char *name = fTransName->GetText();
   if (!strcmp(name, "no_name") || !strcmp(name, fTranslation->GetName())) return;
   fTranslation->SetName(name);
}

//______________________________________________________________________________
Bool_t TGeoTranslationEditor::DoParameters()
{
// Slot for checking parameters.
   Double_t dx = fTransDx->GetNumber();
   Double_t dy = fTransDy->GetNumber();
   Double_t dz = fTransDz->GetNumber();
   Bool_t changed = kFALSE;
   if (dx != fTranslation->GetTranslation()[0] || 
       dy != fTranslation->GetTranslation()[1] || 
       dz != fTranslation->GetTranslation()[2]) changed = kTRUE;
   if (!changed) return kFALSE;
   fUndo->SetEnabled();
   fTranslation->SetTranslation(dx, dy, dz);
   if (fPad) {
      fPad->Modified();
      fPad->Update();
   }   
   return kTRUE;
}

//______________________________________________________________________________
void TGeoTranslationEditor::DoApply()
{
// Slot for applying changes.
   DoName();
   if (DoParameters()) {
      fUndo->SetEnabled();
      fCancel->SetEnabled(kFALSE);
      fApply->SetEnabled(kFALSE);
   }   
}

//______________________________________________________________________________
void TGeoTranslationEditor::DoCancel()
{
// Slot for cancelling last modifications non-applied.
   if (!fNamei.Length()) fTransName->SetText("no_name");
   else fTransName->SetText(fNamei.Data());
   fTransDx->SetNumber(fDxi);
   fTransDy->SetNumber(fDyi);
   fTransDz->SetNumber(fDzi);
   fApply->SetEnabled(kFALSE);
   fUndo->SetEnabled(kFALSE);
   fCancel->SetEnabled(kFALSE);
}

//______________________________________________________________________________
void TGeoTranslationEditor::DoModified()
{
// Slot for notifying changes.
   fApply->SetEnabled();
   if (fUndo->GetState()==kButtonDisabled) fCancel->SetEnabled();
}

//______________________________________________________________________________
void TGeoTranslationEditor::DoUndo()
{
// Slot for undoing last operation.
   DoCancel();
   DoParameters();
   fCancel->SetEnabled(kFALSE);
   fUndo->SetEnabled(kFALSE);
   fApply->SetEnabled(kFALSE);
}
   
//______________________________________________________________________________
void TGeoTranslationEditor::DoDx()
{
// Slot for dx.
   DoModified();
}

//______________________________________________________________________________
void TGeoTranslationEditor::DoDy()
{
// Slot for dx.
   DoModified();
}

//______________________________________________________________________________
void TGeoTranslationEditor::DoDz()
{
// Slot for dx.
   DoModified();
}

//////////////////////////////////////////////////////////////////////////
//                                                                      //
//  TGeoRotationEditor                                                  //
//                                                                      //
//  Editor for a TGeoRotation.                                          //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

ClassImp(TGeoRotationEditor)

//______________________________________________________________________________
TGeoRotationEditor::TGeoRotationEditor(const TGWindow *p, Int_t width,
                                   Int_t height, UInt_t options, Pixel_t back)
   : TGeoGedFrame(p, width, height, options | kVerticalFrame, back)
{
   // Constructor for rotation editor
   fRotation   = 0;
   fPhii = fThetai = fPsii = 0.0;
   fAngleX = fAngleY = fAngleZ = 0.0;
   fNamei = "";
   fIsModified = kFALSE;
   fIsEditable = kFALSE;
      
   // TextEntry for name
   MakeTitle("Name");
   fRotName = new TGTextEntry(this, new TGTextBuffer(50), kMATRIX_NAME);
   fRotName->Resize(135, fRotName->GetDefaultHeight());
   fRotName->SetToolTipText("Enter the rotation name");
   fRotName->Associate(this);
   AddFrame(fRotName, new TGLayoutHints(kLHintsLeft, 3, 1, 2, 5));

   TGTextEntry *nef;
   MakeTitle("Euler angles");
   TGCompositeFrame *compxyz = new TGCompositeFrame(this, 140, 30, kVerticalFrame | kRaisedFrame | kDoubleBorder);
   // Number entry for phi angle
   TGCompositeFrame *f1 = new TGCompositeFrame(compxyz, 118, 10, kHorizontalFrame |
                                 kLHintsExpandX | kFixedWidth | kOwnBackground);
   f1->AddFrame(new TGLabel(f1, " PHI "), new TGLayoutHints(kLHintsLeft, 1, 1, 6, 0));
   fRotPhi = new TGNumberEntry(f1, 0., 5, kMATRIX_PHI);
   nef = (TGTextEntry*)fRotPhi->GetNumberEntry();
   nef->SetToolTipText("Modify the first rotation angle about Z");
   fRotPhi->Associate(this);
   fRotPhi->Resize(90, fRotPhi->GetDefaultHeight());
   f1->AddFrame(fRotPhi, new TGLayoutHints(kLHintsRight , 2, 2, 2, 2));
   compxyz->AddFrame(f1, new TGLayoutHints(kLHintsLeft | kLHintsExpandX , 2, 2, 2, 2));
   
   // Number entry for theta angle
   TGCompositeFrame *f2 = new TGCompositeFrame(compxyz, 118, 10, kHorizontalFrame |
                                 kLHintsExpandX | kFixedWidth | kOwnBackground);
   f2->AddFrame(new TGLabel(f2, "THETA"), new TGLayoutHints(kLHintsLeft, 1, 1, 6, 0));
   fRotTheta = new TGNumberEntry(f2, 0., 5, kMATRIX_THETA);
   nef = (TGTextEntry*)fRotTheta->GetNumberEntry();
   nef->SetToolTipText("Modify the second rotation angle about the new X");
   fRotTheta->Associate(this);
   fRotTheta->Resize(90, fRotTheta->GetDefaultHeight());
   f2->AddFrame(fRotTheta, new TGLayoutHints(kLHintsRight , 2, 2, 2, 2));
   compxyz->AddFrame(f2, new TGLayoutHints(kLHintsLeft | kLHintsExpandX , 2, 2, 2, 2));
   
   // Number entry for psi angle
   TGCompositeFrame *f3 = new TGCompositeFrame(compxyz, 118, 10, kHorizontalFrame |
                                 kLHintsExpandX | kFixedWidth | kOwnBackground);
   f3->AddFrame(new TGLabel(f3, " PSI "), new TGLayoutHints(kLHintsLeft, 1, 1, 6, 0));
   fRotPsi = new TGNumberEntry(f3, 0., 5, kMATRIX_PSI);
   nef = (TGTextEntry*)fRotPsi->GetNumberEntry();
   nef->SetToolTipText("Modify the third rotation angle about Z");
   fRotPsi->Associate(this);
   fRotPsi->Resize(90, fRotPsi->GetDefaultHeight());
   f3->AddFrame(fRotPsi, new TGLayoutHints(kLHintsRight , 2, 2, 2, 2));
   compxyz->AddFrame(f3, new TGLayoutHints(kLHintsLeft | kLHintsExpandX , 2, 2, 2, 2));

   compxyz->Resize(150,compxyz->GetDefaultHeight());
   AddFrame(compxyz, new TGLayoutHints(kLHintsLeft, 6, 6, 2, 2));
   
   MakeTitle("Rotate about axis");
   compxyz = new TGCompositeFrame(this, 140, 30, kVerticalFrame | kRaisedFrame | kDoubleBorder);
   // Number entry for rotation angle about one axis
   f1 = new TGCompositeFrame(compxyz, 118, 10, kHorizontalFrame |
                                 kLHintsExpandX | kFixedWidth | kOwnBackground);
   f1->AddFrame(new TGLabel(f1, "ANGLE"), new TGLayoutHints(kLHintsLeft, 1, 1, 6, 0));
   fRotAxis = new TGNumberEntry(f1, 0., 5, kMATRIX_DX);
   nef = (TGTextEntry*)fRotAxis->GetNumberEntry();
   nef->SetToolTipText("Enter the new rotation angle about the selected axis");
   fRotAxis->Associate(this);
   fRotAxis->Resize(90, fRotAxis->GetDefaultHeight());
   f1->AddFrame(fRotAxis, new TGLayoutHints(kLHintsRight , 2, 2, 2, 2));
   compxyz->AddFrame(f1, new TGLayoutHints(kLHintsLeft | kLHintsExpandX , 2, 2, 2, 2));
   
   // Radio buttons group for axis selection
   TGHButtonGroup *bg1 = new TGHButtonGroup(compxyz, " Axis ");
   fRotX = new TGRadioButton(bg1, " &X ", kMATRIX_DX);
   fRotY = new TGRadioButton(bg1, " &Y ", kMATRIX_DY);
   fRotZ = new TGRadioButton(bg1, " &Z ", kMATRIX_DZ);
   bg1->SetRadioButtonExclusive();
   bg1->Show();
   compxyz->AddFrame(bg1, new TGLayoutHints(kLHintsLeft | kLHintsExpandX , 2, 2, 2, 2));

   compxyz->Resize(150,compxyz->GetDefaultHeight());
   AddFrame(compxyz, new TGLayoutHints(kLHintsLeft, 6, 6, 2, 2));

      
   // Buttons
   TGCompositeFrame *f23 = new TGCompositeFrame(this, 118, 20, kHorizontalFrame | kSunkenFrame | kDoubleBorder);
   fApply = new TGTextButton(f23, "Apply");
   f23->AddFrame(fApply, new TGLayoutHints(kLHintsLeft, 2, 2, 4, 4));
   fApply->Associate(this);
   fCancel = new TGTextButton(f23, "Cancel");
   f23->AddFrame(fCancel, new TGLayoutHints(kLHintsCenterX, 2, 2, 4, 4));
   fCancel->Associate(this);
   fUndo = new TGTextButton(f23, " Undo ");
   f23->AddFrame(fUndo, new TGLayoutHints(kLHintsRight , 2, 2, 4, 4));
   fUndo->Associate(this);
   AddFrame(f23,  new TGLayoutHints(kLHintsLeft, 6, 6, 2, 2));  
   fUndo->SetSize(fCancel->GetSize());
   fApply->SetSize(fCancel->GetSize());
}

//______________________________________________________________________________
TGeoRotationEditor::~TGeoRotationEditor()
{
// Destructor
   TGFrameElement *el;
   TIter next(GetList());
   while ((el = (TGFrameElement *)next())) {
      if (el->fFrame->IsComposite()) 
         TGeoTabManager::Cleanup((TGCompositeFrame*)el->fFrame);
   }
   Cleanup();   
}

//______________________________________________________________________________
void TGeoRotationEditor::ConnectSignals2Slots()
{
   // Connect signals to slots.
   fApply->Connect("Clicked()", "TGeoRotationEditor", this, "DoApply()");
   fCancel->Connect("Clicked()", "TGeoRotationEditor", this, "DoCancel()");
   fUndo->Connect("Clicked()", "TGeoRotationEditor", this, "DoUndo()");
   fRotName->Connect("TextChanged(const char *)", "TGeoRotationEditor", this, "DoModified()");
   fRotPhi->Connect("ValueSet(Long_t)", "TGeoRotationEditor", this, "DoRotPhi()");
   fRotTheta->Connect("ValueSet(Long_t)", "TGeoRotationEditor", this, "DoRotTheta()");
   fRotPsi->Connect("ValueSet(Long_t)", "TGeoRotationEditor", this, "DoRotPsi()");
   fRotAxis->Connect("ValueSet(Long_t)", "TGeoRotationEditor", this, "DoRotAngle()");
   fInit = kFALSE;
}


//______________________________________________________________________________
void TGeoRotationEditor::SetModel(TObject* obj)
{
   // Connect to the selected rotation.
   if (obj == 0 || (obj->IsA()!=TGeoRotation::Class())) {
      SetActive(kFALSE);
      return;                 
   } 
   fRotation = (TGeoRotation*)obj;
   fRotation->GetAngles(fPhii, fThetai, fPsii);
   const char *sname = fRotation->GetName();
   if (!strcmp(sname, fRotation->ClassName())) fRotName->SetText("no_name");
   else {
      fRotName->SetText(sname);
      fNamei = sname;
   }   
   fRotPhi->SetNumber(fPhii);
   fRotTheta->SetNumber(fThetai);
   fRotPsi->SetNumber(fPsii);
   fRotAxis->SetNumber(0.0);

   fApply->SetEnabled(kFALSE);
   fUndo->SetEnabled(kFALSE);
   fCancel->SetEnabled(kFALSE);
   
   if (fInit) ConnectSignals2Slots();
   SetActive();
}

//______________________________________________________________________________
void TGeoRotationEditor::DoName()
{
// Slot for name.
   const char *name = fRotName->GetText();
   if (!strcmp(name, "no_name") || !strcmp(name, fRotation->GetName())) return;
   fRotation->SetName(name);
}

//______________________________________________________________________________
void TGeoRotationEditor::DoRotPhi()
{
// Slot for phi (Euler X convention)
   if (fRotPhi->GetNumber() < 0.) fRotPhi->SetNumber(fRotPhi->GetNumber()+360.);
   if (fRotPhi->GetNumber() >= 360.) fRotPhi->SetNumber(fRotPhi->GetNumber()-360.);
   DoModified();
}

//______________________________________________________________________________
void TGeoRotationEditor::DoRotTheta()
{
// Slot for theta (Euler X convention)
   if (fRotTheta->GetNumber() < 0.) fRotTheta->SetNumber(fRotTheta->GetNumber()+360.);
   if (fRotTheta->GetNumber() >= 360.) fRotTheta->SetNumber(fRotTheta->GetNumber()-360.);
   DoModified();
}

//______________________________________________________________________________
void TGeoRotationEditor::DoRotPsi()
{
// Slot for psi (Euler X convention)
   if (fRotPsi->GetNumber() < 0.) fRotPsi->SetNumber(fRotPsi->GetNumber()+360.);
   if (fRotPsi->GetNumber() >= 360.) fRotPsi->SetNumber(fRotPsi->GetNumber()-360.);
   DoModified();
}

//______________________________________________________________________________
void TGeoRotationEditor::DoRotAngle()
{
// Slot for additional rotation about one axis.
   if (fRotAxis->GetNumber() < 0.) fRotAxis->SetNumber(fRotAxis->GetNumber()+360.);
   if (fRotAxis->GetNumber() >= 360.) fRotAxis->SetNumber(fRotAxis->GetNumber()-360.);
   DoModified();
}

//______________________________________________________________________________
Bool_t TGeoRotationEditor::DoParameters()
{
// Slot for checking parameters.
   Double_t phi = fRotPhi->GetNumber();
   Double_t theta = fRotTheta->GetNumber();
   Double_t psi = fRotPsi->GetNumber();
   Double_t angle = fRotAxis->GetNumber();
   Double_t phi0 = 0., theta0 = 0., psi0 = 0.;
   fRotation->GetAngles(phi0,theta0,psi0);
   Bool_t changed = kFALSE;
   if (phi != psi0 || theta != theta0 || psi != psi0) changed = kTRUE;
   if (changed) fRotation->SetAngles(phi, theta, psi);
   // Check if we have to rotate about one axis
   if (angle != 0.0) {
      if (fRotX->IsOn()) {fRotation->RotateX(angle); changed = kTRUE;}
      if (fRotY->IsOn()) {fRotation->RotateY(angle); changed = kTRUE;}
      if (fRotZ->IsOn()) {fRotation->RotateZ(angle); changed = kTRUE;}
   }   
   if (!changed) return kFALSE;   
   fRotAxis->SetNumber(0.0);
   fUndo->SetEnabled();
   if (fPad) {
      fPad->Modified();
      fPad->Update();
   }   
   return kTRUE;
}

//______________________________________________________________________________
void TGeoRotationEditor::DoApply()
{
// Slot for applying modifications.
   DoName();
   if (DoParameters()) {
      fUndo->SetEnabled();
      fCancel->SetEnabled(kFALSE);
      fApply->SetEnabled(kFALSE);
   }   
}

//______________________________________________________________________________
void TGeoRotationEditor::DoCancel()
{
// Slot for cancelling last un-applied operations.
   if (!fNamei.Length()) fRotName->SetText("no_name");
   else fRotName->SetText(fNamei.Data());
   fRotPhi->SetNumber(fPhii);
   fRotTheta->SetNumber(fThetai);
   fRotPsi->SetNumber(fPsii);
   fRotAxis->SetNumber(0.0);
   fApply->SetEnabled(kFALSE);
   fUndo->SetEnabled(kFALSE);
   fCancel->SetEnabled(kFALSE);
}

//______________________________________________________________________________
void TGeoRotationEditor::DoModified()
{
// Slot for notifying changes.
   fApply->SetEnabled();
   if (fUndo->GetState()==kButtonDisabled) fCancel->SetEnabled();
}

//______________________________________________________________________________
void TGeoRotationEditor::DoUndo()
{
// Slot for undoing last changes.
   DoCancel();
   DoParameters();
   fCancel->SetEnabled(kFALSE);
   fUndo->SetEnabled(kFALSE);
   fApply->SetEnabled(kFALSE);
}

   
//////////////////////////////////////////////////////////////////////////
//                                                                      //
//  TGeoCombiTransEditor                                                //
//                                                                      //
//  Editor for a TGeoCombiTrans.                                        //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

ClassImp(TGeoCombiTransEditor)

//______________________________________________________________________________
TGeoCombiTransEditor::TGeoCombiTransEditor(const TGWindow *p, Int_t width,
                                   Int_t height, UInt_t options, Pixel_t back)
   : TGeoGedFrame(p, width, height, options | kVerticalFrame, back)
{
   // Constructor for combi matrix editor
   fCombi   = 0;
   fPhii = fThetai = fPsii = 0.0;
   fDxi = fDyi = fDzi = 0.0;
   fAngleX = fAngleY = fAngleZ = 0.0;
   fNamei = "";
   fIsModified = kFALSE;
   fIsEditable = kFALSE;
      
   // TextEntry for name
   MakeTitle("Name");
   fRotName = new TGTextEntry(this, new TGTextBuffer(50), kMATRIX_NAME);
   fRotName->Resize(135, fRotName->GetDefaultHeight());
   fRotName->SetToolTipText("Enter the rotation name");
   fRotName->Associate(this);
   AddFrame(fRotName, new TGLayoutHints(kLHintsLeft, 3, 1, 2, 5));

   TGTextEntry *nef;
   MakeTitle("Translations on axes");
   TGCompositeFrame *compxyz = new TGCompositeFrame(this, 118, 30, kVerticalFrame | kRaisedFrame | kDoubleBorder);
   // Number entry for dx
   TGCompositeFrame *f1 = new TGCompositeFrame(compxyz, 118, 10, kHorizontalFrame |
                                 kLHintsExpandX | kFixedWidth | kOwnBackground);
   f1->AddFrame(new TGLabel(f1, "DX"), new TGLayoutHints(kLHintsLeft, 1, 1, 6, 0));
   fTransDx = new TGNumberEntry(f1, 0., 5, kMATRIX_DX);
   nef = (TGTextEntry*)fTransDx->GetNumberEntry();
   nef->SetToolTipText("Enter the translation on X");
   fTransDx->Associate(this);
   f1->AddFrame(fTransDx, new TGLayoutHints(kLHintsLeft | kLHintsExpandX , 2, 2, 2, 2));
   compxyz->AddFrame(f1, new TGLayoutHints(kLHintsLeft | kLHintsExpandX , 2, 2, 2, 2));
   
   // Number entry for dy
   TGCompositeFrame *f2 = new TGCompositeFrame(compxyz, 118, 10, kHorizontalFrame |
                                 kLHintsExpandX | kFixedWidth | kOwnBackground);
   f2->AddFrame(new TGLabel(f2, "DY"), new TGLayoutHints(kLHintsLeft, 1, 1, 6, 0));
   fTransDy = new TGNumberEntry(f2, 0., 5, kMATRIX_DY);
   nef = (TGTextEntry*)fTransDy->GetNumberEntry();
   nef->SetToolTipText("Enter the translation on Y");
   fTransDy->Associate(this);
   f2->AddFrame(fTransDy, new TGLayoutHints(kLHintsLeft | kLHintsExpandX , 2, 2, 2, 2));
   compxyz->AddFrame(f2, new TGLayoutHints(kLHintsLeft | kLHintsExpandX , 2, 2, 2, 2));
   
   // Number entry for dx
   TGCompositeFrame *f3 = new TGCompositeFrame(compxyz, 118, 10, kHorizontalFrame |
                                 kLHintsExpandX | kFixedWidth | kOwnBackground);
   f3->AddFrame(new TGLabel(f3, "DZ"), new TGLayoutHints(kLHintsLeft, 1, 1, 6, 0));
   fTransDz = new TGNumberEntry(f3, 0., 5, kMATRIX_DZ);
   nef = (TGTextEntry*)fTransDz->GetNumberEntry();
   nef->SetToolTipText("Enter the translation on Z");
   fTransDz->Associate(this);
   f3->AddFrame(fTransDz, new TGLayoutHints(kLHintsLeft | kLHintsExpandX , 2, 2, 2, 2));
   compxyz->AddFrame(f3, new TGLayoutHints(kLHintsLeft | kLHintsExpandX , 2, 2, 2, 2));
   
   compxyz->Resize(150,30);
   AddFrame(compxyz, new TGLayoutHints(kLHintsLeft, 6, 6, 2, 2));


   MakeTitle("Euler angles");
   compxyz = new TGCompositeFrame(this, 140, 30, kVerticalFrame | kRaisedFrame | kDoubleBorder);
   // Number entry for phi angle
   f1 = new TGCompositeFrame(compxyz, 118, 10, kHorizontalFrame |
                                 kLHintsExpandX | kFixedWidth | kOwnBackground);
   f1->AddFrame(new TGLabel(f1, " PHI "), new TGLayoutHints(kLHintsLeft, 1, 1, 6, 0));
   fRotPhi = new TGNumberEntry(f1, 0., 5, kMATRIX_PHI);
   nef = (TGTextEntry*)fRotPhi->GetNumberEntry();
   nef->SetToolTipText("Modify the first rotation angle about Z");
   fRotPhi->Associate(this);
   fRotPhi->Resize(90, fRotPhi->GetDefaultHeight());
   f1->AddFrame(fRotPhi, new TGLayoutHints(kLHintsRight , 2, 2, 2, 2));
   compxyz->AddFrame(f1, new TGLayoutHints(kLHintsLeft | kLHintsExpandX , 2, 2, 2, 2));
   
   // Number entry for theta angle
   f2 = new TGCompositeFrame(compxyz, 118, 10, kHorizontalFrame |
                                 kLHintsExpandX | kFixedWidth | kOwnBackground);
   f2->AddFrame(new TGLabel(f2, "THETA"), new TGLayoutHints(kLHintsLeft, 1, 1, 6, 0));
   fRotTheta = new TGNumberEntry(f2, 0., 5, kMATRIX_THETA);
   nef = (TGTextEntry*)fRotTheta->GetNumberEntry();
   nef->SetToolTipText("Modify the second rotation angle about the new X");
   fRotTheta->Associate(this);
   fRotTheta->Resize(90, fRotTheta->GetDefaultHeight());
   f2->AddFrame(fRotTheta, new TGLayoutHints(kLHintsRight , 2, 2, 2, 2));
   compxyz->AddFrame(f2, new TGLayoutHints(kLHintsLeft | kLHintsExpandX , 2, 2, 2, 2));
   
   // Number entry for psi angle
   f3 = new TGCompositeFrame(compxyz, 118, 10, kHorizontalFrame |
                                 kLHintsExpandX | kFixedWidth | kOwnBackground);
   f3->AddFrame(new TGLabel(f3, " PSI "), new TGLayoutHints(kLHintsLeft, 1, 1, 6, 0));
   fRotPsi = new TGNumberEntry(f3, 0., 5, kMATRIX_PSI);
   nef = (TGTextEntry*)fRotPsi->GetNumberEntry();
   nef->SetToolTipText("Modify the third rotation angle about Z");
   fRotPsi->Associate(this);
   fRotPsi->Resize(90, fRotPsi->GetDefaultHeight());
   f3->AddFrame(fRotPsi, new TGLayoutHints(kLHintsRight , 2, 2, 2, 2));
   compxyz->AddFrame(f3, new TGLayoutHints(kLHintsLeft | kLHintsExpandX , 2, 2, 2, 2));

   compxyz->Resize(150,compxyz->GetDefaultHeight());
   AddFrame(compxyz, new TGLayoutHints(kLHintsLeft, 6, 6, 2, 2));
   
   MakeTitle("Rotate about axis");
   compxyz = new TGCompositeFrame(this, 140, 30, kVerticalFrame | kRaisedFrame | kDoubleBorder);
   // Number entry for rotation angle about one axis
   f1 = new TGCompositeFrame(compxyz, 118, 10, kHorizontalFrame |
                                 kLHintsExpandX | kFixedWidth | kOwnBackground);
   f1->AddFrame(new TGLabel(f1, "ANGLE"), new TGLayoutHints(kLHintsLeft, 1, 1, 6, 0));
   fRotAxis = new TGNumberEntry(f1, 0., 5, kMATRIX_DX);
   nef = (TGTextEntry*)fRotAxis->GetNumberEntry();
   nef->SetToolTipText("Enter the new rotation angle about the selected axis");
   fRotAxis->Associate(this);
   fRotAxis->Resize(90, fRotAxis->GetDefaultHeight());
   f1->AddFrame(fRotAxis, new TGLayoutHints(kLHintsRight , 2, 2, 2, 2));
   compxyz->AddFrame(f1, new TGLayoutHints(kLHintsLeft | kLHintsExpandX , 2, 2, 2, 2));
   
   // Radio buttons group for axis selection
   TGHButtonGroup *bg1 = new TGHButtonGroup(compxyz, " Axis ");
   fRotX = new TGRadioButton(bg1, " &X ", kMATRIX_DX);
   fRotY = new TGRadioButton(bg1, " &Y ", kMATRIX_DY);
   fRotZ = new TGRadioButton(bg1, " &Z ", kMATRIX_DZ);
   bg1->SetRadioButtonExclusive();
   bg1->Show();
   compxyz->AddFrame(bg1, new TGLayoutHints(kLHintsLeft | kLHintsExpandX , 2, 2, 2, 2));

   compxyz->Resize(150,compxyz->GetDefaultHeight());
   AddFrame(compxyz, new TGLayoutHints(kLHintsLeft, 6, 6, 2, 2));

      
   // Buttons
   TGCompositeFrame *f23 = new TGCompositeFrame(this, 118, 20, kHorizontalFrame | kSunkenFrame | kDoubleBorder);
   fApply = new TGTextButton(f23, "&Apply");
   f23->AddFrame(fApply, new TGLayoutHints(kLHintsLeft, 2, 2, 4, 4));
   fApply->Associate(this);
   fCancel = new TGTextButton(f23, "&Cancel");
   f23->AddFrame(fCancel, new TGLayoutHints(kLHintsCenterX, 2, 2, 4, 4));
   fCancel->Associate(this);
   fUndo = new TGTextButton(f23, " &Undo ");
   f23->AddFrame(fUndo, new TGLayoutHints(kLHintsRight , 2, 2, 4, 4));
   fUndo->Associate(this);
   AddFrame(f23,  new TGLayoutHints(kLHintsLeft, 6, 6, 2, 2));  
   fUndo->SetSize(fCancel->GetSize());
   fApply->SetSize(fCancel->GetSize());
}

//______________________________________________________________________________
TGeoCombiTransEditor::~TGeoCombiTransEditor()
{
// Destructor
   TGFrameElement *el;
   TIter next(GetList());
   while ((el = (TGFrameElement *)next())) {
      if (el->fFrame->IsComposite()) 
         TGeoTabManager::Cleanup((TGCompositeFrame*)el->fFrame);
   }
   Cleanup();   
}

//______________________________________________________________________________
void TGeoCombiTransEditor::ConnectSignals2Slots()
{
   // Connect signals to slots.
   fApply->Connect("Clicked()", "TGeoCombiTransEditor", this, "DoApply()");
   fCancel->Connect("Clicked()", "TGeoCombiTransEditor", this, "DoCancel()");
   fUndo->Connect("Clicked()", "TGeoCombiTransEditor", this, "DoUndo()");
   fRotName->Connect("TextChanged(const char *)", "TGeoCombiTransEditor", this, "DoModified()");
   fRotPhi->Connect("ValueSet(Long_t)", "TGeoCombiTransEditor", this, "DoRotPhi()");
   fRotTheta->Connect("ValueSet(Long_t)", "TGeoCombiTransEditor", this, "DoRotTheta()");
   fRotPsi->Connect("ValueSet(Long_t)", "TGeoCombiTransEditor", this, "DoRotPsi()");
   fRotAxis->Connect("ValueSet(Long_t)", "TGeoCombiTransEditor", this, "DoRotAngle()");
   fTransDx->Connect("ValueSet(Long_t)", "TGeoCombiTransEditor", this, "DoDx()");
   fTransDy->Connect("ValueSet(Long_t)", "TGeoCombiTransEditor", this, "DoDy()");
   fTransDz->Connect("ValueSet(Long_t)", "TGeoCombiTransEditor", this, "DoDz()");
   fTransDx->GetNumberEntry()->Connect("TextChanged(const char *)", "TGeoCombiTransEditor", this, "DoDx()");
   fTransDy->GetNumberEntry()->Connect("TextChanged(const char *)", "TGeoCombiTransEditor", this, "DoDy()");
   fTransDz->GetNumberEntry()->Connect("TextChanged(const char *)", "TGeoCombiTransEditor", this, "DoDz()");
   fInit = kFALSE;
}


//______________________________________________________________________________
void TGeoCombiTransEditor::SetModel(TObject* obj)
{
   // Connect to the selected combi matrix.
   if (obj == 0 || (obj->IsA()!=TGeoCombiTrans::Class())) {
      SetActive(kFALSE);
      return;                 
   } 
   fCombi = (TGeoCombiTrans*)obj;
   TGeoRotation *rot = fCombi->GetRotation();
   if (rot) rot->GetAngles(fPhii, fThetai, fPsii);
   const char *sname = fCombi->GetName();
   if (!strcmp(sname, fCombi->ClassName())) fRotName->SetText("no_name");
   else {
      fRotName->SetText(sname);
      fNamei = sname;
   }   
   
   fDxi = fCombi->GetTranslation()[0];
   fDyi = fCombi->GetTranslation()[1];
   fDzi = fCombi->GetTranslation()[2];
   fTransDx->SetNumber(fDxi);
   fTransDy->SetNumber(fDyi);
   fTransDz->SetNumber(fDzi);

   fRotPhi->SetNumber(fPhii);
   fRotTheta->SetNumber(fThetai);
   fRotPsi->SetNumber(fPsii);
   fRotAxis->SetNumber(0.0);

   fApply->SetEnabled(kFALSE);
   fUndo->SetEnabled(kFALSE);
   fCancel->SetEnabled(kFALSE);
   
   if (fInit) ConnectSignals2Slots();
   SetActive();
}

//______________________________________________________________________________
void TGeoCombiTransEditor::DoName()
{
// Slot for name.
   const char *name = fRotName->GetText();
   if (!strcmp(name, "no_name") || !strcmp(name, fCombi->GetName())) return;
   fCombi->SetName(name);
}

//______________________________________________________________________________
void TGeoCombiTransEditor::DoRotPhi()
{
// Slot for phi (Euler X convention)
   if (fRotPhi->GetNumber() < 0.) fRotPhi->SetNumber(fRotPhi->GetNumber()+360.);
   if (fRotPhi->GetNumber() >= 360.) fRotPhi->SetNumber(fRotPhi->GetNumber()-360.);
   DoModified();
}

//______________________________________________________________________________
void TGeoCombiTransEditor::DoRotTheta()
{
// Slot for theta (Euler X convention)
   if (fRotTheta->GetNumber() < 0.) fRotTheta->SetNumber(fRotTheta->GetNumber()+360.);
   if (fRotTheta->GetNumber() >= 360.) fRotTheta->SetNumber(fRotTheta->GetNumber()-360.);
   DoModified();
}

//______________________________________________________________________________
void TGeoCombiTransEditor::DoRotPsi()
{
// Slot for psi (Euler X convention)
   if (fRotPsi->GetNumber() < 0.) fRotPsi->SetNumber(fRotPsi->GetNumber()+360.);
   if (fRotPsi->GetNumber() >= 360.) fRotPsi->SetNumber(fRotPsi->GetNumber()-360.);
   DoModified();
}

//______________________________________________________________________________
void TGeoCombiTransEditor::DoRotAngle()
{
// Slot for additional rotation about one axis.
   if (fRotAxis->GetNumber() < 0.) fRotAxis->SetNumber(fRotAxis->GetNumber()+360.);
   if (fRotAxis->GetNumber() >= 360.) fRotAxis->SetNumber(fRotAxis->GetNumber()-360.);
   DoModified();
}

//______________________________________________________________________________
Bool_t TGeoCombiTransEditor::DoParameters()
{
// Slot for checking parameters.
   Double_t dx = fTransDx->GetNumber();
   Double_t dy = fTransDy->GetNumber();
   Double_t dz = fTransDz->GetNumber();
   Bool_t changedtr = kFALSE;
   if (dx != fCombi->GetTranslation()[0] || 
       dy != fCombi->GetTranslation()[1] || 
       dz != fCombi->GetTranslation()[2]) changedtr = kTRUE;
   if (changedtr) fCombi->SetTranslation(dx, dy, dz);
   Double_t phi = fRotPhi->GetNumber();
   Double_t theta = fRotTheta->GetNumber();
   Double_t psi = fRotPsi->GetNumber();
   Double_t angle = fRotAxis->GetNumber();
   Double_t phi0 = 0., theta0 = 0., psi0 = 0.;
   TGeoRotation *rot = fCombi->GetRotation();
   if (rot) rot->GetAngles(phi0,theta0,psi0);
   else {
      if (phi!=fPhii || theta!=fThetai || psi!=fPsii) {
         TGeoRotation r("rot",10.,0.,0.);
         fCombi->SetRotation(r);
         rot = fCombi->GetRotation();
         rot->SetAngles(0.,0.,0.);
      }
   }      
   Bool_t changed = kFALSE;
   if (phi != psi0 || theta != theta0 || psi != psi0) changed = kTRUE;
   if (changed && rot) rot->SetAngles(phi, theta, psi);
   // Check if we have to rotate about one axis
   if (angle != 0.0) {
      if (fRotX->IsOn()) {fCombi->RotateX(angle); changed = kTRUE;}
      if (fRotY->IsOn()) {fCombi->RotateY(angle); changed = kTRUE;}
      if (fRotZ->IsOn()) {fCombi->RotateZ(angle); changed = kTRUE;}
   }
   if (changedtr) changed = kTRUE;   
   if (!changed) return kFALSE;   
   fRotAxis->SetNumber(0.0);
   fUndo->SetEnabled();
   if (fPad) {
      fPad->Modified();
      fPad->Update();
   }   
   return kTRUE;
}

//______________________________________________________________________________
void TGeoCombiTransEditor::DoApply()
{
// Slot for applying modifications.
   DoName();
   if (DoParameters()) {
      fUndo->SetEnabled();
      fCancel->SetEnabled(kFALSE);
      fApply->SetEnabled(kFALSE);
   }   
}

//______________________________________________________________________________
void TGeoCombiTransEditor::DoCancel()
{
// Slot for cancelling last un-applied operations.
   if (!fNamei.Length()) fRotName->SetText("no_name");
   else fRotName->SetText(fNamei.Data());
   fTransDx->SetNumber(fDxi);
   fTransDy->SetNumber(fDyi);
   fTransDz->SetNumber(fDzi);
   fRotPhi->SetNumber(fPhii);
   fRotTheta->SetNumber(fThetai);
   fRotPsi->SetNumber(fPsii);
   fRotAxis->SetNumber(0.0);
   fApply->SetEnabled(kFALSE);
   fUndo->SetEnabled(kFALSE);
   fCancel->SetEnabled(kFALSE);
}

//______________________________________________________________________________
void TGeoCombiTransEditor::DoModified()
{
// Slot for notifying changes.
   fApply->SetEnabled();
   if (fUndo->GetState()==kButtonDisabled) fCancel->SetEnabled();
}

//______________________________________________________________________________
void TGeoCombiTransEditor::DoUndo()
{
// Slot for undoing last changes.
   DoCancel();
   DoParameters();
   fCancel->SetEnabled(kFALSE);
   fUndo->SetEnabled(kFALSE);
   fApply->SetEnabled(kFALSE);
}
   
//______________________________________________________________________________
void TGeoCombiTransEditor::DoDx()
{
// Slot for X.
   DoModified();
}

//______________________________________________________________________________
void TGeoCombiTransEditor::DoDy()
{
// Slot for Y.
   DoModified();
}

//______________________________________________________________________________
void TGeoCombiTransEditor::DoDz()
{
// Slot for Z.
   DoModified();
}


Last change: Wed Jun 25 08:45:39 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.