View Javadoc
1   package com.github.celldynamics.quimp.plugin.utils;
2   
3   import java.awt.BorderLayout;
4   import java.awt.Choice;
5   import java.awt.Component;
6   import java.awt.Dimension;
7   import java.awt.FlowLayout;
8   import java.awt.GridLayout;
9   import java.awt.Label;
10  import java.awt.Panel;
11  import java.awt.event.ActionEvent;
12  import java.awt.event.ActionListener;
13  import java.awt.event.WindowAdapter;
14  import java.awt.event.WindowEvent;
15  import java.util.Arrays;
16  import java.util.Collections;
17  import java.util.HashSet;
18  import java.util.Iterator;
19  import java.util.Map;
20  import java.util.Set;
21  
22  import javax.swing.BorderFactory;
23  import javax.swing.JButton;
24  import javax.swing.JCheckBox;
25  import javax.swing.JFrame;
26  import javax.swing.JPanel;
27  import javax.swing.JScrollPane;
28  import javax.swing.JSpinner;
29  import javax.swing.JTextPane;
30  import javax.swing.SpinnerNumberModel;
31  
32  import org.apache.commons.lang3.text.WordUtils;
33  import org.slf4j.Logger;
34  import org.slf4j.LoggerFactory;
35  
36  import com.github.celldynamics.quimp.plugin.ParamList;
37  
38  /**
39   * Simple window builder for QuimP plugins
40   * 
41   * <p>Allow user to construct simple window for his plugins just by passing textual description of
42   * what
43   * that window should contain.
44   * 
45   * <p>Main function (BuildWindow) accepts HashMap with pairs [name,params] where name is unique name
46   * of
47   * the parameter and params defines how this parameter will be displayed in UI (see
48   * BuildWindow(final ParamList)). Using this mapping there is next list ui created that contains
49   * the same names but now joined with UI components. This list is used for addressing these
50   * component basing on theirs names. The UI controls are stored at ui which is protected and
51   * may be used for influencing these controls by user. To identify certain UI control its name is
52   * required which is the string passed as first dimension of def definition passed to to
53   * BuildWindow method. Below code shows how to change property of control
54   * 
55   * <pre>
56   * <code>
57   * String key = "paramname"; // case insensitive JSpinner comp = (JSpinner)
58   * ui.get(key); // get control using its name
59   * comp.getEditor()).getTextField().setColumns(5);
60   * </code>
61   * </pre>
62   * 
63   * <p><b>Warning</b>
64   * 
65   * <p>UI type as JSpinner keeps data in double format even in values passed through by
66   * setValues(ParamList) are integer (ParamList keeps data as String). Therefore getValues can return
67   * this list with the same data but in double syntax (5 -> 5.0). Any try of convention of "5.0" to
68   * integer value will cause NumberFormatException. To avoid this problem use
69   * QuimP.plugin.ParamList.getIntValue(String) from ParamList of treat all strings in ParamList as
70   * Double.
71   * 
72   * <p>Methods getValues() and setValues() should be used by class extending QWindowBuilder for
73   * setting
74   * and achieving parameters from GUI. Note that parameters in UIs are validated only when they
75   * become out of focus. Until cursor is in UI its value is not updated internally, thus getValues()
76   * returns its old snapshot.
77   * 
78   * <p>reservedKeys is list of reserved keys that are not UI elements. They are processed in
79   * different
80   * way. Other behaviour: By default on close or when user clicked Cancel window is hided only, not
81   * destroyed. This is due to preservation of all settings. Lifetime of window depends on QuimP
82   * 
83   * <p>All parameters passed to and from QWindowBuilder as ParamList are encoded as {@link String}
84   * 
85   * @author p.baniukiewicz
86   */
87  public abstract class QWindowBuilder {
88  
89    /**
90     * The Constant LOGGER.
91     */
92    static final Logger LOGGER = LoggerFactory.getLogger(QWindowBuilder.class.getName());
93  
94    /**
95     * Delimiter used in UI definition strings.
96     */
97    public static final char DELIMITER = ':';
98    /**
99     * The plugin wnd.
100    */
101   protected JFrame pluginWnd; // main window object
102 
103   /**
104    * The window state.
105    */
106   protected boolean windowState; // current window state \c true if visible
107 
108   /**
109    * The plugin panel.
110    */
111   protected JPanel pluginPanel; // Main panel extended on whole \c pluginWnd
112 
113   /**
114    * The ui.
115    */
116   protected ComponentList ui; // list of all UI elements
117 
118   /** The def. */
119   private ParamList def; // definition of window and parameters
120 
121   /** The reserved keys. */
122   private final HashSet<String> reservedKeys =
123           new HashSet<String>(Arrays.asList(new String[] { "help", "name" })); // reserved keys
124 
125   /** The ui type. */
126   // definition string - positions of configuration data in value string (see BuildWindow)
127   private final int uiType = 0; // type of UI control to create
128 
129   /** The sr min. */
130   private final int srMin = 1; // spinner min value
131 
132   /** The sr max. */
133   private final int srMax = 2; // spinner max value
134 
135   /** The sr step. */
136   private final int srStep = 3; // spinner step value
137 
138   /** The sr default. */
139   private final int srDefault = 4; // spinner default value
140 
141   /** The sr fract. */
142   private final int srFract = 5; // spinner number of fractional places
143 
144   /**
145    * The apply B.
146    */
147   protected JButton applyB; // Apply button (do nothing but may be overwritten)
148 
149   /**
150    * The cancel B.
151    */
152   protected JButton cancelB; // Cancel button (hides it)
153 
154   /**
155    * Default constructor.
156    */
157   public QWindowBuilder() {
158     LOGGER.trace("Entering constructor");
159     ui = new ComponentList();
160     def = null;
161   }
162 
163   /**
164    * Main window builder.
165    * 
166    * <p>The window is constructed using configuration provided by def parameter which is Map of
167    * [key,value]. The key is the name of the parameter that should be related to value held in it
168    * (e.g window, smooth, step, etc.). The name is not case sensitive but should not contain spaces
169    * (use underscore). Keys are strictly related
170    * to UI elements that are created by this method (basing on configuration passed in value). Keys
171    * are used to produce UI control label, any underscore is replaced by space and key is
172    * capitalised.
173    * There are two special names that are not related to UI directly:
174    * <ol>
175    * <li>help - defines textual help provided as parameter. It supports HTML
176    * <li>name - defines plugin name provided as parameter
177    * </ol>
178    * 
179    * <p>The parameter list is defined as String and its content is depended on key. For help and
180    * name it contains single string with help text and plugin name respectively.
181    * 
182    * <p>The UI elements are defined for all other cases in value filed of Map as comma separated
183    * string. UI element name is case insensitive. Known UI are as follows:
184    * <ul>
185    * <li>spinner - creates Spinner control. It requires 4 parameters (in order). Fifth parameter is
186    * help text and it is <b>optional</b>
187    * <ol>
188    * <li>minimal range
189    * <li>maximal range
190    * <li>step
191    * <li>default value
192    * </ol>
193    * <li>spinnerd - creates Spinner control. It requires 5 parameters (in order). Sixth parameter is
194    * help text and it is <b>optional</b>
195    * <ol>
196    * <li>minimal range
197    * <li>maximal range
198    * <li>step
199    * <li>default value
200    * <li>Precision as number of fractional numbers
201    * </ol>
202    * <li>choiceh - creates Choice control. It requires 1 or more parameters - entries in list. Last
203    * parameter is help text and it is <b>compulsory</b>
204    * <ol>
205    * <li>first entry
206    * <li>second entry
207    * <li>...
208    * <li>help
209    * </ol>
210    * <li>choice - creates Choice control without help. It requires 0 or more parameters
211    * <ol>
212    * <li>first entry
213    * <li>second entry
214    * <li>...
215    * </ol>
216    * <li>button - creates JButton control. It requires 1 parameter. Last parameter is
217    * help text and it is <b>optional</b>
218    * <ol>
219    * <li>Name on the button
220    * </ol>
221    * <li>checkbox - creates JCheckBox control. It requires 2 parameters (in order). Last parameter
222    * is help text and it is <b>optional</b>
223    * <ol>
224    * <li>checkbox name
225    * <li>initial value (true or false)
226    * </ol>
227    * </ul>
228    * For choice calling {@link QWindowBuilder#setValues(ParamList)} is justified only if passed
229    * parameters will be present in list already (so it has
230    * been used during creation of window, passed in constructor) In this case it causes selection
231    * of this entry in list. Otherwise passed value will be ignored. setVales for Choice does
232    * not add new entry to list.
233    * 
234    * <p>The type of required UI element associated with given parameter name (Key) is coded in
235    * value of given Key in accordance with list above. The correct order of sub-parameters must be
236    * preserved. By default window is not visible yet. User must call ShowWindow or ToggleWindow. The
237    * Apply
238    * button does nothing. It is only to refocus after change of values in spinners. They are not
239    * updated until unfocused. User can overwrite this behaviour in his own class derived from
240    * QWindowBuilder
241    * 
242    * <p>This method can be overridden in implementing class that allows for e.g. setting size of the
243    * window or add listeners:
244    * 
245    * <pre>
246    * <code>
247    * public void buildWindow(ParamList def) {
248    *     super.buildWindow(def); // add preferred size to this window
249    *     pluginWnd.setPreferredSize(new Dimension(300, 450));
250    *     pluginWnd.pack();
251    *     pluginWnd.setVisible(true);
252    *     pluginWnd.addWindowListener(new myWindowAdapter()); // close not hide ((JButton)
253    *     ui.get("Load Mask")).addActionListener(this);
254    *     applyB.addActionListener(this);
255    * }
256    * </code>
257    * </pre>
258    * 
259    * <p>Throw IllegalArgumentException or other unchecked exceptions on wrong syntax of def
260    * 
261    * @param def Configuration as described
262    */
263   public void buildWindow(final ParamList def) {
264     if (def.size() < 2) {
265       throw new IllegalArgumentException("Window must contain title and" + " at least one control");
266     }
267     this.def = def; // remember parameters
268     ui.clear(); // clear all ui stored on second call of third method
269 
270     pluginWnd = new JFrame(); // create frame with title given as first position in table
271     pluginPanel = new JPanel(); // main panel on whole window
272     // divide window on two zones
273     // - upper for controls,
274     // - middle for help
275     pluginPanel.setLayout(new BorderLayout());
276 
277     Panel north = new Panel(); // panel for controls
278     // get layout size
279     int siz = def.size(); // total size of Map
280     // but grid layout does not contain help and name or other reserved non
281     // UI keys
282     Set<String> s = def.keySet(); // get Set of keys
283     for (String k : reservedKeys) { // and check if any of them is in s
284       if (s.contains(k)) {
285         siz--;
286       }
287     }
288     GridLayout gridL = new GridLayout(siz, 3); // Nx3, by default in row we have control and its des
289     north.setLayout(gridL);
290     gridL.setVgap(5); // set bigger gaps
291     gridL.setHgap(5);
292 
293     String helpText;
294     // iterate over def entries except first one which is always title
295     // every decoded control is put into ordered hashmap together with its
296     // descriptor (label)
297     for (Map.Entry<String, String> e : def.entrySet()) {
298       String key = e.getKey();
299       if (reservedKeys.contains(key)) {
300         continue;
301       }
302       String[] uiparams = StringParser.getParams(e.getValue(), DELIMITER);
303       if (uiparams.length == 0) {
304         throw new IllegalArgumentException("Probably wrong syntax in UI definition");
305       }
306       switch (uiparams[uiType].toLowerCase()) {
307         case "spinner": // by default all spinners are double
308         {
309           helpText = spinnerVerify(uiparams);
310           SpinnerNumberModel model = new SpinnerNumberModel(Double.parseDouble(uiparams[srDefault]),
311                   Double.parseDouble(uiparams[srMin]), // min
312                   Double.parseDouble(uiparams[srMax]), // max
313                   Double.parseDouble(uiparams[srStep])); // step
314           JSpinner sp = new JSpinner(model);
315           ui.put(key, sp);
316 
317           String lab = WordUtils.capitalize(key.replaceAll("_", " "));
318           ui.put(key + "label", new Label(lab)); // des
319           ui.put(key + "help", new Label(helpText));
320         }
321           break;
322         case "spinnerd": // by default all spinners are double
323         {
324           helpText = spinnerdVerify(uiparams);
325           SpinnerNumberModel model = new SpinnerNumberModel(Double.parseDouble(uiparams[srDefault]),
326                   Double.parseDouble(uiparams[srMin]), // min
327                   Double.parseDouble(uiparams[srMax]), // max
328                   Double.parseDouble(uiparams[srStep])); // step
329           JSpinner sp = new JSpinner(model);
330           String c = "";
331           Double val = Double.parseDouble(uiparams[srFract]);
332           if (val == 0) {
333             c = "0";
334           } else {
335             c = "0." + String.join("", Collections.nCopies(val.intValue(), "0"));
336           }
337           sp.setEditor(new JSpinner.NumberEditor(sp, c));
338           ui.put(key, sp);
339           String lab = WordUtils.capitalize(key.replaceAll("_", " "));
340           ui.put(key + "label", new Label(lab)); // des
341           ui.put(key + "help", new Label(helpText));
342         }
343           break;
344         case "choiceh": {
345           helpText = choiceVerify(uiparams);
346           Choice c = new Choice();
347           for (int i = uiType + 1; i < uiparams.length - 1; i++) {
348             c.add(uiparams[i]);
349           }
350           c.select(0);
351           ui.put(key, c);
352           String lab = WordUtils.capitalize(key.replaceAll("_", " "));
353           ui.put(key + "label", new Label(lab)); // des
354           ui.put(key + "help", new Label(helpText));
355         }
356           break;
357         case "choice": {
358           if (uiparams.length < 1) { // default
359             throw new IllegalArgumentException(
360                     "Probably wrong syntax in UI definition for " + uiparams[uiType]);
361           }
362           Choice c1 = new Choice();
363           for (int i = uiType + 1; i < uiparams.length; i++) {
364             c1.add(uiparams[i]);
365           }
366           c1.select(0);
367           ui.put(key, c1);
368           String lab = WordUtils.capitalize(key.replaceAll("_", " "));
369           ui.put(key + "label", new Label(lab)); // add description
370           ui.put(key + "help", new Label(""));
371         }
372           break;
373         case "button": {
374           helpText = buttonVerify(uiparams);
375           JButton b = new JButton(uiparams[1]);
376           ui.put(key, b);
377           String lab = WordUtils.capitalize(key.replaceAll("_", " "));
378           ui.put(key + "label", new Label(lab)); // des
379           ui.put(key + "help", new Label(helpText));
380         }
381           break;
382         case "checkbox": {
383           helpText = checkboxVerify(uiparams);
384           JCheckBox cb = new JCheckBox(WordUtils.capitalize(uiparams[1]),
385                   Boolean.parseBoolean(uiparams[2]));
386           ui.put(key, cb);
387           String lab = WordUtils.capitalize(key.replaceAll("_", " "));
388           ui.put(key + "label", new Label(lab)); // des
389           ui.put(key + "help", new Label(helpText));
390         }
391           break;
392         default:
393           // wrong param syntax
394           throw new IllegalArgumentException("Unknown ui type" + " provided: " + key);
395       }
396     }
397 
398     // iterate over all components and add them to grid layout
399     for (Map.Entry<String, Component> me : ui.entrySet()) {
400       north.add(me.getValue());
401     }
402 
403     // add non ui elements
404     if (def.containsKey("name")) {
405       // border on whole window
406       pluginPanel.setBorder(BorderFactory.createTitledBorder("Plugin " + def.get("name")));
407     }
408     if (def.containsKey("help")) {
409       JTextPane helpArea = new JTextPane(); // default size of text area
410       // helpArea.setLineWrap(true);
411       // helpArea.setWrapStyleWord(true);
412       helpArea.setPreferredSize(new Dimension(80, 200));
413       helpArea.setContentType("text/html");
414       JScrollPane helpPanel = new JScrollPane(helpArea);
415       helpArea.setEditable(false);
416       pluginPanel.add(helpPanel, BorderLayout.CENTER); // locate at center position
417       helpArea.setText(def.get("help")); // set help text
418     }
419 
420     // add Apply button on south
421     Panel south = new Panel();
422     south.setLayout(new FlowLayout());
423     applyB = new JButton("Apply");
424     south.add(applyB);
425     cancelB = new JButton("Cancel");
426     south.add(cancelB);
427     // set action on Cancel - window is hided
428     cancelB.addActionListener(new ActionListener() {
429       @Override
430       public void actionPerformed(ActionEvent e) {
431         pluginWnd.setVisible(false);
432         windowState = false;
433       }
434     });
435 
436     // build window
437     pluginPanel.add(north, BorderLayout.NORTH);
438     pluginPanel.add(south, BorderLayout.SOUTH);
439     pluginWnd.add(pluginPanel);
440     pluginWnd.pack();
441     // add listener on close - window is hidden to preserve settings
442     pluginWnd.addWindowListener(new WindowAdapter() {
443       @Override
444       public void windowClosing(WindowEvent we) {
445         LOGGER.trace("Window closing");
446         windowState = false;
447         pluginWnd.setVisible(false);
448       }
449     });
450     windowState = false; // by default window is not visible. User must call ShowWindow or ToggleWi
451   }
452 
453   /**
454    * Verify syntax for spinner and return help text if any.
455    * 
456    * @param uiparams uiparams
457    * @return Help text (last from list)
458    */
459   private String spinnerVerify(String[] uiparams) {
460     String helpText = "";
461     if (uiparams.length != 5) { // default
462       if (uiparams.length != 6) { // with help text
463         throw new IllegalArgumentException(
464                 "Probably wrong syntax in UI definition for " + uiparams[uiType]);
465       } else {
466         helpText = uiparams[5];
467       }
468     }
469     return helpText;
470   }
471 
472   /**
473    * Verify syntax for spinner and return help text if any.
474    * 
475    * @param uiparams uiparams
476    * @return Help text (last from list)
477    */
478   private String spinnerdVerify(String[] uiparams) {
479     String helpText = "";
480     if (uiparams.length != 6) { // default
481       if (uiparams.length != 7) { // with help text
482         throw new IllegalArgumentException(
483                 "Probably wrong syntax in UI definition for " + uiparams[uiType]);
484       } else {
485         helpText = uiparams[5];
486       }
487     }
488     return helpText;
489   }
490 
491   /**
492    * Verify syntax for choice and return help text if any.
493    * 
494    * @param uiparams uiparams
495    * @return Help text (last from list)
496    */
497   private String choiceVerify(String[] uiparams) {
498     String helpText = "";
499     if (uiparams.length < 2) { // default
500       throw new IllegalArgumentException(
501               "Probably wrong syntax in UI definition for " + uiparams[uiType]);
502     } else {
503       helpText = uiparams[uiparams.length - 1];
504     }
505     return helpText;
506   }
507 
508   /**
509    * Verify syntax for button and return help text if any.
510    * 
511    * @param uiparams uiparams
512    * @return Help text (last from list)
513    */
514   private String buttonVerify(String[] uiparams) {
515     String helpText = "";
516     if (uiparams.length != 2) { // default
517       if (uiparams.length != 3) {
518         throw new IllegalArgumentException(
519                 "Probably wrong syntax in UI definition for " + uiparams[uiType]);
520       } else {
521         helpText = uiparams[2];
522       }
523     }
524     return helpText;
525   }
526 
527   /**
528    * Verify syntax for checkbox and return help text if any.
529    * 
530    * @param uiparams uiparams
531    * @return Help text (last from list)
532    */
533   private String checkboxVerify(String[] uiparams) {
534     String helpText = "";
535     if (uiparams.length != 3) { // default
536       if (uiparams.length != 4) {
537         throw new IllegalArgumentException(
538                 "Probably wrong syntax in UI definition for " + uiparams[uiType]);
539       } else {
540         helpText = uiparams[3];
541       }
542     }
543     return helpText;
544   }
545 
546   /**
547    * Show or hide window.
548    * 
549    * @param state State of the window true to show, false to hide
550    */
551   public void showWindow(boolean state) {
552     pluginWnd.setVisible(state);
553     windowState = state;
554   }
555 
556   /**
557    * Toggle window visibility if input is \c true. Close it immediately if input is \c false
558    * 
559    * @param val Demanded state of window. If \c true visibility of window is toggled, if \c false
560    *        window is closing.
561    * @return Current status of window \c true if visible, \c false if not
562    */
563   public boolean toggleWindow(boolean val) {
564     if (!val) {
565       windowState = false;
566       showWindow(windowState);
567     } else {
568       windowState = !windowState;
569       showWindow(windowState);
570     }
571     return windowState;
572   }
573 
574   /**
575    * Check if window is visible.
576    * 
577    * @return true if it is visible, false otherwise
578    */
579   public boolean isWindowVisible() {
580     return windowState;
581   }
582 
583   /**
584    * Set plugin parameters.
585    * 
586    * <p>Use the same parameters names as in BuildWindow(Map[String, String[]]). The name of the
587    * parameter is key in Map. Every parameter passed to this method should have its
588    * representation in GUI and thus it must be present in def parameter of
589    * BuildWindow(Map[String, String[]]) All values are passed as:
590    * <ol>
591    * <li>Double in case of spinners
592    * </ol>
593    * 
594    * <p>User has to care for correct format passed to UI control. If input values are above range
595    * defined in def, new range is set for UI control. Unknown keys are skipped.
596    * 
597    * @param vals [key,value] pairs to fill UI.
598    */
599   public void setValues(final ParamList vals) {
600     // iterate over parameters and match names to UIs
601     for (Map.Entry<String, String> e : vals.entrySet()) {
602       String key = e.getKey();
603       String val = e.getValue();
604       // find key in def and get type of control and its instance
605       String[] ret = def.getParsed(key, DELIMITER);
606       if (ret.length == 0) { // skip unknown codes
607         return;
608       }
609       switch (ret[uiType].toLowerCase()) { // first string in vals is type
610         // control, see BuildWindow
611         case "spinnerd":
612         case "spinner": {
613           // get UI component of name key (keys in vals must match to keys in BuildWindow(def))
614           JSpinner comp = (JSpinner) ui.get(key);
615           comp.setValue(Double.parseDouble(val)); // set value from vals
616           SpinnerNumberModel sm = (SpinnerNumberModel) comp.getModel();
617           if (sm.getNextValue() == null) {
618             sm.setMaximum(Double.parseDouble(val));
619           } else if (sm.getPreviousValue() == null) {
620             sm.setMinimum(Double.parseDouble(val));
621           }
622           break;
623         }
624         case "choiceh":
625         case "choice": {
626           Choice comp = (Choice) ui.get(key);
627           comp.select(val);
628           break;
629         }
630         case "button": {
631           break;
632         }
633         case "checkbox": {
634           JCheckBox c = (JCheckBox) ui.get(key);
635           c.setSelected(Boolean.parseBoolean(val));
636           break;
637         }
638         default:
639           throw new IllegalArgumentException(
640                   "Unknown UI type in setValues: " + def.getParsed(key, DELIMITER)[uiType]);
641       }
642     }
643   }
644 
645   /**
646    * Receives parameters related to UI elements as Map.
647    * 
648    * <p>To get one particular parameter use getIntegerFromUI(String) or getDoubleFromUI(String)
649    * 
650    * <p>JSpinners are set to support double values and that values are returned here. It means that
651    * originally pushed to UI integers are changed to Double what can affect set/getpluginConfig
652    * from filter interface as well
653    * 
654    * @return List of [key,param], where key is the name of parameter passed to QWindowBuilder
655    *         class through BuildWindow method. The method remaps those keys to related UI controls
656    *         and reads values associated to them.
657    * @see #getDoubleFromUI(String)
658    * @see #getIntegerFromUI(String)
659    * 
660    */
661   public ParamList getValues() {
662     ParamLists/quimp/plugin/ParamList.html#ParamList">ParamList ret = new ParamList();
663     // iterate over all UI elements
664     Iterator<Map.Entry<String, Component>> entryIterator = ui.entrySet().iterator();
665     while (entryIterator.hasNext()) {
666       Map.Entry<String, Component> m = entryIterator.next();
667       String key = m.getKey();
668       // check type of component
669       switch (def.getParsed(key, DELIMITER)[uiType].toLowerCase()) {
670         case "spinnerd":
671         case "spinner": {
672           JSpinner val = (JSpinner) m.getValue(); // get value
673           ret.put(key, String.valueOf(val.getValue())); // store it in returned Map at
674           // the same key
675           break;
676         }
677         case "choiceh":
678         case "choice": {
679           Choice val = (Choice) m.getValue();
680           ret.put(key, val.getSelectedItem());
681           break;
682         }
683         case "button": {
684           break;
685         }
686         case "checkbox": {
687           JCheckBox c = (JCheckBox) m.getValue();
688           ret.put(key, String.valueOf(c.isSelected()));
689           break;
690         }
691         default:
692           throw new IllegalArgumentException(
693                   "Unknown UI type in getValues: " + def.getParsed(key, DELIMITER)[uiType]);
694       }
695       entryIterator.next(); // skip label. ui Map has repeating entries UI,label,UI1,label1,..
696       entryIterator.next(); // skip help
697     }
698     return ret;
699   }
700 
701   /**
702    * Return value related to given key.
703    * 
704    * <p>Value is retrieved from ui element related to given \b key. Relation between keys and ui
705    * elements is defined by user in configuration list provided to buildWindow(final ParamList).
706    * 
707    * <p>The key must be defined and exists in that list. In case of wrong conversion it may be
708    * exception thrown. User is responsible to call this method for proper key.
709    * 
710    * @param key Key to be read from configuration list, case insensitive
711    * @return integer representation of value under \c key
712    * @see #buildWindow(ParamList)
713    */
714   public int getIntegerFromUI(final String key) {
715     return (int) getDoubleFromUI(key);
716   }
717 
718   /**
719    * Return value related to given key.
720    * 
721    * @param key key
722    * @return {@link #getIntegerFromUI(String)}
723    * 
724    * @see #getIntegerFromUI(String)
725    */
726   public double getDoubleFromUI(final String key) {
727     // get list of all params from ui as <key,val> list
728     ParamList uiParam = getValues();
729     return uiParam.getDoubleValue(key);
730   }
731 
732   /**
733    * Return value related to given key.
734    * 
735    * @param key key
736    * @return {@link #getIntegerFromUI(String)}
737    * 
738    * @see #getIntegerFromUI(String)
739    */
740   public boolean getBooleanFromUI(final String key) {
741     // get list of all params from ui as <key,val> list
742     ParamList uiParam = getValues();
743     return uiParam.getBooleanValue(key);
744   }
745 
746   /**
747    * Return value related to given key. Added for convenience
748    * 
749    * @param key key
750    * @return {@link #getIntegerFromUI(String)}
751    * 
752    * @see #getIntegerFromUI(String)
753    */
754   public String getStringFromUI(final String key) {
755     // get list of all params from ui as <key,val> list
756     ParamList uiParam = getValues();
757     return uiParam.getStringValue(key);
758   }
759 
760   /**
761    * Stores components under Keys that are not case insensitive.
762    *
763    * @author p.baniukiewicz
764    */
765   public class ComponentList extends LinkedStringMap<Component> {
766 
767     /** The Constant serialVersionUID. */
768     private static final long serialVersionUID = -5157229346595354602L;
769 
770   }
771 }