001/*
002 *                    BioJava development code
003 *
004 * This code may be freely distributed and modified under the
005 * terms of the GNU Lesser General Public Licence.  This should
006 * be distributed with the code.  If you do not have a copy,
007 * see:
008 *
009 *      http://www.gnu.org/copyleft/lesser.html
010 *
011 * Copyright for this code is held jointly by the individual
012 * authors.  These should be listed in @author doc comments.
013 *
014 * For more information on the BioJava project and its aims,
015 * or to join the biojava-l mailing list, visit the home page
016 * at:
017 *
018 *      http://www.biojava.org/
019 *
020 */
021package org.biojava.nbio.structure.align.gui;
022
023import org.biojava.nbio.structure.align.ce.ConfigStrucAligParams;
024
025import javax.swing.*;
026import java.awt.*;
027import java.awt.event.ActionEvent;
028import java.awt.event.ActionListener;
029import java.lang.reflect.Method;
030import java.util.ArrayList;
031import java.util.List;
032
033/**
034 * UI for {@link ConfigStrucAligParams}, for the AlignmentGUI.
035 *
036 * Visually parameters are displayed as a label and an input field such as a text box.
037 * The following methods are used to determine which properties are accessible:
038 * <ul>
039 * <li> {@link ConfigStrucAligParams#getUserConfigParameterNames() getUserConfigParameterNames()}
040 *      Parameter labels
041 * <li> {@link ConfigStrucAligParams#getUserConfigParameters() getUserConfigParameters()}
042 *      Parameter method names, to be prepended with 'set' or 'get'
043 * <li> {@link ConfigStrucAligParams#getUserConfigTypes() getUserConfigTypes()}
044 *      Types for each parameter (Integer, Float, Boolean, Enum, String[])
045 * <li> {@link ConfigStrucAligParams#getUserConfigHelp() getUserConfigHelp()}
046 *      Alt text for each parameter
047 * </ul>
048 *
049 * @author Andreas Prlic
050 *
051 */
052public class ParameterGUI extends JFrame{
053
054        private static final long serialVersionUID = 723386061184110161L;
055
056        private ConfigStrucAligParams params ;
057        private List<Component> textFields;
058
059        /**
060         * Constructor for a ParameterGUI. Generalization for any type of
061         * Structural Alignment algorithm that implements the parameter interface.
062         *
063         * @param params parameter bean
064         * @param algorithm name of the algorithm
065         */
066        @SuppressWarnings("rawtypes")
067        public ParameterGUI(ConfigStrucAligParams params, String algorithm) {
068
069                if (params == null) return;
070                this.params = params;
071
072                this.setTitle("Parameters for " + algorithm);
073
074                List<String> names = params.getUserConfigParameterNames();
075                List<String> keys  = params.getUserConfigParameters();
076                List<Class> types  = params.getUserConfigTypes();
077
078                List<String> helps = params.getUserConfigHelp();
079
080                // quick check for bugs in params
081                assert(names.size() == keys.size());
082                assert(names.size() == types.size());
083                assert(names.size() == helps.size());
084
085                textFields = new ArrayList<Component>();
086                Box vBox = Box.createVerticalBox();
087
088                for (int i = 0 ; i < keys.size(); i++){
089                        Class type = types.get(i);
090
091                        Box hBox = Box.createHorizontalBox();
092                        String name = names.get(i);
093                        JLabel label = new JLabel(name);
094                        String help = helps.get(i);
095                        label.setToolTipText(help);
096                        String key = keys.get(i);
097                        Object value = getValue(key);
098
099                        String data = value.toString();
100                        Component field;
101                        if ( type.isEnum() ) {
102                                Object[] values = type.getEnumConstants();
103                                JComboBox jcbox = new JComboBox(values);
104                                jcbox.setSelectedItem(value);
105                                field = jcbox;
106
107                        } else if ( type == Boolean.class){
108
109                                String[] values = new String[]{"true","false"};
110                                JComboBox jcbox = new JComboBox(values);
111                                if ( data.equalsIgnoreCase("false"))
112                                        jcbox.setSelectedIndex(1);
113                                else
114                                        jcbox.setSelectedIndex(0);
115
116                                field = jcbox;
117
118                                //field.setToolTipText(help);
119
120                        } else {
121                                JTextField tfield = new JTextField(10);
122
123                                if ( type == String[].class) {
124                                        String stuff = "";
125                                        for ( String da : (String[]) value){
126                                                stuff += da + " ";
127                                        }
128                                        data = stuff;
129
130
131                                }
132                                tfield.setText(data);
133                                tfield.setToolTipText(help);
134                                field = tfield;
135                        }
136
137                        hBox.add(label);
138                        hBox.add(Box.createGlue());
139                        hBox.add(field);
140
141                        vBox.add(hBox);
142
143                        textFields.add(field);
144
145                }
146
147
148                JButton abort = new JButton("Cancel");
149                abort.addActionListener(new ActionListener(){
150                        @Override
151                        public void actionPerformed(ActionEvent event) {
152                                destroy();
153                                dispose();               }
154                });
155
156                JButton defaultB = new JButton("Default");
157                defaultB.addActionListener(new ActionListener(){
158                        @Override
159                        public void actionPerformed(ActionEvent event) {
160                                setDefault();
161                        }
162                });
163
164                JButton close = new JButton("Apply");
165
166                close.addActionListener(new ActionListener(){
167                        @Override
168                        public void actionPerformed(ActionEvent event) {
169
170                                storeParameters();
171
172                                destroy();
173                                dispose();               }
174                });
175
176                Box hBox = Box.createHorizontalBox();
177                hBox.add(abort);
178                hBox.add(Box.createGlue());
179                hBox.add(defaultB);
180                hBox.add(Box.createGlue());
181                hBox.add(close);
182
183                vBox.add(hBox);
184                this.getContentPane().add(vBox);
185                this.pack();
186                this.setVisible(true);
187        }
188
189        @SuppressWarnings({  "rawtypes" })
190        protected void setDefault() {
191                params.reset();
192
193                List<String> keys  = params.getUserConfigParameters();
194                List<Class> types  = params.getUserConfigTypes();
195                //List<String> names = params.getUserConfigParameterNames();
196                for (int i = 0 ; i < keys.size(); i++){
197
198                        Class type = types.get(i);
199                        Object data = getValue(keys.get(i));
200                        if( type.isEnum()) {
201                                JComboBox field = (JComboBox)  textFields.get(i);
202                                field.setSelectedItem(data);
203                                field.updateUI();
204                        }  else if ( type == Boolean.class){
205                                JComboBox field = (JComboBox)  textFields.get(i);
206                                if ( data.toString().equalsIgnoreCase("false"))
207                                        field.setSelectedIndex(1);
208                                else
209                                        field.setSelectedIndex(0);
210                                field.updateUI();
211
212                        } else {
213                                JTextField field = (JTextField)textFields.get(i);
214                                if ( type.isArray()){
215                                        String stuff = "";
216                                        for ( String da : (String[]) data){
217                                                stuff += da + " ";
218                                        }
219
220                                        field.setText(stuff);
221                                } else {
222
223                                        field.setText(data.toString());
224                                }
225                                field.updateUI();
226                        }
227
228
229                }
230                this.repaint();
231
232        }
233
234        private void destroy(){
235                //avoid memory leaks...
236                textFields = null;
237                params = null;
238        }
239
240        @SuppressWarnings("rawtypes")
241        protected void storeParameters() {
242                //List<String> names = params.getUserConfigParameterNames();
243                List<String> keys = params.getUserConfigParameters();
244                List<Class> types = params.getUserConfigTypes();
245
246                for (int i = 0 ; i < keys.size(); i++){
247                        Class type = types.get(i);
248                        String key  = keys.get(i);
249                        // String name = keys.get(i);
250                        String value = null;
251                        System.out.println(key);
252                        if( type.isEnum() ) {
253                                JComboBox field = (JComboBox)  textFields.get(i);
254                                Enum sel = (Enum)field.getSelectedItem();
255                                value = sel.name();
256                        } else if ( type == Boolean.class){
257                                JComboBox field = (JComboBox)  textFields.get(i);
258                                int sel = field.getSelectedIndex();
259                                Boolean flag = true;
260                                if ( sel == 1 )
261                                        flag = false;
262                                value = flag.toString();
263                        } else {
264                                JTextField field = (JTextField)textFields.get(i);
265                                value = field.getText();
266                        }
267
268                        setValue(key, type, value);
269                }
270
271                System.out.println("new parameters: " + params.toString());
272
273        }
274
275        @SuppressWarnings({ "unchecked" })
276        private void setValue(String name, Class type, String value) {
277                try {
278                        String methodName = "set" + name;
279
280                        Class paramC = params.getClass();
281
282                        Method m =paramC.getMethod(methodName,type);
283
284
285                        Object data = null;
286
287                        if ( type == Integer.class){
288                                data = Integer.parseInt(value);
289                        } else if ( type == Double.class){
290                                data = Double.parseDouble(value);
291                        } else if ( type == Float.class) {
292                                data = Float.parseFloat(value);
293                        } else if ( type == Boolean.class) {
294                                data = Boolean.parseBoolean(value);
295                        } else if ( type == Short.class) {
296                                data = Short.parseShort(value);
297                        } else if ( type == String[].class) {
298                                data = value.split(" ");
299                        } else if ( type.isEnum() ) {
300                                data = Enum.valueOf(type, value);
301                        }
302
303                        if (data == null){
304                                System.err.println("Could not set value " + value +
305                                                " for field " + name);
306                                return;
307                        }
308                        m.invoke(params, data);
309
310
311                } catch (Exception e){
312                        e.printStackTrace();
313
314                }
315
316        }
317
318        @SuppressWarnings("unchecked")
319        private Object  getValue(String name){
320                // first try with get form
321                try {
322                        String methodName = "get" + name;
323
324                        Class paramC = params.getClass();
325
326                        Method m;
327                        try {
328                                //try boolean getter
329                                m = paramC.getMethod(methodName,(Class[])null);
330                        } catch(NoSuchMethodException e) {
331                                //try boolean getter
332                                methodName = "is" + name;
333                                m = paramC.getMethod(methodName,(Class[])null);
334                        }
335
336                        Object value = m.invoke(params);
337
338                        return value;
339                } catch (Exception e){
340                        e.printStackTrace();
341                        return null;
342                }
343
344
345        }
346}