View Javadoc

1   /*
2    * Copyright (c) 2003-2008 by Cosylab d. d.
3    *
4    * This file is part of CosyBeans-Common.
5    *
6    * CosyBeans-Common is free software: you can redistribute it and/or modify
7    * it under the terms of the GNU General Public License as published by
8    * the Free Software Foundation, either version 3 of the License, or
9    * (at your option) any later version.
10   *
11   * CosyBeans-Common is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   * GNU General Public License for more details.
15   *
16   * You should have received a copy of the GNU General Public License
17   * along with CosyBeans-Common.  If not, see <http://www.gnu.org/licenses/>.
18   */
19  
20  package com.cosylab.gui.components.introspection;
21  
22  import java.util.HashMap;
23  
24  import com.cosylab.introspection.DataFormatter;
25  
26  import javax.swing.table.AbstractTableModel;
27  
28  
29  /**
30   * A table model, which help edit arbitrary set of properties. Each property
31   * has arbitrary name, value and type. In connection with
32   * <code>PropertiesTable</code> this model is capabel of JavaBeans editing
33   * based on introspection.
34   *
35   * @author <a href="mailto:miha.kadunc@cosylab.com">Miha Kadunc</a>
36   * @version $id$
37   */
38  public class PropertiesTableModel extends AbstractTableModel
39  {
40  	private static final long serialVersionUID = 1L;
41  	private HashMap<String,Integer> namesToIndex;
42  	private String[] names = null;
43  	private Object[] values = null;
44  	private Class[] types = null;
45  	private boolean typeShowing = false;
46  	int valCol = 1;
47  	private int rows = 0;
48  	private boolean editable= true;
49  
50  	/**
51  	 * Constructor for PropertiesTableModel.
52  	 */
53  	public PropertiesTableModel()
54  	{
55  		super();
56  		names = new String[0];
57  		types = new Class[0];
58  		values = new Object[0];
59  		rows = 0;
60  		namesToIndex= new HashMap<String,Integer>(16);
61  	}
62  
63  	/**
64  	 * Creates new model with specified property names, types and values.
65  	 *
66  	 * @param names String[]
67  	 * @param types Class[]
68  	 * @param values Object[]
69  	 */
70  	public PropertiesTableModel(String[] names, Class[] types, Object[] values)
71  	{
72  		this();
73  		setPropertyNames(names);
74  		setPropertyTypes(types);
75  		setPropertyValues(values);
76  	}
77  
78  	/*
79  	 * @see TableModel#getRowCount()
80  	 */
81  	public int getRowCount()
82  	{
83  		return rows;
84  	}
85  
86  	/**
87  	 * Sets the parameter names
88  	 *
89  	 * @param names String[]
90  	 */
91  	public synchronized void setPropertyNames(String[] names)
92  	{
93  		if (names == null) {
94  			this.names = new String[0];
95  		} else {
96  			this.names = names;
97  			namesToIndex.clear();
98  			for (int i = 0; i < names.length; i++) {
99  				namesToIndex.put(names[i],i);
100 			}
101 		}
102 
103 		rows = this.names.length;
104 
105 		if (values.length != rows) {
106 			values = new Object[rows];
107 		}
108 
109 		if (types.length != rows) {
110 			types = new Class[rows];
111 		}
112 	}
113 
114 	/**
115 	 * Sets the parameters
116 	 *
117 	 * @param values Object[]
118 	 */
119 	public synchronized void setPropertyValues(Object[] values)
120 	{
121 		if (values == null || values.length != rows) {
122 			this.values = new Object[rows];
123 		} else {
124 			this.values = values;
125 		}
126 	}
127 
128 	/**
129 	 * Sets the parameter types
130 	 *
131 	 * @param types Class[]
132 	 */
133 	public synchronized void setPropertyTypes(Class[] types)
134 	{
135 		if (types == null || types.length != rows) {
136 			this.types = new Class[rows];
137 		} else {
138 			this.types = types;
139 		}
140 	}
141 
142 	/*
143 	 * @see TableModel#getColumnCount()
144 	 */
145 	public int getColumnCount()
146 	{
147 		return valCol + 1;
148 	}
149 
150 	/*
151 	 * @see TableModel#getValueAt(int, int)
152 	 */
153 	public synchronized Object getValueAt(int rowIndex, int columnIndex)
154 	{
155 		if (rowIndex >= getRowCount() || columnIndex >= getColumnCount()) {
156 			return null;
157 		}
158 
159 		if (columnIndex == 0) {
160 			return names[rowIndex];
161 		} else if (columnIndex == 1 && typeShowing) {
162 			return DataFormatter.toString(types[rowIndex]);
163 		} else if (columnIndex == valCol) {
164 			return values[rowIndex];
165 		} else {
166 			return null;
167 		}
168 	}
169 
170 	/*
171 	 * @see AbstractTableModel#findColumn(String)
172 	 */
173 	public int findColumn(String columnName)
174 	{
175 		if (columnName == "property") {
176 			return 0;
177 		}
178 
179 		if (columnName == "type" && typeShowing) {
180 			return 1;
181 		}
182 
183 		if (columnName == "value") {
184 			return valCol;
185 		} else {
186 			return -1;
187 		}
188 	}
189 
190 	/*
191 	 * @see TableModel#getColumnName(int)
192 	 */
193 	public String getColumnName(int columnIndex)
194 	{
195 		if (columnIndex == 0) {
196 			return "property";
197 		}
198 
199 		if (columnIndex == valCol) {
200 			return "value";
201 		}
202 
203 		if (columnIndex == 1 && typeShowing) {
204 			return "type";
205 		} else {
206 			return super.getColumnName(columnIndex);
207 		}
208 	}
209 
210 	/*
211 	 * @see TableModel#isCellEditable(int, int)
212 	 */
213 	public boolean isCellEditable(int rowIndex, int columnIndex)
214 	{
215 		return (columnIndex == valCol) && isEditable();
216 	}
217 
218 	/*
219 	 * @see TableModel#setValueAt(Object, int, int)
220 	 */
221 	public synchronized void setValueAt(Object aValue, int rowIndex,
222 	    int columnIndex)
223 	{
224 		if (rowIndex >= getRowCount() || columnIndex >= getColumnCount()) {
225 			return;
226 		}
227 
228 		if (columnIndex == 0 && aValue instanceof String) {
229 			names[rowIndex] = (String)aValue;
230 		} else if (columnIndex == valCol) {
231 			if (values[rowIndex] != aValue) {
232 				Object oldValue = values[rowIndex];
233 
234 				try {
235 					values[rowIndex] = EditorsHelper.convert(aValue,
236 						    types[rowIndex]);
237 					fireTableCellUpdated(rowIndex, typeShowing ? 2 : 1);
238 				} catch (Exception e) {
239 					e.printStackTrace();
240 					values[rowIndex] = oldValue;
241 				}
242 			}
243 		} else if (columnIndex == 1 && typeShowing && aValue instanceof Class) {
244 			types[rowIndex] = (Class)aValue;
245 		}
246 
247 		return;
248 	}
249 
250 	synchronized void setValueForProperty(String name, Object value)
251 	{
252 		Integer i = namesToIndex.get(name);
253 
254 		if (i==null) {
255 			return;
256 		}
257 
258 		values[i] = value;
259 
260 		//System.out.println(name+" "+names[i]+" "+i+" "+value);
261 		fireTableCellUpdated(i, valCol);
262 	}
263 
264 	/**
265 	 * Returns array with names of properties.
266 	 *
267 	 * @return String[]
268 	 */
269 	public String[] getPropertyNames()
270 	{
271 		return names;
272 	}
273 
274 	/**
275 	 * Returns array with types of properties.
276 	 *
277 	 * @return Class[]
278 	 */
279 	public Class[] getPropertyTypes()
280 	{
281 		return types;
282 	}
283 
284 	/**
285 	 * Returns array with values of properties.
286 	 *
287 	 * @return Object[]
288 	 */
289 	public Object[] getPropertyValues()
290 	{
291 		return values;
292 	}
293 
294 	/**
295 	 * Returns <code>true</code> if table shows additional column with property
296 	 * types.
297 	 *
298 	 * @return boolean
299 	 */
300 	public boolean isTypeShowing()
301 	{
302 		return typeShowing;
303 	}
304 
305 	/**
306 	 * Enables table to show additional column with property types.
307 	 *
308 	 * @param typeShowing The typeShowing to set
309 	 */
310 	public void setTypeShowing(boolean typeShowing)
311 	{
312 		this.typeShowing = typeShowing;
313 		valCol = typeShowing ? 2 : 1;
314 	}
315 
316 	/**
317 	 * Returns type of property in specified row.
318 	 *
319 	 * @param row
320 	 *
321 	 * @return
322 	 */
323 	public Class getTypeForRow(int row)
324 	{
325 		return types[row];
326 	}
327 	
328 	/**
329 	 * Check if the table contains the given property.
330 	 * 
331 	 * @param name
332 	 * @return
333 	 */
334 	public boolean containsProperty(String name) {
335 		return namesToIndex.containsKey(name);
336 	}
337 	
338 	/**
339 	 * Returns true if editting is allowed.
340 	 * 
341 	 * @return
342 	 */
343 	public boolean isEditable() {
344 		return editable;
345 	}
346 
347 	/**
348 	 * Sets the editable property of this model.
349 	 * 
350 	 * @param editable
351 	 */
352 	public void setEditable(boolean editable) {
353 		this.editable = editable;
354 	}
355 }
356 
357 /* __oOo__ */