package org.openswing.swing.client; import java.beans.*; import java.util.*; import java.awt.*; import java.awt.event.*; import javax.swing.*; import org.openswing.swing.form.model.client.*; import org.openswing.swing.logger.client.*; import org.openswing.swing.util.client.*; import com.toedter.calendar.*; import javax.swing.text.JTextComponent; /** * <p>Title: OpenSwing Framework</p> * <p>Description: Class that could be used as bease class for an input control.</p> * <p>Copyright: Copyright (C) 2006 Mauro Carniel</p> * * <p> This file is part of OpenSwing Framework. * This library is free software; you can redistribute it and/or * modify it under the terms of the (LGPL) Lesser General Public * License as published by the Free Software Foundation; * * GNU LESSER GENERAL PUBLIC LICENSE * Version 2.1, February 1999 * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * The author may be contacted at: * maurocarniel@tin.it</p> * * @author Mauro Carniel * @version 1.0 */ public class BaseInputControl extends JPanel implements InputControl { /** attribute name that identifies the input control */ private String attributeName = null; /** mandatory property of the input control */ private boolean required = false; /** define if the input control is enabled on INSERT mode */ private boolean enabledOnInsert = true; /** define if the input control is enabled on EDIT mode */ private boolean enabledOnEdit = true; /** define if the input control value is duplicated when user has clicked on COPY button */ private boolean canCopy = true; /** define if the input control value is changed */ private boolean changed = false; /** label used when showing error messages related to the input control */ private LabelControl linkedLabel = null; /** mandatory symbol */ private JLabel requiredIcon = new JLabel("*"); /** old input control value */ protected Object oldValue; /** value changed listener list */ private ArrayList valueChangedListeners = new ArrayList(); /** default background color of the binding component */ protected Color defaultBackgroundColor = null; /** tooltip text */ private String toolTipText = null; /** column text horizontal alignment */ private int textAlignment = SwingConstants.LEFT; /** popup menu */ private InputControlPopupMenu inputControlPopupMenu; /** * Constructor. */ public BaseInputControl() { this.setOpaque(false); addFocusListener(new FocusListener() { public void focusGained(FocusEvent e) { if (!getBindingComponent().hasFocus()) // set focus to the component inside this... getBindingComponent().requestFocus(); } public void focusLost(FocusEvent e) { } }); if (Beans.isDesignTime()) { requiredIcon.setForeground(Color.red); requiredIcon.setFont(new Font(requiredIcon.getFont().getFontName(),Font.PLAIN,20)); requiredIcon.setPreferredSize(new Dimension(15, 15)); requiredIcon.setFocusable(false); } else { requiredIcon.setText(""); requiredIcon.setIcon(new ImageIcon(ClientUtils.getImage("obl.gif",getClass()))); } } /** * Method called by the sub-class to initialize focus listener used to push input control value in the VOModel. * @param component component inside this */ protected void initListeners() { defaultBackgroundColor = getBindingComponent().getBackground(); getBindingComponent().addFocusListener(new FocusListener() { public void focusGained(FocusEvent e) { controlFocusGained(e); } public void focusLost(FocusEvent e) { controlFocusLost(e); } }); if (getBindingComponent() instanceof ItemSelectable) { ((ItemSelectable)getBindingComponent()).addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { if (e.getStateChange()==e.SELECTED && attributeName!=null) { maybeFireValueChangedEvent(); } } }); } inputControlPopupMenu = new InputControlPopupMenu(this); ClientUtils.addTabListener(getBindingComponent()); } /** * @return component inside this whose contains the value */ public JComponent getBindingComponent() { Logger.error(this.getClass().getName(), "getBindingComponent", "This method must be overridden in '"+this.getClass().getName()+"'",null); return null; } /** * Add a value changed listener to this input control. * @param listener value changed listener to add */ public final void addValueChangedListener(ValueChangeListener listener) { this.valueChangedListeners.add(listener); } /** * Remove a value changed listener from this input control. * @param listener value changed listener to remove */ public final void removeValueChangedListener(ValueChangeListener listener) { this.valueChangedListeners.remove(listener); } /** * Method called by the sub-class to fire a value changed event. */ protected void maybeFireValueChangedEvent() { // retrieve current value... Object newValue = getValue(); if (isEnabled() && ((this.oldValue==null && newValue!=null) || (this.oldValue!=null && newValue==null) || (this.oldValue!=null && newValue!=null && ! this.oldValue.equals(newValue)))) { // mark the input control as changed setChanged(true); // fire value changed events... ValueChangeEvent e = new ValueChangeEvent(this, attributeName, this.oldValue, newValue); for (int i = 0; i < this.valueChangedListeners.size(); i++) ((ValueChangeListener)this.valueChangedListeners.get(i)).valueChanged(e); // update old value... this.oldValue = newValue; } } /** * This method is called when the input control receives focus. */ private void controlFocusGained(FocusEvent e) { if (this instanceof DateControl) maybeFireValueChangedEvent(); oldValue = getValue(); if (ClientSettings.VIEW_BACKGROUND_SEL_COLOR && isEnabled()) { getBindingComponent().setBackground(ClientSettings.BACKGROUND_SEL_COLOR); } if (ClientSettings.SELECT_DATA_IN_EDITABLE_FORM && isEnabled() && getBindingComponent() instanceof JTextComponent) ((JTextComponent)getBindingComponent()).select(0,((JTextComponent)getBindingComponent()).getText().length()); } /** * This method is called when the input control losts focus. */ private void controlFocusLost(FocusEvent e) { if (ClientSettings.VIEW_BACKGROUND_SEL_COLOR && isEnabled()) { getBindingComponent().setBackground(defaultBackgroundColor); } maybeFireValueChangedEvent(); } /** * Link the input control label to the specified label. * @param linkedLabel label used when showing error messages related to the input control */ public final void setLinkLabel(LabelControl linkedLabel) { this.linkedLabel = linkedLabel; } /** * @return label used when showing error messages related to the input control */ public final LabelControl getLinkLabel() { return linkedLabel; } /** * @return mandatory property of the input control */ public final boolean isRequired() { return required; } /** * @return current Font setting */ public final Font getFont() { return getBindingComponent()==null?null:getBindingComponent().getFont(); } /** * Set the specified font. * @param font Font to set */ public final void setFont(Font font) { if (getBindingComponent()!=null) getBindingComponent().setFont(font); } /** * Set a tooltip text. This text will be translated according to the internationalization settings. * @param toolTipText tool tip text entry in the dictionary */ public final void setToolTipText(String toolTipText) { this.toolTipText = toolTipText; if (!Beans.isDesignTime()) getBindingComponent().setToolTipText(ClientSettings.getInstance().getResources().getResource(toolTipText)); } /** * @return tool tip text entry in the dictionary */ public final String getToolTipText() { return toolTipText; } /** * Define mandatory property of the input control. * @param require mandatory property of the input control */ public final void setRequired(boolean required) { if (!this.required && required && ClientSettings.VIEW_MANDATORY_SYMBOL) { if (this.getLayout() instanceof FlowLayout) this.add(requiredIcon); else if (this.getLayout() instanceof BorderLayout) this.add(requiredIcon,BorderLayout.EAST); else if (this.getLayout() instanceof GridBagLayout) this.add(requiredIcon, new GridBagConstraints(4, 0, 1, 1, 0.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 5, 0)); this.revalidate(); this.repaint(); } else if (this.required && !required && ClientSettings.VIEW_MANDATORY_SYMBOL) { this.remove(requiredIcon); } this.required = required; } /** * @return <code>true</code> if the input control is enabled on INSERT mode, <code>false</code> otherwise */ public final boolean isEnabledOnInsert() { return enabledOnInsert; } /** * Define if the input control is enabled on INSERT mode. * @param enabled <code>true</code> if the input control is enabled on INSERT mode, <code>false</code> otherwise */ public final void setEnabledOnInsert(boolean enabled) { this.enabledOnInsert = enabled; } /** * @return <code>true</code> if the input control is enabled on EDIT mode, <code>false</code> otherwise */ public final boolean isEnabledOnEdit() { return enabledOnEdit; } /** * Define if the input control is enabled on EDIT mode, <code>false</code> otherwise * @param enabled mandatory property of the input control */ public final void setEnabledOnEdit(boolean enabled) { this.enabledOnEdit = enabled; } /** * @return define if the input control value is duplicated when user has clicked on COPY button */ public final boolean isCanCopy() { return canCopy; } /** * Define if the input control value is duplicated when user has clicked on COPY button. * @param canCopy define if the input control value is duplicated when user has clicked on COPY button */ public final void setCanCopy(boolean canCopy) { this.canCopy = canCopy; } /** * Link the input control to the form which contains it and with the specified the attribute. * @param attributeName attribute name to which link the input control */ public final void setAttributeName(String attributeName) { this.attributeName = attributeName; // AttributeNameEditor.setColumnType(this.getClass()); } /** * Link the input control to the form which contains it and with the specified the attribute. * @param attributeName attribute name to which link the input control */ public final String getAttributeName() { return attributeName; } /** * Set current input control abilitation. */ public void setEnabled(boolean enabled) { Logger.error(this.getClass().getName(), "setEnabled", "This method must be overridden in '"+this.getClass().getName()+"'",null); } /** * @return current input control abilitation */ public boolean isEnabled() { try { Logger.error(this.getClass().getName(), "isEnabled", "This method must be overridden in '" + this.getClass().getName() + "'", null); return false; } catch (Exception ex) { return false; } } /** * @return value related to the input control */ public Object getValue() { Logger.error(this.getClass().getName(), "getValue", "This method must be overridden in '"+this.getClass().getName()+"'",null); return null; } /** * Set value to the input control. * @param value value to set into the input control */ public void setValue(Object value) { Logger.error(this.getClass().getName(), "setValue", "This method must be overridden in '"+this.getClass().getName()+"'",null); } /** * @return <code>true</code> if the input control value is changed, <code>false</code> otherwise */ public final boolean isChanged() { return changed; } /** * Define if the input control value is changed. * @param changed <code>true</code> if the input control value is changed, <code>false</code> otherwise */ public final void setChanged(boolean changed) { this.changed = changed; } /** * @return value changed listeners list */ public final ValueChangeListener[] getValueChangeListeners() { return (ValueChangeListener[])valueChangedListeners.toArray(new ValueChangeListener[valueChangedListeners.size()]); } public void requestFocus() { getBindingComponent().requestFocus(); } /** * @return column text horizontal alignment */ public final int getTextAlignment() { return this.textAlignment; } /** * Set column text horizontal alignement. * @param alignment column text horizontal alignement; possible values: "SwingConstants.LEFT", "SwingConstants.RIGHT", "SwingConstants.CENTER". */ public final void setTextAlignment(int alignment) { this.textAlignment = alignment; if (!Beans.isDesignTime() && getBindingComponent()!=null && getBindingComponent() instanceof JTextField) ((JTextField)getBindingComponent()).setHorizontalAlignment(alignment); } }