package org.javafxdata.control.cell;

import java.util.ArrayList;
import java.util.List;

import javafx.scene.control.ListCell;

/**
 * Convenience extension to the {@link ListCell} class to expose a basic
 * CSS implementation (whilst the real JavaFX implementation is in
 * development). The only methods that should be used are {@link #getCssState(List)}
 * and {@link #stateChanged(String, String...)}. Refer to these methods
 * for more information on how to use them in your custom cells.
 * 
 * @author <a href="http://www.jonathangiles.net">Jonathan Giles</a>
 * @param <T> The type of the item contained within the cell.
 */
public class CSSListCell<T> extends ListCell<T> {
    
    /**
     * Creates a new instance of the {@link CSSListCell}.
     */
    public CSSListCell() {
        
    }
    
    /**
     * Override this method to specify which pseudo class states the
     * cell is in, based on the {@link #itemProperty() item} that is
     * currently contained within it. For example, the {@link MoneyCellFactory}
     * implementation of this method might resemble the following:
     * 
     * <pre>
     * &#064;Override public void getCssState(List<String> s) {
     *     Number n = getItem();
     *     if (n == null) return;
     *     
     *     double value = n.doubleValue();
     *     
     *     if (value < 0) s.add("negative");
     *     if (value > 0) s.add("positive");
     * }
     * </pre>
     * 
     * Doing this, it is now posible to style the cell based on these
     * psuedo class states. For example, assuming the {@link MoneyCellFactory}
     * had a style class of 'money-cell' (which it does), you could then
     * have CSS along the lines of the following:
     * 
     * <pre>
     * .money-cell:positive {
     *   -fx-text-fill: green;
     * }
     * .money-cell:negative {
     *   -fx-text-fill: red;
     * }
     * </pre>
     * 
     * This CSS results in positive values being green, and negative values
     * being red. By exposing the pseudo class states in CSS, it is possible
     * for the cell to be totally styled using CSS. This makes it trivial to
     * reuse the cell with an entirely different look.
     *  
     * @param s A {@link List} of Strings which represent the current state
     *      of the cell. It is legal to add further strings to the list, to
     *      specify further states.
     */
    public void getCssState(List<String> s) {
        // no-op by default
    }
    
    /**
     * Call this method from the {@link #updateItem(Object, boolean) updateItem}
     * method when the item changes, and therefore the state of the cell has
     * changed. The strings passed to this method should be the same as those
     * that are provided via {@link #getCssState(List) getCssState}. 
     * 
     * <p>Only call this method using the strings of states that have actually 
     * changed. For example, when the MoneyCell changes from being negative to
     * positive, call <code>stateChanged("negative", "positive")</code>. Note
     * that order does not matter.
     */
    protected final void stateChanged(String state, String... states) {
        impl_pseudoClassStateChanged(state);
        for (String s : states) {
            impl_pseudoClassStateChanged(s);
        }
    }
    
    /**
     * @treatasprivate implementation detail
     * @deprecated This is an internal API that is not intended for use 
     * and will be removed in the next version.
     */
    @Deprecated @Override public long impl_getPseudoClassState() {
        List<String> states = new ArrayList<String>();
        getCssState(states);
        return CSSCell.getPseudoClassState(super.impl_getPseudoClassState(), states);
    }
}