001package icy.gui.component;
002
003import icy.gui.component.NumberTextField.ValueChangeListener;
004
005import java.awt.GridBagConstraints;
006import java.awt.GridBagLayout;
007import java.awt.Insets;
008import java.awt.Rectangle;
009import java.awt.geom.Rectangle2D;
010
011import javax.swing.JLabel;
012import javax.swing.JPanel;
013import javax.swing.event.ChangeEvent;
014import javax.swing.event.ChangeListener;
015
016/**
017 * Component letting user to define a range (RangeSlider + 2 inputs fields)
018 * 
019 * @author Stephane
020 */
021public class Region2DComponent extends JPanel implements ValueChangeListener
022{
023    protected NumberTextField xStartField;
024    protected NumberTextField yStartField;
025    protected NumberTextField widthField;
026    protected NumberTextField heightField;
027
028    public Region2DComponent(double x, double y, double w, double h, boolean integer)
029    {
030        super();
031
032        initialize();
033
034        xStartField.setInteger(integer);
035        yStartField.setInteger(integer);
036        widthField.setInteger(integer);
037        heightField.setInteger(integer);
038
039        xStartField.setNumericValue(x);
040        yStartField.setNumericValue(y);
041        widthField.setNumericValue(w);
042        heightField.setNumericValue(h);
043
044    }
045
046    public Region2DComponent(double x, double y, double w, double h)
047    {
048        this(x, y, w, h, false);
049    }
050
051    public Region2DComponent(boolean integer)
052    {
053        this(0d, 0d, 100d, 100d, integer);
054    }
055
056    public Region2DComponent()
057    {
058        this(0d, 0d, 100d, 100d, false);
059    }
060
061    protected void initialize()
062    {
063        setBorder(null);
064
065        GridBagLayout gridBagLayout = new GridBagLayout();
066        gridBagLayout.columnWidths = new int[] {0, 0, 0, 0, 0, 0};
067        gridBagLayout.rowHeights = new int[] {0, 0};
068        gridBagLayout.columnWeights = new double[] {1.0, 1.0, 0.0, 1.0, 1.0, Double.MIN_VALUE};
069        gridBagLayout.rowWeights = new double[] {0.0, Double.MIN_VALUE};
070        setLayout(gridBagLayout);
071
072        xStartField = new NumberTextField();
073        xStartField.setToolTipText("Start X position of the region");
074        xStartField.addValueListener(this);
075        GridBagConstraints gbc_xStartField = new GridBagConstraints();
076        gbc_xStartField.fill = GridBagConstraints.HORIZONTAL;
077        gbc_xStartField.insets = new Insets(0, 0, 0, 2);
078        gbc_xStartField.gridx = 0;
079        gbc_xStartField.gridy = 0;
080        add(xStartField, gbc_xStartField);
081        yStartField = new NumberTextField();
082        yStartField.setToolTipText("Start Y position of the region");
083        yStartField.addValueListener(this);
084        GridBagConstraints gbc_yStartField = new GridBagConstraints();
085        gbc_yStartField.fill = GridBagConstraints.HORIZONTAL;
086        gbc_yStartField.insets = new Insets(0, 0, 0, 2);
087        gbc_yStartField.gridx = 1;
088        gbc_yStartField.gridy = 0;
089        add(yStartField, gbc_yStartField);
090        heightField = new NumberTextField();
091        heightField.setToolTipText("Height of the region");
092        heightField.addValueListener(this);
093        widthField = new NumberTextField();
094        widthField.setToolTipText("Width of the region");
095        widthField.addValueListener(this);
096        JLabel sepLabel = new JLabel("-");
097        GridBagConstraints gbc_sepLabel = new GridBagConstraints();
098        gbc_sepLabel.fill = GridBagConstraints.VERTICAL;
099        gbc_sepLabel.insets = new Insets(0, 0, 0, 2);
100        gbc_sepLabel.gridx = 2;
101        gbc_sepLabel.gridy = 0;
102        add(sepLabel, gbc_sepLabel);
103        GridBagConstraints gbc_widthField = new GridBagConstraints();
104        gbc_widthField.fill = GridBagConstraints.HORIZONTAL;
105        gbc_widthField.insets = new Insets(0, 0, 0, 2);
106        gbc_widthField.gridx = 3;
107        gbc_widthField.gridy = 0;
108        add(widthField, gbc_widthField);
109        GridBagConstraints gbc_heightField = new GridBagConstraints();
110        gbc_heightField.fill = GridBagConstraints.HORIZONTAL;
111        gbc_heightField.gridx = 4;
112        gbc_heightField.gridy = 0;
113        add(heightField, gbc_heightField);
114
115        validate();
116    }
117
118    /**
119     * Set 2D region values.
120     */
121    public void setRegion(double x, double y, double w, double h)
122    {
123        xStartField.setNumericValue(x);
124        yStartField.setNumericValue(y);
125        widthField.setNumericValue(w);
126        heightField.setNumericValue(h);
127    }
128
129    /**
130     * Set 2D region values.
131     */
132    public void setRegion(int x, int y, int w, int h)
133    {
134        xStartField.setNumericValue(x);
135        yStartField.setNumericValue(y);
136        widthField.setNumericValue(w);
137        heightField.setNumericValue(h);
138    }
139
140    /**
141     * Set 2D region values.
142     */
143    public void setRegion(Rectangle region)
144    {
145        setRegion(region.x, region.y, region.width, region.height);
146    }
147
148    /**
149     * Get 2D region values.
150     */
151    public Rectangle2D getRegion()
152    {
153        if (isInteger())
154            return new Rectangle((int) xStartField.getNumericValue(), (int) yStartField.getNumericValue(),
155                    (int) widthField.getNumericValue(), (int) heightField.getNumericValue());
156
157        return new Rectangle2D.Double(xStartField.getNumericValue(), yStartField.getNumericValue(),
158                widthField.getNumericValue(), heightField.getNumericValue());
159    }
160
161    /**
162     * Return true if the range use integer number
163     */
164    public boolean isInteger()
165    {
166        return xStartField.isInteger();
167    }
168
169    /**
170     * Return true if the range use integer number
171     */
172    public void setInteger(boolean value)
173    {
174        xStartField.setInteger(value);
175        yStartField.setInteger(value);
176        widthField.setInteger(value);
177        heightField.setInteger(value);
178    }
179
180    @Override
181    public void setEnabled(boolean enabled)
182    {
183        xStartField.setEnabled(enabled);
184        yStartField.setEnabled(enabled);
185        widthField.setEnabled(enabled);
186        heightField.setEnabled(enabled);
187
188        super.setEnabled(enabled);
189    }
190
191    protected void fireChangedEvent()
192    {
193        final ChangeEvent event = new ChangeEvent(this);
194
195        for (ChangeListener listener : getListeners(ChangeListener.class))
196            listener.stateChanged(event);
197    }
198
199    public void addChangeListener(ChangeListener listener)
200    {
201        listenerList.add(ChangeListener.class, listener);
202    }
203
204    public void removeChangeListener(ChangeListener listener)
205    {
206        listenerList.remove(ChangeListener.class, listener);
207    }
208
209    @Override
210    public void valueChanged(double newValue, boolean validate)
211    {
212        if (validate)
213            fireChangedEvent();
214    }
215}