/*********************************************************************************** * * Copyright (c) 2015 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.controllers.edit; import java.net.URL; import java.util.Arrays; import java.util.List; import java.util.ResourceBundle; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.fxml.FXML; import javafx.fxml.Initializable; import javafx.scene.control.Button; import javafx.scene.control.CheckBox; import javafx.scene.control.ComboBox; import javafx.scene.control.Label; import javafx.scene.control.ListCell; import javafx.scene.control.ListView; import javafx.scene.control.TextField; import javafx.scene.input.KeyEvent; import javafx.scene.layout.AnchorPane; import javafx.util.Callback; import javafx.util.StringConverter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import pl.baczkowicz.mqttspy.common.generated.ProtocolVersionEnum; import pl.baczkowicz.mqttspy.common.generated.ReconnectionSettings; import pl.baczkowicz.mqttspy.configuration.ConfigurationUtils; import pl.baczkowicz.mqttspy.configuration.ConfiguredConnectionDetails; import pl.baczkowicz.mqttspy.configuration.generated.UserInterfaceMqttConnectionDetails; import pl.baczkowicz.mqttspy.ui.EditConnectionController; import pl.baczkowicz.mqttspy.utils.ConnectionUtils; import pl.baczkowicz.mqttspy.utils.MqttUtils; import pl.baczkowicz.spy.ui.keyboard.KeyboardUtils; import pl.baczkowicz.spy.ui.panes.SpyPerspective; /** * Controller for editing a single connection - connectivity tab. */ @SuppressWarnings({"unchecked", "rawtypes"}) public class EditConnectionConnectivityController extends AnchorPane implements Initializable, EditConnectionSubController { private final static Logger logger = LoggerFactory.getLogger(EditConnectionConnectivityController.class); // Connectivity //@FXML //private Label multiLabel; @FXML private Label keepAliveLabel; @FXML private Label timeoutLabel; @FXML private Label reconnectIntervalLabel; @FXML private Label resubscribeLabel; @FXML private ComboBox<String> connectionTypeCombo; @FXML private ComboBox<ProtocolVersionEnum> protocolCombo; @FXML private TextField brokerAddressText; @FXML private CheckBox reconnect; @FXML private TextField reconnectionInterval; @FXML private CheckBox resubscribe; @FXML private TextField clientIdText; @FXML private Button addTimestampButton; @FXML private Label lengthLabel; @FXML private TextField connectionTimeout; @FXML private TextField keepAlive; @FXML private CheckBox cleanSession; // Other fields private final ChangeListener basicOnChangeListener = new ChangeListener() { @Override public void changed(ObservableValue observable, Object oldValue, Object newValue) { onChange(); } }; /** The parent controller. */ private EditConnectionController parent; // =============================== // === Initialisation ============ // =============================== public void initialize(URL location, ResourceBundle resources) { protocolCombo.getSelectionModel().selectedIndexProperty().addListener(basicOnChangeListener); protocolCombo.setCellFactory(new Callback<ListView<ProtocolVersionEnum>, ListCell<ProtocolVersionEnum>>() { @Override public ListCell<ProtocolVersionEnum> call(ListView<ProtocolVersionEnum> l) { return new ListCell<ProtocolVersionEnum>() { @Override protected void updateItem(ProtocolVersionEnum item, boolean empty) { super.updateItem(item, empty); if (item == null || empty) { setText(null); } else { if (item.equals(ProtocolVersionEnum.MQTT_DEFAULT)) { setText("MQTT (auto-resolve)"); } else { setText(item.value()); } } } }; } }); protocolCombo.setConverter(new StringConverter<ProtocolVersionEnum>() { @Override public String toString(ProtocolVersionEnum item) { if (item == null) { return null; } else { if (item.equals(ProtocolVersionEnum.MQTT_DEFAULT)) { return "MQTT (auto-resolve)"; } return item.value(); } } @Override public ProtocolVersionEnum fromString(String id) { return null; } }); for (ProtocolVersionEnum protocolEnum : ProtocolVersionEnum.values()) { protocolCombo.getItems().add(protocolEnum); } connectionTypeCombo.getItems().add("Default"); connectionTypeCombo.getItems().add("WebSockets"); connectionTypeCombo.getSelectionModel().selectedIndexProperty().addListener(basicOnChangeListener); brokerAddressText.textProperty().addListener(new ChangeListener() { @Override public void changed(ObservableValue observable, Object oldValue, Object newValue) { parent.updateConnectionName(); onChange(); } }); clientIdText.textProperty().addListener(new ChangeListener() { @Override public void changed(ObservableValue observable, Object oldValue, Object newValue) { parent.updateConnectionName(); onChange(); } }); cleanSession.selectedProperty().addListener(basicOnChangeListener); connectionTimeout.textProperty().addListener(basicOnChangeListener); connectionTimeout.addEventFilter(KeyEvent.KEY_TYPED, KeyboardUtils.nonNumericKeyConsumer); keepAlive.textProperty().addListener(basicOnChangeListener); keepAlive.addEventFilter(KeyEvent.KEY_TYPED, KeyboardUtils.nonNumericKeyConsumer); reconnect.selectedProperty().addListener(new ChangeListener() { @Override public void changed(ObservableValue observable, Object oldValue, Object newValue) { updateReconnection(); onChange(); } }); reconnectionInterval.textProperty().addListener(basicOnChangeListener); reconnectionInterval.addEventFilter(KeyEvent.KEY_TYPED, KeyboardUtils.nonNumericKeyConsumer); resubscribe.selectedProperty().addListener(basicOnChangeListener); } public void init() { // Nothing to do here } // =============================== // === FXML ====================== // =============================== @FXML private void addTimestamp() { updateClientId(true); } public boolean updateClientId(final boolean addTimestamp) { String clientId = clientIdText.getText(); String newClientId = clientId; if (MqttUtils.limitClientId(parent.getEditedConnectionDetails().getProtocol()) && clientId.length() > MqttUtils.MAX_CLIENT_LENGTH_FOR_3_1) { newClientId = clientId.substring(0, MqttUtils.MAX_CLIENT_LENGTH_FOR_3_1); } if (addTimestamp) { newClientId = MqttUtils.generateClientIdWithTimestamp(newClientId, parent.getEditedConnectionDetails().getProtocol()); } if (!clientId.equals(newClientId)) { final int currentCurrentPosition = clientIdText.getCaretPosition(); clientIdText.setText(newClientId); clientIdText.positionCaret(currentCurrentPosition); return true; } return false; } public void updateClientIdLength() { if (MqttUtils.limitClientId(parent.getEditedConnectionDetails().getProtocol())) { lengthLabel.setText("Length = " + clientIdText.getText().length() + "/" + MqttUtils.MAX_CLIENT_LENGTH_FOR_3_1); } else { lengthLabel.setText("Length = " + clientIdText.getText().length()); } } // =============================== // === Logic ===================== // =============================== private void onChange() { parent.onChange(); } @Override public UserInterfaceMqttConnectionDetails readValues(final UserInterfaceMqttConnectionDetails connection) { final List<String> serverURIs = Arrays.asList(brokerAddressText.getText().split(ConnectionUtils.SERVER_DELIMITER)); for (final String serverURI : serverURIs) { logger.trace("Adding " + serverURI); // Trim and remove any prefixes - these are done dynamically based on SSL mode connection.getServerURI().add(serverURI.trim().replaceAll(MqttUtils.TCP_PREFIX, "").replaceAll(MqttUtils.SSL_PREFIX, "")); } if (brokerAddressText.getText().endsWith(ConnectionUtils.SERVER_DELIMITER)) { logger.trace("Adding empty"); connection.getServerURI().add(""); } connection.setClientID(clientIdText.getText()); connection.setProtocol(protocolCombo.getSelectionModel().getSelectedItem()); connection.setWebSocket(connectionTypeCombo.getSelectionModel().getSelectedIndex() == 1); connection.setCleanSession(cleanSession.isSelected()); connection.setConnectionTimeout(Integer.valueOf(connectionTimeout.getText())); connection.setKeepAliveInterval(Integer.valueOf(keepAlive.getText())); if (reconnect.isSelected()) { connection.setReconnectionSettings( new ReconnectionSettings( Integer.valueOf(reconnectionInterval.getText()) * 1000, resubscribe.isSelected())); } return connection; } public void updateReconnection() { if (reconnect.isSelected()) { reconnectionInterval.setDisable(false); if (reconnectionInterval.getText().length() == 0) { reconnectionInterval.setText(String.valueOf(ConfigurationUtils.DEFAULT_RECONNECTION_INTERVAL / 1000)); resubscribe.setSelected(true); } resubscribe.setDisable(false); } else { reconnectionInterval.setDisable(true); reconnectionInterval.setText(""); resubscribe.setDisable(true); resubscribe.setSelected(false); } } @Override public void displayConnectionDetails(final ConfiguredConnectionDetails connection) { // Connectivity protocolCombo.getSelectionModel().select(connection.getProtocol()); connectionTypeCombo.getSelectionModel().select(connection.isWebSocket() ? 1 : 0); brokerAddressText.setText(ConnectionUtils.serverURIsToString(connection.getServerURI())); clientIdText.setText(connection.getClientID()); connectionTimeout.setText(connection.getConnectionTimeout().toString()); keepAlive.setText(connection.getKeepAliveInterval().toString()); cleanSession.setSelected(connection.isCleanSession()); reconnect.setSelected(connection.getReconnectionSettings() != null); if (connection.getReconnectionSettings() != null) { reconnect.setSelected(true); reconnectionInterval.setText(String.valueOf(connection.getReconnectionSettings().getRetryInterval() / 1000)); resubscribe.setSelected(connection.getReconnectionSettings().isResubscribe()); } else { reconnect.setSelected(false); reconnectionInterval.setText(""); resubscribe.setSelected(false); } updateReconnection(); } // =============================== // === Setters and getters ======= // =============================== @Override public void setParent(final EditConnectionController controller) { this.parent = controller; } public TextField getClientIdText() { return clientIdText; } public TextField getBrokerAddressText() { return brokerAddressText; } public void setPerspective(SpyPerspective perspective) { final boolean detailed = perspective.equals(SpyPerspective.DETAILED) || perspective.equals(SpyPerspective.SUPER_SPY); connectionTimeout.setVisible(detailed); keepAlive.setVisible(detailed); reconnectionInterval.setVisible(detailed); resubscribe.setVisible(detailed); // multiLabel.setVisible(detailed); keepAliveLabel.setVisible(detailed); timeoutLabel.setVisible(detailed); reconnectIntervalLabel.setVisible(detailed); resubscribeLabel.setVisible(detailed); } }