/*
 * Java-Gnome Bindings Library
 *
 * Copyright 1998-2004 the Java-Gnome Team, all rights reserved.
 *
 * The Java-Gnome bindings library is free software distributed under
 * the terms of the GNU Library General Public License version 2.
 */

package org.gnu.gnome;

import java.util.Date;
import java.util.Vector;

import org.gnu.glib.EventMap;
import org.gnu.glib.Type;
import org.gnu.gnome.event.DateEditEvent;
import org.gnu.gnome.event.DateEditListener;
import org.gnu.gtk.HBox;
import org.gnu.gtk.event.GtkEventType;

/**
 * A control which allows the user to select a date.
 */
public class DateEdit extends HBox {
	/**
	 * Listeners for handling DateEdit events
	 */
	private Vector dateEditListeners = null;

	/**
	 * Creates a new DateEdit control initialized to the given date.
	 * @param date The date to which the control should be initilized.
	 * @param timeDisplay True if the time should be shown.  False if the date
	 *                    only should be shown.
	 * @param use24fmt True if the control should display time in the 24 hour
	 *                 format.  False if the 24 hour format should not be used.
	 */
	public DateEdit(java.util.Date date, boolean timeDisplay, boolean use24fmt) {
		super(gnome_date_edit_new(date.getTime() / 1000, timeDisplay, use24fmt));
		initializeEventHandlers();
	}

	/**
	 * Construct a new DateEdit from a handle to a native resource.
	 */
	public DateEdit(int handle) {
		super(handle);
		initializeEventHandlers();
	}

	/**
	 * Returns true if the control shows the time in the 24 hour format.
	 * @return True if time is being shown in the 24 hour format.  Flase if the
	 *         time is being shown in the 12 hour format.
	 */
	public boolean get24HourFormat() {
		int flags = gnome_date_edit_get_flags(getHandle());
		int formatFlag = DateEditFlags.HR24.getValue();

		return ((flags & formatFlag) == formatFlag);
	}

	public Date getInitialTime() {
		long time_t = gnome_date_edit_get_initial_time(getHandle()) * 1000;
		return new Date(time_t);
	}

	/**
	 * Get the date/time indicated in the DateEdit control.
	 * @return the date/time.
	 */
	public Date getTime() {
		long time_t = gnome_date_edit_get_time(getHandle()) * 1000;
		return new Date(time_t);
	}

	/**
	 * Returns true if the control shows the time as well as date.
	 * @return True if time is being shown.  Flase if the date only is being
	 *         shown.
	 */
	public boolean getTimeDisplay() {
		int flags = gnome_date_edit_get_flags(getHandle());
		int showTimeBitValue = DateEditFlags.SHOW_TIME.getValue();

		return ((flags & showTimeBitValue) == showTimeBitValue);
	}

	public void setPopupRange(int lowHour, int upHour) {
		gnome_date_edit_set_popup_range(getHandle(), lowHour, upHour);
	}

	/**
	 * Set the date/time indicated in the DateEdit control.
	 * @param date The date/time to display.
	 */
	public void setTime(Date date) {
		long time_t = date.getTime() / 1000;
		gnome_date_edit_set_time(getHandle(), time_t);
	}

	/**
	 * Change the way the time display is formated.
	 * @param enabled True if time should be shown in 24 hour format.  Flase if
	 *                the date should be shown in 12 hour format.
	 */
	public void set24HourFormat(boolean enabled) {
		int flags = gnome_date_edit_get_flags(getHandle());
		int formatFlag = DateEditFlags.HR24.getValue();

		if (enabled && (flags & formatFlag) == 0) {
			flags = flags | formatFlag;
		} else if ((!enabled) && (flags & formatFlag) > 0) {
			flags = flags - formatFlag;
		} else {
			// The flag does not need to be changed.
			return;
		}
		gnome_date_edit_set_flags(getHandle(), flags);
	}

	/**
	 * Enabled/Disable the functionallity which shows time as well as date.
	 * @param enabled True if time should be shown.  Flase if the date only
	 *                should be shown.
	 */
	public void setTimeDisplay(boolean enabled) {
		int flags = gnome_date_edit_get_flags(getHandle());
		int showTimeBitValue = DateEditFlags.SHOW_TIME.getValue();

		if (enabled && (flags & showTimeBitValue) == 0) {
			flags = flags | showTimeBitValue;
		} else if ((!enabled) && (flags & showTimeBitValue) > 0) {
			flags = flags - showTimeBitValue;
		} else {
			// The flag does not need to be changed.
			return;
		}
		gnome_date_edit_set_flags(getHandle(), flags);
	}

	/**
	 * Retrieve the runtime type used by the GLib library.
	 */
	public static Type getType() {
		return new Type(gnome_date_edit_get_type());
	}

	////////////////////////////////////////
	// Event handling
	////////////////////////////////////////

	/**
	 * Register an object to handle DateEdit events.
	 * @see org.gnu.gnome.event.DateEditListener
	 */
	public void addListener(DateEditListener listener) {
		// Don't add the listener a second time if it is in the Vector.
		int i = findListener(dateEditListeners, listener);
		if (i == -1) {
			if (null == dateEditListeners) {
				dateEditListeners = new Vector();
			}
			dateEditListeners.addElement(listener);
		}
	}
	/**
	 * Removes a listener
	 * @see #addListener(DateEditListeners)
	 */
	public void removeListener(DateEditListener listener) {
		int i = findListener(dateEditListeners, listener);
		if (i > -1) {
			dateEditListeners.remove(i);
		}
		if (0 == dateEditListeners.size()) {
			dateEditListeners = null;
		}
	}
	protected void fireDateEditEvent(DateEditEvent event) {
		if (null == dateEditListeners) {
			return;
		}
		int size = dateEditListeners.size();
		int i = 0;
		while (i < size) {
			DateEditListener del = (DateEditListener)dateEditListeners.elementAt(i);
			del.dateEditEvent(event);
			i++;
		}
	}

	private void handleDateChanged() {
		fireDateEditEvent(new DateEditEvent(this, DateEditEvent.Type.DATE_CHANGED));
	}

	private void handleTimeChanged() {
		fireDateEditEvent(new DateEditEvent(this, DateEditEvent.Type.TIME_CHANGED));
	}

	protected void initializeEventHandlers() {
		if (!eventsInitialized) {
			super.initializeEventHandlers();
			evtMap.initialize(this);
			eventsInitialized = true;
		}
	}

	public Class getEventListenerClass(String signal) {
		Class cls = evtMap.getEventListenerClass(signal);
		if (cls == null) cls = super.getEventListenerClass(signal);
		return cls;
	}

	public GtkEventType getEventType(String signal) {
		GtkEventType et = evtMap.getEventType(signal);
		if (et == null) et = super.getEventType(signal);
		return et;
	}

	private static EventMap evtMap = new EventMap();
	static {
		addEvents(evtMap);
	}

	/**
	* Implementation method to build an EventMap for this widget class.
	* Not useful (or supported) for application use.
	*/
	private static void addEvents(EventMap anEvtMap) {
		anEvtMap.addEvent("date_changed", "handleDateChanged", DateEditEvent.Type.DATE_CHANGED, DateEditListener.class);
		anEvtMap.addEvent("time_changed", "handleTimeChanged", DateEditEvent.Type.TIME_CHANGED, DateEditListener.class);
	}

	/****************************************
	 * BEGINNING OF GENERATED CODE
	 ****************************************/
	native static final protected int gnome_date_edit_get_type();
	native static final protected int gnome_date_edit_new(long the_time, boolean show_time, boolean use_24_format);
	native static final protected int gnome_date_edit_new_flags(long the_time, int flags);
	native static final protected void gnome_date_edit_set_time(int gde, long the_time);
	native static final protected long gnome_date_edit_get_time(int gde);
	native static final protected void gnome_date_edit_set_popup_range(int gde, int low_hour, int up_hour);
	native static final protected void gnome_date_edit_set_flags(int gde, int flags);
	native static final protected int gnome_date_edit_get_flags(int gde);
	native static final protected long gnome_date_edit_get_initial_time(int gde);
	/****************************************
	 * END OF GENERATED CODE
	 ****************************************/
}
