/***************************************************************************
                          multilayout.cpp  -  layout manager class
                             -------------------
    begin                : Sat Jan 24 2004
    copyright            : (C) 2004 by Andre Somers
    email                : andre@kflog.org


 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/
#include "multilayout.h"

//Every class subclassing QLayout should have an appropriate Iterator.
class MultiLayoutIterator :public QGLayoutIterator
{
public:
	MultiLayoutIterator(QList<QLayoutItem> *l)
		: idx(0), list(l) {}

	QLayoutItem *current()
	{ return idx<int(list->count()) ? list->at(idx) : 0; }

	QLayoutItem *next()
	{ idx++; return current(); }

	QLayoutItem *takeCurrent()
	{ return list->take(idx); }

private:
	int idx;
	QList<QLayoutItem> *list;
};

QLayoutIterator MultiLayout::iterator()
{
	return QLayoutIterator(new MultiLayoutIterator(&list) );
}

int MultiLayout::addItemExt(QLayoutItem *item)
{
	//add the new LayoutItem to our list, and set it as the current if it is the first one
	list.append(item);
	if (_i==-1) {
		_i=0;
		_current=item;
	}

	//create new bitarray, and scan the LayoutItem for widgets
	QBitArray * a=new QBitArray(widgetList.count());
	scanItem(item,a);
	visibleWidgetList.append(a);

	//make sure all bitarrays in the list are long enough
	int wCnt=widgetList.count();
	for (int i=0;i<visibleWidgetList.count();i++) {
		visibleWidgetList.at(i)->resize(wCnt);
	}

	return _i;
}

void MultiLayout::addItem(QLayoutItem *item) {
	//The addItem can't have a return value, but we want to
	//return the index. So addItemExt is called and the return
	//value ignored.
	addItemExt(item);
}

MultiLayout::~MultiLayout()
{
	deleteAllItems();
}

void MultiLayout::setGeometry(const QRect &rect)
{
	QLayout::setGeometry(rect);

	if (list.count() ==0)
		return;

	_current->setGeometry(rect);
}

QSize MultiLayout::sizeHint() const
{
	QSize s(0,0);
	if (list.count() ==0)
		return s;

	s=s.expandedTo(_current->minimumSize());

	return s;
}

QSize MultiLayout::minimumSize() const
{
	QSize s(0,0);
	if (list.count() ==0)
		return s;

	s=s.expandedTo(_current->minimumSize());

	return s;
}

void MultiLayout::activate(uint i)
{
	if (i>list.count()-1)
		return;
	_i=i;
	_current = list.at(i);

	//show and hide the relevant widgets
	QBitArray * a=visibleWidgetList.at(_i);
	for (int j=0;j<a->size();j++) {
		if (a->testBit(j)) {
			widgetList.at(j)->show();
		} else {
			widgetList.at(j)->hide();
		}
	}

	//now do the actual layouting work
	QLayout::activate();
}

int MultiLayout::current()
{
	if (list.count()==0)
		return -1;

	return _i;
}

void MultiLayout::scanItem(QLayoutItem * i, QBitArray * a)
{
	int pos=-1;
	QWidget * wid=i->widget();
	if (wid!=0) {//this layout item is a widget
		pos= widgetList.find(wid);
		if (pos==-1) {//this widget is not in the list yet, so add it
			widgetList.append(wid);
			pos=widgetList.count()-1;
		}
		if (pos >= int(a->size())) {
			a->resize(pos+1);
		}
		a->setBit(pos);//set the bit for this widget to true, to mark it is in this layout.
		return;
	}

	QLayout * lay=i->layout();
	if (lay!=0) {//this layout item is itself a layout
		QLayoutIterator it=lay->iterator();
		QLayoutItem * child;
		while ((child=it.current())!=0) {
			//iterate recursively over all the layout items...
			scanItem(child, a);
			++it;
		}
	}

	//The third option for a QLayoutItem is a QSpacerItem, wich we simply ignore.
}
