/****************************************************************************** * Product: Adempiere ERP & CRM Smart Business Solution * * Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * * under the terms version 2 of the GNU General Public License as published * * by the Free Software Foundation. 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 General Public License for more details. * * You should have received a copy of the GNU General Public License along * * with this program; if not, write to the Free Software Foundation, Inc., * * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * * For the text or an alternative of this public license, you may reach us * * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * * or via info@compiere.org or http://www.compiere.org/license.html * *****************************************************************************/ package org.compiere.grid.ed; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.Container; import java.awt.Dimension; import java.awt.Frame; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.awt.event.MouseEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyVetoException; import java.sql.Timestamp; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.logging.Level; import javax.swing.JComponent; import javax.swing.JPopupMenu; import javax.swing.JTextField; import javax.swing.LookAndFeel; import javax.swing.SwingUtilities; import javax.swing.text.Document; import org.adempiere.plaf.AdempierePLAF; import org.compiere.apps.AEnv; import org.compiere.apps.FieldRecordInfo; import org.compiere.model.GridField; import org.compiere.model.MRole; import org.compiere.swing.CButton; import org.compiere.swing.CTextField; import org.compiere.util.CLogger; import org.compiere.util.DisplayType; import org.compiere.util.Env; import org.omidp.util.LocaleUtil; import org.omidp.util.PersianCalendar; /** * Date Edit. * Maintains data as Timestamp * * @author Jorg Janke * @version $Id: VDate.java,v 1.2 2006/07/30 00:51:28 jjanke Exp $ */ public class VDate extends JComponent implements VEditor, ActionListener, KeyListener, FocusListener { /** * */ private static final long serialVersionUID = 5265412413586160999L; /***************************************************************************** * Mouse Listener for Popup Menu */ class VDate_mouseAdapter extends java.awt.event.MouseAdapter { /** * Constructor * @param adaptee adaptee */ VDate_mouseAdapter(VDate adaptee) { this.adaptee = adaptee; } // VLookup_mouseAdapter private VDate adaptee; /** * Mouse Listener * @param e MouseEvent */ public void mouseClicked(MouseEvent e) { // System.out.println("mouseClicked " + e.getID() + " " + e.getSource().getClass().toString()); // popup menu if (SwingUtilities.isRightMouseButton(e)) adaptee.popupMenu.show((Component)e.getSource(), e.getX(), e.getY()); } // mouse Clicked } // VLookup_mouseAdapter /** * IDE Bean Constructor */ public VDate() { this (DisplayType.Date); } // VDate /** * Simple Constructor * @param displayType display Type */ public VDate (int displayType) { this("Date", false, false, true, displayType, "Date"); } // VDate /** * Create right aligned Date field * @param columnName column name * @param mandatory mandatory * @param isReadOnly read only * @param isUpdateable updateable * @param displayType display type * @param title title */ public VDate(String columnName, boolean mandatory, boolean isReadOnly, boolean isUpdateable, int displayType, String title) { super(); super.setName(columnName); m_columnName = columnName; m_title = title; // LookAndFeel.installBorder(this, "TextField.border"); this.setLayout(new BorderLayout()); this.setFocusable(false); // Size this.setPreferredSize(m_text.getPreferredSize()); int height = m_text.getPreferredSize().height; setMinimumSize(new Dimension (30,height)); VDate_mouseAdapter mouse = new VDate_mouseAdapter(this); // popup m_text.addMouseListener(mouse); // *** Text *** m_text.setBorder(null); m_text.setHorizontalAlignment(JTextField.TRAILING); if (m_displayType == DisplayType.Date) { m_text.addFocusListener(this); m_text.addKeyListener(this); m_text.setCaret(new VOvrCaret()); } else if (m_displayType == DisplayType.DateTime) m_text.setColumns(20); // Background setMandatory(mandatory); this.add(m_text, BorderLayout.CENTER); // if (displayType == DisplayType.DateTime || displayType == DisplayType.Time) m_displayType = displayType; // default = Date setFormat(); // *** Button *** m_button.setIcon(Env.getImageIcon("Calendar10.gif")); m_button.setMargin(new Insets(0, 0, 0, 0)); m_button.setPreferredSize(new Dimension(height, height)); m_button.addActionListener(this); m_button.setFocusable(false); this.add(m_button, BorderLayout.EAST); // Prefereed Size this.setPreferredSize(this.getPreferredSize()); // causes r/o to be the same length // ReadWrite if (isReadOnly || !isUpdateable) setReadWrite(false); else setReadWrite(true); } // VDate /** * Dispose */ public void dispose() { m_text = null; m_button = null; m_mField = null; } // dispose /** * Set Document * @param doc doc */ protected void setDocument(Document doc) { m_text.setDocument(doc); } // getDocument private String m_columnName; protected int m_displayType = DisplayType.Date; private String m_title; private boolean m_setting; private String m_oldText; private String m_initialText; // private SimpleDateFormat m_format; // private boolean m_readWrite; private boolean m_mandatory; /** The Text Field */ private CTextField m_text = new CTextField (12); /** The Button */ private CButton m_button = new CButton(); // Popup JPopupMenu popupMenu = new JPopupMenu(); // Field for Value Preference private GridField m_mField = null; /** Logger */ private static CLogger log = CLogger.getCLogger(VDate.class); /** * Set ReadWrite - field is always r/o for Time or DateTime * @param value value */ public void setReadWrite (boolean value) { m_readWrite = value; // this.setFocusable(value); // editor if (m_displayType == DisplayType.Date) m_text.setReadWrite(value); // sets Background else { m_text.setEditable(false); m_text.setFocusable(false); setBackground(false); } // Don't show button if not ReadWrite if (m_button.isVisible() != value) m_button.setVisible(value); if (m_button.isEnabled() != value) m_button.setEnabled(value); } // setReadWrite /** * IsReadWrite * @return true if rw */ public boolean isReadWrite() { return m_readWrite; } // isReadWrite /** * Set Mandatory (and back bolor) * @param mandatory mandatory */ public void setMandatory (boolean mandatory) { m_mandatory = mandatory; m_text.setMandatory(mandatory); setBackground(false); } // setMandatory /** * Is it mandatory * @return true if mandatory */ public boolean isMandatory() { return m_mandatory; } // isMandatory /** * Set Background based on ReadWrite / mandatory / error * @param error if true, set background to error color, otherwise mandatory/ReadWrite */ public void setBackground (boolean error) { if (error) m_text.setBackground(AdempierePLAF.getFieldBackground_Error()); else if (!m_readWrite) m_text.setBackground(AdempierePLAF.getFieldBackground_Inactive()); else if (m_mandatory) m_text.setBackground(AdempierePLAF.getFieldBackground_Mandatory()); else m_text.setBackground(AdempierePLAF.getFieldBackground_Normal()); } // setBackground /** * Set Foreground * @param fg color */ public void setForeground(Color fg) { m_text.setForeground(fg); } // setForeground /** * Set Format * Required when Format/Locale changed */ public void setFormat() { m_format = DisplayType.getDateFormat(m_displayType); if (m_displayType == DisplayType.Date) m_text.setDocument(new MDocDate(m_displayType, m_format, m_text, m_title)); } // setFormat /** * Request Focus */ public void requestFocus () { m_text.requestFocus (); } // requestFocus /** * Set Editor to value * @param value timestamp/date or String to be parsed */ public void setValue (Object value) { log.finest("Value=" + value); m_oldText = ""; if (value == null) ; else if (value instanceof java.util.Date) m_oldText = LocaleUtil.isIranLocale() ? new PersianCalendar().GregorianToSolar(m_format.format(value)) : m_format.format(value) ; else { String strValue = value.toString(); // String values - most likely in YYYY-MM-DD (JDBC format) try { java.util.Date date = DisplayType.getDateFormat_JDBC().parse (strValue); m_oldText = m_format.format(date); // convert to display value } catch (ParseException pe0) { // Try local string format try { java.util.Date date = m_format.parse(strValue); m_oldText = m_format.format(date); } catch (ParseException pe1) { log.log(Level.SEVERE, "setValue - " + pe1.getMessage()); m_oldText = ""; } } } if (m_setting) return; m_text.setText(m_oldText); m_initialText = m_oldText; } // setValue /** * Property Change Listener * @param evt event */ public void propertyChange (PropertyChangeEvent evt) { if (evt.getPropertyName().equals(GridField.PROPERTY)) setValue(evt.getNewValue()); } // propertyChange /** * Return Editor value * @return value */ public Timestamp getTimestamp() { if (m_text == null) return null; String value = m_text.getText(); if (value == null || value.length() == 0) return null; if (LocaleUtil.isIranLocale()) { PersianCalendar pc = new PersianCalendar(); value = pc.SolarToGregorian(value.toString()); } // Timestamp ts = null; try { java.util.Date date = m_format.parse(value); ts = new Timestamp(date.getTime()); } catch (ParseException pe) { log.fine(pe.getMessage()); } return ts; } // getValue /** * Return Editor value (Timestamp) * @return value */ public Object getValue() { return getTimestamp(); } // getValue /** * Return Display Value * @return display value */ public String getDisplay() { return m_text.getText(); } // getDisplay /************************************************************************** * Action Listener (Button) * @param e event */ public void actionPerformed (ActionEvent e) { // Preference if (e.getActionCommand().equals(ValuePreference.NAME)) { if (MRole.getDefault().isShowPreference()) ValuePreference.start (m_mField, getValue(), getDisplay()); return; } else if (e.getActionCommand().equals(FieldRecordInfo.CHANGE_LOG_COMMAND)) { FieldRecordInfo.start(m_mField); return; } if (e.getSource() == m_button) { m_button.setEnabled(false); setValue(startCalendar(this, getTimestamp(), m_format, m_displayType, m_title)); try { fireVetoableChange (m_columnName, m_oldText, getValue()); } catch (PropertyVetoException pve) {} m_button.setEnabled(true); m_text.requestFocus(); } } // actionPerformed /** * Action Listener Interface (Text) * @param listener listener */// addActionListener /************************************************************************** * Key Listener Interface * @param e Event */ public void keyTyped(KeyEvent e) {} public void keyPressed(KeyEvent e) {} /** * Key Listener. * - Escape - Restore old Text * - firstChange - signal change * @param e event */ public void keyReleased(KeyEvent e) { log.finest("Key=" + e.getKeyCode() + " - " + e.getKeyChar() + " -> " + m_text.getText()); // ESC if (e.getKeyCode() == KeyEvent.VK_ESCAPE) m_text.setText(m_initialText); } // keyReleased /** * Focus Gained - Save for Escape * @param e event */ public void focusGained (FocusEvent e) { } // focusGained /** * Data Binding to to GridController. * @param e event */ public void focusLost (FocusEvent e) { m_setting = true; try { Timestamp ts = getTimestamp(); // getValue if (ts == null) // format error - just indicate change fireVetoableChange (m_columnName, m_oldText, null); else fireVetoableChange (m_columnName, m_oldText, ts); } catch (PropertyVetoException pve) {} m_setting = false; // did not get Focus first if (e.isTemporary()) return; // log.config( "VDate.focusLost"); if (m_text == null || m_text.getText() == null) return; Object value = getValue(); if (value == null && isMandatory() ) { // teo_sarca [ 1660595 ] Date field: incorrect functionality on paste // setValue(startCalendar(this, getTimestamp(), m_format, m_displayType, m_title)); Timestamp ts = startCalendar(this, getTimestamp(), m_format, m_displayType, m_title); if (ts != null) { setValue(ts); } else { setValue(m_oldText); } } else setValue(value); } // focusLost /** * Invalid Entry - Start Calendar * @param jc parent * @param value value * @param format format * @param displayType display type * @param title title * @return formatted Date */ public static Timestamp startCalendar(Container jc, Timestamp value, SimpleDateFormat format, int displayType, String title) { log.config("Date=" + value); // Find frame Frame frame = Env.getFrame(jc); // Actual Call Calendar cal = new Calendar(frame, title, value, displayType); AEnv.showCenterWindow(frame, cal); Timestamp result = cal.getTimestamp(); log.config( "Result=" + result); if (result == null) result = value; // original else if (result.compareTo(new Timestamp(-1))==0) result = null; cal = null; return result; } // startCalendar /** * Set Field/WindowNo for ValuePreference * @param mField MField */ public void setField (GridField mField) { m_mField = mField; if (m_mField != null && MRole.getDefault().isShowPreference()) ValuePreference.addMenu (this, popupMenu); if (m_mField != null) FieldRecordInfo.addMenu(this, popupMenu); } // setField @Override public GridField getField() { return m_mField; } /** * Set Enabled * @param enabled enabled */ public void setEnabled (boolean enabled) { super.setEnabled(enabled); m_text.setEnabled(enabled); m_button.setEnabled(enabled); if (enabled) m_button.setReadWrite(m_readWrite); } // setEnabled /************************************************************************** * Remove Action Listner * @param l Action Listener */ public void removeActionListener(ActionListener l) { listenerList.remove(ActionListener.class, l); } // removeActionListener /** * Add Action Listner * @param l Action Listener */ public void addActionListener(ActionListener l) { listenerList.add(ActionListener.class, l); } // addActionListener /** * Fire Action Event to listeners * protected void fireActionPerformed() { int modifiers = 0; AWTEvent currentEvent = EventQueue.getCurrentEvent(); if (currentEvent instanceof InputEvent) modifiers = ((InputEvent)currentEvent).getModifiers(); else if (currentEvent instanceof ActionEvent) modifiers = ((ActionEvent)currentEvent).getModifiers(); ActionEvent ae = new ActionEvent (this, ActionEvent.ACTION_PERFORMED, "VDate", EventQueue.getMostRecentEventTime(), modifiers); // Guaranteed to return a non-null array Object[] listeners = listenerList.getListenerList(); // Process the listeners last to first, notifying those that are interested in this event for (int i = listeners.length-2; i>=0; i-=2) { if (listeners[i]==ActionListener.class) { ((ActionListener)listeners[i+1]).actionPerformed(ae); } } } // fireActionPerformed /**/ @Override public void setBackground(Color bg) { m_text.setBackground(bg); } } // VDate