package de.saring.exerciseviewer.gui;
import java.io.IOException;
import de.saring.util.SystemUtils;
import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Tab;
import javafx.stage.Stage;
import de.saring.exerciseviewer.gui.panels.DiagramPanelController;
import de.saring.exerciseviewer.gui.panels.LapPanelController;
import de.saring.exerciseviewer.gui.panels.MainPanelController;
import de.saring.exerciseviewer.gui.panels.OptionalPanelController;
import de.saring.exerciseviewer.gui.panels.SamplePanelController;
import de.saring.exerciseviewer.gui.panels.TrackPanelController;
import de.saring.util.gui.javafx.FxmlLoader;
/**
* Main Controller (MVC) class of the ExerciseViewer dialog window.
*
* @author Stefan Saring
*/
public class EVController {
private static final String FXML_FILE = "/fxml/ExerciseViewer.fxml";
private final EVContext context;
private final MainPanelController mainPanelController;
private final OptionalPanelController optionalPanelController;
private final LapPanelController lapPanelController;
private final SamplePanelController samplePanelController;
private final DiagramPanelController diagramPanelController;
private final TrackPanelController trackPanelController;
private Stage stage;
@FXML
private Tab tabMain;
@FXML
private Tab tabOptional;
@FXML
private Tab tabLaps;
@FXML
private Tab tabSamples;
@FXML
private Tab tabDiagram;
@FXML
private Tab tabTrack;
/**
* Standard c'tor for dependency injection.
*
* @param context the ExerciseViewer UI context
* @param document the ExerciseViewer document / model
*/
public EVController(final EVContext context, final EVDocument document) {
this.context = context;
// manual dependency injection, Guice can't be used here (see comments in EVMain)
mainPanelController = new MainPanelController(context, document);
optionalPanelController = new OptionalPanelController(context, document);
lapPanelController = new LapPanelController(context, document);
samplePanelController = new SamplePanelController(context, document);
diagramPanelController = new DiagramPanelController(context, document);
trackPanelController = new TrackPanelController(context, document);
mainPanelController.setDiagramPanelController(diagramPanelController);
}
/**
* Initializes and displays the ExerciseViewer dialog.
*
* @param stage the Stage to show the dialog in
*/
public void show(final Stage stage) {
this.stage = stage;
// load dialog UI from FXML
Parent root;
try {
root = FxmlLoader.load(EVController.class.getResource(FXML_FILE), context.getResources()
.getResourceBundle(), this);
} catch (IOException e) {
throw new RuntimeException("Failed to load the FXML resource '" + FXML_FILE + "'!", e);
}
setupPanels();
// create scene and show dialog
final Scene scene = new Scene(root);
stage.setScene(scene);
stage.showAndWait();
// trigger a garbage collection when EV has been closed to avoid allocation of additional heap space
SystemUtils.triggerGC();
}
private void setupPanels() {
// load and setup main panel immediately, this tab must be visible on startup
tabMain.setContent(mainPanelController.loadAndSetupPanelContent());
// load all other panels asynchronously, this reduces the startup time massively
Platform.runLater(() -> {
tabOptional.setContent(optionalPanelController.loadAndSetupPanelContent());
tabLaps.setContent(lapPanelController.loadAndSetupPanelContent());
tabSamples.setContent(samplePanelController.loadAndSetupPanelContent());
tabDiagram.setContent(diagramPanelController.loadAndSetupPanelContent());
tabTrack.setContent(trackPanelController.loadAndSetupPanelContent());
// display map and exercise track not before the user wants to see it (reduces startup time)
tabTrack.setOnSelectionChanged(event -> {
if (tabTrack.isSelected()) {
trackPanelController.showMapAndTrack();
}
});
});
}
/**
* Action handler for closing the dialog.
*/
@FXML
private void onClose(final ActionEvent event) {
stage.close();
}
}