/*******************************************************************************
* Copyright (c) 1998, 2015 Oracle and/or its affiliates. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
* which accompanies this distribution.
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Oracle - initial API and implementation from Oracle TopLink
******************************************************************************/
package org.eclipse.persistence.tools.workbench.mappingsplugin.ui.descriptor;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Iterator;
import java.util.ListIterator;
import javax.swing.JButton;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableModel;
import org.eclipse.persistence.tools.workbench.framework.context.WorkbenchContext;
import org.eclipse.persistence.tools.workbench.framework.context.WorkbenchContextHolder;
import org.eclipse.persistence.tools.workbench.framework.resources.ResourceRepository;
import org.eclipse.persistence.tools.workbench.framework.ui.view.AbstractPanel;
import org.eclipse.persistence.tools.workbench.framework.uitools.SwingComponentFactory;
import org.eclipse.persistence.tools.workbench.mappingsmodel.db.MWColumn;
import org.eclipse.persistence.tools.workbench.mappingsmodel.meta.MWClass;
import org.eclipse.persistence.tools.workbench.mappingsmodel.meta.MWMethod;
import org.eclipse.persistence.tools.workbench.mappingsmodel.meta.MWMethodParameter;
import org.eclipse.persistence.tools.workbench.mappingsplugin.ui.common.cell.ClassCellRendererAdapter;
import org.eclipse.persistence.tools.workbench.mappingsplugin.ui.meta.ClassChooserTools;
import org.eclipse.persistence.tools.workbench.mappingsplugin.ui.project.ZeroArgConstructorPreference;
import org.eclipse.persistence.tools.workbench.uitools.app.ListAspectAdapter;
import org.eclipse.persistence.tools.workbench.uitools.app.ListValueModel;
import org.eclipse.persistence.tools.workbench.uitools.app.PropertyAspectAdapter;
import org.eclipse.persistence.tools.workbench.uitools.app.PropertyValueModel;
import org.eclipse.persistence.tools.workbench.uitools.app.SimplePropertyValueModel;
import org.eclipse.persistence.tools.workbench.uitools.app.ValuePropertyPropertyValueModelAdapter;
import org.eclipse.persistence.tools.workbench.uitools.app.swing.ColumnAdapter;
import org.eclipse.persistence.tools.workbench.uitools.app.swing.ListModelAdapter;
import org.eclipse.persistence.tools.workbench.uitools.app.swing.NumberSpinnerModelAdapter;
import org.eclipse.persistence.tools.workbench.uitools.app.swing.ObjectListSelectionModel;
import org.eclipse.persistence.tools.workbench.uitools.app.swing.TableModelAdapter;
import org.eclipse.persistence.tools.workbench.uitools.cell.AdaptableTableCellRenderer;
import org.eclipse.persistence.tools.workbench.uitools.cell.SpinnerTableCellRenderer;
import org.eclipse.persistence.tools.workbench.uitools.cell.TableCellEditorAdapter;
import org.eclipse.persistence.tools.workbench.utility.CollectionTools;
final class MethodParametersPanel
extends AbstractPanel
{
private PropertyValueModel methodHolder;
private ObjectListSelectionModel rowSelectionModel;
private ListValueModel paramatersHolder;
private JButton removeParameterButton;
/**
* This action adds a new database field at the end of the table.
*/
private class AddParameterAction implements ActionListener {
public void actionPerformed(ActionEvent e) {
MWClass type = ClassChooserTools.promptForType(
MethodParametersPanel.this.getMethod().getRepository(),
ClassChooserTools.buildDeclarableNonVoidFilter(),
MethodParametersPanel.this.workbenchContext()
);
// the type will be null if the user pressed cancel or pressed OK but did not select a class
if (type == null)
return;
if (getMethod().isZeroArgumentConstructor()) {
getMethod().addMethodParameter(type);
optionallyAddZeroArgumentConstructor();
}
else if (type.isVoid()) {
JOptionPane.showMessageDialog(currentWindow(),
resourceRepository().getString("METHOD_PARAMETER_TYPE_VOID_WARNING.message"),
resourceRepository().getString("METHOD_PARAMETER_TYPE_VOID_WARNING.title"),
JOptionPane.WARNING_MESSAGE);
}
else {
getMethod().addMethodParameter(type);
}
}
}
// open access for inner class
WorkbenchContext workbenchContext() {
return this.getWorkbenchContext();
}
private class RemoveParameterAction implements ActionListener {
public void actionPerformed(ActionEvent e) {
removeSelectedMethodParameters();
}
}
MethodParametersPanel(PropertyValueModel methodHolder, WorkbenchContextHolder contextHolder) {
super(contextHolder);
this.methodHolder = methodHolder;
initialize();
initializeLayout();
}
private void initialize() {
this.paramatersHolder = buildParametersAdapter();
this.rowSelectionModel = buildRowSelectionModel();
}
private ObjectListSelectionModel buildRowSelectionModel() {
ObjectListSelectionModel rowSelectionModel = new ObjectListSelectionModel(new ListModelAdapter(this.paramatersHolder));
rowSelectionModel.addListSelectionListener(this.buildRowSelectionListener());
return rowSelectionModel;
}
private ListSelectionListener buildRowSelectionListener() {
return new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
if ( ! e.getValueIsAdjusting()) {
removeParameterButton.setEnabled(rowSelectionModel.getSelectedValue() != null);
}
}
};
}
private ListValueModel buildParametersAdapter() {
return new ListAspectAdapter(this.methodHolder, MWMethod.METHOD_PARAMETERS_LIST) {
protected ListIterator getValueFromSubject() {
return ((MWMethod) subject).methodParameters();
}
protected int sizeFromSubject() {
return ((MWMethod) subject).methodParametersSize();
}
};
}
MWMethod getMethod() {
return (MWMethod) methodHolder.getValue();
}
private MWClass getMWClass() {
return (MWClass) getMethod().getMWParent();
}
private Iterator selectedParameters() {
return CollectionTools.iterator(this.rowSelectionModel.getSelectedValues());
}
/**
* Initializes this Columns page.
*/
protected void initializeLayout() {
GridBagConstraints constraints = new GridBagConstraints();
JPanel mainPanel = this;
// Create the buttons first
JPanel buttonPanel = new JPanel(new GridLayout(1, 2, 5, 0));
// Add the Add New Database Field button
JButton addParameterButton = buildButton("ADD_PARAMETER");
addParameterButton.addActionListener(new AddParameterAction());
addParameterButton.setEnabled(false);
this.methodHolder.addPropertyChangeListener(PropertyValueModel.VALUE, buildMethodListener(addParameterButton));
buttonPanel.add(addParameterButton);
// Add the Remove Field button
removeParameterButton = buildButton("REMOVE_PARAMETER");
removeParameterButton.addActionListener(new RemoveParameterAction());
removeParameterButton.setEnabled(false);
buttonPanel.add(removeParameterButton);
constraints.gridx = 0;
constraints.gridy = 1;
constraints.gridwidth = 1;
constraints.gridheight = 1;
constraints.weightx = 0;
constraints.weighty = 0;
constraints.fill = GridBagConstraints.NONE;
constraints.anchor = GridBagConstraints.LINE_END;
constraints.insets = new Insets(5, 5, 0, 0);
mainPanel.add(buttonPanel, constraints);
// Create the table, listeners needs to have access to the buttons
JTable table = this.buildParametersTable();
JScrollPane scrollPane = new JScrollPane(table);
scrollPane.getViewport().setBackground(table.getBackground());
scrollPane.getViewport().setPreferredSize(new Dimension(40, 30));
table.addPropertyChangeListener("enabled", new PropertyChangeHandler(scrollPane));
this.methodHolder.addPropertyChangeListener(PropertyValueModel.VALUE, buildMethodListener(table));
constraints.gridx = 0;
constraints.gridy = 0;
constraints.gridwidth = 1;
constraints.gridheight = 1;
constraints.weightx = 1;
constraints.weighty = 1;
constraints.fill = GridBagConstraints.BOTH;
constraints.anchor = GridBagConstraints.CENTER;
constraints.insets = new Insets(0, 0, 0, 0);
mainPanel.add(scrollPane, constraints);
}
// ************ Parameters ************
private JTable buildParametersTable() {
JTable table = SwingComponentFactory.buildTable(buildParametersTableModel(), rowSelectionModel);
int rowHeight = 20; // start with minimum of 20
TableColumn column = table.getColumnModel().getColumn(ParametersColumnAdapter.TYPE_COLUMN);
column.setCellRenderer(buildTypeRenderer());
column = table.getColumnModel().getColumn(ParametersColumnAdapter.DIMENSIONALITY_COLUMN);
SpinnerTableCellRenderer spinnerRenderer = this.buildNumberSpinnerRenderer();
column.setCellRenderer(spinnerRenderer);
column.setCellEditor(new TableCellEditorAdapter(this.buildNumberSpinnerRenderer()));
rowHeight = Math.max(rowHeight, spinnerRenderer.getPreferredHeight());
table.setRowHeight(rowHeight);
return table;
}
private SpinnerTableCellRenderer buildNumberSpinnerRenderer() {
return new SpinnerTableCellRenderer(new NumberSpinnerModelAdapter(new SimplePropertyValueModel(), new Integer(0), null, new Integer(1), new Integer(0)));
}
private TableCellRenderer buildTypeRenderer() {
return new AdaptableTableCellRenderer(new ClassCellRendererAdapter(resourceRepository()));
}
private TableModel buildParametersTableModel() {
return new TableModelAdapter(this.paramatersHolder, buildParametersTableColumnAdapter());
}
private ColumnAdapter buildParametersTableColumnAdapter() {
return new ParametersColumnAdapter(resourceRepository());
}
private void optionallyAddZeroArgumentConstructor() {
ZeroArgConstructorPreference.optionallyAddZeroArgumentConstructor(this.getMWClass(), this.getWorkbenchContext());
}
protected void removeSelectedMethodParameters() {
getMethod().removeMethodParameters(selectedParameters());
}
// ********** classes **********
private class PropertyChangeHandler implements PropertyChangeListener {
private final JScrollPane scrollPane;
private PropertyChangeHandler(JScrollPane scrollPane) {
this.scrollPane = scrollPane;
}
public void propertyChange(PropertyChangeEvent e) {
JTable table = (JTable) scrollPane.getViewport().getView();
if (table.isEnabled())
scrollPane.getViewport().setBackground(table.getBackground());
else
scrollPane.getViewport().setBackground(UIManager.getColor("control"));
}
}
private static class ParametersColumnAdapter implements ColumnAdapter {
private ResourceRepository resourceRepository;
public static final int COLUMN_COUNT = 2;
public static final int TYPE_COLUMN = 0;
public static final int DIMENSIONALITY_COLUMN = 1;
private static final String[] COLUMN_NAME_KEYS = new String[] {
"TYPE_COLUMN_HEADER",
"DIMENSIONALITY_COLUMN_HEADER",
};
private ParametersColumnAdapter(ResourceRepository repository) {
super();
this.resourceRepository = repository;
}
public int getColumnCount() {
return COLUMN_COUNT;
}
public String getColumnName(int index) {
return this.resourceRepository.getString(COLUMN_NAME_KEYS[index]);
}
public Class getColumnClass(int index) {
switch (index) {
case TYPE_COLUMN: return Object.class;
case DIMENSIONALITY_COLUMN: return Integer.class;
default: return Object.class;
}
}
public boolean isColumnEditable(int index) {
return index != TYPE_COLUMN;
}
public PropertyValueModel[] cellModels(Object subject) {
MWMethodParameter methodParameter = (MWMethodParameter) subject;
PropertyValueModel[] result = new PropertyValueModel[COLUMN_COUNT];
result[TYPE_COLUMN] = this.buildTypeAdapter(methodParameter);
result[DIMENSIONALITY_COLUMN] = this.buildDimensionalityAdapter(methodParameter);
return result;
}
private PropertyValueModel buildTypeAdapter(MWMethodParameter methodParameter) {
PropertyValueModel adapter = new PropertyAspectAdapter(MWMethodParameter.TYPE_PROPERTY, methodParameter) {
protected Object getValueFromSubject() {
return ((MWMethodParameter) subject).getType();
}
protected void setValueOnSubject(Object value) {
((MWMethodParameter) subject).setType((MWClass) value);
}
};
return new ValuePropertyPropertyValueModelAdapter(adapter, MWClass.NAME_PROPERTY);
}
private PropertyValueModel buildDimensionalityAdapter(MWMethodParameter methodParameter) {
return new PropertyAspectAdapter(MWMethodParameter.DIMENSIONALITY_PROPERTY, methodParameter) {
protected Object getValueFromSubject() {
return new Integer(((MWMethodParameter) subject).getDimensionality());
}
protected void setValueOnSubject(Object value) {
((MWMethodParameter) subject).setDimensionality(((Integer) value).intValue());
}
};
}
}
private PropertyChangeListener buildMethodListener(final Component component) {
return new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
component.setEnabled(getMethod() != null);
}
};
}
}