/* Gnome Scan - Scan as easy as you print
 * Copyright © 2007  Étienne Bersac <bersace03@laposte.net>
 *
 * Gnome Scan is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * gnome-scan 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
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with gnome-scan.  If not, write to:
 *
 *	the Free Software Foundation, Inc.
 *	51 Franklin Street, Fifth Floor
 *	Boston, MA 02110-1301, USA
 */
 
#ifndef _GNOME_SCAN_PARAM_SPECS_H
#define _GNOME_SCAN_PARAM_SPECS_H

#include <glib.h>
#include <glib-object.h>
#include <gtk/gtk.h>
#include <gegl.h>
#include "gnome-scan-utils.h"

G_BEGIN_DECLS

/* COMMON */

/**
 * GS_DEFINE_PARAM:
 * @param_name:	param prefix
 * @ParamName:	Capitalized param name
 * @VALUE_TYPE:	The macro returning the value GType
 *
 * Convenient function that avoid duplicated bug writing GLib boiler
 * plate for #GType registration for a custom #GParamSpec.
 *
 * For example:
 * <programlisting>
 GS_DEFINE_PARAM (foo, Foo,bar, Bar, G_TYPE_INT);
 * </programlisting>
 *
 * expands to:
 *
 * <programlisting>
 GType
 foo_param_bar_get_type () {
 static GType type = 0;
 if (!type) {
 const GParamSpecTypeInfo info = {
 sizeof (FooParamBarSpec),
 0, NULL, G_TYPE_INT,
 NULL, NULL, NULL, NULL };
 type = g_param_type_register_static ("FooParamBarSpec", &info);
 }
 return type;
 }
 * </programlisting>
 *
 * You'll then have to declare a #FooParamSpecBar structure as
 * well as declaring foo_param_bar_get_type() and writing some macros.
 **/
#define GS_DEFINE_PARAM(prefix, Prefix, param_name, ParamName, VALUE_TYPE) \
  static void prefix##_param_##param_name##_value_set_default (GParamSpec *pspec, GValue *value); \
  static gint prefix##_param_##param_name##_values_cmp (GParamSpec *pspec, const GValue *a, const GValue *b); \
  GType									\
  prefix##_param_##param_name##_get_type () {				\
    static GType type = 0;						\
    if (!type) {							\
      const GParamSpecTypeInfo info = {					\
	sizeof (Prefix##ParamSpec##ParamName),				\
	0, NULL, VALUE_TYPE,						\
	NULL,								\
	prefix##_param_##param_name##_value_set_default,		\
	NULL,								\
	prefix##_param_##param_name##_values_cmp };			\
      type = g_param_type_register_static (#Prefix "Param" #ParamName "Spec", &info); \
    }									\
    return type;							\
  }

/* GQuarks */
#define	GS_PARAM_GROUP_QUARK			(gs_group_quark ())
#define	GS_PARAM_DOMAIN_QUARK			(gs_domain_quark ())
#define	GS_PARAM_UNIT_QUARK			    (gs_unit_quark ())
#define GS_PARAM_INDEX_QUARK            (gs_index_quark ())
#define	GS_PARAM_WIDGET_TYPE_QUARK		(gs_widget_type_quark ())
#define	GS_PARAM_FORMATS_QUARK			(gs_formats_quark ())


GQuark gs_group_quark			(void)	G_GNUC_CONST;
GQuark gs_domain_quark			(void)	G_GNUC_CONST;
GQuark gs_unit_quark			(void)	G_GNUC_CONST;
GQuark gs_index_quark			(void)	G_GNUC_CONST;
GQuark gs_widget_type_quark		(void)	G_GNUC_CONST;
GQuark gs_formats_quark			(void)	G_GNUC_CONST;

/**
 * GS_PARAM_GROUP_SCANNER_FRONT:
 *
 * Scanner option group for not every user
 **/
#define	GS_PARAM_GROUP_SCANNER_FRONT	(gs_scanner_front_quark ())

/**
 * GS_PARAM_GROUP_SCANNER_FORMAT:
 *
 * Scanner option group for selecting paper format (paper size,
 * orientation, etc.)
 **/
#define	GS_PARAM_GROUP_FORMAT			(gs_format_quark ())

/**
 * GS_PARAM_GROUP_SCANNER_FRONT:
 *
 * Scanner option group for not every user
 **/
#define	GS_PARAM_GROUP_SINK_FRONT		(gs_sink_front_quark ())

/**
 * GS_PARAM_GROUP_PREVIEW:
 *
 * Scanner option group for preview page. Option that's needs instant
 * view of the effect of selecting them
 **/
#define	GS_PARAM_GROUP_PREVIEW			(gs_preview_quark())

/**
 * GS_PARAM_GROUP_HIDDEN:
 *
 * Scanner option group not shown to user
 **/
#define	GS_PARAM_GROUP_HIDDEN			(gs_hidden_quark())

GQuark gs_scanner_front_quark	(void)	G_GNUC_CONST;
GQuark gs_format_quark			(void)	G_GNUC_CONST;
GQuark gs_sink_front_quark		(void)	G_GNUC_CONST;
GQuark gs_preview_quark			(void)	G_GNUC_CONST;
GQuark gs_hidden_quark			(void)	G_GNUC_CONST;

GnomeScanFormat*
gnome_scan_format_new				(gchar *name,
                                      gchar *domain,
                                      gchar *description,
                                      gchar **mime_types,
                                      gchar **extensions);
GQuark		gs_param_spec_get_group			(GParamSpec *spec);
const gchar*	gs_param_spec_get_group_string		(GParamSpec *spec);
void		gs_param_spec_set_group			(GParamSpec *spec, GQuark group);
void		gs_param_spec_set_group_from_string	(GParamSpec *spec,
                                                    const gchar *group);

void		gs_param_spec_set_domain 		(GParamSpec *spec,
                                              const gchar *domain);
const gchar*	gs_param_spec_get_domain		(GParamSpec *spec);

void		gs_param_spec_set_unit 			(GParamSpec *spec,
                                                GnomeScanUnit unit);
GnomeScanUnit	gs_param_spec_get_unit			(GParamSpec *spec);

void    	gs_param_spec_set_index			(GParamSpec *spec,
                                                guint index);
guint   	gs_param_spec_get_index			(GParamSpec *spec);

void    	gs_param_spec_set_widget_type		(GParamSpec *spec,
                                                  GType type);
GType   	gs_param_spec_get_widget_type		(GParamSpec *spec);

gint		gs_param_spec_cmp_index			(GParamSpec*a,
                                                GParamSpec *b);
gint		gs_param_spec_cmp_name			(GParamSpec*a,
                                               GParamSpec *b);

gint		gs_param_values_cmp			(GParamSpec *pspec,
                                            GValue *a,
                                            GValue *b);


GParamSpec*	gs_param_spec_boolean (const gchar *name,
				       const gchar *nick,
				       const gchar *blurb,
				       GQuark group,
				       gboolean default_value,
				       GParamFlags flags);

GParamSpec*	gs_param_spec_int (const gchar *name,
				   const gchar *nick,
				   const gchar *blurb,
				   GQuark group,
				   gint minimum,
				   gint maximum,
				   gint default_value,
				   GParamFlags flags);

GParamSpec*	gs_param_spec_double (const gchar *name,
				      const gchar *nick,
				      const gchar *blurb,
				      GQuark group,
				      gdouble minimum,
				      gdouble maximum,
				      gdouble default_value,
				      GParamFlags flags);

GParamSpec*	gs_param_spec_string (const gchar *name,
				      const gchar *nick,
				      const gchar *blurb,
				      GQuark group,
				      const gchar* default_value,
				      GParamFlags flags);

GParamSpec*	gs_param_spec_pointer (const gchar *name,
				       const gchar *nick,
				       const gchar *blurb,
				       GQuark group,
				       GType widget,
				       GParamFlags flags);

/* RANGE */
#define GS_TYPE_PARAM_RANGE				(gs_param_range_get_type ())
#define GS_PARAM_SPEC_RANGE(p)			(G_TYPE_CHECK_INSTANCE_CAST ((p), GS_TYPE_PARAM_RANGE, GSParamSpecRange))
#define GS_IS_PARAM_SPEC_RANGE(p)		(G_TYPE_CHECK_INSTANCE_TYPE ((p), GS_TYPE_PARAM_RANGE))


typedef struct _GSParamSpecRange GSParamSpecRange;
/**
 * GSParamSpecRange:
 *
 * This spec is used to select existing files.
 */
struct _GSParamSpecRange
{
  /*< private >*/
  GParamSpec	parent_instance;
  /*< public >*/
  GValue *minimum;
  GValue *maximum;
  GValue *step;
  GValue *default_value;
};

GType		gs_param_range_get_type	(void)	G_GNUC_CONST;
GParamSpec*	gs_param_spec_range		(const gchar *name,
						 const gchar *nick,
						 const gchar *blurb,
						 GQuark group,
						 GValue *minimum,
						 GValue *maximum,
						 GValue *step,
						 GValue *default_value,
						 GParamFlags flags);


/* ENUM */
#define GS_TYPE_PARAM_ENUM				(gs_param_enum_get_type ())
#define GS_PARAM_SPEC_ENUM(p)			(G_TYPE_CHECK_INSTANCE_CAST ((p), GS_TYPE_PARAM_ENUM, GSParamSpecEnum))
#define GS_IS_PARAM_SPEC_ENUM(p)		(G_TYPE_CHECK_INSTANCE_TYPE ((p), GS_TYPE_PARAM_ENUM))


typedef struct _GSParamSpecEnum GSParamSpecEnum;
/**
 * GSParamSpecEnum:
 *
 * This spec is used to select existing files.
 */
struct _GSParamSpecEnum
{
  /*< private >*/
  GParamSpec	parent_instance;
	
  /*< public >*/
  GValueArray *values;
  GValue *default_value;
};

GType		gs_param_enum_get_type	(void)	G_GNUC_CONST;
GParamSpec*	gs_param_spec_enum		(const gchar *name,
						 const gchar *nick,
						 const gchar *blurb,
						 GQuark group,
						 GValueArray *values,
						 GValue *default_value,
						 GParamFlags flags);



/* PAPER SIZE */
#define GS_TYPE_PARAM_PAPER_SIZE			(gs_param_paper_size_get_type ())
#define GS_PARAM_SPEC_PAPER_SIZE(p)			(G_TYPE_CHECK_INSTANCE_CAST ((p), GS_TYPE_PARAM_PAPER_SIZE, GSParamSpecPaperSize))
#define GS_IS_PARAM_SPEC_PAPER_SIZE(p)		(G_TYPE_CHECK_INSTANCE_TYPE ((p), GS_TYPE_PARAM_PAPER_SIZE))


typedef struct _GSParamSpecPaperSize GSParamSpecPaperSize;
/**
 * GSParamSpecPaperSize:
 *
 */
struct _GSParamSpecPaperSize
{
  /*< private >*/
  GParamSpec		parent_instance;
	
  /*< public >*/
  GtkPaperSize*			default_ps;
  GSList*			enumeration;
};

GType		gs_param_paper_size_get_type	(void)	G_GNUC_CONST;
GParamSpec*	gs_param_spec_paper_size		(const gchar *name,
							 const gchar *nick,
							 const gchar *blurb,
							 GQuark group,
							 GtkPaperSize* default_ps,
							 GSList* enumeration,
							 GParamFlags flags);

void		gs_param_paper_size_get_extent		(GSParamSpecPaperSize *ps,
							 GnomeScanUnit unit,
							 gdouble *width,
							 gdouble *height);

/* PAGE ORIENTATION */
#define GS_TYPE_PARAM_PAGE_ORIENTATION			(gs_param_page_orientation_get_type ())
#define GS_PARAM_SPEC_PAGE_ORIENTATION(p)			(G_TYPE_CHECK_INSTANCE_CAST ((p), GS_TYPE_PARAM_PAGE_ORIENTATION, GSParamSpecPageOrientation))
#define GS_IS_PARAM_SPEC_PAGE_ORIENTATION(p)		(G_TYPE_CHECK_INSTANCE_TYPE ((p), GS_TYPE_PARAM_PAGE_ORIENTATION))


typedef struct _GSParamSpecPageOrientation GSParamSpecPageOrientation;
/**
 * GSParamSpecPageOrientation:
 *
 */
struct _GSParamSpecPageOrientation
{
  /*< private >*/
  GParamSpec		parent_instance;
	
  /*< public >*/
  guint			default_value;
};

GType		gs_param_page_orientation_get_type	(void)	G_GNUC_CONST;
GParamSpec*	gs_param_spec_page_orientation		(const gchar *name,
							 const gchar *nick,
							 const gchar *blurb,
							 GQuark group,
							 guint default_value,
							 GParamFlags flags);




G_END_DECLS

#endif /* _GNOME_SCAN_PARAM_SPECS_H */
