    // @(#)root/ged:$Name:  $:$Id: TGedEditor.cxx,v 1.8 2004/06/25 17:13:23 brun Exp $
    // Author: Marek Biskup, Ilka Antcheva 02/08/2003

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

    //////////////////////////////////////////////////////////////////////////
    //                                                                      //
    // TGedEditor                                                           //
    //                                                                      //
    // Editor is a composite frame that contains TGedToolBox and            //
    // TGedAttFrames. It is connected to a Canvas and listens for           //
    // selected objects                                                     //
    //                                                                      //
    //////////////////////////////////////////////////////////////////////////

    #include "TGedEditor.h"
    #include "TCanvas.h"
    #include "TGTab.h"
    #include "TGedFrame.h"
    #include "TGLabel.h"
    #include "TGFrame.h"
    #include "TBaseClass.h"
    #include "TSystem.h"

    ClassImp(TGedFrame)
    ClassImp(TGedEditor)

    //______________________________________________________________________________
     TGedEditor::TGedEditor(TCanvas* canvas) :
       TGMainFrame(gClient->GetRoot(), 110, 20)
    {

       fTab = new TGTab(this, 110, 30);
       AddFrame(fTab, new TGLayoutHints(kLHintsTop | kLHintsExpandX, 0, 0, 2, 2));
       fTabContainer = fTab->AddTab("Style");
       fStyle = new TGCompositeFrame(fTabContainer, 110, 30, kVerticalFrame);
       fStyle->AddFrame(new TGedNameFrame(fStyle, 1),\
                        new TGLayoutHints(kLHintsTop | kLHintsExpandX,0, 0, 2, 2));
       fTabContainer->AddFrame(fStyle, new TGLayoutHints(kLHintsTop | kLHintsExpandX,\
                                                         0, 0, 2, 2));
       fWid = 1;

       if (canvas) {
          fModel  = (TObject *)canvas->GetSelected();
          fPad    = canvas->GetSelectedPad();
          fCanvas = canvas;
          fClass  = fModel->IsA();
          GetEditors();
          ConnectToCanvas(canvas);
       } else {
          fModel  = 0;
          fPad    = 0;
          fCanvas = 0;
          fClass  = 0;
       }

       MapSubwindows();
       Resize(GetDefaultSize());
       MapWindow();
       Resize(GetWidth(), canvas->GetWh());
    }

    //______________________________________________________________________________
     void TGedEditor::CloseWindow()
    {
       // When closed via WM close button, just unmap (i.e. hide) editor
       // for later use.

       Hide();
    }

    //______________________________________________________________________________
     void TGedEditor::GetEditors()
    {
       // Get existing editors of selected object

       fStyle->SetEditable(1);

       // Look in TClass::GetEditorList() for any object deriving from TGedFrame,
       Bool_t found = kFALSE;
       TGedElement *ge;
       TList *list = fModel->IsA()->GetEditorList();
       if (list->First() != 0) {

          TIter next1(list);
          while ((ge = (TGedElement *) next1())) {
             // check if the editor ge->fGedframe is already in the list of fStyle
             TList *l = fStyle->GetList();
             if (l->First() != 0) {
                TGFrameElement *fr;
                TIter next(l);
                while ((fr = (TGFrameElement *) next())) {
                   TGedFrame *f = ge->fGedFrame;
                   found = fr->fFrame->InheritsFrom(f->ClassName());
                   if (found) break;
                }
             }
             if (found == kFALSE)
                fStyle->AddFrame(ge->fGedFrame, new TGLayoutHints(kLHintsTop | kLHintsExpandX,\
                                                   0, 0, 2, 2));
          }
       } else {

          //search for a class editor = classname + 'Editor'
           GetClassEditor(fModel->IsA());

          //now scan all base classes
          list = fModel->IsA()->GetListOfBases();
          if (list->First() != 0) GetBaseClassEditor(fModel->IsA());
       }

       fStyle->SetEditable(0);
       fStyle->Layout();
       fStyle->MapSubwindows();
    }

    //______________________________________________________________________________
     void TGedEditor::GetBaseClassEditor(TClass *cl)
    {
       // Scan the base classes of cl and add attribute editors to the list.

       TList *list = cl->GetListOfBases();
       if (list->First() == 0) return;

       TBaseClass *base;
       TIter next(list);

       while ((base = (TBaseClass *)next())) {

          TClass *c1;
          if ((c1 = base->GetClassPointer())) GetClassEditor(c1);

          if (c1->GetListOfBases()->First() == 0) continue;
          else GetBaseClassEditor(c1);
       }
    }

    //______________________________________________________________________________
     void TGedEditor::GetClassEditor(TClass *cl)
    {
       // Add attribute editor of class cl to the list of fStyle frame.

       TClass *class2, *class3;
       Bool_t found = kFALSE;
       class2 = gROOT->GetClass(Form("%sEditor",cl->GetName()));
       if (class2 && class2->InheritsFrom("TGedFrame")) {
          TList *list = fStyle->GetList();
          if (list->First() != 0) {
             TGFrameElement *fr;
             TIter next(list);
             while ((fr = (TGFrameElement *) next())) {;
                found = fr->fFrame->InheritsFrom(class2);
                if (found) break;
             }
          }
          if (found == kFALSE) {
             gROOT->ProcessLine(Form("((TGCompositeFrame *)0x%lx)->AddFrame(new %s((TGWindow *)0x%lx, %d),\
                                     new TGLayoutHints(kLHintsTop | kLHintsExpandX,0, 0, 2, 2))",\
                                     (Long_t)fStyle, class2->GetName(), (Long_t)fStyle, fWid));
             fWid++;
             class3 = (TClass*)gROOT->GetListOfClasses()->FindObject(cl->GetName());
             TGedElement *ge;
             TIter next3(class3->GetEditorList());
             while ((ge = (TGedElement *)next3())) {
                if (!strcmp(ge->fGedFrame->ClassName(), class2->GetName()) && (ge->fCanvas == 0)) {
                   ge->fCanvas = fCanvas;
                }
             }
          }
       }
    }

    //______________________________________________________________________________
     void TGedEditor::ConnectToCanvas(TCanvas *c)
    {

       TQObject::Connect(c, "Selected(TVirtualPad*,TObject*,Int_t)", "TGedEditor",
                         this, "SetModel(TVirtualPad*,TObject*,Int_t)");
       c->Selected(c->GetSelectedPad(), c->GetSelected(), c->GetEvent());
    }

    //______________________________________________________________________________
     void TGedEditor::SetModel(TVirtualPad* pad, TObject* obj, Int_t event)
    {
       fModel = obj;
       fPad   = pad;

       if ((obj->IsA() != fClass) && !obj->IsA()->InheritsFrom(fClass)) {
          fClass = obj->IsA();
          GetEditors();
       }

       TGFrameElement *el;
       TIter next(fStyle->GetList());
       while ((el = (TGFrameElement *) next())) {
          if ((el->fFrame)->InheritsFrom("TGedFrame"))
             ((TGedFrame *)(el->fFrame))->SetModel(pad, obj, event);
       }
    }

    //______________________________________________________________________________
     void TGedEditor::Show()
    {
       // Show editor.

       MapWindow();
    }

    //______________________________________________________________________________
     void TGedEditor::DeleteEditors()
    {
       // Delete GUI editors connected to the canvas fCanvas.

       TClass * cl;
       TIter next(gROOT->GetListOfClasses());
       while((cl = (TClass *)next())) {
          if (cl->GetEditorList()->First() != 0) {
             TList *editors = cl->GetEditorList();
             TIter next1(editors);
             TGedElement *ge;
             while ((ge = (TGedElement *)next1())) {
                if (ge->fCanvas == fCanvas) {
                   editors->Remove(ge);
                }
             }
          }
       }
    }
    //______________________________________________________________________________
     void TGedEditor::Hide()
    {
       // Hide editor.

       UnmapWindow();
    }

    //______________________________________________________________________________
     TGedEditor::~TGedEditor()
    {
      // Editor destructor.

      fStyle->Cleanup();
      Cleanup();
    }

    //______________________________________________________________________________
      void TGedEditor::RecursiveRemove(TObject* obj)
    {
       // Remove references to fModel in case the fModel is being deleted
       // Deactivate attribute frames if they point to obj

       if (fModel != obj ) return;
       SetModel(fPad,0,0);
    }