/*  Inti: Integrated Foundation Classes
 *  Copyright (C) 2002-2003 The Inti Development Team.
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program 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 program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

//! @file inti/gtk/iconfactory.h
//! @brief A GtkIconSource, GtkIconSet and GtkIconFactory C++ wrapper interface.
//!
//! Provides IconSource, IconSet and IconFactory. IconSource contains a Gdk::Pixbuf
//! (or image filename) that serves as the base image for one or more of the icons
//! in an IconSet, along with a specification for which icons in the icon set will
//! be based on that pixbuf or image file. IconSet represents a single icon in 
//! various sizes and widget states.

#ifndef INTI_GTK_ICON_FACTORY_H
#define INTI_GTK_ICON_FACTORY_H

#ifndef INTI_G_BOXED_H
#include <inti/glib/boxed.h>
#endif

#ifndef INTI_G_OBJECT_H
#include <inti/glib/object.h>
#endif

#ifndef INTI_GTK_ENUMS_H
#include <inti/gtk/enums.h>
#endif

#ifndef __GTK_ICON_FACTORY_H__
#include <gtk/gtkiconfactory.h>
#endif

#ifndef _CPP_VECTOR
#include <vector>
#endif

namespace Inti {

namespace Gdk {
class Pixbuf;
}

namespace Gtk {

class IconFactoryClass;
class Settings;
class Style;
class Widget;

//! @name Icon Size Methods
//! @{

bool icon_size_lookup(IconSize size, int *width, int *height, Settings *settings = 0);
//!< Obtains the pixel size of a semantic icon size, possibly modified by user preferences
//!< for a particular Settings.
//!< @param size An icon size.
//!< @param width The location to store icon width.
//!< @param height The location to store icon height.
//!< @param settings A Settings object, used to determine which set of user preferences
//!<                 to use, or null to use the settings for the default screen.
//!< @return <EM>true</EM> if size was a valid size.
//!<
//!< <BR>Normally size would be ICON_SIZE_MENU, ICON_SIZE_BUTTON, etc. This method isn't
//!< normally needed, Gtk::Widget::render_icon() is the usual way to get an icon for
//!< rendering, then just look at the size of the rendered pixbuf. The rendered pixbuf
//!< may not even correspond to the width/height returned by size_lookup(), because themes
//!< are free to render the pixbuf however they like, including changing the usual size.
//!<
//!< <B>Note:</B> The default GDK screen is the only screen in the absence of MultiHead support.

IconSize icon_size_register(const char *name, int width, int height);
//!< Registers a new icon size, along the same lines as ICON_SIZE_MENU, etc.
//!< @param name The name of the icon size.
//!< @param width The icon width.
//!< @param height The icon height.
//!< @return The integer value for the size, as an IconSize.

void icon_size_register_alias(const char *alias, IconSize target);
//!< Registers <EM>alias</EM> as another name for <EM>target</EM>.
//!< @param alias An alias for target.
//!< @param target An existing icon size.
//!<
//!< <BR>Calling size_from_name() with <EM>alias</EM> as the argument will return <EM>target</EM>.

IconSize icon_size_from_name(const char *name);
//!< Looks up the icon size associated with <EM>name</EM>.
//!< @param name The name to look up.
//!< @return The icon size with the given name.

String icon_size_get_name(IconSize size);
//!< Gets the canonical name of the given icon size.
//!< @param size An IconSize.
//!< @return The name of the given icon size.

//! @}

//! @class IconSource iconfactory.h inti/gtk/iconfactory.h
//! @brief A GtkIconSource C++ wrapper class.
//!
//! An IconSource contains a Gdk::Pixbuf (or image filename) that serves as the base image
//! for one or more of the icons in an IconSet, along with a specification for which icons
//! in the icon set will be based on that pixbuf or image file. An icon set contains a set
//! of icons that represent "the same" logical concept in different states, different global
//! text directions, and different sizes.
//!
//! So for example a web browser's "Back to Previous Page" icon might point in a different
//! direction in Hebrew and in English; it might look different when insensitive; and it 
//! might change size depending on toolbar mode (small/large icons). So a single icon set
//! would contain all those variants of the icon. IconSet contains a list of IconSource 
//! from which it can derive specific icon variants in the set.
//!
//! In the simplest case, IconSet contains one source pixbuf from which it derives all variants.
//! The constructor IconSource(Gdk::Pixbuf&) handles this case; if you only have one source 
//! pixbuf, just use that constructor. If you want to use a different base pixbuf for different
//! icon variants, you create multiple icon sources, mark which variants they'll be used to 
//! create, and add them to the icon set with Gtk::IconSet::add_source(). By default, the icon
//! source has all parameters wildcarded. That is, the icon source will be used as the base icon
//! for any desired text direction, widget state, or icon size.

class IconSource : public G::Boxed
{
public:
//! @name Constructors
//! @{

	IconSource();
	//!< Construct a new IconSource.

	explicit IconSource(GtkIconSource *source);
	//!< Construct a new IconSource from an existing GtkIconSource.
	//!< @param source A GtkIconSource.
	//!<
	//!< <BR>This constructor creates a temporary wrapper for a GtkIconSource. It neither
	//!< copies the GtkIconSource or takes over its ownership.

	IconSource(GtkIconSource *source, bool copy);
	//!< Construct a new IconSource from an existing GtkIconSource.
	//!< @param source A GtkIconSource.
	//!< @param copy <EM>true</EM> if a copy of GtkIconSource should be made.
	//!<
	//!< <BR>This constructor either takes over the ownership of the GtkIconSource, or makes a copy
	//!< of the GtkIconSource. It is primarily intended for use by the G::Boxed::wrap() method.

	IconSource(const IconSource& src);
	//!< Copy constructor.

	~IconSource();
	//!< Destructor.

	IconSource& operator=(const IconSource& src);
	//!< Assignment operator.

//! @}
//! @name Accessors
//! @{

	GtkIconSource* gtk_icon_source() const { return (GtkIconSource*)boxed_; }
	//!< Get a pointer to the GtkIconSource structure.

	operator GtkIconSource* () const;
	//!< Conversion operator; safely converts an IconSource to a GtkIconSource pointer.

	String get_filename() const;
	//!< Retrieves the source filename.
	//!< @return The source filename or a null String if none is set.

	Gdk::Pixbuf* get_pixbuf() const;
	//!< Retrieves the source pixbuf, or null if none is set.
	//!< The reference count on the pixbuf is not incremented.

	bool get_size_wildcarded() const;
	//!< Gets the value set by set_size_wildcarded().
	//!< @return <EM>true</EM> if this icon source is a base for any icon size variant.

	bool get_state_wildcarded() const;
	//!< Gets the value set by set_state_wildcarded().
	//!< return <EM>true</EM> if this icon source is a base for any widget state variant.

	bool get_direction_wildcarded() const;
	//!< Gets the value set by set_direction_wildcarded().
	//!< @return <EM>true</EM> if this icon source is a base for any text direction variant.

	TextDirection get_direction() const;
	//!< Obtains the text direction this icon source applies to.
	//!< @return The text direction this source matches.
	//!<
	//!< <BR>The return value is only useful/meaningful if the text direction is not wildcarded.
	
	StateType get_state() const;
	//!< Obtains the widget state this icon source applies to. 
	//!< @return The widget state this source matches.
	//!<
	//!< <BR>The return value is only useful/meaningful if the widget state is not wildcarded.

	IconSize get_size() const;
	//!< Obtains the icon size this icon source applies to.
	//!< @return The icon size this source matches.
	//!<
	//!< <BR>The return value is only useful/meaningful if the icon size is not wildcarded.

//! @}
//! @name Methods
//! @{

	void set_filename(const String& filename);
	//!< Sets the name of an image file to use as a base image when creating icon variants
	//!< for IconSet.
	//!< @param filename The image file to use.
	//!<
	//!< <BR>The filename must be absolute.

	void set_pixbuf(Gdk::Pixbuf *pixbuf);
	//!< Sets a pixbuf to use as a base image when creating icon variants for IconSet. 
	//!< @param pixbuf The pixbuf to use as a source.
	//!<
	//!< <BR>If an icon source has both a filename and a pixbuf set, the pixbuf will take priority.

	void set_direction_wildcarded(bool setting);
	//!< If the text direction is wildcarded, this source can be used as the base image for
	//!< an icon in any TextDirection.
	//!< @param setting <EM>true</EM> to wildcard the text direction.
	//!<
	//!< <BR>If the text direction is not wildcarded, then the text direction the icon source 
	//!< applies to should be set with set_direction(), and the icon source will only be used
	//!< with that text direction. IconSet prefers non-wildcarded sources (exact matches) over
	//!< wildcarded sources, and will use an exact match when possible.
	
	void set_state_wildcarded(bool setting);
	//!< If the widget state is wildcarded, this source can be used as the base image for an
	//!< icon in any StateType.
	//!< @param setting <EM>true</EM> to wildcard the widget state.
	//!<
	//!< <BR>If the widget state is not wildcarded, then the state the source applies to should
	//!< be set with set_state() and the icon source will only be used with that specific state.
	//!< IconSet prefers non-wildcarded sources (exact matches) over wildcarded sources, and 
	//!< will use an exact match when possible. IconSet will normally transform wildcarded source
	//!< images to produce an appropriate icon for a given state, for example lightening an image
	//!< on prelight, but will not modify source images that match exactly.

	void set_size_wildcarded(bool setting);
	//!< If the icon size is wildcarded, this source can be used as the base image for an icon
	//!< of any size. 
	//!< @param setting <EM>true</EM> to wildcard the icon size.
	//!<
	//!< <BR>If the size is not wildcarded, then the size the source applies to should be set
	//!< with set_size() and the icon source will only be used with that specific size. IconSet
	//!< prefers non-wildcarded sources (exact matches) over wildcarded sources, and will use
	//!< an exact match when possible. IconSet will normally scale wildcarded source images to
	//!< produce an appropriate icon at a given size, but will not change the size of source
	//!< images that match exactly.
	
	void set_direction(TextDirection direction);
	//!< Sets the text direction this icon source is intended to be used with.
	//!< @param direction The text direction this source applies to.
	//!< 
	//!< <BR>Setting the text direction on an icon source makes no difference if the text direction
	//!< is wildcarded. Therefore, you should usually call set_direction_wildcarded() to un-wildcard
	//!< it in addition to calling this method.

	void set_state(StateType state);
	//!< Sets the widget state this icon source is intended to be used with.
	//!< @param state The widget state this source applies to.
	//!<
	//!< <BR>Setting the widget state on an icon source makes no difference if the state is
	//!< wildcarded. Therefore, you should usually call set_state_wildcarded() to un-wildcard
	//!< it in addition to calling this method.

	void set_size(IconSize size);
	//!< Sets the icon size this icon source is intended to be used with.
	//!< @param size The icon size this source applies to.
	//!< 
	//!< <BR>Setting the icon size on an icon source makes no difference if the size is wildcarded.
	//!< Therefore, you should usually call set_size_wildcarded() to un-wildcard it in addition to
	//!< calling this method.

//! @}
};

//! @class IconSet iconfactory.h inti/gtk/iconfactory.h
//! @brief A GtkIconSet C++ wrapper class.
//!
//! An IconSet represents a single icon in various sizes and widget states. It can
//! provide a Gdk::Pixbuf for a given size and state on request, and automatically
//! caches some of the rendered Gdk::Pixbuf objects. Normally you would use 
//! Gtk::Widget::render_icon() instead of using IconSet directly. The one case 
//! where you'd use IconSet is to create application-specific icon sets to place
//! in an IconFactory.

class IconSet : public G::Boxed
{
public:
//! @name Constructors
//! @{

	IconSet();
	//!< Construct a new IconSet.

	explicit IconSet(Gdk::Pixbuf& pixbuf);
	//!< Construct a new IconSet with pixbuf as the default/fallback source image. 
	//!< @param pixbuf A Gdk::Pixbuf.
	//!<
	//!< <BR>If you don't add any additional IconSource to the icon set, all variants of the
	//!< icon will be created from pixbuf, using scaling, pixelation, etc. as required to
	//!< adjust the icon size or make the icon look insensitive/prelighted.

	explicit IconSet(GtkIconSet *icon_set);
	//!< Construct a new IconSet from an existing GtkIconSet.
	//!< @param icon_set A GtkIconSet.
	//!<
	//!< <BR>This constructor creates a temporary wrapper for a GtkIconSet. It neither
	//!< copies the GtkIconSet or takes over its ownership.

	IconSet(GtkIconSet *icon_set, bool copy);
	//!< Construct a new IconSet from an existing GtkIconSet.
	//!< @param icon_set A GtkIconSet.
	//!< @param copy <EM>true</EM> if a copy of GtkIconSet should be made.
	//!<
	//!< <BR>This constructor either takes over the ownership of the GtkIconSet, or makes
	//!< a copy of the GtkIconSet. This constructor is primarily intended for use by the
	//!< G::Boxed::wrap() method.

	IconSet(const IconSet& src);
	//!< Copy constructor.

	~IconSet();
	//!< Destructor.

	IconSet& operator=(const IconSet& src);
	//!< Assignment operator.
	
//! @}
//! @name Accessors
//! @{

	GtkIconSet* gtk_icon_set() const { return (GtkIconSet*)boxed_; }
	//!< Get a pointer to the GtkIconSet structure.

	operator GtkIconSet* () const;
	//!< Conversion operator; safely converts an IconSet to a GtkIconSet pointer.

	bool get_sizes(std::vector<IconSize>& sizes) const;
	//!< Obtains a list of icon sizes this icon set can render.
	//!< @param sizes A reference to a vector of IconSize to hold the sizes.
	//!< @return <EM>true</EM> if <EM>sizes</EM> contains any sizes; <EM>false</EM> if empty.

//! @}
//! @name Methods
//! @{

	Pointer<Gdk::Pixbuf> render_icon(Style& style, StateType state, IconSize size,
	                                 Widget* widget = 0, const char *detail = 0,
					 TextDirection direction = TEXT_DIR_LTR);
	//!< Renders an icon using Gtk::Style::render_icon().
	//!< @param style A Style associated with widget.
	//!< @param state The widget state.
	//!< @param size The icon size.
	//!< @param widget The widget that will display the icon, or null.
	//!< @param detail The detail to pass to the theme engine, or null.
	//!< @param direction The text direction.
	//!< @return A Gdk::Pixbuf to be displayed.
	//!<
	//!< <BR>In most cases, Gtk::Widget::render_icon() is better, since it automatically provides
	//!< most of the arguments from the current widget settings. This method never returns null;
	//!< if the icon can't be rendered (perhaps because an image file fails to load), a default
	//!< "missing image" icon will be returned instead. A smart pointer to a Gdk::Pixbuf is 
	//!< returned because the returned pixbuf must be unreferenced. This will happen automatically
	//!< when the smart pointer goes out of scope.

	void add_source(const IconSource& source);
	//!< Add an IconSource to the icon set.
	//!< @param source An IconSource.
	//!<
	//!< <BR>Icon sets have a list of IconSource, which they use as base icons for rendering icons
	//!< in different states and sizes. 
	//!<
	//!< Icons are scaled, made to look insensitive, etc. in render_icon(), but IconSet needs base
	//!< images to work with. The base images and when to use them are described by a IconSource.
	//!< This method copies <EM>source</EM>, so you can reuse the same source immediately without
	//!< affecting the icon set. An example of when you'd use this method: a web browser's "Back
	//!< to Previous Page" icon might point in a different direction in Hebrew and in English;
	//!< it might look different when insensitive; and it might change size depending on toolbar
	//!< mode (small/large icons). So a single icon set would contain all those variants of the
	//!< icon, and you might add a separate source for each one.
	//!<
	//!< You should nearly always add a "default" icon source with all fields wildcarded, which will
	//!< be used as a fallback if no more specific source matches. IconSet always prefers more specific
	//!< icon sources to more generic icon sources. The order in which you add the sources to the icon
	//!< set does not matter. When you construct an IconSet with a pixbuf, the icon set creates a default
	//!< icon source based on the pixbuf.

//! @}
};

//! @class IconFactory iconfactory.h inti/gtk/iconfactory.h
//! @brief A GtkIconFactory C++ wrapper class.
//!
//! An icon factory manages a collection of IconSets; an IconSet manages a set of variants
//! of a particular icon (i.e. a IconSet contains variants for different sizes and widget
//! states). Icons in an icon factory are named by a stock ID, which is a simple string
//! identifying the icon. Each Style has a list of IconFactorys derived from the current
//! theme; those icon factories are consulted first when searching for an icon. If the
//! theme doesn't set a particular icon, GTK+ looks for the icon in a list of default icon
//! factories, maintained by IconFactory's add_default() and remove_default() methods.
//! Applications with icons should add a default icon factory with their icons, which will
//! allow themes to override the icons for the application (see application.cc in the
//! inti-demo demo program).

class IconFactory : public G::Object
{
	friend class G::Object;
	friend class IconFactoryClass;

	IconFactory(const IconFactory&);
	IconFactory& operator=(const IconFactory&);
	
protected:
//! @name Constructors
//! @{

	explicit IconFactory(GtkIconFactory *icon_factory, bool reference = true);
	//!< Construct a new IconFactory from an existing GtkIconFactory.
	//!< @param icon_factory A pointer to a GtkIconFactory.
	//!< @param reference Set false if the initial reference count is floating, set true if it's not.
	//!<
	//!< <BR>The <EM>icon_factory</EM> can be a newly created GtkIconFactory or an existing
	//!< GtkIconFactory (see G::Object::Object).

//! @}
	
public:
//! @name Constructors
//! @{

	IconFactory();
	//!< Construct a new IconFactory.

	virtual ~IconFactory();
	//!< Destructor.
	
//! @}
//! @name Accessors
//! @{

	GtkIconFactory* gtk_icon_factory() const { return (GtkIconFactory*)instance; }
	//!< Get a pointer to the GtkIconFactory structure.

	GtkIconFactoryClass* gtk_icon_factory_class() const;
	//!< Get a pointer to the GtkIconFactoryClass structure.

	operator GtkIconFactory* () const;
	//!< Conversion operator; safely converts an IconFactory to a GtkIconFactory pointer.

//! @}
//! @name Methods
//! @{

	void add(const char *stock_id, IconSet& icon_set);
	//!< Adds the given icon_set to the icon factory, under the name stock_id.
	//!< @param stock_id The icon name.
	//!< @param icon_set The icon set.
	//!<
	//!< <BR>The <EM>stock_id</EM> should be namespaced for your application, e.g.
	//!< "myapp-whatever-icon". Normally applications create an IconFactory, then
	//!< add it to the list of default factories with add_default(). Then they pass
	//!< the stock_id to widgets such as Image to display the icon. Themes can
	//!< provide an icon with the same name (such as "myapp-whatever-icon") to 
	//!< override your application's default icons. If an icon already existed in
	//!< factory for stock_id, it is unreferenced and replaced with the new icon_set.

	Pointer<IconSet> lookup(const char *stock_id);
	//!< Looks up <EM>stock_id</EM> in the icon factory, returning an icon set
	//!< if found, otherwise null. 
	//!< @param stock_id The icon name.
	//!< @return The icon set of stock_id.
	//!<
	//!< <BR>For display to the user, use Gtk::Style::lookup_icon_set() for the widget that
	//!< will display the icon instead of using this method directly, so that themes are
	//!< taken into account.
	
	void add_default();
	//!< Adds the IconFactory to the list of icon factories searched by Gtk::Style::lookup_icon_set().
	//!< This means that, for example, a stock Image widget will be able to find icons in  an icon
	//!< factory. There will normally be an icon factory added for each library or application that
	//!< comes with icons. The default icon factories can be overridden by themes.

	void remove_default();
	//!< Removes the IconFactory from the list of default icon factories. 

//! @}
	
	static Pointer<IconSet> lookup_default(const char *stock_id);
	//!< Looks for an icon set in the list of default icon factories.
	//!< @param stock_id The icon name.
	//!< @return The icon set of stock_id.
	//!<
	//!< <BR>For display to the user, use Gtk::Style::lookup_icon_set() for the widget that
	//!< will display the icon instead of using this method directly, so that themes are
	//!< taken into account.
};

} // namespace Gtk

} // namespace Inti

#endif // INTI_GTK_ICON_FACTORY_H

