Index: DefaultJExpressionBuilder.java
===================================================================
--- DefaultJExpressionBuilder.java	(revision 43986)
+++ DefaultJExpressionBuilder.java	(revision 43987)
@@ -5,12 +5,16 @@
 import java.awt.Dimension;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
+import java.awt.event.KeyAdapter;
 import java.awt.event.KeyEvent;
 import java.awt.event.KeyListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
 import java.net.URL;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Date;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Objects;
 import javax.swing.DefaultListCellRenderer;
@@ -18,10 +22,12 @@
 import javax.swing.JComponent;
 import javax.swing.JLabel;
 import javax.swing.JList;
+import javax.swing.JOptionPane;
 import javax.swing.JTree;
 import javax.swing.SwingUtilities;
 import javax.swing.event.ListSelectionEvent;
 import javax.swing.event.ListSelectionListener;
+import javax.swing.event.TreeModelEvent;
 import javax.swing.event.TreeModelListener;
 import javax.swing.event.TreeSelectionEvent;
 import javax.swing.event.TreeSelectionListener;
@@ -51,6 +57,7 @@
 import org.gvsig.tools.swing.api.ToolsSwingManager;
 import org.gvsig.tools.swing.api.pickercontroller.PickerController;
 import org.gvsig.tools.swing.api.script.ScriptSwingManager;
+import org.gvsig.tools.swing.api.threadsafedialogs.ThreadSafeDialogsManager;
 import org.gvsig.tools.swing.icontheme.IconTheme;
 
 /**
@@ -67,13 +74,16 @@
     private ScriptSwingManager.ScriptEditor scriptEditor;
     
     private final ExpressionBuilderConfig config;
+    private ElementsTreeModel treeModel;
     
     private class ElementsTreeModel implements TreeModel {
 
         private final GroupElement root;
+        private final HashSet<TreeModelListener> listeners;
 
         public ElementsTreeModel(GroupElement root) {
             this.root = root;
+            this.listeners = new HashSet<>();
         }
 
         @Override
@@ -81,6 +91,20 @@
             return this.root;
         }
 
+        public void reload() {
+            this.reload(this.root);
+            this.fireTreeChanged();
+        }
+        
+        private void reload(Element element) {
+            if (element instanceof Element) {
+                if (element instanceof GroupElement) {
+                    reload(element);
+                }
+                element.reload();
+            }
+        }
+        
         private List<Element> getChilds(final GroupElement node) {
             List<Element> x = new ArrayList<>();
             for (Element element : node.getElements()) {
@@ -125,12 +149,20 @@
 
         @Override
         public void addTreeModelListener(TreeModelListener l) {
+            this.listeners.add(l);
         }
 
         @Override
         public void removeTreeModelListener(TreeModelListener l) {
+            this.listeners.remove(l);
         }
 
+        protected void fireTreeChanged() {
+            for (TreeModelListener listener : listeners) {
+                TreeModelEvent e = new TreeModelEvent(this, new Object[] {this.root});
+                listener.treeNodesChanged(e);
+            }
+        }
     }
 
     public DefaultJExpressionBuilder(ExpressionEvaluatorSwingManager manager, ExpressionBuilderConfig config) {
@@ -246,6 +278,47 @@
                 }
             }
         });
+        this.lstSimpleElement.addMouseListener(new MouseAdapter() {
+            @Override
+            public void mouseClicked(MouseEvent e) {
+                if( e.getButton()==MouseEvent.BUTTON1 && e.getClickCount()==2 ) {
+                    ListElement<SimpleElement> element = (ListElement<SimpleElement>) lstSimpleElement.getSelectedValue();
+                    if (element != null) {
+                        doSelectElement(element.getValue());
+                        doInsert(element.getValue());
+                    }
+                }
+            }
+        });
+        this.lstSimpleElement.addKeyListener(new KeyAdapter() {
+            @Override
+            public void keyReleased(KeyEvent e) {
+                if( e.getKeyCode()==KeyEvent.VK_ENTER ) {
+                    ListElement<SimpleElement> element = (ListElement<SimpleElement>) lstSimpleElement.getSelectedValue();
+                    if (element != null) {
+                        doSelectElement(element.getValue());
+                        doInsert(element.getValue());
+                    }
+                }
+            }
+            
+            @Override
+            public void keyTyped(KeyEvent e) {
+                if( e.getKeyCode()==KeyEvent.VK_ENTER ) {
+                    ListElement<SimpleElement> element = (ListElement<SimpleElement>) lstSimpleElement.getSelectedValue();
+                    if (element != null) {
+                        doSelectElement(element.getValue());
+                        doInsert(element.getValue());
+                    }
+                }
+            }
+        });
+        this.btnSimpleElementTimeLimit.addActionListener(new ActionListener() {
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                doSetTimeLimit();
+            }
+        });
         this.btnSimpleElementSortDown.addActionListener(new ActionListener() {
             @Override
             public void actionPerformed(ActionEvent e) {
@@ -260,21 +333,13 @@
                 model.sort(true);
             }
         });
-        this.txtSimpleElementFilter.addKeyListener(new KeyListener() {
+        this.txtSimpleElementFilter.addKeyListener(new KeyAdapter() {
             @Override
             public void keyTyped(KeyEvent e) {
                 if (e.getKeyChar() == '\n') {
                     doFilter();
                 }
             }
-
-            @Override
-            public void keyPressed(KeyEvent e) {
-            }
-
-            @Override
-            public void keyReleased(KeyEvent e) {
-            }
         });
         this.btnAdd.addActionListener(new ActionListener() {
             @Override
@@ -335,7 +400,8 @@
         this.pnlScriptEditorContainer.add(this.scriptEditor.asJComponent(), BorderLayout.CENTER);
     
         this.tabExpressionBuilder.setEnabledAt(0, this.config.getScriptsEnabled());
-        this.setPreferredSize(new Dimension(750, 500));
+        this.setPreferredSize(new Dimension(650, 350));
+        this.txtDescription.setPreferredSize(new Dimension(200,200));
     }
 
     private String removeCursorMark(String s) {
@@ -388,31 +454,31 @@
                 html.append("<b>Value</b> NULL<br>\n");
             } else {
                 html.append("<b>Constant</b><br>\n<br>\n");
-                html.append("<b>Value</b> ").append(repr(value)).append("<br>\n<br>\n");
-                html.append("<b>Type</b> ").append(value.getClass().getSimpleName()).append("<br>\n<br>\n");
+                html.append("<b>Value</b> ").append(repr(value)).append("<br>\n");
+                html.append("<b>Type</b> ").append(value.getClass().getSimpleName()).append("<br>\n");
             }
             
         } else if( element instanceof VariableElement ) {
                 VariableElement var = (VariableElement)element;
-                html.append("<b>").append(var.getLabel()).append("</b><br>\n<br>\n\n");
-                html.append("<b>Source</b> ").append(var.getSource()).append("<br>\n<br>\n");
-                html.append("<b>Name</b> ").append(var.getName()).append("<br>\n<br>\n");
-                html.append("<b>Type</b> ").append(var.getTypeName()).append("<br>\n<br>\n");
+                html.append("<b>").append(var.getLabel()).append("</b><br>\n<br>\n");
+                html.append("<b>Source</b> ").append(var.getSource()).append("<br>\n");
+                html.append("<b>Name</b> ").append(var.getName()).append("<br>\n");
+                html.append("<b>Type</b> ").append(var.getTypeName()).append("<br>\n");
             
         } else if( element instanceof FunctionElement ) {
             Function function = ((FunctionElement)element).getFunction();
             if (function == null) {
                 html.append("<b>Function</b> ").append(element.getName()).append("<br>\n<br>\n");
                 html.append("<b>Return</b> Object<br>\n<br>\n");
-                html.append("<b>Template:</b> ").append(element.getName()).append("()<br>\n<br>\n");
+                html.append("<b>Template:</b> ").append(element.getName()).append("()<br>\n");
             } else {
                 html.append("<b>Function</b> ").append(element.getName()).append("<br>\n<br>\n");
                 html.append("<b>Return</b> ");
                 html.append(StringUtils.isEmpty(function.returnType())?"Objec": function.returnType());
-                html.append("<br>\n<br>\n");
+                html.append("<br>\n");
                 html.append("<b>Template</b> ");
                 html.append(StringUtils.isEmpty(function.template())?element.getName()+"()": removeCursorMark(function.template()));
-                html.append("<br>\n<br>\n");
+                html.append("<br>\n");
 
                 String[] args = function.descriptionArgs();
                 if (args != null) {
@@ -426,7 +492,7 @@
             }
         } else {
             html.append("<b>Generic element<br>\n<br>\n");
-            html.append("<b>Name</b> ").append(element.getName()).append("</br>\n</br>\n");
+            html.append("<b>Name</b> ").append(element.getName()).append("</br>\n");
             
         }
 
@@ -548,6 +614,11 @@
     }
     
     @Override
+    public void addSymbolTable(String name) {
+        this.config.addSymbolTable(name);
+    }
+    
+    @Override
     public void addSymbolTable(SymbolTable symbolTable) {
         this.config.addSymbolTable(symbolTable);
     }
@@ -575,10 +646,12 @@
     
     @Override
     public JComponent asJComponent() {
-        TreeModel model = new ElementsTreeModel(
-                this.manager.createGroupElement("Elements", this.getElements())
-        );
-        this.treeElements.setModel(model);
+        if( this.treeModel == null ) {
+            this.treeModel = new ElementsTreeModel(
+                    this.manager.createGroupElement("_Elements", this.getElements())
+            );
+            this.treeElements.setModel(this.treeModel);
+        }
         return this;
     }
 
@@ -597,4 +670,27 @@
         
     }
     
+    private void doSetTimeLimit() {
+        ThreadSafeDialogsManager dialogs = ToolsSwingLocator.getThreadSafeDialogsManager();
+        String s = dialogs.inputDialog(
+                "Indicate the time limit in seconds for calculating the elements", 
+                "Time limit", 
+                JOptionPane.QUESTION_MESSAGE, 
+                String.valueOf(this.config.getSimpleElementsLimit())
+        );
+        if( StringUtils.isBlank(s) ) {
+            return;
+        }
+        try {
+            int n = Integer.parseInt(s);
+            this.config.setSimpleElementsLimit(n);
+            this.treeModel.reload();
+        } catch(Exception ex) {
+            dialogs.messageDialog(
+                "Invalid time limit '"+s+"'.", 
+                "Time limit", 
+                JOptionPane.WARNING_MESSAGE
+            );                    
+        }
+    }
 }
