Java tutorial
/* Copyright (C) 2015, University of Kansas Center for Research * * Specify Software Project, specify@ku.edu, Biodiversity Institute, * 1345 Jayhawk Boulevard, Lawrence, Kansas, 66045, USA * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ package edu.ku.brc.specify.plugins; import static edu.ku.brc.ui.UIHelper.createComboBox; import static edu.ku.brc.ui.UIRegistry.loadAndPushResourceBundle; import static edu.ku.brc.ui.UIRegistry.popResourceBundle; import java.awt.CardLayout; import java.awt.Component; import java.awt.Font; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.List; import java.util.Properties; import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JTextField; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.event.DocumentEvent; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import com.jgoodies.forms.builder.PanelBuilder; import com.jgoodies.forms.layout.CellConstraints; import com.jgoodies.forms.layout.FormLayout; import edu.ku.brc.af.core.db.DBFieldInfo; import edu.ku.brc.af.core.db.DBTableIdMgr; import edu.ku.brc.af.core.db.DBTableInfo; import edu.ku.brc.af.prefs.AppPrefsCache; import edu.ku.brc.af.ui.forms.DataObjectGettable; import edu.ku.brc.af.ui.forms.DataObjectGettableFactory; import edu.ku.brc.af.ui.forms.DataObjectSettable; import edu.ku.brc.af.ui.forms.DataObjectSettableFactory; import edu.ku.brc.af.ui.forms.FormHelper; import edu.ku.brc.af.ui.forms.FormViewObj; import edu.ku.brc.af.ui.forms.UIPluginable; import edu.ku.brc.af.ui.forms.ViewFactory; import edu.ku.brc.af.ui.forms.formatters.UIFieldFormatter; import edu.ku.brc.af.ui.forms.formatters.UIFieldFormatterIFace; import edu.ku.brc.af.ui.forms.formatters.UIFieldFormatterMgr; import edu.ku.brc.af.ui.forms.validation.UIValidatable; import edu.ku.brc.af.ui.forms.validation.ValFormattedTextField; import edu.ku.brc.af.ui.forms.validation.ValFormattedTextFieldSingle; import edu.ku.brc.ui.DateWrapper; import edu.ku.brc.ui.DocumentAdaptor; import edu.ku.brc.ui.GetSetValueIFace; import edu.ku.brc.ui.UIRegistry; /** * @author rod * * @code_status Alpha * * Feb 2, 2007 * */ public class PartialDateUI extends JPanel implements GetSetValueIFace, UIPluginable, UIValidatable, ChangeListener { private static final Logger log = Logger.getLogger(PartialDateUI.class); protected DateWrapper scrDateFormat = null; protected DataObjectGettable getter; protected DataObjectSettable setter; protected FormViewObj parent; protected JComboBox formatSelector; protected String cellName = null; protected boolean isDisplayOnly = true; protected ChangeListener changeListener = null; protected String title; protected Object dataObj = null; protected String dateFieldName = null; protected String dateTypeName = null; protected UIFieldFormatter.PartialDateEnum dateType = UIFieldFormatter.PartialDateEnum.Full; protected UIFieldFormatter.PartialDateEnum origDateType = UIFieldFormatter.PartialDateEnum.Full; protected boolean dateTypeIsStr = false; protected UIValidatable[] uivs = new UIValidatable[3]; protected JTextField[] textFields = new JTextField[3]; protected JPanel[] panels = new JPanel[3]; protected CardLayout cardLayout = new CardLayout(); protected JPanel cardPanel; protected UIValidatable currentUIV = null; protected ActionListener comboBoxAL = null; // UIValidatable && UIPluginable protected UIValidatable.ErrorType valState = UIValidatable.ErrorType.Valid; protected boolean isRequired = false; protected boolean isChanged = false; protected boolean isNew = false; protected boolean ignoreDocChanges = false; protected boolean isDateChanged = false; /** * Constructor. */ public PartialDateUI() { loadAndPushResourceBundle("specify_plugins"); title = UIRegistry.getResourceString("PartialDateUI"); popResourceBundle(); } /** * @param tf */ private void setupPopupMenu(final ValFormattedTextField tf) { for (JComponent comp : tf.getTextComps()) { if (comp instanceof JTextField) { ViewFactory.addTextFieldPopup(this, (JTextField) comp, true); } } } /** * Creates the UI. */ protected void createUI() { DocumentAdaptor docListener = null; if (!isDisplayOnly) { docListener = new DocumentAdaptor() { @Override protected void changed(DocumentEvent e) { super.changed(e); if (!ignoreDocChanges) { isChanged = true; isDateChanged = true; if (changeListener != null) { changeListener.stateChanged(new ChangeEvent(PartialDateUI.this)); } } } }; } List<UIFieldFormatterIFace> partialDateList = UIFieldFormatterMgr.getInstance().getDateFormatterList(true); for (UIFieldFormatterIFace uiff : partialDateList) { if (uiff.getName().equals("PartialDateMonth")) { ValFormattedTextField tf = new ValFormattedTextField(uiff, isDisplayOnly, !isDisplayOnly); tf.setRequired(isRequired); if (docListener != null) tf.addDocumentListener(docListener); uivs[1] = tf; textFields[1] = tf.getTextField(); if (isDisplayOnly) { ViewFactory.changeTextFieldUIForDisplay(textFields[1], false); } else { setupPopupMenu(tf); } } else if (uiff.getName().equals("PartialDateYear")) { ValFormattedTextField tf = new ValFormattedTextField(uiff, isDisplayOnly, !isDisplayOnly); tf.setRequired(isRequired); if (docListener != null) tf.addDocumentListener(docListener); uivs[2] = tf; textFields[2] = tf.getTextField(); if (isDisplayOnly) { ViewFactory.changeTextFieldUIForDisplay(textFields[2], false); } else { setupPopupMenu(tf); } } } List<UIFieldFormatterIFace> dateList = UIFieldFormatterMgr.getInstance().getDateFormatterList(false); for (UIFieldFormatterIFace uiff : dateList) { if (uiff.getName().equals("Date")) { ValFormattedTextFieldSingle tf = new ValFormattedTextFieldSingle(uiff, isDisplayOnly, false); tf.setRequired(isRequired); if (docListener != null) tf.addDocumentListener(docListener); uivs[0] = tf; textFields[0] = tf; if (isDisplayOnly) { ViewFactory.changeTextFieldUIForDisplay(textFields[0], false); } else { ViewFactory.addTextFieldPopup(this, tf, true); } } } cardPanel = new JPanel(cardLayout); String[] formatKeys = { "PARTIAL_DATE_FULL", "PARTIAL_DATE_MONTH", "PARTIAL_DATE_YEAR" }; String[] labels = new String[formatKeys.length]; for (int i = 0; i < formatKeys.length; i++) { labels[i] = UIRegistry.getResourceString(formatKeys[i]); cardPanel.add(labels[i], (JComponent) uivs[i]); } formatSelector = createComboBox(labels); formatSelector.setSelectedIndex(0); JComponent typDisplayComp = null; if (!isDisplayOnly) { comboBoxAL = new ActionListener() { public void actionPerformed(ActionEvent ae) { JComboBox cbx = (JComboBox) ae.getSource(); Object dataValue = ((GetSetValueIFace) currentUIV).getValue();//isDateChanged ? ((GetSetValueIFace)currentUIV).getValue() : Calendar.getInstance(); currentUIV = uivs[cbx.getSelectedIndex()]; ignoreDocChanges = true; ((GetSetValueIFace) currentUIV).setValue(dataValue, null); ignoreDocChanges = false; cardLayout.show(cardPanel, formatSelector.getSelectedItem().toString()); isChanged = true; if (changeListener != null) { changeListener.stateChanged(new ChangeEvent(PartialDateUI.this)); } } }; typDisplayComp = formatSelector; formatSelector.addActionListener(comboBoxAL); } PanelBuilder builder = new PanelBuilder( new FormLayout((typDisplayComp != null ? "p, 2px, f:p:g" : "f:p:g"), "p"), this); CellConstraints cc = new CellConstraints(); if (typDisplayComp != null) { builder.add(typDisplayComp, cc.xy(1, 1)); builder.add(cardPanel, cc.xy(3, 1)); } else { builder.add(cardPanel, cc.xy(1, 1)); } } /* (non-Javadoc) * @see edu.ku.brc.af.ui.forms.UIPluginable#canCarryForward() */ @Override public boolean canCarryForward() { return true; } /* (non-Javadoc) * @see edu.ku.brc.af.ui.forms.UIPluginable#getCarryForwardFields() */ @Override public String[] getCarryForwardFields() { return new String[] { dateFieldName, dateTypeName }; } /* (non-Javadoc) * @see edu.ku.brc.af.ui.forms.UIPluginable#getTitle() */ @Override public String getTitle() { return title; } /* (non-Javadoc) * @see edu.ku.brc.af.ui.forms.UIPluginable#isNotEmpty() */ @Override public boolean isNotEmpty() { if (currentUIV != null) { return ((GetSetValueIFace) currentUIV).getValue() != null; } return false; } /* (non-Javadoc) * @see edu.ku.brc.ui.GetSetValueIFace#getValue() */ public Object getValue() { Object fieldVal = null; if (currentUIV != null) { fieldVal = ((GetSetValueIFace) currentUIV).getValue(); } if (!isDisplayOnly && dataObj != null && StringUtils.isNotEmpty(dateFieldName) && StringUtils.isNotEmpty(dateTypeName) && isChanged) { verifyGetterSetters(dataObj); setter.setFieldValue(dataObj, dateFieldName, fieldVal != null && StringUtils.isNotEmpty(fieldVal.toString()) ? fieldVal : null); setter.setFieldValue(dataObj, dateTypeName, formatSelector.getSelectedIndex() + 1); // Need to add one because the first value is None } return dataObj; } /* (non-Javadoc) * @see edu.ku.brc.af.ui.forms.UIPluginable#getFieldNames() */ @Override public String[] getFieldNames() { return new String[] { dateFieldName, dateTypeName }; } /* (non-Javadoc) * @see javax.swing.JComponent#setEnabled(boolean) */ public void setEnabled(final boolean enabled) { super.setEnabled(enabled); for (UIValidatable uiv : uivs) { ((JComponent) uiv).setEnabled(enabled); } formatSelector.setEnabled(enabled); } /** * */ private void verifyGetterSetters(final Object dObj) { if (dObj != null) { if (getter == null) { getter = DataObjectGettableFactory.get(dObj.getClass().getName(), FormHelper.DATA_OBJ_GETTER); } if (setter == null) { setter = DataObjectSettableFactory.get(dObj.getClass().getName(), FormHelper.DATA_OBJ_SETTER); } } } private SimpleDateFormat getDateFormatter() { if (scrDateFormat == null) { scrDateFormat = AppPrefsCache.getDateWrapper("ui", "formatting", "scrdateformat"); } if (scrDateFormat != null) { return scrDateFormat.getSimpleDateFormat(); } return new SimpleDateFormat("yyyy-MM-dd"); } /* (non-Javadoc) * @see edu.ku.brc.ui.GetSetValueIFace#setValue(java.lang.Object, java.lang.String) */ public void setValue(final Object value, final String defaultValue) { if (value != null) { if (!(value instanceof String)) { verifyGetterSetters(dataObj == null ? value : dataObj); } } else { dataObj = null; for (UIValidatable uiv : uivs) { ((GetSetValueIFace) uiv).setValue(null, ""); } currentUIV = uivs[0]; return; } int inx = 0; boolean skipProcessing = false; Calendar calDate = null; if (value instanceof String && StringUtils.isEmpty(defaultValue)) { try { Date date = getDateFormatter().parse(value.toString()); calDate = Calendar.getInstance(); calDate.setTime(date); skipProcessing = true; } catch (ParseException ex) { } } if (!skipProcessing) { dataObj = value; // TODO Really need to verify right here whether the defaultValue as a String is a valid date Object dateObj = getter.getFieldValue(value, dateFieldName); if (dateObj == null && StringUtils.isNotEmpty(defaultValue)) { calDate = Calendar.getInstance(); } if (dateObj instanceof Calendar) { calDate = (Calendar) dateObj; } Object dateTypeObj = getter.getFieldValue(value, dateTypeName); if (dateTypeObj instanceof String) { inx = Integer.parseInt((String) dateTypeObj); dateTypeIsStr = true; } else if (dateTypeObj instanceof Short) { inx = ((Short) dateTypeObj).intValue(); dateTypeIsStr = false; } else if (dateTypeObj instanceof Byte) { inx = ((Byte) dateTypeObj).intValue(); dateTypeIsStr = false; } else { inx = 1; } if (inx > 0) { inx--; // need to subtract one because the first item is "None" } else { log.error(dateTypeName + " was zero and shouldn't have been!"); } } currentUIV = uivs[inx]; if (currentUIV != null) { ignoreDocChanges = true; ((GetSetValueIFace) currentUIV).setValue(calDate, ""); isChanged = true; ignoreDocChanges = false; } dateType = UIFieldFormatter.PartialDateEnum.values()[inx + 1]; if (!skipProcessing) formatSelector.removeActionListener(comboBoxAL); formatSelector.setSelectedIndex(inx); if (!skipProcessing) formatSelector.addActionListener(comboBoxAL); cardLayout.show(cardPanel, formatSelector.getModel().getElementAt(inx).toString()); } //-------------------------------------------------------- //-- UIPluginable //-------------------------------------------------------- /* (non-Javadoc) * @see edu.ku.brc.af.ui.forms.UIPluginable#getUIComponent() */ public JComponent getUIComponent() { return this; } /* (non-Javadoc) * @see edu.ku.brc.af.ui.forms.UIPluginable#initialize(java.util.Properties, boolean) */ public void initialize(final Properties properties, final boolean isViewMode) { this.isDisplayOnly = isViewMode; dateFieldName = properties.getProperty("df"); dateTypeName = properties.getProperty("tp"); createUI(); } /* (non-Javadoc) * @see edu.ku.brc.af.ui.forms.UIPluginable#setCellName(java.lang.String) */ public void setCellName(final String cellName) { this.cellName = cellName; } /* (non-Javadoc) * @see edu.ku.brc.af.ui.forms.UIPluginable#setChangeListener(javax.swing.event.ChangeListener) */ public void addChangeListener(final ChangeListener listener) { this.changeListener = listener; } /* (non-Javadoc) * @see edu.ku.brc.af.ui.forms.UIPluginable#setViewable(edu.ku.brc.af.ui.forms.Viewable) */ @Override public void setParent(final FormViewObj parent) { this.parent = parent; JLabel lbl = parent.getLabelFor(this); if (lbl != null && StringUtils.isNotEmpty(dateFieldName)) { DBTableInfo tblInfo = DBTableIdMgr.getInstance().getByClassName(parent.getView().getClassName()); if (tblInfo != null) { final DBFieldInfo fi = tblInfo.getFieldByName(dateFieldName); if (fi != null) { title = fi.getTitle(); isRequired = fi.isRequired(); if (uivs[0] instanceof ValFormattedTextFieldSingle) { ((ValFormattedTextFieldSingle) uivs[0]).setRequired(isRequired); } else { for (UIValidatable uiv : uivs) { ((ValFormattedTextField) uiv).setRequired(isRequired); } } if (StringUtils.isNotEmpty(fi.getTitle())) { lbl.setText(fi.getTitle() + ":"); if (isRequired) { lbl.setFont(lbl.getFont().deriveFont(Font.BOLD)); } } if (lbl != null) { lbl.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { super.mouseClicked(e); if (e.getClickCount() == 2) { JOptionPane.showMessageDialog(UIRegistry.getMostRecentWindow(), "<html>" + fi.getDescription(), UIRegistry.getResourceString("FormViewObj.UNOTES"), JOptionPane.INFORMATION_MESSAGE); } } }); } } else { log.error("PartialDateUI - Couldn't find date field [" + dateFieldName + "] in data obj View: " + parent.getView().getName()); } } } } /* (non-Javadoc) * @see edu.ku.brc.af.ui.forms.UIPluginable#shutdown() */ public void shutdown() { changeListener = null; dataObj = null; } //-------------------------------------------------------- // UIValidatable Interface //-------------------------------------------------------- /* (non-Javadoc) * @see edu.ku.brc.ui.forms.validation.UIValidatable#cleanUp() */ public void cleanUp() { } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.validation.UIValidatable#getState() */ public ErrorType getState() { return validateState(); } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.validation.UIValidatable#getValidatableUIComp() */ public Component getValidatableUIComp() { return this; } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.validation.UIValidatable#isChanged() */ public boolean isChanged() { return isChanged || (currentUIV != null && currentUIV.isChanged()); } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.validation.UIValidatable#isInError() */ public boolean isInError() { return currentUIV != null ? currentUIV.isInError() : true; } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.validation.UIValidatable#isRequired() */ public boolean isRequired() { return isRequired; } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.validation.UIValidatable#reset() */ public void reset() { for (UIValidatable uiv : uivs) { uiv.reset(); } isChanged = false; isDateChanged = false; dataObj = null; formatSelector.setSelectedIndex(0); // None is zero, Full is 1 for (JTextField tf : textFields) { if (tf != null) { tf.setText(""); } } } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.validation.UIValidatable#setAsNew(boolean) */ public void setAsNew(final boolean isNew) { this.isNew = isNew; } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.validation.UIValidatable#setChanged(boolean) */ public void setChanged(final boolean isChanged) { this.isChanged = isChanged; if (!isChanged) { isDateChanged = false; } } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.validation.UIValidatable#setRequired(boolean) */ public void setRequired(final boolean isRequired) { this.isRequired = isRequired; } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.validation.UIValidatable#setState(edu.ku.brc.ui.forms.validation.UIValidatable.ErrorType) */ public void setState(final ErrorType state) { for (UIValidatable uiv : uivs) { uiv.setState(state); } } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.validation.UIValidatable#validateState() */ public ErrorType validateState() { ErrorType errType = ErrorType.Valid; if (currentUIV != null) { errType = currentUIV.validateState(); if (errType == ErrorType.Incomplete && !isRequired) { errType = ErrorType.Valid; } } else { errType = ErrorType.Error; } return errType; } /* (non-Javadoc) * @see javax.swing.event.ChangeListener#stateChanged(javax.swing.event.ChangeEvent) */ public void stateChanged(final ChangeEvent e) { if (changeListener != null) { changeListener.stateChanged(e); } } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.validation.UIValidatable#getReason() */ public String getReason() { return null; } /* (non-Javadoc) * @see edu.ku.brc.af.ui.forms.UIPluginable#carryForwardStateChange() */ @Override public void carryForwardStateChange() { // no op } /* (non-Javadoc) * @see edu.ku.brc.af.ui.forms.UIPluginable#setNewObj(boolean) */ @Override public void setNewObj(boolean isNewObj) { // no op } }