001    /*
002     * Copyright 2002 - 2008 JEuclid, http://jeuclid.sf.net
003     * 
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     *      http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    
017    /* $Id: ParametersDialog.java,v 613e4e95ff93 2010/02/17 13:59:15 max $ */
018    
019    package net.sourceforge.jeuclid.app.mathviewer;
020    
021    import java.awt.BorderLayout;
022    import java.awt.Color;
023    import java.awt.FlowLayout;
024    import java.awt.GridBagConstraints;
025    import java.awt.GridBagLayout;
026    import java.awt.event.ActionEvent;
027    import java.awt.event.ActionListener;
028    import java.util.Collections;
029    import java.util.HashMap;
030    import java.util.List;
031    import java.util.Map;
032    
033    import javax.swing.Box;
034    import javax.swing.JButton;
035    import javax.swing.JCheckBox;
036    import javax.swing.JColorChooser;
037    import javax.swing.JComboBox;
038    import javax.swing.JComponent;
039    import javax.swing.JDialog;
040    import javax.swing.JFormattedTextField;
041    import javax.swing.JLabel;
042    import javax.swing.JPanel;
043    import javax.swing.JTextField;
044    import javax.swing.WindowConstants;
045    
046    import net.sourceforge.jeuclid.context.Parameter;
047    import net.sourceforge.jeuclid.context.typewrapper.BooleanTypeWrapper;
048    import net.sourceforge.jeuclid.context.typewrapper.ColorTypeWrapper;
049    import net.sourceforge.jeuclid.context.typewrapper.EnumTypeWrapper;
050    import net.sourceforge.jeuclid.context.typewrapper.NumberTypeWrapper;
051    import net.sourceforge.jeuclid.context.typewrapper.TypeWrapper;
052    import net.sourceforge.jeuclid.swing.JMathComponent;
053    
054    /**
055     * Dialog that lets user see and change all Layout Parameters.
056     * 
057     * @see Parameter
058     * 
059     * @version $Revision: 613e4e95ff93 $
060     */
061    // CHECKSTYLE:OFF
062    public class ParametersDialog extends JDialog {
063        // CHECKSTYLE:ON
064    
065        private static final int NUMBER_OF_COLUMNS = 5;
066    
067        /**
068         * 
069         */
070        private static final long serialVersionUID = 1L;
071    
072        private static final int PADDING = 30;
073    
074        private static interface DataExtractor {
075            Object extractData();
076        }
077    
078        private final JMathComponent mathComponent;
079    
080        // CHECKSTYLE:OFF
081        private final Map<Parameter, DataExtractor> extractors = new HashMap<Parameter, DataExtractor>();
082    
083        // CHECKSTYLE:ON
084    
085        /**
086         * Initialize all the swing stuff.
087         * 
088         * @param parent
089         *            parent MainFrame
090         */
091        public ParametersDialog(final MainFrame parent) {
092            super(parent);
093            this.mathComponent = parent.getMathComponent();
094            this.init();
095        }
096    
097        private void init() {
098    
099            this
100                    .setTitle(Messages
101                            .getString("MathViewer.ParametersDialog.title"));
102            this.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
103            final JPanel paramArea = new JPanel(new GridBagLayout());
104            this.getContentPane().add(paramArea, BorderLayout.CENTER);
105            final GridBagConstraints gbc = new GridBagConstraints();
106            gbc.gridy = 0;
107            gbc.weightx = 1;
108            gbc.ipadx = ParametersDialog.PADDING;
109            // gbc.fill = GridBagConstraints.HORIZONTAL;
110            for (final Parameter param : Parameter.values()) {
111                final JLabel label = new JLabel(param.getOptionName());
112                label.setToolTipText(param.getOptionDesc());
113                gbc.gridx = 0;
114                gbc.anchor = GridBagConstraints.EAST;
115                paramArea.add(label, gbc);
116                gbc.gridx = 1;
117                gbc.anchor = GridBagConstraints.WEST;
118                paramArea.add(this.createInputForParameter(param), gbc);
119                gbc.gridy++;
120            }
121            this.setupButtonsPanel();
122            this.setSize(this.getMinimumSize().width,
123                    this.getPreferredSize().height);
124            this.setLocationByPlatform(true);
125            this.setModal(true);
126        }
127    
128        private void setupButtonsPanel() {
129            final JPanel buttonsPanel = new JPanel(new FlowLayout(
130                    FlowLayout.CENTER));
131            final JButton btnSave = new JButton(Messages
132                    .getString("MathViewer.save"));
133            btnSave.setMnemonic('S');
134            btnSave.addActionListener(new ActionListener() {
135                public void actionPerformed(final ActionEvent e) {
136                    final Map<Parameter, Object> newValues = new HashMap<Parameter, Object>();
137                    for (final Map.Entry<Parameter, ParametersDialog.DataExtractor> entry : ParametersDialog.this.extractors
138                            .entrySet()) {
139                        newValues.put(entry.getKey(), entry.getValue()
140                                .extractData());
141                    }
142                    ParametersDialog.this.mathComponent.setParameters(newValues);
143                    ParametersDialog.this.dispose();
144                }
145            });
146            buttonsPanel.add(btnSave);
147            final JButton btnCancel = new JButton(Messages
148                    .getString("MathViewer.cancel"));
149            btnCancel.setMnemonic('C');
150            btnCancel.addActionListener(new ActionListener() {
151                public void actionPerformed(final ActionEvent e) {
152                    ParametersDialog.this.dispose();
153                }
154            });
155            buttonsPanel.add(btnCancel);
156            this.getContentPane().add(buttonsPanel, BorderLayout.SOUTH);
157        }
158    
159        private JComponent createInputForParameter(final Parameter param) {
160            JComponent input = null;
161            final TypeWrapper type = param.getTypeWrapper();
162            DataExtractor dataExtractor = null;
163            if (type instanceof BooleanTypeWrapper) {
164                final JCheckBox checkbox = new JCheckBox();
165                Boolean val = (Boolean) this.mathComponent.getParameters()
166                        .getParameter(param);
167                if (val == null) {
168                    val = Boolean.FALSE;
169                }
170                checkbox.setSelected(val.booleanValue());
171                input = checkbox;
172                dataExtractor = new DataExtractor() {
173                    public Object extractData() {
174                        return Boolean.valueOf(checkbox.isSelected());
175                    }
176                };
177            } else if (type instanceof ColorTypeWrapper) {
178                final Map.Entry<? extends JComponent, ? extends ParametersDialog.DataExtractor> entry = this
179                        .setupColorParameter(param);
180                input = entry.getKey();
181                dataExtractor = entry.getValue();
182            } else if (type instanceof EnumTypeWrapper) {
183                final Object val = this.mathComponent.getParameters()
184                        .getParameter(param);
185                final JComboBox comboBox = new JComboBox(((EnumTypeWrapper) type)
186                        .values());
187                if (val != null) {
188                    comboBox.setSelectedItem(val);
189                }
190                input = comboBox;
191                dataExtractor = new DataExtractor() {
192                    public Object extractData() {
193                        return comboBox.getSelectedItem();
194                    }
195                };
196            } else if (type instanceof NumberTypeWrapper) {
197                final JFormattedTextField ftf = new JFormattedTextField(
198                        this.mathComponent.getParameters().getParameter(param));
199                input = ftf;
200                dataExtractor = new DataExtractor() {
201                    public Object extractData() {
202                        return ftf.getValue();
203                    }
204                };
205            } else {
206                final Map.Entry<? extends JComponent, ? extends ParametersDialog.DataExtractor> entry = this
207                        .setupTextParameter(param);
208                input = entry.getKey();
209                dataExtractor = entry.getValue();
210            }
211            input.setToolTipText(param.getOptionDesc());
212            this.extractors.put(param, dataExtractor);
213            return input;
214        }
215    
216        private Map.Entry<? extends JComponent, ? extends ParametersDialog.DataExtractor> setupColorParameter(
217                final Parameter param) {
218            Color color = (Color) this.mathComponent.getParameters()
219                    .getParameter(param);
220            if (color == null) {
221                color = Color.white;
222            }
223            final JColorChooser colorChooser = new JColorChooser(color);
224            final JDialog colorChooserDialog = JColorChooser.createDialog(
225                    ParametersDialog.this, Messages
226                            .getString("MathViewer.ParametersDialog.pickColor"),
227                    true, colorChooser, null, null);
228            final JPanel box = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0));
229            box.setBackground(color);
230            final JButton btn = new JButton(Messages
231                    .getString("MathViewer.ParametersDialog.showColorChooser"));
232            btn.addActionListener(new ActionListener() {
233                public void actionPerformed(final ActionEvent e) {
234                    colorChooserDialog.setVisible(true);
235                    box.setBackground(colorChooser.getColor());
236                    box.revalidate();
237                }
238            });
239            box.add(btn);
240            box.add(Box.createHorizontalStrut(ParametersDialog.PADDING));
241            return Collections.singletonMap(box, new DataExtractor() {
242                public Object extractData() {
243                    return colorChooser.getColor();
244                }
245            }).entrySet().iterator().next();
246        }
247    
248        private Map.Entry<? extends JComponent, ? extends ParametersDialog.DataExtractor> setupTextParameter(
249                final Parameter param) {
250            final JTextField text = new JTextField(param
251                    .toString(this.mathComponent.getParameters().getParameter(
252                            param)), 50);
253            text.setMinimumSize(text.getPreferredSize());
254            final Box box = Box.createHorizontalBox();
255            box.add(text);
256            box
257                    .add(Box
258                            .createHorizontalStrut(ParametersDialog.NUMBER_OF_COLUMNS));
259            final JButton btn = new JButton(Messages
260                    .getString("MathViewer.ParametersDialog.showFontSelection"));
261            box.add(btn);
262            btn.addActionListener(new ActionListener() {
263                @SuppressWarnings("unchecked")
264                public void actionPerformed(final ActionEvent e) {
265                    final FontSelectionDialog fsd = new FontSelectionDialog(
266                            ParametersDialog.this, (List<String>) param
267                                    .fromString(text.getText()));
268                    fsd.setVisible(true);
269                    if (fsd.getFontNames().isEmpty()) {
270                        text.setText("");
271                    } else {
272                        text.setText(param.toString(fsd.getFontNames()));
273                    }
274                }
275            });
276            return Collections.singletonMap(box, new DataExtractor() {
277                public Object extractData() {
278                    return param.fromString(text.getText());
279                }
280            }).entrySet().iterator().next();
281        }
282    }