/*  Inti: Integrated Foundation Classes
 *  Copyright (C) 2002-2003 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/entry.h
//! @brief A GtkEntry C++ wrapper interface.
//!
//! Provides Entry, a single line text entry widget.

#ifndef INTI_GTK_ENTRY_H
#define INTI_GTK_ENTRY_H

#ifndef INTI_GTK_EDITABLE_H
#include <inti/gtk/editable.h>
#endif

#ifndef INTI_GTK_CELL_EDITABLE_H
#include <inti/gtk/celleditable.h>
#endif

#ifndef INTI_GTK_WIDGET_H
#include <inti/gtk/widget.h>
#endif

#ifndef __GTK_ENTRY_H__
#include <gtk/gtkentry.h>
#endif

namespace Inti {

namespace G {
class Unichar;
}

namespace Pango {
class Layout;
}

namespace Gtk {

class EntryClass;
class Menu;

//! @class Entry entry.h inti/gtk/entry.h
//! @brief A GtkEntry C++ wrapper class.
//!
//! The Entry widget is a single line text entry widget. A fairly large set of key bindings are
//! supported by default. If the entered text is longer than the allocation of the widget, the
//! widget will scroll so that the cursor position is visible. Entry implements the Editable and
//!< CellEditable interfaces

class Entry : public Widget, public Editable, public CellEditable
{
	friend class G::Object;
	friend class EntryClass;

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

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

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

	virtual void on_populate_popup(Menu& menu);
	//!< Called when the Entry displays its context-sensitive menu.
	//!< @param menu The popup menu.

	virtual void on_activate();
	//!< Called when the Entry is activated by pressing the enter key.
	
	virtual void on_insert_at_cursor(const String& text);
	//!< Called when text is inserted into the Entry at the current cursor position.
	//!< @param text The new text to insert.

//! @}
//  Properties

	typedef G::ReadableProperty<int> CursorPositionPropertyType;
	typedef G::PropertyProxy<G::Object, CursorPositionPropertyType> CursorPositionPropertyProxy;
	static const CursorPositionPropertyType cursor_position_property;

	typedef G::ReadableProperty<int> SelectionBoundPropertyType;
	typedef G::PropertyProxy<G::Object, SelectionBoundPropertyType> SelectionBoundPropertyProxy;
	static const SelectionBoundPropertyType selection_bound_property;

	typedef G::Property<bool> EditablePropertyType;
	typedef G::PropertyProxy<G::Object, EditablePropertyType> EditablePropertyProxy;
	static const EditablePropertyType editable_property;

	typedef G::Property<int> MaxLengthPropertyType;
	typedef G::PropertyProxy<G::Object, MaxLengthPropertyType> MaxLengthPropertyProxy;
	static const MaxLengthPropertyType max_length_property;

	typedef G::Property<bool> VisibilityPropertyType;
	typedef G::PropertyProxy<G::Object, VisibilityPropertyType> VisibilityPropertyProxy;
	static const VisibilityPropertyType visibility_property;

	typedef G::Property<bool> HasFramePropertyType;
	typedef G::PropertyProxy<G::Object, HasFramePropertyType> HasFramePropertyProxy;
	static const HasFramePropertyType has_frame_property;

	typedef G::Property<gunichar, unsigned int> InvisibleCharPropertyType;
	typedef G::PropertyProxy<G::Object, InvisibleCharPropertyType> InvisibleCharPropertyProxy;
	static const InvisibleCharPropertyType invisible_char_property;

	typedef G::Property<bool> ActivatesDefaultPropertyType;
	typedef G::PropertyProxy<G::Object, ActivatesDefaultPropertyType> ActivatesDefaultPropertyProxy;
	static const ActivatesDefaultPropertyType activates_default_property;

	typedef G::Property<int> WidthCharsPropertyType;
	typedef G::PropertyProxy<G::Object, WidthCharsPropertyType> WidthCharsPropertyProxy;
	static const WidthCharsPropertyType width_chars_property;

	typedef G::ReadableProperty<int> ScrollOffsetPropertyType;
	typedef G::PropertyProxy<G::Object, ScrollOffsetPropertyType> ScrollOffsetPropertyProxy;
	static const ScrollOffsetPropertyType scroll_offset_property;

	typedef G::Property<String> TextPropertyType;
	typedef G::PropertyProxy<G::Object, TextPropertyType> TextPropertyProxy;
	static const TextPropertyType text_property;

//  Signals

	typedef G::Signal1<void, GtkMenu*> PopulatePopupSignalType;
	typedef G::SignalProxy<TypeInstance, PopulatePopupSignalType> PopulatePopupSignalProxy;
	static const PopulatePopupSignalType populate_popup_signal;

	typedef G::Signal0<void> ActviateSignalType;
	typedef G::SignalProxy<TypeInstance, ActviateSignalType> ActviateSignalProxy;
	static const ActviateSignalType activate_signal;
	
	typedef G::Signal1<void, const char*> InsertAtCursorSignalType;
	typedef G::SignalProxy<TypeInstance, InsertAtCursorSignalType> InsertAtCursorSignalProxy;
	static const InsertAtCursorSignalType insert_at_cursor_signal;

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

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

	explicit Entry(int max_length);
	//!< Construct a new Entry that accepts at most max_length characters.
	//!< @param max_length The maximum length of the entry, or 0 for no maximum.
	//!<
	//!< <BR>The value passed <EM>max_length</EM> in will be clamped to the range 0-65536.

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

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

	GtkEntryClass* gtk_entry_class() const;
	//!< Get a pointer to the GtkEntryClass structure.

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

	String get_text() const;
	//!< Retrieves the contents of the widget (see also Gtk::Editable::get_chars()).
	//!< @return A String that contains the contents of the widget.

	bool get_visibility() const;
	//!< Returns true if the text in the widget is visible (see set_visibility()).
	
	G::Unichar get_invisible_char() const;
	//!< Retrieves the character displayed in place of the real characters for entries with
	//!< visisbility set to false (see set_invisible_char()).
	//!< @return The current invisible char, or 0, if the entry does not show invisible text at all.

	bool get_has_frame() const;
	//!< Returns true if the entry has a beveled frame (see set_has_frame()).

	bool get_activates_default() const;
	//!< Returns true if the entry will activate the default widget (see set_activates_default()).

	int get_width_chars() const;
	//!< Retrieves the number of chars to request space for, or negative if unset (see set_width_chars()).

	int get_max_length() const;
	//!< Returns the maximum allowed length of the text in the Entry, or 0 if there is no maximum
	//!< (see set_max_length()).
	
	Pango::Layout* get_layout() const;
	//!< Gets the Pango::Layout used to display the entry. 
	//!< @return The PangoLayout for this entry.
	//!<
	//!< <BR>The layout is useful to e.g. convert text positions to pixel positions, in
	//!< combination with get_layout_offsets(). The returned layout is owned by the entry
	//!< and must not be unreferenced by the caller.

	void get_layout_offsets(int *x, int *y) const;
	//!< Obtains the position of the Pango::Layout used to render text in the entry,
	//!< in widget coordinates. 
	//!< @param x The location to store the X offset of the layout, or null.
	//!< @param y The location to store the Y offset of the layout, or null.
	//!<
	//!< <BR>Useful if you want to line up the text in an entry with some other text, e.g.
	//!< when using the entry to implement editable cells in a sheet widget. Also useful
	//!< to convert mouse events into coordinates inside the Pango::Layout, e.g. to take
	//!< some action if some part of the entry text is clicked.

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

	void set_visibility(bool visible);
	//!< Sets whether the contents of the entry are visible or not. 
	//!< @param visible <EM>true</EM> if the contents of the entry are displayed as plain text.
	//!<
	//!< <BR>When visibility is set to false, characters are displayed as the invisible
	//!< char, and will also appear that way when the text in the entry widget is copied
	//!< elsewhere. The default invisible char is the asterisk '*', but it can be changed
	//!< with set_invisible_char().
	
	void set_invisible_char(G::Unichar ch);
	//!< Sets the character to use in place of the actual text when set_visibility() has been
	//!< called to set text visibility to false.
	//!< @param ch A Unicode character.
	//!<
	//!< <BR>The <EM>ch</EM> character is used in "password mode" to show the user how many
	//!< characters have been typed. The default invisible char is an asterisk ('*'). If
	//!< you set the invisible char to 0, then the user will get no feedback at all; there
	//!< will be no text on the screen as they type.
	
	void set_has_frame(bool setting);
	//!< Sets whether the entry has a beveled frame around it.
	//!< @param setting The new value.
	
	void set_max_length(int max);
	//!< Sets the maximum allowed length of the contents of the widget. 
	//!< @param max The maximum length of the entry, or 0 for no maximum.
	//!<
	//!< <BR>The value passed in will be clamped to the range 0-65536. If the current contents
	//!< are longer than the given length, then they will be truncated to fit.

	void set_text(const String& text);
	//!< Sets the text in the widget to the given value, replacing the current contents.
	//!< @param text The new text.

	void set_activates_default(bool setting);
	//!< If setting is true, pressing Enter in the entry will activate the default widget
	//!< for the window containing the entry.
	//!< @param setting <EM>true</EM> to activate the default widget on Enter keypress.
	//!<
	//!< <BR>If setting is true, this usually means that the dialog box containing the entry
	//!< will be closed, since the default widget is usually one of the dialog buttons.

	void set_width_chars(int n_chars);
	//!< Changes the size request of the entry to be about the right size for n_chars characters.
	//!< @param n_chars The width in chars.
	//!<
	//!< <BR>Note that this method changes the size request, the size can still be affected by how
	//!< you pack the widget into containers. If n_chars is -1, the size reverts to the default
	//!< entry size.

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

	const CursorPositionPropertyProxy prop_cursor_position()
	{
		return CursorPositionPropertyProxy(this, &cursor_position_property);
	}
	//!< The current position of the insertion cursor in chars (int : Read).

	const SelectionBoundPropertyProxy prop_selection_bound()
	{
		return SelectionBoundPropertyProxy(this, &selection_bound_property);
	}
	//!< The position of the opposite end of the selection from the cursor in chars (int : Read).

	const EditablePropertyProxy prop_editable()
	{
		return EditablePropertyProxy(this, &editable_property);
	}
	//!< Whether the entry contents can be edited (bool : Read / Write).

	const MaxLengthPropertyProxy prop_max_length()
	{
		return MaxLengthPropertyProxy(this, &max_length_property);
	}
	//!< Maximum number of characters for this entry. Zero if no maximum (int : Read / Write).

	const VisibilityPropertyProxy prop_visibility()
	{
		return VisibilityPropertyProxy(this, &visibility_property);
	}
	//!< Set false to display the "invisible char" instead of the actual text in password mode (bool : Read / Write).

	const HasFramePropertyProxy prop_has_frame()
	{
		return HasFramePropertyProxy(this, &has_frame_property);
	}
	//!< Set false to remove outside bevel from entry (bool : Read / Write).

	const InvisibleCharPropertyProxy prop_invisible_char()
	{
		return InvisibleCharPropertyProxy(this, &invisible_char_property);
	}
	//!< The character to use when masking entry contents in "password mode" (unsigned int : Read / Write).

	const ActivatesDefaultPropertyProxy prop_activates_default()
	{
		return ActivatesDefaultPropertyProxy(this, &activates_default_property);
	}
	//!< Whether to activate the default widget (such as the default button in a dialog)
	//!< when Enter is pressed (bool : Read / Write)

	const WidthCharsPropertyProxy prop_width_chars()
	{
		return WidthCharsPropertyProxy(this, &width_chars_property);
	}
	//!< Number of characters to leave space for in the entry (int : Read / Write).

	const ScrollOffsetPropertyProxy prop_scroll_offset()
	{
		return ScrollOffsetPropertyProxy(this, &scroll_offset_property);
	}
	//!< Number of pixels of the entry scrolled off the screen to the left (int : Read).

	const TextPropertyProxy prop_text()
	{
		return TextPropertyProxy(this, &text_property);
	}
	//!< The contents of the entry (String : Read / Write).

//! @}
//! @name Signal Proxies
//! @{

	const PopulatePopupSignalProxy sig_populate_popup()
	{
		return PopulatePopupSignalProxy(this, &populate_popup_signal);
	}
	//!< Connect to the populate_popup_signal; emitted when the Entry displays its context-sensitive menu.

	const ActviateSignalProxy sig_activate()
	{
		return ActviateSignalProxy(this, &activate_signal);
	}
	//!< Connect to the activate_signal; emitted when the Entry is activated by pressing the enter key.

	const InsertAtCursorSignalProxy sig_insert_at_cursor()
	{
		return InsertAtCursorSignalProxy(this, &insert_at_cursor_signal);
	}
	//!< Connect to the insert_at_cursor_signal; emitted when text is inserted into the Entry at the
	//!< current cursor position.

//! @}
};

} // namespace Gtk

} // namespace Inti

#endif // INTI_GTK_ENTRY_H

