/*******************************************************************************
* Copyright (c) 2015, 2017 Red Hat Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Red Hat - Initial Contribution
*******************************************************************************/
package org.eclipse.linuxtools.internal.docker.ui.wizards;
import static org.eclipse.linuxtools.internal.docker.ui.launch.IRunDockerImageLaunchConfigurationConstants.CPU_PRIORITY;
import static org.eclipse.linuxtools.internal.docker.ui.launch.IRunDockerImageLaunchConfigurationConstants.DATA_VOLUMES;
import static org.eclipse.linuxtools.internal.docker.ui.launch.IRunDockerImageLaunchConfigurationConstants.ENABLE_LIMITS;
import static org.eclipse.linuxtools.internal.docker.ui.launch.IRunDockerImageLaunchConfigurationConstants.ENV_VARIABLES;
import static org.eclipse.linuxtools.internal.docker.ui.launch.IRunDockerImageLaunchConfigurationConstants.LABELS;
import static org.eclipse.linuxtools.internal.docker.ui.launch.IRunDockerImageLaunchConfigurationConstants.MEMORY_LIMIT;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.databinding.Binding;
import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.UpdateValueStrategy;
import org.eclipse.core.databinding.beans.BeanProperties;
import org.eclipse.core.databinding.beans.IBeanValueProperty;
import org.eclipse.core.databinding.observable.IChangeListener;
import org.eclipse.core.databinding.observable.list.IObservableList;
import org.eclipse.core.databinding.observable.map.IObservableMap;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.core.databinding.property.Properties;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.jface.databinding.swt.WidgetProperties;
import org.eclipse.jface.databinding.viewers.ObservableListContentProvider;
import org.eclipse.jface.databinding.viewers.ObservableMapLabelProvider;
import org.eclipse.jface.databinding.viewers.ViewerSupport;
import org.eclipse.jface.databinding.viewers.ViewersObservables;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.viewers.CheckboxTableViewer;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredViewer;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.linuxtools.docker.core.DockerException;
import org.eclipse.linuxtools.docker.core.IDockerConnection;
import org.eclipse.linuxtools.docker.core.IDockerImage;
import org.eclipse.linuxtools.docker.core.IDockerImageInfo;
import org.eclipse.linuxtools.docker.ui.Activator;
import org.eclipse.linuxtools.internal.docker.ui.SWTImagesFactory;
import org.eclipse.linuxtools.internal.docker.ui.jobs.FindImageInfoRunnable;
import org.eclipse.linuxtools.internal.docker.ui.wizards.ImageRunResourceVolumesVariablesModel.MountType;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Scale;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.Text;
/**
* A {@link WizardPage} to let the user select the CPU and memory allocation for
* the container, as well as the volumes to mount.
*
* @author xcoulon
*
*/
public class ImageRunResourceVolumesVariablesPage extends WizardPage {
private final int COLUMNS = 2;
private final DataBindingContext dbc = new DataBindingContext();
private final ImageRunResourceVolumesVariablesModel model;
private final ILaunchConfiguration lastLaunchConfiguration;
/**
* Default constructor.
*
* @param selectedImage
* the {@link IDockerImage} to run
* @throws DockerException
* if obtaining info from the given {@link IDockerConnection}
* failed
*
*/
public ImageRunResourceVolumesVariablesPage(
final IDockerConnection connection) throws DockerException {
super("ImageSelectionPage2", //$NON-NLS-1$
WizardMessages.getString("ImageRunResourceVolVarPage.title"), //$NON-NLS-1$
SWTImagesFactory.DESC_BANNER_REPOSITORY);
setPageComplete(true);
this.model = new ImageRunResourceVolumesVariablesModel(connection);
this.lastLaunchConfiguration = null;
}
/**
* Default constructor.
*
* @param selectedImage
* the {@link IDockerImage} to run
* @param lastLaunchConfiguration
* the last {@link ILaunchConfiguration} used to run this
* {@link IDockerImage} or <code>null</code> if none exists.
* @throws DockerException
* if obtaining info from the given {@link IDockerConnection}
* failed
* @throws CoreException
* if reading attributes from {@link ILaunchConfiguration}
* failed
*
*/
public ImageRunResourceVolumesVariablesPage(final IDockerImage image,
final ILaunchConfiguration lastLaunchConfiguration)
throws DockerException {
super("ImageSelectionPage2", //$NON-NLS-1$
WizardMessages.getString("ImageRunResourceVolVarPage.title"), //$NON-NLS-1$
SWTImagesFactory.DESC_BANNER_REPOSITORY);
setPageComplete(true);
this.model = new ImageRunResourceVolumesVariablesModel(
image);
this.lastLaunchConfiguration = lastLaunchConfiguration;
}
public ImageRunResourceVolumesVariablesModel getModel() {
return model;
}
@Override
public void createControl(Composite parent) {
final ScrolledComposite scrollTop = new ScrolledComposite(parent,
SWT.H_SCROLL | SWT.V_SCROLL);
scrollTop.setExpandVertical(true);
scrollTop.setExpandHorizontal(true);
final Composite container = new Composite(scrollTop, SWT.NONE);
GridLayoutFactory.fillDefaults().numColumns(COLUMNS).margins(6, 6)
.applyTo(container);
GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL)
.applyTo(container);
createVolumeSettingsContainer(container);
// createSectionSeparator(container, true);
createEnvironmentVariablesContainer(container);
createLabelVariablesContainer(container);
createSectionSeparator(container, true);
createResourceSettingsContainer(container);
setDefaultValues();
scrollTop.setContent(container);
Point point = container.computeSize(SWT.DEFAULT, SWT.DEFAULT);
scrollTop.setSize(point);
scrollTop.setMinSize(point);
// TODO: Workaround https://bugs.eclipse.org/bugs/show_bug.cgi?id=487160
setControl(scrollTop);
}
private void createSectionSeparator(final Composite container,
final boolean separator) {
final int SECTION_INDENT = 10;
GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER)
.span(COLUMNS, 1).grab(true, false)
.indent(SWT.DEFAULT, SECTION_INDENT)
.applyTo(new Label(container, separator
? (SWT.SEPARATOR | SWT.HORIZONTAL) : SWT.NONE));
}
private void createResourceSettingsContainer(final Composite parent) {
final Composite container = new Composite(parent, SWT.NONE);
GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL)
.span(COLUMNS, 1).grab(true, false).applyTo(container);
GridLayoutFactory.fillDefaults().spacing(10, 2).applyTo(container);
final Button enableResourceLimitationButton = new Button(container,
SWT.CHECK);
enableResourceLimitationButton.setText(WizardMessages.getString(
"ImageRunResourceVolVarPage.enableLimitationButton")); //$NON-NLS-1$
GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER)
.applyTo(enableResourceLimitationButton);
final int COLUMNS = 5;
final int INDENT = 20;
final Composite subContainer = new Composite(container, SWT.NONE);
GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL)
.indent(INDENT, 0).span(COLUMNS, 1).grab(true, false)
.applyTo(subContainer);
GridLayoutFactory.fillDefaults().numColumns(COLUMNS).margins(6, 6)
.spacing(10, 2).applyTo(subContainer);
// specify CPU limitation
final Label cpuPriorityLabel = new Label(subContainer, SWT.NONE);
cpuPriorityLabel.setText(WizardMessages
.getString("ImageRunResourceVolVarPage.cpuPriorityLabel")); //$NON-NLS-1$
GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER)
.grab(false, false).applyTo(cpuPriorityLabel);
final Button lowCPULimitationButton = new Button(subContainer,
SWT.RADIO);
bindButton(lowCPULimitationButton,
ImageRunResourceVolumesVariablesModel.CPU_LOW);
lowCPULimitationButton.setText(WizardMessages
.getString("ImageRunResourceVolVarPage.lowButton")); //$NON-NLS-1$
GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER)
.applyTo(lowCPULimitationButton);
final Button mediumCPULimitationButton = new Button(subContainer,
SWT.RADIO);
mediumCPULimitationButton.setText(WizardMessages
.getString("ImageRunResourceVolVarPage.mediumButton")); //$NON-NLS-1$
bindButton(mediumCPULimitationButton,
ImageRunResourceVolumesVariablesModel.CPU_MEDIUM);
GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER)
.applyTo(mediumCPULimitationButton);
final Button highCPULimitationButton = new Button(subContainer,
SWT.RADIO);
highCPULimitationButton.setText(WizardMessages
.getString("ImageRunResourceVolVarPage.highButton")); //$NON-NLS-1$
bindButton(highCPULimitationButton,
ImageRunResourceVolumesVariablesModel.CPU_HIGH);
GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER).span(2, 1)
.applyTo(highCPULimitationButton);
// Memory limitation
final Label memoryLimitLabel = new Label(subContainer, SWT.NONE);
memoryLimitLabel.setText(WizardMessages
.getString("ImageRunResourceVolVarPage.memoryLimit")); //$NON-NLS-1$
GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER)
.grab(false, false).applyTo(memoryLimitLabel);
final Scale memoryLimitSpinner = new Scale(subContainer, SWT.NONE);
GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER)
.grab(false, false).span(2, 1).applyTo(memoryLimitSpinner);
memoryLimitSpinner.setBackground(
Display.getDefault().getSystemColor(SWT.COLOR_TRANSPARENT));
memoryLimitSpinner.setMinimum(0);
memoryLimitSpinner.setMaximum(this.model.getTotalMemory());
memoryLimitSpinner.setPageIncrement(64);
dbc.bindValue(WidgetProperties.selection().observe(memoryLimitSpinner),
BeanProperties
.value(ImageRunResourceVolumesVariablesModel.class,
ImageRunResourceVolumesVariablesModel.MEMORY_LIMIT)
.observe(model));
final Text memoryLimitValueText = new Text(subContainer, SWT.BORDER);
GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER)
.grab(false, false).hint(50, SWT.DEFAULT)
.applyTo(memoryLimitValueText);
dbc.bindValue(
WidgetProperties.text(SWT.Modify).observe(memoryLimitValueText),
BeanProperties
.value(ImageRunResourceVolumesVariablesModel.class,
ImageRunResourceVolumesVariablesModel.MEMORY_LIMIT)
.observe(model));
final Label memoryLimitValueLabel = new Label(subContainer, SWT.NONE);
memoryLimitValueLabel.setText("MB"); //$NON-NLS-1$
GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER)
.grab(false, false).applyTo(memoryLimitValueLabel);
// enable/disable controls
final IObservableValue enableResourceLimitationsObservable = BeanProperties
.value(ImageRunResourceVolumesVariablesModel.class,
ImageRunResourceVolumesVariablesModel.ENABLE_RESOURCE_LIMITATIONS)
.observe(model);
dbc.bindValue(
WidgetProperties.selection()
.observe(enableResourceLimitationButton),
enableResourceLimitationsObservable);
enableResourceLimitationsObservable
.addChangeListener(onEnableResourceLimitation(subContainer));
toggleResourceLimitationControls(subContainer);
}
/**
* Binds the given <code>cpuShares</code> value to the given {@link Button}
* when it is selected.
*
* @param button
* the {@link Button} to bind
* @param cpuShares
* the <code>cpuShares</code> to bind to the {@link Button}
* @return
*/
private Binding bindButton(final Button button, final long cpuShares) {
return dbc.bindValue(WidgetProperties.selection().observe(button),
BeanProperties
.value(ImageRunResourceVolumesVariablesModel.class,
ImageRunResourceVolumesVariablesModel.CPU_SHARE_WEIGHT)
.observe(model),
new UpdateValueStrategy() {
@Override
public Object convert(Object value) {
if (value.equals(Boolean.TRUE)) {
return cpuShares;
}
return 0l;
}
}, new UpdateValueStrategy() {
@Override
public Object convert(final Object value) {
return value.equals(cpuShares);
}
});
}
private IChangeListener onEnableResourceLimitation(
final Composite container) {
return event -> toggleResourceLimitationControls(container);
}
private void toggleResourceLimitationControls(Composite container) {
for (Control childControl : container.getChildren()) {
if (model.isEnableResourceLimitations()) {
childControl.setEnabled(true);
} else {
childControl.setEnabled(false);
}
}
}
private void createVolumeSettingsContainer(final Composite container) {
final Label volumesLabel = new Label(container, SWT.NONE);
volumesLabel.setText(WizardMessages
.getString("ImageRunResourceVolVarPage.dataVolumesLabel")); //$NON-NLS-1$
GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER)
.grab(true, false).span(COLUMNS, 1).applyTo(volumesLabel);
final CheckboxTableViewer dataVolumesTableViewer = createVolumesTable(
container);
GridDataFactory.fillDefaults().align(SWT.FILL, SWT.TOP)
.grab(true, false).hint(200, 100)
.applyTo(dataVolumesTableViewer.getTable());
// buttons
final Composite buttonsContainers = new Composite(container, SWT.NONE);
GridDataFactory.fillDefaults().align(SWT.FILL, SWT.TOP)
.grab(false, false).applyTo(buttonsContainers);
GridLayoutFactory.fillDefaults().numColumns(1).margins(0, 0)
.spacing(SWT.DEFAULT, 0).applyTo(buttonsContainers);
final Button addButton = new Button(buttonsContainers, SWT.NONE);
GridDataFactory.fillDefaults().align(SWT.FILL, SWT.TOP)
.grab(true, false).applyTo(addButton);
addButton.setText(WizardMessages
.getString("ImageRunResourceVolVarPage.addButton")); //$NON-NLS-1$
addButton.addSelectionListener(onAddDataVolume(dataVolumesTableViewer));
final Button editButton = new Button(buttonsContainers, SWT.NONE);
GridDataFactory.fillDefaults().align(SWT.FILL, SWT.TOP)
.grab(true, false).applyTo(editButton);
editButton.setText(WizardMessages
.getString("ImageRunResourceVolVarPage.editButton")); //$NON-NLS-1$
editButton
.addSelectionListener(onEditDataVolume(dataVolumesTableViewer));
editButton.setEnabled(false);
final Button removeButton = new Button(buttonsContainers, SWT.NONE);
GridDataFactory.fillDefaults().align(SWT.FILL, SWT.TOP)
.grab(true, false).applyTo(removeButton);
removeButton.setText(WizardMessages
.getString("ImageRunResourceVolVarPage.removeButton")); //$NON-NLS-1$
removeButton.addSelectionListener(
onRemoveDataVolumes(dataVolumesTableViewer));
removeButton.setEnabled(false);
// update table content when selected image changes
bind(dataVolumesTableViewer, model.getDataVolumes(),
BeanProperties.values(DataVolumeModel.class,
DataVolumeModel.CONTAINER_PATH, DataVolumeModel.MOUNT,
DataVolumeModel.READ_ONLY_VOLUME));
dbc.bindSet(
ViewersObservables.observeCheckedElements(
dataVolumesTableViewer, DataVolumeModel.class),
BeanProperties
.set(ImageRunResourceVolumesVariablesModel.SELECTED_DATA_VOLUMES)
.observe(model));
// disable the edit and removeButton if the table is empty
dataVolumesTableViewer.addSelectionChangedListener(
onSelectionChanged(editButton, removeButton));
}
private void setDefaultValues() {
try {
// skip if a previous launch configuration was provided
final IDockerImage selectedImage = model.getSelectedImage();
if (selectedImage == null) {
return;
}
final IDockerImageInfo selectedImageInfo = findImageInfo(
selectedImage);
// using a map filled with entries (key==value) from default volumes
// that can be overridden by values from last launch config
final Map<String, DataVolumeModel> volumes = new HashMap<>();
final Set<DataVolumeModel> selectedVolumes = new HashSet<>();
if (selectedImageInfo != null
&& selectedImageInfo.config() != null) {
for (String volume : selectedImageInfo.config().volumes()) {
volumes.put(volume, new DataVolumeModel(volume));
}
}
if (lastLaunchConfiguration != null) {
// volumes:
final List<String> launchConfigVolumes = lastLaunchConfiguration
.getAttribute(DATA_VOLUMES,
Collections.<String> emptyList());
for (String containerVolume : launchConfigVolumes) {
final DataVolumeModel volume = DataVolumeModel
.parseString(containerVolume);
if (volume != null) {
volumes.put(volume.getContainerPath(), volume);
selectedVolumes.add(volume);
}
}
// environment variables
model.setEnvironmentVariables(
lastLaunchConfiguration.getAttribute(ENV_VARIABLES,
Collections.<String> emptyList()));
// labels
Map<String, String> labels = lastLaunchConfiguration
.getAttribute(LABELS, (Map<String, String>) null);
if (labels != null) {
model.setLabelVariables(labels);
}
// resource limitations
model.setEnableResourceLimitations(lastLaunchConfiguration
.getAttribute(ENABLE_LIMITS, false));
// CPU shares
model.setCpuShareWeight(Long.parseLong(lastLaunchConfiguration
.getAttribute(CPU_PRIORITY, Long.toString(
ImageRunResourceVolumesVariablesModel.CPU_MEDIUM))));
// retrieve memory limit stored in MB
final long memoryLimit = Long.parseLong(lastLaunchConfiguration
.getAttribute(MEMORY_LIMIT, Long.toString(
ImageRunResourceVolumesVariablesModel.DEFAULT_MEMORY)));
// make sure memory limit is not higher than maxMemory
model.setMemoryLimit(
Math.min(model.getTotalMemory(), memoryLimit));
}
model.setDataVolumes(volumes.values());
model.setSelectedDataVolumes(selectedVolumes);
} catch (CoreException | InvocationTargetException
| InterruptedException e) {
Activator.log(e);
}
}
private IDockerImageInfo findImageInfo(final IDockerImage selectedImage)
throws InvocationTargetException, InterruptedException {
final FindImageInfoRunnable findImageInfoRunnable = new FindImageInfoRunnable(
selectedImage);
getContainer().run(true, true, findImageInfoRunnable);
final IDockerImageInfo selectedImageInfo = findImageInfoRunnable
.getResult();
return selectedImageInfo;
}
/**
* Same as
* {@link ViewerSupport#bind(StructuredViewer, IObservableList, org.eclipse.core.databinding.property.value.IValueProperty[])
* but with a custom LabelProvider, DataVolumesLabelProvider
*
* @param viewer
* @param input
* @param labelProperties
*/
private void bind(final StructuredViewer viewer,
final IObservableList input,
final IBeanValueProperty[] labelProperties) {
final ObservableListContentProvider contentProvider = new ObservableListContentProvider();
if (viewer.getInput() != null) {
viewer.setInput(null);
}
viewer.setContentProvider(contentProvider);
viewer.setLabelProvider(
new DataVolumesLabelProvider(Properties.observeEach(
contentProvider.getKnownElements(), labelProperties)));
if (input != null) {
viewer.setInput(input);
}
}
private ISelectionChangedListener onSelectionChanged(
final Button... targetButtons) {
return e -> {
if (e.getSelection().isEmpty()) {
setControlsEnabled(targetButtons, false);
} else {
setControlsEnabled(targetButtons, true);
}
};
}
private SelectionListener onAddDataVolume(
final CheckboxTableViewer dataVolumesTableViewer) {
return new SelectionAdapter() {
@Override
public void widgetSelected(final SelectionEvent e) {
final ContainerDataVolumeDialog dialog = new ContainerDataVolumeDialog(
getShell(), model.getConnection());
dialog.create();
if (dialog.open() == IDialogConstants.OK_ID) {
final DataVolumeModel dataVolume = dialog.getDataVolume();
dataVolume.setSelected(true);
model.getDataVolumes().add(dataVolume);
model.getSelectedDataVolumes().add(dataVolume);
dataVolumesTableViewer.setChecked(dataVolume,
true);
}
}
};
}
private SelectionListener onEditDataVolume(
final CheckboxTableViewer dataVolumesTableViewer) {
return new SelectionAdapter() {
@Override
public void widgetSelected(final SelectionEvent e) {
final IStructuredSelection selection = (IStructuredSelection) dataVolumesTableViewer
.getSelection();
if (selection.isEmpty()) {
return;
}
final DataVolumeModel selectedDataVolume = (DataVolumeModel) selection
.getFirstElement();
final ContainerDataVolumeDialog dialog = new ContainerDataVolumeDialog(
getShell(), model.getConnection(), selectedDataVolume);
dialog.create();
if (dialog.open() == IDialogConstants.OK_ID) {
final DataVolumeModel dialogDataVolume = dialog
.getDataVolume();
selectedDataVolume.setContainerMount(
dialogDataVolume.getContainerMount());
selectedDataVolume
.setMountType(dialogDataVolume.getMountType());
selectedDataVolume.setHostPathMount(
dialogDataVolume.getHostPathMount());
selectedDataVolume.setContainerMount(
dialogDataVolume.getContainerMount());
selectedDataVolume
.setReadOnly(dialogDataVolume.isReadOnly());
model.getSelectedDataVolumes().add(selectedDataVolume);
dataVolumesTableViewer.setChecked(selectedDataVolume, true);
}
}
};
}
private SelectionListener onRemoveDataVolumes(
final TableViewer dataVolumesTableViewer) {
return new SelectionAdapter() {
@Override
public void widgetSelected(final SelectionEvent e) {
final IStructuredSelection selection = dataVolumesTableViewer
.getStructuredSelection();
for (@SuppressWarnings("unchecked")
Iterator<DataVolumeModel> iterator = selection
.iterator(); iterator.hasNext();) {
final DataVolumeModel volume = iterator.next();
model.removeDataVolume(volume);
model.getSelectedDataVolumes().remove(volume);
}
}
};
}
private CheckboxTableViewer createVolumesTable(final Composite container) {
final Table table = new Table(container, SWT.CHECK | SWT.BORDER
| SWT.FULL_SELECTION | SWT.V_SCROLL | SWT.H_SCROLL);
final CheckboxTableViewer tableViewer = new CheckboxTableViewer(table);
table.setHeaderVisible(true);
table.setLinesVisible(true);
dbc.bindSet(
ViewersObservables.observeCheckedElements(tableViewer,
DataVolumeModel.class),
BeanProperties
.set(ImageRunResourceVolumesVariablesModel.SELECTED_DATA_VOLUMES)
.observe(model));
addTableViewerColum(tableViewer,
WizardMessages.getString(
"ImageRunResourceVolVarPage.containerPathColumn"), //$NON-NLS-1$
150);
addTableViewerColum(tableViewer,
WizardMessages
.getString("ImageRunResourceVolVarPage.mountColumn"), //$NON-NLS-1$
150);
addTableViewerColum(tableViewer,
WizardMessages
.getString("ImageRunResourceVolVarPage.readonlyColumn"), //$NON-NLS-1$
60);
return tableViewer;
}
private TableViewerColumn addTableViewerColum(final TableViewer tableViewer,
final String title, final int width) {
final TableViewerColumn viewerColumn = new TableViewerColumn(
tableViewer, SWT.NONE);
final TableColumn column = viewerColumn.getColumn();
if (title != null) {
column.setText(title);
}
column.setWidth(width);
return viewerColumn;
}
private void createLabelVariablesContainer(final Composite container) {
final Label labelVarLabel = new Label(container, SWT.NONE);
labelVarLabel.setText(WizardMessages
.getString("ImageRunResourceVolVarPage.labelVarLabel")); //$NON-NLS-1$
GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER)
.grab(true, false).span(COLUMNS, 1).applyTo(labelVarLabel);
final TableViewer labelVariablesTableViewer = createEnvironmentVariablesTable(
container);
GridDataFactory.fillDefaults().align(SWT.FILL, SWT.TOP)
.grab(true, false).hint(200, 100)
.applyTo(labelVariablesTableViewer.getTable());
// buttons
final Composite buttonsContainers = new Composite(container, SWT.NONE);
GridDataFactory.fillDefaults().align(SWT.FILL, SWT.TOP)
.grab(false, false).applyTo(buttonsContainers);
GridLayoutFactory.fillDefaults().numColumns(1).margins(0, 0)
.spacing(SWT.DEFAULT, 0).applyTo(buttonsContainers);
final Button addButton = new Button(buttonsContainers, SWT.NONE);
GridDataFactory.fillDefaults().align(SWT.FILL, SWT.TOP)
.grab(true, false).applyTo(addButton);
addButton.setText(WizardMessages
.getString("ImageRunResourceVolVarPage.addButton")); //$NON-NLS-1$
addButton.setEnabled(true);
addButton.addSelectionListener(onAddLabelVariable());
final Button editButton = new Button(buttonsContainers, SWT.NONE);
GridDataFactory.fillDefaults().align(SWT.FILL, SWT.TOP)
.grab(true, false).applyTo(editButton);
editButton.setText(WizardMessages
.getString("ImageRunResourceVolVarPage.editButton")); //$NON-NLS-1$
editButton.setEnabled(true);
editButton.addSelectionListener(
onEditLabelVariable(labelVariablesTableViewer));
editButton.setEnabled(false);
final Button removeButton = new Button(buttonsContainers, SWT.NONE);
GridDataFactory.fillDefaults().align(SWT.FILL, SWT.TOP)
.grab(true, false).applyTo(removeButton);
removeButton.setText(WizardMessages
.getString("ImageRunResourceVolVarPage.removeButton")); //$NON-NLS-1$
removeButton.addSelectionListener(
onRemoveLabelVariables(labelVariablesTableViewer));
removeButton.setEnabled(false);
// update table content when selected image changes
ViewerSupport.bind(labelVariablesTableViewer, model.getLabelVariables(),
BeanProperties.values(LabelVariableModel.class,
LabelVariableModel.NAME, LabelVariableModel.VALUE));
// disable the edit and removeButton if the table is empty
labelVariablesTableViewer.addSelectionChangedListener(
onSelectionChanged(editButton, removeButton));
}
private TableViewer createLabelVariablesTable(Composite container) {
final Table table = new Table(container,
SWT.BORDER | SWT.FULL_SELECTION | SWT.V_SCROLL | SWT.H_SCROLL);
final TableViewer tableViewer = new TableViewer(table);
table.setHeaderVisible(true);
table.setLinesVisible(true);
addTableViewerColum(tableViewer,
WizardMessages
.getString("ImageRunResourceVolVarPage.nameColumn"), //$NON-NLS-1$
200);
addTableViewerColum(tableViewer,
WizardMessages
.getString("ImageRunResourceVolVarPage.valueColumn"), //$NON-NLS-1$
200);
return tableViewer;
}
private SelectionListener onAddLabelVariable() {
return new SelectionAdapter() {
@Override
public void widgetSelected(final SelectionEvent e) {
final ContainerLabelVariableDialog dialog = new ContainerLabelVariableDialog(
getShell());
dialog.create();
if (dialog.open() == IDialogConstants.OK_ID) {
model.getLabelVariables().add(dialog.getLabelVariable());
}
}
};
}
private SelectionListener onEditLabelVariable(
final TableViewer LabelVariablesTableViewer) {
return new SelectionAdapter() {
@Override
public void widgetSelected(final SelectionEvent e) {
final LabelVariableModel selectedVariable = (LabelVariableModel) LabelVariablesTableViewer
.getStructuredSelection().getFirstElement();
final ContainerLabelVariableDialog dialog = new ContainerLabelVariableDialog(
getShell(), selectedVariable);
dialog.create();
if (dialog.open() == IDialogConstants.OK_ID) {
selectedVariable
.setName(dialog.getLabelVariable().getName());
selectedVariable
.setValue(dialog.getLabelVariable().getValue());
LabelVariablesTableViewer.refresh();
}
}
};
}
private SelectionListener onRemoveLabelVariables(
final TableViewer linksTableViewer) {
return new SelectionAdapter() {
@Override
public void widgetSelected(final SelectionEvent e) {
final IStructuredSelection selection = linksTableViewer
.getStructuredSelection();
for (@SuppressWarnings("unchecked")
Iterator<LabelVariableModel> iterator = selection
.iterator(); iterator.hasNext();) {
model.removeLabelVariable(iterator.next());
}
}
};
}
private void createEnvironmentVariablesContainer(
final Composite container) {
final Label envVarLabel = new Label(container, SWT.NONE);
envVarLabel.setText(WizardMessages
.getString("ImageRunResourceVolVarPage.envVarLabel")); //$NON-NLS-1$
GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER)
.grab(true, false).span(COLUMNS, 1).applyTo(envVarLabel);
final TableViewer environmentVariablesTableViewer = createEnvironmentVariablesTable(
container);
GridDataFactory.fillDefaults().align(SWT.FILL, SWT.TOP)
.grab(true, false).hint(200, 100)
.applyTo(environmentVariablesTableViewer.getTable());
// buttons
final Composite buttonsContainers = new Composite(container, SWT.NONE);
GridDataFactory.fillDefaults().align(SWT.FILL, SWT.TOP)
.grab(false, false).applyTo(buttonsContainers);
GridLayoutFactory.fillDefaults().numColumns(1).margins(0, 0)
.spacing(SWT.DEFAULT, 0).applyTo(buttonsContainers);
final Button addButton = new Button(buttonsContainers, SWT.NONE);
GridDataFactory.fillDefaults().align(SWT.FILL, SWT.TOP)
.grab(true, false).applyTo(addButton);
addButton.setText(WizardMessages
.getString("ImageRunResourceVolVarPage.addButton")); //$NON-NLS-1$
addButton.setEnabled(true);
addButton.addSelectionListener(onAddEnvironmentVariable());
final Button editButton = new Button(buttonsContainers, SWT.NONE);
GridDataFactory.fillDefaults().align(SWT.FILL, SWT.TOP)
.grab(true, false).applyTo(editButton);
editButton.setText(WizardMessages
.getString("ImageRunResourceVolVarPage.editButton")); //$NON-NLS-1$
editButton.setEnabled(true);
editButton.addSelectionListener(
onEditEnvironmentVariable(environmentVariablesTableViewer));
editButton.setEnabled(false);
final Button removeButton = new Button(buttonsContainers, SWT.NONE);
GridDataFactory.fillDefaults().align(SWT.FILL, SWT.TOP)
.grab(true, false).applyTo(removeButton);
removeButton.setText(WizardMessages
.getString("ImageRunResourceVolVarPage.removeButton")); //$NON-NLS-1$
removeButton.addSelectionListener(
onRemoveEnvironmentVariables(environmentVariablesTableViewer));
removeButton.setEnabled(false);
// update table content when selected image changes
ViewerSupport.bind(environmentVariablesTableViewer,
model.getEnvironmentVariables(),
BeanProperties.values(EnvironmentVariableModel.class,
EnvironmentVariableModel.NAME,
EnvironmentVariableModel.VALUE));
// disable the edit and removeButton if the table is empty
environmentVariablesTableViewer.addSelectionChangedListener(
onSelectionChanged(editButton, removeButton));
}
private TableViewer createEnvironmentVariablesTable(Composite container) {
final Table table = new Table(container,
SWT.BORDER | SWT.FULL_SELECTION | SWT.V_SCROLL | SWT.H_SCROLL);
final TableViewer tableViewer = new TableViewer(table);
table.setHeaderVisible(true);
table.setLinesVisible(true);
addTableViewerColum(tableViewer,
WizardMessages
.getString("ImageRunResourceVolVarPage.nameColumn"), //$NON-NLS-1$
200);
addTableViewerColum(tableViewer,
WizardMessages
.getString("ImageRunResourceVolVarPage.valueColumn"), //$NON-NLS-1$
200);
return tableViewer;
}
private SelectionListener onAddEnvironmentVariable() {
return new SelectionAdapter() {
@Override
public void widgetSelected(final SelectionEvent e) {
final ContainerEnvironmentVariableDialog dialog = new ContainerEnvironmentVariableDialog(
getShell());
dialog.create();
if (dialog.open() == IDialogConstants.OK_ID) {
model.getEnvironmentVariables()
.add(dialog.getEnvironmentVariable());
}
}
};
}
private SelectionListener onEditEnvironmentVariable(
final TableViewer environmentVariablesTableViewer) {
return new SelectionAdapter() {
@Override
public void widgetSelected(final SelectionEvent e) {
final EnvironmentVariableModel selectedVariable = (EnvironmentVariableModel) environmentVariablesTableViewer
.getStructuredSelection().getFirstElement();
final ContainerEnvironmentVariableDialog dialog = new ContainerEnvironmentVariableDialog(
getShell(), selectedVariable);
dialog.create();
if (dialog.open() == IDialogConstants.OK_ID) {
selectedVariable.setName(
dialog.getEnvironmentVariable().getName());
selectedVariable.setValue(
dialog.getEnvironmentVariable().getValue());
environmentVariablesTableViewer.refresh();
}
}
};
}
private SelectionListener onRemoveEnvironmentVariables(
final TableViewer linksTableViewer) {
return new SelectionAdapter() {
@Override
public void widgetSelected(final SelectionEvent e) {
final IStructuredSelection selection = linksTableViewer
.getStructuredSelection();
for (@SuppressWarnings("unchecked")
Iterator<EnvironmentVariableModel> iterator = selection
.iterator(); iterator.hasNext();) {
model.removeEnvironmentVariable(iterator.next());
}
}
};
}
private static void setControlsEnabled(final Control[] controls,
final boolean enabled) {
for (Control control : controls) {
control.setEnabled(enabled);
}
}
private static final class DataVolumesLabelProvider
extends ObservableMapLabelProvider {
private Image CONTAINER_IMAGE = SWTImagesFactory.DESC_CONTAINER
.createImage();
private Image FOLDER_CLOSED_IMAGE = SWTImagesFactory.DESC_FOLDER_CLOSED
.createImage();
private Image FILE_IMAGE = SWTImagesFactory.DESC_FILE.createImage();
public DataVolumesLabelProvider(final IObservableMap[] attributeMaps) {
super(attributeMaps);
}
@Override
public void dispose() {
CONTAINER_IMAGE.dispose();
FOLDER_CLOSED_IMAGE.dispose();
FILE_IMAGE.dispose();
super.dispose();
}
@Override
public Image getColumnImage(Object element, int columnIndex) {
final DataVolumeModel dataVolume = ((DataVolumeModel) element);
if (dataVolume.getMountType() != null && columnIndex == 1) {
switch (dataVolume.getMountType()) {
case CONTAINER:
return CONTAINER_IMAGE;
case HOST_FILE_SYSTEM:
final File hostFile = new File(dataVolume.getMount());
if (!hostFile.exists() || hostFile.isDirectory()) {
return FOLDER_CLOSED_IMAGE;
} else {
return FILE_IMAGE;
}
default:
return null;
}
}
return null;
}
@Override
public String getColumnText(Object element, int columnIndex) {
final DataVolumeModel dataVolume = ((DataVolumeModel) element);
switch (columnIndex) {
case 0:
return dataVolume.getContainerPath();
case 1:
return dataVolume.getMount();
case 2:
if (dataVolume.getMountType() != MountType.HOST_FILE_SYSTEM) {
return null;
} else if (dataVolume.isReadOnly()) {
return WizardMessages
.getString("ImageRunResourceVolVarPage.true"); //$NON-NLS-1$
}
return WizardMessages
.getString("ImageRunResourceVolVarPage.false"); //$NON-NLS-1$
default:
return null;
}
}
}
}