001    /*
002     $Id: DefaultTableModel.java,v 1.2 2003/11/04 12:00:48 jstrachan Exp $
003    
004     Copyright 2003 (C) James Strachan and Bob Mcwhirter. All Rights Reserved.
005    
006     Redistribution and use of this software and associated documentation
007     ("Software"), with or without modification, are permitted provided
008     that the following conditions are met:
009    
010     1. Redistributions of source code must retain copyright
011        statements and notices.  Redistributions must also contain a
012        copy of this document.
013    
014     2. Redistributions in binary form must reproduce the
015        above copyright notice, this list of conditions and the
016        following disclaimer in the documentation and/or other
017        materials provided with the distribution.
018    
019     3. The name "groovy" must not be used to endorse or promote
020        products derived from this Software without prior written
021        permission of The Codehaus.  For written permission,
022        please contact info@codehaus.org.
023    
024     4. Products derived from this Software may not be called "groovy"
025        nor may "groovy" appear in their names without prior written
026        permission of The Codehaus. "groovy" is a registered
027        trademark of The Codehaus.
028    
029     5. Due credit should be given to The Codehaus -
030        http://groovy.codehaus.org/
031    
032     THIS SOFTWARE IS PROVIDED BY THE CODEHAUS AND CONTRIBUTORS
033     ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
034     NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
035     FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
036     THE CODEHAUS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
037     INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
038     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
039     SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
040     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
041     STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
042     ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
043     OF THE POSSIBILITY OF SUCH DAMAGE.
044    
045     */
046    package groovy.model;
047    
048    import groovy.lang.Closure;
049    
050    import java.util.Collections;
051    import java.util.List;
052    
053    import javax.swing.table.AbstractTableModel;
054    import javax.swing.table.DefaultTableColumnModel;
055    import javax.swing.table.TableColumnModel;
056    
057    import org.codehaus.groovy.runtime.InvokerHelper;
058    
059    /**
060     * A default table model made up of PropertyModels on a Value model.
061     * 
062     * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
063     * @version $Revision: 1.2 $
064     */
065    public class DefaultTableModel extends AbstractTableModel {
066    
067        private ValueModel rowModel;
068        private ValueModel rowsModel;
069        private MyTableColumnModel columnModel = new MyTableColumnModel();
070    
071        public DefaultTableModel(ValueModel rowsModel) {
072            this(rowsModel, new ValueHolder());
073        }
074        
075        public DefaultTableModel(ValueModel rowsModel, ValueModel rowModel) {
076            this.rowModel = rowModel;
077            this.rowsModel = rowsModel;
078        }
079        
080        /**
081         * @return the column definitions.
082         */
083        public List getColumnList() {
084            return columnModel.getColumnList();
085        }
086    
087        public TableColumnModel getColumnModel() {
088            return columnModel;
089        }
090        
091        /**
092         * Adds a property model column to the table
093         */
094        public DefaultTableColumn addPropertyColumn(Object headerValue, String property, Class type) {
095            return addColumn(headerValue, new PropertyModel(rowModel, property, type));
096        }
097        
098        /**
099         * Adds a closure based column to the table
100         */
101        public DefaultTableColumn addClosureColumn(Object headerValue, Closure readClosure, Closure writeClosure, Class type) {
102            return addColumn(headerValue, new ClosureModel(rowModel, readClosure, writeClosure, type));
103        }
104        
105        public DefaultTableColumn addColumn(Object headerValue, ValueModel columnValueModel) {
106            DefaultTableColumn answer = new DefaultTableColumn(headerValue, columnValueModel);
107            addColumn(answer);
108            return answer;
109        }
110        
111        /**
112         * Adds a new column definition to the table
113         */
114        public void addColumn(DefaultTableColumn column) {
115            columnModel.addColumn(column);
116        }
117        
118        /**
119         * Removes a column definition from the table
120         */
121        public void removeColumn(DefaultTableColumn column) {
122            columnModel.removeColumn(column);
123        }
124        
125        public int getRowCount() {
126            return getRows().size();
127        }
128    
129        public int getColumnCount() {
130            return columnModel.getColumnCount();
131        }
132        
133        public String getColumnName(int columnIndex) {
134            String answer = null;
135            if (columnIndex < 0 || columnIndex >= columnModel.getColumnCount()) {
136                return answer;
137            }
138            Object value = columnModel.getColumn(columnIndex).getHeaderValue();
139            if (value != null) {
140                return value.toString();
141            }
142            return answer;
143        }
144    
145        public Class getColumnClass(int columnIndex) {
146            return getColumnModel(columnIndex).getType();
147        }
148    
149        public boolean isCellEditable(int rowIndex, int columnIndex) {
150            return getColumnModel(columnIndex).isEditable();
151        }
152    
153        public Object getValueAt(int rowIndex, int columnIndex) {
154            List rows = getRows();
155            Object answer = null;
156            if (rowIndex < 0 || rowIndex >= rows.size()) {
157                return answer;
158            }
159            if (columnIndex < 0 || columnIndex >= columnModel.getColumnCount()) {
160                return answer;
161            }
162            Object row = getRows().get(rowIndex);
163            rowModel.setValue(row);
164            DefaultTableColumn column = (DefaultTableColumn) columnModel.getColumn(columnIndex);
165            if (row == null || column == null) {
166                return answer;
167            }
168            return column.getValue(row, rowIndex, columnIndex);
169        }
170    
171        public void setValueAt(Object value, int rowIndex, int columnIndex) {
172            List rows = getRows();
173            if (rowIndex < 0 || rowIndex >= rows.size()) {
174                return;
175            }
176            if (columnIndex < 0 || columnIndex >= columnModel.getColumnCount()) {
177                return;
178            }
179            Object row = getRows().get(rowIndex);
180            rowModel.setValue(row);
181            DefaultTableColumn column = (DefaultTableColumn) columnModel.getColumn(columnIndex);
182            if (row == null || column == null) {
183                return;
184            }
185            column.setValue(row, value, rowIndex, columnIndex);
186        }
187    
188        protected ValueModel getColumnModel(int columnIndex) {
189            DefaultTableColumn column = (DefaultTableColumn) columnModel.getColumn(columnIndex);
190            return column.getValueModel();
191        }
192    
193        protected List getRows() {
194            Object value = rowsModel.getValue();
195            if (value == null) {
196                return Collections.EMPTY_LIST;
197            }
198            return InvokerHelper.asList(value);
199        }
200    
201        protected static class MyTableColumnModel extends DefaultTableColumnModel {
202            public List getColumnList() {
203                return tableColumns;
204            }
205        }
206        
207        public ValueModel getRowModel() {
208            return rowModel;
209        }
210    
211        public ValueModel getRowsModel() {
212            return rowsModel;
213        }
214    
215    }