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 (-41 / +33 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 1522-1527 Link Here
1522
		}
1494
		}
1523
		return bool.booleanValue();
1495
		return bool.booleanValue();
1524
	}
1496
	}
1525
	 
1497
	
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
	}
1526
	
1518
	
1527
}
1519
}
(-)ui/org/eclipse/debug/internal/ui/viewers/AsynchronousViewer.java (-104 / +37 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 238-244 Link Here
238
	 * @see org.eclipse.jface.viewers.Viewer#inputChanged(java.lang.Object, java.lang.Object)
228
	 * @see org.eclipse.jface.viewers.Viewer#inputChanged(java.lang.Object, java.lang.Object)
239
	 */
229
	 */
240
	protected synchronized void inputChanged(Object input, Object oldInput) {
230
	protected synchronized void inputChanged(Object input, Object oldInput) {
241
		fParentsPendingChildren.clear();
242
		if (fUpdatePolicy == null) {
231
		if (fUpdatePolicy == null) {
243
			fUpdatePolicy = createUpdatePolicy();
232
			fUpdatePolicy = createUpdatePolicy();
244
            fUpdatePolicy.init(this);
233
            fUpdatePolicy.init(this);
Lines 845-866 Link Here
845
    		widget.dispose();
834
    		widget.dispose();
846
		}
835
		}
847
	}
836
	}
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
	}    
864
837
865
	/**
838
	/**
866
	 * A node in the model has been updated
839
	 * A node in the model has been updated
Lines 870-877 Link Here
870
	protected void nodeChanged(ModelNode node) {
843
	protected void nodeChanged(ModelNode node) {
871
		Widget widget = findItem(node);
844
		Widget widget = findItem(node);
872
		if (widget != null) {
845
		if (widget != null) {
873
			widget.setData(node.getElement());
846
			clear(widget);
874
			internalRefresh(node);
847
			attemptPendingUpdates();
875
		}
848
		}
876
	}
849
	}
877
850
Lines 892-929 Link Here
892
	}
865
	}
893
866
894
	/**
867
	/**
895
	 * Called when nodes are set in the model. The children may not have been
868
	 * Clears the given widget
896
	 * retrieved yet when the tree got the call to "set data".
897
	 * 
869
	 * 
898
	 * @param parent
870
	 * @param item
899
	 * @param children
900
	 */
871
	 */
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
926
    protected abstract void clear(Widget item);
872
    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);
927
880
928
	/**
881
	/**
929
	 * Returns the child widet at the given index for the given parent or
882
	 * Returns the child widet at the given index for the given parent or
Lines 949-970 Link Here
949
    protected void attemptPendingUpdates() {
902
    protected void attemptPendingUpdates() {
950
    	attemptSelection(false);
903
    	attemptSelection(false);
951
    }
904
    }
952
905
	
953
	/**
906
	/**
954
	 * The children of a node have changed.
907
	 * Notification a node's children have changed.
908
	 * Updates the child count for the parent's widget
909
	 * and clears children to be updated.
955
	 * 
910
	 * 
956
	 * @param parent
911
	 * @param parentNode
957
	 */
912
	 */
958
	protected void nodeChildrenChanged(ModelNode parentNode) {
913
	protected void nodeChildrenChanged(ModelNode parentNode) {
959
		ModelNode[] childrenNodes = parentNode.getChildrenNodes();
914
		Widget widget = findItem(parentNode);
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();
960
		if (childrenNodes != null) {
932
		if (childrenNodes != null) {
961
			nodeChildrenSet(parentNode, childrenNodes);
933
			for (int i = 0; i < childrenNodes.length; i++) {
962
		} else {
934
				unmapNode(childrenNodes[i]);
963
			Widget widget = findItem(parentNode);
964
			if (widget != null && !widget.isDisposed()) {
965
				int childCount = parentNode.getChildCount();
966
				setItemCount(widget, childCount);
967
				attemptPendingUpdates();
968
			}
935
			}
969
		}
936
		}
970
	}
937
	}
Lines 997-1034 Link Here
997
    	return findItem((Object)node);
964
    	return findItem((Object)node);
998
    }
965
    }
999
966
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
1032
	/*
967
	/*
1033
	 * (non-Javadoc)
968
	 * (non-Javadoc)
1034
	 * 
969
	 * 
Lines 1059-1067 Link Here
1059
		        		        internalRefresh(child);
994
		        		        internalRefresh(child);
1060
		        		    }
995
		        		    }
1061
		        		});
996
		        		});
1062
		        	} else {
997
		        	}
1063
		        		addPendingChildIndex(node, index);
1064
		            }
1065
		        	return;
998
		        	return;
1066
				}
999
				}
1067
			}
1000
			}
(-)ui/org/eclipse/debug/internal/ui/viewers/AsynchronousTreeModel.java (-17 / +8 lines)
Lines 139-145 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);
143
			}
142
			}
144
		});
143
		});
145
    }
144
    }
Lines 240-246 Link Here
240
     * @param node
239
     * @param node
241
     * @param containsChildren
240
     * @param containsChildren
242
     */
241
     */
243
     void setIsContainer(ModelNode node, boolean containsChildren) {
242
     void setIsContainer(final ModelNode node, boolean containsChildren) {
244
    	ModelNode[] prevChildren = null;
243
    	ModelNode[] prevChildren = null;
245
    	synchronized (this) {
244
    	synchronized (this) {
246
			prevChildren = node.getChildrenNodes();
245
			prevChildren = node.getChildrenNodes();
Lines 255-274 Link Here
255
			}
254
			}
256
		}
255
		}
257
//    	 update tree outside lock
256
//    	 update tree outside lock
258
        AsynchronousTreeViewer viewer = getTreeViewer();
257
    	preservingSelection(new Runnable() {
259
		if (containsChildren) {
258
			public void run() {
260
            if (prevChildren == null) {
259
				getViewer().nodeChildrenChanged(node);
261
                viewer.nodeChildrenChanged(node);
260
		    	getTreeViewer().nodeContainerChanged(node);
262
                viewer.nodeContainerChanged(node);
261
			}
263
            } else {
262
		});
264
                viewer.nodeContainerChanged(node);
263
    	
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
        }
273
    }    
264
    }    
274
}
265
}
(-)ui/org/eclipse/debug/internal/ui/viewers/AsynchronousModel.java (-42 / +37 lines)
Lines 475-480 Link Here
475
        
475
        
476
        ModelNode[] prevKids = null;
476
        ModelNode[] prevKids = null;
477
        ModelNode[] newChildren = null;
477
        ModelNode[] newChildren = null;
478
        ModelNode[] unmap = null; 
478
        
479
        
479
        synchronized (this) {
480
        synchronized (this) {
480
        	if (isDisposed()) {
481
        	if (isDisposed()) {
Lines 490-544 Link Here
490
    			}
491
    			}
491
            	parentNode.setChildren(newChildren);
492
            	parentNode.setChildren(newChildren);
492
            } else {
493
            } else {
493
    	        for (int i = 0; i < prevKids.length; i++) {
494
            	newChildren = new ModelNode[children.length];
494
    				ModelNode kid = prevKids[i];
495
            	unmap = new ModelNode[prevKids.length];
495
    				if (i >= children.length) {
496
            	for (int i = 0; i < prevKids.length; i++) {
496
    					kid.dispose();
497
					unmap[i] = prevKids[i];	
497
    					unmapNode(kid);
498
				}
498
    				} else {
499
            	for (int i = 0; i < children.length; i++) {
499
    					ModelNode prevNode = prevKids[i];
500
					Object child = children[i];
500
    					Object nextChild = children[i];
501
					boolean found = false;
501
    					if (!prevNode.getElement().equals(nextChild)) {
502
					for (int j = 0; j < prevKids.length; j++) {
502
    						unmapNode(prevNode);
503
						ModelNode prevKid = prevKids[j];
503
    					}
504
						if (prevKid != null && child.equals(prevKid.getElement())) {
504
    					mapElement(nextChild, prevNode);
505
							newChildren[i] = prevKid;
505
    				}
506
							prevKids[j] = null;
506
    			}
507
							found = true;
507
    			// create new children
508
							break;
508
    	        if (children.length > prevKids.length) {
509
						}
509
    		        newChildren = new ModelNode[children.length];
510
					}
510
    		        System.arraycopy(prevKids, 0, newChildren, 0, prevKids.length);
511
					if (!found) {
511
    		        for (int i = prevKids.length; i < children.length; i ++) {
512
						newChildren[i] = new ModelNode(parentNode, child);
512
    		        	Object child = children[i];
513
						mapElement(child, newChildren[i]);
513
    					ModelNode childNode = new ModelNode(parentNode, child);
514
					}
514
    		        	mapElement(child, childNode);
515
				}
515
    		        	newChildren[i] = childNode;
516
            	for (int i = 0; i < prevKids.length; i++) {
516
    		        }
517
            		ModelNode kid = prevKids[i];
517
    		        parentNode.setChildren(newChildren);
518
            		if (kid != null) {
518
    	        }
519
            			kid.dispose();
519
                if (children.length < prevKids.length) {
520
            			unmapNode(kid);
520
                	newChildren = new ModelNode[children.length];
521
            		}
521
                    System.arraycopy(prevKids, 0, newChildren, 0, children.length);
522
            	}
522
                    parentNode.setChildren(newChildren);
523
    	        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[] finalPrevKids = prevKids; 
528
    	final ModelNode[] finalUnmap = unmap; 
529
        preservingSelection(new Runnable() {
529
        preservingSelection(new Runnable() {
530
            public void run() {
530
            public void run() {
531
            	if (finalPrevKids != null) {
531
            	if (finalUnmap != null) {
532
	                for (int i = 0; i < finalPrevKids.length; i++) {
532
	            	for (int i = 0; i < finalUnmap.length; i++) {
533
	                    ModelNode kid = finalPrevKids[i];
533
						viewer.unmapNode(finalUnmap[i]);
534
	                    if (i >= children.length) {
534
					}
535
	                        viewer.nodeDisposed(kid);
536
	                    } else {
537
	                        viewer.nodeChanged(kid);
538
	                    }
539
	                }
540
            	}
535
            	}
541
                viewer.nodeChildrenChanged(parentNode);
536
            	viewer.nodeChildrenChanged(parentNode);
542
            }
537
            }
543
        });        	        
538
        });        	        
544
539
(-)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