/******************************************************************************* * Copyright (c) 2013, 2015 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; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Observable; import java.util.Observer; import org.cloudfoundry.ide.eclipse.server.core.ApplicationDeploymentInfo; import org.cloudfoundry.ide.eclipse.server.core.internal.ValueValidationUtil; import org.cloudfoundry.ide.eclipse.server.core.internal.application.EnvironmentVariable; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.StatusDialog; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.layout.GridLayoutFactory; import org.eclipse.jface.viewers.IStructuredContentProvider; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.ITableLabelProvider; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.window.Window; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.SWT; import org.eclipse.swt.accessibility.AccessibleAdapter; import org.eclipse.swt.accessibility.AccessibleEvent; 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.graphics.Image; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.swt.widgets.Text; public class EnvironmentVariablesPart extends UIPart implements Observer{ protected ApplicationDeploymentInfo deploymentInfo; private List<EnvironmentVariable> variables; private TableViewer envVariablesViewer; private Button editEnvVarButton; private Button removeEnvVarButton; public EnvironmentVariablesPart() { super(); } public EnvironmentVariablesPart(ApplicationDeploymentInfo deploymentInfo) { super(); this.deploymentInfo = deploymentInfo; if (deploymentInfo != null) { deploymentInfo.addObserver(this); } } public void setInput(List<EnvironmentVariable> variables) { this.variables = variables != null ? variables : new ArrayList<EnvironmentVariable>(); if (envVariablesViewer != null) { envVariablesViewer.setInput(variables); } } public List<EnvironmentVariable> getVariables() { return variables; } public void setVariables(List<EnvironmentVariable> variables) { this.variables = variables; setInput(variables); } public Control createPart(Composite parent) { Composite commonArea = new Composite(parent, SWT.NONE); GridLayoutFactory.fillDefaults().numColumns(2).applyTo(commonArea); GridDataFactory.fillDefaults().grab(true, true).applyTo(commonArea); Composite tableParent = new Composite(commonArea, SWT.NONE); GridLayoutFactory.fillDefaults().numColumns(1).applyTo(tableParent); GridDataFactory.fillDefaults().grab(true, true).applyTo(tableParent); Table table = new Table(tableParent, SWT.BORDER | SWT.MULTI); GridDataFactory.fillDefaults().grab(true, true).applyTo(table); envVariablesViewer = new TableViewer(table); Listener actionEnabler = new Listener() { @Override public void handleEvent(Event event) { setEnabledDisabled(); } }; table.addListener(SWT.Selection, actionEnabler); table.addListener(SWT.FocusOut, actionEnabler); envVariablesViewer.setContentProvider(new IStructuredContentProvider() { public Object[] getElements(Object inputElement) { if (inputElement instanceof Collection) { return ((Collection<?>) inputElement).toArray(new Object[0]); } return null; } public void dispose() { } public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { } }); envVariablesViewer.setLabelProvider(new EnvVarLabelProvider(envVariablesViewer)); table.setHeaderVisible(true); new TableResizeHelper(envVariablesViewer).enableResizing(); int columnIndex = 0; ViewColumn[] columns = ViewColumn.values(); String[] columnProperties = new String[columns.length]; for (ViewColumn column : columns) { columnProperties[columnIndex] = column.name(); TableColumn tableColumn = new TableColumn(table, SWT.NONE, columnIndex++); tableColumn.setData(column); tableColumn.setText(column.name()); tableColumn.setWidth(column.getWidth()); } envVariablesViewer.setColumnProperties(columnProperties); // Add accessibility listener to the table, so screen reader can provide a good description // of what is selected (in this case, an environment variable and its name) envVariablesViewer.getControl().getAccessible ().addAccessibleListener (new AccessibleAdapter() { @Override public void getName (AccessibleEvent e) { if (e.childID >= 0) { if (e.result != null) { e.result = NLS.bind(Messages.EnvironmentVariablesPart_TEXT_TABLE_ACC_LABEL, e.result); } else { e.result = Messages.COMMONTXT_ENV_VAR; } } } }); addEditButtons(commonArea); return commonArea; } protected void setEnabledDisabled() { removeEnvVarButton.setEnabled(isDeleteEnabled()); editEnvVarButton.setEnabled(isEditEnabled()); } private void addEditButtons(Composite parent) { Composite buttonArea = new Composite(parent, SWT.NONE); GridLayoutFactory.fillDefaults().numColumns(1).spacing(SWT.DEFAULT, 4).applyTo(buttonArea); GridDataFactory.fillDefaults().grab(false, true).applyTo(buttonArea); Button newEnvVarButton = new Button(buttonArea, SWT.NONE); newEnvVarButton.setText(Messages.EnvironmentVariablesPart_TEXT_NEW_ENV_VAR); GridDataFactory.fillDefaults().grab(false, false).applyTo(newEnvVarButton); newEnvVarButton.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { handleAdd(); } }); editEnvVarButton = new Button(buttonArea, SWT.NONE); editEnvVarButton.setText(Messages.COMMONTXT_EDIT); editEnvVarButton.setEnabled(false); GridDataFactory.fillDefaults().grab(false, false).applyTo(editEnvVarButton); editEnvVarButton.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { handleEdit(); } }); removeEnvVarButton = new Button(buttonArea, SWT.NONE); removeEnvVarButton.setText(Messages.COMMONTXT_REMOVE); removeEnvVarButton.setEnabled(false); GridDataFactory.fillDefaults().grab(false, false).applyTo(removeEnvVarButton); removeEnvVarButton.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { handleDelete(); } }); } private boolean isEditEnabled() { final List<EnvironmentVariable> vars = getViewerSelection(); boolean isEnabled = vars != null && vars.size() == 1; return isEnabled; } private boolean isDeleteEnabled() { final List<EnvironmentVariable> vars = getViewerSelection(); boolean isEnabled = vars != null && vars.size() > 0; return isEnabled; } protected void handleAdd() { boolean variableChanged = false; Shell shell = CloudUiUtil.getShell(); if (shell != null) { VariableDialogue dialogue = new VariableDialogue(shell, Messages.EnvironmentVariablesPart_ADD_TITLE, null, variables); if (dialogue.open() == Window.OK) { variableChanged = updateVariables(dialogue.getEnvironmentVariable(), null); } } if (variableChanged) { notifyStatusChange(Status.OK_STATUS); } } protected void handleEdit() { boolean variableChanged = false; Shell shell = CloudUiUtil.getShell(); List<EnvironmentVariable> selection = getViewerSelection(); if (shell != null && selection != null && !selection.isEmpty()) { EnvironmentVariable toEdit = selection.get(0); List<EnvironmentVariable> envList = new ArrayList<EnvironmentVariable>(); for (int i = 0; i < variables.size(); i ++) { if(!variables.get(i).getVariable().equals(toEdit.getVariable())) { envList.add(variables.get(i)); } } VariableDialogue dialogue = new VariableDialogue(shell, Messages.EnvironmentVariablesPart_EDIT_TITLE, toEdit, envList); if (dialogue.open() == Window.OK) { variableChanged = updateVariables(dialogue.getEnvironmentVariable(), toEdit); } } if (variableChanged) { notifyStatusChange(Status.OK_STATUS); setEnabledDisabled(); } } protected void handleDelete() { boolean variableChanged = false; List<EnvironmentVariable> selection = getViewerSelection(); if (selection != null && !selection.isEmpty()) { for (EnvironmentVariable toDelete : selection) { variableChanged = variableChanged || updateVariables(null, toDelete); } } if (variableChanged) { notifyStatusChange(Status.OK_STATUS); setEnabledDisabled(); } } protected boolean updateVariables(EnvironmentVariable add, EnvironmentVariable delete) { boolean variableChanged = false; if (variables == null) { variables = new ArrayList<EnvironmentVariable>(); } if (delete != null) { List<EnvironmentVariable> updatedList = new ArrayList<EnvironmentVariable>(); for (EnvironmentVariable var : variables) { if (var.equals(delete)) { variableChanged = true; } else { updatedList.add(var); } } variables = updatedList; } if (add != null) { variables.add(add); variableChanged = true; } setInput(variables); return variableChanged; } protected List<EnvironmentVariable> getViewerSelection() { IStructuredSelection selection = (IStructuredSelection) envVariablesViewer.getSelection(); List<EnvironmentVariable> selectedVars = new ArrayList<EnvironmentVariable>(); if (!selection.isEmpty()) { Object[] servicesObjs = selection.toArray(); for (Object serviceObj : servicesObjs) { selectedVars.add((EnvironmentVariable) serviceObj); } } return selectedVars; } protected void setViewerSelection(EnvironmentVariable var) { if (var != null) { envVariablesViewer.setSelection(new StructuredSelection(var)); } } enum ViewColumn { Variable(200), Value(200); private int width; private ViewColumn(int width) { this.width = width; } public int getWidth() { return width; } } protected class EnvVarLabelProvider extends LabelProvider implements ITableLabelProvider { private final TableViewer viewer; public EnvVarLabelProvider(TableViewer viewer) { this.viewer = viewer; } @Override public Image getImage(Object element) { return null; } public String getColumnText(Object element, int columnIndex) { String result = null; TableColumn column = viewer.getTable().getColumn(columnIndex); if (column != null) { ViewColumn serviceColumn = (ViewColumn) column.getData(); if (serviceColumn != null) { EnvironmentVariable var = (EnvironmentVariable) element; switch (serviceColumn) { case Variable: result = var.getVariable(); break; case Value: result = var.getValue(); break; } } } return result; } public Image getColumnImage(Object element, int columnIndex) { return null; } } protected class VariableDialogue extends StatusDialog { private EnvironmentVariable envVar; private String title; private Text name; private Text value; private List<EnvironmentVariable> variables; public VariableDialogue(Shell shell, String title, EnvironmentVariable envVar, List<EnvironmentVariable> variables) { super(shell); this.envVar = new EnvironmentVariable(); this.title = title; this.variables = variables; if (envVar != null) { this.envVar.setValue(envVar.getValue()); this.envVar.setVariable(envVar.getVariable()); } setHelpAvailable(false); setShellStyle(getShellStyle() | SWT.RESIZE); } public EnvironmentVariable getEnvironmentVariable() { return envVar; } @Override protected Control createButtonBar(Composite parent) { Control control = super.createButtonBar(parent); validate(); return control; } protected void setValues(Control control) { if (control == null || control.isDisposed()) { return; } if (control == name) { envVar.setVariable(name.getText()); } else if (control == value) { envVar.setValue(value.getText()); } validate(); } protected void validate() { Button okButton = getButton(IDialogConstants.OK_ID); if (okButton != null && !okButton.isDisposed()) { boolean isEmpty = ValueValidationUtil.isEmpty(envVar.getVariable()); boolean isDuplicate = false; for (EnvironmentVariable env : variables) { if (env.getVariable().equals(envVar.getVariable())) { isDuplicate = true; break; } } if (isDuplicate) { updateStatus(new Status(IStatus.ERROR, CloudFoundryServerUiPlugin.PLUGIN_ID, Messages.EnvironmentVariablesPart_DUP_VARIABLE_ERROR)); } else { if (isEmpty) { updateStatus(new Status(IStatus.ERROR, CloudFoundryServerUiPlugin.PLUGIN_ID, Messages.EnvironmentVariablesPart_EMPTY_VARIABLE_ERROR)); } else { updateStatus(Status.OK_STATUS); } } okButton.setEnabled(!(isEmpty || isDuplicate)); } } protected Control createDialogArea(Composite parent) { getShell().setText(Messages.COMMONTXT_ENV_VAR); this.setTitle(title); Composite control = (Composite) super.createDialogArea(parent); Composite composite = new Composite(control, SWT.NONE); GridLayout layout = new GridLayout(2, false); GridData data = new GridData(SWT.FILL, SWT.FILL, true, true); data.widthHint = 500; composite.setLayoutData(data); composite.setLayout(layout); Label nameLabel = new Label(composite, SWT.NONE); nameLabel.setText(Messages.COMMONTXT_NAME_WITH_COLON); name = new Text(composite, SWT.BORDER); name.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); if (envVar != null && envVar.getVariable() != null) { name.setText(envVar.getVariable()); } name.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent e) { setValues(name); } }); Label valueLabel = new Label(composite, SWT.NONE); valueLabel.setText(Messages.EnvironmentVariablesPart_TEXT_VALUE_LABEL); value = new Text(composite, SWT.BORDER); value.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); if (envVar != null && envVar.getValue() != null) { value.setText(envVar.getValue()); } value.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent e) { setValues(value); } }); validate(); return control; } } @Override @SuppressWarnings({ "unchecked" }) //$NON-NLS-1$ public void update(Observable o, Object arg) { if (arg != null && arg instanceof List<?> ) { try { List<EnvironmentVariable> envList = (List<EnvironmentVariable>) arg; this.setInput(envList); } catch (Exception e) { if (Logger.ERROR) { Logger.println(Logger.ERROR_LEVEL, this, "update", "Error updating Environment Variable", e); //$NON-NLS-1$ //$NON-NLS-2$ } } } } }