Search text field implemented for non-editable tables. platform_32247-36_root
authordstrupl@netbeans.org
Sat, 12 Feb 2005 16:22:37 +0000
changeset 5813d27818223805
parent 5812 6085dba9dc48
child 5814 e69ce138011a
Search text field implemented for non-editable tables.
tableview/src/org/netbeans/swing/etable/ETable.java
tableview/src/org/netbeans/swing/etable/TestJFrame.form
tableview/src/org/netbeans/swing/etable/TestJFrame.java
     1.1 --- a/tableview/src/org/netbeans/swing/etable/ETable.java	Fri Feb 11 15:38:56 2005 +0000
     1.2 +++ b/tableview/src/org/netbeans/swing/etable/ETable.java	Sat Feb 12 16:22:37 2005 +0000
     1.3 @@ -26,23 +26,11 @@
     1.4  import java.util.List;
     1.5  import java.util.Properties;
     1.6  import java.util.Vector;
     1.7 -import javax.swing.AbstractAction;
     1.8 -import javax.swing.Action;
     1.9 -import javax.swing.BorderFactory;
    1.10 -import javax.swing.Icon;
    1.11 -import javax.swing.ImageIcon;
    1.12 -import javax.swing.JButton;
    1.13 -import javax.swing.JCheckBoxMenuItem;
    1.14 -import javax.swing.JOptionPane;
    1.15 -import javax.swing.JPopupMenu;
    1.16 -import javax.swing.JScrollPane;
    1.17 -import javax.swing.JTable;
    1.18 -import javax.swing.JViewport;
    1.19 -import javax.swing.KeyStroke;
    1.20 -import javax.swing.ListSelectionModel;
    1.21 -import javax.swing.UIManager;
    1.22 +import javax.swing.*;
    1.23  import javax.swing.border.Border;
    1.24  import javax.swing.border.CompoundBorder;
    1.25 +import javax.swing.event.DocumentEvent;
    1.26 +import javax.swing.event.DocumentListener;
    1.27  import javax.swing.event.TableModelEvent;
    1.28  import javax.swing.event.TableModelListener;
    1.29  import javax.swing.table.*;
    1.30 @@ -104,6 +92,20 @@
    1.31       *
    1.32       */
    1.33      private int quickFilterColumn = -1;
    1.34 +
    1.35 +    // Search text field related variables:
    1.36 +    /** */
    1.37 +    private String maxPrefix;
    1.38 +    /** */
    1.39 +    int SEARCH_FIELD_PREFERRED_SIZE = 160;
    1.40 +    /** */
    1.41 +    int SEARCH_FIELD_SPACE = 3;
    1.42 +    /** */
    1.43 +    final private JTextField searchTextField = new SearchTextField();
    1.44 +    /** */
    1.45 +    final private int heightOfTextField = searchTextField.getPreferredSize().height;
    1.46 +            
    1.47 +    
    1.48      
    1.49      /**
    1.50       * If the table data model is changed we reset (and then recompute)
    1.51 @@ -297,8 +299,13 @@
    1.52              if(!getShowHorizontalLines()) {
    1.53                  setShowHorizontalLines(true);
    1.54              }
    1.55 -            Border border = BorderFactory.createLineBorder
    1.56 -                    (UIManager.getColor("Table.borderAllEditable"));
    1.57 +            Color colorBorderAllEditable = UIManager.getColor("Table.borderAllEditable");
    1.58 +            Border border = null;
    1.59 +            if (colorBorderAllEditable != null) {
    1.60 +                border = BorderFactory.createLineBorder(colorBorderAllEditable);
    1.61 +            } else {
    1.62 +                border = BorderFactory.createLineBorder(Color.GRAY);
    1.63 +            }
    1.64              Border filler = BorderFactory.createLineBorder(getBackground());
    1.65              CompoundBorder compound = new CompoundBorder(border, filler);
    1.66              setBorder(new CompoundBorder(compound, border));
    1.67 @@ -310,6 +317,9 @@
    1.68          if (c != null) {
    1.69              setGridColor(c);
    1.70          }
    1.71 +        if (isFullyNonEditable()) {
    1.72 +            setupSearch();
    1.73 +        }
    1.74      }
    1.75      
    1.76      /**
    1.77 @@ -328,8 +338,11 @@
    1.78              editing = FULLY_NONEDITABLE;
    1.79              if(getShowHorizontalLines())
    1.80                  setShowHorizontalLines(false);
    1.81 -            setBorder(BorderFactory.createLineBorder
    1.82 -                    (UIManager.getColor("Table.border")));
    1.83 +            Color lineBorderColor = UIManager.getColor("Table.border");
    1.84 +            if (lineBorderColor == null) {
    1.85 +                lineBorderColor = Color.GRAY;
    1.86 +            }
    1.87 +            setBorder(BorderFactory.createLineBorder(lineBorderColor));
    1.88              Color c = UIManager.getColor("Table.noneditableGrid");
    1.89              if (c != null) {
    1.90                  setGridColor(c);
    1.91 @@ -339,7 +352,13 @@
    1.92              setBorder( null );
    1.93              if(!getShowHorizontalLines())
    1.94                  setShowHorizontalLines(true);
    1.95 -            setGridColor(UIManager.getColor("Table.defaultGrid"));
    1.96 +            Color defaultGridColor = UIManager.getColor("Table.defaultGrid");
    1.97 +            if (defaultGridColor != null) {
    1.98 +                setGridColor(defaultGridColor);
    1.99 +            }
   1.100 +        }
   1.101 +        if (isFullyNonEditable()) {
   1.102 +            setupSearch();
   1.103          }
   1.104      }
   1.105      
   1.106 @@ -349,7 +368,7 @@
   1.107       * @return  true if the the table is fully editable.
   1.108       * @see #setFullyEditable
   1.109       */
   1.110 -    public boolean getFullyEditable() {
   1.111 +    public boolean isFullyEditable() {
   1.112          return editing == FULLY_EDITABLE;
   1.113      }
   1.114      
   1.115 @@ -359,7 +378,7 @@
   1.116       * @return  true if the the table is fully non-editable.
   1.117       * @see #setFullyNonEditable
   1.118       */
   1.119 -    public boolean getFullyNonEditable() {
   1.120 +    public boolean isFullyNonEditable() {
   1.121          return editing == FULLY_NONEDITABLE;
   1.122      }
   1.123      
   1.124 @@ -555,6 +574,11 @@
   1.125       */
   1.126      protected void configureEnclosingScrollPane() {
   1.127          super.configureEnclosingScrollPane();
   1.128 +        
   1.129 +        if (isFullyNonEditable()) {
   1.130 +            setupSearch();
   1.131 +        }
   1.132 +        
   1.133          Container p = getParent();
   1.134          if (p instanceof JViewport) {
   1.135              Container gp = p.getParent();
   1.136 @@ -781,7 +805,255 @@
   1.137              etcm.writeSettings(p, propertyPrefix);
   1.138          }
   1.139      }
   1.140 +    
   1.141 +    /** searchTextField manages focus because it handles VK_TAB key */
   1.142 +    private class SearchTextField extends JTextField {
   1.143 +        public boolean isManagingFocus() {
   1.144 +            return true;
   1.145 +        }
   1.146 +        
   1.147 +        public void processKeyEvent(KeyEvent ke) {
   1.148 +            //override the default handling so that
   1.149 +            //the parent will never receive the escape key and
   1.150 +            //close a modal dialog
   1.151 +            if (ke.getKeyCode() == ke.VK_ESCAPE) {
   1.152 +                removeSearchField();
   1.153 +                // bugfix #32909, reqest focus when search field is removed
   1.154 +                SwingUtilities.invokeLater(new Runnable() {
   1.155 +                    //additional bugfix - do focus change later or removing
   1.156 +                    //the component while it's focused will cause focus to
   1.157 +                    //get transferred to the next component in the
   1.158 +                    //parent focusTraversalPolicy *after* our request
   1.159 +                    //focus completes, so focus goes into a black hole - Tim
   1.160 +                    public void run() {
   1.161 +                        ETable.this.requestFocus();
   1.162 +                    }
   1.163 +                });
   1.164 +            } else {
   1.165 +                super.processKeyEvent(ke);
   1.166 +            }
   1.167 +        }
   1.168 +    }
   1.169 +    
   1.170 +    private List doSearch(String prefix) {
   1.171 +        List results = new ArrayList();
   1.172 +        
   1.173 +        // do search forward the selected index
   1.174 +        int rows[] = getSelectedRows();
   1.175 +        int startIndex = (rows == null || rows.length == 0) ? 0 : rows[0];
   1.176 +        
   1.177 +        int size = getRowCount();
   1.178 +        if ( (size == 0) || (getColumnCount() == 0)) {
   1.179 +            // Empty table; cannot match anything.
   1.180 +            return results;
   1.181 +        }
   1.182 +        
   1.183 +        while (startIndex < size) {
   1.184 +            Object val = getValueAt(startIndex, 0);
   1.185 +            String s = null;
   1.186 +            if (val != null) {
   1.187 +                s = val.toString();    
   1.188 +            }   
   1.189 +            if ((s != null) && (s.toUpperCase().startsWith(prefix.toUpperCase()))) {
   1.190 +                results.add(new Integer(startIndex));
   1.191 +            }
   1.192 +            
   1.193 +            // initialize prefix
   1.194 +            if (maxPrefix == null) {
   1.195 +                maxPrefix = s;
   1.196 +            }
   1.197  
   1.198 +            maxPrefix = findMaxPrefix(maxPrefix, s);
   1.199 +            
   1.200 +            startIndex++;
   1.201 +        }
   1.202 +        
   1.203 +        return results;
   1.204 +    }
   1.205 +    
   1.206 +    private static String findMaxPrefix(String str1, String str2) {
   1.207 +        int i = 0;
   1.208 +        while (str1.regionMatches(true, 0, str2, 0, i)) {
   1.209 +            i++;
   1.210 +        }
   1.211 +        i--;
   1.212 +        if (i >= 0) {
   1.213 +            return str1.substring(0, i);    
   1.214 +        }
   1.215 +        return null;
   1.216 +    }
   1.217 +    
   1.218 +    private void setupSearch() {
   1.219 +        // Remove the default key listeners
   1.220 +        KeyListener keyListeners[] = (KeyListener[]) (getListeners(KeyListener.class));
   1.221 +        for (int i = 0; i < keyListeners.length; i++) {
   1.222 +            removeKeyListener(keyListeners[i]);
   1.223 +        }
   1.224 +        // Add new key listeners
   1.225 +        addKeyListener(new KeyAdapter() {
   1.226 +            private boolean armed = false;
   1.227 +            public void keyPressed(KeyEvent e) {
   1.228 +                int modifiers = e.getModifiers();
   1.229 +                int keyCode = e.getKeyCode();
   1.230 +                if ((modifiers > 0 && modifiers != KeyEvent.SHIFT_MASK) || e.isActionKey())
   1.231 +                    return ;
   1.232 +                char c = e.getKeyChar();
   1.233 +                if (!Character.isISOControl(c) && keyCode != KeyEvent.VK_SHIFT && keyCode != KeyEvent.VK_ESCAPE) {
   1.234 +                    armed = true;
   1.235 +                    e.consume();
   1.236 +                }
   1.237 +            }
   1.238 +            public void keyTyped(KeyEvent e) {
   1.239 +                if (armed) {
   1.240 +                    final KeyStroke stroke = KeyStroke.getKeyStrokeForEvent(e);
   1.241 +                    searchTextField.setText(String.valueOf(stroke.getKeyChar()));
   1.242 +                    
   1.243 +                    displaySearchField();
   1.244 +                    e.consume();
   1.245 +                    armed = false;
   1.246 +                }
   1.247 +            }
   1.248 +        });
   1.249 +        // Create a the "multi-event" listener for the text field. Instead of
   1.250 +        // adding separate instances of each needed listener, we're using a
   1.251 +        // class which implements them all. This approach is used in order
   1.252 +        // to avoid the creation of 4 instances which takes some time
   1.253 +        SearchFieldListener searchFieldListener = new SearchFieldListener();
   1.254 +        searchTextField.addKeyListener(searchFieldListener);
   1.255 +        searchTextField.addFocusListener(searchFieldListener);
   1.256 +        searchTextField.getDocument().addDocumentListener(searchFieldListener);
   1.257 +    }
   1.258 +    
   1.259 +    private class SearchFieldListener extends KeyAdapter
   1.260 +            implements DocumentListener, FocusListener {
   1.261 +        
   1.262 +        /** The last search results */
   1.263 +        private List results = new ArrayList();
   1.264 +        /** The last selected index from the search results. */
   1.265 +        private int currentSelectionIndex;
   1.266 +        
   1.267 +        /**
   1.268 +         * Default constructor.
   1.269 +         */
   1.270 +        SearchFieldListener() {
   1.271 +        }
   1.272 +        
   1.273 +        public void changedUpdate(DocumentEvent e) {
   1.274 +            searchForRow();
   1.275 +        }
   1.276 +        
   1.277 +        public void insertUpdate(DocumentEvent e) {
   1.278 +            searchForRow();
   1.279 +        }
   1.280 +        
   1.281 +        public void removeUpdate(DocumentEvent e) {
   1.282 +            searchForRow();
   1.283 +        }
   1.284 +        
   1.285 +        public void keyPressed(KeyEvent e) {
   1.286 +            int keyCode = e.getKeyCode();
   1.287 +            if (keyCode == KeyEvent.VK_ESCAPE) {
   1.288 +                removeSearchField();
   1.289 +                ETable.this.requestFocus();
   1.290 +            } else if (keyCode == KeyEvent.VK_UP) {
   1.291 +                currentSelectionIndex--;
   1.292 +                displaySearchResult();
   1.293 +                // Stop processing the event here. Otherwise it's dispatched
   1.294 +                // to the table too (which scrolls)
   1.295 +                e.consume();
   1.296 +            } else if (keyCode == KeyEvent.VK_DOWN) {
   1.297 +                currentSelectionIndex++;
   1.298 +                displaySearchResult();
   1.299 +                // Stop processing the event here. Otherwise it's dispatched
   1.300 +                // to the table too (which scrolls)
   1.301 +                e.consume();
   1.302 +            } else if (keyCode == KeyEvent.VK_TAB) {
   1.303 +                if (maxPrefix != null)
   1.304 +                    searchTextField.setText(maxPrefix);
   1.305 +                e.consume();
   1.306 +            } else if (keyCode == KeyEvent.VK_ENTER) {
   1.307 +                removeSearchField();
   1.308 +                
   1.309 +                // TODO: do something on hitting enter???
   1.310 +                e.consume();
   1.311 +                ETable.this.requestFocus();
   1.312 +            }
   1.313 +        }
   1.314 +        
   1.315 +        /** Searches for a row. */
   1.316 +        private void searchForRow() {
   1.317 +            currentSelectionIndex = 0;
   1.318 +            results.clear();
   1.319 +            maxPrefix = null;
   1.320 +            String text = searchTextField.getText().toUpperCase();
   1.321 +            if (text.length() > 0) {
   1.322 +                results = doSearch(text);
   1.323 +                displaySearchResult();
   1.324 +            }
   1.325 +        }
   1.326 +        
   1.327 +        private void displaySearchResult() {
   1.328 +            int sz = results.size();
   1.329 +            if (sz > 0) {
   1.330 +                currentSelectionIndex = ((Integer)results.get(0)).intValue();
   1.331 +                setRowSelectionInterval(currentSelectionIndex, currentSelectionIndex);
   1.332 +            } else {
   1.333 +                clearSelection();
   1.334 +            }
   1.335 +        }
   1.336 +        
   1.337 +        public void focusGained(FocusEvent e) {
   1.338 +            // Do nothing
   1.339 +        }
   1.340 +        
   1.341 +        public void focusLost(FocusEvent e) {
   1.342 +            removeSearchField();
   1.343 +        }
   1.344 +    }
   1.345 +    
   1.346 +    private void displaySearchField() {
   1.347 +        if (!searchTextField.isDisplayable()) {
   1.348 +            searchTextField.setFont(ETable.this.getFont());
   1.349 +            add(searchTextField);
   1.350 +            doLayout();
   1.351 +            searchTextField.repaint();
   1.352 +            // bugfix #28501, avoid the chars duplicated on jdk1.3
   1.353 +            SwingUtilities.invokeLater(new Runnable() {
   1.354 +                public void run() {
   1.355 +                    searchTextField.requestFocus();
   1.356 +                }
   1.357 +            });
   1.358 +        }
   1.359 +    }
   1.360 +    
   1.361 +    public void doLayout() {
   1.362 +        super.doLayout();
   1.363 +        Rectangle visibleRect = getVisibleRect();
   1.364 +        if (searchTextField.isDisplayable()) {
   1.365 +            int width = Math.min(
   1.366 +                    getPreferredSize().width - SEARCH_FIELD_SPACE * 2,
   1.367 +                    SEARCH_FIELD_PREFERRED_SIZE - SEARCH_FIELD_SPACE);
   1.368 +            
   1.369 +            searchTextField.setBounds(
   1.370 +                    Math.max(SEARCH_FIELD_SPACE,
   1.371 +                    visibleRect.x + visibleRect.width - width),
   1.372 +                    visibleRect.y + SEARCH_FIELD_SPACE,
   1.373 +                    Math.min(visibleRect.width, width) - SEARCH_FIELD_SPACE,
   1.374 +                    heightOfTextField);
   1.375 +        }
   1.376 +    }
   1.377 +    
   1.378 +    /**
   1.379 +     * Removes the search field from the table.
   1.380 +     */
   1.381 +    private void removeSearchField() {
   1.382 +        if (searchTextField.isDisplayable()) {
   1.383 +            remove(searchTextField);
   1.384 +            Rectangle r = searchTextField.getBounds();
   1.385 +            this.repaint(r);
   1.386 +        }
   1.387 +    }
   1.388 +    
   1.389      /**
   1.390       * Item to the collection when doing the sorting of table rows.
   1.391       */
     2.1 --- a/tableview/src/org/netbeans/swing/etable/TestJFrame.form	Fri Feb 11 15:38:56 2005 +0000
     2.2 +++ b/tableview/src/org/netbeans/swing/etable/TestJFrame.form	Sat Feb 12 16:22:37 2005 +0000
     2.3 @@ -22,14 +22,28 @@
     2.4          <Component class="org.netbeans.swing.etable.ETable" name="eTable1">
     2.5            <Properties>
     2.6              <Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.editors2.TableModelEditor">
     2.7 -              <Table columnCount="4" rowCount="6">
     2.8 +              <Table columnCount="5" rowCount="20">
     2.9                  <Column editable="false" title="Title 1" type="java.lang.Object">
    2.10                    <Data value="a"/>
    2.11 -                  <Data value="a"/>
    2.12 +                  <Data value="a2"/>
    2.13                    <Data value="b"/>
    2.14 -                  <Data value="b"/>
    2.15 +                  <Data value="b3"/>
    2.16                    <Data value="c"/>
    2.17 -                  <Data value="c"/>
    2.18 +                  <Data value="c2"/>
    2.19 +                  <Data value="d"/>
    2.20 +                  <Data value="d3"/>
    2.21 +                  <Data value="e"/>
    2.22 +                  <Data value="e2"/>
    2.23 +                  <Data value="f"/>
    2.24 +                  <Data value="f2"/>
    2.25 +                  <Data value="g"/>
    2.26 +                  <Data value="g2"/>
    2.27 +                  <Data value="h"/>
    2.28 +                  <Data value="h2"/>
    2.29 +                  <Data value="i"/>
    2.30 +                  <Data value="i2"/>
    2.31 +                  <Data value="j"/>
    2.32 +                  <Data value="j2"/>
    2.33                  </Column>
    2.34                  <Column editable="false" title="Title 2" type="java.lang.Object">
    2.35                    <Data value="x"/>
    2.36 @@ -38,6 +52,20 @@
    2.37                    <Data value="w"/>
    2.38                    <Data value="m"/>
    2.39                    <Data value="n"/>
    2.40 +                  <Data value="df"/>
    2.41 +                  <Data value="f"/>
    2.42 +                  <Data value="mm"/>
    2.43 +                  <Data value="mg"/>
    2.44 +                  <Data value="q"/>
    2.45 +                  <Data value="dfg"/>
    2.46 +                  <Data value="dfg"/>
    2.47 +                  <Data value="fg"/>
    2.48 +                  <Data value="xb"/>
    2.49 +                  <Data value="sdf"/>
    2.50 +                  <Data value="g"/>
    2.51 +                  <Data value="mn"/>
    2.52 +                  <Data value="we"/>
    2.53 +                  <Data value="kl"/>
    2.54                  </Column>
    2.55                  <Column editable="false" title="Title 3" type="java.lang.Object">
    2.56                    <Data value="tttttttt"/>
    2.57 @@ -46,6 +74,20 @@
    2.58                    <Data value="mmmmmm"/>
    2.59                    <Data value="kkkkkkkkkk"/>
    2.60                    <Data value="kkkkk"/>
    2.61 +                  <Data value="wwwwwwww"/>
    2.62 +                  <Data value="ggggggggggggg"/>
    2.63 +                  <Data value="hhhhhhhhhhhh"/>
    2.64 +                  <Data value="qqqqqqqqqqq"/>
    2.65 +                  <Data value="ffffffffffffff"/>
    2.66 +                  <Data value="nnnnnnnnnnnn"/>
    2.67 +                  <Data value="mmmmmmmmmmm"/>
    2.68 +                  <Data value="qqqqqqqqq"/>
    2.69 +                  <Data value="nnnnnnnnnnn"/>
    2.70 +                  <Data value="asdfasdf"/>
    2.71 +                  <Data value="fads"/>
    2.72 +                  <Data value="asdf"/>
    2.73 +                  <Data value="asdfdsafafsdfsd"/>
    2.74 +                  <Data value="asdfasdfafsdasdfasd"/>
    2.75                  </Column>
    2.76                  <Column editable="false" title="Title 4" type="java.lang.Integer">
    2.77                    <Data value="5"/>
    2.78 @@ -54,6 +96,42 @@
    2.79                    <Data value="1"/>
    2.80                    <Data value="10000"/>
    2.81                    <Data value="4"/>
    2.82 +                  <Data value="17"/>
    2.83 +                  <Data value="13"/>
    2.84 +                  <Data value="2"/>
    2.85 +                  <Data value="8"/>
    2.86 +                  <Data value="23"/>
    2.87 +                  <Data value="100"/>
    2.88 +                  <Data value="57"/>
    2.89 +                  <Data value="3"/>
    2.90 +                  <Data value="123"/>
    2.91 +                  <Data value="321"/>
    2.92 +                  <Data value="42"/>
    2.93 +                  <Data value="72"/>
    2.94 +                  <Data value="88"/>
    2.95 +                  <Data value="99"/>
    2.96 +                </Column>
    2.97 +                <Column editable="false" title="Title 5" type="java.lang.Object">
    2.98 +                  <Data value="aaaaab"/>
    2.99 +                  <Data value="aaaaaa"/>
   2.100 +                  <Data value="aaaaaa"/>
   2.101 +                  <Data value="aaaaab"/>
   2.102 +                  <Data value="aaaaab"/>
   2.103 +                  <Data value="aaaaab"/>
   2.104 +                  <Data value="aaaaaccc"/>
   2.105 +                  <Data value="aaaaac"/>
   2.106 +                  <Data value="aaaaac"/>
   2.107 +                  <Data value="aaaaad"/>
   2.108 +                  <Data value="aaaaa"/>
   2.109 +                  <Data value="aaaaa"/>
   2.110 +                  <Data value="aaaaa"/>
   2.111 +                  <Data value="aaaaa"/>
   2.112 +                  <Data value="aaaaa"/>
   2.113 +                  <Data value="aaaaa"/>
   2.114 +                  <Data value="aaaaarrrr"/>
   2.115 +                  <Data value="aaaaa"/>
   2.116 +                  <Data value="aaaaaaaaa"/>
   2.117 +                  <Data value="aaaaa"/>
   2.118                  </Column>
   2.119                </Table>
   2.120              </Property>
     3.1 --- a/tableview/src/org/netbeans/swing/etable/TestJFrame.java	Fri Feb 11 15:38:56 2005 +0000
     3.2 +++ b/tableview/src/org/netbeans/swing/etable/TestJFrame.java	Sat Feb 12 16:22:37 2005 +0000
     3.3 @@ -32,7 +32,7 @@
     3.4      public TestJFrame() {
     3.5          initComponents();
     3.6  //        eTable1.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_OFF);
     3.7 -//        eTable1.setFullyNonEditable(true);
     3.8 +        eTable1.setFullyNonEditable(true);
     3.9      }
    3.10      
    3.11      /** This method is called from within the constructor to
    3.12 @@ -53,22 +53,36 @@
    3.13          setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
    3.14          eTable1.setModel(new javax.swing.table.DefaultTableModel(
    3.15              new Object [][] {
    3.16 -                {"a", "x", "tttttttt", new Integer(5)},
    3.17 -                {"a", "y", "ggggggggg", new Integer(10)},
    3.18 -                {"b", "z", "nnnnnnnn", new Integer(7)},
    3.19 -                {"b", "w", "mmmmmm", new Integer(1)},
    3.20 -                {"c", "m", "kkkkkkkkkk", new Integer(10000)},
    3.21 -                {"c", "n", "kkkkk", new Integer(4)}
    3.22 +                {"a", "x", "tttttttt", new Integer(5), "aaaaab"},
    3.23 +                {"a2", "y", "ggggggggg", new Integer(10), "aaaaaa"},
    3.24 +                {"b", "z", "nnnnnnnn", new Integer(7), "aaaaaa"},
    3.25 +                {"b3", "w", "mmmmmm", new Integer(1), "aaaaab"},
    3.26 +                {"c", "m", "kkkkkkkkkk", new Integer(10000), "aaaaab"},
    3.27 +                {"c2", "n", "kkkkk", new Integer(4), "aaaaab"},
    3.28 +                {"d", "df", "wwwwwwww", new Integer(17), "aaaaaccc"},
    3.29 +                {"d3", "f", "ggggggggggggg", new Integer(13), "aaaaac"},
    3.30 +                {"e", "mm", "hhhhhhhhhhhh", new Integer(2), "aaaaac"},
    3.31 +                {"e2", "mg", "qqqqqqqqqqq", new Integer(8), "aaaaad"},
    3.32 +                {"f", "q", "ffffffffffffff", new Integer(23), "aaaaa"},
    3.33 +                {"f2", "dfg", "nnnnnnnnnnnn", new Integer(100), "aaaaa"},
    3.34 +                {"g", "dfg", "mmmmmmmmmmm", new Integer(57), "aaaaa"},
    3.35 +                {"g2", "fg", "qqqqqqqqq", new Integer(3), "aaaaa"},
    3.36 +                {"h", "xb", "nnnnnnnnnnn", new Integer(123), "aaaaa"},
    3.37 +                {"h2", "sdf", "asdfasdf", new Integer(321), "aaaaa"},
    3.38 +                {"i", "g", "fads", new Integer(42), "aaaaarrrr"},
    3.39 +                {"i2", "mn", "asdf", new Integer(72), "aaaaa"},
    3.40 +                {"j", "we", "asdfdsafafsdfsd", new Integer(88), "aaaaaaaaa"},
    3.41 +                {"j2", "kl", "asdfasdfafsdasdfasd", new Integer(99), "aaaaa"}
    3.42              },
    3.43              new String [] {
    3.44 -                "Title 1", "Title 2", "Title 3", "Title 4"
    3.45 +                "Title 1", "Title 2", "Title 3", "Title 4", "Title 5"
    3.46              }
    3.47          ) {
    3.48              Class[] types = new Class [] {
    3.49 -                java.lang.Object.class, java.lang.Object.class, java.lang.Object.class, java.lang.Integer.class
    3.50 +                java.lang.Object.class, java.lang.Object.class, java.lang.Object.class, java.lang.Integer.class, java.lang.Object.class
    3.51              };
    3.52              boolean[] canEdit = new boolean [] {
    3.53 -                false, false, false, false
    3.54 +                false, false, false, false, false
    3.55              };
    3.56  
    3.57              public Class getColumnClass(int columnIndex) {
    3.58 @@ -83,7 +97,7 @@
    3.59  
    3.60          getContentPane().add(jScrollPane1, java.awt.BorderLayout.CENTER);
    3.61  
    3.62 -        jPanel1.setLayout(new java.awt.GridLayout());
    3.63 +        jPanel1.setLayout(new java.awt.GridLayout(1, 0));
    3.64  
    3.65          jPanel1.add(jTextField1);
    3.66