/* * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. * * * * * * * * * * * * * * * * * * * * */ package javafx.scene.control.cell; import java.util.Map; import javafx.beans.NamedArg; import javafx.beans.property.ReadOnlyBooleanWrapper; import javafx.beans.property.ReadOnlyDoubleWrapper; import javafx.beans.property.ReadOnlyFloatWrapper; import javafx.beans.property.ReadOnlyIntegerWrapper; import javafx.beans.property.ReadOnlyLongWrapper; import javafx.beans.property.ReadOnlyObjectWrapper; import javafx.beans.property.ReadOnlyStringWrapper; import javafx.beans.value.ObservableValue; import javafx.scene.control.TableCell; import javafx.scene.control.TableColumn; import javafx.scene.control.TableColumn.CellDataFeatures; import javafx.scene.control.TableView; import javafx.util.Callback; /** * A convenience implementation of the Callback interface, designed specifically * for use within the {@link TableColumn} * {@link TableColumn#cellValueFactoryProperty() cell value factory}. An example * of how to use this class is: * *

 * ObservableList personsMapList = ...
 *
 * TableColumn<Map, String> firstNameColumn = new TableColumn<Map, String>("First Name");
 * firstNameColumn.setCellValueFactory(new MapValueFactory<String>("firstName"));
 *
 * TableView table = new TableView(personMapList);
 * tableView.getColumns().setAll(firstNameColumn);
 * 
* *

In this example, there is a list of Map instances, where each Map instance * representsa single row in the TableView. The "firstName" string is used as a * key into this map, and the value corresponding to this key is returned, if * one exists. If the value is an {@link ObservableValue}, then this is returned * directly, otherwise the value is wrapped in a {@link ReadOnlyObjectWrapper}. * * @see TableColumn * @see TableView * @see TableCell * @see PropertyValueFactory * @param The type of the class contained within the TableColumn cells. * @since JavaFX 2.2 */ public class MapValueFactory implements Callback, ObservableValue> { private final Object key; /** * Creates a default MapValueFactory, which will use the provided key to * lookup the value for cells in the {@link TableColumn} in which this * MapValueFactory is installed (via the * {@link TableColumn#cellValueFactoryProperty() cell value factory} property. * * @param key The key to use to lookup the value in the {@code Map}. */ public MapValueFactory(final @NamedArg("key") Object key) { this.key = key; } @Override public ObservableValue call(CellDataFeatures cdf) { Map map = cdf.getValue(); Object value = map.get(key); // ideally the map will contain observable values directly, and in which // case we can just return this observable value. if (value instanceof ObservableValue) { return (ObservableValue)value; } // TODO // If we are here, the value in the map for the given key is not observable, // but perhaps the Map is an ObservableMap. If this is the case, we // can add a listener to the map for the given key, and possibly observe // it for changes and return these // if (map instanceof ObservableMap) { // ObservableMap oMap = (ObservableMap) map; // // .... // } // Often time there is special case code to deal with specific observable // value types, so we try to wrap in the most specific type. if (value instanceof Boolean) { return (ObservableValue) new ReadOnlyBooleanWrapper((Boolean)value); } else if (value instanceof Integer) { return (ObservableValue) new ReadOnlyIntegerWrapper((Integer)value); } else if (value instanceof Float) { return (ObservableValue) new ReadOnlyFloatWrapper((Float)value); } else if (value instanceof Long) { return (ObservableValue) new ReadOnlyLongWrapper((Long)value); } else if (value instanceof Double) { return (ObservableValue) new ReadOnlyDoubleWrapper((Double)value); } else if (value instanceof String) { return (ObservableValue) new ReadOnlyStringWrapper((String)value); } // fall back to an object wrapper return new ReadOnlyObjectWrapper((T)value); } }