/*   EXTRAITS DE LA LICENCE
	Copyright CEA, contributeurs : Luc BILLARD et Damien
	CALISTE, laboratoire L_Sim, (2001-2006)
  
	Adresse mèl :
	BILLARD, non joignable par mèl ;
	CALISTE, damien P caliste AT cea P fr.

	Ce logiciel est un programme informatique servant à visualiser des
	structures atomiques dans un rendu pseudo-3D. 

	Ce logiciel est régi par la licence CeCILL soumise au droit français et
	respectant les principes de diffusion des logiciels libres. Vous pouvez
	utiliser, modifier et/ou redistribuer ce programme sous les conditions
	de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA 
	sur le site "http://www.cecill.info".

	Le fait que vous puissiez accéder à cet en-tête signifie que vous avez 
	pris connaissance de la licence CeCILL, et que vous en avez accepté les
	termes (cf. le fichier Documentation/licence.fr.txt fourni avec ce logiciel).
*/

/*   LICENCE SUM UP
	Copyright CEA, contributors : Luc BILLARD et Damien
	CALISTE, laboratoire L_Sim, (2001-2006)

	E-mail address:
	BILLARD, not reachable any more ;
	CALISTE, damien P caliste AT cea P fr.

	This software is a computer program whose purpose is to visualize atomic
	configurations in 3D.

	This software is governed by the CeCILL  license under French law and
	abiding by the rules of distribution of free software.  You can  use, 
	modify and/ or redistribute the software under the terms of the CeCILL
	license as circulated by CEA, CNRS and INRIA at the following URL
	"http://www.cecill.info". 

	The fact that you are presently reading this means that you have had
	knowledge of the CeCILL license and that you accept its terms. You can
	find a copy of this licence shipped with this software at Documentation/licence.en.txt.
*/
#ifndef VISU_EXTENSION_H
#define VISU_EXTENSION_H

#include <glib.h>
#include <glib-object.h>

#include "openGLFunctions/renderingMode.h"
#include "visu_data.h"

/***************/
/* Public part */
/***************/

/**
 * OPENGL_EXTENSION_PRIORITY_FIRST
 *
 * An extension with this priority is drawn first.
 */
#define OPENGL_EXTENSION_PRIORITY_FIRST 0
/**
 * OPENGL_EXTENSION_PRIORITY_HIGH
 *
 * An extension with this priority is quickly drawn.
 */
#define OPENGL_EXTENSION_PRIORITY_HIGH 20
/**
 * OPENGL_EXTENSION_PRIORITY_NORMAL
 *
 * An extension with this priority is drawn after the higher priorities.
 */
#define OPENGL_EXTENSION_PRIORITY_NORMAL 50
/**
 * OPENGL_EXTENSION_PRIORITY_LOW
 *
 * An extension with this priority is drawn among last extensions.
 */
#define OPENGL_EXTENSION_PRIORITY_LOW 80
/**
 * OPENGL_EXTENSION_PRIORITY_LAST
 *
 * An extension with this priority is drawn last.
 */
#define OPENGL_EXTENSION_PRIORITY_LAST 100

/**
 * OpenGLExtension_struct:
 * 
 * This structure allows the user to store data
 * about an OpenGL extension.
 */
struct OpenGLExtension_struct;
/**
 * OpenGLExtension:
 * 
 * Common name to refer to a #OpenGLExtension_struct.
 */
typedef struct OpenGLExtension_struct OpenGLExtension;

/**
 * rebuildObjectListFunc:
 * @dataObj: the #VisuData object to be rebuilt.
 *
 * Prototypes used to recreate OpenGL list of objects for each extension.
 */
typedef void (*rebuildObjectListFunc)(VisuData *dataObj);

/**
 * OpenGLExtension_new:
 * @name: name of the extension (must be non null),
 * @description: a brief description of the extension (can be null),
 * @objectListId: an int to identify an list of OpenGL objects (null
 * if this extension as no OpenGL object,
 * @rebuild: handler to a method that is called every time V_Sim needs
 * to create again the OpenGL object list. If NULL, nothing is called.
 *
 * Create a new OpenGLExtension with the specified name, description
 * and OpenGL object list. The priority is set by default to
 * #OPENGL_EXTENSION_PRIORITY_NORMAL. The flag used to store
 * the OpenGL state is put to FALSE by default (see
 * OpenGLExtensionSet_saveOpenGLState() to chance it).
 *
 * Returns: the new OpenGLExtension or null if something wrong happens.
 */
OpenGLExtension* OpenGLExtension_new(char* name, char* description,
				     int objectListId, rebuildObjectListFunc rebuild);
/**
 * OpenGLExtension_free:
 * @extension: the extension to delete.
 *
 * Free all the allocated attributes of the specified method.
 */
void OpenGLExtension_free(OpenGLExtension* extension);
/**
 * OpenGLExtensionGet_list:
 *
 * This method is used to get the list of all registered OpenGLExtension.
 * This list is own by V_Sim and should not be freed.
 *
 * Returns: the list of all OpenGLExtension.
 */
GList* OpenGLExtensionGet_list();

/**
 * OpenGLExtensionSet_priority:
 * @extension: a #OpenGLExtension object ;
 * @priority: an integer value.
 *
 * Extentions are drawn in an order that depends on their priority.
 * The lower is the number, the sooner the extension is drawn. Flags,
 * such as #OPENGL_EXTENSION_PRIORITY_NORMAL or #OPENGL_EXTENSION_PRIORITY_LOW,
 * can be used or user defined values are also possible.
 */
void OpenGLExtensionSet_priority(OpenGLExtension* extension, int priority);

/**
 * OpenGLExtensionSet_saveOpenGLState:
 * @extension: a #OpenGLExtension object ;
 * @saveState: an boolean value.
 *
 * If the extension needs to change some OpenGL state (to disable the fog for example,
 * or the cullface), a flag should be set to enable V_Sim to restore the right values after
 * the extensio have been called. Because the OpenGL list of an extension is just GL_COMPILE
 * the extension can't just save and restore state itself because when the list is called,
 * the state can have been changed.
 */
void OpenGLExtensionSet_saveOpenGLState(OpenGLExtension *extension, gboolean saveState);

/**
 * OpenGLExtensionSet_sensitiveToRenderingMode:
 * @extension: a #OpenGLExtension object ;
 * @status: an boolean value.
 *
 * If @status is TRUE, when the extension is rendered, OpenGL context is
 * switched to the rendering mode preferd for the extension. Use
 * OpenGLExtensionSet_preferedRenderingMode() to choose one.
 */
void OpenGLExtensionSet_sensitiveToRenderingMode(OpenGLExtension* extension, gboolean status);
/**
 * OpenGLExtensionSet_preferedRenderingMode:
 * @extension: a #OpenGLExtension object ;
 * @value: see #RenderingModeId to choose one or -1.
 *
 * This method is used to specify the rendering mode that the extension should use
 * to be drawn (if the sensitive flag has been set, see
 * OpenGLExtensionSet_sensitiveToRenderingMode()). If the @value is set
 * to -1, the extension follows the global setting for rendering mode.
 *
 * Returns: TRUE if the "OpenGLAskForReDraw" should be emitted.
 */
gboolean OpenGLExtensionSet_preferedRenderingMode(OpenGLExtension* extension,
						  gint value);


/**
 * OpenGLExtensionGet_active:
 * @extension: the extension.
 *
 * Get if the extension is used or not. If not its ObjectList
 * is not rendered.
 *
 * Returns: 1 if used, 0 otherwise.
 */
int OpenGLExtensionGet_active(OpenGLExtension* extension);
/**
 * OpenGLExtensionSet_active:
 * @extension: the extension,
 * @value: the new value.
 *
 * Set if an extension is actually used or not.
 */
void OpenGLExtensionSet_active(OpenGLExtension* extension, int value);

/**
 * OpenGLExtensionRegister:
 * @extension: an extension.
 *
 * A method used by user to registered a new extension.
 */
void OpenGLExtensionRegister(OpenGLExtension *extension);

/**
 * OpenGLExtensionRemove:
 * @extension: an extension.
 *
 * This method is used to removed fom the list of registered #OpenGLExtension
 * the given one. Removing @extension does not free it.
 */
void OpenGLExtensionRemove(OpenGLExtension *extension);

/**
 * callAllExtensionsLists:
 *
 * For each registered extension that has a valid list (id > 1000),
 * it calls it with glCallList.
 */
void callAllExtensionsLists();
/**
 * rebuildAllExtensionsLists:
 * @dataObj: the #VisuData object to be rebuilt.
 *
 * For each registered extension that has a valid rebuild method,
 * it calls it.
 */
void rebuildAllExtensionsLists(VisuData *dataObj);




/****************/
/* Private area */
/****************/

/* Explicit definition of the structure. */
struct OpenGLExtension_struct
{
  /* Some variable to describe this OpenGL extension.
     The attribute name is mandatory since it is
     used to identify the method. */
  char* name;
  char* description;

  /* The id of the possible objects list brings by
     the extension is refered by this int. */
  int objectListId;

  /* Function called to rebuild the object list of the extension. */
  rebuildObjectListFunc rebuild;

  /* A priority for the extension. */
  int priority;

  /* If set, V_Sim save the OpenGL state before the list
     id is called and restore all states after. */
  gboolean saveState;

  /* Fine tune of rendering mode (Wireframe, smooth...).
     The flag isSensitiveToRenderingMode define is the
     extension cares about rendering mode. This flag is FALSE
     by default. When FALSE, the global value for rendering
     mode is used. Otherwise the value is stored in
     preferedRenderingMode. */
  gboolean isSensitiveToRenderingMode;
  gint preferedRenderingMode;

  /* A boolean to know if this extension is actually used
     or not. */
  int used;
};

/**
 * initOpenGLExtensions:
 *
 * Initialise all the variable of this part. It calls all
 * the elements in %listInitExtensionFunc (that stores the
 * init function of the extensions). If these elements return
 * valid OpenGLExtension, they are registered through a call
 * to registerOpenGLExtension().
 *
 * Returns: 1 if everything goes allright during the initialisation.
 */
int initOpenGLExtensions();
/**
 * loadExtensions:
 *
 * This method is used when V_Sim is initialized and should
 * not be called elsewhere. For each valid init method found
 * in #listInitExtensionFunc, it is called.
 */
void loadExtensions();


#endif
