/*  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/label.h
//! @brief A GtkLabel C++ wrapper interface.
//!
//! Provides Label, a widget that displays a small amount of text. As the name implies,
//! most labels are used to label another widget such as a Button, a MenuItem, or an
//! OptionMenu.

#ifndef INTI_GTK_LABEL_H
#define INTI_GTK_LABEL_H

#ifndef INTI_GTK_MISC_H
#include <inti/gtk/misc.h>
#endif

#ifndef __GTK_LABEL_H__
#include <gtk/gtklabel.h>
#endif

namespace Inti {

namespace Pango {
class AttrList;
class Layout;
}

namespace Gtk {

class LabelClass;
class Menu;

//! @class Label label.h inti/gtk/label.h
//! @brief A GtkLabel C++ wrapper class.
//!
//! The Label widget displays a small amount of text. As the name implies, most labels
//! are used to label another widget such as a Button, a MenuItem, or an OptionMenu.
//!
//! <B>Mnemonics</B>
//!
//! Labels may contain mnemonics. Mnemonics are underlined characters in the label, used
//! for keyboard navigation. Mnemonics are created by providing a string with an underscore
//! before the mnemonic character, such as "_File". Constructors and methods that can handle
//! mnemonics have a bool argument <EM>use_underline</EM> to indicate whether or not the
//! string has a mnemonic character. 
//! 
//! Mnemonics automatically activate any activatable widget the label is inside, such as a
//! Button; if the label is not inside the mnemonic's target widget, you have to tell the
//! label about the target using Gtk::Label::set_mnemonic_widget(). Here's a simple example
//! where the label is inside a button:
//! @code
//! // Pressing Alt+H will activate this button
//! Gtk::Button *button = new Gtk::Button("_Hello", true);
//! @endcode
//!
//! To create a mnemonic for a widget alongside the label, such as an Entry, you have to point
//! the label at the entry with Gtk::Label::set_mnemonic_widget():
//! @code
//! // Pressing Alt+H will activate this button
//! Gtk::Entry *entry = new Gtk::Entry;
//! Gtk::Label *label = new Gtk::Label("_Hello", true);
//! label->set_mnemonic_widget(entry);
//! @endcode
//!
//! <B>Markup (styled text)</B>
//!
//! To make it easy to format text in a label (changing colors, fonts, etc.), label text can be
//! provided in a simple markup format. Here's how to create a label with a small font:
//! @code
//! Gtk::Label *label = new Gtk::Label;
//! label->set_markup("<small>Small text</small>");
//! @endcode
//!
//! (See complete documentation of available tags in the Pango manual.)
//! The markup passed to set_markup() must be valid; for example, literal </>/& characters must be
//! escaped as &lt;, &gt;, and &amp;. If you pass text obtained from the user, file, or a network
//! to set_markup(), you'll want to escape it with g_markup_escape_text(). Markup strings are just
//! a convenient way to set the Pango::AttrList on a label; set_attributes() may be a simpler way to
//! set attributes in some cases. Be careful though; Pango::AttrList tends to cause internationalization
//! problems, unless you're applying attributes to the entire string (i.e. unless you set the range of
//! each attribute to [0, G_MAXINT)). The reason is that specifying the start_index and end_index for
//! a Pango::Attribute requires knowledge of the exact string being displayed, so translations will cause
//! problems.
//!
//! <B>Selectable labels</B>
//!
//! Labels can be made selectable with Gtk::Label::set_selectable(). Selectable labels allow the user to
//! copy the label contents to the clipboard. Only labels that contain useful-to-copy information - such
//! as error messages - should be made selectable.
//!
//! <B>Text layout</B>
//!
//! A label can contain any number of paragraphs, but will have performance problems if it contains more
//! than a small number. Paragraphs are separated by newlines or other paragraph separators understood by
//! Pango. Labels can automatically wrap text if you call set_line_wrap(). set_justify() sets how the 
//! lines in a label align with one another. If you want to set how the label as a whole aligns in its
//! available space, see Gtk::Misc::set_alignment().

class Label : public Misc
{
	friend class G::Object;
	friend class LabelClass;

	Label(const Label&);
	Label& operator=(const Label&);

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

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

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

	virtual void on_move_cursor(MovementStep step, int count, bool extend_selection);
	//!< Called when the cursor is moved using the arrow keys.
	//!< @param step The type of cursor movment.
	//!< @param count The number of characters the cursor moved.
	//!< @param extend_selection <EM>true</EM> if the current selection is being extended.
	//!<
	//!< <BR>A count of -1 indicates that the cursor position is being set after the last
	//!< character in the label.

	virtual void on_copy_clipboard();
	//!< Called when the characters in the current selection are to be copied to the clipboard.

	virtual void on_populate_popup(Menu& menu);
	//!< Called just before the popup menu is displayed in response the a right-click on a selectable label.
	//!< @param menu The popup menu.

//! @}
//  Properties

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

	typedef G::Property<Pointer<Pango::AttrList> > AttributesPropertyType;
	typedef G::PropertyProxy<G::Object, AttributesPropertyType> AttributesPropertyProxy;
	static const AttributesPropertyType attributes_property;

	typedef G::Property<bool> UseMarkupPropertyType;
	typedef G::PropertyProxy<G::Object, UseMarkupPropertyType> UseMarkupPropertyProxy;
	static const UseMarkupPropertyType use_markup_property;

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

	typedef G::Property<Justification, int> JustifyPropertyType;
	typedef G::PropertyProxy<G::Object, JustifyPropertyType> JustifyPropertyProxy;
	static const JustifyPropertyType justify_property;

	typedef G::WritableProperty<String> PatternPropertyType;
	typedef G::PropertyProxy<G::Object, PatternPropertyType> PatternPropertyProxy;
	static const PatternPropertyType pattern_property;

	typedef G::Property<bool> WrapPropertyType;
	typedef G::PropertyProxy<G::Object, WrapPropertyType> WrapPropertyProxy;
	static const WrapPropertyType wrap_property;

	typedef G::Property<bool> SelectablePropertyType;
	typedef G::PropertyProxy<G::Object, SelectablePropertyType> SelectablePropertyProxy;
	static const SelectablePropertyType selectable_property;

	typedef G::ReadableProperty<unsigned int> MnemonicKeyvalPropertyType;
	typedef G::PropertyProxy<G::Object, MnemonicKeyvalPropertyType> MnemonicKeyvalPropertyProxy;
	static const MnemonicKeyvalPropertyType mnemonic_keyval_property;

	typedef G::Property<Widget*, G::Object*> MnemonicWidgetPropertyType;
	typedef G::PropertyProxy<G::Object, MnemonicWidgetPropertyType> MnemonicWidgetPropertyProxy;
	static const MnemonicWidgetPropertyType mnemonic_widget_property;

	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;

//  Signals

	typedef G::Signal3<void, GtkMovementStep, int, bool> MoveCursorSignalType;
	typedef G::SignalProxy<TypeInstance, MoveCursorSignalType> MoveCursorSignalProxy;
	static const MoveCursorSignalType move_cursor_signal;

	typedef G::Signal0<void> CopyClipboardSignalType;
	typedef G::SignalProxy<TypeInstance, CopyClipboardSignalType> CopyClipboardSignalProxy;
	static const CopyClipboardSignalType copy_clipboard_signal;

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

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

	Label();
	//!< Construct an empty Label.

	explicit Label(const String& str, bool use_underline = false);
	//!< Construct a new Label with <EM>str</EM> as its text.
	//!< @param str The label text.
	//!< @param use_underline Set to <EM>true</EM> if <EM>str</EM> contains a mnemonic character.
	
	virtual ~Label();
	//!< Destructor.
	
//! @}
//! @name Accessors
//! @{

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

	GtkLabelClass* gtk_label_class() const;
	//!< Get a pointer to the GtkLabelClass structure.

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

	String get_text() const;
	//!< Fetches the text from a label widget, as displayed on the screen.
	//!< @return The text in the label widget.
	//!<
	//!< <BR>This does not include any embedded underlines indicating mnemonics or
	//!< Pango markup (see get_label()).

	Pointer<Pango::AttrList> get_attributes() const;
	//!< Gets the attribute list that was set on the label using set_attributes(), if any.
	//!< @return The attribute list, or null if none was set.
	//!<
	//!< <BR>This method does not reflect attributes that come from the label's markup (see set_markup()).
	//!< If you want to get the effective attributes for the label, use get_layout()->get_attributes().

	String get_label() const;
	//!< Fetches the text from a label widget including any embedded underlines
	//!< indicating mnemonics and Pango markup (see get_text()).
	//!< @return The text of the label widget. 
	
	bool get_use_markup() const;
	//!< Returns whether the label's text is interpreted as marked up with the 
	//!< Pango text markup language (see set_use_markup()).

	bool get_use_underline() const;
	//!< Returns whether an embedded underline in the label indicates a mnemonic
	//!< character key (see set_use_underline()).
	
	unsigned int get_mnemonic_keyval() const;
	//!< If the label has been set so that it has an mnemonic key this function returns
	//!< the keyval used for the mnemonic accelerator.
	//! @return The mnemonic accelerator if set, otherwise GDK_VoidSymbol.
	
	Widget* get_mnemonic_widget() const;
	//!< Retrieves the target of the mnemonic (keyboard shortcut) of this label (see set_mnemonic_widget()).
	//!< @return The target of the label's mnemonic, or null if none has been set.
	 
	Justification get_justify() const;
	//!< Returns the justification of the label (see set_justify()).

	bool get_line_wrap() const;
	//!< Returns whether lines in the label are automatically wrapped (see set_line_wrap()).

	bool get_selectable() const;
	//!< Gets the value set by set_selectable().
	//!< @return <EM>true</EM> if the user can copy text from the label.

	void get_layout_offsets(int *x, int *y) const;
	//!< Obtains the coordinates where the label will draw the Pango::Layout representing
	//!< the text in the label. 
	//!< @param x The location to store X offset of layout, or null.
	//!< @param y The Location to store Y offset of layout, or null.
	//!<
	//!< <BR>This method is useful to convert mouse events into coordinates inside the
	//!< Pango::Layout, e.g. to take some action if some part of the label is clicked.
	//!< Of course you will need to create an EventBox to receive the events, and pack
	//!< the label inside it, since labels are a NO_WINDOW widget. Remember when using
	//!< the Pango::Layout methods you need to convert to and from pixels using 
	//!< PANGO_PIXELS() or PANGO_SCALE.

	bool get_selection_bounds(int *start, int *end) const;
	//!< Gets the selected range of characters in the label.
	//!< @param start The location for start of selection, as a character offset.
	//!< @param end The location for end of selection, as a character offset.
	//!< @return <EM>true</EM> if there's a selection.
	
	Pango::Layout* get_layout() const;
	//!< Gets the Pango::Layout used to display the label. 
	//!< @return The Pango::Layout for the Label.
	//!<
	//!< <BR>The layout is useful to e.g. convert text positions to pixel positions, in
	//!< combination with Gtk::Label::get_layout_offsets(). The returned layout is owned
	//!< by the label.

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

	void set_text(const String& str);
	//!< Sets the text within the Label widget, overwriting any text that was there before.
	//!< @param str The text you want to set.
	//!<
	//!< <BR>Note this will also clear any previously set mnemonic accelerators.
	
	void set_attributes(Pango::AttrList& attrs);
	//!< Sets a Pango::AttrList; the attributes in the list are applied to the label text.
	//!< @param attrs A Pango::AttrList.
	//!<
	//!< <BR>The attributes set with this method will be ignored if the "use_underline" property
	//!< or the "use_markup" property is <EM>true</EM>.

	void set_markup(const String& str);
	//!< Parses str which is marked up with the Pango text markup language, setting the label's
	//!< text and attribute list based on the parse results.
	//!< @param str A markup string (see Pango markup format).

	void set_label(const String& str);
	//!< Sets the text of the label. The label is interpreted as including embedded underlines
	//!< and/or Pango markup depending on the values of use_underline() and use_markup().
	//!< @param str The new text to set for the label.

	void set_markup_with_mnemonic(const String& str);
	//!< Parses str which is marked up with the Pango text markup language, setting the label's
	//!< text and attribute list based on the parse results. 
	//!< @param str A markup string (see Pango markup format).
	//!<
	//!< <BR>If characters in str are preceded by an underscore, they are underlined 
	//!< indicating that they represent a keyboard accelerator called a mnemonic. The
	//!< mnemonic key can be used to activate another widget, chosen automatically,
	//!< or explicitly using Gtk::Label::set_mnemonic_widget().

	void set_mnemonic_widget(Widget *widget);
	//!< If the label has been set so that it has an mnemonic key (using the constructor, 
	//!< set_markup_with_mnemonic(), set_text_with_mnemonic(), or the "use_underline" property)
	//!< the label can be associated with a widget that is the target of the mnemonic. 
	//!< @param widget The target Widget.
	//!<
	//!< <BR>When the label is inside a widget (like a Button or a Notebook tab) it is
	//!< automatically associated with the correct widget, but sometimes (i.e. when the
	//!< target is a Entry next to the label) you need to set it explicitly using this
	//!< method. The target widget will be accelerated by emitting "mnemonic_activate"
	//!< on it. The default handler for this signal will activate the widget if there
	//!< are no mnemonic collisions and toggle focus between the colliding widgets
	//!< otherwise.

	void set_text_with_mnemonic(const String& str);
	//!< Sets the label's text from the string <EM>str</EM>. 
	//!< @param str A string.
	//!<
	//!< <BR>If characters in str are preceded by an underscore, they are underlined indicatin
	//!< that they represent a keyboard accelerator called a mnemonic. The mnemonic key can be
	//!< used to activate another widget, chosen automatically, or explicitly using 
	//!< set_mnemonic_widget().

	void set_justify(Justification jtype);
	//!< Sets the alignment of the lines in the text of the label relative to each other.
	//!< @param jtype A Justification.
	//!< JUSTIFY_LEFT is the default value when the widget is first created. If you instead
	//!< want to set the alignment of the label as a whole, use Gtk::Misc::set_alignment()
	//!< instead. set_justify() has no effect on labels containing only a single line.

	void set_pattern(const String& pattern);
	//!< The pattern of underlines you want under the existing text within the Label widget. 
	//!< @param pattern The pattern string as described below.
	//!<
	//!< <BR>For example, if the current text of the label says "FooBarBaz" passing a pattern
	//!< of "___ ___" will underline "Foo" and "Baz" but not "Bar".
	
	void set_line_wrap(bool wrap);
	//!< Toggles line wrapping within the Label widget. 
	//!< @param wrap The setting.
	//!<
	//!< <BR>If wrap is <EM>true</EM> lines are broken if text exceeds the widget's size.
	//!< If wrap is <EM>false</EM> the text will get cut off by the edge of the widget if
	//!< it exceeds the widget size.

	void set_selectable(bool setting);
	//!< Selectable labels allow the user to select text from the label, for copy-and-paste.
	//!< @param setting <EM>true</EM> to allow selecting text in the label.

	void select_region(int start_offset, int end_offset);
	//!< Selects a range of characters in the label, if the label is selectable (see set_selectable()).
	//!< @param start_offset The start offset (in characters not bytes).
	//!< @param end_offset The end offset (in characters not bytes).
	//!<
	//!< <BR>If the label is not selectable, this function has no effect. If start_offset
	//!< or end_offset are -1, then the end of the label will be substituted.
	
	void set_use_markup(bool setting);
	//!< Sets whether the text of the label contains markup in Pango's text markup language (see set_markup()).
	//!< @param setting <EM>true</EM> if the label's text should be parsed for markup.

	void set_use_underline(bool setting);
	//!< If <EM>setting</EM> is true, an underline in the text indicates the next character
	//!< should be used for the mnemonic accelerator key.
	//!< @param setting <EM>true</EM> if underlines in the text indicate mnemonics.

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

	const LabelPropertyProxy prop_label()
	{
		return LabelPropertyProxy(this, &label_property);
	}
	//!< The text of the label (String : Read / Write).

	const AttributesPropertyProxy prop_attributes()
	{
		return AttributesPropertyProxy(this, &attributes_property);
	}
	//!< A list of style attributes to apply to the label text (Pointer<Pango::AttrList> : Read / Write).

	const UseMarkupPropertyProxy prop_use_markup()
	{
		return UseMarkupPropertyProxy(this, &use_markup_property);
	}
	//!< The text of the label includes XML markup (bool : Read / Write). See pango_parse_markup().

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

	const JustifyPropertyProxy prop_justify()
	{
		return JustifyPropertyProxy(this, &justify_property);
	}
	//!< Alignment of the lines in the text of the label relative to each other (Justification : Read / Write).

	const PatternPropertyProxy prop_pattern()
	{
		return PatternPropertyProxy(this, &pattern_property);
	}
	//!< A string with _ characters in positions corresponding to characters in the text
	//!< to underline (String : Write).

	const WrapPropertyProxy prop_wrap()
	{
		return WrapPropertyProxy(this, &wrap_property);
	}
	//!< If set, wrap lines if the text becomes too wide (bool : Read / Write).

	const SelectablePropertyProxy prop_selectable()
	{
		return SelectablePropertyProxy(this, &selectable_property);
	}
	//!< Whether the label text can be selected with the mouse (bool : Read / Write).

	const MnemonicKeyvalPropertyProxy prop_mnemonic_keyval()
	{
		return MnemonicKeyvalPropertyProxy(this, &mnemonic_keyval_property);
	}
	//!< The mnemonic accelerator key for this label (unsigned int : Read).

	const MnemonicWidgetPropertyProxy prop_mnemonic_widget()
	{
		return MnemonicWidgetPropertyProxy(this, &mnemonic_widget_property);
	}
	//!< The widget to be activated when the label's mnemonic key is pressed (Widget* : Read / Write).

	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).

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

	const MoveCursorSignalProxy sig_move_cursor()
	{
		return MoveCursorSignalProxy(this, &move_cursor_signal);
	}
	//!< Connect to the move_cursor_signal; emitted when the cursor is moved using the arrow keys.

	const CopyClipboardSignalProxy sig_copy_clipboard()
	{
		return CopyClipboardSignalProxy(this, &copy_clipboard_signal);
	}
	//!< Connect to the copy_clipboard_signal; emitted when the characters in the current selection
	//!< are to be copied to the clipboard.

	const PopulatePopupSignalProxy sig_populate_popup()
	{
		return PopulatePopupSignalProxy(this, &populate_popup_signal);
	}
	//!< Connect to the populate_popup_signal; emitted just before the popup menu is displayed in
	//!< response the a right-click on a selectable label.

//! @}
};

} // namespace Gtk

} // namespace Inti

#endif // INTI_GTK_LABEL_H


