KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jface > internal > databinding > internal > viewers > MultiMappingAndListBinding


1 /*******************************************************************************
2  * Copyright (c) 2005, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jface.internal.databinding.internal.viewers;
12
13 import org.eclipse.jface.internal.databinding.provisional.BindSpec;
14 import org.eclipse.jface.internal.databinding.provisional.Binding;
15 import org.eclipse.jface.internal.databinding.provisional.BindingEvent;
16 import org.eclipse.jface.internal.databinding.provisional.DataBindingContext;
17 import org.eclipse.jface.internal.databinding.provisional.observable.IObservable;
18 import org.eclipse.jface.internal.databinding.provisional.observable.list.IListChangeListener;
19 import org.eclipse.jface.internal.databinding.provisional.observable.list.IObservableList;
20 import org.eclipse.jface.internal.databinding.provisional.observable.list.ListDiff;
21 import org.eclipse.jface.internal.databinding.provisional.observable.list.ListDiffEntry;
22 import org.eclipse.jface.internal.databinding.provisional.observable.mapping.IMappingChangeListener;
23 import org.eclipse.jface.internal.databinding.provisional.observable.mapping.IMultiMapping;
24 import org.eclipse.jface.internal.databinding.provisional.observable.mapping.IObservableMultiMappingWithDomain;
25 import org.eclipse.jface.internal.databinding.provisional.observable.mapping.MappingDiff;
26 import org.eclipse.jface.internal.databinding.provisional.observable.value.IObservableValue;
27 import org.eclipse.jface.internal.databinding.provisional.observable.value.WritableValue;
28 import org.eclipse.jface.internal.databinding.provisional.validation.ValidationError;
29 import org.eclipse.jface.internal.databinding.provisional.viewers.IObservableCollectionWithLabels;
30
31 /**
32  *
33  *
34  */

35 public class MultiMappingAndListBinding extends Binding {
36
37     private boolean updating = false;
38
39     private IObservableCollectionWithLabels target;
40
41     private IObservableMultiMappingWithDomain model;
42
43     private IObservableList modelList;
44
45     private final IObservableList targetList;
46
47     /**
48      * @param context
49      * @param targetList
50      * @param target
51      * @param modelList
52      * @param model
53      * @param bindSpec
54      */

55     public MultiMappingAndListBinding(DataBindingContext context,
56             IObservableList targetList, IObservableCollectionWithLabels target,
57             IObservableList modelList, IObservableMultiMappingWithDomain model,
58             BindSpec bindSpec) {
59         super(context);
60         this.targetList = targetList;
61         this.target = target;
62         this.model = model;
63         this.modelList = modelList;
64         // TODO validation/conversion as specified by the bindSpec
65
targetList.addListChangeListener(targetChangeListener);
66         model.addMappingChangeListener(cellsChangeListener);
67         modelList.addListChangeListener(modelChangeListener);
68         updateTargetFromModel();
69     }
70
71     private final IListChangeListener targetChangeListener = new IListChangeListener() {
72         public void handleListChange(IObservableList source, ListDiff diff) {
73         }
74     };
75
76     private IMappingChangeListener cellsChangeListener = new IMappingChangeListener() {
77         public void handleMappingValueChange(IObservable source,
78                 MappingDiff diff) {
79             target.updateElements(diff.getElements().toArray());
80         }
81     };
82
83     private IListChangeListener modelChangeListener = new IListChangeListener() {
84         public void handleListChange(IObservableList source, ListDiff diff) {
85             if (updating) {
86                 return;
87             }
88             // TODO validation
89
BindingEvent e = new BindingEvent(model, targetList, diff,
90                     BindingEvent.EVENT_COPY_TO_TARGET,
91                     BindingEvent.PIPELINE_AFTER_GET);
92             if (failure(errMsg(fireBindingEvent(e)))) {
93                 return;
94             }
95             try {
96                 // get setDiff from event object - might have been modified by a
97
// listener
98
ListDiff setDiff = (ListDiff) e.diff;
99                 ListDiffEntry[] differences = setDiff.getDifferences();
100                 for (int i = 0; i < differences.length; i++) {
101                     ListDiffEntry entry = differences[i];
102                     if (entry.isAddition()) {
103                         targetList.add(entry.getPosition(), entry.getElement());
104                     } else {
105                         targetList.remove(entry.getPosition());
106                     }
107                 }
108                 e.pipelinePosition = BindingEvent.PIPELINE_AFTER_CHANGE;
109                 if (failure(errMsg(fireBindingEvent(e)))) {
110                     return;
111                 }
112             } finally {
113                 updating = false;
114             }
115         }
116     };
117
118     private WritableValue partialValidationErrorObservable = new WritableValue(
119             null);
120
121     private WritableValue validationErrorObservable = new WritableValue(null);
122
123     private ValidationError errMsg(ValidationError validationError) {
124         partialValidationErrorObservable.setValue(null);
125         validationErrorObservable.setValue(validationError);
126         return validationError;
127     }
128
129     private boolean failure(ValidationError errorMessage) {
130         // FIXME: Need to fire a BindingEvent here
131
if (errorMessage != null
132                 && errorMessage.status == ValidationError.ERROR) {
133             return true;
134         }
135         return false;
136     }
137
138     /*
139      * (non-Javadoc)
140      *
141      * @see org.eclipse.jface.internal.databinding.Binding#updateTargetFromModel(org.eclipse.jface.internal.provisional.databinding.ChangeEvent)
142      */

143     public void updateTargetFromModel() {
144         targetList.clear();
145         targetList.addAll(modelList);
146         target.init(new IMultiMapping() {
147             public Object JavaDoc[] getMappingValues(Object JavaDoc element, int[] indices) {
148                 return model.getMappingValues(element, indices);
149             }
150
151             public void setMappingValues(Object JavaDoc element, int[] indices,
152                     Object JavaDoc[] values) {
153                 model.setMappingValues(element, indices, values);
154             }
155         });
156     }
157
158     public IObservableValue getValidationError() {
159         return validationErrorObservable;
160     }
161
162     public IObservableValue getPartialValidationError() {
163         return partialValidationErrorObservable;
164     }
165
166     public void updateModelFromTarget() {
167         // no-op since the target is never out of sync with the model
168
}
169 }
170
Popular Tags