001/*
002 * Gridarta MMORPG map editor for Crossfire, Daimonin and similar games.
003 * Copyright (C) 2000-2011 The Gridarta Developers.
004 *
005 * This program is free software; you can redistribute it and/or modify
006 * it under the terms of the GNU General Public License as published by
007 * the Free Software Foundation; either version 2 of the License, or
008 * (at your option) any later version.
009 *
010 * This program is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
013 * GNU General Public License for more details.
014 *
015 * You should have received a copy of the GNU General Public License along
016 * with this program; if not, write to the Free Software Foundation, Inc.,
017 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
018 */
019
020package net.sf.gridarta.gui.dialog.plugin.parameter;
021
022import java.awt.Component;
023import java.awt.event.ActionEvent;
024import java.awt.event.ActionListener;
025import javax.swing.AbstractButton;
026import javax.swing.JButton;
027import javax.swing.JComponent;
028import javax.swing.JOptionPane;
029import javax.swing.JSpinner;
030import javax.swing.SpinnerModel;
031import javax.swing.SpinnerNumberModel;
032import javax.swing.event.ChangeEvent;
033import javax.swing.event.ChangeListener;
034import net.sf.gridarta.model.archetype.Archetype;
035import net.sf.gridarta.model.gameobject.GameObject;
036import net.sf.gridarta.model.maparchobject.MapArchObject;
037import net.sf.gridarta.plugin.parameter.DoubleParameter;
038import org.jetbrains.annotations.NotNull;
039import org.jetbrains.annotations.Nullable;
040
041public class DoubleParameterView<G extends GameObject<G, A, R>, A extends MapArchObject<A>, R extends Archetype<G, A, R>> implements PluginParameterView<G, A, R>, ActionListener {
042
043    @NotNull
044    private final JSpinner value;
045
046    @NotNull
047    private final AbstractButton config;
048
049    @NotNull
050    private final DoubleParameter<G, A, R> parameter;
051
052    public DoubleParameterView(@NotNull final DoubleParameter<G, A, R> param) {
053        parameter = param;
054        final SpinnerModel mdl = new SpinnerNumberModel(0.0, param.getMin(), param.getMax(), (param.getMax() - param.getMin()) / 100.0);
055        value = new TooltipSpinner(mdl);
056        try {
057            value.setValue(param.getValue());
058        } catch (final IllegalArgumentException e) {
059        }
060        value.addChangeListener(new ChangeListener() {
061
062            @Override
063            public void stateChanged(final ChangeEvent e) {
064                parameter.setValue((Double) ((SpinnerNumberModel) value.getModel()).getNumber());
065            }
066        });
067        config = new JButton("...");
068        config.setBorderPainted(false);
069        config.setActionCommand("Config");
070        config.addActionListener(this);
071        updateTooltip();
072    }
073
074    @NotNull
075    @Override
076    public JComponent getConfigComponent() {
077        return config;
078    }
079
080    @NotNull
081    @Override
082    public JComponent getValueComponent() {
083        return value;
084    }
085
086    private void updateTooltip() {
087        final String toolTip = "[" + Double.toString(parameter.getMin()) + "," + Double.toString(parameter.getMax()) + "]";
088        config.setToolTipText(toolTip);
089        value.setToolTipText(toolTip);
090    }
091
092    @Override
093    public void actionPerformed(@NotNull final ActionEvent e) {
094        if (e.getActionCommand().equals("Config")) {
095            final String min = JOptionPane.showInputDialog("Minimum value:", parameter.getMin());
096            final String max = JOptionPane.showInputDialog("Maximum value:", parameter.getMax());
097            try {
098                parameter.setMax(Double.parseDouble(max));
099                parameter.setMin(Double.parseDouble(min));
100                ((SpinnerNumberModel) value.getModel()).setMinimum(parameter.getMin());
101                ((SpinnerNumberModel) value.getModel()).setMaximum(parameter.getMax());
102                updateTooltip();
103            } catch (final Exception ex) {
104                JOptionPane.showMessageDialog(null, "Could not change Double configuration");
105            }
106        }
107    }
108
109    /**
110     * Extends JSpinner to work around it's tooltip bug This bug has been fixed
111     * since Java 5.0 but we need this workaround for java 4.x users.
112     * @author tchize
113     */
114    private static class TooltipSpinner extends JSpinner {
115
116        private static final long serialVersionUID = 1L;
117
118        private TooltipSpinner(@NotNull final SpinnerModel model) {
119            super(model);
120        }
121
122        /**
123         * This override the JSpinner method to force the tooltip in all
124         * sub-components.
125         * @param text the tooltip to show
126         */
127        @Override
128        public void setToolTipText(@Nullable final String text) {
129            forceTooltip(this, text);
130        }
131
132        private void forceTooltip(@NotNull final JComponent c, @Nullable final String tip) {
133            if (c == this) {
134                super.setToolTipText(tip);
135            } else {
136                c.setToolTipText(tip);
137            }
138            final Component[] components = c.getComponents();
139            for (final Component component : components) {
140                if (component instanceof JComponent) {
141                    forceTooltip((JComponent) component, tip);
142                }
143            }
144        }
145
146    }
147
148}