package org.apache.pivot.wtk;

import org.apache.pivot.beans.BeanAdapter;

/**
 * An individual style binding. It always fires automatic invalidation and repaint but 
 * this can be switched on or off individually.
 * 
 * <p>You can use this in any class, such as a skin class, to ensure that the styles
 * set on the component are automatically reflected in the skin. Just instantiate
 * this object and keep a reference to it in the skin using the skin's {@code getComponent()}
 * as the source. Create this binding in the {@code Skin.install} method.
 * If the skin is reinstalled on a new component, the source for style update events
 * can be set using {@code setSource}.
 * 
 * <p>Style binding can also be completely automated using the {@code PivotStyle}
 * annotation.
 *
 */
public class SingleStyleBinding {

	private BeanAdapter target;
	private String styleKey;
	private Component source;
	private ComponentListener styleUpdatedListener;
	private boolean fireInvalidate = true;
	private boolean fireRepaint = true;

	/**
	 * If true, fire a invalidate on the source component if the
	 * style is updated.
	 * @param fireInvalidateAndPaint
	 */
	public void setFireInvalidate(boolean fireInvalidate) {
		this.fireInvalidate = fireInvalidate;
	}

	/**
	 * If true, fire a repaint on the source component if the style is updated.
	 * @param fireRepaint
	 */
	public void setFireRepaint(boolean fireRepaint) {
		this.fireRepaint = fireRepaint;
	}

	/**
	 * Set the source, in case it changes.
	 * @param source
	 */
	public void setSource(Component source) {
		if (this.source != null)
			this.source.getComponentListeners().remove(styleUpdatedListener);
		this.source = source;
		if (source != null)
			source.getComponentListeners().add(styleUpdatedListener);
	}

	/**
	 * Create a new instance.
	 * @param source
	 * @param styleKey
	 * @param target
	 */
	public SingleStyleBinding(Component source, String styleKey, BeanAdapter target) {
		this.target = target;
		this.source = source;
		this.styleKey = styleKey;

		styleUpdatedListener = new ComponentListener.Adapter() {
			@Override
			public void styleUpdated(Component component, String styleKey, Object previousValue) {
				SingleStyleBinding.this.target.put(styleKey, SingleStyleBinding.this.source.getStyles().get(styleKey));
				if (fireInvalidate)
					SingleStyleBinding.this.source.invalidate();
				if (fireRepaint)
					SingleStyleBinding.this.source.repaint();

			}
		};
		setSource(source);
	}

	/**
	 * Return the style key this binding matches.
	 * @return
	 */
	public String getStyleKey() {
		return styleKey;
	}

	/**
	 * Return the component source, the source of style update events.
	 * @return
	 */
	public Component getSource() {
		return source;
	}
}
