/*  Inti: Integrated Foundation Classes
 *  Copyright (C) 2002 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/combo.h
//! @brief A GtkCombo C++ wrapper interface.

#ifndef INTI_GTK_COMBO_H
#define INTI_GTK_COMBO_H

#ifndef INTI_GTK_HBOX_H
#include <inti/gtk/box.h>
#endif

#ifndef __GTK_SMART_COMBO_H__
#include <gtk/gtkcombo.h>
#endif

namespace Inti {

namespace Gtk {
	
class Button;
class ComboClass;
class Entry;
class Item;
class ScrolledWindow;
class Window;

//! @class Combo combo.h inti/gtk/combo.h
//! @brief A GtkCombo C++ wrapper class.
//!
//! The Combo widget consists of a single-line text entry field and a drop-down list.
//! The drop-down list is displayed when the user clicks on a small arrow button to
//! the right of the entry field. The drop-down list is a GtkList widget and can be
//! accessed as a Widget not a List, using the list() method of the Combo. The GtkList
//! widget is deprecated and not wrapped in Inti. GtkList elements can contain
//! arbitrary widgets, but if an element is not a plain label, then you must use the
//! gtk_list_set_item_string() function. This sets the string which will be placed in
//! the text entry field when the item is selected.
//!
//! By default, the user can step through the items in the list using the arrow (cursor)
//! keys, though this behaviour can be turned off with set_use_arrows(). Normally the
//! arrow keys are only active when the contents of the text entry field matches one of
//! the items in the list. If the contents of the entry field do not match any of the
//! list items, then pressing the arrow keys does nothing. However, by calling 
//! set_use_arrows_always() you can specify that the arrow keys are always active. If
//! the contents of the entry field does not match any of the items in the list, then 
//! pressing the up or down arrow key will set the entry field to the last or first 
//! item in the list, respectively.
//! 
//! <B>Example:</B> Creating a Combo widget with simple text items.
//! @code
//! std::vector<String> items;
//! items.push_back("First Item");
//! items.push_back("Second Item");
//! items.push_back("Third Item");
//! items.push_back("Fourth Item");
//! items.push_back("Fifth Item");
//!
//! Gtk::Combo *combo = new Gtk::Combo;
//! combo->set_popdown_strings(items);
//! add(*combo);
//! @endcode

class Combo : public HBox
{
	friend class G::Object;
	friend class ComboClass;

	Combo(const Combo&);
	Combo& operator=(const Combo&);

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

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

//! @}
//  Properties

	typedef G::Property<bool> EnableArrowKeysPropertyType;
	typedef G::PropertyProxy<G::Object, EnableArrowKeysPropertyType> EnableArrowKeysPropertyProxy;
	static const EnableArrowKeysPropertyType enable_arrow_keys_property;

	typedef G::Property<bool> EnableArrowsAlwaysPropertyType;
	typedef G::PropertyProxy<G::Object, EnableArrowsAlwaysPropertyType> EnableArrowsAlwaysPropertyProxy;
	static const EnableArrowsAlwaysPropertyType enable_arrows_always_property;

	typedef G::Property<bool> CaseSensitivePropertyType;
	typedef G::PropertyProxy<G::Object, CaseSensitivePropertyType> CaseSensitivePropertyProxy;
	static const CaseSensitivePropertyType case_sensitive_property;

	typedef G::Property<bool> AllowEmptyPropertyType;
	typedef G::PropertyProxy<G::Object, AllowEmptyPropertyType> AllowEmptyPropertyProxy;
	static const AllowEmptyPropertyType allow_empty_property;

	typedef G::Property<bool> ValueInListPropertyType;
	typedef G::PropertyProxy<G::Object, ValueInListPropertyType> ValueInListPropertyProxy;
	static const ValueInListPropertyType value_in_list_property;

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

	Combo();
	//!< Construct a new Combo.
	
	virtual ~Combo();
	//!< Destructor.
	
//! @}
//! @name Accessors
//! @{

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

	GtkComboClass* gtk_combo_class() const;
	//!< Get a pointer to the GtkComboClass structure.

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

	Entry* entry() const;
	//!< Returns the Entry widget that displays the selected text entry.

	Widget* list() const;
	//!< Returns the drop down list as a Gtk::Widget because GtkList and GtkListItem
	//!< are deprecated and not wrapped in Inti.

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

	void set_value_in_list(bool value_in_list, bool ok_if_empty);
	//!< Specifies whether the value entered in the text entry field must match one of
	//!< the values in the list. 
	//!< @param value_in_list <EM>true</EM> if the value entered must match one of the values in the list.
	//!< @param ok_if_empty <EM>true</EM> if an empty value is considered valid.
	//!<
	//!< <BR>If this is set then the user will not be able to perform any other action until
	//!< a valid value has been entered. If an empty field is acceptable, the ok_if_empty
	//!< parameter should be <EM>true</EM>.
	
	void set_use_arrows(bool use_arrows);
	//!< Specifies if the arrow (cursor) keys can be used to step through the items
	//!< in the list; this is on by default.
	//!< @param use_arrows <EM>true</EM> if the arrow keys can be used to step through the list items.
	
	void set_use_arrows_always(bool use_arrows_always);
	//!< Specifies if the arrow keys will still work even if the current contents of
	//!< the Entry field do not match any of the list items.
	//!< @param use_arrows_always <EM>true</EM> if the arrow keys should still work.

	void set_case_sensitive(bool case_sensitive);
	//!< Specifies whether the text entered into the Entry field and the text in the
	//!< list items is case sensitive.
	//!< @param case_sensitive <EM>true</EM> if the text in the list items is case sensitive.
	//!<
	//!< <BR>This may be useful, for example, when you have called set_value_in_list()
	//!< to limit the values entered, but you are not worried about differences in case.

	void set_item_string(Item& item, const String& item_value);
	//!< Sets the string to place in the Entry field when a particular list item is selected.
	//!< @param item A Gtk::Item.
	//!< @param item_value The string to place in the Entry when item is selected.
	//!<
	//!< <BR>Call this method if the list item is not a simple label or you want a different
	//!< value displayed in the entry.

	void set_popdown_strings(const std::vector<String>& strings);
	//!< Convenience method to set all of the items in the popup list. (See the example above.)
	//!< @param strings A vector of Strings.
	
	void disable_activate();
	//!< Stops the Combo widget from showing the popup list when the Entry emits the "activate"
	//!< signal, i.e. when the Return key is pressed. 
	//!< This may be useful if, for example, you want the Return key to close a dialog instead.

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

	const EnableArrowKeysPropertyProxy prop_enable_arrow_keys()
	{
		return EnableArrowKeysPropertyProxy(this, &enable_arrow_keys_property);
	}
	//!< Whether the arrow keys move through the list of items (bool : Read / Write).

	const EnableArrowsAlwaysPropertyProxy prop_enable_arrows_always()
	{
		return EnableArrowsAlwaysPropertyProxy(this, &enable_arrows_always_property);
	}
	//!< Whether the arrow keys work, even if the entry contents are not in the list (bool : Read / Write).

	const CaseSensitivePropertyProxy prop_case_sensitive()
	{
		return CaseSensitivePropertyProxy(this, &case_sensitive_property);
	}
	//!< Whether list item matching is case sensitive (bool : Read / Write).

	const AllowEmptyPropertyProxy prop_allow_empty()
	{
		return AllowEmptyPropertyProxy(this, &allow_empty_property);
	}
	//!< Whether an empty value may be entered in this field (bool : Read / Write).

	const ValueInListPropertyProxy prop_value_in_list()
	{
		return ValueInListPropertyProxy(this, &value_in_list_property);
	}
	//!< Whether entered values must already be present in the list (bool : Read / Write).

//! @}
};

} // namespace Gtk

} // namespace Inti

#endif // INTI_GTK_COMBO_H


