You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
426 lines
10 KiB
426 lines
10 KiB
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);
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
}
|