/*! * This program is free software; you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software * Foundation. * * You should have received a copy of the GNU Lesser General Public License along with this * program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html * or from the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * 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 Lesser General Public License for more details. * * Copyright (c) 2002-2013 Pentaho Corporation.. All rights reserved. */ package org.pentaho.reporting.designer.core.editor.parameters; import org.pentaho.reporting.designer.core.settings.WorkspaceSettings; import org.pentaho.reporting.designer.core.util.FastPropertyEditorManager; import org.pentaho.reporting.designer.core.util.table.ElementMetaDataTable; import org.pentaho.reporting.designer.core.util.table.ElementMetaDataTableModel; import org.pentaho.reporting.designer.core.util.table.TableStyle; import org.pentaho.reporting.engine.classic.core.util.beans.BeanException; import org.pentaho.reporting.engine.classic.core.util.beans.ConverterRegistry; import org.pentaho.reporting.libraries.base.util.StringUtils; import org.pentaho.reporting.libraries.designtime.swing.GenericCellRenderer; import org.pentaho.reporting.libraries.designtime.swing.settings.LocaleSettings; import javax.swing.*; import javax.swing.border.Border; import javax.swing.border.EmptyBorder; import javax.swing.plaf.UIResource; import javax.swing.table.AbstractTableModel; import javax.swing.table.TableCellEditor; import java.awt.*; import java.beans.PropertyEditor; import java.lang.reflect.Array; import java.sql.Time; import java.sql.Timestamp; import java.util.Date; import java.util.Locale; import java.util.TimeZone; /** * Todo: Document me! * <p/> * Date: 10.05.2010 Time: 16:24:51 * * @author Thomas Morgner. */ public class DefaultValueEditorPanel extends JPanel { private static class InjectDatePatternLocaleSettings implements LocaleSettings { private Class type; private String pattern; private TimeZone timeZone; private InjectDatePatternLocaleSettings( final Class type, final String pattern, final TimeZone timeZone ) { this.type = type; this.pattern = pattern; this.timeZone = timeZone; } public String getDateFormatPattern() { if ( StringUtils.isEmpty( pattern ) == false && java.sql.Date.class.equals( type ) ) { return pattern; } return WorkspaceSettings.getInstance().getDateFormatPattern(); } public String getTimeFormatPattern() { if ( StringUtils.isEmpty( pattern ) == false && Time.class.equals( type ) ) { return pattern; } return WorkspaceSettings.getInstance().getTimeFormatPattern(); } public String getDatetimeFormatPattern() { if ( StringUtils.isEmpty( pattern ) == false && Date.class.equals( type ) ) { return pattern; } if ( StringUtils.isEmpty( pattern ) == false && Timestamp.class.equals( type ) ) { return pattern; } return WorkspaceSettings.getInstance().getDatetimeFormatPattern(); } public Locale getLocale() { return WorkspaceSettings.getInstance().getLocale(); } public TimeZone getTimeZone() { return timeZone; } } private static class SingleValueMetaTableModel extends AbstractTableModel implements ElementMetaDataTableModel { private Object value; private Class valueType; private static final String[] EMPTY_EXTRA_FIELDS = new String[ 0 ]; private SingleValueMetaTableModel() { valueType = Object.class; } public Object getValue() { return value; } public void setValue( final Object value, final Class valueType ) { if ( valueType == null ) { throw new NullPointerException(); } this.value = value; this.valueType = valueType; fireTableStructureChanged(); } public Class getValueType() { return valueType; } /** * Returns the number of rows in the model. A <code>JTable</code> uses this method to determine how many rows it * should display. This method should be quick, as it is called frequently during rendering. * * @return the number of rows in the model * @see #getColumnCount */ public int getRowCount() { return 1; } /** * Returns the number of columns in the model. A <code>JTable</code> uses this method to determine how many columns * it should create and display by default. * * @return the number of columns in the model * @see #getRowCount */ public int getColumnCount() { return 1; } /** * Returns false. This is the default implementation for all cells. * * @param rowIndex the row being queried * @param columnIndex the column being queried * @return false */ public boolean isCellEditable( final int rowIndex, final int columnIndex ) { return true; } /** * Returns <code>Object.class</code> regardless of <code>columnIndex</code>. * * @param columnIndex the column being queried * @return the Object.class */ public Class getColumnClass( final int columnIndex ) { return valueType; } /** * Returns the value for the cell at <code>columnIndex</code> and <code>rowIndex</code>. * * @param rowIndex the row whose value is to be queried * @param columnIndex the column whose value is to be queried * @return the value Object at the specified cell */ public Object getValueAt( final int rowIndex, final int columnIndex ) { return value; } public String[] getExtraFields( final int row, final int column ) { return EMPTY_EXTRA_FIELDS; } /** * This empty implementation is provided so users don't have to implement this method if their data model is not * editable. * * @param aValue value to assign to cell * @param rowIndex row of cell * @param columnIndex column of cell */ public void setValueAt( final Object aValue, final int rowIndex, final int columnIndex ) { value = aValue; fireTableCellUpdated( rowIndex, columnIndex ); } public Class getClassForCell( final int row, final int column ) { return valueType; } public PropertyEditor getEditorForCell( final int row, final int column ) { if ( String.class.equals( valueType ) ) { return null; } return FastPropertyEditorManager.findEditor( valueType ); } public String getValueRole( final int row, final int column ) { return "Value"; // NON-NLS } public void setTableStyle( final TableStyle tableStyle ) { } public TableStyle getTableStyle() { return TableStyle.ASCENDING; } } private ElementMetaDataTable editor; private SingleValueMetaTableModel singleValueMetaTableModel; /** * Creates a new <code>JPanel</code> with a double buffer and a flow layout. */ public DefaultValueEditorPanel() { singleValueMetaTableModel = new SingleValueMetaTableModel(); editor = new InstantEditingTable(); editor.setDefaultRenderer( Boolean.class, new GenericCellRenderer() ); editor.setDefaultEditor( Boolean.class, new DefaultCellEditor( new JComboBox( new Object[] { null, Boolean.TRUE, Boolean.FALSE } ) ) ); editor.setModel( singleValueMetaTableModel ); setLayout( new BorderLayout() ); // Yes, without a scroll-pane, so that the table looks more like a text-field. add( editor, BorderLayout.CENTER ); installDefaults(); } protected void installDefaults() { // stealing the look-and-feel of a plain text-field. final Font f = editor.getFont(); if ( ( f == null ) || ( f instanceof UIResource ) ) { editor.setFont( UIManager.getFont( "TextField.font" ) ); // NON-NLS } final Color bg = editor.getBackground(); if ( ( bg == null ) || ( bg instanceof UIResource ) ) { editor.setBackground( UIManager.getColor( "TextField.background" ) ); // NON-NLS editor.setSelectionBackground( UIManager.getColor( "TextField.background" ) ); // NON-NLS } final Color fg = editor.getForeground(); if ( ( fg == null ) || ( fg instanceof UIResource ) ) { editor.setForeground( UIManager.getColor( "TextField.foreground" ) ); // NON-NLS editor.setSelectionForeground( UIManager.getColor( "TextField.foreground" ) ); // NON-NLS } final Border b = editor.getBorder(); if ( ( b == null ) || ( b instanceof UIResource ) ) { final Insets insets = UIManager.getInsets( "TextField.margin" ); // NON-NLS if ( insets == null ) { editor.setBorder( UIManager.getBorder( "TextField.border" ) ); // NON-NLS } else { editor.setBorder( BorderFactory.createCompoundBorder ( new EmptyBorder( insets ), UIManager.getBorder( "TextField.border" ) ) );//NON-NLS } // NON-NLS editor.setRowMargin( 2 ); editor.setRowHeight( 20 ); } editor.setShowGrid( false ); editor.setShowHorizontalLines( false ); editor.setShowVerticalLines( false ); } public Object getValue() { final TableCellEditor editor1 = editor.getCellEditor(); if ( editor1 != null ) { editor1.stopCellEditing(); } return singleValueMetaTableModel.getValue(); } public void setValue( final Object value, final Class valueType ) { singleValueMetaTableModel.setValue( value, valueType ); } public void setValueType( final Class valueType, final String pattern, final TimeZone timeZone ) { final Object value = singleValueMetaTableModel.getValue(); if ( valueType.isArray() == singleValueMetaTableModel.getValueType().isArray() ) { try { final String oldValueAsString = ConverterRegistry.toAttributeValue( value ); final Object oldValueConverted = ConverterRegistry.toPropertyValue( oldValueAsString, valueType ); singleValueMetaTableModel.setValue( oldValueConverted, valueType ); } catch ( BeanException e ) { singleValueMetaTableModel.setValue( null, valueType ); } } else if ( valueType.isArray() ) { try { final Object array = Array.newInstance( singleValueMetaTableModel.getValueType(), 1 ); Array.set( array, 0, value ); final String oldValueAsString = ConverterRegistry.toAttributeValue( array ); final Object oldValueConverted = ConverterRegistry.toPropertyValue( oldValueAsString, valueType ); singleValueMetaTableModel.setValue( oldValueConverted, valueType ); } catch ( BeanException e ) { singleValueMetaTableModel.setValue( null, valueType ); } } else // last case: metadata-table contains array { try { final String oldValueAsString = ConverterRegistry.toAttributeValue( Array.get( value, 0 ) ); final Object oldValueConverted = ConverterRegistry.toPropertyValue( oldValueAsString, valueType ); singleValueMetaTableModel.setValue( oldValueConverted, valueType ); } catch ( Exception e ) { singleValueMetaTableModel.setValue( null, valueType ); } } editor.applyLocaleSettings( new InjectDatePatternLocaleSettings( valueType, pattern, timeZone ) ); } }