|
|
package application.customviews;
import java.util.ArrayList; import java.util.HashMap; import java.util.List;
import application.UICoordinator; import application.enums.EntryType; import application.helpers.wrappers.Element; import application.helpers.wrappers.SubElement; import application.res.Backgrounds; import application.res.Text; import javafx.beans.binding.Bindings; import javafx.beans.property.BooleanProperty; import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.event.EventHandler; import javafx.scene.Node; import javafx.scene.control.Label; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.input.MouseEvent; import javafx.scene.layout.AnchorPane; import javafx.scene.layout.BorderPane; import javafx.scene.layout.VBox;
/** * This class represents one element in the select view where the user can * select the data he / she wishes to contribute. The elements can contain * {@link SubEntryView}s with sub elements. Every EntryView can contain an info * view and may be opened for the sub elements (if they exist). * * @author Bianca * */ public class EntryView extends VBox implements ChangeListener<Boolean> { /** * The {@link Element} represented by this {@link EntryView}. */ private Element elem; /** * The header of the element. Is always visible. */ private AnchorPane header; /** * Contains the detailed information for the element as defined in its * {@link EntryType}. */ private BorderPane details; /** * Contains the sub elements if they exist. If there are no subElements, the * view will never be visible and there won't be a button to show it. */ private BorderPane subItem; /** * Indicates whether the information part is currently shown. */ private boolean infoOpen = false; /** * Indicates whether the sub elements are currently shown. */ private boolean subOpen = false; /** * Indicates whether the whole element with all its sub elements is selected. */ private BooleanProperty selected; /** * Represents the button to open the information view of the element. */ private BorderPane help; /** * Represents the button to show the sub elements. */ private BorderPane open; /** * Number of all sub elements. */ private int subElemCount = 0; /** * Number of all selected sub elements. */ private int selectedSubElemCount = 0;
/** * Sets up an {@link EntryView} without sub elements. * * @param elem The data of this entry. */ public EntryView(Element elem) { super(); this.elem = elem; selected = new SimpleBooleanProperty(false); header = new AnchorPane(); details = new BorderPane(); details.setId("Details"); subItem = new BorderPane(); subItem.setId("SubItem"); details.setCenter(new Label(elem.getType().getDesc())); header.minWidthProperty().bind(Bindings.createDoubleBinding(() -> this.getWidth(), this.widthProperty())); header.maxWidthProperty().bind(Bindings.createDoubleBinding(() -> this.getWidth(), this.widthProperty()));
// right side (help button for showing further information)
help = new BorderPane(); help.setId("help"); ImageView helpImage = new ImageView(new Image(UICoordinator.class.getResourceAsStream("help.png"))); help.setCenter(helpImage); AnchorPane.setRightAnchor(help, 0.0); AnchorPane.setTopAnchor(help, 0.0); AnchorPane.setBottomAnchor(help, 0.0);
help.setOnMouseClicked(new EventHandler<MouseEvent>() { @Override public void handle(MouseEvent arg0) { // always close sub elements first
if (subOpen) { closeSub(); }
if (infoOpen) { closeInfo(); } else { getChildren().add(1, details); infoOpen = true; help.setBackground(Backgrounds.greyBackground); } }
});
// middle (name and value etc)
Label text = new Label(String.format(Text.F_ME_SAVE, elem.getType().getValue(), elem.getValue())); AnchorPane.setLeftAnchor(text, 50.0); AnchorPane.setTopAnchor(text, 0.0); AnchorPane.setBottomAnchor(text, 0.0); AnchorPane.setRightAnchor(text, 50.0); header.getChildren().add(text); text.minWidthProperty().bind( Bindings.createDoubleBinding(() -> header.getWidth() - help.getWidth() * 2, header.widthProperty())); text.setOnMouseClicked(new EventHandler<MouseEvent>() { @Override public void handle(MouseEvent event) { setSelected(!getSelected(), true); } });
header.getChildren().add(help); getChildren().add(header);
}
/** * Sets up an {@link EntryView} with sub elements. * * @param elem The data of this entry. * @param subEntries The sub elements which belong to this element */ public EntryView(Element elem, HashMap<String, Integer> subEntries) { this(elem); VBox subContainer = new VBox(); for (String entry : subEntries.keySet()) { subElemCount++; SubEntryView sub = new SubEntryView(new SubElement(entry, subEntries.get(entry))); sub.addCheckListener(this); subContainer.getChildren().add(sub); } subItem.setCenter(subContainer);
// left side
open = new BorderPane(); ImageView openImage = new ImageView(new Image(UICoordinator.class.getResourceAsStream("dreieck2.png"))); open.setId("open"); AnchorPane.setLeftAnchor(open, 0.0); AnchorPane.setTopAnchor(open, 0.0); AnchorPane.setBottomAnchor(open, 0.0); open.setCenter(openImage); openImage.setRotate(180);
open.setOnMouseClicked(new EventHandler<MouseEvent>() {
@Override public void handle(MouseEvent arg0) { // always close info first
if (infoOpen) { closeInfo(); } if (subOpen) { closeSub(); } else { openSub(); } } });
header.getChildren().add(open); }
/** * Returns the value / count of this entry. * * @return The described value. */ public String getValue() { return elem.getValue(); }
/** * Closes the detailed information view if it is open */ private void closeInfo() { getChildren().remove(details); infoOpen = false; help.setBackground(Backgrounds.darkGreyBackground); }
/** * Shows the sub elements if they are not open yet. */ private void openSub() { getChildren().add(subItem); subOpen = true; open.setBackground(Backgrounds.greyBackground); }
/** * Closes the sub elements view if it is not closed yet. */ private void closeSub() { getChildren().remove(subItem); subOpen = false; open.setBackground(Backgrounds.darkGreyBackground);
}
/** * Sets the value of the selection. If wanted it can also adjust the states of * the {@link SubEntryView}s * * @param value New value of the selection. * @param all If true then the {@link SubEntryView}s will also be adjusted. * Otherwise they won't be changed. */ public void setSelected(boolean value, boolean all) { this.selected.set(value); // adjust color of the entry
if (!value) { header.setBackground(null); } else { header.setBackground(Backgrounds.greenBackground); } // adjust the sub elements
if (all && subItem.getCenter() != null) { // there are subitems
for (Node child : ((VBox) subItem.getCenter()).getChildren()) { SubEntryView sub = (SubEntryView) child; sub.setSelected(value); } } }
/** * Gets the selection. * * @return {@code True} if the entry or any sub entry is selected. {@code False} * otherwise. */ public boolean getSelected() { return selectedSubElemCount > 0 || selected.getValue(); }
/** * Allows for a listener to be added to the selection value. * * @param listen Listener to be added. */ public void addCheckListener(ChangeListener<Boolean> listen) { selected.addListener(listen); }
/** * Returns the {@link EntryType} of this {@link EntryView}. * * @return The described value. */ public EntryType getEntryType() { return this.elem.getType(); }
@Override public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) { // Here the sub elements are watched and the selected ones counted
if (newValue) { selectedSubElemCount++; } else { selectedSubElemCount--; } // if any sub element was selected then of course the whole
// element also needs to be selected.
if (selectedSubElemCount > 0) { this.selected.set(true); } else { this.selected.set(false); }
// this adjusts the color of the element but not the selection of the sub
// elements
if (selectedSubElemCount == subElemCount) { setSelected(true, false); } else if (selectedSubElemCount > 0) { header.setBackground(Backgrounds.lightGreenBackground); } else { setSelected(false, false); } }
/** * Returns a list of readable names of all sub elements or an empty list if * their are no sub elements. * * @return The described value. */ public List<String> getSelectedSubElementNames() { List<String> res = new ArrayList<>(); if (subItem.getCenter() != null) { // there are subitems
for (Node child : ((VBox) subItem.getCenter()).getChildren()) { SubEntryView sub = (SubEntryView) child; if (sub.isSelected()) { res.add(sub.getName()); } } }
return res; }
/** * Returns all {@link SubEntryView}s of this entry in a list or an empty lift if * there are now sub elements. * * @return The described value. */ public List<SubEntryView> getSelectedSubElements() { List<SubEntryView> res = new ArrayList<>(); if (subItem.getCenter() != null) { // there are sub elements
for (Node child : ((VBox) subItem.getCenter()).getChildren()) { SubEntryView sub = (SubEntryView) child; if (sub.isSelected()) { res.add(sub); } } }
return res; }
public void selectSubelement(String elementName) { if (subItem.getCenter() != null) { // there are subitems
for (Node child : ((VBox) subItem.getCenter()).getChildren()) { SubEntryView sub = (SubEntryView) child; if (sub.getName().contains(elementName)) { sub.setSelected(true); } } }
}
}
|