1 11 package org.eclipse.jface.internal.databinding.provisional.swt; 12 13 import org.eclipse.core.databinding.observable.ChangeEvent; 14 import org.eclipse.core.databinding.observable.IChangeListener; 15 import org.eclipse.core.databinding.observable.IObservable; 16 import org.eclipse.core.databinding.observable.ObservableTracker; 17 import org.eclipse.core.databinding.observable.list.IListChangeListener; 18 import org.eclipse.core.databinding.observable.list.IObservableList; 19 import org.eclipse.core.databinding.observable.list.ListChangeEvent; 20 import org.eclipse.core.databinding.observable.list.ListDiffEntry; 21 import org.eclipse.swt.events.DisposeEvent; 22 import org.eclipse.swt.events.DisposeListener; 23 import org.eclipse.swt.widgets.Composite; 24 import org.eclipse.swt.widgets.Widget; 25 26 31 public abstract class CompositeUpdater { 32 33 private class UpdateRunnable implements Runnable , IChangeListener { 34 private Widget widget; 35 Object element; 36 37 private boolean dirty = true; 38 39 private IObservable[] dependencies = new IObservable[0]; 40 41 UpdateRunnable(Widget widget, Object element) { 42 this.widget = widget; 43 this.element = element; 44 } 45 46 public void run() { 50 if (theComposite != null && !theComposite.isDisposed() 51 && widget != null && !widget.isDisposed()) { 52 updateIfNecessary(); 53 } 54 } 55 56 private void updateIfNecessary() { 57 if (dirty) { 58 dependencies = ObservableTracker.runAndMonitor(new Runnable () { 59 public void run() { 60 updateWidget(widget, element); 61 } 62 }, this, null); 63 dirty = false; 64 } 65 } 66 67 public void handleChange(ChangeEvent event) { 69 makeDirty(); 71 } 72 73 protected final void makeDirty() { 74 if (!dirty) { 75 dirty = true; 76 stopListening(); 77 if (!theComposite.isDisposed()) { 78 SWTUtil.runOnce(theComposite.getDisplay(), this); 79 } 80 } 81 } 82 83 private void stopListening() { 84 for (int i = 0; i < dependencies.length; i++) { 86 IObservable observable = dependencies[i]; 87 88 observable.removeChangeListener(this); 89 } 90 } 91 } 92 93 private class PrivateInterface implements DisposeListener, 94 IListChangeListener { 95 96 public void widgetDisposed(DisposeEvent e) { 98 CompositeUpdater.this.dispose(); 99 } 100 101 public void handleListChange(ListChangeEvent event) { 102 ListDiffEntry[] diffs = event.diff.getDifferences(); 103 for (int i = 0; i < diffs.length; i++) { 104 ListDiffEntry listDiffEntry = diffs[i]; 105 if (listDiffEntry.isAddition()) { 106 Widget newChild = createWidget(listDiffEntry.getPosition()); 107 final UpdateRunnable updateRunnable = new UpdateRunnable(newChild, listDiffEntry 108 .getElement()); 109 newChild.setData(updateRunnable); 110 updateRunnable.updateIfNecessary(); 111 } else { 112 theComposite.getChildren()[listDiffEntry.getPosition()] 113 .dispose(); 114 } 115 } 116 theComposite.layout(); 117 } 118 119 } 120 121 private PrivateInterface privateInterface = new PrivateInterface(); 122 123 private Composite theComposite; 124 125 private IObservableList model; 126 127 137 public CompositeUpdater(Composite toUpdate, IObservableList model) { 138 this.theComposite = toUpdate; 139 this.model = model; 140 141 model.addListChangeListener(privateInterface); 142 theComposite.addDisposeListener(privateInterface); 143 } 144 145 151 public void dispose() { 152 theComposite.removeDisposeListener(privateInterface); 153 model.removeListChangeListener(privateInterface); 154 } 155 156 171 protected abstract Widget createWidget(int index); 172 173 188 protected abstract void updateWidget(Widget widget, Object element); 189 190 } 191 | Popular Tags |