/*
 *  stackedwidgets.h  -  group of stacked widgets
 *  Program:  kalarm
 *  Copyright © 2008 by David Jarvie <djarvie@kde.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.
 *
 *  This program 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 General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

#ifndef STACKEDWIDGETS_H
#define STACKEDWIDGETS_H

#include <QList>
#include <QScrollArea>
class KDialog;

template <class T> class StackedGroupT;

/**
 *  A widget contained in a stack, whose minimum size hint is that of the largest
 *  widget in the stack. This class works together with StackedGroup.
 *
 *  @author David Jarvie <djarvie@kde.org>
 */
template <class T>
class StackedWidgetT : public T
{
	public:
		/** Constructor.
		 *  @param parent The parent object of this widget.
		 *  @param name The name of this widget.
		 */
		explicit StackedWidgetT(StackedGroupT<T>* group, QWidget* parent = 0)
		      : T(parent),
		        mGroup(group)
		{
			mGroup->addWidget(this);
		}
		~StackedWidgetT()  { mGroup->removeWidget(this); }
		virtual QSize sizeHint() const         { return minimumSizeHint(); }
		virtual QSize minimumSizeHint() const  { return mGroup->minimumSizeHint(); }
	private:
		StackedGroupT<T>* mGroup;
};

/**
 *  A group of stacked widgets whose minimum size hints are all equal to the
 *  largest widget's minimum size hint.
 *
 *  It is inherited from QObject solely to ensure automatic deletion when its
 *  parent widget is deleted.
 *
 *  @author David Jarvie <djarvie@kde.org>
 */
template <class T>
class StackedGroupT : public QObject
{
	public:
		explicit StackedGroupT(QObject* parent = 0) : QObject(parent) {}
		void  addWidget(StackedWidgetT<T>* w)     { mWidgets += w; }
		void  removeWidget(StackedWidgetT<T>* w)  { mWidgets.removeAll(w); }
		virtual QSize minimumSizeHint() const;

	protected:
		QList<StackedWidgetT<T>*> mWidgets;
};

template <class T>
QSize StackedGroupT<T>::minimumSizeHint() const
{
	QSize sz;
	for (int i = 0, count = mWidgets.count();  i < count;  ++i)
		sz = sz.expandedTo(mWidgets[i]->T::minimumSizeHint());
	return sz;
}

/** A non-scrollable stacked widget. */
typedef StackedWidgetT<QWidget> StackedWidget;
/** A group of non-scrollable stacked widgets. */
typedef StackedGroupT<QWidget> StackedGroup;


class StackedScrollGroup;

/**
 *  A stacked widget which becomes scrollable when necessary to fit the height
 *  of the screen.
 *
 *  @author David Jarvie <djarvie@kde.org>
 */
class StackedScrollWidget : public StackedWidgetT<QScrollArea>
{
	public:
		explicit StackedScrollWidget(StackedScrollGroup* group, QWidget* parent = 0);
		QWidget* widget() const  { return viewport()->findChild<QWidget*>(); }
};

/**
 *  A group of stacked widgets which individually become scrollable when necessary
 *  to fit the height of the screen.
 *
 *  @author David Jarvie <djarvie@kde.org>
 */
class StackedScrollGroup : public StackedGroupT<QScrollArea>
{
	public:
		explicit StackedScrollGroup(KDialog*, QObject* tabParent);
		virtual QSize minimumSizeHint() const;
		int   heightReduction() const { return mHeightReduction; }
		QSize adjustSize(bool force = false);
		void  setSized()              { mSized = true; }
		bool  sized() const           { return mSized; }
	private:
		QSize maxMinimumSizeHint() const;

		KDialog* mDialog;
		int   mMinHeight;
		int   mHeightReduction;
		bool  mSized;
};

#endif // STACKEDWIDGETS_H
