/*  Inti: Integrated Foundation Classes
 *  Copyright (C) 2002 The Inti Development Team.
 *  Copyright (C) 2000 Red Hat, Inc.
 *
 *  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/button.h
//! @brief A GtkButton C++ wrapper interface.
//!
//! Provides Button, a widget which is generally used to attach a function to that
//! is called when the button is pressed.

#ifndef INTI_GTK_BUTTON_H
#define INTI_GTK_BUTTON_H

#ifndef INTI_GTK_BIN_H
#include <inti/gtk/bin.h>
#endif

#ifndef __GTK_BUTTON_H__
#include <gtk/gtkbutton.h>
#endif

#ifndef __GTK_STOCK_H__
#include <gtk/gtkstock.h>
#endif

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

namespace Inti {

namespace Gtk {

class ButtonClass;
class Image;

//! @class Button button.h inti/gtk/button.h
//! @brief A GtkButton C++ wrapper class.
//!
//! The Button widget is generally used to attach a function to that is called when
//! the button is pressed. The Button widget can hold any valid child widget. That
//! is it can hold most any other standard Widget. The most commonly used child is
//! the Label.

class Button : public Bin
{
	friend class G::Object;
	friend class ButtonClass;

	Button(const Button&);
	Button& operator=(const Button&);

protected:
//! @name Constructors
//! @{

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

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

	bool depresssed() const;
	//!< Returns true if the button is depressed.

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

	void set_depressed(bool depressed);
	//!< Sets whether the button is currently drawn as down or not.
	//!< @param depressed Set <EM>true</EM> if the button should be drawn with a recessed shadow.
	//!<
	//!< <BR>This is purely a visual setting, and is meant only for use by derived widgets.

//! @}
//! @name Signal Handlers
//! @{

	virtual void on_pressed();
	//!< Called when the button is initially pressed.

	virtual void on_released();
	//!< Called when a button which is pressed is released, no matter where the mouse cursor is. 

	virtual void on_clicked();
	//!< Called when a button clicked on by the mouse and the cursor stays on the button. If the
	//!< cursor is not on the button when the mouse button is released, the signal is not emitted.

	virtual void on_enter();
	//!< Called when the mouse cursor enters the region of the button.

	virtual void on_leave();
	//!< Called when the mouse cursor leaves the region of the button.

	virtual void on_activate();
	//!< Called when the button is activated.
	
//! @}
//  Properties

	typedef G::Property<String> LabelPropertyType;
	typedef G::PropertyProxy<G::Object, LabelPropertyType> LabelPropertyProxy;
	static const LabelPropertyType label_property;

	typedef G::Property<bool> UseUnderlinePropertyType;
	typedef G::PropertyProxy<G::Object, UseUnderlinePropertyType> UseUnderlinePropertyProxy;
	static const UseUnderlinePropertyType use_underline_property;

	typedef G::Property<bool> UseStockPropertyType;
	typedef G::PropertyProxy<G::Object, UseStockPropertyType> UseStockPropertyProxy;
	static const UseStockPropertyType use_stock_property;

	typedef G::Property<ReliefStyle, int> ReliefPropertyType;
	typedef G::PropertyProxy<G::Object, ReliefPropertyType> ReliefPropertyProxy;
	static const ReliefPropertyType relief_property;

//  Signals

	typedef G::Signal0<void> PressedSignalType;
	typedef G::SignalProxy<TypeInstance, PressedSignalType> PressedSignalProxy;
	static const PressedSignalType pressed_signal;

	typedef G::Signal0<void> ReleasedSignalType;
	typedef G::SignalProxy<TypeInstance, ReleasedSignalType> ReleasedSignalProxy;
	static const ReleasedSignalType released_signal;

	typedef G::Signal0<void> ClickedSignalType;
	typedef G::SignalProxy<TypeInstance, ClickedSignalType> ClickedSignalProxy;
	static const ClickedSignalType clicked_signal;

	typedef G::Signal0<void> EnterSignalType;
	typedef G::SignalProxy<TypeInstance, EnterSignalType> EnterSignalProxy;
	static const EnterSignalType enter_signal;

	typedef G::Signal0<void> LeaveSignalType;
	typedef G::SignalProxy<TypeInstance, LeaveSignalType> LeaveSignalProxy;
	static const LeaveSignalType leave_signal;

	typedef G::Signal0<void> ActivateSignalType;
	typedef G::SignalProxy<TypeInstance, ActivateSignalType> ActivateSignalProxy;
	static const ActivateSignalType activate_signal;

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

	Button();
	//!< Constructs an empty Button widget.

	explicit Button(Image& image);
	//!< Constructs a Button widget that contains an Image.
	//!< @param image The Image you want the Button to contain.

	explicit Button(const String& label, bool use_underline = false);
	//!< Constructs a Button widget with a Label child containing the given label.
	//!< @param label The text you want the Label to hold.
	//!< @param use_underline Set <EM>true</EM> if label contains a mnemonic character.
	//!<
	//!< <BR>If characters in label are preceded by an underscore, they are underlined.
	//!< If you need a literal underscore character in a label, use '__' (two underscores). 
	//!< The first underlined character represents a keyboard accelerator called a mnemonic. 
	//!< Pressing Alt and that key activates the button.

	Button(Image& image, const String& label, bool use_underline = false, bool horizontal = false);
	//!< Sets the image and label for the button.
	//!< @param image The Image you want the button to display.
	//!< @param label The text you want the button to display.
	//!< @param use_underline Set <EM>true</EM> if an underline in the label indicates a mnemonic.
	//!< @param horizontal Set <EM>true</EM> if the image and label should be beside each other.
	//!<
	//!< <BR>This constructor lets you display an image and a label inside a button, like a
	//!< toolbar button does. If <EM>horizontal</EM> is true the label is displayed beside the
	//!< image. If <EM>horizontal</EM> is false the label is displayed underneath the image.

	virtual ~Button();
	//!< Destructor.

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

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

	GtkButtonClass* gtk_button_class() const;
	//!< Get a pointer to the GtkButtonClass structure.

	operator GtkButton* () const;
	//!< Conversion operator; safely converts a Button to a GtkButton pointer.

	ReliefStyle get_relief() const;
	//!< Returns the current relief style of the Button.

	String get_label() const;
	//!< Fetches the text from the label of the button, as set by set_label().
	//!< @return The text of the label widget.
	//!<
	//!< <BR>If the label text has not been set the return value will be a null String.
	//!< This will be the case if you create an empty button to use as a container.

	bool get_use_underline() const;
	//!< Returns true if an embedded underline in the button label indicates a mnemonic (see set_use_underline()).
	
	bool get_use_stock() const;
	//!< Returns whether the button label is a stock item.
	//!< @return <EM>true</EM> if the button label is used to select a stock item
	//!<         instead of being used directly as the label text.

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

	void pressed();
	//!< Emits a Button::pressed_signal to the calling Button.

	void released();
	//!< Emits a Button::released_signal to the calling Button.

	void clicked();
	//!< Emits a Button::clicked_signal to the calling Button.

	void enter();
	//!< Emits a Button::enter_signal to the calling Button.

	void leave();
	//!< Emits a Button::leave_signal to the calling Button.

	void set_relief(ReliefStyle newstyle);
	//!< Sets the relief style of the edges of the Button.
	//!< @param newstyle The ReliefStyle to set.
	//!<
	//!< <BR>Three styles exist, RELIEF_NORMAL, RELIEF_HALF, RELIEF_NONE. The default style is,
	//!< as one can guess, RELIEF_NORMAL.

	void set_label(const String& label);
	//!< Sets the text of the label of the button to label.
	//!< @param label A String.
	//!<
	//!< <BR>This method will clear any previously set label. The text is also used to select
	//!< the stock item if set_use_stock() is used.

	void set_use_underline(bool use_underline);
	//!< Sets whether an underline in the text of the button label indicates the next character
	//!< should be used for the mnemonic accelerator key.
	//!< @param use_underline Set <EM>true</EM> if an underline in the text indicates a mnemonic.

	void set_use_stock(bool use_stock);
	//!< Sets whether the label set on the button is used as a stock id to select
	//!< the stock item for the button.
	//!< @param use_stock Set <EM>true</EM> if the button should use a stock item.

	void set_image(Image& image, const String& label, bool use_underline = false, bool horizontal = false);
	//!< Sets the image and label for the button.
	//!< @param image The Image you want the button to display.
	//!< @param label The text you want the button to display.
	//!< @param use_underline Set <EM>true</EM> if an underline in the label indicates a mnemonic.
	//!< @param horizontal Set <EM>true</EM> if the image and label should be beside each other.
	//!<
	//!< <BR>This is a convenience method that lets you display an image and a label inside a
	//!< button, like a toolbar button does. If <EM>horizontal</EM> is true the label is
	//!< displayed beside the image. If <EM>horizontal</EM> is false the label is displayed
	//!< underneath the image. This method will clear any previously set image or label.

//! @}
//! @name Property Proxies
//! @{

	const LabelPropertyProxy prop_label()
	{
		return LabelPropertyProxy(this, &label_property);
	}
	//!< Text of the label widget inside the button, if the button contains a Label (String : Read / Write).

	const UseUnderlinePropertyProxy prop_use_underline()
	{
		return UseUnderlinePropertyProxy(this, &use_underline_property);
	}
	//!< The border relief style (ReliefStyle : Read / Write).

	const UseStockPropertyProxy prop_use_stock()
	{
		return UseStockPropertyProxy(this, &use_stock_property);
	}
	//!< If set, an underline in the text indicates the next character should be used for
	//!< the mnemonic accelerator key (bool : Read / Write).

	const ReliefPropertyProxy prop_relief()
	{
		return ReliefPropertyProxy(this, &relief_property);
	}
	//!< If set, the label is used to pick a stock item instead of being displayed (bool : Read / Write).

//! @}
//! @name Signal Proxies
//! @{
	
	const PressedSignalProxy sig_pressed()
	{
		return PressedSignalProxy(this, &pressed_signal);
	}
	//!< Connect to the pressed_signal; emitted when the button is initially pressed.

	const ReleasedSignalProxy sig_released()
	{
		return ReleasedSignalProxy(this, &released_signal);
	}
	//!< Connect to the released_signal; emitted when a button which is pressed is released,
	//!< no matter where the mouse cursor is.

	const ClickedSignalProxy sig_clicked()
	{
		return ClickedSignalProxy(this, &clicked_signal);
	}
	//!< Connect to the clicked_signal; emitted when a button clicked on by the mouse
	//!< and the cursor stays on the button. If the cursor is not on the button when
	//!< the mouse button is released, the signal is not emitted.

	const EnterSignalProxy sig_enter()
	{
		return EnterSignalProxy(this, &enter_signal);
	}
	//!< Connect to the enter_signal; emitted when the mouse cursor enters the region of the button.

	const LeaveSignalProxy sig_leave()
	{
		return LeaveSignalProxy(this, &leave_signal);
	}
	//!< Connect to the leave_signal; emitted when the mouse cursor leaves the region of the button.

	const ActivateSignalProxy sig_activate()
	{
		return ActivateSignalProxy(this, &activate_signal);
	}
	//!< Connect to the activate_signal; emitted when the button is activated.

//! @}
};

//! @class StockButton button.h inti/gtk/button.h
//! @brief A stock GtkButton C++ wrapper class.
//!
//! The StockButton widget is a button that displays the image and text from a stock item.

class StockButton : public Button
{
public:
//! @name Constructors
//! @{

	explicit StockButton(const char *stock_id);
	//!< Constructs a new Button containing the image and text from a stock item.
	//!< @param stock_id The name of the stock item.
	//!<
	//!< <BR>Some stock ids have preprocessor macros like GTK_STOCK_OK and GTK_STOCK_APPLY.
	//!< If stock_id is unknown, then it will be treated as a mnemonic label.

//! @}
};

} // namespace Gtk

} // namespace Inti

#endif // INTI_GTK_BUTTON_H

