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

de.rpgframework.jfx.DataItemPane Maven / Gradle / Ivy

There is a newer version: 5.3.0
Show newest version
package de.rpgframework.jfx;

import java.lang.System.Logger.Level;
import java.util.Collection;
import java.util.List;
import java.util.ResourceBundle;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.stream.Collectors;

import org.prelle.javafx.ImageSpinningListView;
import org.prelle.javafx.JavaFXConstants;
import org.prelle.javafx.ListWithDetailsView;
import org.prelle.javafx.ListWithDetailsViewColumn;
import org.prelle.javafx.NodeWithTitle;
import org.prelle.javafx.ResponsiveControl;
import org.prelle.javafx.ResponsiveControlManager;
import org.prelle.javafx.WindowMode;

import de.rpgframework.ResourceI18N;
import de.rpgframework.genericrpg.data.Choice;
import de.rpgframework.genericrpg.data.ChoiceOrigin;
import de.rpgframework.genericrpg.data.ComplexDataItem;
import de.rpgframework.genericrpg.data.DataItem;
import de.rpgframework.genericrpg.data.Decision;
import de.rpgframework.genericrpg.data.DecisionContainer;
import de.rpgframework.genericrpg.data.GenericRPGTools;
import de.rpgframework.genericrpg.modification.DataItemModification;
import de.rpgframework.genericrpg.modification.Modification;
import de.rpgframework.genericrpg.modification.ModificationChoice;
import de.rpgframework.genericrpg.modification.ModifiedObjectType;
import de.rpgframework.genericrpg.requirements.Requirement;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.FXCollections;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.Tooltip;
import javafx.scene.image.Image;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.text.Text;
import javafx.scene.text.TextFlow;
import javafx.util.Callback;

/**
 * Provide a spinner to browse through a list of data items
 * and add additional information
 *
 * @author prelle
 *
 */
public class DataItemPane extends ListWithDetailsView implements ResponsiveControl {

	final static ResourceBundle RES = ResourceBundle.getBundle(DataItemPane.class.getName());

	private ObjectProperty> modifConverter = new SimpleObjectProperty<>();
	private ObjectProperty> refTypeConverter = new SimpleObjectProperty<>();

	private ObjectProperty> choiceConverter = new SimpleObjectProperty<>();
	private DecisionContainer decisionContainer;
	private ObjectProperty> decisionHandler = new SimpleObjectProperty<>();
	private ObjectProperty> modDecisionHandler = new SimpleObjectProperty<>();

	private ObjectProperty customNode1 = new SimpleObjectProperty<>();

	private ObjectProperty layoutMode = new SimpleObjectProperty<>(WindowMode.EXPANDED);

	private BooleanProperty showDecisionColumn = new SimpleBooleanProperty(true);
	private BooleanProperty showStatsColumn = new SimpleBooleanProperty(true);
	private BooleanProperty showModificationsInDescription = new SimpleBooleanProperty(true);

	private transient Function reqR;
	private transient Function modR;

	private ImageSpinningListView selector;

	private ListWithDetailsViewColumn colEffects;
	private ListWithDetailsViewColumn colChoices;
	private ListWithDetailsViewColumn colDescription;

	//-------------------------------------------------------------------
	public DataItemPane(Function reqR, Function modR) {
		layoutMode.set(ResponsiveControlManager.getCurrentMode());
		this.reqR = reqR;
		this.modR = modR;

		initComponents();
		initInteractivity();

//		selectedItemValue.addListener( (ov,o,n) -> selectedItem.set((n!=null)?n.getResolved():null));
	}

	//-------------------------------------------------------------------
	private void initColumns() {
		colEffects = new ListWithDetailsViewColumn<>(ResourceI18N.get(RES, "tab.effects"), item -> {
			return getContentStats(item);
		});
		colChoices = new ListWithDetailsViewColumn<>(ResourceI18N.get(RES, "tab.choices"), item -> {
			return getContentStats(item);
		});
		colDescription = new ListWithDetailsViewColumn<>(ResourceI18N.get(RES, "tab.description"), item -> {
			GenericDescriptionVBox ret = new GenericDescriptionVBox(reqR,modR);
			ret.setUseScrollPane(false);
			ret.showModificationsInDescriptionProperty().bind(showModificationsInDescriptionProperty());
			ret.setData(item);
			return ret;
		});
	}

	//-------------------------------------------------------------------
	private void initComponents() {
		initColumns();
		// Configure image spinner
		selector = new ImageSpinningListView();
		getColumns().addAll(colChoices,colDescription);
		setSelectorNode(selector);
	}

	//-------------------------------------------------------------------
	private void initInteractivity() {
		customNode1Property().addListener( (ov,o,n) -> {
			getColumns().setAll(colChoices,colDescription);
			if (n!=null) {
				ListWithDetailsViewColumn custCol = new ListWithDetailsViewColumn<>(n.getTitle(), item -> {
					return n.getContent();
				});
				getColumns().add(0, custCol);
			}
		});
	}

//	//-------------------------------------------------------------------
//	public DataItemPane(Node node, ObjectProperty selected,Function reqR, Function modR) {
//		this(reqR,modR);
//		selectorNode.set(node);
//		selectedItem.bind(selected);
//	}
//
//	//-------------------------------------------------------------------
//	/**
//	 * @see javafx.scene.control.Control#createDefaultSkin()
//	 */
//	@Override
//	public Skin createDefaultSkin() {
//		return new DataItemPaneSkin(this, reqR, modR);
//	}

	//-------------------------------------------------------------------
	public ReadOnlyObjectProperty selectedItemProperty() { return selector.getSelectionModel().selectedItemProperty();}
	public T getSelectedItem() { return selector.getSelectionModel().getSelectedItem();}
	public DataItemPane setSelectedItem(T value) {
		RPGFrameworkJavaFX.logger.log(Level.ERROR, "setSelectedItem({0}) for {1}", value, getId());
		selector.getSelectionModel().select(value);
		return this;
	}

	//-------------------------------------------------------------------
	public void setItems(Collection items) {
		selector.setItems(FXCollections.observableArrayList(items));
		selector.refreshNames();
	}

//	//-------------------------------------------------------------------
//	public ObjectProperty> selectedItemValueProperty() { return selectedItemValue;}
//	public DataItemValue getSelectedItemValue() { return selectedItemValue.get();}
//	public DataItemPane setSelectedItemValue(DataItemValue value) { selectedItemValue.set(value); return this;}

	//-------------------------------------------------------------------
	public ObjectProperty> modificationConverterProperty() { return modifConverter;}
	public Function getModificationConverter() { return modifConverter.get();}
	public DataItemPane setModificationConverter(Function value) { modifConverter.set(value); return this; }

	//-------------------------------------------------------------------
	public ObjectProperty> referenceTypeConverterProperty() { return refTypeConverter;}
	public Function getReferenceTypeConverter() { return refTypeConverter.get();}
	public DataItemPane setReferenceTypeConverter(Function value) { refTypeConverter.set(value); return this; }

	//-------------------------------------------------------------------
	public ObjectProperty> choiceConverterProperty() { return choiceConverter;}
	public Function getChoiceConverter() { return choiceConverter.get();}
	public DataItemPane setChoiceConverter(Function value) { choiceConverter.set(value); return this; }

	//-------------------------------------------------------------------
	public void setUseForChoices(DecisionContainer value) {
		this.decisionContainer = value;
	}

	//-------------------------------------------------------------------
	public ObjectProperty> decisionHandlerProperty() { return decisionHandler;}
	public BiConsumer getDecisionHandler() { return decisionHandler.get();}
	public DataItemPane setDecisionHandler(BiConsumer value) { decisionHandler.set(value); return this; }

	//-------------------------------------------------------------------
	public ObjectProperty> modDecisionHandlerProperty() { return modDecisionHandler;}
	public BiConsumer getModDecisionHandler() { return modDecisionHandler.get();}
	public DataItemPane setModDecisionHandler(BiConsumer value) { modDecisionHandler.set(value); return this; }

	//-------------------------------------------------------------------
	public ObjectProperty customNode1Property() { return customNode1;}
	public NodeWithTitle getCustomNode1() { return customNode1.get();}
	public DataItemPane setCustomNode1(NodeWithTitle value) { customNode1.set(value); return this;}

	//--------------------------------------------------------------------
	public BooleanProperty showDecisionColumnProperty() { return showDecisionColumn; }
	public Boolean  isShowDecisionColumn() { return showDecisionColumn.get(); }
	public DataItemPane setShowDecisionColumn(Boolean value) { showDecisionColumn.set(value); return this; }

	//--------------------------------------------------------------------
	public BooleanProperty showStatsColumnProperty() { return showStatsColumn; }
	public Boolean  isShowStatsColumn() { return showStatsColumn.get(); }
	public DataItemPane setShowStatsColumn(Boolean value) { showStatsColumn.set(value); return this; }

	//-------------------------------------------------------------------
	public ObjectProperty layoutModeProperty() { return layoutMode;}

	//--------------------------------------------------------------------
	public BooleanProperty showModificationsInDescriptionProperty() { return showModificationsInDescription; }
	public Boolean  isShowModificationsInDescription() { return showModificationsInDescription.get(); }
	public DataItemPane setShowModificationsInDescription(Boolean value) { showModificationsInDescription.set(value); return this; }

	//-------------------------------------------------------------------
	/**
	 * @see org.prelle.javafx.ResponsiveControl#setResponsiveMode(org.prelle.javafx.WindowMode)
	 */
	@Override
	public void setResponsiveMode(WindowMode value) {
		RPGFrameworkJavaFX.logger.log(Level.WARNING, getId()+": mode changed to "+value);
		layoutMode.set(value);
	}

	//-------------------------------------------------------------------
	public ObjectProperty> imageConverterProperty() { return selector.imageConverterProperty(); }
	public Callback getImageConverter() { return selector.getImageConverter(); }
	public DataItemPane setImageConverter(Callback value) { selector.setImageConverter(value); return this; }

	//-------------------------------------------------------------------
	public ObjectProperty> nameConverterProperty() { return selector.stringConverterProperty(); }
	public Callback getNameConverter() { return selector.getStringConverter(); }
	public DataItemPane setNameConverter(Callback value) { selector.setStringConverter(value); return this; }

	//-------------------------------------------------------------------
	private Node getContentStats(T raw) {
		VBox contentStats = new VBox();
		RPGFrameworkJavaFX.logger.log(Level.DEBUG, "getContentStats() for {0} using {1}", raw, getModificationConverter());
		if (raw instanceof ComplexDataItem) {
			ComplexDataItem item = (ComplexDataItem)raw;
			ModifiedObjectType previousType = null;
			Function modConv = getModificationConverter();
			for (Modification m : item.getOutgoingModifications()) {
				// Check if it is a new category
				if (m.getReferenceType()!=previousType) {
					String category = String.valueOf(m.getReferenceType());
					if (getReferenceTypeConverter()!=null && m.getReferenceType()!=null)
						category = getReferenceTypeConverter().apply(m.getReferenceType());
					RPGFrameworkJavaFX.logger.log(Level.DEBUG, "RefTypeConv {0} converted {1} into {2}",getReferenceTypeConverter(), m.getReferenceType(), category);
					if (category != null) {
						Label head = new Label(category);
						head.getStyleClass().add(JavaFXConstants.STYLE_HEADING5);
						contentStats.getChildren().add(head);
						VBox.setMargin(head, new Insets(5, 0, 0, 0));
					}
				}
				previousType = m.getReferenceType();

				// Create a (potentially wrapped line) per modification
				Button button = null;
				Tooltip tooltip = null;
				String text = (modConv!=null)?modConv.apply(m):String.valueOf(m);
				Text choiceText = new Text(text);
				choiceText.setStyle("-fx-fill: -fx-text-base-color");
				// Decision text
				Text decText = new Text();
				decText.getStyleClass().add(JavaFXConstants.STYLE_HEADING5);
				if (m instanceof DataItemModification) {
					DataItemModification mod = (DataItemModification)m;
					if (mod.getConnectedChoice()!=null) {
						RPGFrameworkJavaFX.logger.log(Level.DEBUG, "Determine decision text for "+mod+" and choice "+mod.getConnectedChoice()+" using "+decisionContainer);
						if (decisionContainer.getDecision(mod.getConnectedChoice())!=null) {
							updateChoice(mod, decText);
						}

						Choice choice = item.getChoice(mod.getConnectedChoice());
						button = new Button((decText.getText().length()==0)?"?":"!");
						button.setOnAction(ev -> {
							getDecisionHandler().accept(getSelectedItem(), choice);
							RPGFrameworkJavaFX.logger.log(Level.WARNING, "Decision dialog closed------------------updating choice");
							updateChoice(mod, decText);
						});
						button.setUserData(choice);
					} else if (mod.getResolvedKey()!=null && mod.getResolvedKey() instanceof DataItem) {
						DataItem toShow = mod.getResolvedKey();
						if (toShow!=null) {
							tooltip = new Tooltip(toShow.getDescription());
							tooltip.setWrapText(true);
							tooltip.setMaxWidth(300);
						}
					}
				} else if (m instanceof ModificationChoice) {
					ModificationChoice mod = (ModificationChoice)m;
					button = new Button((decText.getText().length()==0)?"?":"!");
					button.setOnAction(ev -> {
						if (getModDecisionHandler()==null) {
							RPGFrameworkJavaFX.logger.log(Level.ERROR, "Missing modDecisionHandler");
						} else {
							getModDecisionHandler().accept(getSelectedItem(), mod);
							RPGFrameworkJavaFX.logger.log(Level.WARNING, "Decision dialog closed------------------");
							updateChoice(mod, decText);
						}
					});
					button.setUserData(mod);
				}
				TextFlow label = new TextFlow(choiceText, decText);

				if (button==null) {
					contentStats.getChildren().add(label);
				} else {
					HBox box = new HBox(5, button, label);
					box.setAlignment(Pos.CENTER_LEFT);
					contentStats.getChildren().add(box);
				}
			}
		}

		return contentStats;
	}

	//-------------------------------------------------------------------
	private void updateChoice(DataItemModification mod, Text decText) {
		System.err.println("DataItemPane.updateChoice("+mod+") for "+getSelectedItem()+" with "+decisionContainer);
		RPGFrameworkJavaFX.updateChoice(
				decisionContainer,
				(ChoiceOrigin)getSelectedItem(),
				getModificationConverter(), mod, decText);
	}
	//-------------------------------------------------------------------
	private void updateChoice(ModificationChoice mod, Text decText) {
		Decision dec = decisionContainer.getDecision(mod.getUUID());
		if (dec == null) {
			decText.setText("");
		} else {
			List modList = GenericRPGTools.decisionToModifications(mod, dec);
			List modListS = modList.stream().map(mb -> getModificationConverter().apply(mb))
					.collect(Collectors.toList());
			decText.setText(" (" + String.join(", ", modListS) + ")");
		}
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy