/*  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/calendar.h
//! @brief A GtkCalendar C++ wrapper interface.

#ifndef INTI_GTK_CALENDAR_H
#define INTI_GTK_CALENDAR_H

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

#ifndef __GTK_CALENDAR_H__
#include <gtk/gtkcalendar.h>
#endif

namespace Inti {

namespace Gtk {

class CalendarClass;

//! @enum CalendarDisplayOptions
//! The display options that specify how the calendar itself is displayed.

enum CalendarDisplayOptions
{
	CALENDAR_SHOW_HEADING = GTK_CALENDAR_SHOW_HEADING, 
	//!< Specifies that the month and year should be displayed.
	CALENDAR_SHOW_DAY_NAMES = GTK_CALENDAR_SHOW_DAY_NAMES,
	//!< Specifies that three letter day descriptions should be present.
	CALENDAR_NO_MONTH_CHANGE = GTK_CALENDAR_NO_MONTH_CHANGE,
	//!< Prevents the user from switching months with the calendar.
	CALENDAR_SHOW_WEEK_NUMBERS = GTK_CALENDAR_SHOW_WEEK_NUMBERS,
	//!< Displays each week numbers of the current year, down the left side of the calendar.
	CALENDAR_WEEK_START_MONDAY = GTK_CALENDAR_WEEK_START_MONDAY
	//!< Starts the calendar week on Monday, instead of the default Sunday.
};

//! CalendarDisplayOptionsField holds one or more values from the CalendarDisplayOptions enumeration OR'd together.

typedef unsigned int CalendarDisplayOptionsField;

//! @class Calendar calendar.h inti/gtk/calendar.h
//! @brief A GtkCalendar C++ wrapper class.
//!
//! Calendar is a widget that displays a calendar, one month at a time. The month and year
//! currently displayed can be altered with select_month(). The exact day can be selected
//! from the displayed month using select_day(). To place a visual marker on a particular
//! day, use mark_day() and to remove the marker, unmark_day(). Alternative, all marks can
//! be cleared with clear_marks(). The way in which the calendar itself is displayed can
//! be altered using display_options(). The selected date can be retrieved from a Calendar
//! using get_date(). If performing many 'mark' operations, the calendar can be frozen to
//! prevent flicker, with freeze(), and 'thawed' again using thaw().

class Calendar : public Widget
{
	friend class G::Object;
	friend class CalendarClass;

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

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

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

	virtual void on_month_changed();
	//!< Called when the user clicks a button to change the selected month on a calendar.

	virtual void on_day_selected();
	//!< Called when the user selects a day.

	virtual void on_day_selected_double_click();
	//!< Called when the user double clicks a button to select a day.

	virtual void on_prev_month();
	//!< Called when the user selects the previous month.

	virtual void on_next_month();
	//!< Called when the user selects the next month.

	virtual void on_prev_year();
	//!< Called when the user selects the previous year.

	virtual void on_next_year();
	//!< Called when the user selects the next year.

//! @}
//  Signals

	typedef G::Signal0<void> MonthChangedSignalType;
	typedef G::SignalProxy<TypeInstance, MonthChangedSignalType> MonthChangedSignalProxy;
	static const MonthChangedSignalType month_changed_signal;

	typedef G::Signal0<void> DaySelectedSignalType;
	typedef G::SignalProxy<TypeInstance, DaySelectedSignalType> DaySelectedSignalProxy;
	static const DaySelectedSignalType day_selected_signal;

	typedef G::Signal0<void> DaySelectedDoubleClickSignalType;
	typedef G::SignalProxy<TypeInstance, DaySelectedDoubleClickSignalType> DaySelectedDoubleClickSignalProxy;
	static const DaySelectedDoubleClickSignalType day_selected_double_click_signal;

	typedef G::Signal0<void> PrevMonthSignalType;
	typedef G::SignalProxy<TypeInstance, PrevMonthSignalType> PrevMonthSignalProxy;
	static const PrevMonthSignalType prev_month_signal;

	typedef G::Signal0<void> NextMonthSignalType;
	typedef G::SignalProxy<TypeInstance, NextMonthSignalType> NextMonthSignalProxy;
	static const NextMonthSignalType next_month_signal;

	typedef G::Signal0<void> PrevYearSignalType;
	typedef G::SignalProxy<TypeInstance, PrevYearSignalType> PrevYearSignalProxy;
	static const PrevYearSignalType prev_year_signal;

	typedef G::Signal0<void> NextYearSignalType;
	typedef G::SignalProxy<TypeInstance, NextYearSignalType> NextYearSignalProxy;
	static const NextYearSignalType next_year_signal;

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

	Calendar();
	//!< Construct a new calendar, with the current date being selected.

	explicit Calendar(CalendarDisplayOptionsField flags);
	//!< Construct a new calendar, with the specified display options and current date selected.
	//!< @param flags One or more values from the CalendarDisplayOptions enum OR'd together.
	//!<
	//!< <BR>This is a convenience constructor that lets you specifiy the display options.

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

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

	GtkCalendarClass* gtk_calendar_class() const;
	//!< Get a pointer to the GtkCalendarClass structure.

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

	int year() const;
	//!< Returns the currently visible year.

	int month() const;
	//!< Returns the currently visible month as a zero-based integer.

	int day() const;
	//!< Returns the currently selected day as a one-based integer (allowed values are 1-31).

	CalendarDisplayOptionsField display_flags() const;
	//!< Returns the current CalendarDisplayOptions OR'd together.

	int num_marked_dates() const;
	//!< Returns the number of days that have a mark over them.

	std::vector<bool> marked_date() const;
	//!< Returns a vector containing the day numbers that currently have a mark over them.

	void get_date(int *year, int *month, int *day) const;
	//!< Obtains the selected date from a Calendar.
	//!< @param year Location to store the year number.
	//!< @param month Location to store the month number.
	//!< @param day Location to store the day number.

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

	bool select_month(int month, int year);
	//!< Shifts the calendar to a different month. 
	//!< @param month A month number between 0 and 11.
	//!< @param year The year the month is in.
	//!< @return Always <EM>true</EM>.
	
	void select_day(int day);
	//!< Selects a day from the current month.
	//!< @param day The day number between 1 and 31, or 0 to unselect the currently selected day.

	bool mark_day(int day);
	//!< Places a visual marker on a particular day.
	//!< @param day The day number to mark between 1 and 31.
	//!< @return Always <EM>true</EM>.

	bool unmark_day(int day);
	//!< Removes the visual marker from a particular day.
	//!< @param day The day number to unmark between 1 and 31.
	//!< @return <EM>true</EM>.
	
	void clear_marks();
	//!< Remove all visual markers. 

	void display_options(CalendarDisplayOptionsField flags);
	//!< Sets the display options (whether to display the year and month headings).
	//!< @param flags One or more values from the CalendarDisplayOptions enum OR'd together.

	void freeze();
	//!< Locks the display of the calendar until it is thawed with thaw().

	void thaw();
	//!< Defrosts a calendar; all the changes made since the last freeze() are displayed. 

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

	const MonthChangedSignalProxy sig_month_changed()
	{
		return MonthChangedSignalProxy(this, &month_changed_signal);
	}
	//!< Connect to the month_changed_signal; emitted when the user clicks a button to change the selected month.

	const DaySelectedSignalProxy sig_day_selected()
	{
		return DaySelectedSignalProxy(this, &day_selected_signal);
	}
	//!< Connect to the day_selected_signal; emitted when the user selects a day.

	const DaySelectedDoubleClickSignalProxy sig_day_selected_double_click()
	{
		return DaySelectedDoubleClickSignalProxy(this, &day_selected_double_click_signal);
	}
	//!< Connect to the day_selected_double_click_signal; emitted when the user selects a day with a double click.

	const PrevMonthSignalProxy sig_prev_month()
	{
		return PrevMonthSignalProxy(this, &prev_month_signal);
	}
	//!< Connect to the prev_month_signal; emitted when the user selects the previous month.

	const NextMonthSignalProxy sig_next_month()
	{
		return NextMonthSignalProxy(this, &next_month_signal);
	}
	//!< Connect to the next_month_signal; emitted when the user selects the next month.

	const PrevYearSignalProxy sig_prev_year()
	{
		return PrevYearSignalProxy(this, &prev_year_signal);
	}
	//!< Connect to the prev_year_signal; emitted when the user selects the previous year.

	const NextYearSignalProxy sig_next_year()
	{
		return NextYearSignalProxy(this, &next_year_signal);
	}
	//!< Connect to the next_year_signal; emitted when the user selects the next year.

//! @}
};

} // namespace Gtk

} // namespace Inti

#endif // INTI_GTK_CALENDAR_H

