/*
* Beanfabrics Framework Copyright (C) by Michael Karneim, beanfabrics.org
* Use is subject to license terms. See license.txt.
*/
package org.beanfabrics.swing;
import java.awt.Graphics;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.Serializable;
import javax.swing.JLabel;
import org.beanfabrics.IModelProvider;
import org.beanfabrics.Link;
import org.beanfabrics.ModelProvider;
import org.beanfabrics.ModelSubscriber;
import org.beanfabrics.Path;
import org.beanfabrics.View;
import org.beanfabrics.event.WeakPropertyChangeListener;
import org.beanfabrics.model.AbstractPM;
import org.beanfabrics.model.IIconPM;
import org.beanfabrics.model.ITextPM;
import org.beanfabrics.model.IValuePM;
/**
* The <code>BnIconLabel</code> is a {@link JLabel} that can subscribe to an
* {@link IIconPM}.
*
* @author Michael Karneim
* @author Marcel Eyke
* @beaninfo
*/
@SuppressWarnings("serial")
public class BnIconLabel extends JLabel implements View<IIconPM>, ModelSubscriber {
private final Link link = new Link(this);
private final PropertyChangeListener listener = new MyWeakPropertyChangeListener();
private class MyWeakPropertyChangeListener implements WeakPropertyChangeListener, Serializable {
public void propertyChange(PropertyChangeEvent evt) {
refresh();
}
};
private IIconPM pModel;
private ErrorIconPainter errorIconPainter = createDefaultErrorIconPainter();
/**
* Constructs a <code>BnIconLabel</code>.
*/
public BnIconLabel() {
}
/**
* Constructs a <code>BnIconLabel</code> and binds it to the specified
* model.
*
* @param pModel the model
*/
public BnIconLabel(IIconPM pModel) {
this();
setPresentationModel(pModel);
}
/**
* Constructs a <code>BnIconLabel</code> and subscribes it for the model at
* the specified Path provided by the given provider.
*
* @param provider
* @param path
*/
public BnIconLabel(ModelProvider provider, Path path) {
this.setModelProvider(provider);
this.setPath(path);
}
/**
* Constructs a <code>BnIconLabel</code> and subscribes it for the model at
* the root level provided by the given provider.
*
* @param provider
*/
public BnIconLabel(ModelProvider provider) {
this.setModelProvider(provider);
this.setPath(new Path());
}
/**
* Returns whether this component is connected to the target
* {@link AbstractPM} to synchronize with.
*
* @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() {
refreshText();
refreshIcon();
refreshToolTip();
}
/**
* Configures the tool tip of this component on the depending on the target
* {@link IValuePM}s attributes.
*/
private void refreshToolTip() {
if (this.pModel == null) {
this.setToolTipText(null);
} else {
this.setToolTipText(pModel.isValid() == false ? pModel.getValidationState().getMessage() : pModel.getDescription());
}
}
/**
* Configures the tool tip of this component on the depending on the target
* {@link IIconPM}s attributes.
*/
private void refreshIcon() {
if (this.pModel != null) {
this.setIcon(this.pModel.getIcon());
} else {
this.setIcon(null);
}
}
/**
* Configures the text of this component on the depending on the target
* {@link ITextPM}s attributes.
*/
private void refreshText() {
if (this.pModel instanceof ITextPM) {
ITextPM textUiModel = (ITextPM)this.pModel;
this.setText(textUiModel.getText());
} else {
this.setText("");
}
}
private ErrorIconPainter createDefaultErrorIconPainter() {
ErrorIconPainter result = new ErrorIconPainter();
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() {
IIconPM pModel = this.getPresentationModel();
if (pModel == null) {
return false;
}
return (pModel.isValid() == false);
}
/** {@inheritDoc} */
public IIconPM getPresentationModel() {
return pModel;
}
/** {@inheritDoc} */
public void setPresentationModel(IIconPM newModel) {
IIconPM oldModel = this.pModel;
if (newModel != null && newModel instanceof ITextPM == false && newModel instanceof IIconPM == false) {
throw new IllegalArgumentException("pModel must be an instance of ITextPM or IIconPM");
}
if (this.pModel != null) {
this.pModel.removePropertyChangeListener(listener);
}
this.pModel = newModel;
if (this.pModel != null) {
this.pModel.addPropertyChangeListener(listener);
}
refresh();
this.firePropertyChange("presentationModel", oldModel, newModel);
}
/** {@inheritDoc} */
public void setModelProvider(IModelProvider provider) {
this.link.setModelProvider(provider);
}
/** {@inheritDoc} */
public IModelProvider getModelProvider() {
return link.getModelProvider();
}
/** {@inheritDoc} */
public void setPath(Path path) {
this.link.setPath(path);
}
/** {@inheritDoc} */
public Path getPath() {
return link.getPath();
}
}