Java tutorial
/******************************************************************************* * Copyright (c) 2012, 2014 Pivotal Software, Inc. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Apache License, * Version 2.0 (the "License); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Contributors: * Pivotal Software, Inc. - initial API and implementation ********************************************************************************/ package org.cloudfoundry.ide.eclipse.server.ui.internal.tunnel; import java.util.EventObject; import java.util.List; import org.cloudfoundry.ide.eclipse.server.core.internal.CloudFoundryPlugin; import org.cloudfoundry.ide.eclipse.server.core.internal.ValueValidationUtil; import org.cloudfoundry.ide.eclipse.server.core.internal.application.EnvironmentVariable; import org.cloudfoundry.ide.eclipse.server.core.internal.tunnel.CommandOptions; import org.cloudfoundry.ide.eclipse.server.core.internal.tunnel.CommandTerminal; import org.cloudfoundry.ide.eclipse.server.core.internal.tunnel.ServerService; import org.cloudfoundry.ide.eclipse.server.core.internal.tunnel.ServerServiceWithPredefinitions; import org.cloudfoundry.ide.eclipse.server.core.internal.tunnel.ServiceCommand; import org.cloudfoundry.ide.eclipse.server.ui.internal.EnvironmentVariablesPart; import org.cloudfoundry.ide.eclipse.server.ui.internal.IPartChangeListener; import org.cloudfoundry.ide.eclipse.server.ui.internal.Messages; import org.cloudfoundry.ide.eclipse.server.ui.internal.PartChangeEvent; import org.cloudfoundry.ide.eclipse.server.ui.internal.UIPart; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.layout.GridLayoutFactory; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.TraverseEvent; import org.eclipse.swt.events.TraverseListener; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.FileDialog; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; /** * Adds a new command definition for a given service. Required values are a * command display name and the location of a command executable. * * A check is performed to see if either one of the have valid, non-empty * values. In addition, when adding a new command, if a command already exists * for the given service with the same display name, and error is shown. * * Display names must be unique. * * Another command can be used to pre-populate the UI. * */ public class AddCommandDisplayPart extends UIPart { private Text options; private Text locationField; private Text displayName; private Text terminalLocation; protected String optionsVal; protected String executableLocationValue; protected String displayNameVal; protected String terminalLocationVal; protected List<EnvironmentVariable> envVariables; private Button findApplicationButton; private boolean applyTerminalToAllCommands = false; private Combo predefinedCommands; private final List<ServiceCommand> predefined; private ServerService service; private Shell shell; private ServiceCommand serviceCommand; private CommandTerminal defaultTerminal; private EnvironmentVariablesPart envVarPart; /** * * @param service * @param serviceCommand . This is what is used to populate the wizard */ public AddCommandDisplayPart(ServerService service, ServiceCommand serviceCommand) { this(service, serviceCommand, null); } public AddCommandDisplayPart(ServerService service, CommandTerminal defaultTerminal) { this(service, null, defaultTerminal); } protected AddCommandDisplayPart(ServerService service, ServiceCommand serviceCommand, CommandTerminal defaultTerminal) { this.predefined = service instanceof ServerServiceWithPredefinitions ? ((ServerServiceWithPredefinitions) service).getPredefinedCommands() : null; this.service = service; this.serviceCommand = serviceCommand; this.defaultTerminal = defaultTerminal; } public Control createPart(Composite parent) { if (shell == null) { shell = parent.getShell(); } Composite main = new Composite(parent, SWT.NONE); GridLayoutFactory.fillDefaults().numColumns(1).applyTo(main); GridDataFactory.fillDefaults().grab(true, true).applyTo(main); createPredefinedArea(main); createAppLocationArea(main); createTerminalLocationArea(main); createOptionsArea(main); createEnvVariablesArea(main); createTunnelVariablesArea(main); readValues(); return main; } protected Composite createGroupComposite(Composite parent, String groupName) { Group group = new Group(parent, SWT.NONE); group.setText(groupName); GridLayoutFactory.fillDefaults().numColumns(1).applyTo(group); GridDataFactory.fillDefaults().grab(true, false).applyTo(group); Composite groupComp = new Composite(group, SWT.NONE); GridLayoutFactory.fillDefaults().numColumns(1).margins(new Point(10, 10)).applyTo(groupComp); GridDataFactory.fillDefaults().grab(true, false).applyTo(groupComp); return groupComp; } protected void createEnvVariablesArea(Composite parent) { parent = createGroupComposite(parent, Messages.COMMONTXT_ENV_VAR); envVarPart = new EnvironmentVariablesPart(); envVarPart.addPartChangeListener(new IPartChangeListener() { public void handleChange(PartChangeEvent event) { envVariables = envVarPart.getVariables(); // No need to validate as environment variables are optional } }); envVarPart.createPart(parent); } protected void createTerminalLocationArea(Composite parent) { parent = createGroupComposite(parent, Messages.AddCommandDisplayPart_TITLE_EXTERNAL_CMDLINE); terminalLocation = new Text(parent, SWT.BORDER); GridDataFactory.fillDefaults().grab(true, false).applyTo(terminalLocation); terminalLocation.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent event) { handleChange(event); } }); final Button terminalButton = new Button(parent, SWT.CHECK); GridDataFactory.fillDefaults().grab(false, false).applyTo(terminalButton); terminalButton.setText(Messages.AddCommandDisplayPart_BUTTON_APPLY_CHANGE); terminalButton.setSelection(applyTerminalToAllCommands); terminalButton.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent event) { applyTerminalToAllCommands = terminalButton.getSelection(); } }); } protected void createAppLocationArea(Composite parent) { // parent = createGroupComposite(parent, "Application"); /* Display name area */ Label commandDisplayName = new Label(parent, SWT.NONE); GridDataFactory.fillDefaults().grab(false, false).applyTo(commandDisplayName); commandDisplayName.setText(Messages.AddCommandDisplayPart_LABEL_DISPLAY_NAME); displayName = new Text(parent, SWT.BORDER); GridDataFactory.fillDefaults().grab(true, false).applyTo(displayName); displayName.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent event) { handleChange(event); } }); Label fileSelectionLabel = new Label(parent, SWT.NONE); GridDataFactory.fillDefaults().grab(false, false).applyTo(fileSelectionLabel); fileSelectionLabel.setText(Messages.AddCommandDisplayPart_LABEL_LOCATION_ENTER); locationField = new Text(parent, SWT.BORDER); GridDataFactory.fillDefaults().grab(false, false).applyTo(locationField); Composite buttonArea = new Composite(parent, SWT.NONE); GridLayoutFactory.fillDefaults().numColumns(1).applyTo(buttonArea); GridDataFactory.fillDefaults().grab(false, false).applyTo(buttonArea); locationField.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent event) { handleChange(event); } }); findApplicationButton = new Button(buttonArea, SWT.PUSH); GridDataFactory.fillDefaults().grab(false, false).applyTo(findApplicationButton); findApplicationButton.setText(Messages.AddCommandDisplayPart_BUTTON_BROWSE); findApplicationButton.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent event) { handleChange(event); } }); } protected void createOptionsArea(Composite parent) { parent = createGroupComposite(parent, Messages.AddCommandDisplayPart_TITLE_APP_OPTION); Label optionsLabel = new Label(parent, SWT.NONE); GridDataFactory.fillDefaults().grab(false, false).applyTo(optionsLabel); optionsLabel.setText(Messages.AddCommandDisplayPart_LABEL_SET_VAR); options = new Text(parent, SWT.MULTI | SWT.WRAP | SWT.BORDER | SWT.V_SCROLL); options.addTraverseListener(new TraverseListener() { public void keyTraversed(TraverseEvent event) { if (event.detail == SWT.TRAVERSE_RETURN && (event.stateMask & SWT.MODIFIER_MASK) != 0) { event.doit = true; } } }); options.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent event) { handleChange(event); } }); GridDataFactory.fillDefaults().grab(true, false).hint(IDialogConstants.ENTRY_FIELD_WIDTH, 80) .applyTo(options); } protected void createTunnelVariablesArea(Composite parent) { Text optionsDescription = new Text(parent, SWT.MULTI | SWT.BORDER); GridDataFactory.fillDefaults().grab(true, true).hint(IDialogConstants.ENTRY_FIELD_WIDTH, 120) .applyTo(optionsDescription); optionsDescription.setEditable(false); optionsDescription.setText(getOptionsDescription()); optionsDescription.setBackground(parent.getBackground()); } public boolean applyTerminalToAllCommands() { return applyTerminalToAllCommands; } protected void createPredefinedArea(Composite parent) { // See if any predefined commands are available are available if (predefined != null && !predefined.isEmpty()) { Label templates = new Label(parent, SWT.NONE); GridDataFactory.fillDefaults().grab(false, false).applyTo(templates); templates.setText(Messages.AddCommandDisplayPart_LABEL_SET_PREDEF_CMD); Composite predefinedArea = new Composite(parent, SWT.NONE); GridLayoutFactory.fillDefaults().numColumns(1).applyTo(predefinedArea); GridDataFactory.fillDefaults().grab(false, false).applyTo(predefinedArea); predefinedCommands = new Combo(predefinedArea, SWT.BORDER | SWT.READ_ONLY); GridDataFactory.fillDefaults().grab(false, false).applyTo(predefinedCommands); predefinedCommands.setEnabled(true); predefinedCommands.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { int selectionIndex = predefinedCommands.getSelectionIndex(); if (selectionIndex != -1) { // Account for the additional entry in the combo that // has no mapped entry in the predefined list int predefIndex = selectionIndex - 1; ServiceCommand value = predefIndex >= 0 && predefIndex < predefined.size() ? predefined.get(predefIndex) : null; setPredefinedCommand(value); } } }); // Add a clear value to allow users to clear the predefined command predefinedCommands.add(Messages.AddCommandDisplayPart_TEXT_SELECT); for (ServiceCommand option : predefined) { predefinedCommands.add(option.getDisplayName()); } predefinedCommands.select(0); } } protected void setPredefinedCommand(ServiceCommand predefinedCommand) { // If no predefined command is set, clear values if (predefinedCommand != null) { displayNameVal = predefinedCommand.getDisplayName(); displayName.setText(displayNameVal != null ? displayNameVal : ""); //$NON-NLS-1$ optionsVal = predefinedCommand.getOptions() != null ? predefinedCommand.getOptions().getOptions() : null; options.setText(optionsVal != null ? optionsVal : ""); //$NON-NLS-1$ executableLocationValue = predefinedCommand.getExternalApplication() != null ? predefinedCommand.getExternalApplication().getExecutableNameAndPath() : null; locationField.setText(executableLocationValue != null ? executableLocationValue : ""); //$NON-NLS-1$ envVariables = predefinedCommand.getEnvironmentVariables(); envVarPart.setInput(envVariables); } else { // Clear the values displayName.setText(""); //$NON-NLS-1$ options.setText(""); //$NON-NLS-1$ locationField.setText(""); //$NON-NLS-1$ envVarPart.setInput(null); } validate(true); } /** * Sets the control values based on the set service command. The set service * command can be either an existing command that is being edited or a * template that requires further input from the user. */ protected void readValues() { if (serviceCommand != null) { executableLocationValue = serviceCommand.getExternalApplication() != null ? serviceCommand.getExternalApplication().getExecutableNameAndPath() : null; if (executableLocationValue != null) { locationField.setText(executableLocationValue); } displayNameVal = serviceCommand.getDisplayName(); if (displayNameVal != null) { displayName.setText(displayNameVal); } optionsVal = serviceCommand.getOptions() != null ? serviceCommand.getOptions().getOptions() : null; if (optionsVal != null) { options.setText(optionsVal); } if (serviceCommand.getCommandTerminal() != null) { terminalLocationVal = serviceCommand.getCommandTerminal().getTerminal(); if (terminalLocationVal != null) { terminalLocation.setText(terminalLocationVal); } } envVariables = serviceCommand.getEnvironmentVariables(); envVarPart.setInput(envVariables); } else if (defaultTerminal != null) { terminalLocationVal = defaultTerminal.getTerminal(); if (terminalLocationVal != null) { terminalLocation.setText(terminalLocationVal); } } validate(false); } public void updateValues(Control eventControl) { if (eventControl == null || eventControl.isDisposed()) { return; } if (eventControl == locationField) { executableLocationValue = locationField.getText(); } else if (eventControl == displayName) { displayNameVal = displayName.getText(); } else if (eventControl == options) { optionsVal = options.getText(); } else if (eventControl == terminalLocation) { terminalLocationVal = terminalLocation.getText(); } else if (eventControl == findApplicationButton) { handleFileLocationButtonSelected(); } } public String getExecutableLocation() { return executableLocationValue; } public String getDisplayName() { return displayNameVal; } public String getOptions() { return optionsVal; } public String getTerminal() { return terminalLocationVal; } protected ServerService getService() { return service; } public List<EnvironmentVariable> getEnvironmentVariables() { return envVariables; } protected String getOptionsDescription() { return CommandOptions.getDefaultTunnelOptionsDescription(); } protected void handleFileLocationButtonSelected() { if (shell != null && locationField != null) { FileDialog fileDialog = new FileDialog(shell, SWT.NONE); fileDialog.setFileName(locationField.getText()); String text = fileDialog.open(); if (text != null) { locationField.setText(text); } } } protected void handleChange(EventObject event) { Object eventSource = event.getSource(); if (eventSource instanceof Control) { Control eventControl = (Control) eventSource; updateValues(eventControl); validate(true); } } /** * Return a non-null message, If and only if there is an error. No errors * should return null. */ protected String getValidationMessage() { String message = null; if (ValueValidationUtil.isEmpty(executableLocationValue)) { message = Messages.AddCommandDisplayPart_TEXT_NO_EXECUTABLE; } else if (ValueValidationUtil.isEmpty(displayNameVal)) { message = Messages.AddCommandDisplayPart_TEXT_NO_DISPLAY_NAME; } else { // Verify that another command doesn't already exist List<ServiceCommand> existingCommands = getService().getCommands(); if (existingCommands != null) { for (ServiceCommand command : existingCommands) { String otherCommandName = command.getDisplayName(); if ((command != serviceCommand) && otherCommandName.equals(displayNameVal)) { message = Messages.AddCommandDisplayPart_TEXT_NAME_EXIST; break; } } } } return message; } protected void validate(boolean setErrorMessage) { String message = getValidationMessage(); IStatus status = null; if (message != null) { // If it is an intial validation, generate an error status so // listeners can update controls accordingly (e.g., // if invoking this part in a wizard, the "Finish" button is // disabled), but set the message to null as to not // display the error to the user until a user enters data status = CloudFoundryPlugin.getErrorStatus(setErrorMessage ? message : null); } else { status = Status.OK_STATUS; } notifyStatusChange(status); } }