/*!
* 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.engine.classic.core.modules.gui.base.parameters;
import java.awt.Color;
import java.awt.SystemColor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.Format;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.JTextComponent;
import org.pentaho.reporting.engine.classic.core.util.beans.BeanException;
import org.pentaho.reporting.engine.classic.core.util.beans.ConverterRegistry;
public class TextComponentEditHandler implements Runnable, DocumentListener, ActionListener {
private Class type;
private String keyName;
private JTextComponent textComponent;
private ParameterUpdateContext updateContext;
private Format formatter;
private Color color;
private boolean inProgress;
private boolean adjustingToExternalInput;
public TextComponentEditHandler( final Class type, final String keyName, final JTextComponent textComponent,
final ParameterUpdateContext updateContext, final Format formatter ) {
this.type = type;
this.keyName = keyName;
this.textComponent = textComponent;
this.updateContext = updateContext;
this.formatter = formatter;
this.color = this.textComponent.getBackground();
if ( color == null ) {
color = SystemColor.text;
}
}
public boolean isAdjustingToExternalInput() {
return adjustingToExternalInput;
}
public void setAdjustingToExternalInput( final boolean adjustingToExternalInput ) {
this.adjustingToExternalInput = adjustingToExternalInput;
}
protected Class getType() {
return type;
}
/**
* Gives notification that there was an insert into the document. The range given by the DocumentEvent bounds the
* freshly inserted region.
*
* @param e
* the document event
*/
public void insertUpdate( final DocumentEvent e ) {
convertParameterValue();
}
/**
* Gives notification that a portion of the document has been removed. The range is given in terms of what the view
* last saw (that is, before updating sticky positions).
*
* @param e
* the document event
*/
public void removeUpdate( final DocumentEvent e ) {
convertParameterValue();
}
/**
* Gives notification that an attribute or set of attributes changed.
*
* @param e
* the document event
*/
public void changedUpdate( final DocumentEvent e ) {
convertParameterValue();
}
private void convertParameterValue() {
if ( inProgress ) {
return;
}
inProgress = true;
SwingUtilities.invokeLater( this );
}
public void run() {
convert( false );
}
protected void convert( final boolean autoUpdate ) {
try {
final String text = textComponent.getText();
textComponent.setBackground( color );
updateContext.setParameterValue( keyName, convertValue( text ), autoUpdate );
} catch ( BeanException e ) {
// ignore, do not update (yet).
textComponent.setBackground( Color.RED );
} finally {
inProgress = false;
}
}
protected Object convertValue( final String text ) throws BeanException {
if ( text == null ) {
return null;
}
if ( formatter != null ) {
try {
final Object o = formatter.parseObject( text );
// this magic converts the date or number value to the real type.
// the formatter always returns doubles/bigdecimals or java.util.Dates
// but we may need sql-dates, long-objects etc ..
final String asText = ConverterRegistry.toAttributeValue( o );
return ConverterRegistry.toPropertyValue( asText, getType() );
} catch ( ParseException e ) {
throw new BeanException( "Failed to format object" );
}
}
if ( Object.class == type || String.class == type ) {
return text;
}
return ConverterRegistry.toPropertyValue( text, type );
}
/**
* Invoked when an action occurs.
*/
public void actionPerformed( final ActionEvent e ) {
convert( true );
}
public static TimeZone createTimeZone( final String selectedItem, final TimeZone defaultValue ) {
if ( selectedItem == null ) {
return defaultValue;
}
if ( "server".equals( selectedItem ) || "client".equals( selectedItem ) ) {
return defaultValue;
}
final String id = String.valueOf( selectedItem );
if ( "utc".equals( id ) ) {
return TimeZone.getTimeZone( "UTC" );
}
final TimeZone timeZone = TimeZone.getTimeZone( id );
if ( "GMT".equals( timeZone.getID() ) && "GMT".equals( id ) == false ) {
// Handle timezones that are not understood by the current JVM.
return defaultValue;
}
return timeZone;
}
public static Format createFormat( final String formatString, final Locale locale, final TimeZone timeZone,
final Class parameterType ) {
if ( formatString == null || parameterType == null ) {
return null;
}
if ( Number.class.isAssignableFrom( parameterType ) ) {
try {
final DecimalFormat decimalFormat = new DecimalFormat( formatString, new DecimalFormatSymbols( locale ) );
decimalFormat.setParseBigDecimal( true );
return decimalFormat;
} catch ( Exception e ) {
// well, seems that was not a number format then ...
}
}
if ( Date.class.isAssignableFrom( parameterType ) ) {
try {
final SimpleDateFormat dateFormat = new SimpleDateFormat( formatString, locale );
dateFormat.setLenient( false );
dateFormat.setTimeZone( timeZone );
return dateFormat;
} catch ( Exception e ) {
// well, seems that was not a date format either ...
}
}
return null;
}
}