/*
* Copyright 2013 Cenote GmbH.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.cenote.jasperstarter.gui;
import com.toedter.calendar.JCalendar;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.Panel;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.lang.reflect.Constructor;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.BorderFactory;
import javax.swing.InputVerifier;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import javax.swing.UIDefaults;
import net.sf.jasperreports.engine.JRParameter;
import net.sf.jasperreports.engine.util.JRLoader;
/**
*
* @author Volker Voßkämper <vvo at cenote.de>
* @version $Revision$
*/
public class ParameterPanel extends JPanel {
private final JTextField paramValue = new JTextField();
private AtomicBoolean valid;
private int textFieldHeight;
UIDefaults uiDefaults = javax.swing.UIManager.getDefaults();
public ParameterPanel(final JRParameter jrParameter, final Map<String, Object> params,
AtomicBoolean valid) {
this.valid = valid;
this.textFieldHeight = 25;
if ("gnome".equals(System.getProperty("sun.desktop"))) {
// the default font in Gnome needs more space
this.textFieldHeight = 30;
}
this.setLayout(new BorderLayout(10, 5));
this.setMaximumSize(new Dimension(800, 60));
this.add(BorderLayout.NORTH, new javax.swing.JSeparator());
boolean hasStringConstructor;
try {
Constructor<?> c = jrParameter.getValueClass()
.getConstructor(String.class);
hasStringConstructor = true;
} catch (NoSuchMethodException ex) {
hasStringConstructor = false;
} catch (SecurityException ex) {
hasStringConstructor = false;
Logger.getLogger(ParameterPanel.class.getName())
.log(Level.SEVERE, null, ex);
}
JLabel paramName = new JLabel(jrParameter.getName() + " :");
paramName.setPreferredSize(new Dimension(180, 25));
paramName.setMaximumSize(new Dimension(180, 25));
JLabel paramType = new JLabel(jrParameter.getValueClassName());
//paramType.setPreferredSize(new Dimension(200,25));
paramType.setMinimumSize(new Dimension(20, 25));
paramType.setMaximumSize(new Dimension(20, 25));
paramValue.setPreferredSize(new Dimension(30, textFieldHeight));
//paramValue.setMaximumSize(new Dimension(100, 25));
JButton valueButton = new JButton("...");
valueButton.setPreferredSize(
new Dimension(textFieldHeight, textFieldHeight));
JPanel valuePanel = new JPanel();
valuePanel.setLayout(new BorderLayout(0, 0));
valuePanel.setMaximumSize(new Dimension(30, textFieldHeight));
valuePanel.add(BorderLayout.CENTER, paramValue);
paramValue.addActionListener(
new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// validate on KEY Enter (like TAB)
((JComponent) e.getSource()).transferFocus();
}
});
if (Date.class
.equals(jrParameter.getValueClass())) {
paramValue.setInputVerifier(
new DateInputVerifier(jrParameter, params));
if (params.get(jrParameter.getName()) != null) {
Date d = (Date) params.get(jrParameter.getName());
paramValue.setText(DateFormat.getDateInstance().format(d));
}
paramValue.setToolTipText(
"Format: "
+ ((SimpleDateFormat) DateFormat.getDateInstance(DateFormat.MEDIUM)).toPattern());
valueButton.addActionListener(new DateActionListener());
valuePanel.add(BorderLayout.EAST, valueButton);
} else if (Image.class
.equals(jrParameter.getValueClass())) {
paramValue.setInputVerifier(
new ImageInputVerifier(jrParameter, params));
if (params.get(jrParameter.getName()) != null) {
Image image = (Image) params.get(jrParameter.getName());
paramValue.setText(image.toString());
}
paramValue.setToolTipText(
"Relative or full path to image.");
valueButton.addActionListener(new FileActionListener());
valuePanel.add(BorderLayout.EAST, valueButton);
} else if (hasStringConstructor) {
paramValue.setInputVerifier(
new GenericInputVerifier(jrParameter, params));
paramValue.setText((String) params.get(jrParameter.getName()));
} else {
paramValue.setText("<non supported type>");
paramValue.setEnabled(false);
}
JLabel description = new JLabel();
if (jrParameter.getDescription() != null) {
description.setText(jrParameter.getDescription());
description.setMaximumSize(new Dimension(180, 25));
description.setBorder(BorderFactory.createEmptyBorder(0, 0, 5, 0));
}
this.add(BorderLayout.WEST, paramName);
this.add(BorderLayout.CENTER, valuePanel);
this.add(BorderLayout.EAST, paramType);
this.add(BorderLayout.SOUTH, description);
}
private class DateInputVerifier extends ParameterInputVerifier {
DateInputVerifier(JRParameter jrParameter, Map<String, Object> params) {
super(jrParameter, params);
}
@Override
public boolean verify(JComponent input) {
String text = ((JTextField) input).getText();
try {
Object o = null;
if (!text.equals("")) {
o = DateFormat.getDateInstance().parse(text);
((JTextField) input).setText(DateFormat.getDateInstance()
.format((Date) o));
}
//System.out.println("DateInputVerifier: ok");
params.put(jrParameter.getName(), o);
input.setBackground(uiDefaults.getColor("TextField.background"));
valid.set(true);
return true;
} catch (ParseException e) {
//System.err.println("DateInputVerifier: exception");
input.setBackground(Color.RED);
((JTextField) input).selectAll();
Toolkit.getDefaultToolkit().beep();
valid.set(false);
return false;
}
}
}
private class ImageInputVerifier extends ParameterInputVerifier {
ImageInputVerifier(JRParameter jrParameter, Map<String, Object> params) {
super(jrParameter, params);
}
@Override
public boolean verify(JComponent input) {
String text = ((JTextField) input).getText();
try {
Object o = null;
Image imageParam = (Image) params.get(jrParameter.getName());
String imageName = "";
if (imageParam != null) {
imageName = imageParam.toString();
}
if (!text.equals("") & !text.equals(imageName)) {
File imageFile = new File(text);
if (!imageFile.isFile()) {
throw new IllegalArgumentException(imageFile.getName()
+ "is not a valid file.");
}
Image image =
Toolkit.getDefaultToolkit().createImage(
JRLoader.loadBytes(imageFile));
MediaTracker traker = new MediaTracker(new Panel());
traker.addImage(image, 0);
try {
traker.waitForID(0);
} catch (Exception e) {
throw new IllegalArgumentException(
"Image tracker error: " + e.getMessage(), e);
}
o = image;
((JTextField) input).setText(imageFile.getAbsolutePath());
}
//System.out.println("ImageInputVerifier: OK");
if (!text.equals(imageName)) {
// don't overwrite a given image
params.put(jrParameter.getName(), o);
}
input.setBackground(uiDefaults.getColor("TextField.background"));
valid.set(true);
return true;
} catch (Exception e) {
//System.err.println("ImageInputVerifier: exception");
input.setBackground(Color.RED);
((JTextField) input).selectAll();
Toolkit.getDefaultToolkit().beep();
valid.set(false);
return false;
}
}
}
private class GenericInputVerifier extends ParameterInputVerifier {
GenericInputVerifier(JRParameter jrParameter, Map<String, Object> params) {
super(jrParameter, params);
}
@Override
public boolean verify(JComponent input) {
String text = ((JTextField) input).getText();
try {
Object o = null;
if (!text.equals("")) {
o = jrParameter.getValueClass().getConstructor(String.class)
.newInstance(text);
((JTextField) input).setText(o.toString());
}
//System.out.println("GenericInputVerifier: ok");
params.put(jrParameter.getName(), o);
input.setBackground(uiDefaults.getColor("TextField.background"));
valid.set(true);
return true;
} catch (Exception e) {
//System.err.println("GenericInputVerifier: exception");
input.setBackground(Color.RED);
((JTextField) input).selectAll();
Toolkit.getDefaultToolkit().beep();
valid.set(false);
return false;
}
}
}
private abstract class ParameterInputVerifier extends InputVerifier {
JRParameter jrParameter;
Map<String, Object> params;
ParameterInputVerifier(JRParameter jrParameter, Map<String, Object> params) {
this.jrParameter = jrParameter;
this.params = params;
}
@Override
public abstract boolean verify(JComponent input);
}
private class FileActionListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
final JFileChooser fc = new JFileChooser();
File file;
file = new File(paramValue.getText());
if (file.isFile()) {
fc.setSelectedFile(file);
}
int returnVal = fc.showOpenDialog((Component) e.getSource());
if (returnVal == JFileChooser.APPROVE_OPTION) {
file = fc.getSelectedFile();
paramValue.setText(file.getAbsolutePath());
// trigger a InputVerifier.verify() and move to next component
// (like KEY Enter or TAB)
paramValue.requestFocusInWindow();
((JComponent) e.getSource()).requestFocusInWindow();
((JComponent) e.getSource()).transferFocus();
}
}
}
private class DateActionListener implements ActionListener {
JLabel selectedDate;
@Override
public void actionPerformed(ActionEvent e) {
final JCalendar cal;
if (!paramValue.getText().equals("")) {
Date date;
try {
date = DateFormat.getDateInstance().parse(paramValue.getText());
} catch (ParseException ex) {
date = new Date();
}
cal = new JCalendar(date);
} else {
cal = new JCalendar();
}
cal.setDecorationBackgroundColor(Color.LIGHT_GRAY);
cal.setBorder(BorderFactory.createEtchedBorder());
JPanel calpanel = new JPanel(new BorderLayout(0, 5));
JPanel buttonpanel = new JPanel(new BorderLayout(0, 0));
buttonpanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 10, 0));
JButton prev = new JButton("<");
JButton next = new JButton(">");
JButton today = new JButton(
DateFormat.getDateInstance(
DateFormat.MEDIUM).format(new Date()));
prev.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
//cal.getMonthChooser().getMonth();
if (cal.getMonthChooser().getMonth() == 0) {
cal.getYearChooser().setYear(cal.getYearChooser().getYear() - 1);
cal.getMonthChooser().setMonth(11);
} else {
cal.getMonthChooser().setMonth(cal.getMonthChooser().getMonth() - 1);
}
}
});
next.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (cal.getMonthChooser().getMonth() == 11) {
cal.getYearChooser().setYear(cal.getYearChooser().getYear() + 1);
cal.getMonthChooser().setMonth(0);
} else {
cal.getMonthChooser().setMonth(cal.getMonthChooser().getMonth() + 1);
}
}
});
today.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
cal.setDate(new Date());
}
});
selectedDate = new JLabel();
selectedDate.setHorizontalAlignment(SwingConstants.CENTER);
selectedDate.setFont(new Font("sansserif", Font.BOLD, 16));
//cal.getDayChooser().addPropertyChangeListener();
cal.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
selectedDate.setText(DateFormat.getDateInstance(
DateFormat.MEDIUM).format(cal.getDate()));
}
});
buttonpanel.add(BorderLayout.WEST, prev);
buttonpanel.add(BorderLayout.CENTER, today);
buttonpanel.add(BorderLayout.EAST, next);
calpanel.add(BorderLayout.NORTH, selectedDate);
calpanel.add(BorderLayout.CENTER, cal);
calpanel.add(BorderLayout.SOUTH, buttonpanel);
int retval =
JOptionPane.showConfirmDialog((Component) e.getSource(), calpanel,
"JasperStarter - Date Picker ",
JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE);
if (retval == JOptionPane.OK_OPTION) {
paramValue.setText(DateFormat.getDateInstance().format(cal.getDate()));
// trigger a InputVerifier.verify() and move to next component
// (like KEY Enter or TAB)
paramValue.requestFocusInWindow();
((JComponent) e.getSource()).requestFocusInWindow();
((JComponent) e.getSource()).transferFocus();
}
}
}
}