Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
View | Details | Raw Unified | Return to bug 173898 | Differences between
and this patch

Collapse All | Expand All

(-)ui/org/eclipse/debug/internal/ui/viewers/model/ViewerUpdateMonitor.java (-18 / +56 lines)
Lines 16-21 Link Here
16
import org.eclipse.core.runtime.jobs.ISchedulingRule;
16
import org.eclipse.core.runtime.jobs.ISchedulingRule;
17
import org.eclipse.debug.internal.core.commands.Request;
17
import org.eclipse.debug.internal.core.commands.Request;
18
import org.eclipse.debug.internal.ui.viewers.AsynchronousSchedulingRuleFactory;
18
import org.eclipse.debug.internal.ui.viewers.AsynchronousSchedulingRuleFactory;
19
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementContentProvider;
19
import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
20
import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
20
import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate;
21
import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate;
21
import org.eclipse.jface.viewers.TreePath;
22
import org.eclipse.jface.viewers.TreePath;
Lines 37-42 Link Here
37
	 * Element
38
	 * Element
38
	 */
39
	 */
39
	private Object fElement;
40
	private Object fElement;
41
	
42
	/**
43
	 * Element content provider
44
	 */
45
	private IElementContentProvider fElementContentProvider;
40
    
46
    
41
    /**
47
    /**
42
     * Whether this request's 'done' method has been called.
48
     * Whether this request's 'done' method has been called.
Lines 44-52 Link Here
44
    private boolean fDone = false;
50
    private boolean fDone = false;
45
    
51
    
46
    /**
52
    /**
47
     * Associated batch operation, or <code>null</code>
53
     * Whether this request has been started
48
     */
54
     */
49
    private BatchUpdate fBatchUpdate = null;
55
    private boolean fStarted = false;
50
    
56
    
51
    protected WorkbenchJob fViewerUpdateJob = new WorkbenchJob("Asynchronous viewer update") { //$NON-NLS-1$
57
    protected WorkbenchJob fViewerUpdateJob = new WorkbenchJob("Asynchronous viewer update") { //$NON-NLS-1$
52
        public IStatus runInUIThread(IProgressMonitor monitor) {
58
        public IStatus runInUIThread(IProgressMonitor monitor) {
Lines 72-85 Link Here
72
     * @param elementPath path to associated model element - empty for root element
78
     * @param elementPath path to associated model element - empty for root element
73
     * @param element associated model element
79
     * @param element associated model element
74
     */
80
     */
75
    public ViewerUpdateMonitor(ModelContentProvider contentProvider, TreePath elementPath, Object element) {
81
    public ViewerUpdateMonitor(ModelContentProvider contentProvider, TreePath elementPath, Object element, IElementContentProvider elementContentProvider) {
82
    	fElementContentProvider = elementContentProvider;
76
        fContentProvider = contentProvider;
83
        fContentProvider = contentProvider;
77
        fElement = element;
84
        fElement = element;
78
        fElementPath = elementPath;
85
        fElementPath = elementPath;
79
        // serialize updates per viewer
86
        // serialize updates per viewer
80
        fViewerUpdateJob.setRule(getUpdateSchedulingRule());
87
        fViewerUpdateJob.setRule(getUpdateSchedulingRule());
81
        fViewerUpdateJob.setSystem(true);
88
        fViewerUpdateJob.setSystem(true);
82
        contentProvider.updateStarted(this);
83
    }
89
    }
84
    
90
    
85
    /**
91
    /**
Lines 98-104 Link Here
98
     */
104
     */
99
    protected ModelContentProvider getContentProvider() {
105
    protected ModelContentProvider getContentProvider() {
100
        return fContentProvider;
106
        return fContentProvider;
101
    }    
107
    }   
108
    
109
    /**
110
     * Returns the element content provider to use for this request
111
     * 
112
     * @return element content provider
113
     */
114
    protected IElementContentProvider getElementContentProvider() {
115
    	return fElementContentProvider;
116
    }
102
    
117
    
103
    /* (non-Javadoc)
118
    /* (non-Javadoc)
104
     * @see org.eclipse.core.runtime.IProgressMonitor#done()
119
     * @see org.eclipse.core.runtime.IProgressMonitor#done()
Lines 110-120 Link Here
110
    		}
125
    		}
111
    		fDone = true;
126
    		fDone = true;
112
		}
127
		}
113
    	if (fBatchUpdate != null) {
128
    	scheduleViewerUpdate();
114
    		fBatchUpdate.done(this);
115
    	} else {
116
    		scheduleViewerUpdate();
117
    	}
118
	}
129
	}
119
    
130
    
120
    /**
131
    /**
Lines 162-177 Link Here
162
	}
173
	}
163
	
174
	
164
	/**
175
	/**
165
	 * Whether this update is rooted at or below the given path.
176
	 * Returns whether this request can coalesce the given request, and performs the
177
	 * coalesce if it can.
166
	 * 
178
	 * 
167
	 * @param path
179
	 * @param update request to coalesce with this request
168
	 * @return whether this update is rooted at or below the given path
180
	 * @return whether it worked
169
	 */
181
	 */
170
	abstract boolean isContained(TreePath path);
182
	abstract boolean coalesce(ViewerUpdateMonitor update);
171
	
183
	
172
	synchronized void setBatchUpdate(BatchUpdate batchUpdate) {
184
	/**
173
		fBatchUpdate = batchUpdate;
185
	 * Starts this request. Subclasses must override startRequest().
174
		batchUpdate.batch(this);
186
	 */
175
	}
187
	final void start() {
188
		synchronized (this) {
189
			if (fStarted) {
190
				return;
191
			}
192
			fStarted = true;
193
		}
194
		getContentProvider().updateStarted(this);
195
		if (!isCanceled()) {
196
			startRequest();
197
		} else {
198
			done();
199
		}
200
	}	
176
	
201
	
202
	/**
203
	 * Subclasses must override to initiate specific request types.
204
	 */
205
	abstract void startRequest();
206
	
207
	/**
208
	 * Returns the priority of this request. Subclasses must override. The
209
	 * highest priority is 1. Priorities indicate the order that waiting
210
	 * requests should be started in (for example, 'hasChildren' before 'update child count'). 
211
	 * 
212
	 * @return priority
213
	 */
214
	abstract int getPriority();
177
}
215
}
(-)ui/org/eclipse/debug/internal/ui/viewers/model/TreeModelContentProvider.java (-103 / +6 lines)
Lines 10-30 Link Here
10
 *******************************************************************************/
10
 *******************************************************************************/
11
package org.eclipse.debug.internal.ui.viewers.model;
11
package org.eclipse.debug.internal.ui.viewers.model;
12
12
13
import java.util.ArrayList;
14
import java.util.HashMap;
15
import java.util.HashSet;
13
import java.util.HashSet;
16
import java.util.List;
17
import java.util.Map;
18
import java.util.Set;
14
import java.util.Set;
19
import java.util.Timer;
20
import java.util.TimerTask;
21
15
22
import org.eclipse.core.runtime.IProgressMonitor;
16
import org.eclipse.core.runtime.IProgressMonitor;
23
import org.eclipse.core.runtime.IStatus;
17
import org.eclipse.core.runtime.IStatus;
24
import org.eclipse.core.runtime.Status;
18
import org.eclipse.core.runtime.Status;
25
import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate;
26
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementContentProvider;
19
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementContentProvider;
27
import org.eclipse.debug.internal.ui.viewers.model.provisional.IHasChildrenUpdate;
28
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
20
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
29
import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
21
import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
30
import org.eclipse.debug.internal.ui.viewers.model.provisional.ModelDelta;
22
import org.eclipse.debug.internal.ui.viewers.model.provisional.ModelDelta;
Lines 49-71 Link Here
49
	protected static final String[] STATE_PROPERTIES = new String[]{IBasicPropertyConstants.P_TEXT, IBasicPropertyConstants.P_IMAGE};
41
	protected static final String[] STATE_PROPERTIES = new String[]{IBasicPropertyConstants.P_TEXT, IBasicPropertyConstants.P_IMAGE};
50
	
42
	
51
	/**
43
	/**
52
	 * Map of parent paths to requests
53
	 */
54
	private Map fPendingChildRequests = new HashMap();
55
	
56
	/**
57
	 * Map of content adapters to requests
58
	 */
59
	private Map fPendingCountRequests = new HashMap();
60
	
61
	/**
62
	 * Map of content adapters to requests
63
	 */
64
	private Map fPendingHasChildrenRequests = new HashMap();	
65
	
66
	private Timer fTimer = new Timer();
67
	
68
	/**
69
	 * Re-filters any filtered children of the given parent element.
44
	 * Re-filters any filtered children of the given parent element.
70
	 * 
45
	 * 
71
	 * @param path parent element
46
	 * @param path parent element
Lines 85-133 Link Here
85
		Object element = getElement(path);
60
		Object element = getElement(path);
86
		IElementContentProvider contentAdapter = getContentAdapter(element);
61
		IElementContentProvider contentAdapter = getContentAdapter(element);
87
		if (contentAdapter != null) {
62
		if (contentAdapter != null) {
88
			ChildrenCountUpdate request = new ChildrenCountUpdate(this, path, element);
63
			ChildrenCountUpdate request = new ChildrenCountUpdate(this, path, element, contentAdapter);
89
			List requests = (List) fPendingCountRequests.get(contentAdapter);
64
			schedule(request);
90
			if (requests != null) {
91
				requests.add(request);
92
				return;
93
			}
94
			requests = new ArrayList();
95
			requests.add(request);
96
			fPendingCountRequests.put(contentAdapter, requests);
97
			final IElementContentProvider adapter = contentAdapter;
98
			fTimer.schedule(new TimerTask() {
99
				public void run() {
100
					List updates = null;
101
					synchronized (TreeModelContentProvider.this) {
102
						updates = (List) fPendingCountRequests.remove(adapter);
103
					}
104
					ChildrenCountUpdate[] array = (ChildrenCountUpdate[]) updates.toArray(new ChildrenCountUpdate[updates.size()]);
105
					batch(array);
106
					adapter.update(array);
107
				}
108
			}, 10L);
109
		}
65
		}
110
	}	
66
	}	
111
	
67
	
112
	protected synchronized void doUpdateElement(TreePath parentPath, int modelIndex) {
68
	protected synchronized void doUpdateElement(TreePath parentPath, int modelIndex) {
113
		ChildrenUpdate request = (ChildrenUpdate) fPendingChildRequests.get(parentPath);
114
		if (request != null) {
115
			if (request.coalesce(modelIndex)) {
116
				return;
117
			} else {
118
				request.start();
119
			}
120
		} 
121
		Object parent = getElement(parentPath);
69
		Object parent = getElement(parentPath);
122
		IElementContentProvider contentAdapter = getContentAdapter(parent);
70
		IElementContentProvider contentAdapter = getContentAdapter(parent);
123
		if (contentAdapter != null) {
71
		if (contentAdapter != null) {
124
			final ChildrenUpdate newRequest = new ChildrenUpdate(this, parentPath, parent, modelIndex, contentAdapter);
72
			ChildrenUpdate request = new ChildrenUpdate(this, parentPath, parent, modelIndex, contentAdapter);
125
			fPendingChildRequests.put(parentPath, newRequest);
73
			schedule(request);
126
			fTimer.schedule(new TimerTask() {
127
				public void run() {
128
					newRequest.start();
129
				}
130
			}, 10L);
131
		}			
74
		}			
132
	}	
75
	}	
133
	
76
	
Lines 135-178 Link Here
135
		Object element = getElement(path);
78
		Object element = getElement(path);
136
		IElementContentProvider contentAdapter = getContentAdapter(element);
79
		IElementContentProvider contentAdapter = getContentAdapter(element);
137
		if (contentAdapter != null) {
80
		if (contentAdapter != null) {
138
			HasChildrenUpdate request = new HasChildrenUpdate(this, path, element);
81
			HasChildrenUpdate request = new HasChildrenUpdate(this, path, element, contentAdapter);
139
			List requests = (List) fPendingHasChildrenRequests.get(contentAdapter);
82
			schedule(request);
140
			if (requests != null) {
141
				requests.add(request);
142
				return;
143
			}
144
			requests = new ArrayList();
145
			requests.add(request);
146
			fPendingHasChildrenRequests.put(contentAdapter, requests);
147
			final IElementContentProvider adapter = contentAdapter;
148
			fTimer.schedule(new TimerTask() {
149
				public void run() {
150
					List list = null;
151
					synchronized (TreeModelContentProvider.this) {
152
						list = (List) fPendingHasChildrenRequests.remove(adapter);
153
					}
154
					adapter.update((IHasChildrenUpdate[]) list.toArray(new IHasChildrenUpdate[list.size()]));
155
				}
156
			}, 10L);
157
		}
83
		}
158
	}		
84
	}		
159
	
85
	
160
	/**
161
	 * Batches the given update requests into one UI job on completion
162
	 * 
163
	 * @param updates updates to batch
164
	 */
165
	protected void batch(ViewerUpdateMonitor[] updates) {
166
		BatchUpdate batch = new BatchUpdate();
167
		for (int i = 0; i < updates.length; i++) {
168
			updates[i].setBatchUpdate(batch);
169
		}
170
	}
171
	
172
	protected synchronized void childRequestStarted(IChildrenUpdate update) {
173
		fPendingChildRequests.remove(update.getElementPath());
174
	}
175
	
176
	/* (non-Javadoc)
86
	/* (non-Javadoc)
177
	 * @see org.eclipse.debug.internal.ui.viewers.model.provisional.viewers.ModelContentProvider#getPresentationContext()
87
	 * @see org.eclipse.debug.internal.ui.viewers.model.provisional.viewers.ModelContentProvider#getPresentationContext()
178
	 */
88
	 */
Lines 322-334 Link Here
322
		getTreeViewer().update(delta.getElement(), STATE_PROPERTIES);
232
		getTreeViewer().update(delta.getElement(), STATE_PROPERTIES);
323
	}
233
	}
324
234
325
	public synchronized void dispose() {
326
		fTimer.cancel();
327
		fPendingChildRequests.clear();
328
		fPendingCountRequests.clear();
329
		super.dispose();
330
	}
331
332
	/* (non-Javadoc)
235
	/* (non-Javadoc)
333
	 * @see org.eclipse.debug.internal.ui.viewers.model.provisional.viewers.ModelContentProvider#buildViewerState(org.eclipse.debug.internal.ui.viewers.provisional.ModelDelta)
236
	 * @see org.eclipse.debug.internal.ui.viewers.model.provisional.viewers.ModelContentProvider#buildViewerState(org.eclipse.debug.internal.ui.viewers.provisional.ModelDelta)
334
	 */
237
	 */
(-)ui/org/eclipse/debug/internal/ui/viewers/model/ModelContentProvider.java (-16 / +156 lines)
Lines 83-91 Link Here
83
	private ListenerList fUpdateListeners = new ListenerList();
83
	private ListenerList fUpdateListeners = new ListenerList();
84
	
84
	
85
	/**
85
	/**
86
	 * List of updates in progress
86
	 * Map of updates in progress: element path -> list of requests
87
	 */
87
	 */
88
	private List fUpdatesInProgress = new ArrayList(); 
88
	private Map fRequestsInProgress = new HashMap();
89
	
90
	/**
91
	 * Map of dependent requests waiting for parent requests to complete:
92
	 *  element path -> list of requests
93
	 */
94
	private Map fWaitingRequests = new HashMap();
89
	
95
	
90
	/**
96
	/**
91
	 * Map of viewer states keyed by viewer input mementos
97
	 * Map of viewer states keyed by viewer input mementos
Lines 164-173 Link Here
164
	 */
170
	 */
165
	public synchronized void dispose() {
171
	public synchronized void dispose() {
166
		// cancel pending updates
172
		// cancel pending updates
167
		synchronized (fUpdatesInProgress) {
173
		synchronized (fRequestsInProgress) {
168
			Iterator iterator = fUpdatesInProgress.iterator();
174
			Iterator iterator = fRequestsInProgress.values().iterator();
169
			while (iterator.hasNext()) {
175
			while (iterator.hasNext()) {
170
				((IRequest) iterator.next()).cancel();
176
				List requests = (List) iterator.next();
177
				Iterator reqIter = requests.iterator();
178
				while (reqIter.hasNext()) {
179
					((IRequest) reqIter.next()).cancel();
180
				}
171
			}
181
			}
172
		}
182
		}
173
		fModelListeners.clear();
183
		fModelListeners.clear();
Lines 797-802 Link Here
797
	protected void unmapPath(TreePath path) {
807
	protected void unmapPath(TreePath path) {
798
		//System.out.println("Unmap " + path.getLastSegment());
808
		//System.out.println("Unmap " + path.getLastSegment());
799
		fTransform.clear(path);
809
		fTransform.clear(path);
810
		cancelSubtreeUpdates(path);
800
	}
811
	}
801
812
802
	/**
813
	/**
Lines 845-853 Link Here
845
	 */
856
	 */
846
	void updateStarted(IViewerUpdate update) {
857
	void updateStarted(IViewerUpdate update) {
847
		boolean begin = false;
858
		boolean begin = false;
848
		synchronized (fUpdatesInProgress) {
859
		synchronized (fRequestsInProgress) {
849
			begin = fUpdatesInProgress.isEmpty();
860
			begin = fRequestsInProgress.isEmpty();
850
			fUpdatesInProgress.add(update);
861
			List requests = (List) fRequestsInProgress.get(update.getElementPath());
862
			if (requests == null) {
863
				requests = new ArrayList();
864
				fRequestsInProgress.put(update.getElementPath(), requests);
865
			}
866
			requests.add(update);
851
		}
867
		}
852
		if (begin) {
868
		if (begin) {
853
			if (DEBUG_UPDATE_SEQUENCE) {
869
			if (DEBUG_UPDATE_SEQUENCE) {
Lines 868-876 Link Here
868
	 */
884
	 */
869
	void updateComplete(IViewerUpdate update) {
885
	void updateComplete(IViewerUpdate update) {
870
		boolean end = false;
886
		boolean end = false;
871
		synchronized (fUpdatesInProgress) {
887
		synchronized (fRequestsInProgress) {
872
			fUpdatesInProgress.remove(update);
888
			List requests = (List) fRequestsInProgress.get(update.getElementPath());
873
			end = fUpdatesInProgress.isEmpty();
889
			if (requests != null) {
890
				requests.remove(update);
891
				trigger(update);
892
				if (requests.isEmpty()) {
893
					fRequestsInProgress.remove(update.getElementPath());
894
				}
895
			}
896
			end = fRequestsInProgress.isEmpty();
874
		}
897
		}
875
		notifyUpdate(UPDATE_COMPLETE, update);
898
		notifyUpdate(UPDATE_COMPLETE, update);
876
		if (DEBUG_UPDATE_SEQUENCE) {
899
		if (DEBUG_UPDATE_SEQUENCE) {
Lines 915-928 Link Here
915
	}	
938
	}	
916
	
939
	
917
	protected void cancelSubtreeUpdates(TreePath path) {
940
	protected void cancelSubtreeUpdates(TreePath path) {
918
		synchronized (fUpdatesInProgress) {
941
		synchronized (fRequestsInProgress) {
919
			for (int i = 0; i < fUpdatesInProgress.size(); i++) {
942
			Iterator iterator = fRequestsInProgress.entrySet().iterator();
920
				ViewerUpdateMonitor update = (ViewerUpdateMonitor) fUpdatesInProgress.get(i);
943
			while (iterator.hasNext()) {
921
				if (update.isContained(path)) {
944
				Entry entry = (Entry) iterator.next();
922
					update.cancel();
945
				TreePath entryPath = (TreePath) entry.getKey();
946
				if (entryPath.startsWith(path, null)) {
947
					List requests = (List) entry.getValue();
948
					Iterator reqIter = requests.iterator();
949
					while (reqIter.hasNext()) {
950
						((IRequest)reqIter.next()).cancel();
951
					}
952
				}
953
			}
954
			List purge = new ArrayList(); 
955
			iterator = fWaitingRequests.keySet().iterator();
956
			while (iterator.hasNext()) {
957
				TreePath entryPath = (TreePath) iterator.next();
958
				if (entryPath.startsWith(path, null)) {
959
					purge.add(entryPath);
923
				}
960
				}
924
			}
961
			}
962
			iterator = purge.iterator();
963
			while (iterator.hasNext()) {
964
				fWaitingRequests.remove(iterator.next());
965
			}
966
		}
967
	}
968
	
969
	/**
970
	 * Returns whether this given request should be run, or should wait for parent
971
	 * update to complete.
972
	 * 
973
	 * @param update
974
	 * @return whether to start the given request
975
	 */
976
	void schedule(ViewerUpdateMonitor update) {
977
		synchronized (fRequestsInProgress) {
978
			List requests = (List) fWaitingRequests.get(update.getElementPath());
979
			if (requests == null) {
980
				// no waiting requests
981
				TreePath parentPath = update.getElementPath();
982
				while (fRequestsInProgress.get(parentPath) == null) {
983
					parentPath = parentPath.getParentPath();
984
					if (parentPath == null) {
985
						// no running requests: start request
986
						update.start();
987
						return;
988
					}
989
				}
990
				// request running on parent, add to waiting list
991
				requests = new ArrayList();
992
				requests.add(update);
993
				fWaitingRequests.put(update.getElementPath(), requests);
994
			} else {
995
				// there are waiting requests: coalesce with existing request?
996
				Iterator reqIter = requests.iterator();
997
				while (reqIter.hasNext()) {
998
					ViewerUpdateMonitor waiting = (ViewerUpdateMonitor) reqIter.next();
999
					if (waiting.coalesce(update)) {
1000
						// coalesced with existing request, done
1001
						return;
1002
					}
1003
				}
1004
				// add to list of waiting requests
1005
				requests.add(update);
1006
				return;
1007
			}
1008
		}
1009
	}
1010
	
1011
	/**
1012
	 * Triggers waiting requests based on the given request that just completed.
1013
	 * 
1014
	 * TODO: do we cancel updates if the request has been canceled?
1015
	 * 
1016
	 * @param request
1017
	 */
1018
	void trigger(IViewerUpdate request) {
1019
		if (fWaitingRequests.isEmpty()) {
1020
			return;
1021
		}
1022
		TreePath completedPath = request.getElementPath();
1023
		List waiting = (List) fWaitingRequests.get(completedPath);
1024
		if (waiting == null) {
1025
			// no waiting, update the entry with the shortest path
1026
			int length = Integer.MAX_VALUE;
1027
			Iterator entries = fWaitingRequests.entrySet().iterator();
1028
			Entry candidate = null;
1029
			while (entries.hasNext()) {
1030
				Entry entry = (Entry) entries.next();
1031
				TreePath key = (TreePath) entry.getKey();
1032
				if (key.getSegmentCount() < length) {
1033
					candidate = entry;
1034
					length = key.getSegmentCount();
1035
				}
1036
			}
1037
			if (candidate != null) {
1038
				startHighestPriorityRequest((TreePath) candidate.getKey(), (List) candidate.getValue());
1039
			}
1040
		} else {
1041
			// start the highest priority request
1042
			startHighestPriorityRequest(completedPath, waiting);
1043
		}
1044
	}
1045
1046
	/**
1047
	 * @param key
1048
	 * @param waiting
1049
	 */
1050
	private void startHighestPriorityRequest(TreePath key, List waiting) {
1051
		int priority = 4;
1052
		ViewerUpdateMonitor next = null;
1053
		Iterator requests = waiting.iterator();
1054
		while (requests.hasNext()) {
1055
			ViewerUpdateMonitor vu = (ViewerUpdateMonitor) requests.next();
1056
			if (vu.getPriority() < priority) {
1057
				next = vu;
1058
				priority = next.getPriority();
1059
			}
1060
		}
1061
		waiting.remove(next);
1062
		if (waiting.isEmpty()) {
1063
			fWaitingRequests.remove(key);
925
		}
1064
		}
1065
		next.start();
926
	}
1066
	}
927
	
1067
	
928
	/**
1068
	/**
(-)ui/org/eclipse/debug/internal/ui/viewers/model/ChildrenCountUpdate.java (-9 / +26 lines)
Lines 11-16 Link Here
11
package org.eclipse.debug.internal.ui.viewers.model;
11
package org.eclipse.debug.internal.ui.viewers.model;
12
12
13
import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenCountUpdate;
13
import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenCountUpdate;
14
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementContentProvider;
14
import org.eclipse.jface.viewers.TreePath;
15
import org.eclipse.jface.viewers.TreePath;
15
import org.eclipse.jface.viewers.TreeViewer;
16
import org.eclipse.jface.viewers.TreeViewer;
16
17
Lines 24-31 Link Here
24
	/**
25
	/**
25
	 * @param contentProvider
26
	 * @param contentProvider
26
	 */
27
	 */
27
	public ChildrenCountUpdate(ModelContentProvider contentProvider, TreePath elementPath, Object element) {
28
	public ChildrenCountUpdate(ModelContentProvider contentProvider, TreePath elementPath, Object element, IElementContentProvider elementContentProvider) {
28
		super(contentProvider, elementPath, element);
29
		super(contentProvider, elementPath, element, elementContentProvider);
29
	}
30
	}
30
31
31
	/* (non-Javadoc)
32
	/* (non-Javadoc)
Lines 49-61 Link Here
49
	public void setChildCount(int numChildren) {
50
	public void setChildCount(int numChildren) {
50
		fCount = numChildren;
51
		fCount = numChildren;
51
	}
52
	}
52
53
	/* (non-Javadoc)
54
	 * @see org.eclipse.debug.internal.ui.viewers.model.ViewerUpdateMonitor#isContained(org.eclipse.jface.viewers.TreePath)
55
	 */
56
	boolean isContained(TreePath path) {
57
		return getElementPath().startsWith(path, null);
58
	}
59
	
53
	
60
	public String toString() {
54
	public String toString() {
61
		StringBuffer buf = new StringBuffer();
55
		StringBuffer buf = new StringBuffer();
Lines 64-67 Link Here
64
		return buf.toString();
58
		return buf.toString();
65
	}	
59
	}	
66
60
61
	/* (non-Javadoc)
62
	 * @see org.eclipse.debug.internal.ui.viewers.model.ViewerUpdateMonitor#coalesce(org.eclipse.debug.internal.ui.viewers.model.ViewerUpdateMonitor)
63
	 */
64
	boolean coalesce(ViewerUpdateMonitor request) {
65
		if (request instanceof ChildrenCountUpdate) {
66
			return getElementPath().equals(request.getElementPath());
67
		}
68
		return false;
69
	}
70
	
71
	/* (non-Javadoc)
72
	 * @see org.eclipse.debug.internal.ui.viewers.model.ViewerUpdateMonitor#startRequest()
73
	 */
74
	void startRequest() {
75
		getElementContentProvider().update(new IChildrenCountUpdate[]{this});
76
	}
77
78
	/* (non-Javadoc)
79
	 * @see org.eclipse.debug.internal.ui.viewers.model.ViewerUpdateMonitor#getPriority()
80
	 */
81
	int getPriority() {
82
		return 2;
83
	}		
67
}
84
}
(-)ui/org/eclipse/debug/internal/ui/viewers/model/BatchUpdate.java (-105 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2006, 2007 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.debug.internal.ui.viewers.model;
12
13
import java.util.ArrayList;
14
import java.util.HashSet;
15
import java.util.Iterator;
16
import java.util.List;
17
import java.util.Set;
18
19
import org.eclipse.core.runtime.IProgressMonitor;
20
import org.eclipse.core.runtime.IStatus;
21
import org.eclipse.core.runtime.Status;
22
import org.eclipse.ui.progress.WorkbenchJob;
23
24
/**
25
 * A group of viewer updates to batch together into one UI update job.
26
 * 
27
 * @since 3.3
28
 */
29
class BatchUpdate {
30
	
31
	/**
32
	 * Pending batched updates
33
	 */
34
	private Set fPending = new HashSet();
35
	
36
	/**
37
	 * List of updates needing to run a UI job
38
	 */
39
	private List fComplete = null;
40
	
41
    protected WorkbenchJob fViewerUpdateJob = new WorkbenchJob("Asynchronous viewer update") { //$NON-NLS-1$
42
        public IStatus runInUIThread(IProgressMonitor monitor) {
43
            // necessary to check if viewer is disposed
44
        	Iterator updates = fComplete.iterator();
45
    		while (updates.hasNext()) {
46
    			ViewerUpdateMonitor update = (ViewerUpdateMonitor) updates.next();
47
		    	try {
48
		            if (!update.isCanceled() && !update.getContentProvider().isDisposed()) {
49
		            	IStatus status = update.getStatus();
50
		                if (status == null || status.isOK()) {
51
		                	update.performUpdate();
52
		                }
53
		            }
54
		    	} finally {
55
		    		update.getContentProvider().updateComplete(update);
56
		    	}
57
    		}
58
            return Status.OK_STATUS;
59
        }
60
    };	
61
    
62
    /**
63
	 * Creates a new batch update.
64
	 */
65
	BatchUpdate() {
66
		fViewerUpdateJob.setSystem(true);
67
	}
68
	
69
	/**
70
	 * Batch the given update with this group.
71
	 * 
72
	 * @param update update to batch
73
	 */
74
	public synchronized void batch(ViewerUpdateMonitor update) {
75
		fPending.add(update);
76
	}
77
	
78
	/**
79
	 * Notification the given update is done.
80
	 * 
81
	 * @param update update completed
82
	 */
83
	public void done(ViewerUpdateMonitor update) {
84
		boolean allDone = false;
85
		synchronized (this) {
86
			fPending.remove(update);
87
			allDone = fPending.isEmpty();
88
			if (!update.isCanceled()) {
89
				if (fComplete == null) {
90
					fComplete = new ArrayList(fPending.size() + 1);
91
				}
92
				fComplete.add(update);
93
			}
94
		}
95
		if (update.isCanceled()) {
96
			update.getContentProvider().updateComplete(update);
97
		}
98
		synchronized (this) {
99
			if (allDone && fComplete != null) {
100
				fViewerUpdateJob.schedule();
101
			}
102
		}
103
	}
104
105
}
(-)ui/org/eclipse/debug/internal/ui/viewers/model/InternalTreeModelViewer.java (+36 lines)
Lines 1042-1045 Link Here
1042
		((TreeModelLabelProvider)getLabelProvider()).removeLabelUpdateListener(listener);
1042
		((TreeModelLabelProvider)getLabelProvider()).removeLabelUpdateListener(listener);
1043
	}
1043
	}
1044
1044
1045
	/**
1046
	 * Overrides replace to perform a 'clearAll' when an item is replaced. This will
1047
	 * re-ask for children since the parent has changed.
1048
	 */
1049
	public void replace(final Object parentElementOrTreePath, final int index,
1050
			final Object element) {
1051
		preservingSelection(new Runnable() {
1052
			public void run() {
1053
				if (internalIsInputOrEmptyPath(parentElementOrTreePath)) {
1054
					if (index < getTree().getItemCount()) {
1055
						updateItem(getTree().getItem(index), element);
1056
					}
1057
				} else {
1058
					Widget[] parentItems = internalFindItems(parentElementOrTreePath);
1059
					for (int i = 0; i < parentItems.length; i++) {
1060
						TreeItem parentItem = (TreeItem) parentItems[i];
1061
						if (index < parentItem.getItemCount()) {
1062
							TreeItem item = parentItem.getItem(index);
1063
							boolean clear = false;
1064
							if (item.getData() != null) {
1065
								if (!item.getData().equals(element)) {
1066
									clear = true;
1067
								}
1068
							}
1069
							updateItem(item, element);
1070
							if (clear) {
1071
								//System.out.println("CLEAR ALL: " + element);
1072
								item.clearAll(true);
1073
							}
1074
						}
1075
					}
1076
				}
1077
			}
1078
1079
		});
1080
	}
1045
}
1081
}
(-)ui/org/eclipse/debug/internal/ui/viewers/model/HasChildrenUpdate.java (-9 / +47 lines)
Lines 10-15 Link Here
10
 *******************************************************************************/
10
 *******************************************************************************/
11
package org.eclipse.debug.internal.ui.viewers.model;
11
package org.eclipse.debug.internal.ui.viewers.model;
12
12
13
import java.util.ArrayList;
14
import java.util.List;
15
16
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementContentProvider;
13
import org.eclipse.debug.internal.ui.viewers.model.provisional.IHasChildrenUpdate;
17
import org.eclipse.debug.internal.ui.viewers.model.provisional.IHasChildrenUpdate;
14
import org.eclipse.jface.viewers.TreePath;
18
import org.eclipse.jface.viewers.TreePath;
15
import org.eclipse.jface.viewers.TreeViewer;
19
import org.eclipse.jface.viewers.TreeViewer;
Lines 21-31 Link Here
21
25
22
	private boolean fHasChildren = false;
26
	private boolean fHasChildren = false;
23
	
27
	
28
	private List fBatchedRequests = null;
29
	
24
	/**
30
	/**
25
	 * @param contentProvider
31
	 * @param contentProvider
26
	 */
32
	 */
27
	public HasChildrenUpdate(ModelContentProvider contentProvider, TreePath elementPath, Object element) {
33
	public HasChildrenUpdate(ModelContentProvider contentProvider, TreePath elementPath, Object element, IElementContentProvider elementContentProvider) {
28
		super(contentProvider, elementPath, element);
34
		super(contentProvider, elementPath, element, elementContentProvider);
29
	}
35
	}
30
36
31
	/* (non-Javadoc)
37
	/* (non-Javadoc)
Lines 50-66 Link Here
50
		fHasChildren = hasChildren;
56
		fHasChildren = hasChildren;
51
	}
57
	}
52
58
53
	/* (non-Javadoc)
54
	 * @see org.eclipse.debug.internal.ui.viewers.model.ViewerUpdateMonitor#isContained(org.eclipse.jface.viewers.TreePath)
55
	 */
56
	boolean isContained(TreePath path) {
57
		return getElementPath().startsWith(path, null);
58
	}
59
60
	public String toString() {
59
	public String toString() {
61
		StringBuffer buf = new StringBuffer();
60
		StringBuffer buf = new StringBuffer();
62
		buf.append("IHasChildrenUpdate: "); //$NON-NLS-1$
61
		buf.append("IHasChildrenUpdate: "); //$NON-NLS-1$
63
		buf.append(getElement());
62
		buf.append(getElement());
64
		return buf.toString();
63
		return buf.toString();
64
	}
65
	
66
	/* (non-Javadoc)
67
	 * @see org.eclipse.debug.internal.ui.viewers.model.ViewerUpdateMonitor#coalesce(org.eclipse.debug.internal.ui.viewers.model.ViewerUpdateMonitor)
68
	 */
69
	boolean coalesce(ViewerUpdateMonitor request) {
70
		if (request instanceof HasChildrenUpdate) {
71
			if (getElementPath().equals(request.getElementPath())) {
72
				// duplicate request
73
				return true;
74
			} else if (getElementContentProvider().equals(request.getElementContentProvider())) {
75
				if (fBatchedRequests == null) {
76
					fBatchedRequests = new ArrayList();
77
					fBatchedRequests.add(this);
78
				}
79
				fBatchedRequests.add(request);
80
				return true;
81
			}
82
		}
83
		return false;
84
	}
85
86
	/* (non-Javadoc)
87
	 * @see org.eclipse.debug.internal.ui.viewers.model.ViewerUpdateMonitor#startRequest()
88
	 */
89
	void startRequest() {
90
		if (fBatchedRequests == null) {
91
			getElementContentProvider().update(new IHasChildrenUpdate[]{this});
92
		} else {
93
			// TODO: batching does not work since requests are keyed per element
94
			getElementContentProvider().update((IHasChildrenUpdate[]) fBatchedRequests.toArray(new IHasChildrenUpdate[fBatchedRequests.size()]));
95
		}
96
	}
97
98
	/* (non-Javadoc)
99
	 * @see org.eclipse.debug.internal.ui.viewers.model.ViewerUpdateMonitor#getPriority()
100
	 */
101
	int getPriority() {
102
		return 1;
65
	}	
103
	}	
66
}
104
}
(-)ui/org/eclipse/debug/internal/ui/viewers/model/FilterTransform.java (-7 / +1 lines)
Lines 29-40 Link Here
29
 * <p>
29
 * <p>
30
 * This class not intended to be subclassed or instantiated. For internal use only.
30
 * This class not intended to be subclassed or instantiated. For internal use only.
31
 * </p>
31
 * </p>
32
 * <p>
33
 * <strong>EXPERIMENTAL</strong>. This class or interface has been added as
34
 * part of a work in progress. There is no guarantee that this API will
35
 * remain unchanged during the 3.3 release cycle. Please do not use this API
36
 * without consulting with the Platform/Debug team.
37
 * </p>
38
 * @since 3.3
32
 * @since 3.3
39
 */
33
 */
40
class FilterTransform {
34
class FilterTransform {
Lines 101-107 Link Here
101
					children.remove(child);
95
					children.remove(child);
102
				}
96
				}
103
			}
97
			}
104
			return children.isEmpty();
98
			return children.isEmpty() && (filteredChildren == null || filteredChildren.length == 0);
105
		}
99
		}
106
		
100
		
107
		boolean clear(TreePath path, int childIndex, int pathIndex) {
101
		boolean clear(TreePath path, int childIndex, int pathIndex) {
(-)ui/org/eclipse/debug/internal/ui/viewers/model/ChildrenUpdate.java (-38 / +35 lines)
Lines 22-29 Link Here
22
	private Object[] fElements;
22
	private Object[] fElements;
23
	private int fIndex;
23
	private int fIndex;
24
	private int fLength;
24
	private int fLength;
25
	private IElementContentProvider fContentProvider;
26
	private boolean fStarted = false;
27
25
28
	/**
26
	/**
29
	 * Constructs a request to update an element
27
	 * Constructs a request to update an element
Lines 31-41 Link Here
31
	 * @param node node to update
29
	 * @param node node to update
32
	 * @param model model containing the node
30
	 * @param model model containing the node
33
	 */
31
	 */
34
	public ChildrenUpdate(ModelContentProvider provider, TreePath elementPath, Object element, int index, IElementContentProvider presentation) {
32
	public ChildrenUpdate(ModelContentProvider provider, TreePath elementPath, Object element, int index, IElementContentProvider elementContentProvider) {
35
		super(provider, elementPath, element);
33
		super(provider, elementPath, element, elementContentProvider);
36
		fIndex = index;
34
		fIndex = index;
37
		fLength = 1;
35
		fLength = 1;
38
		fContentProvider = presentation;
39
	}
36
	}
40
37
41
	/*
38
	/*
Lines 93-129 Link Here
93
		}
90
		}
94
		fElements[index - fIndex] = child;
91
		fElements[index - fIndex] = child;
95
	}
92
	}
96
	
93
97
	/**
94
	/* (non-Javadoc)
98
	 * Coalesce the request with the given index. Return whether the requests can be 
95
	 * @see org.eclipse.debug.internal.ui.viewers.model.ViewerUpdateMonitor#coalesce(org.eclipse.debug.internal.ui.viewers.model.ViewerUpdateMonitor)
99
	 * coalesced.
100
	 * 
101
	 * @param index
102
	 * @return whether it worked
103
	 */
96
	 */
104
	public boolean coalesce(int index) {
97
	boolean coalesce(ViewerUpdateMonitor request) {
105
		if (index == fIndex + fLength) {
98
		if (request instanceof ChildrenUpdate) {
106
			fLength++;
99
			ChildrenUpdate cu = (ChildrenUpdate) request;
107
			return true;
100
			int end = fIndex + fLength;
108
		}
101
			int otherStart = cu.getOffset();
109
		return false;
102
			if (otherStart == end) {
110
	}
103
				fLength = fLength + cu.getLength();
111
	
104
				return true;
112
	public void start() {
105
			} else if (otherStart == fIndex) {
113
		synchronized (this) {
106
				if (cu.getLength() > getLength()) {
114
			if (fStarted) {
107
					fLength = cu.getLength();
115
				return;
108
				}
109
				return true;
110
			} else if ((otherStart > fIndex) && (otherStart < end)) {
111
				int otherEnd = otherStart + cu.getLength();
112
				fLength = otherEnd - fIndex;
113
				return true;
116
			}
114
			}
117
			fStarted = true;
118
		}
119
		//System.out.println("\tRequest (" + fParent + "): " + fIndex + " length: " + fLength);
120
		TreeModelContentProvider contentProvider = (TreeModelContentProvider)getContentProvider();
121
		contentProvider.childRequestStarted(this);
122
		if (!isCanceled()) {
123
			fContentProvider.update(new IChildrenUpdate[]{this});
124
		} else {
125
			done();
126
		}
115
		}
116
		return false;
127
	}
117
	}
128
118
129
	/* (non-Javadoc)
119
	/* (non-Javadoc)
Lines 139-152 Link Here
139
	public int getOffset() {
129
	public int getOffset() {
140
		return fIndex;
130
		return fIndex;
141
	}
131
	}
142
132
	
143
	/* (non-Javadoc)
133
	/* (non-Javadoc)
144
	 * @see org.eclipse.debug.internal.ui.viewers.model.ViewerUpdateMonitor#isContained(org.eclipse.jface.viewers.TreePath)
134
	 * @see org.eclipse.debug.internal.ui.viewers.model.ViewerUpdateMonitor#startRequest()
145
	 */
135
	 */
146
	boolean isContained(TreePath path) {
136
	void startRequest() {
147
		return getElementPath().startsWith(path, null);
137
		getElementContentProvider().update(new IChildrenUpdate[]{this});
148
	}
138
	}
149
	
139
150
	public String toString() {
140
	public String toString() {
151
		StringBuffer buf = new StringBuffer();
141
		StringBuffer buf = new StringBuffer();
152
		buf.append("IChildrenUpdate: "); //$NON-NLS-1$
142
		buf.append("IChildrenUpdate: "); //$NON-NLS-1$
Lines 157-162 Link Here
157
		buf.append(getLength());
147
		buf.append(getLength());
158
		buf.append("}"); //$NON-NLS-1$
148
		buf.append("}"); //$NON-NLS-1$
159
		return buf.toString();
149
		return buf.toString();
150
	}
151
152
	/* (non-Javadoc)
153
	 * @see org.eclipse.debug.internal.ui.viewers.model.ViewerUpdateMonitor#getPriority()
154
	 */
155
	int getPriority() {
156
		return 3;
160
	}	
157
	}	
161
}
158
}
162
159

Return to bug 173898