#
# Licensed under the GNU Lesser General Public License Version 3
#
# This library 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 3 of the license, or
# (at your option) any later version.
#
# This software 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 this library.  If not, see <http://www.gnu.org/licenses/>.


#############################################
### Definitions for wrapping Gtk+ ###########
#############################################

# must start with wrap
wrap: gobject
file: GObject-2.0.gir

addAliases: start
	public import gi.glibtypes;
addAliases: end

noAlias: Type
addEnums: start

	/**
	 * A value which represents the unique identifier of a registered type.
	 */
	enum GType : size_t
	{
		INVALID = 0<<2,
		NONE = 1<<2,
		INTERFACE = 2<<2,
		CHAR = 3<<2,
		UCHAR = 4<<2,
		BOOLEAN = 5<<2,
		INT = 6<<2,
		UINT = 7<<2,
		LONG = 8<<2,
		ULONG = 9<<2,
		INT64 = 10<<2,
		UINT64 = 11<<2,
		ENUM = 12<<2,
		FLAGS = 13<<2,
		FLOAT = 14<<2,
		DOUBLE = 15<<2,
		STRING = 16<<2,
		POINTER = 17<<2,
		BOXED = 18<<2,
		PARAM = 19<<2,
		OBJECT = 20<<2,
		VARIANT = 21<<2,
	}
addEnums: end

struct: CClosure
class: CClosure
import: glib.ConstructionException
import: gobject.ObjectG
noCode: new
noCode: new_swap
noCode: new_object
noCode: new_object_swap
code: start
	/**
	 * Creates a new closure which invokes callbackFunc with userData as
	 * the last parameter.
	 *
	 * Params:
	 *     callbackFunc = the function to invoke
	 *     userData = user data to pass to callbackFunc
	 *     destroyData = destroy notify to be called when userData is no longer used
	 *     swap = if true invoce with usrData as the first parameter
	 *
	 * Throws: ConstructionException GTK+ fails to create the object.
	 */
	public this(GCallback callbackFunc, void* userData, GClosureNotify destroyData, bool swap)
	{
		GClosure* p;

		if ( swap )
			p = g_cclosure_new_swap(callbackFunc, userData, destroyData);
		else
			p = g_cclosure_new(callbackFunc, userData, destroyData);

		if(p is null)
		{
			throw new ConstructionException("null returned by new");
		}

		this(cast(GCClosure*) p);
	}

	/**
	 * A variant of this() which uses object as userData and
	 * calls ObjectG.watchClosure() on object and the created
	 * closure. This function is useful when you have a callback closely
	 * associated with a gobject.ObjectG, and want the callback to no longer run
	 * after the object is is freed.
	 *
	 * Params:
	 *     callbackFunc = the function to invoke
	 *     object = a gobject.ObjectG.ObjectG to pass to callbackFunc
	 *     swap = if true invoce with usrData as the first parameter
	 *
	 * Throws: ConstructionException GTK+ fails to create the object.
	 */
	public this(GCallback callbackFunc, ObjectG object, bool swap)
	{
		GClosure* p;

		if ( swap )
			p = g_cclosure_new_object_swap(callbackFunc, (object is null) ? null : object.getObjectGStruct());
		else
			p = g_cclosure_new_object(callbackFunc, (object is null) ? null : object.getObjectGStruct());

		if(p is null)
		{
			throw new ConstructionException("null returned by new_object");
		}

		this(cast(GCClosure*) p);
	}
code: end

struct: Object
class: ObjectG
import: core.memory
import: gobject.Signals
merge: InitiallyUnowned
noSignal: notify
move: clear_object Object
inout: clear_object object_ptr

code: start
	protected bool isGcRoot;

	/**
	 * Sets our main struct and passes store it on the gobject.
	 * Add a gabage collector root to the gtk+ struct so it doesn't get collect
	 */
	public this (GObject* gObject, bool ownedRef = false)
	{
		this.gObject = gObject;
		if ( gObject !is  null )
		{
			setDataFull("GObject", cast(void*)this, cast(GDestroyNotify)&destroyNotify);
			addToggleRef(cast(GToggleNotify)&toggleNotify, cast(void*)this);

			//If the refCount is larger then 1 toggleNotify isn't called
			if (gObject.refCount > 1 && !isGcRoot)
			{
				GC.addRoot(cast(void*)this);
				isGcRoot = true;
			}

			//Remove the floating reference if there is one.
			if ( isFloating() )
			{
				refSink();
				unref();
			}
			//If we already owned this reference remove the one added by addToggleRef.
			else if ( ownedRef )
			{
				unref();
			}

			//When constructed via GtkBuilder set the structs.
			if ( getStruct() is null)
			{
				setStruct(gObject);
			}
		}
	}

	extern(C)
	{
		static void destroyNotify(ObjectG obj)
		{
			if ( obj.isGcRoot )
			{
				GC.removeRoot(cast(void*)obj);
				obj.isGcRoot = false;
			}

			obj.gObject = null;
		}

		static void toggleNotify(ObjectG obj, GObject* object, int isLastRef)
		{
			if ( isLastRef && obj.isGcRoot )
			{
				GC.removeRoot(cast(void*)obj);
				obj.isGcRoot = false;
			}
			else if ( !obj.isGcRoot )
			{
				GC.addRoot(cast(void*)obj);
				obj.isGcRoot = true;
			}
		}
	}

	~this()
	{
		if ( gObject !is null )
		{
			// Remove the GDestroyNotify callback,
			// for when the D object is destroyed before the C one.
			g_object_steal_data(gObject, cast(char*)"GObject");

			if ( isGcRoot )
			{
				GC.removeRoot(cast(void*)this);
				isGcRoot = false;
			}

			unref();
		}
	}

	/**
	 * Gets a D Object from the objects table of associations.
	 * Params:
	 *  obj = GObject containing the associations.
	 * Returns: the D Object if found, or a newly constructed object if no such Object exists.
	 */
	public static RT getDObject(T, RT=T, U)(U obj, bool ownedRef = false)
	{
		if ( obj is null )
		{
			return null;
		}

		static if ( is(T : ObjectG) )
		{
			auto p = g_object_get_data(cast(GObject*)obj, Str.toStringz("GObject"));

			if ( p !is null )
			{
				static if ( is(RT == interface ) )
				{
					return cast(RT)cast(ObjectG)p;
				}
				else
				{
					return cast(RT)p;
				}
			}
			else
			{
				return new T(obj, ownedRef);
			}
		}
		else
		{
			return new T(obj);
		}
	}

	protected void setStruct(GObject* obj)
	{
		gObject = cast(GObject*)obj;
	}

	/** */
	public void setProperty(string propertyName, int value)
	{
		setProperty(propertyName, new Value(value));
	}

	/** */
	public void setProperty(string propertyName, string value)
	{
		setProperty(propertyName, new Value(value));
	}

	/** */
	public void setProperty(string propertyName, long value)
	{
		//We use g_object_set instead of g_object_set_property, because Value doesn't like longs and ulongs for some reason.
		g_object_set( gObject, Str.toStringz(propertyName), value, null);
	}

	/** */
	public void setProperty(string propertyName, ulong value)
	{
		g_object_set( gObject, Str.toStringz(propertyName), value, null);
	}

	deprecated("Use the member function")
	public static void unref(ObjectG obj)
	{
		obj.unref();
	}

	deprecated("Use the member function")
	public static ObjectG doref(ObjectG obj)
	{
		return obj.doref();
	}

	int[string] connectedSignals;

	void delegate(ParamSpec, ObjectG)[] onNotifyListeners;
	/**
	 * The notify signal is emitted on an object when one of its
	 * properties has been changed. Note that getting this signal
	 * doesn't guarantee that the value of the property has actually
	 * changed, it may also be emitted when the setter for the property
	 * is called to reinstate the previous value.
	 *
	 * This signal is typically used to obtain change notification for a
	 * single property.
	 *
	 * It is important to note that you must use
	 * canonical parameter names for the property.
	 *
	 * Params:
	 *     dlg          = The callback.
	 *     property     = Set this if you only want to receive the signal for a specific property.
	 *     connectFlags = The behavior of the signal's connection.
	 */
	void addOnNotify(void delegate(ParamSpec, ObjectG) dlg, string property = "", ConnectFlags connectFlags=cast(ConnectFlags)0)
	{
		string signalName;

		if ( property == "" )
			signalName = "notify";
		else
			signalName = "notify::"~ property;

		if ( !(signalName in connectedSignals) )
		{
			Signals.connectData(
			this,
			signalName,
			cast(GCallback)&callBackNotify,
			cast(void*)this,
			null,
			connectFlags);
			connectedSignals[signalName] = 1;
		}
		onNotifyListeners ~= dlg;
	}
	extern(C) static void callBackNotify(GObject* gobjectStruct, GParamSpec* pspec, ObjectG _objectG)
	{
		foreach ( void delegate(ParamSpec, ObjectG) dlg ; _objectG.onNotifyListeners )
		{
			dlg(ObjectG.getDObject!(ParamSpec)(pspec), _objectG);
		}
	}
code: end

struct: ObjectClass
merge: InitiallyUnownedClass

struct: ParamSpecBoolean
noCode: true

struct: ParamSpecBoxed
noCode: true

struct: ParamSpecChar
noCode: true

struct: ParamSpecDouble
noCode: true

struct: ParamSpecEnum
noCode: true

struct: ParamSpecFlags
noCode: true

struct: ParamSpecFloat
noCode: true

struct: ParamSpecGType
noCode: true

struct: ParamSpecInt
noCode: true

struct: ParamSpecInt64
noCode: true

struct: ParamSpecLong
noCode: true

struct: ParamSpecObject
noCode: true

struct: ParamSpecOverride
noCode: true

struct: ParamSpecParam
noCode: true

struct: ParamSpecPointer
noCode: true

struct: ParamSpecString
noCode: true

struct: ParamSpecUChar
noCode: true

struct: ParamSpecUInt
noCode: true

struct: ParamSpecUInt64
noCode: true

struct: ParamSpecULong
noCode: true

struct: ParamSpecUnichar
noCode: true

struct: ParamSpecValueArray
noCode: true

struct: ParamSpecVariant
noCode: true

struct: Signals
code: start
	/** */
	public static gulong connectData(void* instanc, string detailedSignal, GCallback cHandler, Object data, GClosureNotify destroyData, GConnectFlags connectFlags)
	{
		return g_signal_connect_data(instanc, Str.toStringz(detailedSignal), cHandler, cast(void*)data, destroyData, connectFlags);
	}
code: end

struct: Type
import: gobject.ObjectG
code: start
	public static T* getInstanceClass(T)(ObjectG obj)
	{
		return cast(T*) (cast(GTypeInstance*)obj.getObjectGStruct()).gClass;
	}

	/**
	 * Get the unique name that is assigned to the Objects type.
	 * Returns: Static type name or NULL.
	 */
	public static string name(ObjectG obj)
	{
		GType type = (cast(GTypeInstance*)obj.getObjectGStruct()).gClass.gType;

		return name(type);
	}
code: end

struct:
class: TypePlugin
extend: Object
implements: TypePlugin

struct: Value
code: start
	/** */
	public this()
	{
		this(new GValue);
	}

	/** */
	this(string value)
	{
		this();
		init(GType.STRING);
		setString(value);
	}

	/** */
	this(int value)
	{
		this();
		init(GType.INT);
		setInt(value);
	}

	/** */
	this(float value)
	{
		this();
		init(GType.FLOAT);
		setFloat(value);
	}

	/** */
	this(double value)
	{
		this();
		init(GType.DOUBLE);
		setDouble(value);
	}
code: end

struct: WeakRef
code: start
	/** */
	this(void* object)
	{
		g_weak_ref_init(gWeakRef, object);
	}
code: end

#
# Move functions defined as global into there respective classes
#

move: boxed_copy Boxed copy
move: boxed_free Boxed free
move: boxed_type_register_static Boxed type_register_static
move: pointer_type_register_static Boxed

move: enum_complete_type_info Enums complete_type_info
move: enum_get_value Enums get_value
move: enum_get_value_by_name Enums get_value_by_name
move: enum_get_value_by_nick Enums get_value_by_nick
move: enum_register_static Enums register_static

move: flags_complete_type_info Flags complete_type_info
move: flags_get_first_value Flags get_first_value
move: flags_get_value_by_name Flags get_value_by_name
move: flags_get_value_by_nick Flags get_value_by_nick
move: flags_register_static Flags register_static

# ParamSpec Constructors?
move: param_spec_boolean Value
move: param_spec_boxed Value
move: param_spec_char Value
move: param_spec_double Value
move: param_spec_enum Value
move: param_spec_flags Value
move: param_spec_float Value
move: param_spec_gtype Value
move: param_spec_int Value
move: param_spec_int64 Value
move: param_spec_long Value
move: param_spec_object Value
move: param_spec_override Value
move: param_spec_param Value
move: param_spec_pointer Value
move: param_spec_string Value
move: param_spec_uchar Value
move: param_spec_uint Value
move: param_spec_uint64 Value
move: param_spec_ulong Value
move: param_spec_unichar Value
move: param_spec_value_array Value
move: param_spec_variant Value

move: param_type_register_static ParamSpec
move: param_value_convert ParamSpec
move: param_value_defaults ParamSpec
move: param_value_set_default ParamSpec
move: param_value_validate ParamSpec
move: param_values_cmp ParamSpec

move: signal_accumulator_first_wins Signals accumulator_first_wins
move: signal_accumulator_true_handled Signals accumulator_true_handled
move: signal_add_emission_hook Signals add_emission_hook
move: signal_chain_from_overridden Signals chain_from_overridden
move: signal_chain_from_overridden_handler Signals chain_from_overridden_handler
move: signal_connect_closure Signals connect_closure
move: signal_connect_closure_by_id Signals connect_closure_by_id
move: signal_connect_data Signals connect_data
move: signal_connect_object Signals connect_object
move: signal_emit Signals emit
move: signal_emit_by_name Signals emit_by_name
move: signal_emit_valist Signals emit_valist
move: signal_emitv Signals emitv
move: signal_get_invocation_hint Signals get_invocation_hint
move: signal_handler_block Signals handler_block
move: signal_handler_disconnect Signals handler_disconnect
move: signal_handler_find Signals handler_find
move: signal_handler_is_connected Signals handler_is_connected
move: signal_handler_unblock Signals handler_unblock
move: signal_handlers_block_matched Signals handlers_block_matched
move: signal_handlers_destroy Signals handlers_destroy
move: signal_handlers_disconnect_matched Signals handlers_disconnect_matched
move: signal_handlers_unblock_matched Signals handlers_unblock_matched
move: signal_has_handler_pending Signals has_handler_pending
move: signal_list_ids Signals list_ids
move: signal_lookup Signals lookup
move: signal_name Signals name
move: signal_new Signals new
move: signal_new_class_handler Signals new_class_handler
move: signal_new_valist Signals new_valist
move: signal_newv Signals newv
move: signal_override_class_closure Signals override_class_closure
move: signal_override_class_handler Signals override_class_handler
move: signal_parse_name Signals parse_name
move: signal_query Signals query
move: signal_remove_emission_hook Signals remove_emission_
move: signal_set_va_marshaller Signals set_va_marshaller
move: signal_stop_emission Signals stop_emission
move: signal_stop_emission_by_name Signals stop_emission_by_name
move: signal_type_cclosure_new Signals type_cclosure_new

move: source_set_closure Closure
move: source_set_dummy_callback Closure

move: strdup_value_contents Value

move: type_add_class_cache_func Type add_class_cache_func
move: type_add_class_private Type add_class_private
move: type_add_instance_private Type add_instance_private
move: type_add_interface_check Type add_interface_check
move: type_add_interface_dynamic Type add_interface_dynamic
move: type_add_interface_static Type add_interface_static
move: type_check_class_cast Type check_class_cast
move: type_check_class_is_a Type check_class_is_a
move: type_check_instance Type check_instance
move: type_check_instance_cast Type check_instance_cast
move: type_check_instance_is_a Type check_instance_is_a
move: type_check_instance_is_fundamentally_a Type check_instance_is_fundamentally_a
move: type_check_is_value_type Type check_is_value_type
move: type_check_value Type check_value
move: type_check_value_holds Type check_value_holds
move: type_children Type children
move: type_create_instance Type create_instance
move: type_default_interface_peek Type default_interface_peek
move: type_default_interface_ref Type default_interface_ref
move: type_default_interface_unref Type default_interface_unref
move: type_depth Type depth
move: type_ensure Type ensure
move: type_free_instance Type free_instance
move: type_from_name Type from_name
move: type_fundamental Type fundamental
move: type_fundamental_next Type fundamental_next
move: type_get_plugin Type get_plugin
move: type_get_qdata Type get_qdata
move: type_get_type_registration_serial Type get_type_registration_serial
move: type_init Type init
move: type_init_with_debug_flags Type init_with_debug_flags
move: type_interfaces Type interfaces
move: type_is_a Type is_a
move: type_name Type name
move: type_name_from_class Type name_from_class
move: type_name_from_instance Type name_from_instance
move: type_next_base Type next_base
move: type_parent Type parent
move: type_qname Type qname
move: type_query Type query
move: type_register_dynamic Type register_dynamic
move: type_register_fundamental Type register_fundamental
move: type_register_static Type register_static
move: type_register_static_simple Type register_static_simple
move: type_remove_class_cache_func Type remove_class_cache_func
move: type_remove_interface_check Type remove_interface_check
move: type_set_qdata Type set_qdata
move: type_test_flags Type test_flags
#move: type_value_table_peek Type value_table_peek
