		/* This file is part of the KDE project
   Copyright (C) 2002 Christoph Cullmann <cullmann@kde.org>
   Copyright (C) 2002,2003 Joseph Wenninger <jowenn@kde.org>

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License version 2 as published by the Free Software Foundation.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.
*/

#include <qwidgetstack.h>
#include <qlayout.h>
#include <qtimer.h>
#include <qtooltip.h>
#include <kmultitabbar.h>

#ifdef NO_KDE
#include "kmdidummy.h"
#include "qapplication.h"
#else
#include <kdebug.h>
#include <kiconloader.h>
#include <kapplication.h>
#include <kconfig.h>
#include <klocale.h>
#endif

#include "kmdimainfrm.h"
#include "kmdidockcontainer.h"

static const char* const not_close_xpm[]={
"5 5 2 1",
"# c black",
". c None",
"#####",
"#...#",
"#...#",
"#...#",
"#####"};

/* THIS IS GOING TO BE REMOVED ONCE THAT CONTAINER IS IN KDELIBS. It's a copy of a private header
*/
class KDockButton_Private : public QPushButton
{
  Q_OBJECT
public:
  KDockButton_Private( QWidget *parent=0, const char *name=0 );
  ~KDockButton_Private();

protected:
  virtual void drawButton( QPainter * );
  virtual void enterEvent( QEvent * );
  virtual void leaveEvent( QEvent * );

private:
  bool moveMouse;
};

KMdiDockContainer::KMdiDockContainer(QWidget *parent, QWidget *win, int position, int flags)
: QWidget(parent),KMdiDockContainerBase()
{
  m_block=false;
  m_inserted=-1;
  m_mainWin = win;
  oldtab=-1;
  mTabCnt=0;
  m_position = position;
  m_previousTab=-1;

  kdDebug(760)<<"KMdiDockContainer created"<<endl;

  QBoxLayout *l;
  m_vertical=!((position==KDockWidget::DockTop) || (position==KDockWidget::DockBottom));

  if (!m_vertical)
    l=new QVBoxLayout(this);
  else
    l=new QHBoxLayout(this);

  l->setAutoAdd(false);

  m_tb=new KMultiTabBar(((position==KDockWidget::DockTop) || (position==KDockWidget::DockBottom))?
    KMultiTabBar::Horizontal:KMultiTabBar::Vertical,this);

  m_tb->setStyle(KMultiTabBar::KMultiTabBarStyle(flags));
  m_tb->showActiveTabTexts(true);

  m_tb->setPosition((position==KDockWidget::DockLeft)?KMultiTabBar::Left:
    (position==KDockWidget::DockBottom)?KMultiTabBar::Bottom:
    (position==KDockWidget::DockTop)?KMultiTabBar::Top:KMultiTabBar::Right);

  m_ws=new QWidgetStack(this);

  m_ws->setSizePolicy(QSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding));

  if ( (position==KDockWidget::DockLeft) || (position==KDockWidget::DockTop))
  {
    l->add(m_tb);
    l->add(m_ws);
  }
  else
  {
    l->add(m_ws);
    l->add(m_tb);
  }

  l->activate();
  m_ws->hide();

}

KMdiDockContainer::~KMdiDockContainer()
{	
  QMap<KMdiDockWidget*,int>::iterator it;
  while (m_map.count()) {
	it = m_map.begin();
	KMdiDockWidget *w=it.key();
	  if (m_overlapButtons.contains(w)) {
	    (static_cast<KDockWidgetHeader*>(w->getHeader()->qt_cast("KDockWidget_Compat::KDockWidgetHeader")))->removeButton(m_overlapButtons[w]);
	    m_overlapButtons.remove(w);
	  }
    m_map.remove(w);
    w->undock();
  }
	deactivated(this);
}


void KMdiDockContainer::init()
{
  if (m_vertical)
  {
    parentDockWidget()->setForcedFixedWidth(m_tb->width());
    activateOverlapMode(m_tb->width());
  }
  else
  {
    parentDockWidget()->setForcedFixedHeight(m_tb->height());
    activateOverlapMode(m_tb->height());
  }
}

KDockWidget *KMdiDockContainer::parentDockWidget()
{
  return (KDockWidget*)parent();
}

void KMdiDockContainer::insertWidget (KDockWidget *dwdg, QPixmap pixmap, const QString &text, int &)
{
  KMdiDockWidget* w = (KMdiDockWidget*) dwdg;
  int tab;
  bool alreadyThere=m_map.contains(w);

  if (alreadyThere)
  {
    tab=m_map[w];
    if (m_ws->addWidget(w,tab)!=tab) kdDebug(760)<<"ERROR COULDN'T READD WIDGET************"<<endl;
    kdDebug(760)<<"READDED WIDGET***********************************"<<endl;
/*JOWENN    m_tb->setTab(tab,true);
    tabClicked(tab);*/
  }
  else
  {
    tab=m_ws->addWidget(w);
    m_map.insert(w,tab);
    m_revMap.insert(tab,w);

    if (((KDockWidget*)parentWidget())->mayBeShow())
      ((KDockWidget*)parentWidget())->dockBack();

    if (w->getHeader()->qt_cast("KDockWidget_Compat::KDockWidgetHeader"))
    {
      kdDebug(760)<<"*** KDockWidgetHeader has been found"<<endl;

      KDockWidgetHeader *hdr=static_cast<KDockWidgetHeader*>(w->getHeader()->
        qt_cast("KDockWidget_Compat::KDockWidgetHeader"));

      KDockButton_Private *btn = new KDockButton_Private( hdr, "OverlapButton" );

      QToolTip::add( btn, i18n("Switch between overlap and side by side mode", "Overlap") );

      btn->setToggleButton( true );
      btn->setPixmap( const_cast< const char** >(not_close_xpm) );
      hdr->addButton(btn);
      m_overlapButtons.insert(w,btn);
      btn->setOn(!isOverlapMode());

      connect(btn,SIGNAL(clicked()),this,SLOT(changeOverlapMode()));
    }

    m_tb->appendTab(pixmap.isNull()?SmallIcon("misc"):pixmap,tab,w->tabPageLabel());

    kdDebug(760)<<"NAMENAMENAMENAME:===========================:"<<w->tabPageLabel()<<endl;

//FB    m_tb->setTab(tab,true);

    connect(m_tb->tab(tab),SIGNAL(clicked(int)),this,SLOT(tabClicked(int)));

    kdDebug(760)<<"KMdiDockContainer::insertWidget()"<<endl;

//FB    m_tb->setTab(oldtab,false);

    mTabCnt++;
    m_inserted=tab;
    int dummy=0;
//FB    tabClicked(tab);
    KDockContainer::insertWidget(w,pixmap,text,dummy);
    itemNames.append(w->name());
    tabCaptions.insert(w->name(),w->tabPageLabel());
    tabTooltips.insert(w->name(),w->toolTipString());
  }

//FB  m_ws->raiseWidget(tab);
}

void KMdiDockContainer::showWidget(KDockWidget *w) {
	if (!m_map.contains((KMdiDockWidget*)w)) return;
	int id=m_map[(KMdiDockWidget*)w];
	m_tb->setTab(id,true);
	tabClicked(id);
}

void KMdiDockContainer::changeOverlapMode()
{
  const KDockButton_Private *btn=dynamic_cast<const KDockButton_Private*>(sender());

  kdDebug(760)<<"KMdiDockContainer::changeOverlapMode: button=="<<btn<<endl;

  if (!btn) return;

  if (!btn->isOn()) {
    kdDebug(760)<<"KMdiDockContainer::changeOverlapMode: activateOverlapMode"<<endl;
    if (m_vertical) {
      activateOverlapMode(m_tb->width());
    }
    else
    {
      activateOverlapMode(m_tb->height());
    }
  } else {
    kdDebug(760)<<"KMdiDockContainer::changeOverlapMode: deactivateOverlapMode"<<endl;
    deactivateOverlapMode();
  }

	for (QMap<KMdiDockWidget*,KDockButton_Private*>::iterator it=m_overlapButtons.begin();
    it!=m_overlapButtons.end();++it)
    it.data()->setOn(!isOverlapMode());
}

void KMdiDockContainer::hideIfNeeded() {
  kdDebug(760)<<"************************* hideIfNeeded *************************"<<endl;
  if (!itemNames.count())
    ((KDockWidget*)parentWidget())->undock();
}

void KMdiDockContainer::removeWidget(KDockWidget* dwdg)
{
    KMdiDockWidget* w = (KMdiDockWidget*) dwdg;
  if (!m_map.contains(w)) return;
  int id=m_map[w];
  m_tb->setTab(id,false);
  tabClicked(id);
  m_tb->removeTab(id);
  m_ws->removeWidget(w);
  m_map.remove(w);
  m_revMap.remove(id);
  if (m_overlapButtons.contains(w)) {
    (static_cast<KDockWidgetHeader*>(w->getHeader()->qt_cast("KDockWidget_Compat::KDockWidgetHeader")))->removeButton(m_overlapButtons[w]);
    m_overlapButtons.remove(w);
  }
  KDockContainer::removeWidget(w);
  itemNames.remove(w->name());
  tabCaptions.remove(w->name());
  tabTooltips.remove(w->name());
  if (!itemNames.count())
    ((KDockWidget*)parentWidget())->undock();
}

void KMdiDockContainer::undockWidget(KDockWidget *dwdg)
{
    KMdiDockWidget* w = (KMdiDockWidget*) dwdg;

  if (!m_map.contains(w))
    return;

  kdDebug(760)<<"Wiget has been undocked, setting tab down"<<endl;
  int id=m_map[w];
  m_tb->setTab(id,false);
  tabClicked(id);
}

void KMdiDockContainer::tabClicked(int t)
{
  kdDebug(760)<<"KMdiDockContainer::tabClicked()"<<endl;
  bool call_makeVisible=!m_tabSwitching;
  m_tabSwitching=true;
  if (m_tb->isTabRaised(t))
  {

    if (m_ws->isHidden())
    {
       m_ws->show ();
       parentDockWidget()->restoreFromForcedFixedSize();
    }
      if (!m_ws->widget(t))
    {
      m_revMap[t]->manualDock(parentDockWidget(),KDockWidget::DockCenter,20);
      if (call_makeVisible) m_revMap[t]->makeDockVisible();//manualDock(parentDockWidget(),KDockWidget::DockCenter,20);
      m_tabSwitching=false;
      emit activated(this);
      return;
    }
    m_ws->raiseWidget(t);
    if (m_ws->widget(t)) {
      KDockWidget *tmpDw=static_cast<KDockWidget*>(m_ws->widget(t)->qt_cast("KDockWidget_Compat::KDockWidget"));
      if (tmpDw) {
        if (tmpDw->getWidget()) tmpDw->getWidget()->setFocus();
      } else kdDebug(760)<<"Something really weird is going on"<<endl;
    } else
      kdDebug(760)<<"KMdiDockContainer::tabClicked(int): m_ws->widget(t)==0 "<<endl;

    if (oldtab!=t) m_tb->setTab(oldtab,false);
    m_tabSwitching=true;
    oldtab=t;
    emit activated(this);
  }
  else
  {
    m_previousTab=t;
//    oldtab=-1;
    if (m_block) return;
    emit deactivated(this);
    m_block=true;
    if (m_ws->widget(t))
    {
//    ((KDockWidget*)m_ws->widget(t))->undock();
    }
    m_block=false;
    m_ws->hide ();
  kdDebug(760)<<"Fixed Width:"<<m_tb->width()<<endl;
  if (m_vertical)
  parentDockWidget()->setForcedFixedWidth(m_tb->width()+2); // strange why it worked before at all
  else
  parentDockWidget()->setForcedFixedHeight(m_tb->height()+2); // strange why it worked before at all
   }
  m_tabSwitching=false;
}

void KMdiDockContainer::setToolTip (KDockWidget *, QString &s)
{
  kdDebug(760)<<"***********************************Setting tooltip for a widget: "<<s<<endl;
}

void KMdiDockContainer::setPixmap(KDockWidget* widget ,const QPixmap& pixmap)
{
  int id=m_ws->id(widget);
  if (id==-1) return;
  KMultiTabBarTab *tab=m_tb->tab(id);
  tab->setIcon(pixmap.isNull()?SmallIcon("misc"):pixmap);
}

void KMdiDockContainer::save(QDomElement& dockEl)
{
	QDomDocument doc=dockEl.ownerDocument();
	QDomElement el;
	el=doc.createElement("name");
	el.appendChild(doc.createTextNode(QString("%1").arg(parent()->name())));
	dockEl.appendChild(el);
	el=doc.createElement("overlapMode");
	el.appendChild(doc.createTextNode(isOverlapMode() ?"true":"false"));
	dockEl.appendChild(el);
	QPtrList<KMultiTabBarTab>* tl=m_tb->tabs();
	QPtrListIterator<KMultiTabBarTab> it(*tl);
	QStringList::Iterator it2=itemNames.begin();
	int i=0;
	for (;it.current()!=0;++it,++it2)
	{
		el=doc.createElement("child");
		el.setAttribute("pos",QString("%1").arg(i));
		QString s=tabCaptions[*it2];
		if (!s.isEmpty()) {
			el.setAttribute("tabCaption",s);
		}
		s=tabTooltips[*it2];
		if (!s.isEmpty()) {
			el.setAttribute("tabTooltip",s);
		}
		el.appendChild(doc.createTextNode(*it2));
		dockEl.appendChild(el);
		if (m_tb->isTabRaised(it.current()->id()))
		{
			QDomElement el2=doc.createElement("raised");
			el2.appendChild(doc.createTextNode(m_ws->widget(it.current()->id())->name()));
			el.appendChild(el2);
		}
		++i;
	}


}

void KMdiDockContainer::load(QDomElement& dockEl)
{
  QString raise;

	for (QDomNode n=dockEl.firstChild();!n.isNull();n=n.nextSibling()) {
		QDomElement el=n.toElement();
		if (el.isNull()) continue;
		if (el.tagName()=="overlapMode") {
			if (el.attribute("overlapMode")!="false")
				activateOverlapMode(m_tb->width());
			else
				deactivateOverlapMode();
		} else if (el.tagName()=="child") {
			KDockWidget *dw=((KDockWidget*)parent())->dockManager()->getDockWidgetFromName(el.text());
			if (dw)
			{
				if (el.hasAttribute("tabCaption")) {
					dw->setTabPageLabel(el.attribute("tabCaption"));
				}
				if (el.hasAttribute("tabTooltip")) {
					dw->setToolTipString(el.attribute("tabTooltip"));
				}
				dw->manualDock((KDockWidget*)parent(),KDockWidget::DockCenter);
			}
		}
	}


  QPtrList<KMultiTabBarTab>* tl=m_tb->tabs();
  QPtrListIterator<KMultiTabBarTab> it1(*tl);
  m_ws->hide();
  if (m_vertical)
  parentDockWidget()->setForcedFixedWidth(m_tb->width());
  else
  parentDockWidget()->setForcedFixedHeight(m_tb->height());
  for (;it1.current()!=0;++it1)
  {
    m_tb->setTab(it1.current()->id(),false);
  }
#ifdef NO_KDE
  qApp->syncX();
#else
  kapp->syncX();
#endif
  m_delayedRaise=-1;

  for (QMap<KMdiDockWidget*,KDockButton_Private*>::iterator it=m_overlapButtons.begin();
    it!=m_overlapButtons.end();++it)
    it.data()->setOn(!isOverlapMode());

  if (!raise.isEmpty())
  {
    for (QMap<KMdiDockWidget*,int>::iterator it=m_map.begin();it!=m_map.end();++it)
    {
      if (it.key()->name()==raise)
      {
        m_delayedRaise=it.data();
        QTimer::singleShot(0,this,SLOT(delayedRaise()));
        kdDebug(760)<<"************** raising *******: "<<it.key()->name()<<endl;
        break;
      }
    }

  }
  if (m_delayedRaise==-1)   QTimer::singleShot(0,this,SLOT(init()));




}

#ifndef NO_KDE
void KMdiDockContainer::save(KConfig* cfg,const QString& group_or_prefix)
{
  QString grp=cfg->group();
  cfg->deleteGroup(group_or_prefix+QString("::%1").arg(parent()->name()));
  cfg->setGroup(group_or_prefix+QString("::%1").arg(parent()->name()));

  if (isOverlapMode()) cfg->writeEntry("overlapMode","true");
    else cfg->writeEntry("overlapMode","false");

  QPtrList<KMultiTabBarTab>* tl=m_tb->tabs();
  QPtrListIterator<KMultiTabBarTab> it(*tl);
  QStringList::Iterator it2=itemNames.begin();
  int i=0;
  for (;it.current()!=0;++it,++it2)
  {
//    cfg->writeEntry(QString("widget%1").arg(i),m_ws->widget(it.current()->id())->name());
    cfg->writeEntry(QString("widget%1").arg(i),(*it2));
    QString s=tabCaptions[*it2];
    if (!s.isEmpty()) {
      cfg->writeEntry(QString("widget%1-tabCaption").arg(i),s);
    }
    s=tabTooltips[*it2];
    if (!s.isEmpty()) {
      cfg->writeEntry(QString("widget%1-tabTooltip").arg(i),s);
    }
//    kdDebug(760)<<"****************************************Saving: "<<m_ws->widget(it.current()->id())->name()<<endl;
    if (m_tb->isTabRaised(it.current()->id()))
      cfg->writeEntry(m_ws->widget(it.current()->id())->name(),true);
  ++i;
  }
  cfg->sync();
  cfg->setGroup(grp);

}

void KMdiDockContainer::load(KConfig* cfg,const QString& group_or_prefix)
{
  QString grp=cfg->group();
  cfg->setGroup(group_or_prefix+QString("::%1").arg(parent()->name()));

  if (cfg->readEntry("overlapMode")!="false")
    activateOverlapMode(m_tb->width());
  else
    deactivateOverlapMode();


  int i=0;
  QString raise;
  while (true)
  {
    QString dwn=cfg->readEntry(QString("widget%1").arg(i));
    if (dwn.isEmpty()) break;
    kdDebug(760)<<"*************************************************************Configuring dockwidget :"<<dwn<<endl;
    KDockWidget *dw=((KDockWidget*)parent())->dockManager()->getDockWidgetFromName(dwn);
    if (dw)
    {
      QString s=cfg->readEntry(QString("widget%1-tabCaption").arg(i));
      if (!s.isEmpty()) {
        dw->setTabPageLabel(s);
      }
      s=cfg->readEntry(QString("widget%1-tabTooltip").arg(i));
      if (!s.isEmpty()) {
        dw->setToolTipString(s);
      }
      dw->manualDock((KDockWidget*)parent(),KDockWidget::DockCenter);
    }
    if (cfg->readBoolEntry(dwn,false)) raise=dwn;
    i++;

  }

  QPtrList<KMultiTabBarTab>* tl=m_tb->tabs();
  QPtrListIterator<KMultiTabBarTab> it1(*tl);
  m_ws->hide();
  if (m_vertical)
  parentDockWidget()->setForcedFixedWidth(m_tb->width());
  else
  parentDockWidget()->setForcedFixedHeight(m_tb->height());
  for (;it1.current()!=0;++it1)
  {
    m_tb->setTab(it1.current()->id(),false);
  }
  kapp->syncX();
  m_delayedRaise=-1;

  for (QMap<KMdiDockWidget* ,KDockButton_Private*>::iterator it=m_overlapButtons.begin();
    it!=m_overlapButtons.end();++it)
    it.data()->setOn(!isOverlapMode());

  if (!raise.isEmpty())
  {
    for (QMap<KMdiDockWidget*,int>::iterator it=m_map.begin();it!=m_map.end();++it)
    {
      if (it.key()->name()==raise)
      {
/*        tabClicked(it.data());
        m_tb->setTab(it.data(),true);
        tabClicked(it.data());
        m_ws->raiseWidget(it.key());
        kapp->sendPostedEvents();
        kapp->syncX();*/

        m_delayedRaise=it.data();
        QTimer::singleShot(0,this,SLOT(delayedRaise()));
        kdDebug(760)<<"************** raising *******: "<<it.key()->name()<<endl;
        break;
      }
    }

  }
  if (m_delayedRaise==-1)   QTimer::singleShot(0,this,SLOT(init()));
  cfg->setGroup(grp);

}
#endif

void KMdiDockContainer::delayedRaise()
{
        m_tb->setTab(m_delayedRaise,true);
        tabClicked(m_delayedRaise);
}

void KMdiDockContainer::collapseOverlapped()
{
  if (m_tabSwitching) return;
  if (isOverlapMode()){
    QPtrList<KMultiTabBarTab>* tl=m_tb->tabs();
          QPtrListIterator<KMultiTabBarTab> it(*tl);
    for(;it.current();++it) {
      if (it.current()->isOn()) {
        kdDebug(760)<<"Lowering TAB"<<endl;
        it.current()->setState(false);
        tabClicked(it.current()->id());
      }
    }
  }
}

void KMdiDockContainer::toggle() {
	kdDebug(760)<<"DockContainer:activate"<<endl;
	if (m_tb->isTabRaised(oldtab)) {
		m_tb->setTab(oldtab,false);
	    	tabClicked(oldtab);
            KMdiMainFrm *mainFrm = dynamic_cast<KMdiMainFrm*>(m_mainWin);
            if (mainFrm)
                mainFrm->activeWindow()->setFocus();
	} else {
		kdDebug(760)<<"KMdiDockContainer::toggle(): raising tab"<<endl;
		if (m_tb->tab(m_previousTab)==0) {
			if (m_tb->tabs()->count()==0) return;
			m_previousTab=m_tb->tabs()->getFirst()->id();
		}
		m_tb->setTab(m_previousTab,true);
	    	tabClicked(m_previousTab);
	}
}

void KMdiDockContainer::prevToolView() {
	QPtrList<KMultiTabBarTab>* tabs=m_tb->tabs();
	int pos=tabs->findRef(m_tb->tab(oldtab));
	if (pos==-1) return;
	pos--;
	if (pos<0) pos=tabs->count()-1;
	KMultiTabBarTab *tab=tabs->at(pos);
	if (!tab) return; //can never happen here, but who knows
	m_tb->setTab(tab->id(),true);
	tabClicked(tab->id());
}

void KMdiDockContainer::nextToolView() {
	QPtrList<KMultiTabBarTab>* tabs=m_tb->tabs();
	int pos=tabs->findRef(m_tb->tab(oldtab));
	if (pos==-1) return;
	pos++;
	if (pos>=(int)tabs->count()) pos=0;
	KMultiTabBarTab *tab=tabs->at(pos);
	if (!tab) return; //can never happen here, but who knows
	m_tb->setTab(tab->id(),true);
	tabClicked(tab->id());
}

#ifndef NO_INCLUDE_MOCFILES
#include "kmdidockcontainer.moc"
#endif
