/*******************************************************************************
* 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.Set;
import javax.swing.AbstractListModel;
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 list model implementation working with an {@link IObservableList} as the
* data structure
*
* @param <M>
* the element type
*/
public class ObservableListModel<M> extends AbstractListModel {
/**
*
*/
private static final long serialVersionUID = 1L;
private IObservableList list;
private IObservableMap[] maps;
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);
fireContentsChanged(ObservableListModel.this, index, index);
}
}
}
};
/**
* Create a new list model instance
*
* @param list
* the list
* @param properties
* the properties to listen to so that the list is in sync with
* the model
*/
public ObservableListModel(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) {
event.diff.accept(new ListDiffVisitor() {
@Override
public void handleRemove(int index, Object element) {
fireIntervalRemoved(ObservableListModel.this, index, index);
}
@Override
public void handleAdd(int index, Object element) {
fireIntervalAdded(ObservableListModel.this, index, index);
}
});
}
});
this.list.addDisposeListener(new IDisposeListener() {
public void handleDispose(DisposeEvent staleEvent) {
for( IObservableMap p : maps ) {
p.dispose();
}
adapter.dispose();
}
});
}
/**
* @return the observable maps
*/
IObservableMap[] getMaps() {
return maps;
}
public Object getElementAt(int index) {
return list.get(index);
}
public int getSize() {
return list.size();
}
}