/*
* Beanfabrics Framework Copyright (C) by Michael Karneim, beanfabrics.org
* Use is subject to license terms. See license.txt.
*/
// TODO javadoc - remove this comment only when the class and all non-public
// methods and fields are documented
package org.beanfabrics.swing.internal;
import java.awt.Graphics;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.Serializable;
import javax.swing.JRadioButton;
import javax.swing.SwingConstants;
import org.beanfabrics.View;
import org.beanfabrics.event.WeakPropertyChangeListener;
import org.beanfabrics.model.AbstractPM;
import org.beanfabrics.model.IBooleanPM;
import org.beanfabrics.model.IValuePM;
import org.beanfabrics.model.PresentationModel;
import org.beanfabrics.swing.ErrorIconPainter;
/**
* The <code>BooleanPMRadioButton</code> is a {@link JRadioButton} that is a
* view on an {@link IBooleanPM}.
*
* @author Michael Karneim
*/
@SuppressWarnings("serial")
public class BooleanPMRadioButton extends JRadioButton implements View<IBooleanPM> {
private IBooleanPM pModel;
private final PropertyChangeListener listener = new MyWeakPropertyChangeListener();
private class MyWeakPropertyChangeListener implements WeakPropertyChangeListener, Serializable {
public void propertyChange(PropertyChangeEvent evt) {
refresh();
}
}
private ErrorIconPainter errorIconPainter = createDefaultErrorIconPainter();
public BooleanPMRadioButton() {
this.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
if (isConnected() == false)
return;
final boolean newValue = isSelected();
pModel.setBoolean(newValue);
}
});
}
public BooleanPMRadioButton(IBooleanPM pModel) {
this();
setPresentationModel(pModel);
}
/** {@inheritDoc} */
public IBooleanPM getPresentationModel() {
return pModel;
}
/** {@inheritDoc} */
public void setPresentationModel(IBooleanPM newModel) {
IBooleanPM oldModel = this.pModel;
if (this.pModel != null) {
this.pModel.removePropertyChangeListener(listener);
}
this.pModel = newModel;
if (this.pModel != null) {
this.pModel.addPropertyChangeListener(listener);
}
this.refresh();
this.firePropertyChange("presentationModel", oldModel, newModel);
}
/**
* Returns whether this component is connected to the target
* {@link PresentationModel} to synchronize with. This is a convenience
* method.
*
* @return <code>true</code> when this component is connected, else
* <code>false</code>
*/
boolean isConnected() {
return this.pModel != null;
}
/**
* Configures this component depending on the target {@link AbstractPM}s
* attributes.
*/
private void refresh() {
if (pModel == null) {
this.setSelected(false);
this.setToolTipText(null);
this.setEnabled(false);
} else {
try {
final Boolean value = pModel.getBoolean();
if (value != null) {
this.setSelected(value);
}
} catch (IllegalStateException ex) {
// not a "boolean text"
// -> keep the old state
}
//TODO jdk 1.6 (rk)
// if (getModel() instanceof DefaultButtonModel) {
// final ButtonGroup group = (ButtonGroup)
// ((DefaultButtonModel)getModel()).getGroup();
// if (group != null) {
// if ( this.isSelected() && value == false)
// group.clearSelection();
// }
// }
final String tooltip;
if (pModel.isValid()) {
tooltip = pModel.getDescription();
} else {
tooltip = pModel.getValidationState().getMessage();
}
this.setToolTipText(tooltip);
this.setEnabled(pModel.isEditable());
}
}
private ErrorIconPainter createDefaultErrorIconPainter() {
ErrorIconPainter result = new ErrorIconPainter();
result.setHorizontalAlignment(getHorizontalTextPosition());
return result;
}
public ErrorIconPainter getErrorIconPainter() {
return errorIconPainter;
}
public void setErrorIconPainter(ErrorIconPainter aErrorIconPainter) {
if (aErrorIconPainter == null) {
throw new IllegalArgumentException("aErrorIconPainter == null");
}
this.errorIconPainter = aErrorIconPainter;
}
/** {@inheritDoc} */
@Override
public void paintChildren(Graphics g) {
super.paintChildren(g);
if (shouldPaintErrorIcon()) {
errorIconPainter.paint(g, this);
}
}
private boolean shouldPaintErrorIcon() {
IValuePM pModel = this.getPresentationModel();
if (pModel == null) {
return false;
}
return (pModel.isValid() == false);
}
@Override
public void setHorizontalTextPosition(int textPosition) {
super.setHorizontalTextPosition(textPosition);
if (errorIconPainter != null) {
this.errorIconPainter.setHorizontalAlignment(invertHorizontalTextPosition(textPosition));
}
}
private int invertHorizontalTextPosition(int textPosition) {
switch (textPosition) {
case SwingConstants.LEFT:
return SwingConstants.RIGHT;
case SwingConstants.RIGHT:
return SwingConstants.LEFT;
case SwingConstants.LEADING:
return SwingConstants.TRAILING;
case SwingConstants.TRAILING:
return SwingConstants.LEADING;
default:
return textPosition;
}
}
}