All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.rpgframework.jfx.rules.skin.AttributeTableSkin Maven / Gradle / Ivy

package de.rpgframework.jfx.rules.skin;

import java.lang.System.Logger;
import java.util.HashMap;
import java.util.Map;

import org.prelle.javafx.JavaFXConstants;
import org.prelle.javafx.SymbolIcon;

import de.rpgframework.character.RuleSpecificCharacterObject;
import de.rpgframework.genericrpg.NumericalValueController;
import de.rpgframework.genericrpg.chargen.RecommendationState;
import de.rpgframework.genericrpg.data.AttributeValue;
import de.rpgframework.genericrpg.data.IAttribute;
import de.rpgframework.jfx.RPGFrameworkJFXConstants;
import de.rpgframework.jfx.rules.AttributeTable;
import de.rpgframework.jfx.rules.AttributeTable.AttributeColumn;
import de.rpgframework.jfx.rules.AttributeTable.Mode;
import javafx.collections.MapChangeListener;
import javafx.collections.ObservableMap;
import javafx.scene.Node;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.SkinBase;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;

/**
 * @author Stefan
 *
 */
@SuppressWarnings({ "rawtypes", "unchecked" })
public class AttributeTableSkin extends SkinBase> {

	private final static Logger logger = System.getLogger(RPGFrameworkJFXConstants.BASE_LOGGER_NAME);

	private class CellData {
		public int columnNumber;
		public Node lastComponent;
	}

	private class ColumnData {
		public AttributeColumn colDef;
		public Map cellData = new HashMap<>();
	}

	private GridPane grid;

	private Map recIcon;
	private Map finVal;
	private Map decButton;
	private Map incButton;
	private Map customColumns;

	private MapChangeListener propertiesMapListener = c -> {
        if (! c.wasAdded()) return;
        if (Properties.RECREATE.equals(c.getKey())) {
            refresh();
            getSkinnable().requestLayout();
            getSkinnable().getProperties().remove(Properties.RECREATE);
        }
    };

	//-------------------------------------------------------------------
	public AttributeTableSkin(AttributeTable control) {
		super(control);
		initComponents();
		initLayout();
		initInteractivity();
		refresh();
		HBox.setHgrow(control, Priority.SOMETIMES);
		control.setMaxWidth(Double.MAX_VALUE);
	}

	//-------------------------------------------------------------------
	@SuppressWarnings("unchecked")
	private void initComponents() {
		grid = new GridPane();
		grid.setVgap(5);
		grid.setHgap(10);
		grid.getStyleClass().add("attribute-table");
		// Recommendation column
		grid.getColumnConstraints().add(new ColumnConstraints());
		// Name column
		ColumnConstraints col2 = new ColumnConstraints();
		col2.setHgrow(Priority.SOMETIMES);
		grid.getColumnConstraints().add(col2);
		// Value column
		ColumnConstraints col3 = new ColumnConstraints();
		col3.setHgrow(Priority.SOMETIMES);
		grid.getColumnConstraints().add(col3);
		// Button columns
		if (getSkinnable().getMode()!=Mode.SHOW_ONLY) {
			grid.getColumnConstraints().add(new ColumnConstraints());
			grid.getColumnConstraints().add(new ColumnConstraints());
		}
		customColumns = new HashMap();
		recIcon   = new HashMap();
		finVal    = new HashMap();
		decButton = new HashMap();
		incButton = new HashMap();
		for (A attr : getSkinnable().getAttributes()) {
			SymbolIcon icon = new SymbolIcon("favorite");
			recIcon.put(attr, icon);
			Label fin = new Label("-");
			fin.getStyleClass().add(JavaFXConstants.STYLE_HEADING5);
			finVal.put(attr, fin);
			decButton.put(attr, new Button(null, new SymbolIcon("remove")));
			incButton.put(attr, new Button(null, new SymbolIcon("add")));
		}

		// Extra columns before the value
		for (AttributeTable.AttributeColumn column : getSkinnable().getColumns()) {
			ColumnData data = new ColumnData();
			data.colDef= column;
			customColumns.put(column, data);
			// Custom column
			ColumnConstraints colX = new ColumnConstraints();
			colX.setHgrow(Priority.SOMETIMES);
			grid.getColumnConstraints().add(colX);
			// Create cells
			for (A attr : getSkinnable().getAttributes()) {
				data.cellData.put(attr, new CellData());
			}
		}
	}

	//-------------------------------------------------------------------
	@SuppressWarnings("unchecked")
	private void initLayout() {
		int y=0;
		for (A attr : getSkinnable().getAttributes()) {
			y++;
			int col=0;
			// Column 0: Attribute name
			SymbolIcon icon = recIcon.get(attr);
			icon.setUserData(attr);
			grid.add(icon, col++, y);

			// Column 1: Attribute name
			Label name = new Label(attr.getName());
			name.setMaxWidth(Double.MAX_VALUE);
			name.setOnMouseClicked(ev -> getSkinnable().setSelectedAttribute(attr));
			grid.add(name, col, y);
//			GridPane.setHgrow(name, Priority.ALWAYS);

			// Extra columns before the value
			for (AttributeTable.AttributeColumn column : getSkinnable().getColumns()) {
				if (!column.isShowBeforeValueColumn()) {
					continue;
				}
				col++;
				CellData cell = customColumns.get(column).cellData.get(attr);
				cell.columnNumber = col;
//				logger.error("B-------> "+col+","+y+" = "+cell);
				// Eventually add header
				if (attr==getSkinnable().getAttributes()[0]) {
					Label header = new Label(column.getTitle());
					grid.add(header, col, 0);
				}
			}

			// Column: Decrease button
			if (getSkinnable().getMode()!=Mode.SHOW_ONLY) {
				col++;
				grid.add(decButton.get(attr), col, y);
			}
			// Column: Final value
			col++;
			grid.add(finVal.get(attr), col, y);
			// Column: Increase button
			if (getSkinnable().getMode()!=Mode.SHOW_ONLY) {
				col++;
				grid.add(incButton.get(attr), col, y);
			}

			// Extra columns behind the value
			for (AttributeTable.AttributeColumn column : getSkinnable().getColumns()) {
				if (column.isShowBeforeValueColumn()) {
					continue;
				}
				col++;
				CellData cell = customColumns.get(column).cellData.get(attr);
				cell.columnNumber = col;
//				logger.error("B-------> "+col+","+y+" = "+cell);
			}
		}

		getChildren().add(grid);
	}

	//-------------------------------------------------------------------
	private void initInteractivity() {
		for (IAttribute key : getSkinnable().getAttributes()) {
			decButton.get(key).setOnAction(ev -> decrease(key));
			incButton.get(key).setOnAction(ev -> increase(key));

		}

		getSkinnable().modelProperty().addListener( (ov,o,n) -> refresh());
		getSkinnable().controllerProperty().addListener( (ov,o,n) -> refresh());
		getSkinnable().modeProperty().addListener( (ov,o,n) -> refresh());

        final ObservableMap properties = getSkinnable().getProperties();
        properties.remove(Properties.RECREATE);
        properties.addListener(propertiesMapListener);



	}

	//-------------------------------------------------------------------
	private void decrease(IAttribute attr) {
		getSkinnable().setSelectedAttribute(attr);

		NumericalValueController> controller = getSkinnable().getController();
		RuleSpecificCharacterObject model = getSkinnable().getModel();
		if (controller!=null && model!=null) {
			controller.decrease(model.getAttribute(attr));
			refresh();
		}
	}

	//-------------------------------------------------------------------
	private void increase(IAttribute attr) {
		getSkinnable().setSelectedAttribute(attr);

		NumericalValueController> controller = getSkinnable().getController();
		RuleSpecificCharacterObject model = getSkinnable().getModel();
		if (controller!=null && model!=null) {
			controller.increase(model.getAttribute(attr));
			refresh();
		}
	}

	//-------------------------------------------------------------------
	private void refresh() {
//		System.out.println("AttributeTableSkin.refresh()") ;
		NumericalValueController> controller = getSkinnable().getController();
		RuleSpecificCharacterObject model = getSkinnable().getModel();
		if (model==null)
			return;

		int y=0;
		for (A attr : getSkinnable().getAttributes()) {
			y++;
			AttributeValue val = model.getAttribute(attr);
			Label fin = finVal.get(attr);
			if (val!=null) {
				fin.setText( String.valueOf(val.getModifiedValue()));
			}
			if (getSkinnable().getMode()!=Mode.SHOW_ONLY && controller!=null) {
				Button dec = decButton.get(attr);
				dec.setDisable(!controller.canBeDecreased(val).get());
				Button inc = incButton.get(attr);
				inc.setDisable(!controller.canBeIncreased(val).get());
			}
			SymbolIcon icon = recIcon.get(attr);
			RecommendationState state = (controller!=null)?controller.getRecommendationState(attr):null;
			if (state==null || state==RecommendationState.NEUTRAL) {
				icon.setVisible(false);
			} else {
				icon.setVisible(true);
				icon.setSymbol( (state==RecommendationState.STRONGLY_RECOMMENDED)?"favorite":"outlinestar");
			}

			// Custom columns
			for (AttributeTable.AttributeColumn column : getSkinnable().getColumns()) {
				ColumnData col = customColumns.get(column);
				if (col==null) {
					continue;
				}
				CellData data = col.cellData.get(attr);;
				// Remove eventually existing old version
				if (data.lastComponent!=null) {
					grid.getChildren().remove(data.lastComponent);
				}
				// Create a new value
				Object cellVal = column.getValueFactory().apply(model, attr);
				// Create a new component
				if (column.getComponentFactory() != null) {
					data.lastComponent = (Node) column.getComponentFactory().apply(attr, cellVal);
				} else {
					data.lastComponent =  new Label(String.valueOf(cellVal));
				}
//				logger.error("-------> "+data.columnNumber+","+y+" = "+data);
				if (data.lastComponent!=null) {
					grid.add(data.lastComponent, data.columnNumber, y);
				}
			}
		}

		getSkinnable().requestLayout();
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy