/*
* Copyright 2014 Loic Merckel
*
* 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 io.uploader.drive.gui.controller;
import io.uploader.drive.drive.DriveUtils;
import io.uploader.drive.gui.dlg.MessageDialogs;
import io.uploader.drive.gui.util.UiUtils;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.Node;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.SelectionMode;
import javafx.scene.control.TreeCell;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeItem.TreeModificationEvent;
import javafx.scene.control.TreeView;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.util.Callback;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.api.services.drive.Drive;
import com.google.api.services.drive.model.File;
import com.google.api.services.drive.model.FileList;
public class DriveDirectoryChooserViewController implements Initializable {
private static final Logger logger = LoggerFactory
.getLogger(DriveDirectoryChooserViewController.class);
@FXML
private TreeView<File> driveTreeView;
private Drive drive = null;
private io.uploader.drive.util.Callback<File> callback = null ;
@Override
public void initialize(URL arg0, ResourceBundle arg1) {
driveTreeView.setShowRoot(false);
driveTreeView.setEditable(false);
driveTreeView.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);
driveTreeView
.setCellFactory(new Callback<TreeView<File>, TreeCell<File>>() {
@Override
public TreeCell<File> call(TreeView<File> p) {
return new TreeCell<File>() {
@Override
protected void updateItem(File file, boolean empty) {
super.updateItem(file, empty);
if (empty) {
setText(null);
setGraphic(null);
} else {
Node graphic = new ImageView(new Image(getClass().getResourceAsStream("/icons/folder.png")));
setText(getItem() == null ? "" : getItem().getTitle());
setGraphic(graphic);
setContentDisplay(ContentDisplay.LEFT);
}
}
};
}
});
}
@FXML
protected void onCancel(ActionEvent event) {
UiUtils.closeDialog (event) ;
}
@FXML
protected void onSelect(ActionEvent event) {
checkController() ;
TreeItem<File> selected = driveTreeView.getSelectionModel().getSelectedItem() ;
if (selected == null) {
MessageDialogs.showMessageDialog(UiUtils.getStage(event), "A directory must be selected", "Error", MessageDialogs.MessageType.ERROR);
return ;
} else {
callback.onSuccess(selected.getValue());
UiUtils.closeDialog(event);
}
}
private void checkController() {
if (drive == null) {
throw new IllegalStateException(
"The Drive must be set before using the controller");
}
if (callback == null) {
throw new IllegalStateException(
"The callback must be set before using the controller");
}
}
public void loadTreeNode(File node) {
checkController();
if (node == null) {
TreeItem<File> root = createNode (null);
try {
FileList dirs = DriveUtils.findDirectories(drive, null, null);
for (File dir : dirs.getItems()) {
root.getChildren().add(createNode(dir));
}
driveTreeView.setRoot(root);
} catch (IOException e) {
logger.error("Error occurred while loading the tree view", e);
}
}
}
private TreeItem<File> createNode (File dir) {
TreeItem<File> treeItem = null ;
if (dir == null) {
treeItem = new TreeItem<File>();
treeItem.setExpanded(true);
} else {
treeItem = new TreeItem<File>(dir) {
private Boolean isLeaf = null ;
@Override
public boolean isLeaf() {
if (isLeaf != null) {
return isLeaf.booleanValue() ;
}
try {
FileList children = DriveUtils.findDirectories (drive, DriveUtils.newId(dir.getId()), Integer.valueOf(1)) ;
isLeaf = Boolean.valueOf(children.getItems() == null || children.getItems().isEmpty()) ;
return isLeaf.booleanValue() ;
} catch (IOException e) {
logger.error("Error occurred while getting children list", e);
}
return true;
}} ;
treeItem.setExpanded(false);
}
treeItem.addEventHandler(TreeItem.branchExpandedEvent (), new EventHandler<TreeModificationEvent<File>>() {
@Override
public void handle(TreeModificationEvent<File> arg0) {
if (TreeItem.branchExpandedEvent ().equals(arg0.getEventType())) {
logger.info("Branch expanded");
TreeItem<File> node = arg0.getTreeItem() ;
File nodeFile = node.getValue() ;
if (node.getChildren().isEmpty()) {
try {
FileList children = DriveUtils.findDirectories (drive, DriveUtils.newId(nodeFile.getId()), null) ;
if (children != null && children.getItems() != null) {
for (File child : children.getItems()) {
node.getChildren().add(createNode(child));
}
}
} catch (IOException e) {
logger.error("Error occurred while expanding the tree", e);
}
}
}
}
});
return treeItem ;
}
public void setDrive(Drive drive) {
this.drive = drive;
}
public void setCallback (io.uploader.drive.util.Callback<File> callback) {
this.callback = callback ;
}
}