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 (-7 / +11 lines)
Lines 473-485 Link Here
473
		}
473
		}
474
	}
474
	}
475
475
476
	/* (non-Javadoc)
476
	public void nodeChanged(ModelNode node) {
477
	 * @see org.eclipse.debug.internal.ui.viewers.AsynchronousViewer#clearChildren(org.eclipse.swt.widgets.Widget)
477
		Widget widget = findItem(node);
478
	 */
478
		if (widget != null && !widget.isDisposed()) {
479
	protected void clearChildren(Widget item) {
479
			if (widget instanceof TableItem) {
480
		if (item instanceof Table) {
480
				clear(widget);
481
			fTable.clearAll();
481
				return;
482
		}	
482
			}
483
			widget.setData(node.getElement());
484
			internalRefresh(node);
485
		}
483
	}
486
	}
484
	
487
	
488
	
485
}
489
}
(-)ui/org/eclipse/debug/internal/ui/viewers/AsynchronousTreeViewer.java (-33 / +41 lines)
Lines 747-752 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
    
750
    protected int getItemCount(Widget widget) {
772
    protected int getItemCount(Widget widget) {
751
    	if (widget instanceof TreeItem) {
773
    	if (widget instanceof TreeItem) {
752
			return ((TreeItem) widget).getItemCount();
774
			return ((TreeItem) widget).getItemCount();
Lines 848-865 Link Here
848
    		fTree.clearAll(true);
870
    		fTree.clearAll(true);
849
    	}
871
    	}
850
    }
872
    }
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
    }
863
873
864
    /*
874
    /*
865
     * (non-Javadoc)
875
     * (non-Javadoc)
Lines 1159-1164 Link Here
1159
		return new AsynchronousTreeModel(this);
1169
		return new AsynchronousTreeModel(this);
1160
	}
1170
	}
1161
    
1171
    
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
    
1162
    /**
1190
    /**
1163
	 * Attempt pending udpates. Subclasses may override but should call super.
1191
	 * Attempt pending udpates. Subclasses may override but should call super.
1164
	 */
1192
	 */
Lines 1494-1519 Link Here
1494
		}
1522
		}
1495
		return bool.booleanValue();
1523
		return bool.booleanValue();
1496
	}
1524
	}
1497
	
1525
	 
1498
	/**
1499
	 * Notification the container status of a node has changed/been computed.
1500
	 * 
1501
	 * @param node
1502
	 */
1503
	protected void nodeContainerChanged(ModelNode node) {
1504
		Widget widget = findItem(node);
1505
		if (widget != null && !widget.isDisposed()) {
1506
			if (node.isContainer()) {
1507
				if (widget instanceof TreeItem) {
1508
					if (((TreeItem)widget).getExpanded()) {
1509
						updateChildren(node);
1510
					}
1511
				} else {
1512
					updateChildren(node);
1513
				}
1514
				attemptPendingUpdates();
1515
			}
1516
		}			
1517
	}
1518
	
1526
	
1519
}
1527
}
(-)ui/org/eclipse/debug/internal/ui/viewers/AsynchronousViewer.java (-37 / +104 lines)
Lines 113-118 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();
116
	
126
	
117
	/**
127
	/**
118
	 * Creates a new viewer 
128
	 * Creates a new viewer 
Lines 228-233 Link Here
228
	 * @see org.eclipse.jface.viewers.Viewer#inputChanged(java.lang.Object, java.lang.Object)
238
	 * @see org.eclipse.jface.viewers.Viewer#inputChanged(java.lang.Object, java.lang.Object)
229
	 */
239
	 */
230
	protected synchronized void inputChanged(Object input, Object oldInput) {
240
	protected synchronized void inputChanged(Object input, Object oldInput) {
241
		fParentsPendingChildren.clear();
231
		if (fUpdatePolicy == null) {
242
		if (fUpdatePolicy == null) {
232
			fUpdatePolicy = createUpdatePolicy();
243
			fUpdatePolicy = createUpdatePolicy();
233
            fUpdatePolicy.init(this);
244
            fUpdatePolicy.init(this);
Lines 834-839 Link Here
834
    		widget.dispose();
845
    		widget.dispose();
835
		}
846
		}
836
	}
847
	}
848
    
849
	/**
850
	 * Unmaps the node from its widget and all of its children nodes from
851
	 * their widgets.
852
	 * 
853
	 * @param node
854
	 */
855
	protected void unmapNode(ModelNode node) {
856
		unmapElement(node);
857
		ModelNode[] childrenNodes = node.getChildrenNodes();
858
		if (childrenNodes != null) {
859
			for (int i = 0; i < childrenNodes.length; i++) {
860
				unmapNode(childrenNodes[i]);
861
			}
862
		}
863
	}    
837
864
838
	/**
865
	/**
839
	 * A node in the model has been updated
866
	 * A node in the model has been updated
Lines 843-850 Link Here
843
	protected void nodeChanged(ModelNode node) {
870
	protected void nodeChanged(ModelNode node) {
844
		Widget widget = findItem(node);
871
		Widget widget = findItem(node);
845
		if (widget != null) {
872
		if (widget != null) {
846
			clear(widget);
873
			widget.setData(node.getElement());
847
			attemptPendingUpdates();
874
			internalRefresh(node);
848
		}
875
		}
849
	}
876
	}
850
877
Lines 865-882 Link Here
865
	}
892
	}
866
893
867
	/**
894
	/**
868
	 * Clears the given widget
895
	 * Called when nodes are set in the model. The children may not have been
896
	 * retrieved yet when the tree got the call to "set data".
869
	 * 
897
	 * 
870
	 * @param item
898
	 * @param parent
899
	 * @param children
871
	 */
900
	 */
901
	protected void nodeChildrenSet(ModelNode parent, ModelNode[] children) {
902
		int[] indicies = removePendingChildren(parent);
903
		Widget widget = findItem(parent);
904
		if (widget != null && !widget.isDisposed()) {
905
			if (indicies != null) {
906
				for (int i = 0; i < indicies.length; i++) {
907
					int index = indicies[i];
908
					Widget item = getChildWidget(widget, index);
909
					if (item != null) {
910
						if (index < children.length) {
911
							ModelNode childNode = children[index];
912
							mapElement(childNode, item);
913
							item.setData(childNode.getElement());
914
							internalRefresh(childNode);
915
						}
916
					}
917
				}
918
				setItemCount(widget, children.length);
919
			} else {
920
				setItemCount(widget, children.length);
921
			}
922
		}
923
		attemptPendingUpdates();
924
	}
925
872
    protected abstract void clear(Widget item);
926
    protected abstract void clear(Widget item);
873
    
874
    /**
875
     * Clears the children of the widget.
876
     * 
877
     * @param item
878
     */
879
    protected abstract void clearChildren(Widget item);
880
927
881
	/**
928
	/**
882
	 * Returns the child widet at the given index for the given parent or
929
	 * Returns the child widet at the given index for the given parent or
Lines 902-937 Link Here
902
    protected void attemptPendingUpdates() {
949
    protected void attemptPendingUpdates() {
903
    	attemptSelection(false);
950
    	attemptSelection(false);
904
    }
951
    }
905
	
952
906
	/**
953
	/**
907
	 * Notification a node's children have changed.
954
	 * The children of a node have changed.
908
	 * Updates the child count for the parent's widget
909
	 * and clears children to be updated.
910
	 * 
955
	 * 
911
	 * @param parentNode
956
	 * @param parent
912
	 */
957
	 */
913
	protected void nodeChildrenChanged(ModelNode parentNode) {
958
	protected void nodeChildrenChanged(ModelNode parentNode) {
914
		Widget widget = findItem(parentNode);
959
		ModelNode[] childrenNodes = parentNode.getChildrenNodes();
915
		if (widget != null && !widget.isDisposed()) {
916
			int childCount = parentNode.getChildCount();
917
			clearChildren(widget);
918
			setItemCount(widget, childCount);
919
			attemptPendingUpdates();
920
		}		
921
	}
922
	
923
	/**
924
	 * Unmaps the node from its widget and all of its children nodes from
925
	 * their widgets.
926
	 * 
927
	 * @param node
928
	 */
929
	protected void unmapNode(ModelNode node) {
930
		unmapElement(node);
931
		ModelNode[] childrenNodes = node.getChildrenNodes();
932
		if (childrenNodes != null) {
960
		if (childrenNodes != null) {
933
			for (int i = 0; i < childrenNodes.length; i++) {
961
			nodeChildrenSet(parentNode, childrenNodes);
934
				unmapNode(childrenNodes[i]);
962
		} else {
963
			Widget widget = findItem(parentNode);
964
			if (widget != null && !widget.isDisposed()) {
965
				int childCount = parentNode.getChildCount();
966
				setItemCount(widget, childCount);
967
				attemptPendingUpdates();
935
			}
968
			}
936
		}
969
		}
937
	}
970
	}
Lines 964-969 Link Here
964
    	return findItem((Object)node);
997
    	return findItem((Object)node);
965
    }
998
    }
966
999
1000
    /**
1001
     * Note that the child at the specified index was requested by a widget
1002
     * when revealed but that the data was not in the model yet. When the data
1003
     * becomes available, map it to its widget.
1004
     * 
1005
     * @param parent
1006
     * @param index
1007
     */
1008
	protected synchronized void addPendingChildIndex(ModelNode parent, int index) {
1009
	    int[] indicies = (int[]) fParentsPendingChildren.get(parent);
1010
	    if (indicies == null) {
1011
	        indicies = new int[]{index};
1012
	    } else {
1013
	        int[] next = new int[indicies.length + 1];
1014
	        System.arraycopy(indicies, 0, next, 0, indicies.length);
1015
	        next[indicies.length] = index;
1016
	        indicies = next;
1017
	    }
1018
	    fParentsPendingChildren.put(parent, indicies);    	
1019
	}
1020
	
1021
	/**
1022
	 * Removes and returns and children indicies that were pending for the given
1023
	 * parent node. May return <code>null</code>.
1024
	 * 
1025
	 * @param parent
1026
	 * @return indicies of children that data were requested for or <code>null</code>
1027
	 */
1028
	protected int[] removePendingChildren(ModelNode parent) {
1029
		return (int[]) fParentsPendingChildren.remove(parent);
1030
	}
1031
967
	/*
1032
	/*
968
	 * (non-Javadoc)
1033
	 * (non-Javadoc)
969
	 * 
1034
	 * 
Lines 994-1000 Link Here
994
		        		        internalRefresh(child);
1059
		        		        internalRefresh(child);
995
		        		    }
1060
		        		    }
996
		        		});
1061
		        		});
997
		        	}
1062
		        	} else {
1063
		        		addPendingChildIndex(node, index);
1064
		            }
998
		        	return;
1065
		        	return;
999
				}
1066
				}
1000
			}
1067
			}
(-)ui/org/eclipse/debug/internal/ui/viewers/AsynchronousTreeModel.java (-8 / +17 lines)
Lines 139-144 Link Here
139
        preservingSelection(new Runnable() {
139
        preservingSelection(new Runnable() {
140
			public void run() {
140
			public void run() {
141
		        viewer.nodeDisposed(node);
141
		        viewer.nodeDisposed(node);
142
				viewer.nodeChildrenChanged(parentNode);
142
			}
143
			}
143
		});
144
		});
144
    }
145
    }
Lines 239-245 Link Here
239
     * @param node
240
     * @param node
240
     * @param containsChildren
241
     * @param containsChildren
241
     */
242
     */
242
     void setIsContainer(final ModelNode node, boolean containsChildren) {
243
     void setIsContainer(ModelNode node, boolean containsChildren) {
243
    	ModelNode[] prevChildren = null;
244
    	ModelNode[] prevChildren = null;
244
    	synchronized (this) {
245
    	synchronized (this) {
245
			prevChildren = node.getChildrenNodes();
246
			prevChildren = node.getChildrenNodes();
Lines 254-265 Link Here
254
			}
255
			}
255
		}
256
		}
256
//    	 update tree outside lock
257
//    	 update tree outside lock
257
    	preservingSelection(new Runnable() {
258
        AsynchronousTreeViewer viewer = getTreeViewer();
258
			public void run() {
259
		if (containsChildren) {
259
				getViewer().nodeChildrenChanged(node);
260
            if (prevChildren == null) {
260
		    	getTreeViewer().nodeContainerChanged(node);
261
                viewer.nodeChildrenChanged(node);
261
			}
262
                viewer.nodeContainerChanged(node);
262
		});
263
            } else {
263
    	
264
                viewer.nodeContainerChanged(node);
265
            }
266
        } else if (!containsChildren && prevChildren != null) {            
267
            for (int i = 0; i < prevChildren.length; i++) {
268
                ModelNode child = prevChildren[i];
269
                viewer.nodeDisposed(child);
270
            }            
271
            viewer.nodeChildrenChanged(node);
272
        }
264
    }    
273
    }    
265
}
274
}
(-)ui/org/eclipse/debug/internal/ui/viewers/AsynchronousModel.java (-37 / +42 lines)
Lines 475-481 Link Here
475
        
475
        
476
        ModelNode[] prevKids = null;
476
        ModelNode[] prevKids = null;
477
        ModelNode[] newChildren = null;
477
        ModelNode[] newChildren = null;
478
        ModelNode[] unmap = null; 
479
        
478
        
480
        synchronized (this) {
479
        synchronized (this) {
481
        	if (isDisposed()) {
480
        	if (isDisposed()) {
Lines 491-539 Link Here
491
    			}
490
    			}
492
            	parentNode.setChildren(newChildren);
491
            	parentNode.setChildren(newChildren);
493
            } else {
492
            } else {
494
            	newChildren = new ModelNode[children.length];
493
    	        for (int i = 0; i < prevKids.length; i++) {
495
            	unmap = new ModelNode[prevKids.length];
494
    				ModelNode kid = prevKids[i];
496
            	for (int i = 0; i < prevKids.length; i++) {
495
    				if (i >= children.length) {
497
					unmap[i] = prevKids[i];	
496
    					kid.dispose();
498
				}
497
    					unmapNode(kid);
499
            	for (int i = 0; i < children.length; i++) {
498
    				} else {
500
					Object child = children[i];
499
    					ModelNode prevNode = prevKids[i];
501
					boolean found = false;
500
    					Object nextChild = children[i];
502
					for (int j = 0; j < prevKids.length; j++) {
501
    					if (!prevNode.getElement().equals(nextChild)) {
503
						ModelNode prevKid = prevKids[j];
502
    						unmapNode(prevNode);
504
						if (prevKid != null && child.equals(prevKid.getElement())) {
503
    					}
505
							newChildren[i] = prevKid;
504
    					mapElement(nextChild, prevNode);
506
							prevKids[j] = null;
505
    				}
507
							found = true;
506
    			}
508
							break;
507
    			// create new children
509
						}
508
    	        if (children.length > prevKids.length) {
510
					}
509
    		        newChildren = new ModelNode[children.length];
511
					if (!found) {
510
    		        System.arraycopy(prevKids, 0, newChildren, 0, prevKids.length);
512
						newChildren[i] = new ModelNode(parentNode, child);
511
    		        for (int i = prevKids.length; i < children.length; i ++) {
513
						mapElement(child, newChildren[i]);
512
    		        	Object child = children[i];
514
					}
513
    					ModelNode childNode = new ModelNode(parentNode, child);
515
				}
514
    		        	mapElement(child, childNode);
516
            	for (int i = 0; i < prevKids.length; i++) {
515
    		        	newChildren[i] = childNode;
517
            		ModelNode kid = prevKids[i];
516
    		        }
518
            		if (kid != null) {
517
    		        parentNode.setChildren(newChildren);
519
            			kid.dispose();
518
    	        }
520
            			unmapNode(kid);
519
                if (children.length < prevKids.length) {
521
            		}
520
                	newChildren = new ModelNode[children.length];
522
            	}
521
                    System.arraycopy(prevKids, 0, newChildren, 0, children.length);
523
    	        parentNode.setChildren(newChildren);
522
                    parentNode.setChildren(newChildren);
523
                }
524
            }        	
524
            }        	
525
        }
525
        }
526
        
526
        
527
        //update viewer outside the lock
527
        //update viewer outside the lock
528
    	final ModelNode[] finalUnmap = unmap; 
528
    	final ModelNode[] finalPrevKids = prevKids; 
529
        preservingSelection(new Runnable() {
529
        preservingSelection(new Runnable() {
530
            public void run() {
530
            public void run() {
531
            	if (finalUnmap != null) {
531
            	if (finalPrevKids != null) {
532
	            	for (int i = 0; i < finalUnmap.length; i++) {
532
	                for (int i = 0; i < finalPrevKids.length; i++) {
533
						viewer.unmapNode(finalUnmap[i]);
533
	                    ModelNode kid = finalPrevKids[i];
534
					}
534
	                    if (i >= children.length) {
535
	                        viewer.nodeDisposed(kid);
536
	                    } else {
537
	                        viewer.nodeChanged(kid);
538
	                    }
539
	                }
535
            	}
540
            	}
536
            	viewer.nodeChildrenChanged(parentNode);
541
                viewer.nodeChildrenChanged(parentNode);
537
            }
542
            }
538
        });        	        
543
        });        	        
539
544
(-)ui/org/eclipse/debug/internal/ui/views/memory/renderings/AsyncVirtualContentTableViewer.java (-2 / +5 lines)
Lines 488-495 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
		            }
493
		        	return;
496
		        	return;
494
				}
497
				}
495
			}
498
			}

Return to bug 127025