numass-framework/numass-viewer/src/main/java/inr/numass/viewer/MainViewerController.java

307 lines
10 KiB
Java
Raw Normal View History

2015-12-18 16:20:47 +03:00
/*
* Copyright 2015 Alexander Nozik.
*
* 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 inr.numass.viewer;
import de.jensd.shichimifx.utils.ConsoleDude;
import de.jensd.shichimifx.utils.SplitPaneDividerSlider;
import hep.dataforge.exceptions.StorageException;
import inr.numass.data.NumassData;
import inr.numass.storage.NumassStorage;
import java.io.File;
import java.net.URL;
import java.util.Optional;
import java.util.ResourceBundle;
2015-12-27 18:04:05 +03:00
import java.util.concurrent.ExecutionException;
2015-12-18 16:20:47 +03:00
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.application.Platform;
2015-12-27 18:04:05 +03:00
import javafx.beans.value.ChangeListener;
2015-12-18 16:20:47 +03:00
import javafx.beans.value.ObservableValue;
2015-12-27 18:04:05 +03:00
import javafx.concurrent.Task;
2015-12-18 16:20:47 +03:00
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonBar.ButtonData;
import javafx.scene.control.ButtonType;
import javafx.scene.control.Dialog;
import javafx.scene.control.Label;
import javafx.scene.control.SplitPane;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.control.ToggleButton;
import javafx.scene.control.TreeTableView;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.GridPane;
import javafx.stage.DirectoryChooser;
2015-12-27 18:04:05 +03:00
import javafx.util.Duration;
2015-12-18 16:20:47 +03:00
import javafx.util.Pair;
import org.controlsfx.control.StatusBar;
/**
* FXML Controller class
*
* @author Alexander Nozik
*/
2015-12-27 18:04:05 +03:00
public class MainViewerController implements Initializable, FXTaskManager {
2015-12-18 16:20:47 +03:00
public static MainViewerController build(NumassStorage root) {
MainViewerController res = new MainViewerController();
res.setRootStorage(root);
return res;
}
@FXML
private TextArea consoleArea;
@FXML
private ToggleButton consoleButton;
@FXML
private SplitPane consoleSplit;
@FXML
private Button loadDirectoryButton;
//controllers
2015-12-22 14:19:17 +03:00
@FXML
2015-12-18 16:20:47 +03:00
private MspViewController mspController;
//main pane views
@FXML
private AnchorPane numassLoaderViewContainer;
@FXML
private TreeTableView<NumassLoaderTreeBuilder.TreeItemValue> numassLoaderDataTree;
@FXML
private StatusBar statusBar;
//tabs
@FXML
private TabPane tabPane;
@FXML
private Tab mainTab;
@FXML
private Tab mspTab;
@FXML
private Tab pressuresTab;
@FXML
private Tab temperaturesTab;
@FXML
private Button loadRemoteButton;
@FXML
private Label storagePathLabel;
/**
* Initializes the controller class.
*
* @param url
* @param rb
*/
@Override
public void initialize(URL url, ResourceBundle rb) {
2015-12-21 16:40:21 +03:00
// TabPaneDetacher.create().makeTabsDetachable(tabPane);
2015-12-18 16:20:47 +03:00
ConsoleDude.hookStdStreams(consoleArea);
2015-12-27 18:04:05 +03:00
SplitPaneDividerSlider slider = new SplitPaneDividerSlider(consoleSplit, 0,
SplitPaneDividerSlider.Direction.DOWN, Duration.seconds(1));
2015-12-18 16:20:47 +03:00
2015-12-27 18:04:05 +03:00
slider.aimContentVisibleProperty().bindBidirectional(consoleButton.selectedProperty());
consoleButton.setSelected(false);
2015-12-22 14:19:17 +03:00
loadRemoteButton.setDisable(true);
2015-12-27 18:04:05 +03:00
mspController.setCallback(this);
2015-12-18 16:20:47 +03:00
}
@FXML
private void onLoadDirectory(ActionEvent event) {
DirectoryChooser chooser = new DirectoryChooser();
chooser.setTitle("Select numass storage root");
chooser.setInitialDirectory(new File(".").getAbsoluteFile());
final File rootDir = chooser.showDialog(((Node) event.getTarget()).getScene().getWindow());
if (rootDir != null) {
2015-12-27 18:04:05 +03:00
Task dirLoadTask = new DirectoryLoadTask(rootDir.toURI().toString());
postTask(dirLoadTask);
Viewer.runTask(dirLoadTask);
2015-12-18 16:20:47 +03:00
}
}
2015-12-27 18:04:05 +03:00
private class DirectoryLoadTask extends Task<Void> {
private final String uri;
public DirectoryLoadTask(String uri) {
this.uri = uri;
}
@Override
protected Void call() throws Exception {
updateTitle("Load storage ("+uri+")");
updateProgress(-1, 1);
updateMessage("Building numass storage tree...");
try {
NumassStorage root = NumassStorage.buildNumassRoot(uri, true, false);
setRootStorage(root);
Platform.runLater(() -> storagePathLabel.setText("Storage: " + uri));
} catch (StorageException ex) {
updateProgress(0, 1);
updateMessage("Failed to load storage " + uri);
Logger.getLogger(MainViewerController.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
2015-12-18 16:20:47 +03:00
}
@Override
2015-12-27 18:04:05 +03:00
@SuppressWarnings("unchecked")
public void postTask(Task task) {
task.setOnRunning((e) -> {
statusBar.setText(task.getTitle() + ": " + task.getMessage());
statusBar.setProgress(task.getProgress());
});
task.messageProperty().addListener((ObservableValue<? extends String> observable, String oldValue, String newValue) -> {
statusBar.setText(task.getTitle() + ": " +newValue);
});
task.progressProperty().addListener((ObservableValue<? extends Number> observable, Number oldValue, Number newValue) -> {
statusBar.setProgress(newValue.doubleValue());
});
task.setOnSucceeded((e) -> {
statusBar.setText(task.getTitle() + ": Complete");
statusBar.setProgress(0);
});
task.setOnFailed((e) -> {
statusBar.setText(task.getTitle() + ": Failed");
statusBar.setProgress(0);
});
2015-12-18 16:20:47 +03:00
}
public void setRootStorage(NumassStorage root) {
2015-12-27 18:04:05 +03:00
Task fillTask = new StorageDataFillTask(root);
postTask(fillTask);
Viewer.runTask(fillTask);
2015-12-18 16:20:47 +03:00
if (mspController != null) {
2015-12-22 14:19:17 +03:00
mspController.setCallback(this);
2015-12-18 16:20:47 +03:00
mspController.fillMspData(root);
} else {
mspTab.getContent().setVisible(false);
}
pressuresTab.getContent().setVisible(false);
temperaturesTab.getContent().setVisible(false);
}
2015-12-27 18:04:05 +03:00
private class StorageDataFillTask extends Task<Void> {
2015-12-18 16:20:47 +03:00
2015-12-27 18:04:05 +03:00
private final NumassStorage root;
public StorageDataFillTask(NumassStorage root) {
this.root = root;
}
@Override
protected Void call() throws Exception {
updateTitle("Fill data to UI ("+root.getName()+")");
this.updateProgress(-1, 1);
this.updateMessage("Loading numass storage tree...");
Task treeBuilderTask = new NumassLoaderTreeBuilder(numassLoaderDataTree, root, (NumassData loader) -> {
NumassLoaderViewComponent component = new NumassLoaderViewComponent();
component.loadData(loader);
component.setCallback(MainViewerController.this);
numassLoaderViewContainer.getChildren().clear();
numassLoaderViewContainer.getChildren().add(component);
AnchorPane.setTopAnchor(component, 0.0);
AnchorPane.setRightAnchor(component, 0.0);
AnchorPane.setLeftAnchor(component, 0.0);
AnchorPane.setBottomAnchor(component, 0.0);
numassLoaderViewContainer.requestLayout();
});
postTask(treeBuilderTask);
Viewer.runTask(treeBuilderTask);
2015-12-18 16:20:47 +03:00
try {
2015-12-27 18:04:05 +03:00
treeBuilderTask.get();
this.updateProgress(0, 1);
this.updateMessage("Numass storage tree loaded.");
this.succeeded();
} catch (InterruptedException | ExecutionException ex) {
this.failed();
2015-12-18 16:20:47 +03:00
throw new RuntimeException(ex);
}
2015-12-27 18:04:05 +03:00
return null;
2015-12-18 16:20:47 +03:00
}
2015-12-27 18:04:05 +03:00
2015-12-18 16:20:47 +03:00
}
@FXML
private void onLoadRemote(ActionEvent event) {
// Create the custom dialog.
Dialog<Pair<String, String>> dialog = new Dialog<>();
dialog.setTitle("Remote storage selection");
dialog.setHeaderText("Select remote storage login options and run");
ButtonType loginButtonType = new ButtonType("Load", ButtonData.OK_DONE);
dialog.getDialogPane().getButtonTypes().addAll(loginButtonType, ButtonType.CANCEL);
// Create the username and password labels and fields.
GridPane grid = new GridPane();
grid.setHgap(10);
grid.setVgap(10);
grid.setPadding(new Insets(20, 150, 10, 10));
TextField storageText = new TextField();
storageText.setPrefWidth(350);
storageText.setText("sftp://trdat:Anomaly@192.168.111.1");
TextField runText = new TextField();
runText.setPromptText("Run name");
grid.add(new Label("Storage path:"), 0, 0);
grid.add(storageText, 1, 0);
grid.add(new Label("Run name:"), 0, 1);
grid.add(runText, 1, 1);
dialog.getDialogPane().setContent(grid);
// Request focus on the username field by default.
2015-12-27 18:04:05 +03:00
storageText.requestFocus();
2015-12-18 16:20:47 +03:00
// Convert the result to a username-password-pair when the login button is clicked.
dialog.setResultConverter(dialogButton -> {
if (dialogButton == loginButtonType) {
return new Pair<>(storageText.getText(), runText.getText());
}
return null;
});
Optional<Pair<String, String>> result = dialog.showAndWait();
if (result.isPresent()) {
2015-12-27 18:04:05 +03:00
Task dirLoadTask = new DirectoryLoadTask(result.get().getKey() + "/data/" + result.get().getValue());
postTask(dirLoadTask);
Viewer.runTask(dirLoadTask);
2015-12-18 16:20:47 +03:00
}
}
}