/*******************************************************************************
* Copyright (c) 2010 BestSolution.at and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Tom Schindl<tom.schindl@bestsolution.at> - initial API and implementation
*******************************************************************************/
package org.eclipse.ufacekit.ui.swing.databinding.swing.model;
import java.util.ArrayList;
import java.util.Set;
import javax.swing.table.AbstractTableModel;
import org.eclipse.core.databinding.observable.DisposeEvent;
import org.eclipse.core.databinding.observable.IDisposeListener;
import org.eclipse.core.databinding.observable.list.IListChangeListener;
import org.eclipse.core.databinding.observable.list.IObservableList;
import org.eclipse.core.databinding.observable.list.ListChangeEvent;
import org.eclipse.core.databinding.observable.list.ListDiffVisitor;
import org.eclipse.core.databinding.observable.map.IMapChangeListener;
import org.eclipse.core.databinding.observable.map.IObservableMap;
import org.eclipse.core.databinding.observable.map.MapChangeEvent;
import org.eclipse.core.databinding.observable.set.ListToSetAdapter;
import org.eclipse.core.databinding.property.value.IValueProperty;
/**
* A table model working on top of a {@link IObservableList}
*/
public class ObservableListTableModel extends AbstractTableModel {
/**
*
*/
private static final long serialVersionUID = 1L;
private IMapChangeListener mapChangeListener = new IMapChangeListener() {
public void handleMapChange(MapChangeEvent event) {
Set<?> affectedElements = event.diff.getChangedKeys();
if (!affectedElements.isEmpty()) {
for (Object o : affectedElements) {
int index = list.indexOf(o);
for (int i = 0; i < getColumnCount(); i++) {
fireTableCellUpdated(index, i);
}
}
}
}
};
private IObservableList list;
private IObservableMap[] maps;
private ArrayList<String> columns = new ArrayList<String>();
/**
* Create a new observable model
*
* @param list
* the domain list
* @param properties
* the observed properties
*/
public ObservableListTableModel(IObservableList list, IValueProperty... properties) {
this.list = list;
this.maps = new IObservableMap[properties.length];
final ListToSetAdapter adapter = new ListToSetAdapter(list);
for (int i = 0; i < properties.length; i++) {
IObservableMap p = properties[i].observeDetail(adapter);
p.addMapChangeListener(mapChangeListener);
maps[i] = p;
}
this.list.addListChangeListener(new IListChangeListener() {
public void handleListChange(ListChangeEvent event) {
if( event.diff.getDifferences().length > 1 ) {
//FIXME Not ideal but it looks the problem with the code below is that
// we need to add index counting logic
fireTableDataChanged();
} else {
event.diff.accept(new ListDiffVisitor() {
@Override
public void handleRemove(int index, Object element) {
fireTableRowsDeleted(index, index);
}
@Override
public void handleAdd(int index, Object element) {
fireTableRowsInserted(index, index);
}
});
}
}
});
this.list.addDisposeListener(new IDisposeListener() {
public void handleDispose(DisposeEvent staleEvent) {
for( IObservableMap p : maps ) {
p.dispose();
}
adapter.dispose();
}
});
}
/**
* Adding a column
*
* @param columnName
* the column name
*/
public void addColumn(String columnName) {
columns.add(columnName);
fireTableStructureChanged();
}
@Override
public String getColumnName(int column) {
return columns.get(column);
}
public int getColumnCount() {
return columns.size();
}
public int getRowCount() {
return list.size();
}
public Object getValueAt(int rowIndex, int columnIndex) {
return list.get(rowIndex);
}
/**
* @return the observable maps
*/
IObservableMap[] getMaps() {
return maps;
}
}