/*!
* 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.libraries.designtime.swing.table;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.pentaho.reporting.libraries.base.util.StringUtils;
import org.pentaho.reporting.libraries.designtime.swing.FormattingTableCellRenderer;
import org.pentaho.reporting.libraries.designtime.swing.GenericCellEditor;
import org.pentaho.reporting.libraries.designtime.swing.GenericCellRenderer;
import org.pentaho.reporting.libraries.designtime.swing.PaintCellRenderer;
import org.pentaho.reporting.libraries.designtime.swing.date.DateCellEditor;
import org.pentaho.reporting.libraries.designtime.swing.date.TimeCellEditor;
import org.pentaho.reporting.libraries.designtime.swing.propertyeditors.PropertyCellEditorWithEllipsis;
import org.pentaho.reporting.libraries.designtime.swing.propertyeditors.PropertyEditorCellEditor;
import org.pentaho.reporting.libraries.designtime.swing.propertyeditors.PropertyEditorCellRenderer;
import org.pentaho.reporting.libraries.designtime.swing.settings.LocaleSettings;
import javax.swing.*;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableModel;
import java.awt.*;
import java.beans.PropertyEditor;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Time;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
public class PropertyTable extends JTable {
public static final String DATETIME_FORMAT_DEFAULT = "yyyy-MM-dd HH:mm:ss.SSSS";
public static final String TIME_FORMAT_DEFAULT = "HH:mm:ss.SSSS";
public static final String DATE_FORMAT_DEFAULT = "yyyy-MM-dd";
private static Log logger = LogFactory.getLog( PropertyTable.class );
private PropertyEditorCellRenderer propertyEditorCellRenderer;
private PropertyCellEditorWithEllipsis propertyEditorCellEditor;
private PropertyEditorCellEditor taggedPropertyEditorCellEditor;
private ArrayCellRenderer arrayCellRenderer;
private ArrayCellEditor arrayCellEditor;
public PropertyTable() {
putClientProperty( "terminateEditOnFocusLost", Boolean.TRUE );
this.setShowHorizontalLines( true );
this.setShowVerticalLines( true );
this.setGridColor( SystemColor.controlShadow );
taggedPropertyEditorCellEditor = new PropertyEditorCellEditor();
propertyEditorCellEditor = new PropertyCellEditorWithEllipsis();
propertyEditorCellRenderer = new PropertyEditorCellRenderer();
arrayCellRenderer = new ArrayCellRenderer();
arrayCellEditor = new ArrayCellEditor();
setDefaultEditor( Object.class, null );
setDefaultEditor( Number.class, new GenericCellEditor( BigDecimal.class ) );
setDefaultEditor( Integer.class, new GenericCellEditor( Integer.class ) );
setDefaultEditor( Float.class, new GenericCellEditor( Float.class ) );
setDefaultEditor( Double.class, new GenericCellEditor( Double.class ) );
setDefaultEditor( Short.class, new GenericCellEditor( Short.class ) );
setDefaultEditor( Byte.class, new GenericCellEditor( Byte.class ) );
setDefaultEditor( Long.class, new GenericCellEditor( Long.class ) );
setDefaultEditor( BigInteger.class, new GenericCellEditor( BigInteger.class ) );
setDefaultEditor( BigDecimal.class, new GenericCellEditor( BigDecimal.class ) );
setDefaultEditor( String.class, new GenericCellEditor( String.class ) );
setDefaultEditor( Date.class, new DateCellEditor( Date.class ) );
setDefaultEditor( java.sql.Date.class, new DateCellEditor( Date.class ) );
setDefaultEditor( Time.class, new TimeCellEditor( Time.class ) );
setDefaultEditor( Timestamp.class, new DateCellEditor( Timestamp.class ) );
setDefaultRenderer( Paint.class, new PaintCellRenderer() );
setDefaultRenderer( Object.class, new GenericCellRenderer() );
setDefaultRenderer( String.class, new GenericCellRenderer() );
final SimpleDateFormat isoDateFormat =
new SimpleDateFormat( DATETIME_FORMAT_DEFAULT, Locale.ENGLISH );
setDefaultRenderer( Date.class, new FormattingTableCellRenderer( isoDateFormat ) );
setDefaultRenderer( java.sql.Date.class, new FormattingTableCellRenderer
( new SimpleDateFormat( DATE_FORMAT_DEFAULT, Locale.ENGLISH ) ) );
setDefaultRenderer( Time.class, new FormattingTableCellRenderer
( new SimpleDateFormat( TIME_FORMAT_DEFAULT, Locale.ENGLISH ) ) );
setDefaultRenderer( Timestamp.class, new FormattingTableCellRenderer( isoDateFormat ) );
}
public PropertyTable( final TableModel dm ) {
this();
setModel( dm );
}
private static SimpleDateFormat createSafely( final String pattern, final String defaultPattern,
final Locale locale ) {
try {
if ( StringUtils.isEmpty( pattern ) == false ) {
return new SimpleDateFormat( pattern, locale );
}
} catch ( Exception e ) {
logger.warn( "Invalid format string found in locale settings", e ); // NON-NLS
}
return new SimpleDateFormat( defaultPattern, locale );
}
public void applyLocaleSettings( final LocaleSettings localeSettings ) {
final SimpleDateFormat isoDateFormat = createSafely( localeSettings.getDatetimeFormatPattern(),
DATETIME_FORMAT_DEFAULT, localeSettings.getLocale() );
final TimeZone timeZone = localeSettings.getTimeZone();
isoDateFormat.setTimeZone( timeZone );
setDefaultRenderer( Date.class, new FormattingTableCellRenderer( isoDateFormat ) );
setDefaultRenderer( Timestamp.class, new FormattingTableCellRenderer( isoDateFormat ) );
final DateCellEditor dateCellEditor = new DateCellEditor( Date.class );
dateCellEditor.setDateFormat( isoDateFormat );
setDefaultEditor( Date.class, dateCellEditor );
final DateCellEditor timestampEditor = new DateCellEditor( Timestamp.class );
timestampEditor.setDateFormat( isoDateFormat );
setDefaultEditor( Timestamp.class, timestampEditor );
final SimpleDateFormat dateFormat = createSafely( localeSettings.getDateFormatPattern(),
DATE_FORMAT_DEFAULT, localeSettings.getLocale() );
dateFormat.setTimeZone( timeZone );
setDefaultRenderer( java.sql.Date.class, new FormattingTableCellRenderer( dateFormat ) );
final DateCellEditor sqlDateCellEditor = new DateCellEditor( java.sql.Date.class );
sqlDateCellEditor.setDateFormat( dateFormat );
setDefaultEditor( java.sql.Date.class, sqlDateCellEditor );
final SimpleDateFormat timeFormat = createSafely( localeSettings.getTimeFormatPattern(),
TIME_FORMAT_DEFAULT, localeSettings.getLocale() );
timeFormat.setTimeZone( timeZone );
setDefaultRenderer( Time.class, new FormattingTableCellRenderer( timeFormat ) );
final TimeCellEditor timeCellEditor = new TimeCellEditor( Time.class );
timeCellEditor.setDateFormat( timeFormat );
setDefaultEditor( Time.class, timeCellEditor );
}
public boolean isCellEditable( final int row, final int column ) {
final int columnIndex = convertColumnIndexToModel( column );
if ( getModel().isCellEditable( row, columnIndex ) ) {
if ( getCellEditor( row, columnIndex ) == null ) {
// no editor, so not editable ...
return false;
}
return true;
}
return false;
}
public TableCellRenderer getCellRenderer( final int row, final int viewColumn ) {
final TableModel tableModel = getModel();
if ( tableModel instanceof PropertyTableModel ) {
final PropertyTableModel model = (PropertyTableModel) getModel();
final int column = convertColumnIndexToModel( viewColumn );
final Class columnClass = model.getClassForCell( row, column );
if ( columnClass.isArray() ) {
return arrayCellRenderer;
}
final PropertyEditor propertyEditor = model.getEditorForCell( row, column );
if ( propertyEditor != null ) {
propertyEditorCellRenderer.setPropertyEditor( propertyEditor );
return propertyEditorCellRenderer;
}
final TableColumn tableColumn = getColumnModel().getColumn( column );
final TableCellRenderer renderer = tableColumn.getCellRenderer();
if ( renderer != null ) {
return renderer;
}
final TableCellRenderer defaultRenderer = getDefaultRenderer( columnClass );
if ( defaultRenderer != null ) {
return defaultRenderer;
}
if ( logger.isTraceEnabled() ) {
logger.trace( "No renderer for column class " + columnClass ); // NON-NLS
}
return getDefaultRenderer( Object.class );
}
return super.getCellRenderer( row, viewColumn );
}
public TableCellEditor getCellEditor( final int row, final int viewColumn ) {
final TableModel tableModel = getModel();
if ( tableModel instanceof PropertyTableModel ) {
final PropertyTableModel model = (PropertyTableModel) getModel();
final int column = convertColumnIndexToModel( viewColumn );
final PropertyEditor propertyEditor = model.getEditorForCell( row, column );
final Class columnClass = model.getClassForCell( row, column );
if ( propertyEditor != null ) {
final String[] tags = propertyEditor.getTags();
if ( columnClass.isArray() ) {
arrayCellEditor.setPropertyEditorType( propertyEditor.getClass() );
} else if ( tags == null || tags.length == 0 ) {
propertyEditorCellEditor.setPropertyEditor( propertyEditor );
return propertyEditorCellEditor;
} else {
taggedPropertyEditorCellEditor.setPropertyEditor( propertyEditor );
return taggedPropertyEditorCellEditor;
}
}
final TableColumn tableColumn = getColumnModel().getColumn( column );
final TableCellEditor renderer = tableColumn.getCellEditor();
if ( renderer != null ) {
return renderer;
}
if ( columnClass.isArray() ) {
return arrayCellEditor;
}
final TableCellEditor editor = getDefaultEditor( columnClass );
if ( editor != null && logger.isTraceEnabled() ) {
logger.trace( "Using preconfigured default editor for column class " + columnClass + ": " + editor ); // NON-NLS
}
return editor;
}
return super.getCellEditor( row, viewColumn );
}
public void stopEditing() {
final TableCellEditor cellEditor = getCellEditor();
if ( cellEditor != null ) {
cellEditor.stopCellEditing();
}
}
}