/* * Rapid Beans Framework: EditorPropertyTimeOfDaySwing.java * * Copyright (C) 2009 Martin Bluemel * * Creation Date: 12/12/2006 * * This program is free software; you can redistribute it and/or modify it under the terms of the * GNU Lesser General Public License as published by the Free Software Foundation; * either version 3 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 Lesser General Public License for more details. * You should have received a copies of the GNU Lesser General Public License and the * GNU General Public License along with this program; if not, see <http://www.gnu.org/licenses/>. */ package org.rapidbeans.presentation.swing; import java.awt.Color; import java.awt.Component; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.LayoutManager; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.math.BigDecimal; import java.util.Locale; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTextField; import org.rapidbeans.core.basic.Property; import org.rapidbeans.core.basic.PropertyQuantity; import org.rapidbeans.core.basic.RapidQuantity; import org.rapidbeans.core.exception.RapidBeansRuntimeException; import org.rapidbeans.core.exception.ValidationException; import org.rapidbeans.core.type.TypePropertyQuantity; import org.rapidbeans.core.util.StringHelper; import org.rapidbeans.domain.math.TimeOfDay; import org.rapidbeans.presentation.Application; import org.rapidbeans.presentation.EditorBean; import org.rapidbeans.presentation.config.ConfigPropEditorBean; /** * a special property editor for RapidQuantity properties. Combines a textHours * field for editing the magnitude with a combo box for selecting the unit. * * @author Martin Bluemel */ public class EditorPropertyTimeOfDaySwing extends EditorPropertySwing { /** * the textHours field. */ private JTextField textHours = new JTextField(); /** * the combo box. */ private JTextField textMinutes = new JTextField(); /** * the combo box. */ private JLabel labelColon = new JLabel(":"); /** * the panel. */ private BBEditorPropertyQuantitySwingPanel panel = null; /** * the panel's layout manager. */ private LayoutManager layout = new GridBagLayout(); /** * @return the editor's widget */ public Object getWidget() { return this.panel; } /** * constructor. * * @param prop * the bean property to edit * @param propBak * the bean property backup * @param bizBeanEditor * the parent bean editor * @param client * the client */ public EditorPropertyTimeOfDaySwing(final Application client, final EditorBean bizBeanEditor, final Property prop, final Property propBak) { super(client, bizBeanEditor, prop, propBak); Component[] comps = { this.textHours, this.textMinutes }; this.panel = new BBEditorPropertyQuantitySwingPanel(comps); super.initColors(); if (!(prop instanceof PropertyQuantity)) { throw new RapidBeansRuntimeException("invalid propperty for a quantity editor"); } if (!(prop.getValue() instanceof TimeOfDay)) { throw new RapidBeansRuntimeException("invalid propperty value for a TimeOfDay editor"); } if (prop.getType().isKeyCandidate()) { if (this.getBeanEditor().getParentBean() == null) { this.textHours.setEditable(false); this.textMinutes.setEnabled(false); this.textMinutes.setBackground(COLOR_KEY); } } this.textHours.addKeyListener(new KeyListener() { public void keyTyped(final KeyEvent e) { } public void keyPressed(final KeyEvent e) { } public void keyReleased(final KeyEvent e) { fireInputFieldChanged(); } }); this.textMinutes.addKeyListener(new KeyListener() { public void keyTyped(final KeyEvent e) { } public void keyPressed(final KeyEvent e) { } public void keyReleased(final KeyEvent e) { fireInputFieldChanged(); } }); this.panel.setLayout(this.layout); this.panel.add(this.textHours, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); this.panel.add(this.labelColon, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); this.panel.add(this.textMinutes, new GridBagConstraints(2, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); this.updateUI(); final ConfigPropEditorBean cfg = getConfig(); if (prop.getReadonly() || (cfg != null && !cfg.getEnabled())) { this.panel.setEnabled(false); } } /** * update the string presented in the editor. */ public void updateUI() { try { this.inputFieldValueCompleted = false; this.setUIEventLock(); final TimeOfDay value = (TimeOfDay) this.getProperty().getValue(); if (value == null) { this.textHours.setText(""); } else { this.textHours.setText(Integer.toString(value.getHours())); this.textMinutes.setText(normalizeMinutesString(Integer.toString(value.getMinutes()))); } } finally { this.releaseUIEventLock(); } } /** * @return the Text field's content */ public Object getInputFieldValue() { RapidQuantity ifValue = null; String s = this.textHours.getText(); if (s.trim().length() > 0) { ifValue = RapidQuantity.createInstance(((TypePropertyQuantity) this.getProperty().getType()) .getQuantitytype().getName(), getInputFieldValueString()); } return ifValue; } /** * validate an input field. * * @return if the string in the input field is valid or at least could at * least get after appending additional characters. * * @param ex * the validation exception */ protected boolean hasPotentiallyValidInputField(final ValidationException ex) { if (ex.getSignature().endsWith("incomplete")) { return this.checkLocalNumber(false); } else { return this.inputFieldValueCompleted; } } /** * show if the input field valuehas been expanded. */ private boolean inputFieldValueCompleted = false; /** * check the localized number. * * @param completenessRequired * if completeness is required * * @return if the local number is ok */ protected boolean checkLocalNumber(final boolean completenessRequired) { boolean ok = true; try { parseLocalNumberHours(completenessRequired); parseLocalNumberMinutes(completenessRequired); } catch (ValidationException e) { ok = false; } return ok; } /** * A helper class for number parsing. * * @author Martin Bluemel */ private class ParsedNumber { // /** // * the number. // */ // private BigDecimal number = null; // /** // * the ok flag. // */ // private boolean ok = false; /** * constructor. * * @param s * the date string * @param l * the locale */ ParsedNumber(final String s, final Locale l) { new BigDecimal(s); } // /** // * @param s the day String to set // */ // public void setNumber(final String s) { // this.number = new BigDecimal(s); // } // /** // * @param o the ok to set // */ // public void setOk(final boolean o) { // this.ok = o; // } // /** // * @return the number // */ // public BigDecimal getNumber() { // return number; // } // /** // * @return the ok // */ // public boolean isOk() { // return ok; // } } /** * validate the hour field. * * @return if the string in the date field is valid or at least could at * least get after appending additional characters. * * @param completenessRequired * if the inpput fiels must be completeS */ private ParsedNumber parseLocalNumberHours(final boolean completenessRequired) { ParsedNumber number = new ParsedNumber(this.textHours.getText(), this.getLocale().getLocale()); return number; } /** * validate the minute field. * * @return if the string in the date field is valid or at least could at * least get after appending additional characters. * * @param completenessRequired * if the inpput fiels must be completeS */ private ParsedNumber parseLocalNumberMinutes(final boolean completenessRequired) { ParsedNumber number = new ParsedNumber(this.textMinutes.getText(), this.getLocale().getLocale()); return number; } /** * @return the input field value as string. */ public String getInputFieldValueString() { return new TimeOfDay(this.textHours.getText() + ':' + normalizeMinutesString(this.textMinutes.getText())) .toString(); } /** * fill the minute String with leading zeros. * * @param min * the minutes * * @return the filled string */ private static String normalizeMinutesString(final String min) { return StringHelper.fillUp(min, 2, '0', StringHelper.FillMode.left); } /** * special panel that forwards set backgound call to its components. * * @author Martin Bluemel */ private final class BBEditorPropertyQuantitySwingPanel extends JPanel { /** * serial id. */ private static final long serialVersionUID = 1L; /** * the parent property editor for the panel. */ private Component[] components = null; /** * constructor with components. * * @param comps * the component widgets */ public BBEditorPropertyQuantitySwingPanel(final Component[] comps) { super(); this.components = comps; } /** * forwards set backgound call to its component widgets. * * @param bg * the new background color */ public void setBackground(final Color bg) { if (components != null) { for (Component comp : this.components) { comp.setBackground(bg); } } else { super.setBackground(bg); } } /** * forwards set enabled call to its component widgets. * * @param en * if enabled or not */ public void setEnabled(final boolean en) { if (components != null) { for (Component comp : this.components) { comp.setEnabled(en); } } else { super.setEnabled(en); } } } }