Java tutorial
/* * soapUI, copyright (C) 2004-2011 smartbear.com * * soapUI is free software; you can redistribute it and/or modify it under the * terms of version 2.1 of the GNU Lesser General Public License as published by * the Free Software Foundation. * * soapUI 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 Lesser General Public License for more details at gnu.org. */ package com.eviware.soapui.support.components; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.Font; import java.awt.Toolkit; import java.awt.datatransfer.StringSelection; import java.awt.event.ActionEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.List; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.BorderFactory; import javax.swing.DefaultCellEditor; import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.JPanel; import javax.swing.JPasswordField; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.JTextField; import javax.swing.TransferHandler; import javax.swing.UIDefaults; import javax.swing.UIManager; import javax.swing.border.TitledBorder; import javax.swing.table.AbstractTableModel; import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.TableCellEditor; import javax.swing.table.TableModel; import org.apache.commons.beanutils.BeanUtils; import org.apache.commons.beanutils.PropertyUtils; import com.eviware.soapui.SoapUI; import com.eviware.soapui.support.PropertyChangeNotifier; import com.eviware.soapui.support.StringUtils; /** * Table for displaying property name/value pairs * * @author Ole.Matzura */ @SuppressWarnings("serial") public class JPropertiesTable<T> extends JPanel { public final static Object[] BOOLEAN_OPTIONS = new Object[] { Boolean.TRUE, Boolean.FALSE }; private PropertiesTableModel<T> tableModel; private JTable table; private TitledBorder titledBorder; private String title; public JPropertiesTable(String title) { this(title, null); } public JPropertiesTable(String title, T propertyObject) { super(new BorderLayout()); this.title = title; tableModel = new PropertiesTableModel<T>(propertyObject); table = new PTable(tableModel); table.getColumnModel().getColumn(0).setHeaderValue("Property"); table.getColumnModel().getColumn(1).setHeaderValue("Value"); table.getColumnModel().getColumn(0).setCellRenderer(new PropertiesTableCellRenderer()); table.getColumnModel().getColumn(1).setCellRenderer(new PropertiesTableCellRenderer()); add(new JScrollPane(table), BorderLayout.CENTER); titledBorder = BorderFactory.createTitledBorder(BorderFactory.createEmptyBorder(), title); /* * Java 7 issue * * old: titledBorder.setTitleFont( titledBorder.getTitleFont().deriveFont( * Font.PLAIN, 11 ) ); titledBorder.getTitleFont() return null in Java 7 */ Font defaultUIFont = getUIDefaultFont(); if (defaultUIFont != null) titledBorder.setTitleFont(getUIDefaultFont().deriveFont(Font.PLAIN, 11)); if (title != null) setBorder(titledBorder); table.setBackground(Color.WHITE); setPreferredSize(table.getPreferredSize()); } private Font getUIDefaultFont() { UIDefaults uidefs = UIManager.getLookAndFeelDefaults(); for (Object key : uidefs.keySet()) { if (uidefs.get(key) instanceof Font) { return uidefs.getFont(key); } } return null; } public void setTitle(String title) { this.title = title; titledBorder.setTitle(title); setBorder(titledBorder); repaint(); } public String getTitle() { return title; } @Override public void removeNotify() { getTableModel().release(); super.removeNotify(); } @Override public void addNotify() { getTableModel().attach(); super.addNotify(); } public void setPropertyObject(T propertyObject) { if (table.isEditing()) table.getCellEditor().stopCellEditing(); tableModel.setPropertyObject(propertyObject); } public PropertiesTableModel<?> getTableModel() { return tableModel; } public PropertyDescriptor addProperty(String caption, String name) { return addProperty(caption, name, false); } public PropertyDescriptor addProperty(String caption, String name, boolean editable) { return addProperty(caption, name, editable, null); } public PropertyDescriptor addProperty(String caption, String name, boolean editable, PropertyFormatter formatter) { return tableModel.addProperty(caption, name, editable, formatter); } public static final class PropertiesTableModel<T> extends AbstractTableModel implements PropertyChangeListener { private List<PropertyDescriptor> properties = new ArrayList<PropertyDescriptor>(); private T propertyObject; private boolean attached; public PropertiesTableModel(T propertyObject) { this.propertyObject = propertyObject; } public void attach() { if (!attached && propertyObject instanceof PropertyChangeNotifier) { ((PropertyChangeNotifier) propertyObject).addPropertyChangeListener(this); attached = true; } } public void setPropertyObject(T propertyObject) { release(); this.propertyObject = propertyObject; attach(); fireTableDataChanged(); } public PropertyDescriptor addProperty(String caption, String name, boolean editable, PropertyFormatter formatter) { PropertyDescriptor propertyDescriptor = new PropertyDescriptor(caption, name, editable, formatter); properties.add(propertyDescriptor); return propertyDescriptor; } public PropertyDescriptor addProperty(String caption, String name, Object[] options) { PropertyDescriptor propertyDescriptor = new PropertyDescriptor(caption, name, options); properties.add(propertyDescriptor); return propertyDescriptor; } public int getRowCount() { return properties.size(); } public int getColumnCount() { return 2; } public boolean isCellEditable(int rowIndex, int columnIndex) { if (columnIndex == 0 || propertyObject == null) return false; return properties.get(rowIndex).isEditable() && PropertyUtils.isWriteable(propertyObject, properties.get(rowIndex).getName()); } public void setValueAt(Object aValue, int rowIndex, int columnIndex) { try { if (propertyObject != null && columnIndex == 1 && properties.get(rowIndex).isEditable()) { BeanUtils.setProperty(propertyObject, properties.get(rowIndex).getName(), aValue); } } catch (IllegalAccessException e) { SoapUI.logError(e); } catch (InvocationTargetException e) { SoapUI.logError(e); } } public Object getValueAt(int rowIndex, int columnIndex) { if (propertyObject == null) return null; try { PropertyDescriptor propertyDescriptor = properties.get(rowIndex); switch (columnIndex) { case 0: return propertyDescriptor.getCaption(); case 1: { Object value = PropertyUtils.getSimpleProperty(propertyObject, propertyDescriptor.getName()); return propertyDescriptor.getFormatter().format(propertyDescriptor.getName(), value); } } } catch (IllegalAccessException e) { SoapUI.logError(e); } catch (InvocationTargetException e) { SoapUI.logError(e); } catch (NoSuchMethodException e) { SoapUI.logError(e); } return null; } public PropertyDescriptor getPropertyDescriptorAt(int row) { return properties.get(row); } public void propertyChange(PropertyChangeEvent evt) { fireTableDataChanged(); } public void release() { if (propertyObject instanceof PropertyChangeNotifier && attached) { ((PropertyChangeNotifier) propertyObject).removePropertyChangeListener(this); attached = false; } } public PropertyDescriptor addPropertyShadow(String caption, String name, boolean editable) { PropertyDescriptor propertyDescriptor = new PropertyDescriptor(caption, name, editable); properties.add(propertyDescriptor); return propertyDescriptor; } } public static class PropertyDescriptor { private final String caption; private final String name; private boolean editable; private PropertyFormatter formatter; private Object[] options; private DefaultCellEditor cellEditor; private String description; public PropertyDescriptor(String caption, String name, boolean editable, PropertyFormatter formatter) { this.caption = caption; this.name = name; this.editable = editable; this.formatter = formatter; JTextField textField = new JTextField(); textField.setBorder(BorderFactory.createEmptyBorder()); cellEditor = new DefaultCellEditor(textField); } public PropertyDescriptor(String caption, String name, Object[] options) { this.caption = caption; this.name = name; this.options = options; editable = true; JComboBox comboBox = new JComboBox(options); if (options.length > 0 && options[0] == null) { comboBox.setEditable(true); comboBox.removeItemAt(0); } comboBox.setBorder(null); cellEditor = new DefaultCellEditor(comboBox); } /** * For password field in table. * * @author robert nemet * @param caption * @param name * @param editable */ public PropertyDescriptor(String caption, String name, boolean editable) { this.caption = caption; this.name = name; this.editable = editable; JPasswordField textField = new JPasswordField(); textField.setBorder(BorderFactory.createEmptyBorder()); cellEditor = new DefaultCellEditor(textField); } public void setFormatter(PropertyFormatter formatter) { this.formatter = formatter; } public PropertyFormatter getFormatter() { return formatter == null ? DefaultFormatter.getInstance() : formatter; } public String getCaption() { return caption; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public boolean isEditable() { return editable; } public Object[] getOptions() { return options; } public boolean hasOptions() { return options != null; } public String getName() { return name; } public TableCellEditor getCellEditor() { return cellEditor; } } private static class PropertiesTableCellRenderer extends DefaultTableCellRenderer { public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { Component component; DefaultCellEditor cellEditor = (DefaultCellEditor) table.getCellEditor(row, column); if (cellEditor.getComponent() instanceof JPasswordField && value instanceof String) { if (value != null && ((String) value).length() > 0) { component = super.getTableCellRendererComponent(table, "**************", isSelected, hasFocus, row, column); } else { component = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); } } else { component = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); } if (component instanceof JComponent) { PropertyDescriptor descriptor = ((PropertiesTableModel<?>) table.getModel()) .getPropertyDescriptorAt(row); if (StringUtils.hasContent(descriptor.getDescription())) { ((JComponent) component).setToolTipText(descriptor.getDescription()); } // do not set tooltip as value for password field, it has no sense. else if (value != null && StringUtils.hasContent(value.toString()) && !(cellEditor.getComponent() instanceof JPasswordField)) { ((JComponent) component).setToolTipText(value.toString()); } else { ((JComponent) component).setToolTipText(null); } } return component; } } /* * defaultcelleditor private class PropertiesTableCellEditor extends * AbstractCellEditor implements TableCellEditor { private JTextField * textField; private JComboBox comboBox; private JComponent current; * * public PropertiesTableCellEditor() { textField = new JTextField(); * comboBox = new JComboBox(); * comboBox.putClientProperty("JComboBox.isTableCellEditor", Boolean.TRUE); } * * public Component getTableCellEditorComponent(JTable table, Object value, * boolean isSelected, int row, int column) { PropertyDescriptor descriptor = * tableModel.getPropertyDescriptorAt( row ); * * if( descriptor.hasOptions()) { comboBox.setModel( new * DefaultComboBoxModel( descriptor.getOptions() )); * comboBox.setSelectedItem( value ); current = comboBox; } else { * textField.setText( value == null ? "" : value.toString() ); current = * textField; } * * current.setBorder( null ); current.setBackground( Color.WHITE ); * * return current; } * * public Object getCellEditorValue() { return current == comboBox ? * comboBox.getSelectedItem() : textField.getText(); } } */ /** * Formatter used for displaying property values * * @author Ole.Matzura */ public interface PropertyFormatter { public Object format(String propertyName, Object value); } private static class DefaultFormatter implements PropertyFormatter { private static PropertyFormatter instance; public static PropertyFormatter getInstance() { if (instance == null) instance = new DefaultFormatter(); return instance; } public Object format(String propertyName, Object value) { return value; } } public PropertyDescriptor addProperty(String caption, String name, Object[] options) { return tableModel.addProperty(caption, name, options); } private class PTable extends JTable { public PTable(TableModel tableModel) { super(tableModel); // setAutoStartEditOnKeyStroke( true ); getActionMap().put(TransferHandler.getCopyAction().getValue(Action.NAME), new AbstractAction() { public void actionPerformed(ActionEvent e) { int row = getSelectedRow(); if (row == -1) return; StringSelection selection = new StringSelection(getValueAt(row, 1).toString()); Toolkit.getDefaultToolkit().getSystemClipboard().setContents(selection, selection); } }); putClientProperty("terminateEditOnFocusLost", Boolean.TRUE); /* * addFocusListener( new FocusAdapter() { * * public void focusLost(FocusEvent e) { if( isEditing() && * getCellEditor() != null ) getCellEditor().stopCellEditing(); }} ); */ } public TableCellEditor getCellEditor(int row, int column) { if (column == 0) return super.getCellEditor(row, column); else return tableModel.getPropertyDescriptorAt(row).getCellEditor(); } } /** * Value in this field will not be showen. It will be masked... * * @author robert nemet * @param caption * @param name * @param editable * @return */ public PropertyDescriptor addPropertyShadow(String caption, String name, boolean editable) { return tableModel.addPropertyShadow(caption, name, editable); } }