blob: 95b8b7586ee6b005b094315cdca22ab44992a533 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005, 2006 IBM Corporation 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:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jface.internal.databinding.internal;
import org.eclipse.jface.databinding.BindSpec;
import org.eclipse.jface.databinding.BindingEvent;
import org.eclipse.jface.databinding.DataBindingContext;
import org.eclipse.jface.databinding.observable.list.IListChangeListener;
import org.eclipse.jface.databinding.observable.list.IObservableList;
import org.eclipse.jface.databinding.observable.list.ListDiff;
import org.eclipse.jface.databinding.observable.list.ListDiffEntry;
import org.eclipse.jface.databinding.observable.value.IObservableValue;
import org.eclipse.jface.databinding.observable.value.WritableValue;
import org.eclipse.jface.internal.databinding.provisional.validation.ValidationError;
/**
*
* implementation note: this class extends a deprecated class for backwards compatibility.
*/
public class ListBinding extends org.eclipse.jface.internal.databinding.provisional.Binding {
private boolean updating = false;
private IObservableList modelList;
private final IObservableList targetList;
/**
* @param context
* @param targetList
* @param target
* @param modelList
* @param model
* @param bindSpec
*/
public ListBinding(DataBindingContext context, IObservableList targetList,
IObservableList modelList, BindSpec bindSpec) {
super(context);
this.targetList = targetList;
this.modelList = modelList;
// TODO validation/conversion as specified by the bindSpec
targetList.addListChangeListener(targetChangeListener);
modelList.addListChangeListener(modelChangeListener);
updateTargetFromModel();
}
/* (non-Javadoc)
* @see org.eclipse.jface.internal.databinding.provisional.Binding#dispose()
*/
public void dispose() {
targetList.removeListChangeListener(targetChangeListener);
modelList.removeListChangeListener(modelChangeListener);
super.dispose();
}
private final IListChangeListener targetChangeListener = new IListChangeListener() {
public void handleListChange(IObservableList source, ListDiff diff) {
if (updating) {
return;
}
// TODO validation
BindingEvent e = new BindingEvent(modelList, targetList, diff,
BindingEvent.EVENT_COPY_TO_MODEL,
BindingEvent.PIPELINE_AFTER_GET);
if (failure(errMsg(fireBindingEvent(e)))) {
return;
}
updating = true;
try {
// get setDiff from event object - might have been modified by a
// listener
ListDiff setDiff = (ListDiff) e.diff;
ListDiffEntry[] differences = setDiff.getDifferences();
for (int i = 0; i < differences.length; i++) {
ListDiffEntry entry = differences[i];
if (entry.isAddition()) {
modelList.add(entry.getPosition(), entry.getElement());
} else {
modelList.remove(entry.getPosition());
}
}
e.pipelinePosition = BindingEvent.PIPELINE_AFTER_CHANGE;
if (failure(errMsg(fireBindingEvent(e)))) {
return;
}
} finally {
updating = false;
}
}
};
private IListChangeListener modelChangeListener = new IListChangeListener() {
public void handleListChange(IObservableList source, ListDiff diff) {
if (updating) {
return;
}
// TODO validation
BindingEvent e = new BindingEvent(modelList, targetList, diff,
BindingEvent.EVENT_COPY_TO_TARGET,
BindingEvent.PIPELINE_AFTER_GET);
if (failure(errMsg(fireBindingEvent(e)))) {
return;
}
updating = true;
try {
// get setDiff from event object - might have been modified by a
// listener
ListDiff setDiff = (ListDiff) e.diff;
ListDiffEntry[] differences = setDiff.getDifferences();
for (int i = 0; i < differences.length; i++) {
ListDiffEntry entry = differences[i];
if (entry.isAddition()) {
targetList.add(entry.getPosition(), entry.getElement());
} else {
targetList.remove(entry.getPosition());
}
}
e.pipelinePosition = BindingEvent.PIPELINE_AFTER_CHANGE;
if (failure(errMsg(fireBindingEvent(e)))) {
return;
}
} finally {
updating = false;
}
}
};
private WritableValue partialValidationErrorObservable = new WritableValue(
null);
private WritableValue validationErrorObservable = new WritableValue(null);
private ValidationError errMsg(ValidationError validationError) {
partialValidationErrorObservable.setValue(null);
validationErrorObservable.setValue(validationError);
return validationError;
}
private boolean failure(ValidationError errorMessage) {
// FIXME: Need to fire a BindingEvent here
if (errorMessage != null
&& errorMessage.status == ValidationError.ERROR) {
return true;
}
return false;
}
public void updateTargetFromModel() {
updating = true;
try {
targetList.clear();
targetList.addAll(modelList);
} finally {
updating = false;
}
}
public IObservableValue getValidationError() {
return validationErrorObservable;
}
public IObservableValue getPartialValidationError() {
return partialValidationErrorObservable;
}
public void updateModelFromTarget() {
updating = true;
try {
modelList.clear();
modelList.addAll(targetList);
} finally {
updating = false;
}
}
}