/**
* Copyright [2015] [Christian Loehnert]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.ks.gallery.ui;
import de.ks.BaseController;
import de.ks.gallery.entity.GalleryFavorite;
import de.ks.gallery.ui.thumbnail.ThumbnailGallery;
import de.ks.persistence.PersistentWork;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.geometry.HPos;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.util.Callback;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
public class GalleryController extends BaseController<Object> {
private static final Logger log = LoggerFactory.getLogger(GalleryController.class);
@FXML
protected VBox favoriteContainer;
@FXML
protected StackPane thumbnailContainer;
@FXML
protected StackPane markedContainer;
@FXML
protected SplitPane root;
@FXML
protected TreeView<File> fileView;
@FXML
protected ToggleButton showHidden;
@FXML
protected Button markFavorite;
protected ThumbnailGallery thumbnailGallery;
protected MarkdedItemController markedItemController;
@Override
public void initialize(URL location, ResourceBundle resources) {
thumbnailGallery = activityInitialization.loadAdditionalController(ThumbnailGallery.class).getController();
thumbnailContainer.getChildren().add(thumbnailGallery.getRoot());
thumbnailGallery.hideLoader();
markedItemController = activityInitialization.loadAdditionalController(MarkdedItemController.class).getController();
markedContainer.getChildren().add(markedItemController.getRoot());
markedItemController.bindTo(thumbnailGallery.getSlideshow());
TreeItem<File> root = createRoot();
fileView.setRoot(root);
fileView.setShowRoot(false);
fileView.setCellFactory(new Callback<TreeView<File>, TreeCell<File>>() {
@Override
public TreeCell<File> call(TreeView<File> param) {
return new TreeCell<File>() {
@Override
protected void updateItem(File item, boolean empty) {
super.updateItem(item, empty);
if (item == null) {
setText("");
} else {
String name = item.getName();
name = name.isEmpty() ? "/" : name;
setText(name);
}
}
};
}
});
fileView.getSelectionModel().selectedItemProperty().addListener((p, o, n) -> {
if (n != null && n != o) {
thumbnailGallery.setFolder(n.getValue(), false);
}
});
}
protected TreeItem<File> createRoot() {
Iterable<Path> rootDirectories = FileSystems.getDefault().getRootDirectories();
TreeItem<File> root = new TreeItem<>(null);
for (Path rootDirectory : rootDirectories) {
TreeItem<File> subRoot = new TreeItem<>(rootDirectory.toFile());
subRoot.expandedProperty().addListener((p, o, n) -> {
if (n) {
expand(subRoot, true);
}
});
root.getChildren().add(subRoot);
expand(subRoot, false);
}
return root;
}
private void expand(TreeItem<File> parent, boolean childExpansion) {
ArrayList<TreeItem<File>> roots = new ArrayList<TreeItem<File>>();
if (childExpansion) {
roots.addAll(parent.getChildren());
} else {
roots.add(parent);
}
for (TreeItem<File> root : roots) {
File[] array = root.getValue().listFiles(pathname -> pathname.isDirectory());
List<File> files = array == null ? Collections.emptyList() : Arrays.asList(array);
files.remove(null);
Collections.sort(files);
if (files != null) {
for (File file : files) {
try {
boolean hidden = Files.isHidden(file.toPath());
boolean add = (hidden && showHidden.isSelected()) || !hidden;
if (add) {
TreeItem<File> item = new TreeItem<>(file);
item.expandedProperty().addListener((p, o, n) -> expand(item, true));
ObservableList<TreeItem<File>> children = root.getChildren();
children.add(item);
log.trace("Adding {} to {}", item.getValue().getName(), root.getValue().getName());
}
} catch (IOException e) {
log.error("Could not check file {}", file, e);
}
}
}
}
}
@Override
public void onStart() {
onResume();
}
@Override
public void onResume() {
reloadFavorites();
}
protected void reloadFavorites() {
List<GalleryFavorite> favorites = PersistentWork.from(GalleryFavorite.class);
Collections.sort(favorites, Comparator.comparing(f -> f.getName()));
controller.getJavaFXExecutor().submit(() -> {
favoriteContainer.getChildren().clear();
for (GalleryFavorite favorite : favorites) {
GridPane container = new GridPane();
container.getColumnConstraints().add(new ColumnConstraints(Control.USE_COMPUTED_SIZE, Control.USE_COMPUTED_SIZE, Control.USE_COMPUTED_SIZE, Priority.ALWAYS, HPos.LEFT, true));
container.getColumnConstraints().add(new ColumnConstraints(Control.USE_COMPUTED_SIZE, Control.USE_COMPUTED_SIZE, Control.USE_COMPUTED_SIZE, Priority.NEVER, HPos.LEFT, true));
Hyperlink link = new Hyperlink(favorite.getName());
link.setOnAction(e -> {
selectPath(favorite.getFolderPath());
});
container.add(link, 0, 0);
Button delete = new Button("(x)");
delete.setOnAction(e -> {
PersistentWork.run(em -> {
GalleryFavorite reloaded = PersistentWork.reload(favorite);
em.remove(reloaded);
});
reloadFavorites();
});
container.add(delete, 1, 0);
favoriteContainer.getChildren().add(container);
}
});
}
protected void selectPath(File folderPath) {
collapseAll();
Path path = folderPath.toPath();
Optional<TreeItem<File>> first = Optional.empty();
for (TreeItem<File> root : fileView.getRoot().getChildren()) {
for (Path path1 : path) {
first = root.getChildren().stream().filter(c -> {
String pathName = path1.getFileName().toString();
String name = c.getValue().getName();
return name.equals(pathName);
}).findFirst();
if (first.isPresent()) {
root.setExpanded(true);
TreeItem<File> fileTreeItem = first.get();
fileTreeItem.setExpanded(true);
root = first.get();
}
}
}
if (first.isPresent()) {
fileView.getSelectionModel().select(first.get());
int index = fileView.getSelectionModel().getSelectedIndex();
fileView.getFocusModel().focus(index);
fileView.scrollTo(index);
}
}
@FXML
void onMarkFavorite() {
TreeItem<File> selectedItem = fileView.getSelectionModel().getSelectedItem();
if (selectedItem != null) {
PersistentWork.persist(new GalleryFavorite(selectedItem.getValue()));
reloadFavorites();
}
}
@FXML
void onShowHidden() {
TreeItem<File> selectedItem = fileView.getSelectionModel().getSelectedItem();
TreeItem<File> root = createRoot();
fileView.setRoot(root);
if (selectedItem != null) {
selectPath(selectedItem.getValue());
}
}
private void collapseAll() {
TreeItem<File> root = fileView.getRoot();
collapse(root);
}
private void collapse(TreeItem<File> root) {
root.setExpanded(false);
root.getChildren().forEach(c -> collapse(c));
}
}