/*
* Geotoolkit.org - An Open Source Java GIS Toolkit
* http://www.geotoolkit.org
*
* (C) 2009-2012, Open Source Geospatial Foundation (OSGeo)
* (C) 2009-2012, Geomatys
*
* This 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;
* version 2.1 of the License.
*
* This 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.
*/
package org.geotoolkit.internal.swing;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.util.Locale;
import javax.swing.BorderFactory;
import javax.swing.JLabel;
import javax.swing.JSpinner;
import javax.swing.JComponent;
import javax.swing.SpinnerNumberModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import org.geotoolkit.resources.Vocabulary;
/**
* A panel containing a "width" and a "height" field, typically for image size.
*
* @author Martin Desruisseaux (Geomatys)
* @version 3.00
*
* @since 3.00
* @module
*/
public class SizeFields extends JComponent implements ChangeListener {
/**
* For cross-version compatibility.
*/
private static final long serialVersionUID = 174936953329285487L;
/**
* The field for selecting the width of target tiles.
*/
private final JSpinner width;
/**
* The field for selecting the height of target tiles.
*/
private final JSpinner height;
/**
* {@code true} if the width and height are in the process of being adjusted together.
* This is used in order to fire only one change event instead than two.
*/
private transient boolean isAdjusting;
/**
* Creates a new panel initialized to the given value.
*
* @param locale The locale to use for creating the panel.
* @param size The initial value to display in the fields.
* @param minSize The minimal size allowed.
*/
public SizeFields(final Locale locale, final Dimension size, final Dimension minSize) {
setLayout(new GridBagLayout());
width = new JSpinner((new SpinnerNumberModel(size.width, minSize.width, null, 1)));
height = new JSpinner((new SpinnerNumberModel(size.height, minSize.height, null, 1)));
final Vocabulary resources = Vocabulary.getResources(locale);
setBorder(BorderFactory.createTitledBorder(resources.getString(Vocabulary.Keys.TilesSize)));
final GridBagConstraints c = new GridBagConstraints();
c.fill = GridBagConstraints.BOTH;
c.gridx=0; c.insets.left=9;
c.gridy=0; add(new JLabel(resources.getLabel(Vocabulary.Keys.Width)), c);
c.gridy++; add(new JLabel(resources.getLabel(Vocabulary.Keys.Height)), c);
c.gridx++; c.weightx=1; c.insets.left=3; c.insets.right=9;
c.gridy=0; add(width, c);
c.gridy++; add(height, c);
width .addChangeListener(this);
height.addChangeListener(this);
}
/**
* Returns the size value currently defined by the user.
*
* @return The current size value.
*/
public Dimension getSizeValue() {
return new Dimension(((Number) width .getValue()).intValue(),
((Number) height.getValue()).intValue());
}
/**
* Sets the size displayed in the fields to the given value.
*
* @param size The value to be displayed in the fields.
*/
public void setSizeValue(final Dimension size) {
isAdjusting = true;
try {
width .setValue(size.width);
height.setValue(size.height);
} finally {
isAdjusting = false;
}
fireStateChanged();
}
/**
* Adds a listener to notify of changes.
*
* @param listener The listener to add.
*/
public void addChangeListener(final ChangeListener listener) {
listenerList.add(ChangeListener.class, listener);
}
/**
* Removes a listener.
*
* @param listener The listener to remove.
*/
public void removeChangeListener(final ChangeListener listener) {
listenerList.remove(ChangeListener.class, listener);
}
/**
* Invoked every time a change in width or height occurs. This method is public
* as an implementation side-effect, but should never be invoked directly.
*
* @param event The change event.
*/
@Override
public void stateChanged(final ChangeEvent event) {
// TODO: If we want to link the change of width and height, do it here.
if (!isAdjusting) {
fireStateChanged();
}
}
/**
* Invoked when the dimension changed.
*/
private void fireStateChanged() {
ChangeEvent event = null;
final Object[] listeners = listenerList.getListenerList();
for (int i=listeners.length; (i-=2)>=0;) {
if (listeners[i] == ChangeListener.class) {
if (event == null) {
event = new ChangeEvent(this);
}
((ChangeListener) listeners[i+1]).stateChanged(event);
}
}
}
}