package com.twasyl.slideshowfx.controls.tree;
import com.twasyl.slideshowfx.utils.DialogHelper;
import de.jensd.fx.glyphs.fontawesome.FontAwesomeIcon;
import de.jensd.fx.glyphs.fontawesome.FontAwesomeIconView;
import javafx.scene.Node;
import javafx.scene.control.*;
import javafx.scene.layout.HBox;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* This class is used to create TreeCell for a TreeView containing files.
* It defines a actions possible when the {@link ContextMenu} is triggered for this cell.
* It also set the drag events defined in the parent {@link TemplateTreeView} to this
* cell.
*
* @author Thierry Wasylczenko
* @version 1.2
* @since SlideshowFX 1.0
*/
public class FileTreeCell extends TreeCell<File> {
private static final Logger LOGGER = Logger.getLogger(FileTreeCell.class.getName());
public FileTreeCell() {
super();
}
@Override
protected void updateItem(File item, boolean empty) {
super.updateItem(item, empty);
initializeDragEvents(item);
initializeGraphic();
defineCellText();
defineContextMenu();
}
/**
* Initialize drag events to the current {@link FileTreeCell}. Drag events are only defined if the given item is a
* a {@link File#isDirectory() directory}. If the item is not a directory, then this method ensures that all
* drag events are removed from this cell.
*
* @param item The file for which drag events will be eventually set.
*/
protected void initializeDragEvents(final File item) {
if (item != null && item.isDirectory()) {
setOnDragOver(((TemplateTreeView) getTreeView()).getOnDragOverItem());
setOnDragDropped(((TemplateTreeView) getTreeView()).getOnDragDroppedItem());
setOnDragDone(((TemplateTreeView) getTreeView()).getOnDragDoneItem());
setOnDragExited(((TemplateTreeView) getTreeView()).getOnDragExitedItem());
} else {
setOnDragOver(null);
setOnDragDropped(null);
setOnDragDone(null);
setOnDragExited(null);
}
}
/**
* Defines the {@link #setGraphic(Node) graphic} of this cell according the availability of the value and the type
* of file this cell is hosting: a file or a directory.
*/
protected void initializeGraphic() {
if (this.getTreeItem() != null && this.getTreeItem().getValue() != null) {
if(this.getTreeItem().getValue().isDirectory()) {
if (this.getTreeItem().isExpanded()) {
setGraphic(new FontAwesomeIconView(FontAwesomeIcon.FOLDER_OPEN));
} else {
setGraphic(new FontAwesomeIconView(FontAwesomeIcon.FOLDER));
}
} else {
setGraphic(new FontAwesomeIconView(FontAwesomeIcon.FILE_TEXT_ALT));
}
} else {
setGraphic(null);
}
}
/**
* Define the {@link #setText(String) text} of this cell. If the {@link TreeView#getRoot() root} of the {@link TreeView}
* hosting this cell is equal to the current {@link #getTreeItem() item}, then {@code /} is defined as text,
* otherwise it is the {@link File#getName() name} of the provided file.
*/
protected void defineCellText() {
if (isEmpty()) {
setText("");
} else if (getTreeItem() == null) {
setText("null");
} else if (getTreeView().getRoot() == getTreeItem()) {
setText("/");
} else {
setText(getTreeItem().getValue().getName());
}
}
/**
* Define the {@link ContextMenu} of this cell. This method can be called each time the item of the cell changes.
*/
protected void defineContextMenu() {
if (getContextMenu() == null) {
this.setContextMenu(new ContextMenu());
}
getContextMenu().getItems().clear();
final TemplateTreeView treeView = (TemplateTreeView) getTreeView();
if (getItem() != null && getItem().isDirectory()) {
getContextMenu().getItems().add(this.createNewFileMenuItem());
getContextMenu().getItems().add(this.createNewDirectoryMenuItem());
}
if (treeView.isItemRenamingAllowed(getTreeItem())) {
getContextMenu().getItems().add(this.createRenameMenuItem());
}
if (treeView.isItemDeletionEnabled(getTreeItem())) {
getContextMenu().getItems().add(this.createDeleteMenuItem());
}
}
/**
* Creates the {@link MenuItem} that will allow to create a new file under the directory this cell is hosting.
*
* @return The {@link MenuItem} allowing to create a new file.
*/
protected MenuItem createNewFileMenuItem() {
final MenuItem newFile = new MenuItem("New file");
newFile.setOnAction(event -> {
final TemplateTreeView treeView = (TemplateTreeView) getTreeView();
treeView.promptUserAndCreateNewFile();
});
return newFile;
}
/**
* Creates the {@link MenuItem} that will allow to create a new directory under the directory this cell is hosting.
*
* @return The {@link MenuItem} allowing to create a new directory.
*/
protected MenuItem createNewDirectoryMenuItem() {
final MenuItem newFile = new MenuItem("New directory");
newFile.setOnAction(event -> {
final TemplateTreeView treeView = (TemplateTreeView) getTreeView();
treeView.promptUserAndCreateNewDirectory();
});
return newFile;
}
/**
* Creates the {@link MenuItem} that will allow to rename the file or directory this cell is hosting.
*
* @return The {@link MenuItem} allowing to rename contents.
*/
protected MenuItem createRenameMenuItem() {
final MenuItem renameItem = new MenuItem("Rename");
renameItem.setOnAction(event -> {
try {
final TextField textField = new TextField();
textField.setText(this.getTreeItem().getValue() == null ? "" : this.getTreeItem().getValue().getName());
final Label label = new Label("New name: ");
label.setLabelFor(textField);
final HBox hbox = new HBox(5);
hbox.getChildren().addAll(label, textField);
final ButtonType response = DialogHelper.showCancellableDialog("Rename", hbox);
if (response != null && response == ButtonType.OK) {
((TemplateTreeView) this.getTreeView()).renameContentOfTreeView(this.getTreeItem(), textField.getText());
}
} catch (IOException e) {
LOGGER.log(Level.SEVERE, "Can not rename item", e);
}
});
return renameItem;
}
/**
* Creates the {@link MenuItem} that will allow to delete the file or directory this cell is hosting.
*
* @return The {@link MenuItem} allowing to delete contents.
*/
protected MenuItem createDeleteMenuItem() {
final MenuItem deleteItem = new MenuItem("Delete");
deleteItem.setOnAction(event -> {
try {
final ButtonType answer = DialogHelper.showConfirmationAlert("Delete", "Are you sure you want to delete " + this.getItem().getName() + "?");
if (answer == ButtonType.YES) {
((TemplateTreeView) this.getTreeView()).deleteContentOfTreeView(this.getTreeItem());
}
} catch (IOException e) {
LOGGER.log(Level.SEVERE, "Can not delete item", e);
}
});
return deleteItem;
}
}