/**
* Squidy Interaction Library 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.
*
* Squidy Interaction 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Squidy Interaction Library. If not, see
* <http://www.gnu.org/licenses/>.
*
* 2009 Human-Computer Interaction Group, University of Konstanz.
* <http://hci.uni-konstanz.de>
*
* Please contact info@squidy-lib.de or visit our website
* <http://www.squidy-lib.de> for further information.
*/
package org.squidy.designer.component;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.JComponent;
import javax.swing.JSlider;
import org.squidy.designer.model.NodeShape;
import org.squidy.designer.piccolo.JComponentWrapper;
import org.squidy.designer.shape.VisualShape;
import org.squidy.designer.util.FontUtils;
import org.squidy.designer.zoom.impl.InformationShape;
import org.squidy.manager.IBasicControl;
import org.squidy.manager.controls.ComboBoxControl;
import edu.umd.cs.piccolo.util.PBounds;
import edu.umd.cs.piccolo.util.PPaintContext;
import edu.umd.cs.piccolox.pswing.PSwingCanvas;
public class TableEntry<C extends IBasicControl<?, ? extends JComponent>> extends VisualShape<VisualShape<?>> {
/**
* Generated serial version UID.
*/
private static final long serialVersionUID = -3501810293934427374L;
private C control;
private String valueName;
private String postfix;
private String prefix;
boolean hasError = false;
private static final Insets insets = new Insets(5, 5, 5, 5);
/**
* @param name
* @param description
* @param control
* @param prefix
* @param postfix
*/
public TableEntry(String name, String description, C control, String prefix, String postfix) {
this.control = control;
this.valueName = name;
this.postfix = postfix;
this.prefix = prefix;
JComponent component = control.getComponent();
Dimension dimension = component.getPreferredSize();
setBounds(0, 0, 990, insets.top + dimension.getHeight() + insets.bottom);
prepareInformation(description);
prepareControl(control);
}
/**
* @param information
*/
private void prepareInformation(String description) {
PBounds bounds = getBoundsReference();
InformationShape information = new InformationShape(valueName, description);
addChild(information);
information.setScale(0.02);
double offsetY = bounds.getCenterY() - information.localToParent(information.getBounds()).getCenterY();
information.setOffset(10 + 10, offsetY);
}
/**
* @param control
*/
private void prepareControl(C control) {
JComponent component = control.getComponent();
final JComponentWrapper componentWrapper = new JComponentWrapper(component);
addChild(componentWrapper);
// --- Take this out as soon as Piccolo Library sets Environment
// automatically
if (control instanceof ComboBoxControl) {
final ComboBoxControl box = (ComboBoxControl) control;
box.getComponent().addPropertyChangeListener(new PropertyChangeListener() {
/*
* (non-Javadoc)
*
* @see
* java.beans.PropertyChangeListener#propertyChange(java.beans
* .PropertyChangeEvent)
*/
public void propertyChange(PropertyChangeEvent evt) {
if ("ancestor".equals(evt.getPropertyName())) {
Container c = box.getComponent().getParent();
while (c != null && !(c instanceof PSwingCanvas)) {
c = c.getParent();
}
if (c instanceof PSwingCanvas) {
box.getComponent().setEnvironment(componentWrapper, (PSwingCanvas) c);
}
}
}
});
}
control.addPropertyChangeListener(NodeShape.PROPERTY_BINDING_OK, new PropertyChangeListener() {
/* (non-Javadoc)
* @see java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent)
*/
public void propertyChange(PropertyChangeEvent evt) {
hasError = false;
invalidatePaint();
}
});
control.addPropertyChangeListener(NodeShape.PROPERTY_BINDING_EXCEPTION, new PropertyChangeListener() {
/* (non-Javadoc)
* @see java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent)
*/
public void propertyChange(PropertyChangeEvent evt) {
hasError = true;
invalidatePaint();
}
});
Font font = internalFont.deriveFont(18.0f);
double componentOffsetX = component.getPreferredSize().getWidth() + insets.right;
if (component instanceof JSlider) {
componentOffsetX += FontUtils.getWidthOfText(component.getFontMetrics(font), String.valueOf(((JSlider) component).getMaximum())) + insets.left + insets.right;
}
if (postfix != null) {
componentOffsetX += FontUtils.getWidthOfText(component.getFontMetrics(font), postfix);
}
PBounds bounds = getBoundsReference();
componentWrapper.setOffset(bounds.getWidth() - componentOffsetX - 10, insets.top);
}
/**
* @param paintContext
*/
@Override
protected void paintShape(PPaintContext paintContext) {
super.paintShape(paintContext);
Graphics2D g = paintContext.getGraphics();
g.setFont(internalFont.deriveFont(12.0f));
PBounds bounds = getBoundsReference();
double x = bounds.getX() + 10;
double y = bounds.getY();
double width = bounds.getWidth() - 20;
double height = bounds.getHeight();
g.setStroke(new BasicStroke(1.5f));
// g.drawRoundRect(x, y, width / 2, height, 15, 15);
// g.drawRoundRect(x + width / 2, y, width / 2, height, 15, 15);
g.setColor(hasError ? Color.RED : Color.WHITE);
if (isRenderPrimitiveRect())
g.fillRect((int) x, (int) y, (int) width, (int) height);
else
g.fillRoundRect((int) x, (int) y, (int) width, (int) height, 15, 15);
g.setColor(Color.BLACK);
if (isRenderPrimitiveRect())
g.drawRect((int) x, (int) y, (int) width, (int) height);
else
g.drawRoundRect((int) x, (int) y, (int) width, (int) height, 15, 15);
g.drawLine((int) (x + width / 2), (int) y, (int) (x + width / 2), (int) (y + height));
FontMetrics fm = g.getFontMetrics();
double centerFont = fm.getAscent() / (double) 2 - fm.getDescent() / 2;
// double centerFont = 0;
g.setColor(Color.BLACK);
g.drawString(valueName, (int) (x + 45), (int) ((y + (height / 2) + centerFont)));
int postfixWidth = FontUtils.getWidthOfText(fm, postfix);
g.drawString(postfix, (int) (x + width - postfixWidth - insets.right), (int) (y + (height / 2) + centerFont));
JComponent component = control.getComponent();
if (component instanceof JSlider) {
String value = String.valueOf(((JSlider) component).getValue());
int fontWidth = FontUtils.getWidthOfText(fm, value) + insets.right;
g.drawString(value, (int) (x + width - postfixWidth - insets.right - fontWidth), (int) (y + (height / 2) + centerFont));
}
}
}