/*
    ParaGUI - crossplatform widgetset
    Copyright (C) 2000,2001  Alexander Pipelka
 
    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.
 
    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; if not, write to the Free
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
    Alexander Pipelka
    pipelka@teleweb.at
 
    Last Update:      $Author: pipelka $
    Update Date:      $Date: 2001/06/28 08:38:08 $
    Source File:      $Source: /usr/local/CVSROOT/linux/paragui/include/pgapplication.h,v $
    CVS/RCS Revision: $Revision: 1.1.2.9 $
    Status:           $State: Exp $
*/

#ifndef PG_APPLICATION_H
#define PG_APPLICATION_H

#ifdef SWIG
%include "swigcommon.h"
%module pgapplication
%{
#include "pgapplication.h"
%}
#endif

#include <vector>
#include <string>

#include "pgmessageobject.h"

#define NO_EVENTTHREAD 1

/**
	@author Alexander Pipelka

	@short The class that represent an application in ParaGUI. It handles the main loop, screen attibutes etc.

	An application must have a maximum of one PG_Application. If you try to create more than one PG_Application
	the constructor will exit your application with an console error message.

        Every Paragui application needs to have a <code>PG_Application</code> object. The Application object is
        the controller for events, screen initialization, theme support and main loop.
        Here is an example of the steps necesary for creating a simple Paragui application that opens a 640x480
        window with a button in the middle.

        <pre>
        \code		
        #include <paragui.h>
        #include <pgapplication.h>
        #include <pgbutton.h>
        
        
        // Event handler for button click 
        PARAGUI_CALLBACK(buttonHandler) { 
          cout << "Ouch !\\n";
          return true;
        } 
          
        
        int main(  int argc, char **argv ) { 
          const int WIDTH  = 640; 
          const int HEIGHT = 480; 
          
          PG_Application app; 
          
          app.LoadTheme("qnx");                      // Load the QNX theme 
          app.InitScreen(640,480,16,SDL_SWSURFACE);  // SDL_SURFACE | SDL_FULLSCREEN for full screen support

          PG_Button btnOK(NULL,0, PG_Rect((WIDTH-100)/2,(HEIGHT-20)/2,100,20),"Push me !");

          btnOK.SetEventCallback(MSG_BUTTONCLICK,buttonHandler); // Set the event handler
          btnOK.Show(); 
           
          app.Run();                                 // Application loop, exit with Esc by default 
        } 

        \endcode
        </pre>
*/

class DECLSPEC PG_Application : public PG_MessageObject  {
public:

	/**  */
	PG_Application();

	/**  */
	~PG_Application();

	/**
		Initialize the screen

		@param	w			screenwidth in pixels
		@param	h			screenheight in pixels
		@param	depth	screendepth in bits per pixel
		@param	flags	PG_ screen initialization flags
	*/
#ifdef SWIG
	// swig messes up the default arguments
	bool InitScreen(int w, int h, int depth, unsigned int flags);
#else
	bool InitScreen(int w, int h, int depth=DISPLAY_DEPTH, Uint32 flags = SDL_SWSURFACE /* | SDL_FULLSCREEN*/ | SDL_HWPALETTE);
#endif

	/**
		Load a widget theme

		@param	xmltheme			name of the theme (e.g. default)
		@param	asDefault		apply the theme as default widgettheme
		@param	searchpath		path where the themefile is located
	*/
	PG_Theme* LoadTheme(const char* xmltheme, bool asDefault = true, const char* searchpath = NULL);

	/**
		Run the applications main eventloop
		@param	threaded			run the eventloop in a separate thread
		@return					pointer to event thread
		If theaded is false this function will exit when the eventloop quits (MSG_QUIT). If threaded is true
		it will return immediately and a thread processing events is started.
		CAUTION: Threaded eventloops are unsuported under Win32 (windows specific behavior)
	*/
	SDL_Thread* Run(bool threaded = false);

	/**
		Exit the main eventloop
	*/
	void Quit();

	/**
		Cleanup the application data
	*/
	void Shutdown();
		
	/**
		Set a custom screen surface

		@param	screen				pointer to a surface
		@return							pointer the new screen surface
	*/
	SDL_Surface* SetScreen(SDL_Surface* screen);

	/**
		Get the current screen surface

		@return							pointer the screen surface
	*/
	static SDL_Surface* GetScreen();

	/**
		Get the default font
		@return							pointer to font definition
	*/
	static TTF_Font* GetDefaultFont();

	/**
		Set a lock on the screen surface (to avoid concurrent drawing operations)
		@return							true - the lock was established successfully
	*/
	static bool LockScreen();

	/**
		Unlock the screen surface
		@return							true - the unlock operation was successful
	*/
	static bool UnlockScreen();

	/**
		Set the application's background image
		@param	filename			path to a bitmap file
		@param	mode				background mode (BKMODE_TILE | BKMODE_STRETCH)
		@return							true - background image was altered successfully
	*/
	bool SetBackground(const char* filename, int mode=BKMODE_TILE);

	/**
		Set the application's background image
		@param	surface			pointer to a background surface
		@param	mode				background mode (BKMODE_TILE | BKMODE_STRETCH)
		@return							true - background image was altered successfully
	*/
#ifdef SWIG
	%name(SetBackground2) bool SetBackground(SDL_Surface* surface, int mode=BKMODE_TILE);
#else
	bool SetBackground(SDL_Surface* surface, int mode=BKMODE_TILE);
#endif

	/**
		Redraw the application background
	*/
	static void RedrawBackground(const PG_Rect& rect);

	/**
		Enable / disable the emergency quit key ("ESC")
		@param	esc					true - "ESC" key actiavted
	*/
	void SetEmergencyQuit(bool esc);

	/**
	Set the font rendering style
	@param	solid		true - solid font rendering / false - alpha blended font rendering
	*/
	static void SetFontRendering(bool solid);

	/**
	Get the font rendering style
	@return			true - solid font rendering / false - alpha blended font rendering
	*/
	static bool GetFontRendering();

	/**
	Set the application search patch
	@param	path		the application will search for file (images,...) in this patch
	*/
	static void SetApplicationPath(char* path);

	/**
	Return the current application path
	@return			the current path
	*/
	static const char* GetApplicationPath();

	/**
	Tries to find a specifies file
	@param	file		file to look for
	@return			path where the file was found (of NULL if nor found)
	*/
	static const char* GetRelativePath(char* file);

	/**
	Get the current screen (or window) height
	@return			height in pixels
	*/
	static int GetScreenHeight();

	/**
	Get the current screen (or window) width
	@return			width in pixels
	*/
	static int GetScreenWidth();

	/**
	Do a page flip (only for double buffered screens)
	*/
	static void FlipPage();

	/**
	Load a font
	@param	filename	fontfile to load
	@param	size		pixelsize of the font
	@return			pointer to font definition
	*/
	static TTF_Font* LoadFont(char* filename, int size);

	/**  */
#ifndef SWIG
	void PrintVideoTest();
#endif

	/**
	Get the current default widgettheme
	@return			pointer to PG_Theme definition
	*/
	static PG_Theme* GetTheme();

	/**
	Check if the application is currently in bulk mode (OpenGL)
	@return			true / false
	Bulkmode means that all widget are always blitted at once. (OpenGL)
	*/
	static bool GetBulkMode();

	static void SetBulkMode(bool bulk = true);

	static bool GetGLMode();

	void EnableBackground(bool enable = true);

/**
 Set application`s window-manager icon
 @param filename image file to load
 Set icon for application`s window-manager window. You must use bitmap
 with sizes dividable by 8 transparent color with palete.=20
 Transparent color is the color of first up-left pixel.
 THIS FUNCTION MUST BE PROCESSED BEFORE PG_Application::InitScreen()
 */
 void SetIcon(const char *filename);

/**
 Set application`s window-manager title and icon name.
 @param title title name
 @param icon icon name
 Sets the title-bar and icon name of the display window.
 */
 void SetCaption(const char *title, const char *icon);

/**
 Get application`s window-manager title and icon name.
 @param title return place for title name pointer
 @param icon return place for icon name pointer
 Set pointers to the window title and icon name.
 */
 void GetCaption(char **title, char **icon);

 /**
 Iconify/Minimise the window-manager window
 @return   returns non-zero on success or 0 if iconification is not support or was refused by the window manager.
 If the application is running in a window managed environment Iconify attempts to iconify/minimise it.
 */
 int Iconify(void);
protected:

	/**  */
	bool eventKeyUp(const SDL_KeyboardEvent* key);

	/**  */
	bool eventQuit(int id, PG_Widget* widget, unsigned long data);

	/**  */
	bool eventResize(const SDL_ResizeEvent* event);

	/**  */
	virtual void eventInit();

private:

	// disable the copy operators
	PG_Application(const PG_Application&);
	PG_Application& operator=(const PG_Application&);

	bool my_freeBackground;
	static SDL_Surface* my_background;
	int my_backmode;

	static bool FileExists(const char* filename);

	static PG_Theme* my_Theme;

#ifndef SWIG
	static std::string app_path;
#endif

	static PG_Application* pGlobalApp;
	static SDL_Surface* screen;
	static TTF_Font* font;
	static SDL_mutex* mutexScreen;
	static bool bulkMode;
	static bool glMode;
	static bool emergencyQuit;
	static bool solidFontRendering;
	static bool enableBackground;
};

#endif // PG_APPLICATION_H
