/*********************************************************************************** * * Copyright (c) 2014 Kamil Baczkowicz * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * and Eclipse Distribution License v1.0 which accompany this distribution. * * The Eclipse Public License is available at * http://www.eclipse.org/legal/epl-v10.html * * The Eclipse Distribution License is available at * http://www.eclipse.org/org/documents/edl-v10.php. * * Contributors: * * Kamil Baczkowicz - initial API and implementation and/or initial documentation * */ package pl.baczkowicz.mqttspy.ui; import java.io.File; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.event.EventHandler; import javafx.fxml.FXML; import javafx.scene.Scene; import javafx.scene.control.CheckMenuItem; import javafx.scene.control.MenuItem; import javafx.scene.control.RadioMenuItem; import javafx.scene.control.Tab; import javafx.scene.control.TabPane; import javafx.scene.layout.AnchorPane; import javafx.stage.FileChooser; import javafx.stage.FileChooser.ExtensionFilter; import javafx.stage.Stage; import javafx.stage.Window; import javafx.stage.WindowEvent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import pl.baczkowicz.mqttspy.common.generated.PublicationDetails; import pl.baczkowicz.mqttspy.configuration.ConfigurationManager; import pl.baczkowicz.mqttspy.configuration.generated.TabbedSubscriptionDetails; import pl.baczkowicz.mqttspy.configuration.generated.UserInterfaceMqttConnectionDetails; import pl.baczkowicz.mqttspy.stats.ConnectionStatsUpdater; import pl.baczkowicz.mqttspy.stats.StatisticsManager; import pl.baczkowicz.mqttspy.ui.connections.ConnectionManager; import pl.baczkowicz.mqttspy.ui.events.LoadConfigurationFileEvent; import pl.baczkowicz.mqttspy.ui.events.NewPerspectiveSelectedEvent; import pl.baczkowicz.mqttspy.ui.events.ShowAboutWindowEvent; import pl.baczkowicz.mqttspy.ui.events.ShowEditConnectionsWindowEvent; import pl.baczkowicz.mqttspy.ui.events.ShowExternalWebPageEvent; import pl.baczkowicz.mqttspy.ui.events.ShowFormattersWindowEvent; import pl.baczkowicz.mqttspy.ui.events.ShowMessageLogEvent; import pl.baczkowicz.mqttspy.ui.events.ShowNewSubscriptionWindowEvent; import pl.baczkowicz.mqttspy.ui.events.ShowTestCasesWindowEvent; import pl.baczkowicz.mqttspy.ui.utils.DialogUtils; import pl.baczkowicz.mqttspy.versions.VersionManager; import pl.baczkowicz.spy.eventbus.IKBus; import pl.baczkowicz.spy.exceptions.SpyUncaughtExceptionHandler; import pl.baczkowicz.spy.exceptions.XMLException; import pl.baczkowicz.spy.ui.panes.PaneVisibilityStatus; import pl.baczkowicz.spy.ui.panes.SpyPerspective; /** * Controller for the main window. */ public class MainController { private final static Logger logger = LoggerFactory.getLogger(MainController.class); /** * The name of this field needs to be set to the name of the pane + * Controller (i.e. <fx:id>Controller). */ @FXML private ControlPanelController controlPanelPaneController; @FXML private AnchorPane mainPane; @FXML private TabPane connectionTabs; @FXML private MenuItem openConfigFileMenu; @FXML private MenuItem newConnectionMenu; @FXML private MenuItem newSubscriptionMenu; @FXML private MenuItem editConnectionsMenu; @FXML private RadioMenuItem defaultPerspective; @FXML private RadioMenuItem basicPerspective; @FXML private RadioMenuItem detailedPerspective; @FXML private RadioMenuItem spyPerspective; @FXML private RadioMenuItem superSpyPerspective; @FXML private CheckMenuItem resizeMessagePaneMenu; private ConfigurationManager configurationManager; private Stage stage; private Scene scene; private IKBus eventBus; private StatisticsManager statisticsManager; private ConnectionManager connectionManager; // private SpyPerspective selectedPerspective = SpyPerspective.DEFAULT; private double lastWidth; private double lastHeight; private VersionManager versionManager; private ViewManager viewManager; public MainController() throws XMLException { Thread.setDefaultUncaughtExceptionHandler(new SpyUncaughtExceptionHandler()); } public void init() { statisticsManager.loadStats(); // Set up scene scene = getParentWindow().getScene(); // Set up window events getParentWindow().setOnCloseRequest(new EventHandler<WindowEvent>() { public void handle(WindowEvent t) { exit(); } }); scene.widthProperty().addListener(new ChangeListener<Number>() { @Override public void changed(ObservableValue<? extends Number> observableValue, Number oldSceneWidth, Number newSceneWidth) { if (!getStage().isMaximized()) { setLastWidth((double) newSceneWidth); } } }); scene.heightProperty().addListener(new ChangeListener<Number>() { @Override public void changed(ObservableValue<? extends Number> observableValue, Number oldSceneHeight, Number newSceneHeight) { if (!getStage().isMaximized()) { setLastHeight((double) newSceneHeight); } } }); // Clear any test tabs stage.setTitle("mqtt-spy"); controlPanelPaneController.setMainController(this); controlPanelPaneController.setConfigurationMananger(configurationManager); controlPanelPaneController.setEventBus(eventBus); controlPanelPaneController.setConnectionManager(connectionManager); controlPanelPaneController.setVersionManager(versionManager); controlPanelPaneController.init(); new Thread(new ConnectionStatsUpdater(connectionManager)).start(); } @FXML public void createNewConnection() { logger.trace("Creating new connection..."); eventBus.publish(new ShowEditConnectionsWindowEvent(getParentWindow(), true, null)); } @FXML public void editConnections() { eventBus.publish(new ShowEditConnectionsWindowEvent(getParentWindow(), false, null)); } @FXML public void newSubscription() { final Tab selectedTab = this.getConnectionTabs().getSelectionModel().getSelectedItem(); final ConnectionController controller = connectionManager.getControllerForTab(selectedTab); if (controller != null) { eventBus.publish(new ShowNewSubscriptionWindowEvent( controller, PaneVisibilityStatus.DETACHED, controller.getNewSubscriptionPaneStatus().getVisibility())); } } @FXML private void showFormatters() { eventBus.publish(new ShowFormattersWindowEvent(getParentWindow(), false)); } @FXML public void showTestCases() { eventBus.publish(new ShowTestCasesWindowEvent(getParentWindow())); } @FXML public void openMessageLog() { eventBus.publish(new ShowMessageLogEvent(getParentWindow())); } @FXML public void exit() { // This is triggered by the user connectionManager.disconnectAll(); statisticsManager.saveStats(); configurationManager.saveUiProperties( getLastWidth(), getLastHeight(), stage.isMaximized(), viewManager.getPerspective(), resizeMessagePaneMenu.isSelected()); System.exit(0); } /** * Sets the perspective. * * @param selectedPerspective the selectedPerspective to set */ public void updateSelectedPerspective(final SpyPerspective selectedPerspective) { switch (selectedPerspective) { case BASIC: basicPerspective.setSelected(true); break; case DETAILED: detailedPerspective.setSelected(true); break; case SPY: spyPerspective.setSelected(true); break; case SUPER_SPY: superSpyPerspective.setSelected(true); break; default: defaultPerspective.setSelected(true); break; } eventBus.publish(new NewPerspectiveSelectedEvent(selectedPerspective)); } public TabPane getConnectionTabs() { return connectionTabs; } public void addConnectionTab(Tab tab) { connectionTabs.getTabs().add(tab); } private Window getParentWindow() { return mainPane.getScene().getWindow(); } @FXML public void openConfigurationFile() { final FileChooser fileChooser = new FileChooser(); fileChooser.setTitle("Select configuration file to open"); String extensions = "xml"; fileChooser.setSelectedExtensionFilter(new ExtensionFilter("XML file", extensions)); final File selectedFile = fileChooser.showOpenDialog(getParentWindow()); if (selectedFile != null) { eventBus.publish(new LoadConfigurationFileEvent(selectedFile)); // loadConfigurationFileOnRunLater(selectedFile); } } public void populateConnectionPanes(final UserInterfaceMqttConnectionDetails connectionDetails, final ConnectionController connectionController) { for (final PublicationDetails publicationDetails : connectionDetails.getPublication()) { // Add it to the list of pre-defined topics connectionController.getNewPublicationPaneController().recordPublicationTopic(publicationDetails.getTopic()); } for (final TabbedSubscriptionDetails subscriptionDetails : connectionDetails.getSubscription()) { // Check if we should create a tab for the subscription if (subscriptionDetails.isCreateTab()) { connectionController.getNewSubscriptionPaneController().subscribe(subscriptionDetails, connectionDetails.isAutoSubscribe()); } // Add it to the list of pre-defined topics connectionController.getNewSubscriptionPaneController().recordSubscriptionTopic(subscriptionDetails.getTopic()); } } @FXML private void showPerspective() { final SpyPerspective selectedPerspective; if (spyPerspective.isSelected()) { selectedPerspective = SpyPerspective.SPY; } else if (superSpyPerspective.isSelected()) { selectedPerspective = SpyPerspective.SUPER_SPY; } else if (detailedPerspective.isSelected()) { selectedPerspective = SpyPerspective.DETAILED; } else if (basicPerspective.isSelected()) { selectedPerspective = SpyPerspective.BASIC; } else { selectedPerspective = SpyPerspective.DEFAULT; } eventBus.publish(new NewPerspectiveSelectedEvent(selectedPerspective)); } @FXML private void resizeMessagePane() { // Connection tabs for (final ConnectionController controller : connectionManager.getConnectionControllers()) { controller.getResizeMessageContentMenu().setSelected(resizeMessagePaneMenu.isSelected()); } // Offline (message log) tabs for (final ConnectionController controller : connectionManager.getOfflineConnectionControllers()) { controller.getResizeMessageContentMenu().setSelected(resizeMessagePaneMenu.isSelected()); } } @FXML private void restoreConfiguration() { if (DialogUtils.showDefaultConfigurationFileMissingChoice("Restore defaults", mainPane.getScene().getWindow())) { eventBus.publish(new LoadConfigurationFileEvent(ConfigurationManager.getDefaultConfigurationFile())); // loadConfigurationFileOnRunLater(ConfigurationManager.getDefaultConfigurationFile()); } } @FXML private void showAbout() { eventBus.publish(new ShowAboutWindowEvent(getParentWindow())); } @FXML private void openGettingInvolved() { eventBus.publish(new ShowExternalWebPageEvent("https://github.com/kamilfb/mqtt-spy/wiki/Getting-involved")); } @FXML private void overviewWiki() { eventBus.publish(new ShowExternalWebPageEvent("https://github.com/kamilfb/mqtt-spy/wiki/Overview")); } @FXML private void changelogWiki() { eventBus.publish(new ShowExternalWebPageEvent("https://github.com/kamilfb/mqtt-spy/wiki/Changelog")); } @FXML private void scriptingWiki() { eventBus.publish(new ShowExternalWebPageEvent("https://github.com/kamilfb/mqtt-spy/wiki/Scripting")); } @FXML private void messageSearchWiki() { eventBus.publish(new ShowExternalWebPageEvent("https://github.com/kamilfb/mqtt-spy/wiki/MessageSearch")); } @FXML private void loggingWiki() { eventBus.publish(new ShowExternalWebPageEvent("https://github.com/kamilfb/mqtt-spy/wiki/Logging")); } // ********************* public void setStage(Stage primaryStage) { this.stage = primaryStage; } public Stage getStage() { return this.stage; } /** * Sets the configuration manager. * * @param configurationManager the configurationManager to set */ public void setConfigurationManager(ConfigurationManager configurationManager) { this.configurationManager = configurationManager; } /** * Sets the event bus. * * @param eventBus the eventBus to set */ public void setEventBus(final IKBus eventBus) { this.eventBus = eventBus; } public void setConnectionManager(final ConnectionManager connectionManager) { this.connectionManager = connectionManager; } public void setStatisticsManager(final StatisticsManager statisticsManager) { this.statisticsManager = statisticsManager; } /** * Gets last recorded width. * * @return the lastWidth */ public double getLastWidth() { return lastWidth; } /** * Sets last recorded width. * * @param lastWidth the lastWidth to set */ public void setLastWidth(double lastWidth) { this.lastWidth = lastWidth; } /** * Gets last recorder height * * @return the lastHeight */ public double getLastHeight() { return lastHeight; } /** * Sets last recorded height. * * @param lastHeight the lastHeight to set */ public void setLastHeight(double lastHeight) { this.lastHeight = lastHeight; } public CheckMenuItem getResizeMessagePaneMenu() { return resizeMessagePaneMenu; } public void setViewManager(final ViewManager viewManager) { this.viewManager = viewManager; } public void setVersionManager(final VersionManager versionManager) { this.versionManager = versionManager; } /** * @return the newConnectionMenu */ public MenuItem getNewConnectionMenu() { return newConnectionMenu; } /** * @param newConnectionMenu the newConnectionMenu to set */ public void setNewConnectionMenu(MenuItem newConnectionMenu) { this.newConnectionMenu = newConnectionMenu; } /** * @return the editConnectionsMenu */ public MenuItem getEditConnectionsMenu() { return editConnectionsMenu; } /** * @param editConnectionsMenu the editConnectionsMenu to set */ public void setEditConnectionsMenu(MenuItem editConnectionsMenu) { this.editConnectionsMenu = editConnectionsMenu; } public MenuItem getNewSubuscriptionMenu() { return newSubscriptionMenu; } }