/* * Copyright (C) 2006-2016 DLR, Germany * * All rights reserved * * http://www.rcenvironment.de/ */ package de.rcenvironment.core.gui.communication.views.contributors; import java.util.Arrays; import java.util.Comparator; import java.util.WeakHashMap; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.window.Window; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.MessageBox; import de.rcenvironment.core.communication.connection.api.ConnectionSetup; import de.rcenvironment.core.communication.connection.api.ConnectionSetupService; import de.rcenvironment.core.communication.connection.api.ConnectionSetupState; import de.rcenvironment.core.communication.connection.api.DisconnectReason; import de.rcenvironment.core.communication.model.NetworkContactPoint; import de.rcenvironment.core.gui.communication.views.internal.AnchorPoints; import de.rcenvironment.core.gui.communication.views.model.NetworkGraphNodeWithContext; import de.rcenvironment.core.gui.communication.views.model.SimpleNetworkViewNode; import de.rcenvironment.core.gui.communication.views.spi.NetworkViewContributor; import de.rcenvironment.core.gui.communication.views.spi.SelfRenderingNetworkViewNode; import de.rcenvironment.core.gui.communication.views.spi.StandardUserNodeActionNode; import de.rcenvironment.core.gui.communication.views.spi.StandardUserNodeActionType; import de.rcenvironment.core.utils.common.StringUtils; import de.rcenvironment.core.utils.incubator.ServiceRegistry; /** * Contributes the subtree showing the list of current {@link ConnectionSetup}s. * * @author Robert Mischke */ public class ConnectionSetupsListContributor extends NetworkViewContributorBase { private static final AnchorPoints PARENT_ANCHOR = AnchorPoints.MAIN_NETWORK_SECTION_PARENT_NODE; /** * Tree wrapper for a {@link ConnectionSetup}. * * @author Robert Mischke */ private final class ConnectionSetupNode implements SelfRenderingNetworkViewNode, StandardUserNodeActionNode { private final ConnectionSetup connectionSetup; ConnectionSetupNode(ConnectionSetup connectionSetup) { // consistency check if (connectionSetup == null) { throw new NullPointerException(); } this.connectionSetup = connectionSetup; } @Override public NetworkViewContributor getContributor() { return ConnectionSetupsListContributor.this; } @Override public String getText() { String subState = ""; ConnectionSetupState connectionState = connectionSetup.getState(); DisconnectReason disconnectReason = connectionSetup.getDisconnectReason(); if ((connectionState == ConnectionSetupState.DISCONNECTED || connectionState == ConnectionSetupState.DISCONNECTING) && (disconnectReason != null)) { subState = ": " + disconnectReason.getDisplayText(); } return StringUtils.format("%s (%s%s)", connectionSetup.getDisplayName(), connectionState.getDisplayText(), subState); } @Override public Image getImage() { if (connectionSetup.getState() == ConnectionSetupState.CONNECTED) { return connectedImage; } else { return disconnectedImage; } } @Override public boolean getHasChildren() { return false; } @Override public boolean isActionApplicable(StandardUserNodeActionType actionType) { final ConnectionSetupState state = connectionSetup.getState(); switch (actionType) { case START: return state.isReasonableToAllowStart(); case STOP: return state.isReasonableToAllowStop(); case EDIT: case DELETE: return state == ConnectionSetupState.DISCONNECTED; default: return false; } } @Override public void performAction(StandardUserNodeActionType actionType) { switch (actionType) { case START: connectionSetup.signalStartIntent(); break; case STOP: connectionSetup.signalStopIntent(); break; case EDIT: performEdit(); break; case DELETE: performDelete(); break; default: break; } } private void performEdit() { String connectionName = connectionSetup.getDisplayName(); String networkContactString = connectionSetup.getNetworkContactPointString(); EditNetworkConnectionDialog dialog = new EditNetworkConnectionDialog(treeViewer.getTree().getShell(), connectionName, networkContactString); if (dialog.open() == Window.OK) { String newConnectionName = dialog.getConnectionName(); boolean newConnectImmediately = dialog.getConnectImmediately(); NetworkContactPoint ncp = dialog.getParsedNetworkContactPoint(); connectionSetupService.disposeConnectionSetup(connectionSetup); if (ncp != null) { ConnectionSetup newNetworkConnection = connectionSetupService.createConnectionSetup( ncp, newConnectionName, true); if (newConnectImmediately) { newNetworkConnection.signalStartIntent(); } } } } private void performDelete() { String connectionName = connectionSetup.getDisplayName(); String networkContactString = connectionSetup.getNetworkContactPointString(); MessageBox dialog = new MessageBox(treeViewer.getTree().getShell(), SWT.ICON_QUESTION | SWT.OK | SWT.CANCEL); dialog.setText("Delete Connection"); dialog.setMessage("Do you really want to delete connection \"" + connectionName + "\" to contact point \"" + networkContactString + "\" ?"); if (dialog.open() == SWT.OK) { connectionSetupService.disposeConnectionSetup(connectionSetup); } } } private static final int ROOT_PRIORITY = 20; private final Image connectedImage; private final Image disconnectedImage; private SelfRenderingNetworkViewNode rootNode; private final WeakHashMap<ConnectionSetup, ConnectionSetupNode> wrapperMap = new WeakHashMap<>(); private ConnectionSetupService connectionSetupService; public ConnectionSetupsListContributor() { connectedImage = ImageDescriptor.createFromURL( getClass().getResource("/resources/icons/connect.png")).createImage(); //$NON-NLS-1$ disconnectedImage = ImageDescriptor.createFromURL( getClass().getResource("/resources/icons/disconnect.png")).createImage(); //$NON-NLS-1$ connectionSetupService = ServiceRegistry.createAccessFor(this).getService(ConnectionSetupService.class); } @Override public int getRootElementsPriority() { return ROOT_PRIORITY; } @Override public Object[] getTopLevelElements(Object parentNode) { if (parentNode != PARENT_ANCHOR) { return null; } boolean hasConnections = currentModel.connectionSetups != null && !currentModel.connectionSetups.isEmpty(); rootNode = new SimpleNetworkViewNode("Connections", disconnectedImage, this, hasConnections); return new Object[] { rootNode }; } @Override public int getInstanceDataElementsPriority() { return 0; // disabled } @Override public Object[] getChildrenForNetworkInstanceNode(NetworkGraphNodeWithContext parentNode) { return EMPTY_ARRAY; } @Override public boolean hasChildren(Object parentNode) { // all nodes are self-rendering throw newUnexpectedCallException(); } @Override public Object[] getChildren(Object node) { if (node != rootNode) { throw newUnexpectedCallException(); } if (currentModel.connectionSetups == null) { return EMPTY_ARRAY; } // get and sort actual setups final ConnectionSetup[] setups = currentModel.connectionSetups.toArray(new ConnectionSetup[currentModel.connectionSetups.size()]); Arrays.sort(setups, new Comparator<ConnectionSetup>() { @Override public int compare(ConnectionSetup o1, ConnectionSetup o2) { return o1.getDisplayName().compareTo(o2.getDisplayName()); } }); // wrap into node class final ConnectionSetupNode[] nodes = new ConnectionSetupNode[setups.length]; int pos = 0; for (ConnectionSetup setup : setups) { // TODO check: use wrapperMap as cache here? ConnectionSetupNode wrapper = new ConnectionSetupNode(setup); wrapperMap.put(setup, wrapper); nodes[pos++] = wrapper; } // return wrappers return nodes; } @Override public Object getParent(Object node) { if (node == rootNode) { return PARENT_ANCHOR; } else { return rootNode; } } @Override public String getText(Object node) { throw newUnexpectedCallException(); } @Override public Image getImage(Object node) { throw newUnexpectedCallException(); } @Override public void dispose() { // self-created (not shared) images, so dispose them connectedImage.dispose(); disconnectedImage.dispose(); } /** * A custom method as we don't strictly separate the main UI code from the contributors. */ public void showAddConnectionDialog() { AddNetworkConnectionDialog dialog = new AddNetworkConnectionDialog(treeViewer.getTree().getShell()); if (dialog.open() == Window.OK) { String connectionName = dialog.getConnectionName(); boolean connectImmediately = dialog.getConnectImmediately(); NetworkContactPoint ncp = dialog.getParsedNetworkContactPoint(); if (ncp != null) { if (connectionName.isEmpty()) { connectionName = ncp.getHost() + ":" + ncp.getPort(); } ConnectionSetup cs = connectionSetupService.createConnectionSetup(ncp, connectionName, true); if (connectImmediately) { cs.signalStartIntent(); } } } } /** * Returns the wrapper used to represent the given {@link ConnectionSetup} in the GUI tree. * * @param setup the {@link ConnectionSetup} to look for * @return the wrapper tree element */ public Object getTreeNodeForSetup(ConnectionSetup setup) { return wrapperMap.get(setup); } /** * @return the tree element to refresh when the list of {@link ConnectionSetup}s changes */ public Object getFullRefreshRootElement() { //For some reason, refreshing the root element does not work. return PARENT_ANCHOR; } /** * @return the tree element to expand when the list of {@link ConnectionSetup}s changes */ public Object getRootElementToExpand() { return rootNode; } }