package org.openswing.swing.client; import java.beans.*; import java.util.*; import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.event.*; import javax.swing.plaf.*; import javax.swing.plaf.basic.*; import org.openswing.swing.form.model.client.*; import org.openswing.swing.logger.client.*; import org.openswing.swing.util.client.*; /** * <p>Title: OpenSwing Framework</p> * <p>Description: check-box whose text is translated according to internalization settings. * As default behavior, check-box supports two states: Boolean.TRUE (selected) and Boolean.FALSE (deselected). * Optionally (when "allowNullValue" property has been set to <code>true</code>), check-box supports three states: Boolean.TRUE (selected) and Boolean.FALSE (deselected) and null (not selected and gray).</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 CheckBoxControl extends JCheckBox implements InputControl { /** attribute name to which link the input control */ private String attributeName = null; /** label used when showing error messages related to the input control (optional) */ private LabelControl label = null; /** define if the input control is enabled on INSERT mode */ private boolean enabledOnInsert = true; /** define if the input control is enabled on EDIT model */ private boolean enabledOnEdit = true; /** define if the input control value is duplicated when user has clicked on COPY button */ private boolean canCopy = false; /** old input control value */ protected Object oldValue; /** value changed listener list */ private ArrayList valueChangedListeners = new ArrayList(); /** default background color of the binding component */ private Color defaultBackgroundColor = null; /** define if the input control value is changed */ private boolean changed = false; /** tooltip text */ private String toolTipText = null; /** define if null value is alloed (i.e. distinct from Boolean.FALSE value); default value: <code>false</code> */ private boolean allowNullValue = false; /** ButtonModel associated to the check-box when "allowNullValue" property is set to <code>true</code> */ private CheckBoxButtonModel model = null; public CheckBoxControl() { setOpaque(false); initListeners(); } /** * @return current Font setting */ public final Font getFont() { return super.getFont(); } /** * Set the specified font. * @param font Font to set */ public final void setFont(Font font) { super.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()) super.setToolTipText(ClientSettings.getInstance().getResources().getResource(toolTipText)); } /** * @return tool tip text entry in the dictionary */ public final String getToolTipText() { return toolTipText; } /** * 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 = getBackground(); addFocusListener(new FocusListener() { public void focusGained(FocusEvent e) { controlFocusGained(e); } public void focusLost(FocusEvent e) { controlFocusLost(e); } }); addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { if (e.getStateChange()==e.SELECTED && attributeName!=null) { maybeFireValueChangedEvent(); } } }); ClientUtils.addTabListener(this); } /** * 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)))) { // update old value... this.oldValue = 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); } } /** * This method is called when the input control receives focus. */ private void controlFocusGained(FocusEvent e) { oldValue = getValue(); if (ClientSettings.VIEW_BACKGROUND_SEL_COLOR && isEnabled()) { UIManager.put("CheckBox.background", ClientSettings.BACKGROUND_SEL_COLOR); UIManager.put("CheckBoxMenuItem.selectionBackground", ClientSettings.BACKGROUND_SEL_COLOR); repaint(); } } /** * This method is called when the input control losts focus. */ private void controlFocusLost(FocusEvent e) { if (ClientSettings.VIEW_BACKGROUND_SEL_COLOR && isEnabled()) { UIManager.put("CheckBox.background", defaultBackgroundColor); UIManager.put("CheckBoxMenuItem.selectionBackground", defaultBackgroundColor); repaint(); } maybeFireValueChangedEvent(); } /** * 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; } /** * 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; } /** * @return mandatory property of the input control */ public final boolean isRequired() { return false; } /** * Link the input control label to the specified label. * @param label label used when showing error messages related to the input control */ public final void setLinkLabel(LabelControl label) { this.label = label; } /** * 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 LabelControl getLinkLabel() { return label; } /** * @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; } /** * @return value related to the input control */ public final Object getValue() { if (allowNullValue) { return model.getCurrentValue(); } else return new Boolean(this.isSelected()); } /** * Set value to the input control. * @param value value to set into the input control */ public final void setValue(Object value) { if (allowNullValue) { try { model.setCurrentValue( (Boolean) value); } catch (ClassCastException ex) { Logger.error(this.getClass().getName(), "setValue", "Value is not of type Boolean: "+value.getClass().getName(),null); } } else { if (value==null) this.setSelected(false); else if (value instanceof Boolean) this.setSelected(((Boolean)value).booleanValue()); else { Logger.error(this.getClass().getName(), "setValue", "Value is not of type Boolean: "+value.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; } /** * Set abilitation setting. * @param enabled flag used to set abilitation of control */ public final void setEnabled(boolean enabled) { super.setEnabled(enabled); setFocusable(enabled || ClientSettings.DISABLED_INPUT_CONTROLS_FOCUSABLE); try { UIManager.put("CheckBox.background", (Color)UIManager.getColor("TextField.inactiveBackground")); UIManager.put("CheckBoxMenuItem.selectionBackground", (Color)UIManager.getColor("TextField.inactiveBackground")); } catch (Exception ex) { } } /** * Set check box label. * @param text check box label */ public final void setText(String text) { if (Beans.isDesignTime()) super.setText(text); else super.setText(ClientSettings.getInstance().getResources().getResource(text)); } /** * @return define if null value is alloed (i.e. distinct from Boolean.FALSE value) */ public final boolean isAllowNullValue() { return allowNullValue; } /** * Define if null value is alloed (i.e. distinct from Boolean.FALSE value) * @param allowNullValue define if null value is alloed (i.e. distinct from Boolean.FALSE value) */ public final void setAllowNullValue(boolean allowNullValue) { this.allowNullValue = allowNullValue; if (allowNullValue) { MouseListener[] ll = this.getMouseListeners(); for(int i=0;i<ll.length;i++) if (ll[i] instanceof BasicButtonListener) this.removeMouseListener(ll[i]); super.addMouseListener(new MouseAdapter() { public void mousePressed(MouseEvent e) { if (!CheckBoxControl.this.isEnabled()) return; grabFocus(); if (model.getCurrentValue()==null) model.setCurrentValue(Boolean.FALSE); else if (Boolean.TRUE.equals(model.getCurrentValue())) model.setCurrentValue(null); else if (Boolean.FALSE.equals(model.getCurrentValue())) model.setCurrentValue(Boolean.TRUE); } }); ActionMap map = new ActionMapUIResource(); map.put("pressed", new AbstractAction() { public void actionPerformed(ActionEvent e) { grabFocus(); if (model.getCurrentValue()==null) model.setCurrentValue(Boolean.FALSE); else if (Boolean.TRUE.equals(model.getCurrentValue())) model.setCurrentValue(null); else if (Boolean.FALSE.equals(model.getCurrentValue())) model.setCurrentValue(Boolean.TRUE); } }); map.put("released", null); SwingUtilities.replaceUIActionMap(this, map); model = new CheckBoxButtonModel(getModel()); setModel(model); } } public final void setSelected(boolean selected) { if (allowNullValue) { model.setCurrentValue(new Boolean(selected)); } else super.setSelected(selected); } /** * @return value changed listeners list */ public final ValueChangeListener[] getValueChangeListeners() { return (ValueChangeListener[])valueChangedListeners.toArray(new ValueChangeListener[valueChangedListeners.size()]); } /** * <p>Title: OpenSwing Framework</p> * <p>Description: Inner class used to support three states: Boolean.TRUE, Boolean.FALSE and null</p> * <p>Copyright: Copyright (C) 2006 Mauro Carniel</p> * @author Mauro Carniel * @version 1.0 */ class CheckBoxButtonModel implements ButtonModel { private final ButtonModel model; public CheckBoxButtonModel(ButtonModel model) { this.model = model; } public void setCurrentValue(Boolean value) { if (value==null) { model.setArmed(true); setPressed(true); setSelected(false); } else if (Boolean.FALSE.equals(value)) { model.setArmed(false); setPressed(false); setSelected(false); } else if (Boolean.TRUE.equals(value)) { model.setArmed(false); setPressed(false); setSelected(true); } } public Boolean getCurrentValue() { if (isSelected()) { return Boolean.TRUE; } else if (!isSelected() && isArmed()) { return null; } else { return Boolean.FALSE; } } public final void setEnabled(boolean b) { setFocusable(b); model.setEnabled(b); } public boolean isSelected() { return model.isSelected(); } public boolean isEnabled() { try { return model.isEnabled(); } catch (Exception ex) { return false; } } public boolean isPressed() { return model.isPressed(); } public boolean isRollover() { return model.isRollover(); } public void setSelected(boolean selected) { model.setSelected(selected); } public void setPressed(boolean pressed) { model.setPressed(pressed); } public void setRollover(boolean rollover) { model.setRollover(rollover); } public void setMnemonic(int mnemonic) { model.setMnemonic(mnemonic); } public int getMnemonic() { return model.getMnemonic(); } public void setActionCommand(String command) { model.setActionCommand(command); } public String getActionCommand() { return model.getActionCommand(); } public void setGroup(ButtonGroup group) { model.setGroup(group); } public void addActionListener(ActionListener listener) { model.addActionListener(listener); } public void removeActionListener(ActionListener listener) { model.removeActionListener(listener); } public void addItemListener(ItemListener listener) { model.addItemListener(listener); } public void removeItemListener(ItemListener listener) { model.removeItemListener(listener); } public void addChangeListener(ChangeListener listener) { model.addChangeListener(listener); } public void removeChangeListener(ChangeListener listener) { model.removeChangeListener(listener); } public Object[] getSelectedObjects() { return model.getSelectedObjects(); } public void setArmed(boolean armed) { } public boolean isArmed() { return model.isArmed(); } } }