/*
JWildfire - an image and animation processor written in Java
Copyright (C) 1995-2014 Andreas Maschke
This 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 2.1 of the
License, or (at your option) any later version.
This software 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 this software;
if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jwildfire.create.tina.swing;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.JTextField;
import javax.swing.SpinnerModel;
import javax.swing.SpinnerNumberModel;
import javax.swing.event.ChangeListener;
import org.jwildfire.base.Tools;
public class JWFNumberField extends JPanel implements MotionCurveEditor {
private static final double DFLT_STEP = 0.5;
private static final double DFLT_MOUSE_SPEED = 0.40;
private static final long serialVersionUID = 1L;
private double mouseSpeed;
private double valueStep;
private boolean hasMinValue = false;
private boolean hasMaxValue = false;
private double minValue = 0.0;
private double maxValue = 0.0;
private int xMouseOrigin = 0;
private double originValue = 0.0;
private boolean onlyIntegers = false;
private SpinnerNumberModel spinnerModel;
private boolean mouseAdjusting = false;
private int mouseChangeCount = 0;
private boolean withMotionCurve = false;
private String motionPropertyName = "";
private String linkedMotionControlName = "";
private Component linkedMotionControl = null;
private String linkedLabelControlName = "";
private Component linkedLabelControl = null;
private JSpinner spinnerField;
private JButton motionCurveBtn;
public static class JWFNumberFieldButton extends JButton {
private static final long serialVersionUID = 1L;
private JWFNumberField owner;
public JWFNumberFieldButton() {
super();
}
public JWFNumberFieldButton(JWFNumberField pOwner) {
super();
owner = pOwner;
}
public JWFNumberField getOwner() {
return owner;
}
public void setOwner(JWFNumberField pOwner) {
owner = pOwner;
}
}
public JWFNumberField() {
setLayout(new BorderLayout());
motionCurveBtn = new JWFNumberFieldButton(this);
motionCurveBtn.setText("");
motionCurveBtn.setToolTipText("Create/edit a motion curve");
motionCurveBtn.setFont(new Font("Dialog", Font.BOLD, 8));
motionCurveBtn.setIcon(new ImageIcon(getClass().getResource("/org/jwildfire/swing/icons/new/curve-money2.png")));
add(motionCurveBtn, BorderLayout.WEST);
/*
spinnerField = new JSpinner();
add(spinnerField, BorderLayout.CENTER);
spinnerModel = new SpinnerNumberModel(new Double(0), null, null, new Double(valueStep));
spinnerField.setModel(spinnerModel);
*/
spinnerModel = new SpinnerNumberModel(new Double(0), null, null, new Double(valueStep));
spinnerField = new JSpinner(spinnerModel) {
@Override
protected JComponent createEditor(SpinnerModel model) {
return new NumberEditor(this, "0.#######");
}
};
add(spinnerField, BorderLayout.CENTER);
setValueStep(DFLT_STEP);
setMouseSpeed(DFLT_MOUSE_SPEED);
addEvents();
((JSpinner.DefaultEditor) spinnerField.getEditor()).getTextField().setHorizontalAlignment(JTextField.LEADING);
configureMotionCurveBtn(withMotionCurve);
setCursor();
}
private void configureMotionCurveBtn(boolean visible) {
Dimension size = visible ? new Dimension(22, 24) : new Dimension(0, 0);
motionCurveBtn.setPreferredSize(size);
motionCurveBtn.setMinimumSize(size);
motionCurveBtn.setMaximumSize(size);
motionCurveBtn.setVisible(visible);
}
public double getValueStep() {
return valueStep;
}
public void setValueStep(double valueStep) {
this.valueStep = valueStep;
spinnerModel.setStepSize(valueStep);
}
private void setCursor() {
((JSpinner.DefaultEditor) spinnerField.getEditor()).getTextField().setCursor(Cursor.getPredefinedCursor(Cursor.W_RESIZE_CURSOR));
}
private void addEvents() {
((JSpinner.DefaultEditor) spinnerField.getEditor()).getTextField().addMouseListener(
new java.awt.event.MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
if (!isEnabled())
return;
xMouseOrigin = e.getX();
Object value = getValue();
if (value != null && value instanceof Double) {
originValue = (Double) value;
}
else if (value != null && value instanceof Integer) {
originValue = (Integer) value;
}
else {
originValue = 0;
}
mouseAdjusting = true;
mouseChangeCount = 0;
}
@Override
public void mouseReleased(MouseEvent e) {
mouseAdjusting = false;
}
});
((JSpinner.DefaultEditor) spinnerField.getEditor()).getTextField().addMouseMotionListener(
new java.awt.event.MouseMotionAdapter() {
@Override
public void mouseDragged(MouseEvent e) {
if (!isEnabled())
return;
double MINMOVE = 3;
double dx = xMouseOrigin - e.getX();
if (mouseChangeCount > 0 || dx > MINMOVE || dx < -MINMOVE) {
double value = (originValue) - dx * valueStep * mouseSpeed * EditingPrecision.getCurrent().getMultiplier();
if (hasMinValue && value < minValue) {
value = minValue;
}
else if (hasMaxValue && value > maxValue) {
value = maxValue;
}
spinnerField.setValue(value);
mouseChangeCount++;
}
}
});
}
public void setText(String pText) {
if (pText != null && pText.length() > 0) {
double val = Tools.stringToDouble(pText);
if (onlyIntegers) {
val = Tools.FTOI(val);
}
spinnerField.setValue(val);
}
else
spinnerField.setValue(0.0);
}
public String getText() {
return Tools.doubleToString((Double) getValue());
}
public boolean isHasMinValue() {
return hasMinValue;
}
public void setHasMinValue(boolean hasMinValue) {
this.hasMinValue = hasMinValue;
spinnerModel.setMinimum(hasMinValue ? minValue : null);
}
public boolean isHasMaxValue() {
return hasMaxValue;
}
public void setHasMaxValue(boolean hasMaxValue) {
this.hasMaxValue = hasMaxValue;
spinnerModel.setMaximum(hasMaxValue ? maxValue : null);
}
public double getMinValue() {
return minValue;
}
public void setMinValue(double minValue) {
this.minValue = minValue;
spinnerModel.setMinimum(hasMinValue ? minValue : null);
}
public double getMaxValue() {
return maxValue;
}
public void setMaxValue(double maxValue) {
this.maxValue = maxValue;
spinnerModel.setMaximum(hasMaxValue ? maxValue : null);
}
public void setEditable(boolean enabled) {
setEnabled(enabled);
}
public boolean isOnlyIntegers() {
return onlyIntegers;
}
public void setOnlyIntegers(boolean onlyIntegers) {
this.onlyIntegers = onlyIntegers;
if (onlyIntegers) {
spinnerModel.setStepSize(1.0);
}
else {
spinnerModel.setStepSize(valueStep);
}
}
public Object getValue() {
Object val = spinnerField.getValue();
if (val != null && val instanceof Double && onlyIntegers) {
val = new Double(Tools.FTOI((Double) val));
}
return val;
}
public Integer getIntValue() {
Object value = getValue();
if (value instanceof Double) {
return Tools.FTOI((Double) value);
}
else {
return (Integer) value;
}
}
public Double getDoubleValue() {
Object value = getValue();
if (value instanceof Integer) {
return 1.0 * ((Integer) value);
}
else {
return (Double) value;
}
}
public boolean isMouseAdjusting() {
return mouseAdjusting;
}
public int getMouseChangeCount() {
return mouseChangeCount;
}
public void addChangeListener(ChangeListener listener) {
spinnerField.addChangeListener(listener);
}
public void setValue(double value) {
spinnerField.setValue(value);
}
@Override
public void setFont(Font font) {
super.setFont(font);
if (spinnerField != null) {
spinnerField.setFont(font);
}
}
public void addActionListener(ActionListener listener) {
motionCurveBtn.addActionListener(listener);
}
@Override
public boolean isWithMotionCurve() {
return withMotionCurve;
}
@Override
public void setWithMotionCurve(boolean pWithMotionCurve) {
withMotionCurve = pWithMotionCurve;
configureMotionCurveBtn(withMotionCurve);
}
public String getMotionPropertyName() {
return motionPropertyName;
}
public void setMotionPropertyName(String pMotionPropertyName) {
motionPropertyName = pMotionPropertyName;
}
public String getLinkedMotionControlName() {
return linkedMotionControlName;
}
public void setLinkedMotionControlName(String pLinkedMotionControlName) {
linkedMotionControlName = pLinkedMotionControlName;
linkedMotionControl = null;
}
public Component getLinkedMotionControl() {
if (linkedMotionControlName != null && linkedMotionControlName.length() > 0 && linkedMotionControl == null) {
for (Component component : getParent().getComponents()) {
if (linkedMotionControlName.equals(component.getName())) {
linkedMotionControl = component;
break;
}
}
}
return linkedMotionControl;
}
public String getLinkedLabelControlName() {
return linkedLabelControlName;
}
public void setLinkedLabelControlName(String pLinkedLabelControlName) {
linkedLabelControlName = pLinkedLabelControlName;
linkedLabelControl = null;
}
public JLabel _findControl(Container parent, String name) {
for (Component component : parent.getComponents()) {
if (component instanceof JLabel && name.equals(component.getName())) {
return (JLabel) component;
}
else if (component instanceof Container) {
JLabel res = _findControl((Container) component, name);
if (res != null) {
return res;
}
}
}
return null;
}
public JLabel getLinkedLabelControl() {
if (linkedLabelControlName != null && linkedLabelControlName.length() > 0 && linkedLabelControl == null) {
Container parent = getParent();
while (parent != null && linkedLabelControl == null) {
linkedLabelControl = _findControl(parent, linkedLabelControlName);
parent = parent.getParent();
}
}
return (JLabel) linkedLabelControl;
}
public void setEnabled(boolean enabled) {
spinnerField.setEnabled(enabled);
motionCurveBtn.setEnabled(enabled);
}
public boolean isEnabled() {
return spinnerField.isEnabled();
}
public void enableMotionCurveBtn(boolean enabled) {
motionCurveBtn.setEnabled(enabled);
}
public void enableSpinnerField(boolean enabled) {
spinnerField.setEnabled(enabled);
}
public double getMouseSpeed() {
return mouseSpeed;
}
public void setMouseSpeed(double pMouseSpeed) {
mouseSpeed = pMouseSpeed;
}
public JSpinner exposeInternalSpinnerField() {
return spinnerField;
}
public JButton exposeInternalMotionCurveBtn() {
return motionCurveBtn;
}
public void setHasCurve(boolean pHasCurve) {
if (motionCurveBtn != null) {
if (pHasCurve)
motionCurveBtn.setIcon(new ImageIcon(getClass().getResource("/org/jwildfire/swing/icons/new/curve-money2a.png")));
else
motionCurveBtn.setIcon(new ImageIcon(getClass().getResource("/org/jwildfire/swing/icons/new/curve-money2.png")));
}
if (spinnerField != null) {
spinnerField.setVisible(!pHasCurve);
}
}
}