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.af.ui.forms.validation; import static edu.ku.brc.ui.UIHelper.createLabel; import static edu.ku.brc.ui.UIHelper.setControlSize; import java.awt.CardLayout; import java.awt.Color; import java.awt.Component; import java.awt.Dimension; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Insets; import java.awt.Point; import java.awt.Toolkit; import java.awt.event.FocusAdapter; import java.awt.event.FocusEvent; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.awt.image.BufferedImage; import java.util.Calendar; import java.util.Date; import java.util.List; import java.util.Vector; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTextField; import javax.swing.KeyStroke; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import javax.swing.text.AttributeSet; import javax.swing.text.BadLocationException; import org.apache.commons.lang.StringUtils; import com.jgoodies.forms.builder.PanelBuilder; import com.jgoodies.forms.layout.CellConstraints; import com.jgoodies.forms.layout.FormLayout; import edu.ku.brc.af.prefs.AppPrefsCache; 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.UIFieldFormatterField; 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.formatters.UIFieldFormatterField.FieldType; import edu.ku.brc.ui.ColorWrapper; import edu.ku.brc.ui.DocumentAdaptor; import edu.ku.brc.ui.UIHelper; import edu.ku.brc.ui.UIRegistry; /** * A Multiple JTextFields (wrapped inside a JPanel) that provides for "formatted" input. The format "mask" is define in XML * via the UIFieldFormatterMgr class. This is idea for text fields that have a standard size and a specific format (i.e. Dates) * The mask enables the "fields" and separators to be specifically defined. * * NOTE: This impl has multiple Text Field, one for each part of the format. * * @code_status Beta * * @author rods * */ @SuppressWarnings("serial") public class ValFormattedTextField extends JPanel implements ValFormattedTextFieldIFace { //private static final Logger log = Logger.getLogger(ValFormattedTextField.class); protected static ColorWrapper valTextColor = null; protected static ColorWrapper requiredFieldColor = null; protected static ColorWrapper viewFieldColor = null; protected UIValidatable.ErrorType valState = UIValidatable.ErrorType.Valid; protected boolean isRequired = false; protected boolean isChanged = false; protected boolean isNew = false; protected boolean isViewOnly = false; protected boolean isPartialOK = false; protected boolean isSearch = false; protected Color bgColor = null; protected JTextField viewtextField = null; protected boolean shouldIgnoreNotifyDoc = true; protected boolean needsUpdating = false; protected String currCachedValue = null; protected List<JFormattedDoc> documents = new Vector<JFormattedDoc>(); protected String defaultValue = null; protected UIFieldFormatterIFace formatter; protected List<UIFieldFormatterField> fields = null; protected boolean isFromUIFmtOverride = false; protected List<DocumentListener> documentListeners = null; protected boolean isAutoFmtOn = true; protected Object origValue = null; protected ChangeListener changeListener = null; protected CardLayout cardLayout; protected JPanel cardPanel = null; protected BGTextField viewTF = null; protected JTextField editTF = null; //--- protected Color textColor = new Color(0, 0, 0, 64); protected JComponent[] comps = null; protected char autoNumberChar = UIFieldFormatterMgr.getAutoNumberPatternChar(); protected KeyStroke pasteKeyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_V, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()); /** * Constructor * @param dataObjFormatterName the formatters name */ protected ValFormattedTextField() { super(); setOpaque(false); } /** * Constructor. * @param formatter * @param isViewOnly * @param isAllEditable */ public ValFormattedTextField(final UIFieldFormatterIFace formatter, final boolean isViewOnly, final boolean isAllEditable) { this(formatter, isViewOnly, isAllEditable, false); } /** * Constructor. * @param formatter * @param isViewOnly * @param isAllEditable * @param isPartialOK */ public ValFormattedTextField(final UIFieldFormatterIFace formatter, final boolean isViewOnly, final boolean isAllEditable, final boolean isPartialOK) { this(); this.isViewOnly = isViewOnly; this.isPartialOK = isPartialOK; init(formatter, isAllEditable); } /** * Constructor. * @param formatter the formatters */ public ValFormattedTextField(final UIFieldFormatterIFace formatter, final boolean isViewOnly) { this(formatter, isViewOnly, false, false); } /** * Constructor. * @param formatter the formatters */ public ValFormattedTextField(final String formatterName, final boolean isViewOnly) { this(formatterName, isViewOnly, false, false); } /** * Constructor * @param formatterName the formatters name * @param isViewOnly * @param isAllEditable * @param isPartialOK */ public ValFormattedTextField(final String formatterName, final boolean isViewOnly, final boolean isAllEditable, final boolean isPartialOK) { super(); this.isViewOnly = isViewOnly; this.isPartialOK = isPartialOK; init(UIFieldFormatterMgr.getInstance().getFormatter(formatterName), isAllEditable); } /** * Constructor * @param formatterName the formatters name * @param isViewOnly * @param isAllEditable */ public ValFormattedTextField(final String formatterName, final boolean isViewOnly, final boolean isAllEditable) { super(); this.isViewOnly = isViewOnly; init(UIFieldFormatterMgr.getInstance().getFormatter(formatterName), isAllEditable); } /** * @param isPartialOK the isPartialOK to set */ public void setPartialOK(final boolean isPartialOK) { boolean isDifferent = this.isPartialOK != isPartialOK; this.isPartialOK = isPartialOK; if (isDifferent) { setRequired(isRequired); // will adjust the color } } /* (non-Javadoc) * @see javax.swing.JComponent#requestFocus() */ @Override public void requestFocus() { if (comps != null && comps[0] != null) { comps[0].requestFocus(); //comps[0].requestFocusInWindow(); } } /** * @param formatterArg * @param isAllEditable */ protected void init(final UIFieldFormatterIFace formatterArg, final boolean isAllEditable) { setFormatterInternal(formatterArg); createUI(); if (!isPartialOK && (valTextColor == null || requiredFieldColor == null || viewFieldColor == null)) { valTextColor = AppPrefsCache.getColorWrapper("ui", "formatting", "valtextcolor"); requiredFieldColor = AppPrefsCache.getColorWrapper("ui", "formatting", "requiredfieldcolor"); viewFieldColor = AppPrefsCache.getColorWrapper("ui", "formatting", "viewfieldcolor"); } if (!isViewOnly && comps != null && !isAllEditable) { int inx = 0; for (UIFieldFormatterField field : fields) { if (field.isIncrementer() && !isPartialOK) { if (comps[inx] instanceof JTextField) { ViewFactory.changeTextFieldUIForDisplay(((JTextField) comps[inx]), getBackground(), false); } else if (comps[inx] instanceof JPanel) { ViewFactory.changeTextFieldUIForDisplay(viewTF, getBackground(), false); } } inx++; } } } /** * @return the text field */ public JTextField getTextField() { return viewtextField; } /** * @return the comps */ public JComponent[] getTextComps() { return comps; } /** * @param textField */ protected void addFocusAdapter(final JTextField textField) { textField.addFocusListener(new FocusAdapter() { @Override public void focusGained(FocusEvent e) { ((JTextField) e.getSource()).selectAll(); repaint(); } @Override public void focusLost(FocusEvent e) { isNew = false; validateState(); repaint(); } }); } /** * Creates the various UI Components for the formatter. */ protected void createUI() { CellConstraints cc = new CellConstraints(); if (isViewOnly || (formatter != null && !formatter.isUserInputNeeded() && fields != null && fields.size() == 1)) { viewtextField = new JTextField(); setControlSize(viewtextField); // Remove by rods 12/5/08 this messes thihngs up // values don't get inserted correctly, shouldn't be needed anyway //JFormattedDoc document = new JFormattedDoc(viewtextField, formatter, formatter.getFields().get(0)); //viewtextField.setDocument(document); //document.addDocumentListener(this); //documents.add(document); ViewFactory.changeTextFieldUIForDisplay(viewtextField, false); PanelBuilder builder = new PanelBuilder(new FormLayout("1px,f:p:g,1px", "1px,f:p:g,1px"), this); builder.add(viewtextField, cc.xy(2, 2)); bgColor = viewtextField.getBackground(); } else { JTextField txt = new JTextField(); Font txtFont = txt.getFont(); Font font = new Font("Courier", Font.PLAIN, txtFont.getSize()); BufferedImage bi = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB); Graphics2D g = bi.createGraphics(); g.setFont(font); FontMetrics fm = g.getFontMetrics(font); g.dispose(); Insets ins = txt.getBorder().getBorderInsets(txt); int baseWidth = ins.left + ins.right; bgColor = txt.getBackground(); StringBuilder sb = new StringBuilder("1px"); for (UIFieldFormatterField f : fields) { sb.append(","); if (f.getType() == FieldType.separator || f.getType() == FieldType.constant) { sb.append('p'); } else { sb.append(((fm.getMaxAdvance() * f.getSize()) + baseWidth) + "px"); } } sb.append(",1px"); PanelBuilder builder = new PanelBuilder(new FormLayout(sb.toString(), "1px,P:G,1px"), this); comps = new JComponent[fields.size()]; int inx = 0; for (UIFieldFormatterField f : fields) { JComponent comp = null; JComponent tfToAdd = null; if (f.getType() == FieldType.separator || f.getType() == FieldType.constant) { comp = createLabel(f.getValue()); if (f.getType() == FieldType.constant) { comp.setBackground(Color.WHITE); comp.setOpaque(true); } tfToAdd = comp; } else { JTextField tf = new BGTextField(f.getSize(), isViewOnly ? "" : f.getValue()); tfToAdd = tf; if (inx == 0) { tf.addKeyListener(new KeyAdapter() { @Override public void keyPressed(KeyEvent e) { checkForPaste(e); } }); } JFormattedDoc document = new JFormattedDoc(tf, formatter, f); tf.setDocument(document); document.addDocumentListener(new DocumentAdaptor() { @Override protected void changed(DocumentEvent e) { isChanged = true; if (!shouldIgnoreNotifyDoc) { String fldStr = getText(); int len = StringUtils.isNotEmpty(fldStr) ? fldStr.length() : 0; if (formatter != null && len > 0 && formatter.isLengthOK(len)) { setState(formatter.isValid(fldStr) ? UIValidatable.ErrorType.Valid : UIValidatable.ErrorType.Error); repaint(); } //validateState(); if (changeListener != null) { changeListener.stateChanged(new ChangeEvent(this)); } if (documentListeners != null) { for (DocumentListener dl : documentListeners) { dl.changedUpdate(null); } } } currCachedValue = null; } }); documents.add(document); addFocusAdapter(tf); comp = tf; comp.setFont(font); if (f.isIncrementer()) { editTF = tf; cardLayout = new CardLayout(); cardPanel = new JPanel(cardLayout); cardPanel.add("edit", tf); viewTF = new BGTextField(f.getSize(), isViewOnly ? "" : f.getValue()); viewTF.setDocument(document); cardPanel.add("view", viewTF); cardLayout.show(cardPanel, "view"); comp = cardPanel; tfToAdd = cardPanel; } } setControlSize(tfToAdd); builder.add(comp, cc.xy(inx + 2, 2)); comps[inx] = tfToAdd; inx++; } } } /** * @param e the key event */ protected void checkForPaste(final KeyEvent e) { if (e.getKeyCode() == pasteKeyStroke.getKeyCode() && e.getModifiers() == pasteKeyStroke.getModifiers()) { String text = UIHelper.getTextFromClipboard(); if (text != null && text.length() <= formatter.getLength()) { setValue(text, null); } } } /** * @param changeListener the changeListener to set */ public void setChangeListener(ChangeListener changeListener) { this.changeListener = changeListener; } /** * Sets the formatter. * @param dataObjFormatterName the formatter to use */ protected void setFormatterInternal(final UIFieldFormatterIFace formatterArg) { if (formatter != formatterArg && formatterArg != null) { formatter = formatterArg; fields = formatter.getFields(); } } /** * Sets the BG color of all the text fields. * @param color */ protected void setBGColor(final Color color) { if (viewtextField != null) { viewtextField.setBackground(color); } else if (comps != null) { for (JComponent comp : comps) { if (comp instanceof JTextField) { ((JTextField) comp).setBackground(color); } } } } /** * Sets the formatter and reset the current value into the new format. * @param dataObjFormatterName the formatter to use */ public void setFormatter(final UIFieldFormatterIFace formatter) { Object currentValue = isChanged ? getValue() : origValue; setFormatterInternal(formatter); setValue(currentValue, ""); } /* (non-Javadoc) * @see edu.ku.brc.af.ui.forms.validation.UIValidatable#isNotEmpty() */ public boolean isNotEmpty() { String txt = getText(); return !(txt == null || txt.isEmpty()); } /** * @return */ public String getText() { if (viewtextField != null) { return viewtextField.getText(); } StringBuilder sb = new StringBuilder(); int inx = 0; String prevStr = null; for (JComponent c : comps) { String val = null; if (c instanceof JLabel) { val = ((JLabel) c).getText(); prevStr = val; } else if (c instanceof JTextField) { val = ((JTextField) c).getText(); } else if (c instanceof JPanel) { if (isAutoFmtOn) { val = viewTF.getText(); if (StringUtils.isEmpty(val)) { val = viewTF.getBgStr(); } } else { val = editTF.getText(); } } if (StringUtils.isEmpty(val)) { if (!formatter.getFields().get(inx).isIncrementer()) { if (!isPartialOK) { return null; } if (prevStr != null) { sb.setLength(sb.length() - prevStr.length()); } } break; } sb.append(val); if (!(c instanceof JLabel)) { prevStr = null; } inx++; } currCachedValue = sb.toString(); return currCachedValue; } /* (non-Javadoc) * @see java.awt.Component#setEnabled(boolean) */ @Override public void setEnabled(boolean enabled) { boolean isEnabled = enabled; if (!isViewOnly) { boolean isNeeded = formatter.isUserInputNeeded(); if (enabled && isNeeded) { isEnabled = isNeeded; } else { isEnabled = enabled; } setBGColor(isRequired && isEnabled && !isViewOnly ? requiredFieldColor.getColor() : bgColor); } super.setEnabled(isEnabled); if (viewtextField != null) { viewtextField.setEnabled(isEnabled); } else if (comps != null) { for (JComponent comp : comps) { if (comp instanceof JTextField) { ((JTextField) comp).setEnabled(isEnabled); } else if (comp instanceof JPanel) { viewTF.setEnabled(isEnabled); editTF.setEnabled(isEnabled); } } } } /* (non-Javadoc) * @see javax.swing.text.JTextComponent#setText(java.lang.String) */ public void setText(final String text, final boolean notify) { if (viewtextField != null) { viewtextField.setText(text); return; } shouldIgnoreNotifyDoc = !notify; boolean isTextEmpty = StringUtils.isEmpty(text); int txtLen = text.length(); //int len = formatter.getLength(); int inx = 0; int pos = 0; for (UIFieldFormatterField field : fields) { String val; if (isTextEmpty) { /*if (field.isEntryField()) { if (field.getType() == FieldType.year) { val = Integer.toString(Calendar.getInstance().get(Calendar.YEAR)); } else { val = ""; } } else { val = field.getValue(); }*/ val = ""; } else { if (pos < txtLen) { val = text.substring(pos, Math.min(pos + field.getSize(), txtLen)); } else { val = ""; } } if (comps[inx] instanceof JLabel) { if (!val.equals(field.getValue())) { valState = UIValidatable.ErrorType.Error; } } else if (comps[inx] instanceof JPanel) { if (isAutoFmtOn) { if (StringUtils.isNotEmpty(val)) { viewTF.setText(val); } } else { editTF.setText(val); } } else { ((JTextField) comps[inx]).setText(val); } pos += field.getSize(); inx++; } shouldIgnoreNotifyDoc = false; repaint(); } /* (non-Javadoc) * @see java.awt.Component#paint(java.awt.Graphics) */ @Override public void paint(Graphics g) { super.paint(g); if (!isViewOnly && !isPartialOK && !isNew && valState == UIValidatable.ErrorType.Error && isEnabled()) { Dimension size; if (comps != null && comps.length > 0) { size = getSize(); Component lastComp = comps[comps.length - 1]; size.width = lastComp.getBounds().x + lastComp.getBounds().width; size.height--; } else if (editTF != null) { size = editTF.getSize(); } else { size = getSize(); } UIHelper.drawRoundedRect((Graphics2D) g, valTextColor.getColor(), size, 0); } } /** * Returns true if the no validation errors, false if there are * @return true if the no validation errors, false if there are */ public boolean isOK() { return valState == UIValidatable.ErrorType.Valid; } /** * Sets the text and notifies the validator of the change. This is used manually callit directly. * @param text the new text (must already be formatted). */ public void setText(final String text) { setText(text, true); } /** * @param isViewOnly the isViewOnly to set */ public void setViewOnly(boolean isViewOnly) { this.isViewOnly = isViewOnly; } //-------------------------------------------------- //-- AutoNumberableIFace Interface //-------------------------------------------------- /* (non-Javadoc) * @see edu.ku.brc.ui.forms.validation.AutoNumberableIFace#updateAutoNumbers() */ public void updateAutoNumbers() { if (isAutoFmtOn && needsUpdating) { String nextNum = formatter.getNextNumber(getText()); if (StringUtils.isNotEmpty(nextNum)) { try { setText(nextNum, false); //shouldIgnoreNotifyDoc = true; //setValue(nextNum, nextNum); //shouldIgnoreNotifyDoc = false; needsUpdating = false; return; } catch (Exception ex) { edu.ku.brc.af.core.UsageTracker.incrHandledUsageCount(); edu.ku.brc.exceptions.ExceptionTracker.getInstance().capture(ValFormattedTextField.class, ex); ex.printStackTrace(); } } needsUpdating = true; } } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.validation.AutoNumberableIFace#isFormatterAutoNumber() */ public boolean isFormatterAutoNumber() { return !isPartialOK && formatter != null && formatter.getAutoNumber() != null; } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.validation.AutoNumberableIFace#setAutoNumberEnabled(boolean) */ public void setAutoNumberEnabled(boolean turnOn) { if (formatter.isIncrementer() && cardPanel != null && isAutoFmtOn != turnOn) { cardLayout.show(cardPanel, turnOn ? "view" : "edit"); isAutoFmtOn = turnOn; setChanged(true); if (changeListener != null) { changeListener.stateChanged(new ChangeEvent(this)); } } else { isAutoFmtOn = turnOn; } } //-------------------------------------------------- //-- UIValidatable Interface //-------------------------------------------------- /* (non-Javadoc) * @see edu.kui.brc.ui.validation.UIValidatable#valState() */ public boolean isInError() { return valState != UIValidatable.ErrorType.Valid; } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.validation.UIValidatable#getState() */ public ErrorType getState() { return valState; } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.validation.UIValidatable#setState(edu.ku.brc.ui.forms.validation.UIValidatable.ErrorType) */ public void setState(ErrorType state) { this.valState = state; } /* (non-Javadoc) * @see edu.kui.brc.ui.validation.UIValidatable#isRequired() */ public boolean isRequired() { return isRequired && !isViewOnly; } /* (non-Javadoc) * @see edu.kui.brc.ui.validation.UIValidatable#setRequired(boolean) */ public void setRequired(boolean isRequired) { this.isRequired = isRequired; setBGColor( !isPartialOK && isRequired && isEnabled() && !isViewOnly ? requiredFieldColor.getColor() : bgColor); } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.validation.UIValidatable#isChanged() */ public boolean isChanged() { return isChanged; } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.validation.UIValidatable#setChanged(boolean) */ public void setChanged(boolean isChanged) { this.isChanged = isChanged; } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.validation.UIValidatable#setAsNew(boolean) */ public void setAsNew(boolean isNew) { this.isNew = isRequired ? isNew : false; } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.validation.UIValidatable#reset() */ public void reset() { origValue = null; if (StringUtils.isNotEmpty(defaultValue)) { setText(defaultValue); } validateState(); repaint(); } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.validation.UIValidatable#getValidatableUIComp() */ public Component getValidatableUIComp() { return this; } /** * @return if all the fields have the correct amount of characters, it skips incrementer fields */ protected boolean isFilled() { try { int inx = 0; for (UIFieldFormatterField f : fields) { if ((!f.isIncrementer() || !isAutoFmtOn) && f.getType() != FieldType.constant && f.getType() != FieldType.separator) { JFormattedDoc doc = documents.get(inx); int len = f.getSize(); if (doc.getLength() != len) { return false; } inx++; } } } catch (Exception ex) { ex.printStackTrace(); } return true; } /* (non-Javadoc) * @see java.awt.Component#validate() */ public UIValidatable.ErrorType validateState() { UIValidatable.ErrorType oldState = valState; if (isPartialOK) { boolean hasText = false; for (int i = 0; i < documents.size(); i++) { JFormattedDoc doc = documents.get(i); if (!hasText && doc.getLength() > 0 && i > 0) { return valState = UIValidatable.ErrorType.Error; } if (doc.getLength() > 0) { hasText = true; } } return valState = UIValidatable.ErrorType.Valid; } if (isViewOnly) { valState = UIValidatable.ErrorType.Valid; } else if (formatter != null && formatter.isUserInputNeeded()) { String data = getText(); if (StringUtils.isEmpty(data)) { valState = isRequired ? UIValidatable.ErrorType.Incomplete : UIValidatable.ErrorType.Valid; } else if (!isPartialOK && !isFilled()) { valState = formatter.isLengthOK(data.length()) ? UIValidatable.ErrorType.Valid : UIValidatable.ErrorType.Error; // Only validate against the formatter if the it is the right length if (valState == UIValidatable.ErrorType.Valid) { valState = UIFieldFormatter.isValid(formatter, data, !isAutoFmtOn) ? UIValidatable.ErrorType.Valid : UIValidatable.ErrorType.Error; } } else if (isPartialOK) { valState = StringUtils.isNotEmpty(data) ? UIValidatable.ErrorType.Valid : UIValidatable.ErrorType.Error; } else { valState = UIFieldFormatter.isValid(formatter, data, !isAutoFmtOn) ? UIValidatable.ErrorType.Valid : UIValidatable.ErrorType.Error; } } else { valState = UIValidatable.ErrorType.Valid; } if (oldState != valState) { repaint(); } return valState; } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.validation.UIValidatable#cleanUp() */ public void cleanUp() { UIHelper.removeFocusListeners(this); UIHelper.removeKeyListeners(this); for (JFormattedDoc document : documents) { for (DocumentListener l : document.getDocumentListeners()) { document.removeDocumentListener(l); } } documents.clear(); documents = null; formatter = null; fields = null; UIHelper.removeFocusListeners(this); } /* (non-Javadoc) * @see edu.ku.brc.ui.forms.validation.UIValidatable#getReason() */ public String getReason() { return null; } //-------------------------------------------------------- // GetSetValueIFace //-------------------------------------------------------- /* (non-Javadoc) * @see edu.ku.brc.af.ui.GetSetValueIFace#setValue(java.lang.Object, java.lang.String) */ public void setValue(final Object value, final String defaultValue) { this.defaultValue = defaultValue; String data; if (value != null) { if (value instanceof String) { data = (String) value; } else if (value instanceof Date) { data = formatter.getDateWrapper().format((Date) value); } else if (value instanceof Calendar) { data = formatter.getDateWrapper().format(((Calendar) value).getTime()); } else { data = value.toString(); } } else { data = StringUtils.isNotEmpty(defaultValue) ? defaultValue : ""; } if (origValue == null) { origValue = value; } // Bug 9297 - Without the fix below popup forms with Auto-Incrementing // formatted number that have one segment will not work. boolean isPartialOkay = isPartialOK; if (formatter != null && isPartialOK) { isPartialOkay = formatter.isIncrementer() && formatter.getFields().size() > 1; } // Done Bug 9297 String fmtVal; if (formatter != null && !isPartialOkay) { if (formatter.isInBoundFormatter()) { if (data.length() > 0 && data.length() != formatter.getLength()) { UIRegistry.showError(UIRegistry.getLocalizedMessage("ValFormattedTextField.WR_SIZE", formatter.getName(), data.length(), formatter.getLength())); } needsUpdating = (StringUtils.isEmpty(data) || data.length() != formatter.getLength()) && formatter.getAutoNumber() != null && formatter.isIncrementer(); fmtVal = (String) formatter.formatToUI(data); } else { if (value == null) { needsUpdating = true; } fmtVal = data; } } else { fmtVal = data; } setText(fmtVal); validateState(); repaint(); } /* (non-Javadoc) * @see edu.ku.brc.af.ui.GetSetValueIFace#getValue() */ public Object getValue() { if (formatter.isDate() && !isPartialOK) { return UIHelper.getCalendar(getText(), formatter.getDateWrapper()); } // else String val = getText(); if (formatter.isFromUIFormatter() || isFromUIFmtOverride) { if (StringUtils.isNotEmpty(val)) { return formatter.formatFromUI(getText()); } } return val != null && val.isEmpty() ? null : val; } /** * @param dl */ public void addDocumentListener(final DocumentListener dl) { if (documentListeners == null) { documentListeners = new Vector<DocumentListener>(); } documentListeners.add(dl); } /** * @param dl */ public void removeDocumentListener(final DocumentListener dl) { if (documentListeners != null) { documentListeners.remove(dl); } } /** * @param isFromUIFmtOverride the isFromUIFmtOverride to set */ public void setFromUIFmtOverride(boolean isFromUIFmtOverride) { this.isFromUIFmtOverride = isFromUIFmtOverride; } //-------------------------------------------------------- // Individual Text Field //-------------------------------------------------------- class BGTextField extends JTextField { protected String bgStr = ""; protected Point pnt = null; protected Insets inner; public BGTextField(final int size, final String bgStr) { super(size); this.bgStr = bgStr; this.inner = getInsets(); } /** * @return the bgStr */ public String getBgStr() { return bgStr; } /* (non-Javadoc) * @see javax.swing.text.JTextComponent#setText(java.lang.String) */ public void setText(final String text) { JFormattedDoc document = (JFormattedDoc) getDocument(); document.setIgnoreNotify(shouldIgnoreNotifyDoc); super.setText(isEnabled() ? text : ""); document.setIgnoreNotify(false); } /* (non-Javadoc) * @see java.awt.Component#paint(java.awt.Graphics) */ @Override public void paint(Graphics g) { super.paint(g); String text = getText(); int bgStrLen = bgStr == null ? 0 : bgStr.length(); int txtLen = text == null ? 0 : text.length(); if (isEnabled()) { if (txtLen < bgStrLen) { FontMetrics fm = g.getFontMetrics(); int w = fm.stringWidth(text); pnt = new Point(inner.left + w, inner.top + fm.getAscent()); g.setColor(textColor); g.drawString(bgStr.substring(text.length(), bgStr.length()), pnt.x, pnt.y); } if (valState == UIValidatable.ErrorType.Error && isEnabled()) { UIHelper.drawRoundedRect((Graphics2D) g, isNew ? new Color(249, 249, 0) : valTextColor.getColor(), getSize(), 1); } else if (valState == UIValidatable.ErrorType.Incomplete && isEnabled()) { UIHelper.drawRoundedRect((Graphics2D) g, new Color(249, 249, 0), getSize(), 1); } } } } //------------------------------------------------------------------------- //-- //------------------------------------------------------------------------- public class JFormattedDoc extends ValPlainTextDocument { protected int docLimit; protected JTextField textField; protected UIFieldFormatterIFace docFormatter; protected UIFieldFormatterField docField; /** * CReate a special formatted document * @param textField the textfield the document is associated with * @param formatter the formatter * @param docLenLimit the lengthof the format */ public JFormattedDoc(final JTextField textField, final UIFieldFormatterIFace formatter, final UIFieldFormatterField docField) { super(); this.textField = textField; this.docFormatter = formatter; this.docField = docField; this.docLimit = docField.getSize(); } /** * Check to see if the input was correct (doesn't check against the separator) * @param field the field info * @param str the str to be checked * @returntrue char matches the type of input, false it is in error */ protected boolean isCharOK(final UIFieldFormatterField field, final String str) { FieldType type = field.getType(); if (type == FieldType.alpha && !StringUtils.isAlpha(str)) { return false; } else if (type == FieldType.alphanumeric && !StringUtils.isAlphanumeric(str)) { return false; } else if ((type == FieldType.numeric || type == FieldType.year) && !StringUtils.isNumeric(str)) { return false; } return true; } /** * Checks to see if the icoming string maps correctly to the format and ll the chars match the appropriate type * @param str the string * @return true - ok, false there was an error */ protected boolean okToInsertText(final String str) { String contentStr = textField.getText(); int newLen = contentStr.length() + str.length(); if (newLen == docLimit && str.charAt(0) == autoNumberChar) { return true; } return newLen <= docLimit && isCharOK(docField, str); } /* (non-Javadoc) * @see javax.swing.text.Document#insertString(int, java.lang.String, javax.swing.text.AttributeSet) */ @Override public void insertString(final int offset, final String strArg, final AttributeSet attr) throws BadLocationException { String str = strArg; if (str == null) { return; } if (okToInsertText(str)) { super.insertString(offset, str, attr); } if (getLength() == docLimit) { int inx = 0; for (UIFieldFormatterField f : fields) { int len = fields.size(); if (f == docField && inx < len - 1) { for (int i = inx + 1; i < len; i++) { UIFieldFormatterField nxtField = fields.get(i); if (!nxtField.isByYear() && nxtField.isEntryField()) { comps[i].requestFocus(); break; } } } inx++; } } if (!shouldIgnoreNotifyDoc) { validateState(); } } } /** * */ /* public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { @SuppressWarnings("synthetic-access") public void run() { try { UIHelper.OSTYPE osType = UIHelper.getOSType(); if (osType == UIHelper.OSTYPE.Windows ) { //UIManager.setLookAndFeel(new WindowsLookAndFeel()); UIManager.setLookAndFeel(new PlasticLookAndFeel()); PlasticLookAndFeel.setPlasticTheme(new ExperienceBlue()); } else if (osType == UIHelper.OSTYPE.Linux ) { //UIManager.setLookAndFeel(new GTKLookAndFeel()); UIManager.setLookAndFeel(new PlasticLookAndFeel()); } Vector<UIFieldFormatterField> fields = new Vector<UIFieldFormatterField>(); fields.add(new UIFieldFormatterField(FieldType.year, 4, "YYYY", false, true)); fields.add(new UIFieldFormatterField(FieldType.separator, 1, "-", false)); fields.add(new UIFieldFormatterField(FieldType.alpha, 2, "XX", false)); fields.add(new UIFieldFormatterField(FieldType.separator, 1, "-", false)); fields.add(new UIFieldFormatterField(FieldType.numeric, 4, "NNNN", true)); UIFieldFormatter uif = new UIFieldFormatter("Accession", false, null, Accession.class, true, true, fields); ValFormattedTextField formattedTextField = new ValFormattedTextField(uif, false); CustomDialog dlg = new CustomDialog(null, "Test", true, formattedTextField); formattedTextField.setText("2005-IT-001"); dlg.setVisible(true); System.out.println(formattedTextField.getText()); dlg.dispose(); } catch (Exception e) { edu.ku.brc.af.core.UsageTracker.incrHandledUsageCount(); edu.ku.brc.exceptions.ExceptionTracker.getInstance().capture(ValFormattedTextField.class, e); edu.ku.brc.af.core.UsageTracker.incrHandledUsageCount(); edu.ku.brc.exceptions.ExceptionTracker.getInstance().capture(ValFormattedTextField.class, e); log.error("Can't change L&F: ", e); } } }); }*/ }