package DisplayProject.swingdisplayer;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.EventObject;
import javax.swing.BorderFactory;
import javax.swing.JCheckBox;
import javax.swing.JFormattedTextField;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.KeyStroke;
import javax.swing.LayoutFocusTraversalPolicy;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
@SuppressWarnings("serial")
public class DimensionDisplayer extends PropertyDisplayer {
private PropertyDescriptor descriptor;
private Method readMethod;
private Method writeMethod;
private Component owningComponent;
private DualField editorComponent;
private static class NumericField extends JFormattedTextField implements DocumentListener, FocusListener {
public NumericField() {
super();
this.getDocument().addDocumentListener(this);
this.addFocusListener(this);
this.setValue("0");
}
public void changedUpdate(DocumentEvent e) {
resize();
fireTextChanged();
}
public void insertUpdate(DocumentEvent e) {
resize();
fireTextChanged();
}
public void removeUpdate(DocumentEvent e) {
resize();
fireTextChanged();
}
private void fireTextChanged() {
String value = getText();
if (value.length() != 0) {
firePropertyChange("text", null, value);
}
}
private void resize() {
String value = getText();
Font f = this.getFont();
FontMetrics fm = this.getFontMetrics(f);
int width = SwingUtilities.computeStringWidth(fm, value);
if (width != this.getWidth()) {
Dimension d = new Dimension(width, super.getHeight());
this.setMinimumSize(d);
if (this.getParent() != null) {
this.getParent().invalidate();
this.getParent().validate();
}
}
}
public void focusGained(FocusEvent e) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
// Select all. Do it on the EDT to ensure the formatter has been properly installed first
selectAll();
}
});
}
public void focusLost(FocusEvent e) {}
@Override
protected void processKeyEvent(KeyEvent e) {
System.out.println(e);
if (e.getID() == KeyEvent.KEY_TYPED) {
if (Character.isDigit(e.getKeyChar())) {
super.processKeyEvent(e);
}
else if (e.getKeyChar() == '+' || e.getKeyChar() == '-') {
int value = Integer.parseInt(this.getText());
int newValue;
if (e.getKeyChar() == '+') {
newValue = Math.abs(value);
}
else {
newValue = -Math.abs(value);
}
if (newValue != value) {
this.setText(Integer.toString(newValue));
}
e.consume();
}
else {
e.consume();
}
}
else {
if (e.getID() == KeyEvent.KEY_PRESSED && e.getKeyCode() == KeyEvent.VK_UP) {
int value = Integer.parseInt(this.getText());
this.setText(Integer.toString(value+1));
this.selectAll();
e.consume();
}
else if (e.getID() == KeyEvent.KEY_PRESSED && e.getKeyCode() == KeyEvent.VK_DOWN) {
int value = Integer.parseInt(this.getText());
this.setText(Integer.toString(value-1));
this.selectAll();
e.consume();
}
// else if (e.getID() == KeyEvent.KEY_PRESSED && e.getKeyCode() == KeyEvent.VK_TAB) {
// this.transferFocus();
// e.consume();
// }
else if (e.getID() == KeyEvent.KEY_RELEASED && (e.getKeyCode() == KeyEvent.VK_UP || e.getKeyCode() == KeyEvent.VK_DOWN)) {
e.consume();
}
else {
super.processKeyEvent(e);
}
}
}
}
public static class DualField extends JPanel {
private final Dimension dim = new Dimension();
private NumericField part1;
private NumericField part2;
private JCheckBox allowsNullWidget = null;
private Font normalFont = null;
private Font italicsFont = null;
public DualField(String text1, String text2, Dimension value) {
this(text1, text2);
this.setValue(value);
}
public DualField(String text1, String text2, Point value) {
this(text1, text2);
this.setValue(value);
}
public DualField(String text1, String text2) {
this(text1, text2, false);
}
public DualField(String text1, String text2, boolean allowsNull) {
this.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
int indexCount = 0;
gbc.anchor = GridBagConstraints.WEST;
gbc.fill = GridBagConstraints.NONE;
gbc.gridy = 0;
gbc.insets = new Insets(0, 2, 0, 2);
if (allowsNull) {
this.allowsNullWidget = new JCheckBox("null");
this.allowsNullWidget.setOpaque(false);
this.allowsNullWidget.setForeground(null);
this.allowsNullWidget.setMinimumSize(new Dimension(this.allowsNullWidget.getMinimumSize().width, 14));
gbc.gridx = indexCount++;
this.add(allowsNullWidget, gbc);
this.allowsNullWidget.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
boolean isSelected = allowsNullWidget.isSelected();
if (isSelected) {
if (italicsFont == null) {
normalFont = part1.getFont();
Font f = normalFont;
italicsFont = f.deriveFont(Font.ITALIC);
}
part1.setForeground(Color.LIGHT_GRAY);
part1.setEnabled(false);
part1.setFocusable(false);
part1.setFont(italicsFont);
part2.setForeground(Color.LIGHT_GRAY);
part2.setEnabled(false);
part2.setFocusable(false);
part2.setFont(italicsFont);
}
else {
part1.setForeground(null);
part1.setEnabled(true);
part1.setFocusable(true);
part1.setFont(normalFont);
part2.setForeground(null);
part2.setEnabled(true);
part2.setFocusable(true);
part2.setFont(normalFont);
}
firePropertyChange("isNull", !isSelected, isSelected);
}
});
}
gbc.gridx = indexCount++;
JLabel label1 = new JLabel(text1);
label1.setOpaque(false);
label1.setForeground(null);
this.add(label1, gbc);
gbc.fill = GridBagConstraints.BOTH;
// gbc.weightx = 1;
gbc.gridx = indexCount++;
part1 = new NumericField();
part1.setBorder(null);
part1.setOpaque(false);
part1.setForeground(null);
part1.addPropertyChangeListener("text", new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
int value = Integer.valueOf((String)evt.getNewValue());
dim.width = value;
firePropertyChange("part1", null, value);
}
});
this.add(part1, gbc);
gbc.gridx = indexCount++;
label1 = new JLabel(text2);
label1.setOpaque(false);
label1.setForeground(null);
this.add(label1, gbc);
gbc.fill = GridBagConstraints.BOTH;
gbc.weightx = 1;
gbc.gridx = indexCount++;
part2 = new NumericField();
part2.setBorder(null);
part2.setOpaque(false);
part2.setForeground(null);
part2.addPropertyChangeListener("text", new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
int value = Integer.valueOf((String)evt.getNewValue());
dim.height = value;
firePropertyChange("part2", null, value);
}
});
this.add(part2, gbc);
this.setBorder(BorderFactory.createLineBorder(Color.BLACK));
this.setBackground(Color.WHITE);
this.setFocusTraversalPolicy(new LayoutFocusTraversalPolicy());
this.setFocusTraversalPolicyProvider(true);
}
public void setValue(Dimension d) {
if (d == null) {
if (allowsNullWidget != null) {
allowsNullWidget.setSelected(true);
this.part1.setValue("0");
this.part2.setValue("0");
}
else {
throw new NullPointerException("Cannot specify a null dimension when not constructed with allowsNull = true");
}
}
else {
this.part1.setValue(Integer.toString(d.width));
this.part2.setValue(Integer.toString(d.height));
}
}
public void setValue(Point d) {
if (d == null) {
if (allowsNullWidget != null) {
allowsNullWidget.setSelected(true);
this.part1.setValue("0");
this.part2.setValue("0");
}
else {
throw new NullPointerException("Cannot specify a null dimension when not constructed with allowsNull = true");
}
}
else {
this.part1.setValue(Integer.toString(d.x));
this.part2.setValue(Integer.toString(d.y));
}
}
public Dimension getValue() {
if (allowsNullWidget != null && allowsNullWidget.isSelected()) {
return null;
}
return new Dimension(this.dim);
}
public int getPart1() {
if (allowsNullWidget != null && allowsNullWidget.isSelected()) {
return 0;
}
return dim.width;
}
public int getPart2() {
if (allowsNullWidget != null && allowsNullWidget.isSelected()) {
return 0;
}
return dim.height;
}
@Override
protected boolean processKeyBinding(KeyStroke ks, KeyEvent e, int condition, boolean pressed) {
if (!e.isConsumed() && e.getID() == KeyEvent.KEY_PRESSED) {
if (e.getKeyChar() == KeyEvent.VK_TAB && e.getModifiers() == 0 && part1.isFocusOwner()) {
part2.requestFocusInWindow();
e.consume();
return true;
}
if (e.getKeyChar() == KeyEvent.VK_TAB && e.getModifiers() == KeyEvent.SHIFT_MASK && part2.isFocusOwner()) {
part1.requestFocusInWindow();
e.consume();
return true;
}
}
return super.processKeyBinding(ks, e, condition, pressed);
}
}
public void setEditingInformation(Component c, PropertyDescriptor pd) {
this.owningComponent = c;
this.descriptor = pd;
this.writeMethod = descriptor.getWriteMethod();
this.readMethod = descriptor.getReadMethod();
}
public Object getCellEditorValue() {
if (editorComponent != null) {
return editorComponent.getValue();
}
return null;
}
public boolean isCellEditable() {
if (descriptor != null && descriptor.getPropertyType().equals(Boolean.TYPE) && writeMethod != null && readMethod != null) {
return true;
}
return false;
}
public boolean isCellEditable(EventObject anEvent) {
return isCellEditable();
}
public boolean shouldSelectCell(EventObject anEvent) {
if (anEvent instanceof MouseEvent) {
MouseEvent e = (MouseEvent)anEvent;
return e.getID() != MouseEvent.MOUSE_DRAGGED;
}
return true;
}
public Component getTableCellEditorComponent(JTable table,
Object value, boolean is1Selected, int row, int column) {
if (descriptor != null && descriptor.getWriteMethod() != null) {
final DualField field = new DualField("w:", "h:");
field.setBorder(null);
PropertyChangeListener listener = new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
try {
writeMethod.invoke(owningComponent, field.getValue());
} catch (Exception e1) {
e1.printStackTrace();
}
}
};
field.addPropertyChangeListener("part1", listener);
field.addPropertyChangeListener("part2", listener);
field.setValue((Dimension)value);
//editorComponent = field;
return field;
}
return null;
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
boolean isReadOnly, Component component, int row, int column) {
DualField result = new DualField("w:", "h:", (Dimension)value); //this.rendererComponent;
result.setBorder(null);
result.setOpaque(true);
return result;
}
// private boolean allowsNull = false;
// private boolean nullValue = false;
@Override
public void preSelect(PropertyDescriptor pd, Component component, JTable table) {
}
}