001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.layer.geoimage;
003
004import static org.openstreetmap.josm.tools.I18n.tr;
005
006import java.awt.GridBagLayout;
007import java.awt.event.FocusListener;
008import java.awt.event.ItemListener;
009
010import javax.swing.JCheckBox;
011import javax.swing.JComponent;
012import javax.swing.JLabel;
013import javax.swing.JPanel;
014import javax.swing.JSeparator;
015import javax.swing.JSpinner;
016import javax.swing.SpinnerNumberModel;
017import javax.swing.SwingConstants;
018import javax.swing.event.ChangeListener;
019
020import org.openstreetmap.josm.data.gpx.GpxImageDirectionPositionSettings;
021import org.openstreetmap.josm.tools.GBC;
022
023/**
024 * Panel allowing user to enter {@link GpxImageDirectionPositionSettings}.
025 * @since 18061
026 */
027public class ImageDirectionPositionPanel extends JPanel {
028
029    private final JCheckBox cChangeImageDirection = new JCheckBox();
030    private final JSpinner sOffsetDegrees = new JSpinner(new SpinnerNumberModel(0, -360, 360, 1));
031
032    private final JSpinner sX = new JSpinner(new SpinnerNumberModel(0.0, -50.0, 50.0, 0.1));
033    private final JSpinner sY = new JSpinner(new SpinnerNumberModel(0.0, -50.0, 50.0, 0.1));
034    private final JSpinner sZ = new JSpinner(new SpinnerNumberModel(0.0, -20.0, 20.0, 0.1));
035
036    /**
037     * Constructs a new {@code ImageMetadataModificationPanel}
038     * @param changeDirectionText the text displayed for the change image direction combobox
039     */
040    protected ImageDirectionPositionPanel(String changeDirectionText) {
041        super(new GridBagLayout());
042
043        cChangeImageDirection.setText(changeDirectionText);
044        add(cChangeImageDirection, GBC.eol().insets(0, 0, 0, 5));
045        cChangeImageDirection.addActionListener(e -> sOffsetDegrees.setEnabled(!sOffsetDegrees.isEnabled()));
046        addSetting(tr("Offset angle in degrees:"), sOffsetDegrees);
047        sOffsetDegrees.setEnabled(false);
048
049        add(new JSeparator(SwingConstants.HORIZONTAL),
050                GBC.eol().fill(GBC.HORIZONTAL).insets(0, 12, 0, 12));
051
052        add(new JLabel(tr("Shift image relative to the direction (in meters)")),
053                GBC.eol().insets(0, 0, 0, 5));
054        addSetting(tr("X:"), sX);
055        addSetting(tr("Y:"), sY);
056        addSetting(tr("Elevation:"), sZ);
057    }
058
059    /**
060     * Returns a new {@code ImageMetadataModificationPanel} in a GPX trace context.
061     * @return a new {@code ImageMetadataModificationPanel} in a GPX trace context
062     */
063    public static ImageDirectionPositionPanel forGpxTrace() {
064        return new ImageDirectionPositionPanel(tr("Set image direction towards the next GPX waypoint"));
065    }
066
067    /**
068     * Returns a new {@code ImageMetadataModificationPanel} in an image sequence context.
069     * @return a new {@code ImageMetadataModificationPanel} in an image sequence context
070     */
071    public static ImageDirectionPositionPanel forImageSequence() {
072        return new ImageDirectionPositionPanel(tr("Set image direction towards the next one"));
073    }
074
075    protected void addSetting(String text, JComponent component) {
076        add(new JLabel(text, JLabel.RIGHT), GBC.std().insets(15, 0, 5, 5).fill(GBC.HORIZONTAL).weight(0, 0));
077        add(component, GBC.std().fill(GBC.HORIZONTAL));
078        add(GBC.glue(1, 0), GBC.eol().fill(GBC.HORIZONTAL).weight(1, 0));
079    }
080
081    /**
082     * Returns the settings set by user.
083     * @return the settings set by user
084     */
085    public GpxImageDirectionPositionSettings getSettings() {
086        return new GpxImageDirectionPositionSettings(
087                cChangeImageDirection.isSelected(),
088                (Integer) sOffsetDegrees.getValue(),
089                (Double) sX.getValue(),
090                (Double) sY.getValue(),
091                (Double) sZ.getValue());
092    }
093
094    /**
095     * Adds a focus listener on all spinners of this panel.
096     * @param focusListener focus listener to add
097     */
098    public void addFocusListenerOnComponent(FocusListener focusListener) {
099        sOffsetDegrees.addFocusListener(focusListener);
100        sX.addFocusListener(focusListener);
101        sY.addFocusListener(focusListener);
102        sZ.addFocusListener(focusListener);
103    }
104
105    /**
106     * Adds a change listener on all checkboxes of this panel.
107     * @param listener change listener to add
108     * @since 18078
109     */
110    public void addItemListenerOnComponents(ItemListener listener) {
111        cChangeImageDirection.addItemListener(listener);
112    }
113
114    /**
115     * Adds a change listener on all spinners of this panel.
116     * @param listener change listener to add
117     */
118    public void addChangeListenerOnComponents(ChangeListener listener) {
119        sOffsetDegrees.addChangeListener(listener);
120        sX.addChangeListener(listener);
121        sY.addChangeListener(listener);
122        sZ.addChangeListener(listener);
123    }
124}