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.table;
21  
22  import com.cosylab.util.ObjectList;
23  
24  import java.util.ArrayList;
25  import java.util.Collections;
26  import java.util.Comparator;
27  import java.util.Iterator;
28  
29  
30  /**
31   * <code>TableRowModelSupport</code> support implementation of
32   * <code>TableRowModel</code> based on <code>ArrayList</code>.
33   * 
34   * <p>
35   * <b>Note!</b><br/> This class is not synchronized and is not thread safe.
36   * </p>
37   *
38   * @author <a href="mailto:igor.kriznar@cosylab.com">Igor Kriznar</a>
39   * @version $Id: TableRowModelSupport.java,v 1.14 2008-04-22 12:28:40 jbobnar Exp $
40   *
41   * @since May 4, 2004.
42   */
43  public class TableRowModelSupport implements TableRowModel
44  {
45  	// TODO sync on listeners missing
46  	private ObjectList listeners = new ObjectList(TableRowModelListener.class);
47  	private int columnCount = -1;
48  	private ArrayList<TableRow> rows = new ArrayList<TableRow>();
49  	private String[] columnNames = null;
50  	private Comparator<TableRow> comparator;
51  
52  	/**
53  	 * Creates new instance.
54  	 */
55  	public TableRowModelSupport()
56  	{
57  		super();
58  	}
59  
60  	/* (non-Javadoc)
61  	 * @see com.cosylab.gui.components.table.TableRowModel#getColumnCount()
62  	 */
63  	public int getColumnCount()
64  	{
65  		if (columnCount < 0) {
66  			synchronized (rows) {
67  				if (rows.size() == 0) {
68  					return 0;
69  				}
70  
71  				int c = 0;
72  				Iterator it = rows.iterator();
73  
74  				while (it.hasNext()) {
75  					int i = ((TableRow)it.next()).getValueCount();
76  
77  					if (i > c) {
78  						c = i;
79  					}
80  				}
81  
82  				return c;
83  			}
84  		}
85  
86  		return columnCount;
87  	}
88  
89  	/**
90  	 * Sets the number of columns this model presents.
91  	 *
92  	 * @param count the number of columns
93  	 */
94  	public void setColumnCount(int count)
95  	{
96  		columnCount = count;
97  	}
98  
99  	/* (non-Javadoc)
100 	 * @see com.cosylab.gui.components.table.TableRowModel#getRowCount()
101 	 */
102 	public int getRowCount()
103 	{
104 		return rows.size();
105 	}
106 
107 	/* (non-Javadoc)
108 	 * @see com.cosylab.gui.components.table.TableRowModel#getRowAt(int)
109 	 */
110 	public TableRow getRowAt(int rowIndex)
111 	{
112 		return getRow(rowIndex);
113 	}
114 
115 	/* (non-Javadoc)
116 	 * @see com.cosylab.gui.components.table.TableRowModel#getRowIndex(com.cosylab.gui.components.table.TableRow)
117 	 */
118 	public int getRowIndex(TableRow row)
119 	{
120 		synchronized (rows) {
121 			return rows.indexOf(row);
122 		}
123 	}
124 
125 	/* (non-Javadoc)
126 	 * @see com.cosylab.gui.components.table.TableRowModel#addTableRowModelListener(com.cosylab.gui.components.table.TableRowModelListener)
127 	 */
128 	public void addTableRowModelListener(TableRowModelListener l)
129 	{
130 		listeners.add(l);
131 	}
132 
133 	/* (non-Javadoc)
134 	 * @see com.cosylab.gui.components.table.TableRowModel#removeTableRowModelListener(com.cosylab.gui.components.table.TableRowModelListener)
135 	 */
136 	public void removeTableRowModelListener(TableRowModelListener l)
137 	{
138 		listeners.remove(l);
139 	}
140 
141 	/* (non-Javadoc)
142 	 * @see com.cosylab.gui.components.table.TableRowModel#getColumnName(int)
143 	 */
144 	public String getColumnName(int index)
145 	{
146 		if (columnNames == null) {
147 			return String.valueOf(index);
148 		}
149 
150 		return columnNames[index];
151 	}
152 
153 	/**
154 	 * Sets column names.
155 	 *
156 	 * @param names the column names
157 	 */
158 	public void setColumnNames(String[] names)
159 	{
160 		columnNames = names;
161 	}
162 
163 	/**
164 	 * Adds row to the end of the row list.
165 	 *
166 	 * @param row the row to be added
167 	 */
168 	public void addRow(TableRow row)
169 	{
170 		row.setParentModel(this);
171 
172 		boolean structure = false;
173 
174 		synchronized (rows) {
175 			structure = rows.size() == 0;
176 			rows.add(row);
177 		}
178 
179 		if (structure) {
180 			fireStructureChange(row);
181 		} else {
182 			fireRowAdded(row, rows.size() - 1);
183 		}
184 	}
185 
186 	/**
187 	 * Inserts row at the specified index.
188 	 *
189 	 * @param index the index where to insert
190 	 * @param row the row to be added
191 	 */
192 	public void addRow(int index, TableRow row)
193 	{
194 		row.setParentModel(this);
195 
196 		boolean structure = false;
197 
198 		synchronized (rows) {
199 			structure = rows.size() == 0;
200 			rows.add(index, row);
201 		}
202 
203 		if (structure) {
204 			fireStructureChange(row);
205 		} else {
206 			fireRowAdded(row, index);
207 		}
208 	}
209 
210 	/**
211 	 * Returns row at given index,
212 	 *
213 	 * @param index the index of  the row
214 	 *
215 	 * @return the row at the specified index
216 	 */
217 	public TableRow getRow(int index)
218 	{
219 		synchronized (rows) {
220 			if (index > -1 && index < rows.size()) {
221 				return (TableRow)rows.get(index);
222 			}
223 
224 			return null;
225 		}
226 	}
227 
228 	/**
229 	 * Removes row from this model.
230 	 *
231 	 * @param index rowindex to be roemoved
232 	 *
233 	 * @return the removed row
234 	 */
235 	public TableRow removeRow(int index)
236 	{
237 		TableRow r;
238 
239 		boolean structure = false;
240 
241 		synchronized (rows) {
242 			r = (TableRow)rows.remove(index);
243 			structure = rows.size() == 0;
244 		}
245 
246 		r.setParentModel(null);
247 
248 		if (structure) {
249 			fireStructureChange(r);
250 		} else {
251 			fireRowRemoved(r, index);
252 		}
253 
254 		return r;
255 	}
256 
257 	/**
258 	 * Removes row from this model.
259 	 *
260 	 * @param row the row to be removed
261 	 */
262 	public void removeRow(TableRow row)
263 	{
264 		int i;
265 
266 		boolean structure = false;
267 
268 		synchronized (rows) {
269 			i = rows.indexOf(row);
270 
271 			if (i < 0) {
272 				return;
273 			}
274 
275 			rows.remove(i);
276 			structure = rows.size() == 0;
277 		}
278 
279 		row.setParentModel(null);
280 
281 		if (structure) {
282 			fireStructureChange(row);
283 		} else {
284 			fireRowRemoved(row, i);
285 		}
286 	}
287 
288 	protected void fireChange(TableRowModelEvent event)
289 	{
290 		TableRowModelListener[] l = (TableRowModelListener[])listeners.toArray();
291 
292 		for (int i = 0; i < l.length; i++) {
293 			try {
294 				l[i].tableChanged(event);
295 			} catch (Exception e) {
296 				e.printStackTrace();
297 			}
298 		}
299 	}
300 
301 	protected void fireStructureChange(TableRow r)
302 	{
303 		fireChange(new TableRowModelEvent(r, TableRowModelEvent.HEADER_ROW));
304 	}
305 
306 	protected void fireRowAdded(TableRow row, int index)
307 	{
308 		fireChange(new TableRowModelEvent(row, index,
309 		        TableRowModelEvent.ALL_VALUES, TableRowModelEvent.INSERT));
310 	}
311 
312 	protected void fireRowRemoved(TableRow row, int index)
313 	{
314 		fireChange(new TableRowModelEvent(row, index,
315 		        TableRowModelEvent.ALL_VALUES, TableRowModelEvent.DELETE));
316 	}
317 
318 	/* (non-Javadoc)
319 	 * @see com.cosylab.gui.components.table.TableRowModel#fireRowUpdate(com.cosylab.gui.components.table.TableRow, int)
320 	 */
321 	public void fireRowUpdate(TableRow row, int valueIndex)
322 	{
323 		fireChange(new TableRowModelEvent(row, getRowIndex(row), valueIndex,
324 		        TableRowModelEvent.UPDATE));
325 	}
326 
327 	/**
328 	 * Removes all rows from this model.
329 	 */
330 	public void removeAllRows()
331 	{
332 		if (rows.size() == 0) {
333 			return;
334 		}
335 
336 		TableRow[] r;
337 
338 		synchronized (rows) {
339 			r = new TableRow[rows.size()];
340 			rows.toArray(r);
341 			rows.clear();
342 		}
343 
344 		for (int i = 0; i < r.length; i++) {
345 			r[i].setParentModel(null);
346 		}
347 
348 		fireStructureChange(r[0]);
349 	}
350 
351 	/* (non-Javadoc)
352 	 * @see com.cosylab.gui.components.table.TableRowModel#sortRows(int, boolean)
353 	 */
354 	public void sortRows(int column, boolean descending)
355 	{
356 		if (rows.size() == 0) {
357 			return;
358 		}
359 
360 		synchronized (rows) {
361 			if (comparator == null)
362 				Collections.sort(rows, new DefaultRowComparator(column, descending));
363 			else
364 				if (comparator instanceof RowComparator) {
365 					((RowComparator)comparator).setColumn(column);
366 					((RowComparator)comparator).setDescending(descending);
367 				}
368 				Collections.sort(rows, comparator);
369 		}
370 
371 		fireChange(new TableRowModelEvent(getRow(0), -1));
372 	}
373 
374 	/**
375 	 * @return the comparator
376 	 */
377 	public Comparator getComparator() {
378 		return comparator;
379 	}
380 
381 	/**
382 	 * @param comparator the comparator to set
383 	 */
384 	public void setComparator(Comparator<TableRow> comparator) {
385 		this.comparator = comparator;
386 	}
387 }
388 
389 /* __oOo__ */