1 /*
2  * aTunes
3  * Copyright (C) Alex Aranda, Sylvain Gaudard and contributors
4  *
5  * See http://www.atunes.org/wiki/index.php?title=Contributing for information about contributors
6  *
7  * http://www.atunes.org
8  * http://sourceforge.net/projects/atunes
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  */
20 
21 package net.sourceforge.atunes.gui;
22 
23 import javax.swing.ImageIcon;
24 import javax.swing.JTable;
25 import javax.swing.event.TableModelEvent;
26 import javax.swing.table.DefaultTableColumnModel;
27 import javax.swing.table.TableCellEditor;
28 import javax.swing.table.TableCellRenderer;
29 import javax.swing.table.TableColumn;
30 
31 import net.sourceforge.atunes.model.AudioObjectProperty;
32 import net.sourceforge.atunes.model.IBeanFactory;
33 import net.sourceforge.atunes.model.IColorMutableImageIcon;
34 import net.sourceforge.atunes.model.IColumn;
35 import net.sourceforge.atunes.model.IColumnModel;
36 import net.sourceforge.atunes.model.IColumnSet;
37 import net.sourceforge.atunes.model.ILookAndFeel;
38 import net.sourceforge.atunes.model.ILookAndFeelManager;
39 import net.sourceforge.atunes.model.ITableCellRendererCode;
40 import net.sourceforge.atunes.model.PlaybackState;
41 import net.sourceforge.atunes.utils.StringUtils;
42 
43 /**
44  * Common column model for tables
45  *
46  * @author alex
47  *
48  */
49 public abstract class AbstractCommonColumnModel extends DefaultTableColumnModel
50 		implements IColumnModel {
51 
52 	private static final long serialVersionUID = -8202322203076350708L;
53 	/** The table. */
54 	private JTable table;
55 	/** Column set */
56 	private IColumnSet columnSet;
57 	/** The model. */
58 	private AbstractCommonTableModel model;
59 	/** The column being moved. */
60 	private int columnBeingMoved = -1;
61 	/** The column moved to. */
62 	private int columnMovedTo = -1;
63 	private ColumnMoveListener columnMoveListener;
64 	private ColumnModelListener columnModelListener;
65 
66 	private ILookAndFeelManager lookAndFeelManager;
67 
68 	private IBeanFactory beanFactory;
69 
getBeanFactory()70 	protected final IBeanFactory getBeanFactory() {
71 		return this.beanFactory;
72 	}
73 
74 	/**
75 	 * @param beanFactory
76 	 */
setBeanFactory(final IBeanFactory beanFactory)77 	public void setBeanFactory(final IBeanFactory beanFactory) {
78 		this.beanFactory = beanFactory;
79 	}
80 
81 	/**
82 	 * @param lookAndFeelManager
83 	 */
setLookAndFeelManager( final ILookAndFeelManager lookAndFeelManager)84 	public void setLookAndFeelManager(
85 			final ILookAndFeelManager lookAndFeelManager) {
86 		this.lookAndFeelManager = lookAndFeelManager;
87 	}
88 
89 	/**
90 	 * @param table
91 	 */
setTable(final JTable table)92 	public void setTable(final JTable table) {
93 		this.table = table;
94 	}
95 
96 	/**
97 	 * @param model
98 	 */
setModel(final AbstractCommonTableModel model)99 	public void setModel(final AbstractCommonTableModel model) {
100 		this.model = model;
101 	}
102 
getLookAndFeel()103 	protected final ILookAndFeel getLookAndFeel() {
104 		return this.lookAndFeelManager.getCurrentLookAndFeel();
105 	}
106 
107 	/**
108 	 * Return column for x position.
109 	 *
110 	 * @param x
111 	 *            the x
112 	 *
113 	 * @return the column index at position
114 	 */
getColumnIndexAtPosition(final int x)115 	public final int getColumnIndexAtPosition(final int x) {
116 		int computedX = x;
117 		if (computedX < 0) {
118 			return -1;
119 		}
120 
121 		for (int column = 0; column < getColumnCount(); column++) {
122 			computedX = computedX - getColumn(column).getPreferredWidth();
123 			if (computedX < 0) {
124 				return column;
125 			}
126 		}
127 
128 		return -1;
129 	}
130 
131 	/**
132 	 * Updates columns width.
133 	 */
updateColumnWidth()134 	protected final void updateColumnWidth() {
135 		for (int i = 0; i < getColumnCount(); i++) {
136 			Class<? extends IColumn<?>> col = getColumnId(i);
137 			int width = getColumn(i).getPreferredWidth();
138 			setWidthForColumn(col, width);
139 		}
140 	}
141 
142 	/**
143 	 * Sets width for a column.
144 	 *
145 	 * @param c
146 	 *            the c
147 	 * @param width
148 	 *            the width
149 	 */
setWidthForColumn(final Class<? extends IColumn<?>> c, final int width)150 	private final void setWidthForColumn(final Class<? extends IColumn<?>> c,
151 			final int width) {
152 		getColumn(c).setWidth(width);
153 	}
154 
155 	/**
156 	 * Arrange columns.
157 	 *
158 	 * @param reapplyFilter
159 	 *            the reapply filter
160 	 */
161 	@Override
arrangeColumns(final boolean reapplyFilter)162 	public final void arrangeColumns(final boolean reapplyFilter) {
163 		setCurrentColumns();
164 		this.model.refresh(TableModelEvent.UPDATE);
165 		if (reapplyFilter) {
166 			reapplyFilter();
167 		}
168 	}
169 
170 	/**
171 	 * Return Column object for a given column number.
172 	 *
173 	 * @param column
174 	 *            the column
175 	 *
176 	 * @return the column
177 	 */
getColumnObject(final int column)178 	public final IColumn<?> getColumnObject(final int column) {
179 		return getColumn(getColumnId(column));
180 	}
181 
182 	/**
183 	 * Returns class of column given by index
184 	 *
185 	 * @param index
186 	 * @return
187 	 */
getColumnId(final int index)188 	private final Class<? extends IColumn<?>> getColumnId(final int index) {
189 		return this.columnSet.getColumnId(index);
190 	}
191 
192 	/**
193 	 * Returns a column object given its class
194 	 *
195 	 * @param columnClass
196 	 * @return
197 	 */
getColumn( final Class<? extends IColumn<?>> columnClass)198 	private final IColumn<?> getColumn(
199 			final Class<? extends IColumn<?>> columnClass) {
200 		return this.columnSet.getColumn(columnClass);
201 	}
202 
203 	/**
204 	 * Returns alignment of current column
205 	 *
206 	 * @param column
207 	 * @return
208 	 */
getColumnAlignment(final int column)209 	public int getColumnAlignment(final int column) {
210 		return getColumn(getColumnId(column)).getAlignment();
211 	}
212 
213 	/**
214 	 * Initializes columns
215 	 */
setCurrentColumns()216 	private void setCurrentColumns() {
217 		this.columnSet.setCurrentColumns();
218 	}
219 
getColumnMoveListener()220 	private ColumnMoveListener getColumnMoveListener() {
221 		if (this.columnMoveListener == null) {
222 			this.columnMoveListener = new ColumnMoveListener(this);
223 		}
224 		return this.columnMoveListener;
225 	}
226 
getColumnModelListener()227 	private ColumnModelListener getColumnModelListener() {
228 		if (this.columnModelListener == null) {
229 			this.columnModelListener = new ColumnModelListener(this,
230 					this.beanFactory);
231 		}
232 		return this.columnModelListener;
233 	}
234 
235 	/**
236 	 * Allows user to move columns
237 	 *
238 	 * @param enable
239 	 */
enableColumnChange(final boolean enable)240 	public void enableColumnChange(final boolean enable) {
241 		this.table.getTableHeader().setReorderingAllowed(enable);
242 		if (enable) {
243 			// Add listener for column size changes
244 			addColumnModelListener(getColumnModelListener());
245 			this.table.getTableHeader().addMouseListener(
246 					getColumnMoveListener());
247 		} else {
248 			removeColumnModelListener(getColumnModelListener());
249 			this.table.getTableHeader().removeMouseListener(
250 					getColumnMoveListener());
251 		}
252 	}
253 
254 	/**
255 	 * Apply filter
256 	 */
reapplyFilter()257 	protected abstract void reapplyFilter();
258 
259 	/**
260 	 * Updates a column according to settings from column set
261 	 *
262 	 * @param aColumn
263 	 */
updateColumnSettings(final TableColumn aColumn)264 	protected void updateColumnSettings(final TableColumn aColumn) {
265 		// Get column data
266 		IColumn<?> column = getColumnObject(aColumn.getModelIndex());
267 
268 		// Set width
269 		aColumn.setPreferredWidth(column.getWidth());
270 		aColumn.setWidth(column.getWidth());
271 
272 		// Set resizable
273 		aColumn.setResizable(column.isResizable());
274 
275 		// If has cell editor, set cell editor
276 		TableCellEditor cellEditor = column.getCellEditor();
277 		if (cellEditor != null) {
278 			aColumn.setCellEditor(cellEditor);
279 		}
280 
281 		// If has renderer, set cell renderer
282 		TableCellRenderer cellRenderer = column.getCellRenderer();
283 		if (cellRenderer != null) {
284 			aColumn.setCellRenderer(cellRenderer);
285 		}
286 	}
287 
288 	/**
289 	 * @return the columnSet
290 	 */
291 	@Override
getColumnSet()292 	public IColumnSet getColumnSet() {
293 		return this.columnSet;
294 	}
295 
296 	/**
297 	 * @param columnSet
298 	 *            the columnSet to set
299 	 */
setColumnSet(final IColumnSet columnSet)300 	public void setColumnSet(final IColumnSet columnSet) {
301 		this.columnSet = columnSet;
302 	}
303 
304 	/**
305 	 * Returns renderer code for given class
306 	 *
307 	 * @param clazz
308 	 * @return
309 	 */
getRendererCodeFor(final Class<?> clazz)310 	public ITableCellRendererCode<?, ?> getRendererCodeFor(final Class<?> clazz) {
311 		AbstractTableCellRendererCode<?, ?> renderer = null;
312 		if (clazz.equals(PlaybackState.class)) {
313 			renderer = this.beanFactory
314 					.getBean(PlaybackStateTableCellRendererCode.class);
315 		} else if (clazz.equals(Integer.class)) {
316 			renderer = this.beanFactory
317 					.getBean(IntegerTableCellRendererCode.class);
318 		} else if (clazz.equals(ImageIcon.class)) {
319 			renderer = this.beanFactory
320 					.getBean(ImageIconTableCellRendererCode.class);
321 		} else if (clazz.equals(String.class)) {
322 			renderer = this.beanFactory.getBean("stringTableCellRendererCode",
323 					StringTableCellRendererCode.class);
324 		} else if (clazz.equals(TextAndIcon.class)) {
325 			renderer = this.beanFactory
326 					.getBean(TextAndIconTableCellRendererCode.class);
327 		} else if (clazz.equals(AudioObjectProperty.class)) {
328 			renderer = this.beanFactory
329 					.getBean(PropertyTableCellRendererCode.class);
330 		} else if (clazz.equals(IColorMutableImageIcon.class)) {
331 			renderer = this.beanFactory
332 					.getBean(ColorMutableTableCellRendererCode.class);
333 		} else {
334 			throw new IllegalArgumentException(StringUtils.getString(
335 					"No renderer found for class: ", clazz.getName()));
336 		}
337 		return renderer;
338 	}
339 
340 	/**
341 	 * @return the table
342 	 */
getTable()343 	protected JTable getTable() {
344 		return this.table;
345 	}
346 
347 	/**
348 	 * @param columnBeingMoved
349 	 */
setColumnBeingMoved(int columnBeingMoved)350 	protected void setColumnBeingMoved(int columnBeingMoved) {
351 		this.columnBeingMoved = columnBeingMoved;
352 	}
353 
354 	/**
355 	 * @param columnMovedTo
356 	 */
setColumnMovedTo(int columnMovedTo)357 	protected void setColumnMovedTo(int columnMovedTo) {
358 		this.columnMovedTo = columnMovedTo;
359 	}
360 
361 	/**
362 	 * @return
363 	 */
getColumnBeingMoved()364 	protected int getColumnBeingMoved() {
365 		return columnBeingMoved;
366 	}
367 
368 	/**
369 	 * @return
370 	 */
getColumnMovedTo()371 	protected int getColumnMovedTo() {
372 		return columnMovedTo;
373 	}
374 
375 }
376