/*
*
* * Copyright (C) 2015 CS SI
* *
* * This program is free software; you can redistribute it and/or modify it
* * under the terms of the GNU General Public License as published by the Free
* * Software Foundation; either version 3 of the License, or (at your option)
* * any later version.
* * This program is distributed in the hope that it will be useful, but WITHOUT
* * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* * more details.
* *
* * You should have received a copy of the GNU General Public License along
* * with this program; if not, see http://www.gnu.org/licenses/
*
*/
package org.esa.snap.ui.tooladapter.model;
import com.bc.ceres.binding.*;
import com.bc.ceres.binding.converters.ArrayConverter;
import com.bc.ceres.binding.converters.FloatConverter;
import com.bc.ceres.binding.converters.IntegerConverter;
import com.bc.ceres.swing.binding.BindingContext;
import org.apache.commons.collections.BidiMap;
import org.apache.commons.collections.bidimap.DualHashBidiMap;
import org.esa.snap.core.gpf.annotations.ParameterDescriptorFactory;
import org.esa.snap.core.gpf.descriptor.PropertyAttributeException;
import org.esa.snap.core.gpf.descriptor.TemplateParameterDescriptor;
import org.esa.snap.core.gpf.descriptor.ToolAdapterOperatorDescriptor;
import org.esa.snap.core.gpf.descriptor.ToolParameterDescriptor;
import org.esa.snap.core.gpf.operators.tooladapter.ToolAdapterConstants;
import org.esa.snap.core.gpf.ui.OperatorParameterSupport;
import org.esa.snap.core.util.StringUtils;
import org.esa.snap.rcp.util.Dialogs;
import org.esa.snap.ui.AbstractDialog;
import org.esa.snap.ui.AppContext;
import org.esa.snap.ui.UIUtils;
import org.esa.snap.ui.tool.ToolButtonFactory;
import org.esa.snap.ui.tooladapter.dialogs.TemplateParameterEditorDialog;
import org.esa.snap.ui.tooladapter.dialogs.ToolParameterEditorDialog;
import org.openide.util.NbBundle;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.filechooser.FileFilter;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
import java.awt.*;
import java.awt.event.*;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
/**
* Table holding the operator parameter descriptors
*
* @author Ramona Manda
* @author Cosmin Cara
*/
@NbBundle.Messages({
"Column_Name_Text=Name",
"Column_Description_Text=Description",
"Column_Label_Text=Label",
"Column_DataType_Text=Data type",
"Column_DefaultValue_Text=Default value",
"Type_TemplateFileClass_Text=Template Parameter",
"Type_BeforeTemplateFileClass_Text=Template Before",
"Type_AfterTemplateFileClass_Text=Template After",
"Type_RegularFileClass_Text=File",
"Type_FolderClass_Text=Folder",
"Type_FileListClass_Text=File List",
"Type_StringClass_Text=String",
"Type_IntegerClass_Text=Integer",
"Type_ListClass_Text=List",
"Type_BooleanClass_Text=Boolean",
"Type_FloatClass_Text=Decimal",
"Type_ProductList_Text=Product List"
})
public class OperatorParametersTable extends JTable {
private static final Logger logger = Logger.getLogger(OperatorParametersTable.class.getName());
private static String[] columnNames = {"", "Name", "Description", "Label", "Data type", "Default value", ""};
private static String[] columnsMembers = {"del", "name", "description", "label", "dataType", "defaultValue", "edit"};
private static int[] widths = {27, 100, 200, 80, 100, 249, 30};
private static final BidiMap typesMap = new DualHashBidiMap();
static {
typesMap.put(Bundle.Type_TemplateFileClass_Text(), CustomParameterClass.TemplateFileClass);
typesMap.put(Bundle.Type_BeforeTemplateFileClass_Text(), CustomParameterClass.BeforeTemplateFileClass);
typesMap.put(Bundle.Type_AfterTemplateFileClass_Text(), CustomParameterClass.AfterTemplateFileClass);
typesMap.put(Bundle.Type_RegularFileClass_Text(), CustomParameterClass.RegularFileClass);
typesMap.put(Bundle.Type_FolderClass_Text(), CustomParameterClass.FolderClass);
typesMap.put(Bundle.Type_FileListClass_Text(), CustomParameterClass.FileListClass);
typesMap.put(Bundle.Type_StringClass_Text(), CustomParameterClass.StringClass);
typesMap.put(Bundle.Type_IntegerClass_Text(), CustomParameterClass.IntegerClass);
typesMap.put(Bundle.Type_ListClass_Text(), CustomParameterClass.ListClass);
typesMap.put(Bundle.Type_BooleanClass_Text(), CustomParameterClass.BooleanClass);
typesMap.put(Bundle.Type_FloatClass_Text(), CustomParameterClass.FloatClass);
}
private ToolAdapterOperatorDescriptor operator = null;
private Map<ToolParameterDescriptor, PropertyMemberUIWrapper> propertiesValueUIDescriptorMap;
private MultiRenderer tableRenderer;
private BindingContext context;
private final TableCellRenderer dataTypesComboCellRenderer;
private final AppContext appContext;
private final DefaultTableCellRenderer labelTypeCellRenderer;
private JComboBox cellDefaultValueComboBox;
private JCheckBox cellDefaultValueCheckBox;
private JScrollPane cellDefaultValueList;
private FilePanel cellDefaultValueFile;
private JComboBox cellDataTypesComboBox;
private JTextField cellTextComponent;
private JComponent currentDisplayedCellComponent;
private int cellComponentColumnIndex;
private int cellComponentRowIndex;
public OperatorParametersTable(ToolAdapterOperatorDescriptor operator, AppContext appContext) {
this.operator = operator;
this.appContext = appContext;
propertiesValueUIDescriptorMap = new HashMap<>();
dataTypesComboCellRenderer = new DefaultTableCellRenderer();
labelTypeCellRenderer = new DefaultTableCellRenderer();
labelTypeCellRenderer.setText(Bundle.Type_ProductList_Text());
List<ToolParameterDescriptor> data = operator.getToolParameterDescriptors();
PropertySet propertySet = new OperatorParameterSupport(operator).getPropertySet();
//if there is an exception in the line above, can be because the default value does not match the type
//TODO determine if (and which) param has a wrong type
context = new BindingContext(propertySet);
for (ToolParameterDescriptor paramDescriptor : data) {
if (paramDescriptor.getName().equals(ToolAdapterConstants.TOOL_SOURCE_PRODUCT_ID)) {
propertiesValueUIDescriptorMap.put(paramDescriptor, PropertyMemberUIWrapperFactory.buildEmptyPropertyWrapper());
} else {
propertiesValueUIDescriptorMap.put(paramDescriptor, PropertyMemberUIWrapperFactory.buildPropertyWrapper("defaultValue", paramDescriptor, operator, context, null));
}
}
tableRenderer = new MultiRenderer();
setModel(new OperatorParametersTableNewTableModel());
setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
for (int i = 0; i < widths.length; i++) {
getColumnModel().getColumn(i).setPreferredWidth(widths[i]);
}
this.putClientProperty("JComboBox.isTableCellEditor", Boolean.FALSE);
this.setRowHeight(20);
addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent event) {
int clickedColumn = columnAtPoint(event.getPoint());
int clickedRow = rowAtPoint(event.getPoint());
if (clickedColumn >= 0 && clickedRow >= 0 && isTableCellEditable(clickedRow, clickedColumn)) {
mouseClickOnCell(clickedColumn, clickedRow);
}
}
});
FocusListener focusListener = new FocusAdapter() {
@Override
public void focusLost(FocusEvent focusEvent) {
hideCurrentDisplayedCellComponent(focusEvent);
}
};
createCellDefaultValueList(focusListener);
createCellDefaultValueFileChooser(focusListener);
createCellDefaultValueCheckBox(focusListener);
createCellDefaultValueComboBox(focusListener);
createCellTextComponent(focusListener);
createCellDataTypesComponent();
resetCellComponentPosition();
}
private void createCellDefaultValueFileChooser(FocusListener focusListener) {
this.cellDefaultValueFile = new FilePanel();
this.cellDefaultValueFile.setBackground(Color.white);
this.cellDefaultValueFile.setOpaque(true);
this.cellDefaultValueFile.setVisible(false);
this.cellDefaultValueFile.addTextComponentFocusListener(focusListener);
this.cellDefaultValueFile.addBrowseButtonActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent event) {
ToolParameterDescriptor descriptor = operator.getToolParameterDescriptors().get(cellComponentRowIndex);
String parameterType = descriptor.getParameterType();
int selectionMode = JFileChooser.FILES_ONLY;
if (ToolAdapterConstants.FOLDER_PARAM_MASK.equals(parameterType)) {
selectionMode = JFileChooser.DIRECTORIES_ONLY;
}
FileFilter filter = null;
if (ToolAdapterConstants.TEMPLATE_PARAM_MASK.equals(parameterType) || ToolAdapterConstants.TEMPLATE_BEFORE_MASK.equals(parameterType)
|| ToolAdapterConstants.TEMPLATE_AFTER_MASK.equals(parameterType)) {
filter = new FileFilter() {
@Override
public boolean accept(File file) {
return file.isDirectory() || file.getName().toLowerCase().endsWith(".vm");
}
@Override
public String getDescription() {
return "*.vm files";
}
};
}
File selectedFile = cellDefaultValueFile.showFileChooserDialog(selectionMode, filter);
if (selectedFile != null) {
descriptor.setDefaultValue(selectedFile.getAbsolutePath());
fireTableRowsChanged();
}
}
});
}
private void createCellDefaultValueList(FocusListener focusListener) {
JList list = new JList();
list.addFocusListener(focusListener);
this.cellDefaultValueList = new JScrollPane(list);
this.cellDefaultValueList.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
this.cellDefaultValueList.setBorder(new EmptyBorder(0, 0, 0, 0));
this.cellDefaultValueList.setOpaque(true);
this.cellDefaultValueList.setVisible(false);
this.cellDefaultValueList.setBackground(Color.white);
this.cellDefaultValueList.addFocusListener(new FocusAdapter() {
@Override
public void focusGained(FocusEvent event) {
cellDefaultValueList.getViewport().getView().requestFocusInWindow();
}
});
}
private void createCellDefaultValueCheckBox(FocusListener focusListener) {
this.cellDefaultValueCheckBox = new JCheckBox();
this.cellDefaultValueCheckBox.setBackground(Color.white);
this.cellDefaultValueCheckBox.setOpaque(true);
this.cellDefaultValueCheckBox.setVisible(false);
this.cellDefaultValueCheckBox.addFocusListener(focusListener);
}
private void createCellDefaultValueComboBox(FocusListener focusListener) {
this.cellDefaultValueComboBox = new JComboBox();
this.cellDefaultValueComboBox.setOpaque(true);
this.cellDefaultValueComboBox.setVisible(false);
this.cellDefaultValueComboBox.setBorder(new EmptyBorder(0, 0, 0, 0));
this.cellDefaultValueComboBox.addFocusListener(focusListener);
}
private void createCellDataTypesComponent() {
this.cellDataTypesComboBox = new JComboBox(typesMap.keySet().toArray());
this.cellDataTypesComboBox.setOpaque(true);
this.cellDataTypesComboBox.setVisible(false);
this.cellDataTypesComboBox.setBorder(new EmptyBorder(0, 0, 0, 0));
this.cellDataTypesComboBox.addActionListener(ev -> {
String typeName = (String) cellDataTypesComboBox.getSelectedItem();
cellDataTypeChanged(typeName, this.cellComponentRowIndex, this.cellComponentColumnIndex);
});
this.cellDataTypesComboBox.addFocusListener(new FocusAdapter() {
@Override
public void focusLost(FocusEvent focusEvent) {
hideCurrentDisplayedCellComponent();
}
});
}
private void createCellTextComponent(FocusListener focusListener) {
this.cellTextComponent = new JTextField();
this.cellTextComponent.setOpaque(true);
this.cellTextComponent.setVisible(false);
this.cellTextComponent.setBorder(new EmptyBorder(0, 0, 0, 0));
this.cellTextComponent.addFocusListener(focusListener);
}
private void mouseClickOnCell(int clickedColumn, int clickedRow) {
if (clickedColumn == 0) {
if (canRemoveRow(clickedRow)) {
removeRow(clickedRow);
}
}
else if (clickedColumn == 6) {
showToolParameterEditorDialog(clickedRow);
} else if (clickedColumn == 4) {
showCellDataTypeComboBoxEditor(clickedColumn, clickedRow);
} else if (clickedColumn == 5) {
showCellDefaultValueComponent(clickedColumn, clickedRow);
} else if (clickedColumn == 1 || clickedColumn == 2 || clickedColumn == 3) {
showCellTextComponentEditor(clickedColumn, clickedRow);
}
}
private void showCellDefaultValueComponent(int clickedColumn, int clickedRow) {
ToolParameterDescriptor descriptor = this.operator.getToolParameterDescriptors().get(clickedRow);
String defaultValue = descriptor.getDefaultValue();
if (descriptor.getDataType() == String.class || descriptor.getDataType() == Integer.class || descriptor.getDataType() == Float.class) {
String[] valueSet = descriptor.getValueSet();
if (valueSet != null && valueSet.length > 0) {
DefaultComboBoxModel model = new DefaultComboBoxModel();
Object itemToSelect = null;
for (int i=0; i<valueSet.length; i++) {
model.addElement(valueSet[i]);
if (defaultValue != null && defaultValue.equals(valueSet[i])) {
itemToSelect = valueSet[i];
}
}
model.setSelectedItem(itemToSelect);
this.cellDefaultValueComboBox.setModel(model);
setCurrentCellComponentEditor(clickedColumn, clickedRow, this.cellDefaultValueComboBox);
} else {
this.cellTextComponent.setText(defaultValue);
setCurrentCellComponentEditor(clickedColumn, clickedRow, this.cellTextComponent);
}
} else if (descriptor.getDataType() == Boolean.class) {
this.cellDefaultValueCheckBox.setSelected(Boolean.parseBoolean(defaultValue));
setCurrentCellComponentEditor(clickedColumn, clickedRow, this.cellDefaultValueCheckBox);
} else if (descriptor.getDataType() == File.class) {
this.cellDefaultValueFile.setText(defaultValue);
setCurrentCellComponentEditor(clickedColumn, clickedRow, this.cellDefaultValueFile);
} else if (descriptor.getDataType() == String[].class) {
showCellDefaultValueList(clickedColumn, clickedRow);
}
}
private void showCellDefaultValueList(int clickedColumn, int clickedRow) {
ToolParameterDescriptor descriptor = this.operator.getToolParameterDescriptors().get(clickedRow);
String defaultValue = descriptor.getDefaultValue();
String[] valueSet = descriptor.getValueSet();
JList list = (JList)this.cellDefaultValueList.getViewport().getView();
DefaultListModel model = new DefaultListModel();
java.util.List<Integer> selectedIndices = new ArrayList<Integer>();
if (valueSet != null && valueSet.length > 0) {
for (int i=0; i<valueSet.length; i++) {
model.addElement(valueSet[i]);
}
String[] itemsToSelect = null;
if (!StringUtils.isNullOrEmpty(defaultValue)) {
itemsToSelect = defaultValue.split(ArrayConverter.SEPARATOR);
}
if (itemsToSelect != null && itemsToSelect.length > 0) {
for (int i=0; i<model.getSize(); i++) {
Object item = model.getElementAt(i);
for (int k=0; k<itemsToSelect.length; k++) {
if (item.equals(itemsToSelect[k])) {
selectedIndices.add(i);
break;
}
}
}
}
}
list.setModel(model);
int[] indices = new int[selectedIndices.size()];
for (int i=0; i<selectedIndices.size(); i++) {
indices[i] = selectedIndices.get(i).intValue();
}
list.setSelectedIndices(indices);
setCurrentCellComponentEditor(clickedColumn, clickedRow, this.cellDefaultValueList);
}
@Override
public void doLayout() {
super.doLayout();
if (hasValidCellComponent()) {
Rectangle tableCellBounds = getCellRect(this.cellComponentRowIndex, this.cellComponentColumnIndex, false);
this.currentDisplayedCellComponent.setBounds(tableCellBounds.x, tableCellBounds.y, tableCellBounds.width, tableCellBounds.height);
}
}
private boolean hasValidCellComponent() {
return (this.currentDisplayedCellComponent != null) && (this.cellComponentColumnIndex >= 0) && (this.cellComponentRowIndex >= 0);
}
private final void showCellDataTypeComboBoxEditor(int columnIndex, int rowIndex) {
Object cellValue = getValueAt(rowIndex, columnIndex);
String cellValueAsString = (cellValue == null) ? "" : cellValue.toString();
ActionListener[] listeners = this.cellDataTypesComboBox.getActionListeners();
for (int i=0; i<listeners.length; i++) {
this.cellDataTypesComboBox.removeActionListener(listeners[i]);
}
this.cellDataTypesComboBox.setSelectedItem(cellValueAsString);
for (int i=0; i<listeners.length; i++) {
this.cellDataTypesComboBox.addActionListener(listeners[i]);
}
setCurrentCellComponentEditor(columnIndex, rowIndex, this.cellDataTypesComboBox);
}
private void showCellTextComponentEditor(int columnIndex, int rowIndex) {
Object cellValue = getValueAt(rowIndex, columnIndex);
String cellValueAsString = (cellValue == null) ? "" : cellValue.toString();
this.cellTextComponent.setText(cellValueAsString);
setCurrentCellComponentEditor(columnIndex, rowIndex, this.cellTextComponent);
}
private final void setCurrentCellComponentEditor(int columnIndex, int rowIndex, JComponent cellComponent) {
if (this.currentDisplayedCellComponent != null && cellComponent != this.currentDisplayedCellComponent) {
this.currentDisplayedCellComponent.setVisible(false);
remove(this.currentDisplayedCellComponent);
fireTableRowsChanged();
}
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
currentDisplayedCellComponent = cellComponent;
cellComponentColumnIndex = columnIndex;
cellComponentRowIndex = rowIndex;
add(currentDisplayedCellComponent);
Rectangle tableCellBounds = getCellRect(cellComponentRowIndex, cellComponentColumnIndex, false);
currentDisplayedCellComponent.setBounds(tableCellBounds.x, tableCellBounds.y, tableCellBounds.width, tableCellBounds.height);
currentDisplayedCellComponent.setVisible(true);
currentDisplayedCellComponent.requestFocusInWindow();
}
});
}
private void hideCurrentDisplayedCellComponent(FocusEvent focusEvent) {
if (hasValidCellComponent()) {
ToolParameterDescriptor descriptor = operator.getToolParameterDescriptors().get(this.cellComponentRowIndex);
if (this.currentDisplayedCellComponent instanceof JTextField) {
String cellText = ((JTextField)this.currentDisplayedCellComponent).getText();
if (this.cellComponentColumnIndex == 1) {
setParameterNameAt(cellText, this.cellComponentRowIndex, this.cellComponentColumnIndex);
} else if (this.cellComponentColumnIndex == 2) {
descriptor.setDescription(cellText);
} else if (this.cellComponentColumnIndex == 3) {
descriptor.setLabel(cellText);
} else if (this.cellComponentColumnIndex == 5) {
descriptor.setDefaultValue(cellText);
}
} else if (this.currentDisplayedCellComponent instanceof JCheckBox) {
boolean isSelected = ((JCheckBox)this.currentDisplayedCellComponent).isSelected();
if (this.cellComponentColumnIndex == 5) {
descriptor.setDefaultValue(Boolean.toString(isSelected));
}
} else if (this.currentDisplayedCellComponent instanceof JComboBox) {
if (this.cellComponentColumnIndex == 5) {
String selectedItem = (String) ((JComboBox)this.currentDisplayedCellComponent).getSelectedItem();
descriptor.setDefaultValue(selectedItem);
}
} else if (this.currentDisplayedCellComponent instanceof FilePanel) {
if (this.cellComponentColumnIndex == 5) {
String filePath = ((FilePanel)this.currentDisplayedCellComponent).getText();
descriptor.setDefaultValue(filePath);
}
} else if ((this.currentDisplayedCellComponent instanceof JList) || (this.currentDisplayedCellComponent instanceof JScrollPane)) {
if (this.cellComponentColumnIndex == 5) {
JList list = null;
if (this.currentDisplayedCellComponent instanceof JList) {
list = (JList)this.currentDisplayedCellComponent;
} else {
JScrollPane scrollPane = (JScrollPane)this.currentDisplayedCellComponent;
list = (JList)scrollPane.getViewport().getView();
}
int[] indices = list.getSelectedIndices();
String defaultValue = "";
for (int i=0; i<indices.length; i++) {
if (i > 0) {
defaultValue += ",";
}
defaultValue += (String)list.getModel().getElementAt(indices[i]);
}
descriptor.setDefaultValue(defaultValue);
}
}
hideCurrentDisplayedCellComponent();
}
}
private void hideCurrentDisplayedCellComponent() {
remove(this.currentDisplayedCellComponent);
this.currentDisplayedCellComponent.setVisible(false);
resetCellComponentPosition();
requestFocusInWindow();
this.currentDisplayedCellComponent = null;
fireTableRowsChanged();
}
private void resetCellComponentPosition() {
this.cellComponentColumnIndex = -1;
this.cellComponentRowIndex = -1;
}
public void stopVariablesTableEditing() {
if (getEditingRow() >= 0 && getEditingColumn() >= 0) {
getCellEditor(getEditingRow(), getEditingColumn()).stopCellEditing();
}
}
private void removeRow(int rowIndex) {
ToolParameterDescriptor descriptor = operator.getToolParameterDescriptors().get(rowIndex);
operator.removeParamDescriptor(descriptor);
fireTableRowsChanged();
}
private boolean canRemoveRow(int rowIndex) {
ToolParameterDescriptor descriptor = operator.getToolParameterDescriptors().get(rowIndex);
String descriptorName = descriptor.getName();
return !ToolAdapterConstants.TOOL_SOURCE_PRODUCT_ID.equals(descriptorName) &&
!ToolAdapterConstants.TOOL_SOURCE_PRODUCT_FILE.equals(descriptorName) &&
!ToolAdapterConstants.TOOL_TARGET_PRODUCT_FILE.equals(descriptorName);
}
private boolean isTableCellEditable(int rowIndex, int columnIndex) {
ToolParameterDescriptor descriptor = operator.getToolParameterDescriptors().get(rowIndex);
String descriptorName = descriptor.getName();
if (ToolAdapterConstants.TOOL_SOURCE_PRODUCT_ID.equals(descriptorName) || ToolAdapterConstants.TOOL_SOURCE_PRODUCT_FILE.equals(descriptorName)) {
return false;
}
if (ToolAdapterConstants.TOOL_TARGET_PRODUCT_FILE.equals(descriptorName) && (columnIndex == 0 || columnIndex == 1 || columnIndex == 4 || columnIndex == 6)) {
return false;
}
return true;
}
public void addParameterToTable() {
String defaultParameterName = null;
int count = this.operator.getToolParameterDescriptors().size();
boolean canContinue = true;
int index = 0;
while (canContinue) {
index++;
canContinue = false;
defaultParameterName = "parameterName" + Integer.toString(index);
for (int i=0; i<count && !canContinue; i++) {
ToolParameterDescriptor param = this.operator.getToolParameterDescriptors().get(i);
if (param.getName().equals(defaultParameterName)) {
canContinue = true;
}
}
}
TemplateParameterDescriptor newParameter = new TemplateParameterDescriptor(defaultParameterName, String.class);
addParameterToTable(newParameter);
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
int rowIndex = operator.getToolParameterDescriptors().size() - 1;
showCellTextComponentEditor(1, rowIndex);
}
});
}
public void addParameterToTable(ToolParameterDescriptor param) {
try {
operator.getToolParameterDescriptors().add(param);
PropertyDescriptor propertyDescriptor = ParameterDescriptorFactory.convert(param, new ParameterDescriptorFactory().getSourceProductMap());
propertyDescriptor.setDefaultValue(param.getDefaultValue());
DefaultPropertySetDescriptor propertySetDescriptor = new DefaultPropertySetDescriptor();
propertySetDescriptor.addPropertyDescriptor(propertyDescriptor);
PropertyContainer container = PropertyContainer.createMapBacked(new HashMap<>(), propertySetDescriptor);
context.getPropertySet().addProperties(container.getProperties());
createDefaultComponent(param, propertyDescriptor);
fireTableRowsChanged();
} catch (Exception ex){
logger.warning(ex.getMessage());
}
}
private void rebuildEditorCell(ToolParameterDescriptor descriptor, Map<String, Object> attributes) {
PropertySet propertySet = context.getPropertySet();
Property actualProperty = propertySet.getProperty(descriptor.getName());
propertySet.removeProperty(actualProperty);
PropertyDescriptor propertyDescriptor = null;
try {
propertyDescriptor = ParameterDescriptorFactory.convert(descriptor, new ParameterDescriptorFactory().getSourceProductMap());
} catch (ConversionException ex) {
logger.warning(ex.getMessage());
}
propertyDescriptor.setDefaultValue(descriptor.getDefaultValue());
if (attributes != null && attributes.size() > 0) {
for (Map.Entry<String, Object> entry : attributes.entrySet()) {
propertyDescriptor.setAttribute(entry.getKey(), entry.getValue());
}
}
DefaultPropertySetDescriptor propertySetDescriptor = new DefaultPropertySetDescriptor();
propertySetDescriptor.addPropertyDescriptor(propertyDescriptor);
PropertyContainer container = PropertyContainer.createMapBacked(new HashMap<>(), propertySetDescriptor);
Object defaultValue = null;
if (descriptor.getDefaultValue() != null) {
defaultValue = descriptor.getDefaultTypedValue();
}
try {
container.getProperty(propertyDescriptor.getName()).setValue(defaultValue);
} catch (ValidationException ex) {
logger.warning(ex.getMessage());
}
propertySet.addProperties(container.getProperties());
createDefaultComponent(descriptor, propertyDescriptor);
fireTableRowsChanged();
}
private void createDefaultComponent(ToolParameterDescriptor descriptor, PropertyDescriptor propertyDescriptor) {
if (descriptor.getDataType() == String.class || descriptor.getDataType() == Integer.class || descriptor.getDataType() == Float.class) {
} else if (descriptor.getDataType() == Boolean.class) {
} else if (descriptor.getDataType() == String[].class) {
} else if (descriptor.getDataType() == File.class) {
} else {
this.propertiesValueUIDescriptorMap.put(descriptor, PropertyMemberUIWrapperFactory.buildPropertyWrapper("defaultValue", descriptor, operator, context, null));
}
}
@Override
public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
Component component = super.prepareRenderer(renderer, row, column);
ToolParameterDescriptor descriptor = operator.getToolParameterDescriptors().get(row);
switch (descriptor.getName()) {
case ToolAdapterConstants.TOOL_SOURCE_PRODUCT_ID:
case ToolAdapterConstants.TOOL_SOURCE_PRODUCT_FILE:
case ToolAdapterConstants.TOOL_TARGET_PRODUCT_ID:
case ToolAdapterConstants.TOOL_TARGET_PRODUCT_FILE:
component.setBackground(Color.lightGray);
break;
default:
component.setBackground(SystemColor.text);
component.setForeground(SystemColor.textText);
break;
}
return component;
}
@Override
public TableCellRenderer getCellRenderer(int row, int column) {
switch (column){
case 0:
case 5:
case 6:
return tableRenderer;
case 4:
ToolParameterDescriptor descriptor = operator.getToolParameterDescriptors().get(row);
if (descriptor.getName().equals(ToolAdapterConstants.TOOL_SOURCE_PRODUCT_ID)) {
return labelTypeCellRenderer;
} else {
return dataTypesComboCellRenderer;
}
default:
return super.getCellRenderer(row, column);
}
}
public BindingContext getBindingContext(){
return context;
}
public void showToolParameterEditorDialog(int rowIndex) {
ToolParameterDescriptor descriptor = operator.getToolParameterDescriptors().get(rowIndex);
if (!descriptor.isParameter() && descriptor.getDataType().equals(File.class)) {
try {
TemplateParameterEditorDialog editor = new TemplateParameterEditorDialog(appContext,(TemplateParameterDescriptor) descriptor, operator);
int returnCode = editor.show();
if (returnCode == AbstractDialog.ID_OK) {
rebuildEditorCell(descriptor, null);
}
}catch (Exception ex){
ex.printStackTrace();
Dialogs.showError(ex.getMessage());
}
} else {
ToolParameterEditorDialog editor = new ToolParameterEditorDialog(appContext, this.operator, descriptor);
int returnCode = editor.show();
if (returnCode == AbstractDialog.ID_OK) {
rebuildEditorCell(descriptor, null);
}
}
}
private void fireTableRowsChanged() {
((AbstractTableModel)getModel()).fireTableDataChanged();
}
public static boolean checkUniqueParameterName(ToolAdapterOperatorDescriptor operator, String parameterName, ToolParameterDescriptor descriptorToEdit) {
int count = operator.getToolParameterDescriptors().size();
for (int i=0; i<count; i++) {
ToolParameterDescriptor param = operator.getToolParameterDescriptors().get(i);
if (descriptorToEdit != param) {
if (param.getName().equals(parameterName)) {
Dialogs.showInformation("Duplicate parameter name.");
return false;
}
}
}
return true;
}
private void setParameterNameAt(String parameterName, int rowIndex, int columnIndex) {
ToolParameterDescriptor descriptor = this.operator.getToolParameterDescriptors().get(rowIndex);
if (!checkUniqueParameterName(this.operator, parameterName, descriptor)) {
return;
}
String oldName = descriptor.getName();
PropertySet propertySet = this.context.getPropertySet();
Property oldProperty = propertySet.getProperty(oldName);
Object defaultValue = (oldProperty == null) ? null : oldProperty.getValue();
descriptor.setName(parameterName);
//since the name is changed, the context must be changed also
propertySet.removeProperty(oldProperty);
try {
PropertyDescriptor propertyDescriptor = ParameterDescriptorFactory.convert(descriptor, new ParameterDescriptorFactory().getSourceProductMap());
if (defaultValue != null) {
String defaultValueAsString = ToolParameterEditorDialog.processDefaultValue(defaultValue);
descriptor.setDefaultValue(defaultValueAsString);
propertyDescriptor.setDefaultValue(defaultValue);
}
if (descriptor.getParameterType().equals(ToolAdapterConstants.FOLDER_PARAM_MASK)) {
propertyDescriptor.setAttribute("directory", true);
}
DefaultPropertySetDescriptor propertySetDescriptor = new DefaultPropertySetDescriptor();
propertySetDescriptor.addPropertyDescriptor(propertyDescriptor);
PropertyContainer container = PropertyContainer.createMapBacked(new HashMap<>(), propertySetDescriptor);
try {
container.setDefaultValues();
}catch (IllegalStateException ex){
logger.warning(ex.getMessage());
}
propertySet.addProperties(container.getProperties());
createDefaultComponent(descriptor, propertyDescriptor);
fireTableRowsChanged();
} catch (ConversionException e) {
logger.warning(e.getMessage());
Dialogs.showError(e.getMessage());
}
}
private void cellDataTypeChanged(Object aValue, int rowIndex, int columnIndex) {
ToolParameterDescriptor descriptor = operator.getToolParameterDescriptors().get(rowIndex);
if (descriptor.isTemplateParameter() &&
ToolAdapterConstants.TEMPLATE_PARAM_MASK.equals(descriptor.getParameterType()) &&
(((TemplateParameterDescriptor)descriptor).getTemplate() != null ||
((TemplateParameterDescriptor)descriptor).getParameterDescriptors().stream().findFirst().isPresent())) {
return;
}
CustomParameterClass customClass = (CustomParameterClass)typesMap.get(aValue);
if (customClass == null) {
customClass = CustomParameterClass.StringClass;
}
Map<String, Object> extra = null;
if (customClass.equals(CustomParameterClass.FolderClass)) {
extra = new HashMap<>();
extra.put("directory", Boolean.TRUE);
}
descriptor.setParameterType(customClass.getTypeMask());
if (descriptor.getDataType() != customClass.getParameterClass()) {
descriptor.setDataType(customClass.getParameterClass());
boolean canResetDefaultValue = true;
if (customClass.getParameterClass() == String.class || customClass.getParameterClass() == String[].class) {
canResetDefaultValue = false;
} else if (customClass.getParameterClass() == Integer.class) {
if (!StringUtils.isNullOrEmpty(descriptor.getDefaultValue())) {
IntegerConverter integerConverter = new IntegerConverter();
try {
Number number = integerConverter.parse(descriptor.getDefaultValue());
if (number != null) {
descriptor.setDefaultValue(number.toString());
canResetDefaultValue = false;
}
} catch (ConversionException e) {
// ignore exception and reset the default value
}
}
} else if (customClass.getParameterClass() == Float.class) {
if (!StringUtils.isNullOrEmpty(descriptor.getDefaultValue())) {
FloatConverter integerConverter = new FloatConverter();
try {
Number number = integerConverter.parse(descriptor.getDefaultValue());
if (number != null) {
descriptor.setDefaultValue(number.toString());
canResetDefaultValue = false;
}
} catch (ConversionException e) {
// ignore exception and reset the default value
}
}
}
if (canResetDefaultValue) {
descriptor.setDefaultValue(null); // reset the default value
}
descriptor.setValueSet(null); // reset the value set
rebuildEditorCell(descriptor, extra);
}
}
@Override
public boolean isCellEditable(int row, int column) {
return false;
}
private class OperatorParametersTableNewTableModel extends AbstractTableModel {
private OperatorParametersTableNewTableModel() {
super();
}
@Override
public String getColumnName(int column) {
return columnNames[column];
}
@Override
public int getColumnCount() {
return columnNames.length;
}
@Override
public int getRowCount() {
return operator.getToolParameterDescriptors().size();
}
@Override
public Object getValueAt(int row, int column) {
ToolParameterDescriptor descriptor = operator.getToolParameterDescriptors().get(row);
switch (column) {
case 0:
return false;
case 4:
String cellValue = null;
if (descriptor.getName().equals(ToolAdapterConstants.TOOL_SOURCE_PRODUCT_ID)) {
cellValue = Bundle.Type_ProductList_Text();
} else if (descriptor.getName().equals(ToolAdapterConstants.TOOL_SOURCE_PRODUCT_FILE)) {
cellValue = Bundle.Type_FileListClass_Text();
} else if (descriptor.getName().equals(ToolAdapterConstants.TOOL_TARGET_PRODUCT_FILE)) {
cellValue = Bundle.Type_RegularFileClass_Text();
} else if (CustomParameterClass.getObject(descriptor.getDataType(), descriptor.getParameterType()).equals(CustomParameterClass.FolderClass)) {
cellValue = Bundle.Type_FolderClass_Text();
} else {
CustomParameterClass item = CustomParameterClass.getObject(descriptor.getDataType(), descriptor.getParameterType());
cellValue = (String)typesMap.getKey(item);
}
return cellValue;
case 5:
return descriptor.getDefaultValue();
case 6:
return false;
default:
try {
return descriptor.getAttribute(columnsMembers[column]);
} catch (PropertyAttributeException e) {
logger.warning(e.getMessage());
return String.format("Error: %s", e.getMessage());
}
}
}
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return false;
}
}
private class MultiRenderer extends AbstractCellEditor implements TableCellRenderer {
private TableCellRenderer defaultRenderer;
private AbstractButton deleteButton;
private AbstractButton editButton;
private JCheckBox checkBoxRenderer;
private JTextField textComponentRenderer;
public MultiRenderer() {
checkBoxRenderer = new JCheckBox();
textComponentRenderer = new JTextField();
textComponentRenderer.setBorder(new EmptyBorder(0, 0, 0, 0));
defaultRenderer = new DefaultTableCellRenderer();
deleteButton = ToolButtonFactory.createButton(UIUtils.loadImageIcon("/org/esa/snap/resources/images/icons/DeleteShapeTool16.gif"), false);
editButton = new JButton("...");
deleteButton.addActionListener(e -> fireEditingStopped());
editButton.addActionListener(e -> fireEditingStopped());
}
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
ToolParameterDescriptor descriptor = operator.getToolParameterDescriptors().get(row);
switch (column) {
case 0:
return deleteButton;
case 5:
String defaultValue = descriptor.getDefaultValue();
if (descriptor.getDataType() == Boolean.class) {
this.checkBoxRenderer.setSelected(Boolean.parseBoolean(defaultValue));
return this.checkBoxRenderer;
} else if (descriptor.getDataType() == String.class || descriptor.getDataType() == Integer.class || descriptor.getDataType() == Float.class) {
this.textComponentRenderer.setText(defaultValue);
return this.textComponentRenderer;
} else if (descriptor.getDataType() == String[].class) {
this.textComponentRenderer.setText(defaultValue);
return this.textComponentRenderer;
} else if (descriptor.getDataType() == File.class) {
this.textComponentRenderer.setText(defaultValue);
return this.textComponentRenderer;
}
try {
return propertiesValueUIDescriptorMap.get(descriptor).getUIComponent();
} catch (Exception e) {
logger.warning(e.getMessage());
return null;
}
case 6:
return editButton;
default:
return defaultRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
}
}
@Override
public Object getCellEditorValue() {
return null;
}
}
}