/*  Inti - GTK+ C++ Object Developemnt Enviroment
 *  Copyright (C) 2002-2003 The Inti Develeopement 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/notebook.h
//! @brief A GtkNotebook C++ wrapper interface.
//!
//! Provides Notebook, a Container widget whose children are pages that can be switched
//! between using tab labels along one edge.

#ifndef INTI_GTK_NOTEBOOK_H
#define INTI_GTK_NOTEBOOK_H

#ifndef INTI_GTK_CONTAINER_H
#include <inti/gtk/container.h>
#endif

#ifndef __GTK_NOTEBOOK_H__
#include <gtk/gtknotebook.h>
#endif

namespace Inti {

namespace Gtk {

class Label;
class NotebookClass;

//! @enum NotebookTab
//! NotebookTab defines the notebook tab which received the focus when a home or end key
//! is pressed on the keyboard.

enum NotebookTab
{
	NOTEBOOK_TAB_FIRST = GTK_NOTEBOOK_TAB_FIRST, 
	//!< The first tab in the notebook page list (GDK_Home or GDK_KP_Home).

	NOTEBOOK_TAB_LAST = GTK_NOTEBOOK_TAB_LAST 
	//!< The last tab in the notebook page list (GKD_End or GDK_KP_End).
};

//! @class Notebook notebook.h inti/gtk/notebook.h
//! @brief A GtkNotebook C++ wrapper class.
//!
//! The Notebook widget is a Container whose children are pages that can be switched
//! between using tab labels along one edge. There are many configuration options for
//! Notebook. Among other things, you can choose on which edge the tabs appear
//! (see set_tab_pos()), whether, if there are too many tabs to fit the noteobook 
//! should be made bigger or scrolling arrows added (see set_scrollable()), and whether
//! there will be a popup menu allowing the users to switch pages. (see popup_enable(),
//! popup_disable()).

class Notebook : public Container
{
	friend class G::Object;
	friend class NotebookClass;

	Notebook(const Notebook&);
	Notebook& operator=(const Notebook&);

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

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

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

	virtual void on_switch_page(GtkNotebookPage *page, unsigned int page_num);
	//!< Called when the user or a function changes the current page.
	//!< @param page The new current page.
	//!< @param page_num The index of the page.

//! @}
//  Properties

	typedef G::Property<int> PagePropertyType;
	typedef G::PropertyProxy<G::Object, PagePropertyType> PagePropertyProxy;
	static const PagePropertyType page_property;

	typedef G::Property<PositionType, int> TabPosPropertyType;
	typedef G::PropertyProxy<G::Object, TabPosPropertyType> TabPosPropertyProxy;
	static const TabPosPropertyType tab_pos_property;

	typedef G::WritableProperty<unsigned int> TabBorderPropertyType;
	typedef G::PropertyProxy<G::Object, TabBorderPropertyType> TabBorderPropertyProxy;
	static const TabBorderPropertyType tab_border_property;

	typedef G::Property<unsigned int> TabHBorderPropertyType;
	typedef G::PropertyProxy<G::Object, TabHBorderPropertyType> TabHBorderPropertyProxy;
	static const TabHBorderPropertyType tab_hborder_property;

	typedef G::Property<unsigned int> TabVBorderPropertyType;
	typedef G::PropertyProxy<G::Object, TabVBorderPropertyType> TabVBorderPropertyProxy;
	static const TabVBorderPropertyType tab_vborder_property;

	typedef G::Property<bool> ShowTabsPropertyType;
	typedef G::PropertyProxy<G::Object, ShowTabsPropertyType> ShowTabsPropertyProxy;
	static const ShowTabsPropertyType show_tabs_property;

	typedef G::Property<bool> ShowBorderPropertyType;
	typedef G::PropertyProxy<G::Object, ShowBorderPropertyType> ShowBorderPropertyProxy;
	static const ShowBorderPropertyType show_border_property;

	typedef G::Property<bool> ScrollablePropertyType;
	typedef G::PropertyProxy<G::Object, ScrollablePropertyType> ScrollablePropertyProxy;
	static const ScrollablePropertyType scrollable_property;

	typedef G::Property<bool> EnablePopupPropertyType;
	typedef G::PropertyProxy<G::Object, EnablePopupPropertyType> EnablePopupPropertyProxy;
	static const EnablePopupPropertyType enable_popup_property;

	typedef G::Property<bool> HomogeneousPropertyType;
	typedef G::PropertyProxy<G::Object, HomogeneousPropertyType> HomogeneousPropertyProxy;
	static const HomogeneousPropertyType homogeneous_property;

//  Child properties

	typedef Gtk::ChildProperty<String> TabLabelPropertyType;
	typedef Gtk::ChildPropertyProxy<Container, TabLabelPropertyType> TabLabelPropertyProxy;
	static const TabLabelPropertyType tab_label_property;

	typedef Gtk::ChildProperty<String> MenuLabelPropertyType;
	typedef Gtk::ChildPropertyProxy<Container, MenuLabelPropertyType> MenuLabelPropertyProxy;
	static const MenuLabelPropertyType menu_label_property;

	typedef Gtk::ChildProperty<unsigned int> PositionPropertyType;
	typedef Gtk::ChildPropertyProxy<Container, PositionPropertyType> PositionPropertyProxy;
	static const PositionPropertyType position_property;

	typedef Gtk::ChildProperty<bool> TabExpandPropertyType;
	typedef Gtk::ChildPropertyProxy<Container, TabExpandPropertyType> TabExpandPropertyProxy;
	static const TabExpandPropertyType tab_expand_property;

	typedef Gtk::ChildProperty<bool> TabFillPropertyType;
	typedef Gtk::ChildPropertyProxy<Container, TabFillPropertyType> TabFillPropertyProxy;
	static const TabFillPropertyType tab_fill_property;

	typedef Gtk::ChildProperty<PackType, int> TabPackPropertyType;
	typedef Gtk::ChildPropertyProxy<Container, TabPackPropertyType> TabPackPropertyProxy;
	static const TabPackPropertyType tab_pack_property;

//  Signals

	typedef G::Signal2<void, GtkNotebookPage*, unsigned int> SwitchPageSignalType;
	typedef G::SignalProxy<TypeInstance, SwitchPageSignalType> SwitchPageSignalProxy;
	static const SwitchPageSignalType switch_page_signal;

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

	Notebook();
	//!< Construct a new notebook with no pages.

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

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

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

	GtkNotebookClass* gtk_notebook_class() const;
	//!< Get a pointer to the GtkNotebookClass structure.

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

	int get_current_page() const;
	//!< Returns the page number of the current page.
	//!< @return The index (starting from 0) of the current page in the notebook. 
	//!<
	//!< <BR>If the notebook has no pages, then -1 will be returned.

	Widget* get_current_nth_page() const;
	//!< Returns the child widget contained in the current page.
	//!< @return The child widget, or null if the notebook has no pages.

	Widget* get_nth_page(int page_num) const;
	//!< Returns the child widget contained in page number <EM>page_num</EM>.
	//!< @param page_num The index of a page in the noteobok, or -1 to get the last page.
	//!< @return The child widget, or null if page_num is out of bounds.

	int get_n_pages() const;
	//!< Returns the number of pages in the notebook.

	int page_num(const Widget& child) const;
	//!< Finds the index of the page which contains the given child widget.
	//!< @param child A Widget.
	//!< @return The index of the page containing child, or -1 if child is not in the notebook.

	bool get_show_border() const;
	//!< Returns whether a bevel will be drawn around the notebook pages (see set_show_border()).
	//!< @return <EM>true</EM> if the bevel is drawn.

	bool get_show_tabs() const;
	//!< Returns whether the tabs of the notebook are shown (see set_show_tabs()).
	//!< @return  <EM>true</EM> if the tabs are shown.

	PositionType get_tab_pos() const;
	//!< Gets the edge at which the tabs for switching pages in the notebook are drawn.
	//!< @return The edge at which the tabs are drawn.

	bool get_scrollable() const;	
	//!< Returns whether the tab label area has arrows for scrolling (see set_scrollable()).
	//!< @return <EM>true</EM> if arrows for scrolling are present.

	Label* get_tab_label(const Widget& child) const;
	//!< Returns the tab label widget for the page containing child.
	//!< @param child The page.
	//!< @return The tab label.
	//!<
	//!< <BR>null is returned if child is not in notebook or if no tab label has specifically
	//!< been set for <EM>child</EM>.

	Label* get_tab_label(int page_num) const;
	//!< Returns the tab label widget for the page with the index <EM>page_num</EM>.
	//!< @param page_num The index of a page in the noteobok, or -1 to get the last page.
	//!< @return The tab label.
	//!<
	//!< <BR>null is returned if child is not in notebook or if no tab label has specifically
	//!< been set for <EM>child</EM>.

	String get_tab_label_text(const Widget& child) const;
	//!< Retrieves the text of the tab label for the page containing child.
	//!< @param child A widget contained in a page of notebook.
	//!< @return The text of the tab label, or a null String if the tab label widget is not a Label.

	String get_tab_label_text(int page_num) const;
	//!< Retrieves the text of the tab label for the page with the index <EM>page_num</EM>.
	//!< @param page_num The index of a page in the noteobok, or -1 to get the last page.
	//!< @return The text of the tab label, or a null String if the tab label widget is not a Label.

	Label* get_menu_label(const Widget& child) const;
	//!< Retrieves the menu label widget of the page containing child.
	//!< @param child A widget contained in a page of notebook.
	//!< @return The menu label, or null if the page does not have a menu label other than the default.

	Label* get_menu_label(int page_num) const;
	//!< Retrieves the menu label widget of the page with the index <EM>page_num</EM>.
	//!< @param page_num The index of a page in the noteobok, or -1 to get the last page.
	//!< @return The menu label, or null if the page does not have a menu label other than the default.

	String get_menu_label_text(const Widget& child) const;
	//!< Retrieves the text of the menu label for the page containing child.
	//!< @param child The child widget of a page of the notebook.
	//!< @return The text of the menu label, or a null String if the widget does not have a menu label
	//!<         other than the default menu label, or the menu label widget is not a Label.

	String get_menu_label_text(int page_num) const;
	//!< Retrieves the text of the menu label for the page with the index <EM>page_num</EM>.
	//!< @param page_num The index of a page in the noteobok, or -1 to get the last page.
	//!< @return The text of the menu label, or a null String if the widget does not have a menu label
	//!<         other than the default menu label, or the menu label widget is not a Label.

	void query_tab_label_packing(const Widget& child, bool *expand, bool *fill, PackType *pack_type) const;
	//!< Query the packing attributes for the tab label for the page containing child.
	//!< @param child The child widget.
	//!< @param expand The location to store the expand value (or null).
	//!< @param fill The location to store the fill value (or null).
	//!< @param pack_type The location to store the pack_type (or null).

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

	void append_page(Widget& child, Widget *tab_label = 0, Widget *menu_label = 0);
	//!< Appends a page to the notebook, specifying the widget to use as the label in the tab
	//!< and the widget to use as the label in the popup menu.
	//!< @param child The Widget to use as the contents of the page.
	//!< @param tab_label The Widget to be used as the label for the page, or null
	//!<                  to use the default label, 'page N'.
	//!< @param menu_label The widget to use as a label for the page-switch menu, if that is enabled.
	//!<
	//!< <BR>If null, and tab_label is a Label or null, then the menu label will be a newly created
	//!< label with the same text as tab_label; If tab_label is not a Label, menu_label must be
	//!< specified if the page-switch menu is to be used.

	void append_page(Widget& child, const String& tab_label, const String& menu_label = 0);
	//!< Appends a page to the notebook with the specified tab label text and the popup menu label text.
	//!< @param child The Widget to use as the contents of the page.
	//!< @param tab_label The tab label text.
	//!< @param menu_label The menu_label text.
	//!<
	//!< <BR>This method creates default tab and menu labels.

	void prepend_page(Widget& child, Widget *tab_label = 0, Widget *menu_label = 0);
	//!< Prepends a page to the notebook, specifying the widget to use as the label in the tab
	//!< and the widget to use as the label in the popup menu.
	//!< @param child The Widget to use as the contents of the page.
	//!< @param tab_label The Widget to be used as the label for the page, or null
	//!<                  to use the default label, 'page N'.
	//!< @param menu_label The widget to use as a label for the page-switch menu, if that is enabled.
	//!<
	//!< <BR>If null, and tab_label is a Label or null, then the menu label will be a newly created
	//!< label with the same text as tab_label; If tab_label is not a Label, menu_label must be
	//!< specified if the page-switch menu is to be used.

	void prepend_page(Widget& child, const String& tab_label, const String& menu_label = 0);
	//!< Prepends a page to the notebook with the specified tab label text and the popup menu label text.
	//!< @param child The Widget to use as the contents of the page.
	//!< @param tab_label The tab label text.
	//!< @param menu_label The menu_label text.
	//!<
	//!< <BR>This method creates default tab and menu labels.

	void insert_page(Widget& child, int position, Widget *tab_label = 0, Widget *menu_label = 0);
	//!< Insert a page into the notebook, specifying the widget to use as the label in the tab
	//!< and the widget to use as the label in the popup menu.
	//!< @param child The Widget to use as the contents of the page.
	//!< @param position The index (starting at 0) at which to insert the page.
	//!< @param tab_label The Widget to be used as the label for the page, or null
	//!<                  to use the default label, 'page N'.
	//!< @param menu_label The widget to use as a label for the page-switch menu, if that is enabled.
	//!<
	//!< <BR>If null, and tab_label is a Label or null, then the menu label will be a newly created
	//!< label with the same text as tab_label; If tab_label is not a Label, menu_label must be
	//!< specified if the page-switch menu is to be used. A position value of 0 prepends the new page
	//!< before all the others. A position value of -1 will append the new page after all the others.

	void insert_page(Widget& child, int position, const String& tab_label, const String& menu_label = 0);
	//!< Insert a page into the notebook with the specified tab label text and the popup menu label text.
	//!< @param child The Widget to use as the contents of the page.
	//!< @param position The index (starting at 0) at which to insert the page.
	//!< @param tab_label The tab label text.
	//!< @param menu_label The menu_label text.
	//!<
	//!< <BR>This method creates default tab and menu labels. A position value of 0 prepends the 
	//!< new page before all the others. A position value of -1 will append the new page after
	//!< all the others.

	void remove_page(int page_num);
	//!< Removes the page from the notebook with the index <EM>page_num</EM>.
	//!< @param page_num The index of a notebook page, starting from 0. If -1, the last page will be removed.

	void set_current_page(int page_num);
	//!< Switches to the page number <EM>page_num</EM>.
	//!< @param page_num The index of the page to switch to, starting from 0.
	//!< 
	//!< <BR>If <EM>page_num</EM> is negative, the last page will be used. If <EM>page_num</EM>
	//!< is greater than the number of pages in the notebook, nothing will be done.

	void next_page();
	//!< Switches to the next page. Nothing happens if the current page is the last page.

	void prev_page();
	//!< Switches to the previous page. Nothing happens if the current page is the first page.

	void set_show_border(bool show_border);
	//!< Sets whether a bevel will be drawn around the notebook pages. 
	//!< @param show_border <EM>true</EM> if a bevel should be drawn around the notebook.
	//!<
	//!< <BR>This only has a visual effect when the tabs are not shown (see set_show_tabs()).

	void set_show_tabs(bool show_tabs);
	//!< Sets whether to show the tabs for the notebook or not.
	//!< @param show_tabs <EM>true</EM> if the tabs should be shown.

	void set_tab_pos(PositionType pos);
	//!< Sets the edge at which the tabs for switching pages in the notebook are drawn.
	//!< @param pos The edge to draw the tabs at.

	void set_scrollable(bool scrollable);
	//!< Sets whether the tab label area will have arrows for scrolling if there are
	//!< too many tabs to fit in the area.
	//!< @param scrollable <EM>true</EM> if scroll arrows should be added.

	void popup_enable();
	//!< Enables the popup menu: if the user clicks with the right mouse button on the bookmarks,
	//!< a menu with all the pages will be popped up.

	void popup_disable();
	//!< Disables the popup menu.

	void set_tab_label(Widget& child, Widget *tab_label);
	//!< Changes the tab label for the page containing child.
	//!< @param child The child widget.
	//!< @param tab_label The tab label widget to use, or null for default tab label.

	void set_tab_label_text(Widget& child, const String& tab_text);
	//!< Creates a new label widget and sets it as the tab label for the page containing child.
	//!< @param child The child widget.
	//!< @param tab_text The label text.

	void set_menu_label(Widget& child, Widget *menu_label);
	//!< Changes the menu label for the page containing child.
	//!< @param child The child widget.
	//!< @param menu_label The menu label, or null for default.

	void set_menu_label_text(Widget& child, const String& menu_text);
	//!< Creates a new label widget and sets it as the menu label for the page containing child.
	//!< @param child The child widget.
	//!< @param menu_text The label text.

	void set_tab_label_packing(Widget& child, bool expand, bool fill, PackType pack_type);
	//!< Sets the packing parameters for the tab label of the page containing child 
	//!< (see Gtk::Box::pack_start() for the exact meaning of the parameters).
	//!< @param child The child widget
	//!< @param expand Whether to expand the bookmark or not.
	//!< @param fill Whether the bookmark should fill the allocated area or not.
	//!< @param pack_type The position of the bookmark.

	void reorder_child(Widget& child, int position);
	//!< Reorders the page containing child, so that it appears in position position.
	//!< @param child The child to move.
	//!< @param position The new position, or -1 to move to the end.
	//!<
	//!< <BR>If position is greater than or equal to the number of children in the list or negative,
	//!< child will be moved to the end of the list.

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

	const PagePropertyProxy prop_page()
	{
		return PagePropertyProxy(this, &page_property);
	}
	//!< The index of the current page (int : Read / Write).

	const TabPosPropertyProxy prop_tab_pos()
	{
		return TabPosPropertyProxy(this, &tab_pos_property);
	}
	//!< Which side of the notebook holds the tabs (PositionType : Read / Write).

	const TabBorderPropertyProxy prop_tab_border()
	{
		return TabBorderPropertyProxy(this, &tab_border_property);
	}
	//!< Width of the border around the tab labels (unsigned int : Write).

	const TabHBorderPropertyProxy prop_tab_hborder()
	{
		return TabHBorderPropertyProxy(this, &tab_hborder_property);
	}
	//!< Width of the horizontal border of tab labels (unsigned int : Read / Write).

	const TabVBorderPropertyProxy prop_tab_vborder()
	{
		return TabVBorderPropertyProxy(this, &tab_vborder_property);
	}
	//!< Width of the vertical border of tab labels (unsigned int : Read / Write).

	const ShowTabsPropertyProxy prop_show_tabs()
	{
		return ShowTabsPropertyProxy(this, &show_tabs_property);
	}
	//!< Whether tabs should be shown or not (bool : Read / Write).

	const ShowBorderPropertyProxy prop_show_border()
	{
		return ShowBorderPropertyProxy(this, &show_border_property);
	}
	//!< Whether the border should be shown or not (bool : Read / Write).

	const ScrollablePropertyProxy prop_scrollable()
	{
		return ScrollablePropertyProxy(this, &scrollable_property);
	}
	//!< If true, scroll arrows are added if there are too many tabs to fit (bool : Read / Write).

	const EnablePopupPropertyProxy prop_enable_popup()
	{
		return EnablePopupPropertyProxy(this, &enable_popup_property);
	}
	//!< If true, pressing the right mouse button on the notebook pops up a menu
	//!< that you can use to go to a page (bool : Read / Write).

	const HomogeneousPropertyProxy prop_homogeneous()
	{
		return HomogeneousPropertyProxy(this, &homogeneous_property);
	}
	//!< Whether tabs should have homogeneous sizes (bool : Read / Write).

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

	const TabLabelPropertyProxy prop_tab_label()
	{
		return TabLabelPropertyProxy(this, &tab_label_property);
	}
	//!< The string displayed on the childs tab label (String : Read / Write).

	const MenuLabelPropertyProxy prop_menu_label()
	{
		return MenuLabelPropertyProxy(this, &menu_label_property);
	}
	//!< The string displayed in the childs menu entry (String : Read / Write).

	const PositionPropertyProxy prop_position()
	{
		return PositionPropertyProxy(this, &position_property);
	}
	//!< The index of the child in the parent (int : Read / Write).

	const TabExpandPropertyProxy prop_tab_expand()
	{
		return TabExpandPropertyProxy(this, &tab_expand_property);
	}
	//!< Whether to expand the childs tab or not (bool : Read / Write).

	const TabFillPropertyProxy prop_tab_fill()
	{
		return TabFillPropertyProxy(this, &tab_fill_property);
	}
	//!< Whether the childs tab should fill the allocated area or not (bool : Read / Write).

	const TabPackPropertyProxy prop_tab_pack()
	{
		return TabPackPropertyProxy(this, &tab_pack_property);
	}
	//!< A PackType indicating whether the child is packed with reference to the
	//!< start or end of the parent (PackType : Read / Write).

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

	const SwitchPageSignalProxy sig_switch_page()
	{
		return SwitchPageSignalProxy(this, &switch_page_signal);
	}
	//!< Connect to the switch_page_signal; emitted when the user or a function
	//!< changes the current page.

//! @}
};

} // namespace Gtk

} // namespace Inti

#endif // INTI_GTK_NOTEBOOK_H

