/*******************************************************************************
* Copyright (c) 2008 Ralf Ebert
* 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:
* Ralf Ebert - initial API and implementation
*******************************************************************************/
package de.ralfebert.rcputils.databinding;
import java.util.Iterator;
import java.util.LinkedHashSet;
import org.eclipse.core.databinding.Binding;
import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.observable.ChangeEvent;
import org.eclipse.core.databinding.observable.IChangeListener;
import org.eclipse.core.databinding.observable.IObservable;
import org.eclipse.core.databinding.observable.list.IListChangeListener;
import org.eclipse.core.databinding.observable.list.ListChangeEvent;
import org.eclipse.core.databinding.observable.list.ListDiffVisitor;
import org.eclipse.core.runtime.Assert;
/**
* ChangeTracker allows to observe all model or target observables in a
* DataBindingContext. Can be used to set the dirty flag of an editor when
* something changes.
*
* @author Ralf Ebert <info@ralfebert.de>
*/
public class ChangeTracker {
private final LinkedHashSet<IChangeListener> changeListeners = new LinkedHashSet<IChangeListener>();
private final IChangeListener CHANGE_LISTENER = new IChangeListener() {
public void handleChange(ChangeEvent event) {
for (IChangeListener changeListener : changeListeners) {
changeListener.handleChange(event);
}
}
};
private final ListDiffVisitor BINDINGS_MODEL_DIFF_VISITOR = new ListDiffVisitor() {
@Override
public void handleRemove(int index, Object element) {
Assert.isTrue(element instanceof Binding, element + " is not a Binding");
removeObservable(((Binding) element).getModel());
}
@Override
public void handleAdd(int index, Object element) {
Assert.isTrue(element instanceof Binding, element + " is not a Binding");
addObservable(((Binding) element).getModel());
}
};
private final IListChangeListener BINDINGS_MODEL_CHANGE_LISTENER = new IListChangeListener() {
public void handleListChange(ListChangeEvent event) {
event.diff.accept(BINDINGS_MODEL_DIFF_VISITOR);
}
};
private final ListDiffVisitor BINDINGS_TARGET_DIFF_VISITOR = new ListDiffVisitor() {
@Override
public void handleRemove(int index, Object element) {
Assert.isTrue(element instanceof Binding, element + " is not a Binding");
removeObservable(((Binding) element).getTarget());
}
@Override
public void handleAdd(int index, Object element) {
Assert.isTrue(element instanceof Binding, element + " is not a Binding");
addObservable(((Binding) element).getTarget());
}
};
private final IListChangeListener BINDINGS_TARGET_CHANGE_LISTENER = new IListChangeListener() {
public void handleListChange(ListChangeEvent event) {
event.diff.accept(BINDINGS_TARGET_DIFF_VISITOR);
}
};
public void addObservable(IObservable observable) {
observable.addChangeListener(CHANGE_LISTENER);
}
public void removeObservable(IObservable observable) {
observable.removeChangeListener(CHANGE_LISTENER);
}
@SuppressWarnings("unchecked")
public void trackModelObservables(DataBindingContext bindings) {
for (Iterator<Binding> iterator = bindings.getBindings().iterator(); iterator.hasNext();) {
Binding binding = iterator.next();
addObservable(binding.getModel());
}
bindings.getBindings().addListChangeListener(BINDINGS_MODEL_CHANGE_LISTENER);
}
@SuppressWarnings("unchecked")
public void trackTargetObservables(DataBindingContext bindings) {
for (Iterator<Binding> iterator = bindings.getBindings().iterator(); iterator.hasNext();) {
Binding binding = iterator.next();
addObservable(binding.getTarget());
}
bindings.getBindings().addListChangeListener(BINDINGS_TARGET_CHANGE_LISTENER);
}
public void addChangeListener(IChangeListener changeListener) {
changeListeners.add(changeListener);
}
public void removeChangeListener(IChangeListener changeListener) {
changeListeners.remove(changeListener);
}
}