/*
 * 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.gtk;

import java.util.Iterator;
import java.util.Vector;

import org.gnu.glib.EventMap;
import org.gnu.glib.EventType;
import org.gnu.glib.Handle;
import org.gnu.glib.Type;
import org.gnu.gtk.event.CellRendererToggleEvent;
import org.gnu.gtk.event.CellRendererToggleListener;

/**
 * The CellRendererToggle is a {@link CellRenderer} for boolean data. 
 */
public class CellRendererToggle extends CellRenderer {
	private static EventMap evtMap = new EventMap();

	static {
		addEvents(evtMap);
	}
	// we use a set so we don't have repeated elements on the list
	private Vector listeners = null;

	/**
	 * Constructs a new Cell Renderer.
	 */
	public CellRendererToggle() {
		super(gtk_cell_renderer_toggle_new());
	}

	/**
	 * If radio is TRUE, the cell renderer renders a radio toggle
	 * (ie a toggle in a group of mutually-exclusive toggles). If
	 * FALSE, it renders a check toggle (a standalone boolean
	 * option). This can be set globally for the cell renderer, or
	 * changed just before rendering each cell in the model (for
	 * {@link TreeView}, you set up a per-row setting using {@link
	 * TreeViewColumn} to associate model columns with cell
	 * renderer properties).
	 * @param radio TRUE to make the toggle look like a radio button
	 */
	public void setRadio(boolean radio) {
		gtk_cell_renderer_toggle_set_radio(getHandle(), radio);
	}

	/**
	 * Sets whether all cells are toggled. You will usually want to do this
	 * based on data in the model, using {@link
	 * TreeViewColumn#addAttributeMapping(CellRenderer, CellRendererAttribute,
	 * DataColumn)} with the {@link CellRendererToggle.Attribute#ACTIVE} attribute.
	 * @param toggled If true, all cells will be toggled, or cheked.
	 */
	public void setToggled(boolean toggled) {
		gtk_cell_renderer_toggle_set_active(getHandle(), toggled);
	}

	/**
	 * Sets whether the user can change the toggled status of the cell. This
	 * method will change the setting for all cells. It can be set on a cell by
	 * cell basis by including the data in the model and attaching the {@link
	 * CellRendererToggle.Attribute#ACTIVATABLE} property, using the {@link
	 * TreeViewColumn#addAttributeMapping(CellRenderer, CellRendererAttribute,
	 * DataColumn)} property
	 * @param setting If true, the value of all cells may be changed.
	 */
	public void setUserEditable(boolean setting) {
		setActivatable(getHandle(), setting);
	}

	/** Attributes for mapping to data in the TreeModel */
	public static class Attribute extends CellRendererAttribute {
		private Attribute(String attr) {
			super(attr);
		}
		/** The state of the toggle */
		public static final Attribute ACTIVE = new Attribute("active");
		/** Whether the user can change the state of the toggle */
		public static final Attribute ACTIVATABLE = new Attribute("activatable");
		/** The inconsistent state of the button. */
		public static final Attribute INCONSISTENT = new Attribute("inconsistent");
		/** Draw the toggle button as a radio button. */
		public static final Attribute RADIO = new Attribute("radio");
	}

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

	private static void addEvents(EventMap anEvtMap) {
		anEvtMap.addEvent(
			"toggled",
			"handleTogled",
			CellRendererToggleEvent.Type.TOGGLED,
			CellRendererToggleListener.class);
	}

	private void handleTogled(String arg) {
		fireCellRendererToggleEvent(new CellRendererToggleEvent(this, arg));
	}

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

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

	public void fireCellRendererToggleEvent(CellRendererToggleEvent evt) {
		final Iterator i = listeners.iterator();
		while (i.hasNext())
			 ((CellRendererToggleListener)i.next()).cellRendererToggleEvent(evt);
	}
	/**
	 * Register an object to handle CellRendererToggle events.
	 * @see org.gnu.gtk.event.CellRendererTextListener
	 */
	public void addListener(CellRendererToggleListener l) {
		int i = Widget.findListener(listeners, l);
		if (i == -1) {
			if (null == listeners) {
				evtMap.initialize(this, CellRendererToggleEvent.Type.TOGGLED);
				listeners = new Vector();
			}
			listeners.addElement(l);
		}
	}
	/**
	 * Removes a listener.
	 * @see #addListener(CellRendererToggleListener)
	 */
	public void removeListener(CellRendererToggleListener l) {
		int i = Widget.findListener(listeners, l);
		if (i > -1)
			listeners.remove(i);
		if (0 == listeners.size()) {
			evtMap.uninitialize(this, CellRendererToggleEvent.Type.TOGGLED);
			listeners = null;
		}
	}


	native static final protected void setActivatable(Handle toggle, boolean setting);
	native static final protected int gtk_cell_renderer_toggle_get_type();
	native static final protected Handle gtk_cell_renderer_toggle_new();
	native static final protected boolean gtk_cell_renderer_toggle_get_radio(Handle toggle);
	native static final protected void gtk_cell_renderer_toggle_set_radio(Handle toggle, boolean radio);
	native static final protected boolean gtk_cell_renderer_toggle_get_active(Handle toggle);
	native static final protected void gtk_cell_renderer_toggle_set_active(Handle toggle, boolean setting);

}
