/*********************************************************************************** * * 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; import java.net.URL; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.ResourceBundle; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.event.EventHandler; import javafx.fxml.FXML; import javafx.fxml.Initializable; import javafx.geometry.Pos; import javafx.scene.control.Button; import javafx.scene.control.TableCell; import javafx.scene.control.TableColumn; import javafx.scene.control.TableView; import javafx.scene.control.TextField; import javafx.scene.control.cell.PropertyValueFactory; import javafx.scene.input.MouseButton; import javafx.scene.input.MouseEvent; import javafx.scene.layout.AnchorPane; import javafx.util.Callback; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import pl.baczkowicz.mqttspy.common.generated.ProtocolVersionEnum; import pl.baczkowicz.mqttspy.configuration.ConfigurationManager; import pl.baczkowicz.mqttspy.configuration.ConfiguredConnectionDetails; import pl.baczkowicz.mqttspy.utils.ConnectionUtils; import pl.baczkowicz.spy.configuration.BaseConfigurationUtils; import pl.baczkowicz.spy.exceptions.ConfigurationException; import pl.baczkowicz.spy.ui.configuration.ConfiguredConnectionGroupDetails; import pl.baczkowicz.spy.ui.properties.ConnectionListItemProperties; import pl.baczkowicz.spy.ui.properties.ConnectionTreeItemProperties; import pl.baczkowicz.spy.ui.utils.ImageUtils; /** * Controller for editing a single connection. */ @SuppressWarnings({"unchecked", "rawtypes"}) public class EditConnectionGroupController extends AnchorPane implements Initializable { final static Logger logger = LoggerFactory.getLogger(EditConnectionGroupController.class); @FXML private TextField connectionGroupNameText; // Action buttons @FXML private Button connectButton; @FXML private Button saveButton; @FXML private Button undoButton; @FXML private TableView<ConnectionListItemProperties> connectionList; @FXML private TableColumn<ConnectionListItemProperties, String> nameColumn; @FXML private TableColumn<ConnectionListItemProperties, String> protocolColumn; @FXML private TableColumn<ConnectionListItemProperties, String> detailsColumn; // Other fields private MainController mainController; private ConfiguredConnectionGroupDetails editedConnectionGroupDetails; private List<ConfiguredConnectionDetails> connections; private Map<ConnectionListItemProperties, ConfiguredConnectionDetails> connectionMapping; private boolean recordModifications; private int noModificationsLock; private EditConnectionsController editConnectionsController; // =============================== // === Initialisation ============ // =============================== public void initialize(URL location, ResourceBundle resources) { nameColumn.setCellValueFactory(new PropertyValueFactory<ConnectionListItemProperties, String>("name")); protocolColumn.setCellValueFactory(new PropertyValueFactory<ConnectionListItemProperties, String>("protocol")); protocolColumn.setCellFactory(new Callback<TableColumn<ConnectionListItemProperties,String>, TableCell<ConnectionListItemProperties,String>>() { @Override public TableCell<ConnectionListItemProperties, String> call( TableColumn<ConnectionListItemProperties, String> param) { final TableCell<ConnectionListItemProperties, String> cell = new TableCell<ConnectionListItemProperties, String>() { @Override public void updateItem(final String item, boolean empty) { super.updateItem(item, empty); if (getTableRow().getItem() != null) { if (item.contains("MQTT")) { setGraphic(ImageUtils.createIcon("mqtt-icon", 18)); setText(item.replace("Default", "")); } else { setText(item); } } else { setGraphic(null); setText(null); } } }; cell.setAlignment(Pos.TOP_CENTER); return cell; } }); detailsColumn.setCellValueFactory(new PropertyValueFactory<ConnectionListItemProperties, String>("details")); detailsColumn.setCellFactory(new Callback<TableColumn<ConnectionListItemProperties,String>, TableCell<ConnectionListItemProperties,String>>() { @Override public TableCell<ConnectionListItemProperties, String> call( TableColumn<ConnectionListItemProperties, String> param) { final TableCell<ConnectionListItemProperties, String> cell = new TableCell<ConnectionListItemProperties, String>() { @Override public void updateItem(final String item, boolean empty) { super.updateItem(item, empty); if (getTableRow().getItem() != null) { final ConnectionListItemProperties row = (ConnectionListItemProperties) getTableRow().getItem(); setGraphic(ConnectionController.createSecurityIcons( row.isTlsEnabled(), row.isUserAuthenticationEnabled(), true)); setText(item); } else { setGraphic(null); setText(null); } } }; return cell; } }); connectionList.setOnMouseClicked(new EventHandler<MouseEvent>() { @Override public void handle(MouseEvent mouseEvent) { if (mouseEvent.getButton().equals(MouseButton.PRIMARY)) { if (mouseEvent.getClickCount() == 2) { final ConnectionListItemProperties selected = connectionList.getSelectionModel().getSelectedItem(); if (selected != null) { editConnectionsController.selectConnection(connectionMapping.get(selected)); } } } } }); connectionGroupNameText.textProperty().addListener(new ChangeListener() { @Override public void changed(ObservableValue observable, Object oldValue, Object newValue) { onChange(); } }); } public void init() { } // =============================== // === FXML ====================== // =============================== @FXML private void undo() { editedConnectionGroupDetails.undo(); editConnectionsController.listConnections(); // Note: listing connections should display the existing one updateButtons(); } @FXML private void save() { editedConnectionGroupDetails.apply(); editConnectionsController.listConnections(); updateButtons(); } @FXML public void createConnection() throws ConfigurationException { for (final ConfiguredConnectionDetails connection : connections) { editConnectionsController.openConnection(connection); } } // =============================== // === Logic ===================== // =============================== public void onChange() { if (recordModifications) { if (readAndDetectChanges()) { updateButtons(); editConnectionsController.listConnections(); } } } private boolean readAndDetectChanges() { editedConnectionGroupDetails.setName(connectionGroupNameText.getText()); boolean changed = !editedConnectionGroupDetails.getName(). equals(editedConnectionGroupDetails.getLastSavedValues().getName()); logger.debug("Values read. Changed = " + changed); editedConnectionGroupDetails.setModified(changed); return changed; } public void editConnectionGroup(final ConfiguredConnectionGroupDetails connectionGroup, final List<ConnectionTreeItemProperties> list) { synchronized (this) { this.editedConnectionGroupDetails = connectionGroup; this.connections = new ArrayList<>(); ConfigurationManager.findConnections(connectionGroup, connections); displayConnectionDetails(editedConnectionGroupDetails); updateButtons(); } } private void updateButtons() { if (editedConnectionGroupDetails != null && editedConnectionGroupDetails.isModified()) { saveButton.setDisable(false); undoButton.setDisable(false); } else { saveButton.setDisable(true); undoButton.setDisable(true); } } private void displayConnectionDetails(final ConfiguredConnectionGroupDetails group) { connectionGroupNameText.setText(group.getName()); connectionGroupNameText.setDisable(group.getID().equals(BaseConfigurationUtils.DEFAULT_GROUP)); connectionList.getItems().clear(); connectionMapping = new HashMap<>(); for (final ConfiguredConnectionDetails connection : connections) { final ProtocolVersionEnum protocol = connection.getProtocol(); final ConnectionListItemProperties properties = new ConnectionListItemProperties( connection.getName(), (protocol == null ? ProtocolVersionEnum.MQTT_DEFAULT.value() : protocol.value()), connection.getClientID() + "@" + ConnectionUtils.serverURIsToString(connection.getServerURI()), connection.getSSL() != null, connection.getUserAuthentication() != null); connectionList.getItems().add(properties); connectionMapping.put(properties, connection); } // editedConnectionGroupDetails.setBeingCreated(false); } // =============================== // === Setters and getters ======= // =============================== public void setEditConnectionsController(EditConnectionsController editConnectionsController) { this.editConnectionsController = editConnectionsController; } public void setMainController(MainController mainController) { this.mainController = mainController; } public void setRecordModifications(boolean recordModifications) { if (!recordModifications) { logger.trace("Modifications suspended..."); noModificationsLock++; this.recordModifications = recordModifications; } else { noModificationsLock--; // Only allow modifications once the parent caller removes the lock if (noModificationsLock == 0) { logger.trace("Modifications restored..."); this.recordModifications = recordModifications; } } } /** * @return the mainController */ public MainController getMainController() { return mainController; } }