diff --git a/memory/org.eclipse.cdt.debug.ui.memory.traditional/META-INF/MANIFEST.MF b/memory/org.eclipse.cdt.debug.ui.memory.traditional/META-INF/MANIFEST.MF index f42d50dbd38..f21cbf7eb1b 100644 --- a/memory/org.eclipse.cdt.debug.ui.memory.traditional/META-INF/MANIFEST.MF +++ b/memory/org.eclipse.cdt.debug.ui.memory.traditional/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-SymbolicName: org.eclipse.cdt.debug.ui.memory.traditional;singleton:=true -Bundle-Version: 1.4.0.qualifier +Bundle-Version: 1.5.0.qualifier Bundle-Localization: plugin Require-Bundle: org.eclipse.debug.core, org.eclipse.debug.ui, diff --git a/memory/org.eclipse.cdt.debug.ui.memory.traditional/pom.xml b/memory/org.eclipse.cdt.debug.ui.memory.traditional/pom.xml index c0d5618df0a..7d9ff4916ab 100644 --- a/memory/org.eclipse.cdt.debug.ui.memory.traditional/pom.xml +++ b/memory/org.eclipse.cdt.debug.ui.memory.traditional/pom.xml @@ -11,7 +11,7 @@ ../../pom.xml - 1.4.0-SNAPSHOT + 1.5.0-SNAPSHOT org.eclipse.cdt.debug.ui.memory.traditional eclipse-plugin diff --git a/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/Rendering.java b/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/Rendering.java index 820a90a9ce5..71c3ec2395d 100755 --- a/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/Rendering.java +++ b/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/Rendering.java @@ -163,11 +163,22 @@ public class Rendering extends Composite implements IDebugEventSetListener /** * Maintains the subset of items visible in the current view address range. * This information is refreshed when the associated Panes are about to be redrawn + * Note: Only the start address of each entry is included i.e. one entry per information item * @since 1.4 */ protected final Map> fMapStartAddrToInfoItems = Collections .synchronizedMap(new HashMap>()); + /** + * Maps any address within a memory information range to a corresponding list of information items + * sharing that address. + * This is useful to e.g. produce a tooltip while hovering over any memory location of a memory information range + * + * @since 1.5 + */ + protected final Map> fMapAddrToInfoItems = Collections + .synchronizedMap(new HashMap>()); + public Rendering(Composite parent, TraditionalRendering renderingParent) { super(parent, SWT.DOUBLE_BUFFERED | SWT.NO_BACKGROUND | SWT.H_SCROLL @@ -1198,6 +1209,7 @@ public class Rendering extends Composite implements IDebugEventSetListener } fMapStartAddrToInfoItems.clear(); + fMapAddrToInfoItems.clear(); super.dispose(); } diff --git a/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/RenderingAddressInfo.java b/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/RenderingAddressInfo.java index 95405a0a51d..f449221b7d2 100644 --- a/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/RenderingAddressInfo.java +++ b/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/RenderingAddressInfo.java @@ -132,6 +132,7 @@ public class RenderingAddressInfo extends Rendering fSelectedContext = null; fMapStartAddrToInfoItems.clear(); + fMapAddrToInfoItems.clear(); fAddressInfoTypeStatusMap.clear(); fAddressInfoItems = null; @@ -261,6 +262,7 @@ public class RenderingAddressInfo extends Rendering // The selection has changed, so our Address information may no longer be valid fAddressInfoItems = addressInfoItems; fMapStartAddrToInfoItems.clear(); + fMapAddrToInfoItems.clear(); if (fBinaryPane.isVisible()) { redrawPanes(); @@ -334,6 +336,7 @@ public class RenderingAddressInfo extends Rendering IMemoryBlockAddressInfoItem[] items = fAddressInfoItems; if (items == null || !fParent.isShowCrossRefInfoGlobalPref()) { fMapStartAddrToInfoItems.clear(); + fMapAddrToInfoItems.clear(); return fMapStartAddrToInfoItems; } @@ -343,6 +346,7 @@ public class RenderingAddressInfo extends Rendering // unless the cell size matches the addressable size of the target system if (fParent.getAddressableSize() != getBytesPerColumn()) { fMapStartAddrToInfoItems.clear(); + fMapAddrToInfoItems.clear(); return fMapStartAddrToInfoItems; } } @@ -357,6 +361,7 @@ public class RenderingAddressInfo extends Rendering synchronized (fMapStartAddrToInfoItems) { // Refreshing the Address to InfoItem data map fMapStartAddrToInfoItems.clear(); + fMapAddrToInfoItems.clear(); BigInteger startAddress = getViewportStartAddress(); // Get the endAddress considering a page that uses single height, // Note: The UI may some times present rows with double height even if the user does not see items @@ -395,6 +400,29 @@ public class RenderingAddressInfo extends Rendering if (itemStartIsInRange || itemEndIsInRange || itemSpansOverVisibleRange) { fMapStartAddrToInfoItems.put(item.getAddress(), allValuesMap.get(item.getAddress())); filteredValuesMap.put(item.getAddress(), allValuesMap.get(item.getAddress())); + // Add information items for each address within the range + // But establish the limits to only add information to visible items (i.e. limiting the processing) + BigInteger firstItemVisibleAddress = itemStartIsInRange ? item.getAddress() : startAddress; + BigInteger lastItemVisibleAddress = itemEndIsInRange ? item.getAddress().add(item.getRangeInAddressableUnits().subtract(BigInteger.ONE)) : endAddress; + + for (BigInteger candidateAddress=firstItemVisibleAddress; candidateAddress.compareTo(lastItemVisibleAddress) <=0; candidateAddress = candidateAddress.add(BigInteger.ONE)) { + List allItemsAtBase = allValuesMap.get(item.getAddress()); + List newInfoItems = filterToItemsValidForAddress(allItemsAtBase, item.getAddress(), candidateAddress); + + // Add new valid items to the map, associating it to candidate address + List existingItems = fMapAddrToInfoItems.get(candidateAddress); + if (existingItems == null) { + // Brand new list of items + fMapAddrToInfoItems.put(candidateAddress, newInfoItems); + } else { + // Appending new items to the existing list + for (IMemoryBlockAddressInfoItem newItem : newInfoItems) { + if (!existingItems.contains(newItem)) { + existingItems.add(newItem); + } + } + } + } } } } @@ -402,10 +430,56 @@ public class RenderingAddressInfo extends Rendering return filteredValuesMap; } + /** + * @param allBaseItems - Set of items sharing the same starting address + * @param baseAddress - The starting address + * @param candidateAddress - An address higher than base address + * @return - The set of items that are still overlapping at the incremented address + */ + private List filterToItemsValidForAddress(List allBaseItems, + BigInteger baseAddress, BigInteger candidateAddress) { + + List items = new ArrayList<>(); + + // Keep info items applicable for the given address + BigInteger range = candidateAddress.subtract(baseAddress); + + // sanity check - should not happen + if (range.compareTo(BigInteger.ZERO) < 0) { + // return empty list + return items; + } + else if (range.compareTo(BigInteger.ZERO) == 0) { + // Since all items share the same start address, + // all items must be valid for a single address span + return allBaseItems; + } + + // Aggregate elements having a length equal or higher than the span between base address and current address + for (IMemoryBlockAddressInfoItem item : allBaseItems) { + if (item.getRangeInAddressableUnits().compareTo(range) >=0 ) { + items.add(item); + } + } + + return items; + } + @Override String buildAddressInfoString(BigInteger cellAddress, String separator, boolean addTypeHeaders) { - List infoItems = fMapStartAddrToInfoItems.get(cellAddress); + List infoItems; + if (addTypeHeaders) { + // Tooltip information + infoItems = fMapAddrToInfoItems.get(cellAddress); + } else { + // element information + infoItems = fMapStartAddrToInfoItems.get(cellAddress); + } + return buildAddressInfoString(cellAddress, separator, addTypeHeaders, infoItems); + } + + private String buildAddressInfoString(BigInteger cellAddress, String separator, boolean addTypeHeaders, List infoItems) { if (infoItems == null || infoItems.size() < 1) { // No information to display return ""; @@ -455,7 +529,7 @@ public class RenderingAddressInfo extends Rendering @Override boolean hasAddressInfo(BigInteger cellAddress) { - return fMapStartAddrToInfoItems.keySet().contains(cellAddress); + return fMapAddrToInfoItems.keySet().contains(cellAddress); } /**