org.esa.snap.ui.tooladapter.model.OperatorParametersTable.java Source code

Java tutorial

Introduction

Here is the source code for org.esa.snap.ui.tooladapter.model.OperatorParametersTable.java

Source

/*
 *
 *  * 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.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.*;
import org.esa.snap.core.gpf.operators.tooladapter.ToolAdapterConstants;
import org.esa.snap.core.gpf.ui.OperatorParameterSupport;
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.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import java.awt.*;
import java.io.File;
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_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 String[] columnNames = { "", "Name", "Description", "Label", "Data type", "Default value", "" };
    private static String[] columnsMembers = { "del", "name", "description", "alias", "dataType", "defaultValue",
            "edit" };
    private static int[] widths = { 27, 100, 200, 80, 100, 249, 30 };
    private static final BidiMap typesMap;
    private ToolAdapterOperatorDescriptor operator = null;
    private Map<ToolParameterDescriptor, PropertyMemberUIWrapper> propertiesValueUIDescriptorMap;
    private MultiRenderer tableRenderer;
    private BindingContext context;
    private DefaultCellEditor comboCellEditor;
    private TableCellRenderer comboCellRenderer;
    private AppContext appContext;
    private DefaultTableCellRenderer labelTypeCellRenderer = new DefaultTableCellRenderer();
    private Logger logger;

    static {
        typesMap = new DualHashBidiMap();
        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_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);
    }

    public void stopVariablesTableEditing() {
        if (getEditingRow() >= 0 && getEditingColumn() >= 0) {
            getCellEditor(getEditingRow(), getEditingColumn()).stopCellEditing();
        }
    }

    public OperatorParametersTable(ToolAdapterOperatorDescriptor operator, AppContext appContext) {
        logger = Logger.getLogger(OperatorParametersTable.class.getName());
        this.operator = operator;
        this.appContext = appContext;
        propertiesValueUIDescriptorMap = new HashMap<>();
        JComboBox typesComboBox = new JComboBox(typesMap.keySet().toArray());
        comboCellEditor = new DefaultCellEditor(typesComboBox);
        comboCellRenderer = new DefaultTableCellRenderer();
        labelTypeCellRenderer.setText(Bundle.Type_ProductList_Text());

        List<TemplateParameterDescriptor> 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);
    }

    public void addParameterToTable(TemplateParameterDescriptor param) {
        try {
            PropertyDescriptor property = ParameterDescriptorFactory.convert(param,
                    new ParameterDescriptorFactory().getSourceProductMap());
            operator.getToolParameterDescriptors().add(param);
            DefaultPropertySetDescriptor propertySetDescriptor = new DefaultPropertySetDescriptor();
            try {
                property.setDefaultValue(param.getDefaultValue());
            } catch (Exception ex) {
                logger.warning(ex.getMessage());
            }
            propertySetDescriptor.addPropertyDescriptor(property);
            PropertyContainer container = PropertyContainer.createMapBacked(new HashMap<>(), propertySetDescriptor);
            context.getPropertySet().addProperties(container.getProperties());
            propertiesValueUIDescriptorMap.put(param, PropertyMemberUIWrapperFactory
                    .buildPropertyWrapper("defaultValue", param, operator, context, null));
            revalidate();
        } catch (Exception ex) {
            logger.warning(ex.getMessage());
        }
    }

    @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);
            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 comboCellRenderer;
            }
        default:
            return super.getCellRenderer(row, column);
        }
    }

    @Override
    public TableCellEditor getCellEditor(int row, int column) {
        switch (column) {
        case 0:
        case 5:
        case 6:
            return tableRenderer;
        case 4:
            return comboCellEditor;
        default:
            return getDefaultEditor(String.class);
        }
    }

    public BindingContext getBindingContext() {
        return context;
    }

    public boolean editCellAt(int row, int column) {
        return super.editCellAt(row, column);
    }

    class OperatorParametersTableNewTableModel extends AbstractTableModel {

        @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:
                if (descriptor.getName().equals(ToolAdapterConstants.TOOL_SOURCE_PRODUCT_ID)) {
                    return Bundle.Type_ProductList_Text();
                } else if (descriptor.getName().equals(ToolAdapterConstants.TOOL_SOURCE_PRODUCT_FILE)) {
                    return Bundle.Type_FileListClass_Text();
                } else {
                    return typesMap.getKey(CustomParameterClass.getObject(descriptor.getDataType(),
                            descriptor.getParameterType()));
                }
            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) {
            ToolParameterDescriptor descriptor = operator.getToolParameterDescriptors().get(rowIndex);
            final String descriptorName = descriptor.getName();
            final Class<?> dataType = descriptor.getDataType();
            return !ToolAdapterConstants.TOOL_SOURCE_PRODUCT_ID.equals(descriptorName)
                    && !ToolAdapterConstants.TOOL_SOURCE_PRODUCT_FILE.equals(descriptorName)
                    && !(ToolAdapterConstants.TOOL_TARGET_PRODUCT_FILE.equals(descriptorName)
                            && (columnIndex == 0 || columnIndex == 1 || columnIndex == 4 || columnIndex == 6))
                    && !(dataType.isArray() && columnIndex > 4);
        }

        @Override
        public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
            TemplateParameterDescriptor descriptor = operator.getToolParameterDescriptors().get(rowIndex);
            String defaultValue = descriptor.getDefaultValue();
            switch (columnIndex) {
            case 0:
                operator.removeParamDescriptor(descriptor);
                revalidate();
                break;
            case 1:
                String oldName = descriptor.getName();
                descriptor.setName(aValue.toString());
                //since the name is changed, the context must be changed also
                context.getPropertySet().removeProperty(context.getPropertySet().getProperty(oldName));
                try {
                    PropertyDescriptor property = ParameterDescriptorFactory.convert(descriptor,
                            new ParameterDescriptorFactory().getSourceProductMap());
                    try {
                        property.setDefaultValue(defaultValue);
                    } catch (Exception ex) {
                        logger.warning(ex.getMessage());
                    }
                    DefaultPropertySetDescriptor propertySetDescriptor = new DefaultPropertySetDescriptor();
                    propertySetDescriptor.addPropertyDescriptor(property);
                    PropertyContainer container = PropertyContainer.createMapBacked(new HashMap<>(),
                            propertySetDescriptor);
                    context.getPropertySet().addProperties(container.getProperties());
                    propertiesValueUIDescriptorMap.put(descriptor, PropertyMemberUIWrapperFactory
                            .buildPropertyWrapper("defaultValue", descriptor, operator, context, null));
                    revalidate();
                    repaint();
                } catch (ConversionException e) {
                    logger.warning(e.getMessage());
                    Dialogs.showError(e.getMessage());
                }
                break;
            case 4:
                //type editing
                CustomParameterClass customClass = (CustomParameterClass) typesMap.get(aValue);
                if (customClass == null) {
                    customClass = CustomParameterClass.StringClass;
                }
                descriptor.setParameterType(customClass.getTypeMask());
                if (descriptor.getDataType() != customClass.getParameterClass()) {
                    descriptor.setDataType(customClass.getParameterClass());
                    descriptor.setDefaultValue(defaultValue);
                    rebuildEditorCell(descriptor);
                }
                break;
            case 5:
                //the custom editor should handle this
                break;
            case 6:
                //edit details
                int returnCode = -1;
                if (!descriptor.isParameter() && descriptor.getDataType().equals(File.class)) {
                    try {
                        TemplateParameterEditorDialog editor = new TemplateParameterEditorDialog(appContext, "",
                                descriptor, propertiesValueUIDescriptorMap.get(descriptor), operator);
                        returnCode = editor.show();
                    } catch (Exception ex) {
                        Dialogs.showError(ex.getMessage());
                    }
                } else {
                    Object value = getBindingContext().getBinding(descriptor.getName()).getPropertyValue();
                    try {
                        ToolParameterEditorDialog editor = new ToolParameterEditorDialog(appContext,
                                "Parameter editor for " + descriptor.getName(), descriptor, value);
                        returnCode = editor.show();
                    } catch (Exception ex) {
                        logger.warning(ex.getMessage());
                        Dialogs.showError(
                                "Could not edit parameter " + descriptor.getName() + " : " + ex.getMessage());
                    }
                }
                if (returnCode == AbstractDialog.ID_OK) {
                    rebuildEditorCell(descriptor);
                }
                break;
            default:
                try {
                    descriptor.setAttribute(columnsMembers[columnIndex], aValue == null ? null : aValue.toString());
                } catch (PropertyAttributeException e) {
                    logger.warning(e.getMessage());
                }
            }
        }
    }

    private void rebuildEditorCell(TemplateParameterDescriptor descriptor) {

        context.getPropertySet().removeProperty(context.getPropertySet().getProperty(descriptor.getName()));
        PropertyDescriptor property;
        try {
            try {
                property = ParameterDescriptorFactory.convert(descriptor,
                        new ParameterDescriptorFactory().getSourceProductMap());
            } catch (Exception ex) {
                logger.warning(ex.getMessage());
                descriptor.setDefaultValue("");
                property = ParameterDescriptorFactory.convert(descriptor,
                        new ParameterDescriptorFactory().getSourceProductMap());
            }
            try {
                property.setDefaultValue(descriptor.getDefaultValue());
            } catch (Exception ex) {
                logger.warning(ex.getMessage());
                property.setDefaultValue("");
            }
            DefaultPropertySetDescriptor propertySetDescriptor = new DefaultPropertySetDescriptor();
            propertySetDescriptor.addPropertyDescriptor(property);
            PropertyContainer container = PropertyContainer.createMapBacked(new HashMap<>(), propertySetDescriptor);
            try {
                container.getProperty(property.getName()).setValue(descriptor.getDefaultValue());
            } catch (Exception ex) {
                logger.warning(ex.getMessage());
                try {
                    container.getProperty(property.getName()).setValue("");
                } catch (Exception exx) {
                }
            }
            context.getPropertySet().addProperties(container.getProperties());
            propertiesValueUIDescriptorMap.put(descriptor, PropertyMemberUIWrapperFactory
                    .buildPropertyWrapper("defaultValue", descriptor, operator, context, null));

            revalidate();
            repaint();
        } catch (ConversionException e) {
            logger.warning(e.getMessage());
            Dialogs.showError(e.getMessage());
        }
    }

    class MultiRenderer extends AbstractCellEditor implements TableCellEditor, TableCellRenderer {
        private TableCellRenderer defaultRenderer = new DefaultTableCellRenderer();
        private AbstractButton delButton = ToolButtonFactory.createButton(
                UIUtils.loadImageIcon("/org/esa/snap/resources/images/icons/DeleteShapeTool16.gif"), false);
        private AbstractButton editButton = new JButton("...");

        public MultiRenderer() {
            delButton.addActionListener(e -> fireEditingStopped());
            editButton.addActionListener(e -> fireEditingStopped());
        }

        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
                boolean hasFocus, int row, int column) {
            ParameterDescriptor descriptor = operator.getToolParameterDescriptors().get(row);
            switch (column) {
            case 0:
                return delButton;
            case 5:
                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 Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row,
                int column) {
            ParameterDescriptor descriptor = operator.getToolParameterDescriptors().get(row);
            switch (column) {
            case 0:
                return delButton;
            case 5:
                try {
                    return propertiesValueUIDescriptorMap.get(descriptor).getUIComponent();
                } catch (Exception e) {
                    logger.warning(e.getMessage());
                    return null;
                }
            case 6:
                return editButton;
            default:
                return getDefaultEditor(String.class).getTableCellEditorComponent(table, value, isSelected, row,
                        column);
            }
        }

        @Override
        public Object getCellEditorValue() {
            return null;
        }
    }
}