// @(#)root/gui:$Name:  $:$Id: TGShutter.cxx,v 1.6 2003/11/05 13:08:26 rdm Exp $
// Author: Fons Rademakers   18/9/2000

/*************************************************************************
 * 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.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TGShutter, TGShutterItem                                             //
//                                                                      //
// A shutter widget contains a set of shutter items that can be         //
// open and closed like a shutter.                                      //
// This widget is usefull to group a large number of options in         //
// a number of categories.                                              //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TGShutter.h"
#include "TGButton.h"
#include "TList.h"
#include "TTimer.h"
#include "Riostream.h"


ClassImp(TGShutterItem)
ClassImp(TGShutter)

//______________________________________________________________________________
TGShutter::TGShutter(const TGWindow *p, UInt_t options) :
   TGCompositeFrame(p, 10, 10, options)
{
   // Create shutter frame.

   fSelectedItem        = 0;
   fClosingItem         = 0;
   fHeightIncrement     = 1;
   fClosingHeight       = 0;
   fClosingHadScrollbar = kFALSE;
   fTimer               = 0;
   fTrash               = new TList;
   fTrash->SetOwner();
}

//______________________________________________________________________________
TGShutter::~TGShutter()
{
   // Cleanup shutter widget.

   if (fTimer) delete fTimer;
   delete fTrash;
}

//______________________________________________________________________________
void TGShutter::AddItem(TGShutterItem *item)
{
   // Add shutter item to shutter frame.

   TGLayoutHints *hints = new TGLayoutHints(kLHintsExpandX | kLHintsExpandY);
   AddFrame(item, hints);
   fTrash->Add(hints);
   if (!fSelectedItem)
      fSelectedItem = item;
}

//______________________________________________________________________________
Bool_t TGShutter::ProcessMessage(Long_t /*msg*/, Long_t parm1, Long_t /*parm2*/)
{
   // Handle shutter messages.

   if (!fList) return kFALSE;

   TGFrameElement *el;
   TGShutterItem  *child, *item = 0;

   TIter next(fList);
   while ((el = (TGFrameElement *) next())) {
      child = (TGShutterItem *) el->fFrame;
      if (parm1 == child->WidgetId()) {
         item = child;
         break;
      }
   }

   if (!item) return kFALSE;

   if (!fSelectedItem)
      fSelectedItem = (TGShutterItem*) ((TGFrameElement*)fList->First())->fFrame;
   if (fSelectedItem == item) return kTRUE;

   fHeightIncrement = 1;
   fClosingItem = fSelectedItem;
   fClosingHeight = fClosingItem->GetHeight();
   fClosingHeight -= fClosingItem->fButton->GetDefaultHeight();
   fSelectedItem = item;
   if (!fTimer) fTimer = new TTimer(this, 6); //10);
   fTimer->Reset();
   fTimer->TurnOn();

   return kTRUE;
}

//______________________________________________________________________________
Bool_t TGShutter::HandleTimer(TTimer *)
{
   // Shutter item animation.

   if (!fClosingItem) return kFALSE;
   fClosingHeight -= fHeightIncrement;
   fHeightIncrement += 5;
   if (fClosingHeight > 0) {
      fTimer->Reset();
   } else {
      fClosingItem   = 0;
      fClosingHeight = 0;
      fTimer->TurnOff();
   }
   Layout();

   return kTRUE;
}

//______________________________________________________________________________
void TGShutter::Layout()
{
   // Layout shutter items.

   TGFrameElement *el;
   TGShutterItem  *child;
   Int_t y, bh, exh;

   if (!fList) return;

   if (!fSelectedItem)
      fSelectedItem = (TGShutterItem*) ((TGFrameElement*)GetList()->First())->fFrame;

   exh = Int_t(fHeight - (fBorderWidth << 1));
   TIter next(fList);
   while ((el = (TGFrameElement *) next())) {
      child = (TGShutterItem *) el->fFrame;
      bh = child->fButton->GetDefaultHeight();
      exh -= bh;
   }

   y = fBorderWidth;
   next.Reset();
   while ((el = (TGFrameElement *) next())) {
      child = (TGShutterItem *) el->fFrame;
      bh = child->fButton->GetDefaultHeight();
      if (child == fSelectedItem) {
         if (fClosingItem)
            child->fCanvas->SetScrolling(TGCanvas::kCanvasNoScroll);
         else
            child->fCanvas->SetScrolling(TGCanvas::kCanvasScrollVertical);
         child->ShowFrame(child->fCanvas);
         child->MoveResize(fBorderWidth, y, fWidth - (fBorderWidth << 1),
                           exh - fClosingHeight + bh);
         y += exh - fClosingHeight + bh;
      } else if (child == fClosingItem) {
         child->fCanvas->SetScrolling(TGCanvas::kCanvasNoScroll);
         child->MoveResize(fBorderWidth, y, fWidth - (fBorderWidth << 1),
                           fClosingHeight + bh);
         y += fClosingHeight + bh;
      } else {
         child->MoveResize(fBorderWidth, y, fWidth - (fBorderWidth << 1), bh);
         child->HideFrame(child->fCanvas);
         y += bh;
      }
   }
}

//______________________________________________________________________________
void TGShutter::SetSelectedItem(TGShutterItem *item)
{
   // Set item to be the currently open shutter item.

   fSelectedItem = item;
   Layout();
}

//______________________________________________________________________________
TGShutterItem::TGShutterItem(const TGWindow *p, TGHotString *s, Int_t id,
                             UInt_t options) :
   TGVerticalFrame (p, 10, 10, options), TGWidget (id)
{
   // Create a shutter item.

   fButton = new TGTextButton(this, s, id);
   fCanvas = new TGCanvas(this, 10, 10, kChildFrame);
   fContainer = new TGVerticalFrame(fCanvas->GetViewPort(), 10, 10, kOwnBackground);
   fCanvas->SetContainer(fContainer);
   fContainer->SetBackgroundColor(fClient->GetShadow(GetDefaultFrameBackground()));

   AddFrame(fButton, fL1 = new TGLayoutHints(kLHintsTop | kLHintsExpandX));
   AddFrame(fCanvas, fL2 = new TGLayoutHints(kLHintsExpandY | kLHintsExpandX));

   fButton->Associate((TGFrame *) p);
}

//______________________________________________________________________________
TGShutterItem::~TGShutterItem()
{
   // Clan up shutter item.

   delete fL1;
   delete fL2;
   delete fButton;
   delete fContainer;
   delete fCanvas;
}

//______________________________________________________________________________
void TGShutterItem::SavePrimitive(ofstream &out, Option_t *option)
{
    // Save a shutter item widget as a C++ statement(s) on output stream out

   char quote = '"';
   TGTextButton *b = (TGTextButton *)fButton;
   const char *text = b->GetText()->GetString();
   char hotpos = b->GetText()->GetHotPos();
   Int_t lentext = b->GetText()->GetLength();
   char *outext = new char[lentext+2];       // should be +2 because of \0
   Int_t i=0;


   while (lentext) {
      if (i == hotpos-1) {
         outext[i] = '&';
         i++;
      }
      outext[i] = *text;
      i++;
      text++;
      lentext--;
   }
   outext[i]=0;

   out << endl;
   out << "   // " << quote << outext << quote << " shutter item " << endl;
   out << "   TGShutterItem *";
   out << GetName() << " = new TGShutterItem(" << fParent->GetName()
       << ", new TGHotString(" << quote << outext << quote << "),"
       << fButton->WidgetId() << "," << GetOptionString() << ");" << endl;

   delete [] outext;

   TList *List = ((TGCompositeFrame *)GetContainer())->GetList();

   if (!List) return;

   out << "   TGCompositeFrame *" << GetContainer()->GetName()
       << " = (TGCompositeFrame *)" << GetName() << "->GetContainer();" << endl;

   TGFrameElement *el;
   TIter next(List);

   while ((el = (TGFrameElement *) next())) {
      el->fFrame->SavePrimitive(out, option);
      out << "   " << GetContainer()->GetName() <<"->AddFrame(" << el->fFrame->GetName();
      el->fLayout->SavePrimitive(out, option);
      out << ");"<< endl;
   }
}

//______________________________________________________________________________
void TGShutter::SavePrimitive(ofstream &out, Option_t *option)
{
    // Save a shutter widget as a C++ statement(s) on output stream out.

   out << endl;
   out << "   // shutter" << endl;

   out << "   TGShutter *";
   out << GetName() << " = new TGShutter(" << fParent->GetName() << ","
       << GetOptionString() << ");" << endl;

   if (!fList) return;

   TGFrameElement *el;
   TIter next(fList);

   while ((el = (TGFrameElement *) next())) {
      el->fFrame->SavePrimitive(out, option);
      out << "   " << GetName() <<"->AddItem(" << el->fFrame->GetName();
      //el->fLayout->SavePrimitive(out, option);
      out << ");"<< endl;
   }

   out << "   " << GetName() << "->SetSelectedItem("
       << GetSelectedItem()->GetName() << ");" << endl;
   out << "   " <<GetName()<< "->Resize("<<GetWidth()<<","<<GetHeight()<<");"<<endl;

}

