it.unibo.alchemist.boundary.projectview.controller.LeftLayoutController Maven / Gradle / Ivy
/*
* Copyright (C) 2010-2019, Danilo Pianini and contributors listed in the main project's alchemist/build.gradle file.
*
* This file is part of Alchemist, and is distributed under the terms of the
* GNU General Public License, with a linking exception,
* as described in the file LICENSE in the Alchemist distribution's top directory.
*/
package it.unibo.alchemist.boundary.projectview.controller;
import java.awt.Desktop;
import java.awt.Desktop.Action;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.io.File;
import java.io.IOException;
import java.util.ResourceBundle;
import org.jooq.lambda.Unchecked;
import org.kaikikm.threadresloader.ResourceLoader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import it.unibo.alchemist.boundary.l10n.LocalizedResourceBundle;
import it.unibo.alchemist.boundary.projectview.ProjectGUI;
import it.unibo.alchemist.boundary.projectview.model.Project;
import it.unibo.alchemist.boundary.projectview.utils.URLManager;
import it.unibo.alchemist.boundary.projectview.utils.ProjectIOUtils;
import it.unibo.alchemist.boundary.projectview.utils.SVGImageUtils;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.Button;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.StackPane;
import javafx.stage.Modality;
import javafx.stage.Stage;
/**
*
*
*/
public class LeftLayoutController {
private static final Logger L = LoggerFactory.getLogger(ProjectGUI.class);
private static final ResourceBundle RESOURCES = LocalizedResourceBundle.get("it.unibo.alchemist.l10n.ProjectViewUIStrings");
private static final double RUN_WIDTH = 1.875;
private static final double RUN_HEIGHT = 3.33;
private static final double TREE_ICON_WIDTH = 1.3021;
private static final double TREE_ICON_HEIGHT = 2.3148;
@FXML
private Button run;
@FXML
private StackPane pane;
@FXML
private TreeView treeView; // NOPMD: Casadio - JavaFX requires the variable is not local
private Image folder;
private Image file;
private ProjectGUI main;
private String pathFolder;
private String selectedFile;
private CenterLayoutController ctrlCenter;
/**
*
*/
public void initialize() {
SVGImageUtils.installSvgLoader();
this.run.setGraphic(new ImageView(SVGImageUtils.getSvgImage("icon/run.svg", RUN_WIDTH, RUN_HEIGHT)));
this.run.setText(RESOURCES.getString("run"));
this.run.setDisable(true);
this.folder = SVGImageUtils.getSvgImage("icon/folder.svg", TREE_ICON_WIDTH, TREE_ICON_HEIGHT);
this.file = SVGImageUtils.getSvgImage("icon/file.svg", TREE_ICON_WIDTH, TREE_ICON_HEIGHT);
}
/**
*
* @param main Main class.
*/
public void setMain(final ProjectGUI main) {
this.main = main;
}
/**
*
* @return path of project folder
*/
public String getPathFolder() {
return this.pathFolder;
}
/**
*
* @return path of selected file
*/
public String getSelectedFilePath() {
return this.selectedFile;
}
/**
*
* @param ctrlCenter A controller of CenterLayout
*/
public void setCtrlCenter(final CenterLayoutController ctrlCenter) {
this.ctrlCenter = ctrlCenter;
}
/**
*
* @param dir Selected directory
*/
public void setTreeView(final File dir) {
this.pathFolder = dir.getAbsolutePath();
final TreeItem root = new TreeItem<>(dir.getName(), new ImageView(SVGImageUtils.getSvgImage("icon/project.svg", TREE_ICON_WIDTH, TREE_ICON_HEIGHT)));
root.setExpanded(true);
this.treeView = new TreeView<>(root);
displayProjectContent(dir, root);
this.pane.getChildren().add(this.treeView);
this.treeView.getSelectionModel().selectedItemProperty().addListener(new ChangeListener>() {
@Override
public void changed(final ObservableValue extends TreeItem> observable,
final TreeItem oldVal,
final TreeItem newVal) {
final TreeItem selectedItem = (TreeItem) newVal;
TreeItem parent = selectedItem.getParent();
final StringBuilder path = new StringBuilder(File.separator + selectedItem.getValue());
while (parent != null) {
if (parent.getParent() != null) {
path.insert(0, File.separator + parent.getValue());
}
parent = parent.getParent();
}
selectedFile = pathFolder + path;
}
});
this.treeView.setOnMouseClicked(mouseEv -> {
final File target = new File(selectedFile);
if (mouseEv.getClickCount() == 2 && target.exists() && target.isFile()) {
final Desktop desk = Desktop.getDesktop();
if (desk.isSupported(Action.OPEN)) {
new Thread(() -> {
try {
desk.open(target);
} catch (IOException e) {
L.error("Error opening file.", e);
}
}).start();
}
}
});
final ContextMenu menu = new ContextMenu();
final MenuItem newFolder = new MenuItem(RESOURCES.getString("new_folder"));
newFolder.setOnAction(e -> loadLayout(true));
final MenuItem newFile = new MenuItem(RESOURCES.getString("new_file"));
newFile.setOnAction(e -> loadLayout(false));
menu.getItems().addAll(newFolder, newFile);
this.treeView.setContextMenu(menu);
}
/**
*
*/
@FXML
public void clickRun() {
if (this.ctrlCenter.getProject() != null) {
this.ctrlCenter.checkChanges();
}
final Project project = ProjectIOUtils.loadFrom(this.pathFolder);
if (project != null) {
final Thread thread = new Thread(Unchecked.runnable(() -> {
ResourceLoader.setDefault();
project.runAlchemistSimulation(false);
}), "SingleRunGUI");
URLManager.getInstance().setupThreadClassLoader(thread);
thread.setDaemon(true);
thread.start();
} else {
final Alert alert = new Alert(AlertType.ERROR);
alert.setTitle(RESOURCES.getString("error_running"));
alert.setHeaderText(RESOURCES.getString("error_running_header"));
alert.setContentText(RESOURCES.getString("error_running_content"));
alert.showAndWait();
}
}
/**
*
*/
public void setEnableRun() {
this.run.setDisable(false);
}
private void displayProjectContent(final File dir, final TreeItem root) {
final File[] files = dir.listFiles();
if (files != null) {
for (final File file: files) {
if (!file.getName().equals(".alchemist_project_descriptor.json")) {
final TreeItem singleFile;
if (file.isDirectory()) {
singleFile = new TreeItem<>(file.getName(), new ImageView(this.folder));
displayProjectContent(file, singleFile);
root.getChildren().add(singleFile);
} else {
singleFile = new TreeItem<>(file.getName(), new ImageView(this.file));
root.getChildren().add(singleFile);
}
root.setExpanded(true);
}
}
}
}
private void loadLayout(final boolean isFolder) {
final FXMLLoader loader = new FXMLLoader();
loader.setLocation(ResourceLoader.getResource(ProjectGUI.RESOURCE_LOCATION + "/view/NewFolderOrFileDialog.fxml"));
AnchorPane pane;
try {
pane = (AnchorPane) loader.load();
} catch (IOException e) {
throw new IllegalStateException(e);
}
final Stage stage = new Stage();
if (isFolder) {
stage.setTitle(RESOURCES.getString("folder_name_title"));
} else {
stage.setTitle(RESOURCES.getString("file_name_title"));
}
stage.initModality(Modality.WINDOW_MODAL);
stage.initOwner(this.main.getStage());
stage.setResizable(false);
final Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
final double width = screenSize.getWidth() * 20.83 / 100;
final double height = screenSize.getHeight() * 13.89 / 100;
final Scene scene = new Scene(pane, width, height);
stage.setScene(scene);
final NewFolderOrFileDialogController controller = loader.getController();
controller.initialize(isFolder);
controller.setSelectedItem(this.selectedFile);
controller.setStage(stage);
stage.showAndWait();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy