/*
    This file is part of the Boson game
    Copyright (C) 2004-2005 Andreas Beckermann (b_mann@gmx.de)

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

// note the copyright above: this is LGPL!
#ifndef BOUFOMANAGER_H
#define BOUFOMANAGER_H

#include <qobject.h>

class QMouseEvent;
class QWheelEvent;
class QKeyEvent;
template<class T1, class T2> class QMap;
template<class T1> class QValueList;
class QDomElement;

class BoUfoActionCollection;
class BoUfoMenuBar;
class BoUfoToolBar;
class BoUfoWidget;
class BoUfoInternalFrame;
class BoUfoLayeredPane;
class BoUfoFontInfo;

namespace ufo {
	class UXToolkit;
	class UXDisplay;
	class UContext;
	class UXContext;
	class URootPane;
	class UObject;
	class ULayoutManager;
	class UDimension;
	class UDrawable;
	class UImage;
	class UImageIO;
	class UPoint;
	class UFontInfo;
	class UFont;

	class UWidget;
	class UButton;
	class UCheckBox;
	class URadioButton;
	class UTextEdit;
	class UAbstractSlider;
	class USlider;
	class UListBox;
	class ULineEdit;
	class ULabel;
	class UComboBox;
	class UInternalFrame;
	class UBoProgress;
	class ULayeredPane;
	class UWidgetUI;
	class UButtonGroup;
	class UDockWidget;


	class UActionEvent;
	class UMouseEvent;
	class UMouseWheelEvent;
	class UWidgetEvent;
	class UKeyEvent;
	class UFocusEvent;
};

/**
 * This is the primary class for the boson wrapper around libufo (BoUfo). It
 * creates a libufo context and display and provides convenience methods for
 * event handling.
 *
 * Most of this is straight forward, but some important things are to be
 * mentioned:
 *
 * libufo maintains an event queue (just like e.g. Qt). Whenever you push
 * an event to a libufo class, you need to dispatch the events before they take
 * effect. You can do this using @ref dispatchEvent. Since we usually re-render
 * the screen in certain intervals in boson, it may be convenient for you to
 * render the ufo widgets like this:
 * <pre>
 * mUfoManager->dispatchEvents();
 * mUfoManager->render();
 * </pre>
 * This way you can safely forget about dispatching events, because it is done
 * sufficiently often.
 *
 * The @ref menuBar is a very special case, because we use the *ui.rc xml files,
 * just like KDE does. Therefore you do not need to create a menubar yourself -
 * instead use @ref BoUfoAction to declare your action (similar to @ref KAction)
 * and let your menu be generated by @ref BoActionCollection::createGUI.
 *
 * @author Andreas Beckermann <b_mann@gmx.de>
 **/
class BoUfoManager : public QObject
{
	Q_OBJECT
public:
	/**
	 * @param opaque If FALSE (default) the @ref contentWidget is
	 * transparent.
	 **/
	BoUfoManager(int w, int h, bool opaque = false);
	~BoUfoManager();

	/**
	 * Set the directory where libufo should search for it's files (images,
	 * fonts, ...)
	 *
	 * In Boson this is set automatically on construction to
	 * $KDEDIR/share/apps/boson
	 **/
	void setDataDir(const QString& dir);
	QString dataDir() const;

	/**
	 * @return The BoUfoManager object that maintains the currently active
	 * context, see @ref ufo::UToolkit::getCurrentContext or NULL if no
	 * context is current, or if no BoUfoManager manages that context. Note
	 * that if a BoUfoManager is existing, this method returns NULL only, if
	 * you changed the libufo context manually.
	 **/
	static BoUfoManager* currentUfoManager();

	/**
	 * @internal
	 * @return The BoUfoManager object that manages @p context or NULL if
	 * none does.
	 **/
	static BoUfoManager* ufoManagerForContext(ufo::UContext* context);

	// AB: note that atm we always use video device size == context size
	void resize(int w, int h);

	ufo::UXToolkit* toolkit() const;

	ufo::UXDisplay* display() const
	{
		return mDisplay;
	}

	ufo::UXContext* context() const
	{
		return mContext;
	}
	ufo::URootPane* rootPane() const
	{
		return mRootPane;
	}

	/**
	 * You should prefer @ref contentWidget instead, which returns the same
	 * widget.
	 **/
	ufo::UWidget* contentPane() const
	{
		return mContentPane;
	}

	/**
	 * @return A BoUfo wrapper around @ref contentPane. Use this instead of
	 * @ref contentPane.
	 **/
	BoUfoWidget* contentWidget() const
	{
		return mContentWidget;
	}

	/**
	 * @return The layered pane of the @ref ufo::URootPane. This is the
	 * desktop pane, containing the @ref contentWidget as well as the
	 * menubar
	 **/
	BoUfoLayeredPane* layeredPaneWidget() const
	{
		return mLayeredPaneWidget;
	}

	BoUfoWidget* rootPaneWidget() const
	{
		return mRootPaneWidget;
	}

	void addFrame(BoUfoInternalFrame*);
	void removeFrame(BoUfoInternalFrame*);

	/**
	 * This may be required when you have multiple BoUfoManager objects
	 * around (e.g. when you use more than one window). You should always
	 * make the context current before using anything in BoUfo/libufo.
	 *
	 * You can safely ignore this if you have only one BoUfoManager object.
	 **/
	void makeContextCurrent();

	void dispatchEvents();
	void render(bool pushAttributesMatrices = true);


	/**
	 * Use @ref BoUfoActionCollection::initActionCollection to set this
	 **/
	void setActionCollection(BoUfoActionCollection* c)
	{
		mActionCollection = c;
	}
	BoUfoActionCollection* actionCollection() const
	{
		return mActionCollection;
	}
	/**
	 * Called internally. Use @ref BoUfoActionCollection to create menus.
	 **/
	void setMenuBarData(BoUfoMenuBar* m);
	BoUfoMenuBar* menuBarData() const
	{
		return mMenuBarData;
	}
	/**
	 * Called internally.
	 **/
	void setToolBarData(BoUfoToolBar* m);
	BoUfoToolBar* toolBarData() const
	{
		return mToolBarData;
	}
	BoUfoWidget* toolBarContentWidget();

	bool sendEvent(QEvent* e);

	void setUfoToolkitProperty(const QString& key, const QString& value);
	QString ufoToolkitProperty(const QString& key) const;
	QMap<QString, QString> toolkitProperties() const;

	void setGlobalFont(const BoUfoFontInfo& font);
	const BoUfoFontInfo& globalFont() const;

	QValueList<BoUfoFontInfo> listFonts();
	QValueList<BoUfoFontInfo> listFonts(const BoUfoFontInfo&);

	bool focusedWidgetTakesKeyEvents() const;

protected:
	bool sendResizeEvent(int w, int h);
	bool sendMousePressEvent(QMouseEvent* e);
	bool sendMouseReleaseEvent(QMouseEvent* e);
	bool sendMouseMoveEvent(QMouseEvent* e);
	bool sendWheelEvent(QWheelEvent* e);
	bool sendKeyPressEvent(QKeyEvent* e);
	bool sendKeyReleaseEvent(QKeyEvent* e);

private:
	ufo::UXDisplay* mDisplay;
	ufo::UXContext* mContext;

	ufo::URootPane* mRootPane;
	ufo::UWidget* mContentPane;
	BoUfoWidget* mContentWidget;
	BoUfoLayeredPane* mLayeredPaneWidget;
	BoUfoWidget* mRootPaneWidget;

	BoUfoActionCollection* mActionCollection;
	BoUfoMenuBar* mMenuBarData;
	BoUfoToolBar* mToolBarData;
	BoUfoFontInfo* mGlobalFont;
	ufo::UDockWidget* mToolBarDockWidget;
	BoUfoWidget* mToolBarContentWidget;
};

#endif
