package com.twasyl.slideshowfx.controls.builder.nodes;
import com.twasyl.slideshowfx.ui.controls.ExtendedTextField;
import com.twasyl.slideshowfx.utils.DialogHelper;
import de.jensd.fx.glyphs.fontawesome.FontAwesomeIcon;
import de.jensd.fx.glyphs.fontawesome.FontAwesomeIconView;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.control.*;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import static com.twasyl.slideshowfx.ui.controls.validators.Validators.isInteger;
import static com.twasyl.slideshowfx.ui.controls.validators.Validators.isNotEmpty;
/**
* Control allowing to define a slide. The control extends the {@link TitledPane} in order to properly be displayed
* within the editor.
*
* @author Thierry Wasylczenko
* @version 1.0
* @since SlideshowFX 1.3
*/
public class SlideDefinition extends TitledPane {
private static final Logger LOGGER = Logger.getLogger(SlideDefinition.class.getName());
private ExtendedTextField slideId = new ExtendedTextField("ID", true, 2);
private ExtendedTextField name = new ExtendedTextField("Name", true);
private ExtendedTextField file = new ExtendedTextField("File", true);
private Button delete = new Button();
private Button addSlideElementButton = new Button();
private VBox slideElementsPane = new VBox(5);
private List<SlideElementDefinition> slideElements = new ArrayList<>();
public SlideDefinition() {
this.textProperty().bind(this.name.textProperty());
this.setCollapsible(true);
this.initializeMandatoryFields();
this.initializeDeleteButton();
this.initializeAddSlideElementButton();
final HBox elements = new HBox(5, new Label("Elements:"), this.addSlideElementButton);
elements.setAlignment(Pos.BASELINE_LEFT);
final VBox internalContainer = new VBox(5, getSlideConfigurationPane(), elements, this.slideElementsPane);
this.setContent(internalContainer);
}
private FlowPane getSlideConfigurationPane() {
final HBox group1 = new HBox(5, this.file, this.delete);
group1.setAlignment(Pos.BOTTOM_LEFT);
final FlowPane pane = new FlowPane(5, 5, this.slideId, this.name, group1);
return pane;
}
private void initializeMandatoryFields() {
this.slideId.setValidator(isInteger());
this.name.setValidator(isNotEmpty());
this.file.setValidator(isNotEmpty());
}
private void initializeDeleteButton() {
this.delete.getStyleClass().add("delete-slide");
this.delete.setGraphic(new FontAwesomeIconView(FontAwesomeIcon.TRASH_ALT));
this.delete.setTooltip(new Tooltip("Delete this slide"));
}
private void initializeAddSlideElementButton() {
this.addSlideElementButton.setText("Add element");
this.addSlideElementButton.setTooltip(new Tooltip("Add a slide element"));
this.addSlideElementButton.setOnAction(event -> {
this.addSlideElement();
});
}
public void setOnDelete(final EventHandler<ActionEvent> action) {
this.delete.setOnAction(action);
}
public SlideElementDefinition addSlideElement() {
final SlideElementDefinition element = new SlideElementDefinition();
element.setOnDelete(event -> {
final ButtonType answer = DialogHelper.showConfirmationAlert("Delete slide element", "Are you sure you want to delete this slide element?");
if (answer == ButtonType.YES) {
this.slideElements.remove(element);
this.slideElementsPane.getChildren().remove(element);
}
});
this.slideElements.add(element);
this.slideElementsPane.getChildren().add(element);
return element;
}
public int getSlideId() {
try {
return Integer.parseInt(this.slideId.getText());
} catch (NumberFormatException ex) {
LOGGER.log(Level.WARNING, "Can not parse slide ID", ex);
return -1;
}
}
public void setSlideId(final int slideId) {
this.slideId.setText(String.valueOf(slideId));
}
public String getName() {
return this.name.getText();
}
public void setName(final String name) {
this.name.setText(name);
}
public String getFile() {
return this.file.getText();
}
public void setFile(final String file) {
this.file.setText(file);
}
public List<SlideElementDefinition> getSlideElements() {
return this.slideElements;
}
/**
* Check if the given slide definition is valid. The slide is valid if it's ID, name, file and all
* {@link SlideElementDefinition elements} are valid.
*
* @return {@code true} if the slide is valid, {@code false} otherwise.
*/
public boolean isValid() {
return this.isIdValid() && this.isNameValid() && this.isFileValid() && areElementsValid();
}
protected boolean isIdValid() {
return this.slideId.isValid();
}
protected boolean isNameValid() {
return this.name.isValid();
}
protected boolean isFileValid() {
return this.file.isValid();
}
protected boolean areElementsValid() {
boolean valid = true;
if (!this.slideElements.isEmpty()) {
int index = 0;
while (valid && index < this.slideElements.size()) {
valid = this.slideElements.get(index++).isValid();
}
}
return valid;
}
}