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 127025 | Differences between
and this patch

Collapse All | Expand All

(-)ui/org/eclipse/debug/internal/ui/viewers/AsynchronousTableViewer.java (-11 / +7 lines)
Lines 473-489 Link Here
473
		}
473
		}
474
	}
474
	}
475
475
476
	public void nodeChanged(ModelNode node) {
476
	/* (non-Javadoc)
477
		Widget widget = findItem(node);
477
	 * @see org.eclipse.debug.internal.ui.viewers.AsynchronousViewer#clearChildren(org.eclipse.swt.widgets.Widget)
478
		if (widget != null && !widget.isDisposed()) {
478
	 */
479
			if (widget instanceof TableItem) {
479
	protected void clearChildren(Widget item) {
480
				clear(widget);
480
		if (item instanceof Table) {
481
				return;
481
			fTable.clearAll();
482
			}
482
		}	
483
			widget.setData(node.getElement());
484
			internalRefresh(node);
485
		}
486
	}
483
	}
487
	
484
	
488
	
489
}
485
}
(-)ui/org/eclipse/debug/internal/ui/viewers/AsynchronousTreeViewer.java (-40 / +27 lines)
Lines 747-774 Link Here
747
        return paths;
747
        return paths;
748
    }
748
    }
749
    
749
    
750
    /**
751
     * Container status of a node changed
752
     * 
753
     * @param node
754
     */
755
    protected void nodeContainerChanged(ModelNode node) {
756
		Widget widget = findItem(node);
757
		if (widget != null && !widget.isDisposed()) {
758
			boolean expanded = true;
759
			if (node.isContainer() && getItemCount(widget) == 0) {
760
				setItemCount(widget, 1);
761
			}
762
			if (widget instanceof TreeItem) {
763
				expanded = ((TreeItem) widget).getExpanded();
764
			}
765
			if (expanded) {
766
				updateChildren(node);
767
			}
768
		}
769
		attemptPendingUpdates();
770
	}
771
    
772
    protected int getItemCount(Widget widget) {
750
    protected int getItemCount(Widget widget) {
773
    	if (widget instanceof TreeItem) {
751
    	if (widget instanceof TreeItem) {
774
			return ((TreeItem) widget).getItemCount();
752
			return ((TreeItem) widget).getItemCount();
Lines 870-875 Link Here
870
    		fTree.clearAll(true);
848
    		fTree.clearAll(true);
871
    	}
849
    	}
872
    }
850
    }
851
    
852
    /* (non-Javadoc)
853
     * @see org.eclipse.debug.internal.ui.viewers.AsynchronousViewer#clearChildren(org.eclipse.swt.widgets.Widget)
854
     */
855
    protected void clearChildren(Widget widget) {
856
    	if (widget instanceof TreeItem && !widget.isDisposed()) {
857
			TreeItem item = (TreeItem) widget;
858
			item.clearAll(true);
859
		} else {
860
			fTree.clearAll(true);
861
		}
862
    }
873
863
874
    /*
864
    /*
875
     * (non-Javadoc)
865
     * (non-Javadoc)
Lines 1169-1192 Link Here
1169
		return new AsynchronousTreeModel(this);
1159
		return new AsynchronousTreeModel(this);
1170
	}
1160
	}
1171
    
1161
    
1172
1173
    /* (non-Javadoc)
1174
     * @see org.eclipse.debug.internal.ui.viewers.AsynchronousModelViewer#nodeChanged(org.eclipse.debug.internal.ui.viewers.ModelNode)
1175
     */
1176
    public void nodeChanged(ModelNode node) {
1177
		Widget widget = findItem(node);
1178
		if (widget != null && !widget.isDisposed()) {
1179
			if (widget instanceof TreeItem) {
1180
				clear(widget);
1181
				return;
1182
			}
1183
			widget.setData(node.getElement());
1184
			mapElement(node, widget);
1185
			internalRefresh(node);
1186
			attemptPendingUpdates();
1187
		}
1188
	}
1189
    
1190
    /**
1162
    /**
1191
	 * Attempt pending udpates. Subclasses may override but should call super.
1163
	 * Attempt pending udpates. Subclasses may override but should call super.
1192
	 */
1164
	 */
Lines 1523-1527 Link Here
1523
		return bool.booleanValue();
1495
		return bool.booleanValue();
1524
	}
1496
	}
1525
	 
1497
	 
1498
	protected void xxxContainerChanged(ModelNode node) {
1499
		Widget widget = findItem(node);
1500
		if (widget != null && !widget.isDisposed()) {
1501
			if (node.isContainer()) {
1502
				if (widget instanceof TreeItem) {
1503
					if (((TreeItem)widget).getExpanded()) {
1504
						updateChildren(node);
1505
					}
1506
				} else {
1507
					updateChildren(node);
1508
				}
1509
				attemptPendingUpdates();
1510
			}
1511
		}			
1512
	}
1526
	
1513
	
1527
}
1514
}
(-)ui/org/eclipse/debug/internal/ui/viewers/AsynchronousViewer.java (-99 / +66 lines)
Lines 113-128 Link Here
113
113
114
	protected static final String OLD_LABEL = "old_label"; //$NON-NLS-1$
114
	protected static final String OLD_LABEL = "old_label"; //$NON-NLS-1$
115
	protected static final String OLD_IMAGE = "old_image"; //$NON-NLS-1$
115
	protected static final String OLD_IMAGE = "old_image"; //$NON-NLS-1$
116
117
    /**
118
     * Map of parent nodes for which children were needed to "set data"
119
     * in the virtual widget. A parent is added to this map when we try go
120
     * get children but they aren't there yet. The children are retrieved
121
     * asynchronously, and later put back into the widgetry.
122
     * The value is an array of ints of the indicies of the children that 
123
     * were requested. 
124
     */	
125
	private Map fParentsPendingChildren = new HashMap();
126
	
116
	
127
	/**
117
	/**
128
	 * Creates a new viewer 
118
	 * Creates a new viewer 
Lines 241-247 Link Here
241
	 * @see org.eclipse.jface.viewers.Viewer#inputChanged(java.lang.Object, java.lang.Object)
231
	 * @see org.eclipse.jface.viewers.Viewer#inputChanged(java.lang.Object, java.lang.Object)
242
	 */
232
	 */
243
	protected synchronized void inputChanged(Object input, Object oldInput) {
233
	protected synchronized void inputChanged(Object input, Object oldInput) {
244
		fParentsPendingChildren.clear();
245
		if (fUpdatePolicy == null) {
234
		if (fUpdatePolicy == null) {
246
			fUpdatePolicy = createUpdatePolicy();
235
			fUpdatePolicy = createUpdatePolicy();
247
            fUpdatePolicy.init(this);
236
            fUpdatePolicy.init(this);
Lines 736-746 Link Here
736
	}
725
	}
737
	
726
	
738
	protected synchronized void restoreSelection(ISelection oldSelection) {
727
	protected synchronized void restoreSelection(ISelection oldSelection) {
739
		doAttemptSelectionToWidget(oldSelection, false);
728
		ISelection remaining = doAttemptSelectionToWidget(oldSelection, false);
740
		// send out notification if old and new differ
729
		// send out notification if old and new differ
741
		fCurrentSelection = newSelectionFromWidget();
730
		fCurrentSelection = newSelectionFromWidget();
742
		if (!fCurrentSelection.equals(oldSelection))
731
		if (!fCurrentSelection.equals(oldSelection)) {
743
			handleInvalidSelection(oldSelection, fCurrentSelection);		
732
			handleInvalidSelection(oldSelection, fCurrentSelection);
733
			// if the remaining selection still exists in the model, make it pending
734
			if (selectionExists(remaining)) {
735
				setSelection(remaining);
736
			}
737
		}
738
	}
739
	
740
	/**
741
	 * Returns whether the selection exists in the model
742
	 */
743
	protected boolean selectionExists(ISelection selection) {
744
		if (selection.isEmpty()) {
745
			return false;
746
		}
747
		if (selection instanceof IStructuredSelection) {
748
			IStructuredSelection ss = (IStructuredSelection) selection;
749
			Iterator iterator = ss.iterator();
750
			while (iterator.hasNext()) {
751
				Object element = iterator.next();
752
				if (getModel().getNodes(element) == null) {
753
					return false;
754
				}
755
			}
756
		}
757
		return true;
744
	}
758
	}
745
    
759
    
746
	/**
760
	/**
Lines 818-831 Link Here
818
    protected void nodeDisposed(ModelNode node) {
832
    protected void nodeDisposed(ModelNode node) {
819
    	Widget widget = findItem(node);
833
    	Widget widget = findItem(node);
820
    	if (widget != null) {
834
    	if (widget != null) {
821
    		unmapElement(node);
835
    		unmapNode(node);
822
    		widget.dispose();
836
    		widget.dispose();
823
    		ModelNode[] childrenNodes = node.getChildrenNodes();
824
    		if (childrenNodes != null) {
825
    			for (int i = 0; i < childrenNodes.length; i++) {
826
					nodeDisposed(childrenNodes[i]);
827
				}
828
			}
829
		}
837
		}
830
	}
838
	}
831
839
Lines 837-844 Link Here
837
	public void nodeChanged(ModelNode node) {
845
	public void nodeChanged(ModelNode node) {
838
		Widget widget = findItem(node);
846
		Widget widget = findItem(node);
839
		if (widget != null) {
847
		if (widget != null) {
840
			widget.setData(node.getElement());
848
			clear(widget);
841
			internalRefresh(node);
849
			attemptPendingUpdates();
842
		}
850
		}
843
	}
851
	}
844
852
Lines 859-896 Link Here
859
	}
867
	}
860
868
861
	/**
869
	/**
862
	 * Called when nodes are set in the model. The children may not have been
870
	 * Clears the given widget
863
	 * retrieved yet when the tree got the call to "set data".
864
	 * 
871
	 * 
865
	 * @param parent
872
	 * @param item
866
	 * @param children
867
	 */
873
	 */
868
	protected void nodeChildrenSet(ModelNode parent, ModelNode[] children) {
869
		int[] indicies = removePendingChildren(parent);
870
		Widget widget = findItem(parent);
871
		if (widget != null && !widget.isDisposed()) {
872
			if (indicies != null) {
873
				for (int i = 0; i < indicies.length; i++) {
874
					int index = indicies[i];
875
					Widget item = getChildWidget(widget, index);
876
					if (item != null) {
877
						if (index < children.length) {
878
							ModelNode childNode = children[index];
879
							mapElement(childNode, item);
880
							item.setData(childNode.getElement());
881
							internalRefresh(childNode);
882
						}
883
					}
884
				}
885
				setItemCount(widget, children.length);
886
			} else {
887
				setItemCount(widget, children.length);
888
			}
889
		}
890
		attemptPendingUpdates();
891
	}
892
893
    protected abstract void clear(Widget item);
874
    protected abstract void clear(Widget item);
875
    
876
    /**
877
     * Clears the children of the widget.
878
     * 
879
     * @param item
880
     */
881
    protected abstract void clearChildren(Widget item);
894
882
895
	/**
883
	/**
896
	 * Returns the child widet at the given index for the given parent or
884
	 * Returns the child widet at the given index for the given parent or
Lines 916-937 Link Here
916
    protected void attemptPendingUpdates() {
904
    protected void attemptPendingUpdates() {
917
    	attemptSelection(false);
905
    	attemptSelection(false);
918
    }
906
    }
919
907
	
920
	/**
908
	/**
921
	 * The children of a node have changed.
909
	 * Updates the child count for the parent's widget
910
	 * and clears children to be updated.
922
	 * 
911
	 * 
923
	 * @param parent
912
	 * @param parentNode
924
	 */
913
	 */
925
	protected void nodeChildrenChanged(ModelNode parentNode) {
914
	protected void xxxChildrenChanged(ModelNode parentNode) {
926
		ModelNode[] childrenNodes = parentNode.getChildrenNodes();
915
		Widget widget = findItem(parentNode);
916
		if (widget != null && !widget.isDisposed()) {
917
			int childCount = parentNode.getChildCount();
918
			clearChildren(widget);
919
			setItemCount(widget, childCount);
920
			attemptPendingUpdates();
921
		}		
922
	}
923
	
924
	/**
925
	 * Unmaps the node from its widget and all of its children nodes from
926
	 * their widgets.
927
	 * 
928
	 * @param node
929
	 */
930
	protected void unmapNode(ModelNode node) {
931
		unmapElement(node);
932
		ModelNode[] childrenNodes = node.getChildrenNodes();
927
		if (childrenNodes != null) {
933
		if (childrenNodes != null) {
928
			nodeChildrenSet(parentNode, childrenNodes);
934
			for (int i = 0; i < childrenNodes.length; i++) {
929
		} else {
935
				unmapNode(childrenNodes[i]);
930
			Widget widget = findItem(parentNode);
931
			if (widget != null && !widget.isDisposed()) {
932
				int childCount = parentNode.getChildCount();
933
				setItemCount(widget, childCount);
934
				attemptPendingUpdates();
935
			}
936
			}
936
		}
937
		}
937
	}
938
	}
Lines 964-1001 Link Here
964
    	return findItem((Object)node);
965
    	return findItem((Object)node);
965
    }
966
    }
966
967
967
    /**
968
     * Note that the child at the specified index was requested by a widget
969
     * when revealed but that the data was not in the model yet. When the data
970
     * becomes available, map it to its widget.
971
     * 
972
     * @param parent
973
     * @param index
974
     */
975
	protected synchronized void addPendingChildIndex(ModelNode parent, int index) {
976
	    int[] indicies = (int[]) fParentsPendingChildren.get(parent);
977
	    if (indicies == null) {
978
	        indicies = new int[]{index};
979
	    } else {
980
	        int[] next = new int[indicies.length + 1];
981
	        System.arraycopy(indicies, 0, next, 0, indicies.length);
982
	        next[indicies.length] = index;
983
	        indicies = next;
984
	    }
985
	    fParentsPendingChildren.put(parent, indicies);    	
986
	}
987
	
988
	/**
989
	 * Removes and returns and children indicies that were pending for the given
990
	 * parent node. May return <code>null</code>.
991
	 * 
992
	 * @param parent
993
	 * @return indicies of children that data were requested for or <code>null</code>
994
	 */
995
	protected int[] removePendingChildren(ModelNode parent) {
996
		return (int[]) fParentsPendingChildren.remove(parent);
997
	}
998
999
	/*
968
	/*
1000
	 * (non-Javadoc)
969
	 * (non-Javadoc)
1001
	 * 
970
	 * 
Lines 1026-1034 Link Here
1026
		        		        internalRefresh(child);
995
		        		        internalRefresh(child);
1027
		        		    }
996
		        		    }
1028
		        		});
997
		        		});
1029
		        	} else {
998
		        	}
1030
		        		addPendingChildIndex(node, index);
1031
		            }
1032
		        	return;
999
		        	return;
1033
				}
1000
				}
1034
			}
1001
			}
(-)ui/org/eclipse/debug/internal/ui/viewers/AsynchronousTreeModel.java (-19 / +15 lines)
Lines 143-149 Link Here
143
        preservingSelection(new Runnable() {
143
        preservingSelection(new Runnable() {
144
			public void run() {
144
			public void run() {
145
		        viewer.nodeDisposed(node);
145
		        viewer.nodeDisposed(node);
146
				viewer.nodeChildrenChanged(parentNode);
147
			}
146
			}
148
		});
147
		});
149
    }
148
    }
Lines 154-160 Link Here
154
     * @param parent
153
     * @param parent
155
     * @param element
154
     * @param element
156
     */
155
     */
157
	protected void add(ModelNode parent, Object element) {
156
	protected void add(final ModelNode parent, Object element) {
158
        Object[] children = filter(parent.getElement(), new Object[] { element });
157
        Object[] children = filter(parent.getElement(), new Object[] { element });
159
        if (children.length == 0) {
158
        if (children.length == 0) {
160
            return; // added element was filtered out.
159
            return; // added element was filtered out.
Lines 173-179 Link Here
173
        }
172
        }
174
        //TODO sort???
173
        //TODO sort???
175
        // notify the viewer to update
174
        // notify the viewer to update
176
        getTreeViewer().nodeChildrenChanged(parent);		
175
        preservingSelection(new Runnable() {
176
			public void run() {
177
				getTreeViewer().xxxChildrenChanged(parent);
178
			}
179
		});
180
        		
177
	}
181
	}
178
	
182
	
179
    /**
183
    /**
Lines 246-252 Link Here
246
     * @param node
250
     * @param node
247
     * @param containsChildren
251
     * @param containsChildren
248
     */
252
     */
249
     void setIsContainer(ModelNode node, boolean containsChildren) {
253
     void setIsContainer(final ModelNode node, boolean containsChildren) {
250
    	ModelNode[] prevChildren = null;
254
    	ModelNode[] prevChildren = null;
251
    	synchronized (this) {
255
    	synchronized (this) {
252
			prevChildren = node.getChildrenNodes();
256
			prevChildren = node.getChildrenNodes();
Lines 261-280 Link Here
261
			}
265
			}
262
		}
266
		}
263
//    	 update tree outside lock
267
//    	 update tree outside lock
264
        AsynchronousTreeViewer viewer = getTreeViewer();
268
    	preservingSelection(new Runnable() {
265
		if (containsChildren) {
269
			public void run() {
266
            if (prevChildren == null) {
270
				getViewer().xxxChildrenChanged(node);
267
                viewer.nodeChildrenChanged(node);
271
		    	getTreeViewer().xxxContainerChanged(node);
268
                viewer.nodeContainerChanged(node);
272
			}
269
            } else {
273
		});
270
                viewer.nodeContainerChanged(node);
274
    	
271
            }
272
        } else if (!containsChildren && prevChildren != null) {            
273
            for (int i = 0; i < prevChildren.length; i++) {
274
                ModelNode child = prevChildren[i];
275
                viewer.nodeDisposed(child);
276
            }            
277
            viewer.nodeChildrenChanged(node);
278
        }
279
    }    
275
    }    
280
}
276
}
(-)ui/org/eclipse/debug/internal/ui/viewers/AsynchronousModel.java (-43 / +38 lines)
Lines 252-258 Link Here
252
	 * @param element model element
252
	 * @param element model element
253
	 * @return associated nodes or <code>null</code>
253
	 * @return associated nodes or <code>null</code>
254
	 */
254
	 */
255
	public ModelNode[] getNodes(Object element) {
255
	public synchronized ModelNode[] getNodes(Object element) {
256
		return (ModelNode[]) fElementToNodes.get(element);
256
		return (ModelNode[]) fElementToNodes.get(element);
257
	}
257
	}
258
	
258
	
Lines 474-479 Link Here
474
        
474
        
475
        ModelNode[] prevKids = null;
475
        ModelNode[] prevKids = null;
476
        ModelNode[] newChildren = null;
476
        ModelNode[] newChildren = null;
477
        ModelNode[] unmap = null; 
477
        
478
        
478
        synchronized (this) {
479
        synchronized (this) {
479
        	if (isDisposed()) {
480
        	if (isDisposed()) {
Lines 489-543 Link Here
489
    			}
490
    			}
490
            	parentNode.setChildren(newChildren);
491
            	parentNode.setChildren(newChildren);
491
            } else {
492
            } else {
492
    	        for (int i = 0; i < prevKids.length; i++) {
493
            	newChildren = new ModelNode[children.length];
493
    				ModelNode kid = prevKids[i];
494
            	unmap = new ModelNode[prevKids.length];
494
    				if (i >= children.length) {
495
            	for (int i = 0; i < prevKids.length; i++) {
495
    					kid.dispose();
496
					unmap[i] = prevKids[i];	
496
    					unmapNode(kid);
497
				}
497
    				} else {
498
            	for (int i = 0; i < children.length; i++) {
498
    					ModelNode prevNode = prevKids[i];
499
					Object child = children[i];
499
    					Object nextChild = children[i];
500
					boolean found = false;
500
    					if (!prevNode.getElement().equals(nextChild)) {
501
					for (int j = 0; j < prevKids.length; j++) {
501
    						unmapNode(prevNode);
502
						ModelNode prevKid = prevKids[j];
502
    					}
503
						if (prevKid != null && child.equals(prevKid.getElement())) {
503
    					mapElement(nextChild, prevNode);
504
							newChildren[i] = prevKid;
504
    				}
505
							prevKids[j] = null;
505
    			}
506
							found = true;
506
    			// create new children
507
							break;
507
    	        if (children.length > prevKids.length) {
508
						}
508
    		        newChildren = new ModelNode[children.length];
509
					}
509
    		        System.arraycopy(prevKids, 0, newChildren, 0, prevKids.length);
510
					if (!found) {
510
    		        for (int i = prevKids.length; i < children.length; i ++) {
511
						newChildren[i] = new ModelNode(parentNode, child);
511
    		        	Object child = children[i];
512
						mapElement(child, newChildren[i]);
512
    					ModelNode childNode = new ModelNode(parentNode, child);
513
					}
513
    		        	mapElement(child, childNode);
514
				}
514
    		        	newChildren[i] = childNode;
515
            	for (int i = 0; i < prevKids.length; i++) {
515
    		        }
516
            		ModelNode kid = prevKids[i];
516
    		        parentNode.setChildren(newChildren);
517
            		if (kid != null) {
517
    	        }
518
            			kid.dispose();
518
                if (children.length < prevKids.length) {
519
            			unmapNode(kid);
519
                	newChildren = new ModelNode[children.length];
520
            		}
520
                    System.arraycopy(prevKids, 0, newChildren, 0, children.length);
521
            	}
521
                    parentNode.setChildren(newChildren);
522
    	        parentNode.setChildren(newChildren);
522
                }
523
            }        	
523
            }        	
524
        }
524
        }
525
        
525
        
526
        //update viewer outside the lock
526
        //update viewer outside the lock
527
    	final ModelNode[] finalPrevKids = prevKids; 
527
    	final ModelNode[] finalUnmap = unmap; 
528
        preservingSelection(new Runnable() {
528
        preservingSelection(new Runnable() {
529
            public void run() {
529
            public void run() {
530
            	if (finalPrevKids != null) {
530
            	if (finalUnmap != null) {
531
	                for (int i = 0; i < finalPrevKids.length; i++) {
531
	            	for (int i = 0; i < finalUnmap.length; i++) {
532
	                    ModelNode kid = finalPrevKids[i];
532
						viewer.unmapNode(finalUnmap[i]);
533
	                    if (i >= children.length) {
533
					}
534
	                        viewer.nodeDisposed(kid);
535
	                    } else {
536
	                        viewer.nodeChanged(kid);
537
	                    }
538
	                }
539
            	}
534
            	}
540
                viewer.nodeChildrenChanged(parentNode);
535
            	viewer.xxxChildrenChanged(parentNode);
541
            }
536
            }
542
        });        	        
537
        });        	        
543
538
(-)ui/org/eclipse/debug/internal/ui/views/memory/renderings/AsyncVirtualContentTableViewer.java (-5 / +2 lines)
Lines 488-498 Link Here
488
		        		// is causing the table viewer to not scroll or move cursor properly.
488
		        		// is causing the table viewer to not scroll or move cursor properly.
489
		        		// #interalRefresh on a child will never cause a structural
489
		        		// #interalRefresh on a child will never cause a structural
490
		        		// change in a table viewer.  As a result, there is no need to preserve selection
490
		        		// change in a table viewer.  As a result, there is no need to preserve selection
491
		        		internalRefresh(child);
491
		        		internalRefresh(child);	
492
		        		
492
		        	}
493
		        	} else {
494
		        		addPendingChildIndex(node, index);
495
		            }
496
		        	return;
493
		        	return;
497
				}
494
				}
498
			}
495
			}

Return to bug 127025