/*******************************************************************************
* Copyright (c) 2012, 2015 Wind River Systems, 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:
* Wind River Systems - initial API and implementation
*******************************************************************************/
package org.eclipse.tcf.te.launch.ui.tabs.filetransfers;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.Path;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.jface.fieldassist.ControlDecoration;
import org.eclipse.jface.fieldassist.FieldDecoration;
import org.eclipse.jface.fieldassist.FieldDecorationRegistry;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.CheckStateChangedEvent;
import org.eclipse.jface.viewers.CheckboxCellEditor;
import org.eclipse.jface.viewers.CheckboxTableViewer;
import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.jface.viewers.ColumnPixelData;
import org.eclipse.jface.viewers.ColumnViewerToolTipSupport;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.EditingSupport;
import org.eclipse.jface.viewers.ICheckStateListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TableLayout;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.swt.SWT;
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.Listener;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.tcf.te.launch.core.persistence.filetransfer.FileTransfersPersistenceDelegate;
import org.eclipse.tcf.te.launch.core.persistence.launchcontext.LaunchContextsPersistenceDelegate;
import org.eclipse.tcf.te.launch.ui.interfaces.ILaunchConfigurationTabFormPart;
import org.eclipse.tcf.te.launch.ui.nls.Messages;
import org.eclipse.tcf.te.runtime.model.interfaces.IModelNode;
import org.eclipse.tcf.te.runtime.services.interfaces.filetransfer.IFileTransferItem;
import org.eclipse.tcf.te.ui.forms.parts.AbstractTableSection;
import org.eclipse.tcf.te.ui.swt.listener.AbstractDecorationCellPaintListener;
import org.eclipse.ui.forms.IManagedForm;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.Section;
/**
* AbstractFileTransferSection
*/
public abstract class AbstractFileTransferSection extends AbstractTableSection implements ILaunchConfigurationTabFormPart {
protected ControlDecoration controlDecoration;
protected IModelNode launchContext = null;
protected static final String PROPERTY_VALIDATION_RESULT = "validation_result.transient"; //$NON-NLS-1$
/**
* Constructor.
* @param form
* @param parent
*/
public AbstractFileTransferSection(IManagedForm form, Composite parent) {
super(form, parent, SWT.NONE, new String[]{
Messages.FileTransferSection_add_button,
Messages.FileTransferSection_edit_button,
Messages.FileTransferSection_delete_button,
null,
Messages.FileTransferSection_up_button,
Messages.FileTransferSection_down_button});
}
/* (non-Javadoc)
* @see org.eclipse.tcf.te.launch.ui.interfaces.ILaunchConfigurationTabFormPart#initializeFrom(org.eclipse.debug.core.ILaunchConfiguration)
*/
@Override
public void initializeFrom(ILaunchConfiguration configuration) {
IFileTransferItem[] items = FileTransfersPersistenceDelegate.getFileTransfers(configuration);
getTablePart().getViewer().setInput(items);
if (items != null && items.length > 0) {
((TableViewer)getTablePart().getViewer()).setSelection(new StructuredSelection(items[0]), true);
}
launchContext = LaunchContextsPersistenceDelegate.getFirstLaunchContext(configuration);
}
/* (non-Javadoc)
* @see org.eclipse.tcf.te.launch.ui.interfaces.ILaunchConfigurationTabFormPart#performApply(org.eclipse.debug.core.ILaunchConfigurationWorkingCopy)
*/
@Override
public void performApply(ILaunchConfigurationWorkingCopy wc) {
FileTransfersPersistenceDelegate.setFileTransfers(wc, (IFileTransferItem[])getTablePart().getViewer().getInput());
}
/* (non-Javadoc)
* @see org.eclipse.tcf.te.launch.ui.interfaces.ILaunchConfigurationTabFormPart#isValid(org.eclipse.debug.core.ILaunchConfiguration)
*/
@Override
public boolean isValid(ILaunchConfiguration configuration) {
return validateInputList();
}
protected abstract boolean validateInputList();
/* (non-Javadoc)
* @see org.eclipse.tcf.te.ui.forms.parts.AbstractSection#createClient(org.eclipse.ui.forms.widgets.Section, org.eclipse.ui.forms.widgets.FormToolkit)
*/
@Override
protected void createClient(Section section, FormToolkit toolkit) {
Assert.isNotNull(section);
Assert.isNotNull(toolkit);
section.setText(Messages.FileTransferSection_title);
section.setDescription(Messages.FileTransferSection_description);
if (section.getParent().getLayout() instanceof GridLayout) {
section.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_FILL, SWT.CENTER, true, true));
}
Composite client = createClientContainer(section, 2, toolkit);
client.setBackground(section.getBackground());
section.setClient(client);
createPartControl((Composite)section.getClient(), SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.SINGLE | SWT.FULL_SELECTION, 2, toolkit);
// Mark the control update as completed now
setIsUpdating(false);
}
@Override
protected TableViewer createTableViewer(Composite parent, int style) {
return new CheckboxTableViewer(new Table(parent, style | SWT.CHECK));
}
@Override
protected void configureTableViewer(TableViewer viewer) {
super.configureTableViewer(viewer);
ColumnViewerToolTipSupport.enableFor(viewer);
final Table table = viewer.getTable();
if (viewer instanceof CheckboxTableViewer) {
((CheckboxTableViewer)viewer).setCheckStateProvider(new FileTransferCheckStateProvider());
((CheckboxTableViewer)viewer).addCheckStateListener(new ICheckStateListener() {
@Override
public void checkStateChanged(CheckStateChangedEvent event) {
if (event.getElement() instanceof IFileTransferItem) {
IFileTransferItem item = (IFileTransferItem)event.getElement();
item.setProperty(IFileTransferItem.PROPERTY_ENABLED, event.getChecked());
getManagedForm().dirtyStateChanged();
}
}
});
}
TableViewerColumn tvEnableCol = new TableViewerColumn(viewer, SWT.NONE);
final TableColumn colEnable = tvEnableCol.getColumn();
colEnable.setResizable(false);
tvEnableCol.setLabelProvider(new ColumnLabelProvider() {
@Override
public String getText(Object element) {
return null;
}
});
TableViewerColumn tvHostCol = new TableViewerColumn(viewer, SWT.NONE);
final TableColumn colHost = tvHostCol.getColumn();
colHost.setText(Messages.FileTransferSection_host_column);
colHost.setResizable(true);
tvHostCol.setLabelProvider(new ColumnLabelProvider() {
@SuppressWarnings("unchecked")
@Override
public String getToolTipText(Object element) {
if (element instanceof IFileTransferItem) {
IFileTransferItem item = (IFileTransferItem)element;
Map<String,String> invalid = (Map<String,String>)item.getProperty(PROPERTY_VALIDATION_RESULT);
if (invalid != null && invalid.containsKey(IFileTransferItem.PROPERTY_HOST)) {
return invalid.get(IFileTransferItem.PROPERTY_HOST);
}
String host = item.getStringProperty(IFileTransferItem.PROPERTY_HOST);
return host != null ? new Path(host).toOSString() : host;
}
return super.getText(element);
}
@Override
public String getText(Object element) {
if (element instanceof IFileTransferItem) {
IFileTransferItem item = (IFileTransferItem)element;
String host = item.getStringProperty(IFileTransferItem.PROPERTY_HOST);
return host != null ? new Path(host).toOSString() : host;
}
return super.getText(element);
}
});
TableViewerColumn tvDirCol = new TableViewerColumn(viewer, SWT.NONE);
final TableColumn colDir = tvDirCol.getColumn();
colDir.setResizable(false);
colDir.setAlignment(SWT.CENTER);
tvDirCol.setLabelProvider(new ColumnLabelProvider() {
@Override
public String getToolTipText(Object element) {
if (element instanceof IFileTransferItem) {
IFileTransferItem item = (IFileTransferItem)element;
switch (item.getIntProperty(IFileTransferItem.PROPERTY_DIRECTION)) {
case IFileTransferItem.TARGET_TO_HOST:
return Messages.FileTransferSection_toHost_tooltip;
default:
return Messages.FileTransferSection_toTarget_tooltip;
}
}
return super.getToolTipText(element);
}
@Override
public String getText(Object element) {
if (element instanceof IFileTransferItem) {
IFileTransferItem item = (IFileTransferItem)element;
switch (item.getIntProperty(IFileTransferItem.PROPERTY_DIRECTION)) {
case IFileTransferItem.TARGET_TO_HOST:
return Messages.FileTransferSection_toHost_text;
default:
return Messages.FileTransferSection_toTarget_text;
}
}
return super.getText(element);
}
});
tvDirCol.setEditingSupport(new EditingSupport(tvDirCol.getViewer()) {
@Override
protected void setValue(Object element, Object value) {
if (element instanceof IFileTransferItem) {
IFileTransferItem item = (IFileTransferItem)element;
item.setProperty(IFileTransferItem.PROPERTY_DIRECTION,
Boolean.parseBoolean(value.toString()) ? IFileTransferItem.HOST_TO_TARGET : IFileTransferItem.TARGET_TO_HOST);
getManagedForm().dirtyStateChanged();
getViewer().refresh();
}
}
@Override
protected Object getValue(Object element) {
if (element instanceof IFileTransferItem) {
IFileTransferItem item = (IFileTransferItem)element;
return Boolean.valueOf(item.getIntProperty(IFileTransferItem.PROPERTY_DIRECTION) != IFileTransferItem.TARGET_TO_HOST);
}
return null;
}
@Override
protected CellEditor getCellEditor(Object element) {
return new CheckboxCellEditor();
}
@Override
protected boolean canEdit(Object element) {
return true;
}
});
TableViewerColumn tvTargetCol = new TableViewerColumn(viewer, SWT.NONE);
final TableColumn colTarget = tvTargetCol.getColumn();
colTarget.setText(Messages.FileTransferSection_target_column);
colTarget.setResizable(true);
tvTargetCol.setLabelProvider(new ColumnLabelProvider() {
@SuppressWarnings("unchecked")
@Override
public String getToolTipText(Object element) {
if (element instanceof IFileTransferItem) {
IFileTransferItem item = (IFileTransferItem)element;
Map<String,String> invalid = (Map<String,String>)item.getProperty(PROPERTY_VALIDATION_RESULT);
if (invalid != null && invalid.containsKey(IFileTransferItem.PROPERTY_TARGET_STRING)) {
return invalid.get(IFileTransferItem.PROPERTY_TARGET_STRING);
}
return item.getStringProperty(IFileTransferItem.PROPERTY_TARGET_STRING);
}
return super.getText(element);
}
@Override
public String getText(Object element) {
if (element instanceof IFileTransferItem) {
IFileTransferItem item = (IFileTransferItem)element;
return item.getStringProperty(IFileTransferItem.PROPERTY_TARGET_STRING);
}
return super.getText(element);
}
});
TableViewerColumn tvOptionCol = new TableViewerColumn(viewer, SWT.NONE);
final TableColumn colOption = tvOptionCol.getColumn();
colOption.setText(Messages.FileTransferSection_options_column);
colOption.setResizable(true);
tvOptionCol.setLabelProvider(new ColumnLabelProvider() {
@Override
public String getToolTipText(Object element) {
if (element instanceof IFileTransferItem) {
IFileTransferItem item = (IFileTransferItem)element;
return item.getStringProperty(IFileTransferItem.PROPERTY_OPTIONS);
}
return super.getText(element);
}
@Override
public String getText(Object element) {
if (element instanceof IFileTransferItem) {
IFileTransferItem item = (IFileTransferItem)element;
return item.getStringProperty(IFileTransferItem.PROPERTY_OPTIONS);
}
return super.getText(element);
}
});
TableLayout tableLayout = new TableLayout();
tableLayout.addColumnData(new ColumnPixelData(30, true));
tableLayout.addColumnData(new ColumnPixelData(200, true));
tableLayout.addColumnData(new ColumnPixelData(30, true));
tableLayout.addColumnData(new ColumnPixelData(200, true));
tableLayout.addColumnData(new ColumnPixelData(100, true));
table.setLayout(tableLayout);
GridData data = new GridData(GridData.FILL_BOTH | GridData.VERTICAL_ALIGN_BEGINNING);
table.setLayoutData(data);
table.setHeaderVisible(true);
table.setLinesVisible(true);
table.addListener(SWT.Resize, new Listener() {
@Override
public void handleEvent(Event event) {
int width = table.getSize().x - 4 - colEnable.getWidth() - colHost.getWidth() - colDir.getWidth() - colTarget.getWidth();
colOption.setWidth(Math.max(width, 100));
}
});
colHost.addListener(SWT.Resize, new Listener() {
@Override
public void handleEvent(Event event) {
int colWidth = colHost.getWidth();
if (colWidth < 100) {
event.doit = false;
colHost.setWidth(100);
colWidth = 100;
}
int width = table.getSize().x - 4 - colWidth - colEnable.getWidth() - colDir.getWidth() - colTarget.getWidth();
colOption.setWidth(Math.max(width, 100));
}
});
colTarget.addListener(SWT.Resize, new Listener() {
@Override
public void handleEvent(Event event) {
int colWidth = colTarget.getWidth();
if (colWidth < 100) {
event.doit = false;
colTarget.setWidth(100);
colWidth = 100;
}
int width = table.getSize().x - 4 - colWidth - colEnable.getWidth() - colHost.getWidth() - colDir.getWidth();
colOption.setWidth(Math.max(width, 100));
}
});
@SuppressWarnings("unused")
AbstractDecorationCellPaintListener cpl = new AbstractDecorationCellPaintListener(table, 1, 3) {
@SuppressWarnings("unchecked")
@Override
protected int getDecorationState(Object data, int columnIndex) {
if (data instanceof IFileTransferItem) {
IFileTransferItem item = (IFileTransferItem)data;
if (item.getBooleanProperty(IFileTransferItem.PROPERTY_ENABLED)) {
Map<String,String> invalid = (Map<String,String>)item.getProperty(PROPERTY_VALIDATION_RESULT);
if (invalid != null) {
switch (columnIndex) {
case 1:
if (invalid.containsKey(IFileTransferItem.PROPERTY_HOST)) {
return STATE_ERROR;
}
break;
case 3:
if (invalid.containsKey(IFileTransferItem.PROPERTY_TARGET_STRING)) {
return STATE_ERROR;
}
break;
}
}
}
}
return STATE_NONE;
}
};
viewer.setContentProvider(new FileTransferContentProvider());
viewer.addSelectionChangedListener(new ISelectionChangedListener() {
@Override
public void selectionChanged(SelectionChangedEvent event) {
initializeButtonsEnablement();
}
});
doCreateControlDecoration(table);
configureControlDecoration(getControlDecoration());
}
/**
* Creates a new instance of a {@link ControlDecoration} object associated with
* the given control. The method is called after the control has been created.
*
* @param control The control. Must not be <code>null</code>.
* @return The control decoration object instance.
*/
public ControlDecoration doCreateControlDecoration(Control control) {
Assert.isNotNull(control);
controlDecoration = new ControlDecoration(control, SWT.TOP | SWT.LEFT);
return controlDecoration;
}
/**
* Returns the control decoration.
*
* @return The control decoration instance or <code>null</code> if not yet created.
*/
public final ControlDecoration getControlDecoration() {
return controlDecoration;
}
/**
* Configure the given control decoration.
*
* @param decoration The control decoration. Must not be <code>null</code>.
*/
protected void configureControlDecoration(ControlDecoration decoration) {
Assert.isNotNull(decoration);
decoration.setShowOnlyOnFocus(false);
}
/**
* Updates the control decoration to represent the given message and message type.
* If the message is <code>null</code> or the message type is IMessageProvider.NONE,
* no decoration will be shown.
*
* @param message The message.
* @param messageType The message type.
*/
public void updateControlDecoration(String message, int messageType) {
if (getControlDecoration() != null) {
// The description is the same as the message
getControlDecoration().setDescriptionText(message);
// The icon depends on the message type
FieldDecorationRegistry registry = FieldDecorationRegistry.getDefault();
// Determine the id of the decoration to show
String decorationId = FieldDecorationRegistry.DEC_INFORMATION;
if (messageType == IMessageProvider.ERROR) {
decorationId = FieldDecorationRegistry.DEC_ERROR;
} else if (messageType == IMessageProvider.WARNING) {
decorationId = FieldDecorationRegistry.DEC_WARNING;
}
// Get the field decoration
FieldDecoration fieldDeco = registry.getFieldDecoration(decorationId);
if (fieldDeco != null) {
getControlDecoration().setImage(fieldDeco.getImage());
}
if (message == null || messageType == IMessageProvider.NONE) {
getControlDecoration().hide();
}
else {
getControlDecoration().show();
}
}
}
protected List<IFileTransferItem> getInputList() {
return new ArrayList<IFileTransferItem>(Arrays.asList((IFileTransferItem[])getTablePart().getViewer().getInput()));
}
protected void setInputList(List<IFileTransferItem> list) {
getTablePart().getViewer().setInput(list.toArray(new IFileTransferItem[list.size()]));
}
@Override
public void doubleClick(DoubleClickEvent event) {
onButtonEditClick();
}
@Override
protected void onButtonSelected(Button button) {
int selIndex = ((TableViewer)getTablePart().getViewer()).getTable().getSelectionIndex();
List<IFileTransferItem> list = getInputList();
switch (((Integer)button.getData()).intValue()) {
case 0: // Add
onButtonAddClick();
break;
case 1: // Edit
onButtonEditClick();
break;
case 2: // Delete
list.remove(selIndex);
setInputList(list);
if (!list.isEmpty()) {
((TableViewer)getTablePart().getViewer()).setSelection(
new StructuredSelection(list.get(selIndex < list.size() ? selIndex : list.size()-1)), true);
}
break;
case 4: // Up
list.add(selIndex-1, list.remove(selIndex));
setInputList(list);
((TableViewer)getTablePart().getViewer()).setSelection(new StructuredSelection(list.get(selIndex-1)), true);
break;
case 5: // Down
list.add(selIndex+1, list.remove(selIndex));
setInputList(list);
((TableViewer)getTablePart().getViewer()).setSelection(new StructuredSelection(list.get(selIndex+1)), true);
break;
}
validateInputList();
getManagedForm().dirtyStateChanged();
}
protected abstract void onButtonAddClick();
protected abstract void onButtonEditClick();
/* (non-Javadoc)
* @see org.eclipse.tcf.te.ui.forms.parts.AbstractTableSection#initializeButtonsEnablement()
*/
@Override
protected void initializeButtonsEnablement() {
ISelection selection = ((TableViewer)getTablePart().getViewer()).getSelection();
boolean singleSelection = selection instanceof IStructuredSelection && ((IStructuredSelection)selection).size() == 1;
int selIndex = ((TableViewer)getTablePart().getViewer()).getTable().getSelectionIndex();
int count = ((TableViewer)getTablePart().getViewer()).getTable().getItemCount();
getTablePart().getButton(0).setEnabled(getTablePart().isEnabled());
getTablePart().getButton(1).setEnabled(getTablePart().isEnabled() && singleSelection);
getTablePart().getButton(2).setEnabled(getTablePart().isEnabled() && singleSelection);
getTablePart().getButton(4).setEnabled(getTablePart().isEnabled() && singleSelection && selIndex > 0);
getTablePart().getButton(5).setEnabled(getTablePart().isEnabled() && singleSelection && selIndex < count-1);
}
}